|
|
@@ -1,1304 +0,0 @@
|
|
|
-package org.dromara.server.consume.business;
|
|
|
-
|
|
|
-import cn.hutool.core.bean.BeanUtil;
|
|
|
-import cn.hutool.core.date.DateUtil;
|
|
|
-import cn.hutool.core.util.ObjectUtil;
|
|
|
-import cn.hutool.core.util.StrUtil;
|
|
|
-import cn.hutool.json.JSONUtil;
|
|
|
-import lombok.RequiredArgsConstructor;
|
|
|
-import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.apache.commons.lang3.time.DateFormatUtils;
|
|
|
-import org.apache.dubbo.config.annotation.DubboReference;
|
|
|
-import org.dromara.backstage.api.*;
|
|
|
-import org.dromara.backstage.api.domain.vo.*;
|
|
|
-import org.dromara.common.core.config.DefaultConfig;
|
|
|
-import org.dromara.common.core.constant.ApiErrorTypeConstants;
|
|
|
-import org.dromara.common.core.constant.Constants;
|
|
|
-import org.dromara.common.core.domain.R;
|
|
|
-import org.dromara.common.core.domain.model.ErrorInfo;
|
|
|
-import org.dromara.common.core.enums.BagNameEnum;
|
|
|
-import org.dromara.common.core.enums.CardStatusEnum;
|
|
|
-import org.dromara.common.core.enums.TradeStatusEnum;
|
|
|
-import org.dromara.common.core.enums.UserAccountStatusEnum;
|
|
|
-import org.dromara.common.core.utils.RecordIdUtils;
|
|
|
-import org.dromara.server.common.domain.consume.bo.ConsumptionBo;
|
|
|
-import org.dromara.server.consume.cache.TokenManager;
|
|
|
-import org.dromara.server.consume.domain.bo.XfCardLimitedBo;
|
|
|
-import org.dromara.server.consume.domain.convert.RemoteVoConvert;
|
|
|
-import org.dromara.server.consume.domain.vo.PtBagVo;
|
|
|
-import org.dromara.server.consume.domain.vo.XfCardLimitedVo;
|
|
|
-import org.dromara.server.consume.domain.vo.XfConsumeDetailOriginalVo;
|
|
|
-import org.dromara.server.consume.domain.vo.XfTermVo;
|
|
|
-import org.dromara.server.consume.domain.vo.yc.TermToken;
|
|
|
-import org.dromara.server.consume.service.IConsumeDetailOriginalService;
|
|
|
-import org.dromara.server.consume.service.IPtBagService;
|
|
|
-import org.dromara.server.consume.service.IXfCardLimitedService;
|
|
|
-import org.jetbrains.annotations.NotNull;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-
|
|
|
-import java.math.BigDecimal;
|
|
|
-import java.math.RoundingMode;
|
|
|
-import java.text.MessageFormat;
|
|
|
-import java.time.LocalDateTime;
|
|
|
-import java.time.ZoneOffset;
|
|
|
-import java.util.*;
|
|
|
-
|
|
|
-/**
|
|
|
- * name: CheckBusiness
|
|
|
- * package: org.dromara.server.consume.business
|
|
|
- * description: 消费数据验证业务处理
|
|
|
- * date: 2024-11-02 07:49:37 07:49
|
|
|
- *
|
|
|
- * @author luoyibo
|
|
|
- * @version 0.1
|
|
|
- * @since JDK 1.8
|
|
|
- */
|
|
|
-@Slf4j
|
|
|
-@Service
|
|
|
-@RequiredArgsConstructor
|
|
|
-public class CheckBusiness {
|
|
|
- @DubboReference
|
|
|
- private final RemoteCardService remoteCardService;
|
|
|
- @DubboReference
|
|
|
- private final RemoteUserAccountService remoteUserAccountService;
|
|
|
- @DubboReference
|
|
|
- private final RemoteMealTypeService remoteMealTypeService;
|
|
|
- @DubboReference
|
|
|
- private final RemoteOperatorService remoteOperatorService;
|
|
|
- @DubboReference
|
|
|
- private final RemotePtParameterService remotePtParameterService;
|
|
|
- @DubboReference
|
|
|
- private final RemoteXfLimitedService remoteLimitedService;
|
|
|
- @DubboReference
|
|
|
- private final RemoteXfDiscountService remoteDisCountService;
|
|
|
- @DubboReference
|
|
|
- private final RemoteXfQuotaService remoteQuotaService;
|
|
|
- @DubboReference
|
|
|
- private final RemotePtXfTermService remoteXfTermService;
|
|
|
-
|
|
|
- private final IConsumeDetailOriginalService consumeDetailOriginalService;
|
|
|
- private final IPtBagService bagService;
|
|
|
- private final TokenManager tokenManager;
|
|
|
- private final IXfCardLimitedService cardLimitedService;
|
|
|
- private final DefaultConfig defaultConfig;
|
|
|
- private final BaseBusiness baseBusiness;
|
|
|
-
|
|
|
- /**
|
|
|
- * 计算折扣金额
|
|
|
- *
|
|
|
- * @param cardLimitedVo 卡片限制信息
|
|
|
- * @param bo 消费记录
|
|
|
- * @param remoteDiscountVo 折扣信息
|
|
|
- * @return 折扣金额
|
|
|
- */
|
|
|
- @NotNull
|
|
|
- private static BigDecimal getDisCountMoney(XfCardLimitedVo cardLimitedVo, ConsumptionBo bo, RemoteDiscountVo remoteDiscountVo) {
|
|
|
- int rateCount = remoteDiscountVo.getRateType().equals(
|
|
|
- "1") ? cardLimitedVo.getDayDiscountCount().intValue() : cardLimitedVo.getMealDiscountCount().intValue();
|
|
|
- BigDecimal disCountMoney;
|
|
|
- BigDecimal consumeMoney = bo.getConsumeMoney();
|
|
|
- // 折扣率1
|
|
|
- BigDecimal oneRate = remoteDiscountVo.getOneRate();
|
|
|
- // 折扣率2
|
|
|
- BigDecimal twoRate = remoteDiscountVo.getTwoRate();
|
|
|
- // 折扣率3
|
|
|
- BigDecimal threeRate = remoteDiscountVo.getThreeRate();
|
|
|
- // 折扣率4
|
|
|
- BigDecimal fourRate = remoteDiscountVo.getFourRate();
|
|
|
- if (rateCount == 0) {
|
|
|
- disCountMoney = consumeMoney.multiply(oneRate.divide(new BigDecimal("100.0"), 2, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP);
|
|
|
- } else if (rateCount == 1) {// 第二次
|
|
|
- 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);
|
|
|
- } else { // 第四次及以上
|
|
|
- disCountMoney = consumeMoney.multiply(fourRate.divide(new BigDecimal("100.0"), 2, RoundingMode.HALF_UP)).setScale(2,
|
|
|
- RoundingMode.HALF_UP);
|
|
|
- }
|
|
|
- return disCountMoney;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 消费记录参数检检查
|
|
|
- * 1.检查设备编号,设备编号必须大于0
|
|
|
- * 2.检查交易人员标识:卡流水号、物理卡号、人员Id、人员编号至少有1项
|
|
|
- *
|
|
|
- * @param bo 消费记录业务对象
|
|
|
- * @return 检查结果
|
|
|
- */
|
|
|
- public R<ErrorInfo> checkParam(ConsumptionBo bo) {
|
|
|
- ErrorInfo errorInfo;
|
|
|
- // 检查设备机号
|
|
|
- if ((ObjectUtil.isEmpty(bo.getTermNo()) || bo.getTermNo() == 0) && ObjectUtil.isEmpty(bo.getTermMac())) {
|
|
|
- errorInfo = new ErrorInfo(1, ApiErrorTypeConstants.PARAM_ERROR, "设备机号不正确", "设备机号必须大于零!");
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- // 检查交易人员标识
|
|
|
- if (bo.getCardNo() <= 0L && bo.getFactoryId() == 0L && bo.getUserNo() <= 0L && StrUtil.isEmpty(bo.getUserNumb())) {
|
|
|
- errorInfo = new ErrorInfo(1, ApiErrorTypeConstants.PARAM_ERROR, "交易人员标识不满足",
|
|
|
- "必须提供 [CardNo | FactoryId | userNo | userNumb] 中至少1项来标识交易用户");
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查校验码
|
|
|
- *
|
|
|
- * @param bo 消费信息
|
|
|
- * @param mac 校验码
|
|
|
- * @return 检查结果
|
|
|
- */
|
|
|
- public R<ErrorInfo> checkMac(ConsumptionBo bo, String mac) {
|
|
|
- ErrorInfo errorInfo;
|
|
|
- Long termNo = bo.getTermNo();
|
|
|
- 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));
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- if (ObjectUtil.isNotEmpty(mac)) {
|
|
|
- // TODO 2024-12-25 luoyibo 如果mac不为空,需要校验
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 消费记录人员、卡片检查,全部通过后获取到消费账户、卡片及设备的视图信息
|
|
|
- *
|
|
|
- * @param bo 消费记录
|
|
|
- * @param userAccountVo 消费账户
|
|
|
- * @param userCardVo 消费卡片
|
|
|
- * @return 验证结果
|
|
|
- */
|
|
|
- public R<ErrorInfo> checkUser(ConsumptionBo bo, RemoteUserAccountVo userAccountVo, RemoteCardVo userCardVo) {
|
|
|
- long cardNo = ObjectUtil.isEmpty(bo.getCardNo()) ? 0 : bo.getCardNo();
|
|
|
- long factoryId = ObjectUtil.isEmpty(bo.getFactoryId()) ? 0 : bo.getFactoryId();
|
|
|
- long userNo = ObjectUtil.isEmpty(bo.getUserNo()) ? 0 : bo.getUserNo();
|
|
|
- String userNumb = bo.getUserNumb() == null ? null : bo.getUserNumb();
|
|
|
-
|
|
|
- // 卡流水号检查
|
|
|
- if (cardNo > 0) {
|
|
|
- return checkCardNo(bo, userAccountVo, userCardVo);
|
|
|
- }
|
|
|
- // 物理卡号检查
|
|
|
- if (factoryId > 0) {
|
|
|
- return checkFactoryId(bo, userAccountVo, userCardVo);
|
|
|
- }
|
|
|
- // 用户流水号检查
|
|
|
- if (userNo > 0) {
|
|
|
- return checkUserNo(bo, userAccountVo, userCardVo);
|
|
|
- }
|
|
|
- // 人员编号检查
|
|
|
- if (StrUtil.isNotEmpty(userNumb)) {
|
|
|
- return checkUserNumb(bo, userAccountVo, userCardVo);
|
|
|
- }
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 消费设备检查
|
|
|
- *
|
|
|
- * @param bo 消费记录
|
|
|
- * @param useTermVo 消费设备
|
|
|
- * @return 检查结果
|
|
|
- */
|
|
|
- public R<ErrorInfo> checkTerm(ConsumptionBo bo, XfTermVo useTermVo) {
|
|
|
- String msg = ObjectUtil.isEmpty(bo.getTermMac()) ? bo.getTermNo().toString() : bo.getTermMac();
|
|
|
- String tenantId = ObjectUtil.isNotEmpty(bo.getTenantId()) ? bo.getTenantId() : defaultConfig.getTenantId();
|
|
|
- RemoteXfTermVo remoteXfTermVo;
|
|
|
- if ((ObjectUtil.isNotEmpty(bo.getTermNo()) && bo.getTermNo() > 0)) {
|
|
|
- remoteXfTermVo = remoteXfTermService.queryByNo(bo.getTermNo(), tenantId);
|
|
|
- } else {
|
|
|
- remoteXfTermVo = remoteXfTermService.queryByMac(bo.getTermMac());
|
|
|
- }
|
|
|
- if (ObjectUtil.isEmpty(remoteXfTermVo)) {
|
|
|
- ErrorInfo errorInfo = new ErrorInfo(400, "", "设备不存在",
|
|
|
- MessageFormat.format("机号或MAC为[{0}]的设备不存在,不允许交易", msg));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- bo.setTermNo(remoteXfTermVo.getTermNo());
|
|
|
- RemoteVoConvert.INSTANCE.copyRemoteTermVo(useTermVo, remoteXfTermVo);
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 消费逻辑检查,检查是否能消费
|
|
|
- *
|
|
|
- * @param bo 消费记录
|
|
|
- * @param userAccountVo 消费账户
|
|
|
- * @param userCardVo 消费卡片
|
|
|
- * @param useTermVo 消费设备
|
|
|
- * @return 验证结果
|
|
|
- */
|
|
|
- public R<ErrorInfo> checkConsume(ConsumptionBo bo, RemoteUserAccountVo userAccountVo, RemoteCardVo userCardVo, XfTermVo useTermVo) {
|
|
|
- ErrorInfo errorInfo;
|
|
|
- R<ErrorInfo> result;
|
|
|
- // 1.消费账户状态验证,验证账户是否已开户、是否冻结、状态是否正常、是否过有效期
|
|
|
- if ("Y".equals(userAccountVo.getFreezeStatus())) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.NOT_FOUND, "账户已被冻结",
|
|
|
- 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()));
|
|
|
- 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()));
|
|
|
- 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()));
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
-
|
|
|
- // 2.餐类验证
|
|
|
- long startTime=System.currentTimeMillis();
|
|
|
- RemoteMealTypeVo mealType = remoteMealTypeService.queryMealTypeVoByTime(bo.getConsumeDate());
|
|
|
- if (ObjectUtil.isEmpty(mealType)) {
|
|
|
- return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.NOT_FOUND, "不在交易时段", "不在交易时段"));
|
|
|
- }
|
|
|
-
|
|
|
- // 3.设备限制验证,只有消费机上传时会会进行验证,在手工补扣、错扣补款时不进行验证
|
|
|
- startTime=System.currentTimeMillis();
|
|
|
- if (bo.getStatusFlag() == 1 || bo.getStatusFlag() == 4) {
|
|
|
- result = checkTermLimitDeal(bo, useTermVo, userCardVo, mealType);
|
|
|
- if (R.isError(result)) {
|
|
|
- return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.NOT_FOUND, "消费限制判断存在问题", JSONUtil.toJsonStr(result.getData())));
|
|
|
- }
|
|
|
- }
|
|
|
- log.info("折扣验证耗时:{}毫秒", System.currentTimeMillis()-startTime);
|
|
|
- // 4.根据消费机的消费模式验证余额,如果余额不足则返回
|
|
|
- startTime=System.currentTimeMillis();
|
|
|
- result = checkOrigDeductionBag(bo, userAccountVo, useTermVo);
|
|
|
- if (R.isError(result)) {
|
|
|
- return result;
|
|
|
- }
|
|
|
- log.info("卡余验证耗时:{}毫秒", System.currentTimeMillis()-startTime);
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查消费交易的账单,通过验证各种组件如卡片详情、原始记录、餐类信息、扣款钱包以及操作员详情。此外,它还会更新与用户卡片相关的其他消费信息
|
|
|
- *
|
|
|
- * @param bo 包含交易详情的消费业务对象
|
|
|
- * @param userAccountVo 与交易关联的用户账户信息
|
|
|
- * @param userCardVo 与用户关联的卡片信息。
|
|
|
- * @param useTermVo 处理交易的终端信息
|
|
|
- * @param bagVoList 扣款钱包信息的列表
|
|
|
- * @param mealTypeVo 交易餐类信息
|
|
|
- * @param operatorVo 为交易操作员信息
|
|
|
- * @return 返回一个结果对象,包含成功或错误信息。如果发生验证失败,错误信息将包括有关验证失败的详细信息
|
|
|
- */
|
|
|
- public R<ErrorInfo> checkBill(ConsumptionBo bo, RemoteUserAccountVo userAccountVo, RemoteCardVo userCardVo,
|
|
|
- XfTermVo useTermVo, List<PtBagVo> bagVoList, RemoteMealTypeVo mealTypeVo,
|
|
|
- RemoteOperatorVo operatorVo) {
|
|
|
- R<ErrorInfo> result = checkUser(bo, userAccountVo, userCardVo);
|
|
|
- if (R.isError(result)) {
|
|
|
- return result;
|
|
|
- }
|
|
|
- result = checkOriginalRecord(bo, userAccountVo);
|
|
|
- if (R.isError(result)) {
|
|
|
- return result;
|
|
|
- }
|
|
|
- // 获取餐类信息
|
|
|
- RemoteMealTypeVo mealType = remoteMealTypeService.queryMealTypeVoByTime(bo.getConsumeDate());
|
|
|
- if (ObjectUtil.isEmpty(mealType)) {
|
|
|
- mealType.setTypeId("0");
|
|
|
- mealType.setMealName("未知");
|
|
|
- }
|
|
|
- BeanUtil.copyProperties(mealType, mealTypeVo);
|
|
|
- // 获取扣费钱包
|
|
|
- List<PtBagVo> bagVos = new ArrayList<>();
|
|
|
- result = checkDeductionBag(bo, userAccountVo, useTermVo, bagVos);
|
|
|
- if (R.isError(result)) {
|
|
|
- return result;
|
|
|
- }
|
|
|
- bagVoList.addAll(bagVos);
|
|
|
- // 获取营业员信息
|
|
|
- BeanUtil.copyProperties(getOperatorVo(bo), operatorVo);
|
|
|
-
|
|
|
- // 更新卡片的折扣、限额与限次信息
|
|
|
- updateOtherConsumeInfo(bo, userCardVo, mealTypeVo, useTermVo);
|
|
|
-
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置返回的消费用户信息
|
|
|
- *
|
|
|
- * @param bo 消费业务
|
|
|
- * @param accountVo 消费账户
|
|
|
- */
|
|
|
- private void setUserInfo(ConsumptionBo bo, RemoteUserAccountVo accountVo) {
|
|
|
- bo.setUserId(accountVo.getUserId());
|
|
|
- bo.setRealName(StrUtil.isEmpty(accountVo.getRealName()) ? "----" : accountVo.getRealName());
|
|
|
- bo.setUserNo(accountVo.getUserNo());
|
|
|
- bo.setUserNumb(accountVo.getUserNumb());
|
|
|
- bo.setTenantId(accountVo.getTenantId());
|
|
|
- bo.setExpireDate(accountVo.getLifespan());
|
|
|
- bo.setDeptName(accountVo.getDeptName());
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查卡流水号
|
|
|
- *
|
|
|
- * @param bo 消费业务
|
|
|
- * @param userAccountVo 消费账户
|
|
|
- * @param userCardVo 消费卡片
|
|
|
- * @return 检查结果
|
|
|
- */
|
|
|
- @NotNull
|
|
|
- private R<ErrorInfo> checkCardNo(ConsumptionBo bo, RemoteUserAccountVo userAccountVo, RemoteCardVo userCardVo) {
|
|
|
- ErrorInfo errorInfo;
|
|
|
- Long cardNo = bo.getCardNo();
|
|
|
-
|
|
|
- RemoteCardVo cardVo = remoteCardService.queryCardByCardNo(cardNo);
|
|
|
- if (ObjectUtil.isEmpty(cardVo)) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片不存在",
|
|
|
- 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));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- if (bo.getFactoryId() > 0) {
|
|
|
- if (!Objects.equals(cardVo.getFactoryId(), bo.getFactoryId())) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片不正确", "物理卡号不一致,不允许交易");
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- }
|
|
|
- RemoteUserAccountVo accountVo = remoteUserAccountService.getUserAccountVoById(cardVo.getUserId());
|
|
|
- if (Objects.isNull(accountVo)) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "人员不存在",
|
|
|
- MessageFormat.format("流水号为[{0}]的卡片无对应的人员信息,不允许交易", cardNo));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- if (Objects.equals(accountVo.getFreezeStatus(), Constants.SYS_YES)) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "人员被冻结",
|
|
|
- MessageFormat.format("流水号为[{0}]的卡片对应的人员被冻结,不允许交易", cardNo));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- Date nowDate = new Date();
|
|
|
- long currentTime = nowDate.getTime();
|
|
|
- if (accountVo.getLifespan().getTime()<currentTime) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "账户过期",
|
|
|
- MessageFormat.format("流水号为[{0}]的卡片对应的人员账户过期,不允许交易", cardNo));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- // 设置返回的消费用户信息
|
|
|
- setUserInfo(bo, accountVo);
|
|
|
-
|
|
|
- bo.setCardNo(cardVo.getCardNo());
|
|
|
- bo.setFactoryId(cardVo.getFactoryId());
|
|
|
- bo.setCardTypeName(cardVo.getCardTypeName());
|
|
|
- RemoteVoConvert.INSTANCE.copyRemoteUserAccountVo(userAccountVo, accountVo);
|
|
|
- RemoteVoConvert.INSTANCE.copyRemoteCardVo(userCardVo, cardVo);
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查物理卡号
|
|
|
- *
|
|
|
- * @param bo 消费业务
|
|
|
- * @param userAccountVo 消费账户
|
|
|
- * @param userCardVo 消费卡片
|
|
|
- * @return 检查结果
|
|
|
- */
|
|
|
- @NotNull
|
|
|
- private R<ErrorInfo> checkFactoryId(ConsumptionBo bo, RemoteUserAccountVo userAccountVo, RemoteCardVo userCardVo) {
|
|
|
- ErrorInfo errorInfo;
|
|
|
- Long factoryId = bo.getFactoryId();
|
|
|
- RemoteCardVo cardVo = remoteCardService.queryCardByFactoryId(factoryId);
|
|
|
- if (ObjectUtil.isEmpty(cardVo)) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "卡片不存在",
|
|
|
- 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));
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- RemoteUserAccountVo accountVo = remoteUserAccountService.getUserAccountVoById(cardVo.getUserId());
|
|
|
- if (Objects.isNull(accountVo)) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "人员不存在",
|
|
|
- MessageFormat.format("物理卡号为[{0}]的卡片无对应的人员信息,不允许交易", factoryId));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- if (Objects.equals(accountVo.getFreezeStatus(), Constants.SYS_YES)) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "人员被冻结",
|
|
|
- MessageFormat.format("物理卡号为[{0}]的卡片对应的人员被冻结,不允许交易", factoryId));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- Date nowDate = new Date();
|
|
|
- long currentTime = nowDate.getTime();
|
|
|
- if (accountVo.getLifespan().getTime()<currentTime) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "账户过期",
|
|
|
- MessageFormat.format("物理卡号为[{0}]的卡片对应的人员账户过期,不允许交易", factoryId));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- setUserInfo(bo, accountVo);
|
|
|
- bo.setCardNo(cardVo.getCardNo());
|
|
|
- bo.setCardTypeName(cardVo.getCardTypeName());
|
|
|
- RemoteVoConvert.INSTANCE.copyRemoteUserAccountVo(userAccountVo, accountVo);
|
|
|
- RemoteVoConvert.INSTANCE.copyRemoteCardVo(userCardVo, cardVo);
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查用户流水号
|
|
|
- *
|
|
|
- * @param bo 消费业务
|
|
|
- * @param userAccountVo 消费账户
|
|
|
- * @param userCardVo 消费卡片
|
|
|
- * @return 检查结果
|
|
|
- */
|
|
|
- @NotNull
|
|
|
- private R<ErrorInfo> checkUserNo(ConsumptionBo bo, RemoteUserAccountVo userAccountVo, RemoteCardVo userCardVo) {
|
|
|
- ErrorInfo errorInfo;
|
|
|
- Long userNo = bo.getUserNo();
|
|
|
- RemoteUserAccountVo accountVo = remoteUserAccountService.getUserAccountVoByUserNo(userNo);
|
|
|
- if (ObjectUtil.isEmpty(accountVo)) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "人员不存在",
|
|
|
- MessageFormat.format("流水号为[{0}]的人员不存在,不允许交易", userNo));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- if (Objects.equals(accountVo.getFreezeStatus(), Constants.SYS_YES)) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "人员被冻结",
|
|
|
- MessageFormat.format("流水号为[{0}]的人员被冻结,不允许交易", userNo));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- Date nowDate = new Date();
|
|
|
- long currentTime = nowDate.getTime();
|
|
|
- if (accountVo.getLifespan().getTime()<currentTime) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "账户过期",
|
|
|
- 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));
|
|
|
-
|
|
|
- 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));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- setUserInfo(bo, accountVo);
|
|
|
- bo.setCardNo(cardVo.getCardNo());
|
|
|
- bo.setFactoryId(cardVo.getFactoryId());
|
|
|
- bo.setCardTypeName(cardVo.getCardTypeName());
|
|
|
- RemoteVoConvert.INSTANCE.copyRemoteUserAccountVo(userAccountVo, accountVo);
|
|
|
- RemoteVoConvert.INSTANCE.copyRemoteCardVo(userCardVo, cardVo);
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查人员编号
|
|
|
- *
|
|
|
- * @param bo 消费业务
|
|
|
- * @param userAccountVo 消费账户
|
|
|
- * @param userCardVo 消费卡片
|
|
|
- * @return 检查结果
|
|
|
- */
|
|
|
- @NotNull
|
|
|
- private R<ErrorInfo> checkUserNumb(ConsumptionBo bo, RemoteUserAccountVo userAccountVo, RemoteCardVo userCardVo) {
|
|
|
- ErrorInfo errorInfo;
|
|
|
- String userNumb = bo.getUserNumb();
|
|
|
- RemoteUserAccountVo accountVo = remoteUserAccountService.getUserAccountVoByUserNumb(userNumb);
|
|
|
-
|
|
|
- if (ObjectUtil.isEmpty(accountVo)) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "人员不存在",
|
|
|
- MessageFormat.format("编号为[{0}]的人员不存在,不允许交易", userNumb));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- if (Objects.equals(accountVo.getFreezeStatus(), Constants.SYS_YES)) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "人员被冻结",
|
|
|
- MessageFormat.format("编号为[{0}]的人员被冻结,不允许交易", userNumb));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
- Date nowDate = new Date();
|
|
|
- long currentTime = nowDate.getTime();
|
|
|
- if (accountVo.getLifespan().getTime()<currentTime) {
|
|
|
- errorInfo = new ErrorInfo(400, ApiErrorTypeConstants.PARAM_ERROR, "账户过期",
|
|
|
- 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));
|
|
|
-
|
|
|
- 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));
|
|
|
-
|
|
|
- return R.fail(errorInfo);
|
|
|
- }
|
|
|
-
|
|
|
- setUserInfo(bo, accountVo);
|
|
|
- bo.setCardNo(cardVo.getCardNo());
|
|
|
- bo.setFactoryId(cardVo.getFactoryId());
|
|
|
- bo.setCardTypeName(cardVo.getCardTypeName());
|
|
|
-
|
|
|
- RemoteVoConvert.INSTANCE.copyRemoteUserAccountVo(userAccountVo, accountVo);
|
|
|
- RemoteVoConvert.INSTANCE.copyRemoteCardVo(userCardVo, cardVo);
|
|
|
-
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- private R<ErrorInfo> checkOriginalRecord(ConsumptionBo bo, RemoteUserAccountVo userAccountVo) {
|
|
|
- String originalId = RecordIdUtils.getRecordId(bo.getConsumeDate(), bo.getTermNo().shortValue(),
|
|
|
- bo.getTermRecordId().shortValue(), bo.getUserNo().intValue(), 0);
|
|
|
- // 补偿性措施:防止消费时间错乱问题(在线模式)
|
|
|
- int recordType = bo.getRecordStatus().intValue();
|
|
|
- long uniqueRecordId = bo.getRecordId();
|
|
|
- bo.setOriginalId(originalId);
|
|
|
- XfConsumeDetailOriginalVo originalVo;
|
|
|
- if (!((recordType == 106 || recordType == 108 || recordType == 110 || recordType == 111))) {
|
|
|
- originalVo = consumeDetailOriginalService.queryById(originalId);
|
|
|
- if (ObjectUtil.isEmpty(originalVo)) {
|
|
|
- boolean checkFlag = false;
|
|
|
- if (uniqueRecordId > 0) {
|
|
|
- // 根据自增的记录Id查询
|
|
|
- originalVo = consumeDetailOriginalService.queryByRecordId(uniqueRecordId);
|
|
|
- if (ObjectUtil.isNotEmpty(originalVo)) {
|
|
|
- // 如果根据自增Id找到原始记录,以查找的数据重置消费对象的消费日期和原始记录Id
|
|
|
- bo.setConsumeDate(originalVo.getConsumeDate());
|
|
|
- bo.setOriginalId(originalVo.getOriginalId());
|
|
|
- originalId = originalVo.getOriginalId();
|
|
|
- checkFlag = true;
|
|
|
- }
|
|
|
- }
|
|
|
- if (!checkFlag) {
|
|
|
- // 根据卡流水号、机号、机器流水号和消费金额查询
|
|
|
- originalVo = consumeDetailOriginalService.queryByConsumeMoney(bo.getCardNo(), bo.getTermNo(), bo.getTermRecordId(),
|
|
|
- bo.getConsumeMoney());
|
|
|
- if (ObjectUtil.isNotEmpty(originalVo)) {
|
|
|
- bo.setConsumeDate(originalVo.getConsumeDate());
|
|
|
- bo.setRecordId(originalVo.getRecordId());
|
|
|
- bo.setOriginalId(originalVo.getOriginalId());
|
|
|
- // originalId = originalVo.getOriginalId();
|
|
|
- } else {
|
|
|
- bo.setRecordStatus(108L);
|
|
|
- // 判断脱机消费
|
|
|
- R<ErrorInfo> result = doOfflineRecord(bo, originalId, userAccountVo);
|
|
|
- if (R.isError(result)) {
|
|
|
- String msg = MessageFormat.format("处理记录号为[{0}]的脱机消费数据失败", bo.getRecordId());
|
|
|
- return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.RECORD_IS_EXISTS, "处理脱机消费数据失败", msg));
|
|
|
- }
|
|
|
- // 重置这项数据
|
|
|
- bo.setConsumeDate(originalVo.getConsumeDate());
|
|
|
- bo.setRecordId(originalVo.getRecordId());
|
|
|
- bo.setOriginalId(originalVo.getOriginalId());
|
|
|
- // originalId = originalVo.getOriginalId();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- bo.setRecordId(originalVo.getRecordId());
|
|
|
- } else {
|
|
|
- R<ErrorInfo> result = doOfflineRecord(bo, originalId, userAccountVo);
|
|
|
- if (R.isError(result)) {
|
|
|
- return result;
|
|
|
- }
|
|
|
- }
|
|
|
- // XfConsumeDetailVo consumeDetailVo = consumeDetailService.queryVoByOriginalId(originalId);
|
|
|
- // XfConsumeDetailVo consumeDetailVo = consumeDetailService.queryVoByOriginalId(bo.getOriginalId());
|
|
|
- // if (ObjectUtil.isNotEmpty(consumeDetailVo)) {
|
|
|
- // // 认为是重复上传,不再入账
|
|
|
- // return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.RECORD_IS_EXISTS, "原始消费记录已处理",
|
|
|
- // MessageFormat.format("标识为[{0}]的原始消费记录已处理", bo.getRecordId())));
|
|
|
- //}
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- public R<ErrorInfo> checkDeductionBag(ConsumptionBo bo, RemoteUserAccountVo userAccountVo, XfTermVo termVo, List<PtBagVo> bagVos) {
|
|
|
- R<ErrorInfo> result = this.checkOrigDeductionBag(bo, userAccountVo, termVo);
|
|
|
- if (R.isError(result)) {
|
|
|
- return result;
|
|
|
- }
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
- // 设备的扣费钱包字符串
|
|
|
- String consumeType = termVo.getConsumeType();
|
|
|
- // 分解扣费钱包
|
|
|
- List<String> bagCodes = StrUtil.split(consumeType, ",");
|
|
|
- Long userId = userAccountVo.getUserId();
|
|
|
- // 可能会在处理过程中更改实际的消费金额,因此先取出来
|
|
|
- BigDecimal consumeMoney = bo.getConsumeMoney();
|
|
|
- // 扣费的过程金额
|
|
|
- BigDecimal doMoney = bo.getConsumeMoney();
|
|
|
- // 计算后实际需要扣费的钱包,会小于或等于指定的扣费钱包数
|
|
|
- List<PtBagVo> doBagVos = new ArrayList<>();
|
|
|
- BigDecimal totalBalance = BigDecimal.ZERO;
|
|
|
- // 计算扣费钱包的总金额
|
|
|
- for (String bagCode : bagCodes) {
|
|
|
- PtBagVo bagVo = bagService.queryByUserBagCode(userId, bagCode);
|
|
|
- if (ObjectUtil.isNotEmpty(bagVo)) {
|
|
|
- totalBalance = totalBalance.add(bagVo.getBalance());
|
|
|
- }
|
|
|
- }
|
|
|
- for (String bagCode : bagCodes) {
|
|
|
- // 1.查询对应的钱包
|
|
|
- PtBagVo bagVo = bagService.queryByUserBagCode(userId, bagCode);
|
|
|
- if (ObjectUtil.isEmpty(bagVo)) {
|
|
|
- log.warn("人员Id:[{}]没有代码:[{}]的钱包,无法从此钱包扣费", userId, bagCode);
|
|
|
- continue;
|
|
|
- }
|
|
|
- // 2.比较扣费金额
|
|
|
- BigDecimal balance = bagVo.getBalance();
|
|
|
- if (consumeMoney.compareTo(BigDecimal.ZERO) == 0) {
|
|
|
- // 如果是消费0元,设置为第一个钱包扣费
|
|
|
- bagVo.setReceiptMoney(BigDecimal.ZERO);
|
|
|
- bagVo.setBalance(balance);
|
|
|
- sb.append(BagNameEnum.getMessage(Integer.parseInt(bagCode)));
|
|
|
- doBagVos.add(bagVo);
|
|
|
- log.warn("[上传交易]-[扣费钱包]-[钱包代码:{},钱包余额:{},消费金额:{},扣款金额:{},姓名:{}]", bagCode, balance, consumeMoney, doMoney,
|
|
|
- userAccountVo.getRealName());
|
|
|
- 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);
|
|
|
- log.warn("[上传交易]-[扣费钱包]-[钱包代码:{},钱包余额:{},消费金额:{},扣款金额:{},姓名:{}]", bagCode, balance, consumeMoney,
|
|
|
- doMoney, userAccountVo.getRealName());
|
|
|
- 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.warn("[上传交易]-[扣费钱包]-[钱包代码:{},钱包余额:{},消费金额:{},扣款金额:{},姓名:{}]", bagCode, balance, balance,
|
|
|
- doMoney, userAccountVo.getRealName());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- bo.setBalance(totalBalance.subtract(consumeMoney));
|
|
|
- bo.setDigitalSign(sb.toString());
|
|
|
- bagVos.addAll(doBagVos);
|
|
|
-
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- public R<ErrorInfo> checkOrigDeductionBag(ConsumptionBo bo, RemoteUserAccountVo userAccountVo, XfTermVo termVo) {
|
|
|
- // 设备的扣费钱包字符串
|
|
|
- String consumeType = termVo.getConsumeType();
|
|
|
- // 分解扣费钱包
|
|
|
- List<String> bagCodes = StrUtil.split(consumeType, ",");
|
|
|
- Long userId = userAccountVo.getUserId();
|
|
|
- BigDecimal consumeMoney = bo.getConsumeMoney();
|
|
|
- BigDecimal totalBalance = BigDecimal.ZERO;
|
|
|
- // 计算扣费钱包的总金额
|
|
|
- for (String bagCode : bagCodes) {
|
|
|
- PtBagVo bagVo = bagService.queryByUserBagCode(userId, bagCode);
|
|
|
- // 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)));
|
|
|
- }
|
|
|
- bo.setBalance(totalBalance.subtract(consumeMoney));
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设备限额、限次与折扣验证
|
|
|
- *
|
|
|
- * @param bo 消费业务
|
|
|
- * @param termVo 消费设备
|
|
|
- * @param userCardVo 消费卡片
|
|
|
- * @param mealTypeVo 消费类型
|
|
|
- * @return 检查结果
|
|
|
- */
|
|
|
- public R<ErrorInfo> checkTermLimitDeal(ConsumptionBo bo, XfTermVo termVo, RemoteCardVo userCardVo, RemoteMealTypeVo mealTypeVo) {
|
|
|
- Long termNo = termVo.getTermNo();
|
|
|
- BigDecimal consumeValue = bo.getConsumeMoney();
|
|
|
- Long factoryFixId = userCardVo.getFactoryId();
|
|
|
- String mealTypeId = mealTypeVo.getTypeId();
|
|
|
- if (termNo == 0 && ObjectUtil.equal("0", mealTypeId)) {
|
|
|
- // 机号为0并且餐类不在正常餐类
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- // 当前卡片类型
|
|
|
- int cardTypeId = userCardVo.getCardType().intValue();
|
|
|
- // 设备允许卡类
|
|
|
- int termCardTypeId = termVo.getCardType() == null ? 0 : termVo.getCardType();
|
|
|
- // 设备每天最大消费次数
|
|
|
- int termDayCount = termVo.getDayCount() == null ? 0 : termVo.getDayCount();
|
|
|
- // 每天最大消费金额
|
|
|
- BigDecimal termDayMoney = termVo.getDayMoney() == null ? BigDecimal.ZERO : termVo.getDayMoney();
|
|
|
- // 每餐最大消费次数
|
|
|
- int termMealCount = termVo.getMealCount() == null ? 0 : termVo.getMealCount();
|
|
|
- // 单次最大消费金额
|
|
|
- BigDecimal termSingleMoney = termVo.getSingleMoney() == null ? BigDecimal.ZERO : termVo.getSingleMoney();
|
|
|
- // 二次可用最大时间间隔
|
|
|
- int termSwipeInterval = termVo.getSwipeInterval() == null ? 0 : termVo.getSwipeInterval();
|
|
|
- // 设备是否启用了卡有效
|
|
|
- boolean termUseValidity = Objects.equals(termVo.getTermValidity(), "0") ? Boolean.FALSE : Boolean.TRUE;
|
|
|
- // 当前时间
|
|
|
- LocalDateTime currentLocalDt = LocalDateTime.now();
|
|
|
- // 最后消费时间
|
|
|
- LocalDateTime lastPayLocalDt = LocalDateTime.ofInstant(userCardVo.getLastPay().toInstant(), ZoneOffset.of("+8"));
|
|
|
- // 有效期时间
|
|
|
- LocalDateTime expiryLocalDt = LocalDateTime.ofInstant(userCardVo.getLifespan().toInstant(), ZoneOffset.of("+8"));
|
|
|
-
|
|
|
- // 设备消费间隔验证
|
|
|
- if ((currentLocalDt.toEpochSecond(ZoneOffset.of("+8"))
|
|
|
- - lastPayLocalDt.toEpochSecond(ZoneOffset.of("+8"))) / 60 < termSwipeInterval && termSwipeInterval > 0) {
|
|
|
- return R.fail(new ErrorInfo(400, TradeStatusEnum.TimeInterval.toString(), "消费间隔过短", TradeStatusEnum.TimeInterval.getName()));
|
|
|
- }
|
|
|
- // 设备单次限额验证
|
|
|
- if (termSingleMoney.compareTo(consumeValue) < 0 && termSingleMoney.compareTo(BigDecimal.ZERO) > 0) {// 限制金额
|
|
|
- return R.fail(new ErrorInfo(400, TradeStatusEnum.OnceBigMoney.toString(), "超过设备单次限额", TradeStatusEnum.OnceBigMoney.getName()));
|
|
|
- }
|
|
|
- // 设备启用了卡有效时进行卡有效期验证
|
|
|
- if (factoryFixId != 0 && termUseValidity && currentLocalDt.isAfter(expiryLocalDt)) {
|
|
|
- return R.fail(
|
|
|
- new ErrorInfo(400, TradeStatusEnum.CardValidDate.toString(), "卡片已超过失效日期", TradeStatusEnum.CardValidDate.getName()));
|
|
|
- }
|
|
|
- // 消费卡类限制验证
|
|
|
- int offsetTypeId = (int) Math.pow(2, (cardTypeId - 1));
|
|
|
- int temp = offsetTypeId & termCardTypeId;
|
|
|
- if (temp != offsetTypeId) {
|
|
|
- return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.NOT_FOUND, "设备卡类限制", TradeStatusEnum.CardTypeLimit.getName()));
|
|
|
- }
|
|
|
- // 餐限次验证
|
|
|
- String lastMeal = userCardVo.getLastMeal().toString();
|
|
|
- int mealCount = userCardVo.getMealCount().intValue();
|
|
|
- if (!ObjectUtil.equals(lastMeal, mealTypeId) || !currentLocalDt.toLocalDate().isEqual(lastPayLocalDt.toLocalDate())) {
|
|
|
- // 如果当前餐类!=消费餐类,初始化卡片的餐类消费数据
|
|
|
- remoteCardService.initCardMealData(userCardVo.getCardNo(), mealTypeId);
|
|
|
- } else {
|
|
|
- if (termMealCount != 0 && mealCount >= termMealCount) {
|
|
|
- return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitTimes.toString(), "设备餐限次", TradeStatusEnum.MealLimitTimes.getName()));
|
|
|
- }
|
|
|
- }
|
|
|
- // 设备日限次 日限额效验(每日第一次消费)
|
|
|
- int dayCount = userCardVo.getDayCount().intValue();
|
|
|
- BigDecimal dayValue = userCardVo.getDayTotal();
|
|
|
- if (!currentLocalDt.toLocalDate().isEqual(lastPayLocalDt.toLocalDate())) {
|
|
|
- // 如果当前日期!=消费日期,初始化卡片的日消费数据
|
|
|
- remoteCardService.initCardDayData(userCardVo.getCardNo());
|
|
|
- } else {
|
|
|
- if (termDayCount > 0 && dayCount >= termDayCount) {
|
|
|
- return R.fail(new ErrorInfo(400, TradeStatusEnum.DayLimitTimes.toString(), "设备日限次", TradeStatusEnum.DayLimitTimes.getName()));
|
|
|
- }
|
|
|
- if (termDayMoney.compareTo(BigDecimal.ZERO) > 0 && termDayMoney.compareTo(dayValue.add(consumeValue)) < 0) {
|
|
|
- return R.fail(new ErrorInfo(400, TradeStatusEnum.DayLimitMoney.toString(), "设备日限额", TradeStatusEnum.DayLimitMoney.getName()));
|
|
|
- }
|
|
|
- }
|
|
|
- // 当前卡片校验处理
|
|
|
- R<ErrorInfo> result = checkCardLimitDeal(bo, termVo, userCardVo, mealTypeVo);
|
|
|
- if (R.isError(result)) {
|
|
|
- return R.fail(result.getData());
|
|
|
- }
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 卡类限额、限次与折扣验证
|
|
|
- *
|
|
|
- * @param bo 消费业务
|
|
|
- * @param termVo 消费设备
|
|
|
- * @param userCardVo 消费卡片
|
|
|
- * @param mealTypeVo 消费类型
|
|
|
- * @return 检查结果
|
|
|
- */
|
|
|
- public R<ErrorInfo> checkCardLimitDeal(ConsumptionBo bo, XfTermVo termVo, RemoteCardVo userCardVo, RemoteMealTypeVo mealTypeVo) {
|
|
|
- long startTime=System.currentTimeMillis();
|
|
|
- LocalDateTime currentLocalDt = LocalDateTime.now();
|
|
|
- Long cardNo = userCardVo.getCardNo();
|
|
|
- Long mealTypeId = Long.valueOf(mealTypeVo.getTypeId());
|
|
|
- Date lastPayDate = userCardVo.getLastPay();
|
|
|
- // 获取卡片的限制信息
|
|
|
- XfCardLimitedVo cardLimitedVo = cardLimitedService.queryByCardNo(cardNo);
|
|
|
- log.info("卡类限额、限次与折扣初始化耗时1:{}", System.currentTimeMillis()-startTime);
|
|
|
- if (ObjectUtil.isEmpty(cardLimitedVo)) {
|
|
|
- cardLimitedVo = initXfCardLimited(cardNo, mealTypeVo.getMealId(), lastPayDate);
|
|
|
- }
|
|
|
- log.info("卡类限额、限次与折扣初始化耗时:{}", System.currentTimeMillis()-startTime);
|
|
|
- // 最后交易时间
|
|
|
- LocalDateTime lastPayLimitLocalDt = LocalDateTime.ofInstant(cardLimitedVo.getLastPay().toInstant(), ZoneOffset.of("+8"));
|
|
|
- // 最后交易餐类
|
|
|
- Long lastPayLimitMealType = cardLimitedVo.getLastMeal();
|
|
|
- // 判断交易是否为新的一天,如果是则需要重置日消费数据
|
|
|
- if (!lastPayLimitLocalDt.toLocalDate().isEqual(currentLocalDt.toLocalDate())) {
|
|
|
- cardLimitedVo = cardLimitedService.resetDayCardLimitedData(cardNo, mealTypeId.toString());
|
|
|
- }
|
|
|
- // 判断是否为新的餐类,如果是则需要重置餐类消费数据
|
|
|
- if (!Objects.equals(lastPayLimitMealType, mealTypeId)) {
|
|
|
- cardLimitedVo = cardLimitedService.resetMealCardLimitedData(cardNo, mealTypeId.toString());
|
|
|
- }
|
|
|
- log.info("卡类限额、限次与折扣初始化耗时2:{}", System.currentTimeMillis()-startTime);
|
|
|
-
|
|
|
- // 卡类折扣检查
|
|
|
- startTime=System.currentTimeMillis();
|
|
|
- R<ErrorInfo> result = checkCardDisCount(termVo, userCardVo, cardLimitedVo, mealTypeVo, bo);
|
|
|
- if (R.isError(result)) {
|
|
|
- return R.fail(result.getData());
|
|
|
- }
|
|
|
- log.info("卡类折扣检查耗时:{}", System.currentTimeMillis()-startTime);
|
|
|
- // 卡类限额检查
|
|
|
- startTime=System.currentTimeMillis();
|
|
|
- result = checkCardQuota(termVo, userCardVo, cardLimitedVo, mealTypeVo, bo.getConsumeMoney());
|
|
|
- if (R.isError(result)) {
|
|
|
- return R.fail(result.getData());
|
|
|
- }
|
|
|
- log.info("卡类限额检查耗时:{}", System.currentTimeMillis()-startTime);
|
|
|
- // 卡类限次检
|
|
|
- startTime=System.currentTimeMillis();
|
|
|
- result = checkCardLimited(termVo, userCardVo, cardLimitedVo, mealTypeVo);
|
|
|
- if (R.isError(result)) {
|
|
|
- return R.fail(result.getData());
|
|
|
- }
|
|
|
- log.info("卡类限次检查耗时:{}", System.currentTimeMillis()-startTime);
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 卡类的限次验证处理
|
|
|
- *
|
|
|
- * @param termVo 设备信息
|
|
|
- * @param userCardVo 卡片信息
|
|
|
- * @param cardLimitedVo 卡片限制信息
|
|
|
- * @param mealTypeVo 餐类信息
|
|
|
- * @return 验证结果
|
|
|
- */
|
|
|
- private R<ErrorInfo> checkCardLimited(XfTermVo termVo, RemoteCardVo userCardVo, XfCardLimitedVo cardLimitedVo, RemoteMealTypeVo mealTypeVo) {
|
|
|
- String useLimited = remotePtParameterService.getPtParameterByKey("XC_CONSUME");
|
|
|
- String mealType = mealTypeVo.getTypeId();
|
|
|
- if (StrUtil.isEmpty(useLimited) || ObjectUtil.notEqual(useLimited, "1")) {
|
|
|
- // 如果没有启用限次,直接返回
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- Long limitedTermId = remoteLimitedService.queryLimitedTermIdByTermId(termVo.getTermId());
|
|
|
- if (ObjectUtil.equals(limitedTermId, 0L)) {
|
|
|
- // 当前设备没有设置限次
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- RemoteLimitedVo remoteLimitedVo = remoteLimitedService.queryLimitedByCardType(userCardVo.getCardType().intValue());
|
|
|
- if (ObjectUtil.isEmpty(remoteLimitedVo)) {
|
|
|
- // 当前卡类没有限次信息
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- String limitedStatus = remoteLimitedVo.getStatus();
|
|
|
- if (ObjectUtil.isEmpty(limitedStatus) || ObjectUtil.equals(limitedStatus, "0")) {
|
|
|
- // 卡类限次未启用
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- // 每日次数
|
|
|
- Long dayCount = remoteLimitedVo.getDailyCount();
|
|
|
- // 早餐次数
|
|
|
- Long oneCount = remoteLimitedVo.getOneCount();
|
|
|
- // 午餐次数
|
|
|
- Long twoCount = remoteLimitedVo.getTwoCount();
|
|
|
- // 晚餐次数
|
|
|
- Long threeCount = remoteLimitedVo.getThreeCount();
|
|
|
- // 宵夜次数
|
|
|
- Long fourCount = remoteLimitedVo.getFourCount();
|
|
|
-
|
|
|
- if (dayCount.compareTo(0L) > 0 || oneCount.compareTo(0L) > 0 || twoCount.compareTo(0L) > 0 || threeCount.compareTo(
|
|
|
- 0L) > 0 || fourCount.compareTo(0L) > 0) {
|
|
|
- if (dayCount.compareTo(0L) > 0) {
|
|
|
- // 日限次
|
|
|
- if (cardLimitedVo.getDayCount().compareTo(dayCount) >= 0) {
|
|
|
- return R.fail(
|
|
|
- new ErrorInfo(400, TradeStatusEnum.DayLimitTimes.toString(), "卡类日限制次数", TradeStatusEnum.DayLimitTimes.getName()));
|
|
|
- }
|
|
|
- // 早餐限次
|
|
|
- if (ObjectUtil.equals(mealType, "1")) {
|
|
|
- if (cardLimitedVo.getMealCount().compareTo(oneCount) >= 0) {
|
|
|
- return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitTimes.toString(), "卡类早餐限制次数",
|
|
|
- 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()));
|
|
|
- }
|
|
|
- }
|
|
|
- // 晚餐限次
|
|
|
- if (ObjectUtil.equals(mealType, "3")) {
|
|
|
- if (cardLimitedVo.getMealCount().compareTo(threeCount) >= 0) {
|
|
|
- return R.fail(new ErrorInfo(400, TradeStatusEnum.MealLimitTimes.toString(), "卡类晚餐限制次数",
|
|
|
- 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()));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 卡类的限额验证处理
|
|
|
- *
|
|
|
- * @param termVo 设备信息
|
|
|
- * @param userCardVo 卡片信息
|
|
|
- * @param cardLimitedVo 卡片限制信息
|
|
|
- * @param mealTypeVo 餐类信息
|
|
|
- * @param disCountMoney 折扣金额
|
|
|
- * @return 验证结果
|
|
|
- */
|
|
|
- private R<ErrorInfo> checkCardQuota(XfTermVo termVo, RemoteCardVo userCardVo, XfCardLimitedVo cardLimitedVo, RemoteMealTypeVo mealTypeVo,
|
|
|
- BigDecimal disCountMoney) {
|
|
|
- String useQuota = remotePtParameterService.getPtParameterByKey("XE_CONSUME");
|
|
|
- String mealType = mealTypeVo.getTypeId();
|
|
|
- if (StrUtil.isEmpty(useQuota) || ObjectUtil.notEqual(useQuota, "1")) {
|
|
|
- // 如果没有启用限额,直接返回
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- Long quotaTermId = remoteQuotaService.queryQuotaTermIdByTermId(termVo.getTermId());
|
|
|
- if (ObjectUtil.equals(quotaTermId, 0L)) {
|
|
|
- // 当前设备没有设置限额
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- RemoteQuotaVo remoteQuotaVo = remoteQuotaService.queryQuotaByCardType(userCardVo.getCardType().intValue());
|
|
|
- if (ObjectUtil.isEmpty(remoteQuotaVo)) {
|
|
|
- // 当前卡类没有限额信息
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- String quotaStatus = remoteQuotaVo.getStatus();
|
|
|
- if (ObjectUtil.isEmpty(quotaStatus) || ObjectUtil.equals(quotaStatus, "0")) {
|
|
|
- // 卡类限额未启用
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- // 每日金额
|
|
|
- BigDecimal dayMoney = remoteQuotaVo.getDailyMoney();
|
|
|
- // 早餐金额
|
|
|
- BigDecimal oneMoney = remoteQuotaVo.getOneMoney();
|
|
|
- // 午餐金额
|
|
|
- BigDecimal twoMoney = remoteQuotaVo.getTwoMoney();
|
|
|
- // 晚餐金额
|
|
|
- BigDecimal threeMoney = remoteQuotaVo.getThreeMoney();
|
|
|
- // 宵夜金额
|
|
|
- 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) {
|
|
|
- if (dayMoney.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
- BigDecimal mealQuotaMoney = cardLimitedVo.getMealMoney();
|
|
|
- // 日限额
|
|
|
- if (dayMoney.compareTo(cardLimitedVo.getDayMoney().add(disCountMoney)) < 0) {
|
|
|
- return R.fail(
|
|
|
- new ErrorInfo(400, TradeStatusEnum.DayLimitMoney.toString(), "卡类日限制额度", TradeStatusEnum.DayLimitMoney.getName()));
|
|
|
- }
|
|
|
- // 早餐限额
|
|
|
- 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()));
|
|
|
- }
|
|
|
- }
|
|
|
- // 午餐限额
|
|
|
- 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()));
|
|
|
- }
|
|
|
- }
|
|
|
- // 晚餐限额
|
|
|
- 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()));
|
|
|
- }
|
|
|
- }
|
|
|
- // 宵夜限额
|
|
|
- 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()));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 卡类的折扣处理
|
|
|
- *
|
|
|
- * @param termVo 设备信息
|
|
|
- * @param userCardVo 卡片信息
|
|
|
- * @param cardLimitedVo 卡片限制信息
|
|
|
- * @param mealTypeVo 餐类信息
|
|
|
- * @return 验证结果
|
|
|
- */
|
|
|
- private R<ErrorInfo> checkCardDisCount(XfTermVo termVo, RemoteCardVo userCardVo, XfCardLimitedVo cardLimitedVo, RemoteMealTypeVo mealTypeVo,
|
|
|
- ConsumptionBo bo) {
|
|
|
- String useDisCount = remotePtParameterService.getPtParameterByKey("RATE_CONSUME");
|
|
|
- if (StrUtil.isEmpty(useDisCount) || ObjectUtil.notEqual(useDisCount, "1")) {
|
|
|
- // 如果没有启用折扣,直接返回
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- Long disCountTermId = remoteDisCountService.queryDisCountTermIdByTermId(termVo.getTermId());
|
|
|
- if (ObjectUtil.equals(disCountTermId, 0L)) {
|
|
|
- // 当前设备没有设置折扣
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- RemoteDiscountVo remoteDiscountVo = remoteDisCountService.queryDisCountByCardType(userCardVo.getCardType().intValue(),
|
|
|
- mealTypeVo.getTypeId());
|
|
|
- if (ObjectUtil.isEmpty(remoteDiscountVo)) {
|
|
|
- // 当前卡类没有折扣信息
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- String disCountStatus = remoteDiscountVo.getStatus();
|
|
|
- if (ObjectUtil.isEmpty(disCountStatus) || ObjectUtil.equals(disCountStatus, "0")) {
|
|
|
- // 卡类折扣未启用
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
- // 计算折扣金额
|
|
|
- BigDecimal disCountMoney = getDisCountMoney(cardLimitedVo, bo, remoteDiscountVo);
|
|
|
- // 最后的消费金额为折扣后的金额
|
|
|
- bo.setConsumeMoney(disCountMoney);
|
|
|
- return R.ok();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 消费记录入库成功后更新其它消费信息
|
|
|
- * 1.更新卡片交易信息
|
|
|
- * 2.更新卡片的折扣、限次与限额信息
|
|
|
- *
|
|
|
- * @param bo 交易业务对象
|
|
|
- * @param userCardVo 卡片视图对象
|
|
|
- * @param mealTypeVo 餐类视图对象
|
|
|
- * @param termVo 设备视图对象
|
|
|
- */
|
|
|
- private void updateOtherConsumeInfo(ConsumptionBo bo, RemoteCardVo userCardVo, RemoteMealTypeVo mealTypeVo, XfTermVo termVo) {
|
|
|
- Long mealType = Long.parseLong(mealTypeVo.getTypeId());
|
|
|
- Date consumeDate = bo.getConsumeDate();
|
|
|
- String currentDateStr = DateFormatUtils.format(new Date(), "yyyy-MM-dd");
|
|
|
- String consumeDateStr = DateFormatUtils.format(consumeDate, "yyyy-MM-dd");
|
|
|
- if (ObjectUtil.equals(currentDateStr, consumeDateStr)) {
|
|
|
- // 更新卡片交易信息
|
|
|
- Boolean result = remoteCardService.updateCardDayData(userCardVo.getCardNo(), mealType, bo.getConsumeMoney(), consumeDate);
|
|
|
-
|
|
|
- // 限次消费处理
|
|
|
- String useLimited = remotePtParameterService.getPtParameterByKey("XC_CONSUME");
|
|
|
- // 启用了限次
|
|
|
- if (ObjectUtil.isNotEmpty(useLimited) && ObjectUtil.equals(useLimited, "1")) {
|
|
|
- Long limitedTermId = remoteLimitedService.queryLimitedTermIdByTermId(termVo.getTermId());
|
|
|
- // 当前设备也有限次
|
|
|
- if (ObjectUtil.isNotEmpty(limitedTermId) && limitedTermId > 0) {
|
|
|
- // 查询卡类的限次信息
|
|
|
- RemoteLimitedVo remoteLimitedVo = remoteLimitedService.queryLimitedByCardType(userCardVo.getCardType().intValue());
|
|
|
- // 有卡类的限次信息并已启用
|
|
|
- if (ObjectUtil.isNotEmpty(remoteLimitedVo) && ObjectUtil.equals(remoteLimitedVo.getStatus(), "1")) {
|
|
|
- // 更新卡类的限次信息
|
|
|
- result = cardLimitedService.updateLimitedData(userCardVo.getCardNo());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- // 限额消费处理
|
|
|
- String useQuota = remotePtParameterService.getPtParameterByKey("XE_CONSUME");
|
|
|
- // 启用了限额
|
|
|
- if (ObjectUtil.isNotEmpty(useQuota) && ObjectUtil.equals(useQuota, "1")) {
|
|
|
- Long quotaId = remoteQuotaService.queryQuotaTermIdByTermId(termVo.getTermId());
|
|
|
- // 当前设备也有限额
|
|
|
- if (ObjectUtil.isNotEmpty(quotaId) && quotaId > 0) {
|
|
|
- // 查询卡类的限额信息
|
|
|
- RemoteQuotaVo remoteQuotaVo = remoteQuotaService.queryQuotaByCardType(userCardVo.getCardType().intValue());
|
|
|
- // 有卡类的限额信息并已启用
|
|
|
- if (ObjectUtil.isNotEmpty(remoteQuotaVo) && ObjectUtil.equals(remoteQuotaVo.getStatus(), "1")) {
|
|
|
- // 更新卡类的限额信息
|
|
|
- result = cardLimitedService.updateQuotaData(userCardVo.getCardNo(), bo.getConsumeMoney());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- // 折扣消费处理
|
|
|
- String useDisCount = remotePtParameterService.getPtParameterByKey("RATE_CONSUME");
|
|
|
- // 启用了折扣
|
|
|
- if (ObjectUtil.isNotEmpty(useDisCount) && ObjectUtil.equals(useDisCount, "1")) {
|
|
|
- Long disCountTermId = remoteDisCountService.queryDisCountTermIdByTermId(termVo.getTermId());
|
|
|
- // 当前设备也有折扣
|
|
|
- if (ObjectUtil.isNotEmpty(disCountTermId) && disCountTermId > 0) {
|
|
|
- // 查询卡类的折扣信息
|
|
|
- RemoteDiscountVo remoteDisCountVo = remoteDisCountService.queryDisCountByCardType(userCardVo.getCardType().intValue(),
|
|
|
- mealTypeVo.getTypeId());
|
|
|
- // 有卡类的折扣信息并已启用
|
|
|
- if (ObjectUtil.isNotEmpty(remoteDisCountVo) && ObjectUtil.equals(remoteDisCountVo.getStatus(), "1")) {
|
|
|
- // 更新卡类的折扣信息
|
|
|
- result = cardLimitedService.updateDisCountData(userCardVo.getCardNo());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 初始化卡片限制信息
|
|
|
- *
|
|
|
- * @param cardNo 卡流水号
|
|
|
- * @param mealType 餐类
|
|
|
- * @param lastPayDate 最后消费时间
|
|
|
- * @return 卡片限制信息
|
|
|
- */
|
|
|
- private XfCardLimitedVo initXfCardLimited(Long cardNo, Long mealType, Date lastPayDate) {
|
|
|
- LocalDateTime lastPayLocalDt = LocalDateTime.ofInstant(lastPayDate.toInstant(), ZoneOffset.of("+8"));
|
|
|
- XfCardLimitedBo bo = new XfCardLimitedBo();
|
|
|
- bo.setCardNo(cardNo);
|
|
|
- bo.setDayCount(0L);
|
|
|
- bo.setDayMoney(BigDecimal.ZERO);
|
|
|
- bo.setMealCount(0L);
|
|
|
- bo.setMealMoney(BigDecimal.ZERO);
|
|
|
- bo.setDayDiscountCount(0L);
|
|
|
- bo.setMealDiscountCount(0L);
|
|
|
- bo.setLastPay(Date.from(lastPayLocalDt.toInstant(ZoneOffset.of("+8"))));
|
|
|
- bo.setLastMeal(mealType);
|
|
|
-
|
|
|
- return cardLimitedService.insertReturnByBo(bo);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取营业员信息
|
|
|
- *
|
|
|
- * @param bo 消费业务对象
|
|
|
- * @return 营业员信息
|
|
|
- */
|
|
|
- private RemoteOperatorVo getOperatorVo(ConsumptionBo bo) {
|
|
|
- RemoteOperatorVo operatorVo = remoteOperatorService.getVoById(bo.getOperatorId());
|
|
|
- if (ObjectUtil.isEmpty(operatorVo)) {
|
|
|
- operatorVo = new RemoteOperatorVo();
|
|
|
- operatorVo.setOperatorId(bo.getOperatorId());
|
|
|
- operatorVo.setOperatorName(bo.getOperatorName());
|
|
|
- }
|
|
|
- return operatorVo;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理脱机消费记录.
|
|
|
- *
|
|
|
- * @param bo 消费记录对象
|
|
|
- * @param originalId 原始记录Id
|
|
|
- * @param userAccountVo 用户账户信息
|
|
|
- * @return a Result object containing ErrorInfo if there is an error, otherwise null
|
|
|
- */
|
|
|
- private R<ErrorInfo> doOfflineRecord(ConsumptionBo bo, String originalId, RemoteUserAccountVo userAccountVo) {
|
|
|
- try {
|
|
|
- XfConsumeDetailOriginalVo vo;
|
|
|
- Date currentDate = DateUtil.date();
|
|
|
- int recordStatus = bo.getRecordStatus().intValue();
|
|
|
- Long RecordId = bo.getRecordId();
|
|
|
- if (RecordId == 0 && (recordStatus == 106 || recordStatus == 108 || recordStatus == 110 || recordStatus == 111)) {
|
|
|
- if (recordStatus == 110 || recordStatus == 111) {
|
|
|
- vo = consumeDetailOriginalService.queryByConsumeMoney(bo.getCardNo(), bo.getTermNo(), bo.getTermRecordId(),
|
|
|
- bo.getOperatorMoney());
|
|
|
- if (ObjectUtil.isNotEmpty(vo)) {
|
|
|
- resetBoByOfflineResult(bo, vo);
|
|
|
- }
|
|
|
- } else {
|
|
|
- vo = consumeDetailOriginalService.queryByConsumeDate(bo.getCardNo(), bo.getTermNo(), bo.getTermRecordId(), bo.getConsumeDate());
|
|
|
- if (ObjectUtil.isNotEmpty(vo)) {
|
|
|
- resetBoByOfflineResult(bo, vo);
|
|
|
- } else {
|
|
|
- vo = consumeDetailOriginalService.queryById(originalId);
|
|
|
- resetBoByOfflineResult(bo, vo);
|
|
|
- }
|
|
|
- }
|
|
|
- if (bo.getRecordId() == 0) {
|
|
|
- if (bo.getConsumeDate().getTime() > currentDate.getTime()) {
|
|
|
- bo.setConsumeDate(currentDate);
|
|
|
- originalId = RecordIdUtils.getRecordId(bo.getConsumeDate(), bo.getTermNo().shortValue(),
|
|
|
- bo.getTermRecordId().shortValue(), bo.getUserNo().intValue(), 0);
|
|
|
- bo.setOriginalId(originalId);
|
|
|
- }
|
|
|
- vo = new XfConsumeDetailOriginalVo();
|
|
|
- R<ErrorInfo> result = baseBusiness.createOriginalOrder(bo, userAccountVo, vo);
|
|
|
- if (R.isError(result)) {
|
|
|
- return result;
|
|
|
- }
|
|
|
- bo.setRecordId(vo.getRecordId());
|
|
|
- bo.setOriginalId(vo.getOriginalId());
|
|
|
- }
|
|
|
- } else {
|
|
|
- consumeDetailOriginalService.updateRecordStatusByOrginId(recordStatus, originalId);
|
|
|
- }
|
|
|
- return R.ok();
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("[处理脱机记录错误]-[{}]-[{}]", e.getMessage(), Arrays.toString(e.getStackTrace()));
|
|
|
- return R.fail(new ErrorInfo(400, ApiErrorTypeConstants.RECORD_IS_EXISTS, "处理脱机记录错误",
|
|
|
- MessageFormat.format("错误消息:{0}", e.getMessage())));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Resets the ConsumptionBo based on the offline result from XfConsumeDetailOriginalVo.
|
|
|
- * If the provided vo is not null, it updates the bo's recordId and originalId with those from the vo.
|
|
|
- * Additionally, if the dataFlag in the vo is 0, indicating a specific condition related to online transactions,
|
|
|
- * it adjusts the recordStatus of the bo by adding 256 (to mark it as an online transaction) and updates this
|
|
|
- * new status in the database for the given originalId.
|
|
|
- *
|
|
|
- * @param bo The ConsumptionBo object to be reset.
|
|
|
- * @param vo The XfConsumeDetailOriginalVo containing the offline result information.
|
|
|
- */
|
|
|
- private void resetBoByOfflineResult(ConsumptionBo bo, XfConsumeDetailOriginalVo vo) {
|
|
|
- if (ObjectUtil.isNotEmpty(vo)) {
|
|
|
- bo.setRecordId(vo.getRecordId());
|
|
|
- bo.setOriginalId(vo.getOriginalId());
|
|
|
- if (vo.getDataFlag() == 0) {
|
|
|
- /*
|
|
|
- 如果库中原来的原始记录的dataFlag为零,则说明是在线交易时收到一次数据,然而应答之后又没有收到上传的记录,设备却写入了
|
|
|
- 此种记录将采集时得到的DataFlag加上高字节的在线标识256后,得到正确DataFlag,并将之更新到库中
|
|
|
- */
|
|
|
- Long recordStatus = bo.getRecordStatus() + 256;
|
|
|
- bo.setRecordStatus(recordStatus);
|
|
|
- consumeDetailOriginalService.updateRecordStatusByOrginId(recordStatus.intValue(), bo.getOriginalId());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|