diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/product/ShopProductBase.java b/mall-common/src/main/java/com/suisung/mall/common/modules/product/ShopProductBase.java index 9e70324d..a21f4e5f 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/modules/product/ShopProductBase.java +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/product/ShopProductBase.java @@ -39,42 +39,55 @@ public class ShopProductBase implements Serializable{ private Long product_id; @ApiModelProperty(value = "产品名称(in=>2,100)") + @TableField(updateStrategy=NOT_EMPTY) private String product_name; @ApiModelProperty(value = "商品货号") + @TableField(updateStrategy=NOT_EMPTY) private String product_number; @ApiModelProperty(value = "商品卖点:商品广告词") + @TableField(updateStrategy=NOT_EMPTY) private String product_tips; @ApiModelProperty(value = "店铺编号") + @TableField(updateStrategy=NOT_EMPTY) private Integer store_id; @ApiModelProperty(value = "店铺名称") + @TableField(updateStrategy=NOT_EMPTY) private String store_name; @ApiModelProperty(value = "市场价") + @TableField(updateStrategy=NOT_EMPTY) private BigDecimal product_market_price; @ApiModelProperty(value = "商品单价") + @TableField(updateStrategy=NOT_EMPTY) private BigDecimal product_unit_price; @ApiModelProperty(value = "成本价") + @TableField(updateStrategy=NOT_EMPTY) private BigDecimal product_cost_price; @ApiModelProperty(value = "商品主图") + @TableField(updateStrategy=NOT_EMPTY) private String product_image; @ApiModelProperty(value = "产品视频 ") + @TableField(updateStrategy=NOT_EMPTY) private String product_video; @ApiModelProperty(value = "选择售卖区域:完成售卖区域及运费设置") + @TableField(updateStrategy=NOT_EMPTY) private Integer transport_type_id; @ApiModelProperty(value = "如果启用跳转页面") + @TableField(updateStrategy=NOT_EMPTY) private String product_seo_url; @ApiModelProperty(value = "专题布局编号") + @TableField(updateStrategy=NOT_EMPTY) private Integer layout_route_id; @ApiModelProperty(value = "商品审核(ENUM):3001-审核通过;3002-审核中;3000-审核未通过") @@ -86,48 +99,63 @@ public class ShopProductBase implements Serializable{ private Integer product_state_id; @ApiModelProperty(value = "库存锁定(ENUM):1001-下单锁定;1002-支付锁定;") + @TableField(updateStrategy=NOT_EMPTY) private Integer product_inventory_lock; @ApiModelProperty(value = "上架时间:预设上架时间,可以动态修正状态") + @TableField(updateStrategy=NOT_EMPTY) private Date product_sale_time; @ApiModelProperty(value = "计量单位") + @TableField(updateStrategy=NOT_EMPTY) private Integer unit_id; @ApiModelProperty(value = "原产国") + @TableField(updateStrategy=NOT_EMPTY) private String product_country; @ApiModelProperty(value = "币值") + @TableField(updateStrategy=NOT_EMPTY) private String product_currency; @ApiModelProperty(value = "商品添加时间") + @TableField(updateStrategy=NOT_EMPTY) private Long product_add_time; @ApiModelProperty(value = "积分单价") + @TableField(updateStrategy=NOT_EMPTY) private BigDecimal product_unit_points; @ApiModelProperty(value = "资源2单价") + @TableField(updateStrategy=NOT_EMPTY) private Integer product_unit_sp; @ApiModelProperty(value = "排序") + @TableField(updateStrategy=NOT_EMPTY) private Integer product_order; @ApiModelProperty(value = "产品来源编号") + @TableField(updateStrategy=NOT_EMPTY) private Long product_src_id; @ApiModelProperty(value = "供应状态(BOOL):1-启用分销;0-禁用分销") + @TableField(updateStrategy=NOT_EMPTY) private Integer product_fx_enable; @ApiModelProperty(value = "三级分销(BOOL):1-启用分销;0-禁用分销") + @TableField(updateStrategy=NOT_EMPTY) private Integer product_dist_enable; @ApiModelProperty(value = "平台佣金百分比") + @TableField(updateStrategy=NOT_EMPTY) private BigDecimal product_commission_rate; @ApiModelProperty(value = "商品来源(ENUM):1000-发布;1001-天猫;1002-淘宝;1003-阿里巴巴;1004-京东;1005-思迅;") + @TableField(updateStrategy=NOT_EMPTY) private Integer product_from; @ApiModelProperty(value = "来源网址") + @TableField(updateStrategy=NOT_EMPTY) private String product_from_url; @ApiModelProperty(value = "商品表-SKU表数据") @@ -136,6 +164,7 @@ public class ShopProductBase implements Serializable{ //在同步数据的时候,生鲜需要按平台的规格拆分售卖,这些主要记录原始数据,总重量一般为kg,KG,公斤 @ApiModelProperty(value = "总量单位") + @TableField(updateStrategy=NOT_EMPTY) private String unit_name; @ApiModelProperty(value = "总重量") diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/product/ShopProductImage.java b/mall-common/src/main/java/com/suisung/mall/common/modules/product/ShopProductImage.java index 551d9f6b..8b66a0e1 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/modules/product/ShopProductImage.java +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/product/ShopProductImage.java @@ -62,5 +62,13 @@ public class ShopProductImage implements Serializable { @ApiModelProperty(value = "扩展图片") private String item_image_ext_2; + @ApiModelProperty(value = "商品货号同步数据用") + private String product_number; + + @ApiModelProperty(value = "产品名称同步数据用") + private String product_name; + + @ApiModelProperty(value = "商品来源(ENUM):1000-发布;1001-天猫;1002-淘宝;1003-阿里巴巴;1004-京东;1005-思迅;同步数据匹配") + private String product_from; } diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/sync/ImageMappingDto.java b/mall-common/src/main/java/com/suisung/mall/common/modules/sync/ImageMappingDto.java new file mode 100644 index 00000000..95ab6272 --- /dev/null +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/sync/ImageMappingDto.java @@ -0,0 +1,40 @@ +package com.suisung.mall.common.modules.sync; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + + +@Data +public class ImageMappingDto { + @ApiModelProperty(value = "商品图片编号") + private Long productImageId; + + @ApiModelProperty(value = "产品编号:product_id-color_id") + private Long productId; + + @ApiModelProperty(value = "店铺编号") + private Integer storeId; + + @ApiModelProperty(value = "合并图库url") + private String mergedImageUrl; + + @ApiModelProperty(value = "主图") + private String thumb; + + @ApiModelProperty(value = "图库商品名称") + private String imgProductName; + + /** + * 为URL添加域名前缀(如果URL不是以http/https开头) + * + * @param imageDomain 图片域名 + * @param url 图片URL + * @return 添加域名前缀后的URL + */ + public String addDomainPrefix(String imageDomain, String url) { + if (url == null || url.startsWith("http://") || url.startsWith("https://")) { + return url; + } + return imageDomain + (url.startsWith("/") ? url : "/" + url); + } +} diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/sync/ShopImageMappingTemp.java b/mall-common/src/main/java/com/suisung/mall/common/modules/sync/ShopImageMappingTemp.java new file mode 100644 index 00000000..965679d7 --- /dev/null +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/sync/ShopImageMappingTemp.java @@ -0,0 +1,55 @@ +package com.suisung.mall.common.modules.sync; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Date; +@Data +@TableName("shop_image_mapping_temp") +@ApiModel("商品图片映射临时表") +public class ShopImageMappingTemp { + + @TableId(type = IdType.AUTO) + @ApiModelProperty(value = "临时表ID", example = "1") + private Long id; + + @TableField("product_image_id") + @ApiModelProperty(value = "商品图片编号", example = "1001") + private Long productImageId; + + @TableField("product_id") + @ApiModelProperty(value = "产品编号(product_id-color_id)", example = "2001-1") + private Long productId; + + @TableField("product_name") + @ApiModelProperty(value = "产品名称(同步数据用)", example = "夏季新款T恤") + private String productName; + + @TableField("store_id") + @ApiModelProperty(value = "店铺编号", example = "3001") + private Integer storeId; + + @TableField("merged_image_url") + @ApiModelProperty(value = "合并后的图片URL", example = "http://example.com/image1.jpg,http://example.com/image2.jpg") + private String mergedImageUrl; + + @TableField("name") + @ApiModelProperty(value = "图库商品名", example = "夏季男士短袖T恤") + private String name; + + @TableField("thumb") + @ApiModelProperty(value = "主图URL", example = "http://example.com/thumb.jpg") + private String thumb; + + @TableField("create_time") + @ApiModelProperty(value = "创建时间", example = "2023-01-01 00:00:00") + private Date createTime; + + @TableField("update_time") + @ApiModelProperty(value = "更新时间", example = "2023-01-01 00:00:00") + private Date updateTime; +} \ No newline at end of file diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/analytics/service/impl/AnalyticsOrderServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/analytics/service/impl/AnalyticsOrderServiceImpl.java index 12ab5389..fc2468d5 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/analytics/service/impl/AnalyticsOrderServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/analytics/service/impl/AnalyticsOrderServiceImpl.java @@ -220,7 +220,8 @@ public class AnalyticsOrderServiceImpl implements AnalyticsOrderService { TimeRange range = TimeUtil.today(); //统计没有取消的订单 - List orderState = Arrays.asList(StateCode.ORDER_STATE_WAIT_PAY, StateCode.ORDER_STATE_WAIT_PAID, StateCode.ORDER_STATE_WAIT_REVIEW, StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW, StateCode.ORDER_STATE_PICKING, StateCode.ORDER_STATE_WAIT_SHIPPING, StateCode.ORDER_STATE_SHIPPED, StateCode.ORDER_STATE_RECEIVED, StateCode.ORDER_STATE_FINISH, StateCode.ORDER_STATE_SELF_PICKUP); + List orderState = Arrays.asList(StateCode.ORDER_STATE_WAIT_PAY, StateCode.ORDER_STATE_WAIT_PAID, StateCode.ORDER_STATE_WAIT_REVIEW, StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW, StateCode.ORDER_STATE_PICKING, StateCode.ORDER_STATE_WAIT_SHIPPING, StateCode.ORDER_STATE_SHIPPED, StateCode.ORDER_STATE_RECEIVED, StateCode.ORDER_STATE_FINISH, StateCode.ORDER_STATE_SELF_PICKUP, + StateCode.ORDER_STATE_CANCEL); List paidState = Arrays.asList(StateCode.ORDER_PAID_STATE_PART, StateCode.ORDER_PAID_STATE_YES); OrderNumVo todayOrderNum = analyticsOrderDao.getOrderNum(range.getStart(), range.getEnd(), orderState, null, null, null, siteId, storeId); diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/product/mapper/ShopProductImageMapper.java b/mall-shop/src/main/java/com/suisung/mall/shop/product/mapper/ShopProductImageMapper.java index 246b9665..83b52ed1 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/product/mapper/ShopProductImageMapper.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/product/mapper/ShopProductImageMapper.java @@ -2,8 +2,13 @@ package com.suisung.mall.shop.product.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.suisung.mall.common.modules.product.ShopProductImage; +import com.suisung.mall.common.modules.sync.ImageMappingDto; +import io.lettuce.core.dynamic.annotation.Param; import org.springframework.stereotype.Repository; +import java.util.List; + + /** *

* 产品图片表,按照颜色规格 Mapper 接口 @@ -16,4 +21,18 @@ import org.springframework.stereotype.Repository; @Repository public interface ShopProductImageMapper extends BaseMapper { + Integer mappingByBarCodeCount(@Param("storeId") Integer storeId); + + Integer mappingByProductNameCount(@Param("storeId") Integer storeId); + + Integer mappingByProductShortNameCount(@Param("storeId") Integer storeId); + + /** + * 1、条形码匹配 + * 2、标准名称匹配 + * 3、产品名称模糊匹配 + * @param type + * @return + */ + List mappingProductImage(@Param("type") String type,@Param("storeId") Integer storeId,@Param("offset") Integer offset,@Param("limit") Integer limit); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/product/service/ShopProductBaseService.java b/mall-shop/src/main/java/com/suisung/mall/shop/product/service/ShopProductBaseService.java index e84ca01a..33287a5b 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/product/service/ShopProductBaseService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/product/service/ShopProductBaseService.java @@ -286,7 +286,7 @@ public interface ShopProductBaseService extends IBaseService { Pair saveProductBatch(List shopProductBaseList, List shopProductIndexList, List shopProductDataList, List shopProductDetailList, List shopProductInfoList, List> shopProductItemList, - List> shopProductImageList, + List shopProductImageList, List shopProductValidPeriodList, List shopProductAssistIndexList); diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/product/service/impl/ShopProductBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/product/service/impl/ShopProductBaseServiceImpl.java index 2bab11cf..c4870f84 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/product/service/impl/ShopProductBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/product/service/impl/ShopProductBaseServiceImpl.java @@ -5271,7 +5271,7 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl saveProductBatch(List shopProductBaseList, List shopProductIndexList, List shopProductDataList, List shopProductDetailList, List shopProductInfoList, List> shopProductItemList, - List> shopProductImageList, List shopProductValidPeriodList, + List shopProductImageList, List shopProductValidPeriodList, List shopProductAssistIndexList) { // 1. 参数校验 @@ -5301,8 +5301,8 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl> newShopProductItemList=new ArrayList<>(); List> updateShopProductItemList=new ArrayList<>(); - List> newShopProductImageList=new ArrayList<>(); - List> updateShopProductImageList=new ArrayList<>(); + List newShopProductImageList=new ArrayList<>(); + List updateShopProductImageList=new ArrayList<>(); List newShopProductValidPeriodList=new ArrayList<>(); List updateShopProductValidPeriodList=new ArrayList<>(); @@ -5429,7 +5429,7 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl newShopProductDetailList, List updateShopProductDetailList, List newShopProductInfoList, List updateShopProductInfoList, List> newShopProductItemList,List> udpateShopProductItemList, - List> newShopProductImageList, List> udpteShopProductImageList, + List newShopProductImageList, List udpteShopProductImageList, List newShopProductValidPeriodList, List updateShopProductValidPeriodList, List newShopProductAssistIndexList, List udpateShopProductAssistIndexList ) { @@ -5472,16 +5472,6 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl items = newShopProductItemList.get(i); processProductItems(items, productId, addItemSeqs); @@ -5489,7 +5479,7 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl items = udpateShopProductItemList.get(i); processProductItems(items, productId, updateItemSeqs);// updateShopProductItems.addAll(items); - //allItemIds.addAll(itemIds); - // productToItemsMap.put(productId, itemIds); // 处理图片 if(CollUtil.isNotEmpty(udpteShopProductImageList)){ - processProductImages(udpteShopProductImageList.get(i), productId,base.getStore_id()); + processProductImages(udpteShopProductImageList.get(i), productId,base.getStore_id(),updateProducts.get(i).getProduct_number(),updateProducts.get(i).getProduct_name()); } // 处理辅助属性 @@ -5584,7 +5563,7 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl newShopProductValidPeriodList,List updateShopProductValidPeriodList, List newshopProductItemList,List updateshopProductItemList, List newShopProductAnalyticList,List updateShopProductAnalyticList, - List newShopProductItemSeqList,List updateShopProductItemSeqList) { + List newShopProductItemSeqList,List updateShopProductItemSeqList, + List addShopProductImageList,List updateShopProductImageList) { TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); @@ -5660,6 +5640,21 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl productImages, Long productId, Integer storeId) { - if (CollUtil.isEmpty(productImages)) { + private void processProductImages(ShopProductImage productImage, Long productId, Integer storeId,String productNumber,String productName) { + if (ObjectUtil.isEmpty(productImage)) { return; } + productImage.setProduct_id(productId); + productImage.setStore_id(storeId); - // 1. 查询现有图片 - List existingImages = shopProductImageService.getShopProductImageByStoreId(storeId); - Map existingImageMap = existingImages.stream() - .collect(Collectors.toMap(ShopProductImage::getProduct_image_id, Function.identity())); - - // 2. 分离需要新增、更新和删除的图片 - List toAdd = new ArrayList<>(); - List toUpdate = new ArrayList<>(); - List toDelete = new ArrayList<>(); - List delBaiduImages = new ArrayList<>(); - List addBaiduImages = new ArrayList<>(); - - for (ShopProductImage newImage : productImages) { - newImage.setProduct_id(productId); - // 设置默认值 - newImage.setItem_image_ext_1(""); - newImage.setItem_image_ext_2(""); - - // 判断是新增还是更新 - if (newImage.getProduct_image_id() == null) { - toAdd.add(newImage); - if (StrUtil.isNotBlank(newImage.getItem_image_default())) { - addBaiduImages.add(newImage.getItem_image_default()); - } - } else { - ShopProductImage oldImage = existingImageMap.get(newImage.getProduct_image_id()); - if (oldImage != null) { - // 检查图片是否有变化 - if (!StrUtil.equals(oldImage.getItem_image_default(), newImage.getItem_image_default())) { - if (StrUtil.isNotBlank(oldImage.getItem_image_default())) { - delBaiduImages.add(oldImage.getItem_image_default()); - } - if (StrUtil.isNotBlank(newImage.getItem_image_default())) { - addBaiduImages.add(newImage.getItem_image_default()); - } - } - toUpdate.add(newImage); - } - } - } - - // 找出需要删除的图片(存在但不在新列表中) - existingImages.forEach(oldImage -> { - boolean stillExists = productImages.stream() - .anyMatch(img -> Objects.equals(img.getProduct_image_id(), oldImage.getProduct_image_id())); - if (!stillExists) { - toDelete.add(oldImage.getProduct_image_id()); - if (StrUtil.isNotBlank(oldImage.getItem_image_default())) { - delBaiduImages.add(oldImage.getItem_image_default()); - } - } - }); - - // 3. 执行批量操作 - if (CollUtil.isNotEmpty(toAdd)) { - shopProductImageService.saveBatch(toAdd,toAdd.size()); - } - if (CollUtil.isNotEmpty(toUpdate)) { - shopProductImageService.updateBatchById(toUpdate); - } - if (CollUtil.isNotEmpty(toDelete)) { - shopProductImageService.removeByIds(toDelete); - } - + productImage.setColor_id(0L); + productImage.setItem_image_default("1");//设置默认属性1,方便查询匹配图库 + productImage.setProduct_number(productNumber); + productImage.setProduct_name(productName); } + /** * 处理商品辅助属性批量操作 * @param assistIndices 辅助属性列表 diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sync/controller/ProductMappingController.java b/mall-shop/src/main/java/com/suisung/mall/shop/sync/controller/ProductMappingController.java index f1de75a1..c9e249f5 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/sync/controller/ProductMappingController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sync/controller/ProductMappingController.java @@ -6,10 +6,14 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.suisung.mall.common.api.CommonResult; import com.suisung.mall.common.api.IErrorCode; +import com.suisung.mall.common.domain.UserDto; import com.suisung.mall.common.modules.sync.ProductMapping; +import com.suisung.mall.common.pojo.res.ThirdApiRes; import com.suisung.mall.common.service.impl.BaseControllerImpl; +import com.suisung.mall.common.utils.ContextUtil; import com.suisung.mall.shop.sync.exelModel.ImportResult; import com.suisung.mall.shop.sync.service.ProductMappingService; +import com.suisung.mall.shop.sync.service.SyncThirdDataService; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; @@ -18,6 +22,7 @@ import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.io.IOException; @@ -39,6 +44,9 @@ public class ProductMappingController extends BaseControllerImpl { @Value("${file.upload-dir}") private String uploadDir; + @Resource + private SyncThirdDataService syncThirdDataService; + /** * 分页列表查询 * @param pageNum @@ -217,4 +225,18 @@ public class ProductMappingController extends BaseControllerImpl { } } + @ApiOperation(value = "商品图库匹配", notes = "商品图库匹配") + @RequestMapping(value = "/syncShopImages", method = RequestMethod.POST) + public ThirdApiRes syncShopImages(@RequestParam(required = false) String storeId) { + UserDto userDto=ContextUtil.getCurrentUser(); + assert userDto != null; + if(userDto.isStore()){//商店自己同步 + String shopStoreId=userDto.getStore_id(); + syncThirdDataService.syncShopImages(Integer.valueOf(shopStoreId)); + }else {//平台同步 + syncThirdDataService.syncShopImages(Integer.valueOf(storeId)); + } + return new ThirdApiRes().success("服务器已执行商品图库匹配数据操作"); + } + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sync/controller/SyncThirdDataController.java b/mall-shop/src/main/java/com/suisung/mall/shop/sync/controller/SyncThirdDataController.java index d270d801..a2d751c8 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/sync/controller/SyncThirdDataController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sync/controller/SyncThirdDataController.java @@ -10,15 +10,11 @@ package com.suisung.mall.shop.sync.controller; import cn.hutool.json.JSONArray; import com.suisung.mall.common.api.CommonResult; -import com.suisung.mall.common.modules.sync.StoreDbConfig; import com.suisung.mall.common.pojo.req.SyncThirdMemberReq; import com.suisung.mall.common.pojo.res.ThirdApiRes; -import com.suisung.mall.shop.sync.service.SyncAppService; import com.suisung.mall.shop.sync.service.SyncThirdDataService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -26,7 +22,6 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.Date; import java.util.List; -import java.util.Map; @Api(tags = "第三方数据同步") @RestController @@ -185,4 +180,5 @@ public class SyncThirdDataController { } + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sync/mapper/ShopImageMappingTempMapper.java b/mall-shop/src/main/java/com/suisung/mall/shop/sync/mapper/ShopImageMappingTempMapper.java new file mode 100644 index 00000000..65d61a82 --- /dev/null +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sync/mapper/ShopImageMappingTempMapper.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.suisung.mall.shop.sync.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.suisung.mall.common.modules.sync.ShopImageMappingTemp; +import io.lettuce.core.dynamic.annotation.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ShopImageMappingTempMapper extends BaseMapper { + + /** + * 由于模糊匹配数据慢,需要把数据放到临时表 + * @param storeId + */ + void mergeShopImageMappingTemp(@Param("storeId") Integer storeId); + + /** + * 删除临时表数据 + * @param storeId + */ + void deleteShopImageMappingTemp(@Param("storeId") Integer storeId); +} diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/ShopImageMappingTempService.java b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/ShopImageMappingTempService.java new file mode 100644 index 00000000..29a41c19 --- /dev/null +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/ShopImageMappingTempService.java @@ -0,0 +1,7 @@ +package com.suisung.mall.shop.sync.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.suisung.mall.common.modules.sync.ShopImageMappingTemp; +public interface ShopImageMappingTempService extends IService { + +} diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/SyncShopImageService.java b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/SyncShopImageService.java new file mode 100644 index 00000000..2d475cc2 --- /dev/null +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/SyncShopImageService.java @@ -0,0 +1,5 @@ +package com.suisung.mall.shop.sync.service; + +public interface SyncShopImageService { + void syncMapingShopImages(Integer storeId); +} diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/SyncThirdDataService.java b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/SyncThirdDataService.java index 556001dd..fecf7994 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/SyncThirdDataService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/SyncThirdDataService.java @@ -156,4 +156,9 @@ public interface SyncThirdDataService { * @return */ void syncActiveShops(String appKey, String sign, JSONArray activeJsonArray); + + /** + * 同步匹配商品图库数据 + */ + void syncShopImages(Integer storeId); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/ProductMappingServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/ProductMappingServiceImpl.java index c2916f2f..6ab93098 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/ProductMappingServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/ProductMappingServiceImpl.java @@ -16,7 +16,6 @@ import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.annotation.ExcelProperty; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.suisung.mall.common.api.CommonResult; import com.suisung.mall.common.api.StateCode; @@ -165,8 +164,8 @@ public class ProductMappingServiceImpl extends BaseServiceImpl implements ShopImageMappingTempService { + + +} diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncBaseThirdSxAbstract.java b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncBaseThirdSxAbstract.java index 4bf60520..49bcf808 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncBaseThirdSxAbstract.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncBaseThirdSxAbstract.java @@ -32,6 +32,7 @@ import com.suisung.mall.common.modules.sixun.SxSyncGoods; import com.suisung.mall.common.modules.sixun.SxSyncVip; import com.suisung.mall.common.modules.store.ShopStoreActivityBase; import com.suisung.mall.common.modules.store.ShopStoreBase; +import com.suisung.mall.common.pojo.dto.LibraryProductDTO; import com.suisung.mall.common.pojo.req.SyncThirdMemberReq; import com.suisung.mall.common.utils.DateTimeUtils; import com.suisung.mall.common.utils.I18nUtil; @@ -41,6 +42,8 @@ import com.suisung.mall.shop.base.service.ShopBaseProductBrandService; import com.suisung.mall.shop.base.service.ShopBaseProductCategoryService; import com.suisung.mall.shop.base.service.ShopBaseProductSpecService; import com.suisung.mall.shop.base.service.ShopBaseProductTypeService; +import com.suisung.mall.shop.library.service.LibraryProductImageService; +import com.suisung.mall.shop.library.service.LibraryProductService; import com.suisung.mall.shop.number.service.ShopNumberSeqService; import com.suisung.mall.shop.number.service.impl.ShopNumberSeqServiceImpl; import com.suisung.mall.shop.product.service.ShopProductBaseService; @@ -95,6 +98,9 @@ public abstract class SyncBaseThirdSxAbstract{ @Autowired private ShopStoreActivityBaseService shopStoreActivityBaseService; + @Autowired + private LibraryProductService libraryProductService; + /** * 对商品分类进行保存 * @param list @@ -114,6 +120,7 @@ public abstract class SyncBaseThirdSxAbstract{ JSONObject o = (JSONObject) categoryListJSON.get(i); ShopBaseProductType productType=new ShopBaseProductType(); productType.setType_is_draft(1);//发布 + productType.setStore_id(Integer.valueOf(storeId)); if (o != null) { // 重要:分类类型处理(强调共性) Integer typeId = 1001; @@ -127,6 +134,7 @@ public abstract class SyncBaseThirdSxAbstract{ ShopBaseProductType newProductType = new ShopBaseProductType(); newProductType.setType_name(o.getStr("product_type")); newProductType.setType_buildin(0); + newProductType.setStore_id(Integer.valueOf(storeId)); if (productTypeService.save(newProductType)) { typeId = newProductType.getType_id(); } @@ -152,6 +160,10 @@ public abstract class SyncBaseThirdSxAbstract{ firstCate.setStore_id(storeId); firstCate.setType_id(typeId); firstCate.setData_source(2); + List libraryProductDTOS=libraryProductService.matchLibraryProducts(null,o.getStr("first_category_name"),new ArrayList<>()); + if(CollectionUtil.isNotEmpty(libraryProductDTOS)){ + firstCate.setCategory_image(libraryProductDTOS.get(0).getThumb()); + } if (productCategoryService.saveOrUpdate(firstCate)) { // 当前子分类的父类id firstParentId = firstCate.getId(); @@ -175,6 +187,11 @@ public abstract class SyncBaseThirdSxAbstract{ secondCate.setStore_id(storeId); secondCate.setType_id(typeId); secondCate.setData_source(2); + List libraryProductDTOS=libraryProductService.matchLibraryProducts(null,o.getStr("second_category_name"),new ArrayList<>()); + if(CollectionUtil.isNotEmpty(libraryProductDTOS)){ + secondCate.setCategory_image(libraryProductDTOS.get(0).getThumb()); + } + if (productCategoryService.saveOrUpdate(secondCate)) { // 当前子分类的第二级父类id list.get(i).setCategory_parent_id(secondCate.getId()); @@ -197,6 +214,10 @@ public abstract class SyncBaseThirdSxAbstract{ } } + List libraryProductDTOS=libraryProductService.matchLibraryProducts(null,list.get(i).getCategory_name(),new ArrayList<>()); + if(CollectionUtil.isNotEmpty(libraryProductDTOS)){ + list.get(i).setCategory_image(libraryProductDTOS.get(0).getThumb()); + } if (productCategoryService.saveOrUpdate(list.get(i))) { count++; @@ -541,6 +562,7 @@ public abstract class SyncBaseThirdSxAbstract{ List shopProductDetailList=new ArrayList<>(); ; List shopProductInfoList=new ArrayList<>(); ; List> shopProductItemLists=new ArrayList<>(); + List shopProductImageList=new ArrayList<>(); ShopStoreBase store_row = shopStoreBaseService.get(storeId); if (store_row == null) { throw new ApiException(I18nUtil._("无法获取店铺信息!")); @@ -588,7 +610,7 @@ public abstract class SyncBaseThirdSxAbstract{ shopProductBase.setUnit_price(BigDecimal.valueOf(jsonObj.getDouble("retail_price"))); }else { shopProductBase.setShop_weight(jsonObj.getBigDecimal("stock")); - shopProductBase.setProduct_state_id(StateCode.PRODUCT_STATE_NORMAL); + shopProductBase.setProduct_state_id(StateCode.PRODUCT_STATE_OFF_THE_SHELF);//默认是下架 shopProductBase.setUnit_price(BigDecimal.valueOf(jsonObj.getDouble("retail_price"))); } // ShopProductIndex @@ -653,6 +675,7 @@ public abstract class SyncBaseThirdSxAbstract{ ShopProductItem shopProductItem = new ShopProductItem(); shopProductItem.setStore_id(storeIdInt); shopProductItem.setCategory_id(categoryId); + shopProductItem.setItem_src_id(jsonObj.getLong("product_number")); //零售价 shopProductItem.setItem_unit_price(BigDecimal.valueOf(jsonObj.getDouble("retail_price"))); shopProductItem.setItem_advice_price(BigDecimal.valueOf(jsonObj.getDouble("retail_price"))); @@ -672,6 +695,12 @@ public abstract class SyncBaseThirdSxAbstract{ shopProductItem.setItem_is_default(1); shopProductItem.setItem_enable(shopProductBase.getProduct_state_id()); + //shopProductImage + ShopProductImage shopProductImage = new ShopProductImage(); + shopProductImage.setStore_id(storeIdInt); + shopProductImage.setProduct_name(jsonObj.getStr("product_name")); + shopProductImage.setProduct_from("1005"); + //添加数据到list synchronized(shopProductBaseList){ shopProductItemList.add(shopProductItem); @@ -681,12 +710,13 @@ public abstract class SyncBaseThirdSxAbstract{ shopProductDetailList.add(shopProductDetail); shopProductInfoList.add(shopProductInfo); shopProductItemLists.add(shopProductItemList); + shopProductImageList.add(shopProductImage); } resultCount.addAndGet(1); }); // 保存数据 shopProductBaseService.saveProductBatch(shopProductBaseList,shopProductIndexList,shopProductDataList,shopProductDetailList,shopProductInfoList,shopProductItemLists, - new ArrayList>(), + shopProductImageList, new ArrayList(), new ArrayList()); diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncShopImageServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncShopImageServiceImpl.java new file mode 100644 index 00000000..f638d5e2 --- /dev/null +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncShopImageServiceImpl.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.suisung.mall.shop.sync.service.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.suisung.mall.common.api.StateCode; +import com.suisung.mall.common.modules.product.ShopProductBase; +import com.suisung.mall.common.modules.product.ShopProductImage; +import com.suisung.mall.common.modules.product.ShopProductItem; +import com.suisung.mall.common.modules.sync.ImageMappingDto; +import com.suisung.mall.common.utils.StringUtils; +import com.suisung.mall.shop.product.mapper.ShopProductImageMapper; + +import com.suisung.mall.shop.product.service.ShopProductBaseService; +import com.suisung.mall.shop.product.service.ShopProductImageService; +import com.suisung.mall.shop.product.service.ShopProductItemService; +import com.suisung.mall.shop.sixun.utils.CommonUtil; +import com.suisung.mall.shop.sync.mapper.ShopImageMappingTempMapper; +import com.suisung.mall.shop.sync.service.SyncShopImageService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicInteger; + + +@Service +@Slf4j +public class SyncShopImageServiceImpl implements SyncShopImageService { + + @Autowired + private ShopProductImageMapper shopProductImageMapper; + + @Autowired + private ShopImageMappingTempMapper shopImageMappingTempMapper; + + @Autowired + private ShopProductImageService shopProductImageService; + + @Autowired + private ShopProductItemService shopProductItemService; + + @Autowired + private ShopProductBaseService shopProductBaseService; + + @Value("${project.static_domain}") + private String staticDomain; + + private final static Integer BATCH_SIZE=500; + private final static String MAPPING_BARCODE="1";//条形码匹配 + private final static String MAPPING_PRODUCTSHORTNAME="2";//标准名称匹配 + private final static String MAPPING_PRODUCTNAME="3";//产品名称模糊匹配 + + + @Override + public void syncMapingShopImages(Integer storeId) { + mappingProductImages(MAPPING_BARCODE,storeId); + mappingProductImages(MAPPING_PRODUCTSHORTNAME,storeId); + mappingProductImages(MAPPING_PRODUCTNAME,storeId); + } + + /** + * 通过类型匹配 使用游标方式 + * 1、条形码匹配 + * 2、标准名称匹配 + * 3、产品名称模糊匹配 + */ + public void mappingProductImages(String type,Integer storeId){ + Integer total=null; + String typename=""; + switch (type){ + case MAPPING_BARCODE: + typename="条形码匹配"; + total= shopProductImageMapper.mappingByBarCodeCount(storeId); + break; + case MAPPING_PRODUCTSHORTNAME: + typename="标准名称匹配"; + total= shopProductImageMapper.mappingByProductShortNameCount(storeId); + break; + case MAPPING_PRODUCTNAME: + typename="产品名称模糊匹配"; + //先把数据查到临时表再查询 + shopImageMappingTempMapper.deleteShopImageMappingTemp(storeId);//匹配结束,删除临时表数据 + shopImageMappingTempMapper.mergeShopImageMappingTemp(storeId); + total= shopProductImageMapper.mappingByProductNameCount(storeId); + + break; + } + if(total!=null&&total<1){ + log.info("{}无数据",typename); + return; + } + ExecutorService executor = Executors.newFixedThreadPool(6); + List> futures = new ArrayList<>(); + Integer pages= CommonUtil.getPagesCount(total,BATCH_SIZE); + + AtomicInteger success = new AtomicInteger(); + AtomicInteger fails = new AtomicInteger(); + for (int i = 1; i <= pages; i++) { + List imageMappingDtos = shopProductImageMapper.mappingProductImage(type,storeId,(i-1)*BATCH_SIZE,BATCH_SIZE); + final int finalI = i; + futures.add(executor.submit(() -> { + try { + syncBatchShopImage(imageMappingDtos); + success.getAndIncrement(); + return "成功" + finalI; + } catch (Exception e) { + fails.getAndIncrement(); + return "失败"+finalI; + } + })); + } + // 等待所有任务完成 + for (Future future : futures) { + try { + log.info("任务结果: " + future.get()); + } catch (Exception e) { + log.error("任务执行异常: " + e.getMessage()); + } + } + executor.shutdown(); + log.info("成功:{}条,失败:{}条",success,fails); + } + + + /** + * 把匹配的数据更新到商品的图库表 + * @param imageMappingDtos + */ + private void syncBatchShopImage(List imageMappingDtos){ + if(CollectionUtil.isEmpty(imageMappingDtos)){ + log.info("没有匹配到图库"); + return; + } + List shopProductBaseList=new ArrayList<>(); + List shopProductItemList=new ArrayList<>(); + List shopProductImageList=new ArrayList<>(); + for (ImageMappingDto imageMappingDto:imageMappingDtos){ + String mergedImageUrl=imageMappingDto.getMergedImageUrl(); + if(StringUtils.isEmpty(mergedImageUrl)){ + continue; + } + ShopProductImage shopProductImage=new ShopProductImage(); + ShopProductBase shopProductBase=new ShopProductBase(); + ShopProductItem shopProductItem=new ShopProductItem(); + if(mergedImageUrl.contains(",")){ + String [] imageUrls= mergedImageUrl.split(","); + for (String imageUrl:imageUrls){ + shopProductImage.setItem_image_other(imageMappingDto.addDomainPrefix(staticDomain,imageUrl)); + } + }else { + shopProductImage.setItem_image_other(imageMappingDto.addDomainPrefix(staticDomain,mergedImageUrl)); + } + shopProductImage.setProduct_id(imageMappingDto.getProductId()); + shopProductImage.setProduct_image_id(imageMappingDto.getProductImageId()); + shopProductImage.setItem_image_default(imageMappingDto.addDomainPrefix(staticDomain,imageMappingDto.getThumb())); + shopProductImageList.add(shopProductImage); + shopProductBase.setProduct_id(imageMappingDto.getProductId()); + shopProductBase.setProduct_state_id(StateCode.PRODUCT_STATE_NORMAL); + shopProductBaseList.add(shopProductBase); + shopProductItem.setItem_enable(StateCode.PRODUCT_STATE_NORMAL); + shopProductItemList.add(shopProductItem); + } + if(CollectionUtil.isNotEmpty(shopProductImageList)){ + shopProductImageService.updateBatchById(shopProductImageList); + } + if(CollectionUtil.isNotEmpty(shopProductBaseList)){ + shopProductBaseService.updateBatchById(shopProductBaseList); + } + if(CollectionUtil.isNotEmpty(shopProductItemList)){ + shopProductItemService.updateBatchById(shopProductItemList); + } + } + +} diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncThirdDataServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncThirdDataServiceImpl.java index f6f56256..7947bf24 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncThirdDataServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sync/service/impl/SyncThirdDataServiceImpl.java @@ -153,6 +153,9 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements @Autowired private ShopStoreActivityBaseService shopStoreActivityBaseService; + @Autowired + private SyncShopImageService syncShopImageService; + /** * 批量保存商品的分类 * @@ -609,6 +612,12 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements logger.error("同步时间失败" + e.getMessage()); } + syncShopImages(Integer.valueOf(storeId));//同时商品图库数据 + } + + @Override + public void syncShopImages(Integer storeId){ + syncShopImageService.syncMapingShopImages(storeId); } @Override @@ -771,7 +780,7 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements for (Map.Entry entry : stockDeltaMap.entrySet()) { String productKey = entry.getKey(); Integer delta = entry.getValue(); - if (StrUtil.isBlank(productKey) || productKey.equals("0") || delta == null || delta.equals(0)) { + if (StrUtil.isBlank(productKey) || delta == null) { continue; } @@ -847,41 +856,41 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements @Override - public ThirdApiRes fileUploadToOss(String appKey, String sign, String syncType, Date refreshDate, List folders) { - if (StrUtil.isBlank(appKey) || StrUtil.isBlank(sign)) { + public ThirdApiRes fileUploadToOss(String appKey, String sign, String syncType,Date refreshDate, List folders) { + if (StrUtil.isBlank(appKey) || StrUtil.isBlank(sign) ) { return new ThirdApiRes().fail(1003, I18nUtil._("缺少必要参数!")); } // 验签、appid,必要参数判断 SyncApp syncApp = syncAppService.getOne(new LambdaQueryWrapper() - .select(SyncApp::getApp_key, SyncApp::getApp_secret, SyncApp::getStore_id) + .select(SyncApp::getApp_key, SyncApp::getApp_secret,SyncApp::getStore_id) .eq(SyncApp::getApp_key, appKey) - .eq(SyncApp::getApp_secret, sign)); + .eq(SyncApp::getApp_secret,sign)); if (syncApp == null) { return new ThirdApiRes().fail(1001, I18nUtil._("签名有误!")); } String storeId = syncApp.getStore_id(); - if (null == syncApp.getStore_id() || syncApp.getStore_id().isEmpty()) { + if(null==syncApp.getStore_id()|| syncApp.getStore_id().isEmpty()){ logger.info("商店id为空"); - return new ThirdApiRes().fail(250, "商店id为空"); + return new ThirdApiRes().fail(250,"商店id为空"); } - if (folders == null || folders.isEmpty()) { + if(folders==null||folders.isEmpty()){ logger.info("没有商品数据"); - return new ThirdApiRes().fail(250, "没有商品数据"); + return new ThirdApiRes().fail(250,"没有商品数据"); } - String newfolder = new FileUtils().getSyncTypeFlag(syncType, clientPath) + storeId + FileUtils.pathSeparator + folders.get(0) + FileUtils.pathSeparator; + String newfolder=new FileUtils().getSyncTypeFlag(syncType,clientPath)+storeId+FileUtils.pathSeparator+folders.get(0)+FileUtils.pathSeparator; upLoadZipToOss(newfolder);//上传文件到cos //更新当前的获取时间,用户客户端获取 try { QueryWrapper storeDbConfigQueryWrapper = new QueryWrapper<>(); storeDbConfigQueryWrapper.eq("store_id", storeId); - StoreDbConfig storeDbConfig = storeDbConfigService.getOne(storeDbConfigQueryWrapper); - if (ObjectUtil.isNotEmpty(storeDbConfig)) { + StoreDbConfig storeDbConfig=storeDbConfigService.getOne(storeDbConfigQueryWrapper); + if(ObjectUtil.isNotEmpty(storeDbConfig)){ storeDbConfig.setRefreshTime(refreshDate); storeDbConfigService.saveOrUpdate(storeDbConfig); } - } catch (RuntimeException e) { - logger.error("同步时间失败" + e.getMessage()); + }catch (RuntimeException e){ + logger.error("同步时间失败"+e.getMessage()); } return new ThirdApiRes().success("上传成功"); } @@ -895,9 +904,9 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements } // 验签、appid,必要参数判断 SyncApp syncAppO = syncAppService.getOne(new LambdaQueryWrapper() - .select(SyncApp::getApp_key, SyncApp::getApp_secret, SyncApp::getStore_id) + .select(SyncApp::getApp_key, SyncApp::getApp_secret,SyncApp::getStore_id) .eq(SyncApp::getApp_key, appKey) - .eq(SyncApp::getApp_secret, sign)); + .eq(SyncApp::getApp_secret,sign)); if (syncAppO == null) { logger.error("签名有误!"); return; @@ -909,21 +918,20 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements /** * 批量新增或更新活动数据 - * * @param jsonArray */ - private void batchSaveShopStoreActivityBase(JSONArray jsonArray, Integer storeId) { - List addshopStoreActivityBaseList = new ArrayList<>(); - List updateShopStoreActivityBaseList = new ArrayList<>(); - Map stringIntegerMap = checkExistingActive(jsonArray, storeId); - jsonArray.stream().parallel().forEach(object -> { - final JSONObject jsonObj = (JSONObject) object; - String activityName = jsonObj.getStr("activityName"); - Integer activityTypeId = jsonObj.getInt("activityTypeId"); - if (null == activityTypeId) { + private void batchSaveShopStoreActivityBase(JSONArray jsonArray,Integer storeId) { + List addshopStoreActivityBaseList=new ArrayList<>(); + List updateShopStoreActivityBaseList=new ArrayList<>(); + Map stringIntegerMap= checkExistingActive(jsonArray,storeId); + jsonArray.stream().parallel().forEach(object->{ + final JSONObject jsonObj= (JSONObject) object; + String activityName=jsonObj.getStr("activityName"); + Integer activityTypeId=jsonObj.getInt("activityTypeId"); + if(null==activityTypeId){ return; } - ShopStoreActivityBase shopStoreActivityBase = new ShopStoreActivityBase(); + ShopStoreActivityBase shopStoreActivityBase=new ShopStoreActivityBase(); if (activityTypeId == 1) { activityTypeId = StateCode.ACTIVITY_TYPE_LIMITED_DISCOUNT; //限时秒杀 } @@ -931,17 +939,17 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements activityTypeId = StateCode.ACTIVITY_TYPE_ONE_PIECE_DISCOUNT; //折扣 } if (activityTypeId == 3) { - JSONArray activeMaxDesList = jsonObj.getJSONArray("activeMaxDesList"); + JSONArray activeMaxDesList=jsonObj.getJSONArray("activeMaxDesList"); activityTypeId = StateCode.ACTIVITY_TYPE_REDUCTION; //满减 - String rules = ActiveShopJsonUtils.getRules(activeMaxDesList); + String rules= ActiveShopJsonUtils.getRules(activeMaxDesList); shopStoreActivityBase.setActivity_rule(rules); } - Date activityStarttime = jsonObj.getDate("activityStarttime"); - Date activityEndtime = jsonObj.getDate("activityEndtime"); - Integer activityState = jsonObj.getInt("activityState"); - Date activityReleasetime = jsonObj.getDate("activityReleasetime"); - BigDecimal discount = jsonObj.getBigDecimal("discount"); - String key = activityName + "_" + activityStarttime.getTime() + "_" + activityState; + Date activityStarttime=jsonObj.getDate("activityStarttime"); + Date activityEndtime=jsonObj.getDate("activityEndtime"); + Integer activityState=jsonObj.getInt("activityState"); + Date activityReleasetime= jsonObj.getDate("activityReleasetime"); + BigDecimal discount=jsonObj.getBigDecimal("discount"); + String key=activityName+"_"+activityStarttime.getTime()+"_"+activityState; shopStoreActivityBase.setActivity_state(activityState); shopStoreActivityBase.setActivity_name(activityName); shopStoreActivityBase.setActivity_type(1);//免费参与 @@ -953,19 +961,19 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements shopStoreActivityBase.setActivity_endtime(activityEndtime); shopStoreActivityBase.setActivity_state(activityState); shopStoreActivityBase.setSubsite_id(0); - if (stringIntegerMap.containsKey(key)) {//更新 - String keyVal = MapUtil.getStr(stringIntegerMap, key); - shopStoreActivityBase.setActivity_id(MapUtil.getInt(stringIntegerMap, keyVal.split("_")[0])); + if(stringIntegerMap.containsKey(key)){//更新 + String keyVal= MapUtil.getStr(stringIntegerMap,key); + shopStoreActivityBase.setActivity_id(MapUtil.getInt(stringIntegerMap,keyVal.split("_")[0])); updateShopStoreActivityBaseList.add(shopStoreActivityBase); - } else { + }else { addshopStoreActivityBaseList.add(shopStoreActivityBase); } }); - if (CollectionUtil.isNotEmpty(addshopStoreActivityBaseList)) { - shopStoreActivityBaseService.saveBatch(addshopStoreActivityBaseList, addshopStoreActivityBaseList.size()); + if(CollectionUtil.isNotEmpty(addshopStoreActivityBaseList)){ + shopStoreActivityBaseService.saveBatch(addshopStoreActivityBaseList,addshopStoreActivityBaseList.size()); } - if (CollectionUtil.isNotEmpty(updateShopStoreActivityBaseList)) { + if(CollectionUtil.isNotEmpty(updateShopStoreActivityBaseList)){ shopStoreActivityBaseService.updateBatchById(updateShopStoreActivityBaseList); } @@ -976,7 +984,6 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements * 将商品添加到活动 * 1、找出匹配的活动 * 2、新增商品到活动列表 - * * @param appKey * @param sign * @param activeJsonArray @@ -990,9 +997,9 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements } // 验签、appid,必要参数判断 SyncApp syncAppO = syncAppService.getOne(new LambdaQueryWrapper() - .select(SyncApp::getApp_key, SyncApp::getApp_secret, SyncApp::getStore_id) + .select(SyncApp::getApp_key, SyncApp::getApp_secret,SyncApp::getStore_id) .eq(SyncApp::getApp_key, appKey) - .eq(SyncApp::getApp_secret, sign)); + .eq(SyncApp::getApp_secret,sign)); if (syncAppO == null) { logger.error("签名有误!"); return; @@ -1004,84 +1011,83 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements /** * 批量新增或更新活动商品数据 - * * @param jsonArray */ - private void batchAddActiveShopBase(JSONArray jsonArray, Integer storeId) { - List updateShopStoreActivityBaseList = new ArrayList<>(); - Map stringIntegerMap = checkExistingActive(jsonArray, storeId); - Map shopProduckKeyMap = shopProductBaseService.getProductBasicIdByStore(storeId);//获取货架号对应的商品id - Map shopItemKeyMap = shopProductItemService.getProductItemIdByStore(storeId);//获取商品id对应的item的id - Map rulesChe = new HashMap();//存储rule格式activeId:rules,如果不存在则从数据库取,存在则从缓存取数据 - jsonArray.forEach(object -> { - final JSONObject jsonObj = (JSONObject) object; - String activityName = jsonObj.getStr("activityName"); - Integer activityTypeId = jsonObj.getInt("activityTypeId"); - if (null == activityTypeId) { + private void batchAddActiveShopBase(JSONArray jsonArray,Integer storeId) { + List updateShopStoreActivityBaseList=new ArrayList<>(); + Map stringIntegerMap= checkExistingActive(jsonArray,storeId); + Map shopProduckKeyMap=shopProductBaseService.getProductBasicIdByStore(storeId);//获取货架号对应的商品id + Map shopItemKeyMap=shopProductItemService.getProductItemIdByStore(storeId);//获取商品id对应的item的id + Map rulesChe=new HashMap();//存储rule格式activeId:rules,如果不存在则从数据库取,存在则从缓存取数据 + jsonArray.forEach(object->{ + final JSONObject jsonObj= (JSONObject) object; + String activityName=jsonObj.getStr("activityName"); + Integer activityTypeId=jsonObj.getInt("activityTypeId"); + if(null==activityTypeId){ return; } - String ruleType = ""; - List newItems = new ArrayList<>(); - ShopStoreActivityBase shopStoreActivityBase = new ShopStoreActivityBase(); - Integer productId = null; - String itemNo = jsonObj.getStr("itemNo"); - BigDecimal discount = jsonObj.getBigDecimal("discount"); - if (shopProduckKeyMap.containsKey(itemNo)) { - productId = (Integer) shopProduckKeyMap.get(itemNo); + String ruleType=""; + List newItems=new ArrayList<>(); + ShopStoreActivityBase shopStoreActivityBase=new ShopStoreActivityBase(); + Integer productId=null; + String itemNo=jsonObj.getStr("itemNo"); + BigDecimal discount=jsonObj.getBigDecimal("discount"); + if(shopProduckKeyMap.containsKey(itemNo)){ + productId= (Integer) shopProduckKeyMap.get(itemNo); } - if (null == productId) { + if(null==productId){ return; } - Date activityStarttime = jsonObj.getDate("activityStarttime"); - Integer activityState = jsonObj.getInt("activityState"); + Date activityStarttime=jsonObj.getDate("activityStarttime"); + Integer activityState=jsonObj.getInt("activityState"); - String key = activityName + "_" + activityStarttime.getTime() + "_" + activityState; + String key=activityName+"_"+activityStarttime.getTime()+"_"+activityState; - if (stringIntegerMap.containsKey(key)) {//更新 - String keyVal = MapUtil.getStr(stringIntegerMap, key); - String activityId = keyVal.split("_")[0]; - String rules = ""; - if (null != rulesChe.get(activityId)) { - rules = rulesChe.get(activityId); - } else { - rules = keyVal.split("_")[1]; + if(stringIntegerMap.containsKey(key)){//更新 + String keyVal=MapUtil.getStr(stringIntegerMap,key); + String activityId=keyVal.split("_")[0]; + String rules=""; + if(null!=rulesChe.get(activityId)){ + rules=rulesChe.get(activityId); + }else { + rules=keyVal.split("_")[1]; } - String itemIds = (String) shopItemKeyMap.get(productId); - if (null != itemIds) { - itemIds = (String) shopItemKeyMap.get(String.valueOf(productId)); + String itemIds= (String) shopItemKeyMap.get(productId); + if(null!=itemIds){ + itemIds= (String) shopItemKeyMap.get(String.valueOf(productId)); } assert itemIds != null; if (activityTypeId == 1) {//限时秒杀 - ruleType = ActiveShopJsonUtils.SECKILL; - BigDecimal oldPrice = jsonObj.getBigDecimal("oldPrice"); - BigDecimal specPrice = jsonObj.getBigDecimal("specPrice"); - if (oldPrice.compareTo(BigDecimal.ZERO) > 0 && specPrice.compareTo(BigDecimal.ZERO) > 0) { - BigDecimal newDiscout = specPrice.divide(oldPrice, 4, RoundingMode.HALF_UP); - newItems.addAll(getFulReduItemList(itemIds, ruleType, newDiscout));//获取满减规则的itemid + ruleType=ActiveShopJsonUtils.SECKILL; + BigDecimal oldPrice=jsonObj.getBigDecimal("oldPrice"); + BigDecimal specPrice=jsonObj.getBigDecimal("specPrice"); + if(oldPrice.compareTo(BigDecimal.ZERO)>0&&specPrice.compareTo(BigDecimal.ZERO)>0){ + BigDecimal newDiscout=specPrice.divide(oldPrice,4, RoundingMode.HALF_UP); + newItems.addAll(getFulReduItemList(itemIds,ruleType,newDiscout));//获取满减规则的itemid } } if (activityTypeId == 2) {//折扣 - if (discount.compareTo(BigDecimal.ZERO) <= 0) { + if(discount.compareTo(BigDecimal.ZERO)<=0){ logger.error("商品折扣要大于0"); return; } - ruleType = ActiveShopJsonUtils.DISCOUNT; - newItems.addAll(getFulReduItemList(itemIds, ruleType, discount));//获取满减规则的itemid + ruleType=ActiveShopJsonUtils.DISCOUNT; + newItems.addAll(getFulReduItemList(itemIds,ruleType,discount));//获取满减规则的itemid } if (activityTypeId == 3) {//满减 - ruleType = ActiveShopJsonUtils.FULLREDUCE; - newItems.addAll(getFulReduItemList(itemIds, ruleType, null));//获取满减规则的itemid + ruleType=ActiveShopJsonUtils.FULLREDUCE; + newItems.addAll(getFulReduItemList(itemIds,ruleType,null));//获取满减规则的itemid } - shopStoreActivityBase.setActivity_id(MapUtil.getInt(stringIntegerMap, activityId)); - String newRules = ActiveShopJsonUtils.buildPromotionRule(ruleType, rules, newItems); - rulesChe.put(activityId, newRules); + shopStoreActivityBase.setActivity_id(MapUtil.getInt(stringIntegerMap,activityId)); + String newRules= ActiveShopJsonUtils.buildPromotionRule(ruleType,rules,newItems); + rulesChe.put(activityId,newRules); shopStoreActivityBase.setActivity_rule(rules); updateShopStoreActivityBaseList.add(shopStoreActivityBase); } }); - if (CollectionUtil.isNotEmpty(updateShopStoreActivityBaseList)) { + if(CollectionUtil.isNotEmpty(updateShopStoreActivityBaseList)){ shopStoreActivityBaseService.updateBatchById(updateShopStoreActivityBaseList); } @@ -1091,59 +1097,58 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements * 一对多,如product_id:1002,item_number:120_121;数据格式为item_id,item_id item_unit_price,item_unit_price * 最终组合item_id,item_id_item_unit_price,item_unit_price * 满减的切割规则的itemid - * * @param itemPrice * @return */ - private List getFulReduItemList(String itemPrice, String activeType, BigDecimal discount) { - List newItems = new ArrayList<>(); - String[] itemPriceArray = itemPrice.split("_"); - String itemIds = itemPriceArray[0]; - String unitPrices = itemPriceArray[1]; - switch (activeType) { + private List getFulReduItemList(String itemPrice,String activeType,BigDecimal discount){ + List newItems=new ArrayList<>(); + String [] itemPriceArray=itemPrice.split("_"); + String itemIds=itemPriceArray[0]; + String unitPrices=itemPriceArray[1]; + switch (activeType){ case ActiveShopJsonUtils.DISCOUNT: - if (itemIds.contains(",")) { - String[] itemIdsArray = itemIds.split(","); + if(itemIds.contains(",")){ + String [] itemIdsArray=itemIds.split(","); for (String itemId : itemIdsArray) { org.json.JSONObject jsonObject = new org.json.JSONObject(); jsonObject.put("item_id", itemId); jsonObject.put("rate", BigDecimalFormatter.formatWithoutTrailingZeros(discount.multiply(new BigDecimal(100)))); newItems.add(jsonObject); } - } else { - org.json.JSONObject jsonObject = new org.json.JSONObject(); - jsonObject.put("item_id", itemIds); + }else { + org.json.JSONObject jsonObject=new org.json.JSONObject(); + jsonObject.put("item_id",itemIds); jsonObject.put("rate", BigDecimalFormatter.formatWithoutTrailingZeros(discount.multiply(new BigDecimal(100)))); newItems.add(jsonObject); } break; case ActiveShopJsonUtils.FULLREDUCE: - if (itemIds.contains(",")) { - String[] itemIdsArray = itemIds.split(","); - for (String itemId : itemIdsArray) { - org.json.JSONObject jsonObject = new org.json.JSONObject(); - jsonObject.put("item_id", itemId); + if(itemIds.contains(",")){ + String [] itemIdsArray=itemIds.split(","); + for(String itemId:itemIdsArray){ + org.json.JSONObject jsonObject=new org.json.JSONObject(); + jsonObject.put("item_id",itemId); newItems.add(jsonObject); } - } else { - org.json.JSONObject jsonObject = new org.json.JSONObject(); - jsonObject.put("item_id", itemIds); + }else { + org.json.JSONObject jsonObject=new org.json.JSONObject(); + jsonObject.put("item_id",itemIds); newItems.add(jsonObject); } break; case ActiveShopJsonUtils.SECKILL: - if (itemIds.contains(",")) { - String[] unitPricesArray = unitPrices.split(","); - String[] itemIdsArray = itemIds.split(","); - for (int i = 0; i < itemIdsArray.length; i++) { + if(itemIds.contains(",")){ + String [] unitPricesArray=unitPrices.split(","); + String [] itemIdsArray=itemIds.split(","); + for (int i=0;i + + + + + + id, product_image_id, product_id, product_name, store_id, merged_image_url, thumb,name + + + INSERT into shop_image_mapping_temp(product_image_id,product_id,product_name,store_id,merged_image_url,thumb,name) + SELECT + temp.product_image_id, + temp.product_id, + temp.product_name, + temp.store_id, + temp. merged_image_url, + temp.thumb, + temp.name + from + ( + SELECT + ROW_NUMBER() over(partition by t.product_name + order by + t.id) rn, + t.* + from + ( + SELECT + spi.product_image_id, + spi.product_id, + spi.product_name, + spi.store_id, + lpi. merged_image_url, + lp.thumb, + lp.id, + lp.name + FROM + -- (select * from shop_product_image limit 7500,500) spi + shop_product_image spi + INNER JOIN library_product lp ON + spi.product_name like CONCAT(lp.name,"%") + -- MATCH(spi.product_name) AGAINST(CONCAT(lp.name, '*') IN BOOLEAN MODE) + -- AND spi.product_name LIKE CONCAT(lp.name, '%') -- 保持精确匹配 + LEFT JOIN ( + SELECT + product_id, + GROUP_CONCAT(image_url SEPARATOR ',') AS merged_image_url + FROM + library_product_image + WHERE + is_main = '0' + GROUP BY + product_id ) lpi ON + lp.id = lpi.product_id + WHERE + spi.product_from = '1005' + AND spi.item_image_default = '1' )t )temp + where + temp.rn = 1 and temp.store_id=#{storeId} + + + + delete from shop_image_mapping_temp where store_id=#{storeId} + + + diff --git a/mall-shop/src/main/resources/mapper/product/ShopProductImageMapper.xml b/mall-shop/src/main/resources/mapper/product/ShopProductImageMapper.xml index 188f4657..2b885a43 100644 --- a/mall-shop/src/main/resources/mapper/product/ShopProductImageMapper.xml +++ b/mall-shop/src/main/resources/mapper/product/ShopProductImageMapper.xml @@ -8,4 +8,249 @@ item_image_diy, item_video, item_image_ext_1, item_image_ext_2 + + + + + + + + + + + + + + + SELECT + temp.product_image_id, + temp.product_id, + temp.store_id, + temp. merged_image_url, + temp.thumb, + temp.name + from + ( + SELECT + ROW_NUMBER() over(partition by t.product_name order by t.id) rn,t.* + from + ( + SELECT + spi.product_image_id, + spi.product_id, + spi.product_name, + spi.store_id, + lpi. merged_image_url, + lp.thumb, + lp.id, + lp.name + FROM + shop_product_image spi + INNER JOIN + library_product lp ON + spi.product_number = lp.barcode + LEFT JOIN + ( + SELECT + product_id, + GROUP_CONCAT(image_url SEPARATOR ',') AS merged_image_url + FROM + library_product_image + WHERE + is_main = '0' + GROUP BY + product_id + ) lpi ON + lp.id = lpi.product_id + WHERE + spi.product_from = '1005' + AND spi.item_image_default = '1' + '' ]]>)t + )temp + where + temp.rn = 1 and temp.store_id=#{storeId} limit #{offset},#{limit} + + + + + + SELECT + temp.product_image_id, + temp.product_id, + temp.store_id, + temp. merged_image_url, + temp.thumb, + temp.name + from + ( + SELECT + ROW_NUMBER() over(partition by t.product_name order by t.id) rn,t.* + from + ( + SELECT + spi.product_image_id, + spi.product_id, + spi.product_name, + spi.store_id, + lpi. merged_image_url, + lp.thumb, + lp.id, + lp.name + FROM + shop_product_image spi + INNER JOIN + library_product lp ON + spi.product_short_name = lp.product_short_name + LEFT JOIN + ( + SELECT + product_id, + GROUP_CONCAT(image_url SEPARATOR ',') AS merged_image_url + FROM + library_product_image + WHERE + is_main = '0' + GROUP BY + product_id + ) lpi ON + lp.id = lpi.product_id + WHERE + spi.product_from = '1005' + AND spi.item_image_default = '1' + '' ]]> + )t + )temp + where + temp.rn = 1 and temp.store_id=#{storeId} limit #{offset},#{limit} + + + + + + select product_image_id, + product_id, + product_name, + store_id, + merged_image_url, + thumb,name + from shop_image_mapping_temp + where store_id=#{storeId} limit #{offset},#{limit} + + + diff --git a/sql/shop/dev/202506023_ddl.sql b/sql/shop/dev/202506023_ddl.sql new file mode 100644 index 00000000..84126065 --- /dev/null +++ b/sql/shop/dev/202506023_ddl.sql @@ -0,0 +1,33 @@ +alter table shop_product_image add `product_name` varchar(100) DEFAULT '' COMMENT '产品名称同步数据用'; +alter table shop_product_image add `product_number` varchar(50) DEFAULT '' COMMENT '商品货号同步数据用'; + + +alter table shop_product_image add `product_short_name` varchar(100) DEFAULT '' COMMENT '商品简称,作为匹配关键字'; +alter table library_product add `product_short_name` varchar(100) DEFAULT '' COMMENT '商品简称,作为匹配关键字'; +alter table shop_product_base add `product_short_name` varchar(100) DEFAULT '' COMMENT '商品简称,作为匹配关键字'; +alter table shop_product_image add `product_from` varchar(5) DEFAULT '' COMMENT '商品来源(ENUM):1000-发布;1001-天猫;1002-淘宝;1003-阿里巴巴;1004-京东;1005-思迅;同步数据匹配'; + +alter table shop_product_image add index `index_sproduct_short_name` (`product_short_name`) USING BTREE; +alter table library_product add index `index_product_short_name` (`product_short_name`) USING BTREE; +alter table shop_product_base add index `index_product_short_name` (`product_short_name`) USING BTREE; +alter table shop_product_image add index `index_product_from` (`product_from`) USING BTREE; +CREATE INDEX idx_shop_product_filter ON shop_product_image(product_from, item_image_default) USING BTREE; + +CREATE TABLE shop_image_mapping_temp ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '临时表id', + `product_image_id` bigint unsigned DEFAULT NULL COMMENT '商品图片编号', + `product_id` bigint unsigned DEFAULT 0 COMMENT '产品编号:product_id-color_id', + `product_name` varchar(100) DEFAULT '' COMMENT '产品名称同步数据用', + `store_id` int unsigned DEFAULT NULL COMMENT '店铺编号', + `merged_image_url` text COMMENT '合并后的图片URL', + `name` varchar(255) DEFAULT '' COMMENT '图库商品名', + `thumb` varchar(512) DEFAULT '' COMMENT '主图', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时', + PRIMARY KEY (`id`), + KEY `index_product_name` (`product_name`) USING BTREE, + KEY `index_name` (`name`) USING BTREE, + KEY `index_store_id` (`store_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品图片映射临时表'; + +