mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 17:08:18 +00:00
feat: ( payment ) implement cbe payment
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
/**
|
||||
* CBE Unified Bill Payment (docs/cbe/CBE_IMPLEMENTATION_PLAN.md §4.1, §5):
|
||||
* - `bill_reference` — the short numeric Bill_Id CBE presents back to us; unique, null for
|
||||
* every non-CBE intent.
|
||||
* - `payer_name` — payer snapshot captured at initiate; fallback for /cbe/query Full_Name.
|
||||
* - `cbe_bill_reference_seq` — backs the 11-digit sequence body of the bill reference.
|
||||
*
|
||||
* DATA SAFETY: purely additive — new nullable columns and a new sequence; no existing rows
|
||||
* or values are touched.
|
||||
*/
|
||||
export class AddCbeBillReference1782300000000 implements MigrationInterface {
|
||||
name = "AddCbeBillReference1782300000000";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "edr_payment"."payment_intent" ADD COLUMN IF NOT EXISTS "bill_reference" varchar(32)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "edr_payment"."payment_intent" ADD COLUMN IF NOT EXISTS "payer_name" varchar(128)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE UNIQUE INDEX IF NOT EXISTS "uq_payment_intent_bill_reference" ON "edr_payment"."payment_intent" ("bill_reference") WHERE "bill_reference" IS NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE SEQUENCE IF NOT EXISTS "edr_payment"."cbe_bill_reference_seq" START 10000001`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`DROP SEQUENCE IF EXISTS "edr_payment"."cbe_bill_reference_seq"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX IF EXISTS "edr_payment"."uq_payment_intent_bill_reference"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "edr_payment"."payment_intent" DROP COLUMN IF EXISTS "payer_name"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "edr_payment"."payment_intent" DROP COLUMN IF EXISTS "bill_reference"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
/**
|
||||
* CBE-protocol audit/idempotency ledger for the Unified Bill Payment integration
|
||||
* (docs/cbe/CBE_IMPLEMENTATION_PLAN.md §4.2).
|
||||
*
|
||||
* - UNIQUE (end_to_end_txn_id, operation): DB-level backstop for the application idempotency
|
||||
* checks — a concurrent duplicate of the same CBE attempt cannot create two rows.
|
||||
* - Partial UNIQUE (cbe_txn_ref) on settled PAYMENTs: blocks Cbe_Txn_Ref replay across bills.
|
||||
*
|
||||
* DATA SAFETY: new table only; nothing existing is touched.
|
||||
*/
|
||||
export class CreateCbeBillOperation1782400000000 implements MigrationInterface {
|
||||
name = "CreateCbeBillOperation1782400000000";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`
|
||||
CREATE TABLE IF NOT EXISTS "edr_payment"."cbe_bill_operation" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"operation" varchar(16) NOT NULL,
|
||||
"bill_id" varchar(32) NOT NULL,
|
||||
"end_to_end_txn_id" varchar(128) NOT NULL,
|
||||
"cbe_txn_ref" varchar(128),
|
||||
"destination_api_name" varchar(64),
|
||||
"intent_id" uuid,
|
||||
"trade_status" varchar(16) NOT NULL,
|
||||
"failure_class" varchar(16),
|
||||
"response_code" varchar(8),
|
||||
"response_description" text,
|
||||
"request_payload" jsonb NOT NULL,
|
||||
"response_payload" jsonb,
|
||||
"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 "uq_cbe_bill_operation_e2e" ON "edr_payment"."cbe_bill_operation" ("end_to_end_txn_id", "operation")`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE UNIQUE INDEX IF NOT EXISTS "uq_cbe_bill_operation_txn_ref" ON "edr_payment"."cbe_bill_operation" ("cbe_txn_ref") WHERE "operation" = 'PAYMENT' AND "trade_status" = 'SUCCESS'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX IF NOT EXISTS "idx_cbe_bill_operation_bill" ON "edr_payment"."cbe_bill_operation" ("bill_id", "operation")`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`DROP TABLE IF EXISTS "edr_payment"."cbe_bill_operation"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user