新增业务种类与历史利率设计文档

This commit is contained in:
wkc
2026-04-29 14:42:31 +08:00
parent 3180c33500
commit 86b8704ad9
2 changed files with 262 additions and 0 deletions

View File

@@ -0,0 +1,247 @@
# 业务种类与历史贷款利率设计
## 背景
利率定价流程新增时,当前页面已经支持先选择客户类型,再通过客户号查询选择客户内码,最后打开个人或企业新增弹窗。新需求要求在新增流程时增加两个字段:
- 业务种类
- 历史贷款利率
字段和接口规则以 `doc/上虞_客户内码客户_历史利率_映射表.xlsx` 的“历史贷款合同查询选择”sheet 以及 `doc/利率定价接口.txt` 的历史合同查询接口为准。
## 已确认规则
- 个人客户和企业客户新增流程同时增加业务种类和历史贷款利率。
- 业务种类选项为:新客、存量新增、存量转贷。
- 业务种类需要保存到流程表,并在详情页展示。
- 业务种类只用于前端判断是否触发历史合同查询,不作为模型入参上传。
- 仅当业务种类选择“存量转贷”时,查询历史贷款合同。
- 存量转贷必须选择一条历史合同记录;未查询到历史合同、未选择历史合同或历史贷款利率为空时,禁止提交。
- 历史贷款利率需要保存到流程表。
- 发起利率定价的模型调用入参需要新增历史贷款利率字段。
- 历史合同查询列表展示 Excel 中“历史贷款合同查询选择”sheet 的全部返回字段,并由用户单选一条。
## 推荐方案
采用后端代理历史合同查询、前端弹窗单选的方案。
前端负责业务种类交互、触发查询、展示历史合同列表、单选回填历史贷款利率和提交前拦截。后端负责代理外部历史合同接口、统一错误处理、保存新增字段,以及在模型调用中传递历史贷款利率。
不采用前端直接调用外部网关地址的方案,避免把外部地址和 `appCode` 暴露到前端,也避免错误处理分散。
不采用进入新增弹窗前先查询历史合同的方案,因为只有存量转贷需要历史合同,前置查询会让新客和存量新增多走不必要步骤。
## 数据流
新增流程保持现有主路径:
1. 列表页点击新增。
2. 选择个人客户或企业客户。
3. 客户号查询并选择客户内码。
4. 打开个人或企业新增弹窗。
5. 在贷款信息中选择业务种类。
6. 若业务种类为新客或存量新增,直接填写其他字段并提交。
7. 若业务种类为存量转贷,前端用当前客户内码查询历史合同。
8. 前端弹出历史贷款合同选择列表。
9. 用户单选一条历史合同。
10. 前端回填该行历史贷款利率。
11. 提交创建接口。
12. 后端保存业务种类和历史贷款利率。
13. 后端调用模型时只把历史贷款利率带入模型请求。
## 历史合同查询接口设计
新增后端业务接口:
```text
GET /loanPricing/workflow/history-contract?custIsn=...
```
接口职责:
1. 校验 `custIsn` 非空。
2. 读取历史合同外部接口配置。
3. 使用 GET 调用外部接口,请求参数名为 `cust_isn`
4. 解析外部接口返回列表。
5. 返回给前端的字段保持下划线命名。
新增配置:
```yaml
loan-rate-history:
url: http://552f7aff0acd4c09ac3b83dbfee57fa0.apigateway.res.dc-pdt-zj96596.com/shangyu_loan_rate_history?appCode=1a89fa84abda480ba93ed73fd01ffd07&cust_isn=
```
开发和测试环境可指向本项目 mock 接口;生产配置使用真实外部接口地址。
## 历史合同返回字段
新增 `HistoryLoanContractVO`JSON 字段按 Excel 保持下划线命名:
| 字段 | 名称 | 用途 |
| --- | --- | --- |
| `cust_isn` | 客户内码 | 前端展示 |
| `loan_contract_history` | 历史贷款合同号 | 前端展示 |
| `guar_type_history` | 历史贷款担保方式 | 前端展示 |
| `product_code_history` | 历史贷款产品代码 | 前端展示 |
| `loan_rate_history` | 历史贷款利率 | 前端展示,用户选择后作为后续参数 |
| `loan_amount_history` | 历史贷款金额 | 前端展示 |
| `loan_sign_date_history` | 历史贷款签订时间 | 前端展示 |
## 创建接口和数据模型
个人创建 DTO `PersonalLoanPricingCreateDTO` 新增:
- `businessType`
- `loanRateHistory`
企业创建 DTO `CorporateLoanPricingCreateDTO` 新增:
- `businessType`
- `loanRateHistory`
校验规则:
- `businessType` 必填。
- `businessType` 只能是新客、存量新增、存量转贷。
- `businessType=存量转贷` 时,`loanRateHistory` 必填。
- `businessType` 为新客或存量新增时,不要求 `loanRateHistory`
流程实体 `LoanPricingWorkflow` 新增:
- `businessType`
- `loanRateHistory`
数据库 `loan_pricing_workflow` 新增:
```sql
ALTER TABLE `loan_pricing_workflow`
ADD COLUMN `business_type` varchar(20) DEFAULT NULL COMMENT '业务种类' AFTER `loan_purpose`,
ADD COLUMN `loan_rate_history` varchar(100) DEFAULT NULL COMMENT '历史贷款利率' AFTER `business_type`;
```
需要同步更新独立 schema SQL 和生产初始化 SQL 中的 `loan_pricing_workflow` 表结构。
## 模型入参
模型入参 `ModelInvokeDTO` 新增:
- `loanRateHistory`
`LoanPricingModelService` 仍按现有方式从 `LoanPricingWorkflow` 复制属性到 `ModelInvokeDTO`。由于 `LoanPricingWorkflow``ModelInvokeDTO` 字段同名,历史贷款利率会进入模型请求。
`businessType` 不添加到 `ModelInvokeDTO`,不进入模型请求。
`ModelService` 仍使用现有 `application/x-www-form-urlencoded` 请求方式,不调整模型调用协议。
## 前端交互
个人和企业新增弹窗都在“贷款信息”区域增加:
- 业务种类:下拉框,选项为新客、存量新增、存量转贷。
- 历史贷款利率:只读输入框,仅当业务种类为存量转贷时展示或启用。
业务种类选择逻辑:
- 选择新客:清空已选历史合同和历史贷款利率。
- 选择存量新增:清空已选历史合同和历史贷款利率。
- 选择存量转贷:使用当前 `custIsn` 查询历史贷款合同,并打开历史合同选择弹窗。
历史贷款合同选择弹窗:
- 宽度沿用客户号查询弹窗的 80%。
- 表格首列为单选框。
- 表格展示客户内码、历史贷款合同号、历史贷款担保方式、历史贷款产品代码、历史贷款利率、历史贷款金额、历史贷款签订时间。
- 用户选择一条记录后点击确定。
- 确定后关闭弹窗,并将该行 `loan_rate_history` 回填到新增表单的 `loanRateHistory`
提交逻辑:
- 业务种类始终必填。
- 存量转贷时必须已选择历史合同。
- 存量转贷时 `loanRateHistory` 为空则禁止提交。
- 新客和存量新增提交时不需要历史贷款利率。
## 详情展示
个人详情和企业详情都需要展示:
- 业务种类
- 历史贷款利率
展示位置放在现有贷款信息或基础信息区域,字段值来自 `loanPricingWorkflow.businessType``loanPricingWorkflow.loanRateHistory`
若历史贷款利率为空,详情页按现有详情页空值展示方式显示。
## 异常处理
- 前端业务种类为空:提示“请选择业务种类”。
- 存量转贷未选择历史合同:提示“请选择历史贷款合同”,禁止提交。
- 存量转贷历史合同返回空列表:提示“未查询到历史贷款合同”,禁止提交。
- 历史合同查询失败:展示后端返回错误,保留当前新增弹窗,不提交。
- 后端历史合同接口 `custIsn` 为空:返回“客户内码不能为空”。
- 外部历史合同接口无返回或返回错误:后端抛出业务异常。
- 创建接口收到存量转贷但历史贷款利率为空:后端返回业务错误。
## Mock 接口
为本地开发和真实页面测试新增历史合同 mock
```text
GET /rate/pricing/mock/history-contract?cust_isn=...
```
mock 接口返回 1 条或多条历史合同记录,字段使用历史合同返回字段中的下划线名称。
开发和测试 profile 的 `loan-rate-history.url` 可配置为本项目 mock 地址。
## 测试方案
### 后端验证
- 历史合同查询接口正常返回下划线字段。
- 历史合同查询接口缺少 `custIsn` 时返回错误。
- 历史合同外部接口返回空列表时,前端可收到空列表并拦截提交。
- 个人创建接口 `businessType=存量转贷` 且缺少 `loanRateHistory` 时返回错误。
- 企业创建接口 `businessType=存量转贷` 且缺少 `loanRateHistory` 时返回错误。
- 个人创建接口带业务种类和历史贷款利率时正常保存。
- 企业创建接口带业务种类和历史贷款利率时正常保存。
- 模型调用请求包含 `loanRateHistory`
- 模型调用请求不包含 `businessType`
### 前端验证
- 个人新增弹窗展示业务种类和历史贷款利率。
- 企业新增弹窗展示业务种类和历史贷款利率。
- 业务种类为新客时不触发历史合同查询。
- 业务种类为存量新增时不触发历史合同查询。
- 业务种类为存量转贷时触发历史合同查询。
- 历史合同弹窗展示全部 7 个返回字段。
- 历史合同弹窗只允许单选一条。
- 选择历史合同后回填历史贷款利率。
- 业务种类从存量转贷切换到新客或存量新增时,清空历史贷款利率。
- 存量转贷未选择历史合同时禁止提交。
### 真实页面验证
按照项目规则,页面功能开发完成后必须启动前端页面,并用浏览器打开真实利率定价流程页面验证,禁止打开 prototype 页面。
真实页面至少覆盖:
1. 个人新客新增并提交。
2. 个人存量新增新增并提交。
3. 个人存量转贷查询历史合同、单选、回填历史贷款利率、提交、详情展示。
4. 企业新客新增并提交。
5. 企业存量新增新增并提交。
6. 企业存量转贷查询历史合同、单选、回填历史贷款利率、提交、详情展示。
7. 存量转贷不选择历史合同直接提交时被拦截。
测试结束后关闭本次测试启动的前端和后端进程。
## 不在本次范围
- 不修改客户号与客户内码映射流程。
- 不改变模型调用协议。
- 不把业务种类作为模型入参。
- 不新增历史合同落库明细表。
- 不保存完整历史合同记录,只保存用户选择后的历史贷款利率。