|
|
@@ -0,0 +1,696 @@
|
|
|
+package zs.payment.service.commodity.impl;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.context.annotation.Lazy;
|
|
|
+import org.springframework.data.mongodb.core.query.Criteria;
|
|
|
+import org.springframework.data.mongodb.core.query.Query;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import zs.payment.dao.yunmall.GoodsDao;
|
|
|
+import zs.payment.dto.yunmall.*;
|
|
|
+import zs.payment.entity.mongodb.yunmall.Goods;
|
|
|
+import zs.payment.entity.mongodb.yunmall.Sku;
|
|
|
+import zs.payment.entity.mysql.*;
|
|
|
+import zs.payment.entity.mysql.flymall.B2cGoodsImgInOnline;
|
|
|
+import zs.payment.entity.mysql.flymall.B2cGoodsSkuInOnline;
|
|
|
+import zs.payment.entity.mysql.flymall.B2cGoodsSpuInOnline;
|
|
|
+import zs.payment.entity.mysql.flymall.B2cShop;
|
|
|
+import zs.payment.exception.ApiException;
|
|
|
+import zs.payment.mapper.primary.ImsEweiShopApplyMapper;
|
|
|
+import zs.payment.mapper.primary.ImsEweiShopGoodsMapper;
|
|
|
+import zs.payment.req.CommodityProcureReq;
|
|
|
+import zs.payment.resp.Result;
|
|
|
+import zs.payment.service.Imseweishopgoods.ImsEweiShopGoodsService;
|
|
|
+import zs.payment.service.imseweishopcategory.ImsEweiShopCategoryService;
|
|
|
+import zs.payment.service.imseweishopgoodsoption.ImsEweiShopGoodsOptionService;
|
|
|
+import zs.payment.service.imseweishopgoodsparam.ImsEweiShopGoodsParamService;
|
|
|
+import zs.payment.service.imseweishopgoodsspec.ImsEweiShopGoodsSpecService;
|
|
|
+import zs.payment.service.imseweishopgoodsspecitem.ImsEweiShopGoodsSpecItemService;
|
|
|
+import zs.payment.service.commodity.CommodityProcureService;
|
|
|
+import zs.payment.service.flymall.b2cgoodsimginonline.B2cGoodsImgInOnlineService;
|
|
|
+import zs.payment.service.flymall.b2cgoodsskuinonline.B2cGoodsSkuInOnlineService;
|
|
|
+import zs.payment.service.flymall.b2cgoodsspuinonline.B2cGoodsSpuInOnlineService;
|
|
|
+import zs.payment.service.flymall.b2cshop.B2cShopService;
|
|
|
+
|
|
|
+import zs.payment.messages.KafkaProducer;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+public class CommodityProcureServiceImpl implements CommodityProcureService {
|
|
|
+
|
|
|
+ private static final String TOPIC_COMMODITY_PROCURE = "commodity.procure";
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ImsEweiShopGoodsService goodsService;
|
|
|
+ @Autowired
|
|
|
+ private ImsEweiShopGoodsSpecService specService;
|
|
|
+ @Autowired
|
|
|
+ private ImsEweiShopGoodsSpecItemService specItemService;
|
|
|
+ @Autowired
|
|
|
+ private ImsEweiShopGoodsOptionService optionService;
|
|
|
+ @Autowired
|
|
|
+ private ImsEweiShopGoodsParamService paramService;
|
|
|
+ @Autowired
|
|
|
+ private ImsEweiShopApplyMapper applyMapper;
|
|
|
+ @Autowired
|
|
|
+ private ImsEweiShopGoodsMapper goodsMapper;
|
|
|
+ @Autowired
|
|
|
+ private ImsEweiShopCategoryService categoryService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private GoodsDao goodsDao;
|
|
|
+ @Autowired
|
|
|
+ private B2cGoodsSpuInOnlineService b2cGoodsSpuInOnlineService;
|
|
|
+ @Autowired
|
|
|
+ private B2cGoodsSkuInOnlineService b2cGoodsSkuInOnlineService;
|
|
|
+ @Autowired
|
|
|
+ private B2cGoodsImgInOnlineService b2cGoodsImgInOnlineService;
|
|
|
+ @Autowired
|
|
|
+ private B2cShopService b2cShopService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private KafkaProducer kafkaProducer;
|
|
|
+
|
|
|
+ @Lazy
|
|
|
+ @Autowired
|
|
|
+ private CommodityProcureService self;
|
|
|
+
|
|
|
+ private static final BigDecimal HUNDRED = new BigDecimal("100");
|
|
|
+ private static final BigDecimal COMMISSION_DEFAULT_RATE = new BigDecimal("0.01");
|
|
|
+ private static final Integer JD_SHOP_ID = 11507;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Result procureGoods(CommodityProcureReq req) {
|
|
|
+ Integer uniacid = req.getUniacid();
|
|
|
+ List<Long> cates = req.getCates();
|
|
|
+
|
|
|
+ // 1. 从MongoDB goods表查询符合条件的gdIds
|
|
|
+ List<Long> gdIds = searchGdIdsFromMongo(req.getPtIds(), req.getShopId(), req.getKeyWord());
|
|
|
+ if (gdIds.isEmpty()) {
|
|
|
+ return Result.fail("未搜索到符合条件的商品");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 查询资质
|
|
|
+ ImsEweiShopApply apply = applyMapper.selectOne(new LambdaQueryWrapper<ImsEweiShopApply>()
|
|
|
+ .eq(ImsEweiShopApply::getUniacid, uniacid)
|
|
|
+ .eq(ImsEweiShopApply::getMerchid, 0)
|
|
|
+ .eq(ImsEweiShopApply::getMallStatus, 1)
|
|
|
+ .eq(ImsEweiShopApply::getShopStatus, 1)
|
|
|
+ .eq(ImsEweiShopApply::getStockstatus, 1)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ if (apply == null || apply.getMallid() == null) {
|
|
|
+ throw new ApiException("资质审核未通过,无法进货");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 异步发送Kafka消息,逐条进货
|
|
|
+ for (Long gdId : gdIds) {
|
|
|
+ JSONObject msg = new JSONObject();
|
|
|
+ msg.put("uniacid", uniacid);
|
|
|
+ msg.put("gdId", gdId);
|
|
|
+ msg.put("mallid", apply.getMallid());
|
|
|
+ msg.put("cates", cates);
|
|
|
+ kafkaProducer.sendMessage(TOPIC_COMMODITY_PROCURE, msg.toJSONString());
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("进货任务已提交,共{}个商品待处理", gdIds.size());
|
|
|
+ return Result.success("进货任务已提交,共" + gdIds.size() + "个商品将异步处理");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result procureSingleGoods(Integer uniacid, Integer gdId, Integer mallid, List<Long> cates) {
|
|
|
+ CategoryResolveResult categoryResult = resolveCategories(cates);
|
|
|
+ return procureSingleGoods(uniacid, gdId, mallid, categoryResult);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Result procureSingleGoods(Integer uniacid, Integer gdId, Integer mallid,
|
|
|
+ CategoryResolveResult categoryResult) {
|
|
|
+ // 1. 从MongoDB查询商品基本信息(含shop、skus含attrs、gd_imgs)
|
|
|
+ Query mongoQuery = new Query(Criteria.where("gd_id").is(gdId));
|
|
|
+ Goods mongoGoods = goodsDao.queryOne(mongoQuery);
|
|
|
+
|
|
|
+ // 2. 从MySQL flymall查询商品详细信息
|
|
|
+ B2cGoodsSpuInOnline spu = b2cGoodsSpuInOnlineService.getById(gdId);
|
|
|
+ if (spu == null) {
|
|
|
+ throw new ApiException("云商城商品数据为空: gdId=" + gdId);
|
|
|
+ }
|
|
|
+ List<B2cGoodsSkuInOnline> dbSkuList = b2cGoodsSkuInOnlineService.findByGdId(String.valueOf(gdId));
|
|
|
+ List<B2cGoodsImgInOnline> dbImgList = b2cGoodsImgInOnlineService.findByGdId(String.valueOf(gdId));
|
|
|
+ B2cShop b2cShop = b2cShopService.getById(spu.getShopId());
|
|
|
+
|
|
|
+ // 3. 构建CloudMallGoods(保持下游逻辑不变)
|
|
|
+ CloudMallGoods yunGoods = buildCloudMallGoods(spu, b2cShop, dbImgList, mongoGoods);
|
|
|
+
|
|
|
+ // 4. 构建attrList(从MongoDB skus的attrs聚合)
|
|
|
+ boolean hasSpec = mongoGoods != null && mongoGoods.getSkus() != null
|
|
|
+ && mongoGoods.getSkus().stream().anyMatch(s -> s.getAttrs() != null && !s.getAttrs().isEmpty());
|
|
|
+ List<CloudMallAttr> attrList = hasSpec ? buildAttrList(mongoGoods.getSkus()) : new ArrayList<>();
|
|
|
+
|
|
|
+ // 5. 构建skuList map
|
|
|
+ Map<String, CloudMallSku> skuMap = buildSkuMap(mongoGoods, dbSkuList);
|
|
|
+
|
|
|
+ // 6. 构建nomalattrList(从spu.normal_attrs解析)
|
|
|
+ List<CloudMallNormalAttr> nomalattrList = parseNormalAttrs(spu.getNormalAttrs());
|
|
|
+
|
|
|
+ // 7. 组装CloudMallGoodsBody
|
|
|
+ CloudMallGoodsBody body = new CloudMallGoodsBody();
|
|
|
+ body.setGoods(yunGoods);
|
|
|
+ body.setAttrList(attrList);
|
|
|
+ body.setNomalattrList(nomalattrList);
|
|
|
+ body.setSkuList(skuMap);
|
|
|
+
|
|
|
+ // 8. 构建商品实体
|
|
|
+ ImsEweiShopGoods goods = buildGoodsEntity(uniacid, gdId, yunGoods, categoryResult, hasSpec);
|
|
|
+
|
|
|
+ // 9. 插入商品
|
|
|
+ goodsService.save(goods);
|
|
|
+ Long goodsId = goods.getId();
|
|
|
+ log.info("进货商品插入成功 gdId={}, goodsId={}", gdId, goodsId);
|
|
|
+
|
|
|
+ // 10. 处理规格和SKU
|
|
|
+ if (!hasSpec) {
|
|
|
+ handleNoSpec(goodsId, uniacid, body, yunGoods);
|
|
|
+ } else {
|
|
|
+ Map<Integer, Long> yunSpecItemIdMap = handleSpecs(goodsId, uniacid, body);
|
|
|
+ handleOptions(goodsId, uniacid, body, yunGoods, yunSpecItemIdMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 11. 计算生态分佣
|
|
|
+ recalculateFenyonglmb(goodsId);
|
|
|
+
|
|
|
+ // 12. 插入商品参数
|
|
|
+ if (body.getNomalattrList() != null) {
|
|
|
+ for (int k = 0; k < body.getNomalattrList().size(); k++) {
|
|
|
+ CloudMallNormalAttr attr = body.getNomalattrList().get(k);
|
|
|
+ ImsEweiShopGoodsParam param = new ImsEweiShopGoodsParam();
|
|
|
+ param.setUniacid(uniacid);
|
|
|
+ param.setTitle(attr.getAttr_name());
|
|
|
+ param.setValue(attr.getAttr_val_name());
|
|
|
+ param.setDisplayorder(k);
|
|
|
+ param.setGoodsid(goodsId.intValue());
|
|
|
+ paramService.save(param);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Result.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 私有方法 ====================
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从MongoDB goods表搜索符合条件的gdIds(参考qiyueGoodsSearch逻辑)
|
|
|
+ */
|
|
|
+ private List<Long> searchGdIdsFromMongo(List<Long> ptIds, Long shopId, String keyWord) {
|
|
|
+ Criteria criteria = new Criteria();
|
|
|
+ // pt_id in ptIds
|
|
|
+ if (ptIds != null && !ptIds.isEmpty()) {
|
|
|
+ criteria.and("pt_id").in(ptIds);
|
|
|
+ }
|
|
|
+ // 排除自身店铺
|
|
|
+ if (shopId != null) {
|
|
|
+ criteria.and("shop.shop_id").ne(shopId);
|
|
|
+ }
|
|
|
+ // 排除自主结算型店铺(shop_type=4)
|
|
|
+ criteria.and("shop.shop_type").ne(4);
|
|
|
+ // 必须有有效SKU
|
|
|
+ criteria.and("skus.sku_id").gt(0);
|
|
|
+ // 关键字搜索(商品名称模糊匹配)
|
|
|
+ if (keyWord != null && !keyWord.trim().isEmpty()) {
|
|
|
+ criteria.and("gd_name").regex(".*" + keyWord.trim() + ".*", "i");
|
|
|
+ }
|
|
|
+
|
|
|
+ Query query = new Query(criteria);
|
|
|
+ // 只查gd_id字段,提高查询效率
|
|
|
+ query.fields().include("gd_id");
|
|
|
+// query.limit(1);
|
|
|
+ List<Goods> goodsList = goodsDao.queryList(query);
|
|
|
+ return goodsList.stream().map(Goods::getGdId).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建CloudMallGoods(从MySQL+MongoDB数据组装,替代原HTTP接口返回)
|
|
|
+ */
|
|
|
+ private CloudMallGoods buildCloudMallGoods(B2cGoodsSpuInOnline spu, B2cShop b2cShop,
|
|
|
+ List<B2cGoodsImgInOnline> dbImgList, Goods mongoGoods) {
|
|
|
+ CloudMallGoods yunGoods = new CloudMallGoods();
|
|
|
+ yunGoods.setGd_name(spu.getGdName());
|
|
|
+ yunGoods.setUnit(spu.getGdUnit());
|
|
|
+ yunGoods.setWeight(spu.getGdWeight() != null ? BigDecimal.valueOf(spu.getGdWeight()) : BigDecimal.ZERO);
|
|
|
+ yunGoods.setDesc(spu.getGdDesc());
|
|
|
+ yunGoods.setStatement_rate(spu.getCommissionRatio());
|
|
|
+ yunGoods.setTg_statement_rate(spu.getTgCommissionRatio());
|
|
|
+
|
|
|
+ // Shop
|
|
|
+ CloudMallShop shop = new CloudMallShop();
|
|
|
+ if (b2cShop != null) {
|
|
|
+ shop.setShop_id(b2cShop.getShopId());
|
|
|
+ shop.setShop_name(b2cShop.getShopName());
|
|
|
+ } else if (mongoGoods != null && mongoGoods.getShop() != null) {
|
|
|
+ shop.setShop_id(mongoGoods.getShop().getShop_id());
|
|
|
+ shop.setShop_name(mongoGoods.getShop().getShop_name());
|
|
|
+ }
|
|
|
+ yunGoods.setShop(shop);
|
|
|
+
|
|
|
+ // Images
|
|
|
+ List<CloudMallImg> imgsInfo = new ArrayList<>();
|
|
|
+ for (B2cGoodsImgInOnline img : dbImgList) {
|
|
|
+ CloudMallImg ci = new CloudMallImg();
|
|
|
+ ci.setImgUrl(img.getGdImg());
|
|
|
+ imgsInfo.add(ci);
|
|
|
+ }
|
|
|
+ yunGoods.setImgsInfo(imgsInfo);
|
|
|
+
|
|
|
+ return yunGoods;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从MongoDB skus的attrs聚合构建attrList(参考Groovy goodsDetail逻辑)
|
|
|
+ */
|
|
|
+ private List<CloudMallAttr> buildAttrList(List<Sku> skus) {
|
|
|
+ Map<Integer, CloudMallAttr> attrMap = new LinkedHashMap<>();
|
|
|
+ for (Sku sku : skus) {
|
|
|
+ if (sku.getAttrs() == null) continue;
|
|
|
+ for (Sku.SkuAttr attr : sku.getAttrs()) {
|
|
|
+ CloudMallAttr existing = attrMap.get(attr.getAttr_id());
|
|
|
+ if (existing == null) {
|
|
|
+ existing = new CloudMallAttr();
|
|
|
+ existing.setAttr_id(attr.getAttr_id());
|
|
|
+ existing.setAttr_name(attr.getAttr_name());
|
|
|
+ existing.setValues(new ArrayList<>());
|
|
|
+ attrMap.put(attr.getAttr_id(), existing);
|
|
|
+ }
|
|
|
+ // 去重添加attr_val
|
|
|
+ boolean valExists = existing.getValues().stream()
|
|
|
+ .anyMatch(v -> v.getAttr_val_id().equals(attr.getAttr_val_id()));
|
|
|
+ if (!valExists) {
|
|
|
+ CloudMallAttrValue val = new CloudMallAttrValue();
|
|
|
+ val.setAttr_val_id(attr.getAttr_val_id());
|
|
|
+ val.setAttr_val_name(attr.getAttr_val_name());
|
|
|
+ existing.getValues().add(val);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return new ArrayList<>(attrMap.values());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建skuList map(MongoDB结构数据 + MySQL价格/库存)
|
|
|
+ */
|
|
|
+ private Map<String, CloudMallSku> buildSkuMap(Goods mongoGoods, List<B2cGoodsSkuInOnline> dbSkuList) {
|
|
|
+ Map<String, CloudMallSku> skuMap = new LinkedHashMap<>();
|
|
|
+ if (mongoGoods == null || mongoGoods.getSkus() == null || mongoGoods.getSkus().isEmpty()) {
|
|
|
+ // 无MongoDB数据时,直接用MySQL SKU构建
|
|
|
+ for (B2cGoodsSkuInOnline dbSku : dbSkuList) {
|
|
|
+ CloudMallSku cloudSku = new CloudMallSku();
|
|
|
+ cloudSku.setSku_id(dbSku.getSkuId());
|
|
|
+ cloudSku.setSku_price(dbSku.getGdPrice());
|
|
|
+ cloudSku.setCost_price(dbSku.getCostPrice());
|
|
|
+ cloudSku.setMk_price(dbSku.getMkPrice());
|
|
|
+ cloudSku.setStock(dbSku.getGdStock());
|
|
|
+ skuMap.put("sku_" + dbSku.getSkuId(), cloudSku);
|
|
|
+ }
|
|
|
+ return skuMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ // MySQL skuId -> B2cGoodsSkuInOnline 映射
|
|
|
+ Map<Integer, B2cGoodsSkuInOnline> dbSkuMap = dbSkuList.stream()
|
|
|
+ .collect(Collectors.toMap(B2cGoodsSkuInOnline::getSkuId, s -> s, (a, b) -> a));
|
|
|
+
|
|
|
+ for (Sku mongoSku : mongoGoods.getSkus()) {
|
|
|
+ B2cGoodsSkuInOnline dbSku = dbSkuMap.get(mongoSku.getSku_id());
|
|
|
+ if (dbSku == null) continue;
|
|
|
+
|
|
|
+ String skuKey;
|
|
|
+ String attrValNameStr = "";
|
|
|
+ if (mongoSku.getAttrs() != null && !mongoSku.getAttrs().isEmpty()) {
|
|
|
+ skuKey = "sku_" + mongoSku.getAttrs().stream()
|
|
|
+ .map(a -> String.valueOf(a.getAttr_val_id()))
|
|
|
+ .sorted()
|
|
|
+ .collect(Collectors.joining("_"));
|
|
|
+ attrValNameStr = mongoSku.getAttrs().stream()
|
|
|
+ .map(Sku.SkuAttr::getAttr_val_name)
|
|
|
+ .collect(Collectors.joining("+"));
|
|
|
+ } else {
|
|
|
+ skuKey = "sku_" + mongoSku.getSku_id();
|
|
|
+ }
|
|
|
+
|
|
|
+ CloudMallSku cloudSku = new CloudMallSku();
|
|
|
+ cloudSku.setSku_id(dbSku.getSkuId());
|
|
|
+ cloudSku.setSku_price(dbSku.getGdPrice());
|
|
|
+ cloudSku.setCost_price(dbSku.getCostPrice());
|
|
|
+ cloudSku.setMk_price(dbSku.getMkPrice());
|
|
|
+ cloudSku.setStock(dbSku.getGdStock());
|
|
|
+ cloudSku.setSku_img(mongoSku.getSku_img());
|
|
|
+ cloudSku.setAttr_val_name_str(attrValNameStr);
|
|
|
+
|
|
|
+ skuMap.put(skuKey, cloudSku);
|
|
|
+ }
|
|
|
+ return skuMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析normal_attrs为CloudMallNormalAttr列表
|
|
|
+ * normal_attrs格式:{"attr_id":["val1","val2"],...}
|
|
|
+ * 注:完整的attr_name需要查询ptmall的attr表,此处使用attr_id作为降级
|
|
|
+ */
|
|
|
+ private List<CloudMallNormalAttr> parseNormalAttrs(String normalAttrs) {
|
|
|
+ List<CloudMallNormalAttr> result = new ArrayList<>();
|
|
|
+ if (normalAttrs == null || normalAttrs.trim().isEmpty()) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ JSONObject attrsJson = JSONObject.parseObject(normalAttrs);
|
|
|
+ for (String attrIdKey : attrsJson.keySet()) {
|
|
|
+ CloudMallNormalAttr attr = new CloudMallNormalAttr();
|
|
|
+ attr.setAttr_name(attrIdKey);
|
|
|
+ List<Object> valList = attrsJson.getJSONArray(attrIdKey).toJavaList(Object.class);
|
|
|
+ String valStr = valList.stream().map(Object::toString).sorted().collect(Collectors.joining(","));
|
|
|
+ attr.setAttr_val_name(valStr);
|
|
|
+ result.add(attr);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("解析normal_attrs失败: {}", normalAttrs, e);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建商品实体
|
|
|
+ */
|
|
|
+ private ImsEweiShopGoods buildGoodsEntity(Integer uniacid, Integer gdId, CloudMallGoods yunGoods,
|
|
|
+ CategoryResolveResult categoryResult, boolean hasSpec) {
|
|
|
+ ImsEweiShopGoods goods = new ImsEweiShopGoods();
|
|
|
+ goods.setCommoditytype(1);
|
|
|
+ goods.setGd_id(gdId);
|
|
|
+ goods.setUniacid(uniacid);
|
|
|
+ goods.setTitle(yunGoods.getGd_name());
|
|
|
+ goods.setUnit(yunGoods.getUnit());
|
|
|
+ goods.setType(1);
|
|
|
+ goods.setStatus(1);
|
|
|
+ goods.setWeight(yunGoods.getWeight());
|
|
|
+ goods.setHasoption(hasSpec ? 1 : 0);
|
|
|
+ goods.setContent(yunGoods.getDesc());
|
|
|
+ goods.setCreatetime(System.currentTimeMillis() / 1000);
|
|
|
+ goods.setInvoice(1);
|
|
|
+ goods.setThumb_first(1);
|
|
|
+ goods.setIssendfree(1);
|
|
|
+
|
|
|
+ // 京东判断
|
|
|
+ boolean isJd = yunGoods.getShop() != null && JD_SHOP_ID.equals(yunGoods.getShop().getShop_id());
|
|
|
+ goods.setIsjingdong(isJd ? 1 : 0);
|
|
|
+ if (yunGoods.getShop() != null) {
|
|
|
+ goods.setMerchid(isJd ? -JD_SHOP_ID : -yunGoods.getShop().getShop_id());
|
|
|
+ goods.setYsh_merchname(yunGoods.getShop().getShop_name());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 分类
|
|
|
+ if (categoryResult != null) {
|
|
|
+ goods.setCates(joinList(categoryResult.getCates()));
|
|
|
+ goods.setPcates(joinList(categoryResult.getPcates()));
|
|
|
+ goods.setCcates(joinList(categoryResult.getCcates()));
|
|
|
+ goods.setTcates(joinList(categoryResult.getTcates()));
|
|
|
+ goods.setPcate(categoryResult.getPcate());
|
|
|
+ goods.setCcate(categoryResult.getCcate());
|
|
|
+ goods.setTcate(categoryResult.getTcate());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 折扣
|
|
|
+ JSONObject discounts = new JSONObject();
|
|
|
+ discounts.put("type", 0);
|
|
|
+ discounts.put("default", "");
|
|
|
+ discounts.put("default_pay", "");
|
|
|
+ goods.setDiscounts(discounts.toJSONString());
|
|
|
+
|
|
|
+ // 图片
|
|
|
+ if (yunGoods.getImgsInfo() != null && !yunGoods.getImgsInfo().isEmpty()) {
|
|
|
+ goods.setThumb(yunGoods.getImgsInfo().get(0).getImgUrl());
|
|
|
+ if (yunGoods.getImgsInfo().size() > 1) {
|
|
|
+ List<String> imgUrlList = yunGoods.getImgsInfo().stream()
|
|
|
+ .skip(1)
|
|
|
+ .map(CloudMallImg::getImgUrl)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ goods.setThumb_url(JSON.toJSONString(imgUrlList));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return goods;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 无规格商品处理
|
|
|
+ */
|
|
|
+ private void handleNoSpec(Long goodsId, Integer uniacid, CloudMallGoodsBody body, CloudMallGoods yunGoods) {
|
|
|
+ Map<String, CloudMallSku> skuList = body.getSkuList();
|
|
|
+ if (skuList == null || skuList.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 取唯一SKU
|
|
|
+ CloudMallSku sku = skuList.values().iterator().next();
|
|
|
+
|
|
|
+ BigDecimal costprice = calculateCostPrice(sku.getSku_price(), sku.getCost_price(),
|
|
|
+ yunGoods.getStatement_rate(), yunGoods.getTg_statement_rate());
|
|
|
+ BigDecimal fenyonglmb = sku.getSku_price().multiply(COMMISSION_DEFAULT_RATE)
|
|
|
+ .setScale(2, RoundingMode.HALF_UP);
|
|
|
+
|
|
|
+ ImsEweiShopGoods update = new ImsEweiShopGoods();
|
|
|
+ update.setId(goodsId);
|
|
|
+ update.setProductprice(sku.getMk_price());
|
|
|
+ update.setCostprice(costprice);
|
|
|
+ update.setMarketprice(sku.getSku_price());
|
|
|
+ update.setTotal(sku.getStock());
|
|
|
+ update.setWeight(yunGoods.getWeight());
|
|
|
+ update.setThumb(sku.getSku_img());
|
|
|
+ update.setHasoption(0);
|
|
|
+ update.setMinprice(sku.getSku_price());
|
|
|
+ update.setMaxprice(sku.getSku_price());
|
|
|
+ update.setFenyonglmb(fenyonglmb);
|
|
|
+ goodsService.updateById(update);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 有规格商品处理:插入规格和规格项
|
|
|
+ *
|
|
|
+ * @return yunspecitemid -> 本地spec_item_id 的映射
|
|
|
+ */
|
|
|
+ private Map<Integer, Long> handleSpecs(Long goodsId, Integer uniacid, CloudMallGoodsBody body) {
|
|
|
+ Map<Integer, Long> yunSpecItemIdMap = new HashMap<>();
|
|
|
+ List<CloudMallAttr> attrList = body.getAttrList();
|
|
|
+
|
|
|
+ for (int k = 0; k < attrList.size(); k++) {
|
|
|
+ CloudMallAttr attr = attrList.get(k);
|
|
|
+
|
|
|
+ // 插入规格
|
|
|
+ ImsEweiShopGoodsSpec spec = new ImsEweiShopGoodsSpec();
|
|
|
+ spec.setUniacid(uniacid);
|
|
|
+ spec.setGoodsid(goodsId.intValue());
|
|
|
+ spec.setDisplayorder(k);
|
|
|
+ spec.setTitle(attr.getAttr_name());
|
|
|
+ spec.setYunspecid(attr.getAttr_id());
|
|
|
+ specService.save(spec);
|
|
|
+ Long specId = spec.getId();
|
|
|
+
|
|
|
+ // 插入规格项
|
|
|
+ if (attr.getValues() != null) {
|
|
|
+ for (int n = 0; n < attr.getValues().size(); n++) {
|
|
|
+ CloudMallAttrValue attrVal = attr.getValues().get(n);
|
|
|
+ ImsEweiShopGoodsSpecItem specItem = new ImsEweiShopGoodsSpecItem();
|
|
|
+ specItem.setUniacid(uniacid);
|
|
|
+ specItem.setSpecid(specId.intValue());
|
|
|
+ specItem.setDisplayorder(n);
|
|
|
+ specItem.setTitle(attrVal.getAttr_val_name());
|
|
|
+ specItem.setShowVar(1);
|
|
|
+ specItem.setThumb("");
|
|
|
+ specItem.setVirtualVar(0);
|
|
|
+ specItem.setYunspecitemid(attrVal.getAttr_val_id());
|
|
|
+ specItemService.save(specItem);
|
|
|
+
|
|
|
+ // 建立映射
|
|
|
+ yunSpecItemIdMap.put(attrVal.getAttr_val_id(), specItem.getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return yunSpecItemIdMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 有规格商品处理:插入SKU选项
|
|
|
+ */
|
|
|
+ private void handleOptions(Long goodsId, Integer uniacid, CloudMallGoodsBody body,
|
|
|
+ CloudMallGoods yunGoods, Map<Integer, Long> yunSpecItemIdMap) {
|
|
|
+ Map<String, CloudMallSku> skuList = body.getSkuList();
|
|
|
+ if (skuList == null || skuList.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ int totalStocks = 0;
|
|
|
+ for (Map.Entry<String, CloudMallSku> entry : skuList.entrySet()) {
|
|
|
+ String key = entry.getKey();
|
|
|
+ CloudMallSku sku = entry.getValue();
|
|
|
+
|
|
|
+ // 解析规格key(如 "123_456_sku")
|
|
|
+ String[] parts = key.split("_");
|
|
|
+ List<Long> localSpecIds = new ArrayList<>();
|
|
|
+ for (String part : parts) {
|
|
|
+ if (part.isEmpty() || "sku".equals(part)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ Integer yunSpecItemId = Integer.valueOf(part);
|
|
|
+ Long localId = yunSpecItemIdMap.get(yunSpecItemId);
|
|
|
+ if (localId != null) {
|
|
|
+ localSpecIds.add(localId);
|
|
|
+ }
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ // 忽略非数字部分
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String specs = localSpecIds.stream().map(String::valueOf).collect(Collectors.joining("_"));
|
|
|
+
|
|
|
+ BigDecimal costprice = calculateCostPrice(sku.getSku_price(), sku.getCost_price(),
|
|
|
+ yunGoods.getStatement_rate(), yunGoods.getTg_statement_rate());
|
|
|
+
|
|
|
+ ImsEweiShopGoodsOption option = new ImsEweiShopGoodsOption();
|
|
|
+ option.setUniacid(uniacid);
|
|
|
+ option.setTitle(sku.getAttr_val_name_str());
|
|
|
+ option.setProductprice(sku.getMk_price());
|
|
|
+ option.setCostprice(costprice);
|
|
|
+ option.setMarketprice(sku.getSku_price());
|
|
|
+ option.setStock(sku.getStock());
|
|
|
+ option.setWeight(yunGoods.getWeight());
|
|
|
+ option.setGoodsid(goodsId.intValue());
|
|
|
+ option.setSpecs(specs);
|
|
|
+ option.setVirtual(0);
|
|
|
+ option.setSku_id(sku.getSku_id());
|
|
|
+ option.setThumb(sku.getSku_img());
|
|
|
+ optionService.save(option);
|
|
|
+
|
|
|
+ totalStocks += sku.getStock();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从option子查询更新goods价格
|
|
|
+ goodsMapper.updateGoodsPriceByOption(goodsId);
|
|
|
+
|
|
|
+ // 更新总库存
|
|
|
+ ImsEweiShopGoods updateStock = new ImsEweiShopGoods();
|
|
|
+ updateStock.setId(goodsId);
|
|
|
+ updateStock.setTotal(totalStocks);
|
|
|
+ goodsService.updateById(updateStock);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算并更新生态分佣金额
|
|
|
+ */
|
|
|
+ private void recalculateFenyonglmb(Long goodsId) {
|
|
|
+ ImsEweiShopGoods goods = goodsService.getById(goodsId);
|
|
|
+ if (goods != null && goods.getMinprice() != null) {
|
|
|
+ BigDecimal fenyonglmb = goods.getMinprice().multiply(COMMISSION_DEFAULT_RATE)
|
|
|
+ .setScale(2, RoundingMode.HALF_UP);
|
|
|
+ ImsEweiShopGoods update = new ImsEweiShopGoods();
|
|
|
+ update.setId(goodsId);
|
|
|
+ update.setFenyonglmb(fenyonglmb);
|
|
|
+ goodsService.updateById(update);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析分类(对应PHP reust_cates方法)
|
|
|
+ */
|
|
|
+ private CategoryResolveResult resolveCategories(List<Long> cates) {
|
|
|
+ CategoryResolveResult result = new CategoryResolveResult();
|
|
|
+ List<Long> pcates = new ArrayList<>();
|
|
|
+ List<Long> ccates = new ArrayList<>();
|
|
|
+ List<Long> tcates = new ArrayList<>();
|
|
|
+ long pcateid = 0, ccateid = 0, tcateid = 0;
|
|
|
+
|
|
|
+ for (int i = 0; i < cates.size(); i++) {
|
|
|
+ Long cid = cates.get(i);
|
|
|
+ ImsEweiShopCategory category = categoryService.getById(cid);
|
|
|
+ if (category == null || category.getLevel() == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int level = category.getLevel();
|
|
|
+
|
|
|
+ if (level == 1) {
|
|
|
+ pcates.add(cid);
|
|
|
+ } else if (level == 2) {
|
|
|
+ ccates.add(cid);
|
|
|
+ } else if (level == 3) {
|
|
|
+ tcates.add(cid);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 第一个分类特殊处理(1.x兼容)
|
|
|
+ if (i == 0) {
|
|
|
+ if (level == 1) {
|
|
|
+ pcateid = cid;
|
|
|
+ } else if (level == 2) {
|
|
|
+ ccateid = cid;
|
|
|
+ if (category.getParentId() != null) {
|
|
|
+ pcateid = category.getParentId().longValue();
|
|
|
+ }
|
|
|
+ } else if (level == 3) {
|
|
|
+ tcateid = cid;
|
|
|
+ if (category.getParentId() != null) {
|
|
|
+ ImsEweiShopCategory parent = categoryService.getById(category.getParentId().longValue());
|
|
|
+ if (parent != null) {
|
|
|
+ ccateid = parent.getId();
|
|
|
+ if (parent.getParentId() != null) {
|
|
|
+ pcateid = parent.getParentId().longValue();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ result.setPcate(pcateid);
|
|
|
+ result.setCcate(ccateid);
|
|
|
+ result.setTcate(tcateid);
|
|
|
+ result.setCates(cates);
|
|
|
+ result.setPcates(pcates);
|
|
|
+ result.setCcates(ccates);
|
|
|
+ result.setTcates(tcates);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算成本价
|
|
|
+ * 公式:cost_price有值则取cost_price,否则 sku_price * (100 - statement_rate - tg_statement_rate) / 100
|
|
|
+ */
|
|
|
+ private BigDecimal calculateCostPrice(BigDecimal skuPrice, BigDecimal costPrice,
|
|
|
+ BigDecimal statementRate, BigDecimal tgStatementRate) {
|
|
|
+ if (costPrice != null && costPrice.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ return costPrice.setScale(2, RoundingMode.HALF_UP);
|
|
|
+ }
|
|
|
+ if (statementRate == null) {
|
|
|
+ statementRate = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ if (tgStatementRate == null) {
|
|
|
+ tgStatementRate = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ return skuPrice.multiply(HUNDRED.subtract(statementRate).subtract(tgStatementRate))
|
|
|
+ .divide(HUNDRED, 2, RoundingMode.HALF_UP);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * List<Long> 逗号拼接
|
|
|
+ */
|
|
|
+ private String joinList(List<Long> list) {
|
|
|
+ if (list == null || list.isEmpty()) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ return list.stream().map(String::valueOf).collect(Collectors.joining(","));
|
|
|
+ }
|
|
|
+}
|