mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 23:00:57 +00:00
319 lines
13 KiB
TypeScript
319 lines
13 KiB
TypeScript
import "reflect-metadata";
|
||
import { NestFactory } from "@nestjs/core";
|
||
import { ValidationPipe } from "@nestjs/common";
|
||
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
|
||
import { AppModule } from "./app.module";
|
||
import { HttpExceptionFilter } from "./common/filters/http-exception.filter";
|
||
import { ResponseTransformInterceptor } from "./common/interceptors/response-transform.interceptor";
|
||
import { SessionActivityInterceptor } from "./common/interceptors/session-activity.interceptor";
|
||
|
||
async function bootstrap() {
|
||
// rawBody: true buffers the unparsed request body onto req.rawBody so webhook handlers
|
||
// (e.g. Waafi HMAC verification) can sign over the exact bytes the provider signed.
|
||
const app = await NestFactory.create(AppModule, { rawBody: true });
|
||
|
||
app.enableCors({
|
||
origin: [
|
||
process.env.PORTAL_URL ?? "http://localhost:5174",
|
||
process.env.BACK_OFFICE_URL ?? "http://localhost:5184",
|
||
],
|
||
});
|
||
|
||
app.useGlobalFilters(new HttpExceptionFilter());
|
||
app.useGlobalInterceptors(
|
||
new ResponseTransformInterceptor(),
|
||
app.get(SessionActivityInterceptor),
|
||
);
|
||
app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true, forbidUnknownValues: false }));
|
||
|
||
const config = new DocumentBuilder()
|
||
.setTitle("EDR Passenger API")
|
||
.setDescription(
|
||
`# Ethio-Djibouti Railway Passenger Booking API
|
||
|
||
## Overview
|
||
Enterprise-grade REST API for the Ethio-Djibouti Railway passenger booking and management platform. Built with NestJS, TypeScript, PostgreSQL, and Prisma ORM.
|
||
|
||
## 🆕 Latest Updates
|
||
- **Sequence Ordering:** Stations and coaches now sorted by sequence field for consistent UI display
|
||
- **User Profile Data:** Gender, DOB, passport, and national ID fields for comprehensive passenger profiles
|
||
- **Seat Class Fees:** Premium charges and insurance fees per seat class for transparent pricing
|
||
- **Booking Types:** Support for ONE_WAY and ROUND_TRIP booking categories
|
||
- **Multi-Currency Display:** Bookings track display currency and converted amounts
|
||
- **Ticket Lifecycle:** Tickets now include validatedAt and boardedAt timestamps for complete audit trail
|
||
|
||
## Key Features
|
||
|
||
### 🎫 Booking Lifecycle
|
||
- Search trips with real-time availability
|
||
- Age-based passenger categorization (Adult ≥5 years, Child <5 years)
|
||
- Nationality-based verification (Ethiopian Fayda, International Passport)
|
||
- Passenger information collection with verification
|
||
- Coach and seat selection with real-time availability
|
||
- Seat holding (15-minute expiry)
|
||
- Create bookings with verified passenger data
|
||
- Modify bookings (seat changes, passenger updates)
|
||
- Cancel bookings with automatic refunds
|
||
- Multi-segment journey support
|
||
- Cross-border journeys via Dire Dawa transit (Ethiopia → Djibouti)
|
||
- Round-trip booking with return journey scheduling
|
||
- Coach type selection with seat class and pricing options
|
||
- **NEW:** Booking type tracking (ONE_WAY vs ROUND_TRIP)
|
||
- **NEW:** Display currency and converted pricing per booking
|
||
|
||
### 👤 Passenger Verification
|
||
1. **Ethiopian Nationals:**
|
||
- Automatic Fayda verification for adults (≥5 years)
|
||
- Real-time national ID verification via government database
|
||
- Retrieves verified passenger data (name, DOB, gender)
|
||
- National IDs not stored (policy compliant)
|
||
|
||
2. **International Passengers:**
|
||
- Passport information collection
|
||
- Manual verification for Djiboutian and other nationals
|
||
- No government database verification required
|
||
|
||
### 💰 Age-Based Pricing
|
||
- **ADULT** (≥5 years): Pay 100% of base fare
|
||
- **CHILD** (<5 years): First child travels FREE, subsequent children pay 100%
|
||
- Automatic age calculation from date of birth
|
||
- Example: 2 adults + 3 children = 4× base fare (first child free)
|
||
- **NEW:** Premium charges and insurance fees per seat class
|
||
- **NEW:** Transparent fee breakdown in pricing calculations
|
||
|
||
### 💳 Payment Integration
|
||
1. **Ethiopian Payment Methods:**
|
||
- **Telebirr** - Ethiopia's leading mobile money
|
||
- **CBE Birr** - Commercial Bank of Ethiopia
|
||
|
||
2. **Djiboutian Payment Methods:**
|
||
- **Waafi** - Djibouti's mobile money service
|
||
|
||
3. **International Payment Methods:**
|
||
- **Card** - International card payments (Visa, Mastercard)
|
||
- **Wallet** - Internal wallet system
|
||
|
||
### 🪑 Seat Management
|
||
- Real-time seat availability by coach and class
|
||
- Seat holds with 15-minute expiry
|
||
- Auto-assign seats with contiguous algorithm
|
||
- Seat blocking for maintenance
|
||
- Coach-level seat maps (ordered by sequence)
|
||
- Class-based seating (Economy Regular, Economy Bed, VIP Bed)
|
||
- **NEW:** Sequence-based coach ordering for consistent display
|
||
|
||
### 🎟️ Ticketing
|
||
- QR code and barcode generation
|
||
- PDF ticket generation
|
||
- Gate validation with audit logs
|
||
- Offline validation support
|
||
- Multi-passenger tickets
|
||
- **NEW:** Ticket lifecycle tracking (validatedAt, boardedAt timestamps)
|
||
- **NEW:** Complete audit trail for compliance and reporting
|
||
|
||
### 🏆 Loyalty Program
|
||
- 4 tiers: Bronze, Silver, Gold, Platinum
|
||
- Points accumulation on trips
|
||
- Reward redemption
|
||
- Tier-based benefits
|
||
|
||
### 💰 Wallet System
|
||
- Top-up via payment methods
|
||
- Pay with wallet balance
|
||
- Transaction ledger
|
||
- Refund to wallet
|
||
|
||
### 📍 Live Tracking
|
||
- Real-time trip status
|
||
- Location updates
|
||
- Delay notifications
|
||
- Station crowd signals
|
||
|
||
### 🔒 Fraud Detection
|
||
- Velocity checks (multiple bookings)
|
||
- High-value transaction monitoring
|
||
- Failed payment pattern detection
|
||
- Automatic user blocking
|
||
|
||
### 👤 Passenger Profiles
|
||
- Comprehensive profile data: gender, date of birth, nationality
|
||
- National ID for Ethiopian citizens (Fayda verified)
|
||
- Passport information for international passengers
|
||
- **NEW:** Complete demographic data for personalized services
|
||
- **NEW:** Improved user targeting and communications
|
||
|
||
### 🌍 Internationalization
|
||
- Multi-language support (English, Amharic, French, Oromo)
|
||
- Locale-based responses
|
||
- Currency formatting (ETB, DJF, USD)
|
||
- **NEW:** Multi-currency display per booking (ETB, DJF, USD)
|
||
|
||
### 🚌 Transit Stop Management
|
||
- Automatic detection of cross-border journeys (Ethiopia → Djibouti)
|
||
- Dire Dawa as mandatory transit hub for international journeys
|
||
- Dual-leg fare calculation (domestic + international)
|
||
- Age-based pricing applied independently per leg
|
||
- Seamless multi-segment booking workflow
|
||
- Transit stop optimization and route planning
|
||
|
||
### 🔄 Round-Trip Booking
|
||
- One-way and round-trip journey options
|
||
- Flexible return date selection
|
||
- Combined pricing for outbound + return legs
|
||
- Separate seat management per leg
|
||
- Independent modification/cancellation per leg
|
||
- Return journey tracking and notifications
|
||
- **NEW:** Booking type stored for analytics and reporting
|
||
|
||
### 🚐 Coach Type & Class Selection
|
||
- Browse available coach types per route (standard coaches, premium coaches)
|
||
- View seat classes per coach (Economy Regular, Economy Bed, VIP Bed)
|
||
- Compare base prices by coach type and class
|
||
- Real-time availability per coach configuration
|
||
- Deferred pricing at seat selection stage
|
||
- Coach amenities and features display
|
||
- **NEW:** Sequence-based coach ordering for consistent UI
|
||
- **NEW:** Premium and insurance fee transparency per class
|
||
|
||
### 📊 Data Organization
|
||
- **Stations:** Ordered by sequence (1-15) for consistent route display
|
||
- **Coaches:** Ordered by sequence (1+) per type for predictable configuration
|
||
- **Booking History:** Sorted chronologically with filtering options
|
||
|
||
## Authentication
|
||
|
||
### Passenger Authentication (JWT-auth)
|
||
Used for passenger-facing endpoints. Obtain token via \`POST /auth/login\`.
|
||
|
||
**Usage:** Add header \`Authorization: Bearer <token>\`
|
||
|
||
### Back-office Authentication (IAM-auth)
|
||
Used for agent, fraud, and reporting endpoints. Requires corporate IAM token.
|
||
|
||
**Usage:** Add header \`Authorization: Bearer <iam-token>\`
|
||
|
||
## Passenger Booking Flow
|
||
|
||
### Step 1: Search Trips
|
||
\`POST /search\` with origin, destination, date, passenger counts, and nationality
|
||
|
||
### Step 2: Get Fare Quote
|
||
\`POST /search/fare-quote\` with passenger counts and display currency
|
||
|
||
### Step 3: Passenger Information & Verification
|
||
**For Ethiopian Passengers:**
|
||
\`POST /passengers/verify-fayda\` - Automatic Fayda verification for adults (≥5 years)
|
||
|
||
**For International Passengers:**
|
||
\`POST /passengers/register-international\` - Passport information collection
|
||
|
||
### Step 4: View Seat Map
|
||
\`GET /seats/seatmap/{scheduleId}\` - Show available coaches and seats
|
||
|
||
### Step 5: Login & Hold Seats
|
||
\`POST /auth/login\` then \`POST /seats/hold\` to reserve seats for 15 minutes
|
||
|
||
### Step 6: Create Booking
|
||
\`POST /bookings/guest\` with verified passenger details and held seats
|
||
|
||
### Step 7: Process Payment
|
||
\`POST /payments/telebirr\` (Ethiopian) or \`POST /payments/waafi\` (Djiboutian)
|
||
|
||
### Step 8: Get Tickets
|
||
\`GET /payments/{paymentId}/status\` to confirm payment and retrieve tickets with QR codes
|
||
|
||
## Rate Limiting
|
||
- Auth endpoints: 5 requests/minute
|
||
- General endpoints: 100 requests/minute
|
||
- Webhook endpoints: No limit
|
||
|
||
## Error Handling
|
||
All errors follow standard format:
|
||
\`\`\`json
|
||
{
|
||
"statusCode": 400,
|
||
"message": "Validation failed",
|
||
"error": "Bad Request",
|
||
"timestamp": "2026-05-20T14:30:00.000Z",
|
||
"path": "/bookings"
|
||
}
|
||
\`\`\`
|
||
|
||
## Pagination
|
||
List endpoints support pagination:
|
||
- \`limit\`: Number of items (default: 20, max: 100)
|
||
- \`offset\`: Skip items (default: 0)
|
||
|
||
## Webhooks
|
||
Payment providers send notifications to:
|
||
- \`POST /payments/webhooks/telebirr\` (Ethiopia)
|
||
- \`POST /payments/webhooks/cbe-birr\` (Ethiopia)
|
||
- \`POST /payments/webhooks/waafi\` (Djibouti)
|
||
- \`POST /payments/webhooks/card\` (International)
|
||
|
||
## Support
|
||
- **Email:** support@edr-platform.com
|
||
- **Documentation:** https://docs.edr-platform.com
|
||
- **Status Page:** https://status.edr-platform.com
|
||
`,
|
||
)
|
||
.setVersion("1.0.0")
|
||
.addBearerAuth(
|
||
{ type: "http", scheme: "bearer", bearerFormat: "JWT", in: "header" },
|
||
"JWT-auth",
|
||
)
|
||
.addTag("Agents", "Counter booking, shift management, commission tracking, and reconciliation")
|
||
.addTag("Audit", "User activity logging, system changes, compliance tracking, and audit trails")
|
||
.addTag("Auth", "Passenger registration, login, OTP, password reset, and profile management")
|
||
.addTag("Booking", "Complete booking lifecycle: create, modify, cancel, guest checkout")
|
||
.addTag("Config", "System settings, feature flags, and configuration management")
|
||
.addTag("Currencies", "Multi-currency support, exchange rates, and currency conversion")
|
||
.addTag("Dashboard", "Home screen aggregations: trips, loyalty, wallet, notifications")
|
||
.addTag("Fare Engine", "Distance-based fare calculation with age-based pricing and multi-currency")
|
||
.addTag("Fayda Verification", "Ethiopian national ID verification via Verifayda 2.0 government API")
|
||
.addTag("Fleet", "Train services, coaches, coach types, seat classes, amenities, and configurations")
|
||
.addTag("Fraud Detection", "Velocity checks, monitoring alerts, pattern detection, and user blocking")
|
||
.addTag("Internal Payments", "Internal payment tracking, wallet transactions, and balance management")
|
||
.addTag("Live Tracking", "Real-time trip status, location updates, delays, and crowd signals")
|
||
.addTag("Loyalty", "Points ledger, tier management (Bronze/Silver/Gold/Platinum), rewards")
|
||
.addTag("Notifications", "Multi-channel delivery (email, SMS, push) and preference management")
|
||
.addTag("Passengers", "Registration, Fayda verification, international passports, saved profiles")
|
||
.addTag("Payment", "Telebirr, CBE Birr, Waafi, Card, Wallet payment processing and refunds")
|
||
.addTag("Payment Webhooks", "Payment provider webhook handlers and transaction confirmation")
|
||
.addTag("Promotions", "Promo codes, campaigns, discounts, and redemption tracking")
|
||
.addTag("Reports", "Revenue analytics, occupancy reports, agent sales, and KPI dashboards")
|
||
.addTag("Round Trip", "Round-trip bookings, return scheduling, combined pricing, and management (NEW)")
|
||
.addTag("Routes", "Route templates with ordered stops, fare rules, and baggage allowance")
|
||
.addTag("Schedule", "Trip schedules, availability windows, status tracking, and timing")
|
||
.addTag("Search", "Trip search, fare quotes, coach types, and real-time availability")
|
||
.addTag("Seat Classes", "Economy Regular, Economy Bed, VIP Bed class configuration and pricing")
|
||
.addTag("Seats", "Seat maps, holds (15-min expiry), releases, blocking, and inventory")
|
||
.addTag("Segment-based Seats", "Multi-leg journey seats, segment allocation, and per-leg availability")
|
||
.addTag("Stations", "Station directory, location data, baggage facilities, and amenities")
|
||
.addTag("Support", "FAQ management, search, live chat conversations, and ticket resolution")
|
||
.addTag("Tickets", "QR/barcode generation, PDF tickets, gate validation, and audit trails")
|
||
.addTag("Transit Stops", "Cross-border journey management, Dire Dawa hub, multi-leg routing (NEW)")
|
||
.addTag("Wallet", "Balance management, top-ups, withdrawals, and transaction ledger")
|
||
//.addServer('http://localhost:4000', 'Development')
|
||
// .addServer("https://api.edr-platform.com", "Production")
|
||
.build();
|
||
|
||
const document = SwaggerModule.createDocument(app, config);
|
||
SwaggerModule.setup("api-docs", app, document, {
|
||
customSiteTitle: "EDR Passenger API",
|
||
swaggerOptions: {
|
||
persistAuthorization: true,
|
||
docExpansion: "none",
|
||
filter: true,
|
||
tagsSorter: "alpha",
|
||
operationsSorter: "alpha",
|
||
},
|
||
});
|
||
|
||
const port = process.env.PORT ?? 4000;
|
||
await app.listen(port);
|
||
console.log(`🚀 EDR Passenger API running on port ${port}`);
|
||
console.log(`📚 Swagger: http://localhost:${port}/api-docs`);
|
||
}
|
||
bootstrap();
|