Procházet zdrojové kódy

fix: ORC_RESULT 回调解析 sku_list 写入 order_goods,修复订单详情缺商品问题

- HahaCallbackServiceImpl: ORC_RESULT 处理时解析 sku_list 直接写 t_order_goods
- OrderServiceImpl: 新增 repairOrdersMissingGoods 存量修复方法
- OrderController: 新增 POST /order/repair-goods 修复接口

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
skyline před 2 týdny
rodič
revize
4ac0d9760c

+ 14 - 0
haha-admin/src/main/java/com/haha/admin/controller/OrderController.java

@@ -224,4 +224,18 @@ public class OrderController {
         Map<String, Object> result = hahaCallbackService.getLayerRecognize(orderId, activityId);
         return Result.success("查询成功", result);
     }
+
+    /**
+     * 修复缺失商品记录的订单:解析 items (sku_list) 补写 t_order_goods
+     * 传 activityId 修复单个,不传则批量修复所有
+     */
+    @RequirePermission("order:update")
+    @PostMapping("/repair-goods")
+    public Result<Map<String, Object>> repairOrdersMissingGoods(@RequestParam(required = false) String activityId) {
+        com.haha.service.impl.OrderServiceImpl impl = (com.haha.service.impl.OrderServiceImpl) orderService;
+        int fixed = impl.repairOrdersMissingGoods(activityId);
+        Map<String, Object> data = new HashMap<>();
+        data.put("fixed", fixed);
+        return Result.success("修复完成", data);
+    }
 }

+ 70 - 0
haha-service/src/main/java/com/haha/service/impl/HahaCallbackServiceImpl.java

@@ -100,6 +100,9 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
     @Autowired
     private DataSyncService dataSyncService;
 
+    @Autowired
+    private com.haha.service.ProductService productService;
+
     @Override
     public void handleMessage(Map<String, Object> params) {
         // 签名验证:确保回调来自哈哈平台
@@ -794,9 +797,76 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
             log.info("订单识别信息更新成功 - orderId: {}, 等待回调更新金额", order.getId());
         }
 
+        // 解析sku_list并保存到order_goods表,确保运营平台能立即看到商品信息
+        saveOrderGoodsFromSkuList(order, skuListStr);
+
         saveOrderInfoToRedis(order, activityId);
     }
 
