---
title: "Session 13"
description: "Working Railway Reservation System in Python built from the Session 1 to 6 specifications"
image: "https://syntax.theether.in/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://syntax.theether.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Session 13

This session turns the Railway Reservation System (RRS) documents from Sessions 1 to 6 into a program that runs. The scope statement fixed what the system does, the SRS numbered the requirements, the DFDs and ERD fixed the data, the modular design named the modules, and the screen designs fixed the prompts. The program here, `rrs.py`, implements modules 2 to 5 as a console application with JSON persistence, and every function in it traces back to a requirement id. The manual places this session under Software Change Management because the file you write now is the baseline that Session 14 changes under change control. A baseline you cannot trace is a baseline you cannot change safely.

## Objectives

- Implement Train and Schedule Management, Search and Availability, Booking, and Cancellation and Refund from the Session 3 SRS
- Keep one function per menu action so each requirement maps to one named piece of code
- Enforce the business rules in code: 10-digit PNR, at most 6 passengers, no booking after departure, refund slabs, waitlist promotion in order
- Persist data in a JSON file so the demonstration in Session 14 survives a restart
- Record exactly what was left out of the SRS and why, so the limitations are a decision and not an accident

## Problem Statement

Develop "Railway Reservation System" as per specifications given in Sessions 1, 3, 4, 5 and 6.

## Concept

### Specification to code is a mapping, not a rewrite

Do not design again. Open the Session 3 SRS and the Session 5 structure chart and give each functional requirement a function name before writing any code. The traceability matrix below is written first and filled in as the code is written. In the viva the examiner will pick an FR id and ask where it lives; the answer must be a function name.

### Why a console program and a JSON file

The SRS describes a web system with a payment gateway and SMS. A lab session has about three hours. A console menu removes the UI layer, and a JSON file removes the database server, while keeping every entity from the Session 4 ERD as a dictionary with the same attribute names. `rrs_data.json` holds three top-level maps: `trains`, `schedules`, and `bookings`. Route, Coach, Fare and Passenger records nest inside them, which is the same one-to-many structure the ERD draws.

### Business rules belong in one place each

Each rule from the SRS appears in exactly one function: the refund slabs in `cancel_ticket`, the departure check in `book_ticket` and `find_schedules`, the 6-passenger limit as the constant `MAX_PASSENGERS`, PNR uniqueness in `new_pnr`, waitlist order in `promote_waitlist`. When Session 14 changes a rule, the diff touches one function.

### Seat allocation model

A Coach record is `[coach count, seats per coach]` and seat labels are generated on demand as `3A1-17` (class, coach number, seat number). A schedule stores only which labels are taken and by which PNR, so a cancellation frees a label and the next waitlisted PNR takes it. Availability is per class for the whole run, not per segment, and that is listed as a limitation below.

## Traceability Matrix

FR ids follow the numbering of the Session 3 SRS. Module numbers follow Session 5. User Management (FR-1.1 to FR-1.6), Payment, Notification and Reports are not implemented; see Known Limitations.

