docs(changelog): #6397 全面对齐模板——逐接口自包含详情 + 五、数据库行为 + 九、相关历史PR
changelog-filename-gate / validate (push) Successful in 2s
changelog-filename-gate / validate (push) Successful in 2s
这个提交包含在:
@@ -25,11 +25,11 @@ base: "dev-v3"
|
||||
|
||||
## 二、变更接口清单
|
||||
|
||||
| # | 接口 | 方法 | 路径 | 变化 |
|
||||
|---:|---|---|---|---|
|
||||
| 1 | 创建供应商注册草稿 | POST | `/admin/supplier/items/add` | 请求可选增加 `contracts` 完整集合 |
|
||||
| 2 | 提交供应商注册 | POST | `/admin/supplier/items/{supplierId}/submit` | 请求可选增加 `contracts` 完整快照 |
|
||||
| 3 | 查询供应商基本信息 | GET | `/admin/supplier/items/{supplierId}/basic-info/view` | 响应增加 `contracts` 列表 |
|
||||
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||
|---:|---|---|---|---|---|
|
||||
| 1 | 创建供应商注册草稿 | POST | `/admin/supplier/items/add` | 请求体新增可选字段 | 可选增加 `contracts` 完整集合 |
|
||||
| 2 | 提交供应商注册 | POST | `/admin/supplier/items/{supplierId}/submit` | 请求体新增可选字段 | 可选增加 `contracts` 完整快照 |
|
||||
| 3 | 查询供应商基本信息 | GET | `/admin/supplier/items/{supplierId}/basic-info/view` | 响应新增字段 | 响应增加 `contracts` 列表 |
|
||||
|
||||
统一响应均为 `Result<T>`。业务失败可能仍为 HTTP 200,调用方必须同时判断 `code`、`success`、`message` 和 `data`。
|
||||
|
||||
@@ -41,11 +41,11 @@ base: "dev-v3"
|
||||
|
||||
## 三、接口详情
|
||||
|
||||
三个接口的合同字段完全一致,统一在「公共合同字段」约定;各接口的使用场景、请求/响应示例与错误码分节详述。
|
||||
三个接口的合同字段完全一致,先在「公共合同字段」统一约定;各接口再分节给出自包含的使用场景、入参、出参、示例与错误。
|
||||
|
||||
### 公共合同字段
|
||||
|
||||
### 请求字段 `contracts[]`
|
||||
#### 请求字段 `contracts[]`
|
||||
|
||||
| 字段 | 类型 | 创建必填 | 提交既有项必填 | 约束与说明 |
|
||||
|---|---|---:|---:|---|
|
||||
@@ -63,7 +63,7 @@ base: "dev-v3"
|
||||
| `scanFileUrl` | String | 否 | 否 | 合同扫描件永久地址,最长 1000 字符 |
|
||||
| `remark` | String | 否 | 否 | 最长 500 字符 |
|
||||
|
||||
### 响应字段 `contracts[]`
|
||||
#### 响应字段 `contracts[]`
|
||||
|
||||
详情返回上述全部业务字段,并额外返回:
|
||||
|
||||
@@ -78,16 +78,34 @@ base: "dev-v3"
|
||||
|
||||
### 1. 创建供应商注册草稿 `POST /admin/supplier/items/add`
|
||||
|
||||
`POST /admin/supplier/items/add`
|
||||
**VO**: `SupplierDraftSaveReqVO`(请求;响应 data 字段见下表)
|
||||
|
||||
### 使用场景与边界
|
||||
#### 使用场景
|
||||
|
||||
- `contracts` 可省略、为 `null` 或空数组,旧客户端行为不变。
|
||||
- 非空时最多 100 项,合同与供应商主体、资质和 `initialAccounts` 一起成功或一起失败。
|
||||
- 创建请求中的每个合同都是新合同,禁止携带 `contractId`。
|
||||
- 写入仍要求现有供应商创建权限;仅可信 `FINANCE`、`SUPER_ADMIN` 且拥有对应平台权限的身份可执行。
|
||||
供应商注册第一步:创建草稿。`contracts` 为本次新增的可选完整集合,随草稿与供应商主体、资质、`initialAccounts` 一起成功或一起失败;旧客户端省略该字段时行为完全不变。
|
||||
|
||||
### 典型请求
|
||||
#### 入参
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|---|---|---|---|---|---|
|
||||
| `fullName` | Body | String | 是 | 非空白 | 供应商全称(本次未变更,列此定位) |
|
||||
| `taxNo` | Body | String | 是 | 统一社会信用代码 | 本次未变更,列此定位 |
|
||||
| `qualifications` | Body | Array | 否 | - | 资质证照集合(本次未变更) |
|
||||
| `contracts` | Body | Array | 否 | 非空时最多 100 项 | 本次新增:合同完整集合,单项字段见「公共合同字段」;创建时每项禁止携带 `contractId` |
|
||||
| `initialAccounts` | Body | Array | 否 | - | 结算账户集合,字段名不得改(本次未变更) |
|
||||
|
||||
#### 出参
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `supplierId` | String | 供应商 ID,字符串 |
|
||||
| `supplierNo` | String/null | 供应商编号,草稿期可为 null |
|
||||
| `status` | String | 固定 `DRAFT` |
|
||||
| `onboardingStage` | String | 入驻阶段,草稿为 `PROFILE_DRAFT` |
|
||||
| `initialAccounts` | Array | 结算账户回显 |
|
||||
| `updateTime` | String | 聚合版本时间,`yyyy-MM-dd HH:mm:ss` |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
POST /admin/supplier/items/add
|
||||
@@ -135,7 +153,7 @@ Content-Type: application/json
|
||||
}
|
||||
```
|
||||
|
||||
### 成功响应
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -153,7 +171,13 @@ Content-Type: application/json
|
||||
}
|
||||
```
|
||||
|
||||
### 失败响应:创建携带合同 ID
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
`contracts` 省略、为 `null` 或空数组均可正常创建,旧客户端行为不变;创建响应不返回合同明细(合同通过详情接口回显)。草稿无结算账户时 `initialAccounts` 返回空数组 `[]`,不返回 `null`。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
创建请求携带合同 ID(创建时每个合同都是新项,禁止 `contractId`):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -166,20 +190,44 @@ Content-Type: application/json
|
||||
|
||||
失败时不会留下供应商主体或部分合同。
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 非空时最多 100 项,合同与供应商主体、资质和 `initialAccounts` 一起成功或一起失败。
|
||||
- 创建请求中的每个合同都是新合同,禁止携带 `contractId`。
|
||||
- 写入仍要求现有供应商创建权限;仅可信 `FINANCE`、`SUPER_ADMIN` 且拥有对应平台权限的身份可执行。
|
||||
- `endDate` 早于 `startDate` 直接校验失败,零写入。
|
||||
|
||||
### 2. 提交供应商注册 `POST /admin/supplier/items/{supplierId}/submit`
|
||||
|
||||
`POST /admin/supplier/items/{supplierId}/submit`
|
||||
**VO**: `SupplierDraftSaveReqVO`(请求,含 `expectedUpdateTime` 版本;响应 data 字段见下表)
|
||||
|
||||
### 使用场景与快照语义
|
||||
#### 使用场景
|
||||
|
||||
- `contracts` 省略或为 `null`:本次不处理合同,保留草稿当前合同。
|
||||
- `contracts: []`:明确清空当前全部合同。
|
||||
- 非空数组:作为完整快照;带 `contractId` 的项覆盖当前合同,不带 ID 的项新增,当前已有但数组中遗漏的合同删除。
|
||||
- 带 ID 的合同必须属于路径中的供应商;不属于当前供应商、重复 ID、非法枚举、负金额或日期逆序均失败。
|
||||
- `expectedUpdateTime` 仍是供应商聚合并发版本;发生并发修改时调用方应刷新详情后重新组装完整表单。
|
||||
- 合同快照会进入本次审批资料,但提交注册不会自动改写合同自身的 `status`。
|
||||
注册第二步:把草稿完整表单(含合同快照)提交审批。`contracts` 按完整快照语义处理:省略/`null` = 本次不处理合同;`[]` = 明确清空;非空数组 = 全量覆盖(带 ID 覆盖、无 ID 新增、遗漏删除)。
|
||||
|
||||
### 典型请求
|
||||
#### 入参
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|---|---|---|---|---|---|
|
||||
| `supplierId` | Path | String | 是 | 必须存在且未删除 | 目标供应商 |
|
||||
| `fullName` | Body | String | 是 | 非空白 | 完整表单字段(本次未变更,列此定位) |
|
||||
| `contracts` | Body | Array | 否 | 非空时最多 100 项 | 本次新增:合同完整快照,单项字段见「公共合同字段」;既有项必须带回字符串 `contractId` |
|
||||
| `initialAccounts` | Body | Array | 否 | - | 结算账户集合(本次未变更) |
|
||||
| `expectedUpdateTime` | Body | String | 是 | `yyyy-MM-dd HH:mm:ss` | 聚合并发版本,须取详情最新值 |
|
||||
|
||||
#### 出参
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `approvalLogId` | String | 审批日志 ID,字符串 |
|
||||
| `requestNo` | String | 审批请求号 |
|
||||
| `provider` | String | 审批通道,如 `LOCAL_AUTO` |
|
||||
| `approvalStatus` | String | 审批结果,如 `APPROVED` |
|
||||
| `spNo` / `spStatus` | String/null | 外部审批单号/状态,本地通道为 null |
|
||||
| `syncStatus` | String | 结果应用状态,如 `APPLIED` |
|
||||
| `submittedAt` / `finishedAt` | String | 提交/完成时间 |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
POST /admin/supplier/items/2090300000000063970/submit
|
||||
@@ -229,7 +277,7 @@ Content-Type: application/json
|
||||
}
|
||||
```
|
||||
|
||||
### 成功响应
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -250,7 +298,13 @@ Content-Type: application/json
|
||||
}
|
||||
```
|
||||
|
||||
### 失败响应:合同不属于当前供应商
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
`contracts` 省略或为 `null` 时保留草稿当前合同,走既有审批流程,无降级差异;`contracts: []` 为明确清空(不是省略),会删除当前全部合同。草稿本身无合同时按无合同提交,不报错。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
合同不属于当前供应商(或重复 ID、非法枚举、负金额、日期逆序等同族校验失败):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -263,20 +317,50 @@ Content-Type: application/json
|
||||
|
||||
该失败会回滚本次提交表单中的主体、资质、合同和审计变化,供应商仍保持原状态和原版本。
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 带 ID 的合同必须属于路径中的供应商;不属于当前供应商、重复 ID、非法枚举、负金额或日期逆序均失败。
|
||||
- `expectedUpdateTime` 仍是供应商聚合并发版本;发生并发修改时调用方应刷新详情后重新组装完整表单。
|
||||
- 合同快照会进入本次审批资料,但提交注册不会自动改写合同自身的 `status`。
|
||||
- 快照语义易错点:用户明确删除全部合同时发送 `contracts: []`;未加载合同或不处理合同时省略字段,不要误发空数组。
|
||||
|
||||
### 3. 查询供应商基本信息 `GET /admin/supplier/items/{supplierId}/basic-info/view`
|
||||
|
||||
`GET /admin/supplier/items/{supplierId}/basic-info/view`
|
||||
**VO**: `SupplierBasicInfoRespVO`
|
||||
|
||||
### 请求
|
||||
#### 使用场景
|
||||
|
||||
供应商详情首屏:返回主体信息、资质、合同列表(本次新增 `contracts`)与聚合版本。管理端据此渲染「资质证照 → 合同信息 → 结算信息」区块。
|
||||
|
||||
#### 入参
|
||||
|
||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||
|---|---|---|---|---|---|
|
||||
| `supplierId` | Path | String | 是 | 必须存在且未删除 | 目标供应商 |
|
||||
|
||||
无请求体、无查询参数。读取继续要求可信读角色和 `supplier:view` 平台权限。
|
||||
|
||||
#### 出参
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `supplierId` | String | 供应商 ID,字符串 |
|
||||
| `fullName` / `shortName` | String | 供应商名称 |
|
||||
| `tax_no` | String | 脱敏税号 |
|
||||
| `types` | Array | 供应商类型,`typeCode`/`typeName` |
|
||||
| `qualifications` | Array | 资质证照列表(本次未变更) |
|
||||
| `contracts` | Array | 本次新增:合同列表,字段见「公共合同字段」;`amount` 为 String |
|
||||
| `status` | String | 供应商状态 |
|
||||
| `updateTime` | String | 聚合版本时间,提交表单时回传 `expectedUpdateTime` |
|
||||
|
||||
#### 请求示例
|
||||
|
||||
```http
|
||||
GET /admin/supplier/items/2090300000000063970/basic-info/view
|
||||
Authorization: Bearer <admin-token>
|
||||
```
|
||||
|
||||
无请求体。读取继续要求可信读角色和 `supplier:view` 平台权限。
|
||||
|
||||
### 成功响应
|
||||
#### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -349,9 +433,22 @@ Authorization: Bearer <admin-token>
|
||||
}
|
||||
```
|
||||
|
||||
合同按 `contractId` 升序返回,只包含当前有效合同。没有合同时返回空数组 `[]`,不返回 `null`。
|
||||
#### 空数据 / 降级响应
|
||||
|
||||
### 常见失败
|
||||
没有合同时返回空数组 `"contracts": []`,不返回 `null`;合同按 `contractId` 升序返回,只包含当前有效合同。
|
||||
|
||||
#### 错误响应
|
||||
|
||||
常见失败(统一 `Result` 包装,HTTP 200):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 395001,
|
||||
"message": "供应商不存在",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
| 场景 | `code` | 前端处理 |
|
||||
|---|---:|---|
|
||||
@@ -359,6 +456,30 @@ Authorization: Bearer <admin-token>
|
||||
| 可信角色或 `supplier:view` 平台权限不足 | `403` | 展示无权限状态 |
|
||||
| 供应商不存在或已删除 | `395001` | 返回列表并刷新 |
|
||||
|
||||
#### 业务边界
|
||||
|
||||
- 读取要求可信读角色(`ADMIN`/`FINANCE`/`SUPER_ADMIN`)和 `supplier:view` 平台权限。
|
||||
- 敏感字段(税号、证件号、手机号)一律脱敏返回,前端不得期待明文。
|
||||
- `updateTime` 是后续提交表单的并发版本,必须原样缓存回传。
|
||||
|
||||
## 四、契约约束与正确调用方式
|
||||
|
||||
1. 在“资质证照”区域之后新增“合同信息”表格,在合同之后显示原账户表格。
|
||||
2. 原账户表格标题改为“结算信息”;所有请求和响应继续使用 `initialAccounts`,不要改字段名。
|
||||
3. 创建草稿时合同为完整新项,不发送 `contractId`;编辑后提交时,既有合同必须原样带回字符串 `contractId`。
|
||||
4. 提交表单是完整快照。用户明确删除全部合同时发送 `contracts: []`;未加载合同或不处理合同时省略字段,不要误发空数组。
|
||||
5. 所有 ID 均作为字符串保存、比较和回传,不经过 Number 转换。
|
||||
6. 本次不新增接口路径、权限点或业务错误码;旧客户端省略 `contracts` 时继续可用。
|
||||
7. 管理端源码不在本后端工单中修改,前端状态保持 `pending`,直至完成页签、标题和表格接入并提供前端引用。
|
||||
|
||||
## 五、数据库行为
|
||||
|
||||
- 创建草稿与提交注册均为聚合级单事务写入:供应商主体、资质、合同快照、结算账户与审计记录一起成功或一起失败,任一校验失败零写入。
|
||||
- 合同快照随供应商聚合版本(`expectedUpdateTime` 乐观并发控制)持久化;并发修改时提交失败,调用方须刷新详情后重试。
|
||||
- 审计留痕:创建/删除等不可逆操作保留审计记录;测试环境临时数据已通过业务删除接口软删除。
|
||||
- 查询供应商基本信息为只读,无写库行为。
|
||||
- 本次无 DDL、无 Flyway 迁移、无 Redis/MQ 行为变化。
|
||||
|
||||
## 六、边界行为
|
||||
|
||||
- `contracts` 省略、`null` 与空数组语义不同:省略/传 `null` = 不处理合同(旧客户端兼容);`[]` = 明确清空全部合同。
|
||||
@@ -378,6 +499,7 @@ Authorization: Bearer <admin-token>
|
||||
| 基础信息 | 不返回合同列表 | 返回完整 `contracts[]` 及字符串 ID、版本 |
|
||||
| 账户区域标题 | 页面显示“初始账户” | 页面应显示“结算信息”,接口字段仍为 `initialAccounts` |
|
||||
| 页面区块顺序 | 资质后直接进入账户区域 | 资质证照 → 合同信息 → 结算信息 |
|
||||
| 响应 `contracts[].amount`(PR #6450) | Number(如 `1200.50`) | String(如 `"1200.50"`) |
|
||||
|
||||
## 六.7、影响评估
|
||||
|
||||
@@ -386,16 +508,6 @@ Authorization: Bearer <admin-token>
|
||||
- **C 端(mp)**:不涉及,无影响。
|
||||
- **QA 排查面**:问题定位优先看「契约约束与正确调用方式」第 3、4 条(快照回传与空数组语义)与「关键变化」(amount 字符串化)。
|
||||
|
||||
## 四、契约约束与正确调用方式
|
||||
|
||||
1. 在“资质证照”区域之后新增“合同信息”表格,在合同之后显示原账户表格。
|
||||
2. 原账户表格标题改为“结算信息”;所有请求和响应继续使用 `initialAccounts`,不要改字段名。
|
||||
3. 创建草稿时合同为完整新项,不发送 `contractId`;编辑后提交时,既有合同必须原样带回字符串 `contractId`。
|
||||
4. 提交表单是完整快照。用户明确删除全部合同时发送 `contracts: []`;未加载合同或不处理合同时省略字段,不要误发空数组。
|
||||
5. 所有 ID 均作为字符串保存、比较和回传,不经过 Number 转换。
|
||||
6. 本次不新增接口路径、权限点或业务错误码;旧客户端省略 `contracts` 时继续可用。
|
||||
7. 管理端源码不在本后端工单中修改,前端状态保持 `pending`,直至完成页签、标题和表格接入并提供前端引用。
|
||||
|
||||
## 七、不影响范围
|
||||
|
||||
- 不新增接口路径、权限点或业务错误码;旧客户端省略 `contracts` 时行为完全不变。
|
||||
@@ -410,9 +522,15 @@ Authorization: Bearer <admin-token>
|
||||
- 部署:Deploy Panel API 任务 `af3f205b` 终态 `success`、退出码 0、`has_build_error=false`,未发现 Maven、编译或滚动发布错误。
|
||||
- 健康:`hl-resource-service` 的 8082、8182 双实例运行;Nacos `test` 命名空间两实例均 `healthy=true`、`enabled=true`。
|
||||
- 真实 Gateway:23 项断言通过,覆盖合同随草稿创建、详情完整回显、字符串 ID、创建携带 ID 失败、普通 ADMIN 越权、提交外部合同 ID 完整回滚、日期逆序零写入和旧客户端省略 `contracts`。
|
||||
- 同日修正复验(PR #6450):`hl-resource-service` 于 2026-08-26 23:44 滚动发布双实例 UP,jar 构建时间戳与合并提交一致;供应商定向测试 330 项通过;空原因/超长原因的状态变更请求仍由请求校验层返回 400(对外契约不变)。
|
||||
- 清理:两个临时 DRAFT 均通过业务删除接口软删除并回读为不存在;仅保留不可逆的 CREATE/DELETE 操作审计。
|
||||
- 环境限制:部署前锁定 `origin/dev-v3=1a16a5aec7d0b95ec87e6fb222581060a3135984`,但面板 Git API 回读到服务器本地短提交 `6f7d3ca78`,Gitea 无法解析该对象。接口行为已真实验证,后端工单仍等待测试环境恢复精确远端提交后复验,不能据此宣称最终交付完成。
|
||||
|
||||
## 九、相关历史 PR
|
||||
|
||||
- [#6405](https://git.1814.love:8443/wx/HL/pulls/6405):本功能原始落地(合同聚合信息)。
|
||||
- [#6450](https://git.1814.love:8443/wx/HL/pulls/6450):同日每日审查修正——响应 `contracts[].amount` Number→String(金额序列化红线)、状态变更原因错误码段位化(395043/395044,仅内部防御路径,对外契约不变)。
|
||||
|
||||
## 撤回
|
||||
|
||||
1. 从最新 `dev-v3` 创建回退分支,执行 `git revert -m 1 --no-edit 1a16a5aec7d0b95ec87e6fb222581060a3135984`,经独立 PR 合入。
|
||||
|
||||
在新工单中引用
屏蔽一个用户