Browse Source

一键供货代码优化

zhangwl 1 month ago
parent
commit
8181ca0743

+ 94 - 0
src/main/java/zs/payment/mapper/flymall/B2cGoodsAttrMapper.java

@@ -0,0 +1,94 @@
+package zs.payment.mapper.flymall;
+
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 云商城属性相关表操作(对应PHP goodsrelevant_model中的属性操作)
+ * 涉及表:b2c_attr, b2c_attr_value, b2c_pt_attr
+ */
+@Mapper
+public interface B2cGoodsAttrMapper {
+
+    /**
+     * 根据企悦ID查询属性ID(对应PHP getAttrInfoByQyId)
+     */
+    @Select("SELECT attr_id FROM b2c_attr WHERE qy_id = #{qyId} LIMIT 1")
+    Integer findAttrIdByQyId(@Param("qyId") Integer qyId);
+
+    /**
+     * 新增属性(对应PHP addAttrInfo,带qy_id)
+     * @return 自增ID
+     */
+    @Insert("INSERT INTO b2c_attr (attr_name, type, spell, sort, state, create_username, create_time, " +
+            "update_user, update_time, excel_id, entryType, qy_id) " +
+            "VALUES (#{attrName}, 1, '', 0, 0, '企悦接口', NOW(), '企悦接口', NOW(), 0, 3, #{qyId})")
+    @Options(useGeneratedKeys = true, keyProperty = "attrId", keyColumn = "attr_id")
+    int insertAttr(@Param("attrName") String attrName, @Param("qyId") Integer qyId);
+
+    /**
+     * 新增属性(使用Map参数接收自增ID)
+     */
+    @Insert("INSERT INTO b2c_attr (attr_name, type, spell, sort, state, create_username, create_time, " +
+            "update_user, update_time, excel_id, entryType, qy_id) " +
+            "VALUES (#{attrName}, 1, '', 0, 0, '企悦接口', NOW(), '企悦接口', NOW(), 0, 3, #{qyId})")
+    @SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "attrId", before = false, resultType = Integer.class)
+    int insertAttrReturnId(Map<String, Object> params);
+
+    /**
+     * 更新属性(对应PHP editAttrInfo)
+     */
+    @Update("UPDATE b2c_attr SET attr_name = #{attrName}, update_user = '企悦接口', update_time = NOW() " +
+            "WHERE attr_id = #{attrId}")
+    int updateAttr(@Param("attrId") Integer attrId, @Param("attrName") String attrName);
+
+    /**
+     * 删除属性下所有属性值(对应PHP delAttrValueByIdsByqiyue)
+     */
+    @Delete("DELETE FROM b2c_attr_value WHERE attr_id = #{attrId}")
+    int deleteAttrValuesByAttrId(@Param("attrId") Integer attrId);
+
+    /**
+     * 新增单条属性值(带qy_id,对应PHP batchAddAttrValueInfoByQiyue中的单条)
+     */
+    @Insert("INSERT INTO b2c_attr_value (attr_val_name, attr_id, status, create_username, create_time, " +
+            "excel_id, upd_username, upd_time, qy_id) " +
+            "VALUES (#{valName}, #{attrId}, 1, '企悦接口', NOW(), 0, '企悦接口', NOW(), #{qyId})")
+    @Options(useGeneratedKeys = true, keyProperty = "attrValId", keyColumn = "attr_val_id")
+    int insertAttrValue(@Param("valName") String valName, @Param("attrId") Integer attrId, @Param("qyId") Integer qyId);
+
+    /**
+     * 根据企悦ID查询属性值ID(对应PHP getAttrValueByIdsByqiyue)
+     */
+    @Select("SELECT attr_val_id FROM b2c_attr_value WHERE qy_id = #{qyId} LIMIT 1")
+    Integer findAttrValIdByQyId(@Param("qyId") Integer qyId);
+
+    /**
+     * 查询属性下所有属性值ID(对应PHP getattrValIdByAttrId)
+     */
+    @Select("SELECT attr_val_id FROM b2c_attr_value WHERE attr_id = #{attrId}")
+    List<Integer> findAttrValIdsByAttrId(@Param("attrId") Integer attrId);
+
+    /**
+     * 查询品类属性是否存在(用于判断update or insert)
+     */
+    @Select("SELECT COUNT(*) FROM b2c_pt_attr WHERE pt_id = #{ptId} AND attr_id = #{attrId}")
+    int countPtAttr(@Param("ptId") Integer ptId, @Param("attrId") Integer attrId);
+
+    /**
+     * 新增品类属性关联(对应PHP addPtAttrInfo)
+     */
+    @Insert("INSERT INTO b2c_pt_attr (pt_id, attr_id, attr_vals, is_required, is_sale_attr, sort_num, " +
+            "status, create_username, create_time, upd_username, upd_time, excel_id) " +
+            "VALUES (#{ptId}, #{attrId}, '', 1, 1, 0, 1, '企悦接口', NOW(), '企悦接口', NOW(), 0)")
+    int insertPtAttr(@Param("ptId") Integer ptId, @Param("attrId") Integer attrId);
+
+    /**
+     * 更新品类属性关联(对应PHP editPtAttrInfo)
+     */
+    @Update("UPDATE b2c_pt_attr SET upd_username = '企悦接口', upd_time = NOW() " +
+            "WHERE pt_id = #{ptId} AND attr_id = #{attrId}")
+    int updatePtAttr(@Param("ptId") Integer ptId, @Param("attrId") Integer attrId);
+}

