完成
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Failing after 7m30s

This commit is contained in:
2026-07-25 19:06:31 +08:00
parent cb26217205
commit 09ffee8590
7 changed files with 158 additions and 20 deletions

View File

@@ -94,11 +94,25 @@
| #55 分配覆盖 | `POST /api/admin/shop-package-batch-allocations``PATCH /api/admin/shop-package-allocations/:id/expiry-base` | 分配时使用 `expiry_base_override``null` 表示跟随套餐默认值 | | #55 分配覆盖 | `POST /api/admin/shop-package-batch-allocations``PATCH /api/admin/shop-package-allocations/:id/expiry-base` | 分配时使用 `expiry_base_override``null` 表示跟随套餐默认值 |
| #43 系列套餐多选 | `POST /api/admin/shop-series-grants``PUT /api/admin/shop-series-grants/:id/packages` | `packages` 是 1100 项数组,每项包含 `package_id``cost_price`,删除时传 `remove=true` | | #43 系列套餐多选 | `POST /api/admin/shop-series-grants``PUT /api/admin/shop-series-grants/:id/packages` | `packages` 是 1100 项数组,每项包含 `package_id``cost_price`,删除时传 `remove=true` |
#### 3.2.1 #43 套餐价格展示和已授权/未授权区分
#43 不需要新增后端接口,前端按下面两个现有接口组合数据:
1. 调用 `GET /api/admin/packages?series_id={series_id}&page=1&page_size=100` 分页取得该系列全部套餐。列表项直接使用:
- `suggested_retail_price`:建议售价,单位分;未配置时为空。
- `cost_price`:公司成本价,单位分。
2. 编辑已有授权时,调用 `GET /api/admin/shop-series-grants/{grant_id}`,注意路径参数是授权记录 ID不是系列 ID。
3. 将授权详情的 `packages[].package_id` 组成已授权套餐 ID 集合。
4. 套餐列表项的 `id` 在该集合中显示“已授权”,否则显示“未授权”。授权详情 `packages[].cost_price` 是该次店铺授权成本价,不要拿它替代套餐列表的公司成本价。
5. 用户提交多选结果时,创建授权调用 `POST /api/admin/shop-series-grants`;编辑授权调用 `PUT /api/admin/shop-series-grants/{grant_id}/packages`。新增/调价项传 `package_id + cost_price`,删除项传 `package_id + remove=true`
套餐接口是分页接口;一个系列超过 100 个套餐时,前端必须继续请求后续页,再完成已授权集合标记。
### 3.3 审批、退款和员工线下代充值 ### 3.3 审批、退款和员工线下代充值
| 需求 | 接口 | 参数或返回变化 / 前端调用说明 | | 需求 | 接口 | 参数或返回变化 / 前端调用说明 |
| --- | --- | --- | | --- | --- | --- |
| #182/#44 退款 | `GET /api/admin/refunds``GET /api/admin/refunds/:id` | 新增/补齐 `submitter_id``submitter_name``approval_provider``approval_status``approval_status_name` | | #181/#182/#44 退款 | `GET /api/admin/refunds``GET /api/admin/refunds/:id` | 新增/补齐 `asset_identifier``submitter_id``submitter_name``approval_provider``approval_status``approval_status_name`;资产标识是退款创建时固化的快照,卡为 ICCID设备按 VirtualNo 优先、IMEI 兜底;历史空快照不做兼容 |
| #182/#44 充值 | `GET /api/admin/agent-recharges``GET /api/admin/agent-recharges/:id` | 同上;线下代充值的审批状态只读展示 | | #182/#44 充值 | `GET /api/admin/agent-recharges``GET /api/admin/agent-recharges/:id` | 同上;线下代充值的审批状态只读展示 |
| #44 换货 | `GET /api/admin/exchanges``GET /api/admin/exchanges/:id` | 新增/补齐 `submitter_id``submitter_name` | | #44 换货 | `GET /api/admin/exchanges``GET /api/admin/exchanges/:id` | 新增/补齐 `submitter_id``submitter_name` |
| #34 员工线下代充 | `POST /api/admin/agent-recharges` | 仍用原入口;`payment_method=offline` 时传目标 `shop_id`、金额、15 个 `payment_voucher_key` 和备注,创建后等待企微审批 | | #34 员工线下代充 | `POST /api/admin/agent-recharges` | 仍用原入口;`payment_method=offline` 时传目标 `shop_id`、金额、15 个 `payment_voucher_key` 和备注,创建后等待企微审批 |
@@ -110,6 +124,83 @@
| #37 场景模板 | `PUT /api/admin/wecom/scenes/:business_type``GET /api/admin/wecom/scenes` | `business_type``refund_approval``offline_recharge_approval`;传 `application_id``template_id``control_mapping[]` | | #37 场景模板 | `PUT /api/admin/wecom/scenes/:business_type``GET /api/admin/wecom/scenes` | `business_type``refund_approval``offline_recharge_approval`;传 `application_id``template_id``control_mapping[]` |
| #37 回调 | `GET/POST /api/callback/wecom/approval/:application_id` | 由企微服务器调用,前端无需调用 | | #37 回调 | `GET/POST /api/callback/wecom/approval/:application_id` | 由企微服务器调用,前端无需调用 |
#### 3.3.1 企业微信审批 8 个接口的前端调用流程
企业微信配置页使用 8 个 `/api/admin/wecom` 接口账号绑定属于账号模块因此完整闭环是“8 个企微配置接口 + 1 个账号绑定接口”。应用凭据和场景写操作应只向超级管理员开放;前端收到 403 时不要降级绕过。
| 顺序 | 接口 | 页面动作与调用说明 |
| --- | --- | --- |
| 1 | `POST /api/admin/wecom/applications` | 保存应用。传 `corp_id``agent_id``name``secret``callback_token`、43 位 `encoding_aes_key``status=1`。相同 `corp_id + agent_id` 再次提交表示更新;保存响应中的 `id` 是后续 `application_id` |
| 2 | `GET /api/admin/wecom/applications?page=1&page_size=20` | 进入配置页或保存后刷新应用列表,展示连接时间、启用状态、默认发起人和凭据是否完整 |
| 3 | `POST /api/admin/wecom/applications/{id}/test` | 用户点击“测试连接”时调用;`data.success=true` 只表示成功取得 access_token不表示通讯录、模板和回调均已配置完成 |
| 4 | `POST /api/admin/wecom/applications/{id}/members/sync` | 连接成功后点击“同步成员”;后端拉取该自建应用可见范围,返回 `synced_count``synced_at` |
| 5 | `GET /api/admin/wecom/applications/{id}/members?page=1&page_size=20&keyword=...` | 查询最近同步的本地成员快照,`keyword` 可按姓名或 userid 搜索;用于默认发起人和账号绑定的选择器,不要允许手输一个未同步 userid |
| 6 | `PUT /api/admin/wecom/applications/{id}/default-creator` | 从成员选择器取 `userid`,请求体为 `{"userid":"zhangsan"}`。代理等非企微账号提交业务时,企微审批由该成员代为发起,但本地业务提交人仍保持真实账号 |
| 7 | `PUT /api/admin/wecom/scenes/{business_type}` | 分别保存退款和线下代充值模板映射;后端会实时读取企微模板详情并校验控件 ID、类型、必填控件和选择项 key校验失败时页面应保留用户输入并展示后端错误 |
| 8 | `GET /api/admin/wecom/scenes?page=1&page_size=20` | 进入场景页或保存后刷新,展示 `business_type_name`、模板名称、状态、最近校验时间和控件映射 |
应用保存请求示例:
```json
{
"corp_id": "wwxxxxxxxxxxxxxxxx",
"agent_id": 1000002,
"name": "测试环境审批应用",
"secret": "企微应用Secret",
"callback_token": "企微后台配置的回调Token",
"encoding_aes_key": "43位EncodingAESKey",
"status": 1
}
```
场景路径只支持:
- `refund_approval`:退款审批。
- `offline_recharge_approval`:员工线下代充值审批。
场景保存请求示例:
```json
{
"application_id": 1,
"template_id": "企微模板ID",
"control_mapping": [
{
"business_field": "refund_no",
"control_id": "Text-xxxxxxxx",
"control_type": "Text",
"option_mapping": {}
}
],
"status": 1
}
```
`control_mapping``control_id``control_type` 和选择项 key 必须来自企微后台已经创建的模板。退款可映射业务字段为 `refund_no``order_id``order_no``asset_identifier``asset_type``actual_received_amount``requested_refund_amount``refund_voucher_key``refund_reason``package_usage_id``submitter_id``submitter_name`;线下代充值可映射 `recharge_no``shop_id``shop_name``amount``amount_cent``payment_voucher_key``remark``submitter_id``submitter_name`。企微模板中的必填控件必须全部映射。
完成成员同步后,账号管理页还要调用:
```http
PUT /api/admin/accounts/{account_id}/wecom-binding
```
```json
{
"application_id": 1,
"userid": "zhangsan"
}
```
前端完整配置顺序为:保存应用 → 测试连接 → 同步成员 → 查询成员 → 设置默认发起人 → 给需要本人发起审批的系统账号绑定成员 → 保存两个业务场景 → 查询场景确认均已启用。应用可见范围变化后,应重新同步成员并检查默认发起人和账号绑定。
#### 3.3.2 配置完成后的业务审批流程
1. 前端继续调用原业务接口创建退款或员工线下代充值,不直接调用企微发起审批接口。
2. 后端保存业务单、通用审批实例和提交事件,并异步向企微发起审批;前端根据业务列表/详情的 `approval_provider``approval_status``approval_status_name` 只读展示进度。
3. `approval_status` 可能为:`0` 提交中、`1` 审批中、`2` 已通过、`3` 已拒绝、`4` 已撤销、`5` 通过后撤销、`6` 已删除、`7` 提交失败、`8` 提交结果未知。页面名称优先直接使用 `approval_status_name`
4. 企微回调和 Worker 轮询共同同步最终状态;`GET/POST /api/callback/wecom/approval/{application_id}` 只由企微服务器调用,前端禁止调用。
5. `approval_provider=wecom` 或存在 `approval_instance_id` 时,前端不得显示退款通过/驳回、线下充值确认等旧人工按钮。企微通过后,退款终结或钱包入账由后端自动幂等执行。
### 3.4 通知、批量任务、导出和 Gateway ### 3.4 通知、批量任务、导出和 Gateway
| 需求 | 接口 | 参数或返回变化 / 前端调用说明 | | 需求 | 接口 | 参数或返回变化 / 前端调用说明 |
@@ -127,6 +218,47 @@
| #49 创建设备分配任务 | `POST /api/admin/devices/import/allocations` | 传 `file_key + operation_type + target_id``operation_type=assign_shop|assign_series` | | #49 创建设备分配任务 | `POST /api/admin/devices/import/allocations` | 传 `file_key + operation_type + target_id``operation_type=assign_shop|assign_series` |
| #49 查询任务 | `GET /api/admin/devices/import/tasks``GET /api/admin/devices/import/tasks/:id` | 复用原设备导入任务页面,新增展示 `operation_type``operation_name``target_id``status_name` | | #49 查询任务 | `GET /api/admin/devices/import/tasks``GET /api/admin/devices/import/tasks/:id` | 复用原设备导入任务页面,新增展示 `operation_type``operation_name``target_id``status_name` |
### 3.5 前端静态 CSV 模板
本期需要前端提供两份静态文件模板,**都是 CSV不接受 Excel`.xls`/`.xlsx`**。文件使用 UTF-8 编码,允许 UTF-8 BOM最大 10MB最多 1000 行数据(不含表头)。每个文件只允许一列,不要添加空行、说明行或示例外的其他列。
#### 模板一:批量订购套餐
- 建议文件名:`批量订购套餐模板.csv`
- 上传用途:`purpose=batch_purchase`
- 套餐、支付方式和线下凭证由页面另外选择,不放在 CSV 中。
| 列序号 | 固定表头 | 必填 | 填写内容 |
| --- | --- | --- | --- |
| 1 | `资产标识` | 是 | 每行一个资产标识。卡支持 ICCID、VirtualNo 或 MSISDN设备支持 VirtualNo、IMEI 或 SN |
```csv
资产标识
89860012345678901234
CARD-VIRTUAL-0001
DEVICE-VIRTUAL-0001
860123456789012
```
#### 模板二:设备批量分配
- 建议文件名:`设备批量分配模板.csv`
- 上传用途:`purpose=device_batch_allocation`
- 目标代理或套餐系列由页面另外选择,不放在 CSV 中。“分配代理”和“设置套餐系列”可以共用这一份模板。
| 列序号 | 固定表头 | 必填 | 填写内容 |
| --- | --- | --- | --- |
| 1 | `设备标识` | 是 | 每行一个设备标识,支持 VirtualNo、IMEI 或 SN |
```csv
设备标识
DEVICE-VIRTUAL-0001
860123456789012
SN202607250001
```
> 前端下载的静态模板可以只保留表头,上述数据行仅用于说明格式。资产标识必须按文本原样保存,不得转换为科学计数法、浮点数或截断前导零。
## 四、前端本期最容易漏掉的工作 ## 四、前端本期最容易漏掉的工作
- 换货列表拆成新、旧资产两个搜索参数。 - 换货列表拆成新、旧资产两个搜索参数。

