This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-08-31
|
||||
94
openspec/changes/add-employee-collection-bills/design.md
Normal file
94
openspec/changes/add-employee-collection-bills/design.md
Normal file
@@ -0,0 +1,94 @@
|
||||
## Context
|
||||
|
||||
见 `proposal.md` 与 `specs/employee-collection-bill/spec.md`。现有后台套餐订单、代理充值、企业微信审批和审计已有各自业务事实,但没有将“后台账号代客户经办后的公司应收”作为独立对象保存。现有 `tb_agent_recharge_record` 已有金额、支付凭证和审批实例关联;套餐订单已有 `actual_paid_amount`。这些来源只能提供已确定的金额和关联键,不能被新功能改写。
|
||||
|
||||
本设计只处理上线后事件。线下付款并非本系统支付渠道事实,企业微信审批人员以第三方记录核验,因此本地只留存申请人声明、附件、冻结快照和企业微信最终结果。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 让账单、申请和分摊形成可并发保护、可重提、可审计的本地财务事实。
|
||||
- 使企业微信是唯一终审来源,同时沿用已有可靠提交、回调和轮询恢复机制。
|
||||
- 在订单/充值入账、退款和核销之间建立明确且幂等的关联。
|
||||
|
||||
**Non-Goals:**
|
||||
- 不建设公司收款账户目录,不接入或改造 OCR 契约,不校验同一外部付款在不同申请间的累计分摊。
|
||||
- 不回填历史业务,不允许“其他”来源手工建账,不处理平台代理 C 端资产钱包充值。
|
||||
- 不以账单功能重构订单、代理充值或企业微信通用审批模块。
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. 账单、申请、分摊分表保存
|
||||
|
||||
建立员工代收款账单、核销申请、核销分摊和线下收款方式字典四类事实。账单绑定唯一来源业务;申请绑定一次外部付款和一个企业微信审批实例;分摊连接申请与账单并冻结账单来源摘要。附件复用现有对象存储键/附件模式,审批快照复用既有通用审批上下文能力。
|
||||
|
||||
不把多笔付款、账单状态或附件塞入来源订单 JSON:来源订单既有生命周期不等于员工欠款,且一笔付款对多账单是独立关系。
|
||||
|
||||
### 2. 金额统一使用分,分摊在锁定账单中预占
|
||||
|
||||
账单应收、已核销、预占和申请付款金额均用 `int64` 分。提交/重提在同一 GORM 事务中按账单 ID 升序 `FOR UPDATE` 锁定,重新计算“应收金额 - 已通过分摊 - 其他审批中分摊”,再写申请与分摊。企业微信通过消费同样锁定申请和相关账单,使用审批实例唯一关联/状态条件更新保证至多入账一次。
|
||||
|
||||
不使用乐观展示余额或仅在回调时校验;那会让并发审批中申请超额占用同一账单。
|
||||
|
||||
### 3. 企业微信审批作为唯一状态推进器
|
||||
|
||||
申请提交事务只写本地申请、冻结快照、审批实例及可靠提交请求。审批回调和既有兜底查询都进入同一个幂等消费用例:通过才计入账单已核销,驳回才释放预占。提交失败或渠道未知保持在途,禁止本地财务人工改审批结果。
|
||||
|
||||
已驳回“重提”保留原申请主键,但新增一次审批实例及当次不可变快照;已通过分摊永不更新。这样列表可以按申请聚合,审计仍能回放每次审批。
|
||||
|
||||
### 4. 来源事件采用幂等 Outbox/消费者
|
||||
|
||||
线下套餐订单创建成功和代理充值审批入账完成后,在各自成功事务中写唯一来源事件或直接以唯一来源约束创建账单;选择以现有 Outbox 可用模式为准。消费者以来源类型+来源 ID 唯一约束去重。订单创建不得等待企业微信或外部付款;代理充值必须以“已通过且已入账”这一既有终态作为来源。
|
||||
|
||||
### 5. 退款只自动影响未存在已通过分摊的账单
|
||||
|
||||
退款处理在退款成功业务事务中查找来源账单并锁定。无已通过分摊时写冲销/关闭事实及更新金额;有已通过分摊时不动账,只写可追溯关联提示。这避免已由企业微信核验的员工欠款被退款回调静默重建或冲销。
|
||||
|
||||
## 业务动作契约
|
||||
|
||||
以下是本 Change 新增后台动作的已确认设计;路径遵循既有 `/api/admin` 路由约定,所有金额字段均为 `int64` 分,所有成功响应使用既有 `pkg/response` 包装。
|
||||
|
||||
### 收款方式字典维护
|
||||
|
||||
- `POST /employee-collection-payment-methods`:仅超级管理员。请求包含 `code`(1~64 字符、全局唯一)、`name`(1~100 字符)、`sort`(非负整数)、`enabled`、`remark`(最多 500 字符)。创建后返回字典 ID、字段值和创建时间。
|
||||
- `PUT /employee-collection-payment-methods/:id`:仅超级管理员;不得修改已引用项的 `code`,可修改名称、排序、启停和备注。不存在返回既有“资源不存在”错误;重复编码返回稳定“收款方式编码已存在”错误。
|
||||
- `DELETE /employee-collection-payment-methods/:id`:仅未被申请引用的项可物理删除;已引用返回“收款方式已被引用,只能停用”。每个成功写操作记录操作者和前后快照。
|
||||
|
||||
### 账单查询与关闭
|
||||
|
||||
- `GET /employee-collection-bills`:员工强制加 `debtor_account_id=当前账号`;财务、超级管理员按既有数据范围过滤。支持来源类型、来源单号、账单状态、欠款人、客户/店铺、创建时间范围筛选和分页。每行返回账单 ID、来源摘要、欠款人快照、应收、已核销、预占、剩余、状态和创建时间。
|
||||
- `GET /employee-collection-bills/:id`:在同一数据范围校验后返回账单、来源摘要、退款冲销、分摊、申请与审批历史;附件只返回既有授权下载所需的安全引用,不返回对象存储敏感内容。
|
||||
- `POST /employee-collection-bills/:id/close`:仅超级管理员;请求 `reason` 必填、最长 500 字符。事务中锁定账单,存在审批中申请返回“账单存在审批中核销申请,不能关闭”;已关闭返回既有状态冲突;成功时仅作废未核销余额并写关闭审计。
|
||||
|
||||
### 核销申请创建、修改与重提
|
||||
|
||||
- `POST /employee-collection-applications`:员工为本人可见账单创建,超级管理员可代办但请求必须附 `acting_reason`(1~500 字符)。请求包含 `payment_method_id`、`paid_amount`(正分)、`payer_name`、`paid_at`(带时区 RFC3339 时间)、`external_transaction_no`、`payment_voucher_keys`(1~5 个既有附件键)、`remark`、`allocations[]`;每个分摊包含 `bill_id` 和正的 `amount`。
|
||||
- 服务按账单 ID 升序锁定,校验字典启用、账单可见且未关闭、分摊不超过该账单 `应收-已核销-其他审批中预占`、分摊总额不超过 `paid_amount`。成功返回申请 ID、状态 `审批中`、审批实例 ID、冻结快照与各分摊;任一校验失败时不保存申请、分摊或预占。
|
||||
- `PUT /employee-collection-applications/:id`:仅申请人或代办超级管理员,且仅已驳回申请可修改;入参同创建。事务释放旧驳回版本无预占事实,重新锁定和校验账单,保存新的不可变材料快照并创建新的企业微信审批实例。已通过、审批中、已撤销/关闭状态返回状态冲突。
|
||||
|
||||
### 企业微信审批结果消费
|
||||
|
||||
- 企业微信回调和既有状态恢复任务均按审批实例 ID 进入同一应用用例,不提供后台“通过/驳回”接口。
|
||||
- 最终通过:锁定申请及按 ID 升序的全部账单;仅当申请仍为审批中时,将每笔分摊从预占转入已核销,重新计算账单 `待核销/部分核销/已核销` 状态,标记申请已通过,并记录审批结果。重复或乱序的同一终态不重复增加已核销金额。
|
||||
- 最终驳回:仅当申请仍为审批中时释放全部预占,标记已驳回并保存审批意见;重复回调不重复释放。提交失败、回调延迟和未知结果维持在途,由既有查询恢复任务确认,不得人工改写终态。
|
||||
|
||||
### 来源建账与退款冲销
|
||||
|
||||
- 后台线下套餐订单成功提交后,以 `order.id`、`operator_account_id`、`operator_account_type=platform` 和非空 `actual_paid_amount` 判定建账;来源唯一键为 `order:{id}`。重复订单事务、可靠事件重放或消费者重试均返回同一账单,不重复建账。
|
||||
- 代理线下充值仅在既有审批最终通过且钱包入账完成后,以 `agent_recharge.id` 为唯一来源建账;线上充值、审批未通过或未完成入账不建账。
|
||||
- 套餐退款成功时锁定来源账单:无已通过分摊的全额退款关闭账单;无已通过分摊的部分退款冲减应收;存在已通过分摊时只新增退款关联提示,不修改应收、已核销或员工欠款。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- [企业微信回调重复、乱序或未知] → 以审批实例、申请状态和分摊状态条件更新幂等消费,复用渠道查询恢复。
|
||||
- [外部付款敏感信息泄露] → 附件使用对象键和既有授权访问;日志/审计只记录脱敏摘要与业务 ID。
|
||||
- [来源事件与账单创建不一致] → 在来源成功事务写可靠事件,消费者以唯一来源约束重放。
|
||||
- [超额核销] → 提交、重提和审批通过均锁定账单并校验预占余额。
|
||||
- [退款与核销并发] → 退款和审批消费按相同账单锁顺序串行,已通过分摊优先保留。
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. 新增成对迁移创建字典、账单、申请、分摊、审批快照/冲销关联所需表、唯一约束和查询索引;不修改既有迁移。
|
||||
2. 先部署可读新表和来源事件的兼容代码,再启用账单生产与核销入口;上线时间作为历史切割点写受控配置或迁移基准。
|
||||
3. 在隔离环境验证上线前订单/充值不建账、重复事件不重复建账、并发预占、通过/驳回/重提、退款联动及迁移 up/down/up。
|
||||
4. 回滚时先停止新入口和事件消费;已有账单事实保留,只有维护者确认未产生不可逆业务数据时才执行 down。
|
||||
31
openspec/changes/add-employee-collection-bills/proposal.md
Normal file
31
openspec/changes/add-employee-collection-bills/proposal.md
Normal file
@@ -0,0 +1,31 @@
|
||||
## Why
|
||||
|
||||
平台代理或无代理归属的 C 端客户以线下方式购买套餐、或代理线下充值预存款时,实际经办后台账号形成公司应收欠款。当前系统只有订单或充值审批,无法将这笔欠款、客户外部付款凭证、企业微信核验和最终核销结果形成独立、可分摊且可审计的闭环。
|
||||
|
||||
本 Change 落实讨论稿 AUG26-001:只覆盖功能上线后的新增业务,不回填任何历史账单,避免把历史支付事实以推测方式写入新财务账。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 新增员工代收款账单:后台线下套餐订单创建成功后,或代理线下预存款/主钱包充值经企业微信审批通过并完成入账后,按确定金额为实际经办账号创建唯一账单。
|
||||
- 新增核销申请和账单分摊:员工按一笔外部付款创建一张申请,可选择多张账单并填写各自分摊金额;同一账单可由多笔已通过申请分次核销。
|
||||
- 新增固定分类的线下收款方式字典;申请冻结字典名称、外部付款、附件、账单分摊和审批快照。OCR 仅可预填流水号和付款金额,人工确认值才是业务事实。
|
||||
- 核销申请仅由企业微信最终通过或驳回驱动;提交失败、回调延迟或结果未知复用既有审批查询/恢复闭环,禁止本地人工绕过终审。
|
||||
- 新增账单、核销申请、分摊、附件与审批记录的权限受控查询;超级管理员关闭未结清账单、来源订单退款时的账单冲销均保留审计。
|
||||
- **BREAKING**:会生成员工账单的后台线下套餐订单不再在创建时强制上传付款凭证;凭证和外部付款信息改为核销申请必填。赠送套餐等不生成账单的既有线下订单继续保持原凭证要求。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `employee-collection-bill`: 员工代收款账单、线下收款方式、分摊核销申请、企业微信审批闭环、退款冲销和财务查询。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- 无。本 Change 通过新能力监听并引用既有订单和代理充值的已确定业务事实,不重写其既有主规格。
|
||||
|
||||
## Impact
|
||||
|
||||
- 数据:新增账单、收款方式字典、核销申请、分摊和审批快照等表;订单/充值来源只保存可追溯关联,不回填历史记录。
|
||||
- 写侧:后台线下套餐下单、代理线下充值入账、核销提交/重提/关闭、企业微信审批结果消费、套餐退款。
|
||||
- 读取:财务账单与申请列表、详情、导出;员工仅看本人,财务/超级管理员按既有数据范围看全部。
|
||||
- 依赖:复用既有企业微信通用审批实例、可靠提交和状态恢复机制;OCR 与外部付款渠道不在本 Change 新建契约。
|
||||
@@ -0,0 +1,83 @@
|
||||
## Purpose
|
||||
|
||||
为后台账号代客户经办的线下套餐购买和代理预存款充值建立独立的员工应收、外部付款核验和企业微信终审闭环;该能力只保存可追溯的本地业务事实,不推测或回填历史第三方付款。
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 员工代收款账单来源、金额与上线边界
|
||||
系统 SHALL 仅为功能上线后新发生的下列业务创建员工代收款账单,并以实际发起该业务的后台账号作为不可修改的欠款人:
|
||||
|
||||
- 平台业务员或超级管理员创建的、会生成账单的后台线下套餐订单,账单金额取订单 `actual_paid_amount`;代理代购和无代理归属自营 C 端均适用。该订单创建成功后仍按既有规则立即激活。
|
||||
- 代理线下预存款/主钱包充值在企业微信最终通过且完成入账后,账单金额取对应充值记录 `amount`。
|
||||
|
||||
客户自行线上支付、平台代理 C 端客户充值资产钱包、订单失败或取消、赠送套餐等不产生员工账单的既有线下订单,以及“其他”手工来源 MUST NOT 创建账单。系统 MUST 为同一来源业务建立至多一张账单,并保存来源类型、来源 ID、来源单号、客户/店铺快照、欠款人、应收金额和创建时间;上线前业务不回填、不补建。
|
||||
|
||||
#### Scenario: 后台线下套餐订单产生账单
|
||||
- **WHEN** 平台业务员或超级管理员成功创建一个需要生成账单的后台线下套餐订单
|
||||
- **THEN** 系统以该操作账号为欠款人、以订单 `actual_paid_amount` 为应收金额创建唯一待核销账单,且订单无需因未上传付款凭证而阻断
|
||||
|
||||
#### Scenario: 审批入账的代理充值产生账单
|
||||
- **WHEN** 功能上线后代理线下预存款/主钱包充值经企业微信最终通过并完成入账
|
||||
- **THEN** 系统以实际发起充值的后台账号和充值 `amount` 创建唯一待核销账单
|
||||
|
||||
#### Scenario: 重复来源或历史业务不产生重复账单
|
||||
- **WHEN** 同一来源业务被重复处理、重复回调,或业务发生在功能上线前
|
||||
- **THEN** 系统至多保留一张来源关联账单,且不补建上线前账单
|
||||
|
||||
### Requirement: 账单余额、状态与关闭
|
||||
账单 SHALL 独立维护 `待核销`、`部分核销`、`已核销`、`已关闭` 状态及应收金额、已核销金额、审批中预占金额和剩余可核销金额。只有企业微信最终通过的分摊增加已核销金额;审批中的分摊预占剩余可核销金额,防止并发申请超额核销。账单已核销金额等于应收金额时 MUST 为已核销;关闭账单只作废当时未核销余额,已核销金额必须保留。
|
||||
|
||||
欠款人离职、禁用或变更组织后,账单欠款人身份和既有账单范围 MUST 保持不变。员工仅可查询本人账单和申请;财务与超级管理员可按既有数据范围查询;仅超级管理员可代办创建、修改或重提申请,且必须记录实际代办人和原因。
|
||||
|
||||
#### Scenario: 部分核销后仍可继续核销
|
||||
- **WHEN** 一张账单存在企业微信已通过但未结清的分摊
|
||||
- **THEN** 系统增加已核销金额、将账单标记为部分核销,并仅允许新的分摊使用未被已通过或审批中分摊占用的余额
|
||||
|
||||
#### Scenario: 关闭未结清账单
|
||||
- **WHEN** 超级管理员对待核销、部分核销或已驳回关联申请的账单填写关闭原因并执行关闭,且账单不存在审批中申请
|
||||
- **THEN** 系统作废未核销余额、将账单标记为已关闭、保留已核销金额和操作审计
|
||||
|
||||
#### Scenario: 审批中账单不可关闭
|
||||
- **WHEN** 超级管理员尝试关闭存在审批中核销申请的账单
|
||||
- **THEN** 系统拒绝关闭,账单金额和状态不变
|
||||
|
||||
### Requirement: 外部付款核销申请与分摊
|
||||
员工 SHALL 按一笔外部付款创建一张核销申请。申请 MUST 选择一个启用的线下收款方式字典项,并保存其稳定编码和名称快照;必须保存经人工确认的付款金额、付款方、付款时间、外部交易流水号、至少一个支付凭证和可选其他凭证、备注及一个或多个账单分摊。申请人只能通过勾选可见账单创建分摊,系统带出只读来源订单、客户和资产信息。
|
||||
|
||||
系统 SHALL 按账单产生时间从早到晚用本次付款金额预填分摊,最后一张填入剩余金额;申请人可修改各分摊金额。单笔分摊 MUST 大于零且不得超过该账单可核销余额;分摊总额 MUST 不超过本次人工确认付款金额。同一外部付款可被多个核销申请引用,本期 MUST NOT 对跨申请累计分摊金额实施系统防重或金额上限校验。
|
||||
|
||||
#### Scenario: 一笔付款分摊多张账单
|
||||
- **WHEN** 员工选择多张可见账单并提交一笔外部付款的核销申请
|
||||
- **THEN** 系统按账单时间预填分摊、校验每张账单可核销余额和申请总额,并为该申请创建唯一企业微信审批实例
|
||||
|
||||
#### Scenario: 账单并发申请预占
|
||||
- **WHEN** 两个核销申请并发选择同一账单的剩余余额
|
||||
- **THEN** 系统至多接受不超过该账单未核销余额的审批中和已通过分摊,其余申请返回余额不足且不创建超额分摊
|
||||
|
||||
### Requirement: 核销申请审批、重提与幂等
|
||||
核销申请状态 SHALL 为 `审批中`、`已通过`、`已驳回`、`已撤销/已关闭`,且不得以申请状态覆盖账单核销状态。提交或重提时系统 MUST 冻结当次收款方式、外部付款、附件、备注、账单分摊及审批材料快照,并创建新的企业微信审批实例。
|
||||
|
||||
企业微信最终通过时,系统 MUST 幂等地将申请标记为已通过、将各分摊写入账单已核销金额并释放其预占;最终驳回时 MUST 标记申请已驳回、释放全部预占且保留审批意见。已驳回申请可修改全部申请内容后重提,历史审批实例、材料和结果不得覆盖;已通过分摊不可修改。企业微信提交失败、回调延迟或结果未知时申请保持在途,系统 MUST 使用既有查询/恢复机制确认渠道结果,且不得由本地人工通过或拒绝绕过企业微信。
|
||||
|
||||
#### Scenario: 企业微信通过核销申请
|
||||
- **WHEN** 企业微信对含多笔分摊的核销申请返回最终通过,且该结果首次被消费
|
||||
- **THEN** 系统仅一次更新申请、各账单已核销金额和状态,并保留审批实例及冻结快照
|
||||
|
||||
#### Scenario: 企业微信驳回后重提
|
||||
- **WHEN** 企业微信最终驳回核销申请
|
||||
- **THEN** 系统释放预占、保留驳回实例和意见;员工或有代办权限的超级管理员修改申请后重提时创建新的审批实例
|
||||
|
||||
### Requirement: 收款方式字典、退款联动与可追溯性
|
||||
系统 SHALL 提供唯一固定分类的线下收款方式字典。超级管理员可维护名称、稳定编码、排序、启停和备注;已被业务引用的字典项 MUST NOT 被物理删除,只能停用,且历史申请继续显示冻结名称。
|
||||
|
||||
来源套餐订单全额退款且账单从未存在已通过分摊时,系统 MUST 自动关闭账单并记录“来源订单全额退款”;部分退款且从未存在已通过分摊时,系统 MUST 按退款金额冲减账单应收金额并保留来源订单退款冲销记录。账单存在任一已通过分摊时,系统 MUST NOT 自动冲销,仅在账单详情提示来源订单退款。退款不恢复已核销账单的员工欠款。
|
||||
|
||||
账单、申请、分摊、附件、审批实例、字典快照、关闭和退款冲销 MUST 可按权限查询并记录操作审计;审计和日志不得保存完整支付凭证敏感内容。OCR 若可用仅用于预填,必须允许申请人或审核人更正,且识别值不是资金事实。
|
||||
|
||||
#### Scenario: 来源订单部分退款且未核销
|
||||
- **WHEN** 来源套餐订单部分退款,且其账单不存在任何已通过分摊
|
||||
- **THEN** 系统按退款金额冲减账单应收金额,保留退款冲销关联,并重新计算账单状态和可核销余额
|
||||
|
||||
#### Scenario: 被引用字典项停用
|
||||
- **WHEN** 超级管理员停用已被核销申请引用的线下收款方式
|
||||
- **THEN** 新申请不可选择该方式,历史申请仍展示其冻结名称和稳定编码
|
||||
27
openspec/changes/add-employee-collection-bills/tasks.md
Normal file
27
openspec/changes/add-employee-collection-bills/tasks.md
Normal file
@@ -0,0 +1,27 @@
|
||||
## 1. 账单数据与基础契约
|
||||
|
||||
- [ ] 1.1 盘点现有订单、代理充值、通用企业微信审批、附件、Outbox 和审计模型,确定来源事件、附件键和审批快照的复用点;不得复制敏感付款内容。
|
||||
- [ ] 1.2 新增成对迁移及 GORM 模型:线下收款方式字典、员工代收款账单、核销申请、申请—账单分摊、退款冲销/审批快照关联;为来源唯一性、审批实例唯一性、账单查询和分摊锁定建立约束/索引。
|
||||
- [ ] 1.3 定义金额分、账单状态、申请状态、来源类型和稳定错误码;实现中文名称、DTO 枚举说明及金额/附件/分摊校验。
|
||||
- [ ] 1.4 实现超级管理员维护线下收款方式字典的新增、编辑、启停和受引用不可删除规则,并写配置审计。
|
||||
|
||||
## 2. 来源建账与账单读取
|
||||
|
||||
- [ ] 2.1 在后台线下套餐订单成功路径识别应建账场景,以实际操作后台账号和 `actual_paid_amount` 可靠、幂等地创建账单;调整仅该场景的创建时付款凭证要求,保留赠送等非建账订单的既有要求。
|
||||
- [ ] 2.2 在代理线下预存款/主钱包充值企业微信通过且完成入账路径可靠、幂等地创建账单,金额取充值 `amount`;线上充值和未入账审批不得建账。
|
||||
- [ ] 2.3 实现账单列表、详情和统计 Query:按来源、状态、时间、员工、客户筛选,员工仅见本人,财务/超级管理员按数据范围见全部;返回应收、已核销、预占和未核销金额及审批中标识。
|
||||
- [ ] 2.4 实现账单关闭用例:仅超级管理员、仅允许无审批中申请的未结清账单、必须填写原因,并在事务内保存状态变化与成功审计。
|
||||
|
||||
## 3. 核销申请、审批与退款联动
|
||||
|
||||
- [ ] 3.1 实现核销申请创建和已驳回重提:锁定选中账单、按时间预填、校验付款金额与分摊、预占余额、冻结收款方式/外部付款/附件/账单摘要,并创建新的企业微信审批实例和可靠提交请求。
|
||||
- [ ] 3.2 接入企业微信最终通过、驳回、提交失败和状态查询恢复:通过时一次性增加已核销并释放预占,驳回时释放预占;用审批实例、状态条件更新和账单锁保证重复/乱序回调不重复核销。
|
||||
- [ ] 3.3 实现代办权限、申请/分摊/审批历史查询及附件授权访问;超级管理员代办创建、修改或重提时强制记录实际代办人和原因。
|
||||
- [ ] 3.4 在套餐退款成功处理链路实现账单冲销:无已通过分摊的全额退款自动关闭、部分退款冲减应收;存在已通过分摊时只保留退款关联提示,不恢复欠款。
|
||||
- [ ] 3.5 为建账、申请提交/重提、审批通过/驳回、账单关闭和退款冲销补齐事务内审计;检查日志、错误和导出不暴露附件内容、完整交易敏感体或 OCR 原始结果。
|
||||
|
||||
## 4. 路由、文档与验证
|
||||
|
||||
- [ ] 4.1 注册账单、申请、字典和导出所需路由及 RouteSpec,补齐 `internal/bootstrap`、`cmd/api/docs.go` 和 `cmd/gendocs/main.go` 装配;Handler 使用 `pkg/response` 和稳定错误。
|
||||
- [ ] 4.2 在隔离数据库按显式 `DB_*` 和 `scripts/migrate.sh` 验证迁移 up/down/up;人工核对上线前来源不建账、来源幂等、并发预占、审批重放、驳回重提、关闭限制及退款三类联动。
|
||||
- [ ] 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。
|
||||
Reference in New Issue
Block a user