mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
import { BaseRepository } from '@edr/api-common';
|
|
import { Injectable } from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { EntityManager, Repository } from 'typeorm';
|
|
|
|
import { TrainSchedule, TrainScheduleStatus } from './entities/train-schedule.entity';
|
|
|
|
@Injectable()
|
|
export class TrainSchedulesRepository extends BaseRepository<TrainSchedule> {
|
|
constructor(
|
|
@InjectRepository(TrainSchedule)
|
|
repository: Repository<TrainSchedule>,
|
|
) {
|
|
super(repository);
|
|
}
|
|
|
|
private repo(manager?: EntityManager) {
|
|
return manager ? manager.getRepository(TrainSchedule) : this.repository;
|
|
}
|
|
|
|
findByIdWithFullGraph(id: string, manager?: EntityManager): Promise<TrainSchedule | null> {
|
|
return this.repo(manager).findOne({
|
|
where: { id },
|
|
relations: {
|
|
// Yards carry the route's display name; without them formatRouteLabel
|
|
// 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 },
|
|
wagons: {
|
|
wagonType: true,
|
|
physicalWagon: true,
|
|
allocations: {
|
|
booking: { company: true, bookingContainers: { containerType: true } },
|
|
containerItems: true,
|
|
},
|
|
},
|
|
},
|
|
originStation: true,
|
|
destinationStation: true,
|
|
scheduleBookings: {
|
|
booking: {
|
|
company: true,
|
|
originYard: true,
|
|
destinationYard: true,
|
|
bookingContainers: { containerType: true },
|
|
cargoType: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Light fetch for human-facing labels (notifications): reference, train
|
|
* number, departure and the two station names — none of the composition
|
|
* graph {@link findByIdWithFullGraph} drags in.
|
|
*/
|
|
findByIdWithStations(id: string): Promise<TrainSchedule | null> {
|
|
return this.repository.findOne({
|
|
where: { id },
|
|
relations: { originStation: true, destinationStation: true },
|
|
});
|
|
}
|
|
|
|
async updateStatus(
|
|
id: string,
|
|
status: TrainScheduleStatus,
|
|
extra?: Partial<TrainSchedule>,
|
|
manager?: EntityManager,
|
|
): Promise<void> {
|
|
await this.repo(manager).update(id, { status, ...extra } as never);
|
|
}
|
|
|
|
/**
|
|
* Highest NNNNN sequence already issued for `S-<year>-…` references. Includes
|
|
* soft-deleted rows so the next number never reuses one still occupying the
|
|
* unique index (see the same pattern on BookingsRepository).
|
|
*/
|
|
async maxReferenceSequence(year: number): Promise<number> {
|
|
const row = await this.repository
|
|
.createQueryBuilder('schedule')
|
|
.withDeleted()
|
|
.select(
|
|
"COALESCE(MAX(CAST(SUBSTRING(schedule.reference FROM '[0-9]+$') AS int)), 0)",
|
|
'max',
|
|
)
|
|
.where('schedule.reference LIKE :prefix', { prefix: `S-${year}-%` })
|
|
.getRawOne<{ max: string | number | null }>();
|
|
return Number(row?.max ?? 0);
|
|
}
|
|
}
|