This commit is contained in:
gaowdong 2025-04-28 10:32:33 +08:00
parent 9b2045952e
commit 81f77eda76
17 changed files with 703 additions and 308 deletions

View File

@ -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<AccWalletInfo> 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<AccWalletInfo> selectAccWalletInfoByUserId(Long userId) {
return accWalletInfoMapper.selectAccWalletInfoByUserId(userId);
}
public AccWalletInfo selectAccWalletInfoByUserIdAndWalletId(Long userId, Integer walletId) {
return accWalletInfoMapper.selectAccWalletInfoByUserIdAndWalletId(userId, walletId);
}
}

View File

@ -17,4 +17,6 @@ public class WalletUpdateDTO {
private PayTypeEnum payTypeEnum;
private Long orderNo;
private String deviceSn;
private boolean isBatch = false;
private String operationUser;
}

View File

@ -15,4 +15,5 @@ public class WalletBalanceOperation {
private Integer payType;
private Long orderNo;
private String deviceSn;
private String operationUser;
}

View File

@ -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);
}

View File

@ -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<AccWalletInfo> 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;
}
}

View File

@ -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<OrderInfo> orderPlaceHandler(List<OrderInfo> 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<OrderInfo> 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<OrderInfo> orderInfoList) {
OrderPayDTO orderPayDTO = buildOrderPayDTO(orderInfoList);
try {
List<AccWalletInfo> 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<OrderInfo> 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<AccWalletInfo> walletInfoList, AccWalletIdEnum walletIdEnum) {
return walletInfoList.stream()
.filter(walletInfo -> walletIdEnum.getKey().equals(walletInfo.getWalletId()))
.map(AccWalletInfo::getWalletBal)
.findFirst()
.orElse(BigDecimal.ZERO);
}
}

View File

@ -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<OrderInfo> list = orderInfoService.selectOrderInfoList(orderQueryParam);
return getDataTable(list);
}
@PostMapping("/web/refund/list")
@ResponseBody
public TableDataInfo webRefundList(@RequestBody @Valid OrderRefundHistoryParam param)
{
startPage();
List<OrderRefundHistoryVO> 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<OrderInfo> 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();
}

View File

@ -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<OrderDetail> orderDetailList;
public List<OrderInfo> of(OrderAddParam param) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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<Long> 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<Long> canteenIdList;
/** 档口id */
private Long stallId;
private List<Long> stallIdList;
/** 餐次类型 1-早餐 2-午餐 3-晚餐 4-下午茶 5-夜宵 */
private Integer mealtimeType;
private List<Integer> 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<Integer> orderTypeList;
/** 订单状态 1 已下单 2 已完成 3 已取消 */
@Excel(name = "订单状态 1 已下单 2 已完成 3 已取消")
private Integer orderState;
private List<Integer> 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<Integer> 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);

View File

@ -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<Long> 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);
}
}

View File

@ -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<Long> orderIds);
public List<OrderRefundHistoryVO> orderRefundHistory(@Param("param") OrderRefundHistoryParam param);
}

View File

@ -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<OrderRefundHistoryVO> orderRefundHistory(@Param("param") OrderRefundHistoryParam param);
}

View File

@ -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<OrderInfo> canteenOrderInfoList = new OrderInfo().of(orderAddParam);
checkOrdersTotalAmount(canteenOrderInfoList, orderAddParam.getRealAmount());
List<OrderInfo> 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<OrderInfo> canteenOrderInfoList = new OrderInfo().of(orderAddParam);
checkOrdersTotalAmount(canteenOrderInfoList, orderAddParam.getRealAmount());
List<OrderInfo> 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<OrderInfo> canteenOrderInfoList = new ShopOrderAddParam().of(orderAddParam);
List<OrderInfo> 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<OrderInfo> orderInfoList = new ArrayList<>();
orderInfoList.add(orderInfo);
orderPay(orderInfoList);
}
}
private void orderPay(List<OrderInfo> orderInfoList) {
OrderPayDTO orderPayDTO = buildOrderPayDTO(orderInfoList);
try {
List<AccWalletInfo> 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);
}
AccRedisUtils.lockUpdateAccWalletBalance(orderInfo.getUserId());
orderBusiness.orderPay(orderInfoList);
}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("支付失败");
orderBusiness.updateOrderPayFailed(orderInfoList);
throw new ServiceException(ex.getMessage());
}finally {
AccRedisUtils.unlockUpdateAccWalletBalance(orderInfo.getUserId());
}
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<AccWalletInfo> 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<OrderInfo> 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<OrderRefundHistoryVO> orderRefundHistory(OrderRefundHistoryParam param) {
return orderInfoMapper.orderRefundHistory(param);
}
private void checkOrdersTotalAmount(List<OrderInfo> 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);
}

View File

