diff --git a/changelogs-v2/2026-09/07_7265_供应商账户原地修改与变更明细-新增接口-管理后台.md b/changelogs-v2/2026-09/07_7265_供应商账户原地修改与变更明细-新增接口-管理后台.md new file mode 100644 index 00000000..eb3390cc --- /dev/null +++ b/changelogs-v2/2026-09/07_7265_供应商账户原地修改与变更明细-新增接口-管理后台.md @@ -0,0 +1,260 @@ +--- +schema: "hl-changelog/v2" +ticket: "7265" +title: "供应商账户原地修改与变更明细" +consumer: "admin" +author: "lc(GIT)" +change_type: "新增接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "后端已部署并通过 TEST Gateway 验证;前端待改为按原 accountId 刷新账户,并接入账户变更明细分页接口。" +updated_at: "2026-09-07" +base: "dev-v3" +--- + +# 供应商账户:原地修改与变更明细 + +## 一、关键变化 + +- `PUT /admin/supplier/bank-accounts/{accountId}/update` 现在返回原 `accountId`,账户列表不再新增待审替换行。审批期间正式账户保持原值和 `ACTIVE`,通过后在同一行应用新值,驳回或撤销则保持不变。 +- 新增账户变更明细分页接口,展示该账户的创建、修改、启用、停用和删除历史。 +- 本文覆盖 #7182 中“修改会新建账户、返回新 accountId”的旧说明。前端不得把修改响应追加为第二条账户数据。 + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|---|---|---|---|---| +| 1 | 提交账户修改审批 | PUT | `/admin/supplier/bank-accounts/{accountId}/update` | 行为修改 | 改为原 accountId 原地审批 | +| 2 | 查询账户变更明细 | GET | `/admin/supplier/bank-accounts/{accountId}/change-records/page` | 新增接口 | 按单个账户分页查询变更事实 | + +## 三、接口详情 + +### 1. 提交账户修改审批 `PUT /admin/supplier/bank-accounts/{accountId}/update` + +**VO**: `SupplierAccountUpdateReqVO / BankAccountSubmitResultRespVO` + +#### 使用场景 + +对 `ACTIVE` 账户提交完整新资料并发起企微审批。提交成功后继续使用原账户行和原 `accountId`。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| `accountId` | Path | String | 是 | 正整数 | 当前账户 ID | +| `accountType` | Body | String | 是 | `CORPORATE` / `PERSONAL` | 对公 / 对私 | +| `bankName` | Body | String | 是 | 非空,最长 500 字符 | 开户银行 | +| `bankBranch` | Body | String/null | 否 | 最长 500 字符 | 开户支行 | +| `accountNo` | Body | String | 是 | 8~128 位,仅数字、空格和 `-` | 除当前账户外须全局唯一 | +| `proofFileUrls` | Body | Array/null | 否 | 最多 20 项 | 完整快照;`[]` 表示清空 | +| `settleMode` | Body | String/null | 否 | `PREPAY` / `MONTHLY` / `SINGLE` | 结算方式 | +| `accountPeriod` | Body | String/null | 条件必填 | `MONTHLY` 时必填,其他方式须为空 | 月结账期 | +| `invoiceType` | Body | String/null | 否 | `SPECIAL` / `NORMAL` / `NONE` | 发票类型 | +| `taxRate` | Body | String/null | 条件必填 | 可开票时必填;`NONE` 时须为空 | 税率 | +| `expectedUpdateTime` | Body | String | 是 | `yyyy-MM-dd HH:mm:ss` | 账户详情或列表的最新 `updateTime` | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| `accountId` / `approvalLogId` | String | 原账户 ID / 本次审批记录 ID | +| `requestNo` / `provider` / `spNo` | String | 幂等号 / 审批提供方 / 企微单号 | +| `approvalStatus` / `approvalStatusName` | String | 审批状态 / 中文名 | +| `syncStatus` | String | 审批结果同步状态 | +| `accountStatus` / `isDefault` | String | 正式账户当前状态 / 默认标记 | +| `submittedAt` / `finishedAt` | String/null | 提交时间 / 终态时间 | + +#### 请求示例 + +```http +PUT /admin/supplier/bank-accounts/726500000000000001/update +Authorization: Bearer <当前有效凭证> +Content-Type: application/json + +{"accountType":"CORPORATE","bankName":"示例银行","bankBranch":"示例支行","accountNo":"6222000012345678","proofFileUrls":[],"settleMode":"PREPAY","accountPeriod":null,"invoiceType":"NONE","taxRate":null,"expectedUpdateTime":"2026-09-07 15:00:00"} +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "accountId": "726500000000000001", + "approvalLogId": "726500000000000002", + "requestNo": "SUP-ACC-UPDATE-example", + "provider": "WECOM", + "approvalStatus": "PENDING", + "approvalStatusName": "审核中", + "spNo": "202609070001", + "spStatus": null, + "syncStatus": "REQUESTING", + "accountStatus": "ACTIVE", + "isDefault": "NO", + "submittedAt": "2026-09-07 15:00:01", + "finishedAt": null + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无空成功数据。企微异常时可能保留原审批事实并返回 `APPLY_FAILED` 或 `RESULT_UNCERTAIN`;正式账户不会提前改变,前端不得自动创建新申请。 + +#### 错误响应 + +```json +{"code":395028,"message":"该账户正在变更审批中,请勿重复提交","data":null,"success":false} +``` + +#### 业务边界 + +- 仅 `ACTIVE` 供应商的 `ACTIVE` 账户可修改;需要账户管理与审批提交权限。 +- `code=200` 仅表示审批已提交,不表示新值已生效;响应 `accountId` 与 Path 中原值相同。 +- 同一账户已有在途审批、版本过期或新账号被其他账户占用时失败且不产生第二条账户。 + +### 2. 查询账户变更明细 `GET /admin/supplier/bank-accounts/{accountId}/change-records/page` + +**VO**: `SupplierAccountChangeRecordPageReqVO / PageResult` + +#### 使用场景 + +在账户管理页查看指定账户的完整变更时间线,并按操作、状态、字段或时间范围筛选。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| `accountId` | Path | String | 是 | 正整数 | 账户 ID | +| `page` | Query | Integer | 否 | 默认 1,最小 1 | 页码;兼容 `pageNo` | +| `pageSize` | Query | Integer | 否 | 默认 20,范围 1~100 | 每页数量 | +| `operationType` | Query | String | 否 | `CREATE` / `UPDATE` / `ENABLE` / `DISABLE` / `DELETE` | 操作类型 | +| `fieldName` | Query | String | 否 | 最长 64,不能全空白 | 精确筛选变更字段 | +| `status` | Query | String | 否 | `DRAFT` / `PENDING` / `REJECTED` / `ACTIVE` / `DISABLED` | 事实中的账户状态 | +| `from` / `to` | Query | String | 否 | `yyyy-MM-dd HH:mm:ss` | 必须成对传入,且 `from <= to` | +| `sortBy` | Query | String | 否 | `occurredAt` / `changeLogId`,默认前者 | 排序字段 | +| `sortDirection` | Query | String | 否 | `ASC` / `DESC`,默认 `DESC` | 排序方向 | + +#### 出参 + +| 字段 | 类型 | 说明 | +|---|---|---| +| `records[].operationType` | String | 操作类型 | +| `records[].oldValue` / `newValue` | String | 变更前后中文业务摘要 | +| `records[].valueAvailability` | String | `FULL` 或 `LEGACY_MASKED_UNRECOVERABLE` | +| `records[].changeReason` | String | 变更原因 | +| `records[].status` | String | 账户状态中文名 | +| `records[].operatorName` / `operatorRole` | String | 操作人展示名 / 操作时角色中文名 | +| `records[].occurredAt` | String | 发生时间,格式 `yyyy-MM-dd HH:mm:ss` | +| `total` / `page` / `pageSize` | Integer | 总数 / 当前页 / 每页数量 | + +#### 请求示例 + +```http +GET /admin/supplier/bank-accounts/726500000000000001/change-records/page?page=1&pageSize=20&operationType=UPDATE&sortBy=occurredAt&sortDirection=DESC +Authorization: Bearer <当前有效凭证> +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { + "records": [{ + "operationType": "UPDATE", + "oldValue": "开户支行:旧示例支行", + "newValue": "开户支行:新示例支行", + "valueAvailability": "FULL", + "changeReason": "提交收款账户修改审批,终审前保留原账户原值生效", + "status": "已生效", + "operatorName": "示例管理员", + "operatorRole": "超级管理员", + "occurredAt": "2026-09-07 15:00:01" + }], + "total": 1, + "page": 1, + "pageSize": 20 + }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +无记录时返回 `records: []`、`total: 0`。操作人服务降级时返回不含内部 ID 的稳定展示名;历史完整值不可恢复时返回 `valueAvailability=LEGACY_MASKED_UNRECOVERABLE`。 + +#### 错误响应 + +```json +{"code":395045,"message":"历史查询起始与结束时间必须同时传入","data":null,"success":false} +``` + +#### 业务边界 + +- 需要 `supplier:approval:read`;账户证明附件继续受 `supplier:account:proof:read` 独立控制,无权限时摘要显示“无权查看”。 +- 查询只返回 Path 指定账户的事实,不混入同供应商其他账户或主体变更。 +- `oldValue`、`newValue` 可能含完整业务值,前端须按敏感信息展示规范处理。 + +## 四、契约约束与正确调用方式 + +1. 编辑前读取账户详情,完整回填当前资料和 `updateTime`。 +2. 修改成功后保留原列表行,以响应中的同一 `accountId` 刷新列表;不得追加第二条待审账户。 +3. 在账户操作区新增“变更明细”,调用新增 GET 接口并支持分页,默认按 `occurredAt DESC` 展示。 +4. `approvalStatus=PENDING` 时展示“审核中”,正式账户仍使用列表返回的 `ACTIVE` 原值;终态后重新拉取列表和明细。 +5. 移除 #7182 的“新 accountId / 新待审行替换原行”处理。 + +## 五、数据库行为 + +账户修改提交、审批通过、驳回或撤销均只保留原账户列表行和原 `accountId`;提交审批只追加可查询的审批与变更事实,不新增替换账户。校验失败不改变账户或新增事实。 + +## 六、边界行为 + +- `401`:未登录或凭证失效。 +- `400`:分页、账户字段或结算组合不合法。 +- `395001`:账户或所属供应商不存在;`395002`:无读取或写入权限。 +- `395005` / `395010`:状态不允许或供应商未生效。 +- `395011` / `395028`:账户已有在途审批或变更;`395014`:版本过期;`395027`:新账号被其他账户占用。 +- `395045` / `395046`:时间范围缺一端或起止倒置。 +- `395019`~`395022`:企微配置、绑定、提交或对账异常,不自动新建申请。 +- 业务错误可能仍使用 HTTP 200,必须同时判断响应体 `code` 和 `success`。 + +## 七、不影响范围 + +- 不修改账户新增、启用、停用、删除和默认账户切换接口。 +- 不改变现有请求字段、枚举或审批状态字段;不影响小程序接口。 +- 旧替换式账户历史继续可读,不合并或删除历史记录。 + +## 八、测试环境已验证 + +- 修改请求返回原 `accountId`;提交前后账户列表与有效账户数量均为 1,正式账户内容未提前变化。 +- 新接口返回新增的 `UPDATE` 明细,分页和 `operationType` 筛选有效。 +- 未登录返回 `401`;非法账号返回 `400`;时间范围只传一端返回 `395045`,失败路径未产生写入。 + +**当前状态:后端已部署并通过 TEST Gateway 验证;待前端接入。** + +## 十、相关文档 + +- [Issue #7265](https://git.1814.love:8443/wx/HL/issues/7265) +- [PR #7271](https://git.1814.love:8443/wx/HL/pulls/7271) +- [被本文纠正的 #7182 说明](https://git.1814.love:8443/wx/HL/issues/7182) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#7265](https://git.1814.love:8443/wx/HL/issues/7265) +- **PR**: [#7271](https://git.1814.love:8443/wx/HL/pulls/7271) +- **Merge commit**: [859a62ddb512074b33103be9bb9e4e579bdbb3ad](https://git.1814.love:8443/wx/HL/commit/859a62ddb512074b33103be9bb9e4e579bdbb3ad) + +### 联系人 + +- **后端负责人**: @lc