瀏覽代碼

feature: 消费管理
1.多钱包扣费

luoyb 1 年之前
父節點
當前提交
806f83c10e

+ 64 - 51
ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/business/CheckBusiness.java

@@ -100,7 +100,7 @@ public class CheckBusiness {
         // 检查交易人员标识
         if (bo.getCardNo() <= 0 && bo.getFactoryId() == 0 && bo.getUserNo() <= 0 && StrUtil.isEmpty(bo.getUserNumb())) {
             errorInfo = new ErrorInfo(1, ApiErrorTypeConstants.PARAM_ERROR, "交易人员标识不满足",
-                                      "必须提供 [CardNo | FactoryId | userNo | userNumb] 中至少1项来标识交易用户");
+                "必须提供 [CardNo | FactoryId | userNo | userNumb] 中至少1项来标识交易用户");
             return R.fail(errorInfo);
         }
         return R.ok();
@@ -119,7 +119,7 @@ public class CheckBusiness {
         TermToken token = tokenManager.getTermToken().get(String.valueOf(termNo));
         if (ObjectUtil.isEmpty(token)) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.INVALID_TOKEN, "Token不存在",
-                                      MessageFormat.format("没有找到机号为[{0}]的设备的Token!", termNo));
+                MessageFormat.format("没有找到机号为[{0}]的设备的Token!", termNo));
             return R.fail(errorInfo);
         }
         if (ObjectUtil.isNotEmpty(mac)) {
@@ -171,10 +171,10 @@ public class CheckBusiness {
     public R<ErrorInfo> checkTerm(ConsumptionBo bo, XfTermVo useTermVo) {
         long termNo = bo.getTermNo();
         String tenantId = ObjectUtil.isNotEmpty(bo.getTenantId()) ? bo.getTenantId() : defaultConfig.getTenantId();
-        RemoteXfTermVo remoteXfTermVo = remoteXfTermService.queryByNo(termNo,tenantId);
+        RemoteXfTermVo remoteXfTermVo = remoteXfTermService.queryByNo(termNo, tenantId);
         if (ObjectUtil.isEmpty(remoteXfTermVo)) {
             ErrorInfo errorInfo = new ErrorInfo(400, "", "设备不存在",
-                                                MessageFormat.format("机号为[{0}]的设备不存在,不允许交易", termNo));
+                MessageFormat.format("机号为[{0}]的设备不存在,不允许交易", termNo));
 
             return R.fail(errorInfo);
         }
@@ -199,22 +199,22 @@ public class CheckBusiness {
         // 1.消费账户状态验证,验证账户是否已开户、是否冻结、状态是否正常、是否过有效期
         if ("Y".equals(userAccountVo.getFreezeStatus())) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.NOT_FOUND, "账户已被冻结",
-                                      MessageFormat.format("流水号为[{0}]的账户已被冻结,不允许交易", userAccountVo.getUserNo()));
+                MessageFormat.format("流水号为[{0}]的账户已被冻结,不允许交易", userAccountVo.getUserNo()));
             return R.fail(errorInfo);
         }
         if ("N".equals(userAccountVo.getStatus())) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.NOT_FOUND, "账户状态不正常",
-                                      MessageFormat.format("流水号为[{0}]的账户状态不正常,不允许交易", userAccountVo.getUserNo()));
+                MessageFormat.format("流水号为[{0}]的账户状态不正常,不允许交易", userAccountVo.getUserNo()));
             return R.fail(errorInfo);
         }
         if (!ObjectUtil.equal(userAccountVo.getAccountStatus(), UserAccountStatusEnum.IS_OPEN.code().toString())) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.NOT_FOUND, "账户尚未开户",
-                                      MessageFormat.format("流水号为[{0}]的账户尚未开户,不允许交易", userAccountVo.getUserNo()));
+                MessageFormat.format("流水号为[{0}]的账户尚未开户,不允许交易", userAccountVo.getUserNo()));
             return R.fail(errorInfo);
         }
         if (userAccountVo.getLifespan() != null && bo.getConsumeDate().getTime() > userAccountVo.getLifespan().getTime()) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.NOT_FOUND, "账户已过有效期",
