mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 16:28:12 +00:00
Package passenger numbers and pricing updates
This commit is contained in:
109
apps/edr-passenger-api/src/seed/segment-fare.seeder.ts
Normal file
109
apps/edr-passenger-api/src/seed/segment-fare.seeder.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { PrismaService } from '../common/prisma.service';
|
||||
|
||||
const SEED_FLAG = 'SEED_SEGMENT_FARES';
|
||||
|
||||
/**
|
||||
* Seeds SegmentFareRule rows for every origin→destination pair on the
|
||||
* Addis Ababa–Djibouti route across all active seat classes.
|
||||
*
|
||||
* Skip-if-loaded: uses Prisma upsert on the unique constraint
|
||||
* (routeId, originStopSequence, destinationStopSequence, seatClassId, nationality).
|
||||
* Re-running is safe — existing rows are updated in-place.
|
||||
*/
|
||||
@Injectable()
|
||||
export class SegmentFareSeeder {
|
||||
private readonly logger = new Logger(SegmentFareSeeder.name);
|
||||
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async run() {
|
||||
if (process.env[SEED_FLAG]?.trim().toLowerCase() !== 'true') {
|
||||
this.logger.log(`Skipping segment fare seed — set ${SEED_FLAG}=true to enable`);
|
||||
return;
|
||||
}
|
||||
|
||||
const route = await this.prisma.route.findFirst({
|
||||
where: { active: true },
|
||||
include: { stops: { orderBy: { sequence: 'asc' } } },
|
||||
});
|
||||
|
||||
if (!route) {
|
||||
this.logger.warn('No active route found — skipping segment fare seed');
|
||||
return;
|
||||
}
|
||||
|
||||
const seatClasses = await this.prisma.seatClass.findMany({
|
||||
where: { isActive: true },
|
||||
});
|
||||
|
||||
if (!seatClasses.length) {
|
||||
this.logger.warn('No active seat classes found — skipping segment fare seed');
|
||||
return;
|
||||
}
|
||||
|
||||
const stops = route.stops;
|
||||
const validFrom = new Date('2025-01-01T00:00:00.000Z');
|
||||
|
||||
// Rate table: ETB minor units per km, keyed by (nationalityType, bedPosition)
|
||||
// null bedPosition = regular seat
|
||||
const rateTable: Record<string, Record<string | 'null', number>> = {
|
||||
LOCAL: { null: 3000, UPPER: 4000, MIDDLE: 5500, LOWER: 6000 },
|
||||
INTERNATIONAL: { null: 6000, UPPER: 8000, MIDDLE: 11000, LOWER: 12000 },
|
||||
};
|
||||
|
||||
let upserted = 0;
|
||||
|
||||
for (const seatClass of seatClasses) {
|
||||
const natType = seatClass.nationalityType ?? 'LOCAL';
|
||||
const bedPos = seatClass.bedPosition ?? 'null';
|
||||
const ratePerKm = rateTable[natType]?.[bedPos] ?? rateTable['LOCAL']['null'];
|
||||
|
||||
for (let i = 0; i < stops.length - 1; i++) {
|
||||
for (let j = i + 1; j < stops.length; j++) {
|
||||
const origin = stops[i];
|
||||
const dest = stops[j];
|
||||
|
||||
// Approximate distance: sum of per-stop distanceKm if available,
|
||||
// otherwise fall back to sequence-gap × 50 km.
|
||||
let distanceKm = 0;
|
||||
for (let k = i; k < j; k++) {
|
||||
distanceKm += stops[k + 1].distanceKm ?? 50;
|
||||
}
|
||||
|
||||
const baseFareMinor = Math.round(distanceKm * ratePerKm);
|
||||
|
||||
await this.prisma.segmentFareRule.upsert({
|
||||
where: {
|
||||
routeId_originStopSequence_destinationStopSequence_seatClassId_nationality: {
|
||||
routeId: route.id,
|
||||
originStopSequence: origin.sequence,
|
||||
destinationStopSequence: dest.sequence,
|
||||
seatClassId: seatClass.id,
|
||||
nationality: natType,
|
||||
},
|
||||
},
|
||||
update: { baseFareMinor, validFrom },
|
||||
create: {
|
||||
routeId: route.id,
|
||||
originStopSequence: origin.sequence,
|
||||
destinationStopSequence: dest.sequence,
|
||||
seatClassId: seatClass.id,
|
||||
nationality: natType,
|
||||
baseFareMinor,
|
||||
currency: 'ETB',
|
||||
validFrom,
|
||||
},
|
||||
});
|
||||
|
||||
upserted++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`Segment fare seed complete — ${upserted} rules upserted ` +
|
||||
`(${stops.length} stops × ${seatClasses.length} seat classes)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user