文件
hl-api-changelog/changelogs-v2/2026-09/07_7290_供应商合同十项必填并移除登记原因-修改接口-管理后台.md
T
Mimingguang cb4262b39b
changelog-filename-gate / validate (push) Failing after 2s
docs(changelog): #7290 前端 verified(commit 87cf8ba8)
2026-09-07 20:23:24 +08:00

14 KiB

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 7290 供应商合同十项必填并移除登记原因 admin lc(GIT) 修改接口 deployed verified verified mmg 87cf8ba8 2026-09-07 前端已交付并验证(commit 87cf8ba8):SupplierContractEditModal 十项转必填(文本 trim 非空/枚举日期判空/autoRenew 按 ===true-false 不把 false 当空,endDate 合并必填+不早于开始日期单条 rule),contractNo label 补合同编号→合同编号;删登记/修改原因输入+changeReasonRule+buildBody 不再组装 changeReason;必填恒携带、可选(contractType/amount/pricingMode/settleCycle/remark)保持新增省略/编辑整份替换,expectedUpdateTime 围栏与 395014/395051 提示不变;api add/update JSDoc 改新口径,delete 与删除审计流程零改动。目标 spec 24/24 绿+supplier 域 183/183 绿+checkpoint 全绿(Vitest 全量+生产构建)。 2026-09-07 dev-v3

供应商合同:十项必填并移除登记原因

一、关键变化

  • 新增、编辑合同均要求提交:合同名称、合同编号、合同状态、业务线、关联主合同、签署日期、自动续约、有效期开始、有效期结束、合同附件。
  • 页面字段 contractNo 的文案改为“合同编号”,不再显示“补合同编号”。
  • 新增、编辑不再要求登记原因,请移除原因输入框并停止发送 changeReason;旧调用方多传该字段仍兼容忽略。
  • 新增、编辑成功后不再产生供应商变更审计。合同删除接口及其必填原因、删除审计均不变。

本文覆盖此前 #6654、#6842 中“合同业务字段可空、新增或编辑原因必填”的旧口径。

二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 新增供应商合同 POST /admin/supplier/items/{supplierId}/contracts/add 请求校验与行为修改 十项必填,移除登记原因与新增审计
2 编辑供应商合同 PUT /admin/supplier/items/{supplierId}/contracts/{contractId}/update 请求校验与行为修改 十项必填,移除登记原因与编辑审计

三、接口详情

1. 新增供应商合同 POST /admin/supplier/items/{supplierId}/contracts/add

VO: SupplierContractCreateReqVO / SupplierContractRespVO

使用场景

在已有供应商下新增一份完整合同,不再填写登记原因。

入参

字段 位置 类型 必填 约束 说明
supplierId Path String 是 正整数 ID 所属供应商
contractName Body String 是 非空,最长 500 合同名称
contractNo Body String 是 非空,最长 100 合同编号;页面不得再写“补合同编号”
status Body String 是 DRAFT / ACTIVE / SIGNED / EXPIRED 合同状态
businessLine Body String 是 非空,最长 100 业务线
relatedMainContract Body String 是 非空,最长 100 关联主合同引用
signDate Body String 是 yyyy-MM-dd 签署日期
autoRenew Body Boolean 是 true / false 自动续约;false 是有效值
startDate Body String 是 yyyy-MM-dd 有效期开始
endDate Body String 是 不早于 startDate 有效期结束
scanFileUrl Body String 是 非空,最长 1000 合同附件永久地址
contractType Body String/null 否 FRAME / SINGLE_TRIP / PURCHASE 合同类型
amount Body String/null 否 非负,最多 10 位整数和 2 位小数 合同金额
pricingMode Body String/null 否 最长 100 计价方式
settleCycle Body String/null 否 最长 32 结算周期
remark Body String/null 否 最长 500 备注

changeReason 已从请求模型移除,不要再由新增表单组装。

出参

字段 类型 说明
code / message / success Integer / String / Boolean 成功为 200 / 成功 / true
data.contractId String 合同 ID
data.contractName / contractNo String 合同名称 / 合同编号
data.status / businessLine String 合同状态 / 业务线
data.relatedMainContract String 关联主合同
data.signDate / startDate / endDate String yyyy-MM-dd
data.autoRenew Boolean 自动续约
data.scanFileUrl String 合同附件地址
data.contractType / amount / pricingMode / settleCycle / remark 对应类型/null 可选字段,响应结构不变
data.updateTime String 合同版本,yyyy-MM-dd HH:mm:ss

