hl-api-changelog/changelogs/2026-04/30_feat_contract-scheme_dispute-fields.md

7.7 KiB

新增:合同方案补充仲裁机构/管辖法院字段 + 12301 dispute 节点完整化

类型: 后端 FEAT(新增字段+老 BUG 修复) 关联: 工单 #1561 / PR #1565 (合并到 dev sha d3190de5) 日期: 2026-04-30 前端处理者: mmg 影响范围: 管理后台 → 合同方案管理 → 编辑合同方案弹窗 → 争议解决方式


业务背景

管理后台合同方案编辑页(web.test.1814.love:9443/contract/scheme),用户截图反馈:选择"仲裁/诉讼"时必须填对应地点,合同 PDF 模板里要用

排查发现:

  • 12301 平台 dispute.tribunalName 字段已支持,但 ContractCreateService.assembleParam 从未把 scheme.tribunalName 透传过去 → 合同 PDF 仲裁条款常年是空模板(老 BUG)
  • 合同方案表 contract_scheme 没有诉讼地点字段
  • disputeResolution 注释在不同代码处自相矛盾(ContractSchemeRequest 1=仲裁/2=诉讼 vs ContractApplyParam 1=诉讼/2=仲裁)

经过 4 轮 PM 整改 + 4 轮评审委员会评审(综合 9.925/10)+ 架构师勘误 + dev 编码,本次 PR 一并解决。


⚠️ 关键:disputeResolution 语义统一为 1=诉讼 / 2=仲裁

ContractSchemeRequest 注释 "1=仲裁 2=诉讼" 写反了,本次后端统一以 12301 平台真值为准:

含义
1 诉讼 (litigation)
2 仲裁 (arbitration)

前端 hl-ui 字典 dispute_resolution 渲染如原按 "1=仲裁" 请翻转,否则用户选错语义。

测试服 DB 现存方案数据已经按 1=诉讼/2=仲裁 自洽(scheme_id=3 dispute=1 国内冬季诉讼;scheme_id=2046840448906940417 dispute=2 仲裁,均合理)— 确认 ContractApplyParam 注释才是真值。


后端改动概要

1. 字段

contract_scheme 表增量加 2 列(已在测试服 DDL 落地):

ALTER TABLE contract_scheme
    ADD COLUMN tribunal_name    VARCHAR(100) NULL COMMENT '仲裁机构名称(disputeResolution=2 仲裁时必填)',
    ADD COLUMN litigation_court VARCHAR(100) NULL COMMENT '管辖法院(disputeResolution=1 诉讼时必填)';

2. ReqVO / RespVO

ContractSchemeRequest / ContractSchemeVO 加 2 字段:

@ApiModelProperty(value = "仲裁机构名称(disputeResolution=2 时必填)", example = "北京仲裁委员会")
@Size(max = 100, message = "仲裁机构名称长度不能超过 100 个字符")
private String tribunalName;

@ApiModelProperty(value = "管辖法院(disputeResolution=1 时必填)", example = "北京市朝阳区人民法院")
@Size(max = 100, message = "管辖法院长度不能超过 100 个字符")
private String litigationCourt;

3. 校验

联合校验在 Service 层(VO 层不加 @NotBlank,因为依赖 disputeResolution 值组合):

场景 校验 错误码 业务码
disputeResolution=2(仲裁)缺 tribunalName 拦截 SCHEME_TRIBUNAL_NAME_REQUIRED 510216
disputeResolution=1(诉讼)缺 litigationCourt 拦截 SCHEME_LITIGATION_COURT_REQUIRED 510217
反向字段(选仲裁但传了诉讼地点等) 不强制清空 - -

4. 合同条款渲染

supplementaryClause 拼接顺序改为:

[1] safetyNotice    (安全告知书,平台标准条款)
[2] disputeClause   (争议解决条款,本次新增)
[3] userClause      (用户自定义补充约定)

disputeClause 文本格式(本期固定模板):

  • 仲裁: "双方因履行本合同发生争议的,提交{tribunalName}仲裁解决。"
  • 诉讼: "双方因履行本合同发生争议的,提交{litigationCourt}诉讼解决。"

12301 dispute 节点也会按 resolution 路由对应字段:

  • 2=仲裁 → 输出 dispute.tribunalName
  • 1=诉讼 → 输出 dispute.litigationCourt

腾讯电子签链路通过共享 param.supplementaryClause 自动同步获得 disputeClause 文本(后端零改动)。

