This commit is contained in:
wkc
2026-01-16 16:16:13 +08:00
commit 8295b39278
662 changed files with 71808 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
package com.ruoyi.loanratepricing.controller;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.loanratepricing.domain.dto.FinalRateAdjustDTO;
import com.ruoyi.loanratepricing.domain.dto.FinalRateSubmitDTO;
import com.ruoyi.loanratepricing.domain.dto.OptInvokeDTO;
import com.ruoyi.loanratepricing.domain.entity.LoanPricingApply;
import com.ruoyi.loanratepricing.domain.vo.FinalRateAdjustVO;
import com.ruoyi.loanratepricing.service.RatePricingService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @Author 吴凯程
* @Date 2025/11/10
**/
@Api(tags = "莲都利率测算")
@RestController
@RequestMapping("/rate/pricing")
public class LoanRatePricingController extends BaseController {
@Resource
private RatePricingService ratePricingService;
@ApiOperation("发起利率定价申请,或加载利率定价申请")
@Anonymous
@PostMapping("/load")
public R<LoanPricingApply> loadRatePricingApply(@RequestBody OptInvokeDTO optInvokeDTO) {
return R.ok(ratePricingService.loadRatePricingApply(optInvokeDTO));
}
@Anonymous
@ApiOperation("测算最终利率")
@PostMapping("/invoke")
public R<FinalRateAdjustVO> invokeFinalRate(@RequestBody FinalRateAdjustDTO finalRateAdjustDTO) {
return R.ok(ratePricingService.invokeFinalRate(finalRateAdjustDTO));
}
@Anonymous
@ApiOperation("提交利率定价申请")
@PostMapping("/submit")
public R<String> submitFinalRate(@RequestBody FinalRateSubmitDTO finalRateSubmitDTO) {
return R.ok(ratePricingService.submitFinalRate(finalRateSubmitDTO));
}
}

View File

@@ -0,0 +1,101 @@
package com.ruoyi.loanratepricing.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.loanratepricing.domain.entity.LoanPricingApply;
import com.ruoyi.loanratepricing.service.ModelService;
import com.ruoyi.loanratepricing.service.OptService;
import com.ruoyi.loanratepricing.service.RatePricingService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @Author 吴凯程
* @Date 2025/11/10
**/
@Api(tags = "莲都利率测算测试接口")
@RestController
@RequestMapping("/rate/pricing/mock")
public class LoanRatePricingMockController extends BaseController {
@Resource
private RatePricingService ratePricingService;
@Resource
private OptService optService;
@Resource
private ModelService modelService;
@ApiOperation("发起利率定价流程")
@Anonymous
@PostMapping("/submit/application")
public AjaxResult submitApplication() {
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode objectNode = objectMapper.createObjectNode();
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
String formattedDateTime = now.format(formatter);
objectNode.put("applicationId", Long.parseLong(formattedDateTime));
objectNode.put("midEntEleDdc", "0");
objectNode.put("midEntWaterDdc", "0");
objectNode.put("midPerEleDdc", "1");
objectNode.put("midPerQuickPay", "1");
return new AjaxResult(0, "success", objectNode);
}
@Anonymous
@ApiOperation("提交利率测算结果")
@PostMapping("/submit/result")
public AjaxResult submitRatePricingResult(@RequestBody LoanPricingApply loanPricingApply) {
return new AjaxResult(0, "success", null);
}
@Anonymous
@ApiOperation("查询议价池")
@GetMapping("/pool/balance")
public AjaxResult queryPoolBalance(@RequestParam String ownerId) {
ObjectNode jsonNodes = loadJsonFromResource("data/pool_balance.json");
return new AjaxResult(0, "success", jsonNodes);
}
@Anonymous
@ApiOperation("查询利率测算记录")
@GetMapping("/application")
public AjaxResult queryApplication(@RequestParam Long id) {
LoanPricingApply loanPricingApply = ratePricingService.queryLoanPricingApplyFromRedis(id);
return new AjaxResult(0, "success", loanPricingApply);
}
@Anonymous
@ApiOperation("调用模型获取测算利率")
@PostMapping("/invokeModel")
public AjaxResult invokeModel() {
ObjectNode jsonNodes = loadJsonFromResource("data/model_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);
}
}
}

View File

@@ -0,0 +1,76 @@
package com.ruoyi.loanratepricing.controller;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.loanratepricing.domain.dto.ModelInvokeDTO;
import com.ruoyi.loanratepricing.domain.dto.OptInvokeDTO;
import com.ruoyi.loanratepricing.domain.entity.LoanPricingApply;
import com.ruoyi.loanratepricing.domain.entity.ModelOutputFields;
import com.ruoyi.loanratepricing.domain.vo.OptPoolBalance;
import com.ruoyi.loanratepricing.service.ModelService;
import com.ruoyi.loanratepricing.service.OptService;
import com.ruoyi.loanratepricing.service.RatePricingService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/**
* @Author 吴凯程
* @Date 2025/11/10
**/
@Api(tags = "莲都利率测算接口测试")
@RestController
@RequestMapping("/rate/pricing/opt")
public class LoanRatePricingTestController extends BaseController {
@Resource
private RatePricingService ratePricingService;
@Resource
private OptService optService;
@Resource
private ModelService modelService;
@ApiOperation("发起利率定价流程")
@Anonymous
@PostMapping("/submit/application")
public R<JSONObject> submitApplication(@RequestBody OptInvokeDTO optInvokeDTO) {
return R.ok(optService.submitApplication(optInvokeDTO));
}
@Anonymous
@ApiOperation("提交利率测算结果")
@PostMapping("/submit/result")
public R<String> submitRatePricingResult(@RequestBody LoanPricingApply loanPricingApply) {
return R.ok(optService.submitRatePricingResult(loanPricingApply));
}
@Anonymous
@ApiOperation("查询议价池")
@GetMapping("/pool/balance")
public R<OptPoolBalance> queryPoolBalance(@RequestParam String userCode) {
return R.ok(optService.queryPoolBalance(userCode));
}
@Anonymous
@ApiOperation("查询利率测算记录")
@GetMapping("/application")
public R<LoanPricingApply> queryApplication(@RequestParam String id) {
return R.ok(optService.queryLoanPricingApply(id));
}
@Anonymous
@ApiOperation("调用模型获取测算利率")
@PostMapping("/invokeModel")
public R<ModelOutputFields> invokeModel(@RequestBody ModelInvokeDTO modelInvokeDTO) {
return R.ok(modelService.invokeModel(modelInvokeDTO));
}
}

