diff --git a/changelogs-v2/2026-07/10_4884_线下收款代收人-修改接口-管理后台.md b/changelogs-v2/2026-07/10_4884_线下收款代收人-修改接口-管理后台.md index 8fd6f5d..63cde89 100644 --- a/changelogs-v2/2026-07/10_4884_线下收款代收人-修改接口-管理后台.md +++ b/changelogs-v2/2026-07/10_4884_线下收款代收人-修改接口-管理后台.md @@ -197,16 +197,7 @@ GET /v3/admin/order/2075415307597357058/payment/manual-receipt/options "channel": "BANK_TRANSFER", "channelText": "银行转账", "allowedPayTypes": ["DEPOSIT", "FULL"], - "collectors": [ - { - "collectorType": "COMPANY_ACCOUNT", - "collectorId": null, - "collectorName": "公司账户", - "collectorRole": "COMPANY_ACCOUNT", - "collectorRoleText": "公司账户", - "defaultSelected": true - } - ] + "collectors": [] }, { "channel": "DRIVER_CASH", diff --git a/changelogs-v2/2026-07/21_5120_对公转账代收人规则纠正-修改接口-管理后台.md b/changelogs-v2/2026-07/21_5120_对公转账代收人规则纠正-修改接口-管理后台.md new file mode 100644 index 0000000..1402ab9 --- /dev/null +++ b/changelogs-v2/2026-07/21_5120_对公转账代收人规则纠正-修改接口-管理后台.md @@ -0,0 +1,411 @@ +# 📝【契约纠正·管理后台】对公转账不需要代收人 (#5120) + +> **变更性质**:现有接口契约澄清 + 历史文档示例纠错|**端类型**:管理后台|**更新日期**:2026-07-21 +> +> 本次没有发布新的后端字段、枚举或行为变更;下文说明接口已有的稳定契约。 + +## 1. 接口背景 + +管理后台在“登记线下收款”中选择“对公转账”后仍显示“代收人”,与当前接口契约不一致。对公转账不由某位员工代收,只需填写转账流水号;代收人仅在“报账人收款”渠道下需要选择。 + +2026-07-10 的历史通知曾在示例中给 `BANK_TRANSFER.collectors` 放入“公司账户”对象,该示例与实际响应不符,本次一并纠正为空数组。 + +## 2. 变更清单 + +| # | 方法 | 路径 | 通知类型 | 说明 | +|---|---|---|---|---| +| 1 | GET | `/v3/admin/order/{orderId}/payment/manual-receipt/options` | 契约澄清 | `BANK_TRANSFER.collectors` 始终为 `[]`;各渠道使用各自的候选项 | +| 2 | POST | `/v3/admin/order/{orderId}/payment/manual-receipt` | 契约澄清 | `collectorStaffId` 仅对 `DRIVER_CASH` 条件必填;`BANK_TRANSFER` 条件必填 `transferRef` | +| 3 | 文档 | `2026-07/10_4884_线下收款代收人-修改接口-管理后台.md` | 示例纠错 | 将对公转账的错误 `collectors` 对象改为 `[]` | + +## 3. 接口详情 + +### 3.1 查询线下收款选项 + +- **方法与路径**:`GET /v3/admin/order/{orderId}/payment/manual-receipt/options` +- **使用场景**:打开登记线下收款表单时,查询当前订单可用的渠道、款项类型、代收人和收款方式。 +- **认证**:需要管理后台 JWT。 +- **幂等性**:幂等,只读查询。 +- **限流**:无接口专属限流规则。 + +### 3.2 登记线下收款 + +- **方法与路径**:`POST /v3/admin/order/{orderId}/payment/manual-receipt` +- **使用场景**:按 options 当前返回的可用渠道和款项类型登记一笔线下收款。 +- **认证**:需要管理后台 JWT。 +- **幂等性**:非幂等,每次成功请求会新增一条收款记录。 +- **限流**:无接口专属限流规则。 + +## 4. 接口入参 + +### 4.1 路径参数(两个接口通用) + +| 字段 | 位置 | 类型 | 必填 | 说明 | +|---|---|---|---|---| +| `orderId` | Path | String(Long) | 是 | 订单 ID,按字符串处理 | + +GET 接口无 Query 参数、无请求体。 + +### 4.2 POST 请求体 + +| 字段 | 类型 | 必填 | 说明 | 校验规则 | +|---|---|---|---|---| +| `channel` | String | 是 | 收款渠道 | `DRIVER_CASH` / `BANK_TRANSFER` / `CONSULTANT_COLLECTION` | +| `payType` | String | 是 | 款项类型 | 必须取 options 中当前渠道的 `allowedPayTypes` | +| `amount` | Decimal | 是 | 收款金额 | 最小 `0.01`,不能超过当前可收余额 | +| `receivedAt` | String(LocalDateTime) | 否 | 收款时间 | `yyyy-MM-dd'T'HH:mm:ss`;不传默认当前时间 | +| `transferRef` | String | 条件必填 | 对公转账流水号 | `BANK_TRANSFER` 必填,其他渠道不使用 | +| `receiptMethod` | String | 否 | 收款方式 | 取当前渠道 `receiptMethods[].value`;`BANK_TRANSFER` 为空 | +| `collectorStaffId` | String(Long) | 条件必填 | 代收人 assignmentId | **仅 `DRIVER_CASH` 必填**,且必须取当前渠道 `collectors[].collectorId` | +| `collectorType` | String | 否 | 实际代收人类型 | 不传时按 `channel` 推导;如传入,必须与渠道匹配 | +| `voucherUrls` | Array | 否 | 凭证图片 URL 列表 | 可为空数组或不传 | +| `remark` | String | 否 | 备注 | 最长 500 字 | + +### 4.3 渠道联动必填矩阵 + +| `channel` | `collectorStaffId` | `collectorType` | `transferRef` | 代收人规则 | +|---|---|---|---|---| +| `BANK_TRANSFER` | 不需要;误传也不作为员工代收人处理 | 可不传;如传只能为 `COMPANY_ACCOUNT` | **必填** | 不选择任何员工,公司账户是收款归属而非代收人候选项 | +| `CONSULTANT_COLLECTION` | 不需要 | 可不传;如传只能为 `CONSULTANT` | 不需要 | 使用订单定制师,不使用员工选择器 | +| `DRIVER_CASH` | **必填** | 可不传;如传只能为 `ORDER_STAFF` | 不需要 | 仅能选当前订单 options 返回的有效报账人 | + +## 5. 出参(响应) + +### 5.1 通用响应包装 + +| 字段 | 类型 | 说明 | +|---|---|---| +| `code` | Integer | `200` 表示成功,其他值为业务错误码 | +| `message` | String | 结果或错误说明 | +| `data` | Object/null | 业务数据;失败时通常为 `null` | +| `success` | Boolean | 是否成功 | + +### 5.2 GET options 的 `data` + +| 字段 | 类型 | 说明 | +|---|---|---| +| `channels` | Array | 当前订单的线下收款渠道列表 | +| `channels[].channel` | String | 渠道枚举值 | +| `channels[].channelText` | String | 渠道展示文案 | +| `channels[].allowedPayTypes` | Array | 当前订单状态下该渠道允许的款项类型;以本次响应为准 | +| `channels[].disabled` | Boolean | `true` 表示当前不可提交该渠道 | +| `channels[].disabledReason` | String/null | 禁用原因;可用时为 `null` | +| `channels[].collectors` | Array | **该渠道自己的代收人候选列表**;`BANK_TRANSFER` 为 `[]` | +| `channels[].receiptMethods` | Array | 该渠道可选收款方式;`BANK_TRANSFER` 为 `[]` | +| `collectors[].collectorType` | String | 代收人类型 | +| `collectors[].collectorId` | String(Long) | `ORDER_STAFF` 为 assignmentId,`CONSULTANT` 为管理员 ID | +| `collectors[].collectorName` | String | 代收人姓名 | +| `collectors[].collectorRole` | String | 代收人角色值 | +| `collectors[].collectorRoleText` | String | 代收人角色文案 | +| `collectors[].defaultSelected` | Boolean | 是否默认选中 | +| `receiptMethods[].value` | String | 收款方式值 | +| `receiptMethods[].label` | String | 收款方式文案 | +| `receiptMethods[].defaultSelected` | Boolean | 是否默认选中 | + +### 5.3 POST 的 `data` + +| 字段 | 类型 | 说明 | +|---|---|---| +| `id` | String(Long) | 收款凭据 ID | +| `orderId` | String(Long) | 订单 ID | +| `channel` / `channelLabel` | String | 收款渠道值 / 文案 | +| `payType` / `payTypeLabel` | String | 款项类型值 / 文案 | +| `amount` | Decimal | 本次收款金额 | +| `receivedAt` | String(LocalDateTime) | 收款时间 | +| `collectorStaffId` / `collectorStaffName` | String(Long)/String/null | 仅 `DRIVER_CASH` 有值 | +| `collectorType` | String | 实际代收人类型 | +| `collectorAdminId` | String(Long)/null | `CONSULTANT_COLLECTION` 为定制师管理员 ID | +| `collectorName` / `collectorRole` | String | 代收归属快照名称 / 角色 | +| `transferRef` | String/null | 对公转账流水号,仅 `BANK_TRANSFER` 有值 | +| `receiptMethod` / `receiptMethodLabel` | String/null | 收款方式值 / 文案;`BANK_TRANSFER` 为空 | +| `voucherUrls` | Array | 凭证图片 URL 列表 | +| `remark` | String/null | 备注 | +| `operatorName` | String | 登记人姓名 | +| `createTime` | String(LocalDateTime) | 登记时间 | +| `voided` | Boolean | 是否已撤销;新登记为 `false` | +| `voidedByName` / `voidedAt` / `voidReason` | String/null | 撤销信息;新登记时为 `null` | +| `paidAmountAfter` | Decimal | 登记后订单累计已付金额 | +| `payStatusAfter` | String | 登记后订单支付状态 | + +## 6. 枚举 / 数据字典 + +### 6.1 `channel` + +**所属字段**:`channel` / `channels[].channel`|**类型**:String + +| 值 | 中文 | 说明 | +|---|---|---| +| `BANK_TRANSFER` | 对公转账 | 无员工代收人,必须填 `transferRef` | +| `CONSULTANT_COLLECTION` | 定制师代收 | 使用订单定制师,不传 `collectorStaffId` | +| `DRIVER_CASH` | 报账人收款 | 仅允许尾款,必须从本渠道 `collectors` 选择代收人 | + +### 6.2 `payType` + +**所属字段**:`payType` / `channels[].allowedPayTypes[]`|**类型**:String + +| 值 | 中文 | 说明 | +|---|---|---| +| `DEPOSIT` | 订金 | 是否可登记以 options 当前返回为准 | +| `FULL` | 全款 | 是否可登记以 options 当前返回为准 | +| `BALANCE` | 尾款 | 是否可登记以 options 当前返回为准;`DRIVER_CASH` 只允许此值 | + +> `BANK_TRANSFER` 的通用契约可支持 `DEPOSIT` / `FULL` / `BALANCE`,但具体订单当次能提交哪些值,必须以 options 的 `allowedPayTypes` 为准,不要将某个实例的 `BALANCE` 硬编码为全局规则。 + +### 6.3 `collectorType` + +**所属字段**:`collectorType` / `collectors[].collectorType`|**类型**:String + +| 值 | 中文 | 匹配渠道 | +|---|---|---| +| `COMPANY_ACCOUNT` | 公司账户 | `BANK_TRANSFER` | +| `CONSULTANT` | 定制师 | `CONSULTANT_COLLECTION` | +| `ORDER_STAFF` | 订单工作人员 | `DRIVER_CASH` | + +### 6.4 `receiptMethod` + +**所属字段**:`receiptMethod` / `receiptMethods[].value`|**类型**:String + +| 值 | 中文 | 说明 | +|---|---|---| +| `WECHAT_TRANSFER` | 微信转账 | 人员代收渠道的当前默认字典值 | +| `CASH` | 现金收款 | 人员代收渠道的当前默认字典值 | + +`BANK_TRANSFER.receiptMethods=[]`;该字典可扩展,实际可选值以 options 当次返回为准。 + +### 6.5 `payStatusAfter` + +**所属字段**:POST 响应 `payStatusAfter`|**类型**:String + +| 值 | 中文 | 说明 | +|---|---|---| +| `UNPAID` | 未付款 | 尚未完成有效收款 | +| `DEPOSIT_PAID` | 已付订金 | 订金已收 | +| `FULLY_PAID` | 已付全款 | 应收金额已收齐 | + +## 7. 错误码 + +| code | message / 含义 | 触发场景 | +|---|---|---| +| `520011` | 支付类型无效或与订单状态不匹配 | `payType` 不在当前 options 允许范围内 | +| `520401` | 收款渠道非法 | `channel` 不在三个渠道枚举中 | +| `520402` | 对公转账渠道必须填写转账流水号 | `BANK_TRANSFER` 未传 `transferRef` | +| `520403` | 报账人收款渠道必须指定代收人 | `DRIVER_CASH` 未传 `collectorStaffId` | +| `520404` | 代收人不属于本订单人员 | `collectorStaffId` 不是本订单有效人员 | +| `520407` | 订单已取消,不允许登记线下收款 | 已取消订单提交 POST | +| `520408` | 收款金额必须大于 0 | `amount < 0.01` | +| `520409` | 线下收款代收人类型非法 | `collectorType` 与 `channel` 不匹配 | +| `520410` | 报账人收款只能登记尾款 | `DRIVER_CASH` 提交 `DEPOSIT` 或 `FULL` | +| `520411` | 报账人收款必须选择本订单报账人 | 选中的订单人员不是报账人 | +| `520412` | 订单没有可用定制师,不能登记定制师代收 | `CONSULTANT_COLLECTION` 无可用定制师 | +| `520413` | 本次收款金额超过当前可收余额 | `amount` 大于当前可收金额 | + +## 8. 示例(典型 + 边界 + 异常) + +### 8.1 典型:查询选项,对公转账无代收人 + +**请求**: + +```http +GET /v3/admin/order/2079454953641836546/payment/manual-receipt/options +Authorization: Bearer + +无请求体 +``` + +**响应**: + +```json +{ + "code": 200, + "message": "操作成功", + "data": { + "channels": [ + { + "channel": "CONSULTANT_COLLECTION", + "channelText": "定制师代收", + "allowedPayTypes": ["BALANCE"], + "disabled": false, + "disabledReason": null, + "collectors": [ + { + "collectorType": "CONSULTANT", + "collectorId": "2037350531801993218", + "collectorName": "张三", + "collectorRole": "CONSULTANT", + "collectorRoleText": "定制师", + "defaultSelected": true + } + ], + "receiptMethods": [ + {"value": "WECHAT_TRANSFER", "label": "微信转账", "defaultSelected": true}, + {"value": "CASH", "label": "现金收款", "defaultSelected": false} + ] + }, + { + "channel": "BANK_TRANSFER", + "channelText": "对公转账", + "allowedPayTypes": ["BALANCE"], + "disabled": false, + "disabledReason": null, + "collectors": [], + "receiptMethods": [] + }, + { + "channel": "DRIVER_CASH", + "channelText": "报账人收款", + "allowedPayTypes": [], + "disabled": true, + "disabledReason": "本订单暂无可代收报账人", + "collectors": [], + "receiptMethods": [ + {"value": "WECHAT_TRANSFER", "label": "微信转账", "defaultSelected": true}, + {"value": "CASH", "label": "现金收款", "defaultSelected": false} + ] + } + ] + }, + "success": true +} +``` + +### 8.2 边界:对公转账不传代收人 + +**场景说明**:`collectorStaffId` 和 `collectorType` 都不传;仅提交 options 当前允许的款项类型与对公转账流水号。 + +**请求**: + +```http +POST /v3/admin/order/2079454953641836546/payment/manual-receipt +Authorization: Bearer +Content-Type: application/json + +{ + "channel": "BANK_TRANSFER", + "payType": "BALANCE", + "amount": 100.00, + "transferRef": "BANK202607210001", + "voucherUrls": [], + "remark": "客户对公转账" +} +``` + +**响应**: + +```json +{ + "code": 200, + "message": "操作成功", + "data": { + "id": "2079600000000000001", + "orderId": "2079454953641836546", + "channel": "BANK_TRANSFER", + "channelLabel": "对公转账", + "payType": "BALANCE", + "payTypeLabel": "尾款", + "amount": 100.00, + "receivedAt": "2026-07-21T15:30:00", + "collectorStaffId": null, + "collectorStaffName": null, + "collectorType": "COMPANY_ACCOUNT", + "collectorAdminId": null, + "collectorName": "公司账户", + "collectorRole": "COMPANY_ACCOUNT", + "transferRef": "BANK202607210001", + "receiptMethod": null, + "receiptMethodLabel": null, + "voucherUrls": [], + "remark": "客户对公转账", + "operatorName": "管理员", + "createTime": "2026-07-21T15:30:00", + "voided": false, + "voidedByName": null, + "voidedAt": null, + "voidReason": null, + "paidAmountAfter": 1600.00, + "payStatusAfter": "DEPOSIT_PAID" + }, + "success": true +} +``` + +### 8.3 异常:报账人收款未选择代收人 + +**请求**: + +```http +POST /v3/admin/order/2079454953641836546/payment/manual-receipt +Authorization: Bearer +Content-Type: application/json + +{ + "channel": "DRIVER_CASH", + "payType": "BALANCE", + "amount": 100.00, + "receiptMethod": "CASH" +} +``` + +**响应**: + +```json +{ + "code": 520403, + "message": "报账人收款渠道必须指定代收人", + "data": null, + "success": false +} +``` + +## 9. 业务边界 + +- `collectors` 是每个 channel 自己的候选列表,不是所有渠道共用的必选列表。 +- `BANK_TRANSFER`:`collectors=[]`,不传 `collectorStaffId`,必须传 `transferRef`;即使误传 `collectorStaffId`,响应中员工代收人 ID 仍为空。 +- `CONSULTANT_COLLECTION`:不要提交 `collectorStaffId`;当订单没有可用定制师时,渠道禁用。 +- `DRIVER_CASH`:仅允许 `BALANCE`,必须传当前订单有效报账人的 assignmentId。 +- options 的 `allowedPayTypes` 随订单状态和可收余额变化。待支付订单中,对公转账/定制师代收可返回 `DEPOSIT`、`FULL`;非待支付且仍有可收余额时可返回 `BALANCE`。 +- 渠道 `disabled=true` 或 `allowedPayTypes=[]` 时,当前不可提交该渠道。 +- 已取消订单、无可收余额的订单不能登记线下收款。 + +## 10. 修改前后对比 + +> 本节对比的是“错误理解 / 错误文档示例”与“正确的现有契约”,不表示后端今日发布了新的接口变更。 + +| 项目 | 错误理解 / 历史错误示例 | 正确契约 | +|---|---|---| +| 对公转账的代收人候选 | `BANK_TRANSFER.collectors` 含“公司账户”对象 | `BANK_TRANSFER.collectors=[]` | +| `collectorStaffId` 字段 | 所有渠道都要选代收人,或该字段已从后端删除 | 字段仍保留,**仅 `DRIVER_CASH` 条件必填** | +| 对公转账必填项 | 代收人 | `transferRef` 转账流水号 | +| 定制师代收 | 复用员工代收人选择器并传 `collectorStaffId` | 不要传 `collectorStaffId`,使用订单定制师 | +| 对公转账款项类型 | 固定只能是某一种款项 | 以 options 当前返回的 `allowedPayTypes` 为准 | + +## 11. 影响评估 / 回滚 + +### 11.1 影响评估 + +- **是否破坏向后兼容**:否。后端字段、枚举和行为没有变更。 +- **前端是否必须同步上线**:是。已有页面在 `BANK_TRANSFER` 下显示代收人,需要按正确契约纠正。 + +### 11.2 回滚说明 + +- 本次仅修正通知文档,不涉及后端接口回滚。 +- 若前端回滚渠道联动修正,对公转账将再次错误显示代收人。 + +## 12. 注意事项 + +- 选中 `BANK_TRANSFER` 时,隐藏代收人选择器,并清空从其他渠道切换前残留的 `collectorStaffId`。 +- 选中 `BANK_TRANSFER` 时,显示并校验 `transferRef`,不要根据统一响应结构中“存在 `collectors` 字段”就认定代收人必选。 +- 仅 `DRIVER_CASH` 把 `collectorStaffId` 设为必填,候选项取当前 channel 的 `collectors`。 +- `CONSULTANT_COLLECTION` 不要复用 `DRIVER_CASH` 的员工代收人校验。 +- 不要把测试订单中 `BANK_TRANSFER.allowedPayTypes=["BALANCE"]` 固化为全局规则;每次均以 options 返回为准。 + +## 13. 关联 / 联系人 + +### 13.1 关联 + +- **Issue**:[#5120](https://git.1814.love:8443/wx/HL/issues/5120) +- **后端 PR**:无(本次无后端代码变更) +- **后端 commit**:无(本次无后端代码变更) + +### 13.2 联系人 + +- **后端负责人**:腰苏图