电商项目-商品管理(上)

一、电商商品SPU和SKU的概念

        SPU和SKU的概念,在电商领域非常重要,SPU描述的是商品的集合,以手机为例,例如 华为手机有不同颜色,不同内存大小等相关属性信息。如果只说华为荣誉X60 就是SPU的信息。
        SKU是商品最小销售单元,可以通过SKU描述具体特定的商品华为荣誉X60黑色 128G ,根据这句话特点的描述出了某一个商品。这个就是SPU和SKU。
        商品详情页面 ,加载的是SPU ,商品详情页面是以SPU进行当前商品信息的描述。随着规格信息的切换,颜色的切换,具体细化到了SKU上,随着规格改变价格会变。

        添加购物车的时候添加的是SKU的信息。


        SPU:是一组商品集合,在这组商品集合里,会包含一个或多个SKU的信息,每一个SKU是一个具体的,某个商品的 最小销售单元,可以通过一个SKU集体细化到商品上,从而确定商品的价钱。SPU与SKU 是一对多 或一对一的关系。

SPU = Standard Product Unit  (标准产品单位)

        -概念 : SPU 是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。

        -通俗点讲,属性值、特性相同的货品就可以称为一个 SPU

        例如:华为荣誉X60 就是一个 SPU

SKU=stock keeping unit( 库存量单位)

        -SKU 即库存进出计量的单位, 可以是以件、盒、托盘等为单位。

        -SKU 是物理上不可分割的最小存货单元。在使用时要根据不同业态,不同管理模式来处理。

        -在服装、鞋类商品中使用最多最普遍。

例如:华为荣誉X60 黑色 128G 就是一个 SKU

二、需求分析

1)表结构分析

tb_spu 表 (SPU表)

字段名称字段含义字段类型字段长度备注
id主键VARCHAR
sn货号VARCHAR
nameSPU名VARCHAR
caption副标题VARCHAR
brand_id品牌IDINT
category1_id一级分类INT
category2_id二级分类INT
category3_id三级分类INT
template_id模板IDINT
freight_id运费模板idINT
image图片VARCHAR
images图片列表VARCHAR
sale_service售后服务VARCHAR
introduction介绍TEXT
spec_items规格列表VARCHAR
para_items参数列表VARCHAR
sale_num销量INT
comment_num评论数INT
is_marketable是否上架CHAR
is_enable_spec是否启用规格CHAR
is_delete是否删除CHAR
status审核状态CHAR

tb_sku 表(SKU商品表)

字段名称字段含义字段类型字段长度备注
id商品idVARCHAR
sn商品条码VARCHAR
nameSKU名称VARCHAR
price价格(分)INT
num库存数量INT
alert_num库存预警数量INT
image商品图片VARCHAR
images商品图片列表VARCHAR
weight重量(克)INT
create_time创建时间DATETIME
update_time更新时间DATETIME
spu_idSPUIDBIGINT
category_id类目IDINT
category_name类目名称VARCHAR
brand_name品牌名称VARCHAR
spec规格VARCHAR
sale_num销量INT
comment_num评论数INT
status商品状态 1-正常,2-下架,3-删除CHAR

2)实现思路

前端传递给后端的数据格式 是一个spu对象和sku列表组成的对象


{
    "spu": {
        "name": "这个是商品名称",
        "caption": "这个是副标题",
        "brandId": 12,
        "category1Id": 558,
        "category2Id": 559,
        "category3Id": 560,
        "freightId": 10,
        "image": "http://www.shangcheng.com/image/1.jpg",
         "images": "http://www.shangcheng.com/image/1.jpg,http://www.shangcheng.com/image/2.jpg",
        "introduction": "这个是商品详情,html代码",
         "paraItems": "{'出厂年份':'2023','赠品':'充电器'}",
        "saleService": "七天包退,闪电退货",
        "sn": "020102331",
        "specItems":  "{'颜色':['红','绿'],'机身内存':['128G','8G']}",
        "templateId": 42
    },
    "skuList": [{
        "sn": "10192010292",
         "num": 100,
         "alertNum": 20,
         "price": 900000,
         "spec": "{'颜色':'红','机身内存':'128G'}",
         "image": "http://www.shangcheng.com/image/1.jpg",
         "images": "http://www.shangcheng.com/image/1.jpg,http://www.shangcheng.com/image/2.jpg",
        "status": "1",
        "weight": 130
    },
    {
        "sn": "10192010293",
         "num": 100,
         "alertNum": 20,
         "price": 600000,
         "spec": "{'颜色':'蓝','机身内存':'256G'}",
         "image": "http://www.shangcheng.com/image/1.jpg",
         "images": "http://www.shangcheng.com/image/1.jpg,http://www.shangcheng.com/image/2.jpg",
        "status": "1",
        "weight": 130
    }
  ]
}

三、代码实现

        商品数据库 ,表有  tb_album ,tb_brand, tb_category, tb_category_brand, tb_para,tb_pref,tb_sku,tb_spu,tb_spec

        SPU与SKU的保存涉及到的业务表有,品牌与分类关联,规格数据,分布式ID

        注:基于网关调用具体服务,应该携带令牌。添加操作首先需要进行认证登录,需要获取JWT令牌,携带令牌才能进行添加。

3.1 SPU与SKU列表的保存

代码实现:

(1)shangcheng_service_goods_api工程创建组合实体类Goods

/**
 * 商品组合实体类
 */
public class Goods implements Serializable {
​
    private Spu spu;
    private List<Sku> skuList;
​
    public Spu getSpu() {
        return spu;
    }
​
    public void setSpu(Spu spu) {
        this.spu = spu;
    }
​
    public List<Sku> getSkuList() {
        return skuList;
    }
​
    public void setSkuList(List<Sku> skuList) {
        this.skuList = skuList;
    }
}

(2)shangcheng_service_goods工程SpuService新增方法add(Goods goods)

     /***
     * 新增
     * @param goods
     */
    void add(Goods goods);

(3)shangcheng_service_goods工程SpuServiceImpl实现此方法

    @Autowired
    private CategoryMapper categoryMapper;
​
    @Autowired
    private SkuMapper skuMapper;
​
    @Autowired
    private BrandMapper brandMapper;
​
    @Autowired
    private IdWorker idWorker;
​
    /**
     * 保存商品 SPU+SKU列表
     * @param goods 商品组合实体类
     */
    @Transactional
    @Override
    public void add(Goods goods) {

        //1.添加spu
        Spu spu = goods.getSpu();
        //设置分布式id
        long spuId = idWorker.nextId();
        spu.setId(String.valueOf(spuId));
        //设置删除状态.
        spu.setIsDelete("0");
        //上架状态
        spu.setIsMarketable("0");
        //审核状态
        spu.setStatus("0");
        spuMapper.insertSelective(spu);

        //2.添加sku集合
        this.saveSkuList(goods);
    }
​
    /**
     * 保存sku列表
     * @param goods
     */
    private void saveSkuList(Goods goods){
        Spu spu = goods.getSpu();
        //查询分类对象
        Category category = categoryMapper.selectByPrimaryKey(spu.getCategory3Id());

        //查询品牌对象
        Brand brand = brandMapper.selectByPrimaryKey(spu.getBrandId());

        //设置品牌与分类的关联关系
        //查询关联表
        CategoryBrand categoryBrand = new CategoryBrand();
        categoryBrand.setBrandId(spu.getBrandId());
        categoryBrand.setCategoryId(spu.getCategory3Id());
        int count = categoryBrandMapper.selectCount(categoryBrand);
        if (count == 0){
            //品牌与分类还没有关联关系
            categoryBrandMapper.insert(categoryBrand);
        }

        //获取sku集合
        List<Sku> skuList = goods.getSkuList();
        if (skuList != null){
            //遍历sku集合,循环填充数据并添加到数据库中
            for (Sku sku : skuList) {
                //设置skuId
                sku.setId(String.valueOf(idWorker.nextId()));
                //设置sku规格数据
                if (StringUtils.isEmpty(sku.getSpec())){
                    sku.setSpec("{}");
                }
                //设置sku名称(spu名称+规格)
                String name = spu.getName();
                //将规格json转换为map,将map中的value进行名称的拼接
                Map<String,String> specMap = JSON.parseObject(sku.getSpec(), Map.class);
                if (specMap != null && specMap.size()>0){
                    for (String value : specMap.values()) {
                        name+=" "+value;
                    }
                }
                sku.setName(name);
                //设置spuid
                sku.setSpuId(spu.getId());
                //设置创建与修改时间
                sku.setCreateTime(new Date());
                sku.setUpdateTime(new Date());
                //商品分类id
                sku.setCategoryId(category.getId());
                //设置商品分类名称
                sku.setCategoryName(category.getName());
                //设置品牌名称
                sku.setBrandName(brand.getName());
                //将sku添加到数据库
                skuMapper.insertSelective(sku);

            }
        }
    }

