Backoffice contact details, currency mgmt. updates

This commit is contained in:
Stephanos A
2026-07-11 12:16:05 +03:00
parent 3c3924b33f
commit 50ebe8ddda
14 changed files with 323 additions and 355 deletions

View File

@@ -39,10 +39,18 @@ export class PassengersService {
const where: any = {};
if (search) {
// IAM user search: resolve matching iamUserIds first, then filter by passengerId
const iamRows = await this.dataSource.query<{ id: string }[]>(
`SELECT id FROM iam.users WHERE (name->>'en') ILIKE $1 OR (name->>'am') ILIKE $1 OR email ILIKE $1 OR phone_number ILIKE $1`,
[`%${search}%`],
);
const matchedPassengers = iamRows.length > 0
? await this.prisma.passenger.findMany({ where: { iamUserId: { in: iamRows.map(r => r.id) } }, select: { id: true } })
: [];
where.OR = [
{ fullName: { contains: search, mode: 'insensitive' } },
{ passenger: { user: { email: { contains: search, mode: 'insensitive' } } } },
{ passenger: { user: { phone: { contains: search, mode: 'insensitive' } } } },
...(matchedPassengers.length > 0 ? [{ passengerId: { in: matchedPassengers.map(p => p.id) } }] : []),
];
}
@@ -66,7 +74,6 @@ export class PassengersService {
include: {
passenger: {
include: {
user: true,
loyalty: true,
wallet: true,
_count: { select: { bookings: true } },
@@ -106,17 +113,13 @@ export class PassengersService {
return {
items: items.map(profile => {
const passenger = profile.passenger;
const localUser = (passenger as any)?.user ?? null;
const iam = passenger?.iamUserId ? iamMap.get(passenger.iamUserId) : undefined;
const faydaVerified = localUser?.faydaVerified === true
|| iam?.metadata?.faydaVerified === true
const faydaVerified = iam?.metadata?.faydaVerified === true
|| iam?.metadata?.faydaVerified === 'true';
// Get additional data from bookings for guest passengers
const guestBooking = (passenger as any)?.bookings?.[0] ?? null;
const guestSeat = guestBooking?.seats?.[0] ?? null;
// Parse notes JSON to extract phone and other data
let notesData: any = null;
if (profile.notes) {
try {
@@ -129,25 +132,23 @@ export class PassengersService {
return {
id: profile.id,
fullName: profile.fullName,
email: localUser?.email ?? iam?.email ?? notesData?.email ?? guestBooking?.contactEmail ?? null,
phone: localUser?.phone ?? iam?.phone_number ?? notesData?.phone ?? guestBooking?.contactPhone ?? null,
gender: profile.gender ?? localUser?.gender ?? iam?.metadata?.gender ?? null,
email: iam?.email ?? notesData?.email ?? guestBooking?.contactEmail ?? null,
phone: iam?.phone_number ?? notesData?.phone ?? guestBooking?.contactPhone ?? null,
gender: profile.gender ?? iam?.metadata?.gender ?? null,
dateOfBirth: profile.dateOfBirth
? new Date(profile.dateOfBirth).toISOString().split('T')[0]
: (localUser?.dateOfBirth
? (localUser.dateOfBirth instanceof Date ? localUser.dateOfBirth.toISOString().split('T')[0] : localUser.dateOfBirth)
: iam?.metadata?.dateOfBirth ?? null),
nationality: localUser?.nationality ?? iam?.metadata?.nationality ?? notesData?.nationality ?? (guestSeat?.passportCountry ? (guestSeat.passportCountry === 'Ethiopia' ? 'Ethiopian' : guestSeat.passportCountry) : null),
nationalityCode: localUser?.nationalityCode ?? iam?.metadata?.nationalityCode ?? null,
: (iam?.metadata?.dateOfBirth ?? null),
nationality: iam?.metadata?.nationality ?? notesData?.nationality ?? (guestSeat?.passportCountry ? (guestSeat.passportCountry === 'Ethiopia' ? 'Ethiopian' : guestSeat.passportCountry) : null),
nationalityCode: iam?.metadata?.nationalityCode ?? null,
faydaVerified,
faydaVerifiedAt: localUser?.faydaVerifiedAt ?? iam?.metadata?.faydaVerifiedAt ?? null,
passportNumber: localUser?.passportNumber ?? iam?.metadata?.passportNumber ?? notesData?.passportNumber ?? guestSeat?.passportNumber ?? null,
passportCountry: localUser?.passportCountry ?? iam?.metadata?.passportCountry ?? notesData?.passportCountry ?? guestSeat?.passportCountry ?? null,
passportExpiryDate: localUser?.passportExpiryDate ?? iam?.metadata?.passportExpiryDate ?? null,
faydaVerifiedAt: iam?.metadata?.faydaVerifiedAt ?? null,
passportNumber: iam?.metadata?.passportNumber ?? notesData?.passportNumber ?? guestSeat?.passportNumber ?? null,
passportCountry: iam?.metadata?.passportCountry ?? notesData?.passportCountry ?? guestSeat?.passportCountry ?? null,
passportExpiryDate: iam?.metadata?.passportExpiryDate ?? null,
idDocumentType: profile.nationalId ? 'NATIONAL_ID' : (notesData?.idDocumentType ?? null),
verified: faydaVerified,
lastLoginAt: localUser?.lastLoginAt ?? null,
role: localUser?.role ?? null,
lastLoginAt: null,
role: null,
loyalty: passenger?.loyalty
? { tier: passenger.loyalty.tier, pointsBalance: passenger.loyalty.pointsBalance, lifetimePoints: (passenger.loyalty as any).lifetimePoints ?? 0 }
: null,
@@ -279,6 +280,8 @@ export class PassengersService {
passengerName: p.passengerName,
dateOfBirth: p.dateOfBirth,
nationality: p.nationality,
phone: p.phone ?? null,
email: p.email ?? null,
})),
message: 'Passenger details saved successfully',
};
@@ -434,18 +437,12 @@ export class PassengersService {
async deletePassenger(id: string, cascade = false) {
// id may be a TravelerProfile.id (from the list endpoint) or a Passenger.id
let passenger = await this.prisma.passenger.findUnique({
where: { id },
include: { user: true },
});
let passenger = await this.prisma.passenger.findUnique({ where: { id } });
if (!passenger) {
const profile = await this.prisma.travelerProfile.findUnique({ where: { id } });
if (!profile?.passengerId) throw new NotFoundException('Passenger not found');
passenger = await this.prisma.passenger.findUnique({
where: { id: profile.passengerId },
include: { user: true },
});
passenger = await this.prisma.passenger.findUnique({ where: { id: profile.passengerId } });
if (!passenger) throw new NotFoundException('Passenger not found');
}
@@ -454,7 +451,7 @@ export class PassengersService {
if (!cascade) {
const usage = await this.checkPassengerUsage(passengerId);
if (usage.isInUse && usage.constraints) {
const passengerName = (passenger as any).user?.fullName || `Passenger ${passengerId.slice(-8)}`;
const passengerName = `Passenger ${passengerId.slice(-8)}`;
throw new DeleteOperationException('Passenger', passengerName, usage.constraints);
}
}