feat(P25-1/P25-5/P26-1/P26-3/P24-1/P29-4): 落地内部OA够用版后端与试运行能力

关联 Issue: P25-1, P25-2, P25-3, P25-4, P25-5, P26-1, P26-3, P24-1, P24-2, P29-1, P29-2, P29-3, P29-4
这个提交包含在:
2026-03-21 18:03:20 +08:00
父节点 9b7cd818f7
当前提交 e39e41287e
共修改 45 个文件,包含 4571 行新增和 328 行删除
@@ -0,0 +1,313 @@
-- CreateEnum
CREATE TYPE "BudgetControlMode" AS ENUM ('warn', 'block', 'manual_review');
-- CreateEnum
CREATE TYPE "RiskFlagStatus" AS ENUM ('open', 'resolved', 'dismissed');
-- CreateEnum
CREATE TYPE "PaymentBatchStatus" AS ENUM ('draft', 'reviewed', 'executed', 'failed', 'cancelled');
-- CreateEnum
CREATE TYPE "PaymentBatchEntityType" AS ENUM ('reimbursement', 'travel_order');
-- CreateEnum
CREATE TYPE "BudgetControlRuleEntityType" AS ENUM ('all', 'reimbursement', 'purchase_request', 'travel_request');
-- AlterTable
ALTER TABLE "approval_rules" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "asset_cards" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "asset_categories" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "budget_pools" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "card_authorizations" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "card_transactions" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "cost_centers" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "departments" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "document_categories" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "document_sequences" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "employees" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "expense_types" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "feature_flags" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "holiday_calendar_days" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "holiday_calendars" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "integration_bindings" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "integration_outbox" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "integration_sync_states" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "inventory_checks" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "invoice_pool" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "leave_policies" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "leave_requests" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "leave_types" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "legal_entities" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "notification_channels" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "purchase_request_items" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "purchase_requests" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "reimbursement_forms" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "reimbursement_items" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "suppliers" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "travel_orders" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "travel_reconciliation_batches" ALTER COLUMN "id" DROP DEFAULT;
-- AlterTable
ALTER TABLE "travel_reconciliation_items" ALTER COLUMN "id" DROP DEFAULT;
-- AlterTable
ALTER TABLE "travel_request_segments" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "travel_requests" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- AlterTable
ALTER TABLE "workflow_definitions" ADD COLUMN "archived_at" TIMESTAMP(3),
ADD COLUMN "published_at" TIMESTAMP(3),
ADD COLUMN "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN "updated_by" UUID;
-- AlterTable
ALTER TABLE "workflow_instances" ALTER COLUMN "updated_at" SET DEFAULT CURRENT_TIMESTAMP;
-- CreateTable
CREATE TABLE "budget_control_rules" (
"id" UUID NOT NULL,
"name" TEXT NOT NULL,
"entity_type" "BudgetControlRuleEntityType" NOT NULL DEFAULT 'all',
"department_id" UUID,
"legal_entity_id" UUID,
"cost_center_id" UUID,
"expense_type_id" UUID,
"control_mode" "BudgetControlMode" NOT NULL,
"priority" INTEGER NOT NULL DEFAULT 100,
"enabled" BOOLEAN NOT NULL DEFAULT true,
"notes" TEXT,
"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 "budget_control_rules_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "entity_risk_flags" (
"id" UUID NOT NULL,
"entity_type" VARCHAR(32) NOT NULL,
"entity_id" UUID NOT NULL,
"risk_code" VARCHAR(64) NOT NULL,
"level" VARCHAR(16) NOT NULL,
"title" TEXT NOT NULL,
"detail" TEXT,
"source" VARCHAR(32) NOT NULL,
"status" "RiskFlagStatus" NOT NULL DEFAULT 'open',
"payload_json" JSONB,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" UUID,
"resolved_at" TIMESTAMP(3),
"resolved_by" UUID,
CONSTRAINT "entity_risk_flags_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "payment_batches" (
"id" UUID NOT NULL,
"batch_no" VARCHAR(64) NOT NULL,
"entity_type" "PaymentBatchEntityType" NOT NULL,
"name" TEXT NOT NULL,
"status" "PaymentBatchStatus" NOT NULL DEFAULT 'draft',
"default_payment_date" DATE,
"default_payment_channel" VARCHAR(20),
"voucher_prefix" VARCHAR(32),
"review_comment" TEXT,
"execution_summary_json" JSONB,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" UUID,
"reviewed_at" TIMESTAMP(3),
"reviewed_by" UUID,
"executed_at" TIMESTAMP(3),
"executed_by" UUID,
"cancelled_at" TIMESTAMP(3),
"cancelled_by" UUID,
"updated_at" TIMESTAMP(3) NOT NULL,
"updated_by" UUID,
CONSTRAINT "payment_batches_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "payment_batch_items" (
"id" UUID NOT NULL,
"payment_batch_id" UUID NOT NULL,
"entity_id" UUID NOT NULL,
"entity_code" TEXT NOT NULL,
"entity_title" TEXT NOT NULL,
"amount" DECIMAL(14,2) NOT NULL,
"currency_code" VARCHAR(8) NOT NULL DEFAULT 'CNY',
"payment_voucher_no_override" VARCHAR(50),
"payment_date_override" DATE,
"payment_channel_override" VARCHAR(20),
"status" VARCHAR(16) NOT NULL DEFAULT 'pending',
"failure_code" VARCHAR(64),
"failure_message" TEXT,
"snapshot_json" JSONB NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "payment_batch_items_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "portal_announcements" (
"id" UUID NOT NULL,
"title" TEXT NOT NULL,
"summary" TEXT NOT NULL,
"link_url" TEXT,
"starts_at" TIMESTAMP(3),
"ends_at" TIMESTAMP(3),
"enabled" BOOLEAN NOT NULL DEFAULT true,
"priority" INTEGER NOT NULL DEFAULT 100,
"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 "portal_announcements_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "migration_runs" (
"id" UUID NOT NULL,
"run_type" VARCHAR(32) NOT NULL,
"status" VARCHAR(32) NOT NULL DEFAULT 'draft',
"source_filename" TEXT NOT NULL,
"summary_json" JSONB,
"error_json" JSONB,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"created_by" UUID,
CONSTRAINT "migration_runs_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "cutover_scopes" (
"id" UUID NOT NULL,
"scope_type" VARCHAR(32) NOT NULL,
"scope_key" VARCHAR(64) NOT NULL,
"enabled" BOOLEAN NOT NULL DEFAULT false,
"starts_at" TIMESTAMP(3),
"notes" TEXT,
"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 "cutover_scopes_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "idx_budget_control_rules_entity_enabled" ON "budget_control_rules"("entity_type", "enabled", "archived_at");
-- CreateIndex
CREATE INDEX "idx_budget_control_rules_scope" ON "budget_control_rules"("department_id", "legal_entity_id", "cost_center_id");
-- CreateIndex
CREATE INDEX "idx_budget_control_rules_expense_type" ON "budget_control_rules"("expense_type_id");
-- CreateIndex
CREATE INDEX "idx_entity_risk_flags_entity_status" ON "entity_risk_flags"("entity_type", "entity_id", "status");
-- CreateIndex
CREATE INDEX "idx_entity_risk_flags_status_source_created" ON "entity_risk_flags"("status", "source", "created_at");
-- CreateIndex
CREATE UNIQUE INDEX "payment_batches_batch_no_key" ON "payment_batches"("batch_no");
-- CreateIndex
CREATE INDEX "idx_payment_batches_entity_status_created" ON "payment_batches"("entity_type", "status", "created_at");
-- CreateIndex
CREATE INDEX "idx_payment_batch_items_batch_status" ON "payment_batch_items"("payment_batch_id", "status");
-- CreateIndex
CREATE INDEX "idx_payment_batch_items_entity_id" ON "payment_batch_items"("entity_id");
-- CreateIndex
CREATE INDEX "idx_portal_announcements_enabled_priority" ON "portal_announcements"("enabled", "priority", "starts_at", "ends_at");
-- CreateIndex
CREATE INDEX "idx_migration_runs_type_status_created" ON "migration_runs"("run_type", "status", "created_at");
-- CreateIndex
CREATE INDEX "idx_cutover_scopes_enabled_type" ON "cutover_scopes"("enabled", "scope_type");
-- CreateIndex
CREATE UNIQUE INDEX "cutover_scopes_scope_type_scope_key_ux" ON "cutover_scopes"("scope_type", "scope_key");
-- CreateIndex
CREATE INDEX "idx_workflow_definitions_entity_archived" ON "workflow_definitions"("entity_type", "archived_at");
-- RenameForeignKey
ALTER TABLE "travel_reconciliation_items" RENAME CONSTRAINT "travel_reconciliation_items_batch_id_fkey" TO "travel_reconciliation_items_travel_reconciliation_batch_id_fkey";
-- AddForeignKey
ALTER TABLE "payment_batch_items" ADD CONSTRAINT "payment_batch_items_payment_batch_id_fkey" FOREIGN KEY ("payment_batch_id") REFERENCES "payment_batches"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1,55 @@
ALTER TABLE "invoice_pool"
DROP CONSTRAINT IF EXISTS "invoice_pool_status_invariants_chk";
ALTER TABLE "invoice_pool"
ADD CONSTRAINT "invoice_pool_status_invariants_chk"
CHECK (
(
"status" IN ('pending_ocr', 'ocr_failed', 'available')
AND "linked_reimbursement_id" IS NULL
AND "linked_item_id" IS NULL
AND "travel_order_id" IS NULL
AND "archived_reason" IS NULL
AND "archived_at" IS NULL
)
OR (
"status" = 'bound'
AND "archived_reason" IS NULL
AND "archived_at" IS NULL
AND (
(
"linked_reimbursement_id" IS NOT NULL
AND "travel_order_id" IS NULL
)
OR (
"linked_reimbursement_id" IS NULL
AND "travel_order_id" IS NOT NULL
)
)
)
OR (
"status" = 'archived'
AND "archived_reason" IS NOT NULL
AND "archived_at" IS NOT NULL
AND (
(
"archived_reason" = 'used_complete'
AND (
(
"linked_reimbursement_id" IS NOT NULL
AND "travel_order_id" IS NULL
)
OR (
"linked_reimbursement_id" IS NULL
AND "travel_order_id" IS NOT NULL
)
)
)
OR (
"archived_reason" IN ('unused_timeout', 'manual')
AND "linked_reimbursement_id" IS NULL
AND "travel_order_id" IS NULL
)
)
)
);
文件差异内容过多而无法显示 加载差异