(4)修改SpuController的add方法

    /**
     * 新增数据
     * @param goods
     * @return
     */
    @PostMapping
    public Result add(@RequestBody Goods goods){
        spuService.add(goods);
        return new Result(true,StatusCode.OK,"添加成功");
    }

3.2 品牌与分类关联

实现思路:

将分类ID与SPU的品牌ID 一起插入到关系表tb_category_brand中

(1)创建实体类

@Table(name="tb_category_brand")
public class CategoryBrand implements Serializable {
​
    @Id
    private Integer categoryId;
​
    @Id
    private Integer brandId;
​
​
    public Integer getCategoryId() {
        return categoryId;
    }
​
    public void setCategoryId(Integer categoryId) {
        this.categoryId = categoryId;
    }
​
    public Integer getBrandId() {
        return brandId;
    }
​
    public void setBrandId(Integer brandId) {
        this.brandId = brandId;
    }
}

这个表是联合主键,所以templateId和brandId都有@Id注解

(2)新建数据访问接口

public interface CategoryBrandMapper extends Mapper<CategoryBrand> {
  
}

(3)SpuServiceImpl引入

 @Autowired
    private CategoryBrandMapper categoryBrandMapper;

(4)修改SpuServiceImpl的saveSkuList方法,添加分类与品牌之间的关联, 

 /**
     * 保存sku列表
     * @param goods
     */
    private void saveSkuList(Goods goods){
        Spu spu = goods.getSpu();
        //查询分类对象
        Category category = categoryMapper.selectByPrimaryKey(spu.getCategory3Id());

        //查询品牌对象
        Brand brand = brandMapper.selectByPrimaryKey(spu.getBrandId());

        //设置品牌与分类的关联关系
        //查询关联表
        CategoryBrand categoryBrand = new CategoryBrand();
        categoryBrand.setBrandId(spu.getBrandId());
        categoryBrand.setCategoryId(spu.getCategory3Id());
        int count = categoryBrandMapper.selectCount(categoryBrand);
        if (count == 0){
            //品牌与分类还没有关联关系
            categoryBrandMapper.insert(categoryBrand);
        }

        //获取sku集合
        List<Sku> skuList = goods.getSkuList();
        if (skuList != null){
            //遍历sku集合,循环填充数据并添加到数据库中
            for (Sku sku : skuList) {
                //设置skuId
                sku.setId(String.valueOf(idWorker.nextId()));
                //设置sku规格数据
                if (StringUtils.isEmpty(sku.getSpec())){
                    sku.setSpec("{}");
                }
                //设置sku名称(spu名称+规格)
                String name = spu.getName();
                //将规格json转换为map,将map中的value进行名称的拼接
                Map<String,String> specMap = JSON.parseObject(sku.getSpec(), Map.class);
                if (specMap != null && specMap.size()>0){
                    for (String value : specMap.values()) {
                        name+=" "+value;
                    }
                }
                sku.setName(name);
                //设置spuid
                sku.setSpuId(spu.getId());
                //设置创建与修改时间
                sku.setCreateTime(new Date());
                sku.setUpdateTime(new Date());
                //商品分类id
                sku.setCategoryId(category.getId());
                //设置商品分类名称
                sku.setCategoryName(category.getName());
                //设置品牌名称
                sku.setBrandName(brand.getName());
                //将sku添加到数据库
                skuMapper.insertSelective(sku);

            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值