- 实现账户管理改进设计文档中的所有核心功能 - 三科目余额管理 (个人余额、劳动报酬、冻结余额) - 交易状态机 (created → pending → bank_submitted → success/failed/timeout → reversed) - 三键幂等体系 (JZTxId/BankTxId/SourceKey) - 优先级扣款规则 (先个人后劳动) - 在途资金管理 (可用→在途→结转/回退) - 三账对账闭环 (总账 = 银行账 + 在途净额) - 补偿服务域 (超时检测、重试、死信队列) - 虚拟银行模拟器用于业务测试 - 完整的集成测试套件 (133 个测试全部通过) - Docker 容器化部署配置 - 前端 Vue3 + TypeScript 项目结构
307 lines
15 KiB
SQL
307 lines
15 KiB
SQL
-- 银行账户管理系统 - 数据库初始化脚本
|
|
-- 创建时间: 2026-01-05
|
|
|
|
-- =====================================================
|
|
-- 账户域表
|
|
-- =====================================================
|
|
|
|
-- 实体账户
|
|
CREATE TABLE IF NOT EXISTS physical_account (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
account_no VARCHAR(32) UNIQUE NOT NULL COMMENT '银行账号',
|
|
bank_code VARCHAR(20) NOT NULL COMMENT '银行代码',
|
|
bank_name VARCHAR(100) COMMENT '银行名称',
|
|
consistency_mode ENUM('strong', 'eventual') DEFAULT 'eventual' COMMENT '一致性模式',
|
|
outbound_control ENUM('receive_only', 'online_bank', 'token') DEFAULT 'online_bank' COMMENT '出金管控模式',
|
|
status ENUM('active', 'frozen', 'closed') DEFAULT 'active' COMMENT '账户状态',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
INDEX idx_bank_code (bank_code),
|
|
INDEX idx_status (status)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='实体账户表';
|
|
|
|
-- 虚拟子账户
|
|
CREATE TABLE IF NOT EXISTS virtual_sub_account (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
physical_account_id BIGINT NOT NULL COMMENT '所属实体账户ID',
|
|
account_code VARCHAR(32) UNIQUE NOT NULL COMMENT '子账户编号',
|
|
account_type ENUM('settlement', 'management', 'temporary') NOT NULL COMMENT '账户类型',
|
|
valid_from DATETIME COMMENT '有效期开始',
|
|
valid_to DATETIME COMMENT '有效期结束',
|
|
status ENUM('active', 'frozen', 'closed') DEFAULT 'active' COMMENT '账户状态',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
FOREIGN KEY (physical_account_id) REFERENCES physical_account(id),
|
|
INDEX idx_physical_account (physical_account_id),
|
|
INDEX idx_account_type (account_type),
|
|
INDEX idx_status (status),
|
|
INDEX idx_valid_to (valid_to)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='虚拟子账户表';
|
|
|
|
-- 账户控制配置
|
|
CREATE TABLE IF NOT EXISTS account_control (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
physical_account_id BIGINT UNIQUE NOT NULL COMMENT '实体账户ID',
|
|
reconciliation_interval INT DEFAULT 60 COMMENT '对账频率(分钟)',
|
|
direct_connect_config JSON COMMENT '银企直连配置',
|
|
third_party_config JSON COMMENT '第三方支付配置',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
FOREIGN KEY (physical_account_id) REFERENCES physical_account(id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='账户控制配置表';
|
|
|
|
-- 子账户池
|
|
CREATE TABLE IF NOT EXISTS sub_account_pool (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
physical_account_id BIGINT NOT NULL COMMENT '所属实体账户ID',
|
|
name VARCHAR(100) NOT NULL COMMENT '池名称',
|
|
valid_from DATETIME NOT NULL COMMENT '有效期开始',
|
|
valid_to DATETIME NOT NULL COMMENT '有效期结束',
|
|
auto_close_rule JSON COMMENT '自动销户规则',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
FOREIGN KEY (physical_account_id) REFERENCES physical_account(id),
|
|
INDEX idx_physical_account (physical_account_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='子账户池表';
|
|
|
|
-- =====================================================
|
|
-- 账务域表
|
|
-- =====================================================
|
|
|
|
-- 会计科目
|
|
CREATE TABLE IF NOT EXISTS accounting_subject (
|
|
code VARCHAR(20) PRIMARY KEY COMMENT '科目代码',
|
|
name VARCHAR(100) NOT NULL COMMENT '科目名称',
|
|
category ENUM('asset', 'liability', 'income', 'expense') NOT NULL COMMENT '科目类别',
|
|
direction_default TINYINT DEFAULT 1 COMMENT '默认增加方向: 1=借方增加, -1=贷方增加',
|
|
parent_code VARCHAR(20) COMMENT '父科目代码',
|
|
level INT DEFAULT 1 COMMENT '科目级别',
|
|
INDEX idx_category (category),
|
|
INDEX idx_parent_code (parent_code)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会计科目表';
|
|
|
|
-- 初始化会计科目
|
|
INSERT INTO accounting_subject (code, name, category, direction_default, parent_code, level) VALUES
|
|
('1001', '现金', 'asset', 1, NULL, 1),
|
|
('1002', '银行存款', 'asset', 1, NULL, 1),
|
|
('1003', '在途资金', 'asset', 1, NULL, 1),
|
|
('2001', '客户存款', 'liability', -1, NULL, 1),
|
|
('2002', '待清算款项', 'liability', -1, NULL, 1),
|
|
('3001', '手续费收入', 'income', -1, NULL, 1),
|
|
('4001', '利息支出', 'expense', 1, NULL, 1)
|
|
ON DUPLICATE KEY UPDATE name = VALUES(name);
|
|
|
|
-- 账户余额
|
|
CREATE TABLE IF NOT EXISTS account_balance (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
account_id BIGINT NOT NULL COMMENT '账户ID',
|
|
account_type ENUM('physical', 'virtual') NOT NULL COMMENT '账户类型',
|
|
system_balance DECIMAL(20,2) DEFAULT 0 COMMENT '系统余额',
|
|
bank_balance DECIMAL(20,2) DEFAULT 0 COMMENT '银行余额',
|
|
available_balance DECIMAL(20,2) DEFAULT 0 COMMENT '可支配余额',
|
|
frozen_amount DECIMAL(20,2) DEFAULT 0 COMMENT '冻结金额',
|
|
transit_amount DECIMAL(20,2) DEFAULT 0 COMMENT '在途金额',
|
|
version INT DEFAULT 0 COMMENT '乐观锁版本',
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
UNIQUE KEY uk_account (account_id, account_type),
|
|
INDEX idx_account_type (account_type)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='账户余额表';
|
|
|
|
-- 余额组成
|
|
CREATE TABLE IF NOT EXISTS balance_component (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
balance_id BIGINT NOT NULL COMMENT '余额ID',
|
|
subject_code VARCHAR(20) NOT NULL COMMENT '科目代码',
|
|
amount DECIMAL(20,2) DEFAULT 0 COMMENT '金额',
|
|
FOREIGN KEY (balance_id) REFERENCES account_balance(id),
|
|
INDEX idx_balance_id (balance_id),
|
|
INDEX idx_subject_code (subject_code)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='余额组成表';
|
|
|
|
-- 记账分录(凭证头)
|
|
CREATE TABLE IF NOT EXISTS ledger_entry (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
entry_no VARCHAR(32) UNIQUE NOT NULL COMMENT '分录编号',
|
|
txn_no VARCHAR(32) NOT NULL COMMENT '关联交易号',
|
|
post_date DATE NOT NULL COMMENT '记账日期',
|
|
post_time DATETIME NOT NULL COMMENT '记账时间',
|
|
description VARCHAR(200) COMMENT '摘要描述',
|
|
status ENUM('pending', 'posted', 'reversed') DEFAULT 'pending' COMMENT '状态',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
INDEX idx_txn_no (txn_no),
|
|
INDEX idx_post_date (post_date),
|
|
INDEX idx_status (status)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='记账分录表';
|
|
|
|
-- 分录明细(凭证行)
|
|
CREATE TABLE IF NOT EXISTS ledger_line (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
entry_id BIGINT NOT NULL COMMENT '分录ID',
|
|
account_id BIGINT NOT NULL COMMENT '账户ID',
|
|
account_type ENUM('physical', 'virtual') NOT NULL COMMENT '账户类型',
|
|
subject_code VARCHAR(20) NOT NULL COMMENT '科目代码',
|
|
direction ENUM('debit', 'credit') NOT NULL COMMENT '借贷方向',
|
|
amount DECIMAL(20,2) NOT NULL COMMENT '金额',
|
|
FOREIGN KEY (entry_id) REFERENCES ledger_entry(id),
|
|
INDEX idx_entry_id (entry_id),
|
|
INDEX idx_account (account_id, account_type),
|
|
INDEX idx_subject_code (subject_code)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='分录明细表';
|
|
|
|
-- =====================================================
|
|
-- 交易域表
|
|
-- =====================================================
|
|
|
|
-- 系统交易
|
|
CREATE TABLE IF NOT EXISTS system_transaction (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
txn_no VARCHAR(32) UNIQUE NOT NULL COMMENT '交易号',
|
|
txn_type VARCHAR(20) NOT NULL COMMENT '交易类型',
|
|
from_account_id BIGINT COMMENT '转出账户ID',
|
|
to_account_id BIGINT COMMENT '转入账户ID',
|
|
amount DECIMAL(20,2) NOT NULL COMMENT '金额',
|
|
status ENUM('pending', 'processing', 'confirmed', 'failed', 'mismatch') DEFAULT 'pending' COMMENT '状态',
|
|
bank_ref_no VARCHAR(64) COMMENT '银行参考号',
|
|
remark VARCHAR(200) COMMENT '备注',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
confirmed_at DATETIME COMMENT '确认时间',
|
|
INDEX idx_txn_type (txn_type),
|
|
INDEX idx_from_account (from_account_id),
|
|
INDEX idx_to_account (to_account_id),
|
|
INDEX idx_status (status),
|
|
INDEX idx_bank_ref_no (bank_ref_no),
|
|
INDEX idx_created_at (created_at)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统交易表';
|
|
|
|
-- 银行交易
|
|
CREATE TABLE IF NOT EXISTS bank_transaction (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
bank_ref_no VARCHAR(64) UNIQUE NOT NULL COMMENT '银行参考号',
|
|
physical_account_id BIGINT NOT NULL COMMENT '实体账户ID',
|
|
txn_type VARCHAR(20) NOT NULL COMMENT '交易类型',
|
|
direction ENUM('inbound', 'outbound') NOT NULL COMMENT '交易方向',
|
|
amount DECIMAL(20,2) NOT NULL COMMENT '金额',
|
|
counterparty_name VARCHAR(100) COMMENT '对手方名称',
|
|
counterparty_account VARCHAR(32) COMMENT '对手方账号',
|
|
txn_time DATETIME NOT NULL COMMENT '交易时间',
|
|
sync_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '同步时间',
|
|
match_status ENUM('unmatched', 'matched', 'mismatch') DEFAULT 'unmatched' COMMENT '匹配状态',
|
|
matched_txn_no VARCHAR(32) COMMENT '匹配的系统交易号',
|
|
remark VARCHAR(200) COMMENT '摘要',
|
|
INDEX idx_physical_account (physical_account_id),
|
|
INDEX idx_txn_time (txn_time),
|
|
INDEX idx_match_status (match_status),
|
|
INDEX idx_matched_txn_no (matched_txn_no)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='银行交易表';
|
|
|
|
-- =====================================================
|
|
-- 对账域表
|
|
-- =====================================================
|
|
|
|
-- 对账批次
|
|
CREATE TABLE IF NOT EXISTS reconciliation_batch (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
batch_no VARCHAR(32) UNIQUE NOT NULL COMMENT '批次编号',
|
|
physical_account_id BIGINT NOT NULL COMMENT '实体账户ID',
|
|
recon_date DATE NOT NULL COMMENT '对账日期',
|
|
total_count INT DEFAULT 0 COMMENT '总记录数',
|
|
matched_count INT DEFAULT 0 COMMENT '匹配数',
|
|
mismatch_count INT DEFAULT 0 COMMENT '不匹配数',
|
|
status ENUM('processing', 'completed', 'need_review') DEFAULT 'processing' COMMENT '状态',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
completed_at DATETIME COMMENT '完成时间',
|
|
INDEX idx_physical_account (physical_account_id),
|
|
INDEX idx_recon_date (recon_date),
|
|
INDEX idx_status (status),
|
|
UNIQUE KEY uk_account_date (physical_account_id, recon_date)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='对账批次表';
|
|
|
|
-- 对账明细
|
|
CREATE TABLE IF NOT EXISTS reconciliation_item (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
batch_id BIGINT NOT NULL COMMENT '批次ID',
|
|
system_txn_no VARCHAR(32) COMMENT '系统交易号',
|
|
bank_ref_no VARCHAR(64) COMMENT '银行参考号',
|
|
system_amount DECIMAL(20,2) COMMENT '系统金额',
|
|
bank_amount DECIMAL(20,2) COMMENT '银行金额',
|
|
diff_amount DECIMAL(20,2) DEFAULT 0 COMMENT '差异金额',
|
|
status ENUM('matched', 'system_unreached', 'bank_unreached', 'amount_mismatch', 'adjusted') NOT NULL COMMENT '状态',
|
|
remark VARCHAR(200) COMMENT '处理备注',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
FOREIGN KEY (batch_id) REFERENCES reconciliation_batch(id),
|
|
INDEX idx_batch_id (batch_id),
|
|
INDEX idx_status (status)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='对账明细表';
|
|
|
|
-- 手工补录
|
|
CREATE TABLE IF NOT EXISTS manual_adjustment (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
adjustment_no VARCHAR(32) UNIQUE NOT NULL COMMENT '补录编号',
|
|
related_txn_no VARCHAR(32) COMMENT '关联交易号',
|
|
reconciliation_item_id BIGINT COMMENT '关联对账项ID',
|
|
adjustment_type ENUM('add', 'reverse', 'modify') NOT NULL COMMENT '补录类型',
|
|
account_id BIGINT NOT NULL COMMENT '账户ID',
|
|
amount DECIMAL(20,2) NOT NULL COMMENT '金额',
|
|
reason VARCHAR(500) NOT NULL COMMENT '原因说明',
|
|
operator VARCHAR(50) NOT NULL COMMENT '操作人',
|
|
approver VARCHAR(50) COMMENT '审批人',
|
|
status ENUM('pending', 'approved', 'rejected') DEFAULT 'pending' COMMENT '状态',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
approved_at DATETIME COMMENT '审批时间',
|
|
INDEX idx_related_txn_no (related_txn_no),
|
|
INDEX idx_operator (operator),
|
|
INDEX idx_status (status)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='手工补录表';
|
|
|
|
-- =====================================================
|
|
-- 积分域表
|
|
-- =====================================================
|
|
|
|
-- 积分账户
|
|
CREATE TABLE IF NOT EXISTS points_account (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
sub_account_id BIGINT NOT NULL COMMENT '关联子账户ID',
|
|
points_type ENUM('production', 'management', 'other') NOT NULL COMMENT '积分类型',
|
|
balance DECIMAL(20,2) DEFAULT 0 COMMENT '积分余额',
|
|
total_earned DECIMAL(20,2) DEFAULT 0 COMMENT '累计获得',
|
|
total_spent DECIMAL(20,2) DEFAULT 0 COMMENT '累计消费',
|
|
total_expired DECIMAL(20,2) DEFAULT 0 COMMENT '累计过期',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
FOREIGN KEY (sub_account_id) REFERENCES virtual_sub_account(id),
|
|
UNIQUE KEY uk_sub_account_type (sub_account_id, points_type),
|
|
INDEX idx_points_type (points_type)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='积分账户表';
|
|
|
|
-- 积分交易
|
|
CREATE TABLE IF NOT EXISTS points_transaction (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
txn_no VARCHAR(32) UNIQUE NOT NULL COMMENT '交易编号',
|
|
points_account_id BIGINT NOT NULL COMMENT '积分账户ID',
|
|
txn_type ENUM('earn', 'spend', 'transfer', 'expire', 'adjust') NOT NULL COMMENT '交易类型',
|
|
amount DECIMAL(20,2) NOT NULL COMMENT '积分数量',
|
|
balance_before DECIMAL(20,2) NOT NULL COMMENT '交易前余额',
|
|
balance_after DECIMAL(20,2) NOT NULL COMMENT '交易后余额',
|
|
related_business_id VARCHAR(64) COMMENT '关联业务ID',
|
|
remark VARCHAR(200) COMMENT '备注',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
FOREIGN KEY (points_account_id) REFERENCES points_account(id),
|
|
INDEX idx_points_account (points_account_id),
|
|
INDEX idx_txn_type (txn_type),
|
|
INDEX idx_created_at (created_at)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='积分交易表';
|
|
|
|
-- 积分规则
|
|
CREATE TABLE IF NOT EXISTS points_rule (
|
|
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
|
name VARCHAR(100) NOT NULL COMMENT '规则名称',
|
|
points_type ENUM('production', 'management', 'other') NOT NULL COMMENT '积分类型',
|
|
rule_type VARCHAR(20) NOT NULL COMMENT '规则类型',
|
|
config JSON NOT NULL COMMENT '规则配置',
|
|
enabled TINYINT(1) DEFAULT 1 COMMENT '是否启用',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
|
INDEX idx_points_type (points_type),
|
|
INDEX idx_enabled (enabled)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='积分规则表';
|
|
|
|
|