请求示例

{
  "contractName": "年度服务合同",
  "contractNo": "HT-2026-001",
  "status": "SIGNED",
  "businessLine": "旅行服务",
  "relatedMainContract": "MAIN-2026-001",
  "signDate": "2026-09-07",
  "autoRenew": false,
  "startDate": "2026-09-07",
  "endDate": "2027-09-06",
  "scanFileUrl": "https://files.example.com/contracts/demo.pdf",
  "contractType": "FRAME",
  "amount": "1200.50",
  "pricingMode": "按团结算",
  "settleCycle": "MONTHLY",
  "remark": null
}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "contractId": "2097000000000000001",
    "contractName": "年度服务合同",
    "contractNo": "HT-2026-001",
    "contractType": "FRAME",
    "signDate": "2026-09-07",
    "startDate": "2026-09-07",
    "endDate": "2027-09-06",
    "businessLine": "旅行服务",
    "relatedMainContract": "MAIN-2026-001",
    "autoRenew": false,
    "amount": "1200.50",
    "pricingMode": "按团结算",
    "settleCycle": "MONTHLY",
    "status": "SIGNED",
    "scanFileUrl": "https://files.example.com/contracts/demo.pdf",
    "remark": null,
    "updateTime": "2026-09-07 20:00:00"
  },
  "success": true
}

空数据 / 降级响应

没有空成功数据。十项必填字段缺少、为 null 或文本为空白时均失败,data 为 null。

错误响应

{"code":400,"message":"合同编号不能为空","data":null,"success":false}

业务边界

  • 前端提交前应同时校验十项必填;业务错误可能仍使用 HTTP 200,必须判断响应体 code 和 success。
  • autoRenew=false 不得被空值过滤器删除;startDate 不得晚于 endDate。
  • 权限、供应商状态、审批冻结、幂等和错误码均保持原规则。

2. 编辑供应商合同 PUT /admin/supplier/items/{supplierId}/contracts/{contractId}/update

VO: SupplierContractUpdateReqVO / SupplierContractRespVO

使用场景

完整编辑一份已有合同,不再填写编辑原因。

入参

字段 位置 类型 必填 约束 说明
supplierId Path String 是 正整数 ID 所属供应商
contractId Path String 是 正整数 ID 目标合同
contractName Body String 是 非空,最长 500 合同名称
contractNo Body String 是 非空,最长 100 合同编号
status Body String 是 DRAFT / ACTIVE / SIGNED / EXPIRED 合同状态
businessLine Body String 是 非空,最长 100 业务线
relatedMainContract Body String 是 非空,最长 100 关联主合同引用
signDate Body String 是 yyyy-MM-dd 签署日期
autoRenew Body Boolean 是 true / false 自动续约
startDate Body String 是 yyyy-MM-dd 有效期开始
endDate Body String 是 不早于 startDate 有效期结束
scanFileUrl Body String 是 非空,最长 1000 合同附件永久地址
expectedUpdateTime Body String/null 否 yyyy-MM-dd HH:mm:ss 传入时必须匹配合同当前版本
contractType / amount / pricingMode / settleCycle / remark Body 对应类型/null 否 与新增接口一致 完整替换时原样回传需保留的可选值

changeReason 已从请求模型移除,不要再由编辑表单组装。

出参

字段 类型 说明
code / message / success Integer / String / Boolean 成功为 200 / 成功 / true
data.contractId String 原合同 ID
data.contractName / contractNo / status / businessLine String 编辑后的必填文本字段
data.relatedMainContract / scanFileUrl String 关联主合同 / 合同附件地址
data.signDate / startDate / endDate String 编辑后的日期
data.autoRenew Boolean 编辑后的自动续约值
data.contractType / amount / pricingMode / settleCycle / remark 对应类型/null 编辑后的可选字段
data.updateTime String 新合同版本,供下一次编辑或删除使用

请求示例

