Files
loan-pricing/docs/superpowers/specs/2026-05-11-shangyu-pricing-field-adjustment-design.md

232 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 上虞利率定价字段口径调整设计
## 背景
当前上虞利率定价新增流程已经具备个人、企业两个新增弹窗,并已有业务种类、历史贷款利率和历史贷款合同选择链路。本次需求是在现有链路上调整字段口径:
- 前端通用业务种类改为 `新增/存量新增/存量转贷`,仅 `存量转贷` 查询历史贷款合同。
- `质押 + 存单质押` 时新增 `couponRate` 存单票面利率,客户经理填写后上传。
- 上虞对私剔除 `loanPurpose` 贷款用途和 `bizProof` 是否有经营佐证。
- 上虞对私、对公按客户类型和担保方式分别调整 `collType` 可选值。
用户已确认本次按页面、创建接口、服务校验、流程保存、模型调用参数全链路同步调整。用户也确认 `couponRate``质押 + 存单质押` 时必须填写。对公 `businessType` 上传模型接口这一条用户已明确要求忽略,因此本设计不新增、不验证 `businessType` 模型入参链路;本次模型入参调整只覆盖 `couponRate`
## 范围
### 本次包含
- 调整个人和企业新增弹窗的 `businessType` 选项。
- 保持 `businessType=存量转贷` 才查询历史贷款合同。
- 新增 `couponRate` 条件展示、必填校验、提交和模型入参传递。
- 移除个人新增弹窗中的 `loanPurpose``bizProof`
- 后端取消个人创建 DTO 对 `loanPurpose``bizProof` 的必填依赖。
- 按个人/企业和抵押/质押分别校验 `collType` 可选值。
- 新增或更新数据库字段定义,使 `couponRate` 能保存到流程表。
- 更新直接相关的前端静态断言和后端单元测试。
### 本次不包含
- 不重做历史贷款合同查询接口。
- 不改历史贷款合同选择弹窗结构。
- 不新增字典配置或字段配置化能力。
- 不处理旧历史数据回填。
- 不新增或验证对公 `businessType` 上传模型逻辑;该条按用户确认忽略。
## 推荐方案
采用全链路最短路径同步方案。
页面负责字段展示、条件清空和提交前整理。后端负责创建 DTO 接收、统一业务校验、流程实体保存和模型入参传递。SQL 同步补充 `coupon_rate` 字段,保证新环境和已有环境都能落库。
不采用只改前端的方式,因为直接调用创建接口会绕过 `couponRate` 必填和 `collType` 口径校验。不采用配置化字段规则,因为本次口径明确,配置化会超出需求范围。
## 前端设计
### 通用业务种类
个人新增弹窗和企业新增弹窗的 `businessType` 选项统一为:
- `新增`
- `存量新增`
- `存量转贷`
交互规则:
- 选择 `存量转贷` 时,沿用现有客户内码查询历史贷款合同逻辑。
- 选择 `新增``存量新增` 时,清空历史合同选择和 `loanRateHistory`
-`存量转贷` 提交前不上传 `loanRateHistory`
### 存单票面利率
个人和企业新增弹窗都新增 `couponRate` 输入框,字段名称展示为 `存单票面利率`
展示和提交规则:
- 仅当 `guarType=质押``collType=存单质押` 时展示。
- 展示时必填。
- 切换担保方式或抵质押类型后,如果不再满足 `质押 + 存单质押`,清空 `couponRate`
- 不满足条件时提交前不上传 `couponRate`
### 上虞对私字段调整
个人新增弹窗移除:
- `贷款用途 loanPurpose`
- `是否有经营佐证 bizProof`
个人提交数据不再包含这两个字段。个人的 `loanLoop``collThirdParty` 等既有字段保持现有处理方式。
个人 `collType` 选项:
- `guarType=抵押``一线/一类/二类/三类`
- `guarType=质押``存单质押/其他质押`
### 上虞对公字段调整
企业 `collType` 选项:
- `guarType=抵押``一类/二类/三类/四类/排污权抵押/设备等其他不动产抵押`
- `guarType=质押``存单质押/股权质押/其他质押`
企业其他既有上传字段保持现状。
## 后端设计
### DTO 和实体
`PersonalLoanPricingCreateDTO`
- `businessType` 允许值改为 `新增/存量新增/存量转贷`
- 移除 `loanPurpose` 必填和枚举校验。
- 移除 `bizProof` 业务依赖。
- 新增 `couponRate`
`CorporateLoanPricingCreateDTO`
- `businessType` 允许值改为 `新增/存量新增/存量转贷`
- 新增 `couponRate`
- `collType` 允许值覆盖对公抵押和质押新口径。
`LoanPricingWorkflow`
- `businessType` 注释更新为 `新增/存量新增/存量转贷`
- 新增 `couponRate` 字段,对应数据库 `coupon_rate`
- 个人剔除字段不再作为本次创建链路必需字段。
`ModelInvokeDTO`
- 新增 `couponRate`,用于模型调用参数。
- 不新增或调整 `businessType` 模型入参;该条按用户确认不纳入本次范围。
`LoanPricingConverter`
- 个人和企业创建 DTO 都映射 `couponRate`
- 个人转换不再依赖 `loanPurpose``bizProof`
### 服务层校验
创建流程统一校验放在 `LoanPricingWorkflowServiceImpl`,确保绕过前端直接调用接口也会被拦截。
校验规则:
- `businessType` 必填,只允许 `新增/存量新增/存量转贷`
- `businessType=存量转贷` 时,`loanRateHistory` 必填。
- `guarType=质押``collType=存单质押` 时,`couponRate` 必填。
- `custType=个人``guarType=抵押` 时,`collType` 只允许 `一线/一类/二类/三类`
- `custType=个人``guarType=质押` 时,`collType` 只允许 `存单质押/其他质押`
- `custType=企业``guarType=抵押` 时,`collType` 只允许 `一类/二类/三类/四类/排污权抵押/设备等其他不动产抵押`
- `custType=企业``guarType=质押` 时,`collType` 只允许 `存单质押/股权质押/其他质押`
当担保方式不是抵押或质押时,不要求 `collType``couponRate`
## 数据库设计
流程表新增字段:
```sql
ALTER TABLE `loan_pricing_workflow`
ADD COLUMN `coupon_rate` varchar(100) DEFAULT NULL COMMENT '存单票面利率' AFTER `loan_rate_history`;
```
需要同步更新:
- 当前迁移 SQL。
- `sql/loan_pricing_workflow.sql`
- `sql/loan_pricing_schema_20260328.sql`
- `sql/loan_pricing_prod_init_20260331.sql`
已有历史数据不回填,`coupon_rate` 允许为空。
## 数据流
1. 用户进入利率定价列表,选择新增。
2. 用户选择个人或企业客户,并通过客户号映射选择客户内码。
3. 打开对应新增弹窗。
4. 用户选择业务种类。
5. 若业务种类为 `存量转贷`,前端使用客户内码查询历史贷款合同并回填 `loanRateHistory`
6. 用户选择担保方式和抵质押类型。
7. 若选择 `质押 + 存单质押`,前端展示并要求填写 `couponRate`
8. 前端提交前清理不适用字段。
9. 后端创建接口接收 DTO。
10. 转换器映射为 `LoanPricingWorkflow`
11. 服务层做业务种类、历史利率、抵质押类型和 `couponRate` 校验。
12. 流程表保存。
13. 模型调用前复制流程字段到 `ModelInvokeDTO`,带出 `couponRate``businessType` 模型入参不在本次设计范围内。
## 错误处理
- 业务种类为空:提示 `请选择业务种类` 或后端返回 `业务种类不能为空`
- 业务种类为旧值或非法值:后端返回 `业务种类必须是:新增、存量新增、存量转贷之一`
- `存量转贷` 未选择历史贷款合同:提示或返回 `请选择历史贷款合同`
- `质押 + 存单质押` 未填写 `couponRate`:提示或返回 `存单票面利率不能为空`
- `collType` 不符合当前客户类型和担保方式:后端返回对应可选值错误。
## 测试设计
### 前端静态断言
更新或新增前端测试脚本,覆盖:
- 个人和企业新增弹窗都包含 `新增/存量新增/存量转贷`
- 个人和企业新增弹窗不再包含旧选项 `新客`
- 个人新增弹窗不再展示 `贷款用途``是否有经营佐证`
- 个人抵押选项为 `一线/一类/二类/三类`
- 个人质押选项包含 `存单质押/其他质押`
- 企业抵押选项为 `一类/二类/三类/四类/排污权抵押/设备等其他不动产抵押`
- 企业质押选项为 `存单质押/股权质押/其他质押`
- `couponRate` 仅在 `质押 + 存单质押` 条件下展示、必填、提交。
- 非适用条件提交前删除 `couponRate`
### 后端单元测试
更新 `LoanPricingWorkflowServiceImplTest` 或新增直接相关测试,覆盖:
- `businessType=新增` 通过。
- `businessType=新客` 拒绝。
- `businessType=存量转贷` 且缺少 `loanRateHistory` 拒绝。
- `guarType=质押``collType=存单质押` 且缺少 `couponRate` 拒绝。
- 个人抵押允许 `一线/一类/二类/三类`,拒绝对公专属抵押值。
- 企业抵押允许 `排污权抵押/设备等其他不动产抵押`
- 企业质押允许 `股权质押/其他质押`
### 实际页面验证
实现完成后按项目规则验证:
- 使用 `nvm` 控制前端 Node 版本。
- 启动前端页面并用 Playwright 打开真实页面,不使用 prototype。
- 验证个人新增弹窗字段移除、业务种类选项、抵押/质押选项和 `couponRate` 条件展示。
- 验证企业新增弹窗业务种类选项、抵押/质押选项和 `couponRate` 条件展示。
- 验证 `存量转贷` 仍会触发历史合同查询,`新增/存量新增` 不触发。
- 测试结束关闭本次启动的前后端进程。
## 验收标准
- 页面字段和选项与本设计一致。
- 创建接口不能接受旧业务种类 `新客`
- `质押 + 存单质押` 未填 `couponRate` 时前后端都不能提交成功。
- 不适用 `couponRate` 时不会上传该字段。
- `couponRate` 能保存到流程表并进入模型调用参数。
- 对私不再要求或上传 `loanPurpose``bizProof`
- 前端静态断言、后端单元测试和真实页面验证通过。