From 0d061155ed868a3006507ab1d10ee6b781a37684 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 21 Jan 2026 15:58:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 3 +- CLAUDE.md | 1 + .../src/main/resources/application-dev.yml | 4 +- .../ruoyi/common/utils/http/HttpUtils.java | 82 +++++++- .../config/handler/MyMetaHandler.java | 33 ++++ .../LoanPricingWorkflowController.java | 9 +- .../LoanRatePricingMockController.java | 55 ++++++ .../domain/dto/ModelInvokeDTO.java | 153 +++++++++++++++ .../{ => entity}/LoanPricingWorkflow.java | 13 +- .../domain/entity/ModelCorpOutputFields.java | 125 +++++++++++++ .../entity/ModelRetailOutputFields.java | 175 ++++++++++++++++++ .../domain/vo/LoanPricingWorkflowVO.java | 21 +++ .../mapper/LoanPricingWorkflowMapper.java | 5 +- .../mapper/ModelCorpOutputFieldsMapper.java | 15 ++ .../mapper/ModelRetailOutputFieldsMapper.java | 15 ++ .../service/ILoanPricingWorkflowService.java | 5 +- .../service/LoanPricingModelService.java | 69 +++++++ .../loanpricing/service/ModelService.java | 37 ++-- .../impl/LoanPricingWorkflowServiceImpl.java | 55 ++++-- .../src/main/resources/data/corp_output.json | 68 +++++++ .../main/resources/data/retail_output.json | 68 +++++++ .../components/WorkflowCreateDialog.vue | 2 +- sql/loan_pricing_workflow.sql | 3 +- sql/model_corp.sql | 59 ++++++ sql/model_retail.sql | 114 ++++++++++++ 25 files changed, 1134 insertions(+), 55 deletions(-) create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/handler/MyMetaHandler.java create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanRatePricingMockController.java create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java rename ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/{ => entity}/LoanPricingWorkflow.java (90%) create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelRetailOutputFields.java create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/vo/LoanPricingWorkflowVO.java create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/ModelCorpOutputFieldsMapper.java create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/ModelRetailOutputFieldsMapper.java create mode 100644 ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java create mode 100644 ruoyi-loan-pricing/src/main/resources/data/corp_output.json create mode 100644 ruoyi-loan-pricing/src/main/resources/data/retail_output.json create mode 100644 sql/model_corp.sql create mode 100644 sql/model_retail.sql diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 8ff1601..973268b 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -14,7 +14,8 @@ "Bash(powershell -Command:*)", "Bash(openspec archive add-loan-pricing-create:*)", "Bash(git add:*)", - "Bash(cd:*)" + "Bash(cd:*)", + "mcp__zai-mcp-server__extract_text_from_screenshot" ], "additionalDirectories": [ "d:\\利率定价\\loan-pricing-892\\loan-pricing-892-v2.0" diff --git a/CLAUDE.md b/CLAUDE.md index 8ea4443..6484190 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,6 +11,7 @@ ## Java Code Style - 在实体类中使用 `@Data` 注解保证代码的简洁 - 尽量使用 MyBatis Plus 进行 CRUD 操作(版本 3.5.10,Spring Boot 3 适配版) +- 服务层中的使用@Resource注释,替代@Autowired # 测试验证 - /login/test接口可以传入username和password获取token,用于测试验证接口的功能。 diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index f86c9c1..953b5a3 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -100,4 +100,6 @@ spring: # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) - max-wait: -1ms \ No newline at end of file + max-wait: -1ms +model: + url: http://localhost:8080/rate/pricing/mock/invokeModel \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java index 534d21c..fe8bb5c 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java @@ -11,6 +11,8 @@ import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Map; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; @@ -21,7 +23,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.utils.StringUtils; -import org.springframework.http.MediaType; +import org.springframework.http.*; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; /** * 通用http发送方法 @@ -290,4 +295,79 @@ public class HttpUtils return true; } } + + /** + * 发送 POST 请求(application/x-www-form-urlencoded 格式) + * @param url 请求地址 + * @param params 表单参数 + * @param headers 请求头(可为 null) + * @param responseType 响应类型 + * @param 泛型返回值 + * @return 响应结果 + */ + public static T doPostFormUrlEncoded(String url, Map params, HttpHeaders headers, Class responseType) { + // 构建表单参数 + MultiValueMap formParams = new LinkedMultiValueMap<>(); + if (params != null && !params.isEmpty()) { + formParams.setAll(params); + } + + // 构建请求头(指定 Content-Type) + HttpHeaders requestHeaders = headers == null ? new HttpHeaders() : headers; + requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + requestHeaders.setAcceptCharset(Collections.singletonList(StandardCharsets.UTF_8)); + + HttpEntity> requestEntity = new HttpEntity<>(formParams, requestHeaders); + RestTemplate restTemplate = new RestTemplate(); + // 发送请求 + try { + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.POST, + requestEntity, + responseType + ); + log.info("---------------------->POST(form-urlencoded) 请求成功,URL:{},响应结果:{}", url, response.getBody()); + return response.getBody(); + } catch (Exception e) { + throw new RuntimeException("POST(form-urlencoded) 请求失败,URL:" + url + ",异常信息:" + e.getMessage(), e); + } + } + + // ========== 新增:JSON 格式 POST 请求 ========== + /** + * 发送 POST 请求(application/json 格式) + * @param url 请求地址 + * @param requestBody 请求体(Java 对象,自动序列化为 JSON) + * @param headers 请求头(可为 null,默认已设置 Content-Type: application/json) + * @param responseType 响应类型 + * @param 响应泛型类型 + * @param 请求体类型 + * @return 响应结果 + */ + public static T doPostJson(String url, R requestBody, HttpHeaders headers, Class responseType) { + // 构建请求头,默认设置 JSON 格式 + HttpHeaders requestHeaders = headers == null ? new HttpHeaders() : headers; + // 确保 Content-Type 为 JSON,避免外部传入覆盖 + if (!requestHeaders.containsKey(HttpHeaders.CONTENT_TYPE)) { + requestHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); + } + + // 构建请求实体(请求体 + 请求头) + HttpEntity requestEntity = new HttpEntity<>(requestBody, requestHeaders); + RestTemplate restTemplate = new RestTemplate(); + // 发送 JSON POST 请求 + try { + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.POST, + requestEntity, + responseType + ); + log.info("---------------------->POST(JSON) 请求成功,URL:{},响应结果:{}", url, response.getBody()); + return response.getBody(); + } catch (Exception e) { + throw new RuntimeException("POST(JSON) 请求失败,URL:" + url + ",异常信息:" + e.getMessage(), e); + } + } } \ No newline at end of file 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..8aa0d50 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/handler/MyMetaHandler.java @@ -0,0 +1,33 @@ +package com.ruoyi.framework.config.handler; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.ruoyi.common.utils.SecurityUtils; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * 实体类自动配置创建日期和更新日期 + * + * @author 600477 + * @date 2023/6/6 + */ +@Component +public class MyMetaHandler implements MetaObjectHandler { + + @Override + public void insertFill(MetaObject metaObject) { + this.setFieldValByName("createBy", SecurityUtils.getUsername(), metaObject); + this.setFieldValByName("createTime", new Date(), metaObject); + this.setFieldValByName("updateBy", SecurityUtils.getUsername(), metaObject); + this.setFieldValByName("updateTime", new Date(), metaObject); + + } + + @Override + public void updateFill(MetaObject metaObject) { + this.setFieldValByName("updateBy", SecurityUtils.getUsername(), metaObject); + this.setFieldValByName("updateTime", new Date(), metaObject); + } +} diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java index 127b666..116707e 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanPricingWorkflowController.java @@ -10,7 +10,8 @@ import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableSupport; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.SecurityUtils; -import com.ruoyi.loanpricing.domain.LoanPricingWorkflow; +import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; +import com.ruoyi.loanpricing.domain.vo.LoanPricingWorkflowVO; import com.ruoyi.loanpricing.service.ILoanPricingWorkflowService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -41,10 +42,6 @@ public class LoanPricingWorkflowController extends BaseController @PostMapping("/create") public AjaxResult create(@Validated @RequestBody LoanPricingWorkflow loanPricingWorkflow) { - // 设置创建者 - loanPricingWorkflow.setCreateBy(SecurityUtils.getUsername()); - loanPricingWorkflow.setUpdateBy(SecurityUtils.getUsername()); - LoanPricingWorkflow result = loanPricingWorkflowService.createLoanPricing(loanPricingWorkflow); return success(result); } @@ -76,7 +73,7 @@ public class LoanPricingWorkflowController extends BaseController @Parameter(description = "业务方流水号") @PathVariable("serialNum") String serialNum) { - LoanPricingWorkflow workflow = loanPricingWorkflowService.selectLoanPricingBySerialNum(serialNum); + LoanPricingWorkflowVO workflow = loanPricingWorkflowService.selectLoanPricingBySerialNum(serialNum); if (workflow == null) { return error("记录不存在"); diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanRatePricingMockController.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanRatePricingMockController.java new file mode 100644 index 0000000..55e7707 --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/controller/LoanRatePricingMockController.java @@ -0,0 +1,55 @@ +package com.ruoyi.loanpricing.controller; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.ruoyi.common.annotation.Anonymous; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; + +import com.ruoyi.loanpricing.domain.dto.ModelInvokeDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.core.io.ClassPathResource; +import org.springframework.web.bind.annotation.*; + + +import java.io.InputStream; + + +/** + * @Author 吴凯程 + * @Date 2025/11/10 + **/ +@Tag(name = "测算测试接口") +@RestController +@RequestMapping("/rate/pricing/mock") +public class LoanRatePricingMockController extends BaseController { + + @Anonymous + @Operation(summary = "调用模型获取测算利率") + @PostMapping("/invokeModel") + public AjaxResult invokeModel( ModelInvokeDTO modelInvokeDTO) { + ObjectNode jsonNodes; + if (modelInvokeDTO.getCustType().equals("个人")) { + jsonNodes = loadJsonFromResource("data/retail_output.json"); + } else { + jsonNodes = loadJsonFromResource("data/corp_output.json"); + } + + return new AjaxResult(10000, "success", jsonNodes); + } + + private ObjectNode loadJsonFromResource(String resourcePath){ + ClassPathResource classPathResource = new ClassPathResource(resourcePath); + try (InputStream inputStream = classPathResource.getInputStream();){ + + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(inputStream, ObjectNode.class); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + +} 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 new file mode 100644 index 0000000..9a0348c --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java @@ -0,0 +1,153 @@ +package com.ruoyi.loanpricing.domain.dto; + +import lombok.Data; + +/** + * @Author 吴凯程 + * @Date 2025/12/23 + **/ +@Data +public class ModelInvokeDTO { + /** + * 业务方流水号(必填) + * 可使用时间戳,或自定义随机生成 + */ + private String serialNum; + + /** + * 机构编码(必填) + * 固定值:931000 + */ + private String orgCode; + + /** + * 运行模式(必填) + * 固定值:1:同步 + */ + private String runType = "1"; + + /** + * 客户内码(必填) + */ + private String custIsn; + + /** + * 客户类型(必填) + * 可选值:个人/企业 + */ + private String custType; + + /** + * 担保方式(必填) + * 可选值:信用,保证,抵押,质押 + */ + private String guarType; + + /** + * 中间业务_个人_快捷支付(非必填) + * 可选值:true/false + */ + private String midPerQuickPay; + + /** + * 中间业务_个人_电费代扣(非必填) + * 可选值:true/false + */ + private String midPerEleDdc; + + /** + * 中间业务_企业_电费代扣(非必填) + * 可选值:true/false + */ + private String midEntEleDdc; + + /** + * 中间业务_企业_水费代扣(非必填) + * 可选值:true/false + */ + private String midEntWaterDdc; + + /** + * 申请金额(必填) + * 单位:元 + */ + private String applyAmt; + + /** + * 净身企业(非必填) + * 可选值:true/false + */ + private String isCleanEnt; + + /** + * 开立基本结算账户(非必填) + * 可选值:true/false + */ + private String hasSettleAcct; + + /** + * 制造业企业(非必填) + * 可选值:true/false + */ + private String isManufacturing; + + /** + * 省农担担保贷款(非必填) + * 可选值:true/false + */ + private String isAgriGuar; + + /** + * 是否纳税信用等级A级(非必填) + * 可选值:true/false + */ + private String isTaxA; + + /** + * 是否县级及以上农业龙头企业(非必填) + * 可选值:true/false + */ + private String isAgriLeading; + + private String isInclusiveFinance; + + /** + * 贷款用途(非必填) + * 可选值:consumer/business + */ + private String loanPurpose; + + /** + * 是否有经营佐证(非必填) + * 可选值:true/false + */ + private String bizProof; + + /** + * 抵质押类型(非必填) + * 可选值:抵押/质押 + */ + private String collType; + + /** + * 抵质押物是否三方所有(非必填) + * 可选值:true/false + */ + private String collThirdParty; + +// /** +// * 贷款利率(必填) +// */ +// private String loanRate; + + /** + * 客户名称(非必填) + */ + private String custName; + + /** + * 证件类型(非必填) + */ + private String idType; + +} diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/LoanPricingWorkflow.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java similarity index 90% rename from ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/LoanPricingWorkflow.java rename to ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java index fecdaf9..4b62b75 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/LoanPricingWorkflow.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java @@ -1,8 +1,6 @@ -package com.ruoyi.loanpricing.domain; +package com.ruoyi.loanpricing.domain.entity; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -27,6 +25,9 @@ public class LoanPricingWorkflow implements Serializable @TableId(type = IdType.AUTO) private Long id; + /** 模型输出ID */ + private Long modelOutputId; + /** 业务方流水号 */ private String serialNum; @@ -108,16 +109,20 @@ public class LoanPricingWorkflow implements Serializable private String isInclusiveFinance; /** 创建者 */ + @TableField(fill = FieldFill.INSERT) private String createBy; /** 创建时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(fill = FieldFill.INSERT) private Date createTime; /** 更新者 */ + @TableField(fill = FieldFill.INSERT_UPDATE) private String updateBy; /** 更新时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; } 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 new file mode 100644 index 0000000..c7ec5ad --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java @@ -0,0 +1,125 @@ +package com.ruoyi.loanpricing.domain.entity; + +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 lombok.Data; + +import java.util.Date; + +/** + * 贷款定价模型输入参数对象 + * + * @author ruoyi + * @date 2025-01-21 + */ +@Data +public class ModelCorpOutputFields { + + @TableId(type = IdType.AUTO) + private Long id; + // 客户内码 + private String custIsn; + // 客户类型 + private String custType; + // 担保方式 + private String guarType; + // 客户名称 + private String custName; + // 证件类型 + private String idType; + // 证件号码 + private String idNum; + // 基准利率 + private String baseLoanRate; + // 我行首贷客户 + private String isFirstLoan; + // 用信天数 + private String faithDay; + // BP_首贷 + private String bpFirstLoan; + // BP_贷龄 + private String bpAgeLoan; + // TOTAL_BP_忠诚度 + private String totalBpLoyalty; + // 存款年日均 + private String balanceAvg; + // 贷款年日均 + private String loanAvg; + // 派生率 + private String derivationRate; + // TOTAL_BP_贡献度 + private String totalBpContribution; + // 中间业务_企业_企业互联 + private String midEntConnect; + // 中间业务_企业_有效价值客户 + private String midEntEffect; + // 中间业务_企业_国际业务 + private String midEntInter; + // 中间业务_企业_承兑 + private String midEntAccept; + // 中间业务_企业_贴现 + private String midEntDiscount; + // 中间业务_企业_电费代扣 + private String midEntEleDdc; + // 中间业务_企业_水费代扣 + private String midEntWaterDdc; + // 中间业务_企业_税务代扣 + private String midEntTax; + // BP_中间业务 + private String bpMid; + // 代发工资户数 + private String payroll; + // 存量贷款余额 + private String invLoanAmount; + // BP_代发工资 + private String bpPayroll; + // 净身企业 + private String isCleanEnt; + // 开立基本结算账户 + private String hasSettleAcct; + // 省农担担保贷款 + private String isAgriGuar; + // 绿色贷款 + private String isGreenLoan; + // 科技型企业 + private String isTechEnt; + // BP_企业客户类别 + private String bpEntType; + // TOTAL_BP_关联度 + private String totoalBpRelevance; + // 贷款期限 + private String loanTerm; + // BP_贷款期限 + private String bpLoanTerm; + // 申请金额 + private String applyAmt; + // BP_贷款额度 + private String bpLoanAmount; + // 抵质押类型 + private String collType; + // 抵质押物是否三方所有 + private String collThirdParty; + // BP_抵押物 + private String bpCollateral; + // 灰名单客户 + private String greyCust; + // 本金逾期 + private String prinOverdue; + // 利息逾期 + private String interestOverdue; + // 信用卡逾期 + private String cardOverdue; + // BP_灰名单与逾期 + private String bpGreyOverdue; + // TOTAL_BP_风险度 + private String totoalBpRisk; + // 浮动BP + private String totalBp; + // 测算利率 + private String calculateRate; + + @TableField(fill = FieldFill.INSERT) + private Date createTime; +} 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 new file mode 100644 index 0000000..3eb775e --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelRetailOutputFields.java @@ -0,0 +1,175 @@ +package com.ruoyi.loanpricing.domain.entity; + +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 lombok.Data; + +import java.util.Date; + +/** + * 贷款定价模型输入参数对象 + * + * @author ruoyi + * @date 2025-01-21 + */ +@Data +public class ModelRetailOutputFields { + + @TableId(type = IdType.AUTO) + private Long id; + + // 客户内码 + private String custIsn; + + // 客户类型 + private String custType; + + // 担保方式 + private String guarType; + + // 客户名称 + private String custName; + + // 证件类型 + private String idType; + + // 证件号码 + private String idNum; + + // 基准利率 + private String baseLoanRate; + + // 我行首贷客户 + private String isFirstLoan; + + // 用信天数 + private String faithDay; + + // 客户年龄 + private String custAge; + + // BP_首贷 + private String bpFirstLoan; + + // BP_贷龄 + private String bpAgeLoan; + + // BP_年龄 + private String bpAge; + + // TOTAL_BP_忠诚度 + private String totalBpLoyalty; + + // 存款年日均 + private String balanceAvg; + + // 贷款年日均 + private String loanAvg; + + // 派生率 + private String derivationRate; + + // TOTAL_BP_贡献度 + private String totalBpContribution; + + // 中间业务_个人_信用卡 + private String midPerCard; + + // 中间业务_个人_一码通 + private String midPerPass; + + // 中间业务_个人_丰收互联 + private String midPerHarvest; + + // 中间业务_个人_有效客户 + private String midPerEffect; + + // 中间业务_个人_快捷支付 + private String midPerQuickPay; + + // 中间业务_个人_电费代扣 + private String midPerEleDdc; + + // 中间业务_个人_水费代扣 + private String midPerWaterDdc; + + // 中间业务_个人_华数费代扣 + private String midPerHuashuDdc; + + // 中间业务_个人_煤气费代扣 + private String MidPerGasDdc; + + // 中间业务_个人_市民卡 + private String midPerCitizencard; + + // 中间业务_个人_理财业务 + private String midPerFinMan; + + // 中间业务_个人_etc + private String midPerEtc; + + // BP_中间业务 + private String bpMid; + + // TOTAL_BP_关联度(注意原字段名拼写错误:totoalBpRelevance,已保留原拼写) + private String totoalBpRelevance; + + // 申请金额 + private String applyAmt; + + // BP_贷款额度 + private String bpLoanAmount; + + // 贷款用途 + private String loanPurpose; + + // 是否有经营佐证 + private String bizProof; + + // BP_贷款用途 + private String bpLoanUse; + + // 循环功能 + private String loanLoop; + + // BP_循环功能 + private String bpLoanLoop; + + // 抵质押类型 + private String collType; + + // 抵质押物是否三方所有 + private String collThirdParty; + + // BP_抵押物 + private String bpCollateral; + + // 灰名单客户 + private String greyCust; + + // 本金逾期 + private String prinOverdue; + + // 利息逾期 + private String interestOverdue; + + // 信用卡逾期 + private String cardOverdue; + + // BP_灰名单与逾期 + private String bpGreyOverdue; + + // TOTAL_BP_风险度(注意原字段名拼写错误:totoalBpRisk,已保留原拼写) + private String totoalBpRisk; + + // 浮动BP + private String totalBp; + + // 测算利率 + private String calculateRate; + + @TableField(fill = FieldFill.INSERT) + private Date createTime; +} diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/vo/LoanPricingWorkflowVO.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/vo/LoanPricingWorkflowVO.java new file mode 100644 index 0000000..bac1861 --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/vo/LoanPricingWorkflowVO.java @@ -0,0 +1,21 @@ +package com.ruoyi.loanpricing.domain.vo; + +import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; +import com.ruoyi.loanpricing.domain.entity.ModelCorpOutputFields; +import com.ruoyi.loanpricing.domain.entity.ModelRetailOutputFields; +import lombok.Data; + +/** + * @Author: wkc + * @CreateTime: 2026-01-21 + */ +@Data +public class LoanPricingWorkflowVO { + + private LoanPricingWorkflow loanPricingWorkflow; + + private ModelRetailOutputFields modelRetailOutputFields; + + private ModelCorpOutputFields modelCorpOutputFields; + +} diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/LoanPricingWorkflowMapper.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/LoanPricingWorkflowMapper.java index 67e89ca..1df34f7 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/LoanPricingWorkflowMapper.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/LoanPricingWorkflowMapper.java @@ -1,10 +1,7 @@ package com.ruoyi.loanpricing.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.ruoyi.loanpricing.domain.LoanPricingWorkflow; -import org.apache.ibatis.annotations.Param; - -import java.util.List; +import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; /** * 利率定价流程Mapper接口 diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/ModelCorpOutputFieldsMapper.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/ModelCorpOutputFieldsMapper.java new file mode 100644 index 0000000..e02b519 --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/ModelCorpOutputFieldsMapper.java @@ -0,0 +1,15 @@ +package com.ruoyi.loanpricing.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.loanpricing.domain.entity.ModelCorpOutputFields; + +/** + * 对公贷款定价模型输出字段Mapper接口 + * + * @author ruoyi + * @date 2025-01-21 + */ +public interface ModelCorpOutputFieldsMapper extends BaseMapper +{ + +} diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/ModelRetailOutputFieldsMapper.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/ModelRetailOutputFieldsMapper.java new file mode 100644 index 0000000..f3aa994 --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/mapper/ModelRetailOutputFieldsMapper.java @@ -0,0 +1,15 @@ +package com.ruoyi.loanpricing.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.loanpricing.domain.entity.ModelRetailOutputFields; + +/** + * 零售贷款定价模型输出字段Mapper接口 + * + * @author ruoyi + * @date 2025-01-21 + */ +public interface ModelRetailOutputFieldsMapper extends BaseMapper +{ + +} diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java index c11d5d0..3a5188d 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ILoanPricingWorkflowService.java @@ -2,7 +2,8 @@ package com.ruoyi.loanpricing.service; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.ruoyi.loanpricing.domain.LoanPricingWorkflow; +import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; +import com.ruoyi.loanpricing.domain.vo.LoanPricingWorkflowVO; import java.util.List; @@ -45,5 +46,5 @@ public interface ILoanPricingWorkflowService * @param serialNum 业务方流水号 * @return 利率定价流程 */ - public LoanPricingWorkflow selectLoanPricingBySerialNum(String serialNum); + public LoanPricingWorkflowVO selectLoanPricingBySerialNum(String serialNum); } 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 new file mode 100644 index 0000000..a2b96c6 --- /dev/null +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java @@ -0,0 +1,69 @@ +package com.ruoyi.loanpricing.service; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.common.utils.bean.BeanUtils; +import com.ruoyi.loanpricing.domain.dto.ModelInvokeDTO; +import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; +import com.ruoyi.loanpricing.domain.entity.ModelCorpOutputFields; +import com.ruoyi.loanpricing.domain.entity.ModelRetailOutputFields; +import com.ruoyi.loanpricing.mapper.LoanPricingWorkflowMapper; +import com.ruoyi.loanpricing.mapper.ModelCorpOutputFieldsMapper; +import com.ruoyi.loanpricing.mapper.ModelRetailOutputFieldsMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Service; + +import java.util.Objects; + +/** + * @Author: wkc + * @CreateTime: 2026-01-21 + */ +@Service +@Slf4j +@EnableAsync +public class LoanPricingModelService { + + @Resource + private ModelService modelService; + + @Resource + private LoanPricingWorkflowMapper loanPricingWorkflowMapper; + + @Resource + private ModelRetailOutputFieldsMapper modelRetailOutputFieldsMapper; + + @Resource + private ModelCorpOutputFieldsMapper modelCorpOutputFieldsMapper; + + public void invokeModelAsync(Long workflowId) { + LoanPricingWorkflow loanPricingWorkflow = loanPricingWorkflowMapper.selectById(workflowId); + if (Objects.isNull(loanPricingWorkflow)){ + log.error("未找到对应的流程信息,未调用模型服务"); + return; + } + ModelInvokeDTO modelInvokeDTO = new ModelInvokeDTO(); + BeanUtils.copyProperties(loanPricingWorkflow, modelInvokeDTO); + JSONObject response = modelService.invokeModel(modelInvokeDTO); + if (loanPricingWorkflow.getCustType().equals("个人")){ + // 个人模型 + ModelRetailOutputFields modelRetailOutputFields = JSON.parseObject(response.toJSONString(), ModelRetailOutputFields.class); + modelRetailOutputFieldsMapper.insert(modelRetailOutputFields); + log.info("个人模型调用成功"); + loanPricingWorkflow.setModelOutputId(modelRetailOutputFields.getId()); + loanPricingWorkflowMapper.updateById(loanPricingWorkflow); + log.info("更新流程信息成功"); + }else if (loanPricingWorkflow.getCustType().equals("企业")){ + // 企业模型 + ModelCorpOutputFields modelCorpOutputFields = JSON.parseObject(response.toJSONString(), ModelCorpOutputFields.class); + modelCorpOutputFieldsMapper.insert(modelCorpOutputFields); + log.info("企业模型调用成功"); + loanPricingWorkflow.setModelOutputId(modelCorpOutputFields.getId()); + loanPricingWorkflowMapper.updateById(loanPricingWorkflow); + log.info("更新流程信息成功"); + } + } +} diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ModelService.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ModelService.java index d0077e3..73fd9cf 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ModelService.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/ModelService.java @@ -7,14 +7,15 @@ import com.ruoyi.common.core.domain.entity.SysDictData; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.http.HttpUtils; -import com.ruoyi.loanratepricing.domain.RatePricingProperties; -import com.ruoyi.loanratepricing.domain.dto.ModelInvokeDTO; -import com.ruoyi.loanratepricing.domain.entity.ModelOutputFields; +import com.ruoyi.loanpricing.domain.dto.ModelInvokeDTO; +import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; +import org.springframework.beans.factory.annotation.Value; + + import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.stereotype.Service; -import javax.annotation.Resource; -import java.util.List; import java.util.Map; import java.util.Objects; @@ -24,28 +25,28 @@ import java.util.Objects; **/ @Service @Slf4j +@EnableAsync public class ModelService { - @Resource - private RatePricingProperties ratePricingProperties; + @Value("${model.url}") + private String modelUrl; - @Resource - private RedisCache redisCache; - public ModelOutputFields invokeModel(ModelInvokeDTO modelInvokeDTO) { + + public JSONObject invokeModel(ModelInvokeDTO modelInvokeDTO) { Map requestBody = entityToMap(modelInvokeDTO); - JSONObject response = HttpUtils.doPostFormUrlEncoded(ratePricingProperties.getModelUrl(), requestBody, null, JSONObject.class); + JSONObject response = HttpUtils.doPostFormUrlEncoded(modelUrl, requestBody, null, JSONObject.class); log.info("------------------->调用模型返回结果:" + JSON.toJSONString(response)); if(Objects.nonNull(response) && response.containsKey("code") && response.getInteger("code") == 10000){ JSONObject mappingOutputFields = response.getJSONObject("data").getJSONObject("mappingOutputFields"); - return JSON.parseObject(mappingOutputFields.toJSONString(), ModelOutputFields.class); +// return JSON.parseObject(mappingOutputFields.toJSONString(), ModelOutputFields.class); + return mappingOutputFields; }else{ log.error("------------------->调用模型失败,失败原因为:" + response.getString("message")); throw new ServiceException("调用模型失败"); } } - /** * 使用FastJSON将实体类转换为Map * @param obj 待转换的实体类对象 @@ -60,16 +61,6 @@ public class ModelService { return JSON.parseObject(jsonStr, new TypeReference>() {}); } - private void replaceIndicatorToVariableName(JSONObject jsonObject) { - List variableNameList = redisCache.getCacheObject("sys_dict:model_indicator_metric"); - variableNameList.forEach(sysDictData -> { - if (jsonObject.containsKey(sysDictData.getDictLabel())) { - jsonObject.put(sysDictData.getDictValue(), jsonObject.get(sysDictData.getDictLabel())); - jsonObject.remove(sysDictData.getDictLabel()); - } - }); - } - 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 0bd69d8..6b2d136 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 @@ -3,16 +3,24 @@ package com.ruoyi.loanpricing.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.ruoyi.loanpricing.domain.LoanPricingWorkflow; +import com.ruoyi.loanpricing.domain.entity.LoanPricingWorkflow; +import com.ruoyi.loanpricing.domain.entity.ModelCorpOutputFields; +import com.ruoyi.loanpricing.domain.entity.ModelRetailOutputFields; +import com.ruoyi.loanpricing.domain.vo.LoanPricingWorkflowVO; import com.ruoyi.loanpricing.mapper.LoanPricingWorkflowMapper; +import com.ruoyi.loanpricing.mapper.ModelCorpOutputFieldsMapper; +import com.ruoyi.loanpricing.mapper.ModelRetailOutputFieldsMapper; import com.ruoyi.loanpricing.service.ILoanPricingWorkflowService; -import org.springframework.beans.factory.annotation.Autowired; +import com.ruoyi.loanpricing.service.LoanPricingModelService; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.Objects; /** * 利率定价流程Service业务层处理 @@ -23,9 +31,19 @@ import java.util.List; @Service public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowService { - @Autowired + @Resource private LoanPricingWorkflowMapper loanPricingWorkflowMapper; + @Resource + private LoanPricingModelService loanPricingModelService; + + @Resource + private ModelRetailOutputFieldsMapper modelRetailOutputFieldsMapper; + + @Resource + private ModelCorpOutputFieldsMapper modelCorpOutputFieldsMapper; + + /** * 发起利率定价流程 * @@ -33,6 +51,7 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi * @return 结果 */ @Override + @Transactional(rollbackFor = Exception.class) public LoanPricingWorkflow createLoanPricing(LoanPricingWorkflow loanPricingWorkflow) { // 自动生成业务方流水号(时间戳) @@ -43,19 +62,16 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi // 设置默认值 if (!StringUtils.hasText(loanPricingWorkflow.getOrgCode())) { - loanPricingWorkflow.setOrgCode("931000"); + loanPricingWorkflow.setOrgCode("892000"); } if (!StringUtils.hasText(loanPricingWorkflow.getRunType())) { loanPricingWorkflow.setRunType("1"); } - // 设置创建时间和更新时间 - Date now = new Date(); - loanPricingWorkflow.setCreateTime(now); - loanPricingWorkflow.setUpdateTime(now); - loanPricingWorkflowMapper.insert(loanPricingWorkflow); + loanPricingModelService.invokeModelAsync(loanPricingWorkflow.getId()); + return loanPricingWorkflow; } @@ -97,11 +113,28 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi * @return 利率定价流程 */ @Override - public LoanPricingWorkflow selectLoanPricingBySerialNum(String serialNum) + public LoanPricingWorkflowVO selectLoanPricingBySerialNum(String serialNum) { + LoanPricingWorkflowVO loanPricingWorkflowVO = new LoanPricingWorkflowVO(); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(LoanPricingWorkflow::getSerialNum, serialNum); - return loanPricingWorkflowMapper.selectOne(wrapper); + LoanPricingWorkflow loanPricingWorkflow = loanPricingWorkflowMapper.selectOne(wrapper); + loanPricingWorkflowVO.setLoanPricingWorkflow(loanPricingWorkflow); + + if (Objects.nonNull(loanPricingWorkflow.getModelOutputId())){ + if (loanPricingWorkflow.getCustType().equals("个人")){ + ModelRetailOutputFields modelRetailOutputFields = modelRetailOutputFieldsMapper.selectById(loanPricingWorkflow.getModelOutputId()); + loanPricingWorkflowVO.setModelRetailOutputFields(modelRetailOutputFields); + } + if (loanPricingWorkflow.getCustType().equals("企业")){ + ModelCorpOutputFields modelCorpOutputFields = modelCorpOutputFieldsMapper.selectById(loanPricingWorkflow.getModelOutputId()); + loanPricingWorkflowVO.setModelCorpOutputFields(modelCorpOutputFields); + } + } + + + return loanPricingWorkflowVO; } /** diff --git a/ruoyi-loan-pricing/src/main/resources/data/corp_output.json b/ruoyi-loan-pricing/src/main/resources/data/corp_output.json new file mode 100644 index 0000000..5752edc --- /dev/null +++ b/ruoyi-loan-pricing/src/main/resources/data/corp_output.json @@ -0,0 +1,68 @@ +{ + "traceId": "350626558347246735E7F4722CUZRWOMNRR53O0", + "cost": 2267, + "tokenId": "17364055486305E7F4722M8IPFWNL8TOBEB", + "mappingOutputFields": { + "custIsn": "CUST20260121001", + "custType": "企业客户", + "guarType": "抵押担保", + "custName": "北京智联科技有限公司", + "idType": "营业执照", + "idNum": "91110108MA00XXXXXX", + "baseLoanRate": "3.45", + "isFirstLoan": "N", + "faithDay": "730", + "bpFirstLoan": "0", + "bpAgeLoan": "5.2", + "totalBpLoyalty": "8.5", + "balanceAvg": "5000000.00", + "loanAvg": "3000000.00", + "derivationRate": "1.8", + "totalBpContribution": "12.3", + "midEntConnect": "100000.00", + "midEntEffect": "50000.00", + "midEntInter": "80000.00", + "midEntAccept": "200000.00", + "midEntDiscount": "150000.00", + "midEntEleDdc": "30000.00", + "midEntWaterDdc": "10000.00", + "midEntTax": "40000.00", + "bpMid": "6.8", + "payroll": "200", + "invLoanAmount": "2500000.00", + "bpPayroll": "4.1", + "isCleanEnt": "Y", + "hasSettleAcct": "Y", + "isAgriGuar": "N", + "isGreenLoan": "Y", + "isTechEnt": "Y", + "bpEntType": "7.5", + "totoalBpRelevance": "9.2", + "loanTerm": "36", + "bpLoanTerm": "3.3", + "applyAmt": "5000000.00", + "bpLoanAmount": "5.8", + "collType": "房产抵押", + "collThirdParty": "N", + "bpCollateral": "4.5", + "greyCust": "N", + "prinOverdue": "N", + "interestOverdue": "N", + "cardOverdue": "N", + "bpGreyOverdue": "0", + "totoalBpRisk": "1.2", + "totalBp": "48.2", + "calculateRate": "3.932" + }, + "extensionMap": {}, + "reasonMessage": "Running successfully", + "bizTime": 1736405548630, + "outputFields": {}, + "workflowCode": "TBKH", + "orgCode": "802000", + "bizId": "2025010914345", + "reasonCode": 200, + "workflowVersion": 14, + "callTime": 1736405548630, + "status": 1 +} \ No newline at end of file diff --git a/ruoyi-loan-pricing/src/main/resources/data/retail_output.json b/ruoyi-loan-pricing/src/main/resources/data/retail_output.json new file mode 100644 index 0000000..b01601b --- /dev/null +++ b/ruoyi-loan-pricing/src/main/resources/data/retail_output.json @@ -0,0 +1,68 @@ +{ + "traceId": "350626558347246735E7F4722CUZRWOMNRR53O0", + "cost": 2267, + "tokenId": "17364055486305E7F4722M8IPFWNL8TOBEB", + "mappingOutputFields": { + "custIsn": "CUST20260121001", + "custType": "个人", + "guarType": "信用担保", + "custName": "张三", + "idType": "身份证", + "idNum": "330106199001011234", + "baseLoanRate": "4.35", + "isFirstLoan": "是", + "faithDay": "365", + "custAge": "36", + "bpFirstLoan": "50", + "bpAgeLoan": "30", + "bpAge": "20", + "totalBpLoyalty": "95", + "balanceAvg": "50000.00", + "loanAvg": "100000.00", + "derivationRate": "1.2", + "totalBpContribution": "88", + "midPerCard": "1000.50", + "midPerPass": "500.00", + "midPerHarvest": "800.20", + "midPerEffect": "是", + "midPerQuickPay": "300.00", + "midPerEleDdc": "150.00", + "midPerWaterDdc": "80.00", + "midPerHuashuDdc": "120.00", + "MidPerGasDdc": "90.00", + "midPerCitizencard": "200.00", + "midPerFinMan": "5000.00", + "midPerEtc": "180.00", + "bpMid": "45", + "totoalBpRelevance": "90", + "applyAmt": "200000.00", + "bpLoanAmount": "60", + "loanPurpose": "个人消费", + "bizProof": "有", + "bpLoanUse": "55", + "loanLoop": "支持", + "bpLoanLoop": "40", + "collType": "无抵质押", + "collThirdParty": "否", + "bpCollateral": "0", + "greyCust": "否", + "prinOverdue": "否", + "interestOverdue": "否", + "cardOverdue": "否", + "bpGreyOverdue": "98", + "totoalBpRisk": "95", + "totalBp": "350", + "calculateRate": "6.15" + }, + "extensionMap": {}, + "reasonMessage": "Running successfully", + "bizTime": 1736405548630, + "outputFields": {}, + "workflowCode": "TBKH", + "orgCode": "802000", + "bizId": "2025010914345", + "reasonCode": 200, + "workflowVersion": 14, + "callTime": 1736405548630, + "status": 1 +} \ No newline at end of file diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/WorkflowCreateDialog.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/WorkflowCreateDialog.vue index 8dc387c..a5ae858 100644 --- a/ruoyi-ui/src/views/loanPricing/workflow/components/WorkflowCreateDialog.vue +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/WorkflowCreateDialog.vue @@ -226,7 +226,7 @@ export default { /** 表单重置 */ reset() { this.form = { - orgCode: '931000', + orgCode: '', runType: '1', custIsn: undefined, custName: undefined, diff --git a/sql/loan_pricing_workflow.sql b/sql/loan_pricing_workflow.sql index 155aec4..ea61783 100644 --- a/sql/loan_pricing_workflow.sql +++ b/sql/loan_pricing_workflow.sql @@ -3,7 +3,8 @@ DROP TABLE IF EXISTS `loan_pricing_workflow`; CREATE TABLE `loan_pricing_workflow` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', `serial_num` varchar(50) NOT NULL COMMENT '业务方流水号', - `org_code` varchar(20) NOT NULL DEFAULT '931000' COMMENT '机构编码', + `model_output_id` bigint(20) NULL COMMENT '模型输出id', + `org_code` varchar(20) NOT NULL DEFAULT '' COMMENT '机构编码', `run_type` varchar(10) NOT NULL DEFAULT '1' COMMENT '运行模式: 1-同步', `cust_isn` varchar(50) NOT NULL COMMENT '客户内码', `cust_type` varchar(20) NOT NULL COMMENT '客户类型: 个人/企业', diff --git a/sql/model_corp.sql b/sql/model_corp.sql new file mode 100644 index 0000000..88c9271 --- /dev/null +++ b/sql/model_corp.sql @@ -0,0 +1,59 @@ +/* + * 客户贷款利率测算表 + */ +DROP TABLE IF EXISTS model_corp_output_fields; +CREATE TABLE `model_corp_output_fields` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键ID', + `cust_isn` VARCHAR(100) COMMENT '客户内码', + `cust_type` VARCHAR(100) COMMENT '客户类型', + `guar_type` VARCHAR(100) COMMENT '担保方式', + `cust_name` VARCHAR(100) COMMENT '客户名称', + `id_type` VARCHAR(100) COMMENT '证件类型', + `id_num` VARCHAR(100) COMMENT '证件号码', + `base_loan_rate` VARCHAR(100) COMMENT '基准利率', + `is_first_loan` VARCHAR(100) COMMENT '我行首贷客户', + `faith_day` VARCHAR(100) COMMENT '用信天数', + `bp_first_loan` VARCHAR(100) COMMENT 'BP_首贷', + `bp_age_loan` VARCHAR(100) COMMENT 'BP_贷龄', + `total_bp_loyalty` VARCHAR(100) COMMENT 'TOTAL_BP_忠诚度', + `balance_avg` VARCHAR(100) COMMENT '存款年日均', + `loan_avg` VARCHAR(100) COMMENT '贷款年日均', + `derivation_rate` VARCHAR(100) COMMENT '派生率', + `total_bp_contribution` VARCHAR(100) COMMENT 'TOTAL_BP_贡献度', + `mid_ent_connect` VARCHAR(100) COMMENT '中间业务_企业_企业互联', + `mid_ent_effect` VARCHAR(100) COMMENT '中间业务_企业_有效价值客户', + `mid_ent_inter` VARCHAR(100) COMMENT '中间业务_企业_国际业务', + `mid_ent_accept` VARCHAR(100) COMMENT '中间业务_企业_承兑', + `mid_ent_discount` VARCHAR(100) COMMENT '中间业务_企业_贴现', + `mid_ent_ele_ddc` VARCHAR(100) COMMENT '中间业务_企业_电费代扣', + `mid_ent_water_ddc` VARCHAR(100) COMMENT '中间业务_企业_水费代扣', + `mid_ent_tax` VARCHAR(100) COMMENT '中间业务_企业_税务代扣', + `bp_mid` VARCHAR(100) COMMENT 'BP_中间业务', + `payroll` VARCHAR(100) COMMENT '代发工资户数', + `inv_loan_amount` VARCHAR(100) COMMENT '存量贷款余额', + `bp_payroll` VARCHAR(100) COMMENT 'BP_代发工资', + `is_clean_ent` VARCHAR(100) COMMENT '净身企业', + `has_settle_acct` VARCHAR(100) COMMENT '开立基本结算账户', + `is_agri_guar` VARCHAR(100) COMMENT '省农担担保贷款', + `is_green_loan` VARCHAR(100) COMMENT '绿色贷款', + `is_tech_ent` VARCHAR(100) COMMENT '科技型企业', + `bp_ent_type` VARCHAR(100) COMMENT 'BP_企业客户类别', + `totoal_bp_relevance` VARCHAR(100) COMMENT 'TOTAL_BP_关联度', + `loan_term` VARCHAR(100) COMMENT '贷款期限', + `bp_loan_term` VARCHAR(100) COMMENT 'BP_贷款期限', + `apply_amt` VARCHAR(100) COMMENT '申请金额', + `bp_loan_amount` VARCHAR(100) COMMENT 'BP_贷款额度', + `coll_type` VARCHAR(100) COMMENT '抵质押类型', + `coll_third_party` VARCHAR(100) COMMENT '抵质押物是否三方所有', + `bp_collateral` VARCHAR(100) COMMENT 'BP_抵押物', + `grey_cust` VARCHAR(100) COMMENT '灰名单客户', + `prin_overdue` VARCHAR(100) COMMENT '本金逾期', + `interest_overdue` VARCHAR(100) COMMENT '利息逾期', + `card_overdue` VARCHAR(100) COMMENT '信用卡逾期', + `bp_grey_overdue` VARCHAR(100) COMMENT 'BP_灰名单与逾期', + `totoal_bp_risk` VARCHAR(100) COMMENT 'TOTAL_BP_风险度', + `total_bp` VARCHAR(100) COMMENT '浮动BP', + `calculate_rate` VARCHAR(100) COMMENT '测算利率', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户贷款利率测算表'; \ No newline at end of file diff --git a/sql/model_retail.sql b/sql/model_retail.sql new file mode 100644 index 0000000..cee6d3c --- /dev/null +++ b/sql/model_retail.sql @@ -0,0 +1,114 @@ +/* + * 零售模型输出字段表 + * 存储客户基本信息、BP评分、资产信息、风险信息等贷款测算相关数据 + */ + DROP TABLE IF EXISTS model_retail_output_fields; +CREATE TABLE IF NOT EXISTS model_retail_output_fields ( + -- 主键ID(自增,用于表的唯一标识) + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + -- 客户内码(业务唯一标识) + cust_isn VARCHAR(100) NOT NULL COMMENT '客户内码', + -- 客户类型(如:个人/企业) + cust_type VARCHAR(100) DEFAULT '' COMMENT '客户类型', + -- 担保方式(如:信用担保/抵押担保) + guar_type VARCHAR(100) DEFAULT '' COMMENT '担保方式', + -- 客户名称 + cust_name VARCHAR(100) DEFAULT '' COMMENT '客户名称', + -- 证件类型(如:身份证/营业执照) + id_type VARCHAR(100) DEFAULT '' COMMENT '证件类型', + -- 证件号码(脱敏存储) + id_num VARCHAR(100) DEFAULT '' COMMENT '证件号码', + -- 基准利率(百分比,如4.35) + base_loan_rate VARCHAR(100) DEFAULT '' COMMENT '基准利率', + -- 我行首贷客户(是/否) + is_first_loan VARCHAR(100) DEFAULT '' COMMENT '我行首贷客户', + -- 用信天数 + faith_day VARCHAR(100) DEFAULT '' COMMENT '用信天数', + -- 客户年龄 + cust_age VARCHAR(100) DEFAULT '' COMMENT '客户年龄', + -- BP_首贷 + bp_first_loan VARCHAR(100) DEFAULT '' COMMENT 'BP_首贷', + -- BP_贷龄 + bp_age_loan VARCHAR(100) DEFAULT '' COMMENT 'BP_贷龄', + -- BP_年龄 + bp_age VARCHAR(100) DEFAULT '' COMMENT 'BP_年龄', + -- TOTAL_BP_忠诚度 + total_bp_loyalty VARCHAR(100) DEFAULT '' COMMENT 'TOTAL_BP_忠诚度', + -- 存款年日均(元) + balance_avg VARCHAR(100) DEFAULT '' COMMENT '存款年日均', + -- 贷款年日均(元) + loan_avg VARCHAR(100) DEFAULT '' COMMENT '贷款年日均', + -- 派生率 + derivation_rate VARCHAR(100) DEFAULT '' COMMENT '派生率', + -- TOTAL_BP_贡献度 + total_bp_contribution VARCHAR(100) DEFAULT '' COMMENT 'TOTAL_BP_贡献度', + -- 中间业务_个人_信用卡 + mid_per_card VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_信用卡', + -- 中间业务_个人_一码通 + mid_per_pass VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_一码通', + -- 中间业务_个人_丰收互联 + mid_per_harvest VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_丰收互联', + -- 中间业务_个人_有效客户(是/否) + mid_per_effect VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_有效客户', + -- 中间业务_个人_快捷支付 + mid_per_quick_pay VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_快捷支付', + -- 中间业务_个人_电费代扣 + mid_per_ele_ddc VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_电费代扣', + -- 中间业务_个人_水费代扣 + mid_per_water_ddc VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_水费代扣', + -- 中间业务_个人_华数费代扣 + mid_per_huashu_ddc VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_华数费代扣', + -- 中间业务_个人_煤气费代扣 + mid_per_gas_ddc VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_煤气费代扣', + -- 中间业务_个人_市民卡 + mid_per_citizencard VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_市民卡', + -- 中间业务_个人_理财业务 + mid_per_fin_man VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_理财业务', + -- 中间业务_个人_etc + mid_per_etc VARCHAR(100) DEFAULT '' COMMENT '中间业务_个人_etc', + -- BP_中间业务 + bp_mid VARCHAR(100) DEFAULT '' COMMENT 'BP_中间业务', + -- TOTAL_BP_关联度 + totoal_bp_relevance VARCHAR(100) DEFAULT '' COMMENT 'TOTAL_BP_关联度', + -- 申请金额(元) + apply_amt VARCHAR(100) DEFAULT '' COMMENT '申请金额', + -- BP_贷款额度 + bp_loan_amount VARCHAR(100) DEFAULT '' COMMENT 'BP_贷款额度', + -- 贷款用途(如:个人消费/经营) + loan_purpose VARCHAR(100) DEFAULT '' COMMENT '贷款用途', + -- 是否有经营佐证(是/否) + biz_proof VARCHAR(100) DEFAULT '' COMMENT '是否有经营佐证', + -- BP_贷款用途 + bp_loan_use VARCHAR(100) DEFAULT '' COMMENT 'BP_贷款用途', + -- 循环功能(支持/不支持) + loan_loop VARCHAR(100) DEFAULT '' COMMENT '循环功能', + -- BP_循环功能 + bp_loan_loop VARCHAR(100) DEFAULT '' COMMENT 'BP_循环功能', + -- 抵质押类型(如:无抵质押/房产抵押) + coll_type VARCHAR(100) DEFAULT '' COMMENT '抵质押类型', + -- 抵质押物是否三方所有(是/否) + coll_third_party VARCHAR(100) DEFAULT '' COMMENT '抵质押物是否三方所有', + -- BP_抵押物 + bp_collateral VARCHAR(100) DEFAULT '' COMMENT 'BP_抵押物', + -- 灰名单客户(是/否) + grey_cust VARCHAR(100) DEFAULT '' COMMENT '灰名单客户', + -- 本金逾期(是/否) + prin_overdue VARCHAR(100) DEFAULT '' COMMENT '本金逾期', + -- 利息逾期(是/否) + interest_overdue VARCHAR(100) DEFAULT '' COMMENT '利息逾期', + -- 信用卡逾期(是/否) + card_overdue VARCHAR(100) DEFAULT '' COMMENT '信用卡逾期', + -- BP_灰名单与逾期 + bp_grey_overdue VARCHAR(100) DEFAULT '' COMMENT 'BP_灰名单与逾期', + -- TOTAL_BP_风险度 + totoal_bp_risk VARCHAR(100) DEFAULT '' COMMENT 'TOTAL_BP_风险度', + -- 浮动BP + total_bp VARCHAR(100) DEFAULT '' COMMENT '浮动BP', + -- 测算利率(百分比,如6.15) + calculate_rate VARCHAR(100) DEFAULT '' COMMENT '测算利率', + -- 创建时间(审计字段) + create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + -- 主键约束 + PRIMARY KEY (id) + +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='零售模型输出字段表'; \ No newline at end of file