{
  "contractName": "年度服务合同(续签)",
  "contractNo": "HT-2026-001-A",
  "status": "ACTIVE",
  "businessLine": "旅行服务",
  "relatedMainContract": "MAIN-2026-001",
  "signDate": "2026-09-07",
  "autoRenew": true,
  "startDate": "2026-09-07",
  "endDate": "2028-09-06",
  "scanFileUrl": "https://files.example.com/contracts/demo-a.pdf",
  "contractType": "FRAME",
  "amount": "1500.00",
  "pricingMode": "按团结算",
  "settleCycle": "MONTHLY",
  "remark": "续签",
  "expectedUpdateTime": "2026-09-07 20:00:00"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "data": {
    "contractId": "2097000000000000001",
    "contractName": "年度服务合同(续签)",
    "contractNo": "HT-2026-001-A",
    "contractType": "FRAME",
    "signDate": "2026-09-07",
    "startDate": "2026-09-07",
    "endDate": "2028-09-06",
    "businessLine": "旅行服务",
    "relatedMainContract": "MAIN-2026-001",
    "autoRenew": true,
    "amount": "1500.00",
    "pricingMode": "按团结算",
    "settleCycle": "MONTHLY",
    "status": "ACTIVE",
    "scanFileUrl": "https://files.example.com/contracts/demo-a.pdf",
    "remark": "续签",
    "updateTime": "2026-09-07 20:00:01"
  },
  "success": true
}

空数据 / 降级响应

没有空成功数据。历史合同仍可读取;编辑历史合同前须先补齐十项必填字段。

错误响应

{"code":400,"message":"合同附件不能为空","data":null,"success":false}

业务边界

  • 编辑仍是完整替换;十项必填字段必须全部提交,可选字段需按是否保留正确回传。
  • expectedUpdateTime 可省略,提交时应使用详情返回的合同版本;版本过期返回 395014。
  • 删除接口不在本次变化内,删除仍必须提交 changeReason 并产生删除审计。

四、契约约束与正确调用方式

  1. 新增、编辑表单将十项字段全部标为必填,尤其不得把 autoRenew=false 当空值。
  2. 将 contractNo 的页面标签统一改为“合同编号”。
  3. 移除新增、编辑的登记原因输入与校验,请求体不再组装 changeReason。
  4. 编辑时从详情的 contracts[] 完整回填并提交;隐藏的可选字段继续原样保留。
  5. 删除合同继续沿用原因弹框和原 DELETE 请求体,不要一并移除。

五、数据库行为

新增、编辑成功后保存完整合同值,但不新增供应商变更审计;校验失败时合同与审计均不变化。删除仍为软删除并保留原删除审计。本次无表结构或历史数据迁移。

六、边界行为

  • 缺少任一必填字段:code=400、success=false,不会写入或修改合同。
  • 未登录:code=401;无写权限:395002;合同不存在或归属错误:395051;日期倒置:395054;无实际变化:395057。
  • 历史合同可能含空字段,读取不受影响;再次编辑时须补齐十项。
  • 旧请求额外携带 changeReason 不会失败,但后端不保存该值,也不产生新增、编辑审计。

六.6、修改前后对比

字段 / 行为 修改前 修改后
十项业务字段 均可省略或清空 新增、编辑全部必填
contractNo 页面文案 补合同编号 合同编号
新增、编辑 changeReason 必填 不需要;旧请求多传兼容忽略
新增、编辑供应商变更审计 产生审计 不产生审计
删除原因与审计 原因必填并产生审计 不变

六.7、影响评估

  • 是否破坏向后兼容:对缺少十项中任一字段的旧新增、编辑请求是收紧变化;旧请求多传 changeReason 仍兼容。
  • 前端是否必须同步上线:是。必须调整必填、文案和新增/编辑原因交互。
  • 前端 workaround 清理点:删除新增、编辑原因弹框及 changeReason 组装;保留删除原因流程。

七、不影响范围

  • 仅影响管理后台供应商合同新增、编辑。
  • 不修改合同删除、供应商主体、收款账户、小程序接口、响应字段、数据库结构及历史合同读取。

八、测试环境已验证

  • POST 与 PUT 各对十项字段逐项省略,共 20 个请求均返回 code=400,失败路径零写入。
  • 不带 changeReason 的新增、编辑均成功;autoRenew=false 正常保存,旧请求多传 changeReason 仍兼容。
  • 新增、编辑对应的供应商变更审计均为 0;临时合同已删除,原删除审计保持存在。

当前状态:后端已部署并验证;待前端处理。

十、相关文档

关联 / 联系人

链接

联系人

  • 后端负责人: @lc