master:系统调优;

pull/1121/head
liujiang 2025-10-16 20:14:24 +08:00
parent 802927498b
commit bad6ee092b
8 changed files with 233 additions and 190 deletions

View File

@ -11,7 +11,6 @@ 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;
import com.ruoyi.web.controller.xkt.migartion.vo.fhb.FhbProdVO;
import com.ruoyi.xkt.service.shipMaster.IShipMasterService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
@ -33,7 +32,6 @@ import java.util.stream.Collectors;
@RequestMapping("/rest/v1/fhb")
public class FhbController extends BaseController {
final IShipMasterService shipMasterService;
final RedisCache redisCache;
/**
@ -130,11 +128,12 @@ public class FhbController extends BaseController {
/**
* step5
*
* @return
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@GetMapping("/error/cus/disc/{supplierId}")
public R<CusDiscErrorVO> getErrorCusDisc(@PathVariable Integer 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<>());
@ -168,11 +167,9 @@ public class FhbController extends BaseController {
}
// ======================================================================================================================================
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PostMapping("/colors/cache/{supplierId}")
public R<Integer> createColorsCache(@PathVariable Integer supplierId) {

View File

@ -31,7 +31,6 @@ import com.ruoyi.xkt.enums.EProductStatus;
import com.ruoyi.xkt.enums.ListingType;
import com.ruoyi.xkt.mapper.*;
import com.ruoyi.xkt.service.IPictureService;
import com.ruoyi.xkt.service.shipMaster.IShipMasterService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
@ -66,7 +65,6 @@ import static com.ruoyi.common.constant.Constants.WEIGHT_DEFAULT_ZERO;
@RequestMapping("/rest/v1/gt-fhb")
public class GtAndFhbBizController extends BaseController {
final IShipMasterService shipMasterService;
final RedisCache redisCache;
final StoreProductColorMapper prodColorMapper;
final StoreProductColorSizeMapper prodColorSizeMapper;
@ -846,7 +844,8 @@ public class GtAndFhbBizController extends BaseController {
/**
*
* @param storeId ID
*
* @param storeId ID
* @param supplierId ID
*/
private void initStoreColorList(Long storeId, Integer supplierId) {
@ -887,7 +886,4 @@ public class GtAndFhbBizController extends BaseController {
}
}

View File

@ -1,5 +1,8 @@
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;
@ -9,7 +12,10 @@ 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.GtAndTYCompareDownloadVO;
import com.ruoyi.web.controller.xkt.migartion.vo.GtAndTYInitVO;
import com.ruoyi.web.controller.xkt.migartion.vo.gt.GtCateVO;
@ -19,11 +25,13 @@ 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.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.shipMaster.IShipMasterService;
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;
@ -34,23 +42,26 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
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;
/**
* Compare
*
* @author ruoyi
*/
@Slf4j
@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;
@ -63,34 +74,8 @@ public class GtAndTyBiz2Controller extends BaseController {
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 上传到图搜服务器之后还要确认
}
final EsClientWrapper esClientWrapper;
final FsNotice fsNotice;
/**
@ -357,15 +342,6 @@ public class GtAndTyBiz2Controller extends BaseController {
return R.ok();
}
/**
* step4
*/
@ -381,33 +357,43 @@ public class GtAndTyBiz2Controller extends BaseController {
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);
}
});
// 处理的思路以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> cacheList = redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + initVO.getUserId());
if (CollectionUtils.isEmpty(cacheList)) {
// 找到TY对应的商品
List<TyProdImportVO> tyProdList = ObjectUtils.defaultIfNull(redisCache.getCacheObject(CacheConstants.MIGRATION_TY_PROD_KEY + initVO.getUserId()), new ArrayList<>());
if (CollectionUtils.isEmpty(tyProdList)) {
throw new ServiceException("TY商品列表为空", HttpStatus.ERROR);
}
// ty货号正在生效的颜色map因为客户优惠有些是删除的颜色需要通过这里去过滤
Map<String, Set<String>> tyExistArtNoColorMap = cacheList.stream().collect(Collectors
Map<String, Set<String>> tyExistArtNoColorMap = tyProdList.stream().collect(Collectors
.groupingBy(TyProdImportVO::getProdArtNum, Collectors.mapping(TyProdImportVO::getColorName, Collectors.toSet())));
// TY货号下颜色的map
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);
}
}));
// 从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);
}
// 增加一重保险客户优惠必须大于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)) {
@ -428,11 +414,10 @@ public class GtAndTyBiz2Controller extends BaseController {
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));
List<String> tyAtrNoList = Optional.ofNullable(gtMatchTyArtNoMap.get(storeProd.getProdArtNum())).orElseThrow(() -> new ServiceException("没有TY货号!" + storeProd.getProdArtNum(), HttpStatus.ERROR));
// 处理档口商品库存
this.handleProdStock(tyAtrNoList, tyProdStockMap, buJuProdColorMap, storeProd.getStoreId(), storeProd.getId(), storeProd.getProdArtNum(), prodStockList);
@ -451,6 +436,88 @@ public class GtAndTyBiz2Controller extends BaseController {
return R.ok();
}
/**
* step5
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PostMapping("/sync-es/{storeId}")
public R<Integer> syncToEs(@PathVariable("storeId") Long storeId) {
// 将公共的商品同步到ES
List<StoreProduct> storeProdList = this.storeProdMapper.selectList(new LambdaQueryWrapper<StoreProduct>()
.eq(StoreProduct::getDelFlag, Constants.UNDELETED).eq(StoreProduct::getStoreId, storeId));
if (CollectionUtils.isEmpty(storeProdList)) {
return R.fail();
}
final List<String> storeProdIdList = storeProdList.stream().map(StoreProduct::getId).map(String::valueOf).collect(Collectors.toList());
// 所有的分类
List<SysProductCategory> prodCateList = this.prodCateMapper.selectList(new LambdaQueryWrapper<SysProductCategory>()
.eq(SysProductCategory::getDelFlag, Constants.UNDELETED));
Map<Long, SysProductCategory> prodCateMap = prodCateList.stream().collect(Collectors.toMap(SysProductCategory::getId, x -> x));
// 获取当前商品最低价格
Map<Long, BigDecimal> prodMinPriceMap = this.prodColorSizeMapper.selectStoreProdMinPriceList(storeProdIdList).stream().collect(Collectors
.toMap(StoreProdMinPriceDTO::getStoreProdId, StoreProdMinPriceDTO::getPrice));
// 档口商品的属性map
Map<Long, StoreProductCategoryAttribute> cateAttrMap = this.prodCateAttrMapper.selectList(new LambdaQueryWrapper<StoreProductCategoryAttribute>()
.eq(StoreProductCategoryAttribute::getDelFlag, Constants.UNDELETED).in(StoreProductCategoryAttribute::getStoreProdId, storeProdIdList))
.stream().collect(Collectors.toMap(StoreProductCategoryAttribute::getStoreProdId, x -> x));
// 档口商品对应的档口
Map<Long, Store> storeMap = this.storeMapper.selectList(new LambdaQueryWrapper<Store>().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<ESProductDTO> 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<BulkOperation> 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("批量新增到 ES 成功的 id列表: {}", response.items().stream().map(BulkResponseItem::id).collect(Collectors.toList()));
// 有哪些没执行成功的,需要发飞书通知
List<String> successIdList = response.items().stream().map(BulkResponseItem::id).collect(Collectors.toList());
List<String> unExeIdList = storeProdIdList.stream().map(String::valueOf).filter(x -> !successIdList.contains(x)).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(unExeIdList)) {
fsNotice.sendMsg2DefaultChat(storeId + ",批量新增商品到 ES 失败", "以下storeProdId未执行成功: " + unExeIdList);
} else {
fsNotice.sendMsg2DefaultChat(storeId + ",批量新增商品到 ES 成功", "共处理 " + response.items().size() + " 条记录");
}
} catch (Exception e) {
log.error("批量新增到 ES 失败", e);
fsNotice.sendMsg2DefaultChat(storeId + ",批量新增商品到 ES 失败", e.getMessage());
}
return R.ok();
}
/**
*
@ -509,8 +576,7 @@ public class GtAndTyBiz2Controller extends BaseController {
/**
*
*/
private void handleCusDisc(String tyAtrNo, Map<String, Set<String>> tyExistArtNoColorMap,
Map<String, Map<String, List<TyCusDiscImportVO>>> tyCusDiscGroupMap,
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货号下有哪些颜色存在客户优惠
@ -529,7 +595,7 @@ public class GtAndTyBiz2Controller extends BaseController {
// TODO 该处TY 与 FHB处理不同
// TODO 该处TY 与 FHB处理不同
// TODO 该处TY 与 FHB处理不同
tyCusDiscList.forEach(tyCusDisc -> {
tyCusDiscList.stream().filter(x -> x.getDiscount() > 0).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客户优惠 转为步橘系统优惠
@ -543,9 +609,8 @@ public class GtAndTyBiz2Controller extends BaseController {
*
*
* @param initVO
* @return List<StoreCustomer>
*/
private List<StoreCustomer> initStoreCusList(GtAndTYInitVO initVO) {
private void initStoreCusList(GtAndTYInitVO initVO) {
List<TyCusImportVO> cacheList = ObjectUtils.defaultIfNull(redisCache
.getCacheObject(CacheConstants.MIGRATION_TY_CUS_KEY + initVO.getUserId()), new ArrayList<>());
if (CollectionUtils.isEmpty(cacheList)) {
@ -557,7 +622,6 @@ public class GtAndTyBiz2Controller extends BaseController {
.map(x -> new StoreCustomer().setStoreId(initVO.getStoreId()).setCusName(x.getCusName()))
.collect(Collectors.toList());
this.storeCusMapper.insert(storeCusList);
return storeCusList;
}
/**
@ -674,45 +738,4 @@ public class GtAndTyBiz2Controller extends BaseController {
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

@ -1,5 +1,8 @@
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;
@ -9,7 +12,10 @@ 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.GtAndTYCompareDownloadVO;
import com.ruoyi.web.controller.xkt.migartion.vo.GtAndTYInitVO;
import com.ruoyi.web.controller.xkt.migartion.vo.gt.GtCateVO;
@ -19,11 +25,13 @@ 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.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.shipMaster.IShipMasterService;
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;
@ -34,23 +42,26 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
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;
/**
* Compare
*
* @author ruoyi
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/rest/v1/gt-ty")
public class GtAndTyBizController extends BaseController {
final IShipMasterService shipMasterService;
final RedisCache redisCache;
final StoreProductColorMapper prodColorMapper;
final StoreProductColorSizeMapper prodColorSizeMapper;
@ -63,34 +74,8 @@ public class GtAndTyBizController extends BaseController {
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 上传到图搜服务器之后还要确认
}
final EsClientWrapper esClientWrapper;
final FsNotice fsNotice;
/**
* step1
@ -485,8 +470,6 @@ public class GtAndTyBizController extends BaseController {
});
});
// 档口客户优惠
this.storeCusProdDiscMapper.insert(prodCusDiscList);
@ -495,6 +478,88 @@ public class GtAndTyBizController extends BaseController {
return R.ok();
}
/**
* step5
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@PostMapping("/sync-es/{storeId}")
public R<Integer> syncToEs(@PathVariable("storeId") Long storeId) {
// 将公共的商品同步到ES
List<StoreProduct> storeProdList = this.storeProdMapper.selectList(new LambdaQueryWrapper<StoreProduct>()
.eq(StoreProduct::getDelFlag, Constants.UNDELETED).eq(StoreProduct::getStoreId, storeId));
if (CollectionUtils.isEmpty(storeProdList)) {
return R.fail();
}
final List<String> storeProdIdList = storeProdList.stream().map(StoreProduct::getId).map(String::valueOf).collect(Collectors.toList());
// 所有的分类
List<SysProductCategory> prodCateList = this.prodCateMapper.selectList(new LambdaQueryWrapper<SysProductCategory>()
.eq(SysProductCategory::getDelFlag, Constants.UNDELETED));
Map<Long, SysProductCategory> prodCateMap = prodCateList.stream().collect(Collectors.toMap(SysProductCategory::getId, x -> x));
// 获取当前商品最低价格
Map<Long, BigDecimal> prodMinPriceMap = this.prodColorSizeMapper.selectStoreProdMinPriceList(storeProdIdList).stream().collect(Collectors
.toMap(StoreProdMinPriceDTO::getStoreProdId, StoreProdMinPriceDTO::getPrice));
// 档口商品的属性map
Map<Long, StoreProductCategoryAttribute> cateAttrMap = this.prodCateAttrMapper.selectList(new LambdaQueryWrapper<StoreProductCategoryAttribute>()
.eq(StoreProductCategoryAttribute::getDelFlag, Constants.UNDELETED).in(StoreProductCategoryAttribute::getStoreProdId, storeProdIdList))
.stream().collect(Collectors.toMap(StoreProductCategoryAttribute::getStoreProdId, x -> x));
// 档口商品对应的档口
Map<Long, Store> storeMap = this.storeMapper.selectList(new LambdaQueryWrapper<Store>().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<ESProductDTO> 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<BulkOperation> 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("批量新增到 ES 成功的 id列表: {}", response.items().stream().map(BulkResponseItem::id).collect(Collectors.toList()));
// 有哪些没执行成功的,需要发飞书通知
List<String> successIdList = response.items().stream().map(BulkResponseItem::id).collect(Collectors.toList());
List<String> unExeIdList = storeProdIdList.stream().map(String::valueOf).filter(x -> !successIdList.contains(x)).collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(unExeIdList)) {
fsNotice.sendMsg2DefaultChat(storeId + ",批量新增商品到 ES 失败", "以下storeProdId未执行成功: " + unExeIdList);
} else {
fsNotice.sendMsg2DefaultChat(storeId + ",批量新增商品到 ES 成功", "共处理 " + response.items().size() + " 条记录");
}
} catch (Exception e) {
log.error("批量新增到 ES 失败", e);
fsNotice.sendMsg2DefaultChat(storeId + ",批量新增商品到 ES 失败", e.getMessage());
}
return R.ok();
}
/**
*
@ -573,7 +638,7 @@ public class GtAndTyBizController extends BaseController {
// TODO 该处TY 与 FHB处理不同
// TODO 该处TY 与 FHB处理不同
// TODO 该处TY 与 FHB处理不同
tyCusDiscList.forEach(tyCusDisc -> {
tyCusDiscList.stream().filter(x -> x.getDiscount() > 0).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客户优惠 转为步橘系统优惠

View File

@ -11,7 +11,6 @@ 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.gt.GtProdVO;
import com.ruoyi.xkt.mapper.SysProductCategoryMapper;
import com.ruoyi.xkt.service.shipMaster.IShipMasterService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
@ -21,10 +20,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
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;
/**
@ -37,7 +34,6 @@ import java.util.stream.Collectors;
@RequestMapping("/rest/v1/gt")
public class GtController extends BaseController {
final IShipMasterService shipMasterService;
final RedisCache redisCache;
final SysProductCategoryMapper prodCateMapper;

View File

@ -181,7 +181,7 @@ public class TyController extends BaseController {
*/
@PreAuthorize("@ss.hasAnyRoles('admin,general_admin')")
@GetMapping("/error/cus/disc/{userId}")
public R<CusDiscErrorVO> getErrorCusDisc(@PathVariable Integer 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. 有哪些是优惠价大于销售价的
@ -226,11 +226,7 @@ public class TyController extends BaseController {
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));
@ -243,11 +239,7 @@ public class TyController extends BaseController {
});
if (CollectionUtils.isNotEmpty(errorList)) {
throw new ServiceException(errorList.toString(), HttpStatus.ERROR);
}*/
}
}
}

View File

@ -1,9 +0,0 @@
package com.ruoyi.xkt.service.shipMaster;
/**
* @author ruoyi
*/
public interface IShipMasterService {
}

View File

@ -1,17 +0,0 @@
package com.ruoyi.xkt.service.shipMaster.impl;
import com.ruoyi.xkt.service.shipMaster.IShipMasterService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
/**
*
*
* @author ruoyi
*/
@Service
@RequiredArgsConstructor
public class ShipMasterServiceImpl implements IShipMasterService {
}