Files
rent/docs/database/finance-database.md
T
2026-05-14 19:12:26 +08:00

12 KiB
Raw Blame History

财务系统数据库表结构说明

数据库表与 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. 自动创建的数据

执行迁移脚本后会自动创建:

  1. 触发器
    • trg_user_create_account: 用户注册时自动创建用户账户
    • trg_merchant_create_account: 商家审核通过时自动创建商家账户

3. 表结构版本说明

⚠️ 重要: 旧版本的 settlementswithdrawals 表定义已删除。

当前使用: 按角色分离的账户和交易表(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_service_fee` 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 字段用于乐观锁,防止并发问题
  • balancefrozen_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_typerelated_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 记录

索引说明

关键索引

  1. accounts 表

    • uk_type_owner: 唯一索引,确保每个用户/商家只有一个账户
    • idx_status: 按状态查询
  2. transactions 表

    • uk_transaction_no: 唯一索引,防止重复交易
    • idx_account_id: 按账户查询流水
    • idx_business: 按业务类型和业务ID查询
    • idx_created_at: 按时间范围查询
  3. settlements 表

    • uk_settlement_no: 唯一索引
    • idx_merchant_id: 按商家查询
    • idx_period: 按周期查询
  4. 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. 触发器

  • 用户注册时自动创建账户
  • 商家审核通过时自动创建账户

下一步工作

  1. 数据库表结构已完成
  2. Entity 层已完成
  3. Service 层已完成
  4. Controller 层已完成
  5. DTO 层已完成
  6. 执行数据库迁移脚本
  7. 集成到订单模块(订单支付时调用账户服务)
  8. 编写单元测试
  9. 前端页面开发

注意事项

  1. 删除旧版 settlements 表定义: 数据库脚本中第 394-417 行的旧版本定义应该删除,避免混淆。

  2. 执行迁移脚本: 确保按顺序执行 001_init_schema.sql,会自动创建所有表和触发器。

  3. 平台账户: 迁移脚本会自动创建平台账户(owner_id=0),无需手动创建。

  4. 定时任务: 需要在 NestJS 中启用 @nestjs/schedule 模块,定时任务才会执行。