Merge branch 'dev' of github.com:Tria-plc/edr-platform into freight_feature/usermanagement

This commit is contained in:
Marshal
2026-07-05 22:22:34 +00:00
152 changed files with 7486 additions and 3075 deletions

View File

@@ -0,0 +1,59 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
/**
* Multi-truck customer (self-haul) assignment. Replaces the single
* booking.customer_truck_* fields with a per-booking list of trucks, each
* carrying 12 containers and tracking its own arrival. The legacy
* booking.customer_truck_* columns are kept as a synced booking-level flag
* (any truck assigned / all trucks arrived) so the warehouse exit-gate and
* delivery-approval logic keep working.
*/
export class AddCustomerTruckAssignments1950000000000 implements MigrationInterface {
name = 'AddCustomerTruckAssignments1950000000000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE IF NOT EXISTS freight.customer_truck_assignments (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
booking_id uuid NOT NULL REFERENCES freight.bookings(id) ON DELETE CASCADE,
plate_number varchar(32) NOT NULL,
driver_name varchar(120) NOT NULL,
truck_type varchar(60) NOT NULL,
assigned_at timestamptz NOT NULL DEFAULT now(),
arrived_at timestamptz,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz
);
`);
await queryRunner.query(
`CREATE INDEX IF NOT EXISTS "IDX_customer_truck_assignments_booking" ON freight.customer_truck_assignments (booking_id);`,
);
await queryRunner.query(`
CREATE TABLE IF NOT EXISTS freight.customer_truck_containers (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
assignment_id uuid NOT NULL REFERENCES freight.customer_truck_assignments(id) ON DELETE CASCADE,
booking_id uuid NOT NULL REFERENCES freight.bookings(id) ON DELETE CASCADE,
container_number varchar(64) NOT NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now(),
deleted_at timestamptz
);
`);
await queryRunner.query(
`CREATE INDEX IF NOT EXISTS "IDX_customer_truck_containers_assignment" ON freight.customer_truck_containers (assignment_id);`,
);
// One container number can be loaded onto exactly one truck per booking.
await queryRunner.query(`
CREATE UNIQUE INDEX IF NOT EXISTS "UQ_customer_truck_containers_booking_number"
ON freight.customer_truck_containers (booking_id, container_number)
WHERE deleted_at IS NULL;
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE IF EXISTS freight.customer_truck_containers;`);
await queryRunner.query(`DROP TABLE IF EXISTS freight.customer_truck_assignments;`);
}
}

View File

@@ -0,0 +1,36 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
/**
* Per-container receive tracking. A booking's containers arrive individually
* (on separate self-haul trucks), so each container unit tracks whether it has
* been received into the port and, once staff confirm it, the GRN it belongs to.
* A single GRN covers the containers received together — so if the whole booking
* arrives at once, all its units share one GRN (per-booking GRN).
*/
export class AddContainerReceiptToBookingContainerUnits1960000000000
implements MigrationInterface
{
name = 'AddContainerReceiptToBookingContainerUnits1960000000000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE freight.booking_container_units
ADD COLUMN IF NOT EXISTS received_to_port boolean NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS received_at timestamptz,
ADD COLUMN IF NOT EXISTS grn_number varchar(100)
`);
await queryRunner.query(
`CREATE INDEX IF NOT EXISTS "IDX_booking_container_units_grn" ON freight.booking_container_units (grn_number);`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP INDEX IF EXISTS freight."IDX_booking_container_units_grn";`);
await queryRunner.query(`
ALTER TABLE freight.booking_container_units
DROP COLUMN IF EXISTS received_to_port,
DROP COLUMN IF EXISTS received_at,
DROP COLUMN IF EXISTS grn_number
`);
}
}

View File

@@ -0,0 +1,26 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
/**
* Import self-haul trucks are weighed on leaving. The customer does not
* pre-specify what an import truck takes — staff register the containers loaded
* and the weighed gross when the truck departs. These columns capture that.
*/
export class AddCustomerTruckDeparture1970000000000 implements MigrationInterface {
name = 'AddCustomerTruckDeparture1970000000000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE freight.customer_truck_assignments
ADD COLUMN IF NOT EXISTS gross_weight_kg numeric(14, 2),
ADD COLUMN IF NOT EXISTS departed_at timestamptz
`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE freight.customer_truck_assignments
DROP COLUMN IF EXISTS gross_weight_kg,
DROP COLUMN IF EXISTS departed_at
`);
}
}