View File

@@ -37,7 +37,7 @@
| 需求切片 | 主通道 | 完整业务边界 | 明确不迁移范围 | | 需求切片 | 主通道 | 完整业务边界 | 明确不迁移范围 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| #189#181#57 | 旧 `Handler → Service → Store → Model` | 对现有换货、退款、订单路径做局部修复和拦截 | 不迁移换货、退款或订单模块 | | #189#181#57 | 旧 `Handler → Service → Store → Model` | 对现有换货、退款、订单路径做局部修复和拦截;新建设备退款固化订单资产标识快照 | 不迁移换货、退款或订单模块,不兼容历史空快照 |
| #182#44#53 | 既有 Query 或旧 Store 查询 | 列表/详情字段、实名筛选、批量账号名称解析 | 不建聚合、历史投影或事件消费者 | | #182#44#53 | 既有 Query 或旧 Store 查询 | 列表/详情字段、实名筛选、批量账号名称解析 | 不建聚合、历史投影或事件消费者 |
| #41#62#48 | 简单写 + 既有读取 | 店铺开关、实名策略、系统配置的更新和查询 | 不建领域模型,不重构认证/支付模块 | | #41#62#48 | 简单写 + 既有读取 | 店铺开关、实名策略、系统配置的更新和查询 | 不建领域模型,不重构认证/支付模块 |
| #188#97#33 | Application/既有通知 Adapter | 产生明确业务事件后向既有站内通知接线 | 不建营销平台或新通知中心 | | #188#97#33 | Application/既有通知 Adapter | 产生明确业务事件后向既有站内通知接线 | 不建营销平台或新通知中心 |
@@ -63,8 +63,9 @@
| 企微场景配置 | 管理员配置 `business_type → template_id` 及业务字段到控件 ID/类型/选项 key 的映射;模板必须先在企微后台创建 | | 企微场景配置 | 管理员配置 `business_type → template_id` 及业务字段到控件 ID/类型/选项 key 的映射;模板必须先在企微后台创建 |
| 实名顺序 | 保持已约定的单资产 PATCH、卡批量 POST、设备批量 POST枚举仅为 `none/before_order/after_order`,批量上限 500、全成全败 | | 实名顺序 | 保持已约定的单资产 PATCH、卡批量 POST、设备批量 POST枚举仅为 `none/before_order/after_order`,批量上限 500、全成全败 |
| 列表人员字段 | 退款、充值、换货返回提交人 ID/名称;审批人仅从已同步企微详情中的 userid 批量映射,映射不到返回空,不实时调用企微 | | 列表人员字段 | 退款、充值、换货返回提交人 ID/名称;审批人仅从已同步企微详情中的 userid 批量映射,映射不到返回空,不实时调用企微 |
| 设备退款资产标识 | 创建退款时从订单固化 `asset_identifier`;列表和详情只返回退款快照,不按 `device_id` 查询当前设备,不兼容历史空快照;单卡继续使用 ICCID 快照 |
| 批量订购 | CSV 只有资产标识列;请求额外选择一个套餐和一个支付方式,不选择代理;整批使用相同参数 | | 批量订购 | CSV 只有资产标识列;请求额外选择一个套餐和一个支付方式,不选择代理;整批使用相同参数 |
| 导出 | 复用现有导出任务入口,通过六个 datasource code 区分;每类只输出本业务已有且已确认的字段 | | 导出 | 复用现有导出任务入口,通过六个 datasource code 区分;每类只输出系统现有且有稳定来源的字段,原始字段清单中当前无法提供的字段不伪造、不新增模型,也不阻断其他字段导出 |
| 支付方式 | `system_config` 分别保存卡和设备允许的支付方式;两类资产默认均启用 `wallet/wechat/alipay`三项可独立取消但至少保留一项C 端返回当前购包场景有效集合,创建订单时后端再次校验 | | 支付方式 | `system_config` 分别保存卡和设备允许的支付方式;两类资产默认均启用 `wallet/wechat/alipay`三项可独立取消但至少保留一项C 端返回当前购包场景有效集合,创建订单时后端再次校验 |
| 设备批量分配 | 复用现有导入任务 API 和状态模型CSV 单列设备标识;业务参数选择“代理”或“套餐系列”及目标 ID | | 设备批量分配 | 复用现有导入任务 API 和状态模型CSV 单列设备标识;业务参数选择“代理”或“套餐系列”及目标 ID |
@@ -76,7 +77,7 @@
### 5. 企微只做 Adapter审批流程仍由企微模板拥有 ### 5. 企微只做 Adapter审批流程仍由企微模板拥有
系统按应用保存加密 Secret、回调 Token、EncodingAESKey、`corp_id/agent_id` 和一个从当前可见成员中选择的默认审批发起人;`access_token` 按应用缓存并预留提前刷新。管理员从应用可见通讯录选择成员,账号绑定键为 `(corp_id, userid)`,姓名和部门仅为展示快照。内部员工已绑定且仍可见时优先以本人发起,代理等非企微账号始终以应用默认成员发起;本地申请仍保留真实业务提交人,不用默认成员冒充业务操作者。 系统按应用明文保存 Secret、回调 Token、EncodingAESKey、`corp_id/agent_id` 和一个从当前可见成员中选择的默认审批发起人;不要求额外启动加密密钥。`access_token` 按应用缓存并预留提前刷新。管理员从应用可见通讯录选择成员,账号绑定键为 `(corp_id, userid)`,姓名和部门仅为展示快照。内部员工已绑定且仍可见时优先以本人发起,代理等非企微账号始终以应用默认成员发起;本地申请仍保留真实业务提交人,不用默认成员冒充业务操作者。
场景配置保存已知 `template_id`。保存或发布时调用 `oa/gettemplatedetail` 校验控件 ID、类型、必填项和选择项 key。系统不创建模板、不保存审批节点、不计算部门领导或财务人员`oa/applyevent` 使用 `use_template_approver=1`,审批人由企微后台模板决定。 场景配置保存已知 `template_id`。保存或发布时调用 `oa/gettemplatedetail` 校验控件 ID、类型、必填项和选择项 key。系统不创建模板、不保存审批节点、不计算部门领导或财务人员`oa/applyevent` 使用 `use_template_approver=1`,审批人由企微后台模板决定。
@@ -104,7 +105,7 @@
批量订购和设备分配只新增业务解析器/执行器继续使用现有对象存储、任务五态、Asynq 重试、失败明细和下载能力。文件级校验失败不写业务数据;涉及扣款/订购时按现有订单幂等键和钱包流水保证不重复扣款。 批量订购和设备分配只新增业务解析器/执行器继续使用现有对象存储、任务五态、Asynq 重试、失败明细和下载能力。文件级校验失败不写业务数据;涉及扣款/订购时按现有订单幂等键和钱包流水保证不重复扣款。
六类导出分别实现 datasource查询直接投影 DTO不串联多个业务迁移。不存在的字段不得临时创造含义;先从既有数据组合,确认确实缺失后再增加最小字段迁移。 六类导出分别实现 datasource查询直接投影 DTO不串联多个业务迁移。不存在或无稳定来源的字段不得临时创造含义,本 Change 不为此新增字段迁移;该字段从导出表头中省略并在对接说明中记录,不阻断其他稳定字段的导出交付
### 8. 数据、事务、常量与缓存 ### 8. 数据、事务、常量与缓存

