导入多规格匹配功能新增,数据清醒
This commit is contained in:
parent
69e97f1b28
commit
004a7d6646
@ -72,4 +72,7 @@ public class ShopProductSpecItem implements Serializable {
|
|||||||
@TableField(exist=false)
|
@TableField(exist=false)
|
||||||
private boolean isUpdate;
|
private boolean isUpdate;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "规格名称")
|
||||||
|
@TableField(exist=false)
|
||||||
|
private String specName;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,62 @@
|
|||||||
|
package com.suisung.mall.common.modules.sync;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@NoArgsConstructor
|
||||||
|
@TableName("sycn_store_specs")
|
||||||
|
@ApiModel("多规格数据表,用来执行导入的规格后续操作")
|
||||||
|
public class SyncStoreSpecs {
|
||||||
|
@TableId(value = "sycn_specs_id", type = IdType.AUTO)
|
||||||
|
@ApiModelProperty(value = "多规格编号", required = true, example = "10001")
|
||||||
|
private Long sycnSpecsId;
|
||||||
|
|
||||||
|
@TableField(value = "product_number",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||||
|
@ApiModelProperty(value = "条形码", required = true, example = "10001")
|
||||||
|
private String productNumber;
|
||||||
|
|
||||||
|
@TableField(value = "json_specs",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||||
|
@ApiModelProperty(
|
||||||
|
value = "多规格JSON数据,格式如:[{\"spec\": [{\"name\": \"颜色\",\"value\": \"红色\"},{\"name\": \"尺寸\",\"value\": \"10\"}],\"priceAndstock\": {\"price\": 100,\"stock\": 10}}]",
|
||||||
|
example = "[{\"spec\": [{\"name\": \"颜色\",\"value\": \"红色\"},{\"name\": \"尺寸\",\"value\": \"10\"}],\"priceAndstock\": {\"price\": 100,\"stock\": 10}}]"
|
||||||
|
)
|
||||||
|
private String jsonSpecs;
|
||||||
|
|
||||||
|
@TableField(value = "store_id",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||||
|
@ApiModelProperty(value = "店铺编号", required = true, example = "2001")
|
||||||
|
private Integer storeId;
|
||||||
|
|
||||||
|
@TableField(value = "is_deal",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||||
|
@ApiModelProperty(value = "是否处理完成(1:是, 0:否)", required = true, example = "0")
|
||||||
|
private String isDeal;
|
||||||
|
|
||||||
|
@TableField(value = "created_at",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||||
|
@ApiModelProperty(value = "新建时间", example = "2023-01-01T12:00:00")
|
||||||
|
private Date createdAt;
|
||||||
|
|
||||||
|
@TableField(value = "updated_at",updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||||
|
@ApiModelProperty(value = "更新时间", example = "2023-01-02T14:30:00")
|
||||||
|
private Date updatedAt;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "分类id")
|
||||||
|
@TableField(exist = false)
|
||||||
|
private Integer categoryId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "产品id")
|
||||||
|
@TableField(exist = false)
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "产品itemId")
|
||||||
|
@TableField(exist = false)
|
||||||
|
private Long itemId;
|
||||||
|
}
|
||||||
@ -47,9 +47,10 @@ public class JiebaUtils {
|
|||||||
private static final Pattern UNIT_REGEX = Pattern.compile("\\d+[.]?\\d*[a-zA-Z]+"); // 匹配500ml/1.8L
|
private static final Pattern UNIT_REGEX = Pattern.compile("\\d+[.]?\\d*[a-zA-Z]+"); // 匹配500ml/1.8L
|
||||||
private static final Pattern SPEC_REGEX = Pattern.compile("\\d+[a-zA-Z]+[*]\\d+"); // 匹配500L*10
|
private static final Pattern SPEC_REGEX = Pattern.compile("\\d+[a-zA-Z]+[*]\\d+"); // 匹配500L*10
|
||||||
private static final Pattern MIXED_REGEX = Pattern.compile("[a-zA-Z]+[-]?\\d+"); // 匹配RSCW-1949
|
private static final Pattern MIXED_REGEX = Pattern.compile("[a-zA-Z]+[-]?\\d+"); // 匹配RSCW-1949
|
||||||
private static final Pattern DIMENSION_REGEX = Pattern.compile("\\d+(?:\\\\.\\\\d+)?[\\\\u4e00-\\\\u9fa5a-zA-Z]+"); // 匹配维度(如2.0*2.3)
|
private static final Pattern DIMENSION_REGEX = Pattern.compile("\\d+(?:\\\\.\\\\d+)?[\\u4e00-\\u9fa5a-zA-Z]+"); // 匹配维度(如2.0*2.3)
|
||||||
private static final Pattern UNIT_CHN_REGEX = Pattern.compile("([0-9零一二三四五六七八九十百千万亿]+)(条|个|卷)\\b");//匹配只有数字+单位的,如牛油果2个
|
private static final Pattern UNIT_CHN_REGEX = Pattern.compile("([0-9零一二三四五六七八九十百千万亿]+|\\d*\\.?\\d+)\\s*(g|条|个|卷|kg|L)+\\*\\b");//匹配只有数字+单位的,如牛油果2个
|
||||||
private static final Pattern UNIT_EVERY_REGEX = Pattern.compile("([0-9零一二三四五六七八九十百千万亿]+)([个条份根盒包])(?:\\s*([0-9]+)(g|克|ml|毫升)|\\s*/([袋箱盒份]))");//匹配商品名称+数量+数量单位+重量的 如牛油果2个150克
|
private static final Pattern UNIT_CHN_EVERY_REGEX = Pattern.compile("([0-9零一二三四五六七八九十百千万亿]+|\\d*\\.?\\d+)\\s*(g|条|个|卷|kg|L)+\\s*/([袋箱盒份条])");//匹配只有数字+单位的,如牛油果2个
|
||||||
|
private static final Pattern UNIT_EVERY_REGEX = Pattern.compile("([0-9零一二三四五六七八九十百千万亿]+)([个条份根盒包])(?:\\s*([0-9]+)(g|克|ml|毫升)|\\s*/([袋箱盒份条]))");//匹配商品名称+数量+数量单位+重量的 如牛油果2个150克
|
||||||
//private static final Pattern DIMENSION_REGEX = Pattern.compile("([\\u4e00-\\u9fa5]+)(\\d+\\.?\\d*\\*\\d+\\.?\\d*(?:米)?)([\\u4e00-\\u9fa5]+)");
|
//private static final Pattern DIMENSION_REGEX = Pattern.compile("([\\u4e00-\\u9fa5]+)(\\d+\\.?\\d*\\*\\d+\\.?\\d*(?:米)?)([\\u4e00-\\u9fa5]+)");
|
||||||
private static final Map<String,Pattern> PROTECT_PATTERNS = new HashMap<String,Pattern>(){{
|
private static final Map<String,Pattern> PROTECT_PATTERNS = new HashMap<String,Pattern>(){{
|
||||||
put(PROTECT_UNIT,UNIT_REGEX);
|
put(PROTECT_UNIT,UNIT_REGEX);
|
||||||
@ -65,6 +66,10 @@ public class JiebaUtils {
|
|||||||
put("dot","\\.");
|
put("dot","\\.");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
public static final Set<String> filterWords=Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
|
||||||
|
"袋","/","包","盒","个","箱","*","瓶","条","一级","木盒","特级","二级","条盒","礼盒","三级","整袋","塑料","把","整件"
|
||||||
|
)));
|
||||||
|
|
||||||
|
|
||||||
private static void loadUserDict() {
|
private static void loadUserDict() {
|
||||||
// 方法1:通过文件加载
|
// 方法1:通过文件加载
|
||||||
@ -123,14 +128,30 @@ public class JiebaUtils {
|
|||||||
boolean unit = isUnitShop(text);
|
boolean unit = isUnitShop(text);
|
||||||
if(special&&unit){
|
if(special&&unit){
|
||||||
Matcher matcher = UNIT_EVERY_REGEX.matcher(text);
|
Matcher matcher = UNIT_EVERY_REGEX.matcher(text);
|
||||||
|
String original ="";
|
||||||
|
String original2 ="";
|
||||||
if(matcher.find()) {
|
if(matcher.find()) {
|
||||||
String original = matcher.group();
|
original = matcher.group();
|
||||||
// 使用中文保护标记包裹原始值
|
|
||||||
String protectedText = PROTECT_START + original + PROTECT_END;
|
|
||||||
matcher.appendReplacement(sb, Matcher.quoteReplacement(protectedText));
|
|
||||||
matcher.appendTail(sb);
|
|
||||||
}
|
}
|
||||||
}else if(special){
|
Matcher matcher2 = UNIT_CHN_REGEX.matcher(text);
|
||||||
|
if(matcher2.find()) {
|
||||||
|
original2= matcher2.group();
|
||||||
|
}
|
||||||
|
int originalINdex= text.indexOf(original);
|
||||||
|
int originalINdex2= text.indexOf(original2);
|
||||||
|
if(originalINdex>0&&originalINdex2>0){
|
||||||
|
if(originalINdex<originalINdex2){
|
||||||
|
// 使用中文保护标记包裹原始值
|
||||||
|
String protectedText = PROTECT_START + original+ PROTECT_END;
|
||||||
|
matcher.appendReplacement(sb, Matcher.quoteReplacement(protectedText));
|
||||||
|
matcher.appendTail(sb);
|
||||||
|
}else {
|
||||||
|
String protectedText = PROTECT_START +original2+original + PROTECT_END;
|
||||||
|
matcher2.appendReplacement(sb, Matcher.quoteReplacement(protectedText));
|
||||||
|
matcher2.appendTail(sb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if(special||unit){
|
||||||
Matcher matcher = UNIT_CHN_REGEX.matcher(text);
|
Matcher matcher = UNIT_CHN_REGEX.matcher(text);
|
||||||
if(matcher.find()) {
|
if(matcher.find()) {
|
||||||
String original = matcher.group();
|
String original = matcher.group();
|
||||||
@ -139,7 +160,8 @@ public class JiebaUtils {
|
|||||||
matcher.appendReplacement(sb, Matcher.quoteReplacement(protectedText));
|
matcher.appendReplacement(sb, Matcher.quoteReplacement(protectedText));
|
||||||
matcher.appendTail(sb);
|
matcher.appendTail(sb);
|
||||||
}
|
}
|
||||||
} else {
|
}else {
|
||||||
|
stop:
|
||||||
for (Map.Entry<String, Pattern> entry : PROTECT_PATTERNS.entrySet()) {
|
for (Map.Entry<String, Pattern> entry : PROTECT_PATTERNS.entrySet()) {
|
||||||
Matcher matcher = entry.getValue().matcher(text);
|
Matcher matcher = entry.getValue().matcher(text);
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
@ -148,10 +170,10 @@ public class JiebaUtils {
|
|||||||
String protectedText = PROTECT_START + original + PROTECT_END;
|
String protectedText = PROTECT_START + original + PROTECT_END;
|
||||||
matcher.appendReplacement(sb, Matcher.quoteReplacement(protectedText));
|
matcher.appendReplacement(sb, Matcher.quoteReplacement(protectedText));
|
||||||
matcher.appendTail(sb);
|
matcher.appendTail(sb);
|
||||||
break;
|
break stop;
|
||||||
}
|
}
|
||||||
if (sb.length() > 0) {
|
if (sb.length() > 0) {
|
||||||
break;
|
break stop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,7 +276,7 @@ public class JiebaUtils {
|
|||||||
JiebaSegmenter segmenter = new JiebaSegmenter();
|
JiebaSegmenter segmenter = new JiebaSegmenter();
|
||||||
loadUserDict();
|
loadUserDict();
|
||||||
String protectedText = protectPatterns(text);
|
String protectedText = protectPatterns(text);
|
||||||
System.out.println("protectedText: " + protectedText);
|
log.info("protectedText: {}", protectedText);
|
||||||
List<String> tokens = segmenter.sentenceProcess(protectedText).stream()
|
List<String> tokens = segmenter.sentenceProcess(protectedText).stream()
|
||||||
//.filter(word -> word.length() > 1) // 过滤单字
|
//.filter(word -> word.length() > 1) // 过滤单字
|
||||||
// .sorted(Comparator.reverseOrder()) // 按词典词频降序
|
// .sorted(Comparator.reverseOrder()) // 按词典词频降序
|
||||||
@ -285,7 +307,13 @@ public class JiebaUtils {
|
|||||||
} else if (CATEGORY_LIBRARY.contains(word)) {
|
} else if (CATEGORY_LIBRARY.contains(word)) {
|
||||||
fields.putIfAbsent("category", word);
|
fields.putIfAbsent("category", word);
|
||||||
} else if (startsWithDigit(word)) {
|
} else if (startsWithDigit(word)) {
|
||||||
fields.putIfAbsent("specs", word.toLowerCase());
|
for (String unit:UNITS){
|
||||||
|
if (word.contains(unit)) {
|
||||||
|
fields.putIfAbsent("specs", word);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//fields.putIfAbsent("specs", word.toLowerCase());
|
||||||
}else if(SPECIAL_NAME.contains(word)){
|
}else if(SPECIAL_NAME.contains(word)){
|
||||||
fields.putIfAbsent("productShortName", word);
|
fields.putIfAbsent("productShortName", word);
|
||||||
}else {
|
}else {
|
||||||
@ -311,12 +339,12 @@ public class JiebaUtils {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
if(words.size()>1){
|
if(words.size()>1){
|
||||||
int index=words.size()-1;
|
// int index=words.size()-1;
|
||||||
if(!startsWithLetterOrDigitRegex(words.get(index))){
|
// if(!startsWithLetterOrDigitRegex(words.get(index))){
|
||||||
fields.putIfAbsent("productShortName", words.get(index));
|
fields.putIfAbsent("productShortName", machProductName(words,fields.get("brand")));
|
||||||
}else {
|
// }else {
|
||||||
fields.putIfAbsent("productShortName", words.get(index-1));
|
// fields.putIfAbsent("productShortName", words.get(index-1));
|
||||||
}
|
// }
|
||||||
}else {
|
}else {
|
||||||
fields.putIfAbsent("productShortName", words.get(0));
|
fields.putIfAbsent("productShortName", words.get(0));
|
||||||
}
|
}
|
||||||
@ -324,6 +352,31 @@ public class JiebaUtils {
|
|||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 倒叙匹查询配商品名称
|
||||||
|
* @param words
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String machProductName(List<String> words,String brand){
|
||||||
|
int index=words.size()-1;
|
||||||
|
String productName=words.get(index);
|
||||||
|
while (index>-1){
|
||||||
|
productName = words.get(index);
|
||||||
|
if(productName.length()<2){
|
||||||
|
index--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(startsWithLetterOrDigitRegex(productName)||containsFilterWord(productName)||containsNumberLoop(productName)
|
||||||
|
||(StringUtils.isNotEmpty(brand)&&productName.contains(brand))){
|
||||||
|
index--;
|
||||||
|
}else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return productName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 特色字段匹配
|
* 特色字段匹配
|
||||||
* @return
|
* @return
|
||||||
@ -396,18 +449,50 @@ public class JiebaUtils {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否包含数字
|
||||||
|
* @param input
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean containsNumberLoop(String input) {
|
||||||
|
for (char c : input.toCharArray()) {
|
||||||
|
if (Character.isDigit(c)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断过滤词
|
||||||
|
* @param input
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean containsFilterWord(String input) {
|
||||||
|
for (String word : filterWords) {
|
||||||
|
if ("\\*".equals(word)) {
|
||||||
|
if (input.contains("*")) return true;
|
||||||
|
}
|
||||||
|
if (input.contains(word)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// JiebaUtils jiebaUtils = new JiebaUtils();
|
// JiebaUtils jiebaUtils = new JiebaUtils();
|
||||||
String text = "云计算和区块链是热门技术";
|
String text = "四海油彩米10Kg";
|
||||||
// String text = "新鲜牛肉饺子500g";
|
// String text = "新鲜牛肉饺子500g";
|
||||||
//String text = "志高1.8L电热水壶";
|
//String text = "志高1.8L电热水壶";
|
||||||
// String text = "(单充)数据线2m";
|
// String text = "(单充)数据线2m";
|
||||||
// String text = "雅安利2.0*2.3四件套";
|
// String text = "雅安利2.0*2.3四件套";
|
||||||
// String text = "RSCW-1949剃须刀";
|
// String text = "RSCW-1949剃须刀";
|
||||||
System.out.println(cleanNumberAndDigit("日本豆腐3条"));
|
// System.out.println(cleanNumberAndDigit("双汇王中王火腿肠400G10*40g/包"));
|
||||||
//String text="六指鼠童袜001";
|
//String text="六指鼠童袜001";
|
||||||
List<String> words = JiebaUtils.extractKeywords(text);
|
// List<String> words = JiebaUtils.extractKeywords(text);
|
||||||
System.out.println(words);
|
//System.out.println(words);
|
||||||
|
|
||||||
Map<String,String> shopMap= JiebaUtils.getShopDetails(ProductTitleUtil.cleanTitle2(text));
|
Map<String,String> shopMap= JiebaUtils.getShopDetails(ProductTitleUtil.cleanTitle2(text));
|
||||||
System.out.println(shopMap);
|
System.out.println(shopMap);
|
||||||
|
|||||||
@ -53,14 +53,17 @@ public class ProductTitleUtil {
|
|||||||
Arrays.asList("华为", "苹果", "小米", "三星", "美的", "格力", "耐克", "阿迪达斯", "海尔","雀巢","伊利","蒙牛","达能","乐事","多力多滋","三只松鼠","良品铺子","可口可乐",
|
Arrays.asList("华为", "苹果", "小米", "三星", "美的", "格力", "耐克", "阿迪达斯", "海尔","雀巢","伊利","蒙牛","达能","乐事","多力多滋","三只松鼠","良品铺子","可口可乐",
|
||||||
"农夫山泉","元气森林","红牛","雅诗兰黛","欧莱雅","玉兰油","科颜氏","宝洁","汰渍","帮宝适","联合利华","Unilever","含多芬","清扬","大窑","谢村桥牌阡糯","谢村桥牌阡",
|
"农夫山泉","元气森林","红牛","雅诗兰黛","欧莱雅","玉兰油","科颜氏","宝洁","汰渍","帮宝适","联合利华","Unilever","含多芬","清扬","大窑","谢村桥牌阡糯","谢村桥牌阡",
|
||||||
"六个核桃","大豫竹","优乐多","安慕希","纳爱斯","舒客","宜轩", "蓝月亮","海尔","美的","松下","戴森","耐克","安踏","李宁","特仑苏","纯甄","安井","三全","哇哈哈",
|
"六个核桃","大豫竹","优乐多","安慕希","纳爱斯","舒客","宜轩", "蓝月亮","海尔","美的","松下","戴森","耐克","安踏","李宁","特仑苏","纯甄","安井","三全","哇哈哈",
|
||||||
"龙江家园","达利园","春光","妙芙","南星","利嘉旺","卡得福","泓一","爱乡亲","思念","得力","中雪","江南点心局","德庄","六指鼠",
|
"龙江家园","达利园","春光","妙芙","南星","利嘉旺","卡得福","泓一","爱乡亲","思念","得力","中雪","江南点心局","德庄","六指鼠","娃哈哈","开古","不二家","湘亮牌",
|
||||||
"依水塬","乌苏啤酒","阿尔卑斯", "瑞旗","振雷","中狗","宝视达","冷酸灵","骆驼","NIKE","PAMU","康师傅","信智利","双兔","安足莱","新博美","新博","创利")
|
"依水塬","乌苏啤酒","阿尔卑斯", "瑞旗","振雷","中狗","宝视达","冷酸灵","骆驼","NIKE","PAMU","康师傅","信智利","双兔","安足莱","新博美","湘亮牌","忆江南","张骞牌",
|
||||||
|
"新博","创利","哈奇利","好口福","银鹭","开古","百事可乐","邛池","天旭牌","泗泉山","银狼","象芽王","拜将坛","健民","湘亮牌","周大黑","盛华牌","盛华","碗碗香","龙凤王",
|
||||||
|
"陕南健源","百州红","八度名苑","旭美","今麦郞","勇闯天涯","青岛","一起赢","元気森林","云南红茶","盈亮","树堂","乡糯香","汉中魏","金源","疆丝麦耘","四海油","亿家康",
|
||||||
|
"利民")
|
||||||
));
|
));
|
||||||
/**
|
/**
|
||||||
* 品类词库(初始化后不可变)
|
* 品类词库(初始化后不可变)
|
||||||
*/
|
*/
|
||||||
public static final Set<String> CATEGORY_LIBRARY = Collections.unmodifiableSet(new HashSet<>(
|
public static final Set<String> CATEGORY_LIBRARY = Collections.unmodifiableSet(new HashSet<>(
|
||||||
Arrays.asList("手机", "电脑", "空调", "冰箱", "运动鞋", "T恤", "洗发水", "洗衣液","猪脚")
|
Arrays.asList("手机", "电脑", "空调", "冰箱", "运动鞋", "T恤", "洗发水", "洗衣液","猪脚","花生牛奶")
|
||||||
));
|
));
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -88,7 +91,8 @@ public class ProductTitleUtil {
|
|||||||
|
|
||||||
//特殊商品
|
//特殊商品
|
||||||
public static final Set<String> SPECIAL_NAME = Collections.unmodifiableSet(new HashSet<>(
|
public static final Set<String> SPECIAL_NAME = Collections.unmodifiableSet(new HashSet<>(
|
||||||
Arrays.asList("水饺", "面条", "包子","卷纸","卫生纸","紫菜汤","猪肉包","叉烧包","香菇青菜包","面包","黑米")
|
Arrays.asList("水饺", "面条", "包子","卷纸","卫生纸","紫菜汤","猪肉包","叉烧包","香菇青菜包","面包","黑米","棒棒糖","梳子","谢村花雕","古秦洋精","通裕梨花",
|
||||||
|
"台式烤香肠")
|
||||||
));
|
));
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@ -104,8 +108,9 @@ public class ProductTitleUtil {
|
|||||||
Arrays.asList("个","条","份","盒","份","袋")
|
Arrays.asList("个","条","份","盒","份","袋")
|
||||||
));
|
));
|
||||||
public static final Set<String> UNITS = Collections.unmodifiableSet(new HashSet<>(
|
public static final Set<String> UNITS = Collections.unmodifiableSet(new HashSet<>(
|
||||||
Arrays.asList("g","克","kg","千克","ml","毫升","l","升","cm","厘米","mm","毫米","份","盒","份","袋")
|
Arrays.asList("g","克","kg","千克","ml","毫升","l","升","cm","厘米","mm","毫米","份","盒","份","袋","L")
|
||||||
));
|
));
|
||||||
|
|
||||||
private ProductTitleUtil() {
|
private ProductTitleUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,3 +34,105 @@ PAMU 500 n
|
|||||||
香菇青菜包 500 n
|
香菇青菜包 500 n
|
||||||
老鸭汤炖料 500 n
|
老鸭汤炖料 500 n
|
||||||
六指鼠 500 n
|
六指鼠 500 n
|
||||||
|
花生牛奶 500 n
|
||||||
|
碧螺春 500 n
|
||||||
|
红薯仔 500 n
|
||||||
|
棒棒糖 500 n
|
||||||
|
哈密瓜桃味 500 n
|
||||||
|
益生菌 500 n
|
||||||
|
茉莉花茶 500 n
|
||||||
|
棉花糖 500 n
|
||||||
|
照相机 500 n
|
||||||
|
涂鸦画 500 n
|
||||||
|
火腿肠 500 n
|
||||||
|
苏打水 500 n
|
||||||
|
薏米粥 500 n
|
||||||
|
好口福 500 n
|
||||||
|
面条 500 n
|
||||||
|
红豆花生奶 500 n
|
||||||
|
绣花被 500 n
|
||||||
|
黄山小毛峰 500 n
|
||||||
|
宜兴毛尖 500 n
|
||||||
|
龙井八宝茶 500 n
|
||||||
|
忆江南 500 n
|
||||||
|
山楂知己茶 500 n
|
||||||
|
枸杞茶 500 n
|
||||||
|
菊花茶 500 n
|
||||||
|
铁观音 500 n
|
||||||
|
汉中绿茶 500 n
|
||||||
|
汉中炒青 500 n
|
||||||
|
西乡毛尖 500 n
|
||||||
|
西乡特炒 500 n
|
||||||
|
西乡炒青 500 n
|
||||||
|
汉中特炒 500 n
|
||||||
|
汉中仙毫 500 n
|
||||||
|
百事可乐 500 n
|
||||||
|
胚芽茶 500 n
|
||||||
|
黑苦荞 500 n
|
||||||
|
茉莉银毫 500 n
|
||||||
|
茉莉花茶 500 n
|
||||||
|
茉莉毛尖 500 n
|
||||||
|
苦荞茶 500 n
|
||||||
|
云雾绿茶 500 n
|
||||||
|
黄山毛尖 500 n
|
||||||
|
汉中仙毫 500 n
|
||||||
|
拜将坛 500 n
|
||||||
|
汉中功夫红茶 500 n
|
||||||
|
汉中毛尖 500 n
|
||||||
|
云雾毛尖茶 500 n
|
||||||
|
信阳毛尖 500 n
|
||||||
|
雨前毛尖茶 500 n
|
||||||
|
雨前毛尖 500 n
|
||||||
|
速溶饮料 500 n
|
||||||
|
水蜜桃味 500 n
|
||||||
|
枣味茶 500 n
|
||||||
|
果味茶 500 n
|
||||||
|
黑米茶青柑茶 500 n
|
||||||
|
毛尖茶 500 n
|
||||||
|
冻干柠檬 500 n
|
||||||
|
汉中仙毫 500 n
|
||||||
|
云南滇红 500 n
|
||||||
|
决明子 500 n
|
||||||
|
清热下火茶 500 n
|
||||||
|
柠檬干 500 n
|
||||||
|
汉中大米 500 n
|
||||||
|
面皮粉 500 n
|
||||||
|
压榨油 500 n
|
||||||
|
百州红 500 n
|
||||||
|
八度名苑 500 n
|
||||||
|
苦荞 500 n
|
||||||
|
牛肉卷 500 n
|
||||||
|
迷尔山楂 500 n
|
||||||
|
九制梅肉 500 n
|
||||||
|
白馒头 500 n
|
||||||
|
山楂片茶 500 n
|
||||||
|
汉中红茶 500 n
|
||||||
|
电热锅 500 n
|
||||||
|
玫瑰花茶 500 n
|
||||||
|
冰糖雪梨 500 n
|
||||||
|
今麦郞 500 n
|
||||||
|
乌龙茶 500 n
|
||||||
|
雪花啤酒 500 n
|
||||||
|
勇闯天涯 500 n
|
||||||
|
谢村花雕 500 n
|
||||||
|
古秦洋酒 500 n
|
||||||
|
汉斯啤酒 500 n
|
||||||
|
北京二锅头 500 n
|
||||||
|
一起赢 500 n
|
||||||
|
古秦洋精 500 n
|
||||||
|
桃花浪漫 500 n
|
||||||
|
台式烤香肠 500 n
|
||||||
|
孜然散 500 n
|
||||||
|
香甜王 500 n
|
||||||
|
元気森林 500 n
|
||||||
|
苏打气泡水 500 n
|
||||||
|
云南红茶 500 n
|
||||||
|
碗碗香 500 n
|
||||||
|
丝苗香米 500 n
|
||||||
|
压榨菜籽油 500 n
|
||||||
|
乡糯香 500 n
|
||||||
|
鸡蛋面片 500 n
|
||||||
|
疆丝麦耘 500 n
|
||||||
|
亿家康 500 n
|
||||||
|
汉中香米 500 n
|
||||||
|
菜籽油 500 n
|
||||||
@ -284,13 +284,16 @@ public class EsProductImageServiceImpl implements EsProductImageService {
|
|||||||
|
|
||||||
// 2. 为每个关键词构建查询
|
// 2. 为每个关键词构建查询
|
||||||
for (String keyword : keywords) {
|
for (String keyword : keywords) {
|
||||||
String cleanKeyword = ProductTitleUtil.cleanTitle2(keyword);
|
//keyword=keyword.split(" ")[0];
|
||||||
|
String cleanKeyword= ProductTitleUtil.cleanTitle2(keyword);
|
||||||
|
// String[] cleanKeywords = cleanWord.split(" ");
|
||||||
|
// String cleanKeyword=cleanKeywords[0];
|
||||||
keywordToCleanMap.put(cleanKeyword, keyword); // 保留原始关键词映射
|
keywordToCleanMap.put(cleanKeyword, keyword); // 保留原始关键词映射
|
||||||
|
|
||||||
// 构建组合查询
|
// 构建组合查询
|
||||||
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
|
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
|
||||||
//.should(QueryBuilders.matchQuery("barcode", cleanKeyword).boost(1.0f))
|
//.should(QueryBuilders.matchQuery("barcode", cleanKeyword).boost(1.0f))
|
||||||
.should(QueryBuilders.matchQuery("productName", JiebaUtils.cleanNumberAndDigit(cleanKeyword)).boost(1.0f))
|
.should(QueryBuilders.matchQuery("productName", JiebaUtils.cleanNumberAndDigit(keyword)).boost(1.0f))
|
||||||
.should(QueryBuilders.fuzzyQuery("cleanName.keyword", JiebaUtils.cleanNumberAndDigit(cleanKeyword))
|
.should(QueryBuilders.fuzzyQuery("cleanName.keyword", JiebaUtils.cleanNumberAndDigit(cleanKeyword))
|
||||||
.fuzziness(Fuzziness.ONE)
|
.fuzziness(Fuzziness.ONE)
|
||||||
.maxExpansions(20)
|
.maxExpansions(20)
|
||||||
@ -314,7 +317,6 @@ public class EsProductImageServiceImpl implements EsProductImageService {
|
|||||||
.boost(0.5f));
|
.boost(0.5f));
|
||||||
count+=1;
|
count+=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(StringUtil.isNotEmpty(shopDetailMap.get("specs"))){
|
if(StringUtil.isNotEmpty(shopDetailMap.get("specs"))){
|
||||||
boolQuery.should(QueryBuilders.fuzzyQuery("specs.keyword", shopDetailMap.get("specs")) // 模糊查询权重
|
boolQuery.should(QueryBuilders.fuzzyQuery("specs.keyword", shopDetailMap.get("specs")) // 模糊查询权重
|
||||||
.fuzziness(Fuzziness.TWO) // 自动确定模糊度
|
.fuzziness(Fuzziness.TWO) // 自动确定模糊度
|
||||||
|
|||||||
@ -33,4 +33,8 @@ public interface ShopNumberSeqService extends IBaseService<ShopNumberSeq> {
|
|||||||
List<Integer> getBatchUserAccountBaseId(int batchSize);
|
List<Integer> getBatchUserAccountBaseId(int batchSize);
|
||||||
|
|
||||||
void clearKeyStoreAccountBaseId();
|
void clearKeyStoreAccountBaseId();
|
||||||
|
|
||||||
|
List<Integer> getBatchSpecId(int batchSize);
|
||||||
|
|
||||||
|
void clearKeyStoreSepcId();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,10 +3,12 @@ package com.suisung.mall.shop.number.service.impl;
|
|||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.suisung.mall.common.feignService.AccountService;
|
import com.suisung.mall.common.feignService.AccountService;
|
||||||
|
import com.suisung.mall.common.modules.base.ShopBaseProductSpec;
|
||||||
import com.suisung.mall.common.modules.number.ShopNumberSeq;
|
import com.suisung.mall.common.modules.number.ShopNumberSeq;
|
||||||
import com.suisung.mall.common.modules.product.ShopProductSpecItem;
|
import com.suisung.mall.common.modules.product.ShopProductSpecItem;
|
||||||
import com.suisung.mall.core.web.service.RedisService;
|
import com.suisung.mall.core.web.service.RedisService;
|
||||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||||
|
import com.suisung.mall.shop.base.service.ShopBaseProductSpecService;
|
||||||
import com.suisung.mall.shop.number.mapper.ShopNumberSeqMapper;
|
import com.suisung.mall.shop.number.mapper.ShopNumberSeqMapper;
|
||||||
import com.suisung.mall.shop.number.service.ShopNumberSeqService;
|
import com.suisung.mall.shop.number.service.ShopNumberSeqService;
|
||||||
import com.suisung.mall.shop.product.service.ShopProductSpecItemService;
|
import com.suisung.mall.shop.product.service.ShopProductSpecItemService;
|
||||||
@ -45,6 +47,9 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ShopProductSpecItemService shopProductSpecItemService;
|
private ShopProductSpecItemService shopProductSpecItemService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ShopBaseProductSpecService shopBaseProductSpecService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AccountService accountService;
|
private AccountService accountService;
|
||||||
|
|
||||||
@ -208,7 +213,9 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
|||||||
redisService.del(RedisKey.STOREDATACCOUNTBASEID);
|
redisService.del(RedisKey.STOREDATACCOUNTBASEID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearKeyStoreSepcId(){
|
||||||
|
redisService.del(RedisKey.STOREDATASPECID);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除缓存,专门给并发使用,防止redis的缓存没有加载
|
* 清除缓存,专门给并发使用,防止redis的缓存没有加载
|
||||||
@ -244,6 +251,33 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
|||||||
edit(seq);
|
edit(seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存的是最大值,取的是范围,如存最大值1,批量是2,则取范围【1+1,1+2】,如果没有则从1开始算即取范围[0+1,0+2]
|
||||||
|
* @param batchSize
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized List<Integer> getBatchSpecId(int batchSize) {
|
||||||
|
int start=0;
|
||||||
|
if(null!=redisService.get(RedisKey.STOREDATASPECID)){
|
||||||
|
start=(Integer) redisService.get(RedisKey.STOREDATASPECID);
|
||||||
|
redisService.set(RedisKey.STOREDATASPECID,start+batchSize);
|
||||||
|
return IntStream.rangeClosed(start+1, start+batchSize).boxed().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
QueryWrapper<ShopBaseProductSpec> queryWrapper= new QueryWrapper<>();
|
||||||
|
queryWrapper.select("max(spec_id) as spec_id");
|
||||||
|
ShopBaseProductSpec shopBaseProductSpec=shopBaseProductSpecService.getOne(queryWrapper);
|
||||||
|
if(null!=shopBaseProductSpec){
|
||||||
|
start=shopBaseProductSpec.getSpec_id();
|
||||||
|
redisService.set(RedisKey.STOREDATASPECID,start+batchSize);
|
||||||
|
}
|
||||||
|
if(start==0){
|
||||||
|
redisService.set(RedisKey.STOREDATASPECID,start+batchSize);
|
||||||
|
return IntStream.rangeClosed(start+1, start+batchSize).boxed().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
return IntStream.rangeClosed(start+1, start+batchSize).boxed().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 存的是最大值,取的是范围,如存最大值1,批量是2,则取范围【1+1,1+2】,如果没有则从1开始算即取范围[0+1,0+2]
|
* 存的是最大值,取的是范围,如存最大值1,批量是2,则取范围【1+1,1+2】,如果没有则从1开始算即取范围[0+1,0+2]
|
||||||
* @param batchSize
|
* @param batchSize
|
||||||
@ -272,6 +306,7 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 存的是最大值,取的是范围,如存最大值1,批量是2,则取范围【1+1,1+2】,如果没有则从1开始算即取范围[0+1,0+2]
|
* 存的是最大值,取的是范围,如存最大值1,批量是2,则取范围【1+1,1+2】,如果没有则从1开始算即取范围[0+1,0+2]
|
||||||
* @param batchSize
|
* @param batchSize
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import com.suisung.mall.common.modules.page.ShopPageApp;
|
|||||||
import com.suisung.mall.common.modules.store.ShopStoreInfo;
|
import com.suisung.mall.common.modules.store.ShopStoreInfo;
|
||||||
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
||||||
import com.suisung.mall.common.utils.CheckUtil;
|
import com.suisung.mall.common.utils.CheckUtil;
|
||||||
|
import com.suisung.mall.common.utils.ContextUtil;
|
||||||
import com.suisung.mall.common.utils.I18nUtil;
|
import com.suisung.mall.common.utils.I18nUtil;
|
||||||
import com.suisung.mall.core.web.service.CloundService;
|
import com.suisung.mall.core.web.service.CloundService;
|
||||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||||
@ -71,7 +72,7 @@ public class ShopPageAppController extends BaseControllerImpl {
|
|||||||
@RequestParam(name = "pageSize", defaultValue = "100") Integer pageSize) {
|
@RequestParam(name = "pageSize", defaultValue = "100") Integer pageSize) {
|
||||||
|
|
||||||
Map<String, Object> data = new HashMap<>();
|
Map<String, Object> data = new HashMap<>();
|
||||||
UserDto user = getCurrentUser();
|
UserDto user = ContextUtil.getCurrentUser();
|
||||||
|
|
||||||
//读取模板
|
//读取模板
|
||||||
Map data_arr = null;
|
Map data_arr = null;
|
||||||
@ -198,7 +199,7 @@ public class ShopPageAppController extends BaseControllerImpl {
|
|||||||
@RequestParam(name = "app_page_list") String app_page_list,
|
@RequestParam(name = "app_page_list") String app_page_list,
|
||||||
@RequestParam(name = "page_config", defaultValue = "{}") String page_config,
|
@RequestParam(name = "page_config", defaultValue = "{}") String page_config,
|
||||||
@RequestParam(name = "app_member_center", defaultValue = "{}") String app_member_center) {
|
@RequestParam(name = "app_member_center", defaultValue = "{}") String app_member_center) {
|
||||||
UserDto user = getCurrentUser();
|
UserDto user = ContextUtil.getCurrentUser();
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new ApiUserException(I18nUtil._("用户信息异常!"));
|
throw new ApiUserException(I18nUtil._("用户信息异常!"));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import com.suisung.mall.common.modules.page.ShopPageBase;
|
|||||||
import com.suisung.mall.common.modules.product.ShopPageUserForm;
|
import com.suisung.mall.common.modules.product.ShopPageUserForm;
|
||||||
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
||||||
import com.suisung.mall.common.utils.CheckUtil;
|
import com.suisung.mall.common.utils.CheckUtil;
|
||||||
|
import com.suisung.mall.common.utils.ContextUtil;
|
||||||
import com.suisung.mall.common.utils.I18nUtil;
|
import com.suisung.mall.common.utils.I18nUtil;
|
||||||
import com.suisung.mall.core.web.CommonRes;
|
import com.suisung.mall.core.web.CommonRes;
|
||||||
import com.suisung.mall.shop.page.dto.PageBaseListReq;
|
import com.suisung.mall.shop.page.dto.PageBaseListReq;
|
||||||
@ -151,7 +152,7 @@ public class ShopPageBaseController extends BaseControllerImpl {
|
|||||||
@RequestMapping(value = "/remove", method = RequestMethod.POST)
|
@RequestMapping(value = "/remove", method = RequestMethod.POST)
|
||||||
public CommonResult remove(@RequestParam(name = "page_id") Long page_id) {
|
public CommonResult remove(@RequestParam(name = "page_id") Long page_id) {
|
||||||
try {
|
try {
|
||||||
UserDto user = getCurrentUser();
|
UserDto user = ContextUtil.getCurrentUser();
|
||||||
|
|
||||||
// 用户未登录,禁止操作
|
// 用户未登录,禁止操作
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
@ -250,7 +251,7 @@ public class ShopPageBaseController extends BaseControllerImpl {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UserDto user = getCurrentUser();
|
UserDto user = ContextUtil.getCurrentUser();
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new ApiUserException(I18nUtil._("用户信息异常!"));
|
throw new ApiUserException(I18nUtil._("用户信息异常!"));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import lombok.Data;
|
|||||||
public class BrandModelExcel{
|
public class BrandModelExcel{
|
||||||
public static final String TEMPLATE_NAME = "品牌导入模板.xlsx";
|
public static final String TEMPLATE_NAME = "品牌导入模板.xlsx";
|
||||||
@ApiModelProperty("品牌名称")
|
@ApiModelProperty("品牌名称")
|
||||||
@ExcelProperty(value = "商品名称", index = 0)
|
@ExcelProperty(value = "品牌名称", index = 0)
|
||||||
private String brand_name;
|
private String brand_name;
|
||||||
|
|
||||||
@ApiModelProperty("品牌描述")
|
@ApiModelProperty("品牌描述")
|
||||||
|
|||||||
@ -62,5 +62,12 @@ public class SxGoosModelExcel {
|
|||||||
@ExcelProperty(value = "品牌名称", index = 8)
|
@ExcelProperty(value = "品牌名称", index = 8)
|
||||||
private String brand_name;
|
private String brand_name;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "多规格参数,[规格名称:规格值]",example = "[颜色:白色][尺码:28][价格:]")
|
||||||
|
@ExcelProperty(value = "多规格参数", index = 9)
|
||||||
|
private String shop_specs;
|
||||||
|
|
||||||
|
@ExcelProperty(value = "多规格json数据", index = 9)
|
||||||
|
@ExcelIgnore
|
||||||
|
private String jsonSpecs;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,188 @@
|
|||||||
|
package com.suisung.mall.shop.sync.keymanage;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class ProductSpecManager {
|
||||||
|
// 定义商品规格项
|
||||||
|
public static class SpecItem {
|
||||||
|
private String name;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public SpecItem() {}
|
||||||
|
|
||||||
|
public SpecItem(String name, String value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters and Setters
|
||||||
|
public String getName() { return name; }
|
||||||
|
public void setName(String name) { this.name = name; }
|
||||||
|
public String getValue() { return value; }
|
||||||
|
public void setValue(String value) { this.value = value; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name + ": " + value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义价格库存项
|
||||||
|
public static class PriceStockItem {
|
||||||
|
private BigDecimal price;
|
||||||
|
private BigDecimal stock;
|
||||||
|
|
||||||
|
public PriceStockItem() {}
|
||||||
|
|
||||||
|
public PriceStockItem(BigDecimal price, BigDecimal stock) {
|
||||||
|
this.price = price;
|
||||||
|
this.stock = stock;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters and Setters
|
||||||
|
public BigDecimal getPrice() { return price; }
|
||||||
|
public void setPrice(BigDecimal price) { this.price = price; }
|
||||||
|
public BigDecimal getStock() { return stock; }
|
||||||
|
public void setStock(BigDecimal stock) { this.stock = stock; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("¥%.2f (%d件)", price, stock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义完整的商品规格信息
|
||||||
|
public static class ProductSpecInfo {
|
||||||
|
private List<SpecItem> spec;
|
||||||
|
private PriceStockItem priceAndstock;
|
||||||
|
|
||||||
|
public ProductSpecInfo() {
|
||||||
|
this.spec = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters and Setters
|
||||||
|
public List<SpecItem> getSpec() { return spec; }
|
||||||
|
public void setSpec(List<SpecItem> spec) { this.spec = spec; }
|
||||||
|
public PriceStockItem getPriceAndstock() { return priceAndstock; }
|
||||||
|
public void setPriceAndstock(PriceStockItem priceAndstock) {
|
||||||
|
this.priceAndstock = priceAndstock;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 商品规格映射表:商品ID -> JSON字符串
|
||||||
|
private Map<String, List<String>> specsMap;
|
||||||
|
private static Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
|
public Map<String, List<String>> getSpecsMap() {
|
||||||
|
return specsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpecsMap(Map<String, List<String>> specsMap) {
|
||||||
|
this.specsMap = specsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加商品规格
|
||||||
|
*
|
||||||
|
* @param productId 商品ID
|
||||||
|
* @param specItems 规格项列表
|
||||||
|
* @param price 价格
|
||||||
|
* @param stock 库存
|
||||||
|
*/
|
||||||
|
public void addProductSpec(String productId, List<SpecItem> specItems,
|
||||||
|
BigDecimal price, BigDecimal stock) {
|
||||||
|
// 创建价格库存项
|
||||||
|
PriceStockItem priceStockItem = new PriceStockItem(price, stock);
|
||||||
|
|
||||||
|
// 创建商品规格信息
|
||||||
|
ProductSpecInfo specInfo = new ProductSpecInfo();
|
||||||
|
specInfo.setSpec(specItems);
|
||||||
|
specInfo.setPriceAndstock(priceStockItem);
|
||||||
|
|
||||||
|
// 转换为JSON字符串
|
||||||
|
String json = gson.toJson(specInfo);
|
||||||
|
|
||||||
|
// 添加到Map
|
||||||
|
if (!specsMap.containsKey(productId)) {
|
||||||
|
specsMap.put(productId, new ArrayList<>());
|
||||||
|
}
|
||||||
|
specsMap.get(productId).add(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取商品所有规格信息
|
||||||
|
*
|
||||||
|
* @param productId 商品ID
|
||||||
|
* @return 商品规格信息列表
|
||||||
|
*/
|
||||||
|
public String getProductSpecsString(String productId) {
|
||||||
|
if (!specsMap.containsKey(productId)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return gson.toJson(specsMap.get(productId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取商品所有规格信息
|
||||||
|
*
|
||||||
|
* @param productId 商品ID
|
||||||
|
* @return 商品规格信息列表
|
||||||
|
*/
|
||||||
|
public List<String> getSepcMapValue(String productId) {
|
||||||
|
if (!specsMap.containsKey(productId)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return specsMap.get(productId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取商品所有规格信息
|
||||||
|
*
|
||||||
|
* @param productId 商品ID
|
||||||
|
* @return 商品规格信息列表
|
||||||
|
*/
|
||||||
|
public List<ProductSpecInfo> getProductSpecs(String productId) {
|
||||||
|
if (!specsMap.containsKey(productId)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ProductSpecInfo> result = new ArrayList<>();
|
||||||
|
for (String json : specsMap.get(productId)) {
|
||||||
|
ProductSpecInfo info = gson.fromJson(json, ProductSpecInfo.class);
|
||||||
|
result.add(info);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析规格字符串为SpecItem列表
|
||||||
|
*
|
||||||
|
* @param specStr 规格字符串,格式如"[颜色:黑色][尺寸:30]"
|
||||||
|
* @return SpecItem列表
|
||||||
|
*/
|
||||||
|
public List<SpecItem> parseSpecString(String specStr) {
|
||||||
|
List<SpecItem> specItems = new ArrayList<>();
|
||||||
|
|
||||||
|
// 正则表达式匹配格式:[key:value]
|
||||||
|
Pattern pattern = Pattern.compile("\\[(.*?):(.*?)\\]");
|
||||||
|
Matcher matcher = pattern.matcher(specStr);
|
||||||
|
|
||||||
|
while (matcher.find()) {
|
||||||
|
if (matcher.groupCount() == 2) {
|
||||||
|
String name = matcher.group(1).trim();
|
||||||
|
String value = matcher.group(2).trim();
|
||||||
|
specItems.add(new SpecItem(name, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return specItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -20,4 +20,7 @@ public class RedisKey {
|
|||||||
|
|
||||||
|
|
||||||
public static final String STOREDATACCOUNTBASEID="storedata:accountBaseId";
|
public static final String STOREDATACCOUNTBASEID="storedata:accountBaseId";
|
||||||
|
|
||||||
|
|
||||||
|
public static final String STOREDATASPECID="storedata:SpecId";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,10 +4,15 @@ import cn.hutool.core.util.ObjectUtil;
|
|||||||
import cn.hutool.json.JSONArray;
|
import cn.hutool.json.JSONArray;
|
||||||
import com.alibaba.excel.context.AnalysisContext;
|
import com.alibaba.excel.context.AnalysisContext;
|
||||||
import com.alibaba.excel.event.AnalysisEventListener;
|
import com.alibaba.excel.event.AnalysisEventListener;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import com.suisung.mall.common.enums.DicEnum;
|
||||||
|
import com.suisung.mall.common.modules.sync.SyncStoreSpecs;
|
||||||
import com.suisung.mall.common.utils.CommonUtil;
|
import com.suisung.mall.common.utils.CommonUtil;
|
||||||
import com.suisung.mall.common.utils.StringUtils;
|
import com.suisung.mall.common.utils.StringUtils;
|
||||||
import com.suisung.mall.shop.sync.exelModel.SxGoosModelExcel;
|
import com.suisung.mall.shop.sync.exelModel.SxGoosModelExcel;
|
||||||
|
import com.suisung.mall.shop.sync.keymanage.ProductSpecManager;
|
||||||
|
import com.suisung.mall.shop.sync.service.SyncStoreSpecsService;
|
||||||
import com.suisung.mall.shop.sync.service.SyncThirdDataService;
|
import com.suisung.mall.shop.sync.service.SyncThirdDataService;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -15,13 +20,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
import java.util.concurrent.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -30,18 +30,23 @@ import java.util.stream.Collectors;
|
|||||||
public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelExcel> {
|
public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelExcel> {
|
||||||
// 批处理阈值
|
// 批处理阈值
|
||||||
private static final int BATCH_SIZE = 500;
|
private static final int BATCH_SIZE = 500;
|
||||||
|
// 数据缓存
|
||||||
|
private List<SxGoosModelExcel> cachedDataList = new ArrayList<>(BATCH_SIZE);
|
||||||
|
|
||||||
|
private SyncThirdDataService syncThirdDataService;
|
||||||
|
|
||||||
|
private SyncStoreSpecsService syncStoreSpecsService;
|
||||||
|
|
||||||
// 线程池配置
|
// 线程池配置
|
||||||
private final ExecutorService executorService;
|
private final ExecutorService executorService;
|
||||||
// 数据缓存
|
|
||||||
private final List<SxGoosModelExcel> cachedDataList = new ArrayList<>(BATCH_SIZE);
|
private List<Future<?>> futures ;
|
||||||
private final SyncThirdDataService syncThirdDataService;
|
private AtomicInteger success;
|
||||||
private final List<Future<?>> futures;
|
private AtomicInteger fails;
|
||||||
private final AtomicInteger success;
|
private AtomicInteger batchSize;
|
||||||
private final AtomicInteger fails;
|
|
||||||
private final AtomicInteger batchSize;
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
private String storeId;
|
private String storeId;
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
@ -49,19 +54,24 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
|||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
private Map<String, Integer> brandMaps;
|
private Map<String,Integer> brandMaps;
|
||||||
|
|
||||||
|
private ProductSpecManager productSpecManager;
|
||||||
|
|
||||||
public ShopBatchSubmitListener(SyncThirdDataService syncThirdDataService) {
|
public ShopBatchSubmitListener(SyncThirdDataService syncThirdDataService,SyncStoreSpecsService syncStoreSpecsService) {
|
||||||
this.syncThirdDataService = syncThirdDataService;
|
this.syncThirdDataService = syncThirdDataService;
|
||||||
|
this.syncStoreSpecsService = syncStoreSpecsService;
|
||||||
// 创建线程池(根据CPU核心数优化)
|
// 创建线程池(根据CPU核心数优化)
|
||||||
int corePoolSize = Runtime.getRuntime().availableProcessors();
|
int corePoolSize = Runtime.getRuntime().availableProcessors();
|
||||||
// log.info("核心线程数量{}", corePoolSize);
|
log.info("核心线程数量{}" , corePoolSize);
|
||||||
this.executorService = Executors.newFixedThreadPool(corePoolSize);
|
this.executorService = Executors.newFixedThreadPool(6);
|
||||||
this.futures = new ArrayList<>();
|
this.futures = new ArrayList<>();
|
||||||
this.success = new AtomicInteger();
|
this.success = new AtomicInteger();
|
||||||
this.fails = new AtomicInteger();
|
this.fails = new AtomicInteger();
|
||||||
this.batchSize = new AtomicInteger();
|
this.batchSize= new AtomicInteger();
|
||||||
|
this.productSpecManager=new ProductSpecManager();
|
||||||
|
Map<String, List<String>> specsMap=new HashMap<>();
|
||||||
|
productSpecManager.setSpecsMap(specsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -74,6 +84,7 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
|||||||
submitBatch();
|
submitBatch();
|
||||||
// 提交后清空缓存
|
// 提交后清空缓存
|
||||||
cachedDataList.clear();
|
cachedDataList.clear();
|
||||||
|
productSpecManager.getSpecsMap().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,18 +97,19 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
|||||||
batchSize.incrementAndGet();
|
batchSize.incrementAndGet();
|
||||||
submitBatch();
|
submitBatch();
|
||||||
cachedDataList.clear();
|
cachedDataList.clear();
|
||||||
|
productSpecManager.getSpecsMap().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 等待所有任务完成
|
// 等待所有任务完成
|
||||||
for (Future<?> future : futures) {
|
for (Future<?> future : futures) {
|
||||||
try {
|
try {
|
||||||
log.info("任务结果:{}", future.get());
|
log.info("任务结果:{}" ,future.get());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.info("任务执行异常: {}", e.getMessage());
|
log.info("任务执行异常: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.info("Excel解析完成,总处理条数: {}", context.readSheetHolder().getTotal());
|
log.info("Excel解析完成,总处理条数: {}" , context.readSheetHolder().getTotal());
|
||||||
log.info("成功数量:{};失败数量:{}", success.get(), fails.get());
|
log.info("成功数量:{};失败数量:{}",success.get(),fails.get());
|
||||||
// 关闭线程池
|
// 关闭线程池
|
||||||
executorService.shutdown();
|
executorService.shutdown();
|
||||||
}
|
}
|
||||||
@ -105,26 +117,28 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
|||||||
private void submitBatch() {
|
private void submitBatch() {
|
||||||
// 复制当前批次数据(避免异步修改)
|
// 复制当前批次数据(避免异步修改)
|
||||||
List<SxGoosModelExcel> batchCopy = new ArrayList<>(deduplicateById(cachedDataList));
|
List<SxGoosModelExcel> batchCopy = new ArrayList<>(deduplicateById(cachedDataList));
|
||||||
log.info("去重前:{};去重后:{}", cachedDataList.size(), batchCopy.size());
|
Map<String,List<String>> sepcsMap = new HashMap<>(productSpecManager.getSpecsMap());
|
||||||
|
log.info("去重前:{};去重后:{}" , cachedDataList.size(), batchCopy.size());
|
||||||
final int index = batchSize.get();
|
final int index = batchSize.get();
|
||||||
futures.add(executorService.submit(() -> {
|
futures.add(executorService.submit(()->{
|
||||||
int i = 0;
|
int i=0;
|
||||||
while (true) {
|
while (true){
|
||||||
i++;
|
i++;
|
||||||
try {
|
try {
|
||||||
Gson gson = new Gson();
|
Gson gson=new Gson();
|
||||||
String jsonShops = gson.toJson(batchCopy);
|
String jsonShops=gson.toJson(batchCopy);
|
||||||
JSONArray jsonArray = new JSONArray(jsonShops);
|
JSONArray jsonArray=new JSONArray(jsonShops);
|
||||||
syncThirdDataService.baseSaveOrUpdateGoodsBatch(jsonArray, storeId, isNegativeAllowed, brandMaps);
|
syncThirdDataService.baseSaveOrUpdateGoodsBatch(jsonArray,storeId,isNegativeAllowed,brandMaps);
|
||||||
log.info("已提交批次: {} 条", batchCopy.size());
|
log.info("已提交批次: {} 条", batchCopy.size());
|
||||||
success.getAndIncrement();
|
success.getAndIncrement();
|
||||||
return "完成批次:" + index;
|
saveSnycStoreSpec(sepcsMap);
|
||||||
|
return "完成批次:"+index;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (i < 2) {
|
if(i<2){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fails.getAndIncrement();
|
fails.getAndIncrement();
|
||||||
return "失败批次:" + index + ";失败原因:" + e.getMessage();
|
return "失败批次:"+index+";失败原因:"+e.getMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@ -132,34 +146,144 @@ public class ShopBatchSubmitListener extends AnalysisEventListener<SxGoosModelEx
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据处理
|
* 数据处理
|
||||||
*
|
|
||||||
* @param list
|
* @param list
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private List<SxGoosModelExcel> deduplicateById(List<SxGoosModelExcel> list) {
|
private List<SxGoosModelExcel> deduplicateById(List<SxGoosModelExcel> list) {
|
||||||
return list.stream()
|
return list.stream()
|
||||||
.peek(sxGoosModelExcel -> {
|
.peek(sxGoosModelExcel -> {
|
||||||
if (StringUtils.isNotEmpty(sxGoosModelExcel.getShop_spec())) {
|
if(StringUtils.isNotEmpty(sxGoosModelExcel.getShop_spec())){
|
||||||
sxGoosModelExcel.setProduct_spec(Collections.singletonList(sxGoosModelExcel.getShop_spec()));
|
sxGoosModelExcel.setProduct_spec(Collections.singletonList(sxGoosModelExcel.getShop_spec()));
|
||||||
}
|
}
|
||||||
if (null == sxGoosModelExcel.getUnit()) {
|
if(null==sxGoosModelExcel.getUnit()){
|
||||||
sxGoosModelExcel.setUnit("");
|
sxGoosModelExcel.setUnit("");
|
||||||
}
|
}
|
||||||
if (ObjectUtil.isEmpty(sxGoosModelExcel.getBuy_limit())) {
|
if(ObjectUtil.isEmpty(sxGoosModelExcel.getBuy_limit())){
|
||||||
sxGoosModelExcel.setBuy_limit(0);
|
sxGoosModelExcel.setBuy_limit(0);
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(sxGoosModelExcel.getBrand_name())) {
|
if(StringUtils.isEmpty(sxGoosModelExcel.getBrand_name())){
|
||||||
sxGoosModelExcel.setBrand_name("其它品牌");
|
sxGoosModelExcel.setBrand_name("其它品牌");
|
||||||
}
|
}
|
||||||
if (ObjectUtil.isEmpty(sxGoosModelExcel.getStock())) {
|
if(ObjectUtil.isEmpty(sxGoosModelExcel.getStock())){
|
||||||
sxGoosModelExcel.setStock(BigDecimal.ZERO);
|
sxGoosModelExcel.setStock(BigDecimal.ZERO);
|
||||||
}
|
}
|
||||||
sxGoosModelExcel.setProduct_number(sxGoosModelExcel.getProduct_barcode());
|
sxGoosModelExcel.setProduct_number(sxGoosModelExcel.getProduct_barcode());
|
||||||
sxGoosModelExcel.setOriginal_price(sxGoosModelExcel.getRetail_price());
|
sxGoosModelExcel.setOriginal_price(sxGoosModelExcel.getRetail_price());
|
||||||
|
|
||||||
|
if(StringUtils.isNotEmpty(sxGoosModelExcel.getShop_specs())){
|
||||||
|
List<ProductSpecManager.SpecItem> specItems= productSpecManager.parseSpecString(sxGoosModelExcel.getShop_specs());
|
||||||
|
sxGoosModelExcel.setJsonSpecs(specItems.toString());
|
||||||
|
productSpecManager.addProductSpec(sxGoosModelExcel.getProduct_barcode(),specItems,sxGoosModelExcel.getRetail_price(),sxGoosModelExcel.getStock());
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.filter(CommonUtil.distinctByKey(SxGoosModelExcel::getProduct_number))
|
.filter(CommonUtil.distinctByKey(SxGoosModelExcel::getProduct_number))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存多规格数据
|
||||||
|
*/
|
||||||
|
private void saveSnycStoreSpec(Map<String,List<String>> listMap){
|
||||||
|
if(listMap==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//List<SyncStoreSpecs> syncStoreSpecs=new ArrayList<>();
|
||||||
|
List<SyncStoreSpecs> addSyncStoreSpecs=new ArrayList<>();
|
||||||
|
List<SyncStoreSpecs> updateSyncStoreSpecs=new ArrayList<>();
|
||||||
|
Map<String,Long> existId= getExistProductId(listMap);
|
||||||
|
if(existId==null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
listMap.forEach((k,v)->{
|
||||||
|
SyncStoreSpecs syncStoreSpec=new SyncStoreSpecs();
|
||||||
|
syncStoreSpec.setProductNumber(k);
|
||||||
|
syncStoreSpec.setJsonSpecs(v.toString());
|
||||||
|
syncStoreSpec.setIsDeal(DicEnum.YESORNO_0.getCode());
|
||||||
|
syncStoreSpec.setStoreId(Integer.valueOf(storeId));
|
||||||
|
if(existId.containsKey(k)){
|
||||||
|
syncStoreSpec.setSycnSpecsId(existId.get(k));
|
||||||
|
updateSyncStoreSpecs.add(syncStoreSpec);
|
||||||
|
}else {
|
||||||
|
addSyncStoreSpecs.add(syncStoreSpec);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(!addSyncStoreSpecs.isEmpty()){
|
||||||
|
syncStoreSpecsService.saveBatch(addSyncStoreSpecs,addSyncStoreSpecs.size());
|
||||||
|
}
|
||||||
|
if(!updateSyncStoreSpecs.isEmpty()){
|
||||||
|
syncStoreSpecsService.updateBatchById(updateSyncStoreSpecs,updateSyncStoreSpecs.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找存量数据
|
||||||
|
* @param listMap
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Map<String,Long> getExistProductId(Map<String,List<String>> listMap){
|
||||||
|
QueryWrapper<SyncStoreSpecs> queryWrapper = new QueryWrapper<>();
|
||||||
|
listMap.forEach((k,v)->{
|
||||||
|
queryWrapper.or(q->q.eq("store_id",storeId).eq("product_number",k));
|
||||||
|
});
|
||||||
|
|
||||||
|
List<SyncStoreSpecs> syncStoreSpecs = syncStoreSpecsService.list(queryWrapper);
|
||||||
|
if(syncStoreSpecs==null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Map<String,Long> resultMap=new HashMap<>();
|
||||||
|
syncStoreSpecs.forEach(m->{
|
||||||
|
resultMap.put(String.valueOf(m.getProductNumber()),m.getSycnSpecsId());
|
||||||
|
});
|
||||||
|
return resultMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SxGoosModelExcel sxGoosModelExcel = new SxGoosModelExcel();
|
||||||
|
sxGoosModelExcel.setProduct_barcode("1");
|
||||||
|
sxGoosModelExcel.setProduct_name("产品1");
|
||||||
|
sxGoosModelExcel.setShop_specs("颜色");
|
||||||
|
sxGoosModelExcel.setRetail_price(new BigDecimal("100"));
|
||||||
|
sxGoosModelExcel.setStock(new BigDecimal("10"));
|
||||||
|
sxGoosModelExcel.setJsonSpecs("[颜色:红色][尺寸:10]");
|
||||||
|
|
||||||
|
SxGoosModelExcel sxGoosModelExcel1 = new SxGoosModelExcel();
|
||||||
|
sxGoosModelExcel1.setProduct_barcode("2");
|
||||||
|
sxGoosModelExcel1.setProduct_name("产品2");
|
||||||
|
sxGoosModelExcel1.setShop_specs("颜色");
|
||||||
|
sxGoosModelExcel1.setShop_spec("红色");
|
||||||
|
sxGoosModelExcel1.setRetail_price(new BigDecimal("200"));
|
||||||
|
sxGoosModelExcel1.setStock(new BigDecimal("20"));
|
||||||
|
sxGoosModelExcel1.setJsonSpecs("[颜色:黑色][尺寸:20]");
|
||||||
|
|
||||||
|
SxGoosModelExcel sxGoosModelExcel3 = new SxGoosModelExcel();
|
||||||
|
sxGoosModelExcel3.setProduct_barcode("1");
|
||||||
|
sxGoosModelExcel3.setProduct_name("产品3");
|
||||||
|
sxGoosModelExcel3.setShop_specs("颜色");
|
||||||
|
sxGoosModelExcel3.setShop_spec("黑色");
|
||||||
|
sxGoosModelExcel3.setRetail_price(new BigDecimal("300"));
|
||||||
|
sxGoosModelExcel3.setStock(new BigDecimal("30"));
|
||||||
|
sxGoosModelExcel3.setJsonSpecs("[颜色:黑色][尺寸:30]");
|
||||||
|
|
||||||
|
List<SxGoosModelExcel> sxGoosModelExcelList = new ArrayList<>();
|
||||||
|
sxGoosModelExcelList.add(sxGoosModelExcel);
|
||||||
|
sxGoosModelExcelList.add(sxGoosModelExcel1);
|
||||||
|
sxGoosModelExcelList.add(sxGoosModelExcel3);
|
||||||
|
ProductSpecManager productSpecManager=new ProductSpecManager();
|
||||||
|
Map<String, List<String>> specsMap=new HashMap<>();
|
||||||
|
productSpecManager.setSpecsMap(specsMap);
|
||||||
|
|
||||||
|
sxGoosModelExcelList=sxGoosModelExcelList.stream().peek(gm -> {
|
||||||
|
if(StringUtils.isNotEmpty(gm.getJsonSpecs())){
|
||||||
|
List<ProductSpecManager.SpecItem> specItems= productSpecManager.parseSpecString(gm.getJsonSpecs());
|
||||||
|
productSpecManager.addProductSpec(gm.getProduct_barcode(),specItems,gm.getRetail_price(),gm.getStock());
|
||||||
|
}
|
||||||
|
}).filter(CommonUtil.distinctByKey(SxGoosModelExcel::getProduct_barcode))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
Gson goson=new Gson();
|
||||||
|
log.info("规格:{}",productSpecManager.getSepcMapValue("1"));
|
||||||
|
log.info("规格数量:{}",productSpecManager.getSepcMapValue("1").size());
|
||||||
|
log.info(String.valueOf(sxGoosModelExcelList.size()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||||
|
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||||
|
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||||
|
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||||
|
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.suisung.mall.shop.sync.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.suisung.mall.common.modules.sync.SyncStoreSpecs;
|
||||||
|
import feign.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface SyncStoreSpecsMapper extends BaseMapper<SyncStoreSpecs> {
|
||||||
|
|
||||||
|
List<SyncStoreSpecs> findSyncStoreSpecsList(SyncStoreSpecs syncStoreSpecs,@Param("limit") Integer limit,@Param("pageSize") Integer pageSize);
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.suisung.mall.shop.sync.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import com.suisung.mall.common.modules.sync.SyncStoreSpecs;
|
||||||
|
|
||||||
|
public interface SyncStoreSpecsService extends IService<SyncStoreSpecs> {
|
||||||
|
|
||||||
|
void dealSyncStoreSpecs(Integer storeId);
|
||||||
|
}
|
||||||
@ -130,7 +130,7 @@ public class ProductMappingServiceImpl extends BaseServiceImpl<ProductMappingMap
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void computeProductMapping(List<ShopProductBase> shopProductBaseList,Integer storeId,Map shopProductSpecItemMap,Map ShopBaseProductSpecMap, Map productMappingMap,boolean isUpdate,String isPubish) {
|
public void computeProductMapping(List<ShopProductBase> shopProductBaseList,Integer storeId,Map shopProductSpecItemMap,Map ShopBaseProductSpecMap, Map productMappingMap,boolean isUpdate,String isPubish) {
|
||||||
shopProductBaseList= shopProductBaseList.stream().filter(base ->StateCode.PRODUCT_STATE_OFF_THE_SHELF_UNCHECK==(base.getProduct_state_id())).collect(Collectors.toList());
|
shopProductBaseList= shopProductBaseList.stream().filter(base ->ObjectUtil.isNotEmpty(base.getUnit_name())).collect(Collectors.toList());
|
||||||
if (CollUtil.isEmpty(shopProductBaseList)) {
|
if (CollUtil.isEmpty(shopProductBaseList)) {
|
||||||
log.info("没有规格数据要处理");
|
log.info("没有规格数据要处理");
|
||||||
return;
|
return;
|
||||||
@ -266,6 +266,7 @@ public class ProductMappingServiceImpl extends BaseServiceImpl<ProductMappingMap
|
|||||||
if(null!=shopProductSpecItem){
|
if(null!=shopProductSpecItem){
|
||||||
item_spec=shopProductSpecItem.getItem_spec();
|
item_spec=shopProductSpecItem.getItem_spec();
|
||||||
productSpec=shopProductSpecItem.getProduct_spec();
|
productSpec=shopProductSpecItem.getProduct_spec();
|
||||||
|
item.setItem_name(shopProductSpecItem.getSpec_item_name());
|
||||||
if(isUpdate){
|
if(isUpdate){
|
||||||
item.setItem_unit_price(shopProductSpecItem.getItemPrice());
|
item.setItem_unit_price(shopProductSpecItem.getItemPrice());
|
||||||
}else {
|
}else {
|
||||||
|
|||||||
@ -17,10 +17,7 @@ import com.suisung.mall.shop.number.service.ShopNumberSeqService;
|
|||||||
import com.suisung.mall.shop.sync.excleHandle.TemplateStyleHandler;
|
import com.suisung.mall.shop.sync.excleHandle.TemplateStyleHandler;
|
||||||
import com.suisung.mall.shop.sync.exelModel.*;
|
import com.suisung.mall.shop.sync.exelModel.*;
|
||||||
import com.suisung.mall.shop.sync.listen.ShopBatchSubmitListener;
|
import com.suisung.mall.shop.sync.listen.ShopBatchSubmitListener;
|
||||||
import com.suisung.mall.shop.sync.service.ProductMappingService;
|
import com.suisung.mall.shop.sync.service.*;
|
||||||
import com.suisung.mall.shop.sync.service.ShopSyncImportService;
|
|
||||||
import com.suisung.mall.shop.sync.service.StoreDbConfigService;
|
|
||||||
import com.suisung.mall.shop.sync.service.SyncThirdDataService;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@ -58,6 +55,8 @@ public class ShopSyncImportServiceImpl implements ShopSyncImportService {
|
|||||||
private ShopNumberSeqService shopNumberSeqService;
|
private ShopNumberSeqService shopNumberSeqService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ShopBaseProductCategoryService shopBaseProductCategoryService;
|
private ShopBaseProductCategoryService shopBaseProductCategoryService;
|
||||||
|
@Autowired
|
||||||
|
private SyncStoreSpecsService syncStoreSpecsService;
|
||||||
|
|
||||||
private final int limitCnt = 100;
|
private final int limitCnt = 100;
|
||||||
|
|
||||||
@ -224,11 +223,12 @@ public class ShopSyncImportServiceImpl implements ShopSyncImportService {
|
|||||||
storeDbConfigQueryWrapper.eq("store_id", storeId);
|
storeDbConfigQueryWrapper.eq("store_id", storeId);
|
||||||
StoreDbConfig storeDbConfig = storeDbConfigService.getOne(storeDbConfigQueryWrapper);
|
StoreDbConfig storeDbConfig = storeDbConfigService.getOne(storeDbConfigQueryWrapper);
|
||||||
String isNegativeAllowed = storeDbConfig.getIsNegativeAllowed();
|
String isNegativeAllowed = storeDbConfig.getIsNegativeAllowed();
|
||||||
ShopBatchSubmitListener shopBatchSubmitListener=new ShopBatchSubmitListener(syncThirdDataService);
|
ShopBatchSubmitListener shopBatchSubmitListener=new ShopBatchSubmitListener(syncThirdDataService,syncStoreSpecsService);
|
||||||
shopBatchSubmitListener.setStoreId(storeId);
|
shopBatchSubmitListener.setStoreId(storeId);
|
||||||
shopBatchSubmitListener.setBrandMaps(brandMaps);
|
shopBatchSubmitListener.setBrandMaps(brandMaps);
|
||||||
shopBatchSubmitListener.setIsNegativeAllowed(isNegativeAllowed);
|
shopBatchSubmitListener.setIsNegativeAllowed(isNegativeAllowed);
|
||||||
EasyExcel.read(filePath,SxGoosModelExcel.class,shopBatchSubmitListener).sheet().doRead();
|
EasyExcel.read(filePath,SxGoosModelExcel.class,shopBatchSubmitListener).sheet().doRead();
|
||||||
|
syncStoreSpecsService.dealSyncStoreSpecs(Integer.valueOf(storeId));
|
||||||
productMappingService.syncAllProductMapping(Integer.valueOf(storeId), DicEnum.YESORNO_0.getCode());
|
productMappingService.syncAllProductMapping(Integer.valueOf(storeId), DicEnum.YESORNO_0.getCode());
|
||||||
syncThirdDataService.syncShopImages(Integer.valueOf(storeId));
|
syncThirdDataService.syncShopImages(Integer.valueOf(storeId));
|
||||||
cleanCache(storeId);//清理redis数据
|
cleanCache(storeId);//清理redis数据
|
||||||
|
|||||||
@ -0,0 +1,593 @@
|
|||||||
|
package com.suisung.mall.shop.sync.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.convert.Convert;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.crypto.SecureUtil;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.suisung.mall.common.enums.DicEnum;
|
||||||
|
import com.suisung.mall.common.modules.base.ShopBaseProductSpec;
|
||||||
|
import com.suisung.mall.common.modules.base.ShopBaseProductType;
|
||||||
|
import com.suisung.mall.common.modules.product.*;
|
||||||
|
import com.suisung.mall.common.modules.sync.SyncStoreSpecs;
|
||||||
|
import com.suisung.mall.common.utils.StringUtils;
|
||||||
|
import com.suisung.mall.shop.base.service.ShopBaseProductSpecService;
|
||||||
|
import com.suisung.mall.shop.base.service.ShopBaseProductTypeService;
|
||||||
|
import com.suisung.mall.shop.number.service.ShopNumberSeqService;
|
||||||
|
import com.suisung.mall.shop.product.service.*;
|
||||||
|
import com.suisung.mall.shop.sixun.utils.CommonUtil;
|
||||||
|
import com.suisung.mall.shop.sync.Utils.ShopJsonUtils;
|
||||||
|
import com.suisung.mall.shop.sync.keymanage.ProductSpecManager;
|
||||||
|
import com.suisung.mall.shop.sync.mapper.SyncStoreSpecsMapper;
|
||||||
|
import com.suisung.mall.shop.sync.service.SyncStoreSpecsService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.util.Pair;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
import org.springframework.transaction.TransactionDefinition;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.transaction.support.TransactionTemplate;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@lombok.extern.slf4j.Slf4j
|
||||||
|
@Transactional
|
||||||
|
public class SyncStoreSpecsServiceImpl extends ServiceImpl<SyncStoreSpecsMapper, SyncStoreSpecs> implements SyncStoreSpecsService {
|
||||||
|
|
||||||
|
private final Integer batchSize = 500;
|
||||||
|
@Autowired
|
||||||
|
private ShopBaseProductSpecService shopBaseProductSpecService;
|
||||||
|
@Autowired
|
||||||
|
private ShopProductSpecItemService shopProductSpecItemService;
|
||||||
|
@Autowired
|
||||||
|
private ShopNumberSeqService shopNumberSeqService;
|
||||||
|
@Autowired
|
||||||
|
private ShopBaseProductTypeService shopBaseProductTypeService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ShopProductItemService shopProductItemService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ShopProductItemSeqService shopProductItemSeqService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ShopProductInfoService shopProductInfoService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ShopProductIndexService shopProductIndexService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SyncStoreSpecsMapper syncStoreSpecsMapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PlatformTransactionManager transactionManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dealSyncStoreSpecs(Integer storeId) {
|
||||||
|
ExecutorService executor = Executors.newFixedThreadPool(6);
|
||||||
|
AtomicInteger success=new AtomicInteger(0);
|
||||||
|
AtomicInteger fails=new AtomicInteger(0);
|
||||||
|
shopNumberSeqService.clearKeyStoreSepcId();
|
||||||
|
List<Future<?>> futures = new ArrayList<>();
|
||||||
|
QueryWrapper<SyncStoreSpecs> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("store_id", storeId);
|
||||||
|
wrapper.eq("is_deal", DicEnum.YESORNO_0.getCode());
|
||||||
|
SyncStoreSpecs queryDto = new SyncStoreSpecs();
|
||||||
|
queryDto.setStoreId(storeId);
|
||||||
|
queryDto.setIsDeal(DicEnum.YESORNO_0.getCode());
|
||||||
|
long total= this.count(wrapper);
|
||||||
|
int pages= CommonUtil.getPagesCount(Math.toIntExact(total),batchSize);
|
||||||
|
for (int i=1;i<=pages;i++){
|
||||||
|
int finalI = i;
|
||||||
|
futures.add(executor.submit(() -> {
|
||||||
|
try {
|
||||||
|
List<SyncStoreSpecs> syncStoreSpecsList= syncStoreSpecsMapper.findSyncStoreSpecsList(queryDto, finalI -1,batchSize);
|
||||||
|
//处理多规格数据
|
||||||
|
dealShopItemSpec(syncStoreSpecsList,storeId);
|
||||||
|
success.getAndIncrement();
|
||||||
|
syncStoreSpecsList.forEach(syncStoreSpecs -> {
|
||||||
|
syncStoreSpecs.setIsDeal(DicEnum.YESORNO_1.getCode());
|
||||||
|
});
|
||||||
|
this.updateBatchById(syncStoreSpecsList,syncStoreSpecsList.size());
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("失败原因:"+e.getMessage(),e);
|
||||||
|
fails.getAndIncrement();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
// 等待所有任务完成
|
||||||
|
for (Future<?> future : futures) {
|
||||||
|
try {
|
||||||
|
System.out.println("规格任务结果: " + future.get());
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("规格任务执行异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
executor.shutdown();
|
||||||
|
shopNumberSeqService.clearKeyStoreSepcId();
|
||||||
|
log.info("处理多规格数据成功:{}批,失败:{}批", success.get(), fails.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理多规格商品
|
||||||
|
*/
|
||||||
|
@Transactional
|
||||||
|
public void dealShopItemSpec(List<SyncStoreSpecs> syncStoreSpecsList,Integer storeId){
|
||||||
|
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
|
||||||
|
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||||
|
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
|
||||||
|
transactionTemplate.setTimeout(200); // 60秒超时
|
||||||
|
transactionTemplate.execute(status -> {
|
||||||
|
try {
|
||||||
|
ProductSpecManager productSpecManager=new ProductSpecManager();
|
||||||
|
Map<String,List<String>> specMap=new HashMap<>();//存储规格类型
|
||||||
|
Map<String,List<String>> specValueMap=new HashMap<>();//存储规格的值
|
||||||
|
Map<String,Integer> specCateGoryMap=new HashMap<>();//存储分类id
|
||||||
|
Map<String,Long> specsProductIdMap=new HashMap<>();//存储product_id
|
||||||
|
//Map<String,Long> existProductItemMap=new HashMap<>();//存储item_id
|
||||||
|
Gson gson=new Gson();
|
||||||
|
//规格定义
|
||||||
|
List<ShopBaseProductSpec> shopBaseProductSpecList=new ArrayList<>();
|
||||||
|
//规格值定义
|
||||||
|
//解析json
|
||||||
|
for (SyncStoreSpecs syncStoreSpecs : syncStoreSpecsList) {
|
||||||
|
List<String> jsonSpec= new ArrayList<>();
|
||||||
|
cn.hutool.json.JSONArray jsonArray=JSONUtil.parseArray(syncStoreSpecs.getJsonSpecs());
|
||||||
|
for (Object obj : jsonArray) {
|
||||||
|
jsonSpec.add(obj.toString());
|
||||||
|
}
|
||||||
|
specMap.put(String.valueOf(syncStoreSpecs.getProductNumber()),jsonSpec);
|
||||||
|
specCateGoryMap.put(String.valueOf(syncStoreSpecs.getProductNumber()),syncStoreSpecs.getCategoryId());
|
||||||
|
specsProductIdMap.put(syncStoreSpecs.getProductNumber(),syncStoreSpecs.getProductId());
|
||||||
|
// existProductItemMap.put(syncStoreSpecs.getProductNumber(),syncStoreSpecs.getItemId());
|
||||||
|
}
|
||||||
|
productSpecManager.setSpecsMap(specMap);
|
||||||
|
List<ShopProductItem> shopProductItems=new ArrayList<>();
|
||||||
|
specMap.forEach((k,v)->{
|
||||||
|
List<ProductSpecManager.ProductSpecInfo> specInfos= productSpecManager.getProductSpecs(k);
|
||||||
|
for (ProductSpecManager.ProductSpecInfo specInfo : specInfos) {
|
||||||
|
List<ProductSpecManager.SpecItem> specList=specInfo.getSpec();
|
||||||
|
StringBuilder specValue=new StringBuilder();
|
||||||
|
for (ProductSpecManager.SpecItem specItem : specList) {
|
||||||
|
ShopBaseProductSpec shopBaseProductSpec=new ShopBaseProductSpec();
|
||||||
|
shopBaseProductSpec.setStore_id(storeId);
|
||||||
|
shopBaseProductSpec.setSpec_name(specItem.getName());
|
||||||
|
shopBaseProductSpec.setSpec_format("text");
|
||||||
|
shopBaseProductSpec.setSpec_order(50);
|
||||||
|
shopBaseProductSpec.setSpec_category_id(specCateGoryMap.get(k));
|
||||||
|
shopBaseProductSpecList.add(shopBaseProductSpec);
|
||||||
|
List<String> specValueList=new ArrayList<>();
|
||||||
|
if(specValueMap.containsKey(specItem.getName())){
|
||||||
|
specValueList=specValueMap.get(specItem.getName());
|
||||||
|
}
|
||||||
|
if(StringUtils.isNotEmpty(specValue)){
|
||||||
|
specValue.append(",").append(specItem.getValue());
|
||||||
|
}else {
|
||||||
|
specValue.append(specItem.getValue());
|
||||||
|
}
|
||||||
|
specValueList.add(specItem.getValue());
|
||||||
|
specValueMap.put(specItem.getName(),specValueList);
|
||||||
|
}
|
||||||
|
ProductSpecManager.PriceStockItem stockItem= specInfo.getPriceAndstock();
|
||||||
|
ShopProductItem spuItem=new ShopProductItem();
|
||||||
|
spuItem.setItem_barcode(k);
|
||||||
|
spuItem.setItem_number(k);
|
||||||
|
spuItem.setItem_name(specValue.toString());
|
||||||
|
spuItem.setItem_unit_price(stockItem.getPrice());
|
||||||
|
spuItem.setItem_market_price(stockItem.getPrice());
|
||||||
|
spuItem.setItem_quantity(stockItem.getStock().intValue());
|
||||||
|
shopProductItems.add(spuItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//1.新增规格
|
||||||
|
//过滤
|
||||||
|
List<ShopBaseProductSpec> addShopBaseProductSpecList=new ArrayList<>();
|
||||||
|
List<ShopBaseProductSpec> updateShopBaseProductSpecList=new ArrayList<>();
|
||||||
|
List<ShopBaseProductSpec> shopBaseProductSpecs=shopBaseProductSpecList.stream()
|
||||||
|
.filter(com.suisung.mall.common.utils.CommonUtil.distinctByKey(ShopBaseProductSpec::getSpec_name))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
Map<String,Integer> existsMap= getExistShopBaseSpec(shopBaseProductSpecs,storeId);
|
||||||
|
Map<String,Integer> specCateGoryIdMap=new HashMap<>();
|
||||||
|
Map<Integer,List<Integer>> cateGoryIdSpecIdMap=new HashMap<>();
|
||||||
|
for(ShopBaseProductSpec spec:shopBaseProductSpecs){
|
||||||
|
if(existsMap.containsKey(spec.getSpec_name())){
|
||||||
|
spec.setSpec_id(existsMap.get(spec.getSpec_name()));
|
||||||
|
specCateGoryIdMap.put(spec.getSpec_name(),spec.getSpec_id());
|
||||||
|
updateShopBaseProductSpecList.add(spec);
|
||||||
|
}else {
|
||||||
|
addShopBaseProductSpecList.add(spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!addShopBaseProductSpecList.isEmpty()){
|
||||||
|
List<Integer> specIds= shopNumberSeqService.getBatchSpecId(addShopBaseProductSpecList.size());//计算specId
|
||||||
|
for (int i=0;i<specIds.size();i++){
|
||||||
|
addShopBaseProductSpecList.get(i).setSpec_id(specIds.get(i));
|
||||||
|
List<Integer> specIdList=new ArrayList<>();
|
||||||
|
if(cateGoryIdSpecIdMap.containsKey(addShopBaseProductSpecList.get(i).getSpec_category_id())){
|
||||||
|
specIdList=cateGoryIdSpecIdMap.get(addShopBaseProductSpecList.get(i).getSpec_category_id());
|
||||||
|
}
|
||||||
|
specIdList.add(specIds.get(i));
|
||||||
|
cateGoryIdSpecIdMap.put(addShopBaseProductSpecList.get(i).getSpec_category_id(),specIdList);
|
||||||
|
specCateGoryIdMap.put(addShopBaseProductSpecList.get(i).getSpec_name(),specIds.get(i));
|
||||||
|
}
|
||||||
|
//shopBaseProductSpecService.saveBatch(addShopBaseProductSpecList,addShopBaseProductSpecList.size());
|
||||||
|
}
|
||||||
|
// if(!updateShopBaseProductSpecList.isEmpty()){
|
||||||
|
// shopBaseProductSpecService.updateBatchById(updateShopBaseProductSpecList,updateShopBaseProductSpecList.size());
|
||||||
|
// }
|
||||||
|
//2.新增规格的值
|
||||||
|
List<ShopProductSpecItem> specItems=new ArrayList<>();
|
||||||
|
specValueMap.forEach((k,v)->{
|
||||||
|
for (String specVal : v) {
|
||||||
|
ShopProductSpecItem specItem = new ShopProductSpecItem();
|
||||||
|
specItem.setSpec_id(specCateGoryIdMap.get(k));
|
||||||
|
specItem.setCategory_id(specCateGoryMap.get(k));
|
||||||
|
specItem.setStore_id(storeId);
|
||||||
|
specItem.setSpec_item_enable(1);
|
||||||
|
specItem.setSpec_item_name(specVal);
|
||||||
|
specItem.setSpec_item_order("10");
|
||||||
|
specItem.setSpecName(k);
|
||||||
|
specItems.add(specItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Map<String,ShopProductSpecItem> specItemMap=new HashMap<>();//存储specItemValue对应的ShopProductSpecItem
|
||||||
|
List<ShopProductSpecItem> specItemList=specItems.stream()
|
||||||
|
.filter(com.suisung.mall.common.utils.CommonUtil.distinctByKey(ShopProductSpecItem::getSpec_item_name))
|
||||||
|
.collect(Collectors.toList());//去重
|
||||||
|
List<ShopProductSpecItem> addSpecItemList=new ArrayList<>();
|
||||||
|
List<ShopProductSpecItem> updateSpecItemList=new ArrayList<>();
|
||||||
|
Map<String,Integer> specItemIdMap=getExistShopSpecItem(specItemList,storeId);
|
||||||
|
for(ShopProductSpecItem specItem:specItemList){
|
||||||
|
if(specItemIdMap.containsKey(specItem.getSpec_item_name())){
|
||||||
|
specItem.setSpec_item_id(specItemIdMap.get(specItem.getSpec_item_name()));
|
||||||
|
updateSpecItemList.add(specItem);
|
||||||
|
}else {
|
||||||
|
addSpecItemList.add(specItem);
|
||||||
|
}
|
||||||
|
specItemMap.put(specItem.getSpec_item_name(),specItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!addSpecItemList.isEmpty()){
|
||||||
|
List<Integer> specItemIds= shopNumberSeqService.getBatchSpecItemId(addSpecItemList.size());//计算specId
|
||||||
|
for (int i=0;i<specItemIds.size();i++){
|
||||||
|
addSpecItemList.get(i).setSpec_item_id(specItemIds.get(i));
|
||||||
|
specItemMap.put(addSpecItemList.get(i).getSpec_item_name(),addSpecItemList.get(i));
|
||||||
|
}
|
||||||
|
// shopProductSpecItemService.saveBatch(addSpecItemList,addSpecItemList.size());
|
||||||
|
}
|
||||||
|
// if(!updateSpecItemList.isEmpty()){
|
||||||
|
// shopProductSpecItemService.updateBatchById(updateSpecItemList,updateSpecItemList.size());
|
||||||
|
// }
|
||||||
|
//3、新增规格类型
|
||||||
|
List<ShopBaseProductType> shopBaseProductTypes= getShopBaseProductTypeList(syncStoreSpecsList,storeId);
|
||||||
|
for(ShopBaseProductType shopBaseProductType:shopBaseProductTypes){
|
||||||
|
List<Integer> specIdList=new ArrayList<>();
|
||||||
|
if(cateGoryIdSpecIdMap.containsKey(shopBaseProductType.getType_category_id())){
|
||||||
|
specIdList=cateGoryIdSpecIdMap.get(shopBaseProductType.getType_category_id());
|
||||||
|
String [] type_spec_ids=shopBaseProductType.getType_spec_ids().split(",");
|
||||||
|
for (String specId : type_spec_ids) {
|
||||||
|
specIdList.add(Integer.parseInt(specId));
|
||||||
|
}
|
||||||
|
String typeSpecIds= specIdList.stream().map(String::valueOf).distinct().collect(Collectors.joining(","));
|
||||||
|
shopBaseProductType.setType_spec_ids(typeSpecIds);
|
||||||
|
}else {
|
||||||
|
specIdList=cateGoryIdSpecIdMap.get(shopBaseProductType.getType_category_id());
|
||||||
|
if(null!=specIdList){
|
||||||
|
String typeSpecIds= specIdList.stream().map(String::valueOf).distinct().collect(Collectors.joining(","));
|
||||||
|
shopBaseProductType.setType_spec_ids(typeSpecIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!shopBaseProductTypes.isEmpty()){//更新规格类型
|
||||||
|
shopBaseProductTypeService.updateBatchById(shopBaseProductTypes,shopBaseProductTypes.size());
|
||||||
|
}
|
||||||
|
//4、新增shopItem
|
||||||
|
List<ShopProductItem> addShopProductItemList=new ArrayList<>();
|
||||||
|
List<ShopProductItem> updateShopProductItemList=new ArrayList<>();
|
||||||
|
Map<String,Long> existProductItemMap= getExistShopItemList(shopProductItems,storeId);
|
||||||
|
shopProductItems.forEach(item->{
|
||||||
|
item.setProduct_id(specsProductIdMap.get(item.getItem_barcode()));
|
||||||
|
StringBuilder pIspecItemIds= new StringBuilder();
|
||||||
|
String[] pIspecItemNames=item.getItem_name().split(",");
|
||||||
|
List<Map<String, Object>> spectItems=new ArrayList<>();
|
||||||
|
List<Map<String, Object>> specJson=new ArrayList<>();
|
||||||
|
for (String pIspecItemName : pIspecItemNames) {
|
||||||
|
ShopProductSpecItem specItem = specItemMap.get(pIspecItemName);
|
||||||
|
Integer specItemId=specItem.getSpec_item_id();
|
||||||
|
if (StringUtils.isNotEmpty(pIspecItemIds)) {
|
||||||
|
pIspecItemIds.append(",").append(specItemId);
|
||||||
|
} else {
|
||||||
|
pIspecItemIds.append(specItemId);
|
||||||
|
}
|
||||||
|
Map<String,Object> specItemJson=new HashMap<>();
|
||||||
|
specItemJson.put("name",specItem.getSpec_item_name());//规格列表
|
||||||
|
specItemJson.put("id",specItem.getSpec_item_id());
|
||||||
|
spectItems.add(specItemJson);
|
||||||
|
|
||||||
|
Map<String,Object> specJsonMap=new HashMap<>();
|
||||||
|
specJsonMap.put("name",specItem.getSpecName());//规格名称
|
||||||
|
specJsonMap.put("id",specItem.getSpec_id());
|
||||||
|
specJson.add(specJsonMap);
|
||||||
|
}
|
||||||
|
item.setSpec_item_ids(pIspecItemIds.toString());
|
||||||
|
String item_spec= ShopJsonUtils.generateJsonWithOrgJsonItemSpec(spectItems,specJson);
|
||||||
|
// String productInfoSpec= ShopJsonUtils.generateJsonWithOrgJsonProducSpec(spectItems,specJson);
|
||||||
|
item.setItem_spec(item_spec);
|
||||||
|
item.setItem_title("");
|
||||||
|
item.setItem_freetime(0);
|
||||||
|
item.setCategory_id(specCateGoryMap.get(item.getItem_barcode()));
|
||||||
|
if(existProductItemMap.containsKey(item.getItem_name())){
|
||||||
|
item.setItem_id(existProductItemMap.get(item.getItem_barcode()));
|
||||||
|
updateShopProductItemList.add(item);
|
||||||
|
}else {
|
||||||
|
addShopProductItemList.add(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(!addShopProductItemList.isEmpty()){
|
||||||
|
List<Long> generatedIds = shopNumberSeqService.batchCreateNextNo("item_id", addShopProductItemList.size());
|
||||||
|
for (int i = 0; i < generatedIds.size(); i++) {
|
||||||
|
addShopProductItemList.get(i).setItem_id(generatedIds.get(i));
|
||||||
|
addShopProductItemList.get(i).setItem_src_id(String.valueOf(generatedIds.get(i)));
|
||||||
|
}
|
||||||
|
shopProductItemService.saveBatch(addShopProductItemList,addShopProductItemList.size());
|
||||||
|
}
|
||||||
|
if(!updateShopProductItemList.isEmpty()){
|
||||||
|
shopProductItemService.updateBatchById(updateShopProductItemList,updateShopProductItemList.size());
|
||||||
|
}
|
||||||
|
List<ShopProductItemSeq> addShopProductItemSeqList=new ArrayList<>();
|
||||||
|
addShopProductItemList.forEach(item->{
|
||||||
|
ShopProductItemSeq shopProductItemSeq=new ShopProductItemSeq();
|
||||||
|
shopProductItemSeq.setItem_id(item.getItem_id());
|
||||||
|
shopProductItemSeq.setProduct_id(item.getProduct_id());
|
||||||
|
String item_spec=item.getItem_spec();
|
||||||
|
Long productId=item.getProduct_id();
|
||||||
|
cn.hutool.json.JSONArray array_item_spec = cn.hutool.json.JSONUtil.parseArray(item_spec);
|
||||||
|
List<Integer> spec_item_ids=new ArrayList<>();
|
||||||
|
for (Object josn_item_spec : array_item_spec) {
|
||||||
|
cn.hutool.json.JSONObject itemJson = (cn.hutool.json.JSONObject) ((cn.hutool.json.JSONObject) josn_item_spec).get("item");
|
||||||
|
Integer id = Convert.toInt(itemJson.get("id"));
|
||||||
|
if (ObjectUtil.isNotNull(id)) {
|
||||||
|
spec_item_ids.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CollUtil.isNotEmpty(spec_item_ids)) {
|
||||||
|
Collections.sort(spec_item_ids);
|
||||||
|
}
|
||||||
|
String sku_uniqid = "default";
|
||||||
|
if(CollUtil.isNotEmpty(spec_item_ids)){
|
||||||
|
sku_uniqid = CollUtil.join(spec_item_ids, "-");
|
||||||
|
}
|
||||||
|
String product_item_seq_val = String.format("%s:%s", productId, sku_uniqid);
|
||||||
|
String product_item_seq_id = SecureUtil.md5(product_item_seq_val);
|
||||||
|
shopProductItemSeq.setProduct_item_seq_id(product_item_seq_id);
|
||||||
|
shopProductItemSeq.setProduct_item_seq_val(product_item_seq_val);
|
||||||
|
addShopProductItemSeqList.add(shopProductItemSeq);
|
||||||
|
});
|
||||||
|
if(!addShopProductItemSeqList.isEmpty()){
|
||||||
|
shopProductItemSeqService.saveOrUpdateBatch(addShopProductItemSeqList,addShopProductItemSeqList.size());
|
||||||
|
}
|
||||||
|
//更新shopProductInfo
|
||||||
|
Map<Long, List<ShopProductItem>> shopInfoItems=new HashMap<>();
|
||||||
|
List<ShopProductInfo> updateShopProductInfoList=new ArrayList<>();
|
||||||
|
for (ShopProductItem shopProductItem: addShopProductItemList) {
|
||||||
|
Long productId=shopProductItem.getProduct_id();
|
||||||
|
List<ShopProductItem> shopProductItemList=new ArrayList<>();
|
||||||
|
if(shopInfoItems.containsKey(shopProductItem.getProduct_id())){
|
||||||
|
shopProductItemList=shopInfoItems.get(shopProductItem.getProduct_id());
|
||||||
|
}
|
||||||
|
shopProductItemList.add(shopProductItem);
|
||||||
|
shopInfoItems.put(productId,shopProductItemList);
|
||||||
|
}
|
||||||
|
Map<Long,Integer> itemQualityMap=new HashMap<>();
|
||||||
|
shopInfoItems.forEach((productId,sItemList)->{
|
||||||
|
ShopProductInfo spui=new ShopProductInfo();
|
||||||
|
spui.setProduct_id(productId);
|
||||||
|
String item_spec=sItemList.get(0).getItem_spec();
|
||||||
|
cn.hutool.json.JSONArray array_item_spec = cn.hutool.json.JSONUtil.parseArray(item_spec);
|
||||||
|
List<Integer> spec_item_ids=new ArrayList<>();
|
||||||
|
for (Object josn_item_spec : array_item_spec) {
|
||||||
|
Integer specId = Convert.toInt(((cn.hutool.json.JSONObject) josn_item_spec).get("id"));
|
||||||
|
spec_item_ids.add(specId);
|
||||||
|
}
|
||||||
|
String spec_ids=CollUtil.join(spec_item_ids,",");
|
||||||
|
spui.setSpec_ids(spec_ids);
|
||||||
|
|
||||||
|
Map<String,cn.hutool.json.JSONArray> specItemJson=new HashMap<>();
|
||||||
|
cn.hutool.json.JSONArray productUniqidjsonArray=new cn.hutool.json.JSONArray();
|
||||||
|
AtomicReference<Integer> itemQuantity= new AtomicReference<>(0);
|
||||||
|
sItemList.forEach(item->{
|
||||||
|
String itemSpec=item.getItem_spec();
|
||||||
|
cn.hutool.json.JSONArray arrayItemSpec = cn.hutool.json.JSONUtil.parseArray(itemSpec);
|
||||||
|
cn.hutool.json.JSONObject uniqidItemJson=new cn.hutool.json.JSONObject();
|
||||||
|
String specItemIdSpecItemId="";
|
||||||
|
for (Object josn_item_spec : arrayItemSpec) {
|
||||||
|
Integer specId = Convert.toInt(((cn.hutool.json.JSONObject) josn_item_spec).get("id"));
|
||||||
|
Integer specName = Convert.toInt(((cn.hutool.json.JSONObject) josn_item_spec).get("name"));
|
||||||
|
String specIdName=specId+"-"+specName;
|
||||||
|
cn.hutool.json.JSONObject itemJson = (cn.hutool.json.JSONObject) ((cn.hutool.json.JSONObject) josn_item_spec).get("item");
|
||||||
|
cn.hutool.json.JSONArray itemsJsonArray=new cn.hutool.json.JSONArray();
|
||||||
|
if(specItemJson.containsKey(specIdName)){
|
||||||
|
itemsJsonArray=specItemJson.get(specIdName);
|
||||||
|
}
|
||||||
|
itemsJsonArray.add(itemJson);
|
||||||
|
specItemJson.put(specIdName,itemsJsonArray);
|
||||||
|
if(StringUtils.isNotEmpty(specItemIdSpecItemId)){
|
||||||
|
specItemIdSpecItemId=specItemIdSpecItemId+"-"+itemJson.getStr("id");
|
||||||
|
}else {
|
||||||
|
specItemIdSpecItemId=itemJson.getStr("id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uniqidItemJson.set(specItemIdSpecItemId,new Object[]{item.getItem_id(),item.getItem_quantity(),"","1001"});
|
||||||
|
productUniqidjsonArray.add(uniqidItemJson);
|
||||||
|
itemQuantity.updateAndGet(v -> v + item.getItem_quantity());
|
||||||
|
});
|
||||||
|
itemQualityMap.put(productId,itemQuantity.get());
|
||||||
|
cn.hutool.json.JSONArray jsonArraySpecItem=new cn.hutool.json.JSONArray();
|
||||||
|
specItemJson.forEach((key,jsonArray)->{
|
||||||
|
cn.hutool.json.JSONObject itemJson = new cn.hutool.json.JSONObject();
|
||||||
|
itemJson.set("item",jsonArray);
|
||||||
|
String[] specIdName=key.split("-");
|
||||||
|
String specId=specIdName[0];
|
||||||
|
String specName=specIdName[1];
|
||||||
|
itemJson.set("name",specName);
|
||||||
|
itemJson.set("spec_format","text");
|
||||||
|
itemJson.set("id",specId);
|
||||||
|
jsonArraySpecItem.add(itemJson);
|
||||||
|
});
|
||||||
|
String product_spec= JSONUtil.toJsonStr(jsonArraySpecItem);
|
||||||
|
String product_uniqid=JSONUtil.toJsonStr(productUniqidjsonArray);
|
||||||
|
spui.setProduct_spec(product_spec);
|
||||||
|
spui.setProduct_uniqid(product_uniqid);
|
||||||
|
updateShopProductInfoList.add(spui);
|
||||||
|
});
|
||||||
|
if(!updateShopProductInfoList.isEmpty()){
|
||||||
|
shopProductInfoService.updateBatchById(updateShopProductInfoList,updateShopProductInfoList.size());
|
||||||
|
}
|
||||||
|
//5、更新shopindex数量
|
||||||
|
List<ShopProductIndex> shopProductIndexList=new ArrayList<>();
|
||||||
|
itemQualityMap.forEach((productId,stock)->{
|
||||||
|
ShopProductIndex shopProductIndex=new ShopProductIndex();
|
||||||
|
shopProductIndex.setProduct_id(productId);
|
||||||
|
shopProductIndex.setProduct_quantity(stock);
|
||||||
|
shopProductIndexList.add(shopProductIndex);
|
||||||
|
});
|
||||||
|
if(!shopProductIndexList.isEmpty()){
|
||||||
|
shopProductIndexService.updateBatchById(shopProductIndexList,shopProductIndexList.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
//最后保存
|
||||||
|
if(!addShopBaseProductSpecList.isEmpty()){//规格大类
|
||||||
|
shopBaseProductSpecService.saveBatch(addShopBaseProductSpecList,addShopBaseProductSpecList.size());
|
||||||
|
}
|
||||||
|
if(!updateShopBaseProductSpecList.isEmpty()){//规格大类
|
||||||
|
shopBaseProductSpecService.updateBatchById(updateShopBaseProductSpecList,updateShopBaseProductSpecList.size());
|
||||||
|
}
|
||||||
|
if(!addSpecItemList.isEmpty()){//规格值
|
||||||
|
shopProductSpecItemService.saveBatch(addSpecItemList,addSpecItemList.size());
|
||||||
|
}
|
||||||
|
if(!updateSpecItemList.isEmpty()){//规格值
|
||||||
|
shopProductSpecItemService.updateBatchById(updateSpecItemList,updateSpecItemList.size());
|
||||||
|
}
|
||||||
|
//shopitem 最后删除没有规格的商品
|
||||||
|
QueryWrapper<ShopProductItem> queryWrapper=new QueryWrapper<>();
|
||||||
|
queryWrapper.select("item_id");
|
||||||
|
for (ShopProductIndex shopProductIndex:shopProductIndexList) {
|
||||||
|
queryWrapper.or(q->q.eq("store_id",storeId)
|
||||||
|
.eq("product_id",shopProductIndex.getProduct_id())
|
||||||
|
.and(wrapper->wrapper.eq("item_name","")
|
||||||
|
.or()
|
||||||
|
.isNull("item_name")));
|
||||||
|
}
|
||||||
|
List<ShopProductItem> queryShopProductItemList=shopProductItemService.list(queryWrapper);
|
||||||
|
if(!queryShopProductItemList.isEmpty()){
|
||||||
|
List<Long> ItemIds= queryShopProductItemList.stream().map(ShopProductItem::getItem_id).collect(Collectors.toList());
|
||||||
|
QueryWrapper<ShopProductItemSeq> shopProductItemSeqQueryWrapper=new QueryWrapper<>();
|
||||||
|
shopProductItemSeqQueryWrapper.select("product_item_seq_id");
|
||||||
|
shopProductItemSeqQueryWrapper.eq("item_id",ItemIds);
|
||||||
|
List<ShopProductItemSeq> rmSeq= shopProductItemSeqService.list(shopProductItemSeqQueryWrapper);
|
||||||
|
List<String> rmSeqIds=rmSeq.stream().map(ShopProductItemSeq::getProduct_item_seq_id).collect(Collectors.toList());
|
||||||
|
shopProductItemSeqService.removeBatchByIds(rmSeqIds);
|
||||||
|
shopProductItemService.removeBatchByIds(ItemIds,ItemIds.size());
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
status.setRollbackOnly();
|
||||||
|
log.error("批量操作异常", e);
|
||||||
|
return Pair.of(false, "批量操作异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return "success";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询分类规格
|
||||||
|
* @param shopBaseProductSpecs
|
||||||
|
* @param storeId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Map<String,Integer> getExistShopBaseSpec(List<ShopBaseProductSpec> shopBaseProductSpecs,Integer storeId){
|
||||||
|
Map<String,Integer> result=new HashMap<>();
|
||||||
|
QueryWrapper<ShopBaseProductSpec> wrapper = new QueryWrapper<>();
|
||||||
|
for (ShopBaseProductSpec shopBaseProductSpec : shopBaseProductSpecs) {
|
||||||
|
wrapper.or(q->q.eq("spec_name",shopBaseProductSpec.getSpec_name()).eq("store_id",storeId));
|
||||||
|
}
|
||||||
|
List<ShopBaseProductSpec> shopBaseProductSpecList=shopBaseProductSpecService.list(wrapper);
|
||||||
|
for (ShopBaseProductSpec shopBaseProductSpec : shopBaseProductSpecList) {
|
||||||
|
result.put(shopBaseProductSpec.getSpec_name(),shopBaseProductSpec.getSpec_id());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询分类规格
|
||||||
|
* @param shopProductSpecItems
|
||||||
|
* @param storeId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Map<String,Integer> getExistShopSpecItem(List<ShopProductSpecItem> shopProductSpecItems,Integer storeId){
|
||||||
|
Map<String,Integer> result=new HashMap<>();
|
||||||
|
QueryWrapper<ShopProductSpecItem> wrapper = new QueryWrapper<>();
|
||||||
|
for (ShopProductSpecItem shopProductSpecItem : shopProductSpecItems) {
|
||||||
|
wrapper.or(q->q.eq("spec_item_name",shopProductSpecItem.getSpec_item_name()).eq("store_id",storeId));
|
||||||
|
}
|
||||||
|
List<ShopProductSpecItem> shopProductSpecItemList=shopProductSpecItemService.list(wrapper);
|
||||||
|
for (ShopProductSpecItem shopProductSpecItem : shopProductSpecItemList) {
|
||||||
|
result.put(shopProductSpecItem.getSpec_item_name(),shopProductSpecItem.getSpec_item_id());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找分类的类型
|
||||||
|
* @param syncStoreSpecsList
|
||||||
|
* @param storeId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<ShopBaseProductType> getShopBaseProductTypeList(List<SyncStoreSpecs> syncStoreSpecsList,Integer storeId){
|
||||||
|
QueryWrapper<ShopBaseProductType> wrapper = new QueryWrapper<>();
|
||||||
|
for (SyncStoreSpecs syncStoreSpecs : syncStoreSpecsList) {
|
||||||
|
wrapper.or(q->q.eq("store_id",storeId).eq("type_category_id",syncStoreSpecs.getCategoryId()));
|
||||||
|
}
|
||||||
|
return shopBaseProductTypeService.list(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找分类的类型
|
||||||
|
* @param syncStoreSpecsList
|
||||||
|
* @param storeId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Map<String,Long> getExistShopItemList(List<ShopProductItem> syncStoreSpecsList,Integer storeId){
|
||||||
|
QueryWrapper<ShopProductItem> wrapper = new QueryWrapper<>();
|
||||||
|
for (ShopProductItem shopProductItem : syncStoreSpecsList) {
|
||||||
|
wrapper.or(q->q.eq("store_id",storeId)
|
||||||
|
.eq("item_barcode",shopProductItem.getItem_barcode())
|
||||||
|
.eq("item_name",shopProductItem.getItem_name()));
|
||||||
|
}
|
||||||
|
List<ShopProductItem> shopProductItemList=shopProductItemService.list(wrapper);
|
||||||
|
Map<String,Long> result=new HashMap<>();
|
||||||
|
for (ShopProductItem shopProductItem : shopProductItemList) {
|
||||||
|
result.put(shopProductItem.getItem_name(),shopProductItem.getItem_id());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
List<String> spec_item_ids= Arrays.asList("12","13","14","15","16","17","18","19","20");
|
||||||
|
System.out.println(CollUtil.join(spec_item_ids, "-"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.suisung.mall.shop.sync.mapper.SyncStoreSpecsMapper">
|
||||||
|
|
||||||
|
<resultMap id="syncStoreSpecsMap" type="com.suisung.mall.common.modules.sync.SyncStoreSpecs">
|
||||||
|
<result property="sycnSpecsId" column="sycn_specs_id"/>
|
||||||
|
<result property="productNumber" column="product_number"/>
|
||||||
|
<result property="jsonSpecs" column="json_specs"/>
|
||||||
|
<result property="storeId" column="store_id"/>
|
||||||
|
<result property="isDeal" column="is_deal"/>
|
||||||
|
<result property="productId" column="product_id"/>
|
||||||
|
<result property="categoryId" column="category_id"/>
|
||||||
|
<result property="itemId" column="item_id"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="findSyncStoreSpecsList" resultMap="syncStoreSpecsMap">
|
||||||
|
SELECT s.sycn_specs_id ,
|
||||||
|
s.product_number,
|
||||||
|
s.json_specs ,
|
||||||
|
s.store_id,
|
||||||
|
s.is_deal,
|
||||||
|
spi.product_id,
|
||||||
|
spi.category_id,
|
||||||
|
spi.item_id
|
||||||
|
from sycn_store_specs s
|
||||||
|
left join shop_product_item spi
|
||||||
|
on s.product_number =spi.item_barcode
|
||||||
|
<where>
|
||||||
|
s.store_id=#{syncStoreSpecs.storeId}
|
||||||
|
and
|
||||||
|
s.is_deal=#{syncStoreSpecs.isDeal}
|
||||||
|
</where>
|
||||||
|
limit #{limit},#{pageSize}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</mapper>
|
||||||
13
sql/shop/dev/20250819_ddl.sql
Normal file
13
sql/shop/dev/20250819_ddl.sql
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
CREATE TABLE `sycn_store_specs` (
|
||||||
|
`sycn_specs_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '多规格编号',
|
||||||
|
`json_specs` json DEFAULT NULL COMMENT '多规格json数据,如[{"spec": [{"name": "颜色","value": "红色"},{"name": "尺寸","value": "10"}],"priceAndstock": {"price": 100,"stock": 10}},{"spec": [{ "name": "颜色","value": "黑色"},{"name": "尺寸","value": "30"}],
|
||||||
|
"priceAndstock": {"price": 300,"stock": 30}}]',
|
||||||
|
`product_number` varchar(50) DEFAULT '' COMMENT '条形码',
|
||||||
|
`store_id` int unsigned NOT NULL DEFAULT '0' COMMENT '店铺编号',
|
||||||
|
`is_deal` varchar(1) NOT NULL DEFAULT '0' COMMENT '是否处理完成,1:是,0:否',
|
||||||
|
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '新建时间',
|
||||||
|
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`sycn_specs_id`) USING BTREE,
|
||||||
|
KEY `index_store_id` (`store_id`) USING BTREE,
|
||||||
|
KEY `index_is_deal` (`is_deal`) USING BTREE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='多规格数据表';
|
||||||
Loading…
Reference in New Issue
Block a user