mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 21:48:18 +00:00
feat(companies): add Transit Agent service linked to transit-agent roster; forwarder/agent onboarding step, assigned-bookings tab, booking assignment + notify, drop agent validity window
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Links a freight-forwarder company to the transit agent it is registered as.
|
||||
*
|
||||
* An Ethiopian transit agent and a freight forwarder are the same business seen
|
||||
* from two sides: the roster GL uses to assign an officer, and the customer
|
||||
* that signs contracts on other companies' behalf. Until now nothing tied the
|
||||
* two rows together, so a forwarder could onboard under any name and staff had
|
||||
* no way to tell which roster entry it was.
|
||||
*
|
||||
* Two changes:
|
||||
* - `transit_agents.country` — the roster was Djibouti-only, so every existing
|
||||
* row defaults to `DJ`. Only `ET` agents are offered to a forwarder onboarding.
|
||||
* - `companies.transit_agent_id` — nullable: importers and exporters have no
|
||||
* agent, and pre-existing forwarders stay unlinked until they are edited.
|
||||
*/
|
||||
export class CompanyTransitAgentLink3930000000000 implements MigrationInterface {
|
||||
name = 'CompanyTransitAgentLink3930000000000';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.transit_agents
|
||||
ADD COLUMN IF NOT EXISTS country varchar(2) NOT NULL DEFAULT 'DJ'
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS "IDX_transit_agents_country"
|
||||
ON freight.transit_agents (country)
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.companies
|
||||
ADD COLUMN IF NOT EXISTS transit_agent_id uuid
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
CREATE INDEX IF NOT EXISTS "IDX_companies_transit_agent_id"
|
||||
ON freight.companies (transit_agent_id)
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM pg_constraint WHERE conname = 'FK_companies_transit_agent'
|
||||
) THEN
|
||||
ALTER TABLE freight.companies
|
||||
ADD CONSTRAINT "FK_companies_transit_agent"
|
||||
FOREIGN KEY (transit_agent_id)
|
||||
REFERENCES freight.transit_agents (id)
|
||||
ON DELETE SET NULL;
|
||||
END IF;
|
||||
END $$;
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.companies
|
||||
DROP CONSTRAINT IF EXISTS "FK_companies_transit_agent"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
DROP INDEX IF EXISTS freight."IDX_companies_transit_agent_id"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.companies
|
||||
DROP COLUMN IF EXISTS transit_agent_id
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
DROP INDEX IF EXISTS freight."IDX_transit_agents_country"
|
||||
`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.transit_agents
|
||||
DROP COLUMN IF EXISTS country
|
||||
`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
/**
|
||||
* Drops the transit-agent validity window.
|
||||
*
|
||||
* `valid_from` / `valid_to` gated which officers GL could assign, on top of the
|
||||
* `is_active` switch. In practice the dates were never maintained — an agent
|
||||
* whose window lapsed was simply suspended — and with Ethiopian agents now
|
||||
* doubling as the roster a freight forwarder registers itself against, a
|
||||
* date range that silently hides a live business is worse than no range.
|
||||
* `is_active` is the single switch from here on.
|
||||
*
|
||||
* `down()` re-adds the columns as nullable: the dates themselves are gone.
|
||||
*/
|
||||
export class DropTransitAgentValidity3940000000000 implements MigrationInterface {
|
||||
name = 'DropTransitAgentValidity3940000000000';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.transit_agents
|
||||
DROP COLUMN IF EXISTS valid_from,
|
||||
DROP COLUMN IF EXISTS valid_to
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.transit_agents
|
||||
ADD COLUMN IF NOT EXISTS valid_from date,
|
||||
ADD COLUMN IF NOT EXISTS valid_to date
|
||||
`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
/**
|
||||
* Reference sequence for the new `transit_agent` operational profile.
|
||||
*
|
||||
* `company_profiles.type` is a plain varchar, so the role itself needs no DDL;
|
||||
* what it needs is its own reference series (`TA-A00001`, …), minted on
|
||||
* approval exactly like IM/EX/FF. Mirrors the baseline's sequences.
|
||||
*/
|
||||
export class TransitAgentProfileSequence3950000000000 implements MigrationInterface {
|
||||
name = "TransitAgentProfileSequence3950000000000";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
CREATE SEQUENCE IF NOT EXISTS freight.seq_company_profile_ta
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`DROP SEQUENCE IF EXISTS freight.seq_company_profile_ta`,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user