View File

@@ -6,15 +6,15 @@
- 新 Change 完整替代 `complete-july-iteration-test-release` 的后续规划;旧 Change 在本 Change 校验通过前保留完成证据,之后归档为被替代,不继续执行其未完成任务。 - 新 Change 完整替代 `complete-july-iteration-test-release` 的后续规划;旧 Change 在本 Change 校验通过前保留完成证据,之后归档为被替代,不继续执行其未完成任务。
- 实施遵循“存量能力优先”优先修改或复用现有接口、字段、Service、Query、任务和基础设施只有现有能力确实无法承载已确认需求时才允许做边界最小、可说明必要性的新增。 - 实施遵循“存量能力优先”优先修改或复用现有接口、字段、Service、Query、任务和基础设施只有现有能力确实无法承载已确认需求时才允许做边界最小、可说明必要性的新增。
- 本 Change 当前交付不编写或补齐测试代码,不运行单元、集成、验收或业务流程测试,也不执行 `go test``go build`、LSP 诊断、迁移和 OpenAPI 生成;只完成生产代码、必要迁移文件和契约文档至可联调状态,可使用 `gofmt`、只读检查与 `git diff --check` 做静态收口。 - 本 Change 当前交付不编写或补齐测试代码,不运行单元、集成、验收或业务流程测试,也不执行 `go test`常规 `go build`、LSP 诊断和实际迁移;只完成生产代码、必要迁移文件和契约文档至可联调状态,修改 API 契约后必须重新生成 OpenAPI 核对,可使用 `gofmt`、只读检查与 `git diff --check` 做静态收口。
-#189#181#57 等缺陷和 #53#44#182 等字段/筛选需求收敛为旧 Service、Store 和现有 Query 上的局部修改,不进行 DDD 迁移。 -#189#181#57 等缺陷和 #53#44#182 等字段/筛选需求收敛为旧 Service、Store 和现有 Query 上的局部修改,不进行 DDD 迁移#181 的设备退款在创建时固化资产标识快照,列表和详情直接返回快照,不兼容历史空快照
- 增加店铺级 C 端登录限制开关;仅阻止该店铺资产发起新登录,不建立代理 API 权限体系,也不强制吊销已登录 Token。 - 增加店铺级 C 端登录限制开关;仅阻止该店铺资产发起新登录,不建立代理 API 权限体系,也不强制吊销已登录 Token。
- 补齐三种实名顺序及卡/设备批量配置,保持既有 `realname_policy` 模型和前后端接口约定。 - 补齐三种实名顺序及卡/设备批量配置,保持既有 `realname_policy` 模型和前后端接口约定。
- 复用已有站内通知,完成换货单弹窗、固定 100 元钱包余额提醒、套餐 15/7/3 天临期列表和 C 端提醒,不建设通用营销平台。 - 复用已有站内通知,完成换货单弹窗、固定 100 元钱包余额提醒、套餐 15/7/3 天临期列表和 C 端提醒,不建设通用营销平台。
- 复用已完成的渠道无关审批核心,交付最小企业微信 Adapter管理员从通讯录为系统账号绑定 `(corp_id, userid)`,后台创建模板,本系统配置业务场景/模板/控件映射,完成发起、回调、详情查询和轮询补偿;不做扫码绑定、本地流程设计器或未来渠道抽象扩建。 - 复用已完成的渠道无关审批核心,交付最小企业微信 Adapter管理员从通讯录为系统账号绑定 `(corp_id, userid)`,后台创建模板,本系统配置业务场景/模板/控件映射,完成发起、回调、详情查询和轮询补偿;不做扫码绑定、本地流程设计器或未来渠道抽象扩建。
- **BREAKING**:退款和员工线下代充值的人工审批结果改由企业微信终态驱动;新链路可用后停用原系统内人工通过/驳回入口。代理在线扫码充值后置。 - **BREAKING**:退款和员工线下代充值的人工审批结果改由企业微信终态驱动;新链路可用后停用原系统内人工通过/驳回入口。代理在线扫码充值后置。
- 交付单列 CSV 批量订购、六类业务导出、固定档位限速、按资产类型配置支付方式、CSV 批量分配设备等已确认功能均复用现有导入、导出、Gateway、`system_config` 和任务基础设施。 - 交付单列 CSV 批量订购、六类业务导出、固定档位限速、按资产类型配置支付方式、CSV 批量分配设备等已确认功能均复用现有导入、导出、Gateway、`system_config` 和任务基础设施;批量订购沿用现有后台认证和入口可见性,不新增“内部员工”账号类型限制;导出仅输出系统现有且有稳定来源的字段,不为原始清单中的缺失字段新增模型或迁移
- 冻结已经完成的 #45#46#55#60#86#38#94#96#98#43,仅做接口联调或代码证据核验;冻结行业卡现有复机行为,不按旧提案改写。 - 冻结已经完成的 #45#46#55#60#86#38#94#96#98#43,仅做接口联调或代码证据核验;#43 前端可复用套餐列表的建议售价/公司成本价与授权详情的已授权套餐 ID 完成展示和区分,无需新增后端接口;冻结行业卡现有复机行为,不按旧提案改写。
- 明确排除原路退款、聚水潭、跨品类换货、分销佣金提现、代理在线扫码充值、通用营销/ERP、自动限速、本地审批流引擎、全局 Audit Event 专项,以及已关闭且不处理的需求。 - 明确排除原路退款、聚水潭、跨品类换货、分销佣金提现、代理在线扫码充值、通用营销/ERP、自动限速、本地审批流引擎、全局 Audit Event 专项,以及已关闭且不处理的需求。
## Capabilities ## Capabilities
@@ -33,7 +33,7 @@
- `card-replacement`: 换货前拦截活跃退款,并修复换货套餐在原订单退款后未失效的问题。 - `card-replacement`: 换货前拦截活跃退款,并修复换货套餐在原订单退款后未失效的问题。
- `exchange-client-notification`: 创建物流换货单后复用站内通知在 C 端弹窗。 - `exchange-client-notification`: 创建物流换货单后复用站内通知在 C 端弹窗。
- `order-management`: 修复 C 端订单渠道和订单资产标识返回,并支持从历史订单使用稳定资产/套餐引用发起新的下架套餐续费订单。 - `order-management`: 修复 C 端订单渠道和订单资产标识返回,并支持从历史订单使用稳定资产/套餐引用发起新的下架套餐续费订单。
- `refund-api`: 返回正确设备资产标识、提交人,并将退款审批结果切换为企微驱动。 - `refund-api`: 新建退款固化并返回正确设备资产标识快照和提交人,不兼容历史空快照,并将退款审批结果切换为企微驱动。
- `agent-recharge`: 返回提交人,仅保留员工线下代充值并接入企微审批,代理在线扫码充值后置。 - `agent-recharge`: 返回提交人,仅保留员工线下代充值并接入企微审批,代理在线扫码充值后置。
- `exchange-admin-management`: 换货列表和详情返回提交人。 - `exchange-admin-management`: 换货列表和详情返回提交人。
- `asset-realname-policy`: 支持三种实名顺序、单资产修改、卡/设备批量修改和 C 端生效策略字段。 - `asset-realname-policy`: 支持三种实名顺序、单资产修改、卡/设备批量修改和 C 端生效策略字段。
@@ -50,4 +50,4 @@
- **数据与基础设施**:使用 PostgreSQL、Redis/Asynq、现有 Outbox、Integration Log、对象存储、站内通知和 `system_config`;不新增外键或 GORM 关联标签,不引入新依赖。 - **数据与基础设施**:使用 PostgreSQL、Redis/Asynq、现有 Outbox、Integration Log、对象存储、站内通知和 `system_config`;不新增外键或 GORM 关联标签,不引入新依赖。
- **外部系统**:企业微信自建应用与 Gateway。企微上线需应用 Secret、审批权限、通讯录可见范围、可信 IP、回调 Token/EncodingAESKey 和模板 ID。 - **外部系统**:企业微信自建应用与 Gateway。企微上线需应用 Secret、审批权限、通讯录可见范围、可信 IP、回调 Token/EncodingAESKey 和模板 ID。
- **性能**:列表保持分页并批量解析提交人/审批人,禁止 N+1批量实名上限 500 且事务全成全败CSV/导出沿用异步任务,外部接口设置超时、幂等和补偿。 - **性能**:列表保持分页并批量解析提交人/审批人,禁止 N+1批量实名上限 500 且事务全成全败CSV/导出沿用异步任务,外部接口设置超时、幂等和补偿。
- **交付边界**:本 Change 以生产代码、迁移文件、接口契约、联调配置和实施证据齐备为完成标准自动化测试、构建、LSP、迁移执行、OpenAPI 生成及真实企微/Gateway 环境验收不在本次执行范围,后续联调或发布流程另行承担。 - **交付边界**:本 Change 以生产代码、迁移文件、接口契约、联调配置和实施证据齐备为完成标准;API 契约变更需重新生成 OpenAPI 核对。自动化测试、常规构建、LSP、实际迁移执行及真实企微/Gateway 环境验收不在本次执行范围,后续联调或发布流程另行承担。

