master:系统调优;

pull/1121/head
liujiang 2025-10-16 15:49:24 +08:00
parent c684529d91
commit 802927498b
6 changed files with 894 additions and 77 deletions

View File

@ -6,6 +6,7 @@ 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.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;
import com.ruoyi.web.controller.xkt.migartion.vo.fhb.FhbProdStockVO;
@ -93,20 +94,12 @@ public class FhbController extends BaseController {
if (ObjectUtils.isEmpty(cusDiscountVO.getData()) || ObjectUtils.isEmpty(cusDiscountVO.getData().getRecords())) {
return R.ok();
}
// 错误的折扣列表
List<String> errorCusDiscList = new ArrayList<>();
// 设置优惠价格
cusDiscountVO.getData().getRecords().forEach(record -> {
final Integer supplyPrice = ObjectUtils.defaultIfNull(record.getSupplyPrice(), 0);
final Integer customerPrice = ObjectUtils.defaultIfNull(record.getCustomerPrice(), 0);
if (supplyPrice - customerPrice < 0) {
errorCusDiscList.add(record.getArtNo() + ":" + record.getCustomerName() + ":" + record.getColor());
}
record.setDiscount(supplyPrice - customerPrice);
});
if (CollectionUtils.isNotEmpty(errorCusDiscList)) {
throw new ServiceException("供应商商品价格有误!" + errorCusDiscList, HttpStatus.ERROR);
}
// 先从redis中获取列表数据
List<FhbCusDiscountVO.SMCDRecordVO> cacheList = ObjectUtils.defaultIfNull(redisCache
.getCacheObject(CacheConstants.MIGRATION_SUPPLIER_CUS_DISCOUNT_KEY + supplierId), new ArrayList<>());
@ -135,6 +128,44 @@ public class FhbController extends BaseController {
return R.ok();
}
/**
* step5
* @return
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@GetMapping("/error/cus/disc/{supplierId}")
public R<CusDiscErrorVO> getErrorCusDisc(@PathVariable Integer supplierId){
// 先从redis中获取列表数据
List<FhbCusDiscountVO.SMCDRecordVO> cacheList = ObjectUtils.defaultIfNull(redisCache
.getCacheObject(CacheConstants.MIGRATION_SUPPLIER_CUS_DISCOUNT_KEY + supplierId), new ArrayList<>());
if (CollectionUtils.isEmpty(cacheList)) {
return R.ok();
}
List<String> errDiscList = 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() + ",优惠价大于原售价");
}
});
// 2. 有哪些优惠是同一货号不同颜色优惠金额不一致
List<String> errCusDiscUnSameList = new ArrayList<>();
Map<String, Map<String, List<FhbCusDiscountVO.SMCDRecordVO>>> artNoCusDiscMap = cacheList.stream().collect(Collectors
.groupingBy(FhbCusDiscountVO.SMCDRecordVO::getArtNo, Collectors.groupingBy(FhbCusDiscountVO.SMCDRecordVO::getCustomerName)));
artNoCusDiscMap.forEach((artNo, cusDiscMap) -> cusDiscMap.forEach((cusName, cusDiscList) -> {
Map<String, Integer> colorDiscMap = cusDiscList.stream().collect(Collectors.groupingBy(FhbCusDiscountVO.SMCDRecordVO::getColor,
Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparing(FhbCusDiscountVO.SMCDRecordVO::getUpdateTime,
Comparator.nullsFirst(String::compareTo))), record -> record.get().getDiscount())));
// 判断所有颜色的优惠金额是否一致
Set<Integer> discValueSet = new HashSet<>(colorDiscMap.values());
if (discValueSet.size() > 1) {
errCusDiscUnSameList.add(artNo + ":" + cusName + ":" + colorDiscMap.keySet() + ",优惠金额不一致");
}
}));
return R.ok(new CusDiscErrorVO().setErrDiscList(errDiscList).setErrCusDiscUnSameList(errCusDiscUnSameList));
}

View File

@ -311,8 +311,7 @@ public class GtAndFhbBizController extends BaseController {
prodSvcList.add(new StoreProductService().setStoreProdId(storeProd.getId()).setCustomRefund("0")
.setThirtyDayRefund("0").setOneBatchSale("1").setRefundWithinThreeDay("0"));
// 初始化商品的类目属性
StoreProductCategoryAttribute cateAttr = Optional.ofNullable(prodAttrMap.get(gtMatchSkuList.get(0).getProduct_id()))
.orElseThrow(() -> new ServiceException("没有GT商品类目属性!" + storeProd.getProdArtNum(), HttpStatus.ERROR));
StoreProductCategoryAttribute cateAttr = Optional.ofNullable(prodAttrMap.get(gtMatchSkuList.get(0).getProduct_id())).orElse(new StoreProductCategoryAttribute());
cateAttr.setStoreId(storeProd.getStoreId()).setStoreProdId(storeProd.getId());
prodAttrList.add(cateAttr);
});
@ -491,6 +490,8 @@ public class GtAndFhbBizController extends BaseController {
if (CollectionUtils.isEmpty(fhbCusDiscCacheList)) {
throw new ServiceException("fhb供应商客户优惠列表为空!" + initVO.getSupplierId(), HttpStatus.ERROR);
}
// 2025.10.16 增加一重保险客户优惠必须是大于0的
fhbCusDiscCacheList = fhbCusDiscCacheList.stream().filter(x -> x.getDiscount() > 0).collect(Collectors.toList());
List<FhbProdStockVO.SMPSRecordVO> fhbStockCacheList = redisCache
.getCacheObject(CacheConstants.MIGRATION_SUPPLIER_PROD_STOCK_KEY + initVO.getSupplierId());
if (CollectionUtils.isEmpty(fhbStockCacheList)) {

View File

@ -0,0 +1,718 @@
package com.ruoyi.web.controller.xkt.migartion;
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.poi.ExcelUtil;
import com.ruoyi.web.controller.xkt.migartion.vo.GtAndTYCompareDownloadVO;
import com.ruoyi.web.controller.xkt.migartion.vo.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.ty.TyCusDiscImportVO;
import com.ruoyi.web.controller.xkt.migartion.vo.ty.TyCusImportVO;
import com.ruoyi.web.controller.xkt.migartion.vo.ty.TyProdImportVO;
import com.ruoyi.web.controller.xkt.migartion.vo.ty.TyProdStockVO;
import com.ruoyi.xkt.domain.*;
import com.ruoyi.xkt.enums.EProductStatus;
import com.ruoyi.xkt.enums.ListingType;
import com.ruoyi.xkt.mapper.*;
import com.ruoyi.xkt.service.shipMaster.IShipMasterService;
import lombok.RequiredArgsConstructor;
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 javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* Compare
*
* @author ruoyi
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/rest/v1/gt-ty/t2")
public class GtAndTyBiz2Controller extends BaseController {
final IShipMasterService shipMasterService;
final RedisCache redisCache;
final StoreProductColorMapper prodColorMapper;
final StoreProductColorSizeMapper prodColorSizeMapper;
final StoreProductMapper storeProdMapper;
final StoreProductStockMapper prodStockMapper;
final StoreCustomerMapper storeCusMapper;
final StoreCustomerProductDiscountMapper storeCusProdDiscMapper;
final StoreColorMapper storeColorMapper;
final StoreMapper storeMapper;
final StoreProductServiceMapper prodSvcMapper;
final StoreProductCategoryAttributeMapper prodCateAttrMapper;
final SysProductCategoryMapper prodCateMapper;
// TODO 提供导出测试环境数据的接口,不然迁移到生产还要重新来一遍
// TODO 提供导出测试环境数据的接口,不然迁移到生产还要重新来一遍
// TODO 提供导出测试环境数据的接口,不然迁移到生产还要重新来一遍
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PostMapping("/sync-es/{storeId}")
public void syncToEs(@PathVariable("storeId") Long storeId) {
// 同步主图 到 图搜 服务器
// TODO 上传到ES之后还需要确认
// TODO 上传到ES之后还需要确认
// TODO 上传到ES之后还需要确认
}
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PostMapping("/sync-pic/{storeId}")
public void syncToPicSearch(@PathVariable("storeId") Long storeId) {
// 同步主图 到 图搜 服务器
// TODO 上传到图搜服务器之后还要确认
// TODO 上传到图搜服务器之后还要确认
// TODO 上传到图搜服务器之后还要确认
}
/**
* step1
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@GetMapping("/compare/{userId}")
public void compare(HttpServletResponse response, @PathVariable("userId") Integer userId) throws UnsupportedEncodingException {
// 处理的思路以GT为主根据GT的货号 去匹配TY的货号有些档口写的比较规范这种就比较好处理
List<GtProdSkuVO> gtOnSaleList = ObjectUtils.defaultIfNull(redisCache
.getCacheObject(CacheConstants.MIGRATION_GT_SALE_BASIC_KEY + userId), new ArrayList<>());
// gt所有在售的货号列表
List<String> gtArtNoList = gtOnSaleList.stream().map(GtProdSkuVO::getArticle_number).map(String::trim).distinct().collect(Collectors.toList());
Map<String, String> gtOnSaleArtNoColorMap = gtOnSaleList.stream().collect(Collectors.groupingBy(GtProdSkuVO::getArticle_number,
Collectors.collectingAndThen(Collectors.mapping(GtProdSkuVO::getColor, Collectors.toList()),
list -> "(" + list.stream().distinct().collect(Collectors.joining(",")) + ")")));
// 查看gt 下架的商品有多少相似的货号
List<GtProdSkuVO> gtOffSaleBasicList = ObjectUtils.defaultIfNull(redisCache
.getCacheObject(CacheConstants.MIGRATION_GT_OFF_SALE_BASIC_KEY + userId), new ArrayList<>());
List<String> gtOffSaleArtNoList = gtOffSaleBasicList.stream().map(GtProdSkuVO::getArticle_number).distinct().collect(Collectors.toList());
// 找到TY对应的商品
List<TyProdImportVO> tyProdList = ObjectUtils.defaultIfNull(redisCache
.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + userId), new ArrayList<>());
Map<String, String> 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<String, List<String>> gtMatchTyArtNoMap = new HashMap<>();
// 以GT为准在找TY匹配的货号
gtArtNoList.forEach(gtOnSaleArtNo -> tyArtNoColorMap.forEach((tyArtNo, tyArtNoColorStr) -> {
if (tyArtNo.contains(gtOnSaleArtNo)) {
List<String> existMatchArtNoList = gtMatchTyArtNoMap.getOrDefault(gtOnSaleArtNo, new ArrayList<>());
existMatchArtNoList.add(tyArtNo);
gtMatchTyArtNoMap.put(gtOnSaleArtNo, existMatchArtNoList);
}
}));
// 清洗后,相同货号映射
List<String> matchArtNoList = new ArrayList<>();
List<String> multiMatchGtArtNoList = new ArrayList<>();
matchArtNoList.add("============ GT和TY匹配的货号 ============");
// 清洗数据之后GO平台和TY平台 货号一致的,按照这种来展示: GT => [Z1110(黑色,黑色绒里,棕色,棕色绒里)] <= 清洗后的货号 => [Z1110(黑色,黑色绒里,棕色,棕色绒里)] <= TY
gtMatchTyArtNoMap.forEach((gtArtNo, tyArtNoList) -> {
List<String> tyArtNoColorList = tyArtNoList.stream().map(tyArtNo -> tyArtNo + tyArtNoColorMap.get(tyArtNo)).collect(Collectors.toList());
final String sameArtNo = "GT => " + gtArtNo + gtOnSaleArtNoColorMap.get(gtArtNo) + " <= " + gtArtNo + " => " + tyArtNoColorList + " <= TY";
matchArtNoList.add(sameArtNo);
multiMatchGtArtNoList.add(gtArtNo);
});
matchArtNoList.add("============ GT独有的货号 ============");
matchArtNoList.add("============ GT独有的货号 ============");
// 只存在于GT的货号列表
gtOnSaleArtNoColorMap.forEach((gtArtNo, gtArtNoColorStr) -> {
if (!multiMatchGtArtNoList.contains(gtArtNo)) {
matchArtNoList.add(gtArtNo + gtArtNoColorStr);
}
});
matchArtNoList.add("============ TY独有的货号 ============");
matchArtNoList.add("============ TY独有的货号 ============");
List<String> matchTyArtNoList = new ArrayList<>();
// 共同存在GT 和 TY的TY货号
gtMatchTyArtNoMap.forEach((gtArtNo, tyArtNoList) -> matchTyArtNoList.addAll(tyArtNoList));
// 已下架的GT货号如果能在TY找到匹配的也要剔除
gtOffSaleArtNoList.forEach(gtOffSaleArtNo -> tyArtNoColorMap.forEach((tyArtNo, colorNameStr) -> {
if (tyArtNo.contains(gtOffSaleArtNo)) {
matchTyArtNoList.add(tyArtNo);
}
}));
tyArtNoColorMap.forEach((tyArtNo, colorNameStr) -> {
if (!matchTyArtNoList.contains(tyArtNo)) {
matchArtNoList.add(tyArtNo + colorNameStr);
}
});
List<GtAndTYCompareDownloadVO> downloadList = new ArrayList<>();
for (int i = 0; i < matchArtNoList.size(); i++) {
downloadList.add(new GtAndTYCompareDownloadVO().setOrderNum(i + 1).setCode(matchArtNoList.get(i)));
}
ExcelUtil<GtAndTYCompareDownloadVO> util = new ExcelUtil<>(GtAndTYCompareDownloadVO.class);
String encodedFileName = URLEncoder.encode("GT与TY差异" + DateUtils.getDate(), "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename=" + encodedFileName + ".xlsx");
util.exportExcel(response, downloadList, "差异");
}
/**
* step2
*
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PostMapping("/init-prod")
@Transactional
public R<Integer> initProd(@Validated @RequestBody GtAndTYInitVO initVO) {
// 去掉可能的空格
initVO.setExcludeArtNoList(initVO.getExcludeArtNoList().stream().map(String::trim).collect(Collectors.toList()));
Optional.ofNullable(this.storeMapper.selectOne(new LambdaQueryWrapper<Store>()
.eq(Store::getId, initVO.getStoreId()).eq(Store::getDelFlag, Constants.UNDELETED)))
.orElseThrow(() -> new ServiceException("档口不存在!", HttpStatus.ERROR));
// 步骤1: 颜色初始化
this.initStoreColorList(initVO.getStoreId(), initVO.getUserId());
// 步骤2: 客户初始化
this.initStoreCusList(initVO);
// 处理的思路以GT为主根据GT的货号 去匹配TY的货号有些档口写的比较规范这种就比较好处理
List<GtProdSkuVO> gtOnSaleList = ObjectUtils.defaultIfNull(redisCache.getCacheObject(CacheConstants.MIGRATION_GT_SALE_BASIC_KEY + initVO.getUserId()), new ArrayList<>());
// gt所有在售的货号列表
List<String> gtArtNoList = gtOnSaleList.stream().map(GtProdSkuVO::getArticle_number).map(String::trim).distinct().collect(Collectors.toList());
// 找到TY对应的商品
List<TyProdImportVO> tyProdList = ObjectUtils.defaultIfNull(redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + initVO.getUserId()), new ArrayList<>());
Map<String, String> 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<String, List<String>> gtMatchTyArtNoMap = new HashMap<>();
// 以GT为准在找TY匹配的货号
gtArtNoList.forEach(gtOnSaleArtNo -> tyArtNoColorMap.forEach((tyArtNo, tyArtNoColorStr) -> {
if (tyArtNo.contains(gtOnSaleArtNo)) {
List<String> existMatchArtNoList = gtMatchTyArtNoMap.getOrDefault(gtOnSaleArtNo, new ArrayList<>());
existMatchArtNoList.add(tyArtNo);
gtMatchTyArtNoMap.put(gtOnSaleArtNo, existMatchArtNoList);
}
}));
// gt按照货号分组
Map<String, List<GtProdSkuVO>> gtSaleGroupMap = gtOnSaleList.stream().collect(Collectors.groupingBy(GtProdSkuVO::getArticle_number));
// GT分类
List<GtCateVO.GCIDataVO> cacheList = ObjectUtils.defaultIfNull(redisCache
.getCacheObject(CacheConstants.MIGRATION_GT_SALE_CATE_KEY + initVO.getUserId()), new ArrayList<>());
List<SysProductCategory> prodCateList = this.prodCateMapper.selectList(new LambdaQueryWrapper<SysProductCategory>()
.eq(SysProductCategory::getDelFlag, Constants.UNDELETED));
Map<String, Long> dbCateNameMap = prodCateList.stream().collect(Collectors.toMap(SysProductCategory::getName, SysProductCategory::getId));
// GT商品分类和步橘分类映射
Map<Integer, Long> 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);
});
// 当天
final Date voucherDate = java.sql.Date.valueOf(LocalDate.now());
// 所有商品的类目属性map key gt的product_id value StoreProductCategoryAttribute
Map<Integer, StoreProductCategoryAttribute> prodAttrMap = new HashMap<>();
// 待导入的商品
List<StoreProduct> storeProdList = new ArrayList<>();
gtMatchTyArtNoMap.forEach((gtArtNo, tyArtNoList) -> {
// 排除掉需要特殊处理的货号
if (CollectionUtils.isEmpty(initVO.getExcludeArtNoList()) || !initVO.getExcludeArtNoList().contains(gtArtNo)) {
// 获取GT匹配的商品中的第一个商品
List<GtProdSkuVO> gtMatchSkuList = gtSaleGroupMap.get(gtArtNo);
// 初始化档口商品
StoreProduct storeProd = new StoreProduct().setStoreId(initVO.getStoreId()).setProdCateId(cateRelationMap.get(gtMatchSkuList.get(0).getCategory_nid()))
.setPrivateItem(0).setProdArtNum(gtMatchSkuList.get(0).getArticle_number()).setProdTitle(gtMatchSkuList.get(0).getCharacters()).setListingWay(ListingType.RIGHT_NOW.getValue())
.setVoucherDate(voucherDate).setProdStatus(EProductStatus.ON_SALE.getValue()).setRecommendWeight(0L).setSaleWeight(0L).setPopularityWeight(0L);
// 提前设置档口商品的类目属性
this.preMatchAttr(gtMatchSkuList.get(0).getProduct_id(), initVO.getUserId(), prodAttrMap);
storeProdList.add(storeProd);
}
});
this.storeProdMapper.insert(storeProdList);
// 步骤4: 初始化商品属性
List<StoreProductService> prodSvcList = new ArrayList<>();
List<StoreProductCategoryAttribute> prodAttrList = new ArrayList<>();
storeProdList.forEach(storeProd -> {
// 获取GT匹配的商品sku列表
List<GtProdSkuVO> gtMatchSkuList = gtSaleGroupMap.get(storeProd.getProdArtNum());
// 初始化商品服务承诺
prodSvcList.add(new StoreProductService().setStoreProdId(storeProd.getId()).setCustomRefund("0")
.setThirtyDayRefund("0").setOneBatchSale("1").setRefundWithinThreeDay("0"));
// 初始化商品的类目属性
StoreProductCategoryAttribute cateAttr = Optional.ofNullable(prodAttrMap.get(gtMatchSkuList.get(0).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();
}
/**
* step3
*
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PostMapping("/init-color")
@Transactional
public R<Integer> initColor(@Validated @RequestBody GtAndTYInitVO initVO) {
// 从数据库查询最新数据
List<StoreProduct> storeProdList = this.storeProdMapper.selectList(new LambdaQueryWrapper<StoreProduct>()
.eq(StoreProduct::getStoreId, initVO.getStoreId()).eq(StoreProduct::getDelFlag, Constants.UNDELETED));
List<StoreColor> storeColorList = this.storeColorMapper.selectList(new LambdaQueryWrapper<StoreColor>()
.eq(StoreColor::getStoreId, initVO.getStoreId()).eq(StoreColor::getDelFlag, Constants.UNDELETED));
Map<String, StoreColor> storeColorMap = storeColorList.stream().collect(Collectors.toMap(StoreColor::getColorName, x -> x));
// 处理的思路以GT为主根据GT的货号 去匹配TY的货号有些档口写的比较规范这种就比较好处理
List<GtProdSkuVO> gtOnSaleList = ObjectUtils.defaultIfNull(redisCache.getCacheObject(CacheConstants.MIGRATION_GT_SALE_BASIC_KEY + initVO.getUserId()), new ArrayList<>());
// gt所有在售的货号列表
List<String> gtArtNoList = gtOnSaleList.stream().map(GtProdSkuVO::getArticle_number).map(String::trim).distinct().collect(Collectors.toList());
// gt按照货号分组
Map<String, List<GtProdSkuVO>> gtSaleGroupMap = gtOnSaleList.stream().collect(Collectors.groupingBy(GtProdSkuVO::getArticle_number));
// 找到TY对应的商品
List<TyProdImportVO> tyProdList = ObjectUtils.defaultIfNull(redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + initVO.getUserId()), new ArrayList<>());
// TY货号下颜色的map
Map<String, List<TyProdImportVO>> tyProdGroupMap = tyProdList.stream().collect(Collectors.groupingBy(TyProdImportVO::getProdArtNum));
Map<String, String> 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<String, List<String>> gtMatchTyArtNoMap = new HashMap<>();
// 以GT为准在找TY匹配的货号
gtArtNoList.forEach(gtOnSaleArtNo -> tyArtNoColorMap.forEach((tyArtNo, tyArtNoColorStr) -> {
if (tyArtNo.contains(gtOnSaleArtNo)) {
List<String> existMatchArtNoList = gtMatchTyArtNoMap.getOrDefault(gtOnSaleArtNo, new ArrayList<>());
existMatchArtNoList.add(tyArtNo);
gtMatchTyArtNoMap.put(gtOnSaleArtNo, existMatchArtNoList);
}
}));
// 商品所有颜色 尺码 颜色库存初始化
List<StoreProductColor> prodColorList = new ArrayList<>();
List<StoreProductColorSize> prodColorSizeList = new ArrayList<>();
storeProdList.forEach(storeProd -> {
// TY匹配的货号
List<String> tyMatchArtNoList = gtMatchTyArtNoMap.get(storeProd.getProdArtNum());
// 获取GT匹配的商品sku列表
List<GtProdSkuVO> gtMatchSkuList = gtSaleGroupMap.get(storeProd.getProdArtNum());
// 当前货号在GT的所有尺码作为标准尺码
List<Integer> gtStandardSizeList = gtMatchSkuList.stream().map(sku -> (int) Math.floor(Double.parseDouble(sku.getSize()))).collect(Collectors.toList());
AtomicInteger orderNum = new AtomicInteger();
tyMatchArtNoList.forEach(tyArtNo -> {
List<TyProdImportVO> tyMatchSkuList = tyProdGroupMap.get(tyArtNo);
for (TyProdImportVO tyProdImportVO : tyMatchSkuList) {
StoreColor storeColor = Optional.ofNullable(storeColorMap.get(tyProdImportVO.getColorName()))
.orElseThrow(() -> new ServiceException("没有TY商品颜色!" + tyArtNo, 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()));
// 该颜色所有的尺码
for (int j = 0; j < Constants.SIZE_LIST.size(); j++) {
// TY系统条码前缀
final String otherSnPrefix = tyProdImportVO.getTySnPrefix() + Constants.SIZE_LIST.get(j);
prodColorSizeList.add(new StoreProductColorSize().setSize(Constants.SIZE_LIST.get(j)).setStoreColorId(storeColor.getId())
.setStoreProdId(storeProd.getId()).setPrice(tyProdImportVO.getPrice()).setOtherSnPrefix(otherSnPrefix).setNextSn(0)
.setStandard(gtStandardSizeList.contains(Constants.SIZE_LIST.get(j)) ? 1 : 0));
}
}
});
});
// 插入商品颜色及颜色对应的尺码,档口服务承诺
this.prodColorMapper.insert(prodColorList);
prodColorSizeList.sort(Comparator.comparing(StoreProductColorSize::getStoreProdId).thenComparing(StoreProductColorSize::getSize));
this.prodColorSizeMapper.insert(prodColorSizeList);
// 还要更新步橘系统的条码前缀
prodColorSizeList.forEach(x -> x.setSnPrefix(initVO.getStoreId() + String.format("%08d", x.getId())));
this.prodColorSizeMapper.updateById(prodColorSizeList);
return R.ok();
}
/**
* step4
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PostMapping("/init-cus-disc")
@Transactional
public R<Integer> initCusDisc(@Validated @RequestBody GtAndTYInitVO initVO) {
List<StoreProduct> storeProdList = this.storeProdMapper.selectList(new LambdaQueryWrapper<StoreProduct>()
.eq(StoreProduct::getStoreId, initVO.getStoreId()).eq(StoreProduct::getDelFlag, Constants.UNDELETED));
List<StoreProductColor> prodColorList = this.prodColorMapper.selectList(new LambdaQueryWrapper<StoreProductColor>()
.eq(StoreProductColor::getStoreId, initVO.getStoreId()).eq(StoreProductColor::getDelFlag, Constants.UNDELETED));
List<StoreCustomer> storeCusList = this.storeCusMapper.selectList(new LambdaQueryWrapper<StoreCustomer>()
.eq(StoreCustomer::getStoreId, initVO.getStoreId()).eq(StoreCustomer::getDelFlag, Constants.UNDELETED));
Map<String, List<String>> multiSameTyMap = new HashMap<>();
// 查看TY 这边有多少相似的货号
List<TyProdImportVO> tyProdList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + initVO.getUserId());
tyProdList.stream().map(TyProdImportVO::getProdArtNum).distinct()
.forEach(artNo -> {
// 只保留核心连续的数字,去除其他所有符号
String cleanArtNo = this.extractCoreArticleNumber(artNo);
if (CollectionUtils.isEmpty(initVO.getExcludeArtNoList()) || !initVO.getExcludeArtNoList().contains(cleanArtNo)) {
List<String> existList = multiSameTyMap.containsKey(cleanArtNo) ? multiSameTyMap.get(cleanArtNo) : new ArrayList<>();
existList.add(artNo);
multiSameTyMap.put(cleanArtNo, existList);
}
});
// TY商品缓存
List<TyProdImportVO> cacheList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + initVO.getUserId());
if (CollectionUtils.isEmpty(cacheList)) {
throw new ServiceException("TY商品列表为空", HttpStatus.ERROR);
}
// ty货号正在生效的颜色map因为客户优惠有些是删除的颜色需要通过这里去过滤
Map<String, Set<String>> tyExistArtNoColorMap = cacheList.stream().collect(Collectors
.groupingBy(TyProdImportVO::getProdArtNum, Collectors.mapping(TyProdImportVO::getColorName, Collectors.toSet())));
// 从redis中获取已存在的客户优惠数据
List<TyCusDiscImportVO> tyCusDiscCacheList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_CUS_DISCOUNT_KEY + initVO.getUserId());
if (CollectionUtils.isEmpty(tyCusDiscCacheList)) {
throw new ServiceException("ty供应商客户优惠列表为空!" + initVO.getUserId(), HttpStatus.ERROR);
}
// 从redis中获取已存在的商品库存数据
List<TyProdStockVO> tyStockList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_STOCK_KEY + initVO.getUserId());
if (CollectionUtils.isEmpty(tyStockList)) {
throw new ServiceException("ty供应商商品库存列表为空!" + initVO.getUserId(), HttpStatus.ERROR);
}
// TY 货号颜色的库存对应关系
Map<String, Map<String, TyProdStockVO>> tyProdStockMap = tyStockList.stream().collect(Collectors
.groupingBy(TyProdStockVO::getProdArtNum, Collectors.toMap(TyProdStockVO::getColorName, x -> x)));
// TY 货号颜色优惠对应关系
Map<String, Map<String, List<TyCusDiscImportVO>>> tyCusDiscGroupMap = tyCusDiscCacheList.stream().collect(Collectors
.groupingBy(TyCusDiscImportVO::getProdArtNum, Collectors.groupingBy(TyCusDiscImportVO::getColorName)));
// 步橘系统商品所有颜色maps
Map<Long, Map<String, StoreProductColor>> prodColorGroupMap = prodColorList.stream().collect(Collectors
.groupingBy(StoreProductColor::getStoreProdId, Collectors.toMap(StoreProductColor::getColorName, x -> x)));
// 步橘系统客户名称map
Map<String, StoreCustomer> buJuStoreCusMap = storeCusList.stream().collect(Collectors.toMap(StoreCustomer::getCusName, x -> x));
List<StoreCustomerProductDiscount> prodCusDiscList = new ArrayList<>();
List<StoreProductStock> prodStockList = new ArrayList<>();
// 依次遍历商品列表找到货号和FHB货号对应关系然后用颜色进行匹配建立客户优惠关系
storeProdList.forEach(storeProd -> {
final String cleanArtNo = this.extractCoreArticleNumber(storeProd.getProdArtNum());
// 当前商品颜色列表 key 颜色中文名称
Map<String, StoreProductColor> buJuProdColorMap = Optional.ofNullable(prodColorGroupMap.get(storeProd.getId())).orElseThrow(() -> new ServiceException("没有商品颜色!" + storeProd.getProdArtNum(), HttpStatus.ERROR));
// 根据步橘货号 找到TY对应的货号可能是列表
List<String> tyAtrNoList = Optional.ofNullable(multiSameTyMap.get(cleanArtNo)).orElseThrow(() -> new ServiceException("没有TY货号!" + storeProd.getProdArtNum(), HttpStatus.ERROR));
// 处理档口商品库存
this.handleProdStock(tyAtrNoList, tyProdStockMap, buJuProdColorMap, storeProd.getStoreId(), storeProd.getId(), storeProd.getProdArtNum(), prodStockList);
tyAtrNoList.forEach(tyAtrNo -> {
// 处理客户优惠
this.handleCusDisc(tyAtrNo, tyExistArtNoColorMap, tyCusDiscGroupMap, buJuProdColorMap, buJuStoreCusMap, prodCusDiscList, storeProd.getStoreId(), storeProd.getId());
});
});
// 档口客户优惠
this.storeCusProdDiscMapper.insert(prodCusDiscList);
// 档口客户库存
this.prodStockMapper.insert(prodStockList);
return R.ok();
}
/**
*
*
* @param storeId ID
* @param userId GTID
*/
private void initStoreColorList(Long storeId, Integer userId) {
// TY商品缓存
List<TyProdImportVO> cacheList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + userId);
if (CollectionUtils.isEmpty(cacheList)) {
throw new ServiceException("TY商品列表为空", HttpStatus.ERROR);
}
List<String> tyColorList = cacheList.stream().map(TyProdImportVO::getColorName).distinct().collect(Collectors.toList());
List<StoreColor> storeColorList = new ArrayList<>();
for (int i = 0; i < tyColorList.size(); i++) {
storeColorList.add(new StoreColor().setStoreId(storeId).setColorName(tyColorList.get(i)).setOrderNum(i + 1));
}
this.storeColorMapper.insert(storeColorList);
storeColorList.stream().collect(Collectors.toMap(StoreColor::getColorName, x -> x));
}
/**
*
*/
private void handleProdStock(List<String> tyAtrNoList, Map<String, Map<String, TyProdStockVO>> tyProdStockMap, Map<String, StoreProductColor> buJuProdColorMap,
Long storeId, Long storeProdId, String prodArtNum, List<StoreProductStock> prodStockList) {
// 获取ty货号所有颜色的库存
Map<String, TyProdStockVO> tyColorStockMap = new HashMap<>();
tyAtrNoList.forEach(tyArtNo -> tyColorStockMap.putAll(tyProdStockMap.getOrDefault(tyArtNo, new HashMap<>())));
buJuProdColorMap.forEach((buJuColor, buJuProdColor) -> {
StoreProductStock stock = new StoreProductStock().setStoreId(storeId).setStoreProdId(storeProdId).setProdArtNum(prodArtNum)
.setColorName(buJuProdColorMap.get(buJuColor).getColorName()).setStoreProdColorId(buJuProdColorMap.get(buJuColor).getId())
.setStoreColorId(buJuProdColorMap.get(buJuColor).getStoreColorId());
if (tyColorStockMap.containsKey(buJuColor)) {
TyProdStockVO tySizeStock = tyColorStockMap.getOrDefault(buJuColor, null);
stock.setSize30(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize30() : null)
.setSize31(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize31() : null)
.setSize32(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize32() : null)
.setSize33(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize33() : null)
.setSize34(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize34() : null)
.setSize35(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize35() : null)
.setSize36(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize36() : null)
.setSize37(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize37() : null)
.setSize38(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize38() : null)
.setSize39(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize39() : null)
.setSize40(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize40() : null)
.setSize41(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize41() : null)
.setSize42(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize42() : null)
.setSize43(ObjectUtils.isNotEmpty(tySizeStock) ? tySizeStock.getSize43() : null);
}
prodStockList.add(stock);
});
}
/**
*
*/
private void handleCusDisc(String tyAtrNo, Map<String, Set<String>> tyExistArtNoColorMap,
Map<String, Map<String, List<TyCusDiscImportVO>>> tyCusDiscGroupMap,
Map<String, StoreProductColor> buJuProdColorMap, Map<String, StoreCustomer> buJuStoreCusMap,
List<StoreCustomerProductDiscount> prodCusDiscList, Long storeId, Long storeProdId) {
// TY货号下有哪些颜色存在客户优惠
Map<String, List<TyCusDiscImportVO>> tyColorCusDiscMap = tyCusDiscGroupMap.get(tyAtrNo);
if (MapUtils.isEmpty(tyColorCusDiscMap)) {
return;
}
// ty当前货号正在生效的颜色列表
Set<String> existColorSet = tyExistArtNoColorMap.getOrDefault(tyAtrNo, Collections.emptySet());
// 依次遍历存在优惠的颜色,设置步橘系统客户优惠关系
tyColorCusDiscMap.forEach((tyColor, tyCusDiscList) -> {
// 必须是现在正在生效的颜色,才会被添加到系统中
if (!existColorSet.contains(tyColor)) {
return;
}
// TODO 该处TY 与 FHB处理不同
// TODO 该处TY 与 FHB处理不同
// TODO 该处TY 与 FHB处理不同
tyCusDiscList.forEach(tyCusDisc -> {
StoreProductColor buJuProdColor = Optional.ofNullable(buJuProdColorMap.get(tyColor)).orElseThrow(() -> new ServiceException("没有步橘系统对应的颜色!" + tyColor, HttpStatus.ERROR));
StoreCustomer storeCus = Optional.ofNullable(buJuStoreCusMap.get(tyCusDisc.getCusName())).orElseThrow(() -> new ServiceException("没有步橘系统对应的客户!" + tyCusDisc.getCusName(), HttpStatus.ERROR));
// 将FHB客户优惠 转为步橘系统优惠
prodCusDiscList.add(new StoreCustomerProductDiscount().setStoreId(storeId).setStoreProdId(storeProdId).setStoreCusId(storeCus.getId())
.setStoreCusName(storeCus.getCusName()).setStoreProdColorId(buJuProdColor.getId()).setDiscount(tyCusDisc.getDiscount()));
});
});
}
/**
*
*
* @param initVO
* @return List<StoreCustomer>
*/
private List<StoreCustomer> initStoreCusList(GtAndTYInitVO initVO) {
List<TyCusImportVO> cacheList = ObjectUtils.defaultIfNull(redisCache
.getCacheObject(CacheConstants.MIGRATION_TY_CUS_KEY + initVO.getUserId()), new ArrayList<>());
if (CollectionUtils.isEmpty(cacheList)) {
throw new ServiceException("供应商客户列表为空!", HttpStatus.ERROR);
}
List<StoreCustomer> storeCusList = cacheList.stream()
// 排除掉现金客户 因为档口入驻时,会自动创建现金客户
.filter(x -> !Objects.equals(x.getCusName(), Constants.STORE_CUS_CASH))
.map(x -> new StoreCustomer().setStoreId(initVO.getStoreId()).setCusName(x.getCusName()))
.collect(Collectors.toList());
this.storeCusMapper.insert(storeCusList);
return storeCusList;
}
/**
*
*
* @param product_id GTID
* @param userId GTID
* @param prodAttrMap
*/
private void preMatchAttr(Integer product_id, Integer userId, Map<Integer, StoreProductCategoryAttribute> prodAttrMap) {
// 类目属性
Map<String, String> 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);
}
/**
* GT
*
* @param multiSaleSameGoMap
* @param gtSaleGroupMap
* @param cleanArtNo
* @return
*/
private List<GtProdSkuVO> getGtFirstSku(Map<String, List<String>> multiSaleSameGoMap, Map<String, List<GtProdSkuVO>> gtSaleGroupMap, String cleanArtNo) {
// GT匹配的货号
List<String> gtMatchArtNoList = multiSaleSameGoMap.get(cleanArtNo);
// GT 最短的货号
String shortestArtNo = gtMatchArtNoList.stream().min(Comparator.comparingInt(String::length))
.orElse(gtMatchArtNoList.get(0));
return gtSaleGroupMap.get(shortestArtNo);
}
/**
*
* : z1104 -> 1104, z1087 -> 1087, z1003-1 -> 1003, 922- -> 922, -8072 -> 8072
*
* @param articleNumber
* @return
*/
private String extractCoreArticleNumber(String articleNumber) {
if (articleNumber == null || articleNumber.isEmpty()) {
return "";
}
// 使用正则表达式匹配第一组连续的数字
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("\\d+");
java.util.regex.Matcher matcher = pattern.matcher(articleNumber);
// 返回第一组匹配到的数字
if (matcher.find()) {
return matcher.group();
}
// 如果没有找到数字,返回空字符串
throw new ServiceException("货号格式错误", HttpStatus.ERROR);
}
}