-                                      MessageFormat.format("流水号为[{0}]的账户已过有效期,不允许交易", userAccountVo.getUserNo()));
+                MessageFormat.format("流水号为[{0}]的账户已过有效期,不允许交易", userAccountVo.getUserNo()));
             return R.fail(errorInfo);
         }
         // 2.餐类验证
@@ -298,13 +298,13 @@ public class CheckBusiness {
         RemoteCardVo cardVo = remoteCardService.queryCardByCardNo(cardNo);
         if (ObjectUtil.isEmpty(cardVo)) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片不存在",
-                                      MessageFormat.format("流水号为[{0}]的卡片不存在,不允许交易", cardNo));
+                MessageFormat.format("流水号为[{0}]的卡片不存在,不允许交易", cardNo));
 
             return R.fail(errorInfo);
         }
         if (!String.valueOf(CardStatusEnum.NORMAL.code()).equals(cardVo.getStatus())) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片状态不正确",
-                                      MessageFormat.format("流水号为[{0}]的卡片状态不正确,不允许交易", cardNo));
+                MessageFormat.format("流水号为[{0}]的卡片状态不正确,不允许交易", cardNo));
 
             return R.fail(errorInfo);
         }
@@ -338,12 +338,12 @@ public class CheckBusiness {
         RemoteCardVo cardVo = remoteCardService.queryCardByFactoryId(factoryId);
         if (ObjectUtil.isEmpty(cardVo)) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片不存在",
-                                      MessageFormat.format("物理卡号为[{0}]的卡片不存在,不允许交易", factoryId));
+                MessageFormat.format("物理卡号为[{0}]的卡片不存在,不允许交易", factoryId));
             return R.fail(errorInfo);
         }
         if (!String.valueOf(CardStatusEnum.NORMAL.code()).equals(cardVo.getStatus())) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片状态不正确",
-                                      MessageFormat.format("物理卡号为[{0}]的卡片卡片状态不正确,不允许交易", factoryId));
+                MessageFormat.format("物理卡号为[{0}]的卡片卡片状态不正确,不允许交易", factoryId));
             return R.fail(errorInfo);
         }
         RemoteUserAccountVo accountVo = remoteUserAccountService.getUserAccountVoById(cardVo.getUserId());
@@ -369,21 +369,21 @@ public class CheckBusiness {
         RemoteUserAccountVo accountVo = remoteUserAccountService.getUserAccountVoByUserNo(userNo);
         if (ObjectUtil.isEmpty(accountVo)) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "人员不存在",
-                                      MessageFormat.format("流水号为[{0}]的人员不存在,不允许交易", userNo));
+                MessageFormat.format("流水号为[{0}]的人员不存在,不允许交易", userNo));
 
             return R.fail(errorInfo);
         }
         RemoteCardVo cardVo = remoteCardService.queryMainCardByUserId(accountVo.getUserId());
         if (ObjectUtil.isEmpty(cardVo)) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片不存在",
-                                      MessageFormat.format("没有流水号为[{0}]人员的卡片信息,不允许交易", userNo));
+                MessageFormat.format("没有流水号为[{0}]人员的卡片信息,不允许交易", userNo));
 
             return R.fail(errorInfo);
         }
         // 实体卡时需要验证卡状态
         if (!String.valueOf(CardStatusEnum.NORMAL.code()).equals(cardVo.getStatus()) && cardVo.getFactoryId() > 0) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片状态不正确",
-                                      MessageFormat.format("流水号为[{0}]的人员卡片状态不正确,不允许交易", userNo));
+                MessageFormat.format("流水号为[{0}]的人员卡片状态不正确,不允许交易", userNo));
 
             return R.fail(errorInfo);
         }
@@ -411,21 +411,21 @@ public class CheckBusiness {
 
         if (ObjectUtil.isEmpty(accountVo)) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "人员不存在",
-                                      MessageFormat.format("编号为[{0}]的人员不存在,不允许交易", userNumb));
+                MessageFormat.format("编号为[{0}]的人员不存在,不允许交易", userNumb));
 
             return R.fail(errorInfo);
         }
         RemoteCardVo cardVo = remoteCardService.queryMainCardByUserId(accountVo.getUserId());
         if (ObjectUtil.isEmpty(cardVo)) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片不存在",
