From b915389954cc4649966ef63edce7f0ecceb80252 Mon Sep 17 00:00:00 2001 From: wangw <1594593906@qq.com> Date: Wed, 9 Apr 2025 18:23:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=95=E4=B8=AA=20=E5=8F=98=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../czg/product/service/ShopSyncService.java | 64 +++ .../service/impl/ShopConfigServiceImpl.java | 3 +- .../service/impl/ShopSyncServiceImpl.java | 449 +++++++++++++++++- 3 files changed, 508 insertions(+), 8 deletions(-) diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/service/ShopSyncService.java b/cash-common/cash-common-service/src/main/java/com/czg/product/service/ShopSyncService.java index e283aa275..3a3927ff4 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/product/service/ShopSyncService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/service/ShopSyncService.java @@ -8,9 +8,73 @@ public interface ShopSyncService { /** * 同步数据 将源店铺信息 同步到目标店铺(包括分组 分类 单位 规格 商品 SKU 耗材) + * * @param sourceShopId 源店铺ID * @param targetShopId 目标店铺ID */ void sync(Long sourceShopId, Long targetShopId); + /** + * 同步单位(新增/修改字段/逻辑删除 不包含删除) 将源店铺的单位同步到 开了同步商品开关的子店铺 + * + * @param sourceShopId 主店ID + * @param unitId 主店单位Id + */ + void syncUnitBySourceShop(Long sourceShopId, Long unitId); + + /** + * 同步规格(新增/修改字段/逻辑删除 不包含删除) 将源店铺的规格同步到 开了同步商品开关的子店铺 + * + * @param sourceShopId 主店ID + * @param specId 主店规格Id + */ + void syncSpecBySourceShop(Long sourceShopId, Long specId); + + /** + * 同步分类(新增/修改字段/逻辑删除 不包含删除) 将源店铺的分类同步到 开了同步商品开关的子店铺 + * + * @param sourceShopId 主店ID + * @param categoryId 主店分类Id + */ + void syncCategoryBySourceShop(Long sourceShopId, Long categoryId); + + /** + * 同步商品 会同步Sku(新增/修改字段/逻辑删除 不包含删除) 将源店铺的商品同步到 开了同步商品开关的子店铺 + * + * @param sourceShopId 主店ID + * @param productId 主店商品Id + */ + void syncProductBySourceShop(Long sourceShopId, Long productId); + + /** + * 同步分组 (新增/修改字段/逻辑删除 不包含删除) 将源店铺的分组同步到 开了同步商品开关的子店铺 + * + * @param sourceShopId 主店ID + * @param groupId 主店分组Id + */ + void syncGroupBySourceShop(Long sourceShopId, Long groupId); + + /** + * 同步耗材分组 (新增/修改字段/逻辑删除 不包含删除) 将源店铺的耗材分组同步到 开了同步耗材开关的子店铺 + * + * @param sourceShopId 主店ID + * @param consGroupId 主店耗材分组Id + */ + void syncConsGroupBySourceShop(Long sourceShopId, Long consGroupId); + + /** + * 同步耗材信息(新增/修改字段/逻辑删除 不包含删除) 将源店铺的耗材信息同步到 开了同步耗材开关的子店铺 + * + * @param sourceShopId 主店ID + * @param consInfoId 主店ID + */ + void syncConsInfoBySourceShop(Long sourceShopId, Long consInfoId); + + /** + * 同步商品绑定耗材关联关系 开了同步耗材开关的子店铺 + * + * @param sourceShopId 主店ID + * @param sourceProdId 主店商品ID + */ + void syncConsProBySourceShop(Long sourceShopId, Long sourceProdId); } diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopConfigServiceImpl.java b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopConfigServiceImpl.java index d9bd07095..eb7486eeb 100644 --- a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopConfigServiceImpl.java +++ b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopConfigServiceImpl.java @@ -10,6 +10,7 @@ import com.czg.utils.PageUtil; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.spring.service.impl.ServiceImpl; import jakarta.annotation.Resource; +import org.apache.dubbo.config.annotation.DubboService; import org.springframework.stereotype.Service; /** @@ -18,7 +19,7 @@ import org.springframework.stereotype.Service; * @author Tankaikai tankaikai@aliyun.com * @since 1.0 2025-04-03 */ -@Service +@DubboService public class ShopConfigServiceImpl extends ServiceImpl implements ShopConfigService { @Resource diff --git a/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/ShopSyncServiceImpl.java b/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/ShopSyncServiceImpl.java index 65ea14b2a..e9c002f48 100644 --- a/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/ShopSyncServiceImpl.java +++ b/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/ShopSyncServiceImpl.java @@ -3,9 +3,14 @@ package com.czg.service.product.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; +import com.alibaba.fastjson2.JSONWriter; +import com.czg.account.entity.ShopConfig; import com.czg.account.entity.ShopInfo; +import com.czg.account.service.ShopConfigService; import com.czg.account.service.ShopInfoService; import com.czg.account.service.ShopUserService; import com.czg.account.service.SyncNoticeService; @@ -14,20 +19,20 @@ import com.czg.product.entity.*; import com.czg.product.service.*; import com.czg.product.vo.ProductGroupVo; import com.czg.utils.AssertUtil; +import com.mybatisflex.core.query.QueryWrapper; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.DubboReference; import org.apache.dubbo.config.annotation.DubboService; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.stream.Collectors; import static com.mybatisflex.core.query.QueryMethods.column; @@ -36,11 +41,12 @@ import static com.mybatisflex.core.query.QueryMethods.column; * @description */ @Slf4j -@Service @DubboService public class ShopSyncServiceImpl implements ShopSyncService { @DubboReference private ShopInfoService shopInfoService; + @DubboReference + private ShopConfigService shopConfigService; @Resource private ShopProdUnitService unitService; @Resource @@ -81,7 +87,37 @@ public class ShopSyncServiceImpl implements ShopSyncService { } } + /** + * 校验主店 + * + * @param sourceShopId 主店铺ID + * @param type 1-同步商品内容 2-内部耗材内容 + * @return 开启该开关的子店集合 + */ + private Set checkSourceShopInfo(Long sourceShopId, int type) { + AssertUtil.isNull(sourceShopId, "{}不能为空", "源店铺ID"); + ShopInfo sourceShop = shopInfoService.getById(sourceShopId); + if (StrUtil.isBlank(sourceShop.getShopType()) || "only".equals(sourceShop.getShopType()) + || sourceShop.getIsHeadShop() == null || sourceShop.getIsHeadShop() != 1) { + throw new CzgException("同步失败,源店铺不是主店铺或源店铺是单店"); + } + QueryWrapper queryWrapper = new QueryWrapper(); + queryWrapper.select(column(ShopConfig::getId)); + queryWrapper.eq(ShopConfig::getMainId, sourceShopId); + switch (type) { + case 1: + queryWrapper.eq(ShopConfig::getIsEnableProdSync, 1); + break; + case 2: + queryWrapper.eq(ShopConfig::getIsEnableConsSync, 1); + break; + } + List ids = shopConfigService.listAs(queryWrapper, Long.class); + return new HashSet<>(ids); + } + @Override + @Transactional(rollbackFor = Exception.class) public void sync(Long sourceShopId, Long targetShopId) { Map unitMap; Map specMap; @@ -138,6 +174,37 @@ public class ShopSyncServiceImpl implements ShopSyncService { return unitMap; } + @Override + @Transactional(rollbackFor = Exception.class) + public void syncUnitBySourceShop(Long sourceShopId, Long unitId) { + AssertUtil.isNull(unitId, "{}不能为空", "单位ID"); + Set shopIds = checkSourceShopInfo(sourceShopId, 1); + if (CollUtil.isEmpty(shopIds)) { + return; + } + ShopProdUnit mainUnit = unitService.getById(unitId); + AssertUtil.isNull(mainUnit, "需要同步的{}不存在", "单位"); + List list = unitService.queryChain().eq(ShopProdUnit::getSyncId, unitId).in(ShopProdUnit::getShopId, shopIds).list(); + Map map = new HashMap<>(); + if (CollUtil.isNotEmpty(list)) { + map = list.stream().collect(Collectors.toMap(ShopProdUnit::getShopId, t -> t)); + } + Map finalMap = map; + shopIds.forEach(shopId -> { + ShopProdUnit newUnit = BeanUtil.copyProperties(mainUnit, ShopProdUnit.class); + + newUnit.setSyncId(mainUnit.getId()); + newUnit.setShopId(shopId); + if (finalMap.containsKey(shopId)) { + ShopProdUnit unit = finalMap.get(shopId); + newUnit.setId(unit.getId()); + unitService.updateById(newUnit); + } else { + newUnit.setId(null); + unitService.save(newUnit); + } + }); + } //规格 public Map syncSpec(Long sourceShopId, Long pointShopId) { @@ -161,6 +228,38 @@ public class ShopSyncServiceImpl implements ShopSyncService { return specMap; } + + @Override + @Transactional(rollbackFor = Exception.class) + public void syncSpecBySourceShop(Long sourceShopId, Long specId) { + AssertUtil.isNull(specId, "{}不能为空", "规格ID"); + Set shopIds = checkSourceShopInfo(sourceShopId, 1); + if (CollUtil.isEmpty(shopIds)) { + return; + } + ShopProdSpec mainEntity = specService.getById(specId); + AssertUtil.isNull(mainEntity, "需要同步的{}不存在", "规格"); + List list = specService.queryChain().eq(ShopProdSpec::getSyncId, specId).in(ShopProdSpec::getShopId, shopIds).list(); + Map map = new HashMap<>(); + if (CollUtil.isNotEmpty(list)) { + map = list.stream().collect(Collectors.toMap(ShopProdSpec::getShopId, t -> t)); + } + Map finalMap = map; + shopIds.forEach(shopId -> { + ShopProdSpec newEntity = BeanUtil.copyProperties(mainEntity, ShopProdSpec.class); + newEntity.setSyncId(mainEntity.getId()); + newEntity.setShopId(shopId); + if (finalMap.containsKey(shopId)) { + ShopProdSpec childEntity = finalMap.get(shopId); + newEntity.setId(childEntity.getId()); + specService.updateById(newEntity); + } else { + newEntity.setId(null); + specService.save(newEntity); + } + }); + } + // 分类 public Map syncCategory(Long sourceShopId, Long pointShopId) { Map categoryMap = new HashMap<>(); @@ -209,6 +308,45 @@ public class ShopSyncServiceImpl implements ShopSyncService { return categoryMap; } + @Override + @Transactional(rollbackFor = Exception.class) + public void syncCategoryBySourceShop(Long sourceShopId, Long categoryId) { + AssertUtil.isNull(categoryId, "{}不能为空", "分类ID"); + Set shopIds = checkSourceShopInfo(sourceShopId, 1); + if (CollUtil.isEmpty(shopIds)) { + return; + } + ShopProdCategory mainEntity = categoryService.getById(categoryId); + AssertUtil.isNull(mainEntity, "需要同步的{}不存在", "分类"); + List list = categoryService.queryChain().eq(ShopProdCategory::getSyncId, categoryId).in(ShopProdCategory::getShopId, shopIds).list(); + Map map = new HashMap<>(); + if (CollUtil.isNotEmpty(list)) { + map = list.stream().collect(Collectors.toMap(ShopProdCategory::getShopId, t -> t)); + } + Map categoryMap = new HashMap<>(); + if (mainEntity.getPid() != null) { + List categoryList = categoryService.queryChain().eq(ShopProdCategory::getSyncId, mainEntity.getPid()).in(ShopProdCategory::getShopId, shopIds).list(); + if (CollUtil.isNotEmpty(categoryList)) { + categoryMap = categoryList.stream().collect(Collectors.toMap(ShopProdCategory::getShopId, ShopProdCategory::getId)); + } + } + Map finalMap = map; + for (Long shopId : shopIds) { + ShopProdCategory newEntity = BeanUtil.copyProperties(mainEntity, ShopProdCategory.class); + newEntity.setSyncId(mainEntity.getId()); + newEntity.setShopId(shopId); + newEntity.setPid(newEntity.getPid() != null ? categoryMap.get(shopId) : null); + if (finalMap.containsKey(shopId)) { + ShopProdCategory childEntity = finalMap.get(shopId); + newEntity.setId(childEntity.getId()); + categoryService.updateById(newEntity); + } else { + newEntity.setId(null); + categoryService.save(newEntity); + } + } + } + public Map syncProduct(Long sourceShopId, Long pointShopId, Map unitMap, Map specMap, Map cateGoryMap) { List pointProducts = productService.queryChain() @@ -240,11 +378,71 @@ public class ShopSyncServiceImpl implements ShopSyncService { return proMap; } + @Override + @Transactional(rollbackFor = Exception.class) + public void syncProductBySourceShop(Long sourceShopId, Long productId) { + AssertUtil.isNull(productId, "{}不能为空", "商品ID"); + Set shopIds = checkSourceShopInfo(sourceShopId, 1); + if (CollUtil.isEmpty(shopIds)) { + return; + } + Product mainEntity = productService.getById(productId); + AssertUtil.isNull(mainEntity, "需要同步的{}不存在", "商品"); + List list = productService.queryChain().eq(Product::getSyncId, productId).in(Product::getShopId, shopIds).list(); + Map map = new HashMap<>(); + if (CollUtil.isNotEmpty(list)) { + map = list.stream().collect(Collectors.toMap(Product::getShopId, t -> t)); + } + List specList = specService.queryChain().eq(ShopProdSpec::getSyncId, productId).in(ShopProdSpec::getShopId, shopIds).list(); + Map specMap = new HashMap<>(); + if (CollUtil.isNotEmpty(specList)) { + specMap = specList.stream().collect(Collectors.toMap(ShopProdSpec::getShopId, ShopProdSpec::getId)); + } + List unitList = unitService.queryChain().eq(ShopProdUnit::getSyncId, productId).in(ShopProdUnit::getShopId, shopIds).list(); + Map unitMap = new HashMap<>(); + if (CollUtil.isNotEmpty(unitList)) { + unitMap = unitList.stream().collect(Collectors.toMap(ShopProdUnit::getShopId, ShopProdUnit::getId)); + } + List categoryList = categoryService.queryChain().eq(ShopProdCategory::getSyncId, productId).in(ShopProdCategory::getShopId, shopIds).list(); + Map categoryMap = new HashMap<>(); + if (CollUtil.isNotEmpty(categoryList)) { + categoryMap = categoryList.stream().collect(Collectors.toMap(ShopProdCategory::getShopId, ShopProdCategory::getId)); + } + Map finalMap = map; + for (Long shopId : shopIds) { + Product newEntity = BeanUtil.copyProperties(mainEntity, Product.class); + newEntity.setSyncId(mainEntity.getSyncId()); + newEntity.setShopId(shopId); + newEntity.setCategoryId(newEntity.getCategoryId() != null ? categoryMap.get(newEntity.getSpecId()) : null); + newEntity.setSpecId(newEntity.getSpecId() != null ? specMap.get(newEntity.getSpecId()) : null); + newEntity.setUnitId(newEntity.getUnitId() != null ? unitMap.get(newEntity.getUnitId()) : null); + if (finalMap.containsKey(shopId)) { + Product childEntity = finalMap.get(shopId); + newEntity.setId(childEntity.getId()); + productService.updateById(newEntity); + } else { + newEntity.setId(null); + newEntity.setIsSale(0); + newEntity.setStockNumber(0); + productService.save(newEntity); + } + syncSkuBySourceShop(sourceShopId, shopId, productId, newEntity.getId()); + if ("package".equals(newEntity.getType()) || "coupon".equals(newEntity.getType())) { + syncProductPackageBySourceShop(newEntity, shopId); + } + } + } + public Map syncGroup(Long sourceShopId, Long pointShopId, Map pros) { Map groupMap = new HashMap<>(); List pointGroup = groupService.queryChain().select(ProdGroup::getSyncId).eq(ProdGroup::getShopId, pointShopId) .isNotNull(ProdGroup::getSyncId).listAs(Long.class); List list = groupService.queryChain().eq(ProdGroup::getShopId, sourceShopId).list(); + if (CollUtil.isEmpty(list)) { + log.info("分组同步,分组数据为空"); + return new HashMap<>(); + + } for (ProdGroup prodGroup : list) { if (CollUtil.isEmpty(pointGroup) || !pointGroup.contains(prodGroup.getId())) { ProdGroup tbProductGroupNew = BeanUtil.copyProperties(prodGroup, ProdGroup.class); @@ -265,11 +463,75 @@ public class ShopSyncServiceImpl implements ShopSyncService { return groupMap; } - //分组 + @Override + @Transactional(rollbackFor = Exception.class) + public void syncGroupBySourceShop(Long sourceShopId, Long groupId) { + AssertUtil.isNull(groupId, "{}不能为空", "分组ID"); + Set shopIds = checkSourceShopInfo(sourceShopId, 1); + if (CollUtil.isEmpty(shopIds)) { + return; + } + ProdGroup mainEntity = groupService.getById(groupId); + AssertUtil.isNull(mainEntity, "需要同步的{}不存在", "分组"); + List list = groupService.queryChain().eq(ProdGroup::getSyncId, groupId).in(ProdGroup::getShopId, shopIds).list(); + Map map = new HashMap<>(); + if (CollUtil.isNotEmpty(list)) { + map = list.stream().collect(Collectors.toMap(ProdGroup::getShopId, t -> t)); + } + List groupRelations = prodGroupRelationService.queryChain().eq(ProdGroupRelation::getProdGroupId, mainEntity.getId()).list(); + Map groupRelationMap = new HashMap<>(); + if (CollUtil.isNotEmpty(groupRelations)) { + groupRelationMap = groupRelations.stream().collect(Collectors.toMap(ProdGroupRelation::getProductId, ProdGroupRelation::getSort)); + } + List groupRelationList = new ArrayList<>(); + for (Long shopId : shopIds) { + ProdGroup newEntity = BeanUtil.copyProperties(mainEntity, ProdGroup.class); + newEntity.setSyncId(mainEntity.getId()); + newEntity.setShopId(shopId); + if (map.containsKey(shopId)) { + ProdGroup childEntity = map.get(shopId); + newEntity.setId(childEntity.getId()); + groupService.updateById(newEntity); + } else { + newEntity.setId(null); + groupService.save(newEntity); + } + if (CollUtil.isEmpty(groupRelationMap)) { + List oldProdGroup = prodGroupRelationService.queryChain().eq(ProdGroupRelation::getProdGroupId, newEntity.getId()).list(); + if(CollUtil.isEmpty(oldProdGroup)){ + continue; + } + Set oldProds = oldProdGroup.stream().map(ProdGroupRelation::getProductId).collect(Collectors.toSet()); + List rmIds = productService.queryChain().select(Product::getId).eq(Product::getShopId, shopId) + .in(Product::getId, oldProds).isNotNull(Product::getSyncId).listAs(Long.class); + if(CollUtil.isEmpty(rmIds)){ + continue; + } + QueryWrapper queryWrapper = new QueryWrapper(); + queryWrapper.eq(ProdGroupRelation::getProdGroupId, newEntity.getId()); + queryWrapper.in(ProdGroupRelation::getProductId, rmIds); + prodGroupRelationService.remove(queryWrapper); + } else { + List prods = productService.queryChain().select(Product::getId).eq(Product::getShopId, shopId).in(Product::getSyncId, groupRelationMap.keySet()).list(); + for (Product prod : prods) { + ProdGroupRelation newProdGroupRelation = new ProdGroupRelation(); + newProdGroupRelation.setProdGroupId(newEntity.getId()); + newProdGroupRelation.setProductId(prod.getId()); + newProdGroupRelation.setSort(groupRelationMap.get(prod.getSyncId())); + groupRelationList.add(newProdGroupRelation); + } + } + } + if (CollUtil.isNotEmpty(groupRelations)) { + prodGroupRelationService.saveOrUpdateBatch(groupRelationList, 100); + } + } + + //套餐 public void syncProductPackage(Long shopId, Map pros, Map skus) { List list = productService.queryChain() .eq(Product::getShopId, shopId) - .and(column(Product::getType).eq("weight").or(column(Product::getType).eq("coupon"))) + .and(column(Product::getType).eq("package").or(column(Product::getType).eq("coupon"))) .list(); for (Product product : list) { if (StrUtil.isNotBlank(product.getGroupSnap()) && product.getGroupSnap().length() > 5) { @@ -293,8 +555,41 @@ public class ShopSyncServiceImpl implements ShopSyncService { proGroupVo.setNumber(proGroupVo.getCount()); } } + product.setGroupSnap(JSON.toJSONString(proGroupVo, JSONWriter.Feature.WriteMapNullValue)); } } + productService.saveOrUpdateBatch(list, 100); + } + + public void syncProductPackageBySourceShop(Product product, Long pointShopId) { + if (StrUtil.isNotBlank(product.getGroupSnap()) && product.getGroupSnap().length() > 5) { + ProductGroupVo proGroupVo = JSONObject.parseObject(product.getGroupSnap(), ProductGroupVo.class); + List goodList = new ArrayList<>(); + for (ProductGroupVo.Food goods : proGroupVo.getGoods()) { + if (goods.getProId() != null) { + Product sourceProduct = productService.queryChain().eq(Product::getShopId, pointShopId).eq(Product::getSyncId, goods.getProId()).one(); + if (sourceProduct != null) { + goods.setProId(sourceProduct.getId()); + goods.setProName(sourceProduct.getName()); + } + } + if (goods.getSkuId() != null) { + ProdSku sourceSku = skuService.queryChain().eq(ProdSku::getShopId, pointShopId).eq(ProdSku::getSyncId, goods.getSkuId()).one(); + goods.setSkuId(sourceSku.getId()); + goods.setSkuName(sourceSku.getSpecInfo()); + } + goodList.add(goods); + } + proGroupVo.setCount(goodList.size()); + proGroupVo.setGoods(goodList); + if (proGroupVo.getNumber() != null && proGroupVo.getNumber() > 0) { + if (proGroupVo.getNumber() > proGroupVo.getCount()) { + proGroupVo.setNumber(proGroupVo.getCount()); + } + } + product.setGroupSnap(JSON.toJSONString(proGroupVo, JSONWriter.Feature.WriteMapNullValue)); + productService.saveOrUpdate(product); + } } //分组 @@ -320,6 +615,35 @@ public class ShopSyncServiceImpl implements ShopSyncService { return skuMap; } + public void syncSkuBySourceShop(Long sourceShopId, Long pointShopId, Long sourceProductId, Long pointProductId) { + List sourceSkus = skuService.queryChain() + .eq(ProdSku::getShopId, sourceShopId) + .eq(ProdSku::getProductId, sourceProductId) + .list(); + if (CollUtil.isEmpty(sourceSkus)) { + return; + } + List newSaveSkus = new ArrayList<>(); + Set sourceIds = sourceSkus.stream().map(ProdSku::getId).collect(Collectors.toSet()); + + List childSkus = skuService.queryChain().eq(ProdSku::getShopId, pointShopId).in(ProdSku::getSyncId, sourceIds).list(); + Map childSkuMap = childSkus.stream().collect(Collectors.toMap(ProdSku::getSyncId, t -> t)); + for (ProdSku skus : sourceSkus) { + ProdSku newSku = BeanUtil.copyProperties(skus, ProdSku.class); + newSku.setSyncId(skus.getId()); + newSku.setShopId(pointShopId); + newSku.setProductId(pointProductId); + if (childSkuMap.containsKey(skus.getId())) { + ProdSku childSku = childSkuMap.get(skus.getId()); + newSku.setId(childSku.getId()); + } else { + newSku.setId(null); + } + newSaveSkus.add(newSku); + } + skuService.saveOrUpdateBatch(newSaveSkus, 100); + } + public Map syncConsGroup(Long sourceShopId, Long pointShopId) { Map consGroupMap = new HashMap<>(); List pointConsGroup = consGroupService.queryChain().select(ConsGroup::getSyncId) @@ -341,6 +665,37 @@ public class ShopSyncServiceImpl implements ShopSyncService { return consGroupMap; } + @Override + @Transactional(rollbackFor = Exception.class) + public void syncConsGroupBySourceShop(Long sourceShopId, Long consGroupId) { + AssertUtil.isNull(consGroupId, "{}不能为空", "耗材分组ID"); + Set shopIds = checkSourceShopInfo(sourceShopId, 2); + if (CollUtil.isEmpty(shopIds)) { + return; + } + ConsGroup mainEntity = consGroupService.getById(consGroupId); + AssertUtil.isNull(mainEntity, "需要同步的{}不存在", "耗材分组"); + List list = consGroupService.queryChain().eq(ConsGroup::getSyncId, consGroupId).in(ConsGroup::getShopId, shopIds).list(); + Map map = new HashMap<>(); + if (CollUtil.isNotEmpty(list)) { + map = list.stream().collect(Collectors.toMap(ConsGroup::getShopId, t -> t)); + } + Map finalMap = map; + shopIds.forEach(shopId -> { + ConsGroup newEntity = BeanUtil.copyProperties(mainEntity, ConsGroup.class); + newEntity.setSyncId(mainEntity.getId()); + newEntity.setShopId(shopId); + if (finalMap.containsKey(shopId)) { + ConsGroup childEntity = finalMap.get(shopId); + newEntity.setId(childEntity.getId()); + consGroupService.updateById(newEntity); + } else { + newEntity.setId(null); + consGroupService.save(newEntity); + } + }); + } + // 耗材 public Map syncConsInfo(Long sourceShopId, Long pointShopId, Map consGroupMap) { Map consMap = new HashMap<>(); @@ -365,6 +720,43 @@ public class ShopSyncServiceImpl implements ShopSyncService { return consMap; } + @Override + @Transactional(rollbackFor = Exception.class) + public void syncConsInfoBySourceShop(Long sourceShopId, Long consInfoId) { + AssertUtil.isNull(consInfoId, "{}不能为空", "耗材ID"); + Set shopIds = checkSourceShopInfo(sourceShopId, 2); + if (CollUtil.isEmpty(shopIds)) { + return; + } + ConsInfo mainEntity = consInfoService.getById(consInfoId); + AssertUtil.isNull(mainEntity, "需要同步的{}不存在", "耗材"); + List list = consInfoService.queryChain().eq(ConsInfo::getSyncId, consInfoId).in(ConsInfo::getShopId, shopIds).list(); + Map map = new HashMap<>(); + if (CollUtil.isNotEmpty(list)) { + map = list.stream().collect(Collectors.toMap(ConsInfo::getShopId, t -> t)); + } + Map finalMap = map; + for (Long shopId : shopIds) { + ConsInfo newEntity = BeanUtil.copyProperties(mainEntity, ConsInfo.class); + newEntity.setSyncId(mainEntity.getId()); + newEntity.setShopId(shopId); + if (newEntity.getConsGroupId() != null) { + Long consGroupId = consGroupService.queryChain().select(ConsGroup::getId) + .eq(ConsGroup::getSyncId, newEntity.getConsGroupId()).eq(ConsGroup::getShopId, shopId).oneAs(Long.class); + newEntity.setConsGroupId(consGroupId); + } + if (finalMap.containsKey(shopId)) { + ConsInfo childEntity = finalMap.get(shopId); + newEntity.setId(childEntity.getId()); + consInfoService.updateById(newEntity); + } else { + newEntity.setId(null); + newEntity.setStockNumber(BigDecimal.ZERO); + consInfoService.save(newEntity); + } + } + } + public void syncConsPro(Long sourceShopId, Long pointShopId, Map consMap, Map proMap) { List list = prodConsRelationService.queryChain().eq(ProdConsRelation::getShopId, sourceShopId).list(); for (ProdConsRelation prodConsRelation : list) { @@ -376,4 +768,47 @@ public class ShopSyncServiceImpl implements ShopSyncService { log.info("耗材与商品关联关系,同步{}个", list.size()); } + + @Override + @Transactional(rollbackFor = Exception.class) + public void syncConsProBySourceShop(Long sourceShopId, Long sourceProdId) { + AssertUtil.isNull(sourceProdId, "{}不能为空", "商品ID"); + Set shopIds = checkSourceShopInfo(sourceShopId, 2); + if (CollUtil.isEmpty(shopIds)) { + return; + } + List newSaveList = new ArrayList<>(); + List list = prodConsRelationService.queryChain() + .eq(ProdConsRelation::getShopId, sourceShopId).eq(ProdConsRelation::getProductId, sourceProdId).list(); + for (Long shopId : shopIds) { + Product product = productService.queryChain().eq(Product::getSyncId, sourceProdId).eq(Product::getShopId, shopId).one(); + if (product != null) { + if (CollUtil.isEmpty(list)) { + List prods = prodConsRelationService.queryChain().select(ProdConsRelation::getProductId) + .eq(ProdConsRelation::getShopId, shopId).eq(ProdConsRelation::getProductId, product.getId()).listAs(Long.class); + if (CollUtil.isNotEmpty(prods)) { + List remIds = productService.queryChain().select(Product::getId).in(Product::getId, prods).isNotNull(Product::getSyncId).listAs(Long.class); + if (CollUtil.isNotEmpty(remIds)) { + prodConsRelationService.remove(new QueryWrapper().eq(ProdConsRelation::getShopId, shopId).in(ProdConsRelation::getProductId, remIds)); + } + } + } else { + Map map = list.stream().collect(Collectors.toMap(ProdConsRelation::getConsInfoId, ProdConsRelation::getSurplusStock)); + List newCons = consInfoService.queryChain().select(ConsInfo::getId) + .in(ConsInfo::getSyncId, map.keySet()).eq(ConsInfo::getShopId, shopId).list(); + for (ConsInfo newCon : newCons) { + ProdConsRelation prodConsRelation = new ProdConsRelation(); + prodConsRelation.setShopId(shopId); + prodConsRelation.setProductId(product.getId()); + prodConsRelation.setConsInfoId(newCon.getId()); + prodConsRelation.setSurplusStock(map.get(newCon.getSyncId())); + newSaveList.add(prodConsRelation); + } + } + } + } + if (CollUtil.isNotEmpty(newSaveList)) { + prodConsRelationService.saveOrUpdateBatch(newSaveList, 100); + } + } }