diff --git a/changelogs-v2/2026-09/02_6938_供应商注册提交可选主表字段缺席保留-修改接口-管理后台.md b/changelogs-v2/2026-09/02_6938_供应商注册提交可选主表字段缺席保留-修改接口-管理后台.md new file mode 100644 index 00000000..0eefbd07 --- /dev/null +++ b/changelogs-v2/2026-09/02_6938_供应商注册提交可选主表字段缺席保留-修改接口-管理后台.md @@ -0,0 +1,259 @@ +--- +schema: "hl-changelog/v2" +ticket: "6938" +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: "2026-09-02" +status_note: "PR #6941(含补充 #6945/#6946)已合并 dev-v3,合并链终态提交 697ae6f57 已滚动部署 TEST 双实例。注册提交接口可选主表字段语义由缺席清空改为缺席保留;TEST 真实网关验收 32 项断言通过。" +updated_at: "2026-09-02" +base: "dev-v3" +--- + +# 供应商模块: 注册提交可选主表字段缺席保留 + +> **存放目录**: 二期(v3) → `changelogs-v2/2026-09/` +> +> **服务**: hl-resource-service (端口 8082) +> **PR**: #6941 +> **Issue**: #6938 +> **日期**: 2026-09-02 +> **影响范围**: 管理端供应商注册提交表单 + +--- + +## ⚠️ 关键变化(非必须,本版与上版行为不同 / 纠错 / 撤销时必写) + +- 本次变化:注册提交保存完整表单时,**缺席或空白的可选主表字段保留草稿现值,不再清空**。 +- 前端以前以为的:提交表单未回显的字段(如公司联系电话)提交后仍在。 +- 实际旧行为:提交瞬间被静默置空(本单修复前的缺陷);**新行为**:缺席=保留,与增量更新接口语义对齐。 + +--- + +## 一、背景(选填) + +工单 #6938:供应商提交注册时全量表单静默清空未回传字段(公司联系电话丢失)。根因是提交链路按"完整表单权威覆盖"语义把缺席/空白字段写成 NULL 并留下清空审计。修复后提交与增量更新共用"空白=保留"语义。 + +--- + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 提交供应商注册审批 | POST | `/admin/supplier/items/{supplierId}/submit` | 字段缺席语义变更 | 可选主表字段缺席/空白由"清空"改为"保留现值" | + +--- + +## 三、接口详情 + +### 1. 提交供应商注册审批 `POST /admin/supplier/items/{supplierId}/submit` + +**VO**: `SupplierSubmitReqVO` + +#### 使用场景 + +管理端供应商编辑页点击"提交注册"时调用;提交前应用 `GET /admin/supplier/items/{supplierId}/basic-info/view` 回显完整表单。 + +#### 入参 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|------|------|------|------|------|------| +| fullName | Body | String | ✅ | - | 全称,请求权威提供 | +| taxNo | Body | String | ✅ | GB32100 校验位 | 税号,请求权威提供 | +| mainCooperation | Body | String | ✅ | - | 主要合作内容 | +| balance | Body | BigDecimal | ✅ | ≥0 | 余额 | +| paymentType | Body | String | ✅ | - | 支付类型 | +| licenseImageUrl | Body | String | ✅(提交时) | - | 执照影像,维持请求侧必填门禁,缺席拒绝 | +| expectedUpdateTime | Body | LocalDateTime | ✅ | `yyyy-MM-dd HH:mm:ss` | 乐观锁,取视图 updateTime | +| shortName / contactPhone / address / countyId / establishDate / registeredCapital / businessScope / staffScale / remark | Body | - | ❌ | - | **缺席或空白 = 保留草稿现值(本次变更)** | +| legalRepresentative / legalRepresentativeIdNo / legalRepresentativeIdCardFrontUrl / legalRepresentativeIdCardBackUrl | Body | - | ❌ | 格式校验 | 法人四件套,同上缺席保留 | +| types / contacts / qualifications / initialAccounts | Body | List | ❌ | - | 子项快照;`contacts`/`initialAccounts` 缺席 = 保留历史 | + +#### 出参 `Result` + +| 字段 | 类型 | 说明 | +|------|------|------| +| approvalStatus | String | 受理后 `PENDING` | +| spNo | String | 审批单号(TEST 现为真实企微单号) | + +#### 请求示例 + +```json +{ + "fullName": "HL6938-TEST-20260902", + "taxNo": "91150100HL6938T01W", + "mainCooperation": "车队合作", + "balance": "0.00", + "paymentType": "1", + "licenseImageUrl": "https://example.com/hl6938-license.png", + "expectedUpdateTime": "2026-09-02 11:05:52", + "types": [{"typeCode": "FLEET", "isPrimary": 1}], + "qualifications": [{"qualType": "GZZRX_LICENSE", "certNo": "GZZRX2026HL6938A", "permanentValid": true}] +} +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "成功", + "data": { "approvalStatus": "PENDING", "spNo": "202609020001" }, + "success": true +} +``` + +#### 空数据 / 降级响应 + +写接口无空数据场景;提交受理即返回审批单号,无降级分支。 + +```json +{ "code": 200, "data": { "approvalStatus": "PENDING" }, "success": true } +``` + +#### 错误响应 + +```json +{ + "code": 400, + "message": "expectedUpdateTime不能为空", + "success": false, + "data": null +} +``` + +#### 业务边界 + +- 鉴权:写权限 `FINANCE`/`SUPER_ADMIN`;未登录 → 业务码 `401`。 +- 乐观锁:`expectedUpdateTime` 与现值不符 → 业务码 `395014`,零写入。 +- 非草稿状态重复提交 → 状态机拒绝,零写入。 +- 表单与草稿一致时不产生"提交注册前保存完整表单"变更记录。 + +--- + +## 四、契约约束与正确调用方式(接口类必写) + +> 本节只写**后端接受/拒绝 payload 的规则**,不写 UI 渲染建议。 + +### ✅ 正确 / ❌ 错误 payload 对照 + +| 场景 | payload | +|------|---------| +| ✅ 回显全量已填字段提交 | 视图字段全部带回,行为与旧版一致 | +| ✅ 可选字段缺席 | `contactPhone` 等缺省 → 保留草稿现值,**不再清空** | +| ✅ 显式修改可选字段 | `contactPhone: "04712227654"` → 覆盖并双向审计留痕 | +| ❌ 缺席 `licenseImageUrl` | 提交必填门禁拒绝(业务码 3950xx 资质必填) | +| ❌ 缺席 `expectedUpdateTime` | 400,`expectedUpdateTime不能为空` | + +- 缺席保留意味着可选字段**不再支持以空白清空**;确需清空请联系后端评估独立入口。 +- `expectedUpdateTime` 必须取最近一次 `basic-info/view` 返回的 `updateTime`。 + +--- + +## 五、数据库行为(涉及写操作时必写) + +| 前端提交 | `contact_phone` 等可选列 | +|----------|--------------------------| +| 字段缺席或空白 | **保留数据库现值(不再 SET NULL)** | +| 字段显式提供新值 | 覆盖为新值,`supplier_change_log` 记录旧→新 | + +- 无 migration、DDL 或 DML;历史已被清空的旧数据不回写。 + +--- + +## 六、边界行为 + +- 未登录 → 业务码 `401`(网关包装 HTTP 200)。 +- 乐观锁冲突 → 业务码 `395014`,不阻断页面,重新取视图重试即可。 +- 旧客户端继续全量回显提交 → 行为不变。 +- 历史已清空数据 → 保持 NULL,不异常、不回写。 + +--- + +## 六.6、修改前后对比(修改/删除类接口必写,新增跳过) + +### 字段级对比 + +| 字段 | 改前 | 改后 | +|------|------|------| +| 12 个可选文本字段(`contactPhone` 等)缺席/空白 | 清空为 NULL 并记清空审计 | 保留草稿现值,无审计 | +| `countyId`/`establishDate` 缺席 | 清空为 NULL | 保留草稿现值 | + +### 行为级对比 + +| 行为 | 改前 | 改后 | +|------|------|------| +| 提交表单未回显可选字段 | 字段被静默清空 | 字段保留 | +| 提交审计 delta | 出现非用户主动的清空留痕 | 只记录真实变化;一致时不落审计行 | + +## 六.7、影响评估(修改/删除类必写) + +- **是否破坏向后兼容**: 否。请求/响应结构不变;仅缺席字段行为由清空变保留,无合理调用方依赖清空语义。 +- **前端是否必须同步上线**: 否。建议跟进修复提交表单回显(工单验收②的前端分支),后端缺席保留已兜底。 +- **前端 workaround 清理点**: 无。 + +--- + +## 七、不影响范围(显式声明, 帮前端/QA 缩小排查面) + +- **仅影响**: 管理后台供应商注册提交接口的可选主表字段缺席行为。 +- **零影响**: + - 供应商新增 `/add`、增量更新 `/update`(其 `licenseImageUrl` 既有空白清空分支保持原样,不在本单) + - 必填字段(全称/税号/合作内容/余额/支付类型/执照影像)的请求权威语义 + - 供应商状态机、审批流、企微 Provider 交互、审批候选快照结构 + - C 端接口与历史存量数据 + +--- + +## 八、测试环境已验证 + +真实 Gateway(`api.test.1814.love`)+ TEST 数据库实证,带 ✓ 标记: + +``` +POST /admin/supplier/items/add → 200 草稿含全量可选字段 ✓ +POST /admin/supplier/items/{id}/submit(缺席可选字段) → 200 PENDING + 真实单号 ✓ +GET /admin/supplier/items/{id}/basic-info/view → 九个可选字段全部保留 ✓ + (contactPhone=04711234567 座机形态保留,验收①②) +DB supplier_change_log 提交审计 changedFields → 恰为 [contacts,qualifications], + 九字段均不在列,无 "contactPhone":null 清空形态 ✓(验收③) +POST submit(显式改 contactPhone) → 新值生效,审计 before/after + 双向留痕 13847110001→04712227654 ✓(兼容性) +``` + +验证夹具: `HL6938-TEST-20260902`(supplierId=2094985119537217538) / `HL6938B-TEST-20260902`(supplierId=2094987591035101186);验收产生的真实企微在途单已发起撤销。 +自动化: `SupplierAggregateWriterTest` 定向零失败;hl-resource-service 全量 2293 项零失败。部署: TEST 任务 `dcdfb70a`,部署提交 `697ae6f57` 与预期一致,双实例滚动健康。 + +--- + +## 九、相关历史 PR(纠错 / 功能演进时必写) + +| PR | Issue | 说明 | 是否仍有效 | +|----|-------|------|------------| +| #6930 | #6927 | 注册提交接企微四级串行审批 | ✅ 有效 | +| **本 PR #6941** | **#6938** | 可选主表字段缺席保留(补充 #6945/#6946) | ✅ 最新 | + +--- + +## 十、相关文档 + +- 关联 Issue: [wx/HL#6938](https://git.1814.love:8443/wx/HL/issues/6938) +- 关联 PR: [wx/HL#6941](https://git.1814.love:8443/wx/HL/pulls/6941) + +## 关联 / 联系人 + +### 链接 + +- **Issue**: [#6938](https://git.1814.love:8443/wx/HL/issues/6938) +- **PR**: [#6941](https://git.1814.love:8443/wx/HL/pulls/6941)(补充 [#6945](https://git.1814.love:8443/wx/HL/pulls/6945)、[#6946](https://git.1814.love:8443/wx/HL/pulls/6946)) +- **Merge commit**: [697ae6f57](https://git.1814.love:8443/wx/HL/commit/697ae6f57aeea96b0567cfc8766e6ff1a091c1da) + +### 联系人 + +- **后端负责人**: @lc