-                                      MessageFormat.format("没有编号为[{0}]的人员的卡片信息,不允许交易", userNumb));
+                MessageFormat.format("没有编号为[{0}]的人员的卡片信息,不允许交易", userNumb));
 
             return R.fail(errorInfo);
         }
         // 实体卡时需要验证卡状态
         if (!String.valueOf(CardStatusEnum.NORMAL.code()).equals(cardVo.getStatus()) && cardVo.getFactoryId() > 0) {
             errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片状态不正确",
-                                      MessageFormat.format("编号为[{0}]的人员卡片状态不正确,不允许交易", userNumb));
+                MessageFormat.format("编号为[{0}]的人员卡片状态不正确,不允许交易", userNumb));
 
             return R.fail(errorInfo);
         }
@@ -441,18 +441,18 @@ public class CheckBusiness {
 
     private R<ErrorInfo> checkOriginalRecord(ConsumptionBo bo) {
         String originalId = RecordIdUtils.getRecordId(bo.getConsumeDate(), bo.getTermNo().shortValue(),
-                                                      bo.getTermRecordId().shortValue(), bo.getUserNo().intValue(), 0);
+            bo.getTermRecordId().shortValue(), bo.getUserNo().intValue(), 0);
         XfConsumeDetailOriginalVo consumeDetailOriginalVo = consumeDetailOriginalService.queryById(originalId);
         if (ObjectUtil.isEmpty(consumeDetailOriginalVo)) {
             // TODO 正常应该是进行记录类型和脱机消费的检查,此处先按错误处理
             return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.NOT_FOUND, "原始消费记录不存在",
-                                        MessageFormat.format("标识为[{0}]的原始消费记录不存在", bo.getRecordId())));
+                MessageFormat.format("标识为[{0}]的原始消费记录不存在", bo.getRecordId())));
         }
         XfConsumeDetailVo consumeDetailVo = consumeDetailService.queryVoByOriginalId(originalId);
         if (ObjectUtil.isNotEmpty(consumeDetailVo)) {
             // 认为是重复上传,不再入账
             return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.RECORD_IS_EXISTS, "原始消费记录已处理",
-                                        MessageFormat.format("标识为[{0}]的原始消费记录已处理", bo.getRecordId())));
+                MessageFormat.format("标识为[{0}]的原始消费记录已处理", bo.getRecordId())));
         }
         bo.setOriginalId(originalId);
         return R.ok();
