Commit 89aebf3b authored by liwenbin's avatar liwenbin

资产分发初始化代码

parent bc98d9e1
......@@ -320,6 +320,17 @@
<artifactId>protobuf-java-format</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>com.udojava</groupId>
<artifactId>EvalEx</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
</dependencies>
</project>
package com.quantgroup.asset.distribution.config.datasource;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import com.alibaba.druid.pool.DruidDataSource;
/**
* 数据库配置
* @author liwenbin
*
*/
@Configuration
public class DataSourceConfig {
@Value("${spring.datasource.primary.url}")
private String dbUrl;
@Value("${spring.datasource.primary.username}")
private String username;
@Value("${spring.datasource.primary.password}")
private String password;
@Value("${spring.datasource.primary.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.filters}")
private String filters;
@Value("{spring.datasource.connectionProperties}")
private String connectionProperties;
@Bean
@Primary
public DataSource primaryDataSource() throws SQLException {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
datasource.setFilters(filters);
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
@Bean
public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
......@@ -11,7 +11,7 @@ import org.springframework.web.servlet.ModelAndView;
import com.quantgroup.asset.distribution.enums.response.AuthorityResponse;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.service.IAuthorityService;
import com.quantgroup.asset.distribution.service.authority.IAuthorityService;
import com.quantgroup.asset.distribution.service.jpa.entity.AuthorityConfig;
import com.quantgroup.asset.distribution.service.jpa.repository.IAuthorityRepository;
......
package com.quantgroup.asset.distribution.constant;
/**
* 资产属性特征key常量值
* @author liwenbin
*
*/
public class AssetAttributeConstants {
/**
* 用户类型
*/
public static final String USER_LOAN_TYPE = "user_loan_type_latest";
/**
* 风控审核结果
*/
public static final String AUDIT_RESULT = "auditResult";
}
package com.quantgroup.asset.distribution.constant;
/**
* 分发相关常量值
* @author liwenbin
*
*/
public class DistributeConstants {
/**
* 分发规则类型常量
* @author liwenbin
*
*/
public static class RuleType {
/**
* 资金理由
*/
public static final int FUND_ROUTE = 1;
/**
* 助贷资金路由
*/
public static final int AID_FUND_ROUTE = 2;
/**
* 导流
*/
public static final int DIVERSION = 3;
}
}
package com.quantgroup.asset.distribution.constant;
/**
* 分发标识类型常量
* @author liwenbin
*
*/
public class DistributeLogoConstants {
/**
* 首次分发或者异常重试
*/
public static final Integer FIRST = 1;
/**
* 回流
*/
public static final Integer BACK_FLOW = 2;
}
......@@ -21,4 +21,9 @@ public class RedisKeyConstants {
* 助贷资金总金额限制缓存key
*/
public final static String AID_LOAN_ALL_AMOUNT_LIMIT_KEY="AID.LOAN.ALL.AMOUNT.LIMIT.KEY.9QDBFD_";
/**
* 分发失败节点记录
*/
public final static String DISTRIBUTE_FAIL_TYPE_RECORD = "ASSET.DISTRIBUTE.DISTRIBUTE.FAIL.TYPE.KEY.8SAWNB_";
}
package com.quantgroup.asset.distribution.constant;
/**
* 状态常量
* @author liwenbin
*
*/
public class StatusConstants {
public static final Integer SUCCESS = 1;
public static final Integer FAIL = 0;
}
......@@ -2,6 +2,8 @@ package com.quantgroup.asset.distribution.controller;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
......@@ -11,7 +13,7 @@ import com.google.common.base.Stopwatch;
import com.quantgroup.asset.distribution.enums.response.AssetResponse;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.service.IAssetService;
import com.quantgroup.asset.distribution.service.asset.IAssetService;
import com.quantgroup.asset.distribution.util.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
......@@ -30,13 +32,15 @@ public class AssetController {
private IAssetService assetService;
@RequestMapping("/asset_in")
public GlobalResponse assetsIn(AssetForm assetForm) {
public GlobalResponse assetsIn(AssetForm assetForm, HttpServletRequest request) {
Stopwatch stopwatch = Stopwatch.createStarted();
assetForm.setAssetNo(UUIDUtil.getAssetNo());
log.info("资产入库开始, assetForm : {}", JSON.toJSONString(assetForm));
GlobalResponse response = assetService.checkAssetForm(assetForm);
String authKey = request.getHeader("as_auth_key");
log.info("资产入库分发开始, assetForm : {}, authKey : {}", JSON.toJSONString(assetForm), authKey);
boolean check = assetService.checkAssetForm(assetForm);
if (!check) { return GlobalResponse.create( AssetResponse.ASSET_FORM_IS_ERROR); }
assetService.assetsIn(assetForm);
log.info("资产入库结束, assetForm : {}, response : {}, 耗时 : {}", JSON.toJSONString(assetForm), JSON.toJSONString(response), stopwatch.stop().elapsed(TimeUnit.MILLISECONDS));
return response;
log.info("资产入库分发结束, assetForm : {}, authKey : {}, response : {}, 耗时 : {}", JSON.toJSONString(assetForm), authKey, JSON.toJSONString(AssetResponse.SUCCESS), stopwatch.stop().elapsed(TimeUnit.MILLISECONDS));
return GlobalResponse.create(AssetResponse.SUCCESS);
}
}
......@@ -2,6 +2,9 @@ package com.quantgroup.asset.distribution.controller;
import com.quantgroup.asset.distribution.constant.RedisKeyConstants;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.service.asset.IAssetAttributeExtendConfigService;
import com.quantgroup.asset.distribution.service.authority.IAuthorityService;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeRuleConfigService;
import com.quantgroup.asset.distribution.service.redis.IRedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -24,6 +27,12 @@ public class RedisFlushController {
@Autowired
private IRedisService<String> redisService;
@Autowired
private IAssetAttributeExtendConfigService assetAttributeExtendConfigService;
@Autowired
private IAuthorityService authorityService;
@Autowired
private IAssetDistributeRuleConfigService assetDistributeRuleConfigService;
/**
* 助贷资金池刷新
......@@ -37,13 +46,21 @@ public class RedisFlushController {
return GlobalResponse.success();
}
@RequestMapping("/attribute_extend_config_flush")
public GlobalResponse attributeExtendConfigFlush(String key) {
if(authKey.equals(key)) { assetAttributeExtendConfigService.clearAllExtendConfigCache(); }
return GlobalResponse.success();
}
@RequestMapping("/authority_flush")
public GlobalResponse authorityFlush(String key, String authKey, String authPass) {
if(authKey.equals(key)) { authorityService.clearCacheByAuthKeyAndAuthPass(authKey, authPass); }
return GlobalResponse.success();
}
@RequestMapping("/distribute_rule_config_flush")
public GlobalResponse distributeRuleConfigFlush(String key) {
if(authKey.equals(key)) { assetDistributeRuleConfigService.clearRuleConfigCache(); }
return GlobalResponse.success();
}
}
......@@ -9,6 +9,7 @@ import lombok.Getter;
*/
public enum AssetResponse implements GlobalResponseEnum{
SUCCESS(0, "success"),
ASSET_FORM_IS_ERROR(2001, "资产入库参数错误!");
@Getter
......
......@@ -23,7 +23,14 @@ public enum QGExceptionType {
ASSET_IN_CODE_ERROR(2001, "资产入库code异常! uuid : %s, bizNo : %s, code : %s"),
GET_DEC_ATTRIBUTE_VALUE_ERROR(2002, "获取决策资产属性值异常, uuid : %s, keys : %s"),
ASSET_ATTRIBUTE_IS_EMPTY(2003, "%s资产属性值为空");
ASSET_ATTRIBUTE_IS_EMPTY(2003, "%s资产属性值为空"),
DISTRIBUTE_RULE_CONFIG_PRIORITY_IS_NOT_UNIQUE(2021, "资产分发规则优先级不唯一"),
RULE_CALC_ERROR(2022, "规则计算出现错误, expression : %s"),
RULE_CALC_UNKNOW_ERROR(2023, "规则计算出现未知异常, expression : %s"),
RULE_CALC_UNKNOW_RESULT(2024, "规则判断出现未知结果,请联系管理人员, expression : %s"),
UNKNOW_RULE_TYPE(2025, "未知的规则类型, %s"),
NO_DISTRIBUTE_NODE(2026, "未找到分发节点, uuid : %s, assetNo %s, records : %s");
......
package com.quantgroup.asset.distribution.model.entity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import lombok.Data;
@Data
public class DistributeRecord implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Map<String, Object> data;
private List<Record> records;
public DistributeRecord(Map<String, Object> data) {
this.data = data;
records = new ArrayList<>();
}
public void addRecords(Long id, String expression, Integer type, String name, Boolean valid) {
Record record = new Record();
record.setId(id);
record.setExpression(expression);
record.setType(type);
record.setName(name);
record.setValid(valid);
if (records == null) {
records = new ArrayList<>();
}
records.add(record);
}
public void clearRecords() {
records.clear();
}
}
package com.quantgroup.asset.distribution.model.entity;
import java.io.Serializable;
import lombok.Data;
@Data
public class Record implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private Long id;
private String expression;
// 1-资金路由2-助贷3-导流
private Integer type;
private String name;
private Boolean valid;
}
package com.quantgroup.asset.distribution.model.form;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
......@@ -42,6 +44,8 @@ public class AssetForm implements Serializable{
private String callbackUrl;
private int repeatCount = 0;
public Asset transToAsset() {
Asset asset = new Asset();
asset.setAssetNo(this.assetNo);
......@@ -54,4 +58,25 @@ public class AssetForm implements Serializable{
return asset;
}
/**
* 获取通知资金系统FormMap
* @return
*/
public Map<String, String> transToNotifyMap() {
Map<String, String> notifyMap = new HashMap<>();
notifyMap.put("code", this.code);
notifyMap.put("msg", this.msg);
notifyMap.put("uuid", this.uuid);
notifyMap.put("bizChannel", this.bizChannel);
notifyMap.put("bizNo", this.bizNo);
notifyMap.put("bizType", this.bizType);
notifyMap.put("auditResult", this.auditResult);
notifyMap.put("amount", this.amount);
notifyMap.put("deadLine", this.deadLine);
notifyMap.put("exData", this.exData);
notifyMap.put("otherInformation", this.otherInformation);
notifyMap.put("financeProducts", this.financeProducts);
return notifyMap;
}
}
package com.quantgroup.asset.distribution.service.alarm;
/**
* 报警接口
* @author liwenbin
*
*/
public interface IAlarmService {
/**
* 钉钉机器人报警
* @param webhook
* @param alarmLevel
* @param msgTitle
* @param msgContent
*/
public void dingtalkAlarm(String alarmLevel, String msgTitle, String msgContent);
}
package com.quantgroup.asset.distribution.service.alarm.impl;
import java.util.HashMap;
import java.util.Map;
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.quantgroup.asset.distribution.service.alarm.IAlarmService;
import com.quantgroup.asset.distribution.service.httpclient.IHttpService;
import lombok.extern.slf4j.Slf4j;
/**
* 报警接口
* @author liwenbin
*
*/
@Slf4j
@Service
public class AlarmServiceImpl implements IAlarmService{
private static final String ALARM_HTTP_URL = "http://alertserv-dataservice.quantgroup.cn/common/alert/dingtalk";
private static final String ROBOT_WEB_HOOK = "https://oapi.dingtalk.com/robot/send?access_token=53a55ffe3d4a5398a7ba44e4fcee1a3ac006edcba9cfdc4b1f9f692ffc18a5b8";
@Value("${isDebug}")
private Boolean isDebug;
@Autowired
private IHttpService httpService;
@Async
@Override
public void dingtalkAlarm(String alarmLevel, String msgTitle, String msgContent) {
try {
// TODO
if (isDebug) { return; }
Map<String, String> params = new HashMap<>();
params.put("webhook", ROBOT_WEB_HOOK);
params.put("alarmLevel", alarmLevel);
params.put("msgTitle", msgTitle);
params.put("msgContent", msgContent);
httpService.postNoResponse(ALARM_HTTP_URL, params);
} catch (Exception e) {
log.error("钉钉机器人报警异常, msg : {}", msgContent, e);
}
}
}
package com.quantgroup.asset.distribution.service.asset;
import java.util.List;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetAttributeExtendConfig;
/**
* 资产扩展属性配置Service
* @author liwenbin
*
*/
public interface IAssetAttributeExtendConfigService {
/**
* 获取所有可用的扩展属性配置
* @return
*/
public List<AssetAttributeExtendConfig> getAllExtendConfig();
/**
* 情书扩展属性配置缓存
*/
public void clearAllExtendConfigCache();
}
package com.quantgroup.asset.distribution.service;
package com.quantgroup.asset.distribution.service.asset;
import java.util.List;
import java.util.Map;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetAttributeExtendConfig;
/**
......@@ -13,13 +14,19 @@ import com.quantgroup.asset.distribution.service.jpa.entity.AssetAttributeExtend
*/
public interface IAssetAttributeService {
// public List<AssetAttributeExtendConfig> getAllExtendCon
/**
* 获取所有资产属性值
* @param assetAttributeExtendConfigList
* @return
*/
public Map<String, Object> getAllAssetAttributeValue(List<AssetAttributeExtendConfig> assetAttributeExtendConfigList, AssetForm assetForm);
/**
* 资产入库
* @param asset
* @param assetAttributeExtendConfigList
* @param data
*/
public void saveAssetAttrubite(Asset asset, List<AssetAttributeExtendConfig> assetAttributeExtendConfigList, Map<String, Object> data);
}
package com.quantgroup.asset.distribution.service;
package com.quantgroup.asset.distribution.service.asset;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
/**
* 资产Service
......@@ -22,5 +21,5 @@ public interface IAssetService {
* @param assetForm
* @return
*/
public GlobalResponse checkAssetForm(AssetForm assetForm);
public boolean checkAssetForm(AssetForm assetForm);
}
package com.quantgroup.asset.distribution.service.asset.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.quantgroup.asset.distribution.service.asset.IAssetAttributeExtendConfigService;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetAttributeExtendConfig;
import com.quantgroup.asset.distribution.service.jpa.repository.IAssetAttributeExtendConfigRepository;
/**
* 资产扩展属性配置Service
* @author liwenbin
*
*/
@Service
public class AssetAttributeExtendConfigServiceImpl implements IAssetAttributeExtendConfigService{
@Autowired
private IAssetAttributeExtendConfigRepository assetAttributeExtendConfigRepository;
@Cacheable(value="cacheManager",key="'ASSET_1023A_ALL_ATTRIBUTE_EXTEND_CONFIG'")
@Override
public List<AssetAttributeExtendConfig> getAllExtendConfig() {
return assetAttributeExtendConfigRepository.findByEnableIsTrue();
}
@CacheEvict(value = "cacheManager", key = "'ASSET_1023A_ALL_ATTRIBUTE_EXTEND_CONFIG'")
@Override
public void clearAllExtendConfigCache() {
}
}
package com.quantgroup.asset.distribution.service.impl;
package com.quantgroup.asset.distribution.service.asset.impl;
import java.util.HashMap;
import java.util.HashSet;
......@@ -12,15 +12,21 @@ 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 org.springframework.transaction.annotation.Transactional;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.quantgroup.asset.distribution.constant.AssetAttributeConstants;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.service.IAssetAttributeService;
import com.quantgroup.asset.distribution.service.asset.IAssetAttributeService;
import com.quantgroup.asset.distribution.service.httpclient.IHttpService;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetAttributeExtend;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetAttributeExtendConfig;
import com.quantgroup.asset.distribution.service.jpa.repository.IAssetAttributeExtendRepository;
import com.quantgroup.asset.distribution.service.jpa.repository.IAssetRepository;
import lombok.extern.slf4j.Slf4j;
......@@ -36,6 +42,10 @@ public class AssetAttributeServiceImpl implements IAssetAttributeService {
@Autowired
private IHttpService httpService;
@Autowired
private IAssetRepository assetRepository;
@Autowired
private IAssetAttributeExtendRepository assetAttributeExtendRepository;
@Value("${rule.engine.url}")
private String ruleEngineURL;
......@@ -46,20 +56,16 @@ public class AssetAttributeServiceImpl implements IAssetAttributeService {
@Override
public Map<String, Object> getAllAssetAttributeValue(List<AssetAttributeExtendConfig> assetAttributeExtendConfigList, AssetForm assetForm) {
Map<String, Object> data = new HashMap<>();
// 决策特征Set
data.put(AssetAttributeConstants.AUDIT_RESULT, assetForm.getAuditResult());
// 决策特征Key
Set<String> decKeys = new HashSet<>();
// 默认增加一个用户类型
decKeys.add("user_loan_type_latest");
decKeys.add(AssetAttributeConstants.USER_LOAN_TYPE);
if (assetAttributeExtendConfigList != null && assetAttributeExtendConfigList.size() > 0) {
for (AssetAttributeExtendConfig config : assetAttributeExtendConfigList) {
if (config.getAssetAttributeType() == 1) {
// 模型分
decKeys.add(config.getAssetAttributeCode());
}
if (config.getAssetAttributeType() == 1) { decKeys.add(config.getAssetAttributeCode()); }
}
}
// 去请求决策特征
// 请求决策特征
Map<String, Object> decAttributeValue = getDecAttributeValue(decKeys, assetForm);
data.putAll(decAttributeValue);
return data;
......@@ -71,18 +77,46 @@ public class AssetAttributeServiceImpl implements IAssetAttributeService {
* @return
*/
public Map<String, Object> getDecAttributeValue(Set<String> decKeys, AssetForm assetForm) {
if (CollectionUtils.isEmpty(decKeys)) { return MapUtils.EMPTY_MAP; }
String result = httpService.post(ruleEngineURL + "/feature/get", new HashMap<String, String>(){{
put("uuid", assetForm.getUuid());
put("bizChannel", assetForm.getBizChannel());
put("bizNo", assetForm.getBizNo());
put("bizType", assetForm.getBizType());
put("keys", StringUtils.join(decKeys, ","));
}});
JSONObject resultJSON = null;
QGPreconditions.checkArgument(StringUtils.isNotEmpty(result) && (resultJSON = JSON.parseObject(result)).getInteger("code") == 0, QGExceptionType.GET_DEC_ATTRIBUTE_VALUE_ERROR, assetForm.getUuid(), JSON.toJSONString(decKeys));
Map<String, Object > data = resultJSON.getJSONObject("body");
log.info("决策特征属性获取完成, uuid : {}, bizChannel : {}, bizNo : {}, bizType : {}, data : {}", assetForm.getUuid(), assetForm.getBizChannel(), assetForm.getBizNo(), assetForm.getBizType(), JSON.toJSONString(data));
// TODO
// if (CollectionUtils.isEmpty(decKeys)) { return MapUtils.EMPTY_MAP; }
// String result = httpService.post(ruleEngineURL + "/feature/get", new HashMap<String, String>(){{
// put("uuid", assetForm.getUuid());
// put("bizChannel", assetForm.getBizChannel());
// put("bizNo", assetForm.getBizNo());
// put("bizType", assetForm.getBizType());
// put("keys", StringUtils.join(decKeys, ","));
// }});
// JSONObject resultJSON = null;
// QGPreconditions.checkArgument(StringUtils.isNotEmpty(result) && (resultJSON = JSON.parseObject(result)).getInteger("code") == 0, QGExceptionType.GET_DEC_ATTRIBUTE_VALUE_ERROR, assetForm.getUuid(), JSON.toJSONString(decKeys));
// Map<String, Object > data = resultJSON.getJSONObject("body");
// log.info("决策特征属性获取完成, uuid : {}, bizChannel : {}, bizNo : {}, bizType : {}, data : {}", assetForm.getUuid(), assetForm.getBizChannel(), assetForm.getBizNo(), assetForm.getBizType(), JSON.toJSONString(data));
Map<String, Object> data = new HashMap<>();
data.put(AssetAttributeConstants.USER_LOAN_TYPE, 1);
return data;
}
@Transactional(rollbackFor=Exception.class)
@Override
public void saveAssetAttrubite(Asset asset, List<AssetAttributeExtendConfig> assetAttributeExtendConfigList,
Map<String, Object> data) {
// 用户类型特殊处理
QGPreconditions.checkArgument(data.get(AssetAttributeConstants.USER_LOAN_TYPE) != null, QGExceptionType.ASSET_ATTRIBUTE_IS_EMPTY, AssetAttributeConstants.USER_LOAN_TYPE);
asset.setUserLoanType((Integer)data.get(AssetAttributeConstants.USER_LOAN_TYPE));
data.put("user_loan_type", data.get(AssetAttributeConstants.USER_LOAN_TYPE));
assetRepository.save(asset);
if (assetAttributeExtendConfigList != null && assetAttributeExtendConfigList.size() > 0) {
for (AssetAttributeExtendConfig config : assetAttributeExtendConfigList) {
QGPreconditions.checkArgument(data.get(config.getAssetAttributeCode()) != null, QGExceptionType.ASSET_ATTRIBUTE_IS_EMPTY, config.getAssetAttributeCode());
AssetAttributeExtend attributeExtend = new AssetAttributeExtend();
attributeExtend.setAssetNo(asset.getAssetNo());
attributeExtend.setAssetAttributeName(config.getAssetAttributeName());
attributeExtend.setAssetAttributeCode(config.getAssetAttributeCode());
attributeExtend.setAssetAttributeType(config.getAssetAttributeType());
attributeExtend.setAssetAttributeValue(String.valueOf(data.get(config.getAssetAttributeCode())));
attributeExtend.setEnable(true);
assetAttributeExtendRepository.save(attributeExtend);
}
}
}
}
package com.quantgroup.asset.distribution.service.asset.impl;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
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.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.quantgroup.asset.distribution.constant.DistributeLogoConstants;
import com.quantgroup.asset.distribution.exception.QGException;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.service.alarm.IAlarmService;
import com.quantgroup.asset.distribution.service.asset.IAssetAttributeExtendConfigService;
import com.quantgroup.asset.distribution.service.asset.IAssetAttributeService;
import com.quantgroup.asset.distribution.service.asset.IAssetService;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeService;
import com.quantgroup.asset.distribution.service.distribute.IDistributeFailLogService;
import com.quantgroup.asset.distribution.service.httpclient.IHttpService;
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.repository.IAssetAttributeExtendConfigRepository;
import com.quantgroup.asset.distribution.util.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
/**
* 资产Service
* @author liwenbin
*
*/
@Slf4j
@Service
public class AssetServiceImpl implements IAssetService{
@Autowired
private IAssetAttributeExtendConfigService assetAttributeExtendConfigService;
@Autowired
private IAssetAttributeService assetAttributeService;
@Autowired
private IAssetDistributeService assetDistributeService;
@Autowired
private IAlarmService alarmService;
@Autowired
private IDistributeFailLogService distributeFailLogService;
@Async
@Override
public void assetsIn(AssetForm assetForm) {
try {
Asset asset = assetForm.transToAsset();
// 获取所有资产扩展属性配置
List<AssetAttributeExtendConfig> assetAttributeExtendConfigList = assetAttributeExtendConfigService.getAllExtendConfig();
// 获取所有资产扩展属性值
Map<String, Object> data = assetAttributeService.getAllAssetAttributeValue(assetAttributeExtendConfigList, assetForm);
// 资产入库
assetAttributeService.saveAssetAttrubite(asset, assetAttributeExtendConfigList, data);
// 资产分发
assetDistributeService.distribute(assetForm, asset, data, DistributeLogoConstants.FIRST);
} 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());
distributeFailLogService.saveDistributeFailLog(assetForm, qe.qgExceptionType.code + "->" + qe.detail);
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);
distributeFailLogService.saveDistributeFailLog(assetForm, "未知异常.");
alarmService.dingtalkAlarm("Warn", "资产入库分发出现异常", "bizChannel : " + assetForm.getBizChannel()
+ " , bizType : " + assetForm.getBizType() + " , bizNo : " + assetForm.getBizNo()
+ " , assetNo : " + assetForm.getAssetNo() + " , uuid : " + assetForm.getUuid()
+ " , 错误信息 : 未知错误.");
}
}
@Override
public boolean checkAssetForm(AssetForm assetForm) {
// auditResult和deadLine必填
if (StringUtils.isEmpty(assetForm.getAuditResult()) || StringUtils.isEmpty(assetForm.getDeadLine())) { return false; }
if ("true".equals(assetForm.getAuditResult())) {
if (StringUtils.isEmpty(assetForm.getFinanceProducts()) || StringUtils.isEmpty(assetForm.getAmount())) {
// auditResult为true,金融产品集和amount不能为空
return false;
}
BigDecimal amount = new BigDecimal(assetForm.getAmount());
BigDecimal floor = null;
JSONArray array = JSON.parseArray(assetForm.getFinanceProducts());
for (int i = 0, len = array.size(); i < len; ++i) {
JSONObject data = array.getJSONObject(i);
BigDecimal min = new BigDecimal(data.getString("min"));
BigDecimal max = new BigDecimal(data.getString("max"));
BigDecimal cha = max.subtract(min);
// 0 <= max - min <= 1
if (!(cha.compareTo(BigDecimal.ZERO) > -1 && cha.compareTo(BigDecimal.ONE) < 1)) {
return false;
}
if (floor == null || min.compareTo(floor) < 0) {
floor = min;
}
}
// amount >= floor
if (amount.compareTo(floor) < 1) {
return false;
}
}
return true;
}
public static void main(String[] args) {
BigDecimal min = new BigDecimal("98");
BigDecimal max = new BigDecimal("100");
BigDecimal cha = max.subtract(min);
if (cha.compareTo(BigDecimal.ZERO) > -1 && cha.compareTo(BigDecimal.ONE) < 1) {
System.out.println(true);
} else {
System.out.println(false);
}
}
}
package com.quantgroup.asset.distribution.service;
package com.quantgroup.asset.distribution.service.authority;
import com.quantgroup.asset.distribution.service.jpa.entity.AuthorityConfig;
......
package com.quantgroup.asset.distribution.service.impl;
package com.quantgroup.asset.distribution.service.authority.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.stereotype.Service;
import com.quantgroup.asset.distribution.service.IAuthorityService;
import com.quantgroup.asset.distribution.service.authority.IAuthorityService;
import com.quantgroup.asset.distribution.service.jpa.entity.AuthorityConfig;
import com.quantgroup.asset.distribution.service.jpa.repository.IAuthorityRepository;
......@@ -25,13 +24,13 @@ public class AuthorityServiceImpl implements IAuthorityService{
private IAuthorityRepository authorityRepository;
@Override
@Cacheable(value="cacheManager",key="#authKey+'_'+#authPass+'_1021ASSET'")
@Cacheable(value="cacheManager",key="#authKey+'_'+#authPass+'_1021ASSET_AUTHORITY'")
public AuthorityConfig findByAuthKeyAndAuthPass(String authKey, String authPass) {
return authorityRepository.findByAuthKeyAndAuthPassAndEnableIsTrue(authKey, authPass);
}
@Override
@CacheEvict(value = "cacheManager", key = "#authKey+'_'+#authPass+'_1021ASSET'")
@CacheEvict(value = "cacheManager", key = "#authKey+'_'+#authPass+'_1021ASSET_AUTHORITY'")
public void clearCacheByAuthKeyAndAuthPass(String authKey, String authPass) {
log.info("权限配置清楚缓存成功, authKey = {}, authPass = {}", authKey, authPass);
}
......
package com.quantgroup.asset.distribution.service.distribute;
import java.util.List;
import com.quantgroup.asset.distribution.model.entity.DistributeRecord;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetDistributeRecord;
/**
* 资产分发记录Service
* @author liwenbin
*
*/
public interface IAssetDistributeRecordService {
/**
* 保存记录
* @param asset
* @param distributeRecord
* @param distributeStatus
*/
public void saveDistributeRecord(Asset asset, DistributeRecord distributeRecord, Boolean distributeStatus, int ruleType);
/**
* 获取资产分发记录
* @param assetNo
* @return
*/
public List<AssetDistributeRecord> getDistributeRecord(String assetNo);
}
package com.quantgroup.asset.distribution.service.distribute;
import java.util.List;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetDistributeRuleConfig;
/**
* 资产分发规则配置Service
* @author liwenbin
*
*/
public interface IAssetDistributeRuleConfigService {
public List<AssetDistributeRuleConfig> getAllRuleConfigOrderByPriorityAsc();
public void clearRuleConfigCache();
}
package com.quantgroup.asset.distribution.service.distribute;
import java.util.Map;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
/**
* 资产分发Service
* @author liwenbin
*
*/
public interface IAssetDistributeService {
/**
* 资产开始分发
* @param assetForm
* @param asset
* @param startIndex 开始分发节点
* @param distributeLogo 1:初次分发或异常重试, 2:分发失败重新分发(预留)
*/
public void distribute(AssetForm assetForm, Asset asset, Map<String, Object> data, int distributeLogo);
}
package com.quantgroup.asset.distribution.service.distribute;
import com.quantgroup.asset.distribution.model.form.AssetForm;
/**
* 分发失败日志处理Service
* @author liwenbin
*
*/
public interface IDistributeFailLogService {
/**
* 保存失败订单
* @param assetForm
* @param failReason
*/
public void saveDistributeFailLog(AssetForm assetForm, String failReason);
}
package com.quantgroup.asset.distribution.service.distribute.impl;
import java.util.List;
import java.util.Set;
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.quantgroup.asset.distribution.constant.StatusConstants;
import com.quantgroup.asset.distribution.model.entity.DistributeRecord;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeRecordService;
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.repository.IAssetDistributeRecordRepository;
import com.quantgroup.asset.distribution.service.redis.IRedisService;
import lombok.extern.slf4j.Slf4j;
/**
* 资产分发日志记录表
* @author liwenbin
*
*/
@Slf4j
@Service
public class AssetDistributeRecordServiceImpl implements IAssetDistributeRecordService{
@Autowired
private IAssetDistributeRecordRepository assetDistributeRecordRepository;
@Autowired
private IRedisService<Integer> redisService;
@Override
public void saveDistributeRecord(Asset asset, DistributeRecord distributeRecord, Boolean distributeStatus, int ruleType) {
try {
AssetDistributeRecord assetDistributeRecord = new AssetDistributeRecord();
assetDistributeRecord.setAssetNo(asset.getAssetNo());
assetDistributeRecord.setUuid(asset.getUuid());
assetDistributeRecord.setUserLoanType(asset.getUserLoanType());
assetDistributeRecord.setBizChannel(asset.getBizChannel());
assetDistributeRecord.setFinanceProductType(asset.getFinanceProductType());
assetDistributeRecord.setBizNo(asset.getBizNo());
assetDistributeRecord.setAssetDistributeTravel(JSON.toJSONString(distributeRecord));
assetDistributeRecord.setAssetDistributeTarget(ruleType);
assetDistributeRecord.setAssetDistributeStatus(distributeStatus == true ? StatusConstants.SUCCESS : StatusConstants.FAIL);
assetDistributeRecord.setEnable(true);
assetDistributeRecordRepository.save(assetDistributeRecord);
// 完成一次分发,清除分发记录
distributeRecord.clearRecords();
} catch (Exception e) {
log.error("用户记录分发日志异常, uuid : {}", asset.getUuid(), e);
}
}
@Override
public List<AssetDistributeRecord> getDistributeRecord(String assetNo) {
return assetDistributeRecordRepository.findByAssetNo(assetNo);
}
}
package com.quantgroup.asset.distribution.service.distribute.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeRuleConfigService;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetDistributeRuleConfig;
import com.quantgroup.asset.distribution.service.jpa.repository.IAssetDistributeRuleConfigRepository;
/**
* 资产分发规则配置Service
* @author liwenbin
*
*/
@Service
public class AssetDistributeRuleConfigServiceImpl implements IAssetDistributeRuleConfigService{
@Autowired
private IAssetDistributeRuleConfigRepository assetDistributeRuleConfigRepository;
@Override
@Cacheable(value="cacheManager",key="'ASSET_2028D_ALL_RULE_CONFIG'")
public List<AssetDistributeRuleConfig> getAllRuleConfigOrderByPriorityAsc() {
return assetDistributeRuleConfigRepository.findByEnableIsTrueOrderByAssetDistributeRulePriorityAsc();
}
@Override
@CacheEvict(value = "cacheManager", key = "'ASSET_2028D_ALL_RULE_CONFIG'")
public void clearRuleConfigCache() {
}
}
package com.quantgroup.asset.distribution.service.distribute.impl;
import java.util.ArrayList;
import java.util.Collections;
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.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Sets;
import com.quantgroup.asset.distribution.constant.DistributeConstants;
import com.quantgroup.asset.distribution.constant.RedisKeyConstants;
import com.quantgroup.asset.distribution.exception.QGException;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.model.entity.DistributeRecord;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeRecordService;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeRuleConfigService;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeService;
import com.quantgroup.asset.distribution.service.funding.IAidFundRouteService;
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.AssetDistributeRuleConfig;
import com.quantgroup.asset.distribution.service.notify.INotifyService;
import com.quantgroup.asset.distribution.service.redis.IRedisService;
import com.quantgroup.asset.distribution.service.rule.IRuleService;
/**
* 资产分发Service
* @author liwenbin
*
*/
@Service
public class AssetDistributeServiceImpl implements IAssetDistributeService{
/**
* 分发总开关
*/
@Value("${is.distribute}")
private Boolean isDistribute;
@Autowired
private IAssetDistributeRuleConfigService assetDistributeRuleConfigService;
@Autowired
private IRedisService<Integer> redisService;
@Autowired
private IRuleService ruleService;
@Autowired
private IAidFundRouteService aidFundRouteService;
@Autowired
private INotifyService notifyService;
@Autowired
private IAssetDistributeRecordService assetDistributeRecordService;
/**
* 分发
*/
@Override
public void distribute(AssetForm assetForm, Asset asset, Map<String, Object> data, int distributeLogo) {
if (isDistribute) {
List<AssetDistributeRuleConfig> assetDistributeRuleConfigList = assetDistributeRuleConfigService.getAllRuleConfigOrderByPriorityAsc();
// 检查规则配置
checkDistributeRuleConfig(assetDistributeRuleConfigList);
// 获取该资产所有已经尝试分发过的类型
Set<Integer> hasDistributedTypeSet = getAllDistributeRecordType(asset.getAssetNo(), distributeLogo);
boolean success = false;
DistributeRecord record = new DistributeRecord(data);
for (AssetDistributeRuleConfig ruleConfig : assetDistributeRuleConfigList) {
Integer ruleType = ruleConfig.getAssetDistributeRuleType();
// 如果配置被关闭或者该类型被分发过,就默认往下走,主要避免priority调换顺序的情况
if (ruleConfig.getAssetDistributeRuleSwitch() == 0 || hasDistributedTypeSet.contains(ruleType)) { continue; }
String el = ruleConfig.getAssetDistributeRuleEl();
boolean valid = ruleService.valid(el, data);
record.addRecords(ruleConfig.getId(), el, ruleType, ruleConfig.getAssetDistributeRuleName(), valid);
// 保存节点尝试记录
saveAssetAttemptDistributeNode(asset.getAssetNo(), ruleType);
if (valid) {
boolean distributeStatus = beginDistribute(assetForm, asset, ruleType);
assetDistributeRecordService.saveDistributeRecord(asset, record, distributeStatus, ruleType);
// 分发成功
if (distributeStatus) {
success = true;
break;
}
}
}
if (!success) {
// 如果一个分配节点都没找到,报错
throw new QGException(QGExceptionType.NO_DISTRIBUTE_NODE, asset.getUuid(), asset.getAssetNo(), JSON.toJSONString(record));
}
} else {
notifyService.notifyFundServer(assetForm);
}
}
/**
* 开始进行分发
* @param assetForm
* @param ruleType
* @return
*/
public boolean beginDistribute(AssetForm assetForm, Asset asset, int ruleType) {
switch (ruleType) {
case DistributeConstants.RuleType.FUND_ROUTE :
notifyService.notifyFundServer(assetForm);
return true;
case DistributeConstants.RuleType.AID_FUND_ROUTE:
GlobalResponse response = aidFundRouteService.aidFundRoute(assetForm, asset.getUserLoanType());
return response.getCode() == 0;
case DistributeConstants.RuleType.DIVERSION:
notifyService.notifyFundServer(assetForm);
return true;
default :
throw new QGException(QGExceptionType.UNKNOW_RULE_TYPE, ruleType);
}
}
/**
* 分发配置检查
* @param assetDistributeRuleConfigList
*/
public void checkDistributeRuleConfig(List<AssetDistributeRuleConfig> assetDistributeRuleConfigList) {
int prePriority = -1;
for (AssetDistributeRuleConfig assetDistributeRuleConfig : assetDistributeRuleConfigList) {
if (assetDistributeRuleConfig.getAssetDistributeRulePriority().equals(prePriority)) {
throw new QGException(QGExceptionType.DISTRIBUTE_RULE_CONFIG_PRIORITY_IS_NOT_UNIQUE);
}
prePriority = assetDistributeRuleConfig.getAssetDistributeRulePriority();
}
}
/**
* 获取该用户所有分发记录Type,如果用户初次分发或者异常重试返回空
* @param assetNo
* @return
*/
public Set<Integer> getAllDistributeRecordType(String assetNo, int distributeLogo) {
Set<Integer> sets = new HashSet<>();
if (distributeLogo == 1) {
// 用户初次分发或者异常重试直接返回空
return sets;
}
List<Integer> list = redisService.getList(RedisKeyConstants.DISTRIBUTE_FAIL_TYPE_RECORD + assetNo);
if (list == null || list.size() == 0) {
// 如果缓存没有去查库,把库里执行过的都拿出来
List<AssetDistributeRecord> assetDistributeRecords = assetDistributeRecordService.getDistributeRecord(assetNo);
if (assetDistributeRecords == null || assetDistributeRecords.size() == 0) { return sets; }
list = new ArrayList<>();
for (AssetDistributeRecord assetDistributeRecord : assetDistributeRecords) {
JSONArray array = JSON.parseObject(assetDistributeRecord.getAssetDistributeTravel()).getJSONArray("records");
for (int i = 0, len = array.size(); i < len; ++i) {
JSONObject record = array.getJSONObject(i);
list.add(record.getInteger("type"));
}
}
}
sets.addAll(list);
return sets;
}
/**
* 保存资产尝试分发记录节点
*/
public void saveAssetAttemptDistributeNode(String assetNo, Integer ruleType) {
redisService.rightPushEx(RedisKeyConstants.DISTRIBUTE_FAIL_TYPE_RECORD + assetNo, ruleType, 3, TimeUnit.DAYS);
}
}
package com.quantgroup.asset.distribution.service.distribute.impl;
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.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.service.distribute.IDistributeFailLogService;
import com.quantgroup.asset.distribution.service.jpa.entity.Asset;
import com.quantgroup.asset.distribution.service.jpa.entity.DistributeFailLog;
import com.quantgroup.asset.distribution.service.jpa.repository.IDistributeFailLogRepository;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class DistributeFailLogServiceImpl implements IDistributeFailLogService{
@Autowired
private IDistributeFailLogRepository distributeFailLogRepository;
@Async
@Override
public void saveDistributeFailLog(AssetForm assetForm, String failReason) {
try {
DistributeFailLog distributeFailLog = new DistributeFailLog();
distributeFailLog.setBizChannel(assetForm.getBizChannel());
distributeFailLog.setAssetNo(assetForm.getAssetNo());
distributeFailLog.setBizNo(assetForm.getBizNo());
distributeFailLog.setBizType(Integer.parseInt(assetForm.getBizType()));
distributeFailLog.setUuid(assetForm.getUuid());
distributeFailLog.setContext(JSON.toJSONString(assetForm));
distributeFailLog.setFailReason(failReason);
distributeFailLog.setEnable(true);
distributeFailLogRepository.save(distributeFailLog);
} catch (Exception e) {
log.error("资产分发失败订单保存异常, asset : {}", JSON.toJSONString(assetForm), e);
}
}
}
package com.quantgroup.asset.distribution.service.impl;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.quantgroup.asset.distribution.exception.QGException;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.service.IAssetService;
import com.quantgroup.asset.distribution.service.httpclient.IHttpService;
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.repository.IAssetAttributeExtendConfigRepository;
import com.quantgroup.asset.distribution.util.UUIDUtil;
/**
* 资产Service
* @author liwenbin
*
*/
@Service
public class AssetServiceImpl implements IAssetService{
@Autowired
private IAssetAttributeExtendConfigRepository assetAttributeExtendConfigRepository;
@Async
@Override
public void assetsIn(AssetForm assetForm) {
// try {
// QGPreconditions.checkArgument("0".equals(assetForm.getCode()), QGExceptionType.ASSET_IN_CODE_ERROR, assetForm.getUuid(), assetForm.getBizNo(), assetForm.getCode());
// Asset asset = assetForm.transToAsset();
// // 获取所有资产扩展属性配置
// List<AssetAttributeExtendConfig> assetAttributeExtendConfigList = assetAttributeExtendConfigRepository.findByEnableIsTrue();
//
// return null;
// } catch (QGException qe) {
// log.error("风控审核出现错误:{},审核次数 : {} ,uuid : {} ,bizChannel:{},productId:{},bizNo : {},auditNo:{} ",
// qe.qgExceptionType.code + "->" + qe.detail, bizAuditForm.getRepeatCount(),
// bizAuditForm.getUuid(), bizAuditForm.getBizChannel(), bizAuditForm.getProductId(),
// bizAuditForm.getBizNo(), bizAuditForm.getAuditNo());
// // 审核失败放队列 来日继续审核
// iRedisService.rightPushEx("AUDIT.ERROR.USER.9981_01",
// bizAuditForm.setRepeatCount(bizAuditForm.getRepeatCount() + 1)
// .setFailReason(qe.qgExceptionType.code + "->" + qe.detail)
// .setSpaceTime(System.currentTimeMillis()),
// 1, TimeUnit.DAYS);
// // 报警机制
// if (qe.qgExceptionType.code != 2007 || bizAuditForm.getRepeatCount() > 1) {//规则数据为空 一次不报警 因为太多了
// iMonitorAlarmService.alarm("风控审核出现错误",
// "审核次数 : " + bizAuditForm.getRepeatCount() + " ,bizChannel : " + bizAuditForm.getBizChannel()
// + " , productId : " + bizAuditForm.getProductId() + " , bizNo : "
// + bizAuditForm.getBizNo() + " , uuid : " + bizAuditForm.getUuid() + " , 错误信息 : "
// + qe.qgExceptionType.code + "->" + qe.detail,
// "Warn");
// }
// return;
// } catch (Exception ex) {
// log.error("风控审核出现异常,审核次数 : {} ,uuid: {} ,bizChannel : {} ,productId:{},bizNo : {},auditNo:{} ",
// bizAuditForm.getRepeatCount(), bizAuditForm.getUuid(), bizAuditForm.getBizChannel(),
// bizAuditForm.getProductId(), bizAuditForm.getBizNo(), bizAuditForm.getAuditNo(), ex);
// // 审核失败放队列 来日继续审核
// iRedisService.rightPushEx("AUDIT.ERROR.USER.9981_01",
// bizAuditForm.setRepeatCount(bizAuditForm.getRepeatCount() + 1).setFailReason("未知异常")
// .setSpaceTime(System.currentTimeMillis()),
// 1, TimeUnit.DAYS);
// // 报警机制
// iMonitorAlarmService.alarm("风控审核出现异常",
// "审核次数 : " + bizAuditForm.getRepeatCount() + " , bizChannel : " + bizAuditForm.getBizChannel()
// + " , productId : " + bizAuditForm.getProductId() + " , bizNo : "
// + bizAuditForm.getBizNo() + " , uuid : " + bizAuditForm.getUuid() + " , 错误信息 : 未知错误",
// "Warn");
// return;
// }
}
@Override
public GlobalResponse checkAssetForm(AssetForm assetForm) {
return null;
}
}
package com.quantgroup.asset.distribution.service.jpa.entity;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
......@@ -23,8 +24,13 @@ import lombok.Setter;
@Table(name = "asset")
@Entity
@Data
public class Asset {
public class Asset implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
......
package com.quantgroup.asset.distribution.service.jpa.entity;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
......@@ -21,8 +22,13 @@ import lombok.Data;
@Table(name = "asset_atrribute_extend")
@Entity
@Data
public class AssetAttributeExtend {
public class AssetAttributeExtend implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
......
package com.quantgroup.asset.distribution.service.jpa.entity;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
......@@ -22,12 +23,17 @@ import lombok.Data;
@Table(name = "asset_atrribute_extend_config")
@Entity
@Data
public class AssetAttributeExtendConfig {
public class AssetAttributeExtendConfig implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Long id;
@Column(name = "asset_attribute_name")
private String assetAttributeName;
......
package com.quantgroup.asset.distribution.service.jpa.entity;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import lombok.Data;
/**
* 资产分发记录表
* @author liwenbin
*
*/
@Table(name = "asset_distribute_record")
@Entity
@Data
public class AssetDistributeRecord implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "asset_no")
private String assetNo;
@Column(name = "uuid")
private String uuid;
@Column(name = "user_loan_type")
private Integer userLoanType;
@Column(name = "biz_channel")
private String bizChannel;
@Column(name = "finance_product_type")
private Integer financeProductType;
@Column(name = "biz_no")
private String bizNo;
@Column(name = "asset_distribute_travel")
private String assetDistributeTravel;
@Column(name = "asset_distribute_target")
private Integer assetDistributeTarget;
@Column(name = "asset_distribute_status")
private Integer assetDistributeStatus;
@Column(name = "enable")
private Boolean enable;
@Column(name = "created_at")
private Timestamp createdAt;
@Column(name = "updated_at")
private Timestamp updatedAt;
@PrePersist
public void prePersist() {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
createdAt = timestamp;
updatedAt = timestamp;
}
@PreUpdate
public void preUpdate() {
updatedAt = new Timestamp(System.currentTimeMillis());
}
}
package com.quantgroup.asset.distribution.service.jpa.entity;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import lombok.Data;
/**
* 资产分发规则配置表
* @author liwenbin
*
*/
@Table(name = "asset_distribute_rule_config")
@Entity
@Data
public class AssetDistributeRuleConfig implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "asset_distribute_rule_no")
private String assetDistributeRuleNo;
@Column(name = "asset_distribute_rule_name")
private String assetDistributeRuleName;
@Column(name = "asset_distribute_rule_type")
private Integer assetDistributeRuleType;
@Column(name = "asset_distribute_rule_el")
private String assetDistributeRuleEl;
@Column(name = "asset_distribute_rule_priority")
private Integer assetDistributeRulePriority;
@Column(name = "asset_distribute_rule_switch")
private Integer assetDistributeRuleSwitch;
@Column(name = "enable")
private Boolean enable;
@Column(name = "created_by")
private String createdBy;
@Column(name = "updated_by")
private String updatedBy;
@Column(name = "created_at")
private Timestamp createdAt;
@Column(name = "updated_at")
private Timestamp updatedAt;
@PrePersist
public void prePersist() {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
createdAt = timestamp;
updatedAt = timestamp;
}
@PreUpdate
public void preUpdate() {
updatedAt = new Timestamp(System.currentTimeMillis());
}
}
package com.quantgroup.asset.distribution.service.jpa.entity;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
......@@ -21,12 +22,17 @@ import lombok.Data;
@Table(name = "authority_config")
@Entity
@Data
public class AuthorityConfig {
public class AuthorityConfig implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Long id;
@Column(name = "auth_key")
private String authKey;
......
package com.quantgroup.asset.distribution.service.jpa.entity;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import lombok.Data;
/**
* 分发失败日志表
* @author liwenbin
*
*/
@Table(name = "distribute_fail_log")
@Entity
@Data
public class DistributeFailLog implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "biz_channel")
private String bizChannel;
@Column(name = "asset_no")
private String assetNo;
@Column(name = "biz_no")
private String bizNo;
@Column(name = "biz_type")
private Integer bizType;
@Column(name = "uuid")
private String uuid;
@Column(name = "context")
private String context;
@Column(name = "fail_reason")
private String failReason;
@Column(name = "enable")
private Boolean enable;
@Column(name = "created_at")
private Timestamp createdAt;
@Column(name = "updated_at")
private Timestamp updatedAt;
@PrePersist
public void prePersist() {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
createdAt = timestamp;
updatedAt = timestamp;
}
@PreUpdate
public void preUpdate() {
updatedAt = new Timestamp(System.currentTimeMillis());
}
}
......@@ -7,7 +7,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetAttributeExtendConfig;
public interface IAssetAttributeExtendConfigRepository extends JpaRepository<AssetAttributeExtendConfig, Integer>{
public interface IAssetAttributeExtendConfigRepository extends JpaRepository<AssetAttributeExtendConfig, Long>{
public List<AssetAttributeExtendConfig> findByEnableIsTrue();
}
package com.quantgroup.asset.distribution.service.jpa.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetDistributeRecord;
/**
* 资产分发记录Repository
* @author liwenbin
*
*/
public interface IAssetDistributeRecordRepository extends JpaRepository<AssetDistributeRecord, Long>{
public List<AssetDistributeRecord> findByAssetNo(String assetNo);
}
package com.quantgroup.asset.distribution.service.jpa.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetDistributeRuleConfig;
/**
* 资产分发规则配置表
* @author liwenbin
*
*/
public interface IAssetDistributeRuleConfigRepository extends JpaRepository<AssetDistributeRuleConfig, Long>{
/**
* find所有可用规则
* @return
*/
public List<AssetDistributeRuleConfig> findByEnableIsTrueOrderByAssetDistributeRulePriorityAsc();
}
......@@ -10,7 +10,7 @@ import com.quantgroup.asset.distribution.service.jpa.entity.AuthorityConfig;
* @author liwenbin
*
*/
public interface IAuthorityRepository extends JpaRepository<AuthorityConfig, Integer>{
public interface IAuthorityRepository extends JpaRepository<AuthorityConfig, Long>{
/**
* 根据authKey和authPass查到配置
......
package com.quantgroup.asset.distribution.service.jpa.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.quantgroup.asset.distribution.service.jpa.entity.DistributeFailLog;
/**
* 分发失败Repository
* @author liwenbin
*
*/
public interface IDistributeFailLogRepository extends JpaRepository<DistributeFailLog, Long>{
}
package com.quantgroup.asset.distribution.service.notify;
import com.quantgroup.asset.distribution.model.form.AssetForm;
/**
* 通知Service
* @author liwenbin
*
*/
public interface INotifyService {
/**
* 通知资金系统
* @param assetForm
*/
public void notifyFundServer(AssetForm assetForm);
}
package com.quantgroup.asset.distribution.service.notify.impl;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
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.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.service.distribute.IDistributeFailLogService;
import com.quantgroup.asset.distribution.service.httpclient.IHttpService;
import com.quantgroup.asset.distribution.service.notify.INotifyService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class NotifyServiceImpl implements INotifyService{
@Value("${isDebug}")
private Boolean isDebug;
@Autowired
private IHttpService httpService;
@Autowired
private IDistributeFailLogService distributeFailLogService;
@Async
@Override
public void notifyFundServer(AssetForm assetForm) {
try {
if (isDebug) { return; }
log.info("通知资金系统结果开始, uuid : {}, bizNo : {}, assetNo : {}, callbackUrl : {}, assetForm : {}", assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo(), assetForm.getCallbackUrl(), JSON.toJSONString(assetForm));
if (StringUtils.isEmpty(assetForm.getCallbackUrl())) {
log.info("通知资金系统结果失败,callbackUrl为空, uuid : {}, bizNo : {}, assetNo : {}, assetForm : {}", assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo(), JSON.toJSONString(assetForm));
return;
}
Map<String, String> response = httpService.postHasResponse(assetForm.getCallbackUrl(), assetForm.transToNotifyMap());
log.info("通知资金系统结果结束, uuid : {}, bizNo : {}, assetNo : {}, callbackUrl : {}, assetForm : {}, response : {}", assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo(), assetForm.getCallbackUrl(), JSON.toJSONString(assetForm), JSON.toJSONString(response));
if(response==null || response.size()==0 || !"200".equals(response.get("statusCode")) || "error".equals(response.get("response"))) {
distributeFailLogService.saveDistributeFailLog(assetForm, "通知资金系统失败.");
}
} catch (Exception e) {
log.info("通知资金系统结果异常, uuid : {}, bizNo : {}, assetNo : {}, callbackUrl : {}, assetForm : {}", assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo(), assetForm.getCallbackUrl(), JSON.toJSONString(assetForm), e);
}
}
}
package com.quantgroup.asset.distribution.service.rule;
import java.util.Map;
public interface IRuleService {
/**
* 表达式判断
* @param expression 表达式
* @param data 变量数据
* @return 返回true或者false
*/
public boolean valid(String expression, Map<String, Object> data);
}
package com.quantgroup.asset.distribution.service.rule.impl;
import java.math.BigDecimal;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.quantgroup.asset.distribution.exception.QGException;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.service.rule.IRuleService;
import com.quantgroup.asset.distribution.util.calc.Expression;
import com.quantgroup.asset.distribution.util.calc.Expression.ExpressionException;
import lombok.extern.slf4j.Slf4j;
/**
* 规则判断
* @author liwenbin
*
*/
@Slf4j
@Service
public class RuleServiceImpl implements IRuleService{
@Override
public boolean valid(String expression, Map<String, Object> data) {
try {
// 如果el表达式为空,返回true
if (StringUtils.isEmpty(expression)) { return true; }
Expression ex = new Expression(expression);
for (Map.Entry<String, Object> entry : data.entrySet()) {
ex.with(entry.getKey(), String.valueOf(entry.getValue()));
}
BigDecimal res = ex.eval();
QGPreconditions.checkArgument(res.compareTo(BigDecimal.ZERO) == 0 || res.compareTo(BigDecimal.ONE) == 0, QGExceptionType.RULE_CALC_UNKNOW_RESULT, expression);
return res.compareTo(BigDecimal.ONE) == 0;
} catch (ExpressionException expressionException) {
log.error("规则判断出现错误, expression : {}, data : {}", expression, JSON.toJSONString(data), expressionException);
throw new QGException(QGExceptionType.RULE_CALC_ERROR, expression);
} catch (Exception e) {
log.error("规则判断出现未知异常, expression : {}, data : {}", expression, JSON.toJSONString(data), e);
throw new QGException(QGExceptionType.RULE_CALC_UNKNOW_ERROR, expression);
}
}
}
/*
* Copyright 2018 Udo Klimaschewski
*
* http://UdoJava.com/
* http://about.me/udo.klimaschewski
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.quantgroup.asset.distribution.util.calc;
import java.util.ArrayList;
import java.util.List;
/**
* Abstract implementation of a direct function.<br>
* <br>
* This abstract implementation does implement lazyEval so that it returns the result of eval.
*/
public abstract class AbstractFunction extends AbstractLazyFunction implements Function {
/**
* Creates a new function with given name and parameter count.
*
* @param name The name of the function.
* @param numParams The number of parameters for this function.
* <code>-1</code> denotes a variable number of parameters.
*/
protected AbstractFunction(String name, int numParams) {
super(name, numParams);
}
protected AbstractFunction(String name, boolean booleanFunction) {
super(name, booleanFunction);
}
/**
* Creates a new function with given name and parameter count.
*
* @param name The name of the function.
* @param numParams The number of parameters for this function.
* <code>-1</code> denotes a variable number of parameters.
* @param booleanFunction Whether this function is a boolean function.
*/
protected AbstractFunction(String name, int numParams, boolean booleanFunction) {
super(name, numParams, booleanFunction);
}
public Expression.LazyNumber lazyEval(final List<Expression.LazyNumber> lazyParams) {
return new Expression.LazyNumber() {
private List<String> params;
public String eval() {
return AbstractFunction.this.eval(getParams()).toPlainString();
}
private List<String> getParams() {
if (params == null) {
params = new ArrayList<>();
for (Expression.LazyNumber lazyParam : lazyParams) {
params.add(lazyParam.eval());
}
}
return params;
}
};
}
}
/*
* Copyright 2018 Udo Klimaschewski
*
* http://UdoJava.com/
* http://about.me/udo.klimaschewski
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.quantgroup.asset.distribution.util.calc;
import java.util.Locale;
/**
* Abstract implementation of a lazy function which implements all necessary methods with the
* exception of the main logic.
*/
public abstract class AbstractLazyFunction implements LazyFunction {
/**
* Name of this function.
*/
protected String name;
/**
* Number of parameters expected for this function. <code>-1</code> denotes a variable number of
* parameters.
*/
protected int numParams;
/**
* Whether this function is a boolean function.
*/
protected boolean booleanFunction;
/**
* Creates a new function with given name and parameter count.
*
* @param name The name of the function.
* @param numParams The number of parameters for this function.
* <code>-1</code> denotes a variable number of parameters.
* @param booleanFunction Whether this function is a boolean function.
*/
protected AbstractLazyFunction(String name, int numParams, boolean booleanFunction) {
this.name = name.toUpperCase(Locale.ROOT);
this.numParams = numParams;
this.booleanFunction = booleanFunction;
}
/**
* Creates a new function with given name and parameter count.
*
* @param name The name of the function.
* @param numParams The number of parameters for this function.
* <code>-1</code> denotes a variable number of parameters.
*/
protected AbstractLazyFunction(String name, int numParams) {
this(name, numParams, false);
}
public AbstractLazyFunction(String name, boolean booleanFunction) {
this.name = name;
this.booleanFunction = booleanFunction;
}
public String getName() {
return name;
}
public int getNumParams() {
return numParams;
}
public boolean numParamsVaries() {
return numParams < 0;
}
public boolean isBooleanFunction() {
return booleanFunction;
}
}
/*
* Copyright 2018 Udo Klimaschewski
*
* http://UdoJava.com/
* http://about.me/udo.klimaschewski
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.quantgroup.asset.distribution.util.calc;
/**
* Abstract implementation of an operator.
*/
public abstract class AbstractLazyOperator implements LazyOperator {
/**
* This operators name (pattern).
*/
protected String oper;
/**
* Operators precedence.
*/
protected int precedence;
/**
* Operator is left associative.
*/
protected boolean leftAssoc;
/**
* Whether this operator is boolean or not.
*/
protected boolean booleanOperator = false;
/**
* Creates a new operator.
*
* @param oper
* The operator name (pattern).
* @param precedence
* The operators precedence.
* @param leftAssoc
* <code>true</code> if the operator is left associative,
* else <code>false</code>.
* @param booleanOperator
* Whether this operator is boolean.
*/
protected AbstractLazyOperator(String oper, int precedence, boolean leftAssoc, boolean booleanOperator) {
this.oper = oper;
this.precedence = precedence;
this.leftAssoc = leftAssoc;
this.booleanOperator = booleanOperator;
}
/**
* Creates a new operator.
*
* @param oper
* The operator name (pattern).
* @param precedence
* The operators precedence.
* @param leftAssoc
* <code>true</code> if the operator is left associative,
* else <code>false</code>.
*/
protected AbstractLazyOperator(String oper, int precedence, boolean leftAssoc) {
this.oper = oper;
this.precedence = precedence;
this.leftAssoc = leftAssoc;
}
public String getOper() {
return oper;
}
public int getPrecedence() {
return precedence;
}
public boolean isLeftAssoc() {
return leftAssoc;
}
public boolean isBooleanOperator() {
return booleanOperator;
}
}
/*
* Copyright 2018 Udo Klimaschewski
*
* http://UdoJava.com/
* http://about.me/udo.klimaschewski
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.quantgroup.asset.distribution.util.calc;
/**
* Abstract implementation of an operator.
*/
public abstract class AbstractOperator extends AbstractLazyOperator implements Operator {
/**
* Creates a new operator.
*
* @param oper The operator name (pattern).
* @param precedence The operators precedence.
* @param leftAssoc <code>true</code> if the operator is left associative, else
* <code>false</code>.
* @param booleanOperator Whether this operator is boolean.
*/
protected AbstractOperator(String oper, int precedence, boolean leftAssoc,
boolean booleanOperator) {
super(oper, precedence, leftAssoc, booleanOperator);
}
/**
* Creates a new operator.
*
* @param oper The operator name (pattern).
* @param precedence The operators precedence.
* @param leftAssoc <code>true</code> if the operator is left associative, else
* <code>false</code>.
*/
protected AbstractOperator(String oper, int precedence, boolean leftAssoc) {
super(oper, precedence, leftAssoc);
}
public Expression.LazyNumber eval(final Expression.LazyNumber v1,
final Expression.LazyNumber v2) {
return () -> AbstractOperator.this.eval(v1.eval(), v2.eval()).toPlainString();
}
}
/*
* Copyright 2018 Udo Klimaschewski
*
* http://UdoJava.com/
* http://about.me/udo.klimaschewski
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.quantgroup.asset.distribution.util.calc;
import java.math.BigDecimal;
/**
* Abstract implementation of an unary operator.<br>
* <br>
* This abstract implementation implements eval so that it forwards its first parameter to
* evalUnary.
*/
public abstract class AbstractUnaryOperator extends AbstractOperator {
/**
* Creates a new operator.
*
* @param oper The operator name (pattern).
* @param precedence The operators precedence.
* @param leftAssoc <code>true</code> if the operator is left associative, else
* <code>false</code>.
*/
protected AbstractUnaryOperator(String oper, int precedence, boolean leftAssoc) {
super(oper, precedence, leftAssoc);
}
public Expression.LazyNumber eval(final Expression.LazyNumber v1,
final Expression.LazyNumber v2) {
if (v2 != null) {
throw new Expression.ExpressionException(
"Did not expect a second parameter for unary operator");
}
return () -> AbstractUnaryOperator.this.evalUnary(v1.eval()).toPlainString();
}
public BigDecimal eval(String v1, String v2) {
if (v2 != null) {
throw new Expression.ExpressionException(
"Did not expect a second parameter for unary operator");
}
return evalUnary(v1);
}
/**
* Implementation of this unary operator.
*
* @param v1 The parameter.
* @return The result of the operation.
*/
public abstract BigDecimal evalUnary(String v1);
}
/*
* Copyright 2018 Udo Klimaschewski
*
* http://UdoJava.com/
* http://about.me/udo.klimaschewski
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.quantgroup.asset.distribution.util.calc;
import java.math.BigDecimal;
import java.util.List;
/**
* Base interface which is required for all directly evaluated functions.
*/
public interface Function extends LazyFunction {
/**
* Implementation for this function.
*
* @param parameters Parameters will be passed by the expression evaluator as a {@link List} of
* {@link BigDecimal} values.
* @return The function must return a new {@link BigDecimal} value as a computing result.
*/
BigDecimal eval(List<String> parameters);
}
/*
* Copyright 2018 Udo Klimaschewski
*
* http://UdoJava.com/
* http://about.me/udo.klimaschewski
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.quantgroup.asset.distribution.util.calc;
import java.util.List;
/**
* Base interface which is required for lazily evaluated functions. A function is defined by a name,
* a number of parameters it accepts and of course the logic for evaluating the result.
*/
public interface LazyFunction {
/**
* Gets the name of this function.<br>
* <br>
* The name is use to invoke this function in the expression.
*
* @return The name of this function.
*/
String getName();
/**
* Gets the number of parameters this function accepts.<br>
* <br>
* A value of <code>-1</code> denotes that this function accepts a variable number of parameters.
*
* @return The number of parameters this function accepts.
*/
int getNumParams();
/**
* Gets whether the number of accepted parameters varies.<br>
* <br>
* That means that the function does accept an undefined amount of parameters.
*
* @return <code>true</code> if the number of accepted parameters varies.
*/
boolean numParamsVaries();
/**
* Gets whether this function evaluates to a boolean expression.
*
* @return <code>true</code> if this function evaluates to a boolean
* expression.
*/
boolean isBooleanFunction();
/**
* Lazily evaluate this function.
*
* @param lazyParams The accepted parameters.
* @return The lazy result of this function.
*/
Expression.LazyNumber lazyEval(List<Expression.LazyNumber> lazyParams);
}
/*
* Copyright 2018 Udo Klimaschewski
*
* http://UdoJava.com/
* http://about.me/udo.klimaschewski
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.quantgroup.asset.distribution.util.calc;
/**
* Base interface which is required for all operators.
*/
public interface LazyOperator {
/**
* Gets the String that is used to denote the operator in the expression.
*
* @return The String that is used to denote the operator in the expression.
*/
String getOper();
/**
* Gets the precedence value of this operator.
*
* @return the precedence value of this operator.
*/
int getPrecedence();
/**
* Gets whether this operator is left associative (<code>true</code>) or if this operator is right
* associative (<code>false</code>).
*
* @return <code>true</code> if this operator is left associative.
*/
boolean isLeftAssoc();
/**
* Gets whether this operator evaluates to a boolean expression.
*
* @return <code>true</code> if this operator evaluates to a boolean
* expression.
*/
boolean isBooleanOperator();
/**
* Implementation for this operator.
*
* @param v1 Operand 1.
* @param v2 Operand 2.
* @return The result of the operation.
*/
Expression.LazyNumber eval(Expression.LazyNumber v1, Expression.LazyNumber v2);
}
/*
* Copyright 2018 Udo Klimaschewski
*
* http://UdoJava.com/
* http://about.me/udo.klimaschewski
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package com.quantgroup.asset.distribution.util.calc;
import java.math.BigDecimal;
/**
* Base interface which is required for all operators.
*/
public interface Operator extends LazyOperator {
/**
* Implementation for this operator.
*
* @param v1 Operand 1.
* @param v2 Operand 2.
* @return The result of the operation.
*/
BigDecimal eval(String v1, String v2);
}
package com.quantgroup.asset.distribution.authority;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -7,8 +11,11 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.quantgroup.asset.distribution.AssetDistributionBootstrap;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.service.jpa.entity.AuthorityConfig;
import com.quantgroup.asset.distribution.service.jpa.repository.IAuthorityRepository;
import com.quantgroup.asset.distribution.util.calc.Expression;
/**
* 权限配置测试类
......@@ -26,6 +33,31 @@ public class AuthorityTest {
public void testAuthorityRepository() {
AuthorityConfig config = authorityRepository.findByAuthKeyAndAuthPassAndEnableIsTrue("lz_mo_fang", "123456");
System.out.println(config);
}
@Test
public void testRepository() {
}
public static void main(String[] args) {
// com.quantgroup.asset.distribution.util.calc.Expression expression = new com.quantgroup.asset.distribution.util.calc.Expression("filter_fraud_point_v5==false");
// BigDecimal result = expression.with("filter_fraud_point_v5", "true").eval();
// System.out.println(result.compareTo(BigDecimal.ZERO) == 1);
// System.out.println(expression.with("filter_fraud_point_v5", "0.04").with("2022872_result", "32").eval());
// Expression expression = new Expression("filter_fraud_point_v5<0.4");
// System.out.println(expression.with("filter_fraud_point_v5", "0.03").eval());
String expression = "filter_fraud_point_v5>0.06";
Map<String, Object> data = new HashMap<String, Object>();
data.put("filter_fraud_point_v5", (Object)0.07);
data.put("v5", (Object)666);
data.put("liwenbin", (Object)7);
Expression ex = new Expression(expression);
for (Map.Entry<String, Object> entry : data.entrySet()) {
ex.with(entry.getKey(), String.valueOf(entry.getValue()));
}
System.out.println(ex.eval());
}
}
package com.quantgroup.asset.distribution.distribute;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.quantgroup.asset.distribution.AssetDistributionBootstrap;
import com.quantgroup.asset.distribution.model.entity.DistributeRecord;
import com.quantgroup.asset.distribution.service.distribute.IAssetDistributeRecordService;
import com.quantgroup.asset.distribution.service.jpa.entity.AssetDistributeRecord;
@SpringBootTest(classes = AssetDistributionBootstrap.class)
@RunWith(SpringRunner.class)
public class DistributeTest {
@Autowired
private IAssetDistributeRecordService assetDistributeRecordService;
@Test
public void test() {
List<AssetDistributeRecord> assetDistributeRecords = assetDistributeRecordService.getDistributeRecord("ASET0645dd8bdbe5458dacccad57ab22fbaf");
List<Integer> list = new ArrayList<>();
for (AssetDistributeRecord assetDistributeRecord : assetDistributeRecords) {
JSONArray array = JSON.parseObject(assetDistributeRecord.getAssetDistributeTravel()).getJSONArray("records");
for (int i = 0, len = array.size(); i < len; ++i) {
JSONObject record = array.getJSONObject(i);
list.add(record.getInteger("type"));
}
}
System.out.println(list);
}
}
package com.quantgroup.asset.distribution.rule;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.quantgroup.asset.distribution.AssetDistributionBootstrap;
import com.quantgroup.asset.distribution.service.rule.IRuleService;
@SpringBootTest(classes = AssetDistributionBootstrap.class)
@RunWith(SpringRunner.class)
public class RuleValidTest {
@Autowired
private IRuleService ruleService;
@Test
public void testRuleValid() {
Map<String, Object> data = new HashMap<>();
data.put("status", "0");
System.out.println(ruleService.valid("status!=0", data));
}
}
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