实现企业银行账户与建行制单(corporate-bank-account-payment-order)

这个提交包含在:
2026-08-02 23:36:40 +08:00
父节点 f946d64539
当前提交 5261d2849b
共修改 46 个文件,包含 2751 行新增和 73 行删除
@@ -0,0 +1,78 @@
-- Create bank institution master data.
CREATE TABLE "bank_institutions" (
"id" UUID NOT NULL,
"code" VARCHAR(16) NOT NULL,
"name" VARCHAR(100) NOT NULL,
"enabled" BOOLEAN NOT NULL DEFAULT true,
"archived_at" TIMESTAMP(3),
"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 "bank_institutions_pkey" PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "bank_institutions_code_key" ON "bank_institutions"("code");
CREATE INDEX "idx_bank_institutions_status" ON "bank_institutions"("enabled", "archived_at");
-- Create legal-entity-owned company payment accounts.
CREATE TABLE "payment_accounts" (
"id" UUID NOT NULL,
"legal_entity_id" UUID NOT NULL,
"bank_institution_id" UUID NOT NULL,
"account_name" VARCHAR(120) NOT NULL,
"account_number_encrypted" TEXT NOT NULL,
"enabled" BOOLEAN NOT NULL DEFAULT true,
"archived_at" TIMESTAMP(3),
"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 "payment_accounts_pkey" PRIMARY KEY ("id")
);
CREATE INDEX "idx_payment_accounts_legal_entity_status" ON "payment_accounts"("legal_entity_id", "enabled", "archived_at");
CREATE INDEX "idx_payment_accounts_bank_institution" ON "payment_accounts"("bank_institution_id");
CREATE UNIQUE INDEX "payment_accounts_one_active_per_legal_entity_ux"
ON "payment_accounts"("legal_entity_id")
WHERE "enabled" = true AND "archived_at" IS NULL;
ALTER TABLE "payment_accounts"
ADD CONSTRAINT "payment_accounts_legal_entity_id_fkey"
FOREIGN KEY ("legal_entity_id") REFERENCES "legal_entities"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE "payment_accounts"
ADD CONSTRAINT "payment_accounts_bank_institution_id_fkey"
FOREIGN KEY ("bank_institution_id") REFERENCES "bank_institutions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- Employee bank identity is intentionally nullable; existing free text is not guessed.
ALTER TABLE "employees" ADD COLUMN "bank_institution_id" UUID;
CREATE INDEX "idx_employees_bank_institution" ON "employees"("bank_institution_id");
ALTER TABLE "employees"
ADD CONSTRAINT "employees_bank_institution_id_fkey"
FOREIGN KEY ("bank_institution_id") REFERENCES "bank_institutions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
-- Historical payment batches remain nullable and cannot be order-exported.
ALTER TABLE "payment_batches"
ADD COLUMN "legal_entity_id" UUID,
ADD COLUMN "payment_account_id" UUID,
ADD COLUMN "payment_account_snapshot_json" JSONB,
ADD COLUMN "payment_order_export_count" INTEGER NOT NULL DEFAULT 0,
ADD COLUMN "payment_order_last_exported_at" TIMESTAMP(3),
ADD COLUMN "payment_order_last_exported_by" UUID;
CREATE INDEX "idx_payment_batches_legal_entity" ON "payment_batches"("legal_entity_id");
CREATE INDEX "idx_payment_batches_payment_account" ON "payment_batches"("payment_account_id");
CREATE INDEX "idx_payment_batches_order_exported_by" ON "payment_batches"("payment_order_last_exported_by");
ALTER TABLE "payment_batches"
ADD CONSTRAINT "payment_batches_legal_entity_id_fkey"
FOREIGN KEY ("legal_entity_id") REFERENCES "legal_entities"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "payment_batches"
ADD CONSTRAINT "payment_batches_payment_account_id_fkey"
FOREIGN KEY ("payment_account_id") REFERENCES "payment_accounts"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "payment_batches"
ADD CONSTRAINT "payment_batches_payment_order_last_exported_by_fkey"
FOREIGN KEY ("payment_order_last_exported_by") REFERENCES "employees"("id") ON DELETE SET NULL ON UPDATE CASCADE;
+60
查看文件
@@ -598,6 +598,7 @@ model Employee {
bank_account_encrypted String
bank_name String
bank_institution_id String? @db.Uuid
id_number_encrypted String?
password_hash String
@@ -625,6 +626,7 @@ model Employee {
department Department @relation(fields: [department_id], references: [id], onDelete: Restrict)
legal_entity LegalEntity? @relation(fields: [legal_entity_id], references: [id], onDelete: SetNull)
bank_institution BankInstitution? @relation(fields: [bank_institution_id], references: [id], onDelete: SetNull)
direct_manager Employee? @relation("EmployeeToManager", fields: [direct_manager_id], references: [id], onDelete: Restrict)
subordinates Employee[] @relation("EmployeeToManager")
@@ -642,6 +644,7 @@ model Employee {
paid_reimbursements ReimbursementForm[] @relation("ReimbursementPaidBy")
reimbursement_attachments_uploaded ReimbursementAttachment[] @relation("ReimbursementAttachmentUploader")
payment_batch_receipts_uploaded PaymentBatchReceiptAttachment[] @relation("PaymentBatchReceiptAttachmentUploader")
payment_batches_last_exported PaymentBatch[] @relation("PaymentOrderLastExportedBy")
leave_requests LeaveRequest[]
leave_ledgers LeaveLedger[]
wecom_checkin_records WecomCheckinRecord[]
@@ -724,6 +727,7 @@ model Employee {
@@index([department_id])
@@index([legal_entity_id], map: "idx_employees_legal_entity")
@@index([bank_institution_id], map: "idx_employees_bank_institution")
@@index([direct_manager_id])
@@map("employees")
}
@@ -985,12 +989,56 @@ model LegalEntity {
card_authorizations CardAuthorization[]
asset_cards AssetCard[]
budget_pools BudgetPool[] @relation("BudgetPoolLegalEntity")
payment_accounts PaymentAccount[]
payment_batches PaymentBatch[]
@@index([enabled, archived_at], map: "idx_legal_entities_status")
@@index([default_holiday_calendar_id], map: "idx_legal_entities_default_calendar")
@@map("legal_entities")
}
model BankInstitution {
id String @id @default(uuid()) @db.Uuid
code String @unique @db.VarChar(16)
name String @db.VarChar(100)
enabled Boolean @default(true)
archived_at DateTime?
created_at DateTime @default(now())
created_by String? @db.Uuid
updated_at DateTime @default(now()) @updatedAt
updated_by String? @db.Uuid
employees Employee[]
payment_accounts PaymentAccount[]
@@index([enabled, archived_at], map: "idx_bank_institutions_status")
@@map("bank_institutions")
}
model PaymentAccount {
id String @id @default(uuid()) @db.Uuid
legal_entity_id String @db.Uuid
bank_institution_id String @db.Uuid
account_name String @db.VarChar(120)
account_number_encrypted String
enabled Boolean @default(true)
archived_at DateTime?
created_at DateTime @default(now())
created_by String? @db.Uuid
updated_at DateTime @default(now()) @updatedAt
updated_by String? @db.Uuid
legal_entity LegalEntity @relation(fields: [legal_entity_id], references: [id], onDelete: Restrict)
bank_institution BankInstitution @relation(fields: [bank_institution_id], references: [id], onDelete: Restrict)
payment_batches PaymentBatch[]
@@index([legal_entity_id, enabled, archived_at], map: "idx_payment_accounts_legal_entity_status")
@@index([bank_institution_id], map: "idx_payment_accounts_bank_institution")
@@map("payment_accounts")
}
model CostCenter {
id String @id @default(uuid()) @db.Uuid
legal_entity_id String @db.Uuid
@@ -1856,6 +1904,12 @@ model PaymentBatch {
review_comment String?
secondary_review_comment String?
execution_summary_json Json?
legal_entity_id String? @db.Uuid
payment_account_id String? @db.Uuid
payment_account_snapshot_json Json?
payment_order_export_count Int @default(0)
payment_order_last_exported_at DateTime?
payment_order_last_exported_by String? @db.Uuid
created_at DateTime @default(now())
created_by String? @db.Uuid
@@ -1873,8 +1927,14 @@ model PaymentBatch {
items PaymentBatchItem[]
receipt_attachments PaymentBatchReceiptAttachment[]
legal_entity LegalEntity? @relation(fields: [legal_entity_id], references: [id], onDelete: SetNull)
payment_account PaymentAccount? @relation(fields: [payment_account_id], references: [id], onDelete: SetNull)
payment_order_last_exported_by_employee Employee? @relation("PaymentOrderLastExportedBy", fields: [payment_order_last_exported_by], references: [id], onDelete: SetNull)
@@index([entity_type, status, created_at], map: "idx_payment_batches_entity_status_created")
@@index([legal_entity_id], map: "idx_payment_batches_legal_entity")
@@index([payment_account_id], map: "idx_payment_batches_payment_account")
@@index([payment_order_last_exported_by], map: "idx_payment_batches_order_exported_by")
@@map("payment_batches")
}