+ 29 - 0
src/main/java/zs/payment/mapper/flymall/B2cGoodsSpuInOnlineMapper.java

@@ -2,8 +2,37 @@ package zs.payment.mapper.flymall;
 
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 import zs.payment.entity.mysql.flymall.B2cGoodsSpuInOnline;
 import zs.payment.entity.mysql.flymall.B2cGoodsSpuInOnline;
 
 
+import java.math.BigDecimal;
+import java.util.Map;
+
 @Mapper
 @Mapper
 public interface B2cGoodsSpuInOnlineMapper extends BaseMapper<B2cGoodsSpuInOnline> {
 public interface B2cGoodsSpuInOnlineMapper extends BaseMapper<B2cGoodsSpuInOnline> {
+
+    /**
+     * 查询"其它"品牌ID(对应PHP addGoods中的品牌查找逻辑)
+     */
+    @Select("SELECT brand_id FROM b2c_brand WHERE (status != 3 OR status IS NULL) AND brand_name_zh = #{brandName} LIMIT 1")
+    Integer findBrandIdByName(@Param("brandName") String brandName);
+
+    /**
+     * 查询品类的佣金比例(对应PHP getGoodsCategoryByPtId)
+     */
+    @Select("SELECT ledger_ratio, tg_ledger_ratio FROM b2c_product_type WHERE pt_id = #{ptId} LIMIT 1")
+    Map<String, Object> findCommissionByPtId(@Param("ptId") Integer ptId);
+
+    /**
+     * 根据pt_id查询品类分类信息(对应PHP getCategoryByptid)
+     */
+    @Select("SELECT cate_id, cate_name, pt_id, parent_id, level FROM b2c_product_category WHERE pt_id = #{ptId} LIMIT 1")
+    Map<String, Object> findCategoryByPtId(@Param("ptId") Integer ptId);
+
+    /**
+     * 根据cate_id查询父级品类(对应PHP getCategoryBycateid)
+     */
+    @Select("SELECT cate_id, cate_name, pt_id, parent_id, level FROM b2c_product_category WHERE cate_id = #{cateId} LIMIT 1")
+    Map<String, Object> findCategoryByCateId(@Param("cateId") Integer cateId);
 }
 }

+ 384 - 92
src/main/java/zs/payment/service/commodity/impl/CommodityProcureServiceImpl.java

@@ -40,9 +40,13 @@ import zs.payment.service.flymall.b2cgoodsskuinonline.B2cGoodsSkuInOnlineService
 import zs.payment.service.flymall.b2cgoodsspuinonline.B2cGoodsSpuInOnlineService;
 import zs.payment.service.flymall.b2cgoodsspuinonline.B2cGoodsSpuInOnlineService;
 import zs.payment.service.flymall.b2cshop.B2cShopService;
 import zs.payment.service.flymall.b2cshop.B2cShopService;
 
 
+import zs.payment.mapper.flymall.B2cGoodsAttrMapper;
+import zs.payment.mapper.flymall.B2cGoodsSpuInOnlineMapper;
 import zs.payment.messages.KafkaProducer;
 import zs.payment.messages.KafkaProducer;
+import zs.payment.utils.RedisUtils;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
+import java.sql.Timestamp;
 import java.math.RoundingMode;
 import java.math.RoundingMode;
 import java.util.*;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
