feat(finance): add credit and wallet hold lifecycle

This commit is contained in:
2026-09-05 11:54:55 +08:00
parent 6f2b2babc6
commit ba4407eb0d
19 changed files with 587 additions and 70 deletions
@@ -17608,15 +17608,18 @@ SELECT 'PASS' AS migration_status,
'统一增量全部执行完成;父子订单、履约分片、装柜门禁、订舱拖车、报关船期、船司查询、仓库角色、费用、Finance人工财务、公共资源、可靠审计及IAM安全事件结构校验通过' AS message;
-- 一件代发客户资金账户:充值先行,订单消费与冻结/解冻后续接入。
-- 一件代发客户资金账户:实际余额优先,授信额度补足;冻结后结算或解冻。
USE baiyue_finance;
CREATE TABLE IF NOT EXISTS fin_wallet_account (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
customer_id BIGINT UNSIGNED NOT NULL COMMENT '客户ID和隔离键',
currency_code CHAR(3) NOT NULL DEFAULT 'CNY' COMMENT '当前仅CNY',
actual_balance DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '账户实际余额,包含冻结资金',
frozen_balance DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '冻结金额',
available_balance DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '可用余额=实际余额-冻结金额',
frozen_balance DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '冻结总额,包含实际资金与授信冻结',
available_balance DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '总可用余额=实际余额+授信额度-已用授信-冻结总额',
credit_limit DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '授信额度',
credit_used DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '已结算使用的授信',
credit_frozen DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '冻结总额中占用的授信',
version INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '余额乐观锁版本',
created_by BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建操作人ID',
updated_by BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后操作人ID',
@@ -17626,7 +17629,7 @@ CREATE TABLE IF NOT EXISTS fin_wallet_account (
UNIQUE KEY uk_fin_wallet_account_customer (customer_id, currency_code),
CONSTRAINT chk_fin_wallet_account_customer CHECK (customer_id > 0),
CONSTRAINT chk_fin_wallet_account_currency CHECK (currency_code = 'CNY'),
CONSTRAINT chk_fin_wallet_account_balance CHECK (actual_balance >= 0 AND frozen_balance >= 0 AND available_balance >= 0 AND actual_balance = frozen_balance + available_balance)
CONSTRAINT chk_fin_wallet_account_balance CHECK (actual_balance >= 0 AND frozen_balance >= 0 AND available_balance >= 0 AND credit_limit >= 0 AND credit_used >= 0 AND credit_frozen >= 0 AND frozen_balance >= credit_frozen AND actual_balance >= frozen_balance-credit_frozen AND credit_limit >= credit_used+credit_frozen AND available_balance = actual_balance+credit_limit-credit_used-frozen_balance)
) ENGINE=InnoDB COMMENT='客户CNY资金账户主账';
CREATE TABLE IF NOT EXISTS fin_recharge_request (
@@ -17660,11 +17663,14 @@ CREATE TABLE IF NOT EXISTS fin_wallet_ledger (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
customer_id BIGINT UNSIGNED NOT NULL COMMENT '客户ID和隔离键',
business_no VARCHAR(32) NOT NULL COMMENT '账户变动业务编号AC-yyMMdd-####',
change_type VARCHAR(16) NOT NULL COMMENT '变动类型:RECHARGE充值、DEDUCTION扣款、FREEZE冻结、UNFREEZE解冻、CONSUMPTION消费',
change_type VARCHAR(16) NOT NULL COMMENT '变动类型:充值、扣款、冻结、解冻、消费或授信调整',
amount DECIMAL(20,2) NOT NULL COMMENT '带方向变动金额,充值为正、扣款为负',
actual_balance_after DECIMAL(20,2) NOT NULL COMMENT '变动后实际余额',
frozen_balance_after DECIMAL(20,2) NOT NULL COMMENT '变动后冻结金额',
available_balance_after DECIMAL(20,2) NOT NULL COMMENT '变动后可用余额',
credit_limit_after DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '变动后授信额度',
credit_used_after DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '变动后已用授信',
available_credit_after DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '变动后可用授信',
source_type VARCHAR(32) NOT NULL COMMENT 'CLIENT_RECHARGE/MANUAL_RECHARGE/MANUAL_DEDUCTION等',
source_no VARCHAR(128) NULL COMMENT '充值申请号或外部凭证号',
occurred_date DATE NOT NULL COMMENT '业务发生日期',
@@ -17680,9 +17686,66 @@ CREATE TABLE IF NOT EXISTS fin_wallet_ledger (
KEY idx_fin_wallet_ledger_source (customer_id, source_type, source_no),
CONSTRAINT chk_fin_wallet_ledger_customer CHECK (customer_id > 0),
CONSTRAINT chk_fin_wallet_ledger_amount CHECK (amount <> 0),
CONSTRAINT chk_fin_wallet_ledger_balance CHECK (actual_balance_after >= 0 AND frozen_balance_after >= 0 AND available_balance_after >= 0 AND actual_balance_after = frozen_balance_after + available_balance_after)
CONSTRAINT chk_fin_wallet_ledger_balance CHECK (actual_balance_after >= 0 AND frozen_balance_after >= 0 AND available_balance_after >= 0 AND credit_limit_after >= 0 AND credit_used_after >= 0 AND available_credit_after >= 0 AND credit_limit_after >= credit_used_after+available_credit_after AND available_balance_after = actual_balance_after-frozen_balance_after+credit_limit_after-credit_used_after)
) ENGINE=InnoDB COMMENT='客户资金账户不可变余额流水';
CREATE TABLE IF NOT EXISTS fin_wallet_hold (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
customer_id BIGINT UNSIGNED NOT NULL COMMENT '客户ID和隔离键',
business_type VARCHAR(32) NOT NULL COMMENT '调用方业务类型',
business_no VARCHAR(128) NOT NULL COMMENT '调用方业务单号',
amount DECIMAL(20,2) NOT NULL COMMENT '冻结总额',
actual_frozen_amount DECIMAL(20,2) NOT NULL COMMENT '冻结时占用实际资金',
credit_frozen_amount DECIMAL(20,2) NOT NULL COMMENT '冻结时占用授信',
status VARCHAR(16) NOT NULL COMMENT '冻结状态:FROZEN冻结中、SETTLED已结算、RELEASED已释放',
freeze_ledger_id BIGINT UNSIGNED NULL COMMENT '冻结流水ID',
action_ledger_id BIGINT UNSIGNED NULL COMMENT '结算或解冻流水ID',
remark VARCHAR(500) NULL COMMENT '业务说明',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '冻结记录创建时间',
completed_at DATETIME(3) NULL COMMENT '结算或释放完成时间',
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '最后更新时间',
PRIMARY KEY (id),
UNIQUE KEY uk_fin_wallet_hold_business (customer_id,business_type,business_no),
KEY idx_fin_wallet_hold_status (customer_id,status,created_at,id),
CONSTRAINT chk_fin_wallet_hold_customer CHECK (customer_id > 0),
CONSTRAINT chk_fin_wallet_hold_amount CHECK (amount > 0 AND actual_frozen_amount >= 0 AND credit_frozen_amount >= 0 AND amount=actual_frozen_amount+credit_frozen_amount),
CONSTRAINT chk_fin_wallet_hold_status CHECK (status IN ('FROZEN','SETTLED','RELEASED'))
) ENGINE=InnoDB COMMENT='客户资金冻结及结算生命周期';
DROP PROCEDURE IF EXISTS migrate_fin_wallet_credit;
DELIMITER $$
CREATE PROCEDURE migrate_fin_wallet_credit()
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='baiyue_finance' AND TABLE_NAME='fin_wallet_account' AND COLUMN_NAME='credit_limit') THEN
ALTER TABLE fin_wallet_account
ADD COLUMN credit_limit DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '授信额度' AFTER available_balance,
ADD COLUMN credit_used DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '已结算使用的授信' AFTER credit_limit,
ADD COLUMN credit_frozen DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '冻结总额中占用的授信' AFTER credit_used;
END IF;
IF EXISTS (SELECT 1 FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA='baiyue_finance' AND TABLE_NAME='fin_wallet_account' AND CONSTRAINT_NAME='chk_fin_wallet_account_balance' AND CONSTRAINT_TYPE='CHECK') THEN
ALTER TABLE fin_wallet_account DROP CHECK chk_fin_wallet_account_balance;
END IF;
UPDATE fin_wallet_account
SET available_balance=actual_balance+credit_limit-credit_used-frozen_balance;
ALTER TABLE fin_wallet_account ADD CONSTRAINT chk_fin_wallet_account_balance
CHECK (actual_balance >= 0 AND frozen_balance >= 0 AND available_balance >= 0 AND credit_limit >= 0 AND credit_used >= 0 AND credit_frozen >= 0 AND frozen_balance >= credit_frozen AND actual_balance >= frozen_balance-credit_frozen AND credit_limit >= credit_used+credit_frozen AND available_balance = actual_balance+credit_limit-credit_used-frozen_balance);
IF NOT EXISTS (SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='baiyue_finance' AND TABLE_NAME='fin_wallet_ledger' AND COLUMN_NAME='credit_limit_after') THEN
ALTER TABLE fin_wallet_ledger
ADD COLUMN credit_limit_after DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '变动后授信额度' AFTER available_balance_after,
ADD COLUMN credit_used_after DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '变动后已用授信' AFTER credit_limit_after,
ADD COLUMN available_credit_after DECIMAL(20,2) NOT NULL DEFAULT 0 COMMENT '变动后可用授信' AFTER credit_used_after;
END IF;
IF EXISTS (SELECT 1 FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA='baiyue_finance' AND TABLE_NAME='fin_wallet_ledger' AND CONSTRAINT_NAME='chk_fin_wallet_ledger_balance' AND CONSTRAINT_TYPE='CHECK') THEN
ALTER TABLE fin_wallet_ledger DROP CHECK chk_fin_wallet_ledger_balance;
END IF;
ALTER TABLE fin_wallet_ledger ADD CONSTRAINT chk_fin_wallet_ledger_balance
CHECK (actual_balance_after >= 0 AND frozen_balance_after >= 0 AND available_balance_after >= 0 AND credit_limit_after >= 0 AND credit_used_after >= 0 AND available_credit_after >= 0 AND credit_limit_after >= credit_used_after+available_credit_after AND available_balance_after = actual_balance_after-frozen_balance_after+credit_limit_after-credit_used_after);
END$$
DELIMITER ;
CALL migrate_fin_wallet_credit();
DROP PROCEDURE IF EXISTS migrate_fin_wallet_credit;
-- 客户资金账户权限初始化。