View File

@@ -1,10 +1,10 @@
## ADDED Requirements ## ADDED Requirements
### Requirement: 单列 CSV 创建批量订购任务 ### Requirement: 单列 CSV 创建批量订购任务
内部员工 SHALL 上传仅包含资产标识的 CSV并在请求中为整批选择一个套餐和一个支付方式系统不得要求 CSV 包含代理、套餐系列或支付账户,也不得按行选择不同套餐。 通过现有后台认证且当前页面入口可见的用户 SHALL 上传仅包含资产标识的 CSV并在请求中为整批选择一个套餐和一个支付方式系统不新增“内部员工”账号类型限制,不得要求 CSV 包含代理、套餐系列或支付账户,也不得按行选择不同套餐。
#### Scenario: 创建合法批量订购任务 #### Scenario: 创建合法批量订购任务
- **WHEN** 员工上传单列资产 CSV 并选择有效套餐与支付方式 - **WHEN** 已通过现有后台认证的用户上传单列资产 CSV 并选择有效套餐与支付方式
- **THEN** 系统创建异步任务并通过统一响应返回任务 ID 和初始状态 - **THEN** 系统创建异步任务并通过统一响应返回任务 ID 和初始状态
### Requirement: 批量订购复用现有订单和扣款规则 ### Requirement: 批量订购复用现有订单和扣款规则
@@ -17,4 +17,3 @@
#### Scenario: 任务被重复投递 #### Scenario: 任务被重复投递
- **WHEN** Asynq 重复执行同一批量订购任务 - **WHEN** Asynq 重复执行同一批量订购任务
- **THEN** 已成功行不重复下单或扣款 - **THEN** 已成功行不重复下单或扣款

