diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/FhbController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/FhbController.java index 5a2ce6cf9..801fde9fb 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/FhbController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/FhbController.java @@ -6,6 +6,8 @@ import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.web.controller.xkt.migartion.vo.CusDiscErrorVO; import com.ruoyi.web.controller.xkt.migartion.vo.fhb.FhbCusDiscountVO; import com.ruoyi.web.controller.xkt.migartion.vo.fhb.FhbCusVO; @@ -18,6 +20,9 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletResponse; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -132,24 +137,22 @@ public class FhbController extends BaseController { * @return */ @PreAuthorize("@ss.hasAnyRoles('admin,general_admin')") - @GetMapping("/error/cus/disc/{supplierId}") - public R getErrorCusDisc(@PathVariable Integer supplierId) { + @GetMapping("/error/cus/price/{supplierId}") + public void getErrorCusDisc(HttpServletResponse response, @PathVariable Integer supplierId) throws UnsupportedEncodingException { // 先从redis中获取列表数据 List cacheList = ObjectUtils.defaultIfNull(redisCache .getCacheObject(CacheConstants.MIGRATION_SUPPLIER_CUS_DISCOUNT_KEY + supplierId), new ArrayList<>()); - if (CollectionUtils.isEmpty(cacheList)) { - return R.ok(); - } - List errDiscList = new ArrayList<>(); + List errList = new ArrayList<>(); // 1. 有哪些是优惠价大于销售价的 cacheList.forEach(record -> { final Integer supplyPrice = ObjectUtils.defaultIfNull(record.getSupplyPrice(), 0); final Integer customerPrice = ObjectUtils.defaultIfNull(record.getCustomerPrice(), 0); - if (supplyPrice - customerPrice <= 0) { - errDiscList.add(record.getArtNo() + ":" + record.getCustomerName() + ":" + record.getColor() + ",优惠价大于原售价"); + if (supplyPrice - customerPrice < 0) { + errList.add(new CusDiscErrorVO().setCusName(record.getCustomerName()).setProdArtNum(record.getArtNo()) + .setColorName(record.getColor()).setErrMsg("优惠价大于原售价").setDetail("销售价:" + supplyPrice + " 优惠价:" + customerPrice)); } }); - // 2. 有哪些优惠是同一货号不同颜色优惠金额不一致 + /*// 2. 有哪些优惠是同一货号不同颜色优惠金额不一致 List errCusDiscUnSameList = new ArrayList<>(); Map>> artNoCusDiscMap = cacheList.stream().collect(Collectors .groupingBy(FhbCusDiscountVO.SMCDRecordVO::getArtNo, Collectors.groupingBy(FhbCusDiscountVO.SMCDRecordVO::getCustomerName))); @@ -162,8 +165,14 @@ public class FhbController extends BaseController { if (discValueSet.size() > 1) { errCusDiscUnSameList.add(artNo + ":" + cusName + ":" + colorDiscMap.keySet() + ",优惠金额不一致"); } - })); - return R.ok(new CusDiscErrorVO().setErrDiscList(errDiscList).setErrCusDiscUnSameList(errCusDiscUnSameList)); + }));*/ + for (int i = 0; i < errList.size(); i++) { + errList.get(i).setOrderNum(i + 1); + } + ExcelUtil util = new ExcelUtil<>(CusDiscErrorVO.class); + String encodedFileName = URLEncoder.encode("FHB客户优惠问题" + DateUtils.getDate(), "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ".xlsx"); + util.exportExcel(response, errList, "FHB客户优惠问题"); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/FhbOtherBizAfterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/FhbOtherBizAfterController.java new file mode 100644 index 000000000..1037761b1 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/FhbOtherBizAfterController.java @@ -0,0 +1,73 @@ +package com.ruoyi.web.controller.xkt.migartion; + +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.es.EsClientWrapper; +import com.ruoyi.framework.notice.fs.FsNotice; +import com.ruoyi.web.controller.xkt.migartion.vo.gt.GtCateVO; +import com.ruoyi.web.controller.xkt.migartion.vo.gt.GtProdSkuVO; +import com.ruoyi.web.controller.xkt.migartion.vo.gtOnly.GtOnlyInitVO; +import com.ruoyi.xkt.domain.*; +import com.ruoyi.xkt.dto.es.ESProductDTO; +import com.ruoyi.xkt.dto.storeProdColorPrice.StoreProdMinPriceDTO; +import com.ruoyi.xkt.enums.EProductStatus; +import com.ruoyi.xkt.enums.ListingType; +import com.ruoyi.xkt.mapper.*; +import com.ruoyi.xkt.service.IPictureService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import static com.ruoyi.common.constant.Constants.WEIGHT_DEFAULT_ZERO; + +/** + * 只有GT处理 相关 + * + * @author ruoyi + */ +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/rest/v1/fhb-other-biz/after") +public class FhbOtherBizAfterController extends BaseController { + + final RedisCache redisCache; + final StoreProductColorMapper prodColorMapper; + final StoreProductColorSizeMapper prodColorSizeMapper; + final StoreProductMapper storeProdMapper; + final StoreProductStockMapper prodStockMapper; + final StoreColorMapper storeColorMapper; + final StoreMapper storeMapper; + final StoreProductServiceMapper prodSvcMapper; + final StoreProductCategoryAttributeMapper prodCateAttrMapper; + final SysProductCategoryMapper prodCateMapper; + final EsClientWrapper esClientWrapper; + final IPictureService pictureService; + final FsNotice fsNotice; + + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtAndTyBiz2Controller.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtAndTyBiz2Controller.java index 3da288490..5516b64bf 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtAndTyBiz2Controller.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtAndTyBiz2Controller.java @@ -16,10 +16,10 @@ import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.framework.es.EsClientWrapper; import com.ruoyi.framework.notice.fs.FsNotice; -import com.ruoyi.web.controller.xkt.migartion.vo.gtAndTy.GtAndTYCompareDownloadVO; -import com.ruoyi.web.controller.xkt.migartion.vo.gtAndTy.GtAndTYInitVO; import com.ruoyi.web.controller.xkt.migartion.vo.gt.GtCateVO; import com.ruoyi.web.controller.xkt.migartion.vo.gt.GtProdSkuVO; +import com.ruoyi.web.controller.xkt.migartion.vo.gtAndTy.GtAndTYCompareDownloadVO; +import com.ruoyi.web.controller.xkt.migartion.vo.gtAndTy.GtAndTYInitVO; import com.ruoyi.web.controller.xkt.migartion.vo.ty.TyCusDiscImportVO; import com.ruoyi.web.controller.xkt.migartion.vo.ty.TyCusImportVO; import com.ruoyi.web.controller.xkt.migartion.vo.ty.TyProdImportVO; @@ -82,8 +82,8 @@ public class GtAndTyBiz2Controller extends BaseController { * step1 */ @PreAuthorize("@ss.hasAnyRoles('admin,general_admin')") - @GetMapping("/compare/{userId}/{diffStr}") - public void compare(HttpServletResponse response, @PathVariable("userId") Integer userId, @PathVariable("diffStr") String diffStr) throws UnsupportedEncodingException { + @GetMapping("/compare/{userId}") + public void compare(HttpServletResponse response, @PathVariable("userId") Integer userId) throws UnsupportedEncodingException { // 处理的思路,以GT为主,根据GT的货号 去匹配TY的货号,有些档口写的比较规范,这种就比较好处理 List gtOnSaleList = ObjectUtils.defaultIfNull(redisCache .getCacheObject(CacheConstants.MIGRATION_GT_SALE_BASIC_KEY + userId), new ArrayList<>()); @@ -108,7 +108,8 @@ public class GtAndTyBiz2Controller extends BaseController { Map> gtMatchTyArtNoMap = new HashMap<>(); // 以GT为准在,找TY匹配的货号 gtArtNoList.forEach(gtOnSaleArtNo -> tyArtNoColorMap.forEach((tyArtNo, tyArtNoColorStr) -> { - if (Objects.equals(tyArtNo, gtOnSaleArtNo) || Objects.equals(tyArtNo, gtOnSaleArtNo + diffStr)) { + // 3种情况 1:1 货号 2:货号R 3:货号-R + if (Objects.equals(tyArtNo, gtOnSaleArtNo) || Objects.equals(tyArtNo, gtOnSaleArtNo + "R") || Objects.equals(tyArtNo, gtOnSaleArtNo + "-R")) { List existMatchArtNoList = gtMatchTyArtNoMap.getOrDefault(gtOnSaleArtNo, new ArrayList<>()); existMatchArtNoList.add(tyArtNo); gtMatchTyArtNoMap.put(gtOnSaleArtNo, existMatchArtNoList); @@ -142,7 +143,7 @@ public class GtAndTyBiz2Controller extends BaseController { gtMatchTyArtNoMap.forEach((gtArtNo, tyArtNoList) -> matchTyArtNoList.addAll(tyArtNoList)); // 已下架的GT货号,如果能在TY找到匹配的,也要剔除 gtOffSaleArtNoList.forEach(gtOffSaleArtNo -> tyArtNoColorMap.forEach((tyArtNo, colorNameStr) -> { - if (tyArtNo.contains(gtOffSaleArtNo)) { + if (Objects.equals(tyArtNo, gtOffSaleArtNo) || Objects.equals(tyArtNo, gtOffSaleArtNo + "R") || Objects.equals(tyArtNo, gtOffSaleArtNo + "-R")) { matchTyArtNoList.add(tyArtNo); } })); @@ -190,12 +191,12 @@ public class GtAndTyBiz2Controller extends BaseController { Map tyArtNoColorMap = tyProdList.stream().collect(Collectors.groupingBy(TyProdImportVO::getProdArtNum, Collectors.collectingAndThen(Collectors.mapping(TyProdImportVO::getColorName, Collectors.toList()), list -> "(" + list.stream().distinct().collect(Collectors.joining(",")) + ")"))); - // GT和TY匹配的货号map Map> gtMatchTyArtNoMap = new HashMap<>(); // 以GT为准在,找TY匹配的货号 gtArtNoList.forEach(gtOnSaleArtNo -> tyArtNoColorMap.forEach((tyArtNo, tyArtNoColorStr) -> { - if (Objects.equals(tyArtNo, gtOnSaleArtNo) || Objects.equals(tyArtNo, gtOnSaleArtNo + initVO.getDiffStr())) { + // 3种情况 1:1 货号 2:货号R 3:货号-R + if (Objects.equals(tyArtNo, gtOnSaleArtNo) || Objects.equals(tyArtNo, gtOnSaleArtNo + "R") || Objects.equals(tyArtNo, gtOnSaleArtNo + "-R")) { List existMatchArtNoList = gtMatchTyArtNoMap.getOrDefault(gtOnSaleArtNo, new ArrayList<>()); existMatchArtNoList.add(tyArtNo); gtMatchTyArtNoMap.put(gtOnSaleArtNo, existMatchArtNoList); @@ -289,12 +290,12 @@ public class GtAndTyBiz2Controller extends BaseController { Map tyArtNoColorMap = tyProdList.stream().collect(Collectors.groupingBy(TyProdImportVO::getProdArtNum, Collectors.collectingAndThen(Collectors.mapping(TyProdImportVO::getColorName, Collectors.toList()), list -> "(" + list.stream().distinct().collect(Collectors.joining(",")) + ")"))); - // GT和TY匹配的货号map Map> gtMatchTyArtNoMap = new HashMap<>(); // 以GT为准在,找TY匹配的货号 gtArtNoList.forEach(gtOnSaleArtNo -> tyArtNoColorMap.forEach((tyArtNo, tyArtNoColorStr) -> { - if (tyArtNo.contains(gtOnSaleArtNo)) { + // 3种情况 1:1 货号 2:货号R 3:货号-R + if (Objects.equals(tyArtNo, gtOnSaleArtNo) || Objects.equals(tyArtNo, gtOnSaleArtNo + "R") || Objects.equals(tyArtNo, gtOnSaleArtNo + "-R")) { List existMatchArtNoList = gtMatchTyArtNoMap.getOrDefault(gtOnSaleArtNo, new ArrayList<>()); existMatchArtNoList.add(tyArtNo); gtMatchTyArtNoMap.put(gtOnSaleArtNo, existMatchArtNoList); @@ -373,12 +374,12 @@ public class GtAndTyBiz2Controller extends BaseController { Map tyArtNoColorMap = tyProdList.stream().collect(Collectors.groupingBy(TyProdImportVO::getProdArtNum, Collectors.collectingAndThen(Collectors.mapping(TyProdImportVO::getColorName, Collectors.toList()), list -> "(" + list.stream().distinct().collect(Collectors.joining(",")) + ")"))); - // GT和TY匹配的货号map Map> gtMatchTyArtNoMap = new HashMap<>(); // 以GT为准在,找TY匹配的货号 gtArtNoList.forEach(gtOnSaleArtNo -> tyArtNoColorMap.forEach((tyArtNo, tyArtNoColorStr) -> { - if (tyArtNo.contains(gtOnSaleArtNo)) { + // 3种情况 1:1 货号 2:货号R 3:货号-R + if (Objects.equals(tyArtNo, gtOnSaleArtNo) || Objects.equals(tyArtNo, gtOnSaleArtNo + "R") || Objects.equals(tyArtNo, gtOnSaleArtNo + "-R")) { List existMatchArtNoList = gtMatchTyArtNoMap.getOrDefault(gtOnSaleArtNo, new ArrayList<>()); existMatchArtNoList.add(tyArtNo); gtMatchTyArtNoMap.put(gtOnSaleArtNo, existMatchArtNoList); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtOtherBizAfterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtOtherBizAfterController.java new file mode 100644 index 000000000..7bc61a31a --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/GtOtherBizAfterController.java @@ -0,0 +1,488 @@ +package com.ruoyi.web.controller.xkt.migartion; + +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.es.EsClientWrapper; +import com.ruoyi.framework.notice.fs.FsNotice; +import com.ruoyi.web.controller.xkt.migartion.vo.gt.GtCateVO; +import com.ruoyi.web.controller.xkt.migartion.vo.gt.GtProdSkuVO; +import com.ruoyi.web.controller.xkt.migartion.vo.gtBizAfter.GtBizAfterImportVO; +import com.ruoyi.xkt.domain.*; +import com.ruoyi.xkt.dto.es.ESProductDTO; +import com.ruoyi.xkt.dto.storeProdColorPrice.StoreProdMinPriceDTO; +import com.ruoyi.xkt.enums.EProductStatus; +import com.ruoyi.xkt.enums.ListingType; +import com.ruoyi.xkt.mapper.*; +import com.ruoyi.xkt.service.IPictureService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import static com.ruoyi.common.constant.Constants.WEIGHT_DEFAULT_ZERO; + +/** + * 只有GT处理 相关 + * + * @author ruoyi + */ +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/rest/v1/gt-other-biz/after") +public class GtOtherBizAfterController extends BaseController { + + final RedisCache redisCache; + final StoreProductColorMapper prodColorMapper; + final StoreProductColorSizeMapper prodColorSizeMapper; + final StoreProductMapper storeProdMapper; + final StoreProductStockMapper prodStockMapper; + final StoreColorMapper storeColorMapper; + final StoreMapper storeMapper; + final StoreProductServiceMapper prodSvcMapper; + final StoreProductCategoryAttributeMapper prodCateAttrMapper; + final SysProductCategoryMapper prodCateMapper; + final EsClientWrapper esClientWrapper; + final IPictureService pictureService; + final FsNotice fsNotice; + + + /** + * step1 + */ + // 新增颜色、商品基础数据 + @PreAuthorize("@ss.hasAnyRoles('admin,general_admin')") + @PostMapping("/init-prod") + @Transactional + public R initProd(@RequestParam(value = "storeId") Long storeId, @RequestParam(value = "userId") Integer userId, MultipartFile file) throws IOException { + ExcelUtil util = new ExcelUtil<>(GtBizAfterImportVO.class); + List gtAfterImportVOList = util.importExcel(file.getInputStream()); + // 待处理的GT独有的货号 + List gtAfterArtNumList = gtAfterImportVOList.stream().map(GtBizAfterImportVO::getGtAfterArtNum).map(String::trim) + .filter(StringUtils::isNotBlank).map(item -> item.contains("(") ? item.substring(0, item.indexOf("(")) : item) + .collect(Collectors.toList()); + Optional.ofNullable(this.storeMapper.selectOne(new LambdaQueryWrapper() + .eq(Store::getId, storeId).eq(Store::getDelFlag, Constants.UNDELETED))) + .orElseThrow(() -> new ServiceException("档口不存在!", HttpStatus.ERROR)); + // 获取GT所有的货品 + List gtOnSaleCacheList = ObjectUtils.defaultIfNull(redisCache + .getCacheObject(CacheConstants.MIGRATION_GT_SALE_BASIC_KEY + userId), new ArrayList<>()); + if (CollectionUtils.isEmpty(gtOnSaleCacheList)) { + throw new ServiceException("GT商品列表为空", HttpStatus.ERROR); + } + + // TODO 特殊处理,只保留GT单独处理的部分 + gtOnSaleCacheList = gtOnSaleCacheList.stream().filter(x -> gtAfterArtNumList.contains(x.getArticle_number())).collect(Collectors.toList()); + + // 步骤1: 新建颜色 + this.initStoreColorList(storeId, gtOnSaleCacheList); + + // GT分类 + List cacheList = ObjectUtils.defaultIfNull(redisCache + .getCacheObject(CacheConstants.MIGRATION_GT_SALE_CATE_KEY + userId), new ArrayList<>()); + List prodCateList = this.prodCateMapper.selectList(new LambdaQueryWrapper() + .eq(SysProductCategory::getDelFlag, Constants.UNDELETED)); + Map dbCateNameMap = prodCateList.stream().collect(Collectors.toMap(SysProductCategory::getName, SysProductCategory::getId)); + // GT商品分类和步橘分类映射 + Map cateRelationMap = new HashMap<>(); + cacheList.forEach(gtCate -> { + final Long cateId = Optional.ofNullable(dbCateNameMap.get(gtCate.getName())).orElseThrow(() -> new ServiceException("GT分类不存在!", HttpStatus.ERROR)); + cateRelationMap.put(gtCate.getId(), cateId); + }); + // 步骤2: 新增商品 + List storeProdList = new ArrayList<>(); + // 所有商品的类目属性map key gt的product_id value StoreProductCategoryAttribute + Map prodAttrMap = new HashMap<>(); + // 当天 + final Date voucherDate = java.sql.Date.valueOf(LocalDate.now()); + Map gtProdMap = gtOnSaleCacheList.stream().collect(Collectors.toMap(GtProdSkuVO::getArticle_number, x -> x, (s1, s2) -> s2)); + gtProdMap.forEach((artNum, gtProdSkuVO) -> { + // 初始化档口商品 + StoreProduct storeProd = new StoreProduct().setStoreId(storeId).setProdCateId(cateRelationMap.get(gtProdSkuVO.getCategory_nid())).setPrivateItem(0) + .setProdArtNum(gtProdSkuVO.getArticle_number()).setProdTitle(gtProdSkuVO.getCharacters()).setListingWay(ListingType.RIGHT_NOW.getValue()) + .setVoucherDate(voucherDate).setProdStatus(EProductStatus.ON_SALE.getValue()).setRecommendWeight(0L).setSaleWeight(0L).setPopularityWeight(0L); + // 提前设置档口商品的类目属性 + this.preMatchAttr(gtProdSkuVO.getProduct_id(), userId, prodAttrMap); + storeProdList.add(storeProd); + }); + this.storeProdMapper.insert(storeProdList); + + // 商品所有颜色 尺码 颜色库存初始化 + List prodSvcList = new ArrayList<>(); + List prodAttrList = new ArrayList<>(); + storeProdList.forEach(storeProd -> { + GtProdSkuVO gtProdSkuVO = gtProdMap.get(storeProd.getProdArtNum()); + // 初始化商品服务承诺 + prodSvcList.add(new StoreProductService().setStoreProdId(storeProd.getId()).setCustomRefund("0") + .setThirtyDayRefund("0").setOneBatchSale("1").setRefundWithinThreeDay("0")); + // 初始化商品的类目属性 + StoreProductCategoryAttribute cateAttr = Optional.ofNullable(prodAttrMap.get(gtProdSkuVO.getProduct_id())).orElse(new StoreProductCategoryAttribute()); + cateAttr.setStoreId(storeProd.getStoreId()).setStoreProdId(storeProd.getId()); + prodAttrList.add(cateAttr); + }); + // 插入档口服务承诺、商品基本属性 + this.prodSvcMapper.insert(prodSvcList); + this.prodCateAttrMapper.insert(prodAttrList); + return R.ok(); + } + + + /** + * step2 + * 商品颜色及商品颜色尺码 + */ + @PreAuthorize("@ss.hasAnyRoles('admin,general_admin')") + @PostMapping("/init-color") + @Transactional + public R initColor(@RequestParam(value = "storeId") Long storeId, @RequestParam(value = "userId") Integer userId, + @RequestParam(value = "addOverPrice") BigDecimal addOverPrice, MultipartFile file) throws IOException { + ExcelUtil util = new ExcelUtil<>(GtBizAfterImportVO.class); + List gtAfterImportVOList = util.importExcel(file.getInputStream()); + // 待处理的GT独有的货号 + List gtAfterArtNumList = gtAfterImportVOList.stream().map(GtBizAfterImportVO::getGtAfterArtNum).map(String::trim) + .filter(StringUtils::isNotBlank).map(item -> item.contains("(") ? item.substring(0, item.indexOf("(")) : item) + .collect(Collectors.toList()); + // 从数据库查询最新数据 + List storeProdList = this.storeProdMapper.selectList(new LambdaQueryWrapper() + .eq(StoreProduct::getStoreId, storeId).eq(StoreProduct::getDelFlag, Constants.UNDELETED)); + List storeColorList = this.storeColorMapper.selectList(new LambdaQueryWrapper() + .eq(StoreColor::getStoreId, storeId).eq(StoreColor::getDelFlag, Constants.UNDELETED)); + Map storeColorMap = storeColorList.stream().collect(Collectors.toMap(StoreColor::getColorName, x -> x, (v1, v2) -> v2)); + + // 获取GT所有的货品 + List gtOnSaleCacheList = ObjectUtils.defaultIfNull(redisCache + .getCacheObject(CacheConstants.MIGRATION_GT_SALE_BASIC_KEY + userId), new ArrayList<>()); + Map> gtProdSkuMap = gtOnSaleCacheList.stream().collect(Collectors.groupingBy(GtProdSkuVO::getArticle_number)); + // 商品所有颜色 尺码 颜色库存初始化 + List prodColorList = new ArrayList<>(); + List prodColorSizeList = new ArrayList<>(); + storeProdList.stream() + // TODO 特殊处理,只保留GT单独处理的部分 important important important + .filter(storeProd -> gtAfterArtNumList.contains(storeProd.getProdArtNum())) + .forEach(storeProd -> { + // 获取GT匹配的商品sku列表 + List gtMatchSkuList = gtProdSkuMap.get(storeProd.getProdArtNum()); + // 当前货号在GT的所有尺码,作为标准尺码 + List gtStandardSizeList = gtMatchSkuList.stream().map(sku -> (int) Math.floor(Double.parseDouble(sku.getSize()))).collect(Collectors.toList()); + Map prodColorMap = gtMatchSkuList.stream().collect(Collectors.toMap(GtProdSkuVO::getColor, GtProdSkuVO::getColor, (s1, s2) -> s2)); + // GT颜色下尺码价格map + Map> colorSizePriceMap = gtMatchSkuList.stream().collect(Collectors + .groupingBy(GtProdSkuVO::getColor, Collectors.toMap(x -> (int) Math.floor(Double.parseDouble(x.getSize())), GtProdSkuVO::getPrice, (v1, v2) -> v2))); + AtomicInteger orderNum = new AtomicInteger(); + prodColorMap.forEach((color, gtColor) -> { + StoreColor storeColor = Optional.ofNullable(storeColorMap.get(gtColor)) + .orElseThrow(() -> new ServiceException("没有GT商品颜色!" + storeProd.getProdArtNum(), HttpStatus.ERROR)); + // 该商品的颜色 + prodColorList.add(new StoreProductColor().setStoreId(storeProd.getStoreId()).setStoreProdId(storeProd.getId()).setOrderNum(orderNum.addAndGet(1)) + .setColorName(storeColor.getColorName()).setStoreColorId(storeColor.getId()).setProdStatus(EProductStatus.ON_SALE.getValue())); + Map sizePriceMap = Optional.ofNullable(colorSizePriceMap.get(gtColor)) + .orElseThrow(() -> new ServiceException("没有GT商品颜色尺码价格!" + storeProd.getProdArtNum(), HttpStatus.ERROR)); + // 该颜色最低价格 + BigDecimal minPrice = sizePriceMap.values().stream().min(BigDecimal::compareTo).orElse(BigDecimal.ZERO); + // 该颜色所有的尺码 + for (int j = 0; j < Constants.SIZE_LIST.size(); j++) { + final boolean isStandard = gtStandardSizeList.contains(Constants.SIZE_LIST.get(j)); + prodColorSizeList.add(new StoreProductColorSize().setSize(Constants.SIZE_LIST.get(j)).setStoreColorId(storeColor.getId()) + .setStoreProdId(storeProd.getId()).setStandard(isStandard ? 1 : 0).setNextSn(0) + // 销售价格以FHB价格为准 + .setPrice(sizePriceMap.getOrDefault(Constants.SIZE_LIST.get(j), minPrice) + .add(ObjectUtils.defaultIfNull(addOverPrice, BigDecimal.ZERO)))); + } + }); + }); + // 插入商品颜色及颜色对应的尺码,档口服务承诺 + this.prodColorMapper.insert(prodColorList); + prodColorSizeList.sort(Comparator.comparing(StoreProductColorSize::getStoreProdId).thenComparing(StoreProductColorSize::getSize)); + this.prodColorSizeMapper.insert(prodColorSizeList); + // 还要更新步橘系统的条码前缀 + prodColorSizeList.forEach(x -> x.setSnPrefix(storeId + String.format("%08d", x.getId()))); + this.prodColorSizeMapper.updateById(prodColorSizeList); + return R.ok(); + } + + /** + * step3 + */ + @PreAuthorize("@ss.hasAnyRoles('admin,general_admin')") + @PostMapping("/init-stock") + @Transactional + public R initStock(@RequestParam(value = "storeId") Long storeId) { + List storeProdList = this.storeProdMapper.selectList(new LambdaQueryWrapper() + .eq(StoreProduct::getStoreId, storeId).eq(StoreProduct::getDelFlag, Constants.UNDELETED)); + List prodColorList = this.prodColorMapper.selectList(new LambdaQueryWrapper() + .eq(StoreProductColor::getStoreId, storeId).eq(StoreProductColor::getDelFlag, Constants.UNDELETED)); + List prodStockList = this.prodStockMapper.selectList(new LambdaQueryWrapper() + .eq(StoreProductStock::getStoreId, storeId).eq(StoreProductStock::getDelFlag, Constants.UNDELETED)); + + Map storeProdMap = storeProdList.stream().collect(Collectors.toMap(StoreProduct::getId, x -> x)); + List prodColorIdList = prodStockList.stream().map(StoreProductStock::getStoreProdColorId).collect(Collectors.toList()); + // 筛选那些货品是未设置库存的 + List newProdStockList = prodColorList.stream().filter(x -> !prodColorIdList.contains(x.getId())).map(x -> { + StoreProduct storeProd = Optional.ofNullable(storeProdMap.get(x.getStoreProdId())) + .orElseThrow(() -> new ServiceException("没有GT商品!" + x.getStoreProdId(), HttpStatus.ERROR)); + return new StoreProductStock().setStoreId(x.getStoreId()).setStoreProdId(x.getStoreProdId()).setProdArtNum(storeProd.getProdArtNum()) + .setStoreProdColorId(x.getId()).setStoreColorId(x.getStoreColorId()).setColorName(x.getColorName()); + }).collect(Collectors.toList()); + this.prodStockMapper.insert(newProdStockList); + return R.ok(); + } + + + /** + * step4 + */ + @PreAuthorize("@ss.hasAnyRoles('admin,general_admin')") + @PostMapping("/sync-es") + public R syncToEs(@RequestParam(value = "storeId") Long storeId, MultipartFile file) throws IOException { + ExcelUtil util = new ExcelUtil<>(GtBizAfterImportVO.class); + List gtAfterImportVOList = util.importExcel(file.getInputStream()); + // 待处理的GT独有的货号 + List gtAfterArtNumList = gtAfterImportVOList.stream().map(GtBizAfterImportVO::getGtAfterArtNum).map(String::trim) + .filter(StringUtils::isNotBlank).map(item -> item.contains("(") ? item.substring(0, item.indexOf("(")) : item) + .collect(Collectors.toList()); + // 将公共的商品同步到ES + List storeProdList = this.storeProdMapper.selectList(new LambdaQueryWrapper() + .eq(StoreProduct::getDelFlag, Constants.UNDELETED).eq(StoreProduct::getStoreId, storeId) + // TODO 只处理GT独有的存货 important important important important + .in(StoreProduct::getProdArtNum, gtAfterArtNumList)); + if (CollectionUtils.isEmpty(storeProdList)) { + return R.fail(); + } + final List storeProdIdList = storeProdList.stream().map(StoreProduct::getId).map(String::valueOf).collect(Collectors.toList()); + // 所有的分类 + List prodCateList = this.prodCateMapper.selectList(new LambdaQueryWrapper() + .eq(SysProductCategory::getDelFlag, Constants.UNDELETED)); + Map prodCateMap = prodCateList.stream().collect(Collectors.toMap(SysProductCategory::getId, x -> x)); + // 获取当前商品最低价格 + Map prodMinPriceMap = this.prodColorSizeMapper.selectStoreProdMinPriceList(storeProdIdList).stream().collect(Collectors + .toMap(StoreProdMinPriceDTO::getStoreProdId, StoreProdMinPriceDTO::getPrice)); + // 档口商品的属性map + Map cateAttrMap = this.prodCateAttrMapper.selectList(new LambdaQueryWrapper() + .eq(StoreProductCategoryAttribute::getDelFlag, Constants.UNDELETED).in(StoreProductCategoryAttribute::getStoreProdId, storeProdIdList)) + .stream().collect(Collectors.toMap(StoreProductCategoryAttribute::getStoreProdId, x -> x)); + // 档口商品对应的档口 + Map storeMap = this.storeMapper.selectList(new LambdaQueryWrapper().eq(Store::getDelFlag, Constants.UNDELETED) + .in(Store::getId, storeProdList.stream().map(StoreProduct::getStoreId).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(Store::getId, x -> x)); + List esProductDTOList = new ArrayList<>(); + for (StoreProduct product : storeProdList) { + final SysProductCategory cate = prodCateMap.get(product.getProdCateId()); + final SysProductCategory parCate = ObjectUtils.isEmpty(cate) ? null : prodCateMap.get(cate.getParentId()); + final Store store = storeMap.get(product.getStoreId()); + final BigDecimal prodMinPrice = prodMinPriceMap.get(product.getId()); + final StoreProductCategoryAttribute cateAttr = cateAttrMap.get(product.getId()); + ESProductDTO esProductDTO = new ESProductDTO().setStoreProdId(product.getId().toString()).setProdArtNum(product.getProdArtNum()) + .setHasVideo(Boolean.FALSE).setProdCateId(product.getProdCateId().toString()).setCreateTime(DateUtils.getTime()) + .setProdCateName(ObjectUtils.isNotEmpty(cate) ? cate.getName() : "") + .setSaleWeight(WEIGHT_DEFAULT_ZERO.toString()).setRecommendWeight(WEIGHT_DEFAULT_ZERO.toString()) + .setPopularityWeight(WEIGHT_DEFAULT_ZERO.toString()) + .setMainPicUrl("").setMainPicName("").setMainPicSize(BigDecimal.ZERO) + .setParCateId(ObjectUtils.isNotEmpty(parCate) ? parCate.getId().toString() : "") + .setParCateName(ObjectUtils.isNotEmpty(parCate) ? parCate.getName() : "") + .setProdPrice(ObjectUtils.isNotEmpty(prodMinPrice) ? prodMinPrice.toString() : "") + .setSeason(ObjectUtils.isNotEmpty(cateAttr) ? cateAttr.getSuitableSeason() : "") + .setProdStatus(product.getProdStatus().toString()) + .setStoreId(product.getStoreId().toString()) + .setStoreName(ObjectUtils.isNotEmpty(store) ? store.getStoreName() : "") + .setStyle(ObjectUtils.isNotEmpty(cateAttr) ? cateAttr.getStyle() : "") + .setProdTitle(product.getProdTitle()); + if (ObjectUtils.isNotEmpty(cateAttr) && StringUtils.isNotBlank(cateAttr.getStyle())) { + esProductDTO.setTags(Collections.singletonList(cateAttr.getStyle())); + } + esProductDTOList.add(esProductDTO); + } + // 构建批量操作请求 + List bulkOperations = new ArrayList<>(); + for (ESProductDTO esProductDTO : esProductDTOList) { + BulkOperation bulkOperation = new BulkOperation.Builder() + .index(i -> i.id(esProductDTO.getStoreProdId()).index(Constants.ES_IDX_PRODUCT_INFO).document(esProductDTO)) + .build(); + bulkOperations.add(bulkOperation); + } + // 执行批量插入 + try { + BulkResponse response = esClientWrapper.getEsClient().bulk(b -> b.index(Constants.ES_IDX_PRODUCT_INFO).operations(bulkOperations)); + log.info("单独处理GT货号到 ES 成功的 id列表: {}", response.items().stream().map(BulkResponseItem::id).collect(Collectors.toList())); + // 有哪些没执行成功的,需要发飞书通知 + List successIdList = response.items().stream().map(BulkResponseItem::id).collect(Collectors.toList()); + List unExeIdList = storeProdIdList.stream().map(String::valueOf).filter(x -> !successIdList.contains(x)).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(unExeIdList)) { + fsNotice.sendMsg2DefaultChat(storeId + ",单独处理GT货号到 ES 失败", "以下storeProdId未执行成功: " + unExeIdList); + } else { + fsNotice.sendMsg2DefaultChat(storeId + ",单独处理GT货号到 ES 成功", "共处理 " + response.items().size() + " 条记录"); + } + } catch (Exception e) { + log.error("单独处理GT货号到 ES 失败", e); + fsNotice.sendMsg2DefaultChat(storeId + ",单独处理GT货号到 ES 失败", e.getMessage()); + } + return R.ok(); + } + + + /** + * 初始化档口颜色 + * + * @param gtOnSaleCacheList GT所有商品列表 + */ + private void initStoreColorList(Long storeId, List gtOnSaleCacheList) { + // 先查询当前档口所有的颜色,如果没有剩余的颜色,则新增导入 + List existColorList = this.storeColorMapper.selectList(new LambdaQueryWrapper() + .eq(StoreColor::getDelFlag, Constants.UNDELETED).eq(StoreColor::getStoreId, storeId)); + List existColorNameList = existColorList.stream().map(StoreColor::getColorName).collect(Collectors.toList()); + // 当前最大的排序 + int maxOrderNum = existColorList.stream().mapToInt(StoreColor::getOrderNum).max().orElse(0) + 1; + // GT单独处理的货品颜色 + List gtAfterColorList = gtOnSaleCacheList.stream().map(GtProdSkuVO::getColor).filter(color -> !existColorNameList.contains(color)).distinct().collect(Collectors.toList()); + if (CollectionUtils.isEmpty(gtAfterColorList)) { + return; + } + List storeColorList = new ArrayList<>(); + for (int i = 0; i < gtAfterColorList.size(); i++) { + storeColorList.add(new StoreColor().setStoreId(storeId).setColorName(gtAfterColorList.get(i)).setOrderNum(maxOrderNum + i + 1)); + } + this.storeColorMapper.insert(storeColorList); + } + + /** + * 提前匹配类目属性 + * + * @param product_id GT商品ID + * @param userId GT用户ID + * @param prodAttrMap 类目属性 + */ + private void preMatchAttr(Integer product_id, Integer userId, Map prodAttrMap) { + // 类目属性 + Map attrMap = redisCache.getCacheMap(CacheConstants.MIGRATION_GT_SALE_ATTR_KEY + userId + "_" + product_id); + if (MapUtils.isEmpty(attrMap)) { + return; + } + // 将attrMap 的 key 映射到系统中 + StoreProductCategoryAttribute prodAttr = new StoreProductCategoryAttribute(); + // 1. 帮面材质 + if (attrMap.containsKey(Constants.UPPER_MATERIAL_NAME)) { + prodAttr.setUpperMaterial(attrMap.get(Constants.UPPER_MATERIAL_NAME)); + } + // 2. 靴筒内里材质 + if (attrMap.containsKey(Constants.SHAFT_LINING_MATERIAL_NAME)) { + prodAttr.setShaftLiningMaterial(attrMap.get(Constants.SHAFT_LINING_MATERIAL_NAME)); + } + // 3. 靴筒面材质 + if (attrMap.containsKey(Constants.SHAFT_MATERIAL_NAME)) { + prodAttr.setShaftMaterial(attrMap.get(Constants.SHAFT_MATERIAL_NAME)); + } + // 4. 鞋面内里材质 + if (attrMap.containsKey(Constants.SHOE_UPPER_LINING_MATERIAL_NAME)) { + prodAttr.setShoeUpperLiningMaterial(attrMap.get(Constants.SHOE_UPPER_LINING_MATERIAL_NAME)); + } + // 5. 靴款品名 + if (attrMap.containsKey(Constants.SHOE_STYLE_NAME_NAME)) { + prodAttr.setShoeStyleName(attrMap.get(Constants.SHOE_STYLE_NAME_NAME)); + } + // 6. 筒高 + if (attrMap.containsKey(Constants.SHAFT_HEIGHT_NAME)) { + prodAttr.setShaftHeight(attrMap.get(Constants.SHAFT_HEIGHT_NAME)); + } + // 7. 鞋垫材质 + if (attrMap.containsKey(Constants.INSOLE_MATERIAL_NAME)) { + prodAttr.setInsoleMaterial(attrMap.get(Constants.INSOLE_MATERIAL_NAME)); + } + // 8. 上市年份季节 + if (attrMap.containsKey(Constants.RELEASE_YEAR_SEASON_NAME)) { + prodAttr.setReleaseYearSeason(attrMap.get(Constants.RELEASE_YEAR_SEASON_NAME)); + } + // 9. 后跟高 + if (attrMap.containsKey(Constants.HEEL_HEIGHT_NAME)) { + prodAttr.setHeelHeight(attrMap.get(Constants.HEEL_HEIGHT_NAME)); + } + // 10. 跟底款式 + if (attrMap.containsKey(Constants.HEEL_TYPE_NAME)) { + prodAttr.setHeelType(attrMap.get(Constants.HEEL_TYPE_NAME)); + } + // 11. 鞋头款式 + if (attrMap.containsKey(Constants.TOE_STYLE_NAME)) { + prodAttr.setToeStyle(attrMap.get(Constants.TOE_STYLE_NAME)); + } + // 12. 适合季节 + if (attrMap.containsKey(Constants.SUITABLE_SEASON_NAME)) { + prodAttr.setSuitableSeason(attrMap.get(Constants.SUITABLE_SEASON_NAME)); + } + // 13. 开口深度 + if (attrMap.containsKey(Constants.COLLAR_DEPTH_NAME)) { + prodAttr.setCollarDepth(attrMap.get(Constants.COLLAR_DEPTH_NAME)); + } + // 14. 鞋底材质 + if (attrMap.containsKey(Constants.OUTSOLE_MATERIAL_NAME)) { + prodAttr.setOutsoleMaterial(attrMap.get(Constants.OUTSOLE_MATERIAL_NAME)); + } + // 15. 风格 + if (attrMap.containsKey(Constants.STYLE_NAME)) { + prodAttr.setStyle(attrMap.get(Constants.STYLE_NAME)); + } + // 16. 款式 + if (attrMap.containsKey(Constants.DESIGN_NAME)) { + prodAttr.setDesign(attrMap.get(Constants.DESIGN_NAME)); + } + // 17. 皮质特征 + if (attrMap.containsKey(Constants.LEATHER_FEATURES_NAME)) { + prodAttr.setLeatherFeatures(attrMap.get(Constants.LEATHER_FEATURES_NAME)); + } + // 18. 制作工艺 + if (attrMap.containsKey(Constants.MANUFACTURING_PROCESS_NAME)) { + prodAttr.setManufacturingProcess(attrMap.get(Constants.MANUFACTURING_PROCESS_NAME)); + } + // 19. 图案 + if (attrMap.containsKey(Constants.PATTERN_NAME)) { + prodAttr.setPattern(attrMap.get(Constants.PATTERN_NAME)); + } + // 20. 闭合方式 + if (attrMap.containsKey(Constants.CLOSURE_TYPE_NAME)) { + prodAttr.setClosureType(attrMap.get(Constants.CLOSURE_TYPE_NAME)); + } + // 21. 适用场景 + if (attrMap.containsKey(Constants.OCCASION_NAME)) { + prodAttr.setOccasion(attrMap.get(Constants.OCCASION_NAME)); + } + // 22. 厚薄 + if (attrMap.containsKey(Constants.THICKNESS_NAME)) { + prodAttr.setThickness(attrMap.get(Constants.THICKNESS_NAME)); + } + // 23. 流行元素 + if (attrMap.containsKey(Constants.FASHION_ELEMENTS_NAME)) { + prodAttr.setFashionElements(attrMap.get(Constants.FASHION_ELEMENTS_NAME)); + } + // 24. 适用对象 + if (attrMap.containsKey(Constants.SUITABLE_PERSON_NAME)) { + prodAttr.setSuitablePerson(attrMap.get(Constants.SUITABLE_PERSON_NAME)); + } + prodAttrMap.put(product_id, prodAttr); + } + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/TYOtherBizAfterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/TYOtherBizAfterController.java new file mode 100644 index 000000000..148bf34ff --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/TYOtherBizAfterController.java @@ -0,0 +1,74 @@ +package com.ruoyi.web.controller.xkt.migartion; + +import co.elastic.clients.elasticsearch.core.BulkResponse; +import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; +import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.es.EsClientWrapper; +import com.ruoyi.framework.notice.fs.FsNotice; +import com.ruoyi.web.controller.xkt.migartion.vo.gt.GtCateVO; +import com.ruoyi.web.controller.xkt.migartion.vo.gt.GtProdSkuVO; +import com.ruoyi.web.controller.xkt.migartion.vo.gtOnly.GtOnlyInitVO; +import com.ruoyi.xkt.domain.*; +import com.ruoyi.xkt.dto.es.ESProductDTO; +import com.ruoyi.xkt.dto.storeProdColorPrice.StoreProdMinPriceDTO; +import com.ruoyi.xkt.enums.EProductStatus; +import com.ruoyi.xkt.enums.ListingType; +import com.ruoyi.xkt.mapper.*; +import com.ruoyi.xkt.service.IPictureService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +import static com.ruoyi.common.constant.Constants.WEIGHT_DEFAULT_ZERO; + +/** + * 只有GT处理 相关 + * + * @author ruoyi + */ +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/rest/v1/ty-other-biz/after") +public class TYOtherBizAfterController extends BaseController { + + final RedisCache redisCache; + final StoreProductColorMapper prodColorMapper; + final StoreProductColorSizeMapper prodColorSizeMapper; + final StoreProductMapper storeProdMapper; + final StoreProductStockMapper prodStockMapper; + final StoreColorMapper storeColorMapper; + final StoreMapper storeMapper; + final StoreProductServiceMapper prodSvcMapper; + final StoreProductCategoryAttributeMapper prodCateAttrMapper; + final SysProductCategoryMapper prodCateMapper; + final EsClientWrapper esClientWrapper; + final IPictureService pictureService; + final FsNotice fsNotice; + + + + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/TyController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/TyController.java index b8e5b80f5..8de15e66e 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/TyController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/TyController.java @@ -24,10 +24,12 @@ import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * TY 相关 @@ -45,9 +47,8 @@ public class TyController extends BaseController { * step0 */ @PreAuthorize("@ss.hasAnyRoles('admin,general_admin')") - @PostMapping("/filter/{userId}/{compareStr}") - public void filterUnValidProd(HttpServletResponse response, @PathVariable("userId") Integer userId, - @PathVariable("compareStr") String compareStr, MultipartFile file) throws IOException { + @PostMapping("/filter/{userId}") + public void filterUnValidProd(HttpServletResponse response, @PathVariable("userId") Integer userId, MultipartFile file) throws IOException { ExcelUtil util = new ExcelUtil<>(TyProdImportVO.class); List tyProdVOList = util.importExcel(file.getInputStream()); // 获取GT无效的存货并过滤 @@ -61,7 +62,7 @@ public class TyController extends BaseController { List allMatchArtNumList = new ArrayList<>(commonArtNumList); tyProdArtNumList.stream().filter(x -> x.contains("R")).forEach(x -> { for (String comArtNum : commonArtNumList) { - if ( Objects.equals(x, comArtNum + compareStr)) { + if (Objects.equals(x, comArtNum + "R") || Objects.equals(x, comArtNum + "-R")) { System.err.println(x + " : " + comArtNum); allMatchArtNumList.add(x); break; @@ -135,8 +136,9 @@ public class TyController extends BaseController { */ @PreAuthorize("@ss.hasAnyRoles('admin,general_admin')") @PostMapping("/cus/disc/cache") - public R createCusDiscCache(@RequestParam(value = "userId") Long userId, - @RequestParam(value = "cusName") String cusName, MultipartFile file) throws IOException { + public R createCusDiscCache(@RequestParam(value = "userId") Long userId, @RequestParam("compareStr") String compareStr, + MultipartFile file) throws IOException { + final String cusName = file.getOriginalFilename().replaceAll("\\..*$", "").replaceAll("[^\\u4e00-\\u9fa50-9]", "").trim(); ExcelUtil util = new ExcelUtil<>(TyCusDiscImportVO.class); List tyProdVOList = util.importExcel(file.getInputStream()); // 从redis中获取已存在的客户优惠数据 @@ -144,12 +146,25 @@ public class TyController extends BaseController { cacheList = Optional.ofNullable(cacheList).orElse(new ArrayList<>()); // 前置校验 this.cusDiscPrefixFilter(userId, cusName, cacheList); + + // 获取GT所有下架的存货,将该部分存货排除 + // 先从redis中获取列表数据 + List gtOffSaleList = ObjectUtils.defaultIfNull(redisCache + .getCacheObject(CacheConstants.MIGRATION_GT_OFF_SALE_BASIC_KEY + userId), new ArrayList<>()); + // 同时添加 单里 和 绒里 过滤 + List gtOffSaleArtNumList = gtOffSaleList.stream() + .map(x -> x.getArticle_number().trim()) + .flatMap(articleNumber -> Stream.of(articleNumber, articleNumber + compareStr)) + .collect(Collectors.toList()); + // 因为是采用的截图转excel方式,所以每个张图会冗余部分数据长度,导入是需要判断是否已存在 Map importCusDiscMap = new HashMap<>(); List importList = new ArrayList<>(); tyProdVOList.stream() // 只设置有优惠的存货及颜色 - .filter(x -> ObjectUtils.isNotEmpty(x.getBasicPrice()) && ObjectUtils.isNotEmpty(x.getCustomerPrice())) + .filter(x -> StringUtils.isNotBlank(x.getProdArtNum()) && ObjectUtils.isNotEmpty(x.getBasicPrice()) && ObjectUtils.isNotEmpty(x.getCustomerPrice())) + // 排除掉GT已下架部分的存货 + .filter(x -> !gtOffSaleArtNumList.contains(x.getProdArtNum())) .forEach(x -> { if (importCusDiscMap.containsKey(x.getProdArtNum() + ":" + x.getColorName())) { System.err.println(x.getProdArtNum() + ":" + x.getColorName()); @@ -183,22 +198,6 @@ public class TyController extends BaseController { public R createTyProdStockCache(@PathVariable Integer userId, MultipartFile file) throws IOException { ExcelUtil util = new ExcelUtil<>(TyProdStockVO.class); List tyStockList = util.importExcel(file.getInputStream()); - - /*// 判断货号 + 颜色是否存在,“图识”可能不准 - List tyProdVOList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + userId); - // key prod+colorName - Map tyProdColorMap = tyProdVOList.stream().collect(Collectors.toMap(x -> x.getProdArtNum() + ":" + x.getColorName(), x -> x)); - // 错误的货号和颜色,“图识”不准的部分 - List errorList = new ArrayList<>(); - tyStockList.forEach(x -> { - if (!tyProdColorMap.containsKey(x.getProdArtNum() + ":" + x.getColorName())) { - errorList.add(x.getProdArtNum() + ":" + x.getColorName() + ":货号 + 颜色不存在"); - } - }); - if (CollectionUtils.isNotEmpty(errorList)) { - throw new ServiceException(errorList.toString(), HttpStatus.ERROR); - }*/ - // 因为是采用的截图转excel方式,所以每个张图会冗余部分数据长度,导入是需要判断是否已存在 Map importStockMap = new ConcurrentHashMap<>(); List cacheList = new ArrayList<>(); @@ -224,34 +223,43 @@ public class TyController extends BaseController { * step5 */ @PreAuthorize("@ss.hasAnyRoles('admin,general_admin')") - @GetMapping("/error/cus/disc/{userId}") - public R getErrorCusDisc(@PathVariable Integer userId) { + @GetMapping("/error/cus/price/{userId}") + public void getErrorCusDisc(HttpServletResponse response, @PathVariable Integer userId) throws UnsupportedEncodingException { List cacheList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_CUS_DISCOUNT_KEY + userId); - List errDiscList = new ArrayList<>(); + List errList = new ArrayList<>(); // 1. 有哪些是优惠价大于销售价的 cacheList.forEach(record -> { final Integer basicPrice = ObjectUtils.defaultIfNull(record.getBasicPrice(), 0); final Integer customerPrice = ObjectUtils.defaultIfNull(record.getCustomerPrice(), 0); - if (basicPrice - customerPrice <= 0) { - errDiscList.add(record.getProdArtNum() + ":" + record.getCusName() + ":" + record.getColorName() + ",优惠价大于等于原售价"); + if (basicPrice - customerPrice < 0) { + errList.add(new CusDiscErrorVO().setCusName(record.getCusName()).setProdArtNum(record.getProdArtNum()) + .setColorName(record.getColorName()).setErrMsg("优惠价大于原售价").setDetail("销售价:" + basicPrice + " 优惠价:" + customerPrice)); } }); - // 2. 有哪些优惠是同一货号不同颜色优惠金额不一致 - List errCusDiscUnSameList = new ArrayList<>(); + /*// 2. 有哪些优惠是同一货号不同颜色优惠金额不一致 Map>> artNoCusDiscMap = cacheList.stream().collect(Collectors .groupingBy(TyCusDiscImportVO::getProdArtNum, Collectors.groupingBy(TyCusDiscImportVO::getCusName))); // 货号下客户优惠的map artNoCusDiscMap.forEach((artNo, cusDiscMap) -> cusDiscMap.forEach((cusName, cusDiscList) -> { // 不同颜色优惠的map Map colorDiscMap = cusDiscList.stream().collect(Collectors - .toMap(TyCusDiscImportVO::getColorName, x -> ObjectUtils.defaultIfNull(x.getDiscount(), 0))); + .toMap(TyCusDiscImportVO::getColorName, x -> ObjectUtils.defaultIfNull(x.getDiscount(), 0), (v1, v2) -> v2)); // 判断所有颜色的优惠金额是否一致 Set discValueSet = new HashSet<>(colorDiscMap.values()); if (discValueSet.size() > 1) { - errCusDiscUnSameList.add(artNo + ":" + cusName + ":" + colorDiscMap.keySet() + ",优惠金额不一致"); + StringBuilder errSB = new StringBuilder(); + colorDiscMap.forEach((colorName, discount) -> errSB.append(colorName).append(":").append(discount).append(";")); + errList.add(new CusDiscErrorVO().setCusName(cusName).setProdArtNum(artNo).setColorName(colorDiscMap.keySet().toString()) + .setDetail(errSB.toString()).setErrMsg("客户优惠金额不一致")); } - })); - return R.ok(new CusDiscErrorVO().setErrCusDiscUnSameList(errCusDiscUnSameList).setErrDiscList(errDiscList)); + }));*/ + for (int i = 0; i < errList.size(); i++) { + errList.get(i).setOrderNum(i + 1); + } + ExcelUtil util = new ExcelUtil<>(CusDiscErrorVO.class); + String encodedFileName = URLEncoder.encode("TY客户优惠问题" + DateUtils.getDate(), "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ".xlsx"); + util.exportExcel(response, errList, "TY客户优惠问题"); } @@ -270,20 +278,6 @@ public class TyController extends BaseController { if (cusDiscMap.containsKey(cusName)) { throw new ServiceException(cusName + " : 客户已导入过优惠数据", HttpStatus.ERROR); } - // 判断货号 + 颜色是否存在,“图识”可能不准 - List tyProdVOList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + userId); - // key prod+colorName - Map tyProdColorMap = tyProdVOList.stream().collect(Collectors.toMap(x -> x.getProdArtNum() + ":" + x.getColorName(), x -> x)); - // 错误的货号和颜色,“图识”不准的部分 - List errorList = new ArrayList<>(); - cacheList.forEach(x -> { - if (!tyProdColorMap.containsKey(x.getProdArtNum() + ":" + x.getColorName())) { - errorList.add(cusName + ":" + x.getProdArtNum() + ":" + x.getColorName() + ":货号 + 颜色不存在"); - } - }); - if (CollectionUtils.isNotEmpty(errorList)) { - throw new ServiceException(errorList.toString(), HttpStatus.ERROR); - } } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/CusDiscErrorVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/CusDiscErrorVO.java index d2f1370f0..f0bd5892d 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/CusDiscErrorVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/CusDiscErrorVO.java @@ -1,10 +1,9 @@ package com.ruoyi.web.controller.xkt.migartion.vo; +import com.ruoyi.common.annotation.Excel; import lombok.Data; import lombok.experimental.Accessors; -import java.util.List; - /** * @author liangyq * @date 2025-05-11 23:46 @@ -13,9 +12,17 @@ import java.util.List; @Accessors(chain = true) public class CusDiscErrorVO { - // 客户优惠金额小于0 - private List errDiscList; - // 客户在同一货品,不同颜色优惠金额不一致 - private List errCusDiscUnSameList; + @Excel(name = "序号") + private int orderNum; + @Excel(name = "客户名称") + private String cusName; + @Excel(name = "货号") + private String prodArtNum; + @Excel(name = "颜色名称") + private String colorName; + @Excel(name = "错误信息") + private String errMsg; + @Excel(name = "错误详情") + private String detail; } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/gtAndTy/GtAndTYInitVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/gtAndTy/GtAndTYInitVO.java index e03886146..35a60cd93 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/gtAndTy/GtAndTYInitVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/gtAndTy/GtAndTYInitVO.java @@ -20,8 +20,6 @@ public class GtAndTYInitVO { private Integer userId; private Long storeId; - @NotBlank(message = "diffStr不能为空") - private String diffStr; // 大小码加价金额 0 or other private BigDecimal addOverPrice; // GT 和 TY 能匹配但因 两边颜色冲突,需要手动处理的货号 diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/gtBizAfter/GtBizAfterImportVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/gtBizAfter/GtBizAfterImportVO.java new file mode 100644 index 000000000..ee5fb47c3 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/gtBizAfter/GtBizAfterImportVO.java @@ -0,0 +1,23 @@ +package com.ruoyi.web.controller.xkt.migartion.vo.gtBizAfter; + +import com.ruoyi.common.annotation.Excel; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel +@Data +@Accessors(chain = true) +public class GtBizAfterImportVO { + + @Excel(name = "货号对比结果") + private String gtAfterArtNum; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/ty/TyProdImportVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/ty/TyProdImportVO.java index 39853d30b..fa56e0f23 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/ty/TyProdImportVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/migartion/vo/ty/TyProdImportVO.java @@ -25,6 +25,10 @@ public class TyProdImportVO { private BigDecimal price; @Excel(name = "HPBM") private String hpbm; + @Excel(name = "ML") + private String shaftMaterial; + @Excel(name = "ll") + private String shoeUpperLiningMaterial; @Excel(name = "SN") private String sn;