This commit is contained in:
Marshal
2026-07-10 11:08:30 +00:00
parent 45629e436e
commit 10111c9e01
4 changed files with 24 additions and 6 deletions

View File

@@ -43,11 +43,26 @@ export class Route extends BaseEntity {
* Human-readable route label: yard names, not yard codes — "Addis Ababa → Dire Dawa",
* not "ADDIS_ABABA → DIRE_DAWA". A yard's display name is its `label`; `code` is the
* machine identifier and is only a fallback for a yard missing one.
*
* When the route's milestones are loaded (with their yards), the label is the FULL
* ordered corridor — "Addis Ababa → Adama → Dire Dawa" — since milestones already
* include the origin (first) and destination (last). Without milestones it falls
* back to origin → destination.
*/
export function formatRouteLabel(route: {
originYard?: { code?: string; label?: string } | null;
destinationYard?: { code?: string; label?: string } | null;
milestones?: Array<{
sequenceNo: number;
yard?: { code?: string; label?: string } | null;
}> | null;
}): string {
const stops = [...(route.milestones ?? [])]
.sort((a, b) => a.sequenceNo - b.sequenceNo)
.map((m) => m.yard?.label ?? m.yard?.code)
.filter((name): name is string => Boolean(name));
if (stops.length >= 2) return stops.join(' → ');
const origin = route.originYard?.label ?? route.originYard?.code ?? 'Origin';
const dest = route.destinationYard?.label ?? route.destinationYard?.code ?? 'Destination';
return `${origin}${dest}`;

View File

@@ -23,8 +23,9 @@ export class TrainSchedulesRepository extends BaseRepository<TrainSchedule> {
where: { id },
relations: {
// Yards carry the route's display name; without them formatRouteLabel
// degrades to the literal "Origin → Destination".
route: { originYard: true, destinationYard: true },
// degrades to the literal "Origin → Destination". Milestones (with
// their yards) give it the full corridor path.
route: { originYard: true, destinationYard: true, milestones: { yard: true } },
trainSet: {
locomotive: true,
locomotives: { locomotive: true },

View File

@@ -746,8 +746,9 @@ export class BookingBatchService implements OnModuleInit {
trainSet: { locomotive: true },
originStation: true,
destinationStation: true,
// Yards supply the route's display name for `routeName` below.
route: { originYard: true, destinationYard: true },
// Yards supply the route's display name for `routeName` below;
// milestones (with yards) give it the full corridor path.
route: { originYard: true, destinationYard: true, milestones: { yard: true } },
},
order: { [sortBy]: sortOrder } as never,
skip: (page - 1) * pageSize,

View File

@@ -2645,8 +2645,9 @@ export class TrainSchedulingService {
const schedules = await this.trainSchedulesRepository.findAll({
relations: {
trainSet: { locomotive: true, locomotives: { locomotive: true } },
// Yards carry the route's display name used by mapScheduleListItem.
route: { originYard: true, destinationYard: true },
// Yards carry the route's display name used by mapScheduleListItem;
// milestones (with yards) let it show the full corridor path.
route: { originYard: true, destinationYard: true, milestones: { yard: true } },
originStation: true,
destinationStation: true,
scheduleBookings: { booking: true },