View File

@@ -8,9 +8,8 @@
- **THEN** 系统异步生成仅包含其可见退款数据的文件,并通过任务接口提供进度和下载结果 - **THEN** 系统异步生成仅包含其可见退款数据的文件,并通过任务接口提供进度和下载结果
### Requirement: 导出字段必须有稳定来源 ### Requirement: 导出字段必须有稳定来源
每个 datasource MUST 明确列名、数据来源和格式;现有表或可批量关联数据无法提供的字段不得伪造,必须先补充经确认的最小数据字段后才能导出。 每个 datasource MUST 明确列名、数据来源和格式;只输出现有表或可批量关联数据能稳定提供的字段。原始需求清单中当前无法提供的字段 MUST 省略且不得伪造,本 Change 不为此新增业务字段或迁移,也不阻断其他稳定字段导出。
#### Scenario: 字段没有数据来源 #### Scenario: 字段没有数据来源
- **WHEN** 业务要求字段在现有数据中不存在且无法可靠推导 - **WHEN** 业务要求字段在现有数据中不存在且无法可靠推导
- **THEN** 该 datasource 不得用空含义或错误值冒充字段,任务保持未交付直到字段契约确认 - **THEN** 该 datasource 不得用空含义或错误值冒充字段,应省略该列并继续导出其他有稳定来源的字段

