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 a160c00..7dcf960 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 @@ -125,7 +125,7 @@ public class ModelInvokeDTO { /** * 贷款用途(非必填) - * 可选值:consumer/business + * 可选值:经营/消费 */ private String loanPurpose; diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java index 96c9923..220be1b 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/PersonalLoanPricingCreateDTO.java @@ -41,6 +41,11 @@ public class PersonalLoanPricingCreateDTO implements Serializable { @NotBlank(message = "申请金额不能为空") private String applyAmt; + @Schema(description = "贷款用途", requiredMode = Schema.RequiredMode.REQUIRED, example = "business", allowableValues = {"business", "consumer"}) + @NotBlank(message = "贷款用途不能为空") + @Pattern(regexp = "^(business|consumer)$", message = "贷款用途必须是:business、consumer之一") + private String loanPurpose; + @Schema(description = "业务种类", requiredMode = Schema.RequiredMode.REQUIRED, example = "存量转贷", allowableValues = {"新增", "存量新增", "存量转贷"}) @NotBlank(message = "业务种类不能为空") @Pattern(regexp = "^(新增|存量新增|存量转贷)$", message = "业务种类必须是:新增、存量新增、存量转贷之一") diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelRetailOutputFields.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelRetailOutputFields.java index 2fbbb5f..b3a337c 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelRetailOutputFields.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelRetailOutputFields.java @@ -159,12 +159,21 @@ public class ModelRetailOutputFields { // 本金逾期 private String prinOverdue; + // BP_本金逾期 + private String bpPrinOverdue; + // 利息逾期 private String interestOverdue; + // BP_利息逾期 + private String bpIinterestOverdue; + // 信用卡逾期 private String cardOverdue; + // BP_信用卡逾期 + private String bpCardOverdue; + // BP_灰名单与逾期 private String bpGreyOverdue; 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 31dccd4..ac5f4a3 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 @@ -102,11 +102,25 @@ public class LoanPricingModelService { private void normalizePersonalModelInvokeDTO(ModelInvokeDTO modelInvokeDTO) { + modelInvokeDTO.setLoanPurpose(toPersonalModelLoanPurpose(modelInvokeDTO.getLoanPurpose())); modelInvokeDTO.setBizProof(toZeroOne(modelInvokeDTO.getBizProof())); modelInvokeDTO.setLoanLoop(toZeroOne(modelInvokeDTO.getLoanLoop())); modelInvokeDTO.setCollThirdParty(toZeroOne(modelInvokeDTO.getCollThirdParty())); } + private String toPersonalModelLoanPurpose(String value) + { + if ("business".equals(value)) + { + return "经营"; + } + if ("consumer".equals(value)) + { + return "消费"; + } + return value; + } + private void normalizeCorporateModelInvokeDTO(ModelInvokeDTO modelInvokeDTO) { modelInvokeDTO.setCollThirdParty(toZeroOne(modelInvokeDTO.getCollThirdParty())); 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 b6f439e..1cf0689 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 @@ -242,6 +242,7 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi .set(LoanPricingWorkflow::getIdNum, editingWorkflow.getIdNum()) .set(LoanPricingWorkflow::getGuarType, editingWorkflow.getGuarType()) .set(LoanPricingWorkflow::getApplyAmt, editingWorkflow.getApplyAmt()) + .set(LoanPricingWorkflow::getLoanPurpose, editingWorkflow.getLoanPurpose()) .set(LoanPricingWorkflow::getBusinessType, editingWorkflow.getBusinessType()) .set(LoanPricingWorkflow::getLoanRateHistory, editingWorkflow.getLoanRateHistory()) .set(LoanPricingWorkflow::getCouponRate, editingWorkflow.getCouponRate()) 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 e05e2c1..167b3df 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 @@ -28,6 +28,7 @@ public class LoanPricingConverter { entity.setIdNum(dto.getIdNum()); entity.setGuarType(dto.getGuarType()); entity.setApplyAmt(dto.getApplyAmt()); + entity.setLoanPurpose(dto.getLoanPurpose()); entity.setBusinessType(dto.getBusinessType()); entity.setLoanRateHistory(dto.getLoanRateHistory()); entity.setCouponRate(dto.getCouponRate()); diff --git a/ruoyi-loan-pricing/src/main/resources/data/retail_output.json b/ruoyi-loan-pricing/src/main/resources/data/retail_output.json index d9a8af5..6991fa6 100644 --- a/ruoyi-loan-pricing/src/main/resources/data/retail_output.json +++ b/ruoyi-loan-pricing/src/main/resources/data/retail_output.json @@ -49,8 +49,11 @@ "greyCust": "否", "blackCust": "否", "prinOverdue": "否", + "bpPrinOverdue": "0", "interestOverdue": "否", + "bpIinterestOverdue": "0", "cardOverdue": "否", + "bpCardOverdue": "0", "bpGreyOverdue": "98", "totalBpRisk": "95", "totalBp": "350", diff --git a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/domain/entity/ModelRetailOutputFieldsTest.java b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/domain/entity/ModelRetailOutputFieldsTest.java index 1149931..0256a19 100644 --- a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/domain/entity/ModelRetailOutputFieldsTest.java +++ b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/domain/entity/ModelRetailOutputFieldsTest.java @@ -25,5 +25,8 @@ class ModelRetailOutputFieldsTest assertTrue(fieldNames.contains("greyBlackCust"), "缺少字段 greyBlackCust"); assertTrue(fieldNames.contains("blackCust"), "缺少字段 blackCust"); assertTrue(fieldNames.contains("branchBp"), "缺少字段 branchBp"); + assertTrue(fieldNames.contains("bpPrinOverdue"), "缺少字段 bpPrinOverdue"); + assertTrue(fieldNames.contains("bpIinterestOverdue"), "缺少字段 bpIinterestOverdue"); + assertTrue(fieldNames.contains("bpCardOverdue"), "缺少字段 bpCardOverdue"); } } diff --git a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServicePersonalParamsTest.java b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServicePersonalParamsTest.java index 8840287..7cb4b8e 100644 --- a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServicePersonalParamsTest.java +++ b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServicePersonalParamsTest.java @@ -18,8 +18,6 @@ import java.util.Objects; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.verify; @@ -44,27 +42,27 @@ class LoanPricingModelServicePersonalParamsTest { private LoanPricingModelService loanPricingModelService; @Test - void shouldRemoveLoanPurposeAndKeepPersonalModelFieldsInCreateDto() throws NoSuchFieldException { - assertThrows(NoSuchFieldException.class, - () -> PersonalLoanPricingCreateDTO.class.getDeclaredField("loanPurpose")); + void shouldContainLoanPurposeAndPersonalModelFieldsInCreateDto() throws NoSuchFieldException { + assertNotNull(PersonalLoanPricingCreateDTO.class.getDeclaredField("loanPurpose")); assertNotNull(PersonalLoanPricingCreateDTO.class.getDeclaredField("bizProof")); assertNotNull(PersonalLoanPricingCreateDTO.class.getDeclaredField("loanTerm")); } @Test - void shouldMapBizProofButNotLoanPurposeFromPersonalDto() { + void shouldMapLoanPurposeAndBizProofFromPersonalDto() { PersonalLoanPricingCreateDTO dto = new PersonalLoanPricingCreateDTO(); dto.setCustIsn("CUST001"); dto.setCustName("张三"); dto.setGuarType("信用"); dto.setApplyAmt("100000"); + dto.setLoanPurpose("business"); dto.setBusinessType("新增"); dto.setLoanTerm("3"); dto.setBizProof("1"); LoanPricingWorkflow workflow = LoanPricingConverter.toEntity(dto); - assertNull(workflow.getLoanPurpose()); + assertEquals("business", workflow.getLoanPurpose()); assertEquals("1", workflow.getBizProof()); assertEquals("3", workflow.getLoanTerm()); } @@ -89,6 +87,7 @@ class LoanPricingModelServicePersonalParamsTest { workflow.setIdNum("110101199001011234"); workflow.setGuarType("信用"); workflow.setApplyAmt("100000"); + workflow.setLoanPurpose("consumer"); workflow.setLoanTerm("3"); workflow.setBizProof("true"); workflow.setLoanLoop("false"); @@ -114,10 +113,27 @@ class LoanPricingModelServicePersonalParamsTest { && Objects.equals("110101199001011234", dto.getIdNum()) && Objects.equals("信用", dto.getGuarType()) && Objects.equals("100000", dto.getApplyAmt()) + && Objects.equals("消费", dto.getLoanPurpose()) && Objects.equals("3", dto.getLoanTerm()) && Objects.equals("1", dto.getBizProof()) && Objects.equals("0", dto.getLoanLoop()) && Objects.equals("1", dto.getCollThirdParty()) && Objects.equals("一类", dto.getCollType()))); } + + @Test + void shouldConvertBusinessLoanPurposeForPersonalModel() { + LoanPricingWorkflow workflow = new LoanPricingWorkflow(); + workflow.setId(2L); + workflow.setCustType("个人"); + workflow.setLoanPurpose("business"); + + when(loanPricingWorkflowMapper.selectById(2L)).thenReturn(workflow); + when(modelService.invokePersonalModel(any())).thenReturn(new ModelRetailOutputFields()); + + loanPricingModelService.invokeModelAsync(2L); + + verify(modelService).invokePersonalModel(argThat((ModelInvokeDTO dto) -> + Objects.equals("经营", dto.getLoanPurpose()))); + } } 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 6fe0012..56d355f 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 @@ -496,6 +496,7 @@ class LoanPricingWorkflowServiceImplTest dto.setIdNum("110101199001019999"); dto.setGuarType("抵押"); dto.setApplyAmt("200000"); + dto.setLoanPurpose("business"); dto.setBusinessType("新增"); dto.setLoanTerm("3"); dto.setLoanLoop("1"); @@ -510,6 +511,7 @@ class LoanPricingWorkflowServiceImplTest verify(loanPricingWorkflowMapper).update(any(), updateWrapperCaptor.capture()); String sqlSet = updateWrapperCaptor.getValue().getSqlSet(); assertTrue(sqlSet.contains("apply_amt")); + assertTrue(sqlSet.contains("loan_purpose")); assertTrue(sqlSet.contains("cust_name")); assertTrue(sqlSet.contains("id_num")); assertTrue(sqlSet.contains("biz_proof")); @@ -518,6 +520,7 @@ class LoanPricingWorkflowServiceImplTest assertTrue(updateWrapperCaptor.getValue().getParamNameValuePairs().containsValue("张三")); assertTrue(updateWrapperCaptor.getValue().getParamNameValuePairs().containsValue("110101199001019999")); assertTrue(updateWrapperCaptor.getValue().getParamNameValuePairs().containsValue("普通住宅、土地、厂房")); + assertTrue(updateWrapperCaptor.getValue().getParamNameValuePairs().containsValue("business")); assertTrue(updateWrapperCaptor.getValue().getParamNameValuePairs().containsValue("是")); assertTrue(updateWrapperCaptor.getValue().getParamNameValuePairs().containsValue("1")); verify(sensitiveFieldCryptoService, never()).encrypt(any()); diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue index 720ce46..687d849 100644 --- a/ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue @@ -41,7 +41,15 @@ 模型输出结果影响BP - 汇总
{{ item.label }}{{ item.value }}
+ + + 汇总 + + + + +
{{ item.label }}{{ item.value }}
+ {{ row.bpLabel }}:{{ row.bpValue }} @@ -55,8 +63,26 @@ 模型输出结果影响BP - 汇总
{{ item.label }}{{ item.value }}
- {{ row.bpLabel }}:{{ row.bpValue }} + + 汇总 +
+ {{ item.label }} + + + + {{ item.value }} +
+ + + + {{ row.bpValue }} + + @@ -172,6 +198,10 @@ export default { corpOutput: { type: Object, default: null + }, + guarType: { + type: String, + default: null } }, computed: { @@ -190,49 +220,46 @@ export default { this.resultItem('贷款年日均', this.retailOutput.loanAvg), this.resultItem('派生率', this.formatRate(this.retailOutput.derivationRate)) ]), - this.totalRow('TOTAL_BP_贡献度', this.retailOutput.totalBpContribution) + this.totalRow('TOTAL_BP_贡献度', this.retailOutput.totalBpContribution, '最高上限100BP') ] }, retailRelevanceRows() { return [ - this.groupedAnalysisRow([ - this.resultItem('中间业务_个人_信用卡', this.retailOutput.midPerCard), - this.resultItem('中间业务_个人_一码通', this.retailOutput.midPerPass), - this.resultItem('中间业务_个人_丰收互联', this.retailOutput.midPerHarvest), - this.resultItem('中间业务_个人_有效客户', this.retailOutput.midPerEffect), - this.resultItem('中间业务_个人_快捷支付', this.retailOutput.midPerQuickPay), - this.resultItem('中间业务_个人_电费代扣', this.retailOutput.midPerEleDdc), - this.resultItem('中间业务_个人_水费代扣', this.retailOutput.midPerWaterDdc), - this.resultItem('中间业务_个人_华数费代扣', this.retailOutput.midPerHuashuDdc), - this.resultItem('中间业务_个人_煤气费代扣', this.retailOutput.midPerGasDdc), - this.resultItem('中间业务_个人_市民卡', this.retailOutput.midPerCitizencard), - this.resultItem('中间业务_个人_理财业务', this.retailOutput.midPerFinMan), - this.resultItem('中间业务_个人_etc', this.retailOutput.midPerEtc) - ], 'BP_中间业务', this.retailOutput.bpMid), + this.middleBusinessRow('中间业务_个人_信用卡', this.retailOutput.midPerCard, '办理减5个BP,信用卡额度1万元及以上的再减10个BP'), + this.middleBusinessRow('中间业务_个人_一码通', this.retailOutput.midPerPass), + this.middleBusinessRow('中间业务_个人_丰收互联', this.retailOutput.midPerHarvest), + this.middleBusinessRow('中间业务_个人_有效客户', this.retailOutput.midPerEffect), + this.middleBusinessRow('中间业务_个人_快捷支付', this.retailOutput.midPerQuickPay), + this.middleBusinessRow('中间业务_个人_电费代扣', this.retailOutput.midPerEleDdc), + this.middleBusinessRow('中间业务_个人_水费代扣', this.retailOutput.midPerWaterDdc), + this.middleBusinessRow('中间业务_个人_华数费代扣', this.retailOutput.midPerHuashuDdc), + this.middleBusinessRow('中间业务_个人_煤气费代扣', this.retailOutput.midPerGasDdc), + this.middleBusinessRow('中间业务_个人_市民卡', this.retailOutput.midPerCitizencard), + this.middleBusinessRow('中间业务_个人_理财业务', this.retailOutput.midPerFinMan), + this.middleBusinessRow('中间业务_个人_etc', this.retailOutput.midPerEtc), + this.summaryRow('BP_中间业务', this.retailOutput.bpMid, '最高上限-30BP'), this.totalRow('TOTAL_BP_关联度', this.retailOutput.totalBpRelevance) ] }, retailRiskRows() { - return [ + const rows = [ this.analysisRow('申请金额', this.retailOutput.applyAmt, 'BP_贷款额度', this.retailOutput.bpLoanAmount), this.groupedAnalysisRow([ this.resultItem('贷款用途', this.formatLoanPurpose(this.retailOutput.loanPurpose)), this.resultItem('营业执照', this.formatBoolean(this.retailOutput.bizProof)) ], 'BP_贷款用途', this.retailOutput.bpLoanUse), - this.analysisRow('循环功能', this.formatBoolean(this.retailOutput.loanLoop), 'BP_循环功能', this.retailOutput.bpLoanLoop), - this.groupedAnalysisRow([ - this.resultItem('抵质押类型', this.retailOutput.collType), - this.resultItem('抵质押物三方所有', this.formatBoolean(this.retailOutput.collThirdParty)) - ], 'BP_抵押物', this.retailOutput.bpCollateral), - this.groupedAnalysisRow([ - this.resultItem('灰名单客户', this.formatBoolean(this.retailOutput.greyCust)), - this.resultItem('黑名单客户', this.formatBoolean(this.retailOutput.blackCust)), - this.resultItem('本金逾期', this.formatBoolean(this.retailOutput.prinOverdue)), - this.resultItem('利息逾期', this.formatBoolean(this.retailOutput.interestOverdue)), - this.resultItem('信用卡逾期', this.formatBoolean(this.retailOutput.cardOverdue)) - ], 'BP_灰名单与逾期', this.retailOutput.bpGreyOverdue), - this.totalRow('TOTAL_BP_风险度', this.retailOutput.totalBpRisk) + this.analysisRow('循环功能', this.formatBoolean(this.retailOutput.loanLoop), 'BP_循环功能', this.retailOutput.bpLoanLoop) ] + if (this.guarType === '抵押' || this.guarType === '质押') { + rows.push(this.analysisRow('抵押物第三方所有', this.formatBoolean(this.retailOutput.collThirdParty), 'BP_抵押物', this.retailOutput.bpCollateral)) + } + rows.push( + this.analysisRow('本金逾期', this.formatBoolean(this.retailOutput.prinOverdue), 'BP_本金逾期', this.retailOutput.bpPrinOverdue), + this.analysisRow('利息逾期', this.formatBoolean(this.retailOutput.interestOverdue), 'BP_利息逾期', this.retailOutput.bpIinterestOverdue), + this.analysisRow('信用卡逾期', this.formatBoolean(this.retailOutput.cardOverdue), 'BP_信用卡逾期', this.retailOutput.bpCardOverdue), + this.totalRow('TOTAL_BP_风险度', this.retailOutput.totalBpRisk) + ) + return rows }, corporateLoyaltyRows() { return [ @@ -296,8 +323,8 @@ export default { }, methods: { formatRate, - resultItem(label, value) { - return {label, value: this.formatOutputValue(value)} + resultItem(label, value, tooltip = null, showValue = true) { + return {label, value: this.formatOutputValue(value), tooltip, showValue} }, groupedAnalysisRow(results, bpLabel, bpValue, total = false, category = null) { return {results, bpLabel, bpValue: this.formatOutputValue(bpValue), total, category} @@ -305,8 +332,14 @@ export default { analysisRow(resultLabel, resultValue, bpLabel, bpValue) { return this.groupedAnalysisRow([this.resultItem(resultLabel, resultValue)], bpLabel, bpValue) }, - totalRow(bpLabel, bpValue) { - return {summary: true, bpLabel, bpValue: this.formatOutputValue(bpValue), total: true} + middleBusinessRow(resultLabel, bpValue, tooltip = null) { + return this.groupedAnalysisRow([this.resultItem(resultLabel, null, tooltip, false)], null, bpValue) + }, + summaryRow(bpLabel, bpValue, bpTooltip) { + return {summary: true, bpLabel, bpValue: this.formatOutputValue(bpValue), bpTooltip, total: false} + }, + totalRow(bpLabel, bpValue, summaryTooltip = null) { + return {summary: true, bpLabel, bpValue: this.formatOutputValue(bpValue), total: true, summaryTooltip} }, /** 格式化布尔值为中文 */ formatBoolean(value) { @@ -362,6 +395,14 @@ export default { color: #303133; } + .analysis-help { + margin-left: 4px; + color: #909399; + cursor: help; + font-size: 14px; + vertical-align: middle; + } + .output-analysis-table { width: 100%; table-layout: fixed; diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue index 165795c..e25133e 100644 --- a/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue @@ -52,6 +52,14 @@ + + + + + + + + @@ -242,6 +250,7 @@ export default { idNum: this.customerMap ? (this.customerMap.cust_id || '').substring(3) : undefined, guarType: undefined, applyAmt: undefined, + loanPurpose: undefined, loanTerm: undefined, businessType: undefined, loanRateHistory: undefined, @@ -274,6 +283,9 @@ export default { applyAmt: [ {required: true, validator: validateApplyAmt, trigger: "blur"} ], + loanPurpose: [ + {required: true, message: "请选择贷款用途", trigger: "change"} + ], loanTerm: [ {required: true, message: "请选择借款期限", trigger: "change"} ], @@ -397,6 +409,7 @@ export default { idNum: this.editData.idNum, guarType: this.editData.guarType, applyAmt: this.editData.applyAmt, + loanPurpose: this.editData.loanPurpose, loanTerm: this.editData.loanTerm, businessType: this.editData.businessType, loanRateHistory: this.editData.loanRateHistory, @@ -418,6 +431,7 @@ export default { idNum: this.customerMap ? (this.customerMap.cust_id || '').substring(3) : undefined, guarType: undefined, applyAmt: undefined, + loanPurpose: undefined, loanTerm: undefined, businessType: undefined, loanRateHistory: undefined, diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue index f83d923..aae4abc 100644 --- a/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/PersonalWorkflowDetail.vue @@ -57,6 +57,14 @@ {{ detailData.custName }} {{ detailData.idType }} {{ detailData.idNum }} + {{ + formatBoolean(retailOutput && retailOutput.greyCust) + }} + + {{ + formatBoolean(retailOutput && retailOutput.blackCust) + }} + {{ detailData.createTime }} {{ detailData.createBy }} @@ -95,6 +103,7 @@ diff --git a/ruoyi-ui/tests/personal-create-input-params.test.js b/ruoyi-ui/tests/personal-create-input-params.test.js index 398dc0c..fc47be3 100644 --- a/ruoyi-ui/tests/personal-create-input-params.test.js +++ b/ruoyi-ui/tests/personal-create-input-params.test.js @@ -19,10 +19,12 @@ assert( ) assert( - !personalCreateDialog.includes('label="贷款用途"') && - !personalCreateDialog.includes('prop="loanPurpose"') && - !personalCreateDialog.includes('loanPurpose:'), - '个人新增弹窗不应继续保留贷款用途字段' + personalCreateDialog.includes('label="贷款用途"') && + personalCreateDialog.includes('prop="loanPurpose"') && + personalCreateDialog.includes('loanPurpose: undefined') && + personalCreateDialog.includes('loanPurpose: this.editData.loanPurpose') && + personalCreateDialog.includes('请选择贷款用途'), + '个人新增弹窗缺少贷款用途、必填校验或编辑回显' ) assert( @@ -31,8 +33,9 @@ assert( ) assert( - !personalCreateDialog.includes("value=\"consumer\"") && !personalCreateDialog.includes("value=\"business\""), - '个人新增弹窗不应继续保留贷款用途选项' + personalCreateDialog.includes('label="经营" value="business"') && + personalCreateDialog.includes('label="消费" value="consumer"'), + '个人新增弹窗贷款用途选项或协议值不正确' ) assert( diff --git a/ruoyi-ui/tests/retail-display-fields.test.js b/ruoyi-ui/tests/retail-display-fields.test.js index 3306524..27c26ee 100644 --- a/ruoyi-ui/tests/retail-display-fields.test.js +++ b/ruoyi-ui/tests/retail-display-fields.test.js @@ -42,15 +42,22 @@ assert( '个人流程详情关键信息未展示产品最低利率下限' ) +assert( + personalDetail.includes(':guar-type="detailData.guarType"'), + '个人模型输出未使用流程担保方式控制抵押物行' +) + const requiredRetailFields = [ 'retailOutput.loanRateHistory', 'retailOutput.smoothRange', 'retailOutput.finalCalculateRate', 'retailOutput.referenceRate', - 'retailOutput.blackCust', 'retailOutput.branchBp', 'retailOutput.bpLoanUse', - 'retailOutput.midPerGasDdc' + 'retailOutput.midPerGasDdc', + 'retailOutput.bpPrinOverdue', + 'retailOutput.bpIinterestOverdue', + 'retailOutput.bpCardOverdue' ] requiredRetailFields.forEach((field) => { @@ -63,10 +70,18 @@ assert( ) assert( - detailCard.includes('label="客户名称"') - && !detailCard.includes('label="灰黑名单客户"') - && !detailCard.includes('retailOutput && retailOutput.greyBlackCust'), - '个人流程详情基本信息不应展示灰黑名单客户' + basicInfo.includes('label="灰名单客户"') + && basicInfo.includes('retailOutput && retailOutput.greyCust') + && basicInfo.includes('label="黑名单客户"') + && basicInfo.includes('retailOutput && retailOutput.blackCust'), + '个人流程详情基本信息缺少灰名单客户或黑名单客户' +) + +assert( + !modelOutput.includes("this.resultItem('灰名单客户', this.formatBoolean(this.retailOutput.greyCust))") + && !modelOutput.includes("this.resultItem('黑名单客户', this.formatBoolean(this.retailOutput.blackCust))") + && !modelOutput.includes("'BP_灰名单与逾期', this.retailOutput.bpGreyOverdue"), + '个人风险度不应继续展示灰黑客户或旧聚合BP' ) assert( diff --git a/sql/20260824-personal-workflow-optimization.sql b/sql/20260824-personal-workflow-optimization.sql new file mode 100644 index 0000000..6fcd50d --- /dev/null +++ b/sql/20260824-personal-workflow-optimization.sql @@ -0,0 +1,5 @@ +-- 2026-08-24 personal model output overdue BP fields +ALTER TABLE `model_retail_output_fields` + ADD COLUMN `bp_prin_overdue` varchar(100) DEFAULT NULL COMMENT 'BP_本金逾期' AFTER `prin_overdue`, + ADD COLUMN `bp_iinterest_overdue` varchar(100) DEFAULT NULL COMMENT 'BP_利息逾期' AFTER `interest_overdue`, + ADD COLUMN `bp_card_overdue` varchar(100) DEFAULT NULL COMMENT 'BP_信用卡逾期' AFTER `card_overdue`;