View File

@@ -0,0 +1,27 @@
package com.ruoyi.loanratepricing.domain;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @Author 吴凯程
* @Date 2025/12/23
**/
@Data
@Configuration
@ConfigurationProperties(prefix = "rate-pricing")
public class RatePricingProperties {
private String oaUrl;
private String modelUrl;
private String applicationSubmitUrl;
private String pricingResultUrl;
private String poolBalanceUrl;
private String getApplicationUrl;
}

View File

@@ -0,0 +1,20 @@
package com.ruoyi.loanratepricing.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
/**
* @Author 吴凯程
* @Date 2025/12/24
**/
@Data
public class FinalRateAdjustDTO {
private String applicationId;
private BigDecimal finalRate;
}

View File

@@ -0,0 +1,28 @@
package com.ruoyi.loanratepricing.domain.dto;
import lombok.Data;
/**
* @Author 吴凯程
* @Date 2025/12/24
**/
@Data
public class FinalRateSubmitDTO {
private String applicationId;
private String finalRate;
private String branchUsage;
private String outletUsage;
private String managerUsage;
private String profitAmt;
// 审批状态
private String approvalStatus; // 审批状态 0不需要审批 1需要审批
private String approvalLevel; // 审批层级 0不需要审批 1网点 2支行
}

View File

@@ -0,0 +1,135 @@
package com.ruoyi.loanratepricing.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
/**
* 贷款定价申请信息实体类
* 包含申请信息、定价结果、客户信息、各类BP因子等
*/
@Data
public class LoanPricingApplySubmitDTO {
// 申请基本信息
private Long applicationId; // 申请编号
private String orgCode; // 申请机构代码
private String orgName; // 申请机构名称
private String applyUserCode; // 申请人ID
private String applyUserName; // 申请人姓名
// 定价结果
private String baseLoanRate; // 基础利率
private String finalRate; // 最终利率
private String minRateBranch; // 支行最低利率
private String minRateProduct; // 最低利率
private String calculateRate; // 测算利率
private String totalBp; // 浮动BP合计
// 客户基础信息
private String custType; // 客户类型(个人/企业)
private String custIsn; // 客户内码
private String custName; // 客户名称
private String idType; // 证件类型
private String idNo; // 证件号
private String guarType;
private String loanType;
private String loanRate;
// 忠诚度因子BP
private String isKeyClient; // 个人核心用户
private String isFirstLoan; // 我行首贷客户
private String faithDay; // 用信天数
private String custAge; // 客户年龄
private String bpFirstLoan; // BP_首贷
private String bpAgeLoan; // BP_贷龄
private String bpAge; // BP_年龄
private String totalBpLoyalty; // TOTAL_BP_忠诚度
// 贡献度因子BP - 存款相关
private String perAvg; // 借款个人年日均
private String perSp; // 借款个人特殊类存款
private String perFmyAvg; // 配偶_子女年日均
private String perFmySp; // 配偶_子女特殊类存款
private String perEntAvg; // 个人对应企业年日均
private String perEntSp; // 个人对应企业特殊类存款
private String entAvg; // 企业年日均
private String entSp; // 企业特殊类存款
private String entPerAvg; // 企业法人年日均
private String entPerSp; // 企业法人特殊类存款
private String entPerFmyAvg; // 企业法人配偶年日均
private String entPerFmySp; // 企业法人配偶特殊类存款
private String entFinAvg; // 企业财务年日均
private String entFinSp; // 企业财务特殊类存款
private String balanceAvg; // 存款年日均合计
private String loanAvg; // 贷款年日均
private String derivationRate; // 派生率
private String totalBpContribution; // TOTAL_BP_贡献度
// 贡献度因子BP - 中间业务
private String midPerCard; // 中间业务_个人_信用卡
private String midPerPass; // 中间业务_个人_一码通
private String midPerHarvest; // 中间业务_个人_丰收互联
private String midPerEffect; // 中间业务_个人_有效客户
private String midPerQuickPay; // 中间业务_个人_快捷支付
private String midPerEleDdc; // 中间业务_个人_电费代扣
private String midPerCitizencard; // 中间业务_个人_市民卡
private String midEntConnect; // 中间业务_企业_企业互联
private String midEntEffect; // 中间业务_企业_有效价值客户
private String midEntPublicFund; // 中间业务_企业_职工缴纳公积金
private String midEntEleDdc; // 中间业务_企业_电费代扣
private String midEntWaterDdc; // 中间业务_企业_水费代扣
private String midEntTax; // 中间业务_企业_税务代扣
private String bpMid; // BP_中间业务
// 关联度因子BP
private String payroll; // 代发工资户数
private String invLoanAmount; // 存量贷款余额
private String bpPayroll; // BP_代发工资
// 企业客户关联度
private String isCleanEnt; // 净身企业
private String hasSettleAcct; // 开立基本结算账户
private String isManufacturing; // 制造业企业
private String isAgriGuar; // 省农担担保贷款
private String isTaxA; // 是否纳税信用等级A级
private String isAgriLeading; // 是否县级及以上农业龙头企业
private String isInclusiveFinance;
private String bpEntType; // BP_企业客户类别
private String totalBpRelevance; // TOTAL_BP_关联度
// 贷款用途因子BP
private String applyAmt; // 申请金额(元)
private String bpLoanAmount; // BP_贷款额度
private String loanPurpose; // 贷款用途
private String bizProof; // 是否有经营佐证
private String bpLoanUse; // BP_贷款用途
// 抵押物质押因子BP
private String collType; // 抵质押类型
private String collThirdParty; // 抵质押物是否三方所有
private String bpCollateral; // BP_抵押物
// 风险度因子BP
private String greyCust; // 灰名单客户
private String prinOverdue; // 本金逾期
private String interestOverdue; // 利息逾期
private String cardOverdue; // 信用卡逾期
private String bpGreyOverdue; // BP_灰名单与逾期
private String totalBpRisk; // TOTAL_BP_风险度
// 审批状态
private String approvalStatus; // 审批状态
private String approvalLevel; // 审批层级
private BigDecimal branchBalance;
private BigDecimal outletBalance;
private BigDecimal managerBalance;
private BigDecimal branchUsage;
private BigDecimal outletUsage;
private BigDecimal managerUsage;
private BigDecimal profitAmt;
}

