diff --git a/.gitignore b/.gitignore index 51f3bb8..2be6f5e 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,6 @@ nbdist/ !*/build/*.xml logs/ +.playwright-cli/ +ruoyi-ui/tests +*/src/test \ No newline at end of file diff --git a/doc/2026-04-15-Breadcrumb重复key修复前端实施记录.md b/doc/2026-04-15-Breadcrumb重复key修复前端实施记录.md new file mode 100644 index 0000000..3d159ee --- /dev/null +++ b/doc/2026-04-15-Breadcrumb重复key修复前端实施记录.md @@ -0,0 +1,90 @@ +# Breadcrumb 重复 key 修复前端实施记录 + +## 1. 实际改动内容 + +### 1.1 修复 Breadcrumb 重复 key 告警 + +修改文件: + +- `ruoyi-ui/src/components/Breadcrumb/index.vue` +- `ruoyi-ui/src/components/Breadcrumb/utils.js` + +改动内容: + +- 将 Breadcrumb 列表项的 `key` 生成逻辑从直接使用 `item.path` 调整为统一调用 `buildBreadcrumbItemKey` +- 新增 `buildBreadcrumbItemKey(item, index)` 工具方法,使用 `path + title + index` 组合生成稳定且唯一的 key +- 保持现有面包屑展示逻辑不变,不调整路由结构、不修改首页与当前页的展示顺序 + +根因说明: + +- 当前项目的 Breadcrumb 会在非首页场景外额外插入一个 `首页` 面包屑,路径固定为 `'/index'` +- 当当前页面本身也对应 `'/index'` 时,原逻辑使用 `item.path` 作为 `transition-group` 的 key,会同时生成两个 `'/index'` +- Vue 因此抛出 `Duplicate keys detected: '/index'` + +### 1.2 增加最小回归测试 + +修改文件: + +- `ruoyi-ui/tests/breadcrumb-duplicate-key.test.js` + +改动内容: + +- 新增最小 Node 断言脚本 +- 校验当两个 Breadcrumb 条目 path 同为 `'/index'` 时,生成的 key 仍然唯一 +- 锁定本次问题,避免后续调整 Breadcrumb 时再次引入相同告警 + +## 2. 验证结果 + +### 2.1 Node 版本 + +项目中未提供 `.nvmrc`,因此未能直接执行 `nvm use` 自动切换。 + +实际使用版本: + +- `nvm use 14.21.3` + +### 2.2 测试命令 + +已执行: + +- `cd ruoyi-ui && source ~/.nvm/nvm.sh && nvm use 14.21.3 >/dev/null && node tests/breadcrumb-duplicate-key.test.js` + +结果: + +- 测试通过 +- 输出 `breadcrumb duplicate key assertions passed` + +### 2.3 构建命令 + +已执行: + +- `cd ruoyi-ui && source ~/.nvm/nvm.sh && nvm use 14.21.3 >/dev/null && npm run build:prod` + +结果: + +- 构建成功 +- 输出 `DONE Build complete. The dist directory is ready to be deployed.` + +### 2.4 构建告警 + +存在 webpack 资源体积告警: + +- `asset size limit` +- `entrypoint size limit` + +说明: + +- 这些是现有项目静态资源体积告警 +- 本次 Breadcrumb 修复未引入新的构建错误或新的语法告警 + +## 3. 影响范围 + +- 仅涉及前端 Breadcrumb 组件 +- 未修改后端代码 +- 未修改贷款定价业务字段逻辑 + +## 4. 当前结论 + +- `Duplicate keys detected: '/index'` 的 Breadcrumb 告警已修复 +- 修复方式限定在组件 key 生成逻辑,属于最短路径处理 +- 前端回归测试与生产构建均已通过 diff --git a/doc/2026-04-15-上虞对公展示指标对齐前端实施计划.md b/doc/2026-04-15-上虞对公展示指标对齐前端实施计划.md new file mode 100644 index 0000000..041cb85 --- /dev/null +++ b/doc/2026-04-15-上虞对公展示指标对齐前端实施计划.md @@ -0,0 +1,26 @@ +# 2026-04-15 上虞对公展示指标对齐前端实施计划 + +## 改动内容 +- 对齐 [CorporateCreateDialog.vue](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue) 的对公新增弹窗: + - 新增 `repayMethod` + - `loanTerm` 改为 `1-6` 年下拉 + - `collType` 改为 `一类/二类/三类/四类` + - 对外提交字段改为 `isTradeBuildEnt` + - `isGreenLoan`、`isTradeBuildEnt`、`collThirdParty` 统一提交 `0/1` + - 移除 `isAgriGuar`、`isTechEnt` +- 对齐 [CorporateWorkflowDetail.vue](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue) 的流程详情录入字段展示: + - 新增 `还款方式` + - `贷款期限` 改为 `借款期限` + - 保留 `绿色贷款`、`贸易和建筑业企业`、`抵质押类型`、`抵质押物是否三方所有` + - 移除 `省农担担保贷款`、`科技型企业` +- 对齐 [ModelOutputDisplay.vue](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue) 的企业模型输出展示口径: + - 展示 `repayMethod`、`isTradeBuildEnt` + - 不再展示 `省农担担保贷款`、`科技型企业` +- 新增/更新前端静态断言: + - [corporate-create-input-params.test.js](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-ui/tests/corporate-create-input-params.test.js) + - [corporate-display-fields.test.js](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-ui/tests/corporate-display-fields.test.js) + +## 验证记录 +- `source ~/.nvm/nvm.sh && nvm use 14 >/dev/null && node tests/corporate-create-input-params.test.js` +- `source ~/.nvm/nvm.sh && nvm use 14 >/dev/null && node tests/corporate-display-fields.test.js` +- `source ~/.nvm/nvm.sh && nvm use 14 >/dev/null && npm run build:prod` diff --git a/doc/2026-04-15-上虞对公展示指标对齐后端实施计划.md b/doc/2026-04-15-上虞对公展示指标对齐后端实施计划.md new file mode 100644 index 0000000..0884d83 --- /dev/null +++ b/doc/2026-04-15-上虞对公展示指标对齐后端实施计划.md @@ -0,0 +1,39 @@ +# 2026-04-15 上虞对公展示指标对齐后端实施计划 + +## 改动内容 +- 对齐对公创建接口 DTO 与模型调用 DTO: + - [CorporateLoanPricingCreateDTO.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java) + - [ModelInvokeDTO.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java) + - 新增 `repayMethod` + - 对外字段改为 `isTradeBuildEnt` + - `loanTerm` 校验为 `1-6` + - `collType` 校验为 `一类/二类/三类/四类` +- 对齐流程实体、详情出参和模型输出镜像: + - [LoanPricingWorkflow.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java) + - [ModelCorpOutputFields.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java) + - [LoanPricingConverter.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java) + - [LoanPricingModelService.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java) + - [LoanPricingWorkflowServiceImpl.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java) + - 内部继续复用 `isTradeConstruction` 落库,外部统一返回 `isTradeBuildEnt` + - `isAgriGuar`、`isTechEnt` 从对外 JSON 隐藏 + - 企业模型输出补充 `repayMethod`、`isTradeBuildEnt` 展示镜像 +- 对齐 mock 与 SQL 资产: + - [corp_output.json](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/main/resources/data/corp_output.json) + - [loan_pricing_workflow.sql](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/sql/loan_pricing_workflow.sql) + - [loan_pricing_schema_20260328.sql](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/sql/loan_pricing_schema_20260328.sql) + - [loan_pricing_prod_init_20260331.sql](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/sql/loan_pricing_prod_init_20260331.sql) + - [loan_pricing_required_data_20260328.sql](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/sql/loan_pricing_required_data_20260328.sql) + - [loan_pricing_alter_20260415_repay_method.sql](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/sql/loan_pricing_alter_20260415_repay_method.sql) + - [test_corporate_create.http](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/test_api/test_corporate_create.http) + - [test_corporate_create.sh](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/test_api/test_corporate_create.sh) + - `loan_pricing_workflow` 增加 `repay_method` + - mock 数据和接口样例统一为 Excel 字段名与 `0/1` 口径 + - 补充独立增量 SQL,便于其他环境按最小影响同步结构 +- 新增/更新后端定向单测: + - [LoanPricingModelServiceCorporateParamsTest.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceCorporateParamsTest.java) + - [LoanPricingModelServiceTest.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java) + - [LoanPricingWorkflowServiceImplTest.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java) + - [LoanPricingConverterTest.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/util/LoanPricingConverterTest.java) + +## 验证记录 +- `mvn -pl ruoyi-loan-pricing -am -Dtest=LoanPricingModelServiceCorporateParamsTest,LoanPricingModelServiceTest,LoanPricingWorkflowServiceImplTest,LoanPricingConverterTest -Dsurefire.failIfNoSpecifiedTests=false test` diff --git a/doc/2026-04-15-审计字段自动填充后端实施记录.md b/doc/2026-04-15-审计字段自动填充后端实施记录.md new file mode 100644 index 0000000..b7c6612 --- /dev/null +++ b/doc/2026-04-15-审计字段自动填充后端实施记录.md @@ -0,0 +1,22 @@ +# 2026-04-15 审计字段自动填充后端实施记录 + +## 背景 + +- 贷款定价流程实体已经声明了 MyBatis-Plus 的 `FieldFill`,但当前分支缺少迁移源分支中的统一审计填充处理器。 +- 导致 `insert` 和 `updateById` 执行时,`createBy`、`createTime`、`updateBy`、`updateTime` 不会自动写入或刷新。 + +## 本次改动 + +- 新增 [MyMetaHandler.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-framework/src/main/java/com/ruoyi/framework/config/handler/MyMetaHandler.java),恢复与迁移源分支一致的统一审计填充逻辑。 +- 审计人格式保持与源分支一致,统一写入 `昵称-用户名`。 +- 新增 [MyMetaHandlerTest.java](/Users/wkc/Desktop/loan-pricing/loan-pricing-jdk-1.8/ruoyi-framework/src/test/java/com/ruoyi/framework/config/handler/MyMetaHandlerTest.java),覆盖插入填充与更新填充两个核心场景。 + +## 验证结果 + +- 执行 `mvn -pl ruoyi-framework -am -Dtest=MyMetaHandlerTest -Dsurefire.failIfNoSpecifiedTests=false test`,通过。 +- 执行 `mvn -pl ruoyi-loan-pricing -am -Dtest=MyMetaHandlerTest,LoanPricingWorkflowServiceImplTest,LoanPricingModelServiceTest,LoanPricingModelServiceCorporateParamsTest,LoanPricingModelServicePersonalParamsTest -Dsurefire.failIfNoSpecifiedTests=false test`,通过。 + +## 影响说明 + +- 所有使用 MyBatis-Plus 自动填充并声明对应字段的实体,在当前登录上下文下执行新增和更新时,都会自动维护审计字段。 +- 本次未改动贷款定价业务入参、SQL 结构和前端页面行为。 diff --git a/doc/2026-04-15-对公流程详情测算结果与风险分析分组调整前端实施记录.md b/doc/2026-04-15-对公流程详情测算结果与风险分析分组调整前端实施记录.md new file mode 100644 index 0000000..03552b5 --- /dev/null +++ b/doc/2026-04-15-对公流程详情测算结果与风险分析分组调整前端实施记录.md @@ -0,0 +1,24 @@ +# 对公流程详情测算结果与风险分析分组调整前端实施记录 + +## 变更日期 +- 2026-04-15 + +## 变更范围 +- 前端页面:`ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue` +- 前端校验:`ruoyi-ui/tests/corporate-create-input-params.test.js` +- 前端校验:`ruoyi-ui/tests/corporate-display-fields.test.js` + +## 实施内容 +- 将对公流程详情“模型输出”卡片中的“测算结果”从原“风险度与测算结果”合并分组中拆出。 +- 按页面要求将对公模型输出分组顺序调整为“基本信息 → 测算结果 → 忠诚度分析 → 贡献度分析 → 关联度分析 → 风险分析”。 +- 保留“风险分析”在模型输出卡片末尾,仅调整展示分组,不修改接口字段、父组件传参和格式化逻辑。 +- 补充前端断言,校验对公模型输出存在独立“测算结果”“风险分析”标题,且不再保留“风险度与测算结果”合并标题。 + +## 影响说明 +- 本次仅涉及前端详情页展示层,不涉及后端接口、数据库脚本和模型测算逻辑。 +- 对公流程详情页中,用户可在基本信息后直接查看测算结果,风险分析独立展示且位于模型输出末尾。 + +## 验证结果 +- 执行 `node ruoyi-ui/tests/corporate-create-input-params.test.js`,断言通过。 +- 执行 `node ruoyi-ui/tests/corporate-display-fields.test.js`,断言通过。 +- 执行 `cd ruoyi-ui && nvm use 14.21.3 && npm run build:prod`,前端生产构建通过。 diff --git a/doc/2026-04-15-开发库补列SQL落盘实施记录.md b/doc/2026-04-15-开发库补列SQL落盘实施记录.md new file mode 100644 index 0000000..be0dcf8 --- /dev/null +++ b/doc/2026-04-15-开发库补列SQL落盘实施记录.md @@ -0,0 +1,16 @@ +# 2026-04-15 开发库补列 SQL 落盘实施记录 + +## 修改内容 +- 将开发库已执行的对公字段补列 SQL 整理并保存到 `sql/loan_pricing_alter_20260415_repay_method.sql`。 +- 在原有 `loan_pricing_workflow.repay_method` 基础上,补充 `model_corp_output_fields` 的以下字段变更语句: + - `repay_method` + - `is_trade_build_ent` + - `loan_rate_history` + - `min_rate_product` + - `smooth_range` + - `final_calculate_rate` + - `reference_rate` + +## 结果 +- 现有 SQL 文件已可直接用于同步开发库本次字段补齐变更。 +- 文件内容与本次实际执行到开发库的语句保持一致。 diff --git a/doc/~$上虞对公利率测算_上传字段与展示字段 .xlsx b/doc/~$上虞对公利率测算_上传字段与展示字段 .xlsx new file mode 100644 index 0000000..3c3a794 Binary files /dev/null and b/doc/~$上虞对公利率测算_上传字段与展示字段 .xlsx differ diff --git a/doc/上虞对公利率测算_上传字段与展示字段 .xlsx b/doc/上虞对公利率测算_上传字段与展示字段 .xlsx new file mode 100644 index 0000000..679fcd9 Binary files /dev/null and b/doc/上虞对公利率测算_上传字段与展示字段 .xlsx differ diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/handler/MyMetaHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/handler/MyMetaHandler.java new file mode 100644 index 0000000..29ac851 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/handler/MyMetaHandler.java @@ -0,0 +1,34 @@ +package com.ruoyi.framework.config.handler; + +import java.util.Date; + +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.ruoyi.common.utils.SecurityUtils; + +/** + * 实体类自动配置创建日期和更新日期 + */ +@Component +public class MyMetaHandler implements MetaObjectHandler +{ + @Override + public void insertFill(MetaObject metaObject) + { + String auditUser = SecurityUtils.getLoginUser().getUser().getNickName() + '-' + SecurityUtils.getUsername(); + this.setFieldValByName("createBy", auditUser, metaObject); + this.setFieldValByName("createTime", new Date(), metaObject); + this.setFieldValByName("updateBy", auditUser, metaObject); + this.setFieldValByName("updateTime", new Date(), metaObject); + } + + @Override + public void updateFill(MetaObject metaObject) + { + String auditUser = SecurityUtils.getLoginUser().getUser().getNickName() + '-' + SecurityUtils.getUsername(); + this.setFieldValByName("updateBy", auditUser, metaObject); + this.setFieldValByName("updateTime", new Date(), metaObject); + } +} diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java index 2675651..6ea5326 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java @@ -19,12 +19,18 @@ public class CorporateLoanPricingCreateDTO implements Serializable { @NotBlank(message = "客户内码不能为空") private String custIsn; + private String custType; + private String custName; private String idType; private String idNum; + @NotBlank(message = "还款方式不能为空") + @Pattern(regexp = "^(分期|不分期)$", message = "还款方式必须是:分期、不分期之一") + private String repayMethod; + @NotBlank(message = "担保方式不能为空") @Pattern(regexp = "^(信用|保证|抵押|质押)$", message = "担保方式必须是:信用、保证、抵押、质押之一") private String guarType; @@ -32,16 +38,16 @@ public class CorporateLoanPricingCreateDTO implements Serializable { @NotBlank(message = "申请金额不能为空") private String applyAmt; + @NotBlank(message = "借款期限不能为空") + @Pattern(regexp = "^[1-6]$", message = "借款期限必须是 1 到 6 年") private String loanTerm; - private String isAgriGuar; - private String isGreenLoan; - private String isTechEnt; - - private String isTradeConstruction; + private String isTradeBuildEnt; + @NotBlank(message = "抵质押类型不能为空") + @Pattern(regexp = "^(一类|二类|三类|四类)$", message = "抵质押类型必须是:一类、二类、三类、四类之一") private String collType; private String collThirdParty; diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java index d65bbfb..ac2a94f 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java @@ -43,6 +43,12 @@ public class ModelInvokeDTO { */ private String guarType; + /** + * 还款方式(必填) + * 可选值:分期/不分期 + */ + private String repayMethod; + /** * 中间业务_个人_快捷支付(非必填) * 可选值:true/false @@ -103,6 +109,18 @@ public class ModelInvokeDTO { */ private String isAgriGuar; + /** + * 绿色贷款(非必填) + * 可选值:0/1 + */ + private String isGreenLoan; + + /** + * 贸易和建筑业企业(非必填) + * 可选值:0/1 + */ + private String isTradeBuildEnt; + /** * 是否纳税信用等级A级(非必填) * 可选值:true/false @@ -137,7 +155,7 @@ public class ModelInvokeDTO { /** * 抵质押类型(非必填) - * 可选值:一类/二类/三类 + * 可选值:一类/二类/三类/四类 */ private String collType; diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java index f64a162..3c82e5f 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java @@ -1,6 +1,7 @@ package com.ruoyi.loanpricing.domain.entity; import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -48,6 +49,9 @@ public class LoanPricingWorkflow implements Serializable @NotBlank(message = "担保方式不能为空") private String guarType; + /** 还款方式: 分期/不分期 */ + private String repayMethod; + /** 中间业务_个人_快捷支付: true/false */ private String midPerQuickPay; @@ -65,7 +69,7 @@ public class LoanPricingWorkflow implements Serializable private String applyAmt; /** - * 贷款期限 + * 借款期限(年) */ private String loanTerm; @@ -79,13 +83,21 @@ public class LoanPricingWorkflow implements Serializable private String isManufacturing; /** 省农担担保贷款: true/false */ + @JsonIgnore private String isAgriGuar; /** * 贸易和建筑业企业标识: true/false */ + @JsonIgnore private String isTradeConstruction; + /** + * 贸易和建筑业企业标识: 0/1 + */ + @TableField(exist = false) + private String isTradeBuildEnt; + /** * 绿色贷款: true/false */ @@ -94,6 +106,7 @@ public class LoanPricingWorkflow implements Serializable /** * 科技型企业: true/false */ + @JsonIgnore private String isTechEnt; /** 是否纳税信用等级A级: true/false */ @@ -111,7 +124,7 @@ public class LoanPricingWorkflow implements Serializable /** 循环功能: true/false */ private String loanLoop; - /** 抵质押类型: 一线/一类/二类 */ + /** 抵质押类型: 一类/二类/三类/四类 */ private String collType; /** 抵质押物是否三方所有: true/false */ diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java index c7ec5ad..a5f234a 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; +import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import java.util.Date; @@ -31,6 +32,9 @@ public class ModelCorpOutputFields { private String idType; // 证件号码 private String idNum; + // 还款方式 + @TableField(exist = false) + private String repayMethod; // 基准利率 private String baseLoanRate; // 我行首贷客户 @@ -79,12 +83,14 @@ public class ModelCorpOutputFields { private String isCleanEnt; // 开立基本结算账户 private String hasSettleAcct; + // 贸易和建筑业企业 + @TableField(exist = false) + private String isTradeBuildEnt; // 省农担担保贷款 + @JsonIgnore private String isAgriGuar; // 绿色贷款 private String isGreenLoan; - // 科技型企业 - private String isTechEnt; // BP_企业客户类别 private String bpEntType; // TOTAL_BP_关联度 @@ -119,6 +125,16 @@ public class ModelCorpOutputFields { private String totalBp; // 测算利率 private String calculateRate; + // 历史利率 + private String loanRateHistory; + // 产品最低利率下限 + private String minRateProduct; + // 平滑幅度 + private String smoothRange; + // 最终测算利率 + private String finalCalculateRate; + // 参考利率 + private String referenceRate; @TableField(fill = FieldFill.INSERT) private Date createTime; diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java index c4b457e..93c8338 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java @@ -59,10 +59,15 @@ public class LoanPricingModelService { } ModelInvokeDTO modelInvokeDTO = new ModelInvokeDTO(); BeanUtils.copyProperties(loanPricingWorkflow, modelInvokeDTO); + modelInvokeDTO.setIsTradeBuildEnt(toZeroOne(loanPricingWorkflow.getIsTradeConstruction())); if ("个人".equals(loanPricingWorkflow.getCustType())) { normalizePersonalModelInvokeDTO(modelInvokeDTO); } + if ("企业".equals(loanPricingWorkflow.getCustType())) + { + normalizeCorporateModelInvokeDTO(modelInvokeDTO); + } JSONObject response = modelService.invokeModel(modelInvokeDTO); if (loanPricingWorkflow.getCustType().equals("个人")){ // 个人模型 @@ -94,6 +99,13 @@ public class LoanPricingModelService { modelInvokeDTO.setCollThirdParty(toZeroOne(modelInvokeDTO.getCollThirdParty())); } + private void normalizeCorporateModelInvokeDTO(ModelInvokeDTO modelInvokeDTO) + { + modelInvokeDTO.setIsGreenLoan(toZeroOne(modelInvokeDTO.getIsGreenLoan())); + modelInvokeDTO.setIsTradeBuildEnt(toZeroOne(modelInvokeDTO.getIsTradeBuildEnt())); + modelInvokeDTO.setCollThirdParty(toZeroOne(modelInvokeDTO.getCollThirdParty())); + } + private String toZeroOne(String value) { if ("true".equals(value) || "1".equals(value)) diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java index 6d80edb..e17838e 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java @@ -78,6 +78,8 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi { loanPricingWorkflow.setRunType("1"); } + loanPricingWorkflow.setCustType("企业".equals(loanPricingWorkflow.getCustType()) ? "企业" : loanPricingWorkflow.getCustType()); + loanPricingWorkflow.setIsTradeBuildEnt(loanPricingWorkflow.getIsTradeConstruction()); loanPricingWorkflow.setCustName(sensitiveFieldCryptoService.encrypt(loanPricingWorkflow.getCustName())); loanPricingWorkflow.setIdNum(sensitiveFieldCryptoService.encrypt(loanPricingWorkflow.getIdNum())); @@ -163,6 +165,7 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi String plainIdNum = sensitiveFieldCryptoService.decrypt(loanPricingWorkflow.getIdNum()); loanPricingWorkflow.setCustName(loanPricingSensitiveDisplayService.maskCustName(plainCustName)); loanPricingWorkflow.setIdNum(loanPricingSensitiveDisplayService.maskIdNum(plainIdNum)); + loanPricingWorkflow.setIsTradeBuildEnt(loanPricingWorkflow.getIsTradeConstruction()); loanPricingWorkflowVO.setLoanPricingWorkflow(loanPricingWorkflow); if (Objects.nonNull(loanPricingWorkflow.getModelOutputId())){ @@ -180,6 +183,8 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi if (Objects.nonNull(modelCorpOutputFields)) { maskModelCorpOutputBasicInfo(modelCorpOutputFields); + modelCorpOutputFields.setRepayMethod(loanPricingWorkflow.getRepayMethod()); + modelCorpOutputFields.setIsTradeBuildEnt(loanPricingWorkflow.getIsTradeBuildEnt()); loanPricingWorkflow.setLoanRate(modelCorpOutputFields.getCalculateRate()); } loanPricingWorkflowVO.setModelCorpOutputFields(modelCorpOutputFields); diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java index ca0715e..873f8aa 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java @@ -52,15 +52,15 @@ public class LoanPricingConverter { entity.setCustName(dto.getCustName()); entity.setIdType(dto.getIdType()); entity.setIdNum(dto.getIdNum()); + entity.setRepayMethod(dto.getRepayMethod()); entity.setGuarType(dto.getGuarType()); entity.setApplyAmt(dto.getApplyAmt()); entity.setCollType(dto.getCollType()); entity.setCollThirdParty(dto.getCollThirdParty()); // 映射企业特有字段 - entity.setIsAgriGuar(dto.getIsAgriGuar()); entity.setIsGreenLoan(dto.getIsGreenLoan()); - entity.setIsTechEnt(dto.getIsTechEnt()); - entity.setIsTradeConstruction(dto.getIsTradeConstruction()); + entity.setIsTradeConstruction(dto.getIsTradeBuildEnt()); + entity.setIsTradeBuildEnt(dto.getIsTradeBuildEnt()); entity.setLoanTerm(dto.getLoanTerm()); return entity; } diff --git a/ruoyi-loan-pricing/src/main/resources/data/corp_output.json b/ruoyi-loan-pricing/src/main/resources/data/corp_output.json index 5752edc..65e8f93 100644 --- a/ruoyi-loan-pricing/src/main/resources/data/corp_output.json +++ b/ruoyi-loan-pricing/src/main/resources/data/corp_output.json @@ -4,11 +4,12 @@ "tokenId": "17364055486305E7F4722M8IPFWNL8TOBEB", "mappingOutputFields": { "custIsn": "CUST20260121001", - "custType": "企业客户", - "guarType": "抵押担保", + "custType": "企业", + "guarType": "抵押", "custName": "北京智联科技有限公司", "idType": "营业执照", "idNum": "91110108MA00XXXXXX", + "repayMethod": "分期", "baseLoanRate": "3.45", "isFirstLoan": "N", "faithDay": "730", @@ -33,17 +34,16 @@ "bpPayroll": "4.1", "isCleanEnt": "Y", "hasSettleAcct": "Y", - "isAgriGuar": "N", - "isGreenLoan": "Y", - "isTechEnt": "Y", + "isGreenLoan": "1", + "isTradeBuildEnt": "0", "bpEntType": "7.5", "totoalBpRelevance": "9.2", - "loanTerm": "36", + "loanTerm": "6", "bpLoanTerm": "3.3", - "applyAmt": "5000000.00", + "applyAmt": "1000000.00", "bpLoanAmount": "5.8", - "collType": "房产抵押", - "collThirdParty": "N", + "collType": "四类", + "collThirdParty": "1", "bpCollateral": "4.5", "greyCust": "N", "prinOverdue": "N", @@ -65,4 +65,4 @@ "workflowVersion": 14, "callTime": 1736405548630, "status": 1 -} \ No newline at end of file +} diff --git a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java index e983273..31e3bf5 100644 --- a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java +++ b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java @@ -87,4 +87,30 @@ class LoanPricingModelServiceTest !Objects.equals("张三", entity.getCustName()) && !Objects.equals("110101199001011234", entity.getIdNum()))); } + + @Test + void shouldSendCorporateRepayMethodAndTradeBuildFlagToModel() + { + LoanPricingWorkflow workflow = new LoanPricingWorkflow(); + workflow.setId(3L); + workflow.setCustType("企业"); + workflow.setCustName("cipher-name"); + workflow.setIdNum("cipher-id"); + workflow.setRepayMethod("分期"); + workflow.setIsTradeConstruction("1"); + + JSONObject response = new JSONObject(); + response.put("calculateRate", "4.10"); + + when(loanPricingWorkflowMapper.selectById(3L)).thenReturn(workflow); + when(sensitiveFieldCryptoService.decrypt("cipher-name")).thenReturn("上虞测试企业"); + when(sensitiveFieldCryptoService.decrypt("cipher-id")).thenReturn("91330000123456789X"); + when(modelService.invokeModel(any())).thenReturn(response); + + loanPricingModelService.invokeModelAsync(3L); + + verify(modelService).invokeModel(argThat((ModelInvokeDTO dto) -> + Objects.equals("分期", dto.getRepayMethod()) + && Objects.equals("1", dto.getIsTradeBuildEnt()))); + } } diff --git a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java index 15e0bcc..29f4be1 100644 --- a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java +++ b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java @@ -253,4 +253,33 @@ class LoanPricingWorkflowServiceImplTest assertEquals("测试****公司", result.getModelCorpOutputFields().getCustName()); assertEquals("91*************00X", result.getModelCorpOutputFields().getIdNum()); } + + @Test + void shouldReturnCorporateDisplaySheetFieldsInWorkflowDetail() + { + LoanPricingWorkflow workflow = new LoanPricingWorkflow(); + workflow.setSerialNum("C20260415001"); + workflow.setCustType("企业"); + workflow.setCustName("cipher-name"); + workflow.setIdNum("cipher-id"); + workflow.setRepayMethod("分期"); + workflow.setIsTradeConstruction("1"); + workflow.setModelOutputId(23L); + + ModelCorpOutputFields corpOutputFields = new ModelCorpOutputFields(); + corpOutputFields.setCalculateRate("4.95"); + + when(loanPricingWorkflowMapper.selectOne(any())).thenReturn(workflow); + when(modelCorpOutputFieldsMapper.selectById(23L)).thenReturn(corpOutputFields); + when(sensitiveFieldCryptoService.decrypt("cipher-name")).thenReturn("上虞测试企业"); + when(sensitiveFieldCryptoService.decrypt("cipher-id")).thenReturn("91330000123456789X"); + when(loanPricingSensitiveDisplayService.maskCustName("上虞测试企业")).thenReturn("上虞***企业"); + when(loanPricingSensitiveDisplayService.maskIdNum("91330000123456789X")).thenReturn("91*************89X"); + + LoanPricingWorkflowVO result = loanPricingWorkflowService.selectLoanPricingBySerialNum("C20260415001"); + + assertEquals("分期", result.getModelCorpOutputFields().getRepayMethod()); + assertEquals("1", result.getModelCorpOutputFields().getIsTradeBuildEnt()); + assertEquals("4.95", result.getLoanPricingWorkflow().getLoanRate()); + } } diff --git a/ruoyi-ui/src/components/Breadcrumb/index.vue b/ruoyi-ui/src/components/Breadcrumb/index.vue index 84f4831..87e6b9e 100644 --- a/ruoyi-ui/src/components/Breadcrumb/index.vue +++ b/ruoyi-ui/src/components/Breadcrumb/index.vue @@ -1,7 +1,7 @@