--- schema: "hl-changelog/v2" ticket: "7087" title: "供应商账户修改入口与删除限制" consumer: "admin" author: "lc(GIT)" change_type: "修改接口" backend_status: "deployed" gateway_status: "verified" frontend_status: "not_required" frontend_owner: "" frontend_ref: "" target_release: "" verified_at: "" status_note: "现有接口说明与历史口径纠正;前端按草稿账户修改入口接入,取消空数组删除账户。既有 TEST 业务实测及本次只读复核范围见正文。" updated_at: "2026-09-06" base: "dev-v3" --- # 供应商账户:修改入口与删除限制 > **影响范围**:管理后台供应商账户编辑、删除操作。当前状态:后端已部署;前端待核对接入。 ## ⚠️ 关键变化 草稿初始账户通过供应商更新接口修改,必须保留一项账户。**旧 #6669 文档的 `initialAccounts: []` 删除方式已被 #7087 收紧,当前返回 `400 / 账户不能为空`。** 草稿的 `changeReason` 现可省略。 | 操作 | 当前支持情况 | |---|---| | 修改草稿初始账户 | 支持,使用下文接口,供应商及其已有账户必须均为 `DRAFT` | | 修改已提交或已生效账户资料 | 未提供独立接口;不能通过供应商更新绕过状态限制 | | 单独删除账户 | 未提供接口;不能提交空数组清空最后一项账户 | | 设置默认账户 | 已有 `PUT /admin/supplier/bank-accounts/{accountId}/default/update`,仅改变默认标记 | ## 二、变更接口清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|---|---|---|---|---| | 1 | 修改草稿初始账户 | PUT | `/admin/supplier/items/{supplierId}/update` | 现有契约说明 | 通过 `initialAccounts` 完整替换唯一草稿账户;禁止空数组删除 | ## 三、接口详情 ### 1. 修改草稿初始账户 `PUT /admin/supplier/items/{supplierId}/update` **VO**: `SupplierUpdateReqVO / SupplierBankAccountReqVO / SupplierWriteRespVO` #### 使用场景 在资料完整的草稿供应商下修改初始账户。本节列出账户编辑所需载荷;其余主体资料省略时保留现值。保存后主体必填资料、供应商类型、联系人、账户仍须完整。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |---|---|---|---|---|---| | `supplierId` | Path | String | 是 | 正整数 ID | 供应商 ID | | `expectedUpdateTime` | Body | String | 是 | `yyyy-MM-dd HH:mm:ss` | 供应商主体版本,不能使用账户版本 | | `initialAccounts` | Body | Array | 本场景是 | 恰好 1 项 | 省略或 `null` 保留现值;`[]` 拒绝 | | `initialAccounts[].accountType` | Body | String | 是 | `CORPORATE` / `PERSONAL` | 对公 / 对私 | | `initialAccounts[].bankName` | Body | String | 是 | 非空,最长 500 字符 | 开户银行 | | `initialAccounts[].accountNo` | Body | String | 是 | 去空白和连字符后 8~32 位数字 | 收款账号 | | `initialAccounts[].bankBranch` | Body | String/null | 否 | 最长 500 字符 | 开户支行,可清空 | | `initialAccounts[].proofFileUrls` | Body | Array/null | 否 | 最多 20 个不重复的公网 HTTPS 地址,每项最长 1000 字符;不带查询参数或片段 | 证明附件,省略或 `[]` 清空 | | `initialAccounts[].settleMode` | Body | String/null | 否 | `PREPAY` / `MONTHLY` / `SINGLE` | 结算方式 | | `initialAccounts[].accountPeriod` | Body | String/null | 条件必填 | 最长 50 字符;仅 `MONTHLY` 必填,其他方式须为空 | 月结账期 | | `initialAccounts[].invoiceType` | Body | String/null | 否 | `SPECIAL` / `NORMAL` / `NONE` | 发票类型 | | `initialAccounts[].taxRate` | Body | String/null | 条件必填 | 0%~100%,最多两位小数 | 可开票时必填;`NONE` 或未选发票类型时须为空 | | `changeReason` | Body | String | 否 | 最长 500 字符 | 此处为 `DRAFT`,允许省略 | 不提交 `accountId`、`accountName` 或账户状态;户名由供应商全称确定。 #### 出参 | 字段 | 类型 | 说明 | |---|---|---| | `code` / `message` / `success` | Integer / String / Boolean | 业务结果;成功为 `200`、`成功`、`true` | | `data.supplierId` / `data.supplierNo` | String | 供应商 ID / 编号 | | `data.status` / `data.statusName` | String | 本场景为 `DRAFT` / `草稿` | | `data.onboardingStage` | String | 本场景为 `PROFILE_DRAFT` | | `data.initialAccounts` | Array | 保存后的初始账户摘要 | | `data.initialAccounts[].accountId` | String | 当前账户 ID,替换账号后应重新读取 | | `data.initialAccounts[].accountNo` | String | 完整账号 | | `data.initialAccounts[].accountNoMask` | String | 废弃兼容字段,实际同样为完整账号;使用 `accountNo` | | `data.initialAccounts[].status` | String | 本场景为 `DRAFT` | | `data.approval` | null | 草稿直接保存,不发起审批 | | `data.updateTime` | String | 保存后的供应商版本,供下次编辑使用 | #### 请求示例 以下 ID、账号和时间均为示例值。 ```http PUT /admin/supplier/items/2095000000000000001/update Authorization: Bearer <当前有效凭证> Content-Type: application/json { "expectedUpdateTime": "2026-09-06 10:00:00", "initialAccounts": [{ "accountType": "CORPORATE", "bankName": "示例银行", "accountNo": "6222000012345678", "bankBranch": "示例支行", "proofFileUrls": [], "settleMode": "MONTHLY", "accountPeriod": "月结30天", "invoiceType": "SPECIAL", "taxRate": "6%" }] } ``` #### 响应示例 ```json { "code": 200, "message": "成功", "success": true, "data": { "supplierId": "2095000000000000001", "supplierNo": "SUP2095000000000000001", "status": "DRAFT", "statusName": "草稿", "onboardingStage": "PROFILE_DRAFT", "initialAccounts": [{ "accountId": "2095000000000000002", "accountNo": "6222000012345678", "accountNoMask": "6222000012345678", "status": "DRAFT" }], "approval": null, "updateTime": "2026-09-06 10:00:01" } } ``` #### 空数据 / 降级响应 成功响应包含账户摘要。编辑表单完整回显使用 `GET /admin/supplier/items/{supplierId}/account-info/list` 的 `data.bankAccounts`,主体版本取该响应的 `data.updateTime`。摘要不包含银行、附件和结算字段,不能直接作为下次完整账户载荷。 #### 错误响应 提交 `initialAccounts: []`: ```json {"code":400,"message":"账户不能为空","success":false,"data":null} ``` 其他常见业务码:`395002` 无写权限;`395005` 非草稿或主体企微审批未结束;`395009` 已有账户不是草稿;`395014` 主体版本过期;`395027` 账号已占用;`400` 缺版本、字段或结算组合不合法。完全未改变数据也返回 `400 / 未检测到实际变化`。 #### 业务边界 - 要求 `FINANCE` 或 `SUPER_ADMIN` 且具有 `supplier:update`;`ADMIN` 被拒绝。 - 仅可维护草稿初始账户;已提交、已生效、已驳回账户没有资料修改或删除入口。 - 一项账户是完整快照:未提交的可选字段会被清空,需保留的字段必须一并带回。 - 相同账号保留账户 ID;换成新账号会替换旧草稿账户,成功后刷新列表和版本。 ## 四、契约约束与正确调用方式 1. 按供应商读取账户列表和主体版本,草稿页面提交一项完整账户。 2. 从月结切换为其他结算方式时同步清空 `accountPeriod`;选不开票时同步清空 `taxRate`。 3. 保存成功刷新账户;版本冲突先重新读取。前端移除空数组删除逻辑,不生成不存在的账户删除路径。 ## 五、数据库行为 修改成功保留一项草稿账户并刷新供应商版本;更换账号时旧草稿账户不再出现在有效列表。校验失败不改变账户;空数组请求不会删除数据。 ## 六、边界行为 未登录或登录失效按认证失败处理;必须检查响应体 `code`、`success`,不能仅凭 HTTP 200 判断保存成功。既有主体资料不完整时,账户编辑同样会被必填校验拒绝。 ## 六.5、枚举 / 数据字典 ### `accountType` | 值 | 中文 | 说明 | |---|---|---| | `CORPORATE` | 对公 | 必填账户类型之一 | | `PERSONAL` | 对私 | 必填账户类型之一 | ### `settleMode` | 值 | 中文 | 说明 | |---|---|---| | `PREPAY` | 预付 | 账期须为空 | | `MONTHLY` | 月结 | 必填账期 | | `SINGLE` | 单次结算 | 账期须为空 | | `null` | 未登记 | 账期须为空 | ### `invoiceType` | 值 | 中文 | 说明 | |---|---|---| | `SPECIAL` | 专票 | 必填税率 | | `NORMAL` | 普票 | 必填税率 | | `NONE` | 不开票 | 税率须为空 | | `null` | 未登记 | 税率须为空 | ## 六.6、修改前后对比 本次补充文档,后端无新增变更。 | 字段 / 行为 | 旧 #6669 说明 | 当前契约 | |---|---|---| | `initialAccounts: []` | 可清空账户 | #7087 起拒绝,必须保留账户 | | 草稿 `changeReason` | 必填 | #6684 起可省略 | | `expectedUpdateTime` | 必填 | 仍必填,使用供应商主体版本 | | 独立账户修改 / 删除 | 无独立接口 | 仍无独立接口;草稿修改走主体更新 | ## 六.7、影响评估 - 本次没有新增兼容性变化;前端须遵守已部署的账户非空约束。 - 无需与后端同步上线;清理旧的 `[]` 删除调用,按上述状态控制编辑入口。 ## 七、不影响范围 本次说明覆盖草稿初始账户维护;新增账户审批、默认账户切换和合同契约保持现状。 ## 八、测试环境已验证 - 既有业务实测:#6654 最终证据记录草稿账户修改、可选字段清空与版本失败零写入;#7087 记录显式空账户被拒绝、至少一项账户保存成功。旧证据中的整项清空已被 #7087 覆盖。 - 本次于 2026-09-06 通过 TEST Gateway 只读核对 Resource Swagger:主体更新路径及账户请求/摘要字段存在,未发布独立账户修改、删除路径;同时核对最新 `dev-v3` 源码。此次未重复执行共享环境业务写操作。 ## 十、相关文档 - [账户修改既有实测 #6654](https://git.1814.love:8443/wx/HL/issues/6654#issuecomment-43820) - [账户非空约束与实测 #7087](https://git.1814.love:8443/wx/HL/issues/7087#issuecomment-46744) - [草稿免填变更原因 #6684](https://git.1814.love:8443/wx/HL/issues/6684) ## 关联 / 联系人 - **Issue**: [#7087](https://git.1814.love:8443/wx/HL/issues/7087) - **PR**: [#7093](https://git.1814.love:8443/wx/HL/pulls/7093) - **后端负责人**: @lc