# 史诗004：新增记账（信用额度支付）功能

## 概述
为多租户电商平台新增信用额度支付功能，允许后台为特定用户设置信用额度，用户可使用额度进行支付，并在小程序个人中心显示累计欠款，与现有微信支付流程并行工作。

## 业务背景
当前系统仅支持微信支付，缺乏灵活的支付方式。为提升用户体验和业务灵活性，需要引入信用额度支付功能，允许特定用户（如VIP用户、企业用户）使用信用额度进行支付，后台可灵活管理额度。

## 目标
1. 新增信用额度支付方式，与现有微信支付流程并行
2. 后台可设置和查看用户信用额度（用户不可见）
3. 未授权用户额度为0，点击额度支付无效
4. 小程序个人中心显示累计欠款信息
5. 实现多租户余额模块和余额管理UI模块

## 范围
### 包含的功能
1. **多租户余额模块** (`credit-balance-module-mt`)
   - 余额实体设计（用户额度、已用额度、可用额度）
   - 额度变更记录实体
   - 额度管理服务（设置额度、扣减额度、恢复额度、查询余额）
   - 额度支付API接口
   - 额度恢复API接口（结账、取消订单、退款）

2. **多租户余额管理UI模块** (`credit-balance-management-ui-mt`)
   - 用户额度管理界面
   - 额度设置和调整功能
   - 额度使用记录查询
   - 欠款统计和报表

3. **支付流程集成**
   - 扩展支付选项，增加"额度支付"
   - 额度支付订单处理逻辑
   - 额度检查和验证机制
   - 额度恢复机制（结账、取消订单、退款）
   - 小程序个人中心欠款显示

### 不包含的功能
1. 额度自动审批和风控系统
2. 额度利息计算和催收功能
3. 额度分期还款功能
4. 额度提现功能

## 用户故事
### 故事1：创建多租户信用额度模块
**作为** 系统管理员
**我希望** 能够管理用户的信用额度
**以便** 控制用户的支付权限和风险

**验收标准：**
- [x] 创建`credit_balance_mt`表，包含租户ID、用户ID、总额度、已用额度、可用额度等字段
- [x] 创建`credit_balance_log_mt`表，记录额度变更历史
- [x] 实现额度管理服务，包含设置额度、扣减额度、查询余额等方法
- [x] 提供额度查询和管理的API接口
- [x] 添加数据库迁移脚本（注：迁移脚本在server包集成模块时创建，不在模块包中创建）
- [x] 编写单元测试覆盖核心逻辑

**实现状态**：✅ 已完成
**完成时间**：2025-12-02
**实现详情**：
- 创建了完整的多租户信用额度模块包：`@d8d/credit-balance-module-mt`
- 实现了两个实体：`CreditBalanceMt`（信用额度实体）和`CreditBalanceLogMt`（额度变更记录实体）
- 实现了完整的额度管理服务：`CreditBalanceService`，包含设置额度、调整额度、扣减额度、恢复额度等方法
- 实现了6个API接口：查询额度、设置额度、调整额度、查询变更记录、额度支付、结账恢复额度
- 编写了13个单元测试用例和11个集成测试用例，测试通过率100%
- 修复了多个技术问题：PostgreSQL类型兼容性、路由架构重构、测试认证问题、小数精度问题等

### 故事2：创建多租户信用额度管理UI模块
**作为** 后台管理员
**我希望** 有一个界面来管理用户信用额度
**以便** 方便地设置和调整用户额度

**验收标准：**
- [x] 创建用户额度管理对话框组件，显示单个用户的当前额度信息
- [x] 实现额度设置和调整功能
- [x] 提供额度使用记录查询界面
- [x] 显示用户欠款统计信息
- [x] 界面风格与现有后台保持一致
- [x] 添加权限控制，只有管理员可访问
- [x] 组件支持通过props传入用户ID和用户信息
- [x] 组件可独立导出，供用户管理UI包集成使用

