Files
junhong_cmp_fiber/openspec/changes/add-employee-collection-bills/tasks.md
break ce24d5612e
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m20s
feat(员工代收款): 新增员工代收款账单闭环
- 新增 6 张表与成对迁移 000212,扩展企业微信审批场景业务类型白名单
- 后台线下套餐订单与两条代理线下充值入账路径在来源成功事务内建账,来源唯一键幂等
- 核销申请、审批尝试记录、账单分摊预占与驳回重提,审批业务类型 employee_collection_approval
- 企业微信终态消费幂等:通过转已核销、驳回释放预占、通过后撤销不回滚并转异常终态
- 退款成功事务内按 bill_id+refund_id 幂等冲销账单或仅写退款关联提示
- 线下收款方式字典、账单查询/统计/关闭、申请查询与代办权限,均写入事务内审计

OpenSpec Change: add-employee-collection-bills
2026-09-10 18:24:05 +08:00

27 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 1. 账单数据与基础契约
- [x] 1.1 盘点现有订单、代理充值、通用企业微信审批、钱包入账、附件、Outbox 和审计模型,确定来源建账点、附件键和审批尝试记录的复用点;确认新业务类型 `employee_collection_approval` 以审批尝试记录主键作为 `business_id` 的兼容方案;不得复制敏感付款内容。
- [x] 1.2 新增成对迁移与 GORM 模型:线下收款方式字典、员工代收款账单、核销申请、申请—账单分摊、审批尝试记录、退款冲销关联;为来源唯一性、审批实例唯一性、账单查询和分摊锁定建立约束/索引。同时新增迁移扩展 `tb_wecom_approval_scene``business_type` CHECK 以纳入新业务类型(不修改既有迁移)。迁移不预占编号,按实施开始时 `migrations/` 目录最大编号顺延。
- [x] 1.3 定义金额分、账单状态、申请状态、来源类型和稳定错误码实现中文名称、DTO 枚举说明及金额/附件/分摊校验。
- [x] 1.4 实现超级管理员维护线下收款方式字典的新增、编辑、启停和受引用不可删除规则,并写配置审计。
## 2. 来源建账与账单读取
- [x] 2.1 在后台线下套餐订单成功事务内(`tx.Create(order)` 之后)按判据 `payment_method = offline``operator_account_type = platform` ∧ 订单不含赠送套餐 ∧ `actual_paid_amount > 0` 以实际操作平台账号为欠款人、以 `actual_paid_amount` 为应收创建账单;`actual_paid_amount ≤ 0` 不建账;以 `order:{id}` 唯一键保证重复处理、重放或重试返回同一账单;创建时付款凭证的放宽范围与该判据严格互补,赠送等不建账订单保持既有凭证要求;不新增来源 Outbox 事件类型,不存在按历史订单扫描建账的路径。
- [x] 2.2 在“平台账号发起的线下充值入账成功”这一既有事实上、于入账事务内以 `recharge:{id}` 唯一键创建账单,金额取充值 `amount`,欠款人为发起充值的平台账号;覆盖既有企业微信终审通过入账与既有线下充值人工确认入账两条入口;线上充值、审批未通过或未完成入账不建账;不依赖申请表未落库的新字段,不存在按历史充值扫描建账的路径。
- [x] 2.3 实现账单列表、详情和统计 Query按来源、状态、时间、欠款人、客户筛选欠款人仅见本人超级管理员见全部统计与列表使用相同筛选条件与可见性范围返回应收、已核销、未核销金额合计与待处理账单数列表返回应收、已核销、预占和未核销金额及审批中标识。
- [x] 2.4 实现账单关闭用例:仅超级管理员、仅允许无审批中申请的未结清账单、必须填写原因,并在事务内保存状态变化与成功审计。
## 3. 核销申请、审批与退款联动
- [x] 3.1 实现核销申请创建和已驳回重提:锁定选中账单、按时间预填、校验付款金额与分摊、预占余额、每次提交或重提新增一条不可变审批尝试记录(冻结收款方式/外部付款/附件/账单摘要)并以尝试记录主键为 `business_id` 创建新的企业微信审批实例和可靠提交请求;申请只保存最新审批实例 ID。
- [x] 3.2 接入企业微信最终通过、驳回、通过后撤销、提交失败和状态查询恢复:通过时一次性增加已核销并释放预占,驳回时释放预占,通过后撤销时不回滚已核销并将申请转异常终态、保留审计、禁止自动重提;用审批实例、审批尝试记录、状态条件更新和账单锁保证重复/乱序回调不重复核销;施工时列全四处注册点:业务类型常量、`validApprovalBusinessType``sceneBusinessFields`、数据库 CHECK、`cmd/worker/main.go` 的审批决策消费者注册。
- [x] 3.3 实现代办权限、申请/分摊/审批历史查询及附件访问:附件只返回既有对象键引用并复用既有预签名下载能力,不承诺资源级鉴权;超级管理员代办创建、修改或重提时强制记录实际代办人和原因。
- [x] 3.4 在既有套餐退款成功处理事务内实现账单冲销:以本次退款成功金额与账单应收(来源订单 `actual_paid_amount`)比较,等于应收且无已通过或审批中分摊时自动关闭、小于应收且无已通过或审批中分摊时冲减应收;存在已通过或审批中(预占)分摊时只写退款关联提示,不修改应收、已核销或预占;以 `bill_id + refund_id` 唯一事实幂等,不依赖退款事务的 `changed` 标志;不实现 AUG26-006 的退款审批、状态机或渠道退款。
- [x] 3.5 为建账、申请提交/重提、审批通过/驳回/通过后撤销、账单关闭和退款冲销补齐事务内审计;检查日志、审计和错误不暴露附件内容、完整交易敏感体或 OCR 原始结果。
## 4. 路由、文档与验证
- [x] 4.1 注册账单(含统计聚合)、申请和字典所需路由及 RouteSpec补齐 `internal/bootstrap``cmd/api/docs.go``cmd/gendocs/main.go` 装配Handler 使用 `pkg/response` 和稳定错误;不新增导出路由。
- [x] 4.2 按 ENG-TEST-001 在维护者指定的 `junhong_cmp_test` PostgreSQL + Redis DB 6 验证:迁移从本地工作区以显式 `DB_*` 执行 `scripts/migrate.sh`,只创建、删除本 Change 自己的 fixture禁止重置整库不额外要求独立数据库、Redis DB 或 namespace仅连接、迁移或实际行为失败时才阻塞对应场景。人工核对不存在按历史记录扫描或补建的路径、重复消费来源不重复建账、并发预占、审批通过/驳回/重提/通过后撤销/重放、关闭限制、退款三类联动(全额关闭、部分冲减、存在已通过或审批中分摊仅提示),以及迁移 up/down/up。
- [x] 4.3 运行 `gofmt -w`(变更 Go 文件)、`go build ./cmd/api ./cmd/worker``go run cmd/gendocs/main.go``openspec validate add-employee-collection-bills --strict``openspec doctor --json``./scripts/context-health.sh`;自动化测试按项目决策为 N/A。