9.6 KiB
9.6 KiB
财务系统数据库表结构说明
数据库表与 Entity 映射关系
| 数据库表 | Entity 文件 | 说明 | 状态 |
|---|---|---|---|
accounts |
account.entity.ts |
账户表(用户/商家/平台) | ✅ 已完成 |
transactions |
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 已包含完整的财务系统表结构(第 669-901 行)
2. 自动创建的数据
执行迁移脚本后会自动创建:
-
平台账户(
accounts表)account_type: 'platform'owner_id: 0balance: 0.00
-
触发器
trg_user_create_account: 用户注册时自动创建账户trg_merchant_create_account: 商家审核通过时自动创建账户
3. 表结构版本说明
⚠️ 重要: 数据库脚本中有两个 settlements 表定义:
- 旧版本(第 394-417 行): 使用
commission_rate,commission_amount字段 - 新版本(第 804-824 行): 使用
service_fee,settlement_amount字段
当前使用: 新版本(与 Entity 一致)
建议删除旧版本的表定义,避免混淆。
字段说明
accounts(账户表)
CREATE TABLE `accounts` (
`id` BIGINT UNSIGNED AUTO_INCREMENT,
`account_type` ENUM('user','merchant','platform'), -- 账户类型
`owner_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_type_owner` (`account_type`, `owner_id`)
);
关键点:
- 使用
account_type+owner_id唯一标识账户 - 平台账户的
owner_id固定为 0 version字段用于乐观锁,防止并发问题balance和frozen_balance有 CHECK 约束,不能为负数
transactions(交易流水表)
CREATE TABLE `transactions` (
`id` BIGINT UNSIGNED AUTO_INCREMENT,
`transaction_no` VARCHAR(32) UNIQUE, -- 交易流水号
`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_id` BIGINT UNSIGNED, -- 对方账户ID
PRIMARY KEY (`id`),
UNIQUE KEY `uk_transaction_no` (`transaction_no`)
);
关键点:
- 复式记账:每笔转账生成两条流水(一条支出 + 一条收入)
transaction_no相同的两条流水表示同一笔转账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模块,定时任务才会执行。