**实现状态**：✅ 已完成
**完成时间**：2025-12-04
**实现详情**：
- 创建了完整的多租户信用额度管理UI模块包：`@d8d/credit-balance-management-ui-mt`
- 实现了对话框组件模式：`CreditBalanceDialog`，包含三个标签页（额度概览、额度操作、变更记录）
- 实现了完整的API客户端：基于Hono RPC的`creditBalanceClient.ts`，支持多租户上下文
- 实现了所有功能：额度查询、设置、调整、恢复、记录查询、欠款统计
- 集成了权限控制：只有管理员角色可以访问额度管理功能
- 集成了用户管理UI包：在用户管理界面中添加信用额度管理按钮和对话框
- 编写了6个集成测试用例，测试通过率100%
- 修复了多个技术问题：表单验证中文错误消息、Zod类型转换、测试调试、UI集成等

### 故事3：集成额度支付到现有支付流程
**作为** 小程序用户
**我希望** 可以使用信用额度进行支付
**以便** 在余额不足时也能完成购买

**验收标准：**
- [ ] 在支付页面增加"额度支付"选项
- [ ] 实现额度支付订单处理逻辑
- [ ] 额度为0的用户无法使用额度支付
- [ ] 支付成功后更新用户已用额度和可用额度
- [ ] 实现额度恢复机制：
  - [ ] 结账时恢复相应额度（订单完成）
  - [ ] 取消订单时恢复全额额度
  - [ ] 退款时恢复相应额度
- [ ] 在小程序个人中心显示累计欠款
- [ ] 确保与现有微信支付流程并行工作，互不干扰

## 技术设计
### 数据库设计
```sql
-- 用户信用额度表
CREATE TABLE credit_balance_mt (
  id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  tenant_id INT UNSIGNED NOT NULL COMMENT '租户ID',
  user_id INT UNSIGNED NOT NULL COMMENT '用户ID',
  total_limit DECIMAL(10,2) DEFAULT 0.00 COMMENT '总额度',
  used_amount DECIMAL(10,2) DEFAULT 0.00 COMMENT '已用额度',
  available_amount DECIMAL(10,2) GENERATED ALWAYS AS (total_limit - used_amount) STORED COMMENT '可用额度',
  is_enabled TINYINT DEFAULT 1 COMMENT '是否启用(0:禁用,1:启用)',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_tenant_user (tenant_id, user_id),
  INDEX idx_tenant_id (tenant_id),
  INDEX idx_user_id (user_id)
) COMMENT='用户信用额度表';

-- 额度变更记录表
CREATE TABLE credit_balance_log_mt (
  id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  tenant_id INT UNSIGNED NOT NULL COMMENT '租户ID',
  user_id INT UNSIGNED NOT NULL COMMENT '用户ID',
  change_type VARCHAR(20) NOT NULL COMMENT '变更类型: SET_LIMIT(设置额度), PAYMENT(支付扣减), CHECKOUT(结账恢复), CANCEL_ORDER(取消订单恢复), REFUND(退款恢复), ADJUST(调整额度)',
  change_amount DECIMAL(10,2) NOT NULL COMMENT '变更金额（正数表示增加额度，负数表示减少额度）',
  before_total DECIMAL(10,2) COMMENT '变更前总额度',
  after_total DECIMAL(10,2) COMMENT '变更后总额度',
  before_used DECIMAL(10,2) COMMENT '变更前已用额度',
  after_used DECIMAL(10,2) COMMENT '变更后已用额度',
  reference_id VARCHAR(100) COMMENT '关联ID(订单号等)',
  remark VARCHAR(500) COMMENT '备注',
  operator_id INT UNSIGNED COMMENT '操作人ID',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_tenant_user (tenant_id, user_id),
  INDEX idx_reference (reference_id),
  INDEX idx_created (created_at)
) COMMENT='额度变更记录表';
```

**迁移脚本说明**：
根据项目架构，TypeORM迁移脚本应在server包集成`@d8d/credit-balance-module-mt`模块时创建，而不是在模块包中创建。模块包只包含实体定义，迁移脚本由使用该模块的应用层（server包）负责创建和管理。

