|
@@ -2,13 +2,17 @@ package com.zanxiang.game.back.serve.utils;
|
|
|
|
|
|
import com.github.sd4324530.jtuple.Tuple2;
|
|
|
import com.github.sd4324530.jtuple.Tuple3;
|
|
|
+import com.github.sd4324530.jtuple.Tuple4;
|
|
|
import com.github.sd4324530.jtuple.Tuples;
|
|
|
+import com.zanxiang.game.back.serve.pojo.BackPolicyOfSplitLevel;
|
|
|
+import com.zanxiang.game.back.serve.pojo.BackPolicyOfSumRecharge;
|
|
|
import com.zanxiang.game.back.serve.pojo.entity.GameBackPolicy;
|
|
|
import com.zanxiang.game.back.serve.pojo.enums.BackUnitEnum;
|
|
|
import com.zanxiang.game.back.serve.pojo.vo.GameBackPolicyVO;
|
|
|
import com.zanxiang.module.util.DateUtil;
|
|
|
import com.zanxiang.module.util.JsonUtil;
|
|
|
import com.zanxiang.module.util.NumberUtil;
|
|
|
+import com.zanxiang.module.util.exception.BaseException;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.collections4.CollectionUtils;
|
|
|
import org.apache.commons.lang3.RandomUtils;
|
|
@@ -23,28 +27,205 @@ import java.util.Collections;
|
|
|
import java.util.List;
|
|
|
import java.util.Objects;
|
|
|
import java.util.function.Function;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
@Slf4j
|
|
|
public class BackPolicyUtil {
|
|
|
- private static final long[] RECHARGE_LEVEL = {12 * 100L, 30 * 100L, 50 * 100L, 98 * 100L, 198 * 100L, 328 * 100L, 649 * 100L, 998 * 100L, 2998 * 100L};
|
|
|
-
|
|
|
- static {
|
|
|
- Arrays.sort(RECHARGE_LEVEL);
|
|
|
- }
|
|
|
|
|
|
|
|
|
* 订单回传
|
|
|
*
|
|
|
* @return <是否回传,回传金额,回传描述>
|
|
|
*/
|
|
|
- public static Tuple3<Boolean, Long, String> backOrder(String orderId, GameBackPolicy gameBackPolicy,
|
|
|
- long rechargeMoney, boolean isFirstOrder,
|
|
|
- LocalDateTime payTime, LocalDateTime regTime,
|
|
|
- String userId, IBackPolicyCheck backPolicyCheck) {
|
|
|
+ public static Tuple4<Boolean, Long, String, List<Tuple2<Long, LocalDateTime>>> backOrder(String orderId, GameBackPolicy gameBackPolicy,
|
|
|
+ long rechargeMoney, boolean isFirstOrder,
|
|
|
+ LocalDateTime payTime, LocalDateTime regTime,
|
|
|
+ String userId, IBackPolicyCheck backPolicyCheck) {
|
|
|
if (null == gameBackPolicy) {
|
|
|
log.error("订单 id[{}]找不到回传策略,默认回传", orderId);
|
|
|
- return Tuples.tuple(Boolean.TRUE, rechargeMoney, "没有回传策略");
|
|
|
+ return Tuples.tuple(Boolean.TRUE, rechargeMoney, "没有回传策略", null);
|
|
|
+ }
|
|
|
+ if (gameBackPolicy.getPolicyType() == null || Objects.equals(gameBackPolicy.getPolicyType(), GameBackPolicy.TYPE_DEFAULT)) {
|
|
|
+ Tuple3<Boolean, Long, String> backInfo = policyOfDefault(orderId, gameBackPolicy, rechargeMoney, isFirstOrder, payTime, regTime, userId, backPolicyCheck);
|
|
|
+ if (backInfo.first) {
|
|
|
+ Collection<GameBackPolicyVO.SplitStrategy> splitStrategyList = StringUtils.isBlank(gameBackPolicy.getSplitStrategy()) ? Collections.emptyList() : JsonUtil.toList(gameBackPolicy.getSplitStrategy(), List.class, GameBackPolicyVO.SplitStrategy.class);
|
|
|
+ Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitInfo = splitOrder(splitStrategyList, backInfo.second);
|
|
|
+ if (splitInfo.first) {
|
|
|
+ return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, splitInfo.third);
|
|
|
+ } else {
|
|
|
+ return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, null);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, null);
|
|
|
+ }
|
|
|
+ } else if (Objects.equals(gameBackPolicy.getPolicyType(), GameBackPolicy.TYPE_SPLIT_LEVEL)) {
|
|
|
+
|
|
|
+ BackPolicyOfSplitLevel policyOfSplitLevel = JsonUtil.toObj(gameBackPolicy.getTypeOfSplitLevelJson(), BackPolicyOfSplitLevel.class);
|
|
|
+ Tuple3<Boolean, Long, String> backInfo = policyOfSplitLevel(orderId, gameBackPolicy.getId(), policyOfSplitLevel, rechargeMoney, isFirstOrder, payTime, regTime, userId, backPolicyCheck);
|
|
|
+
|
|
|
+ if (backInfo.first) {
|
|
|
+ Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitInfo = splitOrder(policyOfSplitLevel.getSplitStrategy(), backInfo.second);
|
|
|
+ if (splitInfo.first) {
|
|
|
+ return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, splitInfo.third);
|
|
|
+ } else {
|
|
|
+ return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, null);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return Tuple4.with(backInfo.first, backInfo.second, backInfo.third, null);
|
|
|
+ }
|
|
|
+ } else if (Objects.equals(gameBackPolicy.getPolicyType(), GameBackPolicy.TYPE_SUM_RECHARGE)) {
|
|
|
+
|
|
|
+ BackPolicyOfSumRecharge policyOfSumRecharge = JsonUtil.toObj(gameBackPolicy.getTypeOfSumRechargeJson(), BackPolicyOfSumRecharge.class);
|
|
|
+ return policyOfSumRecharge(orderId, gameBackPolicy.getId(), policyOfSumRecharge, rechargeMoney, isFirstOrder, payTime, regTime, userId, backPolicyCheck);
|
|
|
+ }
|
|
|
+ throw new BaseException("未知的回传策略类型:" + gameBackPolicy.getPolicyType());
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 拆单逻辑
|
|
|
+ */
|
|
|
+ public static Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitOrder(Collection<GameBackPolicyVO.SplitStrategy> splitStrategyList, Long backMoney) {
|
|
|
+ if (CollectionUtils.isEmpty(splitStrategyList)) {
|
|
|
+ return Tuple3.with(false, backMoney, null);
|
|
|
+ }
|
|
|
+ GameBackPolicyVO.SplitStrategy backSplitStrategy = null;
|
|
|
+ for (GameBackPolicyVO.SplitStrategy splitStrategy : splitStrategyList) {
|
|
|
+ if (NumberUtil.multiply100(splitStrategy.getPayMoney()).longValue() == backMoney) {
|
|
|
+ backSplitStrategy = splitStrategy;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (backSplitStrategy == null) {
|
|
|
+ return Tuple3.with(false, backMoney, null);
|
|
|
+ }
|
|
|
+ List<Tuple2<Long, LocalDateTime>> result = new ArrayList<>();
|
|
|
+ LocalDateTime beginTime = LocalDateTime.now();
|
|
|
+ long sumMoney = 0L;
|
|
|
+ for (BigDecimal splitMoney : backSplitStrategy.getSplitList()) {
|
|
|
+ long money = NumberUtil.multiply100(splitMoney).longValue();
|
|
|
+ sumMoney += money;
|
|
|
+ result.add(Tuple2.with(money, beginTime));
|
|
|
+ int randomMinute = RandomUtils.nextInt(backSplitStrategy.getBetweenMinuteMin(), backSplitStrategy.getBetweenMinuteMax());
|
|
|
+ beginTime = beginTime.plusMinutes(randomMinute);
|
|
|
+ }
|
|
|
+ return Tuple3.with(true, sumMoney, result);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Tuple3<Boolean, Long, String> policyOfSplitLevel(String orderId, Long policyId, BackPolicyOfSplitLevel policyOfSplitLevel,
|
|
|
+ long rechargeMoney, boolean isFirstOrder,
|
|
|
+ LocalDateTime payTime, LocalDateTime regTime,
|
|
|
+ String userId, IBackPolicyCheck backPolicyCheck) {
|
|
|
+ BigDecimal rechargeAmount = NumberUtil.divide100(new BigDecimal(rechargeMoney));
|
|
|
+ if (policyOfSplitLevel.getRegPayIntervalTime() != null
|
|
|
+ && ((DateUtil.localDateTimeToSecond(payTime) - DateUtil.localDateTimeToSecond(regTime)) / 60) > policyOfSplitLevel.getRegPayIntervalTime()) {
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,超过注册充值间隔时间({}),不回传", orderId, policyId, policyOfSplitLevel.getRegPayIntervalTime());
|
|
|
+ return Tuples.tuple(Boolean.FALSE, rechargeMoney, "超过注册充值间隔时间(" + policyOfSplitLevel.getRegPayIntervalTime() + "),不回传");
|
|
|
+ }
|
|
|
+ if (policyOfSplitLevel.getBackCountOfUser() != null) {
|
|
|
+ long userBackCount = backPolicyCheck.backCountForUser(BackUnitEnum.LARGE_AMOUNT, userId, false);
|
|
|
+ if (userBackCount > policyOfSplitLevel.getBackCountOfUser()) {
|
|
|
+ return Tuples.tuple(Boolean.FALSE, rechargeMoney, "单用户最大回传 " + policyOfSplitLevel.getBackCountOfUser() + "笔,当前已回传 " + userBackCount + "笔");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ BackPolicyOfSplitLevel.RechargeLevel rechargeLevel = null;
|
|
|
+ for (BackPolicyOfSplitLevel.RechargeLevel item : policyOfSplitLevel.getRechargeLevelList()) {
|
|
|
+ if (rechargeAmount.compareTo(item.getMinAmount()) >= 0 && rechargeAmount.compareTo(item.getMaxAmount()) < 0) {
|
|
|
+ rechargeLevel = item;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (rechargeLevel == null) {
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,找不到对应的充值挡位,不回传", orderId, policyId);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, rechargeMoney, "充值金额(" + rechargeAmount + ")未找到对应的挡位,默认不回传");
|
|
|
+ }
|
|
|
+ if (Objects.equals(rechargeLevel.getBackType(), GameBackPolicy.POLICY_TYPE_FIXED_RATE)) {
|
|
|
+
|
|
|
+ String[] temp = rechargeLevel.getBackRate().split(":");
|
|
|
+ int backCount = Integer.parseInt(temp[0]);
|
|
|
+ int ignoreCount = Integer.parseInt(temp[1]);
|
|
|
+ if (backCount == 0) {
|
|
|
+ String backMsg = "按比例回传,回传比例为 0,全部不回传";
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:{}", orderId, policyId, backMsg);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, rechargeMoney, backMsg);
|
|
|
+ }
|
|
|
+ if (ignoreCount == 0) {
|
|
|
+ String backMsg = "按比例回传,忽略比例为 0,全部回传";
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,回传,原因:{}", orderId, policyId, backMsg);
|
|
|
+ return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, policyOfSplitLevel.getDownLevel()), backMsg);
|
|
|
+ }
|
|
|
+ long isBackCount = backPolicyCheck.backCountForFixedRate(backCount + ignoreCount, BackUnitEnum.LARGE_AMOUNT, false);
|
|
|
+ String backMsg = "按比例回传,每 " + (backCount + ignoreCount) + "笔回传 " + backCount + "笔,当前第 " + (isBackCount + 1) + "笔";
|
|
|
+ if (isBackCount >= backCount) {
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:{}", orderId, policyId, backMsg);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, policyOfSplitLevel.getDownLevel()), backMsg);
|
|
|
+ } else {
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,回传,原因:{}", orderId, policyId, backMsg);
|
|
|
+ return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, policyOfSplitLevel.getDownLevel()), backMsg);
|
|
|
+ }
|
|
|
+ } else if (Objects.equals(rechargeLevel.getBackType(), GameBackPolicy.POLICY_TYPE_RANDOM_RATE)) {
|
|
|
+
|
|
|
+ boolean isBack = RandomUtils.nextInt(0, 100) < NumberUtil.multiply100(new BigDecimal(rechargeLevel.getBackRate())).intValue();
|
|
|
+ String backMsg = "随机概率回传(" + NumberUtil.multiply100(new BigDecimal(rechargeLevel.getBackRate())) + "%)";
|
|
|
+ if (!isBack) {
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:{}", orderId, policyId, backMsg);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, policyOfSplitLevel.getDownLevel()), backMsg);
|
|
|
+ } else {
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,回传,原因:{}", orderId, policyId, backMsg);
|
|
|
+ return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, policyOfSplitLevel.getDownLevel()), backMsg);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ throw new RuntimeException("回传策略[" + policyId + "]配置错误,未知的回传类型:" + rechargeLevel.getBackType());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Tuple4<Boolean, Long, String, List<Tuple2<Long, LocalDateTime>>> policyOfSumRecharge(String orderId, Long policyId, BackPolicyOfSumRecharge policyOfSumRecharge,
|
|
|
+ long rechargeMoney, boolean isFirstOrder,
|
|
|
+ LocalDateTime payTime, LocalDateTime regTime,
|
|
|
+ String userId, IBackPolicyCheck backPolicyCheck) {
|
|
|
+ BigDecimal rechargeAmount = NumberUtil.divide100(new BigDecimal(rechargeMoney));
|
|
|
+ if (policyOfSumRecharge.getRegPayIntervalTime() != null
|
|
|
+ && ((DateUtil.localDateTimeToSecond(payTime) - DateUtil.localDateTimeToSecond(regTime)) / 60) > policyOfSumRecharge.getRegPayIntervalTime()) {
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,超过注册充值间隔时间({}),不回传", orderId, policyId, policyOfSumRecharge.getRegPayIntervalTime());
|
|
|
+ return Tuples.tuple(Boolean.FALSE, rechargeMoney, "超过注册充值间隔时间(" + policyOfSumRecharge.getRegPayIntervalTime() + "),不回传", null);
|
|
|
+ }
|
|
|
+ BackPolicyOfSumRecharge.RechargeLevel rechargeLevel = null;
|
|
|
+ for (BackPolicyOfSumRecharge.RechargeLevel item : policyOfSumRecharge.getRechargeLevelList()) {
|
|
|
+ if (rechargeAmount.compareTo(item.getMinAmount()) >= 0 && rechargeAmount.compareTo(item.getMaxAmount()) < 0) {
|
|
|
+ rechargeLevel = item;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (rechargeLevel == null) {
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,找不到对应的累充挡位,不回传", orderId, policyId);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, rechargeMoney, "充值金额(" + rechargeAmount + ")未找到对应的挡位,默认不回传", null);
|
|
|
+ }
|
|
|
+ Tuple2<Long, Long> backInfo = backPolicyCheck.backCountForUserWithSplitOrder(userId);
|
|
|
+ if (rechargeLevel.getBackCountOfUser() <= backInfo.first) {
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,已达到回传的订单数,不回传", orderId, policyId);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, rechargeMoney, "充值金额(" + rechargeAmount + ")已达到回传的订单数(已回传:" + backInfo.first + "笔,当前挡位:" + rechargeLevel.getBackCountOfUser() + "笔),不回传", null);
|
|
|
}
|
|
|
+
|
|
|
+ long backCount = rechargeLevel.getBackCountOfUser() - backInfo.first;
|
|
|
+ long backMoney = backInfo.second - NumberUtil.multiply100(rechargeLevel.getMinAmount()).longValue();
|
|
|
+ if (backMoney <= 0) {
|
|
|
+
|
|
|
+ backMoney = 1;
|
|
|
+ }
|
|
|
+ List<Tuple2<Long, LocalDateTime>> splitOrder = new ArrayList<>();
|
|
|
+ for (int i = 0; i < backCount; i++) {
|
|
|
+ splitOrder.add(Tuple2.with(backMoney, LocalDateTime.now()));
|
|
|
+ }
|
|
|
+ String backMsg = "充值金额(" + rechargeAmount + ") 已回传:" + backInfo.first + "笔,当前挡位:" + rechargeLevel.getBackCountOfUser() + "笔,回传(" + backCount + "-" + backMoney + ")笔";
|
|
|
+ log.error("订单 id[{}]通过回传策略[{}]判断后,回传。回传日志:{}", orderId, policyId, backMsg);
|
|
|
+ return Tuples.tuple(Boolean.TRUE, rechargeMoney, backMsg, splitOrder);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Tuple3<Boolean, Long, String> policyOfDefault(String orderId, GameBackPolicy gameBackPolicy,
|
|
|
+ long rechargeMoney, boolean isFirstOrder,
|
|
|
+ LocalDateTime payTime, LocalDateTime regTime,
|
|
|
+ String userId, IBackPolicyCheck backPolicyCheck) {
|
|
|
if (gameBackPolicy.getSupperSmallAmount() != null && gameBackPolicy.getSupperSmallAmount() >= rechargeMoney) {
|
|
|
log.error("订单 id[{}]被判定为超小额订单({}),默认不回传", orderId, gameBackPolicy.getSupperSmallAmount());
|
|
|
return Tuples.tuple(Boolean.FALSE, rechargeMoney, "超小额订单(<=" + gameBackPolicy.getSupperSmallAmount() + "),不回传");
|
|
@@ -64,6 +245,9 @@ public class BackPolicyUtil {
|
|
|
&& ((DateUtil.localDateTimeToSecond(payTime) - DateUtil.localDateTimeToSecond(regTime)) / 60) > gameBackPolicy.getRegPayIntervalTime()) {
|
|
|
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,超过注册充值间隔时间,走补单逻辑 {}, money: {}.", orderId, gameBackPolicy.getId(), gameBackPolicy.getRegPayIntervalTime(), totalRechargeAmount);
|
|
|
+
|
|
|
+ List<GameBackPolicyVO.PolicyDownLevel> downLevels = StringUtils.isEmpty(gameBackPolicy.getMarkUpDownLevel()) ? Collections.emptyList()
|
|
|
+ : Arrays.stream(gameBackPolicy.getMarkUpDownLevel().split(",")).map(BackPolicyUtil::transformDownLevel).collect(Collectors.toList());
|
|
|
if (gameBackPolicy.getMarkUpOrder() != null && gameBackPolicy.getMarkUpOrder()) {
|
|
|
long money = backUnit == BackUnitEnum.LARGE_AMOUNT ? totalRechargeAmount : rechargeMoney;
|
|
|
markUpTime = gameBackPolicy.getRegPayIntervalTime();
|
|
@@ -87,17 +271,17 @@ public class BackPolicyUtil {
|
|
|
int ignoreCount = Integer.parseInt(temp[1]);
|
|
|
if (backCount == 0) {
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:回传比例 {}", orderId, gameBackPolicy.getId(), backRate);
|
|
|
- return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), "补单-按比例回传,回传比例为 0,全部不回传");
|
|
|
+ return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), "补单-按比例回传,回传比例为 0,全部不回传");
|
|
|
}
|
|
|
if (ignoreCount == 0) {
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,回传,原因:回传比例 {}", orderId, gameBackPolicy.getId(), backRate);
|
|
|
- return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), "补单-按比例回传,忽略比例为 0,全部回传");
|
|
|
+ return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevels), "补单-按比例回传,忽略比例为 0,全部回传");
|
|
|
}
|
|
|
long isBackCount = backPolicyCheck.markUpOfFixedRate(backCount + ignoreCount, markUpTime);
|
|
|
backMsg = "补单-按比例回传,每 " + (backCount + ignoreCount) + "笔回传 " + backCount + "笔,当前第 " + (isBackCount + 1) + "笔";
|
|
|
if (isBackCount >= backCount) {
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:{}", orderId, gameBackPolicy.getId(), backMsg);
|
|
|
- return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), backMsg);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), backMsg);
|
|
|
}
|
|
|
} else if (Objects.equals(backType, GameBackPolicy.POLICY_TYPE_RANDOM_RATE)) {
|
|
|
|
|
@@ -105,22 +289,22 @@ public class BackPolicyUtil {
|
|
|
backMsg = "补单-随机概率回传(" + NumberUtil.multiply100(new BigDecimal(backRate)) + "%)";
|
|
|
if (!isBack) {
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:{}", orderId, gameBackPolicy.getId(), backMsg);
|
|
|
- return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), backMsg);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), backMsg);
|
|
|
}
|
|
|
} else {
|
|
|
throw new RuntimeException("回传策略[" + gameBackPolicy.getId() + "]配置错误,未知的回传类型:" + backType);
|
|
|
}
|
|
|
if (gameBackPolicy.getMarkUpBackCountOfUser() == null) {
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,回传,原因:回传概率 {}", orderId, gameBackPolicy.getId(), backMsg);
|
|
|
- return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), backMsg);
|
|
|
+ return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevels), backMsg);
|
|
|
}
|
|
|
long userBackCount = backPolicyCheck.markUpForUser(userId, markUpTime);
|
|
|
backMsg = backMsg + ",单用户最大回传 " + gameBackPolicy.getMarkUpBackCountOfUser() + "笔,当前已回传 " + userBackCount + "笔";
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,是否回传:{},原因:{}", orderId, gameBackPolicy.getId(), userBackCount < gameBackPolicy.getMarkUpBackCountOfUser(), backMsg);
|
|
|
- return Tuples.tuple(userBackCount < gameBackPolicy.getMarkUpBackCountOfUser(), downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), backMsg);
|
|
|
+ return Tuples.tuple(userBackCount < gameBackPolicy.getMarkUpBackCountOfUser(), downLevel(rechargeMoney, downLevels), backMsg);
|
|
|
} else {
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:超过注册充值间隔时间但是未开启补单", orderId, gameBackPolicy.getId());
|
|
|
- return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, gameBackPolicy.getMarkUpDownLevel()), "补单-未开启补单");
|
|
|
+ return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), "补单-未开启补单");
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -176,6 +360,8 @@ public class BackPolicyUtil {
|
|
|
Integer maxBackCountOfUser = firstPolicy ? gameBackPolicy.getFirstBackCountOfUser() : gameBackPolicy.getRechargeBackCountOfUser();
|
|
|
String backMsg = firstPolicy ? "首-" : "次-";
|
|
|
String downLevelString = firstPolicy ? gameBackPolicy.getFirstDownLevel() : gameBackPolicy.getRechargeDownLevel();
|
|
|
+ List<GameBackPolicyVO.PolicyDownLevel> downLevels = StringUtils.isEmpty(downLevelString) ? Collections.emptyList()
|
|
|
+ : Arrays.stream(downLevelString.split(",")).map(BackPolicyUtil::transformDownLevel).collect(Collectors.toList());
|
|
|
if (Objects.equals(backType, GameBackPolicy.POLICY_TYPE_FIXED_RATE)) {
|
|
|
|
|
|
String[] temp = backRate.split(":");
|
|
@@ -184,18 +370,18 @@ public class BackPolicyUtil {
|
|
|
if (backCount == 0) {
|
|
|
backMsg = backMsg + "按比例回传,回传比例为 0,全部不回传";
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:{}", orderId, gameBackPolicy.getId(), backMsg);
|
|
|
- return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevelString), backMsg);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), backMsg);
|
|
|
}
|
|
|
if (ignoreCount == 0) {
|
|
|
backMsg = backMsg + "按比例回传,忽略比例为 0,全部回传";
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,回传,原因:{}", orderId, gameBackPolicy.getId(), backMsg);
|
|
|
- return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevelString), backMsg);
|
|
|
+ return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevels), backMsg);
|
|
|
}
|
|
|
long isBackCount = backPolicyCheck.backCountForFixedRate(backCount + ignoreCount, backUnit, firstPolicy);
|
|
|
backMsg = backMsg + "按比例回传,每 " + (backCount + ignoreCount) + "笔回传 " + backCount + "笔,当前第 " + (isBackCount + 1) + "笔";
|
|
|
if (isBackCount >= backCount) {
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:{}", orderId, gameBackPolicy.getId(), backMsg);
|
|
|
- return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevelString), backMsg);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), backMsg);
|
|
|
}
|
|
|
} else if (Objects.equals(backType, GameBackPolicy.POLICY_TYPE_RANDOM_RATE)) {
|
|
|
|
|
@@ -203,7 +389,7 @@ public class BackPolicyUtil {
|
|
|
backMsg = backMsg + "随机概率回传(" + NumberUtil.multiply100(new BigDecimal(backRate)) + "%)";
|
|
|
if (!isBack) {
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,不回传,原因:{}", orderId, gameBackPolicy.getId(), backMsg);
|
|
|
- return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevelString), backMsg);
|
|
|
+ return Tuples.tuple(Boolean.FALSE, downLevel(rechargeMoney, downLevels), backMsg);
|
|
|
}
|
|
|
} else {
|
|
|
throw new RuntimeException("回传策略[" + gameBackPolicy.getId() + "]配置错误,未知的回传类型:" + backType);
|
|
@@ -211,100 +397,34 @@ public class BackPolicyUtil {
|
|
|
|
|
|
if (maxBackCountOfUser == null) {
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,回传,原因:回传概率 {}", orderId, gameBackPolicy.getId(), backMsg);
|
|
|
- return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevelString), backMsg);
|
|
|
+ return Tuples.tuple(Boolean.TRUE, downLevel(rechargeMoney, downLevels), backMsg);
|
|
|
}
|
|
|
long userBackCount = backPolicyCheck.backCountForUser(backUnit, userId, firstPolicy);
|
|
|
backMsg = backMsg + ",单用户最大回传 " + maxBackCountOfUser + "笔,当前已回传 " + userBackCount + "笔";
|
|
|
log.error("订单 id[{}]通过回传策略[{}]判断后,是否回传:{},原因:{}", orderId, gameBackPolicy.getId(), userBackCount < maxBackCountOfUser, backMsg);
|
|
|
- return Tuples.tuple(userBackCount < maxBackCountOfUser, downLevel(rechargeMoney, downLevelString), backMsg);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * 拆单逻辑
|
|
|
- */
|
|
|
- public static Tuple3<Boolean, Long, List<Tuple2<Long, LocalDateTime>>> splitOrder(GameBackPolicy gameBackPolicy, Long backMoney) {
|
|
|
- if (gameBackPolicy == null || StringUtils.isBlank(gameBackPolicy.getSplitStrategy())) {
|
|
|
- return Tuple3.with(false, backMoney, null);
|
|
|
- }
|
|
|
- Collection<GameBackPolicyVO.SplitStrategy> splitStrategyList = JsonUtil.toList(gameBackPolicy.getSplitStrategy(), List.class, GameBackPolicyVO.SplitStrategy.class);
|
|
|
- if (CollectionUtils.isEmpty(splitStrategyList)) {
|
|
|
- return Tuple3.with(false, backMoney, null);
|
|
|
- }
|
|
|
- GameBackPolicyVO.SplitStrategy backSplitStrategy = null;
|
|
|
- for (GameBackPolicyVO.SplitStrategy splitStrategy : splitStrategyList) {
|
|
|
- if (NumberUtil.multiply100(splitStrategy.getPayMoney()).longValue() == backMoney) {
|
|
|
- backSplitStrategy = splitStrategy;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (backSplitStrategy == null) {
|
|
|
- return Tuple3.with(false, backMoney, null);
|
|
|
- }
|
|
|
- List<Tuple2<Long, LocalDateTime>> result = new ArrayList<>();
|
|
|
- LocalDateTime beginTime = LocalDateTime.now();
|
|
|
- long sumMoney = 0L;
|
|
|
- for (BigDecimal splitMoney : backSplitStrategy.getSplitList()) {
|
|
|
- long money = NumberUtil.multiply100(splitMoney).longValue();
|
|
|
- sumMoney += money;
|
|
|
- result.add(Tuple2.with(money, beginTime));
|
|
|
- int randomMinute = RandomUtils.nextInt(backSplitStrategy.getBetweenMinuteMin(), backSplitStrategy.getBetweenMinuteMax());
|
|
|
- beginTime = beginTime.plusMinutes(randomMinute);
|
|
|
- }
|
|
|
- return Tuple3.with(true, sumMoney, result);
|
|
|
+ return Tuples.tuple(userBackCount < maxBackCountOfUser, downLevel(rechargeMoney, downLevels), backMsg);
|
|
|
}
|
|
|
|
|
|
- private static Long downLevel(Long rechargeMoney, String downLevelStr) {
|
|
|
- if (StringUtils.isBlank(downLevelStr)) {
|
|
|
+ private static Long downLevel(Long rechargeMoney, List<GameBackPolicyVO.PolicyDownLevel> downLevels) {
|
|
|
+ if (CollectionUtils.isEmpty(downLevels)) {
|
|
|
return rechargeMoney;
|
|
|
}
|
|
|
- String[] downLevelList = downLevelStr.split(",");
|
|
|
- for (String downLevel : downLevelList) {
|
|
|
- String[] tmp = downLevel.split("_");
|
|
|
- long minMoney = Long.parseLong(tmp[0]);
|
|
|
- long maxMoney = Long.parseLong(tmp[1]);
|
|
|
- Long backMoney = Long.parseLong(tmp[2]);
|
|
|
- if (rechargeMoney >= minMoney && rechargeMoney <= maxMoney) {
|
|
|
- return backMoney;
|
|
|
+ BigDecimal rechargeAmount = NumberUtil.divide100(new BigDecimal(rechargeMoney));
|
|
|
+ for (GameBackPolicyVO.PolicyDownLevel downLevel : downLevels) {
|
|
|
+ if (rechargeAmount.compareTo(downLevel.getMinMoney()) >= 0 && rechargeAmount.compareTo(downLevel.getMaxMoney()) <= 0) {
|
|
|
+ return NumberUtil.multiply100(downLevel.getBackMoney()).longValue();
|
|
|
}
|
|
|
}
|
|
|
return rechargeMoney;
|
|
|
}
|
|
|
|
|
|
- private static Tuple2<Integer, Integer> approximate(int molecular, int denominator) {
|
|
|
- if (molecular % denominator == 0) {
|
|
|
- int temp = molecular / denominator;
|
|
|
- return Tuples.tuple(temp, temp);
|
|
|
- }
|
|
|
- int model = 2;
|
|
|
- do {
|
|
|
- if (molecular % model == 0 && denominator % model == 0) {
|
|
|
- molecular = molecular / model;
|
|
|
- denominator = denominator / model;
|
|
|
- continue;
|
|
|
- }
|
|
|
- model++;
|
|
|
- } while (model <= denominator / 2);
|
|
|
- return Tuples.tuple(molecular, denominator);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- * 降档
|
|
|
- */
|
|
|
- public static long lowRechargeLevel(long rechargeMoney, String levelDownStr) {
|
|
|
- if (StringUtils.isBlank(levelDownStr)) {
|
|
|
-
|
|
|
- return rechargeMoney;
|
|
|
- }
|
|
|
- String[] levelDownStrList = levelDownStr.split(",");
|
|
|
- for (String levelDown : levelDownStrList) {
|
|
|
- String[] tmp = levelDown.split("_");
|
|
|
- long min = Long.parseLong(tmp[0]), max = Long.parseLong(tmp[1]), back = Long.parseLong(tmp[2]);
|
|
|
- if (rechargeMoney >= min && rechargeMoney <= max) {
|
|
|
- return back;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return rechargeMoney;
|
|
|
+ private static GameBackPolicyVO.PolicyDownLevel transformDownLevel(String downLevel) {
|
|
|
+ String[] tmp = downLevel.split("_");
|
|
|
+ return GameBackPolicyVO.PolicyDownLevel.builder()
|
|
|
+ .minMoney(NumberUtil.divide100(new BigDecimal(Long.parseLong(tmp[0]))))
|
|
|
+ .maxMoney(NumberUtil.divide100(new BigDecimal(Long.parseLong(tmp[1]))))
|
|
|
+ .backMoney(NumberUtil.divide100(new BigDecimal(Long.parseLong(tmp[2]))))
|
|
|
+ .build();
|
|
|
}
|
|
|
|
|
|
public interface IBackPolicyCheck {
|
|
@@ -332,5 +452,13 @@ public class BackPolicyUtil {
|
|
|
* 获取用户的累充金额
|
|
|
*/
|
|
|
Long totalRechargeAmount();
|
|
|
+
|
|
|
+
|
|
|
+ * 单个用户已回传订单数(包含拆单的订单数)
|
|
|
+ * Tuple2<回传订单数、回传金额>
|
|
|
+ */
|
|
|
+ default Tuple2<Long, Long> backCountForUserWithSplitOrder(String userId) {
|
|
|
+ throw new RuntimeException("暂不支持!!");
|
|
|
+ }
|
|
|
}
|
|
|
}
|