add reference field to train schedules and implement unique sequence generation

This commit is contained in:
Marshal
2026-07-07 23:06:44 +00:00
parent 88b1e548a2
commit 9dd9ace313
9 changed files with 299 additions and 21 deletions

View File

@@ -61,6 +61,12 @@ export class TrainSchedule extends BaseEntity {
@Column({ name: 'train_number', type: 'varchar', length: 20, nullable: true })
trainNumber?: string | null;
// Human-facing unique schedule reference (S-YYYY-NNNNN). Shown on the schedule
// list, booking windows, and load lists. Assigned at creation from the highest
// sequence issued this year (see TrainSchedulesRepository.maxReferenceSequence).
@Column({ name: 'reference', type: 'varchar', length: 20, nullable: true, unique: true })
reference?: string | null;
@Column({ name: 'direction', type: 'varchar', length: 10, nullable: true })
direction?: string | null;

View File

@@ -58,4 +58,22 @@ export class TrainSchedulesRepository extends BaseRepository<TrainSchedule> {
): 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);
}
}