import { MigrationInterface, QueryRunner } from 'typeorm'; export class AddSchedulingAllocationEnhancements1750400000000 implements MigrationInterface { name = 'AddSchedulingAllocationEnhancements1750400000000'; public async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS wagons_required NUMERIC(6,2) NULL, ADD COLUMN IF NOT EXISTS scheduling_status VARCHAR(30) NOT NULL DEFAULT 'NOT_SCHEDULED', ADD COLUMN IF NOT EXISTS hold_started_at TIMESTAMPTZ NULL, ADD COLUMN IF NOT EXISTS hold_expires_at TIMESTAMPTZ NULL, ADD COLUMN IF NOT EXISTS scheduled_at TIMESTAMPTZ NULL; `); await queryRunner.query(` ALTER TABLE freight.train_schedules ADD COLUMN IF NOT EXISTS train_number VARCHAR(20) NULL, ADD COLUMN IF NOT EXISTS direction VARCHAR(10) NULL, ADD COLUMN IF NOT EXISTS actual_departure_at TIMESTAMPTZ NULL, ADD COLUMN IF NOT EXISTS actual_arrival_at TIMESTAMPTZ NULL, ADD COLUMN IF NOT EXISTS prepared_by_user_id UUID NULL, ADD COLUMN IF NOT EXISTS checked_by_user_id UUID NULL, ADD COLUMN IF NOT EXISTS max_wagons INT NOT NULL DEFAULT 53; `); await queryRunner.query(` ALTER TABLE freight.train_set_wagons ADD COLUMN IF NOT EXISTS physical_wagon_id UUID NULL, ADD COLUMN IF NOT EXISTS status VARCHAR(20) NOT NULL DEFAULT 'PLANNED'; `); await queryRunner.query(` ALTER TABLE freight.wagon_booking_allocations ADD COLUMN IF NOT EXISTS load_type VARCHAR(20) NULL, ADD COLUMN IF NOT EXISTS status VARCHAR(20) NOT NULL DEFAULT 'PLANNED', ADD COLUMN IF NOT EXISTS confirmed_at TIMESTAMPTZ NULL, ADD COLUMN IF NOT EXISTS confirmed_by_user_id UUID NULL; `); await queryRunner.query(` ALTER TABLE freight.wagon_types ADD COLUMN IF NOT EXISTS equated_length_m NUMERIC(10,3) NULL, ADD COLUMN IF NOT EXISTS tare_weight_tons NUMERIC(10,3) NULL, ADD COLUMN IF NOT EXISTS supports_container BOOLEAN NOT NULL DEFAULT false, ADD COLUMN IF NOT EXISTS max_container_gross_t NUMERIC(10,3) NULL; `); await queryRunner.query(` ALTER TABLE freight.wagons ADD COLUMN IF NOT EXISTS train_set_wagon_id UUID NULL, ADD COLUMN IF NOT EXISTS current_train_schedule_id UUID NULL; `); await queryRunner.query(` ALTER TABLE freight.containers ADD COLUMN IF NOT EXISTS booking_id UUID NULL, ADD COLUMN IF NOT EXISTS wagon_booking_allocation_id UUID NULL, ADD COLUMN IF NOT EXISTS booking_container_id UUID NULL; `); await queryRunner.query(` ALTER TABLE freight.cargoes ADD COLUMN IF NOT EXISTS wagon_booking_allocation_id UUID NULL, ADD COLUMN IF NOT EXISTS booking_id UUID NULL, ADD COLUMN IF NOT EXISTS load_type VARCHAR(20) NULL; `); await queryRunner.query(` ALTER TABLE freight.cargoes ALTER COLUMN container_id DROP NOT NULL; `); await queryRunner.query(` CREATE TABLE IF NOT EXISTS freight.wagon_allocation_container_items ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), wagon_booking_allocation_id UUID NOT NULL, booking_container_id UUID NULL, container_id UUID NULL, container_number VARCHAR(64) NULL, container_type_id UUID NOT NULL, position_on_wagon SMALLINT NULL, seal_number VARCHAR(64) NULL, chassis_number VARCHAR(64) NULL, gross_weight_tons NUMERIC(10,3) NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ NULL, CONSTRAINT fk_waci_allocation FOREIGN KEY (wagon_booking_allocation_id) REFERENCES freight.wagon_booking_allocations(id) ON DELETE CASCADE, CONSTRAINT fk_waci_booking_container FOREIGN KEY (booking_container_id) REFERENCES freight.booking_container(id) ON DELETE SET NULL, CONSTRAINT fk_waci_container FOREIGN KEY (container_id) REFERENCES freight.containers(id) ON DELETE SET NULL, CONSTRAINT fk_waci_container_type FOREIGN KEY (container_type_id) REFERENCES freight.container_types(id) ); `); await queryRunner.query(` CREATE TABLE IF NOT EXISTS freight.wagon_allocation_bulk_loads ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), wagon_booking_allocation_id UUID NOT NULL UNIQUE, booking_id UUID NOT NULL, cargo_type_id UUID NULL, cargo_description TEXT NULL, pricing_unit VARCHAR(20) NOT NULL DEFAULT 'PER_TON', quantity NUMERIC(12,3) NOT NULL DEFAULT 0, weight_tons NUMERIC(10,3) NOT NULL DEFAULT 0, truck_plate_number VARCHAR(32) NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), deleted_at TIMESTAMPTZ NULL, CONSTRAINT fk_wabl_allocation FOREIGN KEY (wagon_booking_allocation_id) REFERENCES freight.wagon_booking_allocations(id) ON DELETE CASCADE, CONSTRAINT fk_wabl_booking FOREIGN KEY (booking_id) REFERENCES freight.bookings(id), CONSTRAINT fk_wabl_cargo_type FOREIGN KEY (cargo_type_id) REFERENCES freight.cargo_types(id) ON DELETE SET NULL ); `); await queryRunner.query(` CREATE INDEX IF NOT EXISTS idx_bookings_scheduling_status ON freight.bookings(scheduling_status); `); await queryRunner.query(` CREATE INDEX IF NOT EXISTS idx_train_schedules_train_number ON freight.train_schedules(train_number); `); await queryRunner.query(` CREATE INDEX IF NOT EXISTS idx_train_set_wagons_physical_wagon ON freight.train_set_wagons(physical_wagon_id); `); await queryRunner.query(` CREATE INDEX IF NOT EXISTS idx_wagons_train_set_wagon_id ON freight.wagons(train_set_wagon_id); `); await queryRunner.query(` CREATE INDEX IF NOT EXISTS idx_wagons_current_train_schedule_id ON freight.wagons(current_train_schedule_id); `); await queryRunner.query(` CREATE INDEX IF NOT EXISTS idx_waci_allocation ON freight.wagon_allocation_container_items(wagon_booking_allocation_id); `); await queryRunner.query(` CREATE INDEX IF NOT EXISTS idx_wabl_booking ON freight.wagon_allocation_bulk_loads(booking_id); `); await queryRunner.query(` DO $$ BEGIN ALTER TABLE freight.train_set_wagons ADD CONSTRAINT fk_train_set_wagons_physical_wagon FOREIGN KEY (physical_wagon_id) REFERENCES freight.wagons(id) ON DELETE SET NULL; EXCEPTION WHEN duplicate_object THEN NULL; END $$; `); await queryRunner.query(` DO $$ BEGIN ALTER TABLE freight.wagons ADD CONSTRAINT fk_wagons_train_set_wagon FOREIGN KEY (train_set_wagon_id) REFERENCES freight.train_set_wagons(id) ON DELETE SET NULL; EXCEPTION WHEN duplicate_object THEN NULL; END $$; `); await queryRunner.query(` DO $$ BEGIN ALTER TABLE freight.wagons ADD CONSTRAINT fk_wagons_current_train_schedule FOREIGN KEY (current_train_schedule_id) REFERENCES freight.train_schedules(id) ON DELETE SET NULL; EXCEPTION WHEN duplicate_object THEN NULL; END $$; `); await queryRunner.query(` DO $$ BEGIN ALTER TABLE freight.containers ADD CONSTRAINT fk_containers_booking FOREIGN KEY (booking_id) REFERENCES freight.bookings(id) ON DELETE SET NULL; EXCEPTION WHEN duplicate_object THEN NULL; END $$; `); await queryRunner.query(` DO $$ BEGIN ALTER TABLE freight.containers ADD CONSTRAINT fk_containers_wagon_allocation FOREIGN KEY (wagon_booking_allocation_id) REFERENCES freight.wagon_booking_allocations(id) ON DELETE SET NULL; EXCEPTION WHEN duplicate_object THEN NULL; END $$; `); await queryRunner.query(` DO $$ BEGIN ALTER TABLE freight.containers ADD CONSTRAINT fk_containers_booking_container FOREIGN KEY (booking_container_id) REFERENCES freight.booking_container(id) ON DELETE SET NULL; EXCEPTION WHEN duplicate_object THEN NULL; END $$; `); await queryRunner.query(` DO $$ BEGIN ALTER TABLE freight.cargoes ADD CONSTRAINT fk_cargoes_wagon_allocation FOREIGN KEY (wagon_booking_allocation_id) REFERENCES freight.wagon_booking_allocations(id) ON DELETE SET NULL; EXCEPTION WHEN duplicate_object THEN NULL; END $$; `); await queryRunner.query(` DO $$ BEGIN ALTER TABLE freight.cargoes ADD CONSTRAINT fk_cargoes_booking FOREIGN KEY (booking_id) REFERENCES freight.bookings(id) ON DELETE SET NULL; EXCEPTION WHEN duplicate_object THEN NULL; END $$; `); await queryRunner.query(` UPDATE freight.wagon_types SET equated_length_m = 1.3, tare_weight_tons = 22.4, supports_container = true, max_container_gross_t = 30.48 WHERE code = 'NW5'; `); await queryRunner.query(` UPDATE freight.wagon_types SET equated_length_m = 1.6, tare_weight_tons = 25.2, supports_container = false WHERE code = 'PW2'; `); await queryRunner.query(` UPDATE freight.wagon_types SET equated_length_m = 1.5, tare_weight_tons = 25.2, supports_container = false WHERE code = 'KW2'; `); await queryRunner.query(` UPDATE freight.wagon_types SET equated_length_m = 1.3, tare_weight_tons = 23.4, supports_container = false WHERE code = 'CW3'; `); await queryRunner.query(` UPDATE freight.wagon_types SET equated_length_m = 1.3, tare_weight_tons = 24.8, supports_container = false WHERE code = 'CW4'; `); } public async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`DROP TABLE IF EXISTS freight.wagon_allocation_bulk_loads;`); await queryRunner.query(`DROP TABLE IF EXISTS freight.wagon_allocation_container_items;`); await queryRunner.query(` ALTER TABLE freight.cargoes ALTER COLUMN container_id SET NOT NULL; `); await queryRunner.query(` ALTER TABLE freight.bookings DROP COLUMN IF EXISTS wagons_required, DROP COLUMN IF EXISTS scheduling_status, DROP COLUMN IF EXISTS hold_started_at, DROP COLUMN IF EXISTS hold_expires_at, DROP COLUMN IF EXISTS scheduled_at; `); await queryRunner.query(` ALTER TABLE freight.train_schedules DROP COLUMN IF EXISTS train_number, DROP COLUMN IF EXISTS direction, DROP COLUMN IF EXISTS actual_departure_at, DROP COLUMN IF EXISTS actual_arrival_at, DROP COLUMN IF EXISTS prepared_by_user_id, DROP COLUMN IF EXISTS checked_by_user_id, DROP COLUMN IF EXISTS max_wagons; `); await queryRunner.query(` ALTER TABLE freight.train_set_wagons DROP COLUMN IF EXISTS physical_wagon_id, DROP COLUMN IF EXISTS status; `); await queryRunner.query(` ALTER TABLE freight.wagon_booking_allocations DROP COLUMN IF EXISTS load_type, DROP COLUMN IF EXISTS status, DROP COLUMN IF EXISTS confirmed_at, DROP COLUMN IF EXISTS confirmed_by_user_id; `); await queryRunner.query(` ALTER TABLE freight.wagon_types DROP COLUMN IF EXISTS equated_length_m, DROP COLUMN IF EXISTS tare_weight_tons, DROP COLUMN IF EXISTS supports_container, DROP COLUMN IF EXISTS max_container_gross_t; `); await queryRunner.query(` ALTER TABLE freight.wagons DROP COLUMN IF EXISTS train_set_wagon_id, DROP COLUMN IF EXISTS current_train_schedule_id; `); await queryRunner.query(` ALTER TABLE freight.containers DROP COLUMN IF EXISTS booking_id, DROP COLUMN IF EXISTS wagon_booking_allocation_id, DROP COLUMN IF EXISTS booking_container_id; `); await queryRunner.query(` ALTER TABLE freight.cargoes DROP COLUMN IF EXISTS wagon_booking_allocation_id, DROP COLUMN IF EXISTS booking_id, DROP COLUMN IF EXISTS load_type; `); } }