5. 字符净化

tribunalName / litigationCourt 拼入条款文本时净化 \n / \r / \t 为空格(防 12301 errcode=301025,经验来自 PR #1551 reason 字段事故)。


错误响应示例

创建/修改合同方案时,选择仲裁但未填仲裁机构:

HTTP 200 (走业务错误码,非协议错误)
{
  "code": 510216,
  "message": "争议解决方式为仲裁时,仲裁机构名称不能为空",
  "data": null
}

诉讼缺管辖法院:

{
  "code": 510217,
  "message": "争议解决方式为诉讼时,管辖法院不能为空",
  "data": null
}

前端要做的改动 ⚠️

1. 字典 dispute_resolution 翻转(关键)

原可能渲染: 1=仲裁, 2=诉讼 → 改为 1=诉讼, 2=仲裁(与后端一致)。

如不翻转,用户选"仲裁" UI 传 1,后端按"1=诉讼"处理 → 数据完全反向。

2. 编辑合同方案弹窗 — 条件输入框

争议解决方式单选(仲裁/诉讼)下方,动态显示对应输入框:

选中 显示输入框 必填 maxlength placeholder
仲裁(value=2) 「仲裁机构名称」 必填 100 请填写仲裁委员会全称,例:北京仲裁委员会
诉讼(value=1) 「管辖法院」 必填 100 请填写约定管辖法院,例:北京市朝阳区人民法院

3. 切换 resolution 不清空已填值

后端两列独立存,允许保留(用户切换"仲裁→诉讼→仲裁"时,仲裁地点会保留)。

4. 提交字段名

  • disputeResolution (Integer)
  • tribunalName (String)
  • litigationCourt (String)

5. 编辑旧方案兼容

旧方案 tribunalName/litigationCourt 都为 null:

  • 加载时不拦截,允许列表正常显示
  • 用户点击保存时按新规校验拦截(后端会返 510216/510217)

6. 错误码字典

业务码 含义
510216 仲裁机构名称必填
510217 管辖法院必填

部署状态

  • PR #1565 合并到 dev (sha d3190de5,2026-04-30 15:46)
  • 测试服 DDL 已落 (V20260501 ALTER TABLE 添加 2 列)
  • Deploy Panel 部署 hl-order-service-v2 测试服(进行中,管理者跟踪)
  • 测试服 12301 + 腾讯电子签 round-trip 验证待执行
  • Release dev → main 待用户拍板

测试服 round-trip 计划

经网关 https://api.test.1814.love:9443:

  1. POST /admin/contract/scheme disputeResolution=2 不带 tribunalName → 期望 510216
  2. POST /admin/contract/scheme disputeResolution=1 不带 litigationCourt → 期望 510217
  3. POST /admin/contract/scheme 仲裁带 tribunalName → 200 success,GET 详情验证字段回显
  4. PUT 同一方案改诉讼带 litigationCourt → 200,字段独立保留
  5. 真实下单走 12301 报送(仲裁场景)→ 验 dispute.tribunalName 输出 + supplementaryClause 含仲裁文本
  6. 真实下单走腾讯电子签(仲裁场景)→ 验 supplementaryClause form 字段含仲裁文本(跨平台一致性)

单测

mvn -pl hl-order-service-v2 -Dtest='ContractCreateServiceTest,TencentEsignRequestBuilderTest' test:

  • 84 tests,0 failures,0 errors
  • 17 个新单测 (4 校验 + 8 corner case + 4 边界净化顺序隐藏改点 + 1 跨平台)

不动

  • 腾讯电子签模板 widget(运营在腾讯控制台改模板时联动)
  • disputeResolution int → Integer 重构(本期不动)
  • MP / 字典服务 / Feign / MQ / 状态机 / 缓存(本期纯 admin 配置项)
  • 历史合同回填(运营 TODO SQL 附 PR body)

运营 TODO(可选)

历史方案补齐(运营评估后由运维管理员执行,本 PR 不自动跑):

-- 仲裁方案缺仲裁委员会
SELECT scheme_id, name FROM contract_scheme
 WHERE deleted_at IS NULL AND dispute_resolution = 2 AND (tribunal_name IS NULL OR tribunal_name = '');

-- 诉讼方案缺管辖法院
SELECT scheme_id, name FROM contract_scheme
 WHERE deleted_at IS NULL AND dispute_resolution = 1 AND (litigation_court IS NULL OR litigation_court = '');