### 模块结构
```
packages/
├── @d8d/credit-balance-module-mt/     # 多租户余额模块
│   ├── src/
│   │   ├── entities/                  # 实体定义
│   │   │   ├── credit-balance.mt.entity.ts
│   │   │   └── credit-balance-log.mt.entity.ts
│   │   │   └── index.ts
│   │   ├── services/                  # 服务层
│   │   │   ├── credit-balance.service.ts
│   │   │   └── index.ts
│   │   ├── schemas/                   # 数据验证
│   │   │   └── index.ts
│   │   ├── routes/                    # API路由
│   │   │   └── index.ts
│   │   ├── types/                     # 类型定义
│   │   │   └── index.ts
│   │   └── index.ts                   # 主入口文件
│   ├── tests/                         # 测试文件
│   ├── tsconfig.json                  # TypeScript配置
│   ├── vitest.config.ts               # 测试配置
│   └── package.json
└── @d8d/credit-balance-management-ui-mt/   # 余额管理UI模块
    ├── src/
    │   ├── api/                       # API客户端
    │   │   ├── index.ts
    │   │   └── creditBalanceClient.ts
    │   ├── components/                # 组件
    │   │   ├── CreditBalanceManagement.tsx
    │   │   └── index.ts
    │   ├── hooks/                     # React hooks
    │   │   └── index.ts
    │   ├── types/                     # 类型定义
    │   │   ├── index.ts
    │   │   └── creditBalance.ts
    │   └── index.ts                   # 主入口文件
    ├── tests/                         # 测试文件
    ├── eslint.config.js               # ESLint配置
    ├── tsconfig.json                  # TypeScript配置
    ├── vitest.config.ts               # 测试配置
    └── package.json
```

### API设计
#### 对外API（供UI调用）
1. `GET /api/credit-balance/{userId}` - 查询用户额度
2. `PUT /api/credit-balance/{userId}` - 设置用户额度
3. `POST /api/credit-balance/{userId}/adjust` - 调整用户额度
4. `GET /api/credit-balance/{userId}/logs` - 查询额度变更记录
5. `POST /api/credit-balance/payment` - 额度支付
6. `POST /api/credit-balance/checkout` - 结账恢复额度（供信用管理UI调用）

#### 服务接口（供其他模块调用）
1. `CreditBalanceService.restoreBalanceForCancelOrder(orderId, userId, amount)` - 取消订单恢复额度
2. `CreditBalanceService.restoreBalanceForRefund(orderId, userId, refundAmount)` - 退款恢复额度

**设计说明：**
- **结账恢复**：需要人工确认，因此通过信用管理UI手动触发，调用`/api/credit-balance/checkout`接口
- **取消订单恢复**：自动触发，订单模块在取消订单时直接调用`CreditBalanceService.restoreBalanceForCancelOrder()`方法
- **退款恢复**：自动触发，支付模块在退款处理时直接调用`CreditBalanceService.restoreBalanceForRefund()`方法
- **模块间调用**：使用PNPM工作空间，通过`@d8d/credit-balance-module-mt`包名导入服务类进行直接调用

## 集成点
### 与现有系统集成
1. **用户模块集成**：通过`user_id`关联用户信息
2. **订单模块集成**：
   - 扩展`orders_mt`表的`pay_type`字段，新增额度支付类型
   - 订单模块导入`@d8d/credit-balance-module-mt`包，直接调用`CreditBalanceService.restoreBalanceForCancelOrder()`方法处理取消订单时的额度恢复
3. **支付模块集成**：
   - 在`@d8d/mini-payment-mt`中新增额度支付处理逻辑
   - 支付模块导入`@d8d/credit-balance-module-mt`包，直接调用`CreditBalanceService.restoreBalanceForRefund()`方法处理退款时的额度恢复
4. **信用管理UI集成**：
   - 信用管理UI调用额度模块的`/api/credit-balance/checkout`接口处理结账时的额度恢复
