import { BaseEntity } from "@edr/api-common"; import { Column, Entity } from "typeorm"; /** * One row per MoR system number, holding the sequence state EIMS expects across registrations: * the next `SourceSystem.InvoiceCounter` and the IRN that the next document must chain to via * `ReferenceDetails.PreviousIrn`. * * Registration locks this row `FOR UPDATE` for the duration of the submission, which is what keeps * two concurrent registrations from claiming the same counter or breaking the IRN chain. */ @Entity({ schema: "freight", name: "eims_system_state" }) export class EimsSystemState extends BaseEntity { @Column({ name: "system_number", type: "varchar", length: 32, unique: true }) systemNumber!: string; /** Counter to send on the next registration; advanced only once an attempt has consumed it. */ @Column({ name: "next_invoice_counter", type: "bigint", default: 1 }) nextInvoiceCounter!: number; /** * `DocumentDetails.DocumentNumber` for the next registration. * * Separate from our own `invoiceNumber`, which MoR cannot accept: it validates the field against * `^(0|[1-9][0-9]{0,8})$`, a plain integer. */ @Column({ name: "next_document_number", type: "bigint", default: 1 }) nextDocumentNumber!: number; @Column({ name: "in_flight_document_number", type: "bigint", nullable: true }) inFlightDocumentNumber?: number | null; /** * IRN of the last successful registration; null until the first one succeeds. `text`, not a * fixed varchar — same reasoning as `Invoice.eimsIrn`: a real IRN already overflowed varchar(64). */ @Column({ name: "previous_irn", type: "text", nullable: true }) previousIrn?: string | null; /** * Invoice holding the current reservation. Committed before the HTTP call, so it survives a * crash and blocks a blind resubmission of a document that may already have reached MoR. */ @Column({ name: "in_flight_invoice_id", type: "uuid", nullable: true }) inFlightInvoiceId?: string | null; /** Counter handed to the in-flight submission. */ @Column({ name: "in_flight_counter", type: "bigint", nullable: true }) inFlightCounter?: number | null; /** * Why registration is blocked for this system number. Set when a submission ends ambiguously: * the IRN is unknown, so no further document can chain correctly until it is resolved. */ @Column({ name: "blocked_reason", type: "text", nullable: true }) blockedReason?: string | null; /** * Bulk equivalent of `in_flight_invoice_id` — a whole batch, not one invoice, is outstanding * while MoR processes `POST /v1/bulkRegister` asynchronously. See `EimsBulkRegistrationService`. */ @Column({ name: "in_flight_conversation_id", type: "text", nullable: true }) inFlightConversationId?: string | null; }