@@ -85,6 +89,12 @@ public class CommodityProcureServiceImpl implements CommodityProcureService {
 
 
     @Autowired
     @Autowired
     private KafkaProducer kafkaProducer;
     private KafkaProducer kafkaProducer;
+    @Autowired
+    private RedisUtils redisUtils;
+    @Autowired
+    private B2cGoodsSpuInOnlineMapper b2cGoodsSpuInOnlineMapper;
+    @Autowired
+    private B2cGoodsAttrMapper b2cGoodsAttrMapper;
 
 
     private static final BigDecimal HUNDRED = new BigDecimal("100");
     private static final BigDecimal HUNDRED = new BigDecimal("100");
     private static final BigDecimal COMMISSION_DEFAULT_RATE = new BigDecimal("0.01");
     private static final BigDecimal COMMISSION_DEFAULT_RATE = new BigDecimal("0.01");
@@ -783,12 +793,17 @@ public class CommodityProcureServiceImpl implements CommodityProcureService {
     }
     }
 
 
     /**
     /**
-     * 供货:将本地商品推送到云商城
-     * 对应PHP supply()中issupply==1的逻辑(929-1014行)
+     * 供货到云商城(对应PHP supply()中issupply==1的逻辑 + addGoods接口)
+     * 流程:1.保存SPU基础信息 → 2.保存图片 → 3.保存SKU → 4.更新上架状态
      */
      */
     private void supplyGoodsToMall(ImsEweiShopGoods item, Integer storeid, Integer cate, Integer uniacid) {
     private void supplyGoodsToMall(ImsEweiShopGoods item, Integer storeid, Integer cate, Integer uniacid) {
         Long goodsId = item.getId();
         Long goodsId = item.getId();
 
 
+        // 【Bug修复】查重前置:是否已在云商城供货(通过gd_id判断),避免无效查询
+        if (item.getGdId() != null && item.getGdId() > 0) {
+            throw new ApiException("商品已经供货");
+        }
+
         // 多规格时取最大重量
         // 多规格时取最大重量
         if (item.getHasoption() != null && item.getHasoption() == 1) {
         if (item.getHasoption() != null && item.getHasoption() == 1) {
             ImsEweiShopGoodsOption maxWeightOpt = optionService.getOne(new LambdaQueryWrapper<ImsEweiShopGoodsOption>()
             ImsEweiShopGoodsOption maxWeightOpt = optionService.getOne(new LambdaQueryWrapper<ImsEweiShopGoodsOption>()
@@ -801,26 +816,53 @@ public class CommodityProcureServiceImpl implements CommodityProcureService {
             }
             }
         }
         }
 
 
-        // 构建供货数据
-        Map<String, Object> addgoods = new LinkedHashMap<>();
-        addgoods.put("gd_name", item.getTitle());
-        addgoods.put("shop_id", storeid);
-        addgoods.put("pt_id", cate);
-        addgoods.put("gd_weight", item.getWeight());
-        addgoods.put("gd_price", item.getMarketprice());         // 供货中心售价=商城售价
-        addgoods.put("mk_price", item.getProductprice());         // 市场价
-        addgoods.put("cost_price", item.getCostprice());          // 成本价/供货价
-        addgoods.put("gd_stock", item.getTotal());                // 库存
-        addgoods.put("msg1", item.getContent());                  // 商品详情
-        addgoods.put("uniacid", uniacid);
-        addgoods.put("merchid", 0);
-        addgoods.put("storeid", 0);
-        addgoods.put("goodsid", goodsId.intValue());
-
-        // 图片处理:thumb + thumb_url → imgsInfo数组
+        // 构建图片列表
+        List<String> imgsInfo = buildGoodsImages(item, goodsId);
+        // 构建规格列表
+        List<ImsEweiShopGoodsSpec> specs = specService.list(new LambdaQueryWrapper<ImsEweiShopGoodsSpec>()
+                .eq(ImsEweiShopGoodsSpec::getGoodsid, goodsId.intValue())
+                .eq(ImsEweiShopGoodsSpec::getUniacid, uniacid));
+        // 构建SKU选项列表
+        List<ImsEweiShopGoodsOption> options = optionService.list(new LambdaQueryWrapper<ImsEweiShopGoodsOption>()
+                .eq(ImsEweiShopGoodsOption::getGoodsid, goodsId.intValue())
+                .eq(ImsEweiShopGoodsOption::getUniacid, uniacid));
+
+        Timestamp now = new Timestamp(System.currentTimeMillis());
+
+        // Step 1: 保存商品SPU基础信息
+        Integer gdId = saveSpuToCloudMall(item, storeid, cate, uniacid, now);
+        log.info("云商城插入商品SPU成功 goodsId={}, gdId={}", goodsId, gdId);
+
+        // Step 2: 保存商品图片
+        saveImagesToCloudMall(gdId, imgsInfo, now);
+
+        // Step 3: 保存SKU信息(含属性映射)
+        saveSkusToCloudMall(gdId, storeid, item, specs, options, uniacid, cate, now);
+
+        // Step 4: 更新上架状态
+        B2cGoodsSpuInOnline updateSpu = new B2cGoodsSpuInOnline();
+        updateSpu.setGdId(gdId);
+        updateSpu.setIsOnSale(1);
+        if (!b2cGoodsSpuInOnlineService.updateById(updateSpu)) {
+            throw new ApiException("商品上架失败");
+        }
+        log.info("云商城商品上架成功 goodsId={}, gdId={}", goodsId, gdId);
+
+        // 回写云商城商品ID & 供货
+        yunMallGoodsService.saveGoods(gdId.toString(), 1);
+        ImsEweiShopGoods update = new ImsEweiShopGoods();
+        update.setId(goodsId);
+        update.setGdId(gdId);
+        goodsService.updateById(update);
+    }
+
+    /**
+     * 构建商品图片列表:thumb首图 + thumb_url扩展图
+     */
+    private List<String> buildGoodsImages(ImsEweiShopGoods item, Long goodsId) {
         List<String> imgsInfo = new ArrayList<>();
         List<String> imgsInfo = new ArrayList<>();
         if (item.getThumb() != null) {
         if (item.getThumb() != null) {
-            imgsInfo.add(item.getThumb());  // 首图
+            imgsInfo.add(item.getThumb());
         }
         }
         if (item.getThumbUrl() != null && !item.getThumbUrl().isEmpty()) {
         if (item.getThumbUrl() != null && !item.getThumbUrl().isEmpty()) {
             try {
             try {
@@ -832,95 +874,324 @@ public class CommodityProcureServiceImpl implements CommodityProcureService {
                 log.warn("thumb_url解析失败 goodsId={}", goodsId, e);
                 log.warn("thumb_url解析失败 goodsId={}", goodsId, e);
             }
             }
         }
         }
-        addgoods.put("imgsInfo", JSON.toJSONString(imgsInfo));
-
-        // 规格列表
-        List<ImsEweiShopGoodsSpec> specs = specService.list(new LambdaQueryWrapper<ImsEweiShopGoodsSpec>()
-                .eq(ImsEweiShopGoodsSpec::getGoodsid, goodsId.intValue())
-                .eq(ImsEweiShopGoodsSpec::getUniacid, uniacid));
+        return imgsInfo;
+    }
 
 
-        List<Map<String, Object>> specsList = new ArrayList<>();
-        for (ImsEweiShopGoodsSpec spec : specs) {
-            if (spec.getTitle() == null || spec.getTitle().isEmpty()) {
-                throw new ApiException("规格名称为空不能供货");
+    /**
+     * 保存商品SPU基础信息到云商城(对应 PHP _saveAddBaseinfo)
+     * 包含:品牌ID查找、品类路径构建、佣金比例查询
+     * @return 生成的gdId
+     */
+    private Integer saveSpuToCloudMall(ImsEweiShopGoods item, Integer storeid, Integer cate,
+                                       Integer uniacid, Timestamp now) {
+        B2cGoodsSpuInOnline spu = new B2cGoodsSpuInOnline();
+        spu.setGdName(item.getTitle());
+        spu.setShopId(storeid);
+        spu.setPtId(cate);
+        spu.setGdWeight(item.getWeight() != null ? item.getWeight().doubleValue() : 0.0);
+        spu.setGdColor("#000000");
+        spu.setGdNum("QY" + System.currentTimeMillis() + String.format("%04d", (int) (Math.random() * 10000)));
+        // 商品详情描述(对应PHP _saveDetailedDescription → _writeText)
+        // PHP原始逻辑:将content写入NFS文件(1.txt),gd_desc存储文件URL数组
+        // Java直连DB:无法访问PHP NFS,直接存储HTML内容到gd_desc字段
+        // 原始Java代码仅传递msg1=content,未传msg2/msg3
+        spu.setGdDesc(item.getContent());
+        spu.setUniacid(uniacid);
+        spu.setMerchid(0);
+        spu.setStoreid(0);
+        spu.setGoodsid(item.getId().intValue());
+        spu.setIsOnSale(0);       // 先设为0,Step4再更新为上架
+        spu.setIsDel(0);
+        spu.setAuditStatus(1);    // 企悦供货免审
+        spu.setCreateUsername("企悦接口");
+        spu.setUpdUsername("企悦接口");
+        spu.setCreateTime(now);
+        spu.setUpdTime(now);
+
+        // 查询品牌ID(对应PHP中查找/创建"其它"品牌逻辑)
+        try {
+            Integer brandId = b2cGoodsSpuInOnlineMapper.findBrandIdByName("其它");
+            if (brandId != null) {
+                spu.setBrandId(brandId);
             }
             }
-            Map<String, Object> specMap = new LinkedHashMap<>();
-            specMap.put("id", spec.getId());
-            specMap.put("title", spec.getTitle());
+        } catch (Exception e) {
+            log.warn("查询品牌ID失败,跳过 ptId={}", cate, e);
+        }
 
 
-            List<ImsEweiShopGoodsSpecItem> speItems = specItemService.list(
-                    new LambdaQueryWrapper<ImsEweiShopGoodsSpecItem>()
-                            .eq(ImsEweiShopGoodsSpecItem::getSpecid, spec.getId().intValue())
-                            .eq(ImsEweiShopGoodsSpecItem::getUniacid, uniacid));
+        // 构建品类路径cat_ids(对应PHP getCategoryListByid)
+        try {
+            String catIds = buildCategoryPath(cate);
+            if (catIds != null && !catIds.isEmpty()) {
+                spu.setCatIds(catIds);
+            }
+        } catch (Exception e) {
+            log.warn("构建cat_ids失败,跳过 ptId={}", cate, e);
+        }
 
 
-            List<Map<String, Object>> valuesList = new ArrayList<>();
-            for (ImsEweiShopGoodsSpecItem speItem : speItems) {
-                Map<String, Object> valMap = new LinkedHashMap<>();
-                valMap.put("id", speItem.getId());
-                valMap.put("title", speItem.getTitle());
-                valMap.put("sku_img", speItem.getThumb() != null ? speItem.getThumb() : "");
-                valuesList.add(valMap);
+        // 查询佣金比例(对应PHP中从product_type查询ledger_ratio)
+        try {
+            Map<String, Object> commissionMap = b2cGoodsSpuInOnlineMapper.findCommissionByPtId(cate);
+            if (commissionMap != null) {
+                BigDecimal ledgerRatio = toBigDecimal(commissionMap.get("ledger_ratio"));
+                BigDecimal tgLedgerRatio = toBigDecimal(commissionMap.get("tg_ledger_ratio"));
+                spu.setCommissionRatio(ledgerRatio);
+                spu.setCommissionSetRatio(ledgerRatio);
+                spu.setTgCommissionRatio(tgLedgerRatio);
+                spu.setTgCommissionSetRatio(tgLedgerRatio);
+            } else {
+                spu.setCommissionRatio(BigDecimal.ZERO);
+                spu.setCommissionSetRatio(BigDecimal.ZERO);
+                spu.setTgCommissionRatio(BigDecimal.ZERO);
+                spu.setTgCommissionSetRatio(BigDecimal.ZERO);
             }
             }
-            specMap.put("values", valuesList);
-            specsList.add(specMap);
+        } catch (Exception e) {
+            log.warn("查询佣金比例失败,使用默认值0 ptId={}", cate, e);
+            spu.setCommissionRatio(BigDecimal.ZERO);
+            spu.setCommissionSetRatio(BigDecimal.ZERO);
+            spu.setTgCommissionRatio(BigDecimal.ZERO);
+            spu.setTgCommissionSetRatio(BigDecimal.ZERO);
         }
         }
-        addgoods.put("specslist", JSON.toJSONString(specsList));
+        spu.setCommissionTime(now);
+        spu.setTgCommissionTime(now);
 
 
-        // SKU选项列表
-        List<ImsEweiShopGoodsOption> options = optionService.list(new LambdaQueryWrapper<ImsEweiShopGoodsOption>()
-                .eq(ImsEweiShopGoodsOption::getGoodsid, goodsId.intValue())
-                .eq(ImsEweiShopGoodsOption::getUniacid, uniacid));
+        if (!b2cGoodsSpuInOnlineService.save(spu)) {
+            throw new ApiException("保存商品基础信息失败");
+        }
+        return spu.getGdId();
+    }
 
 
-        List<Map<String, Object>> optionsList = new ArrayList<>();
-        for (ImsEweiShopGoodsOption opt : options) {
-            Map<String, Object> optMap = new LinkedHashMap<>();
-            optMap.put("id", opt.getId());
-            optMap.put("title", opt.getTitle());
-            optMap.put("gd_weight", opt.getWeight());
-            optMap.put("gd_price", opt.getMarketprice());             // 供货中心售价=商城售价
-            optMap.put("mk_price", opt.getProductprice());             // 市场价
-            optMap.put("cost_price", item.getCostprice());             // 供货价统一取商品级
-            optMap.put("gd_stock", opt.getStock());
-            optMap.put("specs", opt.getSpecs());
-            optionsList.add(optMap);
-        }
-        addgoods.put("optionslist", JSON.toJSONString(optionsList));
-
-        // 查重:是否已在云商城供货(通过gd_id判断)
-        if (item.getGdId() != null && item.getGdId() > 0) {
-            throw new ApiException("商品已经供货");
+    /**
+     * 构建品类路径(对应PHP getCategoryListByid)
+     * 从叶子节点递归向上查找,最终组装为“根ID,二级ID,...,叶子ID”格式
+     */
+    private String buildCategoryPath(Integer ptId) {
+        Map<String, Object> category = b2cGoodsSpuInOnlineMapper.findCategoryByPtId(ptId);
+        if (category == null) {
+            return null;
+        }
+        List<Integer> cateIds = new ArrayList<>();
+        cateIds.add(toInteger(category.get("cate_id")));
+
+        // 向上递归查找父级,最多4层防止无限循环
+        Object parentId = category.get("parent_id");
+        int maxLevel = 4;
+        while (parentId != null && toInteger(parentId) > 0 && maxLevel-- > 0) {
+            Map<String, Object> parent = b2cGoodsSpuInOnlineMapper.findCategoryByCateId(toInteger(parentId));
+            if (parent == null) break;
+            cateIds.add(toInteger(parent.get("cate_id")));
+            parentId = parent.get("parent_id");
         }
         }
+        // 反转为从根到叶子的顺序
+        Collections.reverse(cateIds);
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < cateIds.size(); i++) {
+            if (i > 0) sb.append(",");
+            sb.append(cateIds.get(i));
+        }
+        return sb.toString();
+    }
 
 
-        // 调用云商城接口创建商品
-        String addGoodsUrl = mallHost + "/addGoods";
-        String content;
-        try {
-            content = HttpUtil.restTemplatePostCurl(addGoodsUrl, addgoods);
-        } catch (Exception e) {
-            log.error("云商城addGoods接口调用失败 goodsId={}", goodsId, e);
-            throw new ApiException("云商城接口调用失败: " + e.getMessage());
+    /**
+     * 保存商品图片到云商城(对应 PHP _saveImgs)
+     */
+    private void saveImagesToCloudMall(Integer gdId, List<String> imgsInfo, Timestamp now) {
+        if (imgsInfo == null || imgsInfo.isEmpty()) {
+            return;
         }
         }
+        for (int i = 0; i < imgsInfo.size(); i++) {
+            B2cGoodsImgInOnline img = new B2cGoodsImgInOnline();
+            img.setGdId(gdId);
+            img.setGdImg(imgsInfo.get(i));
+            img.setAttrValIds("");
+            img.setIsDefault(i == 0 ? 1 : 0);
+            img.setStatus(1);
+            img.setCreateUsername("企悦接口");
+            img.setCreateTime(now);
+            img.setImgSort(i);
+            b2cGoodsImgInOnlineService.save(img);
+        }
+    }
 
 
-        log.info("云商城插入商品 goodsId={}, uniacid={}, url={}, response={}", goodsId, uniacid, addGoodsUrl, content);
+    /**
+     * 保存SKU信息到云商城(对应 PHP _setSkuInfo / _noSaleAttrSetSku)
+     * 包含:属性创建/映射 + SKU持久化 + Redis库存缓存
+     */
+    private void saveSkusToCloudMall(Integer gdId, Integer storeid, ImsEweiShopGoods item,
+                                     List<ImsEweiShopGoodsSpec> specs,
+                                     List<ImsEweiShopGoodsOption> options,
+                                     Integer uniacid, Integer cate, Timestamp now) {
+        // 校验规格名称
+        if (specs != null) {
+            for (ImsEweiShopGoodsSpec spec : specs) {
+                if (spec.getTitle() == null || spec.getTitle().isEmpty()) {
+                    throw new ApiException("规格名称为空不能供货");
+                }
+            }
+        }
 
 
-        JSONObject result = JSON.parseObject(content);
-        if (result == null || result.getIntValue("head") != 200) {
-            String msg = result != null && result.getString("msg") != null ? result.getString("msg") : "供货失败!";
-            throw new ApiException(msg);
+        boolean hasSpecs = specs != null && !specs.isEmpty() && options != null && !options.isEmpty();
+        if (hasSpecs) {
+            // 有规格:先创建/更新属性,再保存SKU(对应PHP _setSkuInfo)
+            // Step A: 为每个规格创建/更新属性记录(对应PHP _saveAttr)
+            Integer ptId = cate != null ? cate : 0;
+            List<Integer> attrIds = saveAttrsToCloudMall(specs, uniacid, ptId);
+
+            // Step B: 保存商品属性关联到SPU(对应PHP _saveGoodsAttr)
+            saveGoodsAttrsToSpu(gdId, attrIds);
+
+            // Step C: 保存SKU,sale_attrs转换为云商城attrValId(对应PHP _saveSku)
+            for (ImsEweiShopGoodsOption opt : options) {
+                B2cGoodsSkuInOnline sku = new B2cGoodsSkuInOnline();
+                sku.setGdId(gdId);
+                sku.setGdPrice(opt.getMarketprice() != null ? opt.getMarketprice() : BigDecimal.ZERO);
+                sku.setCostPrice(item.getCostprice() != null ? item.getCostprice() : BigDecimal.ZERO);
+                sku.setMkPrice(opt.getProductprice() != null ? opt.getProductprice() : BigDecimal.ZERO);
+                sku.setGdStock(opt.getStock() != null ? opt.getStock() : 0);
+                sku.setShopId(storeid);
+                // 将企悦spec_item_id转换为云商城attrValId(对应PHP _saveSku中的sale_attrs映射)
+                sku.setSaleAttrs(mapSpecsToAttrValIds(opt.getSpecs()));
+                sku.setIsDel(0);
+                sku.setCreateUsername("企悦接口");
+                sku.setCreateTime(now);
+                sku.setUpdUsername("企悦接口");
+                sku.setUpdTime(now);
+                sku.setQyId(opt.getId() != null ? opt.getId().intValue() : null);
+                b2cGoodsSkuInOnlineService.save(sku);
+
+                // Redis缓存:对应PHP _saveSku中的redis操作
+                if (sku.getSkuId() != null && opt.getId() != null) {
+                    try {
+                        String optionKey = "option_" + opt.getId().intValue();
+                        redisUtils.set(optionKey, String.valueOf(sku.getSkuId()));
+                        redisUtils.set(String.valueOf(sku.getSkuId()), String.valueOf(sku.getGdStock()));
+                    } catch (Exception e) {
+                        log.warn("Redis缓存多规格SKU库存失败 gdId={}, optionId={}", gdId, opt.getId(), e);
+                    }
+                }
+            }
+        } else {
+            // 无规格:单SKU(对应PHP _noSaleAttrSetSku)
+            B2cGoodsSkuInOnline sku = new B2cGoodsSkuInOnline();
+            sku.setGdId(gdId);
+            sku.setGdPrice(item.getMarketprice() != null ? item.getMarketprice() : BigDecimal.ZERO);
+            sku.setCostPrice(item.getCostprice() != null ? item.getCostprice() : BigDecimal.ZERO);
+            sku.setMkPrice(item.getProductprice() != null ? item.getProductprice() : BigDecimal.ZERO);
+            sku.setGdStock(item.getTotal() != null ? item.getTotal() : 0);
+            sku.setShopId(storeid);
+            sku.setSaleAttrs("");
+            sku.setIsDel(0);
+            sku.setCreateUsername("企悦接口");
+            sku.setCreateTime(now);
+            sku.setUpdUsername("企悦接口");
+            sku.setUpdTime(now);
+            b2cGoodsSkuInOnlineService.save(sku);
+
+            // Redis缓存:对应PHP _noSaleAttrSetSku中的redis操作
+            if (sku.getSkuId() != null) {
+                try {
+                    String goodsKey = "goods_" + gdId;
+                    redisUtils.set(goodsKey, String.valueOf(sku.getSkuId()));
+                    redisUtils.set(String.valueOf(sku.getSkuId()), String.valueOf(sku.getGdStock()));
+                } catch (Exception e) {
+                    log.warn("Redis缓存单SKU库存失败 gdId={}", gdId, e);
+                }
+            }
         }
         }
+    }
 
 
-        // 回写云商城商品ID
-        Integer gdId = result.getJSONObject("result") != null
-                ? result.getJSONObject("result").getInteger("goods_id") : null;
-        if (gdId != null) {
+    /**
+     * 为每个规格创建/更新云商城属性记录(对应PHP _saveAttr)
+     * 流程:查询attr_id→创建/更新attr→维护pt_attr→删除旧attr_value→插入新attr_value
+     * @return 所有规格对应的attrId列表
+     */
+    private List<Integer> saveAttrsToCloudMall(List<ImsEweiShopGoodsSpec> specs, Integer uniacid, Integer ptId) {
+        List<Integer> attrIds = new ArrayList<>();
+        for (ImsEweiShopGoodsSpec spec : specs) {
+            Integer specId = spec.getId().intValue();
+            // 1. 查询是否已有对应属性
+            Integer attrId = b2cGoodsAttrMapper.findAttrIdByQyId(specId);
+            if (attrId != null) {
+                // 已有属性,更新名称
+                b2cGoodsAttrMapper.updateAttr(attrId, spec.getTitle());
+            } else {
+                // 新增属性
+                Map<String, Object> params = new HashMap<>();
+                params.put("attrName", spec.getTitle());
+                params.put("qyId", specId);
+                b2cGoodsAttrMapper.insertAttrReturnId(params);
+                attrId = (Integer) params.get("attrId");
+            }
+            attrIds.add(attrId);
+
+            // 2. 维护品类属性关联(b2c_pt_attr)
+            if (ptId != null && ptId > 0) {
+                int count = b2cGoodsAttrMapper.countPtAttr(ptId, attrId);
+                if (count > 0) {
+                    b2cGoodsAttrMapper.updatePtAttr(ptId, attrId);
+                } else {
+                    b2cGoodsAttrMapper.insertPtAttr(ptId, attrId);
+                }
+            }
 
 
-            //供货
-            yunMallGoodsService.saveGoods(gdId.toString(),1);
+            // 3. 删除该属性下旧的属性值,重新插入
+            b2cGoodsAttrMapper.deleteAttrValuesByAttrId(attrId);
 
 
-            ImsEweiShopGoods update = new ImsEweiShopGoods();
-            update.setId(goodsId);
-            update.setGdId(gdId);
-            goodsService.updateById(update);
+            // 4. 查询规格项并插入属性值
+            List<ImsEweiShopGoodsSpecItem> specItems = specItemService.list(
+                    new LambdaQueryWrapper<ImsEweiShopGoodsSpecItem>()
+                            .eq(ImsEweiShopGoodsSpecItem::getSpecid, specId)
+                            .eq(ImsEweiShopGoodsSpecItem::getUniacid, uniacid));
+            for (ImsEweiShopGoodsSpecItem specItem : specItems) {
+                b2cGoodsAttrMapper.insertAttrValue(
+                        specItem.getTitle(), attrId, specItem.getId().intValue());
+            }
+        }
+        return attrIds;
+    }
+
+    /**
+     * 保存商品属性关联到SPU的sale_attrs字段(对应PHP _saveGoodsAttr)
+     * 构建格式:["attrId_attrValId1", "attrId_attrValId2", ...]
+     */
+    private void saveGoodsAttrsToSpu(Integer gdId, List<Integer> attrIds) {
+        List<String> saleAttrList = new ArrayList<>();
+        for (Integer attrId : attrIds) {
+            List<Integer> attrValIds = b2cGoodsAttrMapper.findAttrValIdsByAttrId(attrId);
+            if (attrValIds != null) {
+                for (Integer attrValId : attrValIds) {
+                    saleAttrList.add(attrId + "_" + attrValId);
+                }
+            }
+        }
+        if (!saleAttrList.isEmpty()) {
+            B2cGoodsSpuInOnline updateSpu = new B2cGoodsSpuInOnline();
+            updateSpu.setGdId(gdId);
+            updateSpu.setSaleAttrs(JSON.toJSONString(saleAttrList));
+            b2cGoodsSpuInOnlineService.updateById(updateSpu);
+        }
+    }
+
+    /**
+     * 将企悦specItemId串转换为云商城attrValId串(对应PHP _saveSku中的sale_attrs映射)
+     * 例如:输入 "10_20" → 输出 "201_301"(其中201、301是b2c_attr_value中对应qy_id=10、20的attr_val_id)
+     */
+    private String mapSpecsToAttrValIds(String specs) {
+        if (specs == null || specs.isEmpty()) {
+            return "";
+        }
+        try {
+            String[] qyIds = specs.split("_");
+            StringBuilder mappedAttrs = new StringBuilder();
+            for (int i = 0; i < qyIds.length; i++) {
+                Integer qyId = Integer.valueOf(qyIds[i].trim());
+                Integer attrValId = b2cGoodsAttrMapper.findAttrValIdByQyId(qyId);
+                if (i > 0) mappedAttrs.append("_");
+                mappedAttrs.append(attrValId != null ? attrValId : qyId);
+            }
+            return mappedAttrs.toString();
+        } catch (Exception e) {
+            log.warn("规格ID映射失败,使用原始值 specs={}", specs, e);
+            return specs;
         }
         }
     }
     }
 
 
@@ -985,4 +1256,25 @@ public class CommodityProcureServiceImpl implements CommodityProcureService {
         log.info("供货/停止供货处理完成 goodsId={}, issupply={}", goodsId, issupply);
         log.info("供货/停止供货处理完成 goodsId={}, issupply={}", goodsId, issupply);
         return Result.success();
         return Result.success();
     }
     }
+
+    /**
+     * 安全转换为BigDecimal
+     */
+    private BigDecimal toBigDecimal(Object val) {
+        if (val == null) return BigDecimal.ZERO;
+        if (val instanceof BigDecimal) return (BigDecimal) val;
+        if (val instanceof Number) return new BigDecimal(val.toString());
+        try { return new BigDecimal(val.toString()); } catch (Exception e) { return BigDecimal.ZERO; }
+    }
+
+    /**
+     * 安全转换为Integer
+     */
+    private Integer toInteger(Object val) {
+        if (val == null) return 0;
+        if (val instanceof Integer) return (Integer) val;
+        if (val instanceof Number) return ((Number) val).intValue();
+        try { return Integer.valueOf(val.toString()); } catch (Exception e) { return 0; }
+    }
+
 }
 }