# 业务种类与历史贷款利率实施记录

## 后端实施

- 个人/企业利率定价创建 DTO 新增 `businessType`、`loanRateHistory` 字段。
- 利率定价流程实体新增 `businessType`、`loanRateHistory` 持久化字段。
- 模型调用 DTO 新增 `loanRateHistory` 字段，保持不新增 `businessType`。
- 个人/企业创建转换器已映射业务种类和历史贷款利率。
- 流程创建服务新增业务种类校验：必填，限定 `新客`、`存量新增`、`存量转贷`；`存量转贷` 必须选择历史贷款合同。
- 新增历史贷款合同代理服务 `LoanRateHistoryService` 和接口 `GET /loanPricing/workflow/history-contract`。
- 本地 mock 新增 `GET /rate/pricing/mock/history-contract`，覆盖正常、无历史合同、历史利率为空场景。
- 本地 mock 客户号映射新增固定测试客户号 `HISTORY_EMPTY` 和 `HISTORY_EMPTY_RATE`。
- dev/uat/pro 配置新增 `loan-rate-history.url`。
- SQL 迁移和初始化脚本新增 `business_type`、`loan_rate_history` 字段。

## 后端验证

- 首次按计划运行 `mvn -pl ruoyi-loan-pricing -am -Dtest=... test` 时，`ruoyi-common` 因未匹配测试触发 Surefire 失败；后续按本仓库多模块测试习惯补充 `-Dsurefire.failIfNoSpecifiedTests=false`。
- 当前 Oracle JDK 21 环境下 Mockito inline mock maker 需要预加载 Byte Buddy agent，验证命令使用 `JAVA_TOOL_OPTIONS=-javaagent:/Users/wkc/.m2/repository/net/bytebuddy/byte-buddy-agent/1.17.8/byte-buddy-agent-1.17.8.jar`。
- 已执行并通过：
  - `mvn -pl ruoyi-loan-pricing -am -Dtest=LoanPricingModelServicePersonalParamsTest,HistoryLoanContractVOTest -Dsurefire.failIfNoSpecifiedTests=false test`
  - `mvn -pl ruoyi-loan-pricing -am -Dtest=LoanPricingModelServicePersonalParamsTest,LoanPricingModelServiceTest,LoanPricingWorkflowServiceImplTest -Dsurefire.failIfNoSpecifiedTests=false test`
  - `mvn -pl ruoyi-loan-pricing -am -Dtest=LoanRateHistoryServiceTest,LoanRatePricingMockControllerHistoryContractTest,LoanPricingWorkflowControllerHistoryContractTest,LoanRatePricingMockControllerCustomerMapTest -Dsurefire.failIfNoSpecifiedTests=false test`
  - `mvn -pl ruoyi-loan-pricing -am -Dtest=LoanPricingModelServicePersonalParamsTest,LoanPricingModelServiceTest -Dsurefire.failIfNoSpecifiedTests=false test`
  - `mvn -pl ruoyi-loan-pricing -am -Dtest=HistoryLoanContractVOTest,LoanRateHistoryServiceTest,LoanPricingWorkflowControllerHistoryContractTest,LoanRatePricingMockControllerHistoryContractTest,LoanPricingWorkflowServiceImplTest,LoanPricingModelServicePersonalParamsTest,LoanPricingModelServiceTest -Dsurefire.failIfNoSpecifiedTests=false test`
  - `mvn -pl ruoyi-loan-pricing -am -Dtest=LoanPricingCustomerMapServiceTest,LoanPricingWorkflowControllerCustomerMapTest,LoanRatePricingMockControllerCustomerMapTest,CustomerMapRecordVOTest -Dsurefire.failIfNoSpecifiedTests=false test`

## 前端实施

- `workflow.js` 新增 `queryHistoryContracts(custIsn)`，请求 `GET /loanPricing/workflow/history-contract`。
- 新增共享组件 `HistoryContractSelector.vue`，按单选方式展示历史贷款合同，字段包含客户内码、历史贷款合同号、历史贷款担保方式、历史贷款产品代码、历史贷款利率、历史贷款金额、历史贷款签订时间。
- 个人/企业新增弹窗新增 `业务种类`，选项为 `新客`、`存量新增`、`存量转贷`。
- 当业务种类为 `存量转贷` 时，按客户内码查询历史贷款合同并弹出单选弹窗；未选合同、无历史合同、历史贷款利率为空时禁止提交。
- 非 `存量转贷` 创建时不提交 `loanRateHistory`。
- 个人/企业详情页在业务信息中展示 `业务种类`、`历史贷款利率`。

## 前端静态验证

- 已执行并通过：
  - `zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:business-type-history-rate'`
  - `zsh -lic 'nvm use 14.21.3 >/dev/null && node ruoyi-ui/tests/customer-map-selection.test.js && npm --prefix ruoyi-ui run test:personal-create-input-params && npm --prefix ruoyi-ui run test:corporate-create-input-params'`
  - `zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run build:prod'`
- `build:prod` 通过，仍存在项目原有资源体积 warning。

## 数据库变更验证

- 已按 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;`
- 已回查字段存在：
  - `business_type varchar(20)`
  - `loan_rate_history varchar(100)`

## 真实页面验证

- 后端已通过 `bin/restart_java_backend.sh restart` 重启并加载最新代码。
- 前端已通过 `zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run dev -- --port 8080'` 启动。
- 使用 in-app browser 打开真实页面 `http://localhost:8080/index`，未使用 prototype 页面。
- 已验证个人 `存量转贷`：
  - 测试客户内码 `81000922431`
  - 历史合同弹窗展示 7 个字段并支持单选。
  - 选择合同后提交成功。
  - 详情页展示 `业务种类=存量转贷`、`历史贷款利率=3.65`。
- 已验证企业 `存量转贷`：
  - 测试客户内码 `81000329003`
  - 历史合同弹窗展示 7 个字段并支持单选。
  - 选择合同后提交成功。
  - 详情页展示 `业务种类=存量转贷`、`历史贷款利率=3.65`。
- 已验证个人 `新客`：
  - 测试客户内码 `81000525694`
  - 不弹出历史贷款合同选择。
  - 提交成功。
  - 详情页展示 `业务种类=新客`，历史贷款利率为空值展示。
- 已验证企业 `存量新增`：
  - 测试客户内码 `81000769824`
  - 不弹出历史贷款合同选择。
  - 提交成功。
  - 详情页展示 `业务种类=存量新增`，历史贷款利率为空值展示。
- 已验证拦截场景：
  - `存量转贷` 打开历史合同弹窗后未选择合同，提示 `请选择历史贷款合同`，禁止提交。
  - 固定客户号 `HISTORY_EMPTY` 映射到 `EMPTY_HISTORY`，历史合同查询为空，提示 `未查询到历史贷款合同`，提交时校验 `请选择历史贷款合同`。
  - 固定客户号 `HISTORY_EMPTY_RATE` 映射到 `EMPTY_RATE`，历史合同存在但历史贷款利率为空，选择时提示 `历史贷款利率不能为空`，提交时仍校验 `请选择历史贷款合同`。
- 已回查数据库：
  - `81000922431 / 个人 / 存量转贷 / 3.65 / 321000`
  - `81000329003 / 企业 / 存量转贷 / 3.65 / 654000`
  - `81000525694 / 个人 / 新客 / NULL / 321000`
  - `81000769824 / 企业 / 存量新增 / NULL / 654000`

## 进程清理

- 页面验证结束后已停止本次测试启动的前端和后端进程。
- 已确认 `8080`、`63310` 端口无监听进程。
