# 上虞个人利率测算输入参数后端 Implementation Plan > **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 补齐个人创建 DTO、流程转换和模型调用参数,使个人模型请求完整覆盖 Excel 要求的输入字段。 **Architecture:** 维持现有“页面提交 -> DTO -> Workflow -> ModelInvokeDTO -> form-urlencoded 调用”的链路,只在个人创建与模型调用相关文件中补齐字段和转换规则。通过后端单元测试与真实接口联调覆盖必填、正常和分支场景。 **Tech Stack:** Spring Boot、MyBatis-Plus、Lombok、JUnit、Maven --- ## 后端模型输入参数确认 个人链路最终需要发给模型的 16 个参数如下: - `serialNum`:服务层自动生成 - `orgCode`:服务层默认值,当前代码为 `892000` - `runType`:服务层默认值 `1` - `custIsn`:页面输入透传 - `custType`:个人链路固定 `个人` - `custName`:页面输入,调用模型前解密后透传 - `idType`:页面输入透传 - `idNum`:页面输入,调用模型前解密后透传 - `guarType`:页面输入透传 - `applyAmt`:页面输入透传 - `loanPurpose`:页面输入透传 - `loanTerm`:页面输入透传 - `bizProof`:页面开关,调用模型前转 `0/1` - `loanLoop`:页面开关,调用模型前转 `0/1` - `collThirdParty`:页面开关,调用模型前转 `0/1` - `collType`:页面下拉透传 调用方式确认: - 参数载体:`ModelInvokeDTO` - 组装方式:`BeanUtils.copyProperties(loanPricingWorkflow, modelInvokeDTO)` - 请求格式:`application/x-www-form-urlencoded` - 发送入口:`ModelService#invokeModel` ## 文件结构 - Modify: [ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java](/Users/wkc/Desktop/loan-pricing/loan-pricing/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java) - 增加 `loanPurpose`、`loanTerm` - Modify: [ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java](/Users/wkc/Desktop/loan-pricing/loan-pricing/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java) - 将新增字段映射到 `LoanPricingWorkflow` - Modify: [ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java](/Users/wkc/Desktop/loan-pricing/loan-pricing/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java) - 增加 `loanTerm`、`loanLoop` - Modify: [ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java](/Users/wkc/Desktop/loan-pricing/loan-pricing/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java) - 在个人模型调用前规范化 `0/1` - Create: [ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServicePersonalParamsTest.java](/Users/wkc/Desktop/loan-pricing/loan-pricing/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServicePersonalParamsTest.java) - 覆盖字段存在与值转换 ### Task 1: 为新增字段补失败测试 **Files:** - Create: `ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServicePersonalParamsTest.java` - [ ] **Step 1: 编写字段与转换测试** ```java @Test void shouldContainLoanPurposeLoanTermAndLoanLoop() { assertThat(ModelInvokeDTO.class.getDeclaredField("loanTerm")).isNotNull(); assertThat(ModelInvokeDTO.class.getDeclaredField("loanLoop")).isNotNull(); } ``` ```java @Test void shouldConvertPersonalBooleanFlagsToZeroOne() { // 构造个人流程对象,断言模型请求中的 bizProof/loanLoop/collThirdParty 为 1/0 } ``` - [ ] **Step 2: 运行测试并确认先失败** Run: `mvn -pl ruoyi-loan-pricing -Dtest=LoanPricingModelServicePersonalParamsTest test` Expected: FAIL,提示字段不存在或转换逻辑未实现 - [ ] **Step 3: 保持测试只覆盖本次改动相关链路** ```java // 仅断言 PersonalLoanPricingCreateDTO / LoanPricingConverter / ModelInvokeDTO / LoanPricingModelService ``` - [ ] **Step 4: 增加最终模型请求参数断言** ```java // 断言 requestBody 包含 serialNum、orgCode、runType、custIsn、custType、custName、 // idType、idNum、guarType、applyAmt、loanPurpose、loanTerm、bizProof、 // loanLoop、collThirdParty、collType ``` - [ ] **Step 5: 再次运行测试确认失败原因稳定** Run: `mvn -pl ruoyi-loan-pricing -Dtest=LoanPricingModelServicePersonalParamsTest test` Expected: FAIL,失败点与新增字段缺失一致 - [ ] **Step 6: 提交** ```bash git add ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServicePersonalParamsTest.java git commit -m "新增个人测算输入参数后端测试" ``` ### Task 2: 补齐个人创建 DTO 与流程映射 **Files:** - Modify: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java` - Modify: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java` - [ ] **Step 1: 在个人 DTO 中增加 `loanPurpose`** ```java @NotBlank(message = "贷款用途不能为空") @Pattern(regexp = "^(consumer|business)$", message = "贷款用途必须是 consumer 或 business") private String loanPurpose; ``` - [ ] **Step 2: 在个人 DTO 中增加 `loanTerm`** ```java @NotBlank(message = "借款期限不能为空") private String loanTerm; ``` - [ ] **Step 3: 在转换器中映射新增字段** ```java entity.setLoanPurpose(dto.getLoanPurpose()); entity.setLoanTerm(dto.getLoanTerm()); ``` - [ ] **Step 4: 运行相关测试确认 DTO 与映射通过** Run: `mvn -pl ruoyi-loan-pricing -Dtest=LoanPricingModelServicePersonalParamsTest test` Expected: 仍可能 FAIL,但失败点已推进到模型调用层 - [ ] **Step 5: 提交** ```bash git add ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java git commit -m "补齐个人测算创建参数字段" ``` ### Task 3: 补齐模型调用 DTO 与个人参数规范化 **Files:** - Modify: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java` - Modify: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java` - [ ] **Step 1: 在模型调用 DTO 中增加缺失字段** ```java private String loanTerm; private String loanLoop; ``` - [ ] **Step 2: 在个人模型调用前做 `0/1` 转换** ```java if ("个人".equals(loanPricingWorkflow.getCustType())) { modelInvokeDTO.setBizProof(toZeroOne(modelInvokeDTO.getBizProof())); modelInvokeDTO.setLoanLoop(toZeroOne(modelInvokeDTO.getLoanLoop())); modelInvokeDTO.setCollThirdParty(toZeroOne(modelInvokeDTO.getCollThirdParty())); } ``` - [ ] **Step 3: 抽出最小辅助方法,避免散落重复逻辑** ```java private String toZeroOne(String value) { if ("true".equals(value) || "1".equals(value)) return "1"; if ("false".equals(value) || "0".equals(value)) return "0"; return value; } ``` - [ ] **Step 4: 运行测试确认通过** Run: `mvn -pl ruoyi-loan-pricing -Dtest=LoanPricingModelServicePersonalParamsTest test` Expected: PASS - [ ] **Step 5: 提交** ```bash git add ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java git commit -m "规范个人测算模型调用参数" ``` ### Task 4: 后端联调与接口验证 **Files:** - Verify: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java` - Verify: `ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java` - [ ] **Step 1: 重新编译并重启后端进程** Run: `mvn -pl ruoyi-admin -am package -DskipTests` Expected: 打包成功,随后重启运行中的后端服务使最新代码生效 - [ ] **Step 2: 验证正常场景** Run: 调用 `POST /loanPricing/workflow/create/personal` Expected: - 返回创建成功 - 请求体包含 `loanPurpose`、`loanTerm` - 模型请求中完整带出 16 个参数 - 其中 `bizProof`、`loanLoop`、`collThirdParty` 为 `0/1` - [ ] **Step 3: 验证必填缺失场景** Run: 缺少 `loanPurpose` 或 `loanTerm` 分别调用接口 Expected: 返回参数校验失败 - [ ] **Step 4: 验证分支场景** Run: 以不同开关组合调用接口 Expected: - `bizProof=true` -> 模型入参 `1` - `bizProof=false` -> 模型入参 `0` - `loanLoop=true/false` 与 `collThirdParty=true/false` 同理 - [ ] **Step 5: 验证结束后停止后端进程并提交** ```bash git add ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServicePersonalParamsTest.java git commit -m "完成个人测算输入参数后端联调" ```