View File

@@ -7,6 +7,10 @@
- **WHEN** 有权限用户查询设备订单产生的退款 - **WHEN** 有权限用户查询设备订单产生的退款
- **THEN** 响应返回设备资产标识、提交人 ID 和提交人名称 - **THEN** 响应返回设备资产标识、提交人 ID 和提交人名称
#### Scenario: 新建设备退款固化资产标识
- **WHEN** 用户为设备订单创建退款申请
- **THEN** 退款记录从订单固化 `asset_identifier`,列表和详情直接返回该快照,不查询设备当前标识;历史空快照保持为空
### Requirement: 退款终态由企微审批驱动 ### Requirement: 退款终态由企微审批驱动
退款申请 SHALL 关联唯一通用审批实例;企微标准决策为 approved 时执行现有退款终结rejected/cancelled/deleted 时按对应终态结束,不得由列表可见权限替代审批权限。 退款申请 SHALL 关联唯一通用审批实例;企微标准决策为 approved 时执行现有退款终结rejected/cancelled/deleted 时按对应终态结束,不得由列表可见权限替代审批权限。
@@ -29,4 +33,3 @@
**Reason**: 审批拒绝改由企业微信回调或轮询同步的标准决策驱动。 **Reason**: 审批拒绝改由企业微信回调或轮询同步的标准决策驱动。
**Migration**: 企微测试闭环可用后停用 `POST /api/admin/refunds/:id/reject`,前端改为只读展示审批状态。 **Migration**: 企微测试闭环可用后停用 `POST /api/admin/refunds/:id/reject`,前端改为只读展示审批状态。

View File

@@ -50,8 +50,12 @@
## 7. 文档与联调交付 ## 7. 文档与联调交付
- [x] 7.1 补齐所有新增/修改 API 的 DTO description、枚举名称字段、中文错误码、路由注释和统一响应示例新增 Handler 同步 `cmd/api/docs.go``cmd/gendocs/main.go`但本次不执行 OpenAPI 生成。【主API 契约】 - [x] 7.1 补齐所有新增/修改 API 的 DTO description、枚举名称字段、中文错误码、路由注释和统一响应示例新增 Handler 同步 `cmd/api/docs.go``cmd/gendocs/main.go`并按后续明确要求生成 OpenAPI 核对契约。【主API 契约】
- [x] 7.2 增量维护 `.scratch/tech-global-audit/审计覆盖基线.md`,逐项登记 Audit Event、Domain Ledger、Integration Log、Outbox 或 N/A 理由。【主:治理门禁】 - [x] 7.2 增量维护 `.scratch/tech-global-audit/审计覆盖基线.md`,逐项登记 Audit Event、Domain Ledger、Integration Log、Outbox 或 N/A 理由。【主:治理门禁】
- [x] 7.3 对全部变更生产代码执行 `gofmt`、只读一致性检查和 `git diff --check`记录未执行测试、构建、LSP、迁移和 OpenAPI 生成的验证缺口。【主:静态收口】 - [x] 7.3 对全部变更生产代码执行 `gofmt`、只读一致性检查和 `git diff --check`,记录未执行测试、常规构建、LSP 和实际迁移的验证缺口OpenAPI 已按后续明确要求生成核对。【主:静态收口】
- [x] 7.4 准备企微、Gateway、Redis/Asynq、对象存储和前端联调所需配置、接口说明、已知限制及回滚步骤本次不执行真实环境闭环。【主联调交付】 - [x] 7.4 准备企微、Gateway、Redis/Asynq、对象存储和前端联调所需配置、接口说明、已知限制及回滚步骤本次不执行真实环境闭环。【主联调交付】
- [x] 7.5 更新实施证据和任务状态,保留 `complete-july-iteration-test-release` 的历史完成证据严格校验、真实联调验收和归档由后续流程处理。【主OpenSpec 收口】 - [x] 7.5 更新实施证据和任务状态,保留 `complete-july-iteration-test-release` 的历史完成证据严格校验、真实联调验收和归档由后续流程处理。【主OpenSpec 收口】
## 8. 补充核对发现的缺口
- [x] 8.1 核对 #181 设备退款资产标识快照链路:新建退款从订单复制按 VirtualNo 优先、IMEI 兜底生成的 `asset_identifier`,列表和详情只返回退款快照,不按 `device_id` 解析当前设备且不兼容历史空快照;单卡 ICCID 口径保持不变。同步更新对接说明并重新生成 OpenAPI 核对 `asset_identifier`。Audit Event、Domain Ledger、Integration Log、Outbox 均 N/A只核对快照写入与读取不修改业务状态。【主旧 Service边界退款资产标识快照不迁移退款、订单或资产模块】