View File

@ -106,7 +106,7 @@ public class GtAndTyBizController extends BaseController {
.getCacheObject(CacheConstants.MIGRATION_GT_SALE_BASIC_KEY + userId), new ArrayList<>());
Map<String, String> articleNoColorMap = gtSaleBasicList.stream().collect(Collectors.groupingBy(GtProdSkuVO::getArticle_number,
Collectors.collectingAndThen(Collectors.mapping(GtProdSkuVO::getColor, Collectors.toList()),
list -> "(" + String.join(",", list) + ")")));
list -> "(" + list.stream().distinct().collect(Collectors.joining(",")) + ")")));
List<String> doubleRunSaleArtNoList = gtSaleBasicList.stream().map(GtProdSkuVO::getArticle_number).distinct().collect(Collectors.toList());
// 查看double_run 在售的商品 这边有多少相似的货号
doubleRunSaleArtNoList.forEach(article_number -> {
@ -134,7 +134,7 @@ public class GtAndTyBizController extends BaseController {
.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + userId), new ArrayList<>());
Map<String, String> tyProdArtNumColorMap = tyProdList.stream().collect(Collectors.groupingBy(TyProdImportVO::getProdArtNum,
Collectors.collectingAndThen(Collectors.mapping(TyProdImportVO::getColorName, Collectors.toList()),
list -> "(" + String.join(",", list) + ")")));
list -> "(" + list.stream().distinct().collect(Collectors.joining(",")) + ")")));
List<String> tyArtNoList = tyProdList.stream().map(TyProdImportVO::getProdArtNum).distinct().collect(Collectors.toList());
tyArtNoList.forEach(prodArtNum -> {
// 只保留核心连续的数字,去除其他所有符号
@ -281,9 +281,11 @@ public class GtAndTyBizController extends BaseController {
// 获取GT匹配的商品中的第一个商品
List<GtProdSkuVO> gtMatchSkuList = this.getGtFirstSku(multiSaleSameGoMap, gtSaleGroupMap, cleanArtNo);
// 初始化档口商品
StoreProduct storeProd = new StoreProduct().setStoreId(initVO.getStoreId()).setProdCateId(cateRelationMap.get(gtMatchSkuList.get(0).getCategory_nid()))
.setProdArtNum(gtMatchSkuList.get(0).getArticle_number()).setProdTitle(gtMatchSkuList.get(0).getCharacters()).setListingWay(ListingType.RIGHT_NOW.getValue())
.setVoucherDate(voucherDate).setProdStatus(EProductStatus.ON_SALE.getValue()).setRecommendWeight(0L).setSaleWeight(0L).setPopularityWeight(0L);
StoreProduct storeProd = new StoreProduct().setStoreId(initVO.getStoreId())
.setProdCateId(cateRelationMap.get(gtMatchSkuList.get(0).getCategory_nid())).setPrivateItem(0)
.setProdArtNum(gtMatchSkuList.get(0).getArticle_number()).setProdTitle(gtMatchSkuList.get(0).getCharacters())
.setListingWay(ListingType.RIGHT_NOW.getValue()).setVoucherDate(voucherDate).setProdStatus(EProductStatus.ON_SALE.getValue())
.setRecommendWeight(0L).setSaleWeight(0L).setPopularityWeight(0L);
// 提前设置档口商品的类目属性
this.preMatchAttr(gtMatchSkuList.get(0).getProduct_id(), initVO.getUserId(), prodAttrMap);
storeProdList.add(storeProd);
@ -302,8 +304,7 @@ public class GtAndTyBizController extends BaseController {
prodSvcList.add(new StoreProductService().setStoreProdId(storeProd.getId()).setCustomRefund("0")
.setThirtyDayRefund("0").setOneBatchSale("1").setRefundWithinThreeDay("0"));
// 初始化商品的类目属性
StoreProductCategoryAttribute cateAttr = Optional.ofNullable(prodAttrMap.get(gtMatchSkuList.get(0).getProduct_id()))
.orElseThrow(() -> new ServiceException("没有GT商品类目属性!" + storeProd.getProdArtNum(), HttpStatus.ERROR));
StoreProductCategoryAttribute cateAttr = Optional.ofNullable(prodAttrMap.get(gtMatchSkuList.get(0).getProduct_id())).orElse(new StoreProductCategoryAttribute());
cateAttr.setStoreId(storeProd.getStoreId()).setStoreProdId(storeProd.getId());
prodAttrList.add(cateAttr);
});
@ -330,7 +331,6 @@ public class GtAndTyBizController extends BaseController {
Map<String, StoreColor> storeColorMap = storeColorList.stream().collect(Collectors.toMap(StoreColor::getColorName, x -> x));
Map<String, List<String>> multiSaleSameGoMap = new HashMap<>();
Map<String, List<String>> multiOffSaleSameGoMap = new HashMap<>();
Map<String, List<String>> multiSameTyMap = new HashMap<>();
List<GtProdSkuVO> gtSaleBasicList = ObjectUtils.defaultIfNull(redisCache
.getCacheObject(CacheConstants.MIGRATION_GT_SALE_BASIC_KEY + initVO.getUserId()), new ArrayList<>());
@ -346,17 +346,6 @@ public class GtAndTyBizController extends BaseController {
}
});
// 查看gt 下架的商品有多少相似的货号
List<GtProdSkuVO> gtOffSaleBasicList = ObjectUtils.defaultIfNull(redisCache
.getCacheObject(CacheConstants.MIGRATION_GT_OFF_SALE_BASIC_KEY + initVO.getUserId()), new ArrayList<>());
gtOffSaleBasicList.stream().map(GtProdSkuVO::getArticle_number).distinct().forEach(article_number -> {
// 只保留核心连续的数字,去除其他所有符号
String cleanArtNo = this.extractCoreArticleNumber(article_number);
List<String> existList = multiOffSaleSameGoMap.containsKey(cleanArtNo) ? multiOffSaleSameGoMap.get(cleanArtNo) : new ArrayList<>();
existList.add(article_number);
multiOffSaleSameGoMap.put(cleanArtNo, existList);
});
// 查看TY 这边有多少相似的货号
List<TyProdImportVO> tyProdList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + initVO.getUserId());
// TY按照颜色分类
@ -458,6 +447,9 @@ public class GtAndTyBizController extends BaseController {
if (CollectionUtils.isEmpty(tyCusDiscCacheList)) {
throw new ServiceException("ty供应商客户优惠列表为空!" + initVO.getUserId(), HttpStatus.ERROR);
}
// 增加一重保险客户优惠必须大于0
tyCusDiscCacheList = tyCusDiscCacheList.stream().filter(x -> x.getDiscount() > 0).collect(Collectors.toList());
// 从redis中获取已存在的商品库存数据
List<TyProdStockVO> tyStockList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_STOCK_KEY + initVO.getUserId());
if (CollectionUtils.isEmpty(tyStockList)) {
@ -580,6 +572,7 @@ public class GtAndTyBizController extends BaseController {
}
// TODO 该处TY 与 FHB处理不同
// TODO 该处TY 与 FHB处理不同
// TODO 该处TY 与 FHB处理不同
tyCusDiscList.forEach(tyCusDisc -> {
StoreProductColor buJuProdColor = Optional.ofNullable(buJuProdColorMap.get(tyColor)).orElseThrow(() -> new ServiceException("没有步橘系统对应的颜色!" + tyColor, HttpStatus.ERROR));
StoreCustomer storeCus = Optional.ofNullable(buJuStoreCusMap.get(tyCusDisc.getCusName())).orElseThrow(() -> new ServiceException("没有步橘系统对应的客户!" + tyCusDisc.getCusName(), HttpStatus.ERROR));

View File

@ -8,6 +8,7 @@ import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.web.controller.xkt.migartion.vo.CusDiscErrorVO;
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;
@ -20,12 +21,8 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@ -94,47 +91,18 @@ public class TyController extends BaseController {
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PostMapping("/cus/disc/cache")
public R<Integer> createCusDiscCache(@RequestParam(value = "userId") Long userId, @RequestParam(value = "cusName") String cusName,
@RequestParam(value = "selfCheck") Boolean selfCheck, MultipartFile file) throws IOException {
// 判断客户是否存在
List<TyCusImportVO> tyCusVOList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_CUS_KEY + userId);
Map<String, TyCusImportVO> tyCusMap = tyCusVOList.stream().collect(Collectors.toMap(TyCusImportVO::getCusName, x -> x));
if (!tyCusMap.containsKey(cusName)) {
throw new ServiceException(cusName + " : 客户不存在", HttpStatus.ERROR);
}
public R<Integer> createCusDiscCache(@RequestParam(value = "userId") Long userId,
@RequestParam(value = "cusName") String cusName, MultipartFile file) throws IOException {
ExcelUtil<TyCusDiscImportVO> util = new ExcelUtil<>(TyCusDiscImportVO.class);
List<TyCusDiscImportVO> tyProdVOList = util.importExcel(file.getInputStream());
// 从redis中获取已存在的客户优惠数据
List<TyCusDiscImportVO> cacheList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_CUS_DISCOUNT_KEY + userId);
cacheList = Optional.ofNullable(cacheList).orElse(new ArrayList<>());
// 判断当前客户是否已导入过,若是则直接报错
Map<String, List<TyCusDiscImportVO>> cusDiscMap = cacheList.stream().collect(Collectors.groupingBy(TyCusDiscImportVO::getCusName));
if (cusDiscMap.containsKey(cusName)) {
throw new ServiceException(cusName + " : 客户已导入过优惠数据", HttpStatus.ERROR);
}
ExcelUtil<TyCusDiscImportVO> util = new ExcelUtil<>(TyCusDiscImportVO.class);
List<TyCusDiscImportVO> tyProdVOList = util.importExcel(file.getInputStream());
// 是否要自校验,校验识图是否准确
if (selfCheck) {
Map<String, Map<String, Integer>> artNoColorDiscountMap = tyProdVOList.stream()
// 只设置有优惠的存货及颜色
.filter(x -> ObjectUtils.isNotEmpty(x.getBasicPrice()))
.collect(Collectors.groupingBy(TyCusDiscImportVO::getProdArtNum, Collectors.toMap(TyCusDiscImportVO::getColorName, x ->
ObjectUtils.defaultIfNull(x.getBasicPrice(), 0) - ObjectUtils.defaultIfNull(x.getCustomerPrice(), 0), (v1, v2) -> v2)));
// 校验同一客户在同一货号不同颜色存在优惠是否相同,不同则需要提示
List<String> discErrorList = new ArrayList<>();
artNoColorDiscountMap.forEach((artNo, colorDiscMap) -> {
// 判断colorDiscMap所有颜色的优惠是否相同
if (colorDiscMap.values().stream().distinct().count() > 1) {
discErrorList.add(cusName + ":" + artNo + "" + "不同颜色优惠力度不同!");
}
});
if (CollectionUtils.isNotEmpty(discErrorList)) {
throw new ServiceException(discErrorList.toString(), HttpStatus.ERROR);
}
}
// 前置校验
this.cusDiscPrefixFilter(userId, cusName, cacheList);
// 因为是采用的截图转excel方式所以每个张图会冗余部分数据长度导入是需要判断是否已存在
Map<String, TyCusDiscImportVO> importCusDiscMap = new ConcurrentHashMap<>();
Map<String, TyCusDiscImportVO> importCusDiscMap = new HashMap<>();
List<TyCusDiscImportVO> importList = new ArrayList<>();
List<String> errorList = new ArrayList<>();
tyProdVOList.stream()
// 只设置有优惠的存货及颜色
.filter(x -> ObjectUtils.isNotEmpty(x.getBasicPrice()) && ObjectUtils.isNotEmpty(x.getCustomerPrice()))
@ -142,10 +110,7 @@ public class TyController extends BaseController {
if (importCusDiscMap.containsKey(x.getProdArtNum() + ":" + x.getColorName())) {
System.err.println(x.getProdArtNum() + ":" + x.getColorName());
} else {
final int discount = x.getBasicPrice() - x.getCustomerPrice();
if (discount <= 0) {
errorList.add(cusName + ":" + x.getProdArtNum() + ":" + x.getColorName() + ":优惠金额不能小于等于0");
}
final int discount = ObjectUtils.defaultIfNull(x.getBasicPrice(), 0) - ObjectUtils.defaultIfNull(x.getCustomerPrice(), 0);
String prodArtNum = x.getProdArtNum().trim();
String colorName = x.getColorName().trim();
// 如果货号包括-R 则表明是 货号为绒里,手动给颜色添加后缀“绒里”
@ -157,16 +122,15 @@ public class TyController extends BaseController {
importList.add(x);
}
});
if (CollectionUtils.isNotEmpty(errorList)) {
throw new ServiceException(errorList.toString(), HttpStatus.ERROR);
}
// 加到总的客户优惠上
CollectionUtils.addAll(cacheList, importList);
// TODO 过滤优惠大于0 是在比较插入数据的时候做的
// 存到redis中
redisCache.setCacheObject(CacheConstants.MIGRATION_TY_CUS_DISCOUNT_KEY + userId, cacheList);
return R.ok();
}
/**
* step4
*/
@ -175,6 +139,22 @@ public class TyController extends BaseController {
public R<Integer> createTyProdStockCache(@PathVariable Integer userId, MultipartFile file) throws IOException {
ExcelUtil<TyProdStockVO> util = new ExcelUtil<>(TyProdStockVO.class);
List<TyProdStockVO> tyStockList = util.importExcel(file.getInputStream());
/*// 判断货号 + 颜色是否存在,“图识”可能不准
List<TyProdImportVO> tyProdVOList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + userId);
// key prod+colorName
Map<String, TyProdImportVO> tyProdColorMap = tyProdVOList.stream().collect(Collectors.toMap(x -> x.getProdArtNum() + ":" + x.getColorName(), x -> x));
// 错误的货号和颜色,“图识”不准的部分
List<String> 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<String, TyProdStockVO> importStockMap = new ConcurrentHashMap<>();
List<TyProdStockVO> cacheList = new ArrayList<>();
@ -196,5 +176,78 @@ public class TyController extends BaseController {
return R.ok();
}
/**
* step5
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@GetMapping("/error/cus/disc/{userId}")
public R<CusDiscErrorVO> getErrorCusDisc(@PathVariable Integer userId){
List<TyCusDiscImportVO> cacheList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_CUS_DISCOUNT_KEY + userId);
List<String> errDiscList = 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() + ",优惠价大于等于原售价");
}
});
// 2. 有哪些优惠是同一货号不同颜色优惠金额不一致
List<String> errCusDiscUnSameList = new ArrayList<>();
Map<String, Map<String, List<TyCusDiscImportVO>>> artNoCusDiscMap = cacheList.stream().collect(Collectors
.groupingBy(TyCusDiscImportVO::getProdArtNum, Collectors.groupingBy(TyCusDiscImportVO::getCusName)));
// 货号下客户优惠的map
artNoCusDiscMap.forEach((artNo, cusDiscMap) -> cusDiscMap.forEach((cusName, cusDiscList) -> {
// 不同颜色优惠的map
Map<String, Integer> colorDiscMap = cusDiscList.stream().collect(Collectors
.toMap(TyCusDiscImportVO::getColorName, x -> ObjectUtils.defaultIfNull(x.getDiscount(), 0)));
// 判断所有颜色的优惠金额是否一致
Set<Integer> discValueSet = new HashSet<>(colorDiscMap.values());
if (discValueSet.size() > 1) {
errCusDiscUnSameList.add(artNo + ":" + cusName + ":" + colorDiscMap.keySet() + ",优惠金额不一致");
}
}));
return R.ok(new CusDiscErrorVO().setErrCusDiscUnSameList(errCusDiscUnSameList).setErrDiscList(errDiscList));
}
/**
*
*/
private void cusDiscPrefixFilter(Long userId, String cusName, List<TyCusDiscImportVO> cacheList) {
// 判断客户是否存在
List<TyCusImportVO> tyCusVOList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_CUS_KEY + userId);
Map<String, TyCusImportVO> tyCusMap = tyCusVOList.stream().collect(Collectors.toMap(TyCusImportVO::getCusName, x -> x));
if (!tyCusMap.containsKey(cusName)) {
throw new ServiceException(cusName + " : 客户不存在", HttpStatus.ERROR);
}
// 判断当前客户是否已导入过,若是则直接报错
Map<String, List<TyCusDiscImportVO>> cusDiscMap = cacheList.stream().collect(Collectors.groupingBy(TyCusDiscImportVO::getCusName));
if (cusDiscMap.containsKey(cusName)) {
throw new ServiceException(cusName + " : 客户已导入过优惠数据", HttpStatus.ERROR);
}
// TODO 临时去掉
// TODO 临时去掉
/* // 判断货号 + 颜色是否存在,“图识”可能不准
List<TyProdImportVO> tyProdVOList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + userId);
// key prod+colorName
Map<String, TyProdImportVO> tyProdColorMap = tyProdVOList.stream().collect(Collectors.toMap(x -> x.getProdArtNum() + ":" + x.getColorName(), x -> x));
// 错误的货号和颜色,“图识”不准的部分
List<String> 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);
}*/
}
}

View File

@ -0,0 +1,21 @@
package com.ruoyi.web.controller.xkt.migartion.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* @author liangyq
* @date 2025-05-11 23:46
*/
@Data
@Accessors(chain = true)
public class CusDiscErrorVO {
// 客户优惠金额小于0
private List<String> errDiscList;
// 客户在同一货品,不同颜色优惠金额不一致
private List<String> errCusDiscUnSameList;
}