docs: record batch return use contract and verification #349
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Architecture-and-Code-Map
|
||||
wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Architecture-and-Code-Map.-
|
||||
wiki_revision: 0e0ad0b3312c524d90e063167dd2e945fb22b0e9
|
||||
synchronized_at: 2026-09-29T01:36:01Z
|
||||
wiki_revision: 9b4a1a06b8e2f6a8dfdbaef87817d840dfa45389
|
||||
synchronized_at: 2026-09-29T02:23:54Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
@@ -561,3 +561,12 @@ Web 唯一展示位置为“采集采购 → SYB 同步记录”:列表状态
|
||||
- Web `syb-products/return-cancel.js` 与列表组件复用单条取消接口;冻结当前页勾选的 SYB 商品 ID 与原匹配 ID,一次确认后串行请求,独立汇总成功、跳过及失败。取消结果不会驱动已有采购或采集任务。
|
||||
- `returnmatch.Service.Cancel` 在锁定原匹配记录的事务中校验可选状态前提,再释放有效占用指针并写取消审计;事务内审计失败则整体回滚。无额外数据库迁移、权限、批量后台任务或外部写入。
|
||||
- 元数据加载失败时禁止批量取消;执行时互斥匹配、确认、取消。网络不确定时只读回原匹配,不自动重复写入;登录失效停止后续请求。列表刷新与失败项勾选恢复受查询 generation 约束,不跨页、不覆盖较新的筛选结果。
|
||||
|
||||
## SYB 当前页批量使用退货(#349)
|
||||
|
||||
实现绑定 4280115(2026-09-29),feat/349-batch-return-use;以 #347 a4c7b5e 为基线,未合并 main、未发布或真实业务验收。
|
||||
|
||||
- Web syb-products/index.vue 新增“使用退货 N”,紧跟“取消匹配”;return-confirm.js 冻结当前页原 SYB / match 身份,去重后一次确认、串行复用既有 confirm API,结果独立汇总。return-cancel.js 和单条操作接入使用期间互斥,不重构取消逻辑。
|
||||
- return-matches.js 的 confirmReturnMatch 增加可选客户端请求选项,仅用于批量汇总时抑制逐项错误弹窗;无新增 HTTP 字段。Server 生产代码、确认锁内 matched 检查、ConfirmedBy/ConfirmedAt、审计和占用指针不变,无迁移或权限变化。
|
||||
- 未知写结果只读回原 match,回读确认不宣称为本次成功;登录失效停止余项。刷新保持筛选与页码,失败选择恢复受 generation、当前页及原 matched 身份约束。未调用 Yeeke 发货或修改采购任务。
|
||||
- 回归入口:Web tests/unit/syb-return-confirm.test.cjs、tests/e2e/syb-return-confirm.spec.ts;Server returnmatch/confirm_batch_test.go。测试使用合成数据和隔离 SQLite,不代表生产 MySQL 并发或真实退货验证。
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Business-Rules-and-Glossary
|
||||
wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Business-Rules-and-Glossary.-
|
||||
wiki_revision: e95c53cec27080e073e6f7a4aaed46d5421dddf5
|
||||
synchronized_at: 2026-09-29T01:36:04Z
|
||||
wiki_revision: 9a7317728132c450c7abf244c3e5eaac7bfb71bc
|
||||
synchronized_at: 2026-09-29T02:23:57Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
@@ -722,3 +722,13 @@ SYB 回填与资料完整性独立:正式SYB任务已有单号且仍关联有
|
||||
- 一次确认后按原匹配编号逐条取消。并发确认、已经取消等状态冲突跳过;其他错误保留失败。网络异常先回读原记录,不盲目重试,不追随后来重新匹配的新记录;登录失效停止剩余写入。
|
||||
- 成功后重新计算采购准备状态,并按当前退货状态与同步可用性判断退货池资格,不保证所有商品立即可采购,不改变既有采购或采集任务。保持查询条件刷新;仅保留仍在当前页、仍为原匹配且可取消的失败项勾选,其余失败项保留在结果表。
|
||||
- 原有单条确认及取消兼容:未携带状态前提的单条取消仍允许取消已确认匹配;本次不新增权限或迁移,不自动创建采购或执行付款。
|
||||
|
||||
## SYB 当前页批量使用退货(#349)
|
||||
|
||||
实现绑定 4280115(2026-09-29),尚未合并/发布,待验收。
|
||||
|
||||
- 管理员、采购员及售后沿用既有权限,工具栏为“匹配退货 → 取消匹配 → 使用退货”。仅当前页勾选且处理阶段 return_pending、原有效匹配 matched 的明细计入使用数量;已用退货与未匹配行不参与。
|
||||
- 一次确认后逐条标记 confirmed / 已用退货,保留有效占用;不是 Yeeke 发货或重出,不修改已有采购/采集任务,不自动创建采购或支付,不扩大原候选资格。
|
||||
- 只操作冻结的原 match ID。并发确认或取消冲突跳过,不追随后来的替代匹配。其他错误失败,各项不互相回滚;登录失效停止后续写入并明确未执行。
|
||||
- 网络结果未知先回读原记录:已确认/已取消显示回读状态而不是本次成功;仍为原 matched 可人工重试;回读失败保留不确定结果,不自动重复提交。
|
||||
- 完成保持筛选、页码和结果明细。成功项在退货待确认筛选下移出;仅当前页仍为原 matched 的可重试失败项恢复勾选,离页结果不丢失、不跨页操作。操作中互斥匹配、使用、取消及单条操作,无新增审批或权限。
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Android-Agent-API-Contract
|
||||
wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Android-Agent-API-Contract.-
|
||||
wiki_revision: fff074b921368be646cda1bf0a434608fc5082c8
|
||||
synchronized_at: 2026-09-29T01:36:20Z
|
||||
wiki_revision: 102d40fb2d960b05684e2a82e85729362070fdb5
|
||||
synchronized_at: 2026-09-29T02:24:16Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
@@ -1408,3 +1408,12 @@ GET /api/admin/v1/purchase-tasks 的既有 status 参数新增查询专用值 sy
|
||||
携带前提时,服务端在锁定 `:id` 原记录的事务中检查状态仍为 `matched` 且有效占用指针存在,否则 HTTP 409 / `STATE_CONFLICT`,不取消已确认或已取消的匹配。不存在返回 HTTP 404 / `NOT_FOUND`。成功仍为 `{code:200,data:{item:ReturnMatch}}`,释放占用并记录 CancelledBy / CancelledAt 和审计日志。权限沿用 admin / purchaser / after_sales,没有新增批量接口或权限点。
|
||||
|
||||
Web 批量入口冻结原匹配 ID 并顺序调用;HTTP 409 状态冲突跳过,权限/网络错误失败,HTTP 401 或登录失效停止后续操作。写入结果未知时只允许只读回读原记录,不自动重发取消;不以 SYB ID 重新查询替代匹配并取消。
|
||||
|
||||
## Admin 批量使用退货复用确认接口(#349)
|
||||
|
||||
实现绑定 4280115(2026-09-29),未合并/发布;仅补充管理端调用规则,Android Agent 契约不变。
|
||||
|
||||
- Web 当前页批量使用复用 POST /api/admin/v1/return-matches/:id/confirm,无新增请求体、批量接口、状态或权限。Server 沿用锁定原记录后仅接受 matched;成功为 {code:200,data:{item:ReturnMatch}},写 confirmed、确认人/时间及审计,保留 active 占用。
|
||||
- HTTP 409 / STATE_CONFLICT 跳过,HTTP 404 / NOT_FOUND 或其他处理错误明确失败。沿用 admin / purchaser / after_sales 权限;HTTP 401、业务认证错误及旧拦截器 false 结果均停止余项,不能误计为成功。
|
||||
- 写结果不明确时仅 GET /api/admin/v1/return-matches/:id 回读冻结原记录,验证 match 身份;已 confirmed/cancelled 显示回读已处理,仍 matched 才允许手动重试。不得自动重发 POST 或改查新匹配后使用。
|
||||
- 无数据库、Server 生产行为、Agent 协议或外部 Yeeke 写入变化。真实业务确认及部署另需授权。
|
||||
|
||||
@@ -64,6 +64,7 @@ test('v2 button order, one confirmation, no write on return, progress and mutual
|
||||
await expect(page.getByText('成功 2 条', { exact: true })).toBeVisible()
|
||||
await expect(page.getByText('跳过 1 条', { exact: true })).toBeVisible()
|
||||
await page.getByRole('button', { name: '返回列表', exact: true }).click()
|
||||
await expect(page.getByRole('dialog', { name: '批量使用退货结果', exact: true })).toBeHidden()
|
||||
await expect(page.getByText('已选择 0 条', { exact: true })).toBeVisible()
|
||||
})
|
||||
|
||||
@@ -78,6 +79,7 @@ for (const mode of ['partial', 'conflict', 'auth', 'readback-confirmed']) {
|
||||
const summary = mode === 'auth' ? '失败 2 条' : mode === 'partial' ? '失败 1 条' : mode === 'conflict' ? '跳过 2 条' : '跳过 3 条'
|
||||
await expect(page.getByText(summary, { exact: true })).toBeVisible()
|
||||
await page.getByRole('button', { name: '返回列表', exact: true }).click()
|
||||
await expect(page.getByRole('dialog', { name: '批量使用退货结果', exact: true })).toBeHidden()
|
||||
if (mode === 'partial') {
|
||||
await expect(page.getByText('已选择 1 条', { exact: true })).toBeVisible()
|
||||
await expect(page.getByRole('button', { name: /使用退货\s*1/ })).toBeEnabled()
|
||||
@@ -110,5 +112,6 @@ test('pending filter and page size retained; used rows disappear', async ({ page
|
||||
expect(lists.at(-1)?.searchParams.get('processStage')).toBe('return_pending')
|
||||
expect(lists.at(-1)?.searchParams.get('pageSize')).toBe('200')
|
||||
await page.getByRole('button', { name: '返回列表', exact: true }).click()
|
||||
await expect(page.getByRole('dialog', { name: '批量使用退货结果', exact: true })).toBeHidden()
|
||||
await expect(page.getByText('暂无 SYB 商品明细', { exact: true })).toBeVisible()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user