12 KiB
12 KiB
财务系统数据库表结构说明
数据库表与 Entity 映射关系
| 数据库表 | Entity 文件 | 说明 | 状态 |
|---|---|---|---|
user_accounts |
user-account.entity.ts |
用户账户表 | ✅ 已完成 |
merchant_accounts |
merchant-account.entity.ts |
商家账户表 | ✅ 已完成 |
platform_accounts |
platform-account.entity.ts |
平台账户表 | ✅ 已完成 |
user_transactions |
user-transaction.entity.ts |
用户交易流水表 | ✅ 已完成 |
merchant_transactions |
merchant-transaction.entity.ts |
商家交易流水表 | ✅ 已完成 |
platform_transactions |
platform-transaction.entity.ts |
平台交易流水表 | ✅ 已完成 |
user_withdrawals |
user-withdrawal.entity.ts |
用户提现表 | ✅ 已完成 |
merchant_withdrawals |
merchant-withdrawal.entity.ts |
商家提现表 | ✅ 已完成 |
platform_withdrawals |
platform-withdrawal.entity.ts |
平台提现表 | ✅ 已完成 |
settlements |
settlement.entity.ts |
结算单表 | ✅ 已完成 |
settlement_items |
settlement-item.entity.ts |
结算明细表 | ✅ 已完成 |
daily_reconciliations |
daily-reconciliation.entity.ts |
日对账表 | ✅ 已完成 |
数据库初始化说明
1. 迁移脚本位置
database/migrations/001_init_schema.sql 已包含完整的财务系统表结构(第 606-901 行)
2. 自动创建的数据
执行迁移脚本后会自动创建:
- 触发器
trg_user_create_account: 用户注册时自动创建用户账户trg_merchant_create_account: 商家审核通过时自动创建商家账户
3. 表结构版本说明
⚠️ 重要: 旧版本的 settlements 和 withdrawals 表定义已删除。
当前使用: 按角色分离的账户和交易表(user_accounts、merchant_accounts、platform_accounts 等)
字段说明
user_accounts(用户账户表)
CREATE TABLE `user_accounts` (
`id` BIGINT UNSIGNED AUTO_INCREMENT,
`user_id` BIGINT UNSIGNED, -- 用户ID
`balance` DECIMAL(12,2) DEFAULT 0.00, -- 可用余额
`frozen_balance` DECIMAL(12,2) DEFAULT 0.00, -- 冻结余额(提现中)
`total_income` DECIMAL(12,2) DEFAULT 0.00, -- 累计收入(邀请返现)
`total_expense` DECIMAL(12,2) DEFAULT 0.00, -- 累计支出(提现)
`version` INT UNSIGNED DEFAULT 0, -- 乐观锁版本号
`status` ENUM('active','frozen','closed'), -- 状态
PRIMARY KEY (`id`),
UNIQUE KEY `uk_user_id` (`user_id`)
);
merchant_accounts(商家账户表)
CREATE TABLE `merchant_accounts` (
`id` BIGINT UNSIGNED AUTO_INCREMENT,
`merchant_id` BIGINT UNSIGNED, -- 商家ID
`balance` DECIMAL(12,2) DEFAULT 0.00, -- 可用余额
`frozen_balance` DECIMAL(12,2) DEFAULT 0.00, -- 冻结余额(提现中)
`debt_amount` DECIMAL(12,2) DEFAULT 0.00, -- 欠款金额(退款扣回)
`total_income` DECIMAL(12,2) DEFAULT 0.00, -- 累计收入(订单结算)
`total_expense` DECIMAL(12,2) DEFAULT 0.00, -- 累计支出(提现+退款扣回)
`total_settlement` DECIMAL(12,2) DEFAULT 0.00, -- 累计结算金额
`total_withdraw` DECIMAL(12,2) DEFAULT 0.00, -- 累计提现金额
`last_settlement_at` DATETIME, -- 最后结算时间
`pending_settlement` DECIMAL(12,2) DEFAULT 0.00, -- 待结算金额
`version` INT UNSIGNED DEFAULT 0, -- 乐观锁版本号
`status` ENUM('active','frozen','closed'), -- 状态
PRIMARY KEY (`id`),
UNIQUE KEY `uk_merchant_id` (`merchant_id`)
);
platform_accounts(平台账户表)
CREATE TABLE `platform_accounts` (
`id` BIGINT UNSIGNED AUTO_INCREMENT,
`account_name` VARCHAR(50), -- 账户名称
`balance` DECIMAL(12,2) DEFAULT 0.00, -- 可用余额
`frozen_balance` DECIMAL(12,2) DEFAULT 0.00, -- 冻结余额
`total_income` DECIMAL(12,2) DEFAULT 0.00, -- 累计收入(订单收入)
`total_expense` DECIMAL(12,2) DEFAULT 0.00, -- 累计支出(商家结算+退款)
`total_service_fee` DECIMAL(12,2) DEFAULT 0.00, -- 累计服务费收入
`version` INT UNSIGNED DEFAULT 0, -- 乐观锁版本号
`status` ENUM('active','frozen','closed'), -- 状态
PRIMARY KEY (`id`)
);
关键点:
- 账户按角色分离:用户、商家、平台各有独立的账户表
- 每个账户表都有
version字段用于乐观锁,防止并发问题 balance和frozen_balance有 CHECK 约束,不能为负数
user_transactions / merchant_transactions / platform_transactions(交易流水表)
交易流水表也按角色分离,结构类似:
CREATE TABLE `user_transactions` (
`id` BIGINT UNSIGNED AUTO_INCREMENT,
`transaction_no` VARCHAR(32) UNIQUE, -- 交易流水号(全局唯一)
`user_id` BIGINT UNSIGNED, -- 用户ID
`account_id` BIGINT UNSIGNED, -- 用户账户ID
`direction` ENUM('income','expense'), -- 方向
`amount` DECIMAL(12,2), -- 金额
`balance_before` DECIMAL(12,2), -- 交易前余额
`balance_after` DECIMAL(12,2), -- 交易后余额
`transaction_type` VARCHAR(50), -- 交易类型
`business_type` VARCHAR(50), -- 业务类型
`business_id` BIGINT UNSIGNED, -- 业务ID
`business_no` VARCHAR(32), -- 业务单号
`related_account_type` ENUM('platform','merchant'), -- 对方账户类型
`related_account_id` BIGINT UNSIGNED, -- 对方账户ID
PRIMARY KEY (`id`),
UNIQUE KEY `uk_transaction_no` (`transaction_no`)
);
关键点:
- 复式记账:每笔转账生成两条流水(一条支出 + 一条收入)
transaction_no相同的两条流水表示同一笔转账related_account_type和related_account_id关联对方账户
settlements(结算单表)
CREATE TABLE `settlements` (
`id` BIGINT UNSIGNED AUTO_INCREMENT,
`settlement_no` VARCHAR(32) UNIQUE, -- 结算单号
`merchant_id` BIGINT UNSIGNED, -- 商家ID
`period_start` DATE, -- 周期开始
`period_end` DATE, -- 周期结束
`order_count` INT UNSIGNED DEFAULT 0, -- 订单数量
`order_amount` DECIMAL(12,2) DEFAULT 0.00, -- 订单总额
`service_fee` DECIMAL(12,2) DEFAULT 0.00, -- 服务费
`settlement_amount` DECIMAL(12,2) DEFAULT 0.00, -- 结算金额
`status` ENUM('pending','settled','failed'), -- 状态
`settled_at` DATETIME, -- 结算时间
PRIMARY KEY (`id`)
);
关键点:
- 每周一凌晨2点自动生成上周的结算单
settlement_amount=order_amount-service_fee- 结算时执行转账:平台账户 → 商家账户
daily_reconciliations(日对账表)
CREATE TABLE `daily_reconciliations` (
`id` BIGINT UNSIGNED AUTO_INCREMENT,
`reconciliation_date` DATE UNIQUE, -- 对账日期
`platform_balance` DECIMAL(12,2), -- 平台余额
`merchant_balance_sum` DECIMAL(12,2), -- 商家余额总和
`user_balance_sum` DECIMAL(12,2), -- 用户余额总和
`total_balance` DECIMAL(12,2), -- 总余额
`order_income` DECIMAL(12,2) DEFAULT 0.00, -- 订单收入
`service_fee` DECIMAL(12,2) DEFAULT 0.00, -- 服务费
`merchant_settlement` DECIMAL(12,2) DEFAULT 0.00, -- 商家结算
`cashback_expense` DECIMAL(12,2) DEFAULT 0.00, -- 返现支出
`withdraw_expense` DECIMAL(12,2) DEFAULT 0.00, -- 提现支出
`refund_expense` DECIMAL(12,2) DEFAULT 0.00, -- 退款支出
`status` ENUM('balanced','unbalanced'), -- 状态
`error_message` TEXT, -- 异常信息
PRIMARY KEY (`id`)
);
关键点:
- 每天凌晨3点自动执行对账
- 检查借贷平衡:收入总额 = 支出总额
- 如有异常记录
error_message并发送告警
业务流程与数据库操作
1. 用户支付订单
1. 用户支付 → 平台账户收入
2. 插入 transactions 记录(平台账户 income)
3. 更新 accounts.balance(平台账户)
2. 周结算
1. 查询上周已完成订单
2. 按商家分组计算结算金额
3. 插入 settlements 记录
4. 插入 settlement_items 记录(订单明细)
5. 执行转账:平台账户 → 商家账户
- 插入 2 条 transactions 记录(复式记账)
- 更新 2 个 accounts.balance
3. 商家提现
1. 商家申请提现
- 插入 merchant_withdrawals 记录
- 冻结商家账户余额(frozen_balance += amount)
2. 管理员审核通过
- 更新 merchant_withdrawals.status = 'approved'
3. 管理员确认打款
- 扣减余额(balance -= amount, frozen_balance -= amount)
- 插入 transactions 记录(商家账户 expense)
- 更新 merchant_withdrawals.status = 'paid'
4. 日对账
1. 统计各账户余额
- SELECT SUM(balance) FROM accounts WHERE account_type = 'platform'
- SELECT SUM(balance) FROM accounts WHERE account_type = 'merchant'
- SELECT SUM(balance) FROM accounts WHERE account_type = 'user'
2. 统计当日交易金额
- SELECT SUM(amount) FROM transactions WHERE direction = 'income'
- SELECT SUM(amount) FROM transactions WHERE direction = 'expense'
3. 检查借贷平衡
- 收入总额 = 支出总额(允许 0.01 元误差)
4. 插入 daily_reconciliations 记录
索引说明
关键索引
-
accounts 表
uk_type_owner: 唯一索引,确保每个用户/商家只有一个账户idx_status: 按状态查询
-
transactions 表
uk_transaction_no: 唯一索引,防止重复交易idx_account_id: 按账户查询流水idx_business: 按业务类型和业务ID查询idx_created_at: 按时间范围查询
-
settlements 表
uk_settlement_no: 唯一索引idx_merchant_id: 按商家查询idx_period: 按周期查询
-
withdrawals 表
uk_withdraw_no: 唯一索引idx_status: 按状态查询(待审核、已打款等)
数据一致性保证
1. 事务保证
所有涉及金额变动的操作都在事务中执行:
- 转账操作(账户余额变动 + 交易流水插入)
- 提现操作(余额冻结/扣减 + 提现记录更新)
- 结算操作(结算单生成 + 转账执行)
2. 乐观锁
accounts 表使用 version 字段实现乐观锁,防止并发更新导致余额错误。
3. CHECK 约束
CONSTRAINT `chk_balance` CHECK (`balance` >= 0)
CONSTRAINT `chk_frozen_balance` CHECK (`frozen_balance` >= 0)
确保余额不会为负数。
4. 触发器
- 用户注册时自动创建账户
- 商家审核通过时自动创建账户
下一步工作
- ✅ 数据库表结构已完成
- ✅ Entity 层已完成
- ✅ Service 层已完成
- ✅ Controller 层已完成
- ✅ DTO 层已完成
- ⏳ 执行数据库迁移脚本
- ⏳ 集成到订单模块(订单支付时调用账户服务)
- ⏳ 编写单元测试
- ⏳ 前端页面开发
注意事项
-
删除旧版 settlements 表定义: 数据库脚本中第 394-417 行的旧版本定义应该删除,避免混淆。
-
执行迁移脚本: 确保按顺序执行
001_init_schema.sql,会自动创建所有表和触发器。 -
平台账户: 迁移脚本会自动创建平台账户(
owner_id=0),无需手动创建。 -
定时任务: 需要在 NestJS 中启用
@nestjs/schedule模块,定时任务才会执行。