feat(P20T3-1,P20T3-2,P20T3-3): 对账批次引擎与ERP摘要出站后端

这个提交包含在:
2026-03-11 16:55:04 +08:00
父节点 41a169ea41
当前提交 fc0295249e
共修改 15 个文件,包含 3733 行新增和 28 行删除
@@ -0,0 +1,116 @@
ALTER TYPE "DocumentCategoryEntityType" ADD VALUE IF NOT EXISTS 'travel_reconciliation_batch';
DO $$ BEGIN
CREATE TYPE "TravelReconciliationBatchStatus" AS ENUM ('draft', 'reconciled');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
CREATE TYPE "TravelReconciliationItemKind" AS ENUM ('order', 'orphan_transaction');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
CREATE TYPE "TravelReconciliationMatchStatus" AS ENUM (
'matched',
'amount_mismatch',
'currency_mismatch',
'missing_transaction',
'duplicate_charge',
'orphan_transaction',
'reversed_after_payment'
);
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
DO $$ BEGIN
CREATE TYPE "TravelReconciliationResolutionStatus" AS ENUM ('pending', 'confirmed');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
CREATE TABLE IF NOT EXISTS "travel_reconciliation_batches" (
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
"batch_no" TEXT NOT NULL,
"legal_entity_id" UUID NOT NULL,
"cost_center_id" UUID,
"period_start" DATE NOT NULL,
"period_end" DATE NOT NULL,
"status" "TravelReconciliationBatchStatus" NOT NULL DEFAULT 'draft',
"summary_json" JSONB NOT NULL,
"confirmed_at" TIMESTAMP(3),
"confirmed_by" UUID,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" UUID,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_by" UUID,
CONSTRAINT "travel_reconciliation_batches_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX IF NOT EXISTS "travel_reconciliation_batches_batch_no_key" ON "travel_reconciliation_batches"("batch_no");
CREATE INDEX IF NOT EXISTS "idx_travel_reconciliation_batches_status_period" ON "travel_reconciliation_batches"("status", "period_start", "period_end");
CREATE INDEX IF NOT EXISTS "idx_travel_reconciliation_batches_legal_cost_center" ON "travel_reconciliation_batches"("legal_entity_id", "cost_center_id");
CREATE INDEX IF NOT EXISTS "idx_travel_reconciliation_batches_confirmed_by" ON "travel_reconciliation_batches"("confirmed_by");
ALTER TABLE "travel_reconciliation_batches"
ADD CONSTRAINT "travel_reconciliation_batches_legal_entity_id_fkey"
FOREIGN KEY ("legal_entity_id") REFERENCES "legal_entities"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE "travel_reconciliation_batches"
ADD CONSTRAINT "travel_reconciliation_batches_cost_center_id_fkey"
FOREIGN KEY ("cost_center_id") REFERENCES "cost_centers"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "travel_reconciliation_batches"
ADD CONSTRAINT "travel_reconciliation_batches_confirmed_by_fkey"
FOREIGN KEY ("confirmed_by") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE;
CREATE TABLE IF NOT EXISTS "travel_reconciliation_items" (
"id" UUID NOT NULL DEFAULT gen_random_uuid(),
"travel_reconciliation_batch_id" UUID NOT NULL,
"item_kind" "TravelReconciliationItemKind" NOT NULL,
"travel_request_id" UUID,
"travel_order_id" UUID,
"card_transaction_id" UUID,
"match_status" "TravelReconciliationMatchStatus" NOT NULL,
"resolution_status" "TravelReconciliationResolutionStatus" NOT NULL DEFAULT 'pending',
"order_amount" DECIMAL(14,2),
"transaction_amount" DECIMAL(14,2),
"currency" VARCHAR(8) NOT NULL DEFAULT 'CNY',
"anomaly_code" VARCHAR(32),
"snapshot_json" JSONB NOT NULL,
"confirmed_at" TIMESTAMP(3),
"confirmed_by" UUID,
"confirm_note" TEXT,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "travel_reconciliation_items_pkey" PRIMARY KEY ("id")
);
CREATE INDEX IF NOT EXISTS "idx_travel_reconciliation_items_batch_resolution" ON "travel_reconciliation_items"("travel_reconciliation_batch_id", "resolution_status");
CREATE INDEX IF NOT EXISTS "idx_travel_reconciliation_items_request" ON "travel_reconciliation_items"("travel_request_id");
CREATE INDEX IF NOT EXISTS "idx_travel_reconciliation_items_order" ON "travel_reconciliation_items"("travel_order_id");
CREATE INDEX IF NOT EXISTS "idx_travel_reconciliation_items_transaction" ON "travel_reconciliation_items"("card_transaction_id");
CREATE INDEX IF NOT EXISTS "idx_travel_reconciliation_items_confirmed_by" ON "travel_reconciliation_items"("confirmed_by");
ALTER TABLE "travel_reconciliation_items"
ADD CONSTRAINT "travel_reconciliation_items_batch_id_fkey"
FOREIGN KEY ("travel_reconciliation_batch_id") REFERENCES "travel_reconciliation_batches"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "travel_reconciliation_items"
ADD CONSTRAINT "travel_reconciliation_items_travel_request_id_fkey"
FOREIGN KEY ("travel_request_id") REFERENCES "travel_requests"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "travel_reconciliation_items"
ADD CONSTRAINT "travel_reconciliation_items_travel_order_id_fkey"
FOREIGN KEY ("travel_order_id") REFERENCES "travel_orders"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "travel_reconciliation_items"
ADD CONSTRAINT "travel_reconciliation_items_card_transaction_id_fkey"
FOREIGN KEY ("card_transaction_id") REFERENCES "card_transactions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "travel_reconciliation_items"
ADD CONSTRAINT "travel_reconciliation_items_confirmed_by_fkey"
FOREIGN KEY ("confirmed_by") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE;