Commit 88cc84b5 authored by data-爬虫-任锋's avatar data-爬虫-任锋

资产分发添加助贷资金导流

parent 05628c06
package com.quantgroup.asset.distribution.service.asset.impl; package com.quantgroup.asset.distribution.service.asset.impl;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.quantgroup.asset.distribution.model.entity.fund.ChannelFundConfigNew;
import com.quantgroup.asset.distribution.service.funding.IFundModuleChannelFundConfigNewService;
import com.quantgroup.asset.distribution.service.jpa.entity.FundModuleChannelFundConfigNew;
import com.quantgroup.asset.distribution.service.rule.vo.IRuleVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Stopwatch; import com.google.common.base.Stopwatch;
import com.quantgroup.asset.distribution.config.annotation.Attribute; import com.quantgroup.asset.distribution.config.annotation.Attribute;
import com.quantgroup.asset.distribution.enums.ExecuteType;
import com.quantgroup.asset.distribution.enums.response.AssetResponse; import com.quantgroup.asset.distribution.enums.response.AssetResponse;
import com.quantgroup.asset.distribution.exception.QGException; import com.quantgroup.asset.distribution.exception.QGException;
import com.quantgroup.asset.distribution.exception.QGExceptionType; import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.model.entity.fund.ChannelFundConfig;
import com.quantgroup.asset.distribution.model.form.AssetForm; import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.GlobalResponse; import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.service.alarm.IAlarmService; import com.quantgroup.asset.distribution.service.alarm.IAlarmService;
...@@ -39,14 +16,19 @@ import com.quantgroup.asset.distribution.service.asset.IAssetAttributeService; ...@@ -39,14 +16,19 @@ import com.quantgroup.asset.distribution.service.asset.IAssetAttributeService;
import com.quantgroup.asset.distribution.service.asset.IAssetService; import com.quantgroup.asset.distribution.service.asset.IAssetService;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeService; import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeService;
import com.quantgroup.asset.distribution.service.distribute.IDistributeFailLogService; import com.quantgroup.asset.distribution.service.distribute.IDistributeFailLogService;
import com.quantgroup.asset.distribution.service.funding.IFundModuleChannelFundConfigService;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset; import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetAttributeExtendConfig; import com.quantgroup.asset.distribution.service.jpa.entity.AssetAttributeExtendConfig;
import com.quantgroup.asset.distribution.service.jpa.entity.FundModuleChannelFundConfig;
import com.quantgroup.asset.distribution.service.product.IFinanceProductHitLogService;
import com.quantgroup.asset.distribution.service.rule.IRuleService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/** /**
* 资产Service * 资产Service
...@@ -67,14 +49,6 @@ public class AssetServiceImpl implements IAssetService{ ...@@ -67,14 +49,6 @@ public class AssetServiceImpl implements IAssetService{
private IAlarmService alarmService; private IAlarmService alarmService;
@Autowired @Autowired
private IDistributeFailLogService distributeFailLogService; private IDistributeFailLogService distributeFailLogService;
@Autowired
private IFundModuleChannelFundConfigNewService fundModuleChannelFundConfigNewService;
@Autowired
private IRuleService ruleService;
@Autowired
private IFinanceProductHitLogService financeProductHitLogService;
private static final ExecutorService executorPool = Executors.newFixedThreadPool(100);
@Async @Async
...@@ -92,12 +66,6 @@ public class AssetServiceImpl implements IAssetService{ ...@@ -92,12 +66,6 @@ public class AssetServiceImpl implements IAssetService{
assetAttributeService.saveAssetAttrubite(asset, assetAttributeExtendConfigList, data); assetAttributeService.saveAssetAttrubite(asset, assetAttributeExtendConfigList, data);
// 把资产基础属性值放入data // 把资产基础属性值放入data
data = addAssetAttributeToData(asset, data); data = addAssetAttributeToData(asset, data);
// 资方配置空跑
doTestExecute(JSON.parseObject(JSON.toJSONString(assetForm), AssetForm.class), data);
// 如果使用资方模块则去命中资方,创建金融产品集
String hitFinanceProduct = hitFundIfUseFundModule(assetForm, data, ExecuteType.ONLINE);
// 资方模块结果处理
checkFundResult(assetForm, hitFinanceProduct);
// 资产分发 // 资产分发
assetDistributeService.distribute(assetForm, asset, data); assetDistributeService.distribute(assetForm, asset, data);
log.info("资产分发完成, uuid : {}, bizNo : {}, assetNo : {}, bizChannel : {}, 耗时 : {}", assetForm.getUuid(), log.info("资产分发完成, uuid : {}, bizNo : {}, assetNo : {}, bizChannel : {}, 耗时 : {}", assetForm.getUuid(),
...@@ -222,194 +190,4 @@ public class AssetServiceImpl implements IAssetService{ ...@@ -222,194 +190,4 @@ public class AssetServiceImpl implements IAssetService{
return sb.toString(); return sb.toString();
} }
/**
* 如果使用资方模块,需要去命中资方
* @param assetForm
*/
public String hitFundIfUseFundModule(AssetForm assetForm, Map<String, Object> data, ExecuteType executeType) {
// 如果auditResult为true, amount或term有一个为空, 那就不管是否是测试,都不能使用资方模块了
// 同时兼容量子魔方白名单,白名单的没有期数直接返回
if ("true".equals(assetForm.getAuditResult()) && (StringUtils.isEmpty(assetForm.getAmount()) || StringUtils.isEmpty(assetForm.getTerm()))) {
return null;
}
FundModuleChannelFundConfigNew config = fundModuleChannelFundConfigNewService.findByBizChannel(assetForm.getBizChannel());
// 未找到资方渠道配置直接通知
if (config == null) {
return null;
}
QGPreconditions.checkArgument(config != null, QGExceptionType.NOT_FOUNT_CHANNEL_FUNDS_INFO, assetForm.getBizChannel());
JSONArray fundArray = new JSONArray();
// 资方去重, 可能存在多条件同一个资方
Set<String> fundSet = new HashSet<>();
List<ChannelFundConfigNew> fundConfigList = JSONArray.parseArray(config.getFunds(), ChannelFundConfigNew.class);
A : for (ChannelFundConfigNew channelFundConfig : fundConfigList) {
IRuleVO ruleVO = ruleService.getIRuleVo(channelFundConfig.getLimits());
if (ruleVO == null) { throw new QGException(QGExceptionType.CRATE_RULE_VO_ERROR); }
// 如果参数为空,直接不满足
Set<String> params = ruleVO.getParamNames();
for (String key : params) {
if (!data.containsKey(key)) {
continue A;
}
}
if (!ruleVO.valid(data)) {
continue A;
}
// 是否配了审核条件
boolean hasAuditResultLimit = params.contains("audit_result");
if (!hasAuditResultLimit) {
// 如果没配,自动过一层auditResult@true的条件
if (!ruleService.valid("audit_result==true", data)) {
continue A;
}
}
String key = channelFundConfig.getFundId() + "_" + channelFundConfig.getFundProductId() + "_" + channelFundConfig.getPriority();
if (!fundSet.contains(key)) {
// 创建并增加资方配置
JSONObject fundInfoJSON = new JSONObject();
fundInfoJSON.put("fundId", channelFundConfig.getFundId());
fundInfoJSON.put("fundProductId", channelFundConfig.getFundProductId());
fundInfoJSON.put("priority", channelFundConfig.getPriority());
fundInfoJSON.put("feeType", channelFundConfig.getFeeType());
fundInfoJSON.put("rateType", channelFundConfig.getRateType());
fundInfoJSON.put("rate", channelFundConfig.getRate());
fundArray.add(fundInfoJSON);
log.info("资方模块用户命中资方条件, uuid : {}, assetNo : {}, bizNo : {}, bizChannel : {}, fundId : {}, fundProductId : {}",
assetForm.getUuid(), assetForm.getAssetNo(), assetForm.getBizNo(), assetForm.getBizChannel(), channelFundConfig.getFundId(), channelFundConfig.getFundProductId());
fundSet.add(key);
}
}
// 如果审核拒绝,也没命中任何资方, 直接返回
if ("false".equals(assetForm.getAuditResult()) && fundArray.size() == 0) {
return null;
}
QGPreconditions.checkArgument(fundArray.size() != 0, QGExceptionType.NO_FUND_INFO_BEEN_HIT, assetForm.getBizChannel(), assetForm.getAmount(), assetForm.getTerm());
// 看命中优先级是否符合要求
boolean[] bucket = new boolean[fundArray.size() + 1];
for (int i = 0, len = fundArray.size(); i < len; i++) {
int priority = fundArray.getJSONObject(i).getIntValue("priority");
if (!(priority > 0 && priority <= len)) {
throw new QGException(QGExceptionType.FUND_PRIORITY_IS_ERROR, assetForm.getBizChannel(), assetForm.getAmount(), assetForm.getTerm());
}
if (bucket[priority]) {
// 多个相同的优先级
throw new QGException(QGExceptionType.FUND_PRIORITY_IS_ERROR, assetForm.getBizChannel(), assetForm.getAmount(), assetForm.getTerm());
}
bucket[priority] = true;
}
String hitFinanceProduct = createFinancePro(assetForm, fundArray);
log.info("资方模块组成金融产品集完成, uuid : {}, assetNo : {}, bizNo : {}, bizChannel : {}, financeProduct : {}, executeType : {}", assetForm.getUuid(), assetForm.getAssetNo(), assetForm.getBizNo(), assetForm.getBizChannel(), hitFinanceProduct, executeType.name());
return hitFinanceProduct;
}
/**
* 资方模块命中后结果处理
* @param assetForm
* @param hitFinanceProduct
* @return
*/
private AssetForm checkFundResult(AssetForm assetForm, String hitFinanceProduct) {
if (hitFinanceProduct == null) {
if ("false".equals(assetForm.getAuditResult())) {
// 把传过来的额度和期数处理为null
assetForm.setAmount(null);
assetForm.setTerm(null);
}
return assetForm;
}
// 金融产品集替换
String oldFinanceProduct = assetForm.getFinanceProducts();
assetForm.setFinanceProducts(hitFinanceProduct);
// 审核结果替换
String oldAuditResult = assetForm.getAuditResult();
if ("false".equals(oldAuditResult)) {
assetForm.setAuditResult("true");
}
// 保存日志
financeProductHitLogService.saveLog(assetForm, oldFinanceProduct, hitFinanceProduct, oldAuditResult, assetForm.getAuditResult(), ExecuteType.ONLINE);
log.info("资方命中后,审核最终结果, assetForm : {}", JSON.toJSONString(assetForm));
return assetForm;
}
/**
* 组建金融产品集
* @param assetForm
* @param fundArray
* @return
*/
private String createFinancePro(AssetForm assetForm, JSONArray fundArray) {
// 首先判断是否有额度期数
QGPreconditions.checkArgument(StringUtils.isNotEmpty(assetForm.getAmount()) && StringUtils.isNotEmpty(assetForm.getTerm()), QGExceptionType.HIT_FUND_BUT_AMOUNT_OR_TERM_IS_EMPTY);
JSONArray financeProductArray = new JSONArray();
JSONObject amountJSON = new JSONObject();
financeProductArray.add(amountJSON);
amountJSON.put("min", assetForm.getAmount());
amountJSON.put("max", assetForm.getAmount());
JSONArray termArray = new JSONArray();
amountJSON.put("terms", termArray);
JSONObject termJSON = new JSONObject();
termArray.add(termJSON);
try {
// 不能是string,否则资方那边会报错
termJSON.put("term", Integer.parseInt(assetForm.getTerm()));
} catch (Exception e) {
termJSON.put("term", Double.parseDouble(assetForm.getTerm()));
}
termJSON.put("fundInfo", fundArray);
return JSON.toJSONString(financeProductArray);
}
/**
* 资方配置空跑
* @param testAssetForm
* @param data
*/
private void doTestExecute(AssetForm assetForm, Map<String, Object> data) {
executorPool.execute(() -> {
try {
assetForm.setBizChannel("88888_" + assetForm.getBizChannel());
String hitFundPro = hitFundIfUseFundModule(assetForm, data, ExecuteType.TEST);
if (hitFundPro != null) {
// 如果命中了记录一下,并且如果审核状态为false改为true
String oldFundPro = assetForm.getFinanceProducts();
String oldAuditResult = assetForm.getAuditResult();
assetForm.setFinanceProducts(hitFundPro);
assetForm.setAuditResult("true");
financeProductHitLogService.saveLog(assetForm, oldFundPro, hitFundPro, oldAuditResult, assetForm.getAuditResult(), ExecuteType.TEST);
} else {
// 如果没命中,且审核结果未false
if ("false".equals(assetForm.getAuditResult())) {
// 把传过来的额度和期数处理为null
assetForm.setAmount(null);
assetForm.setTerm(null);
}
}
log.info("空跑审核最终结果, assetForm : {}", JSON.toJSONString(assetForm));
} catch (QGException qe) {
log.error("资方配置执行空跑出现错误 : {}, uuid : {}, bizChannel : {}, bizType : {}, bizNo : {}, assetNo : {} ",
qe.qgExceptionType.code + "->" + qe.detail, assetForm.getUuid(),
assetForm.getBizChannel(), assetForm.getBizType(),
assetForm.getBizNo(), assetForm.getAssetNo());
alarmService.dingtalkAlarm("Warn", "资方配置执行空跑出现错误", "bizChannel : " + assetForm.getBizChannel()
+ " , bizType : " + assetForm.getBizType() + " , bizNo : " + assetForm.getBizNo()
+ " , assetNo : " + assetForm.getAssetNo() + " , uuid : " + assetForm.getUuid()
+ " , 错误信息 : " + qe.qgExceptionType.code + "->" + qe.detail);
} catch (Exception ex) {
log.error("资方配置执行空跑出现异常, uuid : {}, bizChannel : {}, bizType : {}, bizNo : {}, assetNo : {} ", assetForm.getUuid(),
assetForm.getBizChannel(), assetForm.getBizType(),
assetForm.getBizNo(), assetForm.getAssetNo(), ex);
alarmService.dingtalkAlarm("Warn", "资方配置执行空跑出现异常", "bizChannel : " + assetForm.getBizChannel()
+ " , bizType : " + assetForm.getBizType() + " , bizNo : " + assetForm.getBizNo()
+ " , assetNo : " + assetForm.getAssetNo() + " , uuid : " + assetForm.getUuid()
+ " , 错误信息 : 未知错误.");
}
});
}
} }
package com.quantgroup.asset.distribution.service.distribute.impl; package com.quantgroup.asset.distribution.service.distribute.impl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
...@@ -20,10 +7,13 @@ import com.google.common.base.Stopwatch; ...@@ -20,10 +7,13 @@ import com.google.common.base.Stopwatch;
import com.quantgroup.asset.distribution.constant.DistributeConstants; import com.quantgroup.asset.distribution.constant.DistributeConstants;
import com.quantgroup.asset.distribution.constant.RedisKeyConstants; import com.quantgroup.asset.distribution.constant.RedisKeyConstants;
import com.quantgroup.asset.distribution.constant.StatusConstants; import com.quantgroup.asset.distribution.constant.StatusConstants;
import com.quantgroup.asset.distribution.enums.ExecuteType;
import com.quantgroup.asset.distribution.enums.funding.FundingResult; import com.quantgroup.asset.distribution.enums.funding.FundingResult;
import com.quantgroup.asset.distribution.exception.QGException; import com.quantgroup.asset.distribution.exception.QGException;
import com.quantgroup.asset.distribution.exception.QGExceptionType; import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.model.entity.DistributeRecord; import com.quantgroup.asset.distribution.model.entity.DistributeRecord;
import com.quantgroup.asset.distribution.model.entity.fund.ChannelFundConfigNew;
import com.quantgroup.asset.distribution.model.form.AssetForm; import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.GlobalResponse; import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.service.alarm.IAlarmService; import com.quantgroup.asset.distribution.service.alarm.IAlarmService;
...@@ -31,14 +21,27 @@ import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeReco ...@@ -31,14 +21,27 @@ import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeReco
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeRuleConfigService; import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeRuleConfigService;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeService; import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeService;
import com.quantgroup.asset.distribution.service.funding.IAidFundRouteService; import com.quantgroup.asset.distribution.service.funding.IAidFundRouteService;
import com.quantgroup.asset.distribution.service.funding.IFundModuleChannelFundConfigNewService;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset; import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetDistributeRecord; import com.quantgroup.asset.distribution.service.jpa.entity.AssetDistributeRecord;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetDistributeRuleConfig; import com.quantgroup.asset.distribution.service.jpa.entity.AssetDistributeRuleConfig;
import com.quantgroup.asset.distribution.service.jpa.entity.FundModuleChannelFundConfigNew;
import com.quantgroup.asset.distribution.service.notify.INotifyService; import com.quantgroup.asset.distribution.service.notify.INotifyService;
import com.quantgroup.asset.distribution.service.product.IFinanceProductHitLogService;
import com.quantgroup.asset.distribution.service.redis.IRedisService; import com.quantgroup.asset.distribution.service.redis.IRedisService;
import com.quantgroup.asset.distribution.service.rule.IRuleService; import com.quantgroup.asset.distribution.service.rule.IRuleService;
import com.quantgroup.asset.distribution.service.rule.vo.IRuleVO;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/** /**
* 资产分发Service * 资产分发Service
...@@ -59,8 +62,6 @@ public class AssetDistributeServiceImpl implements IAssetDistributeService{ ...@@ -59,8 +62,6 @@ public class AssetDistributeServiceImpl implements IAssetDistributeService{
@Autowired @Autowired
private IRedisService<Integer> redisService; private IRedisService<Integer> redisService;
@Autowired @Autowired
private IRuleService ruleService;
@Autowired
private IAidFundRouteService aidFundRouteService; private IAidFundRouteService aidFundRouteService;
@Autowired @Autowired
private INotifyService notifyService; private INotifyService notifyService;
...@@ -68,6 +69,14 @@ public class AssetDistributeServiceImpl implements IAssetDistributeService{ ...@@ -68,6 +69,14 @@ public class AssetDistributeServiceImpl implements IAssetDistributeService{
private IAssetDistributeRecordService assetDistributeRecordService; private IAssetDistributeRecordService assetDistributeRecordService;
@Autowired @Autowired
private IAlarmService alarmService; private IAlarmService alarmService;
@Autowired
private IFundModuleChannelFundConfigNewService fundModuleChannelFundConfigNewService;
@Autowired
private IRuleService ruleService;
@Autowired
private IFinanceProductHitLogService financeProductHitLogService;
private static final ExecutorService executorPool = Executors.newFixedThreadPool(4);
/** /**
* 分发 * 分发
...@@ -126,14 +135,26 @@ public class AssetDistributeServiceImpl implements IAssetDistributeService{ ...@@ -126,14 +135,26 @@ public class AssetDistributeServiceImpl implements IAssetDistributeService{
try { try {
switch (ruleType) { switch (ruleType) {
case DistributeConstants.RuleType.FUND_ROUTE: case DistributeConstants.RuleType.FUND_ROUTE:
// 资方配置空跑
doTestExecute(JSON.parseObject(JSON.toJSONString(assetForm), AssetForm.class), data);
// 如果使用资方模块则去命中资方,创建金融产品集
String hitFinanceProduct = hitFundIfUseFundModule(assetForm, data, ExecuteType.ONLINE);
// 资方模块结果处理
checkFundResult(assetForm, hitFinanceProduct);
if(StringUtils.isNotEmpty(hitFinanceProduct)) {
notifyService.notifyFundServer(assetForm, data); notifyService.notifyFundServer(assetForm, data);
return StatusConstants.WAIT; return StatusConstants.WAIT;
}
return StatusConstants.FAIL;
case DistributeConstants.RuleType.AID_FUND_ROUTE: { case DistributeConstants.RuleType.AID_FUND_ROUTE: {
GlobalResponse response = aidFundRouteService.aidFundRoute(assetForm, asset.getUserLoanType(), data); GlobalResponse response = aidFundRouteService.aidFundRoute(assetForm, asset.getUserLoanType(), data);
int status = response.getCode() == 0 ? StatusConstants.SUCCESS : StatusConstants.FAIL; int status = response.getCode() == 0 ? StatusConstants.SUCCESS : StatusConstants.FAIL;
//助贷资金路由 分配失败没有 mq消息 成功有
if(status==0){
// 助贷资金路由目前不从mq里接受终态 // 助贷资金路由目前不从mq里接受终态
assetDistributeRecord.setAssetDistributeStatus(status); assetDistributeRecord.setAssetDistributeStatus(status);
assetDistributeRecordService.updateAssetDistribute(assetDistributeRecord); assetDistributeRecordService.updateAssetDistribute(assetDistributeRecord);
}
return status; return status;
} }
case DistributeConstants.RuleType.DIVERSION: case DistributeConstants.RuleType.DIVERSION:
...@@ -225,4 +246,196 @@ public class AssetDistributeServiceImpl implements IAssetDistributeService{ ...@@ -225,4 +246,196 @@ public class AssetDistributeServiceImpl implements IAssetDistributeService{
" , 错误信息 : 未知错误"); " , 错误信息 : 未知错误");
} }
} }
/**
* 如果使用资方模块,需要去命中资方
* @param assetForm
*/
public String hitFundIfUseFundModule(AssetForm assetForm, Map<String, Object> data, ExecuteType executeType) {
// 如果auditResult为true, amount或term有一个为空, 那就不管是否是测试,都不能使用资方模块了
// 同时兼容量子魔方白名单,白名单的没有期数直接返回
if ("true".equals(assetForm.getAuditResult()) && (StringUtils.isEmpty(assetForm.getAmount()) || StringUtils.isEmpty(assetForm.getTerm()))) {
return null;
}
FundModuleChannelFundConfigNew config = fundModuleChannelFundConfigNewService.findByBizChannel(assetForm.getBizChannel());
// 未找到资方渠道配置直接通知
if (config == null) {
return null;
}
JSONArray fundArray = new JSONArray();
// 资方去重, 可能存在多条件同一个资方
Set<String> fundSet = new HashSet<>();
List<ChannelFundConfigNew> fundConfigList = JSONArray.parseArray(config.getFunds(), ChannelFundConfigNew.class);
A : for (ChannelFundConfigNew channelFundConfig : fundConfigList) {
IRuleVO ruleVO = ruleService.getIRuleVo(channelFundConfig.getLimits());
if (ruleVO == null) { throw new QGException(QGExceptionType.CRATE_RULE_VO_ERROR); }
// 如果参数为空,直接不满足
Set<String> params = ruleVO.getParamNames();
for (String key : params) {
if (!data.containsKey(key)) {
continue A;
}
}
if (!ruleVO.valid(data)) {
continue A;
}
// 是否配了审核条件
boolean hasAuditResultLimit = params.contains("audit_result");
if (!hasAuditResultLimit) {
// 如果没配,自动过一层auditResult@true的条件
if (!ruleService.valid("audit_result==true", data)) {
continue A;
}
}
String key = channelFundConfig.getFundId() + "_" + channelFundConfig.getFundProductId() + "_" + channelFundConfig.getPriority();
if (!fundSet.contains(key)) {
// 创建并增加资方配置
JSONObject fundInfoJSON = new JSONObject();
fundInfoJSON.put("fundId", channelFundConfig.getFundId());
fundInfoJSON.put("fundProductId", channelFundConfig.getFundProductId());
fundInfoJSON.put("priority", channelFundConfig.getPriority());
fundInfoJSON.put("feeType", channelFundConfig.getFeeType());
fundInfoJSON.put("rateType", channelFundConfig.getRateType());
fundInfoJSON.put("rate", channelFundConfig.getRate());
fundArray.add(fundInfoJSON);
log.info("资方模块用户命中资方条件, uuid : {}, assetNo : {}, bizNo : {}, bizChannel : {}, fundId : {}, fundProductId : {}",
assetForm.getUuid(), assetForm.getAssetNo(), assetForm.getBizNo(), assetForm.getBizChannel(), channelFundConfig.getFundId(), channelFundConfig.getFundProductId());
fundSet.add(key);
}
}
// 如果审核拒绝,也没命中任何资方, 直接返回
if ("false".equals(assetForm.getAuditResult()) && fundArray.size() == 0) {
return null;
}
QGPreconditions.checkArgument(fundArray.size() != 0, QGExceptionType.NO_FUND_INFO_BEEN_HIT, assetForm.getBizChannel(), assetForm.getAmount(), assetForm.getTerm());
// 看命中优先级是否符合要求
boolean[] bucket = new boolean[fundArray.size() + 1];
for (int i = 0, len = fundArray.size(); i < len; i++) {
int priority = fundArray.getJSONObject(i).getIntValue("priority");
if (!(priority > 0 && priority <= len)) {
throw new QGException(QGExceptionType.FUND_PRIORITY_IS_ERROR, assetForm.getBizChannel(), assetForm.getAmount(), assetForm.getTerm());
}
if (bucket[priority]) {
// 多个相同的优先级
throw new QGException(QGExceptionType.FUND_PRIORITY_IS_ERROR, assetForm.getBizChannel(), assetForm.getAmount(), assetForm.getTerm());
}
bucket[priority] = true;
}
String hitFinanceProduct = createFinancePro(assetForm, fundArray);
log.info("资方模块组成金融产品集完成, uuid : {}, assetNo : {}, bizNo : {}, bizChannel : {}, financeProduct : {}, executeType : {}", assetForm.getUuid(), assetForm.getAssetNo(), assetForm.getBizNo(), assetForm.getBizChannel(), hitFinanceProduct, executeType.name());
return hitFinanceProduct;
}
/**
* 资方模块命中后结果处理
* @param assetForm
* @param hitFinanceProduct
* @return
*/
private AssetForm checkFundResult(AssetForm assetForm, String hitFinanceProduct) {
if (hitFinanceProduct == null) {
if ("false".equals(assetForm.getAuditResult())) {
// 把传过来的额度和期数处理为null
assetForm.setAmount(null);
assetForm.setTerm(null);
}
return assetForm;
}
// 金融产品集替换
String oldFinanceProduct = assetForm.getFinanceProducts();
assetForm.setFinanceProducts(hitFinanceProduct);
// 审核结果替换
String oldAuditResult = assetForm.getAuditResult();
if ("false".equals(oldAuditResult)) {
assetForm.setAuditResult("true");
}
// 保存日志
financeProductHitLogService.saveLog(assetForm, oldFinanceProduct, hitFinanceProduct, oldAuditResult, assetForm.getAuditResult(), ExecuteType.ONLINE);
log.info("资方命中后,审核最终结果, assetForm : {}", JSON.toJSONString(assetForm));
return assetForm;
}
/**
* 组建金融产品集
* @param assetForm
* @param fundArray
* @return
*/
private String createFinancePro(AssetForm assetForm, JSONArray fundArray) {
// 首先判断是否有额度期数
QGPreconditions.checkArgument(StringUtils.isNotEmpty(assetForm.getAmount()) && StringUtils.isNotEmpty(assetForm.getTerm()), QGExceptionType.HIT_FUND_BUT_AMOUNT_OR_TERM_IS_EMPTY);
JSONArray financeProductArray = new JSONArray();
JSONObject amountJSON = new JSONObject();
financeProductArray.add(amountJSON);
amountJSON.put("min", assetForm.getAmount());
amountJSON.put("max", assetForm.getAmount());
JSONArray termArray = new JSONArray();
amountJSON.put("terms", termArray);
JSONObject termJSON = new JSONObject();
termArray.add(termJSON);
try {
// 不能是string,否则资方那边会报错
termJSON.put("term", Integer.parseInt(assetForm.getTerm()));
} catch (Exception e) {
termJSON.put("term", Double.parseDouble(assetForm.getTerm()));
}
termJSON.put("fundInfo", fundArray);
return JSON.toJSONString(financeProductArray);
}
/**
* 资方配置空跑
* @param assetForm
* @param data
*/
private void doTestExecute(AssetForm assetForm, Map<String, Object> data) {
executorPool.execute(() -> {
try {
assetForm.setBizChannel("88888_" + assetForm.getBizChannel());
String hitFundPro = hitFundIfUseFundModule(assetForm, data, ExecuteType.TEST);
if (hitFundPro != null) {
// 如果命中了记录一下,并且如果审核状态为false改为true
String oldFundPro = assetForm.getFinanceProducts();
String oldAuditResult = assetForm.getAuditResult();
assetForm.setFinanceProducts(hitFundPro);
assetForm.setAuditResult("true");
financeProductHitLogService.saveLog(assetForm, oldFundPro, hitFundPro, oldAuditResult, assetForm.getAuditResult(), ExecuteType.TEST);
} else {
// 如果没命中,且审核结果未false
if ("false".equals(assetForm.getAuditResult())) {
// 把传过来的额度和期数处理为null
assetForm.setAmount(null);
assetForm.setTerm(null);
}
}
log.info("空跑审核最终结果, assetForm : {}", JSON.toJSONString(assetForm));
} catch (QGException qe) {
log.error("资方配置执行空跑出现错误 : {}, uuid : {}, bizChannel : {}, bizType : {}, bizNo : {}, assetNo : {} ",
qe.qgExceptionType.code + "->" + qe.detail, assetForm.getUuid(),
assetForm.getBizChannel(), assetForm.getBizType(),
assetForm.getBizNo(), assetForm.getAssetNo());
alarmService.dingtalkAlarm("Warn", "资方配置执行空跑出现错误", "bizChannel : " + assetForm.getBizChannel()
+ " , bizType : " + assetForm.getBizType() + " , bizNo : " + assetForm.getBizNo()
+ " , assetNo : " + assetForm.getAssetNo() + " , uuid : " + assetForm.getUuid()
+ " , 错误信息 : " + qe.qgExceptionType.code + "->" + qe.detail);
} catch (Exception ex) {
log.error("资方配置执行空跑出现异常, uuid : {}, bizChannel : {}, bizType : {}, bizNo : {}, assetNo : {} ", assetForm.getUuid(),
assetForm.getBizChannel(), assetForm.getBizType(),
assetForm.getBizNo(), assetForm.getAssetNo(), ex);
alarmService.dingtalkAlarm("Warn", "资方配置执行空跑出现异常", "bizChannel : " + assetForm.getBizChannel()
+ " , bizType : " + assetForm.getBizType() + " , bizNo : " + assetForm.getBizNo()
+ " , assetNo : " + assetForm.getAssetNo() + " , uuid : " + assetForm.getUuid()
+ " , 错误信息 : 未知错误.");
}
});
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment