Files
edr-platform/apps/edr-freight-api/src/modules/train-sets/entities/train-set-wagon.entity.ts
2026-07-07 12:28:47 +00:00

72 lines
2.8 KiB
TypeScript

import { BaseEntity } from '@edr/api-common';
import { TrainSetWagonStatus } from '@edr/types';
import { Column, Entity, Index, JoinColumn, ManyToOne, OneToMany } from 'typeorm';
import { WagonBookingAllocation } from '../../train-schedules/entities/wagon-booking-allocation.entity';
import { Wagon } from '../../wagons/entities/wagon.entity';
import { WagonType } from '../../wagon-types/entities/wagon-type.entity';
import { TrainSet } from './train-set.entity';
export const TRAIN_SET_WAGON_STATUSES = [
TrainSetWagonStatus.Planned,
TrainSetWagonStatus.Reserved,
TrainSetWagonStatus.Loaded,
TrainSetWagonStatus.Departed,
] as const;
export type TrainSetWagonStatusType = (typeof TRAIN_SET_WAGON_STATUSES)[number];
@Entity({ schema: 'freight', name: 'train_set_wagons' })
@Index(['trainSetId', 'sequenceNo'], { unique: true })
export class TrainSetWagon extends BaseEntity {
@Column({ name: 'train_set_id', type: 'uuid' })
trainSetId!: string;
@ManyToOne(() => TrainSet, (trainSet) => trainSet.wagons, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'train_set_id' })
trainSet?: TrainSet;
@Column({ name: 'wagon_type_id', type: 'uuid' })
wagonTypeId!: string;
@Column({ name: 'physical_wagon_id', type: 'uuid', nullable: true })
physicalWagonId!: string | null;
@ManyToOne(() => Wagon, { nullable: true, onDelete: 'SET NULL' })
@JoinColumn({ name: 'physical_wagon_id' })
physicalWagon?: Wagon | null;
@ManyToOne(() => WagonType, (wagonType) => wagonType.trainSetWagons)
@JoinColumn({ name: 'wagon_type_id' })
wagonType?: WagonType;
@Column({ name: 'sequence_no', type: 'int' })
sequenceNo!: number;
@Column({ name: 'capacity_tons', type: 'numeric', precision: 10, scale: 3 })
capacityTons!: number;
@Column({ name: 'length_meters', type: 'numeric', precision: 10, scale: 3 })
lengthMeters!: number;
@Column({ name: 'assigned_weight_tons', type: 'numeric', precision: 10, scale: 3, default: 0 })
assignedWeightTons!: number;
@Column({ name: 'status', type: 'varchar', length: 20, default: 'PLANNED' })
status!: string;
// ── Leg occupancy (segment corridor bookings) ──────────────────────────────
// A slot may occupy only part of the route: it boards (attaches/loads) at
// board_yard_id and alights (unloads/detaches) at alight_yard_id. NULL on both
// means the slot rides the whole route (legacy full-route bookings). Slots
// whose legs don't overlap coexist without consuming each other's capacity.
@Column({ name: 'board_yard_id', type: 'uuid', nullable: true })
boardYardId?: string | null;
@Column({ name: 'alight_yard_id', type: 'uuid', nullable: true })
alightYardId?: string | null;
@OneToMany(() => WagonBookingAllocation, (allocation) => allocation.trainSetWagon)
allocations?: WagonBookingAllocation[];
}