Files
edr-platform/apps/edr-freight-api/src/modules/train-scheduling/entities/train-scheduling-global-rules.entity.ts
marshal 75b75e3d4e feat: add contract extension request functionality
- Implemented  method in  to allow customers to request an extension for expired contracts.
- Added  component in  for users to initiate extension requests.
- Updated  to include logic for handling extension requests for expired contracts.
- Enhanced  to display extension request options and status.
- Created migration to add  and  columns to the contracts table.
- Added unit tests for contract extension request and handling in .
- Defined DTOs for request and extension in .
- Updated types in  to include new fields related to contract extensions.
2026-09-06 12:33:40 +00:00

113 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { BaseEntity } from '@edr/api-common';
import { Column, Entity } from 'typeorm';
@Entity({ schema: 'freight', name: 'train_scheduling_global_rules' })
export class TrainSchedulingGlobalRules extends BaseEntity {
/**
* LEGACY — `max_train_length_meters`, `max_train_weight_tons` and
* `max_20ft_container_weight_tons` are no longer read by planning: train
* weight/length come from locomotive configuration and per-box ceilings from
* the rule engine's weight limit rules (`max_capacity_tons`). Kept only so
* existing rows keep loading.
*/
@Column({
name: 'max_train_length_meters',
type: 'numeric',
precision: 10,
scale: 2,
default: 760,
})
maxTrainLengthMeters!: number;
@Column({
name: 'max_train_weight_tons',
type: 'numeric',
precision: 10,
scale: 3,
default: 3500,
})
maxTrainWeightTons!: number;
@Column({ name: 'max_wagons_per_train', type: 'int', default: 53 })
maxWagonsPerTrain!: number;
@Column({
name: 'max_20ft_container_weight_tons',
type: 'numeric',
precision: 8,
scale: 3,
default: 30,
})
max20ftContainerWeightTons!: number;
@Column({
name: 'max_20ft_pair_weight_diff_tons',
type: 'numeric',
precision: 8,
scale: 3,
default: 10,
})
max20ftPairWeightDiffTons!: number;
/** Days before departure the single import booking-window day falls on. */
@Column({ name: 'import_window_lead_days', type: 'int', default: 3 })
importWindowLeadDays!: number;
/** Hours before departure an export booking becomes acceptable (FCFS, no window cycle). */
@Column({ name: 'export_booking_lead_hours', type: 'int', default: 24 })
exportBookingLeadHours!: number;
/** Local (Africa/Addis_Ababa) hour at which the import window opens on its window day. */
@Column({ name: 'window_open_hour', type: 'int', default: 8 })
windowOpenHour!: number;
/**
* Local (Africa/Addis_Ababa) hour the booking desk shuts each day. A not-yet-full
* train whose next cycle would reopen at/after this hour pauses until the next
* morning's windowOpenHour. Set equal to windowOpenHour for a 24-hour desk
* (the default).
*/
@Column({ name: 'window_close_hour', type: 'int', default: 8 })
windowCloseHour!: number;
// Stored in hours; 4 decimals so sub-minute UI durations (4 min = 0.0667h)
// are exact. See WidenWindowDurationHoursPrecision migration.
@Column({
name: 'window_duration_hours',
type: 'numeric',
precision: 6,
scale: 4,
default: 3,
})
windowDurationHours!: number;
/** Max time staff have to accept booking documents after the window closes. */
@Column({ name: 'doc_review_minutes', type: 'int', default: 30 })
docReviewMinutes!: number;
/** Pay window for IMPORT/DOMESTIC bookings (also feeds the window reopen delay). */
@Column({ name: 'payment_window_minutes', type: 'int', default: 60 })
paymentWindowMinutes!: number;
/** Pay window for EXPORT bookings — tunable independently of import. */
@Column({ name: 'export_payment_window_minutes', type: 'int', default: 60 })
exportPaymentWindowMinutes!: number;
/**
* Minutes before departure the IMPORT/DOMESTIC booking window shuts. When set,
* the window's close (first cycle and every reopen) is capped at
* `departure this`, instead of the default open+duration/departure cap.
* NULL or 0 = no offset (previous behaviour).
*/
@Column({ name: 'import_close_offset_minutes', type: 'int', nullable: true })
importCloseOffsetMinutes?: number | null;
/**
* Minutes before departure the EXPORT FCFS booking window shuts. When set, the
* export window closes at `departure this` instead of at departure. NULL or
* 0 = no offset (export closes at departure, previous behaviour).
*/
@Column({ name: 'export_close_offset_minutes', type: 'int', nullable: true })
exportCloseOffsetMinutes?: number | null;
}