فهرست منبع

docs(stories): 创建故事004.003集成额度支付到现有支付流程

- 创建故事004.003文档,定义额度支付集成需求
- 包含7个验收标准:支付页面增加额度选项、额度支付逻辑、额度检查、额度恢复机制等
- 详细任务分解:订单模块扩展、支付模块集成、小程序页面更新等
- 包含完整开发笔记:技术栈、项目结构、数据模型、API设计、集成点
- 提供测试策略和检查清单验证结果

🤖 Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 1 ماه پیش
والد
کامیت
e2ebc9f383
1فایلهای تغییر یافته به همراه256 افزوده شده و 0 حذف شده
  1. 256 0
      docs/stories/004.003.integrate-credit-payment.story.md

+ 256 - 0
docs/stories/004.003.integrate-credit-payment.story.md

@@ -0,0 +1,256 @@
+# Story 004.003: 集成额度支付到现有支付流程
+
+## Status
+Draft
+
+## Story
+**As a** 小程序用户,
+**I want** 可以使用信用额度进行支付,
+**so that** 在余额不足时也能完成购买
+
+## Acceptance Criteria
+1. 在支付页面增加"额度支付"选项
+2. 实现额度支付订单处理逻辑
+3. 额度为0的用户无法使用额度支付
+4. 支付成功后更新用户已用额度和可用额度
+5. 实现额度恢复机制:
+   - 结账时恢复相应额度(订单完成)
+   - 取消订单时恢复全额额度
+   - 退款时恢复相应额度
+6. 在小程序个人中心显示累计欠款
+7. 确保与现有微信支付流程并行工作,互不干扰
+
+## Tasks / Subtasks
+- [ ] **扩展订单模块支持额度支付类型** (AC: 1, 2, 3, 4, 7)
+  - [ ] 检查`orders_mt`表的`pay_type`字段,确认现有支付类型
+  - [ ] 扩展`pay_type`枚举,新增`CREDIT`额度支付类型
+  - [ ] 更新订单实体类型定义,支持额度支付类型
+  - [ ] 更新订单创建schema,验证额度支付相关参数
+
+- [ ] **在支付模块中集成额度支付逻辑** (AC: 1, 2, 3, 4, 7)
+  - [ ] 检查`@d8d/mini-payment-mt`支付模块结构
+  - [ ] 在支付模块中添加额度支付处理逻辑
+  - [ ] 实现额度支付检查:验证用户可用额度
+  - [ ] 实现额度扣减逻辑:调用`CreditBalanceService.payment()`方法
+  - [ ] 更新支付创建流程,支持额度支付类型
+
+- [ ] **实现额度恢复机制** (AC: 5)
+  - [ ] **结账恢复**:在信用管理UI中已实现`/api/credit-balance/checkout`接口调用
+  - [ ] **取消订单恢复**:在订单模块取消订单时调用`CreditBalanceService.restoreBalanceForCancelOrder()`方法
+  - [ ] **退款恢复**:在支付模块退款处理时调用`CreditBalanceService.restoreBalanceForRefund()`方法
+  - [ ] 确保恢复操作的幂等性:同一订单只能恢复一次额度
+
+- [ ] **更新小程序支付页面** (AC: 1, 3, 7)
+  - [ ] 检查小程序支付页面组件结构
+  - [ ] 在支付选项中添加"额度支付"按钮
+  - [ ] 实现额度支付选择逻辑:检查用户可用额度
+  - [ ] 额度为0的用户禁用额度支付选项
+  - [ ] 保持与微信支付选项的并行工作
+
+- [ ] **在小程序个人中心显示欠款信息** (AC: 6)
+  - [ ] 检查小程序个人中心页面结构
+  - [ ] 添加欠款信息显示组件
+  - [ ] 调用额度查询API获取用户欠款信息
+  - [ ] 设计欠款信息显示样式(总额度、已用额度、可用额度、欠款金额)
+
+- [ ] **编写集成测试** (AC: 1, 2, 3, 4, 5, 6, 7)
+  - [ ] **支付流程测试**:测试额度支付完整流程
+  - [ ] **额度恢复测试**:测试结账、取消订单、退款时的额度恢复
+  - [ ] **额度检查测试**:测试额度为0用户无法使用额度支付
+  - [ ] **并发测试**:测试额度支付与微信支付的并行工作
+  - [ ] **欠款显示测试**:测试小程序个人中心欠款信息显示
+
+- [ ] **验证模块间集成** (AC: 7)
+  - [ ] 验证订单模块与额度模块的集成
+  - [ ] 验证支付模块与额度模块的集成
+  - [ ] 验证小程序前端与后端API的集成
+  - [ ] 确保所有模块间调用类型安全
+
+## Dev Notes
+
+### 技术栈信息 [Source: architecture/tech-stack.md]
+- **前端框架**: React 19.1.0 + TypeScript
+- **后端框架**: Hono 4.8.5 + TypeScript
+- **数据库**: PostgreSQL 17 + TypeORM 0.3.25
+- **支付模块**: `@d8d/mini-payment` (微信小程序支付模块)
+- **额度模块**: `@d8d/credit-balance-module-mt` (多租户信用额度模块)
+- **订单模块**: `@d8d/orders-module-mt` (多租户订单管理模块)
+
+### 项目结构信息 [Source: architecture/source-tree.md]
+- **包管理**: 使用pnpm workspace管理多包依赖关系
+- **包架构层次**:
+  - **基础设施层**: shared-types → shared-utils → shared-crud
+  - **测试基础设施**: shared-test-util
+  - **业务模块层**: 多租户模块包(-mt后缀),支持租户数据隔离
+  - **前端界面层**: 共享UI组件包 + 单租户管理界面包 + 多租户管理界面包
+  - **应用层**: server (重构后)
+- **多租户架构**:
+  - **包复制策略**: 基于Epic-007方案,通过复制单租户包创建多租户版本
+  - **租户隔离**: 通过租户ID实现数据隔离,支持多租户部署
+  - **前端包**: 10个多租户管理界面包,支持租户上下文管理
+  - **后端包**: 10个多租户模块包,支持租户数据隔离
+- **文件命名**: 保持现有kebab-case命名约定
+- **模块化架构**: 采用分层包结构,支持按需安装和独立开发
+
+### 从故事004.001和004.002学到的经验教训
+1. **PostgreSQL类型兼容性**: PostgreSQL不支持`tinyint`类型,需要改为`smallint`
+2. **集成测试数据库连接**: 使用`IntegrationTestDatabase`类替代`createIntegrationTestDb`函数
+3. **路由架构**: 参照订单模块采用链式聚合模式,使用独立路由文件聚合导出
+4. **测试写法**: 使用真实JWT令牌和RPC风格API调用
+5. **类型检查**: 注意分页参数类型、枚举使用、referenceId类型等问题
+6. **小数精度**: TypeORM decimal字段返回字符串,在服务中需要转换为数字
+7. **数据库索引**: 避免重复创建相同索引名称
+8. **认证失败**: 创建测试数据工厂,使用真实用户实体生成JWT令牌
+9. **Zod验证**: 将Schema中的`z.number()`改为`z.coerce.number()`
+10. **表单验证**: 为Zod schema字段添加中文错误消息,使用`z.coerce.number()`支持类型转换
+11. **组件集成**: 信用额度管理对话框已集成到用户管理UI包中
+
+### 数据模型设计 [Source: docs/prd/epic-004-credit-payment.md#数据库设计]
+**credit_balance_mt表结构**:
+```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='用户信用额度表';
+```
+
+**credit_balance_log_mt表结构**:
+```sql
+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='额度变更记录表';
+```
+
+### API设计 [Source: docs/prd/epic-004-credit-payment.md#API设计]
+**额度模块对外API(已实现)**:
+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` - 结账恢复额度
+
+**额度模块服务接口(供其他模块调用)**:
+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`包名导入服务类进行直接调用
+
+### 文件位置和命名约定
+- **额度模块包**: `packages/credit-balance-module-mt/`
+- **额度管理UI模块包**: `packages/credit-balance-management-ui-mt/`
+- **支付模块包**: `packages/mini-payment-mt/` (需要检查是否存在多租户版本)
+- **订单模块包**: `packages/orders-module-mt/`
+- **小程序项目**: `mini/` 目录下
+- **测试文件**: 各包的`tests/`目录下
+
+### 集成点要求
+1. **订单模块集成**:
+   - 扩展`orders_mt`表的`pay_type`字段,新增额度支付类型
+   - 订单模块导入`@d8d/credit-balance-module-mt`包
+   - 在取消订单逻辑中调用`CreditBalanceService.restoreBalanceForCancelOrder()`方法
+
+2. **支付模块集成**:
+   - 在`@d8d/mini-payment-mt`中新增额度支付处理逻辑
+   - 支付模块导入`@d8d/credit-balance-module-mt`包
+   - 在退款处理逻辑中调用`CreditBalanceService.restoreBalanceForRefund()`方法
+
+3. **小程序集成**:
+   - 更新支付页面,增加"额度支付"选项
+   - 更新个人中心页面,显示累计欠款信息
+   - 调用额度查询API获取用户额度信息
+
+4. **额度恢复逻辑**:
+   - **幂等性保证**: 同一订单只能恢复一次额度,防止重复恢复
+   - **金额验证**: 恢复金额不能超过原支付金额
+   - **状态检查**: 只有特定订单状态才能触发恢复
+   - **日志记录**: 每次恢复都记录详细的变更日志
+   - **事务处理**: 额度恢复与订单状态更新在同一事务中
+
+### 技术约束
+- **多租户支持**: 所有模块需要支持多租户上下文,通过租户ID进行数据隔离
+- **API集成**: 使用RPC风格的Hono Client进行API调用,确保类型安全
+- **状态管理**: 使用React Query进行服务端状态管理,确保数据同步
+- **错误处理**: 完整的错误处理机制,显示友好的错误提示
+- **事务处理**: 额度扣减和恢复操作使用数据库事务确保数据一致性
+- **并发控制**: 处理额度支付时的并发请求,防止超额支付
+
+### 没有在架构文档中找到的特定指导
+- 具体的支付模块实现细节
+- 具体的订单模块支付类型扩展实现
+- 具体的小程序支付页面修改示例
+- 具体的额度恢复幂等性实现示例
+
+## Testing
+### 测试标准 [Source: architecture/testing-strategy.md]
+- **测试文件位置**: 各包的`tests/`目录下
+- **单元测试位置**: `tests/unit/**/*.test.tsx`
+- **集成测试位置**: `tests/integration/**/*.test.tsx`
+- **测试框架**: Vitest + Testing Library + React Testing Library
+- **覆盖率要求**: 单元测试 ≥ 80%,集成测试 ≥ 60%
+- **测试模式**: 使用测试数据工厂模式,避免硬编码测试数据
+- **API模拟**: 使用MSW或Vitest的mock功能模拟API调用
+
+### 测试策略要求
+- **单元测试**: 验证单个组件功能、hooks逻辑、工具函数
+- **集成测试**: 验证API集成、权限控制、组件间协作
+- **支付流程测试**: 测试额度支付完整流程,包括额度检查、扣减、订单创建
+- **额度恢复测试**: 测试结账、取消订单、退款时的额度恢复逻辑
+- **并发测试**: 测试额度支付与微信支付的并行工作
+- **错误处理测试**: 测试各种错误场景和异常情况(额度不足、额度为0等)
+- **幂等性测试**: 测试额度恢复的幂等性,防止重复恢复
+
+### 测试数据管理
+- 使用测试数据工厂模式创建测试数据
+- 模拟API响应,避免真实API调用
+- 使用唯一标识符确保测试数据隔离
+- 模拟用户认证和权限状态
+- 创建测试用户额度数据(不同额度状态:正常、额度为0、额度不足)
+
+## Change Log
+| Date | Version | Description | Author |
+|------|---------|-------------|--------|
+| 2025-12-04 | 1.0 | 初始故事创建 | Bob (Scrum Master) |
+
+## Dev Agent Record
+*此部分由开发代理在实现过程中填写*
+
+### Agent Model Used
+
+### Debug Log References
+
+### Completion Notes List
+
+### File List
+
+## QA Results
+*此部分由QA代理在审查完成后填写*