mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
264 lines
9.5 KiB
TypeScript
264 lines
9.5 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.
|
||
|
||
## 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
|
||
|
||
### 👤 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)
|
||
|
||
### 💳 Payment Integration
|
||
1. **Ethiopian Payment Methods:**
|
||
- **Telebirr** - Ethiopia's leading mobile money
|
||
- **CBE Birr** - Commercial Bank of Ethiopia
|
||
- **eBirr** - Electronic payment gateway
|
||
|
||
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
|
||
- Class-based seating (Economy Regular, Economy Bed, VIP Bed)
|
||
|
||
### 🎟️ Ticketing
|
||
- QR code and barcode generation
|
||
- PDF ticket generation
|
||
- Gate validation with audit logs
|
||
- Offline validation support
|
||
- Multi-passenger tickets
|
||
|
||
### 🏆 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
|
||
|
||
### 🌍 Internationalization
|
||
- Multi-language support (English, Amharic, French, Oromo)
|
||
- Locale-based responses
|
||
- Currency formatting (ETB, DJF, USD)
|
||
|
||
### 👨💼 Agent Operations
|
||
- Counter booking
|
||
- Shift management
|
||
- Commission tracking
|
||
- Cash reconciliation
|
||
|
||
## 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/ebirr\` (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, and commission tracking")
|
||
.addTag("Auth", "User registration, login, and profile management")
|
||
.addTag("Booking", "Complete booking lifecycle: create, modify, cancel")
|
||
.addTag("Dashboard", "Aggregated dashboard data for home screen")
|
||
.addTag("Fare Engine", "Distance-based fare calculator with multi-currency support")
|
||
.addTag("Fayda Verification", "Ethiopian national ID verification via government API")
|
||
.addTag("Fleet", "Train services, coaches, and seat configurations")
|
||
.addTag("Fraud Detection", "Fraud monitoring, alerts, and user blocking")
|
||
.addTag("Live Tracking", "Real-time trip status, delays, and station crowds")
|
||
.addTag("Loyalty", "Points accumulation, tiers, and reward redemption")
|
||
.addTag("Notifications", "Multi-channel notifications: email, SMS, push")
|
||
.addTag("Passengers", "Passenger registration, verification, and profiles")
|
||
.addTag("Payment", "Payment processing, intents, and refunds")
|
||
.addTag("Payment Webhooks", "Payment provider webhook handlers")
|
||
.addTag("Promotions", "Promo codes, campaigns, and discount management")
|
||
.addTag("Reports", "Sales reports, occupancy analytics, and metrics")
|
||
.addTag("Routes", "Route templates with stops and fare rules")
|
||
.addTag("Schedule", "Trip schedules, availability, and status updates")
|
||
.addTag("Search", "Trip search, availability checks, and fare quotes")
|
||
.addTag("Seat Classes", "Seat class management: Economy, VIP configurations")
|
||
.addTag("Seats", "Seat maps, holds, releases, and blocking")
|
||
.addTag("Segment-based Seats", "Segment-level seat allocation and availability")
|
||
.addTag("Stations", "Station directory and information")
|
||
.addTag("Support", "FAQ management and live chat support")
|
||
.addTag("Tickets", "QR ticket generation, PDFs, and gate validation")
|
||
.addTag("Wallet", "Wallet balance, top-ups, and transaction ledger")
|
||
.addTag("Config", "System configuration and settings")
|
||
//.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();
|