@@ -474,14 +474,14 @@ public class CheckBusiness {
         // 计算扣费钱包的总金额
         for (String bagCode : bagCodes) {
             PtBagVo bagVo = bagService.queryByUserBagCode(userId, bagCode);
-            if(ObjectUtil.isNotEmpty(bagVo)) {
+            if (ObjectUtil.isNotEmpty(bagVo)) {
                 totalBalance = totalBalance.add(bagVo.getBalance());
             }
         }
         // 如果扣费钱包总余额<消费金额,则不允许消费
         if (consumeMoney.compareTo(totalBalance) > 0) {
             return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.CONSUME_CHECK_FAIL, "钱包余额不足",
-                                        MessageFormat.format("余额不足,余额[{0}],消费金额[{1}]", totalBalance, consumeMoney)));
+                MessageFormat.format("余额不足,余额[{0}],消费金额[{1}]", totalBalance, consumeMoney)));
         }
         for (String bagCode : bagCodes) {
             // 1.查询对应的钱包
@@ -492,21 +492,33 @@ public class CheckBusiness {
             }
             // 2.比较扣费金额
             BigDecimal balance = bagVo.getBalance();
-            if (balance.compareTo(BigDecimal.ZERO) >= 0) {
-                if (balance.compareTo(doMoney) >= 0) {
-                    // 如果钱包金额>扣费金额,设置扣费结果并中断循环
-                    bagVo.setReceiptMoney(doMoney);
-                    bagVo.setBalance(balance.subtract(doMoney));
-                    sb.append(BagNameEnum.getMessage(Integer.parseInt(bagCode)));
-                    doBagVos.add(bagVo);
-                    break;
-                } else {
-                    // 将钱包扣费为0,剩余待扣金额=消费金额-原钱包余额
-                    bagVo.setReceiptMoney(balance);
-                    bagVo.setBalance(BigDecimal.ZERO);
-                    doMoney = doMoney.subtract(balance);
-                    sb.append(BagNameEnum.getMessage(Integer.parseInt(bagCode)));
-                    doBagVos.add(bagVo);
+            log.info("钱包代码:{},钱包余额:{},消费金额:{}", bagCode, balance, doMoney);
+            if (doMoney.equals(BigDecimal.ZERO)) {
+                //如果是消费0元,设置为第一个钱包扣费
+                bagVo.setReceiptMoney(doMoney);
+                bagVo.setBalance(balance.subtract(doMoney));
+                sb.append(BagNameEnum.getMessage(Integer.parseInt(bagCode)));
+                doBagVos.add(bagVo);
+                break;
+            } else {
+                //如果消费金额>0,则可能会需要多钱包扣费
+                if (balance.compareTo(BigDecimal.ZERO) > 0) {
+                    //钱包有余额则扣费
+                    if (balance.compareTo(doMoney) >= 0) {
+                        // 如果钱包金额>=扣费金额,设置扣费结果并中断循环
+                        bagVo.setReceiptMoney(doMoney);
+                        bagVo.setBalance(balance.subtract(doMoney));
+                        sb.append(BagNameEnum.getMessage(Integer.parseInt(bagCode)));
+                        doBagVos.add(bagVo);
+                        break;
+                    } else {
+                        // 将钱包扣费为0,剩余待扣金额=消费金额-原钱包余额
+                        bagVo.setReceiptMoney(balance);
+                        bagVo.setBalance(BigDecimal.ZERO);
+                        doMoney = doMoney.subtract(balance);
+                        sb.append(BagNameEnum.getMessage(Integer.parseInt(bagCode)));
+                        doBagVos.add(bagVo);
+                    }
                 }
             }
         }
@@ -561,7 +573,7 @@ public class CheckBusiness {
 
         // 设备消费间隔验证
         if ((currentLocalDt.toEpochSecond(ZoneOffset.of("+8"))
-                 - lastPayLocalDt.toEpochSecond(ZoneOffset.of("+8"))) / 60 < termSwipeInterval && termSwipeInterval > 0) {// 消费间隔
+            - lastPayLocalDt.toEpochSecond(ZoneOffset.of("+8"))) / 60 < termSwipeInterval && termSwipeInterval > 0) {// 消费间隔
             return R.fail(new ErrorInfo(400, TradeStatusEnum.TimeInterval.toString(), "超过设备单次限额", TradeStatusEnum.TimeInterval.getName()));
         }
         // 设备单次限额验证
@@ -715,28 +727,28 @@ public class CheckBusiness {
                 if (ObjectUtil.equals(mealType, "1")) {
                     if (cardLimitedVo.getMealCount().compareTo(oneCount) >= 0) {
                         return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitTimes.toString(), "卡类早餐限制次数",
-                                                    TradeStatusEnum.MealLimitTimes.getName()));
+                            TradeStatusEnum.MealLimitTimes.getName()));
                     }
                 }
                 // 午餐限次
                 if (ObjectUtil.equals(mealType, "2")) {
                     if (cardLimitedVo.getMealCount().compareTo(twoCount) >= 0) {
                         return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitTimes.toString(), "卡类午餐限制次数",
-                                                    TradeStatusEnum.MealLimitTimes.getName()));
+                            TradeStatusEnum.MealLimitTimes.getName()));
                     }
                 }
                 // 晚餐限次
                 if (ObjectUtil.equals(mealType, "3")) {
                     if (cardLimitedVo.getMealCount().compareTo(threeCount) >= 0) {
                         return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitTimes.toString(), "卡类晚餐限制次数",
-                                                    TradeStatusEnum.MealLimitTimes.getName()));
+                            TradeStatusEnum.MealLimitTimes.getName()));
                     }
                 }
                 // 宵夜限次
                 if (ObjectUtil.equals(mealType, "4")) {
                     if (cardLimitedVo.getMealCount().compareTo(fourCount) >= 0) {
                         return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitTimes.toString(), "卡类夜宵限制次数",
-                                                    TradeStatusEnum.MealLimitTimes.getName()));
+                            TradeStatusEnum.MealLimitTimes.getName()));
                     }
                 }
             }
