feat(intercity): a facility only handles the cargo its equipment can lift

Containers need a reach stacker or gantry, so only Indode, Modjo and Dire Dawa
take them. Bulk needs far less and is handled at all five facilities. Having a
facility was previously enough to load anything, so a container booking through
Sebeta or Adama would have been accepted and then had nothing to lift it.

- yard_facilities gains handles_container / handles_bulk, both defaulting true so
  a facility handles everything unless told otherwise; the seeder states the real
  capability.
- The intercity gate now refuses cargo a facility cannot lift, saying which type,
  not just "no facility". canHandleFreight keeps that rule in the resolver so
  callers cannot get it subtly wrong.
- The intercity list resolves each end against the booking's own freight type, so
  the view flags a container booking routed through a bulk-only yard while the
  train is still coming rather than when the load is refused.

Import/export untouched — the gate is still DOMESTIC-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hagernesh
2026-07-17 11:57:27 +00:00
parent 096e69ba43
commit a5973de6e1
7 changed files with 176 additions and 78 deletions

View File

@@ -0,0 +1,30 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
/**
* A facility handles what its equipment can handle. Containers need a reach
* stacker or gantry, so only Indode, Modjo and Dire Dawa take them; bulk needs
* far less, so all five facilities load and unload it.
*
* Both default true — a facility handles everything unless someone says
* otherwise, which keeps existing rows working and makes the seeder the place
* where the real capability is stated.
*/
export class YardFacilityFreightTypes2320000000000 implements MigrationInterface {
name = 'YardFacilityFreightTypes2320000000000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE freight.yard_facilities
ADD COLUMN IF NOT EXISTS handles_container boolean NOT NULL DEFAULT true,
ADD COLUMN IF NOT EXISTS handles_bulk boolean NOT NULL DEFAULT true
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE freight.yard_facilities
DROP COLUMN IF EXISTS handles_container,
DROP COLUMN IF EXISTS handles_bulk
`);
}
}