@ -41,6 +41,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="deliveryType" column="delivery_type" />
<result property="commentState" column="comment_state" />
<result property="remark" column="remark" />
<result property="deviceName" column="device_name" />
<result property="nickName" column="nick_name" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
@ -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
</sql>
<select id="selectOrderInfoList" parameterType="com.bonus.canteen.core.order.domain.param.OrderQueryParam" resultMap="OrderInfoResult">
<include refid="selectOrderInfoVo"/>
<where>
<if test="orderId != null"> and oi.order_id = #{orderId}</if>
<if test="deviceOrderId != null and deviceOrderId != ''"> and oi.device_order_id = #{deviceOrderId}</if>
<if test="deviceSn != null and deviceSn != ''"> and oi.device_sn = #{deviceSn}</if>
<if test="deviceNum != null and deviceNum != ''"> and oi.device_num = #{deviceNum}</if>
@ -72,22 +77,64 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sourceType != null "> and oi.source_type = #{sourceType}</if>
<if test="isOnline != null "> and oi.is_online = #{isOnline}</if>
<if test="canteenId != null "> and oi.canteen_id = #{canteenId}</if>
<if test="canteenIdList != null and canteenIdList.size >0">
and oi.canteen_id in
<foreach collection="canteenIdList" item="canteenId" open="(" separator="," close=")">
#{canteenId}
</foreach>
</if>
<if test="stallId != null "> and oi.stall_id = #{stallId}</if>
<if test="stallIdList != null and stallIdList.size >0">
and oi.stall_id in
<foreach collection="stallIdList" item="stallId" open="(" separator="," close=")">
#{stallId}
</foreach>
</if>
<if test="mealtimeType != null "> and oi.mealtime_type = #{mealtimeType}</if>
<if test="mealtimeTypeList != null and mealtimeTypeList.size >0">
and oi.mealtime_type in
<foreach collection="mealtimeTypeList" item="mealtimeType" open="(" separator="," close=")">
#{mealtimeType}
</foreach>
</if>
<if test="orderDate != null "> and oi.order_date = #{orderDate}</if>
<if test="orderTime != null "> and oi.order_time = #{orderTime}</if>
<if test="orderType != null "> and oi.order_type = #{orderType}</if>
<if test="orderTypeList != null and orderTypeList.size >0">
and oi.order_type in
<foreach collection="orderTypeList" item="orderType" open="(" separator="," close=")">
#{orderType}
</foreach>
</if>
<if test="orderState != null "> and oi.order_state = #{orderState}</if>
<if test="orderStateList != null and orderStateList.size >0">
and oi.order_state in
<foreach collection="orderStateList" item="orderState" open="(" separator="," close=")">
#{orderState}
</foreach>
</if>
<if test="orderRefundState != null "> and oi.order_refund_state = #{orderRefundState}</if>
<if test="deductionType != null "> and oi.deduction_type = #{deductionType}</if>
<if test="payTime != null "> and oi.pay_time = #{payTime}</if>
<if test="payType != null "> and oi.pay_type = #{payType}</if>
<if test="payChannel != null "> and oi.pay_channel = #{payChannel}</if>
<if test="payState != null "> and oi.pay_state = #{payState}</if>
<if test="payStateList != null and payStateList.size >0">
and oi.pay_state in
<foreach collection="payStateList" item="payState" open="(" separator="," close=")">
#{payState}
</foreach>
</if>
<if test="deptIdList != null and deptIdList.size >0">
and su.dept_id in
<foreach collection="deptIdList" item="deptId" open="(" separator="," close=")">
#{deptId}
</foreach>
</if>
<if test="commentState != null "> and oi.comment_state = #{commentState}</if>
<if test="startDateTime != null "> and oi.create_time <![CDATA[ >= ]]> #{startDateTime}</if>
<if test="endDateTime != null "> and oi.create_time <![CDATA[ <= ]]> #{endDateTime}</if>
<if test="searchValue != null ">
<if test="searchValue != null and searchValue != ''">
and (ac.canteen_name like concat('%', #{searchValue}, '%')
or ast.stall_name like concat('%', #{searchValue}, '%')
or EXISTS (select 1 from order_detail od
@ -321,12 +368,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<update id="updateOrderPayResult">
update order_info set
pay_time = now(),
<if test="param.payAmount != null">account_pay_amount = #{param.payAmount},</if>
<if test="param.payState != null">pay_state = #{param.payState},</if>
<if test="param.updateBy != null and param.updateBy != ''">update_by = #{param.updateBy},</if>
<if test="param.orderState != null">order_state = #{param.orderState},</if>
update_time = now()
<if test="param.payTime != null">pay_time = #{param.payTime},</if>
<if test="param.updateTime != null">update_time = #{param.updateTime}</if>
where order_id in
<foreach item="orderId" collection="param.orderIdList" open="(" separator="," close=")">
#{orderId}
@ -344,4 +391,43 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</delete>
<select id="orderRefundHistory" resultType="com.bonus.canteen.core.order.domain.OrderRefundHistoryVO">
select su.user_id,
su.nick_name,
oi.order_id,
oi.real_amount,
oi.pay_time,
oi.pay_type,
<!-- at2.trade_id,-->
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
<if test="param.searchValue != null and param.searchValue != ''">
and (su.nick_name like CONCAT('%',#{param.searchValue},'%')
or su.user_id like CONCAT('%',#{param.searchValue},'%')
)
</if>
<if test="param.deptIdList != null and param.deptIdList.size >0">
and su.dept_id in
<foreach collection="param.deptIdList" item="deptId" open="(" separator="," close=")">
#{deptId}
</foreach>
</if>
<if test="param.startDateTime != null ">
and at2.trade_time <![CDATA[ >= ]]> #{param.startDateTime}
</if>
<if test="param.endDateTime != null ">
and at2.trade_time <![CDATA[ <= ]]> #{param.endDateTime}
</if>
<if test="param.orderId != null">
and oi.order_id =#{param.orderId}
</if>
order by at2.trade_time desc
</select>
</mapper>