商品同步新增映射功能
This commit is contained in:
parent
f694db11e9
commit
d2791afab2
@ -33,8 +33,8 @@ public class SinglePushController {
|
||||
return "success";
|
||||
}
|
||||
|
||||
@PostMapping("/pushTocid")
|
||||
public CommonResult pushTocid(@RequestParam String userId, @RequestParam String message) {
|
||||
@PostMapping("/pushTo")
|
||||
public CommonResult pushTo(@RequestParam String userId, @RequestParam String message) {
|
||||
log.info("pushTocid");
|
||||
return accountSinglePushService.pushTocid(message, userId);
|
||||
}
|
||||
|
||||
@ -42,6 +42,8 @@ public class StateCode {
|
||||
public static final int PRODUCT_STATE_NORMAL = 1001; //正常
|
||||
public static final int PRODUCT_STATE_OFF_THE_SHELF = 1002; //下架
|
||||
|
||||
public static final int PRODUCT_STATE_OFF_THE_SHELF_UNCHECK = 1003; //同步数据的状态,下架未分配商品
|
||||
|
||||
public static final int DEMAND_STATE_CONDUCT = 1000; //采购中
|
||||
public static final int DEMAND_STATE_REJECT = 1030; //被驳回
|
||||
public static final int DEMAND_STATE_EXAMINE = 1040; //审核中
|
||||
|
||||
@ -26,6 +26,8 @@ public enum DicEnum {
|
||||
|
||||
YESORNO_0("0", "否","yesOrno","是否","是否"),
|
||||
YESORNO_1("1", "是","yesOrno","是否","是否"),
|
||||
|
||||
GOODS_UN_SYNC_SX("1", "白条猪","unSyncGoodsSX","思迅非同步商品","白条猪"),
|
||||
;
|
||||
;
|
||||
private String code;
|
||||
|
||||
@ -14,6 +14,8 @@ import lombok.experimental.Accessors;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import static com.baomidou.mybatisplus.annotation.FieldStrategy.NOT_EMPTY;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 商品规格表
|
||||
@ -36,24 +38,33 @@ public class ShopBaseProductSpec implements Serializable {
|
||||
private Integer spec_id;
|
||||
|
||||
@ApiModelProperty(value = "规格类别名称")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String spec_name;
|
||||
|
||||
@ApiModelProperty(value = "规格类别注释")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String spec_remark;
|
||||
|
||||
@ApiModelProperty(value = "显示类型(ENUM): text-文字; image-图片")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String spec_format;
|
||||
|
||||
@ApiModelProperty(value = "排序")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer spec_order;
|
||||
|
||||
@ApiModelProperty(value = "规格分类编号:不是商品类型编号,选择分类,可关联到任意级分类。(可以使用一级分类category_id,只在后台快捷定位中起作用) - 不用新建分类表管理。")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer spec_category_id;
|
||||
|
||||
@ApiModelProperty(value = "系统内置(ENUM):1-是; 0-否 | 系统内置不可删除 默认安装中会添加一个默认颜色规格")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer spec_buildin;
|
||||
|
||||
@ApiModelProperty(value = "规格属性")
|
||||
@TableField(exist = false)
|
||||
private List<ShopProductSpecItem> specItems;
|
||||
|
||||
@ApiModelProperty(value = "所属店铺")
|
||||
private Integer store_id;
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.suisung.mall.common.modules.base;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
@ -11,6 +12,8 @@ import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import static com.baomidou.mybatisplus.annotation.FieldStrategy.NOT_EMPTY;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 商品类型表-强调共性,类别cat是强调区别.
|
||||
@ -33,39 +36,51 @@ public class ShopBaseProductType implements Serializable {
|
||||
private Integer type_id;
|
||||
|
||||
@ApiModelProperty(value = "类型名称")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String type_name;
|
||||
|
||||
@ApiModelProperty(value = "备注")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String type_remark;
|
||||
|
||||
@ApiModelProperty(value = "是否启用辅助属性(ENUM):1-是; 0-否")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer type_is_assist;
|
||||
|
||||
@ApiModelProperty(value = "是否启用参数(ENUM):1-是; 0-否")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer type_is_param;
|
||||
|
||||
@ApiModelProperty(value = "是否启用品牌(ENUM):1-是; 0-否")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer type_is_brand;
|
||||
|
||||
@ApiModelProperty(value = "是否启用实体商品(ENUM):1-是; 0-否")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer type_is_entity;
|
||||
|
||||
@ApiModelProperty(value = "分类编号-可关联到任意级分类。(可以使用一级分类category_id,只在后台快捷定位中起作用) - 要取消快捷定位功能,通过UI交互来更好实现")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer type_category_id;
|
||||
|
||||
@ApiModelProperty(value = "是否草稿(ENUM):1-草稿;0-发布")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer type_is_draft;
|
||||
|
||||
@ApiModelProperty(value = "规格id(DOT)")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String type_spec_ids;
|
||||
|
||||
@ApiModelProperty(value = "品牌编号")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String type_brand_ids;
|
||||
|
||||
@ApiModelProperty(value = "辅助属性(DOT)")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String type_assist_ids;
|
||||
|
||||
@ApiModelProperty(value = "系统内置(ENUM):1-内置; 0-非内置")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer type_buildin;
|
||||
|
||||
}
|
||||
|
||||
@ -15,6 +15,8 @@ import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static com.baomidou.mybatisplus.annotation.FieldStrategy.NOT_EMPTY;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 商品基础表-SPU表
|
||||
@ -28,7 +30,7 @@ import java.util.List;
|
||||
@Accessors(chain = true)
|
||||
@TableName("shop_product_base")
|
||||
@ApiModel(value = "ShopProductBase对象", description = "商品基础表-SPU表")
|
||||
public class ShopProductBase implements Serializable {
|
||||
public class ShopProductBase implements Serializable{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ -76,9 +78,11 @@ public class ShopProductBase implements Serializable {
|
||||
private Integer layout_route_id;
|
||||
|
||||
@ApiModelProperty(value = "商品审核(ENUM):3001-审核通过;3002-审核中;3000-审核未通过")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer product_verify_id;
|
||||
|
||||
@ApiModelProperty(value = "商品状态(LIST):1001-正常;1002-下架仓库中;1000-违规禁售")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer product_state_id;
|
||||
|
||||
@ApiModelProperty(value = "库存锁定(ENUM):1001-下单锁定;1002-支付锁定;")
|
||||
@ -130,5 +134,21 @@ public class ShopProductBase implements Serializable {
|
||||
@TableField(exist = false)
|
||||
private List<ShopProductItem> productItems;
|
||||
|
||||
//在同步数据的时候,生鲜需要按平台的规格拆分售卖,这些主要记录原始数据,总重量一般为kg,KG,公斤
|
||||
@ApiModelProperty(value = "总量单位")
|
||||
private String unit_name;
|
||||
|
||||
@ApiModelProperty(value = "总重量")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private BigDecimal shop_weight;
|
||||
|
||||
@ApiModelProperty(value = "单价")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private BigDecimal unit_price;
|
||||
|
||||
@ApiModelProperty(value = "商品分类编号,通过type决定规格,但是分类下的规格值都不同")
|
||||
@TableField(exist = false)
|
||||
private Integer categoryId;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ import java.util.Date;
|
||||
@Accessors(chain = true)
|
||||
@TableName("shop_product_comment")
|
||||
@ApiModel(value = "ShopProductComment对象", description = "商品评价表")
|
||||
public class ShopProductComment implements Serializable {
|
||||
public class ShopProductComment implements Serializable{
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.suisung.mall.common.modules.product;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
@ -12,6 +13,8 @@ import lombok.experimental.Accessors;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static com.baomidou.mybatisplus.annotation.FieldStrategy.NOT_EMPTY;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 商品信息表
|
||||
@ -34,54 +37,74 @@ public class ShopProductInfo implements Serializable {
|
||||
private Long product_id;
|
||||
|
||||
@ApiModelProperty(value = "SPU商家编码:货号")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String product_number;
|
||||
|
||||
@ApiModelProperty(value = "商品条形码")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String product_barcode;
|
||||
|
||||
@ApiModelProperty(value = "商品型号")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String product_model;
|
||||
|
||||
@ApiModelProperty(value = "属性(JSON) - 辅助属性及VAL")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String product_assist;
|
||||
|
||||
@ApiModelProperty(value = "规格(JSON)-规格、规格值、goods_id")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String product_spec;
|
||||
|
||||
@ApiModelProperty(value = "规格类别编号")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String spec_ids;
|
||||
|
||||
@ApiModelProperty(value = "商品SKU(JSON):{'uniq_id':[item_id, price, url]}")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String product_uniqid;
|
||||
|
||||
@ApiModelProperty(value = "长度单位")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer unit_length_id;
|
||||
|
||||
@ApiModelProperty(value = "重量单位")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer unit_weight_id;
|
||||
|
||||
@ApiModelProperty(value = "商品重量")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private BigDecimal product_weight;
|
||||
|
||||
@ApiModelProperty(value = "尺寸长 x 宽 x 高(DOT):商品体积")
|
||||
private String product_cubage;
|
||||
|
||||
@ApiModelProperty(value = "扣减库存")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer product_subtract;
|
||||
|
||||
@ApiModelProperty(value = "计量单位")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer unit_type_id;
|
||||
|
||||
@ApiModelProperty(value = "商品税别:商品税率可以按照商品分类来设置")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer tax_class_id;
|
||||
|
||||
@ApiModelProperty(value = "每人限购")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer product_buy_limit;
|
||||
|
||||
@ApiModelProperty(value = "参加会员等级折扣")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer product_user_level_discount;
|
||||
|
||||
@ApiModelProperty(value = "参加店铺发放的会员卡折扣")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer product_shop_card_discount;
|
||||
|
||||
// @ApiModelProperty(value = "产品名称")
|
||||
// @TableField(exist=false)
|
||||
// private String productName;
|
||||
|
||||
}
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
package com.suisung.mall.common.modules.product;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.Version;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
@ -13,6 +10,8 @@ import lombok.experimental.Accessors;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static com.baomidou.mybatisplus.annotation.FieldStrategy.NOT_EMPTY;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 商品表-SKU表 商品名称(产品名称+颜色规格名称) =shop_product_item
|
||||
@ -47,27 +46,34 @@ public class ShopProductItem implements Serializable {
|
||||
private Long color_id;
|
||||
|
||||
@ApiModelProperty(value = "是否为默认展示的商品-列表页展示,必须为item_enable")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer item_is_default;
|
||||
|
||||
@ApiModelProperty(value = "SKU商家编码:SKU商家编码为非必填项,若不填写,系统会自动生成一个SKU商家编码。")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String item_number;
|
||||
|
||||
@ApiModelProperty(value = "条形码")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String item_barcode;
|
||||
|
||||
@ApiModelProperty(value = "成本价")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private BigDecimal item_cost_price;
|
||||
|
||||
@ApiModelProperty(value = "平台价")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private BigDecimal item_platform_price;
|
||||
|
||||
@ApiModelProperty(value = "商品建议零售价")
|
||||
private BigDecimal item_advice_price;
|
||||
|
||||
@ApiModelProperty(value = "商品价格")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private BigDecimal item_unit_price;
|
||||
|
||||
@ApiModelProperty(value = "市场价")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private BigDecimal item_market_price;
|
||||
|
||||
@ApiModelProperty(value = "积分价格")
|
||||
@ -77,24 +83,31 @@ public class ShopProductItem implements Serializable {
|
||||
private BigDecimal item_unit_sp;
|
||||
|
||||
@ApiModelProperty(value = "商品库存")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer item_quantity;
|
||||
|
||||
@ApiModelProperty(value = "商品冻结库存")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer item_quantity_frozen;
|
||||
|
||||
@ApiModelProperty(value = "库存预警值")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer item_warn_quantity;
|
||||
|
||||
@ApiModelProperty(value = "商品规格序列化(JSON):{spec_id:spec_item_id, spec_id:spec_item_id, spec_id:spec_item_id}")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String item_spec;
|
||||
|
||||
@ApiModelProperty(value = "商品规格值编号")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private String spec_item_ids;
|
||||
|
||||
@ApiModelProperty(value = "是否启用(LIST):1001-正常;1002-下架仓库中;1000-违规禁售")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer item_enable;
|
||||
|
||||
@ApiModelProperty(value = "被改动(BOOL):0-未改动;1-已改动分销使用")
|
||||
@TableField(updateStrategy=NOT_EMPTY)
|
||||
private Integer item_is_change;
|
||||
|
||||
@ApiModelProperty(value = "商品重量")
|
||||
@ -160,4 +173,14 @@ public class ShopProductItem implements Serializable {
|
||||
@Version
|
||||
@ApiModelProperty(value = "乐观锁")
|
||||
private Integer version;
|
||||
|
||||
// @ApiModelProperty(value = "产品名称")
|
||||
// @TableField(exist=false)
|
||||
// private String productName;
|
||||
|
||||
// @ApiModelProperty(value = "商品SKU(JSON):{'uniq_id':[item_id, price, url]}")
|
||||
// @TableField(exist=false)
|
||||
// private String product_uniqid;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.suisung.mall.common.modules.product;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.suisung.mall.common.modules.product;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
@ -10,6 +11,7 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -50,5 +52,24 @@ public class ShopProductSpecItem implements Serializable {
|
||||
@ApiModelProperty(value = "是否启用(BOOL):0-不显示;1-显示")
|
||||
private Integer spec_item_enable;
|
||||
|
||||
@ApiModelProperty(value = "切割后的价格")
|
||||
@TableField(exist=false)
|
||||
private BigDecimal itemPrice;
|
||||
|
||||
@ApiModelProperty(value = "切割后的库存")
|
||||
@TableField(exist=false)
|
||||
private BigDecimal itemQuantity;
|
||||
|
||||
@ApiModelProperty(value = "规格值")
|
||||
@TableField(exist=false)
|
||||
private String item_spec;
|
||||
|
||||
@ApiModelProperty(value = "规格值")
|
||||
@TableField(exist=false)
|
||||
private String product_spec;
|
||||
|
||||
@ApiModelProperty(value = "是否新增,批次使用")
|
||||
@TableField(exist=false)
|
||||
private boolean isUpdate;
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
package com.suisung.mall.common.modules.sync;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import static com.baomidou.mybatisplus.annotation.FieldStrategy.NOT_EMPTY;
|
||||
|
||||
@Data
|
||||
@TableName("product_mapping")
|
||||
@ApiModel("商品映射实体")
|
||||
public class ProductMapping implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id",type = IdType.AUTO)
|
||||
@ApiModelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
@TableField(value = "product_name",updateStrategy=NOT_EMPTY)
|
||||
@NotEmpty(message="商品名称不能为空")
|
||||
@ApiModelProperty("商品名称")
|
||||
private String productName;
|
||||
|
||||
@TableField(value ="store_id",updateStrategy=NOT_EMPTY)
|
||||
@ApiModelProperty(value = "店铺编号")
|
||||
@NotNull(message="店铺编号不能为空")
|
||||
private Integer storeId;
|
||||
|
||||
@TableField(value ="spec_value",updateStrategy=NOT_EMPTY)
|
||||
@ApiModelProperty("规格数据")
|
||||
@NotNull(message="规格数据不能为空")
|
||||
private BigDecimal specValue;
|
||||
|
||||
@TableField(value ="spec_unit",updateStrategy=NOT_EMPTY)
|
||||
@ApiModelProperty("规格单位")
|
||||
@NotEmpty(message="规格单位不能为空")
|
||||
private String specUnit;
|
||||
|
||||
@TableField(value ="description",updateStrategy=NOT_EMPTY)
|
||||
@ApiModelProperty("商品描述")
|
||||
private String description;
|
||||
|
||||
@TableField(value = "sort_order",updateStrategy=NOT_EMPTY)
|
||||
@ApiModelProperty("排序值")
|
||||
private Integer sortOrder;
|
||||
|
||||
|
||||
/**
|
||||
* 生成唯一键:productName + storeId + specValue + specUnit
|
||||
*/
|
||||
public String getUniqueKey() {
|
||||
return String.format("%s|%d|%s|%s",
|
||||
productName,
|
||||
storeId,
|
||||
specValue.stripTrailingZeros().toPlainString(),
|
||||
specUnit);
|
||||
}
|
||||
}
|
||||
@ -4,10 +4,12 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.domain.UserDto;
|
||||
import com.suisung.mall.common.exception.ApiException;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductSpec;
|
||||
import com.suisung.mall.common.modules.product.ShopProductSpecItem;
|
||||
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.shop.base.service.ShopBaseProductSpecService;
|
||||
import com.suisung.mall.shop.product.service.ShopProductSpecItemService;
|
||||
@ -54,6 +56,9 @@ public class ShopBaseProductSpecController {
|
||||
@RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
|
||||
QueryWrapper<ShopBaseProductSpec> queryWrapper = new QueryWrapper<>();
|
||||
UserDto userDto= ContextUtil.getCurrentUser();
|
||||
Integer storeId = Integer.valueOf(userDto.getStore_id());
|
||||
queryWrapper.eq("store_id",storeId);
|
||||
queryWrapper.orderByAsc("spec_id");
|
||||
if (CheckUtil.isNotEmpty(shopBaseProductSpec.getSpec_name())) {
|
||||
queryWrapper.like("spec_name", shopBaseProductSpec.getSpec_name());
|
||||
@ -74,7 +79,10 @@ public class ShopBaseProductSpecController {
|
||||
@RequestParam(value = "spec_category_id", required = false) Integer spec_category_id,
|
||||
@RequestParam(value = "spec_order") Integer spec_order,
|
||||
@RequestParam(value = "spec_id", required = false) Integer spec_id) {
|
||||
UserDto userDto= ContextUtil.getCurrentUser();
|
||||
Integer storeId = Integer.valueOf(userDto.getStore_id());
|
||||
ShopBaseProductSpec shopBaseProductSpec = new ShopBaseProductSpec();
|
||||
shopBaseProductSpec.setStore_id(storeId);
|
||||
shopBaseProductSpec.setSpec_id(spec_id);
|
||||
shopBaseProductSpec.setSpec_name(spec_name);
|
||||
shopBaseProductSpec.setSpec_format(spec_format);
|
||||
@ -92,19 +100,19 @@ public class ShopBaseProductSpecController {
|
||||
@ApiOperation(value = "商品规格表-通过spec_id删除", notes = "商品规格表-通过spec_id删除")
|
||||
@RequestMapping(value = "/delete", method = RequestMethod.POST)
|
||||
public CommonResult delete(@RequestParam(name = "spec_ids") String spec_ids) {
|
||||
List<Integer> specIds = Convert.toList(Integer.class, spec_ids);
|
||||
if (CollUtil.isEmpty(specIds)) {
|
||||
List<Integer> spes = Convert.toList(Integer.class, spec_ids);
|
||||
if (CollUtil.isEmpty(spes)) {
|
||||
throw new ApiException(I18nUtil._("商品规格编号异常!spec_id: ") + spec_ids);
|
||||
}
|
||||
|
||||
QueryWrapper<ShopProductSpecItem> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.in("spec_id", specIds);
|
||||
queryWrapper.in("spec_id", spes);
|
||||
List<Serializable> spec_item_ids = shopProductSpecItemService.findKey(queryWrapper);
|
||||
if (CollUtil.isNotEmpty(spec_item_ids)) {
|
||||
throw new ApiException(String.format(I18nUtil._("不能删除正在被商品规格值表使用的规格!商品规格值编号【%s】"), CollUtil.join(spec_item_ids, ",")));
|
||||
}
|
||||
|
||||
return CommonResult.success(shopBaseProductSpecService.remove(specIds));
|
||||
return CommonResult.success(shopBaseProductSpecService.remove(spes));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "商品规格表-获取分类规格参数", notes = "商品规格表-获取分类规格参数")
|
||||
|
||||
@ -19,4 +19,9 @@ public interface ShopBaseProductSpecService extends IBaseService<ShopBaseProduct
|
||||
Map<String, List<ShopBaseProductSpec>> specMap();
|
||||
|
||||
List<ShopBaseProductSpec> getSpecsByIds(String type_spec_ids, Integer store_id);
|
||||
|
||||
|
||||
Map getShopBaseProductSpecMap(Integer store_id);
|
||||
|
||||
void clearShopBaseProductSpecMap(Integer store_id);
|
||||
}
|
||||
|
||||
@ -1,23 +1,25 @@
|
||||
package com.suisung.mall.shop.base.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.domain.UserDto;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductCategory;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductSpec;
|
||||
import com.suisung.mall.common.modules.product.ShopProductSpecItem;
|
||||
import com.suisung.mall.common.utils.ContextUtil;
|
||||
import com.suisung.mall.common.utils.I18nUtil;
|
||||
import com.suisung.mall.core.web.service.RedisService;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.base.mapper.ShopBaseProductSpecMapper;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductCategoryService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductSpecService;
|
||||
import com.suisung.mall.shop.product.service.ShopProductSpecItemService;
|
||||
import com.suisung.mall.shop.sync.keymanage.RedisKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
@ -37,9 +39,16 @@ public class ShopBaseProductSpecServiceImpl extends BaseServiceImpl<ShopBaseProd
|
||||
@Autowired
|
||||
private ShopProductSpecItemService itemService;
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
@Override
|
||||
public Map<String, List<ShopBaseProductSpec>> specMap() {
|
||||
List<ShopBaseProductSpec> specs = find(new QueryWrapper<>());
|
||||
QueryWrapper<ShopBaseProductSpec> queryWrapper= new QueryWrapper<>();
|
||||
UserDto userDto= ContextUtil.getCurrentUser();
|
||||
Integer store_id = Integer.valueOf(userDto.getStore_id());
|
||||
queryWrapper.eq("store_id",store_id);
|
||||
List<ShopBaseProductSpec> specs = find(queryWrapper);
|
||||
Map<String, List<ShopBaseProductSpec>> map = new HashMap<>();
|
||||
for (ShopBaseProductSpec spec : specs) {
|
||||
if (spec.getSpec_category_id() == 0) {
|
||||
@ -82,4 +91,30 @@ public class ShopBaseProductSpecServiceImpl extends BaseServiceImpl<ShopBaseProd
|
||||
});
|
||||
return specs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map getShopBaseProductSpecMap(Integer store_id) {
|
||||
Map map=new HashMap<>();
|
||||
String redisKey=RedisKey.STOREDATASHOPBASEPRODUCTSPEC+":"+store_id;
|
||||
if(null!=redisService.get(redisKey)){
|
||||
map= (Map) redisService.get(redisKey);
|
||||
}else {
|
||||
QueryWrapper<ShopBaseProductSpec> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("store_id",store_id);
|
||||
List<ShopBaseProductSpec> shopBaseProductSpecList=this.list(queryWrapper);
|
||||
for(ShopBaseProductSpec spec:shopBaseProductSpecList){
|
||||
map.put(String.valueOf(spec.getSpec_category_id()),spec);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(map)) redisService.set(redisKey, map, 60 * 60);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearShopBaseProductSpecMap(Integer store_id) {
|
||||
String redisKey=RedisKey.STOREDATASHOPBASEPRODUCTSPEC+":"+store_id;
|
||||
if(null!=redisService.get(redisKey)){
|
||||
redisService.del(redisKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,8 +85,8 @@ public class ShopBaseProductTypeServiceImpl extends BaseServiceImpl<ShopBaseProd
|
||||
data.put("assists", assistService.getAssistsByIds(shopBaseProductType.getType_assist_ids()));
|
||||
data.put("brands", brandService.getBrandsByIds(shopBaseProductType.getType_brand_ids()));
|
||||
|
||||
Integer store_id = Convert.toInt(userInfoService.getUser().getStore_id());
|
||||
// Integer store_id =1;
|
||||
// Integer store_id = Convert.toInt(userInfoService.getUser().getStore_id());
|
||||
Integer store_id =1;
|
||||
data.put("specs", specService.getSpecsByIds(shopBaseProductType.getType_spec_ids(), store_id));
|
||||
|
||||
|
||||
|
||||
@ -24,4 +24,9 @@ public interface ShopNumberSeqService extends IBaseService<ShopNumberSeq> {
|
||||
void clearRelateGoodsId();
|
||||
void clearKey();
|
||||
|
||||
void batchUpdateSeq(List<ShopNumberSeq> shopNumberSeqList);
|
||||
|
||||
List<Integer> getBatchSpecItemId(int batchSize);
|
||||
|
||||
void clearKeyStoreItemSepcId();
|
||||
}
|
||||
|
||||
@ -3,22 +3,24 @@ package com.suisung.mall.shop.number.service.impl;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.modules.number.ShopNumberSeq;
|
||||
import com.suisung.mall.common.modules.product.ShopProductSpecItem;
|
||||
import com.suisung.mall.core.web.service.RedisService;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.number.mapper.ShopNumberSeqMapper;
|
||||
import com.suisung.mall.shop.number.service.ShopNumberSeqService;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import com.suisung.mall.shop.product.service.ShopProductSpecItemService;
|
||||
import com.suisung.mall.shop.sync.keymanage.RedisKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.LongStream;
|
||||
|
||||
|
||||
@ -40,6 +42,9 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
private RedisService redisService;
|
||||
private String CACHE_PREFIX = "shop_number_seq:%S";
|
||||
|
||||
@Autowired
|
||||
private ShopProductSpecItemService shopProductSpecItemService;
|
||||
|
||||
/**
|
||||
* 得到下一个Id
|
||||
* 方法走到这里会产生串行化,集群部署这里不能使用单机锁
|
||||
@ -185,11 +190,17 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
}
|
||||
log.info("更新成功{}条数据",count);
|
||||
}
|
||||
public void clearKey(){
|
||||
|
||||
public void clearKey(){
|
||||
redisService.del(String.format(CACHE_PREFIX,"item_id"));
|
||||
redisService.del(String.format(CACHE_PREFIX,"product_id"));
|
||||
|
||||
}
|
||||
|
||||
public void clearKeyStoreItemSepcId(){
|
||||
redisService.del(RedisKey.STOREDATASPECITEMID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除缓存,专门给并发使用,防止redis的缓存没有加载
|
||||
*/
|
||||
@ -223,4 +234,35 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
}
|
||||
edit(seq);
|
||||
}
|
||||
|
||||
/**
|
||||
* 存的是最大值,取的是范围,如存最大值1,批量是2,则取范围【1+1,1+2】,如果没有则从1开始算即取范围[0+1,0+2]
|
||||
* @param batchSize
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public synchronized List<Integer> getBatchSpecItemId(int batchSize) {
|
||||
int start=0;
|
||||
if(null!=redisService.get(RedisKey.STOREDATASPECITEMID)){
|
||||
start=(Integer) redisService.get(RedisKey.STOREDATASPECITEMID);
|
||||
redisService.set(RedisKey.STOREDATASPECITEMID,start+batchSize);
|
||||
}
|
||||
QueryWrapper<ShopProductSpecItem> queryWrapper= new QueryWrapper<>();
|
||||
queryWrapper.select("max(spec_item_id) as spec_item_id");
|
||||
ShopProductSpecItem shopProductSpecItem=shopProductSpecItemService.getOne(queryWrapper);
|
||||
if(null!=shopProductSpecItem){
|
||||
start=shopProductSpecItem.getSpec_item_id();
|
||||
redisService.set(RedisKey.STOREDATASPECITEMID,start+batchSize);
|
||||
}
|
||||
if(start==0){
|
||||
redisService.set(RedisKey.STOREDATASPECITEMID,start+batchSize);
|
||||
return IntStream.rangeClosed(start+1, start+batchSize).boxed().collect(Collectors.toList());
|
||||
}
|
||||
return IntStream.rangeClosed(start+1, start+batchSize).boxed().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.printf(IntStream.rangeClosed(1, 1).boxed().collect(Collectors.toList()).toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -66,7 +66,8 @@ public class ShopProductSpecItemController extends BaseControllerImpl {
|
||||
public CommonResult specItems(ShopProductSpecItem shopProductSpecItem) {
|
||||
|
||||
UserDto user = getCurrentUser();
|
||||
Integer store_id = Convert.toInt(user.getStore_id());
|
||||
//Integer store_id = Convert.toInt(user.getStore_id());
|
||||
Integer store_id = 1;
|
||||
QueryWrapper<ShopProductSpecItem> queryWrapper = new QueryWrapper<>();
|
||||
|
||||
Integer spec_id = shopProductSpecItem.getSpec_id();
|
||||
@ -86,7 +87,8 @@ public class ShopProductSpecItemController extends BaseControllerImpl {
|
||||
@RequestMapping(value = "/edit", method = RequestMethod.POST)
|
||||
public CommonResult edit(ShopProductSpecItem shopProductSpecItem) {
|
||||
UserDto user = getCurrentUser();
|
||||
shopProductSpecItem.setStore_id(Integer.valueOf(user.getStore_id()));
|
||||
// shopProductSpecItem.setStore_id(Integer.valueOf(user.getStore_id()));
|
||||
shopProductSpecItem.setStore_id(1);
|
||||
return CommonResult.success(shopProductSpecItemService.saveOrUpdate(shopProductSpecItem));
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import com.suisung.mall.common.modules.product.ShopProductSpecItem;
|
||||
import com.suisung.mall.core.web.service.IBaseService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -17,4 +18,8 @@ import java.util.List;
|
||||
public interface ShopProductSpecItemService extends IBaseService<ShopProductSpecItem> {
|
||||
|
||||
List<ShopProductSpecItem> getItems(QueryWrapper<ShopProductSpecItem> queryWrapper);
|
||||
|
||||
Map<String,Integer> getExistItem(Integer storeId);
|
||||
|
||||
void clearExistItem(Integer storeId);
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ import com.suisung.mall.common.modules.sixun.SxSyncGoods;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreActivityBase;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreActivityItem;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreBase;
|
||||
import com.suisung.mall.common.modules.sync.ProductMapping;
|
||||
import com.suisung.mall.common.modules.user.ShopUserCart;
|
||||
import com.suisung.mall.common.modules.user.ShopUserFavoritesItem;
|
||||
import com.suisung.mall.common.modules.user.ShopUserProductBrowse;
|
||||
@ -65,13 +66,12 @@ import com.suisung.mall.shop.product.pojo.vo.ProductVo;
|
||||
import com.suisung.mall.shop.product.service.*;
|
||||
import com.suisung.mall.shop.sixun.service.SxSyncGoodsService;
|
||||
import com.suisung.mall.shop.store.service.*;
|
||||
import com.suisung.mall.shop.sync.Utils.BatchInsertUtils;
|
||||
import com.suisung.mall.shop.sync.Utils.ProductPriceCalculator;
|
||||
import com.suisung.mall.shop.sync.Utils.ShopJsonUtils;
|
||||
import com.suisung.mall.shop.sync.service.ProductMappingService;
|
||||
import com.suisung.mall.shop.user.service.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.bouncycastle.jcajce.provider.symmetric.util.BaseMac;
|
||||
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -83,8 +83,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
@ -210,8 +208,11 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
|
||||
@Autowired
|
||||
private PlatformTransactionManager transactionManager;
|
||||
|
||||
@Autowired
|
||||
private SqlSessionFactory sqlSessionFactory;
|
||||
private ProductMappingService productMappingService;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean trySaveProduct(String productObj, String productItems) {
|
||||
@ -459,14 +460,16 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
spec_rows = JSONArray.parseArray(JSON.toJSONString(productSpecList));
|
||||
}
|
||||
|
||||
for (Object spec_row : spec_rows) {
|
||||
JSONObject _spec_row = (JSONObject) spec_row;
|
||||
String spec_format = Convert.toStr(_spec_row.get("spec_format"));
|
||||
if ("image".equals(spec_format)) {
|
||||
// 存在图片规格
|
||||
spec_img_flag = true;
|
||||
buildin_spec_id = Convert.toInt(_spec_row.get("id"), Convert.toInt(_spec_row.get("spec_id"), 0));
|
||||
break;
|
||||
if(null!=spec_rows){
|
||||
for (Object spec_row : spec_rows) {
|
||||
JSONObject _spec_row = (JSONObject) spec_row;
|
||||
String spec_format = Convert.toStr(_spec_row.get("spec_format"));
|
||||
if ("image".equals(spec_format)) {
|
||||
// 存在图片规格
|
||||
spec_img_flag = true;
|
||||
buildin_spec_id = Convert.toInt(_spec_row.get("id"), Convert.toInt(_spec_row.get("spec_id"), 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5313,7 +5316,6 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
// 已存在商品,设置ID并加入更新列表
|
||||
Long existId = existingProducts.get(key);
|
||||
base.setProduct_id(existId);
|
||||
|
||||
shopProductBaseList.get(i).setProduct_id(existId);
|
||||
//shopProductIndexList.get(i).setProduct_id(existId);
|
||||
// shopProductIndexList.get(i).setProduct_unit_points(BigDecimal.ZERO);
|
||||
@ -5357,13 +5359,11 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
if(CollUtil.isNotEmpty(shopProductAssistIndexList)){
|
||||
updateShopProductAssistIndexList.add(shopProductAssistIndexList.get(i));
|
||||
}
|
||||
|
||||
updateProducts.add(base);
|
||||
|
||||
} else {
|
||||
base.setProduct_verify_id(StateCode.PRODUCT_VERIFY_PASSED);//审核通过
|
||||
base.setProduct_state_id(StateCode.PRODUCT_STATE_OFF_THE_SHELF);//下架状态
|
||||
|
||||
// base.setProduct_state_id("StateCode.PRODUCT_STATE_OFF_THE_SHELF");//下架状态
|
||||
shopProductIndexList.get(i).setProduct_unit_points(BigDecimal.ZERO);
|
||||
shopProductIndexList.get(i).setProduct_unit_price_max(base.getProduct_market_price());
|
||||
shopProductIndexList.get(i).setProduct_unit_sp(Convert.toBigDecimal(base.getProduct_unit_sp()));
|
||||
@ -5376,7 +5376,7 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
shopProductIndexList.get(i).setStore_type(1);
|
||||
shopProductIndexList.get(i).setSubsite_id(0);
|
||||
shopProductIndexList.get(i).setProduct_number(base.getProduct_number());
|
||||
|
||||
base.setProduct_market_price(base.getProduct_unit_price());
|
||||
if(CollUtil.isNotEmpty(shopProductIndexList)){
|
||||
newShopProductIndexList.add(shopProductIndexList.get(i));
|
||||
}
|
||||
@ -5447,8 +5447,11 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
List<Serializable> udpateItemIds = new ArrayList<>();
|
||||
List<ShopProductItem> addShopProductItems=new ArrayList<>();
|
||||
List<ShopProductItem> updateShopProductItems=new ArrayList<>();
|
||||
int taskCount = 2;
|
||||
CountDownLatch latch = new CountDownLatch(taskCount);
|
||||
|
||||
List<ShopProductSpecItem> addShopProductSpecItems=new ArrayList<>();
|
||||
List<ShopProductSpecItem> updateShopProductSpecItems=new ArrayList<>();
|
||||
// int taskCount = 2;
|
||||
// CountDownLatch latch = new CountDownLatch(taskCount);
|
||||
// 1. 批量新增
|
||||
if (CollUtil.isNotEmpty(newProducts)) {
|
||||
// 4. 批量生成新商品的ID
|
||||
@ -5466,7 +5469,16 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
newShopProductDataList.get(i).setProduct_id(productId);
|
||||
newShopProductDetailList.get(i).setProduct_id(productId);
|
||||
newShopProductInfoList.get(i).setProduct_id(productId);
|
||||
|
||||
// newShopProductInfoList.get(i).setProductName(newProducts.get(i).getProduct_name());
|
||||
//计算规格
|
||||
// ShopProductSpecItem shopProductSpecItem=processShopProductSpecItem(base);
|
||||
// if(null!=shopProductSpecItem){
|
||||
// if(shopProductSpecItem.isUpdate()){
|
||||
// updateShopProductSpecItems.add(shopProductSpecItem);
|
||||
// }else {
|
||||
// addShopProductSpecItems.add(shopProductSpecItem);
|
||||
// }
|
||||
// }
|
||||
// 处理商品项
|
||||
List<ShopProductItem> items = newShopProductItemList.get(i);
|
||||
processProductItems(items, productId, addItemSeqs);
|
||||
@ -5488,11 +5500,10 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
shopProductAnalytics.setProduct_click(0);
|
||||
addAnalyticsList.add(shopProductAnalytics);
|
||||
}
|
||||
List<Serializable> itemIds = processProductItemsId(addShopProductItems, addItemSeqs);
|
||||
List<Serializable> itemIds = processProductItemsId(addShopProductItems, addItemSeqs,newShopProductInfoList);
|
||||
addItemIds.addAll(itemIds);
|
||||
// 2. 批量更新
|
||||
if (CollUtil.isNotEmpty(newProducts)) {
|
||||
// new Thread(() -> {
|
||||
logger.info("保存任务开始执行");
|
||||
try {
|
||||
long startTime=System.nanoTime();
|
||||
@ -5500,17 +5511,10 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
long endTime = System.nanoTime();
|
||||
long duration = (endTime - startTime);
|
||||
logger.info("新增newProducts--{}条数据耗时:{}",newProducts.size(),duration/1000000000);
|
||||
latch.countDown();
|
||||
} catch (Exception e) {
|
||||
latch.countDown();
|
||||
logger.error("系统异常"+e.getMessage());
|
||||
}
|
||||
// }).start();
|
||||
}else{
|
||||
// latch.countDown();
|
||||
}
|
||||
}else {
|
||||
//latch.countDown();
|
||||
}
|
||||
if (CollUtil.isNotEmpty(updateProducts)) {
|
||||
for(int i=0;i<updateProducts.size();i++){
|
||||
@ -5524,7 +5528,16 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
updateShopProductDataList.get(i).setProduct_id(productId);
|
||||
updateShopProductDetailList.get(i).setProduct_id(productId);
|
||||
updateShopProductInfoList.get(i).setProduct_id(productId);
|
||||
|
||||
//updateShopProductInfoList.get(i).setProductName(updateProducts.get(i).getProduct_name());
|
||||
//计算规格
|
||||
// ShopProductSpecItem shopProductSpecItem=processShopProductSpecItem(base);
|
||||
// if(null!=shopProductSpecItem){
|
||||
// if(shopProductSpecItem.isUpdate()){
|
||||
// updateShopProductSpecItems.add(shopProductSpecItem);
|
||||
// }else {
|
||||
// addShopProductSpecItems.add(shopProductSpecItem);
|
||||
// }
|
||||
// }
|
||||
// 处理商品项
|
||||
List<ShopProductItem> items = udpateShopProductItemList.get(i);
|
||||
processProductItems(items, productId, updateItemSeqs);//
|
||||
@ -5548,11 +5561,10 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
shopProductAnalytics.setProduct_click(0);
|
||||
udpateAnalyticsList.add(shopProductAnalytics);
|
||||
}
|
||||
List<Serializable> itemIds = processProductItemsId(updateShopProductItems, updateItemSeqs);
|
||||
List<Serializable> itemIds = processProductItemsId(updateShopProductItems, updateItemSeqs,newShopProductInfoList);
|
||||
udpateItemIds.addAll(itemIds);
|
||||
// 2. 批量更新
|
||||
if (CollUtil.isNotEmpty(updateProducts)) {
|
||||
// new Thread(() -> {
|
||||
logger.info("更新任务开始执行");
|
||||
try {
|
||||
long startTime=System.nanoTime();
|
||||
@ -5560,25 +5572,25 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
long endTime = System.nanoTime();
|
||||
long duration = (endTime - startTime);
|
||||
logger.info("更新updateProducts-{}条数据耗时:{}",updateProducts.size(),duration/1000000000);
|
||||
latch.countDown();
|
||||
} catch (Exception e) {
|
||||
latch.countDown();
|
||||
logger.error("系统异常"+e.getMessage());
|
||||
}
|
||||
// }).start();
|
||||
}else {
|
||||
//latch.countDown();
|
||||
}
|
||||
}else {
|
||||
// latch.countDown();
|
||||
}
|
||||
// latch.await();
|
||||
// 3. 处理其他表的批量操作(同样需要区分新增和更新)
|
||||
batchProcessOtherTables(newShopProductIndexList,updateShopProductIndexList,newShopProductDataList,updateShopProductDataList,
|
||||
newShopProductDetailList,updateShopProductDetailList,newShopProductInfoList,updateShopProductInfoList,
|
||||
newShopProductValidPeriodList,updateShopProductValidPeriodList,addShopProductItems,updateShopProductItems,
|
||||
addAnalyticsList,udpateAnalyticsList,addItemSeqs,updateItemSeqs);
|
||||
logger.info("处理成功,新增{}条,更新{}条", newProducts.size(), updateProducts.size());
|
||||
|
||||
//计算规格
|
||||
if(CollUtil.isNotEmpty(newProducts)){
|
||||
productMappingService.computeProductMapping(newProducts,newProducts.get(0).getStore_id(),false);
|
||||
}
|
||||
if(CollUtil.isNotEmpty(updateProducts)){
|
||||
productMappingService.computeProductMapping(updateProducts,updateProducts.get(0).getStore_id(),true);
|
||||
}
|
||||
return Pair.of(true, String.format("处理成功,新增%d条,更新%d条",
|
||||
newProducts.size(), updateProducts.size()));
|
||||
} catch (RuntimeException e) {
|
||||
@ -5586,14 +5598,7 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
logger.error("批量操作异常", e);
|
||||
return Pair.of(false, "批量操作异常: " + e.getMessage());
|
||||
}
|
||||
// catch (InterruptedException e) {
|
||||
// status.setRollbackOnly();
|
||||
// logger.error("批量操作异常", e);
|
||||
// return Pair.of(false, "批量操作异常: " + e.getMessage());
|
||||
// }
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 批量保存操作
|
||||
@ -5784,6 +5789,7 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
logger.info("更新updateShopProductItemSeqList-{}条数据耗时:{}",updateShopProductItemSeqList.size(),duration/1000000000);
|
||||
// }
|
||||
}
|
||||
|
||||
}catch (RuntimeException e){
|
||||
logger.info("批量报错附表失败{}",e.getMessage());
|
||||
}
|
||||
@ -5801,35 +5807,104 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
* @param itemSeqs
|
||||
* @return
|
||||
*/
|
||||
private List<Serializable> processProductItemsId(List<ShopProductItem> items,List<ShopProductItemSeq> itemSeqs){
|
||||
private List<Serializable> processProductItemsId(List<ShopProductItem> items,List<ShopProductItemSeq> itemSeqs,
|
||||
List<ShopProductInfo> newShopProductInfoList){
|
||||
List<Serializable> itemIds = new ArrayList<>();
|
||||
if (CollUtil.isEmpty(items)) return itemIds;
|
||||
List<Long> generatedIds = shopNumberSeqService.batchCreateNextNo("item_id", items.size());
|
||||
// Map<String,String> cacheMap=new HashMap<>();
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
Long itemId = generatedIds.get(i);
|
||||
ShopProductItem item = items.get(i);
|
||||
item.setItem_id(itemId);
|
||||
// if(StringUtils.isNotEmpty(item.getItem_spec())){
|
||||
// String product_uniqid=ShopJsonUtils.generateJsonWithOrgJson(item.getSpec_item_ids(),new Object[]{itemId,item.getItem_unit_price(),"",1002});
|
||||
// cacheMap.put(item.getProductName(),product_uniqid);
|
||||
// }
|
||||
itemIds.add(itemId);
|
||||
ShopProductItemSeq field_row= itemSeqs.get(i);
|
||||
field_row.setItem_id(itemId);
|
||||
|
||||
}
|
||||
|
||||
// for(ShopProductInfo shopProductInfo:newShopProductInfoList){
|
||||
// if(ObjectUtil.isNotEmpty(cacheMap.get(shopProductInfo.getProductName()))){
|
||||
// String product_uniqid=cacheMap.get(shopProductInfo.getProductName());
|
||||
// shopProductInfo.setProduct_uniqid(product_uniqid);
|
||||
// }
|
||||
// }
|
||||
return itemIds;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 计算并产生规格 与商品配置表匹配,匹配正确则新增规格商品
|
||||
// * @return
|
||||
// */
|
||||
// private ShopProductSpecItem processShopProductSpecItem(ShopProductBase base){
|
||||
// Map shopProductSpecItemMap = shopProductSpecItemService.getExistItem(base.getStore_id());
|
||||
// Map productMappingMap = productMappingService.getProductMapping();
|
||||
// Map ShopBaseProductSpecMap = baseProductSpecService.getShopBaseProductSpecMap(base.getStore_id());
|
||||
// String productName=base.getProduct_name();
|
||||
//
|
||||
// if(null!=productMappingMap.get(productName)){
|
||||
// Integer specId= (Integer) ShopBaseProductSpecMap.get(base.getProduct_name()+"规格");
|
||||
// ProductMapping productMapping= (ProductMapping) productMappingMap.get(productName);
|
||||
// String Spec_item_name=productMapping.getProductName()+productMapping.getSpecValue()+productMapping.getSpecUnit();//规格名称
|
||||
// Integer Spec_item_id= (Integer) shopProductSpecItemMap.get(Spec_item_name);
|
||||
// ShopProductSpecItem addShopProductSpecItem=new ShopProductSpecItem();
|
||||
// addShopProductSpecItem.setUpdate(true);
|
||||
// if(ObjectUtil.isEmpty(Spec_item_id)){
|
||||
// Spec_item_id=shopNumberSeqService.getSpecItemId();
|
||||
// addShopProductSpecItem.setUpdate(false);
|
||||
// }
|
||||
// addShopProductSpecItem.setStore_id(base.getStore_id());
|
||||
// addShopProductSpecItem.setCategory_id(base.getCategoryId());
|
||||
// addShopProductSpecItem.setSpec_item_id(Spec_item_id);
|
||||
// addShopProductSpecItem.setSpec_id(specId);//根据规格获取
|
||||
// addShopProductSpecItem.setSpec_item_name(Spec_item_name);
|
||||
// addShopProductSpecItem.setSpec_item_enable(1);//上架
|
||||
// addShopProductSpecItem.setSpec_item_order("10");
|
||||
// BigDecimal[] bigDecimals= ProductPriceCalculator.calculatePriceAndQuantity(base.getUnit_price(),base.getShop_weight(),productMapping.getSpecValue(),productMapping.getSpecUnit());
|
||||
// addShopProductSpecItem.setItemPrice(bigDecimals[0]);
|
||||
// addShopProductSpecItem.setItemQuantity(bigDecimals[1]);
|
||||
// List<Map<String, Object>> items=new ArrayList<>();
|
||||
// Map<String,Object> item=new HashMap<>();
|
||||
// item.put("name",addShopProductSpecItem.getSpec_item_name());//规格列表
|
||||
// item.put("id",Spec_item_id);
|
||||
// items.add(item);
|
||||
// List<Map<String, Object>> specItems=new ArrayList<>();
|
||||
// Map<String,Object> specItem=new HashMap<>();
|
||||
// specItem.put("name",base.getProduct_name()+"规格");//规格名称
|
||||
// specItem.put("id",specId);
|
||||
// specItems.add(specItem);
|
||||
// String item_spec=ShopJsonUtils.generateJsonWithOrgJson(items,specItems);
|
||||
// addShopProductSpecItem.setItem_spec(item_spec);
|
||||
// // addShopProductSpecItem.setProduct_uniqid(product_uniqid);
|
||||
// return addShopProductSpecItem;
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
|
||||
// 处理商品项
|
||||
private void processProductItems(List<ShopProductItem> items, Long productId,
|
||||
List<ShopProductItemSeq> itemSeqs) {
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
ShopProductItem item = items.get(i);
|
||||
// item.setProductName(productName);
|
||||
item.setProduct_id(productId);
|
||||
String item_spec = item.getItem_spec();
|
||||
// if(null!=shopProductSpecItem){
|
||||
// item_spec=shopProductSpecItem.getItem_spec();
|
||||
// if(isUpdate){
|
||||
// item.setItem_unit_price(shopProductSpecItem.getItemPrice());
|
||||
// }else {
|
||||
// item.setItem_unit_price(shopProductSpecItem.getItemPrice());
|
||||
// item.setItem_market_price(shopProductSpecItem.getItemPrice());
|
||||
// }
|
||||
// }
|
||||
// itemIds.add(itemId);
|
||||
|
||||
// item.setItem_quantity(null);
|
||||
// ITEM_ID/SKU唯一编号表。
|
||||
// product_id + sort(spec_item_id) = 构造唯一ITEM ID
|
||||
String item_spec = item.getItem_spec();
|
||||
cn.hutool.json.JSONArray array_item_spec = cn.hutool.json.JSONUtil.parseArray(item_spec);
|
||||
List<Integer> spec_item_ids = new ArrayList<>();
|
||||
List<String> item_names = new ArrayList<>();
|
||||
@ -5840,12 +5915,9 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
if (ObjectUtil.isNotNull(id)) spec_item_ids.add(id);
|
||||
item_names.add(name);
|
||||
}
|
||||
|
||||
if (CollUtil.isNotEmpty(spec_item_ids)) Collections.sort(spec_item_ids);
|
||||
|
||||
//用来判断是否使用
|
||||
item.setSpec_item_ids(CollUtil.join(spec_item_ids, ","));
|
||||
|
||||
// 创建itemSeq记录
|
||||
String skuUniqid = generateSkuUniqid(item); // 生成SKU唯一标识
|
||||
String seqVal = productId + ":" + skuUniqid;
|
||||
@ -6080,16 +6152,5 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// private void myShopProductBaseBatch(List<ShopProductBase> list){
|
||||
// SqlSession sqlSession=sqlSessionFactory.openSession();
|
||||
// StopWatch stopWatch=new StopWatch();
|
||||
// stopWatch.start();
|
||||
// shopProductBaseService.saveBatch(list);
|
||||
// sqlSession.commit();
|
||||
// stopWatch.stop();
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,13 +1,20 @@
|
||||
package com.suisung.mall.shop.product.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.modules.product.ShopProductSpecItem;
|
||||
import com.suisung.mall.core.web.service.RedisService;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.product.mapper.ShopProductSpecItemMapper;
|
||||
import com.suisung.mall.shop.product.service.ShopProductSpecItemService;
|
||||
import com.suisung.mall.shop.sync.keymanage.RedisKey;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
@ -20,8 +27,39 @@ import java.util.List;
|
||||
*/
|
||||
@Service
|
||||
public class ShopProductSpecItemServiceImpl extends BaseServiceImpl<ShopProductSpecItemMapper, ShopProductSpecItem> implements ShopProductSpecItemService {
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
@Override
|
||||
public List<ShopProductSpecItem> getItems(QueryWrapper<ShopProductSpecItem> queryWrapper) {
|
||||
return find(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map getExistItem(Integer storeId) {
|
||||
Map map=new HashMap<>();
|
||||
String redisKey=RedisKey.STOREDATAPRODUCTSPECITEM+"storeId:"+storeId;
|
||||
if(null!=redisService.get(redisKey)){
|
||||
map=(Map)redisService.get(redisKey);
|
||||
return map;
|
||||
}
|
||||
QueryWrapper<ShopProductSpecItem> queryWrapper=new QueryWrapper<>();
|
||||
queryWrapper.eq("store_id",storeId);
|
||||
List<ShopProductSpecItem> list= list(queryWrapper);
|
||||
for(ShopProductSpecItem shopProductSpecItem:list){
|
||||
map.put(shopProductSpecItem.getSpec_item_name(),shopProductSpecItem.getSpec_item_id());
|
||||
}
|
||||
if (CollUtil.isNotEmpty(map)) redisService.set(redisKey, map, 60 * 60);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearExistItem(Integer storeId) {
|
||||
String redisKey=RedisKey.STOREDATAPRODUCTSPECITEM+"storeId:"+storeId;
|
||||
if(null!=redisService.get(redisKey)){
|
||||
redisService.del(redisKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package com.suisung.mall.shop.sync.Utils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class BigDecimalFormatter {
|
||||
public static String formatWithoutTrailingZeros(BigDecimal number) {
|
||||
if (number == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 去除末尾0并转换为普通字符串表示
|
||||
BigDecimal stripped = number.stripTrailingZeros();
|
||||
String result = stripped.toPlainString();
|
||||
|
||||
// 处理结果为负0的情况(返回"0"而不是"-0")
|
||||
if (result.startsWith("-0")) {
|
||||
if (result.indexOf('.') == -1) {
|
||||
if (result.length() == 2) { // "-0"
|
||||
return "0";
|
||||
} else if (result.matches("-0+")) { // "-000"
|
||||
return "0";
|
||||
}
|
||||
} else if (result.matches("-0\\.0*")) { // "-0.0" 或 "-0.00"
|
||||
return "0";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
package com.suisung.mall.shop.sync.Utils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
public class ProductPriceCalculator {
|
||||
/**
|
||||
* 计算切割后的商品单价和数量
|
||||
* @param unitPricePerKg 千克单价(元/千克)
|
||||
* @param totalWeightKg 总重量(千克)
|
||||
* @param pieceWeight 切割单位重量(数值)
|
||||
* @param weightUnit 重量单位("g"=克,"kg"=千克)
|
||||
* @return 包含两个元素的数组:[切割后单价(元/单位), 完整单位数量]
|
||||
*/
|
||||
public static BigDecimal[] calculatePriceAndQuantity(
|
||||
BigDecimal unitPricePerKg,
|
||||
BigDecimal totalWeightKg,
|
||||
BigDecimal pieceWeight,
|
||||
String weightUnit) {
|
||||
|
||||
// 参数校验
|
||||
if (unitPricePerKg == null || totalWeightKg == null || pieceWeight == null) {
|
||||
throw new IllegalArgumentException("参数不能为空");
|
||||
}
|
||||
if (unitPricePerKg.compareTo(BigDecimal.ZERO) <= 0 ||
|
||||
pieceWeight.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new IllegalArgumentException("单价和切割重量必须大于0");
|
||||
}
|
||||
if (!"g".equalsIgnoreCase(weightUnit) && !"kg".equalsIgnoreCase(weightUnit)) {
|
||||
throw new IllegalArgumentException("单位必须是'g'或'kg'");
|
||||
}
|
||||
|
||||
// 将切割单位统一转换为千克
|
||||
BigDecimal pieceWeightInKg = "g".equalsIgnoreCase(weightUnit) ?
|
||||
pieceWeight.divide(BigDecimal.valueOf(1000), 10, RoundingMode.HALF_UP) :
|
||||
pieceWeight;
|
||||
|
||||
// 计算切割后单价(不受总重量影响)
|
||||
BigDecimal piecePrice = unitPricePerKg.multiply(pieceWeightInKg)
|
||||
.setScale(2, RoundingMode.HALF_UP); // 保留两位小数
|
||||
|
||||
// 特殊处理:总重量为负数时,数量固定返回99
|
||||
if (totalWeightKg.compareTo(BigDecimal.ZERO) < 0) {
|
||||
return new BigDecimal[]{piecePrice, BigDecimal.valueOf(99)};
|
||||
}
|
||||
|
||||
// 计算完整单位数量(向下取整)
|
||||
BigDecimal quantity = totalWeightKg.divide(pieceWeightInKg, 0, RoundingMode.FLOOR);
|
||||
|
||||
return new BigDecimal[]{piecePrice, quantity};
|
||||
}
|
||||
|
||||
// 示例用法
|
||||
public static void main(String[] args) {
|
||||
// 正常情况示例
|
||||
BigDecimal[] result1 = calculatePriceAndQuantity(
|
||||
new BigDecimal("30"),
|
||||
new BigDecimal("5"),
|
||||
new BigDecimal("500"),
|
||||
"g");
|
||||
System.out.println("正常情况 - 单价: " + result1[0] + " 元/单位, 数量: " + result1[1]);
|
||||
|
||||
// 总重量为负数示例
|
||||
BigDecimal[] result2 = calculatePriceAndQuantity(
|
||||
new BigDecimal("25"),
|
||||
new BigDecimal("-3.5"), // 负数总重量
|
||||
new BigDecimal("250"),
|
||||
"g");
|
||||
System.out.println("负总重量 - 单价: " + result2[0] + " 元/单位, 数量: " + result2[1]);
|
||||
|
||||
// 千克单位示例
|
||||
BigDecimal[] result3 = calculatePriceAndQuantity(
|
||||
new BigDecimal("100"),
|
||||
new BigDecimal("2.5"),
|
||||
new BigDecimal("0.5"),
|
||||
"kg");
|
||||
System.out.println("千克单位 - 单价: " + result3[0] + " 元/单位, 数量: " + result3[1]);
|
||||
|
||||
// 总重量不足一个单位示例
|
||||
BigDecimal[] result4 = calculatePriceAndQuantity(
|
||||
new BigDecimal("40"),
|
||||
new BigDecimal("0.3"),
|
||||
new BigDecimal("0.5"),
|
||||
"kg");
|
||||
System.out.println("不足单位 - 单价: " + result4[0] + " 元/单位, 数量: " + result4[1]);
|
||||
|
||||
/* 预期输出:
|
||||
正常情况 - 单价: 15.00 元/单位, 数量: 10
|
||||
负总重量 - 单价: 6.25 元/单位, 数量: 99
|
||||
千克单位 - 单价: 50.00 元/单位, 数量: 5
|
||||
不足单位 - 单价: 20.00 元/单位, 数量: 0
|
||||
*/
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package com.suisung.mall.shop.sync.Utils;
|
||||
|
||||
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ShopJsonUtils {
|
||||
|
||||
/**
|
||||
*shop_item的item_spec生成
|
||||
* 使用org.json库(需要org.json依赖)
|
||||
* @param items 规格项列表
|
||||
* @param specItems 规格大类
|
||||
* @return JSON字符串
|
||||
*/
|
||||
public static String generateJsonWithOrgJsonItemSpec(List<Map<String, Object>> items,
|
||||
List<Map<String, Object>> specItems) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (int i = 0; i < Math.min(items.size(), specItems.size()); i++) {
|
||||
JSONObject itemObj = new JSONObject();
|
||||
itemObj.put("name", items.get(i).get("name"));
|
||||
itemObj.put("id", items.get(i).get("id"));
|
||||
|
||||
JSONObject categoryObj = new JSONObject();
|
||||
categoryObj.put("item", itemObj);
|
||||
categoryObj.put("name", specItems.get(i).get("name"));
|
||||
categoryObj.put("id", specItems.get(i).get("id"));
|
||||
|
||||
jsonArray.put(categoryObj);
|
||||
}
|
||||
return jsonArray.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*shop_index的product_spec生成,
|
||||
* 使用org.json库(需要org.json依赖)
|
||||
* @param items 规格项列表
|
||||
* @param specItems 规格大类
|
||||
* @return JSON字符串
|
||||
*/
|
||||
public static String generateJsonWithOrgJsonProducSpec(List<Map<String, Object>> items,
|
||||
List<Map<String, Object>> specItems) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (int i = 0; i < Math.min(items.size(), specItems.size()); i++) {
|
||||
JSONArray specItemObj = new JSONArray();
|
||||
JSONObject itemObj = new JSONObject();
|
||||
itemObj.put("name", items.get(i).get("name"));
|
||||
itemObj.put("id", items.get(i).get("id"));
|
||||
specItemObj.put(itemObj);
|
||||
JSONObject categoryObj = new JSONObject();
|
||||
categoryObj.put("item", specItemObj);
|
||||
categoryObj.put("name", specItems.get(i).get("name"));
|
||||
categoryObj.put("id", specItems.get(i).get("id"));
|
||||
|
||||
jsonArray.put(categoryObj);
|
||||
}
|
||||
return jsonArray.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* shop_index 的product_uniqid生成
|
||||
* 使用org.json库生成JSON(无需Gson依赖)
|
||||
* @param key 主键 规格列表id
|
||||
* @param values 值数组
|
||||
* @return JSON字符串
|
||||
*/
|
||||
public static String generateJsonWithOrgJson(String key, Object[] values) {
|
||||
// 参数校验
|
||||
if (values == null || values.length != 4) {
|
||||
throw new IllegalArgumentException("值数组必须包含4个元素");
|
||||
}
|
||||
|
||||
JSONObject jsonObj = new JSONObject();
|
||||
org.json.JSONArray jsonArray = new org.json.JSONArray();
|
||||
jsonArray.put(values[0]); // 整数
|
||||
jsonArray.put(values[1]); // 浮点数
|
||||
jsonArray.put(values[2]); // 字符串
|
||||
jsonArray.put(values[3]); // 整数
|
||||
|
||||
jsonObj.put(key, jsonArray);
|
||||
return jsonObj.toString();
|
||||
}
|
||||
}
|
||||
@ -18,7 +18,7 @@ public class ClientController {
|
||||
@Autowired
|
||||
private SyncThirdDataService syncThirdDataService;
|
||||
|
||||
@ApiOperation(value = "下载客户端应用", notes = "获取加密密钥")
|
||||
@ApiOperation(value = "下载客户端应用", notes = "下载客户端应用")
|
||||
@RequestMapping(value = "/downClientJar",produces = MediaType.APPLICATION_OCTET_STREAM_VALUE, method = RequestMethod.GET)
|
||||
public ResponseEntity<Resource> downClientJar(@RequestParam String primaryKey,String clienVersionName) {
|
||||
return syncThirdDataService.downloadToClient(primaryKey,clienVersionName);
|
||||
|
||||
@ -0,0 +1,220 @@
|
||||
package com.suisung.mall.shop.sync.controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.api.IErrorCode;
|
||||
import com.suisung.mall.common.modules.sync.ProductMapping;
|
||||
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
||||
import com.suisung.mall.shop.sync.exelModel.ImportResult;
|
||||
import com.suisung.mall.shop.sync.service.ProductMappingService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/admin/shop/shop-sync-productMapper")
|
||||
@lombok.extern.slf4j.Slf4j
|
||||
public class ProductMappingController extends BaseControllerImpl {
|
||||
|
||||
|
||||
@Autowired
|
||||
private ProductMappingService productMappingService;
|
||||
|
||||
@Value("${file.upload-dir}")
|
||||
private String uploadDir;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
* @param pageNum
|
||||
* @param pageSize
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "列表查询-分页列表查询商品映射实体", notes = "列表查询-分页列表查询商品映射实体")
|
||||
@RequestMapping(value = "/list", method = RequestMethod.GET)
|
||||
public CommonResult list(@RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
|
||||
ProductMapping productMapping=new ProductMapping();
|
||||
productMapping.setProductName(getParameter("productName"));
|
||||
productMapping.setStoreId(getParameter("storeId",Integer.class));
|
||||
return productMappingService.findPageProductMapping(productMapping,pageNum,pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单笔获取
|
||||
* @param productMapping
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "单笔获取-商品映射实体", notes = "单笔获取-商品映射实体")
|
||||
@RequestMapping(value = "/getProductMapping", method = RequestMethod.GET)
|
||||
public CommonResult getProductMapping(@RequestBody ProductMapping productMapping) {
|
||||
if (productMapping == null|| null==productMapping.getId()) {
|
||||
return CommonResult.failed("id不能为空");
|
||||
}
|
||||
return CommonResult.success(productMappingService.getById(productMapping.getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增
|
||||
* @param productMapping
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "新增-店商品映射实体", notes = "新增-商品映射实体")
|
||||
@RequestMapping(value = "/saveProductMapping", method = RequestMethod.POST)
|
||||
public CommonResult saveProductMapping(@Valid @RequestBody ProductMapping productMapping, BindingResult result) {
|
||||
if(result.hasErrors()) {
|
||||
return CommonResult.failed(Objects.requireNonNull(result.getFieldError()).getDefaultMessage());
|
||||
}
|
||||
return productMappingService.saveProductMapping(productMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "批量新增-店商品映射实体", notes = "批量新增-商品映射实体")
|
||||
@RequestMapping(value = "/saveProductMappingBatch", method = RequestMethod.POST)
|
||||
public CommonResult saveProductMappingBatch(@RequestBody JSONArray jsonProductMappings) {
|
||||
if(jsonProductMappings==null|| jsonProductMappings.isEmpty()){
|
||||
return CommonResult.failed("数据不能为空");
|
||||
}
|
||||
Gson gson = new Gson();
|
||||
List<ProductMapping> productMappings= gson.fromJson(jsonProductMappings.toString(),new TypeToken<List<ProductMapping>>(){}.getType());
|
||||
productMappingService.saveBatch(productMappings,productMappings.size());
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新
|
||||
* @param productMapping
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "更新-商品映射实体", notes = "更新-商品映射实体")
|
||||
@RequestMapping(value = "/udpateProductMapping", method = RequestMethod.PUT)
|
||||
public CommonResult udpateProductMapping(@RequestBody ProductMapping productMapping) {
|
||||
if(productMapping==null|| null==productMapping.getId()) {
|
||||
return CommonResult.failed("缺少必要参数");
|
||||
}
|
||||
if(ObjectUtil.isNotEmpty(productMappingService.getById(productMapping.getId()))) {
|
||||
if(productMappingService.saveOrUpdate(productMapping)){
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
}else {
|
||||
return CommonResult.failed("不存在更新参数");
|
||||
}
|
||||
return CommonResult.failed("更新失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param productMapping
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "删除-商品映射实体", notes = "删除-商品映射实体")
|
||||
@RequestMapping(value = "/delProductMapping", method = RequestMethod.DELETE)
|
||||
public CommonResult delProductMapping(@RequestBody ProductMapping productMapping) {
|
||||
if(productMapping==null|| null==productMapping.getId()) {
|
||||
return CommonResult.failed("缺少必要参数");
|
||||
}
|
||||
if(ObjectUtil.isNotEmpty(productMappingService.getById(productMapping.getId()))) {
|
||||
if(productMappingService.removeById(productMapping.getId())){
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
}else {
|
||||
return CommonResult.failed("不存在更新参数");
|
||||
}
|
||||
return CommonResult.failed("删除失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动计算并上架商品
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "自动计算并上架商品", notes = "自动计算并上架商品")
|
||||
@RequestMapping(value = "/syncProductMaping", method = RequestMethod.PUT)
|
||||
public CommonResult syncProductMaping() {
|
||||
return productMappingService.syncAllProductMapping();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找为同步未分配的商品数据,批量手填
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "查找为同步的商品数据", notes = "删除查找为同步的商品数据")
|
||||
@RequestMapping(value = "/getSyncBaseMapingProducts", method = RequestMethod.GET)
|
||||
public CommonResult getSyncBaseMapingProducts() {
|
||||
return productMappingService.getSyncProductUnchecked();
|
||||
}
|
||||
|
||||
/**
|
||||
* 模板下载
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "导入模板下载", notes = "模板下载")
|
||||
@RequestMapping(value = "/template", method = RequestMethod.GET)
|
||||
public void downloadTemplate(HttpServletResponse response) {
|
||||
productMappingService.downloadTemplate(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入数据
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "模板数据导入", notes = "模板数据导入")
|
||||
@RequestMapping(value = "/importData", method = RequestMethod.POST)
|
||||
public CommonResult importData(@RequestParam("file") MultipartFile file) {
|
||||
ImportResult result = productMappingService.importData(file);
|
||||
return !result.getErrorMessages().isEmpty() ?CommonResult.failed((IErrorCode) result.getErrorMessages()):CommonResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出筛选数据
|
||||
* @param ids
|
||||
* @param response
|
||||
*/
|
||||
@PostMapping("/exportSelected")
|
||||
public void exportSelectedData(@RequestBody List<Long> ids, HttpServletResponse response) {
|
||||
List<ProductMapping> data = productMappingService.listByIds(ids);
|
||||
productMappingService.exportData(response, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载错误报告
|
||||
* @param file
|
||||
* @param response
|
||||
*/
|
||||
@GetMapping("/download")
|
||||
public void downloadFile(@RequestParam String file, HttpServletResponse response) {
|
||||
try {
|
||||
Path filePath = Paths.get(uploadDir, file);
|
||||
if (!Files.exists(filePath)) {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
response.setContentType("application/octet-stream");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + file);
|
||||
Files.copy(filePath, response.getOutputStream());
|
||||
response.getOutputStream().flush();
|
||||
} catch (IOException e) {
|
||||
log.error("下载文件失败", e);
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -12,6 +12,8 @@ import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.modules.sync.StoreDbConfig;
|
||||
import com.suisung.mall.common.modules.sync.SyncApp;
|
||||
import com.suisung.mall.common.modules.sync.SyncFileLog;
|
||||
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
||||
import com.suisung.mall.core.web.controller.BaseController;
|
||||
import com.suisung.mall.shop.sync.service.StoreDbConfigService;
|
||||
import com.suisung.mall.shop.sync.service.SyncFileLogService;
|
||||
import io.swagger.annotations.Api;
|
||||
@ -30,23 +32,26 @@ import org.springframework.web.bind.annotation.*;
|
||||
@Api(tags = "页面导航表-店铺数据库连接配置")
|
||||
@RestController
|
||||
@RequestMapping("/admin/shop/shop-sync-storeDbConfig")
|
||||
public class StoreDbConfigController {
|
||||
public class StoreDbConfigController extends BaseControllerImpl {
|
||||
|
||||
@Autowired
|
||||
private StoreDbConfigService storeDbConfigService;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
* @param storeDbConfig
|
||||
* @param
|
||||
* @param pageNum
|
||||
* @param pageSize
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "列表查询-分页列表查询店铺数据库连接配置", notes = "列表查询-分页列表查询店铺数据库连接配置")
|
||||
@RequestMapping(value = "/list", method = RequestMethod.GET)
|
||||
public CommonResult list(@RequestBody StoreDbConfig storeDbConfig ,
|
||||
@RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
|
||||
public CommonResult list(@RequestParam(name = "pageNum", defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
|
||||
StoreDbConfig storeDbConfig=new StoreDbConfig();
|
||||
storeDbConfig.setStoreId(getParameter("storeId"));
|
||||
storeDbConfig.setHasInternet(getParameter("hasInternet"));
|
||||
storeDbConfig.setHasStart(getParameter("hasStart"));
|
||||
return storeDbConfigService.findStoreDbConfigPageList(storeDbConfig, pageNum, pageSize);
|
||||
}
|
||||
|
||||
|
||||
@ -107,12 +107,7 @@ public class SyncThirdDataController {
|
||||
@RequestParam String appKey,
|
||||
@RequestParam String sign,
|
||||
@RequestParam String syncType) {
|
||||
// new Thread(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
syncThirdDataService.SyncReadSxFileData(appKey,sign,syncType,folders);
|
||||
// }
|
||||
// }).start();
|
||||
syncThirdDataService.SyncReadSxFileData(appKey,sign,syncType,folders);
|
||||
return new ThirdApiRes().success("服务器已处理文件");
|
||||
}
|
||||
|
||||
@ -150,4 +145,5 @@ public class SyncThirdDataController {
|
||||
return syncThirdDataService.getStoreDataRelease(appKey,sign);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
package com.suisung.mall.shop.sync.excleHandle;
|
||||
|
||||
import com.alibaba.excel.metadata.Head;
|
||||
import com.alibaba.excel.metadata.data.WriteCellData;
|
||||
import com.alibaba.excel.write.handler.AbstractCellWriteHandler;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
|
||||
import org.apache.poi.ss.usermodel.BorderStyle;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ExportStyleHandler extends AbstractCellWriteHandler {
|
||||
|
||||
// 设置数据行样式
|
||||
@Override
|
||||
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
|
||||
List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex,
|
||||
Boolean isHead) {
|
||||
if (isHead) {
|
||||
// 表头样式
|
||||
CellStyle cellStyle = cell.getSheet().getWorkbook().createCellStyle();
|
||||
Font font = cell.getSheet().getWorkbook().createFont();
|
||||
font.setBold(true);
|
||||
cellStyle.setFont(font);
|
||||
cell.setCellStyle(cellStyle);
|
||||
} else {
|
||||
// 数据行样式 - 设置边框
|
||||
CellStyle cellStyle = cell.getSheet().getWorkbook().createCellStyle();
|
||||
cellStyle.setBorderTop(BorderStyle.THIN);
|
||||
cellStyle.setBorderBottom(BorderStyle.THIN);
|
||||
cellStyle.setBorderLeft(BorderStyle.THIN);
|
||||
cellStyle.setBorderRight(BorderStyle.THIN);
|
||||
cell.setCellStyle(cellStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.suisung.mall.shop.sync.excleHandle;
|
||||
|
||||
import com.alibaba.excel.metadata.Head;
|
||||
import com.alibaba.excel.metadata.data.WriteCellData;
|
||||
import com.alibaba.excel.write.handler.AbstractCellWriteHandler;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
|
||||
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TemplateStyleHandler extends AbstractCellWriteHandler {
|
||||
|
||||
// 设置表头样式
|
||||
@Override
|
||||
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
|
||||
List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex,
|
||||
Boolean isHead) {
|
||||
if (isHead) {
|
||||
// 设置表头背景色
|
||||
CellStyle cellStyle = cell.getSheet().getWorkbook().createCellStyle();
|
||||
Font font = cell.getSheet().getWorkbook().createFont();
|
||||
font.setBold(true);
|
||||
font.setColor(IndexedColors.WHITE.getIndex());
|
||||
cellStyle.setFont(font);
|
||||
cellStyle.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex());
|
||||
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
cell.setCellStyle(cellStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package com.suisung.mall.shop.sync.exelModel;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ImportResult {
|
||||
private int totalCount; // 总记录数
|
||||
private int successCount; // 成功记录数
|
||||
private int failCount; // 失败记录数
|
||||
private int insertCount; // 新增记录数
|
||||
private int updateCount; // 更新记录数
|
||||
private List<String> errorMessages; // 错误信息
|
||||
private String downloadUrl; // 错误报告下载URL
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.suisung.mall.shop.sync.exelModel;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.suisung.mall.common.modules.sync.ProductMapping;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class ProductMappingExcel {
|
||||
@ExcelProperty(value = "商品名称", index = 0)
|
||||
private String productName;
|
||||
|
||||
@ExcelProperty(value = "店铺编号", index = 1)
|
||||
private Integer storeId;
|
||||
|
||||
@ExcelProperty(value = "规格数据", index = 2)
|
||||
private BigDecimal specValue;
|
||||
|
||||
@ExcelProperty(value = "规格单位", index = 3)
|
||||
private String specUnit;
|
||||
|
||||
@ExcelProperty(value = "商品描述", index = 4)
|
||||
private String description;
|
||||
|
||||
@ExcelProperty(value = "排序值", index = 5)
|
||||
private Integer sortOrder;
|
||||
|
||||
// 转换为实体对象
|
||||
public ProductMapping toEntity() {
|
||||
ProductMapping entity = new ProductMapping();
|
||||
entity.setProductName(this.productName);
|
||||
entity.setStoreId(this.storeId);
|
||||
entity.setSpecValue(this.specValue);
|
||||
entity.setSpecUnit(this.specUnit);
|
||||
entity.setDescription(this.description);
|
||||
entity.setSortOrder(this.sortOrder);
|
||||
return entity;
|
||||
}
|
||||
|
||||
// 从实体对象转换
|
||||
public static ProductMappingExcel fromEntity(ProductMapping entity) {
|
||||
ProductMappingExcel excel = new ProductMappingExcel();
|
||||
excel.setProductName(entity.getProductName());
|
||||
excel.setStoreId(entity.getStoreId());
|
||||
excel.setSpecValue(entity.getSpecValue());
|
||||
excel.setSpecUnit(entity.getSpecUnit());
|
||||
excel.setDescription(entity.getDescription());
|
||||
excel.setSortOrder(entity.getSortOrder());
|
||||
return excel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一键:productName + storeId + specValue + specUnit
|
||||
*/
|
||||
public String getUniqueKey() {
|
||||
return String.format("%s|%d|%s|%s",
|
||||
productName,
|
||||
storeId,
|
||||
specValue.stripTrailingZeros().toPlainString(),
|
||||
specUnit);
|
||||
}
|
||||
}
|
||||
@ -5,4 +5,14 @@ public class RedisKey {
|
||||
//public static final String SXCLIENTKEYVERSION="sxclientKey:version";//客户端版本
|
||||
|
||||
public static final String STOREDATARELEASE="storedata:release";
|
||||
|
||||
public static final String STOREDATAPRODUCTMAPING="storedata:productMaping";
|
||||
|
||||
public static final String STOREDATASHOPBASEPRODUCTSPEC="storedata:shopBaseProductSpec";
|
||||
|
||||
|
||||
public static final String STOREDATASPECITEMID="storedata:SpecItemId";
|
||||
|
||||
public static final String STOREDATAPRODUCTSPECITEM="storedata:ProductSpecItem";
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
package com.suisung.mall.shop.sync.mapper;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.suisung.mall.common.modules.sync.ProductMapping;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface ProductMappingMapper extends BaseMapper<ProductMapping> {
|
||||
|
||||
List<ProductMapping> findPageProductMapping(Page<ProductMapping> page);
|
||||
|
||||
Integer getCount();
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.suisung.mall.shop.sync.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.modules.product.ShopProductBase;
|
||||
import com.suisung.mall.common.modules.sync.ProductMapping;
|
||||
import com.suisung.mall.shop.sync.exelModel.ImportResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ProductMappingService extends IService<ProductMapping> {
|
||||
|
||||
CommonResult findPageProductMapping(ProductMapping productMapping,Integer pageNum,Integer pageSize);
|
||||
|
||||
void computeProductMapping(List<ShopProductBase> shopProductBaseList,Integer storeId, boolean isUpdate);
|
||||
|
||||
Map getProductMapping(Integer storeId);
|
||||
|
||||
CommonResult syncAllProductMapping();
|
||||
|
||||
CommonResult getSyncProductUnchecked();
|
||||
|
||||
// 下载导入模板
|
||||
void downloadTemplate(HttpServletResponse response);
|
||||
|
||||
// 导入Excel数据
|
||||
ImportResult importData(MultipartFile file);
|
||||
|
||||
// 导出数据到Excel
|
||||
void exportData(HttpServletResponse response, List<ProductMapping> data);
|
||||
|
||||
|
||||
// 保存数据
|
||||
CommonResult saveProductMapping(ProductMapping data);
|
||||
|
||||
}
|
||||
@ -0,0 +1,699 @@
|
||||
/*
|
||||
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
|
||||
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
|
||||
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
|
||||
* Vestibulum commodo. Ut rhoncus gravida arcu.
|
||||
*/
|
||||
|
||||
package com.suisung.mall.shop.sync.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.api.StateCode;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductSpec;
|
||||
import com.suisung.mall.common.modules.product.*;
|
||||
import com.suisung.mall.common.modules.sync.ProductMapping;
|
||||
|
||||
import com.suisung.mall.common.utils.ContextUtil;
|
||||
import com.suisung.mall.common.utils.StringUtils;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductSpecService;
|
||||
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.BigDecimalFormatter;
|
||||
import com.suisung.mall.shop.sync.Utils.ProductPriceCalculator;
|
||||
import com.suisung.mall.shop.sync.Utils.ShopJsonUtils;
|
||||
import com.suisung.mall.shop.sync.excleHandle.ExportStyleHandler;
|
||||
import com.suisung.mall.shop.sync.excleHandle.TemplateStyleHandler;
|
||||
import com.suisung.mall.shop.sync.exelModel.ImportResult;
|
||||
import com.suisung.mall.shop.sync.exelModel.ProductMappingExcel;
|
||||
import com.suisung.mall.shop.sync.mapper.ProductMappingMapper;
|
||||
import com.suisung.mall.shop.sync.service.*;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.ValidationException;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Slf4j
|
||||
public class ProductMappingServiceImpl extends BaseServiceImpl<ProductMappingMapper, ProductMapping> implements ProductMappingService {
|
||||
|
||||
@Autowired
|
||||
private ShopProductBaseService shopProductBaseService;
|
||||
@Autowired
|
||||
private ShopProductItemService shopProductItemService;
|
||||
@Autowired
|
||||
private ShopProductInfoService shopProductInfoService;
|
||||
|
||||
@Autowired
|
||||
private ShopProductSpecItemService shopProductSpecItemService;
|
||||
@Autowired
|
||||
private ShopBaseProductSpecService baseProductSpecService;
|
||||
|
||||
@Autowired
|
||||
private ShopNumberSeqService shopNumberSeqService;
|
||||
|
||||
@Autowired
|
||||
private ShopProductIndexService shopProductIndexService;
|
||||
|
||||
@Autowired
|
||||
private ProductMappingService productMappingService;
|
||||
|
||||
@Value("${file.upload-dir}")
|
||||
private String uploadDir;
|
||||
|
||||
private static final String TEMPLATE_NAME = "商品映射模板.xlsx";
|
||||
private static final String EXPORT_NAME = "商品映射数据.xlsx";
|
||||
|
||||
private final Integer SHOPBASEPAGE=500;
|
||||
|
||||
@Override
|
||||
public CommonResult findPageProductMapping(ProductMapping productMapping,Integer pageNum,Integer pageSize) {
|
||||
QueryWrapper<ProductMapping> queryWrapper = new QueryWrapper<>();
|
||||
if(StringUtils.isNotEmpty(productMapping.getProductName())){
|
||||
queryWrapper.eq("product_name",productMapping.getProductName());
|
||||
// queryWrapper.and(mapping ->mapping.like("product_name", productMapping.getProductName()));
|
||||
}
|
||||
if(ObjectUtil.isNotEmpty(productMapping.getStoreId())){
|
||||
queryWrapper.and(m->m.eq("store_id",productMapping.getStoreId()).or().eq("store_id",0));
|
||||
// queryWrapper.and(mapping ->mapping.like("product_name", productMapping.getProductName()));
|
||||
}
|
||||
|
||||
return CommonResult.success(this.lists(queryWrapper,pageNum,pageSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeProductMapping(List<ShopProductBase> shopProductBaseList,Integer storeId,boolean isUpdate) {
|
||||
shopProductBaseList= shopProductBaseList.stream().filter(base ->StateCode.PRODUCT_STATE_OFF_THE_SHELF_UNCHECK==(base.getProduct_state_id())).collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(shopProductBaseList)) {
|
||||
log.info("没有规格数据要处理");
|
||||
return;
|
||||
}
|
||||
Map shopProductSpecItemMap = shopProductSpecItemService.getExistItem(storeId);
|
||||
Map productMappingMap = this.getProductMapping(storeId);
|
||||
Map ShopBaseProductSpecMap = baseProductSpecService.getShopBaseProductSpecMap(storeId);
|
||||
dealData(shopProductBaseList,shopProductSpecItemMap,ShopBaseProductSpecMap,productMappingMap,isUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map getProductMapping(Integer storeId) {
|
||||
Map map=new HashMap();
|
||||
QueryWrapper<ProductMapping> queryWrapper= new QueryWrapper<>();
|
||||
//queryWrapper.eq("store_id", storeId);
|
||||
queryWrapper.and(m->m.eq("store_id",storeId).or().eq("store_id",0)).orderByDesc("sort_order");
|
||||
List<ProductMapping> list= this.list(queryWrapper);
|
||||
for (ProductMapping productMapping:list){
|
||||
map.put(productMapping.getProductName(),productMapping);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据,生成规格列表
|
||||
* @param shopProductBaseList
|
||||
* @param shopProductSpecItemMap
|
||||
* @param ShopBaseProductSpecMap
|
||||
* @param productMappingMap
|
||||
*/
|
||||
public void dealData(List<ShopProductBase> shopProductBaseList,Map shopProductSpecItemMap,Map ShopBaseProductSpecMap, Map productMappingMap,boolean isUpdate){
|
||||
List<ShopProductItem> shopProductItems=findShopProductItemsList(shopProductBaseList);
|
||||
List<ShopProductInfo> shopProductInfoList=findShopProductInfoList(shopProductBaseList);
|
||||
List<ShopProductSpecItem> addShopProductSpecItemList=new ArrayList<>();
|
||||
List<ShopProductSpecItem> updateShopProductSpecItemList=new ArrayList<>();
|
||||
|
||||
List<ShopProductBase> updateShopProductBaseList=new ArrayList<>();
|
||||
List<ShopProductItem> updateShopProductItemList=new ArrayList<>();
|
||||
List<ShopProductInfo> updateShopProductInfoList=new ArrayList<>();
|
||||
//找出需要更新的列表
|
||||
for (int i = 0; i < shopProductBaseList.size(); i++){
|
||||
ShopProductSpecItem shopProductSpecItem=processShopProductSpecItem(shopProductBaseList.get(i),shopProductItems.get(i).getCategory_id(),shopProductSpecItemMap,ShopBaseProductSpecMap,productMappingMap,null);
|
||||
if(shopProductSpecItem!=null){
|
||||
shopProductBaseList.get(i).setProduct_state_id(StateCode.PRODUCT_STATE_NORMAL);
|
||||
shopProductItems.get(i).setItem_enable(StateCode.PRODUCT_STATE_NORMAL);
|
||||
shopProductItems.get(i).setItem_is_default(1);
|
||||
if(shopProductSpecItem.isUpdate()){
|
||||
shopProductBaseList.get(i).setProduct_unit_price(shopProductSpecItem.getItemPrice());
|
||||
updateShopProductSpecItemList.add(shopProductSpecItem);
|
||||
}else {
|
||||
shopProductBaseList.get(i).setProduct_unit_price(shopProductSpecItem.getItemPrice());
|
||||
shopProductBaseList.get(i).setProduct_market_price(shopProductSpecItem.getItemPrice());
|
||||
addShopProductSpecItemList.add(shopProductSpecItem);
|
||||
}
|
||||
updateShopProductBaseList.add(shopProductBaseList.get(i));
|
||||
updateShopProductItemList.add(shopProductItems.get(i));
|
||||
updateShopProductInfoList.add(shopProductInfoList.get(i));
|
||||
proccessItemAndInfo(shopProductItems.get(i),shopProductInfoList.get(i),shopProductSpecItem,isUpdate);
|
||||
}
|
||||
}
|
||||
//再次变量根据addShopProductSpecItemList算出id,这样防止多次链接redis
|
||||
if(!addShopProductSpecItemList.isEmpty()){
|
||||
List<Integer> integers= shopNumberSeqService.getBatchSpecItemId(addShopProductSpecItemList.size());
|
||||
int index=0;
|
||||
for (int i = 0; i < shopProductBaseList.size(); i++){
|
||||
if(index==integers.size()){
|
||||
break;
|
||||
}
|
||||
ShopProductSpecItem shopProductSpecItem=processShopProductSpecItem(shopProductBaseList.get(i),shopProductItems.get(i).getCategory_id(),shopProductSpecItemMap,ShopBaseProductSpecMap,productMappingMap,integers.get(index));
|
||||
if(shopProductSpecItem!=null){
|
||||
if(!shopProductSpecItem.isUpdate()){
|
||||
addShopProductSpecItemList.set(index,shopProductSpecItem);
|
||||
index++;
|
||||
}
|
||||
proccessItemAndInfo(shopProductItems.get(i),shopProductInfoList.get(i),shopProductSpecItem,isUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(CollUtil.isNotEmpty(addShopProductSpecItemList)){
|
||||
shopProductSpecItemService.saveBatch(addShopProductSpecItemList,addShopProductSpecItemList.size());
|
||||
}
|
||||
if(CollUtil.isNotEmpty(updateShopProductSpecItemList)){
|
||||
shopProductSpecItemService.updateBatchById(updateShopProductSpecItemList);
|
||||
}
|
||||
if(CollUtil.isNotEmpty(updateShopProductBaseList)){
|
||||
shopProductBaseService.updateBatchById(updateShopProductBaseList);
|
||||
saveShopProductIndexList(updateShopProductBaseList);
|
||||
}
|
||||
if(CollUtil.isNotEmpty(updateShopProductItemList)){
|
||||
shopProductItemService.updateBatchById(updateShopProductItemList);
|
||||
}
|
||||
if(CollUtil.isNotEmpty(updateShopProductInfoList)){
|
||||
shopProductInfoService.updateBatchById(updateShopProductInfoList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param item
|
||||
*/
|
||||
private void proccessItemAndInfo(ShopProductItem item,ShopProductInfo shopProductInfo,ShopProductSpecItem shopProductSpecItem,boolean isUpdate){
|
||||
String item_spec = item.getItem_spec();
|
||||
String productSpec="";
|
||||
if(null!=shopProductSpecItem){
|
||||
item_spec=shopProductSpecItem.getItem_spec();
|
||||
productSpec=shopProductSpecItem.getProduct_spec();
|
||||
if(isUpdate){
|
||||
item.setItem_unit_price(shopProductSpecItem.getItemPrice());
|
||||
}else {
|
||||
item.setItem_unit_price(shopProductSpecItem.getItemPrice());
|
||||
item.setItem_market_price(shopProductSpecItem.getItemPrice());
|
||||
}
|
||||
}
|
||||
JSONArray array_item_spec = JSONUtil.parseArray(item_spec);
|
||||
List<Integer> spec_item_ids = new ArrayList<>();
|
||||
for (Object josn_item_spec : array_item_spec) {
|
||||
JSONObject itemJ = (JSONObject) ((JSONObject) josn_item_spec).get("item");
|
||||
Integer id = Convert.toInt(itemJ.get("id"));
|
||||
if (ObjectUtil.isNotNull(id)) spec_item_ids.add(id);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(spec_item_ids)) Collections.sort(spec_item_ids);
|
||||
//用来判断是否使用
|
||||
item.setSpec_item_ids(CollUtil.join(spec_item_ids, ","));
|
||||
if(StringUtils.isNotEmpty(item_spec)){
|
||||
item.setItem_spec(item_spec);
|
||||
shopProductInfo.setProduct_spec(productSpec);
|
||||
}
|
||||
String product_uniqid=ShopJsonUtils.generateJsonWithOrgJson(item.getSpec_item_ids(),new Object[]{item.getItem_id(),item.getItem_unit_price(),"",1002});
|
||||
shopProductInfo.setProduct_uniqid(product_uniqid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新index状态为正常
|
||||
* @param shopProductBaseList
|
||||
*/
|
||||
private void saveShopProductIndexList(List<ShopProductBase> shopProductBaseList){
|
||||
if (CollUtil.isEmpty(shopProductBaseList)) {
|
||||
return ;
|
||||
}
|
||||
// 使用IN查询优化(根据数据库特性可能需要分批)
|
||||
QueryWrapper<ShopProductIndex> query = new QueryWrapper<>();
|
||||
query.select("product_id", "product_name", "store_id");
|
||||
|
||||
// 构建OR条件 (store_id=X AND product_number=Y) OR (store_id=A AND product_number=B)...
|
||||
shopProductBaseList.forEach(base -> {
|
||||
query.or(q -> q.eq("store_id", base.getStore_id())
|
||||
.eq("product_id", base.getProduct_id()));
|
||||
});
|
||||
List<ShopProductIndex> updateShopProductIndexList= shopProductIndexService.list(query);
|
||||
updateShopProductIndexList.forEach(shopProductIndex -> {
|
||||
shopProductIndex.setProduct_state_id(StateCode.PRODUCT_STATE_NORMAL);
|
||||
});
|
||||
shopProductIndexService.updateBatchById(updateShopProductIndexList);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param shopProductBaseList
|
||||
* @return
|
||||
*/
|
||||
private List<ShopProductItem> findShopProductItemsList(List<ShopProductBase> shopProductBaseList){
|
||||
if (CollUtil.isEmpty(shopProductBaseList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 使用IN查询优化(根据数据库特性可能需要分批)
|
||||
QueryWrapper<ShopProductItem> query = new QueryWrapper<>();
|
||||
query.select("product_id", "store_id", "item_id","item_unit_price","item_unit_price","item_market_price","category_id");
|
||||
|
||||
// 构建OR条件 (store_id=X AND product_number=Y) OR (store_id=A AND product_number=B)...
|
||||
shopProductBaseList.forEach(base -> {
|
||||
query.or(q -> q.eq("store_id", base.getStore_id())
|
||||
.eq("product_id", base.getProduct_id()));
|
||||
});
|
||||
return shopProductItemService.list(query);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param shopProductBaseList
|
||||
* @return
|
||||
*/
|
||||
private List<ShopProductInfo> findShopProductInfoList(List<ShopProductBase> shopProductBaseList){
|
||||
if (CollUtil.isEmpty(shopProductBaseList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 使用IN查询优化(根据数据库特性可能需要分批)
|
||||
QueryWrapper<ShopProductInfo> query = new QueryWrapper<>();
|
||||
query.select("product_id", "product_number", "product_uniqid","product_weight");
|
||||
|
||||
// 构建OR条件 (store_id=X AND product_number=Y) OR (store_id=A AND product_number=B)...
|
||||
shopProductBaseList.forEach(base -> {
|
||||
query.or(q -> q.eq("product_id", base.getProduct_id()));
|
||||
});
|
||||
return shopProductInfoService.list(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算并产生规格 与商品配置表匹配,匹配正确则新增规格商品
|
||||
* @return
|
||||
*/
|
||||
private ShopProductSpecItem processShopProductSpecItem(ShopProductBase base,Integer categoryId,Map shopProductSpecItemMap,Map ShopBaseProductSpecMap, Map productMappingMap,Integer specItemId){
|
||||
String productName=base.getProduct_name();
|
||||
if(null!=productMappingMap.get(productName)){
|
||||
ShopBaseProductSpec shopBaseProductSpec= (ShopBaseProductSpec) ShopBaseProductSpecMap.get(categoryId);
|
||||
if(null==shopBaseProductSpec){
|
||||
shopBaseProductSpec= (ShopBaseProductSpec) ShopBaseProductSpecMap.get(String.valueOf(categoryId));
|
||||
}
|
||||
Integer specId= shopBaseProductSpec.getSpec_id();
|
||||
ProductMapping productMapping= (ProductMapping) productMappingMap.get(productName);
|
||||
String Spec_item_name=productMapping.getProductName()+ BigDecimalFormatter.formatWithoutTrailingZeros(productMapping.getSpecValue())+productMapping.getSpecUnit();//
|
||||
Integer Spec_item_id = null;
|
||||
ShopProductSpecItem addShopProductSpecItem=new ShopProductSpecItem();
|
||||
addShopProductSpecItem.setUpdate(true);
|
||||
if(ObjectUtil.isNotEmpty(shopProductSpecItemMap.get(Spec_item_name))){
|
||||
Spec_item_id= (Integer) shopProductSpecItemMap.get(Spec_item_name);
|
||||
}else {
|
||||
if(ObjectUtil.isNotEmpty(specItemId)){
|
||||
Spec_item_id=specItemId;
|
||||
}
|
||||
addShopProductSpecItem.setUpdate(false);
|
||||
}
|
||||
addShopProductSpecItem.setStore_id(base.getStore_id());
|
||||
addShopProductSpecItem.setCategory_id(categoryId);
|
||||
addShopProductSpecItem.setSpec_item_id(Spec_item_id);
|
||||
addShopProductSpecItem.setSpec_id(specId);//根据规格获取
|
||||
addShopProductSpecItem.setSpec_item_name(Spec_item_name);
|
||||
addShopProductSpecItem.setSpec_item_enable(1);//上架
|
||||
addShopProductSpecItem.setSpec_item_order("10");
|
||||
BigDecimal[] bigDecimals= ProductPriceCalculator.calculatePriceAndQuantity(base.getUnit_price(),base.getShop_weight(),productMapping.getSpecValue(),productMapping.getSpecUnit());
|
||||
addShopProductSpecItem.setItemPrice(bigDecimals[0]);
|
||||
addShopProductSpecItem.setItemQuantity(bigDecimals[1]);
|
||||
List<Map<String, Object>> items=new ArrayList<>();
|
||||
Map<String,Object> item=new HashMap<>();
|
||||
item.put("name",addShopProductSpecItem.getSpec_item_name());//规格列表
|
||||
item.put("id",Spec_item_id);
|
||||
items.add(item);
|
||||
List<Map<String, Object>> specItems=new ArrayList<>();
|
||||
Map<String,Object> specItem=new HashMap<>();
|
||||
specItem.put("name",shopBaseProductSpec.getSpec_name());//规格名称
|
||||
specItem.put("id",specId);
|
||||
specItems.add(specItem);
|
||||
String item_spec= ShopJsonUtils.generateJsonWithOrgJsonItemSpec(items,specItems);
|
||||
String product_spec= ShopJsonUtils.generateJsonWithOrgJsonProducSpec(items,specItems);
|
||||
addShopProductSpecItem.setItem_spec(item_spec);
|
||||
addShopProductSpecItem.setProduct_spec(product_spec);
|
||||
// addShopProductSpecItem.setProduct_uniqid(product_uniqid);
|
||||
return addShopProductSpecItem;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult syncAllProductMapping() {
|
||||
Integer storeId= Integer.valueOf(Objects.requireNonNull(ContextUtil.getCurrentUser()).getStore_id());
|
||||
//找出范围内的规格产品
|
||||
QueryWrapper<ShopProductBase> queryWrapper= new QueryWrapper<>();
|
||||
queryWrapper.eq("product_state_id", StateCode.PRODUCT_STATE_OFF_THE_SHELF_UNCHECK);
|
||||
queryWrapper.eq("store_id", storeId);
|
||||
long total=shopProductBaseService.count(queryWrapper);
|
||||
|
||||
int pages= CommonUtil.getPagesCount(Math.toIntExact(total),SHOPBASEPAGE);
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(6);
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (int i=1;i<=pages;i++){
|
||||
int finalI = i;
|
||||
futures.add(executor.submit(() -> {
|
||||
this.computeProductMapping(shopProductBaseService.lists(queryWrapper, finalI,SHOPBASEPAGE).getRecords(),storeId,false);
|
||||
return "成功" + finalI;
|
||||
}));
|
||||
}
|
||||
// 等待所有任务完成
|
||||
for (Future<?> future : futures) {
|
||||
try {
|
||||
System.out.println("任务结果: " + future.get());
|
||||
} catch (Exception e) {
|
||||
System.err.println("任务执行异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
executor.shutdown();
|
||||
|
||||
shopNumberSeqService.clearKeyStoreItemSepcId();
|
||||
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult getSyncProductUnchecked() {
|
||||
Integer storeId= Integer.valueOf(Objects.requireNonNull(ContextUtil.getCurrentUser()).getStore_id());
|
||||
//找出范围内的规格产品
|
||||
QueryWrapper<ShopProductBase> queryWrapper= new QueryWrapper<>();
|
||||
queryWrapper.eq("product_state_id", StateCode.PRODUCT_STATE_OFF_THE_SHELF_UNCHECK);
|
||||
queryWrapper.eq("store_id", storeId);
|
||||
return CommonResult.success(shopProductBaseService.list(queryWrapper));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadTemplate(HttpServletResponse response) {
|
||||
try {
|
||||
// 设置响应头
|
||||
setExcelResponseHeader(response, TEMPLATE_NAME);
|
||||
|
||||
// 创建空模板
|
||||
EasyExcel.write(response.getOutputStream(), ProductMappingExcel.class)
|
||||
.sheet("商品映射")
|
||||
.registerWriteHandler(new TemplateStyleHandler())
|
||||
.doWrite(new ArrayList<>());
|
||||
} catch (IOException e) {
|
||||
log.error("下载模板失败", e);
|
||||
throw new RuntimeException("下载模板失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImportResult importData(MultipartFile file) {
|
||||
ImportResult result = new ImportResult( 0,0, 0, 0,0, new ArrayList<>(), null);
|
||||
String fileName = storeUploadedFile(file);
|
||||
|
||||
try {
|
||||
// 1. 读取Excel数据
|
||||
List<ProductMappingExcel> excelList = readExcelData(fileName);
|
||||
result.setTotalCount(excelList.size());
|
||||
|
||||
// 2. 构建唯一键映射
|
||||
Map<String, ProductMapping> existingMap = loadExistingMappings(excelList);
|
||||
|
||||
// 3. 处理导入数据
|
||||
List<ProductMapping> toUpdate = new ArrayList<>();
|
||||
List<ProductMapping> toInsert = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < excelList.size(); i++) {
|
||||
ProductMappingExcel excel = excelList.get(i);
|
||||
int rowNum = i + 2; // Excel行号(标题行+1)
|
||||
|
||||
try {
|
||||
// 验证数据
|
||||
validateExcelData(excel, rowNum);
|
||||
|
||||
// 转换为实体
|
||||
ProductMapping entity = excel.toEntity();
|
||||
String uniqueKey = excel.getUniqueKey();
|
||||
|
||||
// 检查是否已存在
|
||||
if (existingMap.containsKey(uniqueKey)) {
|
||||
ProductMapping existing = existingMap.get(uniqueKey);
|
||||
updateExistingEntity(existing, entity);
|
||||
toUpdate.add(existing);
|
||||
result.setUpdateCount(result.getUpdateCount() + 1);
|
||||
} else {
|
||||
toInsert.add(entity);
|
||||
result.setInsertCount(result.getInsertCount() + 1);
|
||||
}
|
||||
|
||||
result.setSuccessCount(result.getSuccessCount() + 1);
|
||||
} catch (ValidationException e) {
|
||||
result.setFailCount(result.getFailCount() + 1);
|
||||
result.getErrorMessages().add(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 批量操作
|
||||
if (!toInsert.isEmpty()) {
|
||||
productMappingService.saveBatch(toInsert,toInsert.size());
|
||||
}
|
||||
if (!toUpdate.isEmpty()) {
|
||||
productMappingService.updateBatchById(toUpdate,toInsert.size());
|
||||
}
|
||||
|
||||
// 5. 生成错误报告(如果有错误)
|
||||
if (result.getFailCount() > 0) {
|
||||
result.setDownloadUrl(generateErrorReport(result.getErrorMessages(), fileName));
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("导入数据失败", e);
|
||||
throw new RuntimeException("导入数据失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportData(HttpServletResponse response, List<ProductMapping> data) {
|
||||
try {
|
||||
// 设置响应头
|
||||
setExcelResponseHeader(response, EXPORT_NAME);
|
||||
|
||||
// 转换为Excel对象
|
||||
List<ProductMappingExcel> excelData = data.stream()
|
||||
.map(ProductMappingExcel::fromEntity)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 导出Excel
|
||||
EasyExcel.write(response.getOutputStream(), ProductMappingExcel.class)
|
||||
.sheet("商品映射数据")
|
||||
.registerWriteHandler(new ExportStyleHandler())
|
||||
.doWrite(excelData);
|
||||
} catch (IOException e) {
|
||||
log.error("导出数据失败", e);
|
||||
throw new RuntimeException("导出数据失败");
|
||||
}
|
||||
}
|
||||
|
||||
// ================ 私有方法 ================
|
||||
// 加载数据库中已存在的映射
|
||||
private Map<String, ProductMapping> loadExistingMappings(List<ProductMappingExcel> excelList) {
|
||||
// 收集所有唯一键
|
||||
Set<String> uniqueKeys = excelList.stream()
|
||||
.map(ProductMappingExcel::getUniqueKey)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (uniqueKeys.isEmpty()) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
// 分批查询数据库(避免SQL过长)
|
||||
int batchSize = 100;
|
||||
Map<String, ProductMapping> resultMap = new HashMap<>();
|
||||
List<String> keyList = new ArrayList<>(uniqueKeys);
|
||||
|
||||
for (int i = 0; i < keyList.size(); i += batchSize) {
|
||||
int end = Math.min(i + batchSize, keyList.size());
|
||||
List<String> batchKeys = keyList.subList(i, end);
|
||||
|
||||
// 构建查询条件
|
||||
QueryWrapper<ProductMapping> wrapper = new QueryWrapper<>();
|
||||
wrapper.apply(buildUniqueKeyCondition(batchKeys));
|
||||
|
||||
// 查询数据库
|
||||
List<ProductMapping> existingList = productMappingService.list(wrapper);
|
||||
|
||||
// 添加到结果映射
|
||||
existingList.forEach(entity ->
|
||||
resultMap.put(entity.getUniqueKey(), entity));
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 构建唯一键查询条件
|
||||
private String buildUniqueKeyCondition(List<String> uniqueKeys) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("CONCAT_WS('|', product_name, store_id, TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM CAST(spec_value AS CHAR))), spec_unit) IN (");
|
||||
|
||||
for (int i = 0; i < uniqueKeys.size(); i++) {
|
||||
if (i > 0) sb.append(",");
|
||||
sb.append("'").append(uniqueKeys.get(i).replace("'", "''")).append("'");
|
||||
}
|
||||
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
// 更新现有实体
|
||||
private void updateExistingEntity(ProductMapping existing, ProductMapping newEntity) {
|
||||
existing.setDescription(newEntity.getDescription());
|
||||
existing.setSortOrder(newEntity.getSortOrder());
|
||||
// 可根据需要更新其他字段
|
||||
}
|
||||
|
||||
// 验证Excel数据
|
||||
private void validateExcelData(ProductMappingExcel data, int rowNum) {
|
||||
if (StringUtils.isBlank(data.getProductName())) {
|
||||
throw new ValidationException("第" + rowNum + "行: 商品名称不能为空");
|
||||
}
|
||||
|
||||
if (data.getStoreId() == null || data.getStoreId() <= 0) {
|
||||
throw new ValidationException("第" + rowNum + "行: 店铺编号必须大于0");
|
||||
}
|
||||
|
||||
if (data.getSpecValue() == null || data.getSpecValue().compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new ValidationException("第" + rowNum + "行: 规格数据必须大于0");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(data.getSpecUnit())) {
|
||||
throw new ValidationException("第" + rowNum + "行: 规格单位不能为空");
|
||||
}
|
||||
|
||||
if (data.getSortOrder() == null || data.getSortOrder() < 0) {
|
||||
throw new ValidationException("第" + rowNum + "行: 排序值不能为负数");
|
||||
}
|
||||
}
|
||||
|
||||
// 设置Excel响应头
|
||||
private void setExcelResponseHeader(HttpServletResponse response, String fileName) {
|
||||
try {
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
|
||||
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("文件名编码失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 存储上传文件
|
||||
private String storeUploadedFile(MultipartFile file) {
|
||||
if (file.isEmpty()) {
|
||||
throw new RuntimeException("上传文件为空");
|
||||
}
|
||||
|
||||
try {
|
||||
String fileName = System.currentTimeMillis() + "_" + file.getOriginalFilename();
|
||||
Path filePath = Paths.get(uploadDir, fileName);
|
||||
Files.createDirectories(filePath.getParent());
|
||||
Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
|
||||
return filePath.toString();
|
||||
} catch (IOException e) {
|
||||
log.error("存储上传文件失败", e);
|
||||
throw new RuntimeException("存储上传文件失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 读取Excel数据
|
||||
private List<ProductMappingExcel> readExcelData(String filePath) {
|
||||
return EasyExcel.read(filePath)
|
||||
.head(ProductMappingExcel.class)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
}
|
||||
|
||||
// 生成错误报告
|
||||
private String generateErrorReport(List<String> errors, String originalFilePath) {
|
||||
try {
|
||||
String errorFileName = "ERROR_" + Paths.get(originalFilePath).getFileName().toString();
|
||||
Path errorFilePath = Paths.get(uploadDir, errorFileName);
|
||||
|
||||
List<ErrorInfo> errorData = new ArrayList<>();
|
||||
for (int i = 0; i < errors.size(); i++) {
|
||||
errorData.add(new ErrorInfo(i + 1, errors.get(i)));
|
||||
}
|
||||
|
||||
EasyExcel.write(errorFilePath.toString())
|
||||
.head(ErrorInfo.class)
|
||||
.sheet("导入错误")
|
||||
.doWrite(errorData);
|
||||
|
||||
return "/admin/shop/shop-sync-productMapper/download?file=" + URLEncoder.encode(errorFileName, "UTF-8");
|
||||
} catch (Exception e) {
|
||||
log.error("生成错误报告失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CommonResult saveProductMapping(ProductMapping data) {
|
||||
List<String> batchKeys = Arrays.asList(data.getUniqueKey().split(","));
|
||||
|
||||
// 构建查询条件
|
||||
QueryWrapper<ProductMapping> wrapper = new QueryWrapper<>();
|
||||
wrapper.apply(buildUniqueKeyCondition(batchKeys));
|
||||
List<ProductMapping> productMappings= productMappingService.list(wrapper);
|
||||
if(!productMappings.isEmpty()){
|
||||
return CommonResult.failed("存在相同的映射商品数据");
|
||||
}
|
||||
boolean result= productMappingService.save(data);
|
||||
if(result){
|
||||
return CommonResult.success();
|
||||
}
|
||||
return CommonResult.success(false);
|
||||
}
|
||||
|
||||
|
||||
// 错误信息类
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class ErrorInfo {
|
||||
@ExcelProperty("行号")
|
||||
private Integer rowNum;
|
||||
|
||||
@ExcelProperty("错误信息")
|
||||
private String errorMessage;
|
||||
}
|
||||
}
|
||||
@ -45,12 +45,19 @@ public class StoreDbConfigServiceImpl extends BaseServiceImpl<StoreDbConfigMappe
|
||||
|
||||
@Override
|
||||
public CommonResult findStoreDbConfigPageList(StoreDbConfig storeDbConfig,Integer pageNum,Integer pageSize) {
|
||||
|
||||
checked();
|
||||
String storeId= getStoreId(storeDbConfig.getStoreId());
|
||||
QueryWrapper<StoreDbConfig> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("store_id", storeId);
|
||||
queryWrapper.eq("has_internet", storeDbConfig.getHasInternet());
|
||||
queryWrapper.eq("has_start", storeDbConfig.getHasInternet());
|
||||
if(!StringUtils.isEmpty(storeId)){
|
||||
queryWrapper.eq("store_id", storeId);
|
||||
}
|
||||
if(!ObjectUtil.isEmpty(storeDbConfig.getHasInternet())){
|
||||
queryWrapper.eq("has_internet", storeDbConfig.getHasInternet());
|
||||
}
|
||||
if(!ObjectUtil.isEmpty(storeDbConfig.getHasStart())){
|
||||
queryWrapper.eq("has_start", storeDbConfig.getHasStart());
|
||||
}
|
||||
return CommonResult.success(this.lists(queryWrapper,pageNum,pageSize));
|
||||
}
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ import com.alibaba.excel.util.DateUtils;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.api.StateCode;
|
||||
import com.suisung.mall.common.constant.CommonConstant;
|
||||
import com.suisung.mall.common.enums.DicEnum;
|
||||
import com.suisung.mall.common.exception.ApiException;
|
||||
import com.suisung.mall.common.feignService.AccountService;
|
||||
import com.suisung.mall.common.feignService.PayService;
|
||||
@ -21,6 +22,7 @@ import com.suisung.mall.common.modules.account.AccountUserBase;
|
||||
import com.suisung.mall.common.modules.account.AccountUserInfo;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductBrand;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductCategory;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductSpec;
|
||||
import com.suisung.mall.common.modules.base.ShopBaseProductType;
|
||||
import com.suisung.mall.common.modules.number.ShopNumberSeq;
|
||||
import com.suisung.mall.common.modules.pay.PayUserResource;
|
||||
@ -34,13 +36,18 @@ import com.suisung.mall.common.utils.I18nUtil;
|
||||
import com.suisung.mall.common.utils.StringUtils;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductBrandService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductCategoryService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductSpecService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductTypeService;
|
||||
import com.suisung.mall.shop.number.service.ShopNumberSeqService;
|
||||
import com.suisung.mall.shop.number.service.impl.ShopNumberSeqServiceImpl;
|
||||
import com.suisung.mall.shop.product.service.ShopProductBaseService;
|
||||
import com.suisung.mall.shop.product.service.ShopProductItemService;
|
||||
import com.suisung.mall.shop.product.service.impl.ShopProductBaseServiceImpl;
|
||||
import com.suisung.mall.shop.product.service.impl.ShopProductItemServiceImpl;
|
||||
import com.suisung.mall.shop.sixun.dto.SxGoosModel;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreBaseService;
|
||||
import com.suisung.mall.shop.sync.service.ProductMappingService;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -51,6 +58,9 @@ import java.math.BigDecimal;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.baomidou.mybatisplus.extension.toolkit.Db.list;
|
||||
|
||||
@Service
|
||||
public abstract class SyncBaseThirdSxAbstract{
|
||||
@ -70,11 +80,16 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
@Autowired
|
||||
private PayService payService;
|
||||
@Autowired
|
||||
private ShopNumberSeqServiceImpl shopNumberSeqServiceImpl;
|
||||
private ShopNumberSeqService shopNumberSeqService;
|
||||
|
||||
@Autowired
|
||||
private ShopProductBaseServiceImpl shopProductBaseServiceImpl;
|
||||
private ShopProductItemService shopProductItemService;
|
||||
|
||||
@Autowired
|
||||
private ShopProductItemServiceImpl shopProductItemServiceImpl;
|
||||
private ShopBaseProductSpecService shopBaseProductSpecService;
|
||||
|
||||
@Autowired
|
||||
private ProductMappingService productMappingService;
|
||||
|
||||
/**
|
||||
* 对商品分类进行保存
|
||||
@ -86,17 +101,20 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
public int baseSaveOrUpdateShopBaseProductCategoryBatch(List<ShopBaseProductCategory> list ,JSONArray categoryListJSON,
|
||||
String storeId){
|
||||
int count = 0;
|
||||
List<ShopBaseProductType> productTypeList = new ArrayList<>();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).setStore_id(storeId); // app 记录传进来
|
||||
list.get(i).setData_source(2); // 思迅数据来源
|
||||
list.get(i).setCategory_is_enable(1);
|
||||
|
||||
JSONObject o = (JSONObject) categoryListJSON.get(i);
|
||||
ShopBaseProductType productType=new ShopBaseProductType();
|
||||
if (o != null) {
|
||||
// 重要:分类类型处理(强调共性)
|
||||
Integer typeId = 1001;
|
||||
|
||||
if (StrUtil.isNotBlank(o.getStr("product_type"))) {
|
||||
ShopBaseProductType productType = productTypeService.getProductTypeByName(o.getStr("product_type"));
|
||||
productType = productTypeService.getProductTypeByName(o.getStr("product_type"));
|
||||
if (productType != null) {
|
||||
typeId = productType.getType_id();
|
||||
} else {
|
||||
@ -107,6 +125,7 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
if (productTypeService.save(newProductType)) {
|
||||
typeId = newProductType.getType_id();
|
||||
}
|
||||
productType=newProductType;
|
||||
}
|
||||
list.get(i).setType_id(typeId);
|
||||
}
|
||||
@ -157,8 +176,6 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
ShopBaseProductCategory productCategoryTemp = productCategoryService.getCategoryByName(list.get(i).getCategory_parent_id(), list.get(i).getCategory_name(), list.get(i).getStore_id());
|
||||
@ -173,13 +190,16 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (productCategoryService.saveOrUpdate(list.get(i))) {
|
||||
count++;
|
||||
}
|
||||
productType.setType_category_id(list.get(i).getCategory_id());
|
||||
productTypeList.add(productType);
|
||||
}
|
||||
|
||||
saveBatchShopProductProductSpec(storeId,productTypeList);
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -522,6 +542,10 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
}
|
||||
goodsListJSON.stream().parallel().forEach(object -> {
|
||||
final JSONObject jsonObj= (JSONObject) object;
|
||||
String productName= (String) jsonObj.get("product_name");
|
||||
if(productName.equals(DicEnum.GOODS_UN_SYNC_SX.getValue())){//todo 后期改为数据库存储的黑名单
|
||||
return;
|
||||
}
|
||||
Date currentDate = new Date();
|
||||
String cateGoryId="";
|
||||
if(null!=categoryMap.get(jsonObj.get("first_category_name"))){
|
||||
@ -530,24 +554,37 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
Integer categoryId = Convert.toInt(cateGoryId, 0);
|
||||
Integer storeIdInt = Convert.toInt(storeId);
|
||||
|
||||
|
||||
ShopProductBase shopProductBase = new ShopProductBase();
|
||||
shopProductBase.setCategoryId(categoryId);
|
||||
shopProductBase.setProduct_sale_time(Convert.toDate(DateUtil.current() + 600)); //10分钟
|
||||
shopProductBase.setStore_id(storeIdInt);
|
||||
|
||||
shopProductBase.setProduct_number((String) jsonObj.get("product_number"));
|
||||
shopProductBase.setProduct_name((String) jsonObj.get("product_name"));
|
||||
|
||||
shopProductBase.setStore_name(store_row.getStore_name());
|
||||
shopProductBase.setProduct_tips("");
|
||||
shopProductBase.setProduct_video("");
|
||||
shopProductBase.setTransport_type_id(StateCode.DELIVERY_TYPE_SAME_CITY);
|
||||
shopProductBase.setProduct_state_id(StateCode.PRODUCT_STATE_NORMAL);
|
||||
|
||||
shopProductBase.setProduct_inventory_lock(1002); //库存锁定(ENUM):1001-下单锁定;1002-支付锁定;
|
||||
shopProductBase.setProduct_fx_enable(0); // 供应商是否允许批发市场分销
|
||||
shopProductBase.setProduct_dist_enable(0); // 是否允许三级分销
|
||||
shopProductBase.setProduct_from(1005);// 商品来源(ENUM):1000-发布;1001-天猫;1002-淘宝;1003-阿里巴巴;1004-京东;1005-思迅;
|
||||
shopProductBase.setProduct_add_time(currentDate.getTime());
|
||||
|
||||
shopProductBase.setProduct_unit_price(BigDecimal.valueOf(jsonObj.getDouble("retail_price")));
|
||||
//商品总量
|
||||
if(ObjectUtil.isNotEmpty(jsonObj.getStr("unit"))&&ObjectUtil.isNotEmpty(jsonObj.getStr("stock"))
|
||||
&& "KG,kg,公斤".contains(jsonObj.getStr("unit"))){
|
||||
shopProductBase.setShop_weight(jsonObj.getBigDecimal("stock"));
|
||||
shopProductBase.setUnit_name(jsonObj.getStr("unit"));
|
||||
shopProductBase.setProduct_state_id(StateCode.PRODUCT_STATE_OFF_THE_SHELF_UNCHECK);
|
||||
shopProductBase.setUnit_price(BigDecimal.valueOf(jsonObj.getDouble("retail_price")));
|
||||
}else {
|
||||
shopProductBase.setShop_weight(jsonObj.getBigDecimal("stock"));
|
||||
shopProductBase.setProduct_state_id(StateCode.PRODUCT_STATE_NORMAL);
|
||||
shopProductBase.setUnit_price(BigDecimal.valueOf(jsonObj.getDouble("retail_price")));
|
||||
}
|
||||
// ShopProductIndex
|
||||
ShopProductIndex shopProductIndex = new ShopProductIndex();
|
||||
shopProductIndex.setProduct_add_time(currentDate.getTime());
|
||||
@ -616,12 +653,19 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
shopProductItem.setItem_market_price(BigDecimal.valueOf(jsonObj.getDouble("original_price")));
|
||||
//积分价
|
||||
shopProductItem.setItem_unit_points(new BigDecimal(jsonObj.getInt("points")));
|
||||
shopProductItem.setItem_quantity(jsonObj.getInt("stock")); // 库存
|
||||
|
||||
//todo 特色商品切割
|
||||
//负数产品判断
|
||||
if(jsonObj.getInt("stock",99)<0){
|
||||
shopProductItem.setItem_quantity(99); // 库存
|
||||
shopProductItem.setItem_weight(new BigDecimal("0"));//切割重量
|
||||
}
|
||||
|
||||
shopProductItem.setItem_quantity_frozen(0);
|
||||
shopProductItem.setItem_number(jsonObj.getStr("product_number"));// SKU商家编码
|
||||
shopProductItem.setItem_barcode(jsonObj.getStr("product_number")); // 条形码正常情况下就是货号
|
||||
shopProductItem.setItem_is_default(1);
|
||||
shopProductItem.setItem_enable(1);
|
||||
shopProductItem.setItem_enable(shopProductBase.getProduct_state_id());
|
||||
|
||||
//添加数据到list
|
||||
synchronized(shopProductBaseList){
|
||||
@ -633,30 +677,9 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
shopProductInfoList.add(shopProductInfo);
|
||||
shopProductItemLists.add(shopProductItemList);
|
||||
}
|
||||
// synchronized(shopProductIndexList){
|
||||
// shopProductIndexList.add(shopProductIndex);
|
||||
// }
|
||||
//
|
||||
// synchronized(shopProductDataList){
|
||||
// shopProductDataList.add(shopProductData);
|
||||
// }
|
||||
//
|
||||
// synchronized(shopProductDetailList){
|
||||
// shopProductDetailList.add(shopProductDetail);
|
||||
// }
|
||||
//
|
||||
// synchronized(shopProductInfoList){
|
||||
// shopProductInfoList.add(shopProductInfo);
|
||||
// }
|
||||
//
|
||||
// synchronized(shopProductItemLists){
|
||||
// shopProductItemLists.add(shopProductItemList);
|
||||
// }
|
||||
|
||||
// 保存数据
|
||||
|
||||
resultCount.addAndGet(1);
|
||||
});
|
||||
// 保存数据
|
||||
shopProductBaseService.saveProductBatch(shopProductBaseList,shopProductIndexList,shopProductDataList,shopProductDetailList,shopProductInfoList,shopProductItemLists,
|
||||
new ArrayList<List<ShopProductImage>>(),
|
||||
new ArrayList<ShopProductValidPeriod>(),
|
||||
@ -671,7 +694,7 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
List<ShopNumberSeq> shopNumberSeqList=new ArrayList<>();
|
||||
QueryWrapper<ShopProductBase> baseWrapper=new QueryWrapper<>();
|
||||
baseWrapper.select("MAX(product_id) as product_id");
|
||||
ShopProductBase shopProductBase= shopProductBaseServiceImpl.getOne(baseWrapper);
|
||||
ShopProductBase shopProductBase= shopProductBaseService.getOne(baseWrapper);
|
||||
Long productId= shopProductBase.getProduct_id();
|
||||
//QueryWrapper<ShopNumberSeq> baseSeWrapper=new QueryWrapper();
|
||||
//baseSeWrapper.eq("prefix", "product_id");
|
||||
@ -682,7 +705,7 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
//查询产品item
|
||||
QueryWrapper<ShopProductItem> itemQuery=new QueryWrapper<>();
|
||||
itemQuery.select("MAX(item_id) as item_id");
|
||||
ShopProductItem shopProductItem= shopProductItemServiceImpl.getOne(itemQuery);
|
||||
ShopProductItem shopProductItem= shopProductItemService.getOne(itemQuery);
|
||||
Long itemtId= shopProductItem.getItem_id();
|
||||
// QueryWrapper<ShopNumberSeq> itemWrapper=new QueryWrapper();
|
||||
//itemWrapper.eq("prefix", "item_id");
|
||||
@ -691,9 +714,101 @@ public abstract class SyncBaseThirdSxAbstract{
|
||||
shopNumberSeqItem.setPrefix("item_id");
|
||||
shopNumberSeqList.add(shopNumberSeqBase);
|
||||
shopNumberSeqList.add(shopNumberSeqItem);
|
||||
shopNumberSeqServiceImpl.batchUpdateSeq(shopNumberSeqList);
|
||||
shopNumberSeqServiceImpl.clearRelateGoodsId();
|
||||
shopNumberSeqService.batchUpdateSeq(shopNumberSeqList);
|
||||
shopNumberSeqService.clearRelateGoodsId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商品分类生成规格主体
|
||||
* @param storeId
|
||||
*/
|
||||
private synchronized void saveBatchShopProductProductSpec(String storeId,List<ShopBaseProductType> shopBaseProductTypes){
|
||||
Map categoryMap= productCategoryService.getCategoryListByStoreId(storeId);
|
||||
List<ShopBaseProductSpec> shopBaseProductSpecList=new ArrayList<>();
|
||||
Set<Map.Entry> categoryMapSet= categoryMap.entrySet();
|
||||
for(Map.Entry categoryMapEntry:categoryMapSet){
|
||||
ShopBaseProductSpec shopBaseProductSpec=new ShopBaseProductSpec();
|
||||
if(categoryMapEntry.getKey()!=null&& !(NumberUtils.isCreatable(String.valueOf(categoryMapEntry.getKey())))){
|
||||
shopBaseProductSpec.setStore_id(Integer.valueOf(storeId));
|
||||
shopBaseProductSpec.setSpec_category_id((Integer) categoryMapEntry.getValue());
|
||||
shopBaseProductSpec.setSpec_name(categoryMapEntry.getKey()+"规格");
|
||||
shopBaseProductSpecList.add(shopBaseProductSpec);
|
||||
}
|
||||
}
|
||||
Map<String, Integer> existIdMap= checkExistingShopBaseProductSpec(shopBaseProductSpecList);
|
||||
List<ShopBaseProductSpec> insertShopBaseProductSpecList=new ArrayList<>();
|
||||
List<ShopBaseProductSpec> updateShopBaseProductSpecList=new ArrayList<>();
|
||||
QueryWrapper<ShopBaseProductSpec> queryWrapper= new QueryWrapper<>();
|
||||
queryWrapper.select("max(spec_id) as spec_id");
|
||||
int spec_id=shopBaseProductSpecService.getOne(queryWrapper).getSpec_id()+1;
|
||||
//int i=0;
|
||||
for(int i=0;i<shopBaseProductSpecList.size();i++){
|
||||
if(existIdMap.containsKey(shopBaseProductSpecList.get(i).getSpec_name())){
|
||||
shopBaseProductSpecList.get(i).setSpec_id(existIdMap.get(shopBaseProductSpecList.get(i).getSpec_name()));
|
||||
updateShopBaseProductSpecList.add(shopBaseProductSpecList.get(i));
|
||||
|
||||
int finalI = i;
|
||||
shopBaseProductTypes.forEach(shopBaseProductType -> {
|
||||
if((shopBaseProductType.getType_name()+"规格").equals(shopBaseProductSpecList.get(finalI).getSpec_name())){
|
||||
shopBaseProductType.setType_spec_ids(String.valueOf(existIdMap.get(shopBaseProductSpecList.get(finalI).getSpec_name())));
|
||||
}
|
||||
});
|
||||
}else {
|
||||
shopBaseProductSpecList.get(i).setSpec_id(spec_id);
|
||||
int finalSpec_id = spec_id;
|
||||
int finalI1 = i;
|
||||
shopBaseProductTypes.forEach(shopBaseProductType -> {
|
||||
if((shopBaseProductType.getType_name()+"规格").equals(shopBaseProductSpecList.get(finalI1).getSpec_name())){
|
||||
shopBaseProductType.setType_spec_ids(String.valueOf(finalSpec_id));
|
||||
}
|
||||
});
|
||||
insertShopBaseProductSpecList.add(shopBaseProductSpecList.get(i));
|
||||
}
|
||||
spec_id++;
|
||||
}
|
||||
if(CollectionUtil.isNotEmpty(insertShopBaseProductSpecList)){
|
||||
shopBaseProductSpecService.saveBatch(insertShopBaseProductSpecList,insertShopBaseProductSpecList.size());
|
||||
}
|
||||
if(CollectionUtil.isNotEmpty(updateShopBaseProductSpecList)){
|
||||
shopBaseProductSpecService.updateBatchById(updateShopBaseProductSpecList,updateShopBaseProductSpecList.size());
|
||||
}
|
||||
if(CollectionUtil.isNotEmpty(shopBaseProductTypes)){
|
||||
productTypeService.updateBatchById(shopBaseProductTypes,shopBaseProductTypes.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查哪些商品已存在
|
||||
*/
|
||||
private Map<String, Integer> checkExistingShopBaseProductSpec(List<ShopBaseProductSpec> productSpecs) {
|
||||
List<String> storeProductPairs = productSpecs.stream()
|
||||
.map(ShopBaseProductSpec::getSpec_name)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
List<ShopBaseProductSpec> existing = batchGetByStoreAndShopBaseProductSpec(storeProductPairs);
|
||||
return existing.stream()
|
||||
.collect(Collectors.toMap(
|
||||
ShopBaseProductSpec::getSpec_name,
|
||||
ShopBaseProductSpec::getSpec_id
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量根据店铺和货号查询商品
|
||||
*/
|
||||
private List<ShopBaseProductSpec> batchGetByStoreAndShopBaseProductSpec(List<String> ShopBaseProductSpecStr) {
|
||||
if (CollUtil.isEmpty(ShopBaseProductSpecStr)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
QueryWrapper<ShopBaseProductSpec> query = new QueryWrapper<>();
|
||||
query.select("spec_id", "spec_name");
|
||||
ShopBaseProductSpecStr.forEach(specName -> {
|
||||
query.or(q -> q.eq("spec_name", specName));
|
||||
});
|
||||
|
||||
return shopBaseProductSpecService.list(query);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -39,14 +39,15 @@ import com.suisung.mall.common.modules.sync.SyncFileLog;
|
||||
import com.suisung.mall.common.pojo.req.SyncThirdMemberReq;
|
||||
import com.suisung.mall.common.pojo.res.ThirdApiRes;
|
||||
|
||||
import com.suisung.mall.common.utils.ContextUtil;
|
||||
import com.suisung.mall.common.utils.I18nUtil;
|
||||
|
||||
import com.suisung.mall.common.utils.StringUtils;
|
||||
import com.suisung.mall.core.web.service.RedisService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductCategoryService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductSpecService;
|
||||
import com.suisung.mall.shop.number.service.ShopNumberSeqService;
|
||||
import com.suisung.mall.shop.page.service.OssService;
|
||||
import com.suisung.mall.shop.product.service.ShopProductSpecItemService;
|
||||
import com.suisung.mall.shop.sixun.dao.SxDataDao;
|
||||
import com.suisung.mall.shop.sixun.dto.DataBaseInfo;
|
||||
import com.suisung.mall.shop.sixun.dto.SxCategoryModel;
|
||||
@ -68,7 +69,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.InputStreamSource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@ -130,6 +130,11 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
||||
@Autowired
|
||||
private FileUtils fileUtils;
|
||||
|
||||
@Autowired
|
||||
private ShopProductSpecItemService shopProductSpecItemService;
|
||||
|
||||
@Autowired
|
||||
private ShopBaseProductSpecService baseProductSpecService;
|
||||
|
||||
/**
|
||||
* 批量保存商品的分类
|
||||
@ -531,6 +536,8 @@ public class SyncThirdDataServiceImpl extends SyncBaseThirdSxAbstract implements
|
||||
syncPrimaryKey();
|
||||
shopNumberSeqService.clearKey();
|
||||
shopBaseProductCategoryService.clearCategoryCache(storeId);
|
||||
shopProductSpecItemService.clearExistItem(Integer.valueOf(storeId));
|
||||
baseProductSpecService.clearShopBaseProductSpecMap(Integer.valueOf(storeId));
|
||||
List<SyncFileLog> syncFileLogs=new ArrayList<>();
|
||||
for (int i = 0; i < failFolders.size(); i++) {
|
||||
String path=failFolders.get(i);
|
||||
|
||||
@ -5,4 +5,6 @@ spring:
|
||||
name: mall-shop
|
||||
jackson:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
time-zone: GMT+8
|
||||
time-zone: GMT+8
|
||||
file:
|
||||
upload-dir: /tmp/excel_uploads
|
||||
25
sql/shop/dev/20250602_ddl.sql
Normal file
25
sql/shop/dev/20250602_ddl.sql
Normal file
@ -0,0 +1,25 @@
|
||||
CREATE TABLE `product_mapping` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`product_name` varchar(255) NOT NULL COMMENT '商品名称',
|
||||
`spec_value` decimal(18,4) NOT NULL COMMENT '规格数据',
|
||||
`spec_unit` varchar(20) NOT NULL COMMENT '规格单位',
|
||||
`description` text ,
|
||||
`sort_order` int(11) NOT NULL DEFAULT '0' COMMENT '排序值',
|
||||
`store_id` int unsigned NOT NULL DEFAULT '0' COMMENT '店铺编号',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_product_name` (`product_name`) USING BTREE,
|
||||
KEY `idx_store_id` (`store_id`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品映射表';
|
||||
|
||||
alter table shop_product_base add column `unit_name` varchar(2) DEFAULT NULL COMMENT '总量单位';
|
||||
alter table shop_product_base add column `shop_weight` DECIMAL(18,4) NOT NULL COMMENT '总重量'
|
||||
alter table shop_product_base add column `unit_price` DECIMAL(18,4) NOT NULL COMMENT '单价';
|
||||
|
||||
alter table shop_base_product_spec add column `store_id` int unsigned NOT NULL DEFAULT '0' COMMENT '店铺编号';
|
||||
alter table shop_base_product_spec add index `store_id` (`store_id`) USING BTREE;
|
||||
|
||||
INSERT INTO mall_dev.shop_base_product_state
|
||||
(product_state_id, product_state_name, product_state_text_1, product_state_text_2, product_state_remark)
|
||||
VALUES(1003, 'PRODUCT_STATE_OFF_THE_SHELF_UNCHECK', '下架未分配商品', '同步数据未分配', '');
|
||||
|
||||
alter table store_db_config add column refresh_time datetime DEFAULT NULL COMMENT '刷新时间';
|
||||
Loading…
Reference in New Issue
Block a user