caotao 1 день тому
батько
коміт
eacffd9dcf
11 змінених файлів з 144 додано та 3 видалено
  1. 3 1
      ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/enums/TradeMqConstants.java
  2. 2 0
      ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/enums/TradeOrderOperateTypeEnum.java
  3. 17 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/framework/aop/TradeOrderLogAspect.java
  4. 31 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/framework/mq/TradeMqConfig.java
  5. 43 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/framework/mq/TradeMqReceiver.java
  6. 13 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/framework/mq/TradePublishUtils.java
  7. 1 1
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/bo/TradeOrderLogCreateReqBO.java
  8. 6 1
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/impl/TradeOrderLogServiceImpl.java
  9. 12 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/otc/impl/OtcTradeOrderServiceImpl.java
  10. 5 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/pay/TradeOrderPayService.java
  11. 11 0
      ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/pay/impl/TradeOrderPayServiceImpl.java

+ 3 - 1
ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/enums/TradeMqConstants.java

@@ -45,7 +45,9 @@ public class TradeMqConstants {
     public static final String DL_EXCHANGE_INSURANCE ="dl_exchange_insurance";
 
     public static final String DL_INSURANCE_QUERY ="dl.trade.insurance.query";
-
+    // 留位订单自动取消
+    public static final String DL_ROUTE_HOLD_ORDER_CANCEL = "dl.trade.order.hold.cancel";
+    public static final String DELAY_ROUTE_HOLD_ORDER_CANCEL = "delay.trade.order.hold.cancel";
     //********以下是才用插件方式********//
     /**
      * 交易延迟消息交换机

+ 2 - 0
ship-module-trade/ship-module-trade-api/src/main/java/com/yc/ship/module/trade/enums/TradeOrderOperateTypeEnum.java

@@ -15,6 +15,7 @@ public enum TradeOrderOperateTypeEnum {
     ORDER_CREATE(1, "创建订单,结果:{result}"),
     SUPPLIER_ORDER_CREATE(2, "调用供应商系统创建订单,供应商:{supplierName},服务类:{serviceName},平台供应商订单ID:{platSupplierOrderId},结果:{result}"),
     PAY_TIMEOUT_SYSTEM_CANCEL(3, "支付超时系统自动取消"),
+    HOLD_ORDER_TIMEOUT_SYSTEM_CANCEL(36, "留位超时系统自动取消"),  // ← 新增这行
     MANUL_CANCEL(4, "主动取消订单"),
     ORDER_PAY(5, "订单支付,支付方式:{payType},金额:{payAmount}"),
     SUPPLIER_ORDER_PAY(6, "调用供应商系统支付,供应商:{supplierName},平台供应商订单ID:{platSupplierOrderId},结果:{result}"),
@@ -46,6 +47,7 @@ public enum TradeOrderOperateTypeEnum {
     ORDER_DEPOSI_PAY(31, "订单定金支付,支付方式:{payType},金额:{payAmount}"),
     ORDER_BC_PAY(33, "订单补差价支付,支付方式:{payType},金额:{payAmount}"),
     ORDER_AUDIT_LOG(34, "订单进入审核"),
+    ORDER_REMARK_UPDATE(35, "修改订单备注,修改记录:{content},结果:{result}"),
     ;
 
     /**

+ 17 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/framework/aop/TradeOrderLogAspect.java

@@ -60,6 +60,10 @@ public class TradeOrderLogAspect {
      * 拓展参数 Map,用于格式化操作内容
      */
     private static final ThreadLocal<Map<String, Object>> EXTS = new ThreadLocal<>();
+    /**
+     * 租户编号(可选,MQ 线程等场景使用)
+     */
+    private static final ThreadLocal<Long> TENANT_ID = new ThreadLocal<>();
 
     @Resource
     private TradeOrderLogService orderLogService;
@@ -100,6 +104,10 @@ public class TradeOrderLogAspect {
                     .setUserType(getUserType())
                     .setOrderId(orderId).setBeforeStatus(beforeStatus).setAfterStatus(afterStatus)
                     .setOperateType(orderLog.operateType().getType()).setContent(content);
+            Long tenantId = TENANT_ID.get();
+            if (tenantId != null) {
+                createBO.setTenantId(tenantId);
+            }
             orderLogService.createOrderLog(createBO);
         } catch (Exception ex) {
             log.error("[doAfterReturning][orderLog({}) 订单日志错误]", toJsonString(orderLog), ex);
@@ -153,6 +161,14 @@ public class TradeOrderLogAspect {
         USER_TYPE.set(userType);
     }
 
+    public static void setTenantId(Long tenantId) {
+        TENANT_ID.set(tenantId);
+    }
+
+    public static void clearTenantId() {
+        TENANT_ID.remove();
+    }
+
     private static void clear() {
         USER_ID.remove();
         USER_TYPE.remove();
@@ -160,6 +176,7 @@ public class TradeOrderLogAspect {
         BEFORE_STATUS.remove();
         AFTER_STATUS.remove();
         EXTS.remove();
+        TENANT_ID.remove();
     }
 
 }

+ 31 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/framework/mq/TradeMqConfig.java

@@ -54,6 +54,8 @@ public class TradeMqConfig {
     public static final String DL_QUEUE_INSURANCE_QUERY ="dl_queue_insurance_query";
 
     public static final String DELAY_PLUGIN_QUEUE_ORDER_PAY ="delay_plugin_queue_order_pay";
+    public static final String DL_QUEUE_HOLD_ORDER_CANCEL = "dl_queue_hold_order_cancel";
+    public static final String DELAY_QUEUE_HOLD_ORDER_CANCEL = "delay_queue_hold_order_cancel";
 
 
     @Bean
@@ -246,6 +248,35 @@ public class TradeMqConfig {
                 .with(DELAY_ROUTE_ORDER_CONFIRM);
     }
 
+    //==============留位订单自动取消延迟队列===========
+    @Bean(name = "holdOrderCancelDLQueue")
+    public Queue holdOrderCancelDLQueue(){
+        return new Queue(DL_QUEUE_HOLD_ORDER_CANCEL);
+    }
+
+    @Bean
+    Binding bindHoldOrderCancelDLQueue(@Qualifier("holdOrderCancelDLQueue") Queue queue,
+                                       @Qualifier("tradeDeadLetterExchange") TopicExchange exchange) {
+        return BindingBuilder.bind(queue).to(exchange).with(DL_ROUTE_HOLD_ORDER_CANCEL);
+    }
+
+    @Bean(name = "holdOrderCancelDelayQueue")
+    public Queue holdOrderCancelDelayQueue(){
+        return QueueBuilder.durable(DELAY_QUEUE_HOLD_ORDER_CANCEL)
+                // 配置到期后转发的交换
+                .withArgument("x-dead-letter-exchange", DL_EXCHANGE_ORDER)
+                // 配置到期后转发的路由键
+                .withArgument("x-dead-letter-routing-key", DL_ROUTE_HOLD_ORDER_CANCEL)
+                .build();
+    }
+
+    @Bean
+    public Binding bindHoldOrderCancelDelay(@Qualifier("holdOrderCancelDelayQueue") Queue queue,
+                                            @Qualifier("tradeOrderExchange") TopicExchange exchange) {
+        return BindingBuilder.bind(queue).to(exchange)
+                .with(DELAY_ROUTE_HOLD_ORDER_CANCEL);
+    }
+
 
 
     @Bean(name = "orderCheckDLQueue")

+ 43 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/framework/mq/TradeMqReceiver.java

@@ -2,13 +2,17 @@ package com.yc.ship.module.trade.framework.mq;
 
 
 import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.rabbitmq.client.Channel;
 import com.yc.ship.framework.common.pojo.CommonResult;
 import com.yc.ship.framework.tenant.core.aop.TenantIgnore;
+import com.yc.ship.framework.tenant.core.context.TenantContextHolder;
 import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderDO;
 import com.yc.ship.module.trade.dal.mysql.insurance.InsuranceMapper;
+import com.yc.ship.module.trade.enums.TradeOrderStatusEnum;
+import com.yc.ship.module.trade.framework.aop.TradeOrderLogAspect;
 import com.yc.ship.module.trade.service.insurance.InsuranceService;
 import com.yc.ship.module.trade.service.order.TradeOrderBizService;
 import com.yc.ship.module.trade.service.order.TradeOrderRepositoryService;
@@ -250,6 +254,45 @@ public class TradeMqReceiver {
         }
     }
 
+    /**
+     * 留位订单自动取消延迟消息处理
+     * @param data 订单ID
+     * @param message
+     * @param channel
+     * @throws IOException
+     */
+    @RabbitListener(queues = TradeMqConfig.DL_QUEUE_HOLD_ORDER_CANCEL, concurrency = "2")
+    @TenantIgnore
+    public void processHoldOrderCancelDelay(String data, Message message, Channel channel) throws IOException {
+        log.info("收到留位订单自动取消延迟消息:orderId={}", data);
+        try {
+            Long orderId = Long.parseLong(data);
+            TradeOrderDO tradeOrderDO = tradeOrderRepositoryService.getById(orderId);
+
+            // 订单不存在,直接确认消息
+            if (tradeOrderDO == null) {
+                log.warn("留位订单自动取消:订单不存在,orderId={}", orderId);
+                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+                return;
+            }
+
+            // 只有留位状态的订单才自动取消
+            if (ObjectUtil.equal(tradeOrderDO.getOrderStatus(), TradeOrderStatusEnum.YD.getStatus())) {
+                log.info("留位订单自动取消:orderId={}, orderStatus={}", orderId, tradeOrderDO.getOrderStatus());
+                // 调用取消订单逻辑
+                tradeOrderPayService.cancelOrderByHoldTimeout(orderId);
+            } else {
+                log.info("留位订单自动取消:订单状态已变更,无需取消,orderId={}, orderStatus={}",
+                        orderId, tradeOrderDO.getOrderStatus());
+            }
+
+            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+        } catch (Exception e) {
+            log.error("留位订单自动取消延迟MQ处理出现错误,orderId={}", data, e);
+            channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
+        }
+    }
+
     @RabbitListener(queues = TradeMqConfig.QUEUE_CHECK_ORDER_SUCCESS, concurrency = "2")
     @TenantIgnore
     public void processCheckOrderSuccess(String data, Message message, Channel channel) throws IOException {

+ 13 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/framework/mq/TradePublishUtils.java

@@ -141,6 +141,19 @@ public class TradePublishUtils {
         },correlationData);
     }
 
+    /**
+     * 发布留位订单自动取消延迟消息
+     * @param data 消息体(订单ID)
+     * @param delay 延迟时间 毫秒(4小时 = 14400000ms)
+     */
+    public void publishHoldOrderCancelDelayMsg(String data, long delay){
+        CorrelationData correlationData = new CorrelationData(data + "_holdOrderCancelDelayMsg");
+        template.convertAndSend(EXCHANGE_ORDER, DELAY_ROUTE_HOLD_ORDER_CANCEL, data, message -> {
+            // 设置延迟毫秒值,默认 4 小时
+            message.getMessageProperties().setExpiration(String.valueOf((delay == 0) ? 4 * 60 * 60 * 1000 : delay));
+            return message;
+        }, correlationData);
+    }
 
     /**
      * 发布核销订单成功消息

+ 1 - 1
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/bo/TradeOrderLogCreateReqBO.java

@@ -52,6 +52,6 @@ public class TradeOrderLogCreateReqBO {
      */
     @NotEmpty(message = "操作明细不能为空")
     private String content;
-    private String tenantId;
+    private Long tenantId;
 
 }

