diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/menu/service/impl/MenuRecipeDishesServiceImpl.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/menu/service/impl/MenuRecipeDishesServiceImpl.java index 4409d49..2efe242 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/menu/service/impl/MenuRecipeDishesServiceImpl.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/menu/service/impl/MenuRecipeDishesServiceImpl.java @@ -16,6 +16,7 @@ import com.bonus.canteen.core.menu.mapper.MenuRecipeDetailMapper; import com.bonus.common.core.exception.ServiceException; import com.bonus.common.core.utils.DateUtils; import com.bonus.common.houqin.constant.GlobalConstants; +import com.bonus.common.houqin.utils.JacksonUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -107,6 +108,7 @@ public class MenuRecipeDishesServiceImpl extends ServiceImpl orderDetailList) { + log.info("订单扣减库存入参:{}", JacksonUtil.writeValueAsString(orderDetailList)); for(OrderDetail orderDetail : orderDetailList) { if(OrderDetailTypeEnum.KEYAMOUNT.getKey().equals(orderDetail.getDetailType())) { continue; @@ -86,13 +87,14 @@ public class OrderBusiness { } public void addMenuDishSupplyNum(List orderDetailList) { + log.info("订单新增库存入参:{}", JacksonUtil.writeValueAsString(orderDetailList)); for(OrderDetail orderDetail : orderDetailList) { if(OrderDetailTypeEnum.KEYAMOUNT.getKey().equals(orderDetail.getDetailType())) { continue; } MenuRecipeDishes menuRecipeDishes = new MenuRecipeDishes(); ObjectUtils.setAllFieldsToNull(menuRecipeDishes); - menuRecipeDishes.setDetailId(orderDetail.getDetailId()); + menuRecipeDishes.setDetailId(orderDetail.getMenuDetailId()); menuRecipeDishes.setDishesId(orderDetail.getGoodsId()); menuRecipeDishesService.addMenuRecipeDishesSupplyNum(menuRecipeDishes, orderDetail.getQuantity()); } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/constants/OrderStateEnum.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/constants/OrderStateEnum.java index 2a4cf74..d4c940c 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/constants/OrderStateEnum.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/constants/OrderStateEnum.java @@ -1,5 +1,7 @@ package com.bonus.canteen.core.order.constants; +import org.apache.commons.lang3.StringUtils; + public enum OrderStateEnum { PLACE(1, "已下单"), FINISH(2, "已完成"), @@ -21,4 +23,13 @@ public enum OrderStateEnum { public String getDesc() { return this.desc; } + + public static String getDescByKey(Integer key) { + for (OrderStateEnum orderState : OrderStateEnum.values()) { + if (orderState.getKey().equals(key)) { + return orderState.getDesc(); + } + } + return StringUtils.EMPTY; + } } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mq/OrderMqListenerTimeout.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mq/OrderMqListenerTimeout.java new file mode 100644 index 0000000..8f50539 --- /dev/null +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mq/OrderMqListenerTimeout.java @@ -0,0 +1,41 @@ +package com.bonus.canteen.core.order.mq; + +import com.bonus.canteen.core.common.utils.MqPayload; +import com.bonus.canteen.core.order.mq.bo.OrderCancelBO; +import com.bonus.canteen.core.order.service.IOrderInfoService; +import com.bonus.common.houqin.mq.MQListener; +import com.bonus.common.houqin.mq.MQMessageListener; +import com.bonus.common.houqin.utils.JacksonUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; + +import java.util.Objects; + +@MQMessageListener( + group = "order-order-v3-async-timeout", + topic = "order", + tag = "order-v3-async-timeout" +) +public class OrderMqListenerTimeout implements MQListener> { + private static final Logger log = LoggerFactory.getLogger(OrderMqListenerTimeout.class); + + @Autowired + @Lazy + private IOrderInfoService orderInfoService; + + public void onMessage(MqPayload payload) { + log.info("[订单超时MQ]收到消息 {}", payload); + OrderCancelBO payloadData = JacksonUtil.readValue(payload.getData(), OrderCancelBO.class); + if(Objects.nonNull(payloadData)) { + try { + this.orderInfoService.timeOutCancel(payloadData.getOrderId(), "system"); + }catch (Exception ex) { + log.error("[订单超时MQ]处理异常", ex); + } + }else { + log.error("[订单超时MQ]收到消息为空"); + } + } +} diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mq/bo/OrderCancelBO.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mq/bo/OrderCancelBO.java new file mode 100644 index 0000000..0b0e300 --- /dev/null +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mq/bo/OrderCancelBO.java @@ -0,0 +1,10 @@ +package com.bonus.canteen.core.order.mq.bo; + +import lombok.Data; + +@Data +public class OrderCancelBO { + private Long orderId; + private Long merchantId; + private String traceId; +} diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mq/utils/OrderMQUtils.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mq/utils/OrderMQUtils.java new file mode 100644 index 0000000..556c3f8 --- /dev/null +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/mq/utils/OrderMQUtils.java @@ -0,0 +1,29 @@ +package com.bonus.canteen.core.order.mq.utils; + +import cn.hutool.core.lang.UUID; +import com.bonus.canteen.core.common.utils.MqUtil; +import com.bonus.canteen.core.order.mq.bo.OrderCancelBO; +import com.bonus.common.houqin.constant.GlobalConstants; +import com.bonus.common.houqin.mq.constant.LeMqConstant; +import com.bonus.common.houqin.utils.JacksonUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.LocalDateTime; + +public class OrderMQUtils { + private static final Logger log = LoggerFactory.getLogger(OrderMQUtils.class); + public static LocalDateTime orderTimeoutByOrderId(Long orderId, int delaySecond) { + log.info("[订单MQ]发送未支付订单异步支付超时通知, 订单ID: {}", orderId); + try { + OrderCancelBO orderCancelPO = new OrderCancelBO(); + orderCancelPO.setOrderId(orderId); + orderCancelPO.setMerchantId(GlobalConstants.TENANT_ID); + orderCancelPO.setTraceId(UUID.fastUUID().toString()); + MqUtil.sendDelay(JacksonUtil.writeValueAsString(orderCancelPO), LeMqConstant.Topic.ORDER_V3_ASYNC_TIMEOUT, delaySecond * 1000); + }catch (Exception ex) { + log.error("[订单MQ]发送未支付订单超时通知失败, 订单ID: {}", orderId, ex); + } + return LocalDateTime.now().plusSeconds(delaySecond); + } +} 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 456ce93..923444b 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 @@ -71,6 +71,6 @@ public interface IOrderInfoService public void refund(Long orderId, String operationUser); public void pay(Long orderId); List orderRefundHistory(OrderRefundHistoryParam param); - public void writeOffOrderByOrderIds(OrderWriteOffParam param); + public void timeOutCancel(Long orderId, String operationUser); } 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 276d28c..48d6bc2 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 @@ -24,6 +24,7 @@ import com.bonus.canteen.core.order.constants.OrderStateEnum; 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.mq.utils.OrderMQUtils; import com.bonus.canteen.core.order.service.IOrderDetailService; import com.bonus.canteen.core.order.service.IOrderInfoService; import com.bonus.canteen.core.pay.constants.PayChannelEnum; @@ -62,6 +63,7 @@ import java.util.stream.Collectors; public class OrderInfoServiceImpl implements IOrderInfoService { private static final Logger log = LoggerFactory.getLogger(OrderInfoServiceImpl.class); + private static final String ORDER_REFUND_REDIS_KEY = "sc:order_refund_orderId_%s"; @Autowired private OrderInfoMapper orderInfoMapper; @Autowired @@ -127,7 +129,6 @@ public class OrderInfoServiceImpl implements IOrderInfoService List orderDetailList = orderDetailService.selectOrderDetailList(orderDetail); order.setOrderDetailList(orderDetailList); order.setPhoneNumber(SM4EncryptUtils.sm4Decrypt(order.getPhoneNumber())); - order.setMealtimeName(AllocMealtimeTypeEnum.getDescByKey(order.getMealtimeType())); }); } return orderInfoList; @@ -152,6 +153,9 @@ public class OrderInfoServiceImpl implements IOrderInfoService orderBusiness.orderPay(orderInfoList); }catch (Exception ex) { orderBusiness.updateOrderPayFailed(orderInfoList); + for(OrderInfo orderInfo : orderInfoList) { + OrderMQUtils.orderTimeoutByOrderId(orderInfo.getOrderId(), 60 * 10); + } throw new ServiceException(ex.getMessage(), 500001); }finally { AccRedisUtils.unlockUpdateAccWalletBalance(orderAddParam.getUserId()); @@ -364,7 +368,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService if(Objects.isNull(orderInfo)) { throw new ServiceException("订单不存在"); } - String refundKey = String.format("sc:order_refund_orderId_%s", orderId); + String refundKey = String.format(ORDER_REFUND_REDIS_KEY, orderId); if (!RedisUtil.setNx(refundKey, 1, 2)) { log.info("退单处理中:{}", refundKey); throw new ServiceException("退单处理中"); @@ -378,6 +382,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService // if(orderInfo.getOrderState().equals(OrderStateEnum.FINISH.getKey())) { // throw new ServiceException("订单已核销"); // } + List orderDetailList = null; if(PayStateEnum.PAY_SUCC.getKey().equals(orderInfo.getPayState())) { List accTradeList = accTradeService.queryTradeAndWallerInfoByOrderNo (String.valueOf(orderId), AccTradeTypeEnum.CONSUME); @@ -411,7 +416,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService orderInfoMapper.updateOrderInfo(refundOrderInfo); OrderDetail orderDetailQuery = new OrderDetail(); orderDetailQuery.setOrderId(orderId); - List orderDetailList = orderDetailService.selectOrderDetailList(orderDetailQuery); + orderDetailList = orderDetailService.selectOrderDetailList(orderDetailQuery); for(OrderDetail orderDetail : orderDetailList) { orderDetail.setRefundAmount(orderDetail.getRealAmount()); orderDetail.setRefundNum(orderDetail.getQuantity()); @@ -419,7 +424,6 @@ public class OrderInfoServiceImpl implements IOrderInfoService orderDetail.setUpdateBy(StringUtils.isBlank(operationUser) ? SecurityUtils.getUsername() : operationUser); orderDetailService.updateOrderDetail(orderDetail); } - orderBusiness.addMenuDishSupplyNum(orderDetailList); try { DeviceMqPersonalUpdateMessageDTO bean = new DeviceMqPersonalUpdateMessageDTO().setUpdatePerson(Math.toIntExact(orderInfo.getUserId()),"update"); String jsonString = JacksonUtil.writeValueAsString(bean); @@ -436,6 +440,44 @@ public class OrderInfoServiceImpl implements IOrderInfoService refundOrderInfo.setUpdateBy(StringUtils.isBlank(operationUser) ? SecurityUtils.getUsername() : operationUser); refundOrderInfo.setUpdateTime(DateUtils.getNowDate()); orderInfoMapper.updateOrderInfo(refundOrderInfo); + OrderDetail orderDetailQuery = new OrderDetail(); + orderDetailQuery.setOrderId(orderId); + orderDetailList = orderDetailService.selectOrderDetailList(orderDetailQuery); + } + if (orderDetailList != null) { + orderBusiness.addMenuDishSupplyNum(orderDetailList); + } + } + @Override + @Transactional(rollbackFor = {Exception.class}) + public void timeOutCancel(Long orderId, String operationUser) { + log.info("订单超时取消:{}", orderId); + if(Objects.isNull(orderId) || orderId <= 0) { + throw new ServiceException("订单ID不能为空"); + } + OrderInfo orderInfo = selectOrderInfoByOrderId(orderId); + if(Objects.isNull(orderInfo)) { + throw new ServiceException("订单不存在"); + } + String refundKey = String.format(ORDER_REFUND_REDIS_KEY, orderId); + if (!RedisUtil.setNx(refundKey, 1, 2)) { + log.info("退单处理中:{}", refundKey); + throw new ServiceException("退单处理中"); + } + if(orderInfo.getOrderState().equals(OrderStateEnum.WAIT_PLACE.getKey())) { + OrderInfo refundOrderInfo = new OrderInfo(); + refundOrderInfo.setOrderId(orderId); + refundOrderInfo.setOrderRefundState(OrderRefundStateEnum.FINISH.getKey()); + refundOrderInfo.setOrderState(OrderStateEnum.CANCEL.getKey()); + refundOrderInfo.setUpdateBy(StringUtils.isBlank(operationUser) ? SecurityUtils.getUsername() : operationUser); + refundOrderInfo.setUpdateTime(DateUtils.getNowDate()); + orderInfoMapper.updateOrderInfo(refundOrderInfo); + OrderDetail orderDetailQuery = new OrderDetail(); + orderDetailQuery.setOrderId(orderId); + List orderDetailList = orderDetailService.selectOrderDetailList(orderDetailQuery); + orderBusiness.addMenuDishSupplyNum(orderDetailList); + }else { + log.info("[MQ超时订单]订单状态:{}", OrderStateEnum.getDescByKey(orderInfo.getOrderState())); } } } diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/impl/OrderShoppingCartServiceImpl.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/impl/OrderShoppingCartServiceImpl.java index 665bd19..313aa59 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/impl/OrderShoppingCartServiceImpl.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/order/service/impl/OrderShoppingCartServiceImpl.java @@ -1,9 +1,6 @@ package com.bonus.canteen.core.order.service.impl; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; import cn.hutool.core.collection.CollUtil; @@ -21,6 +18,8 @@ import com.bonus.canteen.core.order.service.IOrderShoppingCartService; import com.bonus.common.core.utils.DateUtils; import com.bonus.common.houqin.utils.id.Id; import com.bonus.common.security.utils.SecurityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -34,6 +33,8 @@ import org.springframework.stereotype.Service; @Service public class OrderShoppingCartServiceImpl implements IOrderShoppingCartService { + private static final Logger log = LoggerFactory.getLogger(OrderShoppingCartServiceImpl.class); + @Autowired private OrderShoppingCartMapper orderShoppingCartMapper; @Autowired @@ -86,7 +87,12 @@ public class OrderShoppingCartServiceImpl implements IOrderShoppingCartService .findFirst().orElse(null); menuDishCheckDTO.setApplyDate(orderDateStr); - Map> menuRecipeDishMap = menuModule.getMenuRecipeDish(menuDishCheckDTO); + Map> menuRecipeDishMap = new HashMap<>(); + try{ + menuRecipeDishMap = menuModule.getMenuRecipeDish(menuDishCheckDTO); + }catch (Exception ex) { + log.info("菜单数据获取失败:" + ex.getMessage()); + } for (OrderShoppingCart shoppingCart : carts) { OrderShoppingCartVO shoppingCartVO = convertToOrderShoppingCartVO(shoppingCart, menuRecipeDishMap);