Files
edr-platform/apps/edr-passenger-api/REFACTORING_SUMMARY.md

5.1 KiB

Train Reservation System Refactoring - Complete

Refactoring Summary

Successfully refactored the train reservation system from an incorrect tight-coupling model to a flexible, realistic railway architecture.


🔄 Architecture Changes

Before (Incorrect)

TrainService → Trip → Coach → Seat
  • Coaches were permanently bound to specific trips
  • No reusability of physical coaches
  • Inflexible train composition

After (Correct)

Train → TrainSchedule ↔ CoachAssignment ↔ Coach → Seat
  • Train: Logical service entity (e.g., "Express 301")
  • TrainSchedule: Specific journey with date/time
  • Coach: Physical reusable railway carriage
  • CoachAssignment: Join table linking schedules to coaches
  • Seat: Belongs strictly to physical coach

📋 Files Modified

Schema & Database

  • prisma/schema.prisma - Complete entity redesign
  • prisma/seed.ts - Rewritten for new architecture

DTOs

  • fleet/fleet.dto.ts - New Train/Coach/Assignment DTOs
  • schedules/schedules.dto.ts - TrainSchedule DTOs
  • bookings/bookings.dto.ts - scheduleId instead of tripId

Services

  • fleet/fleet.service.ts - Physical coach management
  • fleet/fleet.controller.ts - New endpoints
  • schedules/schedules.service.ts - TrainSchedule operations
  • schedules/schedules.controller.ts - Updated routes
  • bookings/bookings.service.ts - scheduleId references
  • seats/seats.service.ts - CoachAssignment queries
  • search/search.service.ts - TrainSchedule search
  • segments/segments.service.ts - scheduleId throughout
  • segments/enhanced-seats.service.ts - Fixed references
  • passengers/passengers.service.ts - schedule.train
  • live/live.service.ts - TrainSchedule live tracking
  • live/live.controller.ts - scheduleId routes
  • dashboard/dashboard.service.ts - schedule references
  • reports/reports.service.ts - Occupancy with assignments

🗄️ Database Schema Changes

New Models

model Train {
  id       String @id @default(uuid())
  number   String @unique
  name     String
  schedules TrainSchedule[]
}

model TrainSchedule {
  id            String @id @default(uuid())
  trainId       String
  departureAt   DateTime
  train         Train @relation(...)
  coachAssignments CoachAssignment[]
}

model Coach {
  id          String @id @default(uuid())
  coachNumber String @unique  // Physical identifier
  label       String
  seatClassId String
  mode        String  // 'seat', 'bed', 'convertible'
  totalUnits  Int
  seats       Seat[]
  assignments CoachAssignment[]
}

model CoachAssignment {
  id             String @id @default(uuid())
  scheduleId     String
  coachId        String
  positionNumber Int
  schedule       TrainSchedule @relation(...)
  coach          Coach @relation(...)
}

Renamed Models

  • TrainServiceTrain
  • TripTrainSchedule
  • TripStopTime.tripIdscheduleId
  • TripLiveStatus.tripIdscheduleId
  • Booking.tripIdscheduleId
  • SeatHold.tripIdscheduleId
  • MenuItem.tripIdscheduleId
  • JourneySegment.tripIdscheduleId

🎯 Key Benefits

  1. Reusability: Physical coaches can be assigned to different schedules
  2. Flexibility: Train composition can change per schedule
  3. Realistic: Matches real-world railway operations
  4. Maintainability: Clear separation of logical vs physical entities
  5. Scalability: Easy to add/remove coaches from schedules

🚂 Example Usage

Creating a Physical Coach

const coach = await prisma.coach.create({
  data: {
    coachNumber: 'C-A1',
    label: 'A',
    seatClassId: economyClassId,
    mode: 'seat',
    totalUnits: 60,
  },
});

Assigning Coach to Schedule

await prisma.coachAssignment.create({
  data: {
    scheduleId: schedule1.id,
    coachId: coach.id,
    positionNumber: 1,
  },
});

Querying Schedule with Coaches

const schedule = await prisma.trainSchedule.findUnique({
  where: { id: scheduleId },
  include: {
    train: true,
    coachAssignments: {
      include: {
        coach: {
          include: { seats: true, seatClass: true },
        },
      },
      orderBy: { positionNumber: 'asc' },
    },
  },
});

🔑 Seed Data

  • 2 Trains: Express 301, Express 302
  • 6 Physical Coaches: C-A1, C-B1, C-C1, C-A2, C-B2, C-C2
  • 4 Train Schedules: With flexible coach assignments
  • 3 Seat Classes: Economy Regular, Economy Bed, VIP Bed
  • Users: Admin, Passenger (with wallet/loyalty), Agent

Migration Status

Schema pushed to database successfully Seed data populated All services updated All controllers updated All DTOs updated


📝 Notes

  • Coaches are now reusable physical entities
  • Same coach can serve different schedules at different times
  • Seats belong to coaches, not schedules
  • CoachAssignment provides the many-to-many relationship
  • All references to tripId changed to scheduleId
  • All references to service changed to train

Refactoring completed successfully! 🎉