| Module (Session 5) | FR id (Session 3) | Requirement | Function in rrs.py | DFD process (Session 4) | Screen (Session 6) |
| ------------------ | ----------------- | ----------- | ------------------ | ----------------------- | ------------------ |
| 2 Train and Schedule Management | FR-2.2 | Admin adds a train with type and coaches per class | `add_train` | 2.1 Maintain Train | Add Train form |
| 2 Train and Schedule Management | FR-2.3 | Admin defines the route: stations in sequence with times and distance | `add_train` (route loop) | 2.2 Maintain Route | Add Train form |
| 2 Train and Schedule Management | FR-2.5 | Admin sets a per-km fare for each class | `add_train` (fare loop) | 2.3 Maintain Fare | Add Train form |
| 2 Train and Schedule Management | FR-2.6 | Admin creates a schedule (run) of a train on a date | `add_schedule`, `new_schedule` | 2.4 Create Schedule | Add Schedule form |
| 3 Search and Availability | FR-3.1 | Search trains by source, destination and date | `search_trains`, `find_schedules` | 3.1 Search Trains | Search screen |
| 3 Search and Availability | FR-3.4 | Show seat availability per class, or waitlist position | `check_availability`, `print_availability`, `free_seats` | 3.2 Check Availability | Availability screen |
| 4 Booking | FR-4.2 | Capture up to 6 passengers with age, gender, berth preference | `book_ticket` (passenger loop) | 4.1 Capture Passengers | Booking form |
| 4 Booking | FR-4.5 | Allocate seats in order, or waitlist when none are free | `book_ticket`, `free_seats`, `seat_labels` | 4.2 Allocate Seats | Booking form |
| 4 Booking | FR-4.4 | Compute fare as rate per km x distance x passengers | `book_ticket` (fare line) | 4.3 Compute Fare | Booking form |
| 4 Booking | FR-4.8 | Generate a unique 10-digit PNR and store the booking | `new_pnr`, `book_ticket` | 4.4 Generate PNR | Booking confirmation |
| 4 Booking | FR-4.3 | Refuse booking after the schedule has departed | `book_ticket`, `departure` | 4.1 Capture Passengers | Booking form |
| 5 Cancellation and Refund | FR-5.1 | Cancel a booking by PNR | `cancel_ticket` | 5.1 Cancel Booking | Cancel screen |
| 5 Cancellation and Refund | FR-5.3 | Compute refund by hours before departure | `cancel_ticket` (refund slabs) | 5.2 Compute Refund | Cancel screen |
| 5 Cancellation and Refund | FR-5.5 | Promote the waitlist in order when seats are freed | `promote_waitlist` | 5.3 Promote Waitlist | Cancel screen |
| 4 Booking | FR-4.9 | Look up a booking by PNR | `pnr_lookup`, `print_booking` | 4.5 PNR Enquiry | PNR status screen |
| All | NFR-R3 | Data survives program restart | `load_data`, `save_data` | D1 to D4 data stores | none |
| All | NFR-U2 | Every input validated, no crash on bad input | `ask`, `ask_int`, `ask_date` | none | all forms |

## Program

```python title="rrs.py" file=<rootDir>/public/code/mcs-217/session-13/rrs.py

```

### How to Run

Python 3.8 or later, no packages to install. The first run creates `rrs_data.json` beside the script with two trains (12951 Mumbai Rajdhani and 12137 Punjab Mail) and one schedule each, dated 10 days from today, so a demonstration works immediately. Delete the JSON file to start again.

```text
python3 rrs.py
```

Menu tree: Main menu offers Administrator and Passenger. Administrator: Add train, Add schedule, List trains. Passenger: Search trains, Check availability, Book ticket, Cancel ticket, PNR lookup. Enter 0 to go back.

### Sample Output

Run on 2026-09-26 with Python 3.13 on a fresh data file. Repeated menu listings are removed; each `Choice:` line shows the option typed. The run adds a train with one 1A seat so the waitlist can be shown in a few steps.

