mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 04:15:43 +00:00
Merge branch 'dev' into freight/fix/type-errors
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm';
|
||||
|
||||
export class AddVehicleCodeAndPlates1810000000002 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
const hasCode = await queryRunner.hasColumn('freight.vehicles', 'code');
|
||||
if (!hasCode) {
|
||||
await queryRunner.addColumn(
|
||||
'freight.vehicles',
|
||||
new TableColumn({ name: 'code', type: 'varchar', isNullable: true }),
|
||||
);
|
||||
}
|
||||
|
||||
const hasPower = await queryRunner.hasColumn('freight.vehicles', 'power_plate_no');
|
||||
if (!hasPower) {
|
||||
await queryRunner.addColumn(
|
||||
'freight.vehicles',
|
||||
new TableColumn({ name: 'power_plate_no', type: 'varchar', isNullable: true }),
|
||||
);
|
||||
}
|
||||
|
||||
const hasTrailer = await queryRunner.hasColumn('freight.vehicles', 'trailer_plate_no');
|
||||
if (!hasTrailer) {
|
||||
await queryRunner.addColumn(
|
||||
'freight.vehicles',
|
||||
new TableColumn({ name: 'trailer_plate_no', type: 'varchar', isNullable: true }),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropColumn('freight.vehicles', 'trailer_plate_no');
|
||||
await queryRunner.dropColumn('freight.vehicles', 'power_plate_no');
|
||||
await queryRunner.dropColumn('freight.vehicles', 'code');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Consolidation is now system-managed: the backend consolidates partial-wagon
|
||||
* container bookings automatically, derived from the container quantities. The
|
||||
* `allow_consolidation` opt-in flag is therefore redundant and is dropped.
|
||||
* `consolidation_partner_id` (the actual pairing link) is unaffected.
|
||||
*/
|
||||
export class DropAllowConsolidation1820000000000 implements MigrationInterface {
|
||||
name = 'DropAllowConsolidation1820000000000';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS allow_consolidation;`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS allow_consolidation BOOLEAN NOT NULL DEFAULT false;`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import { MigrationInterface, QueryRunner, Table, TableIndex } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Multi-route general contracts: a contract may reserve quantity across several
|
||||
* routes. Each (contract, route, container type) is a row here; drawdown orders
|
||||
* reference the route line they drew from via booking_orders.route_line_id.
|
||||
*/
|
||||
export class CreateContractRouteLines1820000000001
|
||||
implements MigrationInterface
|
||||
{
|
||||
name = 'CreateContractRouteLines1820000000001';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.createTable(
|
||||
new Table({
|
||||
schema: 'freight',
|
||||
name: 'contract_route_lines',
|
||||
columns: [
|
||||
{ name: 'id', type: 'uuid', isPrimary: true, generationStrategy: 'uuid', default: 'gen_random_uuid()' },
|
||||
{ name: 'contract_booking_id', type: 'uuid' },
|
||||
{ name: 'origin_yard_id', type: 'uuid' },
|
||||
{ name: 'destination_yard_id', type: 'uuid' },
|
||||
{ name: 'container_type_id', type: 'uuid', isNullable: true },
|
||||
{ name: 'quantity', type: 'numeric', precision: 12, scale: 3 },
|
||||
{ name: 'created_at', type: 'timestamptz', default: 'now()' },
|
||||
{ name: 'updated_at', type: 'timestamptz', default: 'now()' },
|
||||
{ name: 'deleted_at', type: 'timestamptz', isNullable: true },
|
||||
],
|
||||
foreignKeys: [
|
||||
{
|
||||
columnNames: ['contract_booking_id'],
|
||||
referencedSchema: 'freight',
|
||||
referencedTableName: 'bookings',
|
||||
referencedColumnNames: ['id'],
|
||||
onDelete: 'CASCADE',
|
||||
},
|
||||
],
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
await queryRunner.createIndex(
|
||||
'freight.contract_route_lines',
|
||||
new TableIndex({
|
||||
name: 'idx_contract_route_lines_contract',
|
||||
columnNames: ['contract_booking_id'],
|
||||
}),
|
||||
);
|
||||
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.booking_orders ADD COLUMN IF NOT EXISTS route_line_id uuid;`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.booking_orders DROP COLUMN IF EXISTS route_line_id;`,
|
||||
);
|
||||
await queryRunner.dropTable('freight.contract_route_lines', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { MigrationInterface, QueryRunner, Table, TableIndex } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Per-document GL review for the post-counter-sign clearance gate. One row per
|
||||
* required clearance document; GL marks each APPROVED or QUERIED before the
|
||||
* booking can proceed to operations.
|
||||
*/
|
||||
export class CreateBookingDocumentReview1820000000002
|
||||
implements MigrationInterface
|
||||
{
|
||||
name = 'CreateBookingDocumentReview1820000000002';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.createTable(
|
||||
new Table({
|
||||
schema: 'freight',
|
||||
name: 'booking_document_review',
|
||||
columns: [
|
||||
{ name: 'id', type: 'uuid', isPrimary: true, generationStrategy: 'uuid', default: 'gen_random_uuid()' },
|
||||
{ name: 'booking_id', type: 'uuid' },
|
||||
{ name: 'setting_code', type: 'varchar', length: '128' },
|
||||
{ name: 'file_key', type: 'varchar', length: '128' },
|
||||
{ name: 'file_record_id', type: 'uuid', isNullable: true },
|
||||
{ name: 'status', type: 'varchar', length: '20', default: "'PENDING'" },
|
||||
{ name: 'note', type: 'text', isNullable: true },
|
||||
{ name: 'reviewed_by_staff_id', type: 'uuid', isNullable: true },
|
||||
{ name: 'reviewed_at', type: 'timestamptz', isNullable: true },
|
||||
{ name: 'created_at', type: 'timestamptz', default: 'now()' },
|
||||
{ name: 'updated_at', type: 'timestamptz', default: 'now()' },
|
||||
{ name: 'deleted_at', type: 'timestamptz', isNullable: true },
|
||||
],
|
||||
foreignKeys: [
|
||||
{
|
||||
columnNames: ['booking_id'],
|
||||
referencedSchema: 'freight',
|
||||
referencedTableName: 'bookings',
|
||||
referencedColumnNames: ['id'],
|
||||
onDelete: 'CASCADE',
|
||||
},
|
||||
],
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
await queryRunner.createIndex(
|
||||
'freight.booking_document_review',
|
||||
new TableIndex({ name: 'idx_booking_document_review_booking', columnNames: ['booking_id'] }),
|
||||
);
|
||||
await queryRunner.createIndex(
|
||||
'freight.booking_document_review',
|
||||
new TableIndex({ name: 'idx_booking_document_review_status', columnNames: ['status'] }),
|
||||
);
|
||||
await queryRunner.createIndex(
|
||||
'freight.booking_document_review',
|
||||
new TableIndex({
|
||||
name: 'uq_booking_document_review_doc',
|
||||
columnNames: ['booking_id', 'setting_code', 'file_key'],
|
||||
isUnique: true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropTable('freight.booking_document_review', true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Staff price adjustment: an optional override of a booking's computed total,
|
||||
* with who/when/why. When set, the customer sees the adjusted total + a badge.
|
||||
*/
|
||||
export class AddPriceAdjustment1820000000003 implements MigrationInterface {
|
||||
name = 'AddPriceAdjustment1820000000003';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS adjusted_total_amount numeric(14,2);`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS adjusted_by_staff_id uuid;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS adjusted_at timestamptz;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS adjustment_reason text;`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS adjustment_reason;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS adjusted_at;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS adjusted_by_staff_id;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS adjusted_total_amount;`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Fold the `surcharge_types` table into self-describing rates.
|
||||
*
|
||||
* Previously a surcharge was a separate row {trigger_condition, rate_id}. Now
|
||||
* each rate carries its own `applies_to` (friendly category) and `trigger`
|
||||
* (ALWAYS = base freight, otherwise a surcharge condition), plus an optional
|
||||
* `cargo_type_id` for bulk leaf commodities. The rule engine reads triggers
|
||||
* directly off LIVE rates, so the join table is no longer needed.
|
||||
*
|
||||
* This migration:
|
||||
* 1. adds applies_to / trigger / cargo_type_id to rates and backfills them
|
||||
* from the existing rate_type matrix,
|
||||
* 2. repoints booking_cargo_modifier from surcharge_type_id → rate_id
|
||||
* (backfilled via surcharge_types.rate_id),
|
||||
* 3. drops surcharge_types and its FK.
|
||||
*/
|
||||
export class FoldSurchargeTypesIntoRates1820000000004 implements MigrationInterface {
|
||||
name = 'FoldSurchargeTypesIntoRates1820000000004';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// ── 1. New rate columns ────────────────────────────────────────────────
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.rates
|
||||
ADD COLUMN IF NOT EXISTS applies_to varchar(20) NOT NULL DEFAULT 'OTHER',
|
||||
ADD COLUMN IF NOT EXISTS "trigger" varchar(20) NOT NULL DEFAULT 'ALWAYS',
|
||||
ADD COLUMN IF NOT EXISTS cargo_type_id uuid NULL;
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.rates
|
||||
ADD CONSTRAINT "FK_rates_cargo_type_id"
|
||||
FOREIGN KEY (cargo_type_id) REFERENCES freight.cargo_types(id)
|
||||
ON DELETE SET NULL;
|
||||
`);
|
||||
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "IDX_rates_trigger" ON freight.rates ("trigger");`,
|
||||
);
|
||||
|
||||
// ── 1a. Backfill applies_to from the legacy rate_type matrix ────────────
|
||||
await queryRunner.query(`
|
||||
UPDATE freight.rates SET applies_to = CASE
|
||||
WHEN rate_type IN ('CONTAINER_IMPORT','CONTAINER_EXPORT','CONTAINER_WITH_RETURN') THEN 'CONTAINER'
|
||||
WHEN rate_type IN ('BULK_IMPORT','BULK_EXPORT') THEN 'BULK'
|
||||
WHEN rate_type IN ('INTERCITY_CONTAINER','INTERCITY_BULK') THEN 'INTERCITY'
|
||||
WHEN rate_type = 'FIRST_MILE' THEN 'FIRST_MILE'
|
||||
WHEN rate_type = 'LAST_MILE' THEN 'LAST_MILE'
|
||||
ELSE 'OTHER'
|
||||
END;
|
||||
`);
|
||||
|
||||
// ── 1b. Backfill trigger from the legacy rate_type matrix ───────────────
|
||||
await queryRunner.query(`
|
||||
UPDATE freight.rates SET "trigger" = CASE
|
||||
WHEN rate_type = 'HAZARD_SURCHARGE' THEN 'HAZARDOUS'
|
||||
WHEN rate_type = 'REEFER_SURCHARGE' THEN 'REEFER'
|
||||
WHEN rate_type = 'OVERWEIGHT_PER_TON' THEN 'OVERWEIGHT'
|
||||
WHEN rate_type = 'DOUBLE_HANDLING' THEN 'SHIPPING_LINE'
|
||||
WHEN rate_type = 'LASHING' THEN 'CONSOLIDATION'
|
||||
WHEN rate_type = 'CANCELLATION_FEE' THEN 'CANCELLATION'
|
||||
WHEN rate_type = 'DEMURRAGE' THEN 'DEMURRAGE'
|
||||
WHEN rate_type = 'PIL_EXTRA_FEE' THEN 'PIL_EXTRA_FEE'
|
||||
ELSE 'ALWAYS'
|
||||
END;
|
||||
`);
|
||||
|
||||
// Align the trigger to the actual surcharge_types mapping where one exists
|
||||
// (covers any rate wired as a surcharge with a non-obvious rate_type).
|
||||
await queryRunner.query(`
|
||||
UPDATE freight.rates r SET "trigger" = m.trig
|
||||
FROM (
|
||||
SELECT st.rate_id, CASE st.trigger_condition
|
||||
WHEN 'CARGO_FLAG_HAZARDOUS' THEN 'HAZARDOUS'
|
||||
WHEN 'CARGO_FLAG_REEFER' THEN 'REEFER'
|
||||
WHEN 'VGM_EXCEEDS_LIMIT' THEN 'OVERWEIGHT'
|
||||
WHEN 'SHIPPING_LINE_MAPPED' THEN 'SHIPPING_LINE'
|
||||
WHEN 'CONSOLIDATION_ENABLED' THEN 'CONSOLIDATION'
|
||||
ELSE 'ALWAYS'
|
||||
END AS trig
|
||||
FROM freight.surcharge_types st
|
||||
WHERE st.rate_id IS NOT NULL AND st.deleted_at IS NULL
|
||||
) m
|
||||
WHERE r.id = m.rate_id AND m.trig <> 'ALWAYS';
|
||||
`);
|
||||
|
||||
// ── 2. Repoint booking_cargo_modifier to rate_id ────────────────────────
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.booking_cargo_modifier
|
||||
ADD COLUMN IF NOT EXISTS rate_id uuid NULL;
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
UPDATE freight.booking_cargo_modifier bcm
|
||||
SET rate_id = st.rate_id
|
||||
FROM freight.surcharge_types st
|
||||
WHERE bcm.surcharge_type_id = st.id AND st.rate_id IS NOT NULL;
|
||||
`);
|
||||
|
||||
// Rows whose surcharge lost its rate can't be repointed — they reference a
|
||||
// now-defunct surcharge. Remove them so the NOT NULL + FK can be enforced.
|
||||
await queryRunner.query(`
|
||||
DELETE FROM freight.booking_cargo_modifier WHERE rate_id IS NULL;
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.booking_cargo_modifier
|
||||
ALTER COLUMN rate_id SET NOT NULL;
|
||||
`);
|
||||
|
||||
// Drop the old FK + column + index for surcharge_type_id.
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.booking_cargo_modifier
|
||||
DROP CONSTRAINT IF EXISTS "FK_booking_cargo_modifier_surcharge_type_id";
|
||||
`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX IF EXISTS freight."IDX_booking_cargo_modifier_surcharge_type_id";`,
|
||||
);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.booking_cargo_modifier
|
||||
DROP COLUMN IF EXISTS surcharge_type_id;
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.booking_cargo_modifier
|
||||
ADD CONSTRAINT "FK_booking_cargo_modifier_rate_id"
|
||||
FOREIGN KEY (rate_id) REFERENCES freight.rates(id);
|
||||
`);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "IDX_booking_cargo_modifier_rate_id" ON freight.booking_cargo_modifier (rate_id);`,
|
||||
);
|
||||
|
||||
// ── 3. Drop the surcharge_types table ───────────────────────────────────
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.surcharge_types;`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
// Recreate surcharge_types (structure only — data is not restored).
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.surcharge_types (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
code varchar(40) NOT NULL,
|
||||
label varchar(100),
|
||||
trigger_condition varchar(50),
|
||||
rate_id uuid,
|
||||
is_active boolean NOT NULL DEFAULT true,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
deleted_at timestamptz
|
||||
);
|
||||
`);
|
||||
await queryRunner.query(
|
||||
`CREATE UNIQUE INDEX IF NOT EXISTS "IDX_surcharge_types_code" ON freight.surcharge_types (code);`,
|
||||
);
|
||||
|
||||
// Restore booking_cargo_modifier.surcharge_type_id (nullable; not backfilled).
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.booking_cargo_modifier
|
||||
DROP CONSTRAINT IF EXISTS "FK_booking_cargo_modifier_rate_id";
|
||||
`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX IF EXISTS freight."IDX_booking_cargo_modifier_rate_id";`,
|
||||
);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.booking_cargo_modifier
|
||||
ADD COLUMN IF NOT EXISTS surcharge_type_id uuid NULL;
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.booking_cargo_modifier DROP COLUMN IF EXISTS rate_id;
|
||||
`);
|
||||
|
||||
// Drop the new rate columns.
|
||||
await queryRunner.query(
|
||||
`DROP INDEX IF EXISTS freight."IDX_rates_trigger";`,
|
||||
);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.rates DROP CONSTRAINT IF EXISTS "FK_rates_cargo_type_id";
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.rates
|
||||
DROP COLUMN IF EXISTS cargo_type_id,
|
||||
DROP COLUMN IF EXISTS "trigger",
|
||||
DROP COLUMN IF EXISTS applies_to;
|
||||
`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Contract validity window. When the backoffice accepts a price-confirmed
|
||||
* booking, staff define how many days the contract stays valid. The window runs
|
||||
* from the accept moment (valid_from) through valid_from + N days (valid_until).
|
||||
* Outside that window the contract is considered expired.
|
||||
*/
|
||||
export class AddContractValidityWindow1820000000005
|
||||
implements MigrationInterface
|
||||
{
|
||||
name = 'AddContractValidityWindow1820000000005';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS contract_validity_days integer;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS contract_valid_from timestamptz;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS contract_valid_until timestamptz;`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS contract_valid_until;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS contract_valid_from;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS contract_validity_days;`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Booking now captures:
|
||||
* - customs clearing as an explicit flag + the customs clearing agent name
|
||||
* (shown when the service includes customs), and
|
||||
* - first/last-mile pickup & delivery coordinates (lat/lng) alongside the
|
||||
* existing address text, so the map picker can store and restore the pin.
|
||||
*
|
||||
* Shipping line is no longer collected from the booking form; the column stays
|
||||
* for historical data and the (now dormant) shipping-line pricing trigger.
|
||||
*/
|
||||
export class AddCustomsAgentAndMileCoordinates1820000000006
|
||||
implements MigrationInterface
|
||||
{
|
||||
name = 'AddCustomsAgentAndMileCoordinates1820000000006';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.bookings
|
||||
ADD COLUMN IF NOT EXISTS first_mile_pickup_lat numeric(10,7) NULL,
|
||||
ADD COLUMN IF NOT EXISTS first_mile_pickup_lng numeric(10,7) NULL,
|
||||
ADD COLUMN IF NOT EXISTS last_mile_delivery_lat numeric(10,7) NULL,
|
||||
ADD COLUMN IF NOT EXISTS last_mile_delivery_lng numeric(10,7) NULL,
|
||||
ADD COLUMN IF NOT EXISTS customs_clearing_enabled boolean NOT NULL DEFAULT false,
|
||||
ADD COLUMN IF NOT EXISTS customs_clearing_agent varchar(200) NULL;
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.bookings
|
||||
DROP COLUMN IF EXISTS customs_clearing_agent,
|
||||
DROP COLUMN IF EXISTS customs_clearing_enabled,
|
||||
DROP COLUMN IF EXISTS last_mile_delivery_lng,
|
||||
DROP COLUMN IF EXISTS last_mile_delivery_lat,
|
||||
DROP COLUMN IF EXISTS first_mile_pickup_lng,
|
||||
DROP COLUMN IF EXISTS first_mile_pickup_lat;
|
||||
`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* General-contract drawdown order fields:
|
||||
* - booking_order_lines.hazardous_quantity / reefer_quantity — per-order counts
|
||||
* the customer enters when toggling hazardous/reefer; drive the surcharge
|
||||
* rates on the spawned child booking.
|
||||
* - bookings.is_reefer — booking-level refrigerated flag so REEFER_SURCHARGE
|
||||
* applies to a contract order even when the container type is not a reefer.
|
||||
* - contract_route_lines.km — road distance configured with the route; road
|
||||
* orders bill KM × the PER_KM rate.
|
||||
*
|
||||
* NOTE: the shared dev DB has no applied migration history, so these columns
|
||||
* are also hand-applied there. ADD COLUMN IF NOT EXISTS keeps that idempotent.
|
||||
*/
|
||||
export class AddGeneralContractOrderFields1820000000010
|
||||
implements MigrationInterface
|
||||
{
|
||||
name = 'AddGeneralContractOrderFields1820000000010';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.booking_order_lines ADD COLUMN IF NOT EXISTS hazardous_quantity numeric(12,3) NOT NULL DEFAULT 0;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.booking_order_lines ADD COLUMN IF NOT EXISTS reefer_quantity numeric(12,3) NOT NULL DEFAULT 0;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings ADD COLUMN IF NOT EXISTS is_reefer boolean NOT NULL DEFAULT false;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.contract_route_lines ADD COLUMN IF NOT EXISTS km numeric(10,2);`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.contract_route_lines DROP COLUMN IF EXISTS km;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.bookings DROP COLUMN IF EXISTS is_reefer;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.booking_order_lines DROP COLUMN IF EXISTS reefer_quantity;`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE freight.booking_order_lines DROP COLUMN IF EXISTS hazardous_quantity;`,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user