mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 18:48:11 +00:00
Merge branch 'alpha' into passenger/feat/iam-integration
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import { Body, Controller, Get, Param, Post, UseGuards, Query } from '@nestjs/common';
|
||||
import { Body, Controller, Get, Param, Post, UseGuards, Query, Request } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse, ApiQuery } from '@nestjs/swagger';
|
||||
import { PassengersService } from './passengers.service';
|
||||
import { CreateTravelerProfileDto, CreateSavedRouteDto, VerifyFaydaDto, RegisterInternationalPassengerDto } from './passengers.dto';
|
||||
import { CreateTravelerProfileDto, CreateSavedRouteDto, VerifyFaydaDto, SavePassengersDto, RegisterPassengerDto } from './passengers.dto';
|
||||
import { JwtGuard } from '../../common/jwt.guard';
|
||||
import { VerifaydaService } from '../verifayda/verifayda.service';
|
||||
import { OptionalJwtGuard } from '../verifayda/optional-jwt.guard';
|
||||
|
||||
@ApiTags('Passenger')
|
||||
@ApiTags('Passengers')
|
||||
@Controller('passengers')
|
||||
export class PassengersController {
|
||||
constructor(
|
||||
@@ -55,14 +56,51 @@ export class PassengersController {
|
||||
@Post('verify-fayda')
|
||||
@ApiOperation({
|
||||
summary: 'Verify Ethiopian national ID via Verifayda 2.0',
|
||||
description: `Verifies Ethiopian national ID and retrieves passenger data from government database.
|
||||
description: `**Standalone endpoint for pre-verification of Ethiopian national IDs**
|
||||
|
||||
---
|
||||
|
||||
### Purpose
|
||||
Pre-verify national ID to auto-fill passenger registration form before submission.
|
||||
|
||||
---
|
||||
|
||||
### Flow
|
||||
|
||||
1. User enters national ID in form
|
||||
|
||||
2. Frontend calls \`POST /passengers/verify-fayda\`
|
||||
|
||||
3. API queries Verifayda 2.0 government database
|
||||
|
||||
4. Returns verified passenger data (name, DOB, gender)
|
||||
|
||||
5. Frontend auto-fills form with verified data
|
||||
|
||||
6. User submits form via \`POST /passengers/register\`
|
||||
|
||||
---
|
||||
|
||||
### Features
|
||||
- Real-time verification via Verifayda 2.0 API
|
||||
- Retrieves verified passenger data (name, DOB, gender, nationality)
|
||||
- National IDs NOT stored (policy compliant)
|
||||
- Retrieves verified data: name, date of birth, gender, nationality
|
||||
- **National IDs NOT stored** (policy compliant)
|
||||
- Only for Ethiopian nationals with national ID
|
||||
- Non-Ethiopians should use passport (no verification required)
|
||||
- Returns passenger details for booking form auto-fill`,
|
||||
- Non-Ethiopians use passport (no verification)
|
||||
|
||||
---
|
||||
|
||||
### Important Notes
|
||||
- This is a **read-only** verification endpoint
|
||||
- Does NOT save passenger data to database
|
||||
- Use \`POST /passengers/register\` to actually register
|
||||
- Falls back to manual entry if Verifayda disabled or fails
|
||||
|
||||
---
|
||||
|
||||
### Authentication
|
||||
- **Public endpoint** (no authentication required)
|
||||
- Can be called before login/registration`,
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
@@ -84,21 +122,143 @@ export class PassengersController {
|
||||
return this.verifaydaService.verifyNationalId(dto.nationalId);
|
||||
}
|
||||
|
||||
@Post('register-international')
|
||||
@Post('register')
|
||||
@UseGuards(OptionalJwtGuard)
|
||||
@ApiBearerAuth('JWT-auth')
|
||||
@ApiOperation({
|
||||
summary: 'Register international passenger with passport details',
|
||||
description: `Saves international passenger profile for booking.
|
||||
summary: 'Universal passenger registration endpoint',
|
||||
description: `**Single endpoint for all passenger registration scenarios**
|
||||
|
||||
- For non-Ethiopian passengers (Djiboutian, Kenyan, etc.)
|
||||
- Collects passport information
|
||||
- No government verification required
|
||||
- Profile saved for future bookings
|
||||
- Can be used by logged-in users or guest users (via deviceId)`,
|
||||
---
|
||||
|
||||
### Automatic Detection
|
||||
The API automatically detects:
|
||||
- **Passenger Type**: Ethiopian (nationalId) vs International (passportNumber)
|
||||
- **Authentication**: Logged-in (JWT token) vs Guest (deviceId)
|
||||
- **Verification**: Auto-attempts Fayda for Ethiopian nationals
|
||||
|
||||
---
|
||||
|
||||
### Scenarios Handled
|
||||
|
||||
#### 1. Guest Ethiopian Passenger
|
||||
- Provide: \`nationalId\`, \`deviceId\`
|
||||
- Behavior: Attempts Fayda verification → Saves to SavedPassengerProfile
|
||||
- Response: \`verified: true/false\`, \`linked: false\`
|
||||
|
||||
#### 2. Guest International Passenger
|
||||
- Provide: \`passportNumber\`, \`passportCountry\`, \`deviceId\`
|
||||
- Behavior: No verification → Saves to SavedPassengerProfile
|
||||
- Response: \`verified: false\`, \`linked: false\`
|
||||
|
||||
#### 3. Logged-in Ethiopian Passenger
|
||||
- Provide: JWT token + \`nationalId\`
|
||||
- Behavior: Attempts Fayda verification → Updates user profile
|
||||
- Response: \`verified: true/false\`, \`linked: true\`
|
||||
|
||||
#### 4. Logged-in International Passenger
|
||||
- Provide: JWT token + \`passportNumber\`, \`passportCountry\`
|
||||
- Behavior: No verification → Updates user profile
|
||||
- Response: \`verified: false\`, \`linked: true\`
|
||||
|
||||
---
|
||||
|
||||
### Authentication
|
||||
- **Optional JWT Bearer Token** (OptionalJwtGuard)
|
||||
- Token present → Links to user account
|
||||
- No token → Saves as guest (requires deviceId)
|
||||
|
||||
---
|
||||
|
||||
### Benefits
|
||||
- Single endpoint for all scenarios
|
||||
- Auto-detects passenger type and flow
|
||||
- Graceful fallback if Fayda fails
|
||||
- Consistent response structure
|
||||
|
||||
---
|
||||
|
||||
### Replaces
|
||||
- Manual verification + save flows`,
|
||||
})
|
||||
@ApiResponse({ status: 201, description: 'International passenger profile saved successfully' })
|
||||
@ApiResponse({ status: 400, description: 'Invalid passport details' })
|
||||
registerInternational(@Body() dto: RegisterInternationalPassengerDto) {
|
||||
return this.service.registerInternational(dto);
|
||||
@ApiResponse({
|
||||
status: 201,
|
||||
description: 'Passenger registered successfully',
|
||||
schema: {
|
||||
example: {
|
||||
id: 'uuid-123',
|
||||
passengerName: 'Abebe Kebede',
|
||||
dateOfBirth: '1985-03-15T00:00:00.000Z',
|
||||
nationality: 'Ethiopian',
|
||||
verified: true,
|
||||
linked: false,
|
||||
message: 'Passenger details saved for guest booking'
|
||||
}
|
||||
}
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 400,
|
||||
description: 'Validation error or verification failed',
|
||||
schema: {
|
||||
example: {
|
||||
statusCode: 400,
|
||||
message: 'Validation failed',
|
||||
error: 'Bad Request'
|
||||
}
|
||||
}
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 401,
|
||||
description: 'Invalid JWT token (only if token provided but invalid)'
|
||||
})
|
||||
registerPassenger(@Body() dto: RegisterPassengerDto, @Request() req: any) {
|
||||
const userId = req.user?.userId;
|
||||
return this.service.registerPassenger({ ...dto, userId });
|
||||
}
|
||||
|
||||
@Post('save-details')
|
||||
@ApiOperation({
|
||||
summary: '[LEGACY] Save all passenger details before seat selection',
|
||||
description: `**Note:** This endpoint is legacy. Consider using \`POST /passengers/register\` instead.
|
||||
|
||||
Saves all passenger details to database before proceeding to seat selection.
|
||||
|
||||
- Required step in booking flow
|
||||
- Saves details for all passengers in booking
|
||||
- Supports both logged-in users and guests
|
||||
- Prevents data loss if user navigates away
|
||||
|
||||
**Migration:** Use \`POST /passengers/register\` for new implementations.`,
|
||||
})
|
||||
@ApiResponse({
|
||||
status: 201,
|
||||
description: 'Passenger details saved successfully',
|
||||
schema: {
|
||||
example: {
|
||||
count: 2,
|
||||
passengerIds: ['uuid-1', 'uuid-2'],
|
||||
passengers: [
|
||||
{
|
||||
id: 'uuid-1',
|
||||
passengerName: 'John Doe',
|
||||
dateOfBirth: '1990-01-01T00:00:00.000Z',
|
||||
nationality: 'Ethiopian'
|
||||
},
|
||||
{
|
||||
id: 'uuid-2',
|
||||
passengerName: 'Jane Doe',
|
||||
dateOfBirth: '1992-05-15T00:00:00.000Z',
|
||||
nationality: 'Ethiopian'
|
||||
}
|
||||
],
|
||||
message: 'Passenger details saved successfully'
|
||||
}
|
||||
}
|
||||
})
|
||||
@ApiResponse({ status: 400, description: 'Validation error - passengers array required' })
|
||||
savePassengers(@Body() body: any) {
|
||||
const passengers = body.passengers || (Array.isArray(body) ? body : [body]);
|
||||
return this.service.savePassengers(passengers, body.userId, body.deviceId);
|
||||
}
|
||||
|
||||
@Post('traveler-profiles')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IsString, IsOptional, IsDateString, IsEnum } from 'class-validator';
|
||||
import { IsString, IsOptional, IsDateString, IsEnum, IsBoolean } from 'class-validator';
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
|
||||
export class CreateTravelerProfileDto {
|
||||
@@ -19,7 +19,15 @@ export class CreateSavedRouteDto {
|
||||
}
|
||||
|
||||
export class VerifyFaydaDto {
|
||||
@ApiProperty({ example: 'ET123456789', description: 'Ethiopian national ID number' })
|
||||
@ApiProperty({
|
||||
example: 'ET123456789',
|
||||
description: `**Ethiopian national ID number**
|
||||
|
||||
- Format: Varies by Ethiopian ID system
|
||||
- Example: ET123456789
|
||||
- Must be valid Ethiopian national ID
|
||||
- Used to query Verifayda 2.0 government database`
|
||||
})
|
||||
@IsString()
|
||||
nationalId: string;
|
||||
}
|
||||
@@ -66,3 +74,184 @@ export class RegisterInternationalPassengerDto {
|
||||
@IsString()
|
||||
deviceId?: string;
|
||||
}
|
||||
|
||||
export class SavePassengerDetailsDto {
|
||||
@ApiProperty({ example: 'Abebe Kebede' })
|
||||
@IsString()
|
||||
name: string;
|
||||
|
||||
@ApiProperty({ example: '1985-03-15' })
|
||||
@IsDateString()
|
||||
dateOfBirth: string;
|
||||
|
||||
@ApiProperty({ example: 'ETHIOPIAN' })
|
||||
@IsString()
|
||||
nationality: string;
|
||||
|
||||
@ApiPropertyOptional({ example: 'ET123456789' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
nationalId?: string;
|
||||
|
||||
@ApiPropertyOptional({ example: 'P1234567' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
passportNumber?: string;
|
||||
|
||||
@ApiPropertyOptional({ example: 'Kenya' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
passportCountry?: string;
|
||||
|
||||
@ApiPropertyOptional({ example: '+251911234567' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
phone?: string;
|
||||
|
||||
@ApiPropertyOptional({ example: 'email@example.com' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
email?: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
faydaSub?: string;
|
||||
}
|
||||
|
||||
export class SavePassengersDto {
|
||||
@ApiProperty({ type: [SavePassengerDetailsDto] })
|
||||
passengers: SavePassengerDetailsDto[];
|
||||
|
||||
@ApiPropertyOptional({ description: 'User ID if logged in' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
userId?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: 'Device ID for guest users' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
deviceId?: string;
|
||||
}
|
||||
|
||||
export class RegisterPassengerDto {
|
||||
@ApiProperty({
|
||||
example: 'Abebe Kebede',
|
||||
description: 'Full name of passenger (required for all scenarios)'
|
||||
})
|
||||
@IsString()
|
||||
passengerName: string;
|
||||
|
||||
@ApiProperty({
|
||||
example: '1985-03-15',
|
||||
description: 'Date of birth in ISO format YYYY-MM-DD (required for all scenarios)'
|
||||
})
|
||||
@IsDateString()
|
||||
dateOfBirth: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
example: 'ET123456789',
|
||||
description: `**Ethiopian national ID number**
|
||||
|
||||
- Triggers automatic Fayda verification if enabled
|
||||
- Use for Ethiopian nationals only
|
||||
- Mutually exclusive with passportNumber
|
||||
- If Fayda enabled: passenger data auto-filled from government database
|
||||
- If Fayda disabled: falls back to manual entry`
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
nationalId?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
example: 'P1234567',
|
||||
description: `**Passport number**
|
||||
|
||||
- Required for international passengers
|
||||
- Mutually exclusive with nationalId
|
||||
- No verification performed (manual entry only)`
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
passportNumber?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
example: 'Kenya',
|
||||
description: 'Passport issuing country (required if passportNumber provided)'
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
passportCountry?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
example: 'Ethiopian',
|
||||
description: `**Nationality**
|
||||
|
||||
- Auto-filled if Fayda verification succeeds
|
||||
- Required for international passengers
|
||||
- Optional for Ethiopian passengers (defaults to "Ethiopian")`
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
nationality?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
example: '+251911234567',
|
||||
description: 'Phone number in international format (optional but recommended)'
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
phone?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
example: 'abebe@example.com',
|
||||
description: 'Email address (optional but recommended)'
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
email?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: `**User ID (auto-populated from JWT token)**
|
||||
|
||||
- Do NOT send this field in request
|
||||
- Automatically extracted from JWT token if present
|
||||
- Used to link passenger to user account`
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
userId?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
example: 'device-uuid-123',
|
||||
description: `**Device ID for guest users**
|
||||
|
||||
- **Required if no JWT token provided (guest mode)**
|
||||
- Generate once and store locally (localStorage/AsyncStorage)
|
||||
- Used to retrieve saved passenger profiles
|
||||
- Format: UUID or any unique string`
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
deviceId?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
example: 'Male',
|
||||
description: 'Gender (auto-filled if Fayda verification succeeds)'
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
gender?: string;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
example: true,
|
||||
description: `**Whether to verify with Fayda (auto-determined)**
|
||||
|
||||
- Default: Auto-detect (true if nationalId provided)
|
||||
- Set to false to skip Fayda verification (use manual entry)
|
||||
- Only applicable for Ethiopian nationals with nationalId`
|
||||
})
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
verifyWithFayda?: boolean;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common';
|
||||
import { PrismaService } from '../../common/prisma.service';
|
||||
import { CreateTravelerProfileDto, CreateSavedRouteDto, RegisterInternationalPassengerDto } from './passengers.dto';
|
||||
import { CreateTravelerProfileDto, CreateSavedRouteDto, RegisterPassengerDto } from './passengers.dto';
|
||||
import { VerifaydaService } from '../verifayda/verifayda.service';
|
||||
|
||||
interface PassengerFilters {
|
||||
search?: string;
|
||||
@@ -11,7 +12,10 @@ interface PassengerFilters {
|
||||
|
||||
@Injectable()
|
||||
export class PassengersService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
private verifaydaService: VerifaydaService,
|
||||
) {}
|
||||
|
||||
async findAll(filters: PassengerFilters = {}) {
|
||||
const { search, verified, page = 1, pageSize = 20 } = filters;
|
||||
@@ -126,29 +130,43 @@ export class PassengersService {
|
||||
return { totalTrips, totalSpend, loyaltyPoints: loyalty?.pointsBalance ?? 0, co2Saved: totalTrips * 6 };
|
||||
}
|
||||
|
||||
async registerInternational(dto: RegisterInternationalPassengerDto) {
|
||||
const profile = await this.prisma.savedPassengerProfile.create({
|
||||
data: {
|
||||
userId: dto.userId,
|
||||
deviceId: dto.deviceId,
|
||||
passengerName: dto.passengerName,
|
||||
dateOfBirth: new Date(dto.dateOfBirth),
|
||||
idDocumentType: 'PASSPORT',
|
||||
passportNumber: dto.passportNumber,
|
||||
passportCountry: dto.passportCountry,
|
||||
nationality: dto.nationality,
|
||||
phone: dto.phone,
|
||||
email: dto.email,
|
||||
},
|
||||
});
|
||||
async savePassengers(passengers: any[], userId?: string, deviceId?: string) {
|
||||
if (!passengers || !Array.isArray(passengers)) {
|
||||
throw new BadRequestException('Passengers array is required');
|
||||
}
|
||||
|
||||
if (passengers.length === 0) {
|
||||
throw new BadRequestException('At least one passenger is required');
|
||||
}
|
||||
|
||||
const savedProfiles = await Promise.all(
|
||||
passengers.map((p) =>
|
||||
this.prisma.savedPassengerProfile.create({
|
||||
data: {
|
||||
userId,
|
||||
deviceId,
|
||||
passengerName: p.name,
|
||||
dateOfBirth: new Date(p.dateOfBirth),
|
||||
idDocumentType: p.nationalId ? 'NATIONAL_ID' : 'PASSPORT',
|
||||
passportNumber: p.passportNumber,
|
||||
passportCountry: p.passportCountry,
|
||||
nationality: p.nationality,
|
||||
phone: p.phone,
|
||||
email: p.email,
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
return {
|
||||
id: profile.id,
|
||||
passengerName: profile.passengerName,
|
||||
dateOfBirth: profile.dateOfBirth,
|
||||
passportNumber: profile.passportNumber,
|
||||
passportCountry: profile.passportCountry,
|
||||
nationality: profile.nationality,
|
||||
message: 'International passenger profile saved successfully',
|
||||
count: savedProfiles.length,
|
||||
passengerIds: savedProfiles.map(p => p.id),
|
||||
passengers: savedProfiles.map(p => ({
|
||||
id: p.id,
|
||||
passengerName: p.passengerName,
|
||||
dateOfBirth: p.dateOfBirth,
|
||||
nationality: p.nationality,
|
||||
})),
|
||||
message: 'Passenger details saved successfully',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -161,4 +179,95 @@ export class PassengersService {
|
||||
createSavedRoute(dto: CreateSavedRouteDto) { return this.prisma.savedRoute.create({ data: dto }); }
|
||||
|
||||
getSavedRoutes(passengerId: string) { return this.prisma.savedRoute.findMany({ where: { passengerId }, orderBy: { tripCount: 'desc' } }); }
|
||||
}
|
||||
|
||||
async registerPassenger(dto: RegisterPassengerDto) {
|
||||
const isEthiopian = !!dto.nationalId;
|
||||
const isLoggedIn = !!dto.userId;
|
||||
let verifiedData: any = null;
|
||||
|
||||
// Auto-verify Ethiopian passengers with national ID if Fayda is enabled
|
||||
if (isEthiopian && dto.verifyWithFayda !== false) {
|
||||
try {
|
||||
const verification = await this.verifaydaService.verifyNationalId(dto.nationalId!);
|
||||
if (verification.verified && verification.passengerData) {
|
||||
verifiedData = verification.passengerData;
|
||||
}
|
||||
} catch (error) {
|
||||
// If verification fails, continue with manual data
|
||||
console.warn('Fayda verification failed, using manual data:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Use verified data if available, otherwise use provided data
|
||||
const finalData = {
|
||||
passengerName: verifiedData?.fullName || dto.passengerName,
|
||||
dateOfBirth: verifiedData?.dateOfBirth || new Date(dto.dateOfBirth),
|
||||
nationality: verifiedData?.nationality || dto.nationality || (isEthiopian ? 'Ethiopian' : null),
|
||||
gender: verifiedData?.gender || dto.gender,
|
||||
phone: dto.phone,
|
||||
email: dto.email,
|
||||
};
|
||||
|
||||
// If logged in, update user profile and link passenger
|
||||
if (isLoggedIn) {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: dto.userId },
|
||||
include: { passenger: true },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new BadRequestException('User not found');
|
||||
}
|
||||
|
||||
// Update user record if not already verified
|
||||
if (!user.faydaVerified && verifiedData) {
|
||||
await this.prisma.user.update({
|
||||
where: { id: dto.userId },
|
||||
data: {
|
||||
fullName: finalData.passengerName,
|
||||
nationality: finalData.nationality,
|
||||
nationalId: dto.nationalId,
|
||||
passportNumber: dto.passportNumber,
|
||||
faydaVerified: !!verifiedData,
|
||||
faydaVerifiedAt: verifiedData ? new Date() : null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
id: user.passenger?.id || user.id,
|
||||
passengerName: finalData.passengerName,
|
||||
dateOfBirth: finalData.dateOfBirth,
|
||||
nationality: finalData.nationality,
|
||||
verified: !!verifiedData,
|
||||
linked: true,
|
||||
message: 'Passenger details saved and linked to user account',
|
||||
};
|
||||
}
|
||||
|
||||
// Guest user - save to SavedPassengerProfile
|
||||
const profile = await this.prisma.savedPassengerProfile.create({
|
||||
data: {
|
||||
deviceId: dto.deviceId,
|
||||
passengerName: finalData.passengerName,
|
||||
dateOfBirth: finalData.dateOfBirth,
|
||||
idDocumentType: isEthiopian ? 'NATIONAL_ID' : 'PASSPORT',
|
||||
passportNumber: dto.passportNumber,
|
||||
passportCountry: dto.passportCountry,
|
||||
nationality: finalData.nationality,
|
||||
phone: dto.phone,
|
||||
email: dto.email,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
id: profile.id,
|
||||
passengerName: finalData.passengerName,
|
||||
dateOfBirth: finalData.dateOfBirth,
|
||||
nationality: finalData.nationality,
|
||||
verified: !!verifiedData,
|
||||
linked: false,
|
||||
message: 'Passenger details saved for guest booking',
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user