```text
Railway Reservation System (Session 13 build)
Choice: 1
Choice: 1
Train number (5 digits): 22222
Train name: Demo Express
Type (Rajdhani/Mail/Express): Express
Number of stations on the route (2-20): 2
Station 1 of 2
  code: AGC
  name: Agra Cantt
  departure HH:MM: 06:10
Station 2 of 2
  code: NDLS
  name: New Delhi
  arrival HH:MM: 09:00
  distance from origin (km): 195
Coaches of class SL (0-10): 0
Coaches of class 3A (0-10): 0
Coaches of class 2A (0-10): 0
Coaches of class 1A (0-10): 1
  seats per 1A coach (1-80): 1
  fare per km for 1A (rupees): 2.50
Train 22222 Demo Express added with 2 stations.
Choice: 2
12137 Punjab Mail      CSMT > BPL > NDLS  classes: SL, 3A
12951 Mumbai Rajdhani  BCT > KOTA > NDLS  classes: 3A, 2A, 1A
22222 Demo Express     AGC > NDLS  classes: 1A
Train number: 22222
Run date (YYYY-MM-DD): 2026-10-08
Schedule S003 created: 22222 on 2026-10-08.
Choice: 0
Choice: 2
Choice: 1
From station code: BCT
To station code: NDLS
Journey date (YYYY-MM-DD): 2026-10-06
S001  12951 Mumbai Rajdhani  dep 17:00  arr 08:35  1384 km
   3A  AVAILABLE 128
   2A  AVAILABLE 48
   1A  AVAILABLE 18
Choice: 3
Schedule id: S001
From station code: BCT
To station code: NDLS
Class (3A/2A/1A): 2A
Number of passengers (1-6): 2
Passenger 1 name: Asha Verma
Passenger 1 age: 34
Passenger 1 gender (M/F/O): F
Passenger 1 berth preference (LB/MB/UB/SL/SU): LB
Passenger 2 name: Rohan Verma
Passenger 2 age: 8
Passenger 2 gender (M/F/O): M
Passenger 2 berth preference (LB/MB/UB/SL/SU): UB
Fare: 1384 km x Rs 2.90/km x 2 passengers = Rs 8027.20  [CONFIRMED]
Confirm booking (Y/N): Y
Booked. PNR 2030868043  status CONFIRMED
PNR 2030868043  12951 Mumbai Rajdhani  2026-10-06  BCT > NDLS  class 2A  fare Rs 8027.20  CONFIRMED
   Asha Verma    34 F  pref LB  seat 2A1-1
   Rohan Verma    8 M  pref UB  seat 2A1-2
Choice: 3
Schedule id: S003
From station code: AGC
To station code: NDLS
Class (1A): 1A
Number of passengers (1-6): 1
Passenger 1 name: Kiran Rao
Passenger 1 age: 41
Passenger 1 gender (M/F/O): M
Passenger 1 berth preference (LB/MB/UB/SL/SU): LB
Fare: 195 km x Rs 2.50/km x 1 passengers = Rs 487.50  [CONFIRMED]
Confirm booking (Y/N): Y
Booked. PNR 9478409106  status CONFIRMED
PNR 9478409106  22222 Demo Express  2026-10-08  AGC > NDLS  class 1A  fare Rs 487.50  CONFIRMED
   Kiran Rao     41 M  pref LB  seat 1A1-1
Choice: 3
Schedule id: S003
From station code: AGC
To station code: NDLS
Class (1A): 1A
Number of passengers (1-6): 1
Passenger 1 name: Meera Nair
Passenger 1 age: 29
Passenger 1 gender (M/F/O): F
Passenger 1 berth preference (LB/MB/UB/SL/SU): LB
Fare: 195 km x Rs 2.50/km x 1 passengers = Rs 487.50  [WAITLISTED]
Confirm booking (Y/N): Y
Booked. PNR 3409290220  status WAITLISTED
PNR 3409290220  22222 Demo Express  2026-10-08  AGC > NDLS  class 1A  fare Rs 487.50  WAITLISTED
   Meera Nair    29 F  pref LB  seat --
Choice: 5
PNR: 9478409106
PNR 9478409106  22222 Demo Express  2026-10-08  AGC > NDLS  class 1A  fare Rs 487.50  CONFIRMED
   Kiran Rao     41 M  pref LB  seat 1A1-1
Choice: 4
PNR: 9478409106
Refund: Rs 427.50 (more than 48 h before departure)
Confirm cancellation (Y/N): Y
Waitlisted PNR 3409290220 promoted to CONFIRMED.
PNR 9478409106 cancelled.
Choice: 5
PNR: 3409290220
PNR 3409290220  22222 Demo Express  2026-10-08  AGC > NDLS  class 1A  fare Rs 487.50  CONFIRMED
   Meera Nair    29 F  pref LB  seat 1A1-1
Choice: 4
PNR: 9478409106
PNR 9478409106 is already cancelled.
Choice: 0
Choice: 0
Bye.
```

Check by hand: fare `1384 x 2.90 x 2 = 8027.20`; refund `487.50 - 60 = 427.50` because departure is 12 days away. Bad input is rejected and the prompt repeats, for example `Schedule id: S999` prints `No such schedule.` and asks again.

## Known Limitations

| SRS item not implemented | Why | Effect on the demonstration |
| ------------------------ | --- | --------------------------- |
| Module 1 User Management (FR-1.1 to FR-1.6) | Role is chosen from a menu; no registration, login or password hash | Anyone can act as Administrator. Acceptable in a single-user lab build |
| Module 6 Payment | Needs an external gateway; the SRS marks it as an external actor | Fare is computed and stored in `total_fare`; no Payment record with mode or txn_ref |
| Module 7 Notification | Needs SMS and email services | The console line printed after booking stands in for the confirmation message |
| Module 8 Reports | Admin-only reads over the same data; no new rule to prove | Occupancy or revenue can be read from `rrs_data.json` by hand |
| Segment-wise availability | A seat is held for the whole run, even for a BCT to KOTA booking | Availability can be under-reported on long routes |
| Berth preference | Stored on the Passenger record but not used in allocation | Seat labels are allocated in order |
| Schedule status changes and delay notices | Out of scope for one user role per module | `status` is always SCHEDULED |
| Concurrency | Single process, file rewritten after each action | Two clerks running two copies could double-book |

## Validation Checklist

Each row is a business rule from the Session 3 SRS with the test performed on the run above.