+    /**
+     * 从 AI 识别的 sku_list 解析商品编码,查本地商品库补全信息后写入 order_goods
+     * 确保 ORDER 回调到达前运营平台也能看到订单商品
+     */
+    private void saveOrderGoodsFromSkuList(Order order, String skuListStr) {
+        if (skuListStr == null || skuListStr.isEmpty()) {
+            return;
+        }
+        try {
+            // 检查是否已有商品记录(ORDER 回调可能已经写入),避免重复
+            Long existingCount = orderGoodsMapper.selectCount(
+                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<OrderGoods>()
+                            .eq(OrderGoods::getOrderId, order.getId()));
+            if (existingCount != null && existingCount > 0) {
+                log.debug("订单商品已存在,跳过 sku_list 写入 - orderId: {}", order.getId());
+                return;
+            }
+
+            JSONArray skuList = JSON.parseArray(skuListStr);
+            if (skuList == null || skuList.isEmpty()) {
+                return;
+            }
+
+            for (int i = 0; i < skuList.size(); i++) {
+                JSONObject sku = skuList.getJSONObject(i);
+                String code = sku.getString("code");
+                Integer number = sku.getInteger("number");
+                if (code == null || code.isEmpty()) {
+                    continue;
+                }
+
+                // 查询本地商品库
+                com.haha.entity.Product product = productService.getProductByCode(code);
+
+                OrderGoods goods = new OrderGoods();
+                goods.setOrderId(order.getId());
+                goods.setOrderNo(order.getOrderNo());
+                goods.setActivityId(order.getActivityId());
+                goods.setDeviceId(order.getDeviceId());
+                goods.setUserId(order.getUserId());
+                goods.setCode(code);
+                goods.setProductNum(number != null ? Math.abs(number) : 1);
+                goods.setCreateTime(LocalDateTime.now());
+
+                if (product != null) {
+                    goods.setProductId(product.getId());
+                    goods.setBarCode(product.getBarcode());
+                    goods.setProductName(product.getName());
+                    goods.setPic(product.getPic());
+                    if (product.getRetailPrice() != null) {
+                        goods.setPrice(BigDecimal.valueOf(product.getRetailPrice()));
+                        goods.setMoney(BigDecimal.valueOf(product.getRetailPrice()));
+                    }
+                }
+
+                orderGoodsMapper.insert(goods);
+            }
+
+            log.info("从sku_list保存订单商品成功 - orderId: {}, 商品数: {}", order.getId(), skuList.size());
+        } catch (Exception e) {
+            log.error("从sku_list保存订单商品失败 - orderId: {}", order.getId(), e);
+        }
+    }
+
     private void updateOrderFromCallback(Order order, String orderId, String activityId,
                                           Object orderMoney, String orderDetail,
                                           String orderName, String orderGoodsStr) {

+ 83 - 0
haha-service/src/main/java/com/haha/service/impl/OrderServiceImpl.java

@@ -96,6 +96,10 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
     @Lazy
     private OrderGoodsMapper orderGoodsMapper;
 
+    @Autowired
+    @Lazy
+    private com.haha.service.ProductService productService;
+
     @Override
     public IPage<Order> getPage(int page, int pageSize, String orderNo, String deviceId,
                                  String payStatus, Integer status, String startDate, String endDate,
@@ -1001,6 +1005,85 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
         return products;
     }
 
+    /**
+     * 修复缺失商品记录的订单:解析 orders.items (sku_list) 补写 t_order_goods
+     *
+     * @param activityId 指定 activityId 修复单个订单,为 null 则批量修复所有缺失商品的订单
+     * @return 修复的订单数
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public int repairOrdersMissingGoods(String activityId) {
+        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
+        wrapper.isNotNull(Order::getItems).ne(Order::getItems, "").ne(Order::getItems, "[]");
+        if (activityId != null && !activityId.isEmpty()) {
+            wrapper.eq(Order::getActivityId, activityId);
+        }
+
+        List<Order> orders = this.list(wrapper);
+        int fixed = 0;
+
+        for (Order order : orders) {
+            Long goodsCount = orderGoodsMapper.selectCount(
+                    new LambdaQueryWrapper<OrderGoods>().eq(OrderGoods::getOrderId, order.getId()));
+            if (goodsCount != null && goodsCount > 0) {
+                continue;
+            }
+
+            String items = order.getItems();
+            if (items == null || items.isEmpty()) {
+                continue;
+            }
+
+            try {
+                JSONArray skuList = JSON.parseArray(items);
+                if (skuList == null || skuList.isEmpty()) {
+                    continue;
+                }
+
+                for (int i = 0; i < skuList.size(); i++) {
+                    JSONObject sku = skuList.getJSONObject(i);
+                    String code = sku.getString("code");
+                    Integer number = sku.getInteger("number");
+                    if (code == null || code.isEmpty()) {
+                        continue;
+                    }
+
+                    com.haha.entity.Product product = productService.getProductByCode(code);
+
+                    OrderGoods goods = new OrderGoods();
+                    goods.setOrderId(order.getId());
+                    goods.setOrderNo(order.getOrderNo());
+                    goods.setActivityId(order.getActivityId());
+                    goods.setDeviceId(order.getDeviceId());
+                    goods.setUserId(order.getUserId());
+                    goods.setCode(code);
+                    goods.setProductNum(number != null ? Math.abs(number) : 1);
+                    goods.setCreateTime(LocalDateTime.now());
+
+                    if (product != null) {
+                        goods.setProductId(product.getId());
+                        goods.setBarCode(product.getBarcode());
+                        goods.setProductName(product.getName());
+                        goods.setPic(product.getPic());
+                        if (product.getRetailPrice() != null) {
+                            goods.setPrice(BigDecimal.valueOf(product.getRetailPrice()));
+                            goods.setMoney(BigDecimal.valueOf(product.getRetailPrice()));
+                        }
+                    }
+
+                    orderGoodsMapper.insert(goods);
+                }
+
+                fixed++;
+                log.info("补写订单商品成功 - orderId: {}, activityId: {}", order.getId(), order.getActivityId());
+            } catch (Exception e) {
+                log.error("补写订单商品失败 - orderId: {}", order.getId(), e);
+            }
+        }
+
+        return fixed;
+    }
+
     /**
      * 标准化图片URL
      */