5. **小程序集成**：更新支付页面和个人中心页面

### 数据流
#### 正向流程（支付扣减）
1. 后台管理员设置用户额度 → 更新`credit_balance_mt`表
2. 用户选择额度支付 → 检查可用额度 → 创建订单 → 扣减额度
3. 支付成功 → 更新订单状态 → 记录额度变更日志（PAYMENT类型）
4. 小程序查询欠款 → 调用额度查询接口 → 显示欠款信息

#### 反向流程（额度恢复）
1. **结账恢复**：订单完成结账 → 信用管理UI调用`/api/credit-balance/checkout` → 恢复相应额度 → 记录日志（CHECKOUT类型）
2. **取消订单恢复**：用户取消订单 → 订单模块调用`CreditBalanceService.restoreBalanceForCancelOrder()` → 恢复全额额度 → 记录日志（CANCEL_ORDER类型）
3. **退款恢复**：管理员处理退款 → 支付模块调用`CreditBalanceService.restoreBalanceForRefund()` → 恢复相应额度 → 记录日志（REFUND类型）

## 额度恢复逻辑
### 恢复场景定义
1. **结账恢复（CHECKOUT）**
   - **触发条件**：订单完成所有流程，用户确认收货
   - **恢复金额**：订单实际支付金额
   - **业务意义**：订单交易完成，额度占用解除
   - **实现方式**：信用管理UI手动触发，调用`/api/credit-balance/checkout`接口

2. **取消订单恢复（CANCEL_ORDER）**
   - **触发条件**：用户在支付后、发货前取消订单
   - **恢复金额**：订单全额支付金额
   - **业务意义**：交易未发生，全额恢复额度
   - **实现方式**：订单模块在取消订单时自动调用`CreditBalanceService.restoreBalanceForCancelOrder()`方法

3. **退款恢复（REFUND）**
   - **触发条件**：管理员处理用户退款申请
   - **恢复金额**：实际退款金额（可能部分退款）
   - **业务意义**：交易撤销，按退款金额恢复额度
   - **实现方式**：支付模块在退款处理时自动调用`CreditBalanceService.restoreBalanceForRefund()`方法

### 恢复规则
1. **幂等性保证**：同一订单只能恢复一次额度，防止重复恢复
2. **金额验证**：恢复金额不能超过原支付金额
3. **状态检查**：只有特定订单状态才能触发恢复
4. **日志记录**：每次恢复都记录详细的变更日志
5. **事务处理**：额度恢复与订单状态更新在同一事务中

## 兼容性要求
1. **API兼容性**：新增API端点，不影响现有API
2. **数据库兼容性**：新增表，不影响现有表结构
3. **UI兼容性**：新增页面和组件，遵循现有UI规范
4. **支付流程兼容性**：额度支付与微信支付并行，互不干扰

## 风险与缓解
### 风险1：额度支付逻辑错误导致财务数据不一致
- **缓解措施**：使用数据库事务处理额度扣减和订单创建
- **验证机制**：添加额度检查和余额验证
- **监控**：记录详细的额度变更日志

### 风险2：额度被恶意使用
- **缓解措施**：后台控制额度启用状态，默认禁用
- **权限控制**：只有管理员可设置和调整额度
- **额度限制**：设置单次支付和累计欠款上限

### 风险3：额度恢复逻辑错误导致额度重复恢复
- **缓解措施**：实现幂等性检查，同一订单只能恢复一次
- **验证机制**：添加恢复前状态检查，防止重复恢复
- **日志审计**：详细记录每次恢复操作，便于审计追踪

### 风险4：影响现有支付流程
- **缓解措施**：额度支付作为可选功能，默认不启用
- **测试策略**：充分测试与现有支付流程的兼容性
- **回滚计划**：可禁用额度支付功能，恢复原有流程

## 测试策略
### 单元测试
- 额度计算逻辑测试
- 额度扣减和恢复测试
- 额度验证测试
- 额度恢复场景测试：
  - 结账恢复额度测试
  - 取消订单恢复额度测试
  - 退款恢复额度测试