@@ -789,7 +801,7 @@ public class CheckBusiness {
         BigDecimal fourMoney = remoteQuotaVo.getFourMoney();
 
         if (dayMoney.compareTo(BigDecimal.ZERO) > 0 || oneMoney.compareTo(BigDecimal.ZERO) > 0 || twoMoney.compareTo(BigDecimal.ZERO) > 0
-                || threeMoney.compareTo(BigDecimal.ZERO) > 0 || fourMoney.compareTo(BigDecimal.ZERO) > 0) {
+            || threeMoney.compareTo(BigDecimal.ZERO) > 0 || fourMoney.compareTo(BigDecimal.ZERO) > 0) {
             if (dayMoney.compareTo(BigDecimal.ZERO) > 0) {
                 BigDecimal mealQuotaMoney = cardLimitedVo.getMealMoney();
                 // 日限额
@@ -801,28 +813,28 @@ public class CheckBusiness {
                 if (ObjectUtil.equals(mealType, "1") && oneMoney.compareTo(BigDecimal.ZERO) > 0) {
                     if (oneMoney.compareTo(mealQuotaMoney.add(disCountMoney)) < 0) {
                         return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitMoney.toString(), "卡类早餐限制额度",
-                                                    TradeStatusEnum.MealLimitMoney.getName()));
+                            TradeStatusEnum.MealLimitMoney.getName()));
                     }
                 }
                 // 午餐限额
                 if (ObjectUtil.equals(mealType, "2") && twoMoney.compareTo(BigDecimal.ZERO) > 0) {
                     if (twoMoney.compareTo(mealQuotaMoney.add(disCountMoney)) < 0) {
                         return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitMoney.toString(), "卡类午餐限制额度",
-                                                    TradeStatusEnum.MealLimitMoney.getName()));
+                            TradeStatusEnum.MealLimitMoney.getName()));
                     }
                 }
                 // 晚餐限额
                 if (ObjectUtil.equals(mealType, "3") && threeMoney.compareTo(BigDecimal.ZERO) > 0) {
                     if (threeMoney.compareTo(mealQuotaMoney.add(disCountMoney)) < 0) {
                         return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitMoney.toString(), "卡类晚餐限制额度",
-                                                    TradeStatusEnum.MealLimitMoney.getName()));
+                            TradeStatusEnum.MealLimitMoney.getName()));
                     }
                 }
                 // 宵夜限额
-                if (ObjectUtil.equals(mealType, "4")&& threeMoney.compareTo(BigDecimal.ZERO) > 0) {
+                if (ObjectUtil.equals(mealType, "4") && threeMoney.compareTo(BigDecimal.ZERO) > 0) {
                     if (fourMoney.compareTo(mealQuotaMoney.add(disCountMoney)) < 0) {
                         return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitMoney.toString(), "卡类夜宵限制额度",
-                                                    TradeStatusEnum.MealLimitMoney.getName()));
+                            TradeStatusEnum.MealLimitMoney.getName()));
                     }
                 }
             }
@@ -977,6 +989,7 @@ public class CheckBusiness {
         }
         return operatorVo;
     }
+
     /**
      * 计算折扣金额
      *
@@ -1005,10 +1018,10 @@ public class CheckBusiness {
             disCountMoney = consumeMoney.multiply(twoRate.divide(new BigDecimal("100.0"), 2, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP);
         } else if (rateCount == 2) {// 第三次
             disCountMoney = consumeMoney.multiply(threeRate.divide(new BigDecimal("100.0"), 2, RoundingMode.HALF_UP)).setScale(2,
-                                                                                                                               RoundingMode.HALF_UP);
+                RoundingMode.HALF_UP);
         } else { // 第四次及以上
             disCountMoney = consumeMoney.multiply(fourRate.divide(new BigDecimal("100.0"), 2, RoundingMode.HALF_UP)).setScale(2,
-                                                                                                                              RoundingMode.HALF_UP);
+                RoundingMode.HALF_UP);
         }
         return disCountMoney;
     }