mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 04:48:18 +00:00
Merge branch 'dev' of github.com:Tria-plc/edr-platform into freight_feature/usermanagement
# Conflicts: # apps/edr-freight-web/backoffice/src/App.tsx
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
/**
|
||||
* EIMS registration state.
|
||||
*
|
||||
* `freight.invoices` gains the per-invoice registration outcome: which EIMS counter the invoice
|
||||
* consumed, the returned IRN, and the last failure. The partial unique index on `eims_irn` is the
|
||||
* database-level guarantee that one IRN can never be recorded against two invoices, independent of
|
||||
* application logic.
|
||||
*
|
||||
* `freight.eims_system_state` is a single row per MoR system number holding the sequence the
|
||||
* gateway expects: the next `SourceSystem.InvoiceCounter` and the `ReferenceDetails.PreviousIrn`
|
||||
* of the last successful registration. Registration takes `FOR UPDATE` on this row, so the counter
|
||||
* and the IRN chain stay consistent under concurrent submissions.
|
||||
*
|
||||
* The `in_flight_*` columns make a submission a *durable reservation*: the counter is consumed and
|
||||
* the holder recorded in a committed transaction before the HTTP call, so a crash mid-flight leaves
|
||||
* evidence instead of silently freeing the slot for a blind resubmission. `blocked_reason` is set
|
||||
* when a submission ends ambiguously (timeout, network, 5xx) — the IRN is unknown, so every later
|
||||
* document for this system number would chain to a stale `PreviousIrn` and registration stops until
|
||||
* a human resolves it.
|
||||
*
|
||||
* `eims_ack_date` is varchar, not timestamptz: EIMS returns a Java ZonedDateTime string
|
||||
* ("2025-03-21T08:33:32.707753413Z[Etc/UTC]") that no JS date parser accepts. It is stored
|
||||
* verbatim so a compliance value is never mangled by a parse.
|
||||
*/
|
||||
export class EimsInvoiceRegistration3300000000000 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.invoices
|
||||
ADD COLUMN IF NOT EXISTS eims_status varchar(20) NOT NULL DEFAULT 'NOT_SUBMITTED',
|
||||
ADD COLUMN IF NOT EXISTS eims_irn varchar(64),
|
||||
ADD COLUMN IF NOT EXISTS eims_invoice_counter bigint,
|
||||
ADD COLUMN IF NOT EXISTS eims_submitted_at timestamptz,
|
||||
ADD COLUMN IF NOT EXISTS eims_ack_date varchar(64),
|
||||
ADD COLUMN IF NOT EXISTS eims_last_error jsonb
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ux_invoices_eims_irn
|
||||
ON freight.invoices (eims_irn) WHERE eims_irn IS NOT NULL
|
||||
`);
|
||||
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS freight.eims_system_state (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
system_number varchar(32) NOT NULL UNIQUE,
|
||||
next_invoice_counter bigint NOT NULL DEFAULT 1,
|
||||
previous_irn varchar(64),
|
||||
in_flight_invoice_id uuid,
|
||||
in_flight_counter bigint,
|
||||
blocked_reason text,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
deleted_at timestamptz
|
||||
)
|
||||
`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS freight.eims_system_state`);
|
||||
await queryRunner.query(`DROP INDEX IF EXISTS freight.ux_invoices_eims_irn`);
|
||||
await queryRunner.query(`
|
||||
ALTER TABLE freight.invoices
|
||||
DROP COLUMN IF EXISTS eims_status,
|
||||
DROP COLUMN IF EXISTS eims_irn,
|
||||
DROP COLUMN IF EXISTS eims_invoice_counter,
|
||||
DROP COLUMN IF EXISTS eims_submitted_at,
|
||||
DROP COLUMN IF EXISTS eims_ack_date,
|
||||
DROP COLUMN IF EXISTS eims_last_error
|
||||
`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user