+ 6 - 1
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/order/impl/TradeOrderLogServiceImpl.java

@@ -33,7 +33,12 @@ public class TradeOrderLogServiceImpl implements TradeOrderLogService {
 
     @Override
     public void createOrderLog(TradeOrderLogCreateReqBO logDTO) {
-        tradeOrderLogMapper.insert(TradeOrderConvert.INSTANCE.convert(logDTO));
+        TradeOrderLogDO logDO = TradeOrderConvert.INSTANCE.convert(logDTO);
+        Long tenantId = logDTO.getTenantId();
+        if (tenantId != null) {
+            logDO.setTenantId(logDTO.getTenantId());
+        }
+        tradeOrderLogMapper.insert(logDO);
     }
 
     @Override

+ 12 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/otc/impl/OtcTradeOrderServiceImpl.java

@@ -2610,6 +2610,18 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
             Map<String, Object> append = TradeOrderLogUtils.append("result", "订单创建成功");
             append.put("content", "");
             tradePublishUtils.publishOrderCreateSuccessMsg(orderId + "");
+            // 如果是留位订单,发送 4 小时自动取消延迟消息
+            if (createVO.getIsYd() != null && createVO.getIsYd() == 1) {
+                // 查询配置信息,获取取消时间
+                String autoClearTime = configApi.getPlatformConfigValueByKey("autoClearTimeoutParam.four_hours");
+                if (StrUtil.isBlank(autoClearTime)) {
+                    autoClearTime = "4";
+                }
+                double hours = Double.parseDouble(autoClearTime);
+                long delayMs = (long) (hours * 60 * 60 * 1000);
+                tradePublishUtils.publishHoldOrderCancelDelayMsg(orderId.toString(), delayMs);
+                log.info("留位订单创建成功,已发送{}小时自动取消延迟消息:orderId={}", autoClearTime,orderId);
+            }
             OtcTradeOrderCreateRespVO respVO = TradeOrderConvert.INSTANCE.convert(result.getData());
             TradeOrderLogUtils.setOrderInfo(orderId, null, orderStatus, append);
             return CommonResult.success(respVO);

+ 5 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/pay/TradeOrderPayService.java

@@ -59,6 +59,11 @@ public interface TradeOrderPayService {
      */
     @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MANUL_CANCEL)
     CommonResult<?> cancelOrder(Long orderId);
+    /**
+     * 取消订单(留位超时系统自动取消)
+     */
+    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.HOLD_ORDER_TIMEOUT_SYSTEM_CANCEL)
+    CommonResult<?> cancelOrderByHoldTimeout(Long orderId);
 
     /**
      * 供应商出票重试

+ 11 - 0
ship-module-trade/ship-module-trade-biz/src/main/java/com/yc/ship/module/trade/service/pay/impl/TradeOrderPayServiceImpl.java

@@ -39,6 +39,7 @@ import com.yc.ship.module.trade.dal.mysql.order.TradeOrderTotalMapper;
 import com.yc.ship.module.trade.dal.mysql.order.TradeVisitorMapper;
 import com.yc.ship.module.trade.enums.*;
 import com.yc.ship.module.trade.framework.annotation.TradeOrderLog;
+import com.yc.ship.module.trade.framework.aop.TradeOrderLogAspect;
 import com.yc.ship.module.trade.framework.common.ExceptionUtils;
 import com.yc.ship.module.trade.framework.common.TradeOrderLogUtils;
 import com.yc.ship.module.trade.service.bill.BillService;
@@ -570,6 +571,16 @@ public class TradeOrderPayServiceImpl implements TradeOrderPayService {
         return orderPayCancelHandler(orderId);
     }
 
+    @Override
+    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.HOLD_ORDER_TIMEOUT_SYSTEM_CANCEL)
+    public CommonResult<?> cancelOrderByHoldTimeout(Long orderId) {
+        TradeOrderDO tradeOrderDO = tradeOrderRepositoryService.getById(orderId);
+        if (tradeOrderDO != null && tradeOrderDO.getTenantId() != null) {
+            TradeOrderLogAspect.setTenantId(tradeOrderDO.getTenantId());
+        }
+        return orderPayCancelHandler(orderId);
+    }
+
     @Override
     public CommonResult<?> retryPaySupplierOrder(Long orderId, Long supplierOrderId) {