View File

@@ -0,0 +1,153 @@
package com.ruoyi.loanratepricing.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;
}

View File

@@ -0,0 +1,163 @@
package com.ruoyi.loanratepricing.domain.dto;
import lombok.Data;
/**
* @Author 吴凯程
* @Date 2025/12/23
**/
@Data
public class OptInvokeDTO {
private String applicationId;
/**
* 客户类型(个人/企业)
*/
private String custType;
/**
* 客户内码
*/
private String custIsn;
/**
* 客户名称
*/
private String custName;
/**
* 证件类型
*/
private String idType;
/**
* 证件号
*/
private String idNo;
/**
* 申请金额
*/
private String applyAmt;
/**
* 担保方式
*/
private String guarType;
/**
* 抵质押类型
*/
private String collType;
/**
* 抵质押物是否三方所有 0-否,1-是
*/
private String collThirdParty;
/**
* 贷款用途
*/
private String loanPurpose;
private String loanRate;
/**
* 是否有经营佐证 0-否,1-是
*/
private String bizProof;
/**
* 贷款产品ID
*/
private String loanProdId;
/**
* 贷款产品
*/
private String loanProd;
/**
* 当日办理业务
*/
private String todayBiz;
/**
* 是否净身企业 0-否,1-是
*/
private String isCleanEnt;
/**
* 是否制造业企业 0-否,1-是
*/
private String isManufacturing;
/**
* 是否省农担担保贷款 0-否,1-是
*/
private String isAgriGuar;
private String isInclusiveFinance;
/**
* 是否纳税信用等级A级 0-否,1-是
*/
private String isTaxA;
/**
* 是否县级及以上农业龙头企业 0-否,1-是
*/
private String isAgriLeading;
/**
* 中间业务_个人_快捷支付非必填
* 可选值true/false
*/
private String midPerQuickPay;
/**
* 中间业务_个人_电费代扣非必填
* 可选值true/false
*/
private String midPerEleDdc;
/**
* 中间业务_企业_电费代扣非必填
* 可选值true/false
*/
private String midEntEleDdc;
/**
* 中间业务_企业_水费代扣非必填
* 可选值true/false
*/
private String midEntWaterDdc;
/**
* 申请机构ID
*/
private String orgCode;
/**
* 申请机构名称
*/
private String orgName;
/**
* 申请人ID
*/
private String applyUserCode;
/**
* 申请人姓名
*/
private String applyUserName;
/**
* 是否开立基本结算账户 0-否,1-是
*/
private String hasSettleAcct;
}

View File

@@ -0,0 +1,135 @@
package com.ruoyi.loanratepricing.domain.entity;
import lombok.Data;
import java.math.BigDecimal;
/**
* 贷款定价申请信息实体类
* 包含申请信息、定价结果、客户信息、各类BP因子等
*/
@Data
public class LoanPricingApply {
// 申请基本信息
private String applicationId; // 申请编号
private String orgCode; // 申请机构代码
private String orgName; // 申请机构名称
private String applyUserCode; // 申请人ID
private String applyUserName; // 申请人姓名
// 定价结果
private String baseLoanRate; // 基础利率
private String finalRate; // 最终利率
private String minRateBranch; // 支行最低利率
private String minRateProduct; // 最低利率
private String calculateRate; // 测算利率
private String totalBp; // 浮动BP合计
// 客户基础信息
private String custType; // 客户类型(个人/企业)
private String custIsn; // 客户内码
private String custName; // 客户名称
private String idType; // 证件类型
private String idNo; // 证件号
private String guarType;
private String loanType;
private String loanRate;
// 忠诚度因子BP
private String isKeyClient; // 个人核心用户
private String isFirstLoan; // 我行首贷客户
private String faithDay; // 用信天数
private String custAge; // 客户年龄
private String bpFirstLoan; // BP_首贷
private String bpAgeLoan; // BP_贷龄
private String bpAge; // BP_年龄
private String totalBpLoyalty; // TOTAL_BP_忠诚度
// 贡献度因子BP - 存款相关
private String perAvg; // 借款个人年日均
private String perSp; // 借款个人特殊类存款
private String perFmyAvg; // 配偶_子女年日均
private String perFmySp; // 配偶_子女特殊类存款
private String perEntAvg; // 个人对应企业年日均
private String perEntSp; // 个人对应企业特殊类存款
private String entAvg; // 企业年日均
private String entSp; // 企业特殊类存款
private String entPerAvg; // 企业法人年日均
private String entPerSp; // 企业法人特殊类存款
private String entPerFmyAvg; // 企业法人配偶年日均
private String entPerFmySp; // 企业法人配偶特殊类存款
private String entFinAvg; // 企业财务年日均
private String entFinSp; // 企业财务特殊类存款
private String balanceAvg; // 存款年日均合计
private String loanAvg; // 贷款年日均
private String derivationRate; // 派生率
private String totalBpContribution; // TOTAL_BP_贡献度
// 贡献度因子BP - 中间业务
private String midPerCard; // 中间业务_个人_信用卡
private String midPerPass; // 中间业务_个人_一码通
private String midPerHarvest; // 中间业务_个人_丰收互联
private String midPerEffect; // 中间业务_个人_有效客户
private String midPerQuickPay; // 中间业务_个人_快捷支付
private String midPerEleDdc; // 中间业务_个人_电费代扣
private String midPerCitizencard; // 中间业务_个人_市民卡
private String midEntConnect; // 中间业务_企业_企业互联
private String midEntEffect; // 中间业务_企业_有效价值客户
private String midEntPublicFund; // 中间业务_企业_职工缴纳公积金
private String midEntEleDdc; // 中间业务_企业_电费代扣
private String midEntWaterDdc; // 中间业务_企业_水费代扣
private String midEntTax; // 中间业务_企业_税务代扣
private String bpMid; // BP_中间业务
// 关联度因子BP
private String payroll; // 代发工资户数
private String invLoanAmount; // 存量贷款余额
private String bpPayroll; // BP_代发工资
// 企业客户关联度
private String isCleanEnt; // 净身企业
private String hasSettleAcct; // 开立基本结算账户
private String isManufacturing; // 制造业企业
private String isAgriGuar; // 省农担担保贷款
private String isTaxA; // 是否纳税信用等级A级
private String isAgriLeading; // 是否县级及以上农业龙头企业
private String isInclusiveFinance;
private String bpEntType; // BP_企业客户类别
private String totalBpRelevance; // TOTAL_BP_关联度
// 贷款用途因子BP
private String applyAmt; // 申请金额(元)
private String bpLoanAmount; // BP_贷款额度
private String loanPurpose; // 贷款用途
private String bizProof; // 是否有经营佐证
private String bpLoanUse; // BP_贷款用途
// 抵押物质押因子BP
private String collType; // 抵质押类型
private String collThirdParty; // 抵质押物是否三方所有
private String bpCollateral; // BP_抵押物
// 风险度因子BP
private String greyCust; // 灰名单客户
private String prinOverdue; // 本金逾期
private String interestOverdue; // 利息逾期
private String cardOverdue; // 信用卡逾期
private String bpGreyOverdue; // BP_灰名单与逾期
private String totalBpRisk; // TOTAL_BP_风险度
// 审批状态
private String approvalStatus; // 审批状态
private String approvalLevel; // 审批层级
private BigDecimal branchBalance;
private BigDecimal outletBalance;
private BigDecimal managerBalance;
private BigDecimal branchUsage;
private BigDecimal outletUsage;
private BigDecimal managerUsage;
private BigDecimal profitAmt;
}

View File

@@ -0,0 +1,186 @@
package com.ruoyi.loanratepricing.domain.entity;
import lombok.Data;
/**
* @Author 吴凯程
* @Date 2025/12/24
**/
@Data
public class ModelOutputFields {
// 基础贷款信息
/** 贷款合同号 */
private String loanContractId;
/** 客户内码 */
private String custIsn;
/** 客户类型 */
private String custType;
/** 客户年龄 */
private String custAge;
/** 贷款金额 */
private String loanAmount;
/** 贷款利率 */
private String loanRate;
/** 贷款日期 */
private String loanDate;
/** 贷款类型 */
private String loanType;
/** 贷款用途 */
private String loanPurpose;
// 客户属性
/** 个人核心用户 */
private String isKeyClient;
/** 我行首贷客户 */
private String isFirstLoan;
/** 用信天数 */
private String faithDay;
// BP相关指标
/** BP_首贷 */
private String bpFirstLoan;
/** BP_贷龄 */
private String bpAgeLoan;
/** BP_年龄 */
private String bpAge;
/** TOTAL_BP_忠诚度 */
private String totalBpLoyalty;
// 存款相关指标
/** 借款个人年日均 */
private String perAvg;
/** 借款个人特殊类存款 */
private String perSp;
/** 配偶_子女年日均 */
private String perFmyAvg;
/** 配偶_子女特殊类存款 */
private String perFmySp;
/** 个人对应企业年日均 */
private String perEntAvg;
/** 个人对应企业特殊类存款 */
private String perEntSp;
/** 企业年日均 */
private String entAvg;
/** 企业特殊类存款 */
private String entSp;
/** 企业法人年日均 */
private String entPerAvg;
/** 企业法人特殊类存款 */
private String entPerSp;
/** 企业法人配偶年日均 */
private String entPerFmyAvg;
/** 企业法人配偶特殊类存款 */
private String entPerFmySp;
/** 企业财务年日均 */
private String entFinAvg;
/** 企业财务特殊类存款 */
private String entFinSp;
/** 存款年日均 */
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 midPerCitizencard;
/** 中间业务_企业_企业互联 */
private String midEntConnect;
/** 中间业务_企业_有效价值客户 */
private String midEntEffect;
/** 中间业务_企业_职工缴纳公积金 */
private String midEntPublicFund;
/** 中间业务_企业_电费代扣 */
private String midEntEleDdc;
/** 中间业务_企业_水费代扣 */
private String midEntWaterDdc;
/** 中间业务_企业_税务代扣 */
private String midEntTax;
/** BP_中间业务 */
private String bpMid;
// 代发工资相关
/** 代发工资户数 */
private String payroll;
/** BP_代发工资 */
private String bpPayroll;
// 企业属性相关
/** 净身企业 */
private String isCleanEnt;
/** 开立基本结算账户 */
private String hasSettleAcct;
/** 制造业企业 */
private String isManufacturing;
/** 省农担担保贷款 */
private String isAgriGuar;
/** 纳税信用等级 */
private String isTaxA;
/** 县级(含)以上农业龙头企业和示范性专业合作社 */
private String isAgriLeading;
/** BP_企业客户类别 */
private String bpEntType;
// 关联度相关
/** TOTAL_BP_关联度 */
private String totalBpRelevance;
// 风控相关
/** 经营佐证 */
private String bizProof;
/** 抵质押物类型 */
private String collType;
/** 灰名单客户 */
private String greyCust;
/** 本金逾期 */
private String prinOverdue;
/** 利息逾期 */
private String interestOverdue;
/** 信用卡逾期 */
private String cardOverdue;
/** BP_贷款额度 */
private String bpLoanAmount;
/** BP_贷款用途 */
private String bpLoanUse;
/** BP_抵押物 */
private String bpCollateral;
/** BP_灰名单与逾期 */
private String bpGreyOverdue;
/** TOTAL_BP_风险度 */
private String totalBpRisk;
/** TOTAL_BP */
private String totalBp;
/** 抵质押物是否三方所有 */
private String collThirdParty;
/** 担保方式 */
private String guarType;
/** 存量贷款余额 */
private String invLoanAmount;
/** 测算利率 */
private String calculateRate;
private String baseLoanRate; // 基础利率
private String minRateBranch; // 支行最低利率
private String minRateProduct; // 最低利率
}

View File

@@ -0,0 +1,32 @@
package com.ruoyi.loanratepricing.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* @Author 吴凯程
* @Date 2025/12/24
**/
@Data
public class FinalRateAdjustVO {
private String applicationId;
private BigDecimal branchBalance;
private BigDecimal outletBalance;
private BigDecimal managerBalance;
private BigDecimal branchUsage;
private BigDecimal outletUsage;
private BigDecimal managerUsage;
private BigDecimal profitAmt;
// 审批状态
private String approvalStatus; // 审批状态 0不需要审批 1需要审批
private String approvalLevel; // 审批层级 0不需要审批 1网点 2支行
}

View File

@@ -0,0 +1,20 @@
package com.ruoyi.loanratepricing.domain.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* @Author 吴凯程
* @Date 2025/12/24
**/
@Data
public class OptPoolBalance {
private BigDecimal branchBalance;
private BigDecimal outletBalance;
private BigDecimal managerBalance;
}

View File

@@ -0,0 +1,79 @@
package com.ruoyi.loanratepricing.service;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
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 lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* @Author 吴凯程
* @Date 2025/12/11
**/
@Service
@Slf4j
public class ModelService {
@Resource
private RatePricingProperties ratePricingProperties;
@Resource
private RedisCache redisCache;
public ModelOutputFields invokeModel(ModelInvokeDTO modelInvokeDTO) {
Map<String, String> requestBody = entityToMap(modelInvokeDTO);
JSONObject response = HttpUtils.doPostFormUrlEncoded(ratePricingProperties.getModelUrl(), 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);
}else{
log.error("------------------->调用模型失败,失败原因为:" + response.getString("message"));
throw new ServiceException("调用模型失败");
}
}
/**
* 使用FastJSON将实体类转换为Map<String, String>
* @param obj 待转换的实体类对象
* @return 转换后的Map
*/
public static Map<String, String> entityToMap(Object obj) {
if (obj == null) {
return null;
}
// 先转为JSON字符串再转换为指定类型的Map
String jsonStr = JSON.toJSONString(obj);
return JSON.parseObject(jsonStr, new TypeReference<Map<String, String>>() {});
}
private void replaceIndicatorToVariableName(JSONObject jsonObject) {
List<SysDictData> 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());
}
});
}
}

View File

@@ -0,0 +1,149 @@
package com.ruoyi.loanratepricing.service;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.loanratepricing.domain.RatePricingProperties;
import com.ruoyi.loanratepricing.domain.dto.LoanPricingApplySubmitDTO;
import com.ruoyi.loanratepricing.domain.dto.OptInvokeDTO;
import com.ruoyi.loanratepricing.domain.entity.LoanPricingApply;
import com.ruoyi.loanratepricing.domain.vo.OptPoolBalance;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* @Author 吴凯程
* @Date 2025/12/23
**/
@Service
@Slf4j
public class OptService {
@Resource
private RatePricingProperties ratePricingProperties;
public JSONObject submitApplication(OptInvokeDTO optInvokeDTO) {
JSONObject json = (JSONObject) JSON.toJSON(optInvokeDTO);
JSONObject response = HttpUtils.doPostJson(ratePricingProperties.getOaUrl() + ratePricingProperties.getApplicationSubmitUrl(), json, null, JSONObject.class);
log.info("------------>发起利率定价申请:" + JSON.toJSONString(response));
if(Objects.nonNull(response) && response.containsKey("code") && response.getInteger("code") == 0){
return response.getJSONObject("data");
}else{
log.error("申请利率定价流程失败" + response.toJSONString());
throw new ServiceException("提交利率定价流程失败:" + response.toJSONString());
}
}
public String submitRatePricingResult(LoanPricingApply loanPricingApply) {
LoanPricingApplySubmitDTO loanPricingApplySubmitDTO = new LoanPricingApplySubmitDTO();
BeanUtils.copyProperties(loanPricingApply, loanPricingApplySubmitDTO);
loanPricingApplySubmitDTO.setApplicationId(Long.parseLong(loanPricingApply.getApplicationId()));
JSONObject json = (JSONObject) JSON.toJSON(loanPricingApplySubmitDTO);
JSONObject response = HttpUtils.doPostJson(ratePricingProperties.getOaUrl() + ratePricingProperties.getPricingResultUrl(), json, null, JSONObject.class);
log.info("------------>提交利率定价申请:" + JSON.toJSONString(response));
if(Objects.nonNull(response) && response.containsKey("code") && response.getInteger("code") == 0){
return "提交利率定价结果成功";
}else{
log.error("提交利率定价结果失败"+ response.toJSONString());
throw new ServiceException("提交利率定价结果失败"+ response.toJSONString());
}
}
public LoanPricingApply queryLoanPricingApply(String applicationId){
Map<String, String> requestParam = new HashMap<>();
requestParam.put("id", applicationId);
JSONObject response = HttpUtils.doGet(ratePricingProperties.getOaUrl() + ratePricingProperties.getGetApplicationUrl(), requestParam, null, JSONObject.class);
log.info("------------>查询利率定价申请信息:" + JSON.toJSONString(response));
if(Objects.nonNull(response) && response.containsKey("code") && response.getInteger("code") == 0){
JSONObject data = response.getJSONObject("data");
return JSON.parseObject(data.toJSONString(), LoanPricingApply.class);
}else{
log.error("查询利率定价申请信息失败"+ response.toJSONString());
throw new ServiceException("查询利率定价申请信息失败"+ response.toJSONString());
}
}
public OptPoolBalance queryPoolBalance(String userCode){
Map<String, String> requestParam = new HashMap<>();
requestParam.put("ownerId", userCode);
requestParam.put("year", getCurrentYear());
requestParam.put("quarter", getCurrentQuarter());
JSONObject response = HttpUtils.doGet(ratePricingProperties.getOaUrl() + ratePricingProperties.getPoolBalanceUrl(), requestParam, null, JSONObject.class);
log.info("------------>查询议价池:" + JSON.toJSONString(response));
if(Objects.nonNull(response) && response.containsKey("code") && response.getInteger("code") == 0){
OptPoolBalance optPoolBalance = new OptPoolBalance();
JSONObject data = response.getJSONObject("data");
if (Objects.isNull(data)){
log.error("查询议价池失败" + response.toJSONString());
return optPoolBalance;
}
if(data.containsKey("branch")){
JSONObject branch = data.getJSONObject("branch");
if(branch.containsKey("availableQuota")){
BigDecimal availableQuota = new BigDecimal(branch.getString("availableQuota"));
optPoolBalance.setBranchBalance(availableQuota);
}else{
optPoolBalance.setBranchBalance(BigDecimal.ZERO);
}
}else{
optPoolBalance.setBranchBalance(BigDecimal.ZERO);
}
if(data.containsKey("network")){
JSONObject network = data.getJSONObject("network");
if(network.containsKey("availableQuota")){
BigDecimal availableQuota = new BigDecimal(network.getString("availableQuota"));
optPoolBalance.setOutletBalance(availableQuota);
}else{
optPoolBalance.setOutletBalance(BigDecimal.ZERO);
}
}else{
optPoolBalance.setOutletBalance(BigDecimal.ZERO);
}
if(data.containsKey("manager")){
JSONObject manager = data.getJSONObject("manager");
if(manager.containsKey("availableQuota")){
BigDecimal availableQuota = new BigDecimal(manager.getString("availableQuota"));
optPoolBalance.setManagerBalance(availableQuota);
}else{
optPoolBalance.setManagerBalance(BigDecimal.ZERO);
}
}else{
optPoolBalance.setManagerBalance(BigDecimal.ZERO);
}
return optPoolBalance;
}else{
log.error("查询议价池失败" + response.toJSONString());
throw new ServiceException("查询议价池失败" + response.toJSONString());
}
}
private String getCurrentYear(){
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
return Integer.toString(year);
}
private String getCurrentQuarter(){
Calendar calendar = Calendar.getInstance();
int quarter = (calendar.get(Calendar.MONTH) + 3) / 3;
return Integer.toString(quarter);
}
}

View File

@@ -0,0 +1,168 @@
package com.ruoyi.loanratepricing.service;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.loanratepricing.domain.dto.FinalRateAdjustDTO;
import com.ruoyi.loanratepricing.domain.dto.FinalRateSubmitDTO;
import com.ruoyi.loanratepricing.domain.dto.ModelInvokeDTO;
import com.ruoyi.loanratepricing.domain.dto.OptInvokeDTO;
import com.ruoyi.loanratepricing.domain.entity.LoanPricingApply;
import com.ruoyi.loanratepricing.domain.entity.ModelOutputFields;
import com.ruoyi.loanratepricing.domain.vo.FinalRateAdjustVO;
import com.ruoyi.loanratepricing.domain.vo.OptPoolBalance;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;
/**
* @Author 吴凯程
* @Date 2025/12/23
**/
@Service
@Slf4j
public class RatePricingService {
@Resource
private RedisCache redisCache;
@Resource
private OptService optService;
@Resource
private ModelService modelService;
private static String APPLICATION_ID_PREFIX = "LOAN_RATE_PRICING_APPLICATION_";
/**
* 创建利率测算申请
* 1. 表单信息提交
* 2. 调用行社流程发起接口取得applicationId
* 3. 调用模型测算接口,获取大部分字段
* 4. 保存流程到redis
*
* @param optInvokeDTO
* @return
*/
public LoanPricingApply loadRatePricingApply(OptInvokeDTO optInvokeDTO){
LoanPricingApply loanPricingApply;
if (Objects.isNull(optInvokeDTO.getApplicationId())){
JSONObject response = optService.submitApplication(optInvokeDTO);
String applicationId = response.getString("applicationId");
ModelInvokeDTO modelInvokeDTO = new ModelInvokeDTO();
BeanUtils.copyProperties(optInvokeDTO, modelInvokeDTO);
modelInvokeDTO.setRunType("1");
modelInvokeDTO.setSerialNum(applicationId);
modelInvokeDTO.setMidEntEleDdc(response.getString("midEntEleDdc"));
modelInvokeDTO.setMidEntWaterDdc(response.getString("midEntWaterDdc"));
modelInvokeDTO.setMidPerEleDdc(response.getString("midPerEleDdc"));
modelInvokeDTO.setMidPerQuickPay(response.getString("midPerQuickPay"));
ModelOutputFields modelOutputFields = modelService.invokeModel(modelInvokeDTO);
loanPricingApply = new LoanPricingApply();
BeanUtils.copyProperties(optInvokeDTO, loanPricingApply);
BeanUtils.copyProperties(modelOutputFields, loanPricingApply);
log.info("--------------->applicationId:{}",applicationId);
loanPricingApply.setApplicationId(applicationId);
redisCache.setCacheObject(APPLICATION_ID_PREFIX + applicationId, loanPricingApply);
}else{
if (redisCache.hasKey(APPLICATION_ID_PREFIX + optInvokeDTO.getApplicationId())){
loanPricingApply = redisCache.getCacheObject(APPLICATION_ID_PREFIX + optInvokeDTO.getApplicationId());
log.info("--------------->通过redis查询记录:{}", loanPricingApply);
}else{
loanPricingApply = optService.queryLoanPricingApply(optInvokeDTO.getApplicationId());
}
}
OptPoolBalance optPoolBalance = optService.queryPoolBalance(loanPricingApply.getApplyUserCode());
BeanUtils.copyProperties(optPoolBalance, loanPricingApply);
log.info("--------------->获取记录:{}", loanPricingApply);
return loanPricingApply;
}
public FinalRateAdjustVO invokeFinalRate(FinalRateAdjustDTO finalRateAdjustDTO){
if (!redisCache.hasKey(APPLICATION_ID_PREFIX + finalRateAdjustDTO.getApplicationId())){
throw new ServiceException("利率定价申请信息不存在,请重新发起");
}
LoanPricingApply loanPricingApply = redisCache.getCacheObject(APPLICATION_ID_PREFIX + finalRateAdjustDTO.getApplicationId());
if (Objects.isNull(loanPricingApply.getMinRateBranch())){
throw new ServiceException("利率定价模型信息不存在,请重新发起");
}
FinalRateAdjustVO finalRateAdjustVO = new FinalRateAdjustVO();
OptPoolBalance optPoolBalance = optService.queryPoolBalance(loanPricingApply.getApplyUserCode());
BeanUtils.copyProperties(optPoolBalance, finalRateAdjustVO);
BigDecimal minRateBranch = new BigDecimal(loanPricingApply.getMinRateBranch());
if (finalRateAdjustDTO.getFinalRate().compareTo(minRateBranch) < 0){
BigDecimal interestAmt = new BigDecimal(loanPricingApply.getApplyAmt()).multiply(minRateBranch.subtract(finalRateAdjustDTO.getFinalRate()));
BigDecimal totalBalance = optPoolBalance.getBranchBalance().add(optPoolBalance.getOutletBalance()).add(optPoolBalance.getManagerBalance());
if (interestAmt.compareTo(totalBalance) > 0){
throw new ServiceException("总利息大于可用余额,无法进行定价");
}
if (optPoolBalance.getManagerBalance().compareTo(BigDecimal.ZERO) > 0 && interestAmt.compareTo(BigDecimal.ZERO) > 0){
finalRateAdjustVO.setApprovalStatus("0");
finalRateAdjustVO.setApprovalLevel("0");
BigDecimal managerUsage = interestAmt.compareTo(optPoolBalance.getManagerBalance()) > 0 ? optPoolBalance.getManagerBalance() : interestAmt;
finalRateAdjustVO.setManagerUsage(managerUsage);
interestAmt = interestAmt.subtract(managerUsage);
}
if (optPoolBalance.getOutletBalance().compareTo(BigDecimal.ZERO) > 0 && interestAmt.compareTo(BigDecimal.ZERO) > 0){
finalRateAdjustVO.setApprovalStatus("1");
finalRateAdjustVO.setApprovalLevel("1");
BigDecimal outletUsage = interestAmt.compareTo(optPoolBalance.getOutletBalance()) > 0 ? optPoolBalance.getOutletBalance() : interestAmt;
finalRateAdjustVO.setOutletUsage(outletUsage);
interestAmt = interestAmt.subtract(outletUsage);
}else{
finalRateAdjustVO.setOutletUsage(BigDecimal.ZERO);
}
if (optPoolBalance.getBranchBalance().compareTo(BigDecimal.ZERO) > 0 && interestAmt.compareTo(BigDecimal.ZERO) > 0){
finalRateAdjustVO.setApprovalStatus("1");
finalRateAdjustVO.setApprovalLevel("2");
BigDecimal branchUsage = interestAmt.compareTo(optPoolBalance.getBranchBalance()) > 0 ? optPoolBalance.getBranchBalance() : interestAmt;
finalRateAdjustVO.setBranchUsage(branchUsage);
interestAmt = interestAmt.subtract(branchUsage);
}else{
finalRateAdjustVO.setBranchUsage(BigDecimal.ZERO);
}
finalRateAdjustVO.setProfitAmt(BigDecimal.ZERO);
}else {
finalRateAdjustVO.setApprovalStatus("0");
finalRateAdjustVO.setApprovalLevel("0");
finalRateAdjustVO.setManagerUsage(BigDecimal.ZERO);
finalRateAdjustVO.setOutletUsage(BigDecimal.ZERO);
finalRateAdjustVO.setBranchUsage(BigDecimal.ZERO);
finalRateAdjustVO.setProfitAmt(new BigDecimal(loanPricingApply.getApplyAmt()).multiply(finalRateAdjustDTO.getFinalRate().subtract(minRateBranch)).divide(BigDecimal.valueOf(6), 4, RoundingMode.HALF_UP));
}
return finalRateAdjustVO;
}
public String submitFinalRate(FinalRateSubmitDTO finalRateSubmitDTO){
LoanPricingApply loanPricingApply;
if (redisCache.hasKey(APPLICATION_ID_PREFIX + finalRateSubmitDTO.getApplicationId())){
loanPricingApply = redisCache.getCacheObject(APPLICATION_ID_PREFIX + finalRateSubmitDTO.getApplicationId());
}else{
loanPricingApply = optService.queryLoanPricingApply(finalRateSubmitDTO.getApplicationId());
}
if (Objects.isNull(loanPricingApply.getMinRateBranch())){
throw new ServiceException("利率定价模型信息不存在,请重新发起");
}
BeanUtils.copyProperties(finalRateSubmitDTO, loanPricingApply);
redisCache.setCacheObject(APPLICATION_ID_PREFIX + loanPricingApply.getApplicationId(), loanPricingApply);
return optService.submitRatePricingResult(loanPricingApply);
}
public LoanPricingApply queryLoanPricingApplyFromRedis(Long applicationId){
if (redisCache.hasKey(APPLICATION_ID_PREFIX + applicationId)){
return redisCache.getCacheObject(APPLICATION_ID_PREFIX + applicationId);
}
return null;
}
}