| Rule | Test | Expected | Observed | Pass |
| ---- | ---- | -------- | -------- | ---- |
| PNR is a 10-digit unique number | Book three tickets | Three distinct 10-digit values | 2030868043, 9478409106, 3409290220 | Yes |
| Max 6 passengers per PNR | Enter 7 at the passenger count prompt | Prompt repeats with range message | `Enter a number from 1 to 6.` | Yes |
| Fare = rate per km x distance x passengers | 2A BCT to NDLS, 2 passengers | 2.90 x 1384 x 2 = 8027.20 | Rs 8027.20 | Yes |
| Seats allocated in order | First 2A booking on S001 | 2A1-1 and 2A1-2 | 2A1-1, 2A1-2 | Yes |
| Waitlist when no seats | Second booking on a 1-seat class | Status WAITLISTED, seat shown as `--` | WAITLISTED | Yes |
| Refund 100% minus clerkage over 48 h | Cancel 12 days before departure | 487.50 - 60 = 427.50 | Rs 427.50 | Yes |
| Refund 50% between 48 h and 12 h | Demo Express scheduled tomorrow, departs 06:10; cancelled at 09:09 today (21 h before) | 50% of 487.50 = 243.75 | Rs 243.75 | Yes |
| No refund under 12 h | 12951 scheduled today, departs 17:00; cancelled at 09:09 (8 h before), fare 4013.60 | Rs 0.00 | Rs 0.00 | Yes |
| Waitlist promoted in order | Cancel the confirmed 1A ticket | First waitlisted PNR gets the freed seat | PNR 3409290220 promoted, seat 1A1-1 | Yes |
| No booking after departure | Admin adds a 12951 run dated yesterday, passenger tries to book it | Refused | `This train has already departed. Booking refused.` | Yes |
| Cancelled PNR cannot be cancelled again | Cancel 9478409106 twice | Second attempt refused | `is already cancelled.` | Yes |
| Data survives restart | Book in one run, look up in the next | Booking found | Found with same seats | Yes |

## Viva Questions

- **Q:** Where is the 48-hour refund rule in the code? **A:** In `cancel_ticket`; hours before departure come from `departure(data, sched)` minus `datetime.now()`.
- **Q:** How is PNR uniqueness guaranteed? **A:** `new_pnr` draws a random 10-digit number and retries while it already exists in `bookings`.
- **Q:** Why is the schedule the unit of booking and not the train? **A:** A train runs on many dates; seats belong to one run. That is the Schedule entity from the Session 4 ERD.
- **Q:** What happens to a waitlisted booking when a confirmed one is cancelled? **A:** `promote_waitlist` takes the first PNR in the class waitlist and allocates freed seats if enough are free for all its passengers.
- **Q:** Why is there no login? **A:** Module 1 was cut for the lab build; role is picked from the menu. It is recorded in Known Limitations, not hidden.
- **Q:** How does the program stop a booking after departure? **A:** `book_ticket` compares `departure()` with the current time and refuses; `find_schedules` also hides departed runs from search.
- **Q:** What is stored in rrs_data.json and how does it map to the ERD? **A:** Three maps: trains (with nested Route, Coach, Fare), schedules (with allocated seats and waitlists), bookings (with nested Passenger and Refund).
- **Q:** Why compute fare from a per-km rate and not a fixed fare per pair of stations? **A:** The Session 4 data dictionary defines Fare as `(train_no, class, rate_per_km)`, so the code follows the data model.

## Common Mistakes

- Building a different system from the one specified. The examiner checks the code against your own SRS; new modules that are not in it earn nothing.
- No traceability. A program without the FR-to-function table cannot be defended in a viva and cannot be changed in Session 14.
- Hard-coding the demonstration data in the program instead of seeding a data file, so the second run cannot show persistence.
- Letting bad input crash the program. Every `input()` goes through `ask`, `ask_int` or `ask_date`.
- Hiding the gaps. Write the Known Limitations table; an honest gap is a design decision, an undiscovered one is a defect.
- Refund computed from booking time instead of departure time. The rule is hours before departure.

## Session Summary

- Traceability matrix from Session 3 FR ids and Session 5 modules to function names
- Full listing of `rrs.py` with the module docstring
- How to run, and the sample session transcript showing add schedule, search, book, waitlist, lookup and cancel with promotion
- Known Limitations table stating what from the SRS is not built and why
- Validation checklist with observed values for every business rule

Source: https://syntax.theether.in/mcs-217/session-13/index.mdx
