diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/business/AccWalletInfoBusiness.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/business/AccWalletInfoBusiness.java new file mode 100644 index 0000000..12acc0f --- /dev/null +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/business/AccWalletInfoBusiness.java @@ -0,0 +1,240 @@ +package com.bonus.canteen.core.account.business; + +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.bonus.canteen.core.account.constants.AccTradeStateEnum; +import com.bonus.canteen.core.account.constants.AccTradeTypeEnum; +import com.bonus.canteen.core.account.constants.WalletBalanceOperationEnum; +import com.bonus.canteen.core.account.domain.AccTrade; +import com.bonus.canteen.core.account.domain.AccTradeWalletDetail; +import com.bonus.canteen.core.account.domain.AccWalletInfo; +import com.bonus.canteen.core.account.domain.WalletUpdateDTO; +import com.bonus.canteen.core.account.domain.bo.WalletBalanceOperation; +import com.bonus.canteen.core.account.mapper.AccWalletInfoMapper; +import com.bonus.canteen.core.account.service.IAccTradeService; +import com.bonus.canteen.core.account.service.IAccTradeWalletDetailService; +import com.bonus.canteen.core.account.service.impl.AccWalletInfoServiceImpl; +import com.bonus.canteen.core.account.utils.AccRedisUtils; +import com.bonus.canteen.core.pay.constants.PayStateEnum; +import com.bonus.common.core.constant.SecurityConstants; +import com.bonus.common.core.exception.ServiceException; +import com.bonus.common.core.utils.DateUtils; +import com.bonus.common.core.web.domain.AjaxResult; +import com.bonus.common.houqin.utils.JacksonUtil; +import com.bonus.common.houqin.utils.id.Id; +import com.bonus.common.security.utils.SecurityUtils; +import com.bonus.system.api.RemoteUserService; +import com.bonus.system.api.domain.SysUser; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +@Component +public class AccWalletInfoBusiness { + private static final Logger log = LoggerFactory.getLogger(AccWalletInfoBusiness.class); + @Autowired + private AccWalletInfoMapper accWalletInfoMapper; + @Resource + private RemoteUserService remoteUserService; + + @Autowired + IAccTradeService accTradeService; + @Autowired + IAccTradeWalletDetailService accTradeWalletDetailService; + @Transactional(rollbackFor = Exception.class) + public void addAccWalletBalance(WalletUpdateDTO walletUpdateDTO) { + log.info("新增钱包入参: {}", JacksonUtil.writeValueAsString(walletUpdateDTO)); + WalletBalanceOperation operation = operationBuilder( + walletUpdateDTO.getAmount(), + walletUpdateDTO.getUserId(), + walletUpdateDTO.getAccWalletIdEnum().getKey(), + walletUpdateDTO.getAccTradeTypeEnum().getKey(), + walletUpdateDTO.getPayChannelEnum().getKey(), + walletUpdateDTO.getPayTypeEnum().getKey(), + walletUpdateDTO.getDeviceSn(), + walletUpdateDTO.getOperationUser()); + operation.setOperationType(WalletBalanceOperationEnum.ADD_BAL.getKey()); + operation.setOrderNo(walletUpdateDTO.getOrderNo()); + acWalletBalanceOperation(operation); + log.info("新增钱包结束"); + } + + @Transactional(rollbackFor = Exception.class) + public void clearAccWalletBalance(WalletUpdateDTO walletUpdateDTO) { + log.info("扣减钱包入参: {}", JacksonUtil.writeValueAsString(walletUpdateDTO)); + try { + WalletBalanceOperation operation = operationBuilder( + walletUpdateDTO.getAmount(), + walletUpdateDTO.getUserId(), + walletUpdateDTO.getAccWalletIdEnum().getKey(), + walletUpdateDTO.getAccTradeTypeEnum().getKey(), + walletUpdateDTO.getPayChannelEnum().getKey(), + walletUpdateDTO.getPayTypeEnum().getKey(), + walletUpdateDTO.getDeviceSn(), + walletUpdateDTO.getOperationUser()); + operation.setOperationType(WalletBalanceOperationEnum.REDUCE_BAL.getKey()); + operation.setOrderNo(walletUpdateDTO.getOrderNo()); + acWalletBalanceOperation(operation); + log.info("扣减钱包结束"); + } finally { + if(!walletUpdateDTO.isBatch()) { + AccRedisUtils.unlockUpdateAccWalletBalance(walletUpdateDTO.getUserId()); + } + } + } + + private WalletBalanceOperation operationBuilder(BigDecimal amount, Long userId, Integer walletId, + Integer tradeType, Integer payChannel, Integer payType, + String deviceSn, String operationUser) { + WalletBalanceOperation operation = new WalletBalanceOperation(); + operation.setUserId(userId); + operation.setAmount(amount); + operation.setWalletId(walletId); + operation.setTradeType(tradeType); + operation.setPayChannel(payChannel); + operation.setPayType(payType); + operation.setDeviceSn(deviceSn); + operation.setOperationUser(StringUtils.isBlank(operationUser) ? SecurityUtils.getUsername() : operationUser); + return operation; + } + + + private void acWalletBalanceOperation(WalletBalanceOperation operation) { + Long tradeId = null; + try{ + List walletInfoList = selectAccWalletInfoByUserId(operation.getUserId()); + BigDecimal accBalTotal = walletInfoList.stream().map(AccWalletInfo::getWalletBal) + .filter(ObjectUtil::isNotNull).reduce(BigDecimal.ZERO, BigDecimal::add); + tradeId = insertAccTradeRecode(operation, accBalTotal); + if(WalletBalanceOperationEnum.getEnum(operation.getOperationType()) == null) { + throw new ServiceException("钱包操作类型不存在"); + } + if(operation.getAmount().compareTo(BigDecimal.ZERO) < 0) { + throw new ServiceException("钱包操作金额不能小于0"); + } + + switch (WalletBalanceOperationEnum.getEnum(operation.getOperationType())) { + case ADD_BAL: + addAccWalletInfo(operation); + break; + case REDUCE_BAL: + reduceAccWalletInfo(operation); + break; + default: + throw new ServiceException("钱包操作类型错误"); + } + walletInfoList = selectAccWalletInfoByUserId(operation.getUserId()); + AccTradeWalletDetail accTradeWalletDetail = new AccTradeWalletDetail(); + accTradeWalletDetail.setTradeId(tradeId); + accTradeWalletDetail.setUserId(operation.getUserId()); + accTradeWalletDetail.setTradeType(operation.getTradeType()); + accTradeWalletDetail.setAmount(operation.getAmount()); + accTradeWalletDetail.setWalletId(operation.getWalletId()); + BigDecimal walletBalByWalletId = walletInfoList.stream().filter((item) -> { + return item.getWalletId().equals(operation.getWalletId()); + }).map(AccWalletInfo::getWalletBal).filter(ObjectUtil::isNotNull).reduce(BigDecimal.ZERO, BigDecimal::add); + accTradeWalletDetail.setWalletBal(walletBalByWalletId); + accTradeWalletDetail.setTradeTime(DateUtils.getNowDate()); + accTradeWalletDetail.setCreateBy(StringUtils.isBlank(operation.getOperationUser()) ? + SecurityUtils.getUsername() : operation.getOperationUser()); + this.accTradeWalletDetailService.insertAccTradeWalletDetail(accTradeWalletDetail); + AccTrade accTrade = new AccTrade(); + accTrade.setTradeId(tradeId); + accTrade.setPayState(PayStateEnum.PAY_SUCC.getKey()); + accTrade.setTradeState(AccTradeStateEnum.TAKE_EFFECT.getKey()); + accTrade.setUpdateBy(StringUtils.isBlank(operation.getOperationUser()) ? + SecurityUtils.getUsername() : operation.getOperationUser()); + accTrade.setWalletBalTotal(walletBalByWalletId); + accTrade.setAccAllBal(walletBalByWalletId); + accTrade.setMachineSn(operation.getDeviceSn()); + this.accTradeService.updateAccTrade(accTrade); + }catch (Exception ex) { + if(Objects.nonNull(tradeId)) { + AccTrade accTrade = new AccTrade(); + accTrade.setTradeId(tradeId); + accTrade.setPayState(PayStateEnum.PAY_FAIL.getKey()); + accTrade.setTradeState(AccTradeStateEnum.CANCELED.getKey()); + accTrade.setUpdateBy(SecurityUtils.getUsername()); + accTrade.setFailReason(StringUtils.substring(ex.getMessage(), 0, 100)); + this.accTradeService.updateAccTrade(accTrade); + } + log.error("修改钱包失败", ex); + throw new ServiceException("修改钱包失败"); + } + } + + private void addAccWalletInfo(WalletBalanceOperation operation) { + accWalletInfoMapper.addAccWalletInfo(operation.getAmount(), operation.getUserId(), operation.getWalletId(), + SecurityUtils.getUserId().toString(), DateUtils.toLocalDateTime(new Date())); + } + + private void reduceAccWalletInfo(WalletBalanceOperation operation) { + AccWalletInfo walletInfo = selectAccWalletInfoByUserIdAndWalletId(operation.getUserId(), + operation.getWalletId()); + if(Objects.isNull(walletInfo) + || walletInfo.getWalletBal().compareTo(BigDecimal.ZERO) < 0 + || (walletInfo.getWalletBal().compareTo(operation.getAmount()) < 0)) { + throw new ServiceException("钱包余额不足"); + } + if(AccTradeTypeEnum.CLEAR.getKey().equals(operation.getOperationType())) { + operation.setAmount(walletInfo.getWalletBal()); + } + accWalletInfoMapper.reduceAccWalletInfo(operation.getAmount(), operation.getUserId(), operation.getWalletId(), + SecurityUtils.getUserId().toString(), DateUtils.toLocalDateTime(new Date())); + } + + private long insertAccTradeRecode(WalletBalanceOperation operation, BigDecimal accBalTotal) { + AjaxResult userResult = remoteUserService.getInfo(operation.getUserId() , SecurityConstants.INNER); + SysUser sysUser = null; + if(Objects.nonNull(userResult)) { + sysUser = JSONObject.parseObject(JSON.toJSONString(userResult.get(AjaxResult.DATA_TAG)), SysUser.class); + } + long tradeId = Id.next(); + LocalDateTime tradeTime = LocalDateTime.now(); + AccTrade accTrade = new AccTrade(); + accTrade.setTradeId(tradeId); + accTrade.setTradeTime(tradeTime); + accTrade.setTradeType(operation.getTradeType()); + accTrade.setAmount(operation.getAmount()); + accTrade.setActualAmount(operation.getAmount()); + accTrade.setWalletBalTotal(accBalTotal); + accTrade.setAccAllBal(accBalTotal); + accTrade.setPayState(PayStateEnum.PAY_INPROCESS.getKey()); + accTrade.setTradeState(AccTradeStateEnum.CREATE.getKey()); + accTrade.setUserId(operation.getUserId()); + accTrade.setPayChannel(operation.getPayChannel()); + accTrade.setPayType(operation.getPayType()); + accTrade.setCreateBy(StringUtils.isBlank(operation.getOperationUser()) ? + SecurityUtils.getUsername() : operation.getOperationUser()); + accTrade.setUpdateBy(StringUtils.isBlank(operation.getOperationUser()) ? + SecurityUtils.getUsername() : operation.getOperationUser()); + if(Objects.nonNull(sysUser)) { + accTrade.setDeptId(sysUser.getDeptId()); + } + if(Objects.nonNull(operation.getOrderNo())) { + accTrade.setOrderNo(operation.getOrderNo().toString()); + } + accTrade.setMachineSn(operation.getDeviceSn()); + this.accTradeService.insertAccTrade(accTrade); + return tradeId; + } + + public List selectAccWalletInfoByUserId(Long userId) { + return accWalletInfoMapper.selectAccWalletInfoByUserId(userId); + } + + public AccWalletInfo selectAccWalletInfoByUserIdAndWalletId(Long userId, Integer walletId) { + return accWalletInfoMapper.selectAccWalletInfoByUserIdAndWalletId(userId, walletId); + } +} diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/domain/WalletUpdateDTO.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/domain/WalletUpdateDTO.java index e208559..f78a081 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/domain/WalletUpdateDTO.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/domain/WalletUpdateDTO.java @@ -17,4 +17,6 @@ public class WalletUpdateDTO { private PayTypeEnum payTypeEnum; private Long orderNo; private String deviceSn; + private boolean isBatch = false; + private String operationUser; } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/domain/bo/WalletBalanceOperation.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/domain/bo/WalletBalanceOperation.java index f4238d3..eeddbe9 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/domain/bo/WalletBalanceOperation.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/domain/bo/WalletBalanceOperation.java @@ -15,4 +15,5 @@ public class WalletBalanceOperation { private Integer payType; private Long orderNo; private String deviceSn; + private String operationUser; } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/service/impl/AccTradeServiceImpl.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/service/impl/AccTradeServiceImpl.java index 99d0922..97b058f 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/service/impl/AccTradeServiceImpl.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/service/impl/AccTradeServiceImpl.java @@ -70,6 +70,7 @@ public class AccTradeServiceImpl implements IAccTradeService { @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) public int insertAccTrade(AccTrade accTrade) { accTrade.setCreateTime(DateUtils.getNowDate()); + accTrade.setUpdateTime(DateUtils.getNowDate()); return accTradeMapper.insertAccTrade(accTrade); } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/service/impl/AccWalletInfoServiceImpl.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/service/impl/AccWalletInfoServiceImpl.java index 1aa8941..5e75fa2 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/service/impl/AccWalletInfoServiceImpl.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/account/service/impl/AccWalletInfoServiceImpl.java @@ -11,6 +11,7 @@ import java.util.stream.Collectors; import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.bonus.canteen.core.account.business.AccWalletInfoBusiness; import com.bonus.canteen.core.account.constants.AccTradeStateEnum; import com.bonus.canteen.core.account.constants.AccTradeTypeEnum; import com.bonus.canteen.core.account.constants.AccWalletIdEnum; @@ -62,13 +63,12 @@ public class AccWalletInfoServiceImpl implements IAccWalletInfoService { @Autowired private AccWalletInfoMapper accWalletInfoMapper; - @Resource - private RemoteUserService remoteUserService; - @Autowired IAccTradeService accTradeService; @Autowired IAccTradeWalletDetailService accTradeWalletDetailService; + @Autowired + AccWalletInfoBusiness accWalletInfoBusiness; /** * 查询钱包详情信息 @@ -177,173 +177,45 @@ public class AccWalletInfoServiceImpl implements IAccWalletInfoService { } } + @Override + public void addAccWalletBalance(WalletUpdateDTO walletUpdateDTO) { + if(!walletUpdateDTO.isBatch()) { + AccRedisUtils.lockUpdateAccWalletBalance(walletUpdateDTO.getUserId()); + } + try { + accWalletInfoBusiness.addAccWalletBalance(walletUpdateDTO); + }catch (Exception ex) { + log.error("钱包充值失败", ex); + throw new ServiceException(ex.getMessage()); + }finally { + if(!walletUpdateDTO.isBatch()) { + AccRedisUtils.unlockUpdateAccWalletBalance(walletUpdateDTO.getUserId()); + } + } + } + + @Override + public void clearAccWalletBalance(WalletUpdateDTO walletUpdateDTO) { + if(!walletUpdateDTO.isBatch()) { + AccRedisUtils.lockUpdateAccWalletBalance(walletUpdateDTO.getUserId()); + } + try { + accWalletInfoBusiness.clearAccWalletBalance(walletUpdateDTO); + + }catch (Exception ex) { + log.error("钱包扣钱失败", ex); + throw new ServiceException(ex.getMessage()); + }finally { + if(!walletUpdateDTO.isBatch()) { + AccRedisUtils.unlockUpdateAccWalletBalance(walletUpdateDTO.getUserId()); + } + } + } + // private void clearAccWalletInfo(WalletBalanceOperation operation) { // accWalletInfoMapper.clearAccWalletInfo(operation.getUserId(), operation.getWalletId(), // SecurityUtils.getUserId().toString(), DateUtils.toLocalDateTime(new Date())); // } - @Transactional(rollbackFor = Exception.class) - public void addAccWalletBalance(WalletUpdateDTO walletUpdateDTO) { - log.info("新增钱包入参: {}", JacksonUtil.writeValueAsString(walletUpdateDTO)); - AccRedisUtils.lockUpdateAccWalletBalance(walletUpdateDTO.getUserId()); - try { - WalletBalanceOperation operation = operationBuilder( - walletUpdateDTO.getAmount(), - walletUpdateDTO.getUserId(), - walletUpdateDTO.getAccWalletIdEnum().getKey(), - walletUpdateDTO.getAccTradeTypeEnum().getKey(), - walletUpdateDTO.getPayChannelEnum().getKey(), - walletUpdateDTO.getPayTypeEnum().getKey(), - walletUpdateDTO.getDeviceSn()); - operation.setOperationType(WalletBalanceOperationEnum.ADD_BAL.getKey()); - operation.setOrderNo(walletUpdateDTO.getOrderNo()); - acWalletBalanceOperation(operation); - log.info("新增钱包结束"); - } finally { - AccRedisUtils.unlockUpdateAccWalletBalance(walletUpdateDTO.getUserId()); - } - } - @Transactional(rollbackFor = Exception.class) - public void clearAccWalletBalance(WalletUpdateDTO walletUpdateDTO) { - log.info("扣减钱包入参: {}", JacksonUtil.writeValueAsString(walletUpdateDTO)); - AccRedisUtils.lockUpdateAccWalletBalance(walletUpdateDTO.getUserId()); - try { - AccWalletInfo walletInfo = selectAccWalletInfoByUserIdAndWalletId(walletUpdateDTO.getUserId(), - walletUpdateDTO.getAccWalletIdEnum().getKey()); - if(Objects.isNull(walletInfo) || (walletInfo.getWalletBal().compareTo(walletUpdateDTO.getAmount()) < 0)) { - throw new ServiceException("钱包余额不足"); - } - WalletBalanceOperation operation = operationBuilder( - walletUpdateDTO.getAmount(), - walletUpdateDTO.getUserId(), - walletUpdateDTO.getAccWalletIdEnum().getKey(), - walletUpdateDTO.getAccTradeTypeEnum().getKey(), - walletUpdateDTO.getPayChannelEnum().getKey(), - walletUpdateDTO.getPayTypeEnum().getKey(), - walletUpdateDTO.getDeviceSn()); - operation.setOperationType(WalletBalanceOperationEnum.REDUCE_BAL.getKey()); - operation.setOrderNo(walletUpdateDTO.getOrderNo()); - acWalletBalanceOperation(operation); - log.info("扣减钱包结束"); - } finally { - AccRedisUtils.unlockUpdateAccWalletBalance(walletUpdateDTO.getUserId()); - } - } - - private WalletBalanceOperation operationBuilder(BigDecimal amount, Long userId, Integer walletId, - Integer tradeType, Integer payChannel, Integer payType, String deviceSn) { - WalletBalanceOperation operation = new WalletBalanceOperation(); - operation.setUserId(userId); - operation.setAmount(amount); - operation.setWalletId(walletId); - operation.setTradeType(tradeType); - operation.setPayChannel(payChannel); - operation.setPayType(payType); - operation.setDeviceSn(deviceSn); - return operation; - } - - - private void acWalletBalanceOperation(WalletBalanceOperation operation) { - Long tradeId = null; - try{ - List walletInfoList = selectAccWalletInfoByUserId(operation.getUserId()); - BigDecimal accBalTotal = walletInfoList.stream().map(AccWalletInfo::getWalletBal) - .filter(ObjectUtil::isNotNull).reduce(BigDecimal.ZERO, BigDecimal::add); - tradeId = insertAccTradeRecode(operation, accBalTotal); - if(WalletBalanceOperationEnum.getEnum(operation.getOperationType()) == null) { - throw new ServiceException("钱包操作类型不存在"); - } - - switch (WalletBalanceOperationEnum.getEnum(operation.getOperationType())) { - case ADD_BAL: - addAccWalletInfo(operation); - break; - case REDUCE_BAL: - reduceAccWalletInfo(operation); - break; - default: - throw new ServiceException("钱包操作类型错误"); - } - walletInfoList = selectAccWalletInfoByUserId(operation.getUserId()); - AccTradeWalletDetail accTradeWalletDetail = new AccTradeWalletDetail(); - accTradeWalletDetail.setTradeId(tradeId); - accTradeWalletDetail.setUserId(operation.getUserId()); - accTradeWalletDetail.setTradeType(operation.getTradeType()); - accTradeWalletDetail.setAmount(operation.getAmount()); - accTradeWalletDetail.setWalletId(operation.getWalletId()); - BigDecimal walletBalByWalletId = walletInfoList.stream().filter((item) -> { - return item.getWalletId().equals(operation.getWalletId()); - }).map(AccWalletInfo::getWalletBal).filter(ObjectUtil::isNotNull).reduce(BigDecimal.ZERO, BigDecimal::add); - accTradeWalletDetail.setWalletBal(walletBalByWalletId); - accTradeWalletDetail.setTradeTime(DateUtils.getNowDate()); - accTradeWalletDetail.setCreateBy(SecurityUtils.getUsername()); - this.accTradeWalletDetailService.insertAccTradeWalletDetail(accTradeWalletDetail); - AccTrade accTrade = new AccTrade(); - accTrade.setTradeId(tradeId); - accTrade.setPayState(PayStateEnum.PAY_SUCC.getKey()); - accTrade.setTradeState(AccTradeStateEnum.TAKE_EFFECT.getKey()); - accTrade.setUpdateBy(SecurityUtils.getUsername()); - accTrade.setWalletBalTotal(walletBalByWalletId); - accTrade.setAccAllBal(walletBalByWalletId); - accTrade.setMachineSn(operation.getDeviceSn()); - this.accTradeService.updateAccTrade(accTrade); - }catch (Exception ex) { - if(Objects.nonNull(tradeId)) { - AccTrade accTrade = new AccTrade(); - accTrade.setTradeId(tradeId); - accTrade.setPayState(PayStateEnum.PAY_FAIL.getKey()); - accTrade.setTradeState(AccTradeStateEnum.CANCELED.getKey()); - accTrade.setUpdateBy(SecurityUtils.getUsername()); - accTrade.setFailReason(StringUtils.substring(ex.getMessage(), 0, 100)); - this.accTradeService.updateAccTrade(accTrade); - } - log.error("修改钱包失败", ex); - throw new ServiceException("修改钱包失败"); - } - } - - private void addAccWalletInfo(WalletBalanceOperation operation) { - accWalletInfoMapper.addAccWalletInfo(operation.getAmount(), operation.getUserId(), operation.getWalletId(), - SecurityUtils.getUserId().toString(), DateUtils.toLocalDateTime(new Date())); - } - - private void reduceAccWalletInfo(WalletBalanceOperation operation) { - accWalletInfoMapper.reduceAccWalletInfo(operation.getAmount(), operation.getUserId(), operation.getWalletId(), - SecurityUtils.getUserId().toString(), DateUtils.toLocalDateTime(new Date())); - } - - private long insertAccTradeRecode(WalletBalanceOperation operation, BigDecimal accBalTotal) { - AjaxResult userResult = remoteUserService.getInfo(operation.getUserId() , SecurityConstants.INNER); - SysUser sysUser = null; - if(Objects.nonNull(userResult)) { - sysUser = JSONObject.parseObject(JSON.toJSONString(userResult.get(AjaxResult.DATA_TAG)), SysUser.class); - } - long tradeId = Id.next(); - LocalDateTime tradeTime = LocalDateTime.now(); - AccTrade accTrade = new AccTrade(); - accTrade.setTradeId(tradeId); - accTrade.setTradeTime(tradeTime); - accTrade.setTradeType(operation.getTradeType()); - accTrade.setAmount(operation.getAmount()); - accTrade.setActualAmount(operation.getAmount()); - accTrade.setWalletBalTotal(accBalTotal); - accTrade.setAccAllBal(accBalTotal); - accTrade.setPayState(PayStateEnum.PAY_INPROCESS.getKey()); - accTrade.setTradeState(AccTradeStateEnum.CREATE.getKey()); - accTrade.setUserId(operation.getUserId()); - accTrade.setPayChannel(operation.getPayChannel()); - accTrade.setPayType(operation.getPayType()); - accTrade.setCreateBy(SecurityUtils.getUsername()); - if(Objects.nonNull(sysUser)) { - accTrade.setDeptId(sysUser.getDeptId()); - } - if(Objects.nonNull(operation.getOrderNo())) { - accTrade.setOrderNo(operation.getOrderNo().toString()); - } - accTrade.setMachineSn(operation.getDeviceSn()); - this.accTradeService.insertAccTrade(accTrade); - return tradeId; - } } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/business/OrderBusiness.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/business/OrderBusiness.java index 331147f..77abb09 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/business/OrderBusiness.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/business/OrderBusiness.java @@ -1,36 +1,62 @@ package com.bonus.canteen.core.order.business; import cn.hutool.core.collection.CollUtil; +import com.bonus.canteen.core.account.constants.AccTradeTypeEnum; +import com.bonus.canteen.core.account.constants.AccWalletIdEnum; +import com.bonus.canteen.core.account.domain.AccWalletInfo; +import com.bonus.canteen.core.account.domain.WalletUpdateDTO; import com.bonus.canteen.core.account.domain.vo.AccInfoDetailsVO; import com.bonus.canteen.core.account.service.IAccInfoService; +import com.bonus.canteen.core.account.service.IAccWalletInfoService; +import com.bonus.canteen.core.account.utils.AccRedisUtils; +import com.bonus.canteen.core.common.utils.MqUtil; import com.bonus.canteen.core.common.utils.ObjectUtils; import com.bonus.canteen.core.menu.domain.MenuRecipeDishes; import com.bonus.canteen.core.menu.service.IMenuRecipeDishesService; import com.bonus.canteen.core.order.constants.OrderDetailTypeEnum; +import com.bonus.canteen.core.order.constants.OrderStateEnum; import com.bonus.canteen.core.order.domain.OrderDetail; import com.bonus.canteen.core.order.domain.OrderInfo; +import com.bonus.canteen.core.order.domain.OrderPayDTO; +import com.bonus.canteen.core.order.domain.OrderPayResultDTO; import com.bonus.canteen.core.order.domain.param.OrderAddParam; import com.bonus.canteen.core.order.mapper.OrderInfoMapper; import com.bonus.canteen.core.order.service.IOrderDetailService; +import com.bonus.canteen.core.order.service.impl.OrderInfoServiceImpl; +import com.bonus.canteen.core.pay.constants.PayChannelEnum; +import com.bonus.canteen.core.pay.constants.PayStateEnum; +import com.bonus.canteen.core.pay.constants.PayTypeEnum; +import com.bonus.canteen.core.user.domain.DeviceMqPersonalUpdateMessageDTO; import com.bonus.common.core.exception.ServiceException; +import com.bonus.common.houqin.mq.constant.LeMqConstant; +import com.bonus.common.houqin.utils.JacksonUtil; +import com.bonus.common.security.utils.SecurityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.List; +import java.util.stream.Collectors; @Component public class OrderBusiness { - @Autowired - private IAccInfoService accInfoService; + private static final Logger log = LoggerFactory.getLogger(OrderBusiness.class); + @Autowired private IOrderDetailService orderDetailService; @Autowired private OrderInfoMapper orderInfoMapper; @Autowired private IMenuRecipeDishesService menuRecipeDishesService; + @Autowired + private IAccWalletInfoService accWalletInfoService; - @Transactional(rollbackFor = Exception.class) + @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) public List orderPlaceHandler(List orderInfoList) { if(CollUtil.isEmpty(orderInfoList)) { throw new ServiceException("订单明细不能为空"); @@ -71,4 +97,107 @@ public class OrderBusiness { menuRecipeDishesService.addMenuRecipeDishesSupplyNum(menuRecipeDishes, orderDetail.getQuantity()); } } + + @Transactional(rollbackFor = Exception.class) + public void updateOrderPayFailed(List orderInfoList) { + OrderPayResultDTO orderPayResultDTO = new OrderPayResultDTO(); + orderPayResultDTO.setOrderIdList(orderInfoList.stream().map(OrderInfo::getOrderId).collect(Collectors.toList())); + orderPayResultDTO.setPayState(PayStateEnum.PAY_FAIL.getKey()); + orderPayResultDTO.setUpdateBy(SecurityUtils.getUsername()); + orderPayResultDTO.setPayTime(LocalDateTime.now()); + orderPayResultDTO.setUpdateTime(LocalDateTime.now()); + orderInfoMapper.updateOrderPayResult(orderPayResultDTO); + } + + @Transactional(rollbackFor = Exception.class) + public void orderPay(List orderInfoList) { + OrderPayDTO orderPayDTO = buildOrderPayDTO(orderInfoList); + try { + List walletInfoList = accWalletInfoService.selectAccWalletInfoByUserId(orderPayDTO.getUserId()); + if (CollUtil.isEmpty(walletInfoList)) { + throw new ServiceException("钱包不存在"); + } + + BigDecimal subsidyWalletBal = getWalletBalance(walletInfoList, AccWalletIdEnum.SUBSIDY); + BigDecimal personalWalletBal = getWalletBalance(walletInfoList, AccWalletIdEnum.WALLET); + BigDecimal totalWalletBal = subsidyWalletBal.add(personalWalletBal); + + if (totalWalletBal.compareTo(orderPayDTO.getOrderTotalAmount()) < 0) { + throw new ServiceException("钱包余额不足"); + } + for(OrderInfo orderInfo : orderInfoList) { + deductFromWallets(orderInfo, subsidyWalletBal); + } + } catch (Exception ex) { + log.error("订单支付异常", ex); + throw new ServiceException("支付失败"); + } + OrderPayResultDTO orderPayResultDTO = new OrderPayResultDTO(); + orderPayResultDTO.setOrderIdList(orderInfoList.stream().map(OrderInfo::getOrderId).collect(Collectors.toList())); + orderPayResultDTO.setPayState(PayStateEnum.PAY_SUCC.getKey()); + orderPayResultDTO.setUpdateBy(SecurityUtils.getUsername()); + orderPayResultDTO.setOrderState(OrderStateEnum.PLACE.getKey()); + orderPayResultDTO.setPayTime(LocalDateTime.now()); + orderPayResultDTO.setUpdateTime(LocalDateTime.now()); + orderInfoMapper.updateOrderPayResult(orderPayResultDTO); + try { + DeviceMqPersonalUpdateMessageDTO bean = new DeviceMqPersonalUpdateMessageDTO().setUpdatePerson(Math.toIntExact(orderInfoList.get(0).getUserId()),"update"); + String jsonString = JacksonUtil.writeValueAsString(bean); + log.info("账户变动发送mq内容:{}", jsonString); + MqUtil.pushToTenantAllDevice(bean, LeMqConstant.Topic.DEVICE_UPDATE_PERSONAL_CONFIG_V4); + } catch (Exception e) { + log.error("发送MQ消息失败", e); + } + } + + private OrderPayDTO buildOrderPayDTO(List orderInfoList) { + OrderPayDTO orderPayDTO = new OrderPayDTO(); + BigDecimal totalAmount = orderInfoList.stream() + .map(OrderInfo::getRealAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + orderPayDTO.setOrderTotalAmount(totalAmount); + orderPayDTO.setUserId(orderInfoList.get(0).getUserId()); + orderPayDTO.setOrderInfoList(orderInfoList); + return orderPayDTO; + } + + private void deductFromWallets(OrderInfo orderInfo, BigDecimal subsidyWalletBal) { + Long orderNo = orderInfo.getOrderId(); + String deviceSn = orderInfo.getDeviceSn(); + if (orderInfo.getRealAmount().compareTo(subsidyWalletBal) <= 0) { + deductWalletBalance(orderInfo.getRealAmount(), orderInfo.getUserId(), AccWalletIdEnum.SUBSIDY, orderNo, deviceSn); + } else if (subsidyWalletBal.compareTo(BigDecimal.ZERO) > 0) { + deductWalletBalance(subsidyWalletBal, orderInfo.getUserId(), AccWalletIdEnum.SUBSIDY, orderNo, deviceSn); + BigDecimal remainAmount = orderInfo.getRealAmount().subtract(subsidyWalletBal); + deductWalletBalance(remainAmount, orderInfo.getUserId(), AccWalletIdEnum.WALLET, orderNo, deviceSn); + } else { + deductWalletBalance(orderInfo.getRealAmount(), orderInfo.getUserId(), AccWalletIdEnum.WALLET, orderNo, deviceSn); + } + } + + private void deductWalletBalance(BigDecimal amount, + Long userId, + AccWalletIdEnum walletIdEnum, + Long orderNo, + String deviceSn) { + WalletUpdateDTO walletUpdateDTO = new WalletUpdateDTO(); + walletUpdateDTO.setAmount(amount); + walletUpdateDTO.setUserId(userId); + walletUpdateDTO.setAccWalletIdEnum(walletIdEnum); + walletUpdateDTO.setAccTradeTypeEnum(AccTradeTypeEnum.CONSUME); + walletUpdateDTO.setPayChannelEnum(PayChannelEnum.ACC); + walletUpdateDTO.setPayTypeEnum(PayTypeEnum.MEAL_CARD); + walletUpdateDTO.setOrderNo(orderNo); + walletUpdateDTO.setDeviceSn(deviceSn); + walletUpdateDTO.setBatch(true); + accWalletInfoService.clearAccWalletBalance(walletUpdateDTO); + } + + private BigDecimal getWalletBalance(List walletInfoList, AccWalletIdEnum walletIdEnum) { + return walletInfoList.stream() + .filter(walletInfo -> walletIdEnum.getKey().equals(walletInfo.getWalletId())) + .map(AccWalletInfo::getWalletBal) + .findFirst() + .orElse(BigDecimal.ZERO); + } } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/controller/OrderInfoController.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/controller/OrderInfoController.java index 4ee896e..4e2efdb 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/controller/OrderInfoController.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/controller/OrderInfoController.java @@ -3,7 +3,9 @@ package com.bonus.canteen.core.order.controller; import java.util.List; import java.util.Objects; +import cn.hutool.core.collection.CollUtil; import com.bonus.canteen.core.order.domain.OrderInfo; +import com.bonus.canteen.core.order.domain.OrderRefundHistoryVO; import com.bonus.canteen.core.order.domain.param.*; import com.bonus.canteen.core.order.service.IOrderInfoService; import com.bonus.common.core.exception.ServiceException; @@ -13,6 +15,7 @@ import com.bonus.common.core.web.domain.AjaxResult; import com.bonus.common.core.web.page.TableDataInfo; import com.bonus.common.log.annotation.SysLog; import com.bonus.common.log.enums.OperaType; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @@ -41,8 +44,32 @@ public class OrderInfoController extends BaseController */ @PostMapping("/list") @ResponseBody - public TableDataInfo list(@RequestBody @Valid OrderQueryParam orderQueryParam) + public TableDataInfo h5List(@RequestBody @Valid OrderQueryParam orderQueryParam) { + if(Objects.isNull(orderQueryParam.getUserId())) { + throw new ServiceException("用户ID不能为空"); + } + startPage(); + List list = orderInfoService.selectOrderInfoList(orderQueryParam); + return getDataTable(list); + } + + @PostMapping("/web/refund/list") + @ResponseBody + public TableDataInfo webRefundList(@RequestBody @Valid OrderRefundHistoryParam param) + { + startPage(); + List list = orderInfoService.orderRefundHistory(param); + return getDataTable(list); + } + + @PostMapping("/web/list") + @ResponseBody + public TableDataInfo webList(@RequestBody @Valid OrderQueryParam orderQueryParam) + { + if(Objects.isNull(orderQueryParam) || CollUtil.isEmpty(orderQueryParam.getOrderTypeList())) { + throw new ServiceException("订单类型不能为空"); + } startPage(); List list = orderInfoService.selectOrderInfoList(orderQueryParam); return getDataTable(list); @@ -127,20 +154,17 @@ public class OrderInfoController extends BaseController @ResponseBody public AjaxResult refund(@PathVariable("orderId") Long orderId) { - orderInfoService.refund(orderId); + orderInfoService.refund(orderId, StringUtils.EMPTY); return AjaxResult.success(); } @SysLog(title = "退单", module = "订单", businessType = OperaType.UPDATE) - @PostMapping("/device/refund/{deviceOrderId}") + @PostMapping("/device/refund") @ResponseBody - public AjaxResult deviceRefund(@PathVariable("deviceOrderId") String deviceOrderId) + public AjaxResult deviceRefund(@RequestBody @Valid DeviceRefundParam param) { - if(Objects.isNull(deviceOrderId)) { - throw new ServiceException("订单ID不能为空"); - } - OrderInfo orderInfo = orderInfoService.selectOrderInfoBydeviceOrderId(deviceOrderId); - orderInfoService.refund(orderInfo.getOrderId()); + OrderInfo orderInfo = orderInfoService.selectOrderInfoBydeviceOrderId(param.getDeviceOrderId()); + orderInfoService.refund(orderInfo.getOrderId(), param.getOperationUser()); return AjaxResult.success(); } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderInfo.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderInfo.java index b99139d..5942266 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderInfo.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderInfo.java @@ -119,8 +119,8 @@ public class OrderInfo extends BaseEntity private BigDecimal refundAmount; /** 下单时间 yyyy-MM-dd HH:mm:ss */ - @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") - @Excel(name = "下单时间 yyyy-MM-dd HH:mm:ss", width = 30, dateFormat = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @Excel(name = "下单时间 yyyy-MM-dd HH:mm:ss", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date orderTime; /** 订单类型 1 当餐 2 预订餐 3 报餐 4 商城 11 线下消费 12 自助餐 21 补扣 22 外部订单 */ @@ -140,8 +140,8 @@ public class OrderInfo extends BaseEntity private Integer deductionType; /** 支付时间 yyyy-MM-dd HH:mm:ss */ - @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") - @Excel(name = "支付时间 yyyy-MM-dd HH:mm:ss", width = 30, dateFormat = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + @Excel(name = "支付时间 yyyy-MM-dd HH:mm:ss", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date payTime; /** 支付方式 */ @@ -176,6 +176,10 @@ public class OrderInfo extends BaseEntity @Excel(name = "评论状态 1 已评论 2 未评论") private Integer commentState; + private String deviceName; + + private String nickName; + List orderDetailList; public List of(OrderAddParam param) { diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderPayResultDTO.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderPayResultDTO.java index c8e2668..ce71d8d 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderPayResultDTO.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderPayResultDTO.java @@ -3,6 +3,7 @@ package com.bonus.canteen.core.order.domain; import lombok.Data; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.List; @Data @@ -12,4 +13,6 @@ public class OrderPayResultDTO { private BigDecimal payAmount; private String updateBy; private Integer orderState; + private LocalDateTime payTime; + private LocalDateTime updateTime; } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderRefundHistoryVO.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderRefundHistoryVO.java new file mode 100644 index 0000000..cf2b7fe --- /dev/null +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/OrderRefundHistoryVO.java @@ -0,0 +1,24 @@ +package com.bonus.canteen.core.order.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +public class OrderRefundHistoryVO implements Serializable { + private Long userId; + private String nickName; + private Long orderId; + private BigDecimal realAmount; + private LocalDateTime payTime; + private String payType; + @JsonIgnore + private Long tradeId; + private BigDecimal actualAmount; + private String tradeType; + private LocalDateTime tradeTime; + private String updateBy; +} diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/param/DeviceRefundParam.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/param/DeviceRefundParam.java new file mode 100644 index 0000000..55cd5b4 --- /dev/null +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/param/DeviceRefundParam.java @@ -0,0 +1,14 @@ +package com.bonus.canteen.core.order.domain.param; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +@Data +public class DeviceRefundParam implements Serializable { + @NotNull + private String deviceOrderId; + @NotNull + private String operationUser; +} diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/param/OrderQueryParam.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/param/OrderQueryParam.java index 5fa3bf7..8324292 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/param/OrderQueryParam.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/param/OrderQueryParam.java @@ -11,6 +11,7 @@ import java.io.Serializable; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.Date; +import java.util.List; /** * 订单对象 order_info @@ -30,56 +31,62 @@ public class OrderQueryParam implements Serializable /** 设备sn */ private String deviceSn; + private Long orderId; + + private List deptIdList; + /** 设备编号 */ private String deviceNum; /** 人员编号 */ - @NotNull(message = "用户ID不能为空") private Long userId; /** 身份验证方式 1 刷卡 2 刷脸 3 扫码 */ private Integer identityVerification; /** 订单来源类型 */ - @Excel(name = "订单来源类型") private Integer sourceType; /** 是否在线订单 1 是 2 否 */ private Integer isOnline; /** 食堂id */ - @Excel(name = "食堂id") private Long canteenId; + private List canteenIdList; + /** 档口id */ private Long stallId; + private List stallIdList; + /** 餐次类型 1-早餐 2-午餐 3-晚餐 4-下午茶 5-夜宵 */ private Integer mealtimeType; + private List mealtimeTypeList; + /** 订单日期 yyyy-MM-dd */ @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") private Date orderDate; /** 下单时间 yyyy-MM-dd HH:mm:ss */ @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") - @Excel(name = "下单时间 yyyy-MM-dd HH:mm:ss", width = 30, dateFormat = "yyyy-MM-dd") private Date orderTime; /** 订单类型 1 当餐 2 预订餐 3 报餐 4 商城 11 线下消费 12 自助餐 21 补扣 22 外部订单 */ - @Excel(name = "订单类型 1 当餐 2 预订餐 3 报餐 4 商城 11 线下消费 12 自助餐 21 补扣 22 外部订单") private Integer orderType; + private List orderTypeList; + /** 订单状态 1 已下单 2 已完成 3 已取消 */ - @Excel(name = "订单状态 1 已下单 2 已完成 3 已取消") private Integer orderState; + private List orderStateList; + /** 订单退款状态 1 未退单 2 已退单 3 部分退单 */ - @Excel(name = "订单退款状态 1 未退单 2 已退单 3 部分退单") private Integer orderRefundState; /** 扣款类型 1 下单扣款 2 核销扣款 */ - @Excel(name = "扣款类型 1 下单扣款 2 核销扣款") private Integer deductionType; /** 支付时间 yyyy-MM-dd HH:mm:ss */ @@ -87,19 +94,17 @@ public class OrderQueryParam implements Serializable private Date payTime; /** 支付方式 */ - @Excel(name = "支付方式") private Integer payType; /** 支付渠道 */ - @Excel(name = "支付渠道") private Integer payChannel; /** 支付状态 1 待支付 2 支付中 3 支付成功 4 支付失败 5 支付取消 6 部分支付 */ - @Excel(name = "支付状态 1 待支付 2 支付中 3 支付成功 4 支付失败 5 支付取消 6 部分支付") private Integer payState; + private List payStateList; + /** 评论状态 1 已评论 2 未评论 */ - @Excel(name = "评论状态 1 已评论 2 未评论") private Integer commentState; @ApiModelProperty("开始时间") @@ -112,7 +117,6 @@ public class OrderQueryParam implements Serializable private String searchValue; - public OrderQueryParam() { this.endDateTime = LocalDateTime.now().plusDays(7); this.startDateTime = LocalDateTime.now().minusDays(7); diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/param/OrderRefundHistoryParam.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/param/OrderRefundHistoryParam.java new file mode 100644 index 0000000..94b1040 --- /dev/null +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/domain/param/OrderRefundHistoryParam.java @@ -0,0 +1,42 @@ +package com.bonus.canteen.core.order.domain.param; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.List; + +/** + * 订单对象 order_info + * + * @author ruoyi + * @date 2025-04-14 + */ + +@Data +public class OrderRefundHistoryParam implements Serializable +{ + private static final long serialVersionUID = 1L; + + private Long orderId; + + private List deptIdList; + + @ApiModelProperty("开始时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime startDateTime; + + @ApiModelProperty("结束时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime endDateTime; + + private String searchValue; + + public OrderRefundHistoryParam() { + this.endDateTime = LocalDateTime.now().plusDays(7); + this.startDateTime = LocalDateTime.now().minusDays(7); + } +} diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mapper/OrderInfoMapper.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mapper/OrderInfoMapper.java index c017239..b8f4a5d 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mapper/OrderInfoMapper.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mapper/OrderInfoMapper.java @@ -2,7 +2,9 @@ package com.bonus.canteen.core.order.mapper; import com.bonus.canteen.core.order.domain.OrderInfo; import com.bonus.canteen.core.order.domain.OrderPayResultDTO; +import com.bonus.canteen.core.order.domain.OrderRefundHistoryVO; import com.bonus.canteen.core.order.domain.param.OrderQueryParam; +import com.bonus.canteen.core.order.domain.param.OrderRefundHistoryParam; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -66,4 +68,6 @@ public interface OrderInfoMapper * @return 结果 */ public int deleteOrderInfoByOrderIds(List orderIds); + + public List orderRefundHistory(@Param("param") OrderRefundHistoryParam param); } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/IOrderInfoService.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/IOrderInfoService.java index d9f9128..1d6cd2e 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/IOrderInfoService.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/IOrderInfoService.java @@ -1,7 +1,9 @@ package com.bonus.canteen.core.order.service; import com.bonus.canteen.core.order.domain.OrderInfo; +import com.bonus.canteen.core.order.domain.OrderRefundHistoryVO; import com.bonus.canteen.core.order.domain.param.*; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -66,6 +68,7 @@ public interface IOrderInfoService */ public int deleteOrderInfoByOrderId(Long orderId); - public void refund(Long orderId); + public void refund(Long orderId, String operationUser); public void pay(Long orderId); + List orderRefundHistory(@Param("param") OrderRefundHistoryParam param); } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/impl/OrderInfoServiceImpl.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/impl/OrderInfoServiceImpl.java index d38546c..dbb422f 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/impl/OrderInfoServiceImpl.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/impl/OrderInfoServiceImpl.java @@ -11,20 +11,15 @@ import com.bonus.canteen.core.account.domain.vo.AccInfoDetailsVO; import com.bonus.canteen.core.account.service.IAccInfoService; import com.bonus.canteen.core.account.service.IAccTradeService; import com.bonus.canteen.core.account.service.IAccWalletInfoService; +import com.bonus.canteen.core.account.utils.AccRedisUtils; import com.bonus.canteen.core.common.utils.MqUtil; import com.bonus.canteen.core.common.utils.RedisUtil; import com.bonus.canteen.core.order.business.OrderBusiness; import com.bonus.canteen.core.order.constants.OrderDetailStateEnum; import com.bonus.canteen.core.order.constants.OrderRefundStateEnum; import com.bonus.canteen.core.order.constants.OrderStateEnum; -import com.bonus.canteen.core.order.domain.OrderDetail; -import com.bonus.canteen.core.order.domain.OrderInfo; -import com.bonus.canteen.core.order.domain.OrderPayDTO; -import com.bonus.canteen.core.order.domain.OrderPayResultDTO; -import com.bonus.canteen.core.order.domain.param.DeviceOrderAddParam; -import com.bonus.canteen.core.order.domain.param.OrderAddParam; -import com.bonus.canteen.core.order.domain.param.OrderQueryParam; -import com.bonus.canteen.core.order.domain.param.ShopOrderAddParam; +import com.bonus.canteen.core.order.domain.*; +import com.bonus.canteen.core.order.domain.param.*; import com.bonus.canteen.core.order.mapper.OrderInfoMapper; import com.bonus.canteen.core.order.service.IOrderDetailService; import com.bonus.canteen.core.order.service.IOrderInfoService; @@ -34,6 +29,7 @@ import com.bonus.canteen.core.pay.constants.PayTypeEnum; import com.bonus.canteen.core.user.domain.DeviceMqPersonalUpdateMessageDTO; import com.bonus.common.core.exception.ServiceException; import com.bonus.common.core.utils.DateUtils; +import com.bonus.common.core.utils.StringUtils; import com.bonus.common.houqin.constant.SourceTypeEnum; import com.bonus.common.houqin.mq.constant.LeMqConstant; import com.bonus.common.houqin.utils.JacksonUtil; @@ -45,6 +41,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -63,8 +60,6 @@ public class OrderInfoServiceImpl implements IOrderInfoService @Autowired private OrderInfoMapper orderInfoMapper; @Autowired - private IAccWalletInfoService accWalletInfoService; - @Autowired private IAccTradeService accTradeService; @Autowired private IAccInfoService accInfoService; @@ -72,6 +67,8 @@ public class OrderInfoServiceImpl implements IOrderInfoService private IOrderDetailService orderDetailService; @Autowired private OrderBusiness orderBusiness; + @Autowired + private IAccWalletInfoService accWalletInfoService; /** * 查询订单 @@ -110,7 +107,6 @@ public class OrderInfoServiceImpl implements IOrderInfoService /** * 查询订单列表 * - * @param orderInfo 订单 * @return 订单 */ @Override @@ -141,7 +137,15 @@ public class OrderInfoServiceImpl implements IOrderInfoService List canteenOrderInfoList = new OrderInfo().of(orderAddParam); checkOrdersTotalAmount(canteenOrderInfoList, orderAddParam.getRealAmount()); List orderInfoList = orderBusiness.orderPlaceHandler(canteenOrderInfoList); - orderPay(orderInfoList); + try { + AccRedisUtils.lockUpdateAccWalletBalance(orderAddParam.getUserId()); + orderBusiness.orderPay(orderInfoList); + }catch (Exception ex) { + orderBusiness.updateOrderPayFailed(orderInfoList); + throw new ServiceException(ex.getMessage()); + }finally { + AccRedisUtils.unlockUpdateAccWalletBalance(orderAddParam.getUserId()); + } return 1; } @Override @@ -157,7 +161,15 @@ public class OrderInfoServiceImpl implements IOrderInfoService List canteenOrderInfoList = new OrderInfo().of(orderAddParam); checkOrdersTotalAmount(canteenOrderInfoList, orderAddParam.getRealAmount()); List orderInfoList = orderBusiness.orderPlaceHandler(canteenOrderInfoList); - orderPay(orderInfoList); + try { + AccRedisUtils.lockUpdateAccWalletBalance(orderAddParam.getUserId()); + orderBusiness.orderPay(orderInfoList); + }catch (Exception ex) { + orderBusiness.updateOrderPayFailed(orderInfoList); + throw new ServiceException(ex.getMessage()); + }finally { + AccRedisUtils.unlockUpdateAccWalletBalance(orderAddParam.getUserId()); + } return 1; } @@ -173,7 +185,15 @@ public class OrderInfoServiceImpl implements IOrderInfoService accInfoService.checkAccStatus(accInfoVO); List canteenOrderInfoList = new ShopOrderAddParam().of(orderAddParam); List orderInfoList = orderBusiness.orderPlaceHandler(canteenOrderInfoList); - orderPay(orderInfoList); + try { + AccRedisUtils.lockUpdateAccWalletBalance(orderAddParam.getUserId()); + orderBusiness.orderPay(orderInfoList); + }catch (Exception ex) { + orderBusiness.updateOrderPayFailed(orderInfoList); + throw new ServiceException(ex.getMessage()); + }finally { + AccRedisUtils.unlockUpdateAccWalletBalance(orderAddParam.getUserId()); + } return 1; } @@ -197,100 +217,21 @@ public class OrderInfoServiceImpl implements IOrderInfoService if(PayStateEnum.isUnPay(orderInfo.getPayState())) { List orderInfoList = new ArrayList<>(); orderInfoList.add(orderInfo); - orderPay(orderInfoList); - } - } - private void orderPay(List orderInfoList) { - OrderPayDTO orderPayDTO = buildOrderPayDTO(orderInfoList); - try { - List walletInfoList = accWalletInfoService.selectAccWalletInfoByUserId(orderPayDTO.getUserId()); - if (CollUtil.isEmpty(walletInfoList)) { - throw new ServiceException("钱包不存在"); + try { + AccRedisUtils.lockUpdateAccWalletBalance(orderInfo.getUserId()); + orderBusiness.orderPay(orderInfoList); + }catch (Exception ex) { + orderBusiness.updateOrderPayFailed(orderInfoList); + throw new ServiceException(ex.getMessage()); + }finally { + AccRedisUtils.unlockUpdateAccWalletBalance(orderInfo.getUserId()); } - - BigDecimal subsidyWalletBal = getWalletBalance(walletInfoList, AccWalletIdEnum.SUBSIDY); - BigDecimal personalWalletBal = getWalletBalance(walletInfoList, AccWalletIdEnum.WALLET); - BigDecimal totalWalletBal = subsidyWalletBal.add(personalWalletBal); - - if (totalWalletBal.compareTo(orderPayDTO.getOrderTotalAmount()) < 0) { - throw new ServiceException("钱包余额不足"); - } - for(OrderInfo orderInfo : orderInfoList) { - deductFromWallets(orderInfo, subsidyWalletBal); - } - } catch (Exception ex) { - OrderPayResultDTO orderPayResultDTO = new OrderPayResultDTO(); - orderPayResultDTO.setOrderIdList(orderInfoList.stream().map(OrderInfo::getOrderId).collect(Collectors.toList())); - orderPayResultDTO.setPayState(PayStateEnum.PAY_FAIL.getKey()); - orderPayResultDTO.setUpdateBy(SecurityUtils.getUsername()); - orderInfoMapper.updateOrderPayResult(orderPayResultDTO); - log.error("订单支付异常", ex); - throw new ServiceException("支付失败"); - } - OrderPayResultDTO orderPayResultDTO = new OrderPayResultDTO(); - orderPayResultDTO.setOrderIdList(orderInfoList.stream().map(OrderInfo::getOrderId).collect(Collectors.toList())); - orderPayResultDTO.setPayState(PayStateEnum.PAY_SUCC.getKey()); - orderPayResultDTO.setUpdateBy(SecurityUtils.getUsername()); - orderPayResultDTO.setOrderState(OrderStateEnum.PLACE.getKey()); - orderInfoMapper.updateOrderPayResult(orderPayResultDTO); - try { - DeviceMqPersonalUpdateMessageDTO bean = new DeviceMqPersonalUpdateMessageDTO().setUpdatePerson(Math.toIntExact(orderInfoList.get(0).getUserId()),"update"); - String jsonString = JacksonUtil.writeValueAsString(bean); - log.info("账户变动发送mq内容:{}", jsonString); - MqUtil.pushToTenantAllDevice(bean, LeMqConstant.Topic.DEVICE_UPDATE_PERSONAL_CONFIG_V4); - } catch (Exception e) { - log.error("发送MQ消息失败", e); } } - private BigDecimal getWalletBalance(List walletInfoList, AccWalletIdEnum walletIdEnum) { - return walletInfoList.stream() - .filter(walletInfo -> walletIdEnum.getKey().equals(walletInfo.getWalletId())) - .map(AccWalletInfo::getWalletBal) - .findFirst() - .orElse(BigDecimal.ZERO); - } - - private void deductFromWallets(OrderInfo orderInfo, BigDecimal subsidyWalletBal) { - Long orderNo = orderInfo.getOrderId(); - String deviceSn = orderInfo.getDeviceSn(); - if (orderInfo.getRealAmount().compareTo(subsidyWalletBal) <= 0) { - deductWalletBalance(orderInfo.getRealAmount(), orderInfo.getUserId(), AccWalletIdEnum.SUBSIDY, orderNo, deviceSn); - } else if (subsidyWalletBal.compareTo(BigDecimal.ZERO) > 0) { - deductWalletBalance(subsidyWalletBal, orderInfo.getUserId(), AccWalletIdEnum.SUBSIDY, orderNo, deviceSn); - BigDecimal remainAmount = orderInfo.getRealAmount().subtract(subsidyWalletBal); - deductWalletBalance(remainAmount, orderInfo.getUserId(), AccWalletIdEnum.WALLET, orderNo, deviceSn); - } else { - deductWalletBalance(orderInfo.getRealAmount(), orderInfo.getUserId(), AccWalletIdEnum.WALLET, orderNo, deviceSn); - } - } - - private void deductWalletBalance(BigDecimal amount, - Long userId, - AccWalletIdEnum walletIdEnum, - Long orderNo, - String deviceSn) { - WalletUpdateDTO walletUpdateDTO = new WalletUpdateDTO(); - walletUpdateDTO.setAmount(amount); - walletUpdateDTO.setUserId(userId); - walletUpdateDTO.setAccWalletIdEnum(walletIdEnum); - walletUpdateDTO.setAccTradeTypeEnum(AccTradeTypeEnum.CONSUME); - walletUpdateDTO.setPayChannelEnum(PayChannelEnum.ACC); - walletUpdateDTO.setPayTypeEnum(PayTypeEnum.MEAL_CARD); - walletUpdateDTO.setOrderNo(orderNo); - walletUpdateDTO.setDeviceSn(deviceSn); - accWalletInfoService.clearAccWalletBalance(walletUpdateDTO); - } - - private OrderPayDTO buildOrderPayDTO(List orderInfoList) { - OrderPayDTO orderPayDTO = new OrderPayDTO(); - BigDecimal totalAmount = orderInfoList.stream() - .map(OrderInfo::getRealAmount) - .reduce(BigDecimal.ZERO, BigDecimal::add); - orderPayDTO.setOrderTotalAmount(totalAmount); - orderPayDTO.setUserId(orderInfoList.get(0).getUserId()); - orderPayDTO.setOrderInfoList(orderInfoList); - return orderPayDTO; + @Override + public List orderRefundHistory(OrderRefundHistoryParam param) { + return orderInfoMapper.orderRefundHistory(param); } private void checkOrdersTotalAmount(List orderInfoList ,BigDecimal totalAmountParam) { @@ -345,7 +286,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService @Override @Transactional(rollbackFor = {Exception.class}) - public void refund(Long orderId) { + public void refund(Long orderId, String operationUser) { if(Objects.isNull(orderId) || orderId <= 0) { throw new ServiceException("订单ID不能为空"); } @@ -388,7 +329,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService refundOrderInfo.setRefundAmount(refundAmount); refundOrderInfo.setOrderRefundState(OrderRefundStateEnum.FINISH.getKey()); refundOrderInfo.setOrderState(OrderStateEnum.CANCEL.getKey()); - refundOrderInfo.setUpdateBy(SecurityUtils.getUsername()); + refundOrderInfo.setUpdateBy(StringUtils.isBlank(operationUser) ? SecurityUtils.getUsername() : operationUser); refundOrderInfo.setUpdateTime(DateUtils.getNowDate()); orderInfoMapper.updateOrderInfo(refundOrderInfo); OrderDetail orderDetailQuery = new OrderDetail(); @@ -398,6 +339,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService orderDetail.setRefundAmount(orderDetail.getRealAmount()); orderDetail.setRefundNum(orderDetail.getQuantity()); orderDetail.setDetailState(OrderDetailStateEnum.REFUNDED.getKey()); + orderDetail.setUpdateBy(StringUtils.isBlank(operationUser) ? SecurityUtils.getUsername() : operationUser); orderDetailService.updateOrderDetail(orderDetail); } orderBusiness.addMenuDishSupplyNum(orderDetailList); @@ -414,7 +356,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService refundOrderInfo.setOrderId(orderId); refundOrderInfo.setOrderRefundState(OrderRefundStateEnum.FINISH.getKey()); refundOrderInfo.setOrderState(OrderStateEnum.CANCEL.getKey()); - refundOrderInfo.setUpdateBy(SecurityUtils.getUsername()); + refundOrderInfo.setUpdateBy(StringUtils.isBlank(operationUser) ? SecurityUtils.getUsername() : operationUser); refundOrderInfo.setUpdateTime(DateUtils.getNowDate()); orderInfoMapper.updateOrderInfo(refundOrderInfo); } diff --git a/bonus-modules/bonus-smart-canteen/src/main/resources/mapper/order/OrderInfoMapper.xml b/bonus-modules/bonus-smart-canteen/src/main/resources/mapper/order/OrderInfoMapper.xml index 6d6da19..7dbb650 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/resources/mapper/order/OrderInfoMapper.xml +++ b/bonus-modules/bonus-smart-canteen/src/main/resources/mapper/order/OrderInfoMapper.xml @@ -41,6 +41,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + @@ -55,15 +57,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" oi.refund_amount, oi.order_time, oi.order_type, oi.order_state, oi.order_refund_state, oi.deduction_type, oi.pay_time, oi.pay_type, oi.pay_channel, oi.pay_state, oi.pay_param, oi.delivery_amount, oi.packing_amount, oi.delivery_type, oi.comment_state, oi.remark, - oi.create_by, oi.create_time, oi.update_by, oi.update_time + di.device_name, su.nick_name, oi.create_by, oi.create_time, oi.update_by, oi.update_time from order_info oi left join alloc_canteen ac on ac.canteen_id = oi.canteen_id left join alloc_stall ast on ast.stall_id = oi.stall_id + left join sys_user su on oi.user_id = su.user_id + left join device_info di on oi.device_sn = di.device_sn + select su.user_id, + su.nick_name, + oi.order_id, + oi.real_amount, + oi.pay_time, + oi.pay_type, + + at2.actual_amount, + at2.trade_type, + at2.trade_time, + at2.update_by + from acc_trade at2 + left join order_info oi on oi.order_id = at2.order_no + left join sys_user su on at2.user_id = su.user_id + where at2.trade_type = 130 and at2.pay_state = 3 + + and (su.nick_name like CONCAT('%',#{param.searchValue},'%') + or su.user_id like CONCAT('%',#{param.searchValue},'%') + ) + + + and su.dept_id in + + #{deptId} + + + + and at2.trade_time = ]]> #{param.startDateTime} + + + and at2.trade_time #{param.endDateTime} + + + and oi.order_id =#{param.orderId} + + order by at2.trade_time desc + + \ No newline at end of file