View File

@@ -0,0 +1,94 @@
{
"traceId": "350626558347246735E7F4722CUZRWOMNRR53O0",
"cost": 2267,
"tokenId": "17364055486305E7F4722M8IPFWNL8TOBEB",
"mappingOutputFields": {
"custIsn": "C20250109001",
"custType": "企业",
"guarType": "省农担担保",
"custName": "浙江绿源农业发展有限公司",
"idType": "统一社会信用代码",
"loanRate": "4.35",
"isKeyClient": "1",
"isFirstLoan": "0",
"faithDay": "210",
"custAge": "6",
"bpFirstLoan": "12",
"bpAgeLoan": "6",
"bpAge": "4",
"totalBpLoyalty": "22",
"perAvg": "80000",
"perSp": "15000",
"perFmyAvg": "45000",
"perFmySp": "8000",
"perEntAvg": "250000",
"perEntSp": "60000",
"entAvg": "1200000",
"entSp": "250000",
"entPerAvg": "90000",
"entPerSp": "20000",
"entPerFmyAvg": "50000",
"entPerFmySp": "10000",
"entFinAvg": "70000",
"entFinSp": "15000",
"balanceAvg": "1843000",
"loanAvg": "950000",
"derivationRate": "1.94",
"totalBpContribution": "28",
"midPerCard": "1",
"midPerPass": "1",
"midPerHarvest": "1",
"midPerEffect": "0",
"midPerQuickPay": "0",
"midPerEleDdc": "0",
"midPerCitizencard": "1",
"midEntConnect": "1",
"midEntEffect": "1",
"midEntPublicFund": "0",
"midEntEleDdc": "0",
"midEntWaterDdc": "0",
"midEntTax": "1",
"bpMid": "15",
"payroll": "200",
"invLoanAmount": "6000000",
"bpPayroll": "10",
"isCleanEnt": "1",
"hasSettleAcct": "0",
"isManufacturing": "1",
"isAgriGuar": "0",
"isTaxA": "0",
"isAgriLeading": "0",
"bpEntType": "18",
"totalBpRelevance": "28",
"applyAmt": "1500000",
"bpLoanAmount": "8",
"loanPurpose": "农产品种植与加工",
"bizProof": "有",
"bpLoanUse": "10",
"collType": "农业设施抵押",
"collThirdParty": "1",
"bpCollateral": "12",
"greyCust": "1",
"prinOverdue": "无",
"interestOverdue": "无",
"cardOverdue": "无",
"bpGreyOverdue": "0",
"totalBpRisk": "0",
"totalBp": "50",
"calculateRate": "4.28",
"baseLoanRate": "3.85",
"minRateBranch": "3.78",
"minRateProduct": "3.70"
},
"extensionMap": {},
"reasonMessage": "Running successfully",
"bizTime": 1736405548630,
"outputFields": {},
"workflowCode": "TBKH",
"orgCode": "802000",
"bizId": "2025010914345",
"reasonCode": 200,
"workflowVersion": 14,
"callTime": 1736405548630,
"status": 1
}

View File

@@ -0,0 +1,47 @@
{
"branch": {
"poolNo": "BR2025Q4001",
"poolType": "PUBLIC",
"ownerId": "B0010001",
"ownerName": "北京市朝阳区支行",
"ownerType": "BRANCH",
"year": "2025",
"quarter": "4",
"status": "1",
"totalQuota": "10000000.00",
"usedQuota": "6528000.50",
"availableQuota": "3471999.50",
"frozenQuota": "0.00",
"usageRate": "65.28"
},
"network": {
"poolNo": "NW2025Q4008",
"poolType": "PRIVATE",
"ownerId": "N0080012",
"ownerName": "北京市朝阳区建国路网点",
"ownerType": "NETWORK",
"year": "2025",
"quarter": "4",
"status": "1",
"totalQuota": "2000000.00",
"usedQuota": "1268900.30",
"availableQuota": "731099.70",
"frozenQuota": "0.00",
"usageRate": "63.45"
},
"manager": {
"poolNo": "MG2025Q4099",
"poolType": "PRIVATE",
"ownerId": "M0990045",
"ownerName": "张三",
"ownerType": "MANAGER",
"year": "2025",
"quarter": "4",
"status": "1",
"totalQuota": "500000.00",
"usedQuota": "389600.80",
"availableQuota": "110399.20",
"frozenQuota": "0.00",
"usageRate": "77.92"
}
}