Seatmap rendering and other updates

This commit is contained in:
Stephanos A
2026-06-09 15:22:27 +03:00
parent bf8cc7e6cf
commit c2bab6cae8
30 changed files with 2020 additions and 329 deletions

View File

@@ -3,8 +3,8 @@ import * as bcrypt from 'bcrypt';
const prisma = new PrismaClient();
const EDR_ROUTE_ID = 'route-edr-main';
const TRAIN_ID = 'train-001';
const EDR_ROUTE_ID = 'route-edr-101';
const TRAIN_ID = 'EDR-101';
async function seedSystemUsers() {
console.log('👥 Seeding system users...');
@@ -140,9 +140,9 @@ async function seedStations() {
async function seedCoachTypesAndClasses() {
console.log('\n🚂 Seeding coach types and seat classes...');
const coachTypes = [
{ code: 'ECO', name: 'Economy', type: 'passenger' },
{ code: 'ECO_BED', name: 'Economy Bed', type: 'sleeper' },
{ code: 'VIP_BED', name: 'VIP Bed', type: 'sleeper' },
{ code: 'HSC', name: 'Hard Seat Coach', type: 'Economy Regular' },
{ code: 'HBC', name: 'Hard Bed Coach', type: 'Economy Bed' },
{ code: 'SBC', name: 'Soft Bed Coach', type: 'VIP Bed' },
];
for (const ct of coachTypes) {
@@ -154,10 +154,12 @@ async function seedCoachTypesAndClasses() {
}
const seatClasses = [
{ name: 'ECONOMY_REGULAR', coachCode: 'ECO', baseFareMinor: 35000 },
{ name: 'ECONOMY_WINDOW', coachCode: 'ECO', baseFareMinor: 37000 },
{ name: 'ECONOMY_BED', coachCode: 'ECO_BED', baseFareMinor: 55000 },
{ name: 'VIP_BED', coachCode: 'VIP_BED', baseFareMinor: 85000 },
{ name: 'VIP Bed Lower', coachCode: 'SBC', baseFareMinor: 900 },
{ name: 'VIP Bed Upper', coachCode: 'SBC', baseFareMinor: 800 },
{ name: 'Economy Bed Upper', coachCode: 'HBC', baseFareMinor: 600 },
{ name: 'Economy Bed Middle', coachCode: 'HBC', baseFareMinor: 550 },
{ name: 'Economy Bed Lower', coachCode: 'HBC', baseFareMinor: 500 },
{ name: 'Economy Regular', coachCode: 'HSC', baseFareMinor: 250 },
];
for (const sc of seatClasses) {
@@ -177,20 +179,19 @@ async function seedRoute() {
const lastStation = await prisma.station.findUnique({ where: { code: 'NAG' } });
const route = await prisma.route.upsert({
where: { code: 'EDR-MAIN' },
where: { code: 'EDR-101' },
update: {},
create: {
id: EDR_ROUTE_ID,
code: 'EDR-MAIN',
name: 'Ethio-Djibouti Railway Main Route',
description: 'Main route connecting Sebeta to Nagad',
effectiveFrom: new Date('2024-01-01'),
code: 'EDR-101',
name: 'Sebeta - Dire Dawa',
description: 'Outbound local route from Sebeta to Dire Dawa',
effectiveFrom: new Date('2026-01-01'),
effectiveUntil: new Date('2034-12-31'),
active: true,
},
});
const stationCodes = ['SBT', 'LEB', 'BSH', 'MOJ', 'ADM', 'MTE', 'MIS', 'BIK', 'DRE', 'ADG', 'AYS', 'DAW', 'ALS', 'HOL', 'NAG'];
const stationCodes = ['SBT', 'LEB', 'BSH', 'MOJ', 'ADM', 'MTE', 'MIS', 'BIK', 'DRE'];
for (let i = 0; i < stationCodes.length; i++) {
const station = await prisma.station.findUnique({ where: { code: stationCodes[i] } });
await prisma.routeStop.upsert({
@@ -204,17 +205,14 @@ async function seedRoute() {
async function seedCoaches() {
console.log('\n🚃 Seeding coaches and seats...');
const ecoCoachType = await prisma.coachType.findUnique({ where: { id: 'ECO' } });
const ecoBedCoachType = await prisma.coachType.findUnique({ where: { id: 'ECO_BED' } });
const vipBedCoachType = await prisma.coachType.findUnique({ where: { id: 'VIP_BED' } });
const ecoCoachType = await prisma.coachType.findUnique({ where: { id: 'HSC' } });
const ecoBedCoachType = await prisma.coachType.findUnique({ where: { id: 'HBC' } });
const vipBedCoachType = await prisma.coachType.findUnique({ where: { id: 'SBC' } });
const coaches = [
{ number: 'C-001', coachTypeId: ecoCoachType!.id, arrangement: '2+2', capacity: 48 },
{ number: 'C-002', coachTypeId: ecoCoachType!.id, arrangement: '2+2', capacity: 48 },
{ number: 'C-003', coachTypeId: ecoCoachType!.id, arrangement: '2+2', capacity: 48 },
{ number: 'C-004', coachTypeId: ecoBedCoachType!.id, arrangement: '2+2', capacity: 32 },
{ number: 'C-005', coachTypeId: ecoBedCoachType!.id, arrangement: '2+2', capacity: 32 },
{ number: 'C-006', coachTypeId: vipBedCoachType!.id, arrangement: '1+1', capacity: 16 },
{ number: 'HSC-0001', coachTypeId: ecoCoachType!.id, arrangement: '3+2', capacity: 40 },
{ number: 'HBC-0001', coachTypeId: ecoBedCoachType!.id, arrangement: '3+0', capacity: 66 },
{ number: 'SBC-0001', coachTypeId: vipBedCoachType!.id, arrangement: '2+0', capacity: 120 },
];
let totalSeats = 0;
@@ -229,9 +227,16 @@ async function seedCoaches() {
for (let row = 1; row <= Math.ceil(coach.capacity / 2); row++) {
for (const col of ['A', 'B', 'C', 'D']) {
if (seatIndex <= coach.capacity) {
let bedPosition: string | null = null;
if (c.coachTypeId === ecoBedCoachType!.id || c.coachTypeId === vipBedCoachType!.id) {
if (row % 3 === 1) bedPosition = 'upper';
else if (row % 3 === 2) bedPosition = 'middle';
else bedPosition = 'lower';
}
await prisma.seat.upsert({
where: { coachId_seatNumber: { coachId: c.id, seatNumber: seatIndex.toString() } },
update: {},
update: { bedPosition },
create: {
coachId: c.id,
seatNumber: seatIndex.toString(),
@@ -239,6 +244,7 @@ async function seedCoaches() {
col,
isWindow: col === 'A' || col === 'D',
isAisle: col === 'B' || col === 'C',
bedPosition,
},
});
seatIndex++;
@@ -258,15 +264,14 @@ async function seedTrips() {
create: { id: TRAIN_ID, number: 'EDR-001', name: 'Djibouti Express' },
});
const route = await prisma.route.findUnique({ where: { code: 'EDR-MAIN' } });
const route = await prisma.route.findUnique({ where: { code: 'EDR-101' } });
const firstStation = await prisma.station.findUnique({ where: { code: 'SBT' } });
const lastStation = await prisma.station.findUnique({ where: { code: 'NAG' } });
const lastStation = await prisma.station.findUnique({ where: { code: 'DIR' } });
const coaches = await prisma.coach.findMany();
const now = new Date();
const schedules = [];
// Bulk prepare schedule data
for (let d = 0; d < 30; d++) {
const tripDate = new Date(now);
tripDate.setDate(tripDate.getDate() + d);
@@ -287,12 +292,10 @@ async function seedTrips() {
});
}
// Bulk create schedules
const createdSchedules = await Promise.all(
schedules.map(s => prisma.trainSchedule.create({ data: s }))
);
// Bulk create coach assignments and live status
const coachAssignments = [];
const liveStatuses = [];