Przeglądaj źródła

feat: 层模版同步后自动初始化设备库存记录

syncFromHaha 完成后从层模版数据中提取所有商品编码,
查本地商品库拿到 productId,为 t_device_inventory 中
不存在的商品自动创建 stock=0 的库存记录。

已存在的记录不覆盖,确保已有库存数据不受影响。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
skyline 1 tydzień temu
rodzic
commit
8ca6fb4490

+ 109 - 1
haha-service/src/main/java/com/haha/service/impl/LayerTemplateServiceImpl.java

@@ -16,13 +16,20 @@ import com.haha.common.constant.CommonConstants;
 import com.haha.common.constant.SyncConstants;
 import com.haha.common.exception.BusinessException;
 import com.haha.common.utils.EntityLabelUtils;
+import com.haha.entity.DeviceInventory;
+import com.haha.entity.InventoryLog;
 import com.haha.entity.LayerTemplate;
+import com.haha.entity.Product;
 import com.haha.mapper.LayerTemplateMapper;
 import com.haha.sdk.HahaClient;
 import com.haha.sdk.api.GoodsApi;
+import com.haha.service.DeviceInventoryService;
+import com.haha.service.InventoryLogService;
 import com.haha.service.LayerTemplateService;
+import com.haha.service.ProductService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
@@ -48,6 +55,12 @@ public class LayerTemplateServiceImpl extends ServiceImpl<LayerTemplateMapper, L
     private final HahaClient hahaClient;
     private final ObjectMapper objectMapper = new ObjectMapper();
 
+    @Autowired
+    private DeviceInventoryService deviceInventoryService;
+
+    @Autowired
+    private ProductService productService;
+
     /**
      * 分页查询层模版列表
      * 支持按设备ID、同步状态、模板名称进行筛选
@@ -319,7 +332,14 @@ public class LayerTemplateServiceImpl extends ServiceImpl<LayerTemplateMapper, L
                 log.info("更新层模版记录: deviceId={}", deviceId);
             }
 
-            // 步骤6: 更新同步状态为"已同步"并记录时间
+            // 步骤6: 从层模版数据初始化库存(仅对尚不存在的商品创建 stock=0 记录)
+            try {
+                initInventoryFromTemplate(deviceId, apiData);
+            } catch (Exception e) {
+                log.error("层模版同步后初始化库存失败: deviceId={}", deviceId, e);
+            }
+
+            // 步骤7: 更新同步状态为"已同步"并记录时间
             updateSyncStatus(deviceId, SyncConstants.STATUS_SYNCED, LocalDateTime.now());
 
             log.info("层模版同步成功: deviceId={}", deviceId);
@@ -905,4 +925,92 @@ public class LayerTemplateServiceImpl extends ServiceImpl<LayerTemplateMapper, L
         }
         return IMAGE_DOMAIN_PREFIX + picUrl;
     }
+
+    /**
+     * 从层模版API数据中提取商品编码,为不存在的商品创建库存记录(stock=0)
+     * 仅在库存记录不存在时创建,已存在的记录不受影响
+     */
+    private void initInventoryFromTemplate(String deviceId, Map<String, Object> apiData) {
+        // 提取所有商品编码
+        java.util.Set<String> productCodes = new java.util.HashSet<>();
+
+        if (apiData.containsKey("products")) {
+            @SuppressWarnings("unchecked")
+            Map<String, Object> products = (Map<String, Object>) apiData.get("products");
+            extractCodesFromFloors(products.get("left"), productCodes);
+            extractCodesFromFloors(products.get("right"), productCodes);
+        }
+
+        if (productCodes.isEmpty()) {
+            log.info("层模版中无商品配置,跳过库存初始化: deviceId={}", deviceId);
+            return;
+        }
+
+        log.info("从层模版提取到 {} 个商品编码,开始初始化库存: deviceId={}", productCodes.size(), deviceId);
+        int created = 0;
+        int skipped = 0;
+
+        for (String code : productCodes) {
+            try {
+                Product product = productService.getProductByCode(code);
+                if (product == null) {
+                    log.debug("商品编码在本地库中不存在,跳过: code={}, deviceId={}", code, deviceId);
+                    skipped++;
+                    continue;
+                }
+
+                DeviceInventory existing = deviceInventoryService.getByDeviceAndProduct(deviceId, product.getId());
+                if (existing != null) {
+                    log.debug("库存记录已存在,跳过: deviceId={}, productCode={}", deviceId, code);
+                    skipped++;
+                    continue;
+                }
+
+                DeviceInventory inventory = new DeviceInventory();
+                inventory.setDeviceId(deviceId);
+                inventory.setProductId(product.getId());
+                inventory.setProductCode(code);
+                inventory.setProductName(product.getName());
+                inventory.setStock(0);
+                inventory.setWarningThreshold(5);
+                inventory.setCreateTime(LocalDateTime.now());
+                inventory.setUpdateTime(LocalDateTime.now());
+                deviceInventoryService.save(inventory);
+                created++;
+
+                log.info("初始化库存记录: deviceId={}, productCode={}, productName={}, stock=0",
+                        deviceId, code, product.getName());
+            } catch (Exception e) {
+                log.error("初始化单条库存记录失败: deviceId={}, productCode={}", deviceId, code, e);
+            }
+        }
+
+        log.info("库存初始化完成: deviceId={}, 创建={}, 跳过={}", deviceId, created, skipped);
+    }
+
+    /**
+     * 从层数据(left/right floors)中提取商品编码
+     */
+    private void extractCodesFromFloors(Object floorsObj, java.util.Set<String> codeSet) {
+        if (floorsObj == null) return;
+
+        try {
+            List<FloorConfig> floors = objectMapper.convertValue(floorsObj,
+                    new TypeReference<List<FloorConfig>>() {});
+
+            if (floors != null) {
+                for (FloorConfig floor : floors) {
+                    if (floor.getGoods() != null) {
+                        for (GoodsItem goods : floor.getGoods()) {
+                            if (goods.getKey() != null && !goods.getKey().isEmpty()) {
+                                codeSet.add(goods.getKey());
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.warn("解析层商品数据失败: {}", e.getMessage());
+        }
+    }
 }