### 集成测试
- 额度支付流程测试
- 额度恢复流程测试：
  - 结账时额度恢复测试
  - 取消订单时额度恢复测试
  - 退款时额度恢复测试
- 与订单模块集成测试
- 与用户模块集成测试

### E2E测试
- 后台额度管理流程测试
- 小程序额度支付流程测试
- 额度恢复场景测试：
  - 结账后额度恢复验证
  - 取消订单后额度恢复验证
  - 退款后额度恢复验证
- 欠款显示功能测试

## 部署计划
### 阶段1：开发环境部署
1. 创建数据库迁移脚本
2. 部署余额模块和UI模块
3. 配置额度支付功能（默认禁用）

### 阶段2：测试环境验证
1. 功能测试和集成测试
2. 性能测试和压力测试
3. 安全测试和权限测试

### 阶段3：生产环境部署
1. 执行数据库迁移
2. 部署新模块
3. 灰度启用额度支付功能
4. 监控系统运行状态

## 成功指标
1. **功能指标**：
   - 后台可成功设置和调整用户额度
   - 用户可使用额度完成支付
   - 额度恢复功能正常工作：
     - 结账时正确恢复额度
     - 取消订单时正确恢复额度
     - 退款时正确恢复额度
   - 小程序正确显示欠款信息
   - 额度为0的用户无法使用额度支付

2. **性能指标**：
   - 额度查询响应时间 < 100ms
   - 额度支付处理时间 < 500ms
   - 系统可用性 > 99.9%

3. **业务指标**：
   - 额度支付成功率 > 95%
   - 用户满意度提升
   - 支付方式多样性增加

## 后续优化建议
1. 额度自动审批流程
2. 额度风控和预警系统
3. 额度分期和还款功能
4. 额度提现和转账功能
5. 额度积分和奖励机制

---
**创建时间**：2025-12-01
**负责人**：产品经理
**状态**：进行中（故事1、故事2已完成）
**优先级**：高

## 开发进度
### 已完成
1. ✅ **故事1：创建多租户信用额度模块**（2025-12-02完成）
   - 创建了完整的多租户信用额度模块包：`@d8d/credit-balance-module-mt`
   - 实现了所有核心功能：实体、服务、API接口、测试
   - 测试通过率100%，代码质量符合项目标准

2. ✅ **故事2：创建多租户信用额度管理UI模块**（2025-12-04完成）
   - 创建了完整的多租户信用额度管理UI模块包：`@d8d/credit-balance-management-ui-mt`
   - 实现了对话框组件模式：`CreditBalanceDialog`，包含三个标签页（额度概览、额度操作、变更记录）
   - 实现了完整的API客户端：基于Hono RPC的`creditBalanceClient.ts`，支持多租户上下文
   - 实现了所有功能：额度查询、设置、调整、恢复、记录查询、欠款统计
   - 集成了权限控制：只有管理员角色可以访问额度管理功能
   - 集成了用户管理UI包：在用户管理界面中添加信用额度管理按钮和对话框
   - 编写了6个集成测试用例，测试通过率100%
   - 修复了多个技术问题：表单验证中文错误消息、Zod类型转换、测试调试、UI集成等

### 待完成
1. 🔄 **故事3：集成额度支付到现有支付流程**

### 技术实现亮点
1. **多租户架构**：严格遵循项目多租户包架构模式，使用`-mt`后缀和租户ID隔离
2. **路由架构**：参照订单模块采用链式聚合模式，支持RPC风格API调用
3. **测试策略**：使用测试数据工厂模式，真实JWT令牌认证，确保测试可靠性
4. **错误处理**：完整的OpenAPI错误响应定义，符合项目标准
5. **数据库设计**：PostgreSQL兼容性优化，解决tinyint类型和decimal精度问题
6. **事务处理**：额度扣减和恢复操作使用数据库事务确保数据一致性