目录

  • 商品服务模块

    1. 品牌管理

      • 品牌对应三级目录的增删改查
    2. 平台属性
      • 数据库表关系
      • 规格参数
      • 增删改查
      • 销售属性
      • 属性分组
    3. 新增商品
      • 获取三级分类及品牌
      • 商品json存储格式
      • 数据库表设计
      • 商品服务调用优惠券服务
      • 多条件查询
      • 日期格式处理
  • 仓储服务模块
    1. 仓库管理

      • 数据库表设计
      • 仓库查询
      • 仓库、SKU关联信息查询
      • 库存数量的新增
      • 合并采购需求到一个采购单
      • 模拟移动端领取采购单
      • 模拟员工完成采购单
  • 分布式基础完结

一、品牌管理

1.品牌对应三级分类的增删改查

点击关联查询,查出该品牌对应的三级分类list

/*** 自定义查询方法* 根据 品牌id 查询关联的 category分类** @return*/@Overridepublic List<CategoryBrandRelationEntity> queryByBrandId(Long brandId) {List<CategoryBrandRelationEntity> data = this.list(new QueryWrapper<CategoryBrandRelationEntity>().eq("brand_id",brandId));return data;}

给增加对应品牌增加 选中的三级分类

 /*** 自定义保存方法* 不仅要保存品牌和分类的关系,还要 查出来品牌名字、分类名字在保存* @param categoryBrandRelation*/@Overridepublic void saveRelationAndBrandName(CategoryBrandRelationEntity categoryBrandRelation) {Long brandId = categoryBrandRelation.getBrandId();Long catelogId = categoryBrandRelation.getCatelogId();// 查询品牌名,分类名CategoryEntity categoryEntity = categoryDao.selectById(catelogId);//CategoryEntity  categoryEntity = categoryDao.selectOne(new QueryWrapper<CategoryEntity>().eq("cat_id", catelogId));String categoryName = categoryEntity.getName();BrandEntity brandEntity = brandDao.selectById(brandId);String brandName = brandEntity.getName();categoryBrandRelation.setBrandName(brandName);categoryBrandRelation.setCatelogName(categoryName);this.save(categoryBrandRelation);}

因为表中存放了brendName 和 CatelogName 都是冗余字段,其他表中也有

因此为了保证数据的一致性,更新时需要级联更新


==== BrandServiceImpl ====/*** 更新品牌表 品牌名字段时,为了保证多表数据一致,需要进行 冗余数据表更新* @param brand*/@Overridepublic void updateAllDetail(BrandEntity brand) {this.updateById(brand);// 更新其他表Long brandId = brand.getBrandId();String brandName = brand.getName();categoryBrandRelationService.updateAllDetail(brandId,brandName);}===== CategoryBrandRelationServiceImpl ======/*** 更新品牌名字段,所有该字段都要更新* @param brandId* @param brandName*/@Overridepublic void updateAllBrandDetail(Long brandId, String brandName) {this.update(new UpdateWrapper<CategoryBrandRelationEntity>().eq("brand_id",brandId).set("brand_name",brandName));}/*** 更新三级分类字段,所有表该字段都要更新* @param catId* @param categoryName*/@Overridepublic void updateAllCategoryDetail(Long catId, String categoryName) {this.update(new UpdateWrapper<CategoryBrandRelationEntity>().eq("catelog_id",catId).set("catelog_name",categoryName));}

二、平台属性

数据库表关系(属性表、属性分组表、关联表)

三级分类表,属性分组表、属性表中 有 三级分类id

属性表

属性分组表

中间表

规格参数
1.新增属性

默认新增属性前端发送信息,后端需要更新 关联表 + 属性表

因此需要新建AttrVo类,加上 attrGroupId 字段便于 更新关联表,因此service层需要

  • 保存信息到属性表
  • 保存信息到关联表

 @Transactional@Overridepublic void saveAttr(AttrVo attr) {AttrEntity attrEntity = new AttrEntity();
//        attrEntity.setAttrName(attr.getAttrName());BeanUtils.copyProperties(attr,attrEntity);//1、保存基本数据this.save(attrEntity);//2、保存关联关系if(attr.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attr.getAttrGroupId()!=null){AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();relationEntity.setAttrGroupId(attr.getAttrGroupId());relationEntity.setAttrId(attrEntity.getAttrId());relationDao.insert(relationEntity);}}
2.查询属性

同样

  • 属性和三级分类、属性分组都有关联,而且 返回前端的数据需要包含 attr_group_name三级分类name
  • 因此需要新建AttrRespVo 需要在属性表实体类的基础上 新增三个字段,第三个字段为了修改时数据回显
 @Overridepublic PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String type) {QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().eq("attr_type","base".equalsIgnoreCase(type)?ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode():ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());if(catelogId != 0){queryWrapper.eq("catelog_id",catelogId);}String key = (String) params.get("key");if(!StringUtils.isEmpty(key)){//attr_id  attr_namequeryWrapper.and((wrapper)->{wrapper.eq("attr_id",key).or().like("attr_name",key);});}IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params),queryWrapper);// page中的信息不够PageUtils pageUtils = new PageUtils(page);List<AttrEntity> records = page.getRecords();List<AttrRespVo> respVos = records.stream().map((attrEntity) -> {AttrRespVo attrRespVo = new AttrRespVo();BeanUtils.copyProperties(attrEntity, attrRespVo);//1、设置分类和分组的名字// 尽量不要多表联合查询if("base".equalsIgnoreCase(type)){// 按照属性id 在 关联表 查出分组idAttrAttrgroupRelationEntity attrId = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));if (attrId != null && attrId.getAttrGroupId()!=null) {// 根据分组id查询分组名字AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrId.getAttrGroupId());attrRespVo.setGroupName(attrGroupEntity.getAttrGroupName());}}// 查询分类名字CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());if (categoryEntity != null) {attrRespVo.setCatelogName(categoryEntity.getName());}return attrRespVo;}).collect(Collectors.toList());pageUtils.setList(respVos);return pageUtils;}
3.修改属性

数据回显

  • 属性表:属性名字
  • 关联表:获取分组id
  • 分组表:根据分组id获取分组名字
  • 分类表:根据分类id获取分类名字、分类路径
@Overridepublic AttrRespVo getAttrInfo(Long attrId) {// 返回结果AttrRespVo respVo = new AttrRespVo();// 属性表信息查询AttrEntity attrEntity = this.getById(attrId);// 属性赋值,但这些还不够BeanUtils.copyProperties(attrEntity,respVo);if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){//1、设置分组信息// 查询关联表AttrAttrgroupRelationEntity attrgroupRelation = relationDao.selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));if(attrgroupRelation!=null){// 获取分组idrespVo.setAttrGroupId(attrgroupRelation.getAttrGroupId());// 获取分组名字AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupRelation.getAttrGroupId());if(attrGroupEntity!=null){respVo.setGroupName(attrGroupEntity.getAttrGroupName());}}}//2、设置分类信息Long catelogId = attrEntity.getCatelogId();// 分组路径Long[] catelogPath = categoryService.getCatelogPathByCatelogId(catelogId);respVo.setCatelogPath(catelogPath);CategoryEntity categoryEntity = categoryDao.selectById(catelogId);if(categoryEntity!=null){// 分组名字respVo.setCatelogName(categoryEntity.getName());}return respVo;}

修改属性

@Transactional@Overridepublic void updateAttr(AttrVo attr) {AttrEntity attrEntity = new AttrEntity();BeanUtils.copyProperties(attr,attrEntity);// 更新属性表this.updateById(attrEntity);if(attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){//1、跟新关联表AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();relationEntity.setAttrGroupId(attr.getAttrGroupId());relationEntity.setAttrId(attr.getAttrId());Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));if(count>0){relationDao.update(relationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attr.getAttrId()));}else{relationDao.insert(relationEntity);}}}
销售属性

内容和规格参数类似,存的信息都在 属性表,attr_type区分,销售属性不用加分组关系


因此在增删改查方法加上判断就行,销售属性,不用加分组关系,也就是不用 关联表

属性分组


每个属性组可以关联 多个 属性,对应的信息保存在 关联表中

属性分组 批量 删除属性举栗,其他原理类似,省略。

@Overridepublic void deleteRelation(AttrGroupRelationVo[] vos) {//relationDao.delete(new QueryWrapper<>().eq("attr_id",1L).eq("attr_group_id",1L));// 封装为关联表的一个实体集合,自定义批量删除方法List<AttrAttrgroupRelationEntity> entities = Arrays.asList(vos).stream().map((item) -> {AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();BeanUtils.copyProperties(item, relationEntity);return relationEntity;}).collect(Collectors.toList());// 使用mapper文件完成删除操作relationDao.deleteBatchRelation(entities);}======= dao =========
package henu.soft.xiaosi.product.dao;import henu.soft.xiaosi.product.entity.AttrAttrgroupRelationEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import javax.websocket.server.PathParam;
import java.util.List;/*** 属性&属性分组关联** @author xiaosi* @email 2589165806@qq.com* @date 2021-07-22 21:04:34*/
@Mapper
public interface AttrAttrgroupRelationDao extends BaseMapper<AttrAttrgroupRelationEntity> {void deleteBatchRelation(@Param("entities") List<AttrAttrgroupRelationEntity> entities);
}====== xml ======<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="henu.soft.xiaosi.product.dao.AttrAttrgroupRelationDao"><!-- 可根据自己的需求,是否要使用 --><resultMap type="henu.soft.xiaosi.product.entity.AttrAttrgroupRelationEntity" id="attrAttrgroupRelationMap"><result property="id" column="id"/><result property="attrId" column="attr_id"/><result property="attrGroupId" column="attr_group_id"/><result property="attrSort" column="attr_sort"/></resultMap><delete id="deleteBatchRelation">DELETE from `pms_attr_attrgroup_relation` where<foreach collection="entities" item="item" separator=" OR ">(attr_id=#{item.attrId} AND attr_group_id=#{item.attrGroupId})</foreach></delete></mapper>

三、新增商品

1.获取选中的三级分类及品牌

2.商品json存储格式
~~~~~{==== SPU信息 ===="spuName": "IPhone xs Max","spuDescription": "机皇","catalogId": 225,"brandId": 15,"weight": 0.1,"publishStatus": 0,"decript": [],"images": [],"bounds": {"buyBounds": 0,"growBounds": 0},"baseAttrs": [{"attrId": 10,"attrValues": "英特尔","showDesc": 1}, {"attrId": 11,"attrValues": "英伟达","showDesc": 1}, {"attrId": 13,"attrValues": "玻璃;塑料","showDesc": 0}],==== SKU 信息 ==================SKU1==============="skus": [{"attr": [{"attrId": 12,"attrName": "颜色","attrValue": "蓝"}],"skuName": "IPhone xs Max 蓝","price": "8848","skuTitle": "IPhone xs Max 蓝","skuSubtitle": "副标题蓝","images": [],"descar": ["蓝"],"fullCount": 0,"discount": 0,"countStatus": 0,"fullPrice": 0,"reducePrice": 0,"priceStatus": 0,"memberPrice": [{"id": 2,"name": "青铜会员","price": 0}, {"id": 3,"name": "黄金会员","price": 0}]}, ===========SKU2============{"attr": [{"attrId": 12,"attrName": "颜色","attrValue": "红"}],"skuName": "IPhone xs Max 红","price": "8849","skuTitle": "IPhone xs Max 红","skuSubtitle": "副标题红","images": [],"descar": ["红"],"fullCount": 0,"discount": 0,"countStatus": 0,"fullPrice": 0,"reducePrice": 0,"priceStatus": 0,"memberPrice": [{"id": 2,"name": "青铜会员","price": 0}, {"id": 3,"name": "黄金会员","price": 0}]}]
}

需要注意

  • 将可能出现小数逇实体改成BigDecimal
  • 将表中主键字段对应属性改为Long
  • 需要加上JSR303校验注解
3.数据库表的设计

spu_info作为SPU基本信息

spu_images

spu_info_desc

product_attr_value

因此保存Spu信息需要

  1. 保存基本信息 spu_info
  2. 保存图片集
  3. 保存详细描述
  4. 保存规格参数
  5. 保存spu对应的sku信息

4.商品服务调用优惠券服务




现在 A服务 需要 像 B服务传 实体数据,需要将信息封装为对象TO,传输过程自动转化json

远程调用coupon服务的save方法

需要远程调用完成保存的内容

  • coupon优惠券信息
  • coupon价格满减信息
 /*** 保存Spu信息步骤* //TODO 高级部分完善* @param vo*/@Transactional@Overridepublic void saveSpuInfo(SpuSaveVo vo) {//1、保存spu基本信息 pms_spu_infoSpuInfoEntity infoEntity = new SpuInfoEntity();BeanUtils.copyProperties(vo,infoEntity);infoEntity.setCreateTime(new Date());infoEntity.setUpdateTime(new Date());this.saveBaseSpuInfo(infoEntity);//2、保存Spu的描述图片 pms_spu_info_descList<String> decript = vo.getDecript();SpuInfoDescEntity descEntity = new SpuInfoDescEntity();descEntity.setSpuId(infoEntity.getId());descEntity.setDecript(String.join(",",decript));spuInfoDescService.saveSpuInfoDesc(descEntity);//3、保存spu的图片集 pms_spu_imagesList<String> images = vo.getImages();imagesService.saveImages(infoEntity.getId(),images);//4、保存spu的规格参数;pms_product_attr_valueList<BaseAttrs> baseAttrs = vo.getBaseAttrs();List<ProductAttrValueEntity> collect = baseAttrs.stream().map(attr -> {ProductAttrValueEntity valueEntity = new ProductAttrValueEntity();valueEntity.setAttrId(attr.getAttrId());AttrEntity id = attrService.getById(attr.getAttrId());valueEntity.setAttrName(id.getAttrName());valueEntity.setAttrValue(attr.getAttrValues());valueEntity.setQuickShow(attr.getShowDesc());valueEntity.setSpuId(infoEntity.getId());return valueEntity;}).collect(Collectors.toList());attrValueService.saveProductAttr(collect);//5、保存spu的积分信息;gulimall_sms->sms_spu_boundsBounds bounds = vo.getBounds();SpuBoundTo spuBoundTo = new SpuBoundTo();BeanUtils.copyProperties(bounds,spuBoundTo);spuBoundTo.setSpuId(infoEntity.getId());R r = couponFeignService.saveSpuBounds(spuBoundTo);if(r.getCode() != 0){log.error("远程保存spu积分信息失败");}//5、保存当前spu对应的所有sku信息;List<Skus> skus = vo.getSkus();if(skus!=null && skus.size()>0){skus.forEach(item->{String defaultImg = "";for (Images image : item.getImages()) {if(image.getDefaultImg() == 1){defaultImg = image.getImgUrl();}}//    private String skuName;//    private BigDecimal price;//    private String skuTitle;//    private String skuSubtitle;SkuInfoEntity skuInfoEntity = new SkuInfoEntity();BeanUtils.copyProperties(item,skuInfoEntity);skuInfoEntity.setBrandId(infoEntity.getBrandId());skuInfoEntity.setCatalogId(infoEntity.getCatalogId());skuInfoEntity.setSaleCount(0L);skuInfoEntity.setSpuId(infoEntity.getId());skuInfoEntity.setSkuDefaultImg(defaultImg);//5.1)、sku的基本信息;pms_sku_infoskuInfoService.saveSkuInfo(skuInfoEntity);Long skuId = skuInfoEntity.getSkuId();List<SkuImagesEntity> imagesEntities = item.getImages().stream().map(img -> {SkuImagesEntity skuImagesEntity = new SkuImagesEntity();skuImagesEntity.setSkuId(skuId);skuImagesEntity.setImgUrl(img.getImgUrl());skuImagesEntity.setDefaultImg(img.getDefaultImg());return skuImagesEntity;}).filter(entity->{//返回true就是需要,false就是剔除return !StringUtils.isEmpty(entity.getImgUrl());}).collect(Collectors.toList());//5.2)、sku的图片信息;pms_sku_imageskuImagesService.saveBatch(imagesEntities);//TODO 没有图片路径的无需保存List<Attr> attr = item.getAttr();List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attr.stream().map(a -> {SkuSaleAttrValueEntity attrValueEntity = new SkuSaleAttrValueEntity();BeanUtils.copyProperties(a, attrValueEntity);attrValueEntity.setSkuId(skuId);return attrValueEntity;}).collect(Collectors.toList());//5.3)、sku的销售属性信息:pms_sku_sale_attr_valueskuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);// //5.4)、sku的优惠、满减等信息;gulimall_sms->sms_sku_ladder\sms_sku_full_reduction\sms_member_priceSkuReductionTo skuReductionTo = new SkuReductionTo();BeanUtils.copyProperties(item,skuReductionTo);skuReductionTo.setSkuId(skuId);if(skuReductionTo.getFullCount() >0 || skuReductionTo.getFullPrice().compareTo(new BigDecimal("0")) == 1){R r1 = couponFeignService.saveSkuReduction(skuReductionTo);if(r1.getCode() != 0){log.error("远程保存sku优惠信息失败");}}});}}
5.多条件查询
 @Overridepublic PageUtils queryPageByCondition(Map<String, Object> params) {QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();String key = (String) params.get("key");if(!StringUtils.isEmpty(key)){wrapper.and((w)->{w.eq("id",key).or().like("spu_name",key);});}// status=1 and (id=1 or spu_name like xxx)String status = (String) params.get("status");if(!StringUtils.isEmpty(status)){wrapper.eq("publish_status",status);}String brandId = (String) params.get("brandId");if(!StringUtils.isEmpty(brandId)&&!"0".equalsIgnoreCase(brandId)){wrapper.eq("brand_id",brandId);}String catelogId = (String) params.get("catelogId");if(!StringUtils.isEmpty(catelogId)&&!"0".equalsIgnoreCase(catelogId)){wrapper.eq("catalog_id",catelogId);}/*** status: 2* key:* brandId: 9* catelogId: 225*/IPage<SpuInfoEntity> page = this.page(new Query<SpuInfoEntity>().getPage(params),wrapper);return new PageUtils(page);}
6.日期格式处理

四、仓储管理

1.数据库表设计

ware_info表

ware_sku表

2.仓库查询

重写模糊查询条件

//    重写模糊查询@Overridepublic PageUtils queryPage(Map<String, Object> params) {QueryWrapper<WareInfoEntity> wrapper = new QueryWrapper<>();String key = (String) params.get("key");if (!StringUtils.isEmpty(key)){wrapper.eq("id",key).or().like("name",key).or().like("address",key).or().like("areacode",key);}IPage<WareInfoEntity> page = this.page(new Query<WareInfoEntity>().getPage(params),wrapper);return new PageUtils(page);}
3.仓库、SKU关联信息查询
 /*** 重新查询条件* @param params* @return*/@Overridepublic PageUtils queryPage(Map<String, Object> params) {QueryWrapper<WareSkuEntity> wrapper = new QueryWrapper<>();String skuId = (String) params.get("skuId");String wareId = (String) params.get("wareId");if(!StringUtils.isEmpty(skuId)){wrapper.eq("skuId",skuId).or().like("skuId",skuId);}if(!StringUtils.isEmpty(wareId)){wrapper.eq("wareId",wareId).or().like("wareId",wareId);}IPage<WareSkuEntity> page = this.page(new Query<WareSkuEntity>().getPage(params),wrapper);return new PageUtils(page);}
4.库存数量的新增

说明

  • 库存数量的新增不能直接使用逆向生成的代码完后新增,而是应该有采购单完成库存数量增加
  • 采购单分为
    • 商品库存紧缺,自动生成采购单
    • 人工生成采购单,然后合并

查询

 @Overridepublic PageUtils queryPage(Map<String, Object> params) {QueryWrapper<PurchaseDetailEntity> wrapper = new QueryWrapper<>();String key = (String) params.get("key");String status = (String) params.get("status");String wareId = (String) params.get("wareId");/*** sku_id、purcase_id 、key模糊查询*/if(!StringUtils.isEmpty(key)){wrapper.and((obj)->{obj.eq("sku_id",key).or().eq("purcase_id",key);});}if(!StringUtils.isEmpty(status)){wrapper.eq("status",status);}if(!StringUtils.isEmpty(wareId)){wrapper.eq("wareId",wareId);}IPage<PurchaseDetailEntity> page = this.page(new Query<PurchaseDetailEntity>().getPage(params),wrapper);return new PageUtils(page);}
5.合并采购需求到一个采购单


1.查找没有领取的采购需求

点击查询条件可以

/*** 查找未被接受的采购单* @param params* @return*/@Overridepublic PageUtils queryPageUnReceive(Map<String, Object> params) {IPage<PurchaseEntity> page = this.page(new Query<PurchaseEntity>().getPage(params),new QueryWrapper<PurchaseEntity>().eq("status",0).or().eq("status",1));return new PageUtils(page);}
2.分配采购单给指定用户

采购需求合并的时候

  • 选择已有的采购单:直接合并。
  • 不选采购单:新建合并的采购单无采单人,可以分配采单人

package henu.soft.common.constant;public class WareConstant {// 采购需求状态public enum  PurchaseStatEnum {CREATED(0,"新建状态"),ASSIGNED(1,"已分配"),REVEIVE(2,"已领取"),FINISH(3,"已完成"),HASERROR(4,"有异常");private int code;private String msg;PurchaseStatEnum(int code,String msg){this.code = code;this.msg = msg;}public int getCode() {return code;}public String getMsg() {return msg;}}// 采购单状态public enum  PurchaseDetailStatEnum {CREATED(0,"新建状态"),ASSIGNED(1,"已分配"),REVEIVE(2,"正在采购"),FINISH(3,"已完成"),HASERROR(4,"采购失败");private int code;private String msg;PurchaseDetailStatEnum(int code,String msg){this.code = code;this.msg = msg;}public int getCode() {return code;}public String getMsg() {return msg;}}
}
package henu.soft.xiaosi.ware.service.impl;import henu.soft.common.constant.WareConstant;
import henu.soft.xiaosi.ware.entity.PurchaseDetailEntity;
import henu.soft.xiaosi.ware.service.PurchaseDetailService;
import henu.soft.xiaosi.ware.vo.MergeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import henu.soft.common.utils.PageUtils;
import henu.soft.common.utils.Query;import henu.soft.xiaosi.ware.dao.PurchaseDao;
import henu.soft.xiaosi.ware.entity.PurchaseEntity;
import henu.soft.xiaosi.ware.service.PurchaseService;
import org.springframework.util.StringUtils;@Service("purchaseService")
public class PurchaseServiceImpl extends ServiceImpl<PurchaseDao, PurchaseEntity> implements PurchaseService {@AutowiredPurchaseDetailService purchaseDetailService;@Overridepublic PageUtils queryPage(Map<String, Object> params) {IPage<PurchaseEntity> page = this.page(new Query<PurchaseEntity>().getPage(params),new QueryWrapper<PurchaseEntity>());return new PageUtils(page);}/*** 查找未被接受的采购单* @param params* @return*/@Overridepublic PageUtils queryPageUnReceive(Map<String, Object> params) {IPage<PurchaseEntity> page = this.page(new Query<PurchaseEntity>().getPage(params),new QueryWrapper<PurchaseEntity>().eq("status",0).or().eq("status",1));return new PageUtils(page);}/*** 合并采购单* - 有分配人* - 无分配人* @param mergeVo*/@Overridepublic void mergerPurchase(MergeVo mergeVo) {Long purchaseId = mergeVo.getPurchaseId();// 无分配人if(purchaseId == null) {PurchaseEntity purchaseEntity = new PurchaseEntity();purchaseEntity.setCreateTime(new Date());purchaseEntity.setUpdateTime(new Date());purchaseEntity.setStatus(WareConstant.PurchaseStatEnum.CREATED.getCode());this.save(purchaseEntity);// 新增之后,回显填充到实体类purchaseId = purchaseEntity.getId();}List<Long> items = mergeVo.getItems();// 哪些采购单,封装成多条记录保存Long finalPurchaseId = purchaseId;List<PurchaseDetailEntity> collect = items.stream().map(i -> {PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();purchaseDetailEntity.setId(i);purchaseDetailEntity.setPurchaseId(finalPurchaseId);purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatEnum.ASSIGNED.getCode());return purchaseDetailEntity;}).collect(Collectors.toList());// 更新采购单信息PurchaseEntity purchaseEntity = new PurchaseEntity();purchaseEntity.setId(purchaseId);purchaseEntity.setUpdateTime(new Date());this.updateById(purchaseEntity);// 更新采购需求purchaseDetailService.saveBatch(collect);}}
6.模拟员工领取采购单

之前合并采购单,完后员工分配之后,采购单变成 已分配,需要 移动端的员工 接受采购单,使采购状态变为 已接受

/*** 员工领取已经被分配的采购单* @param purchaseIds*/@Overridepublic void receivePurchases(List<Long> purchaseIds) {// 更新所有的采购单信息状态List<PurchaseEntity> purchaseEntities = purchaseIds.stream().map(i -> {PurchaseEntity purchaseEntity = this.getById(i);return purchaseEntity;}).filter((item) -> {// 过滤采购单 确认采购单的状态为 新建、已分配状态Integer status = item.getStatus();if (status != null && (status == WareConstant.PurchaseStatEnum.CREATED.getCode() || status == WareConstant.PurchaseStatEnum.ASSIGNED.getCode())) {return true;}return false;}).map((item) -> {// 更新状态item.setStatus(WareConstant.PurchaseStatEnum.REVEIVE.getCode());item.setUpdateTime(new Date());return item;}).collect(Collectors.toList());this.saveBatch(purchaseEntities);// 更新采购需求状态purchaseEntities.forEach((item)->{List<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailService.getPurchaseDetailByPurchaseId(item.getId());// 只更新两个属性List<PurchaseDetailEntity> collect = purchaseDetailEntities.stream().map(entity -> {PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();purchaseDetailEntity.setId(entity.getId());purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatEnum.REVEIVE.getCode());return purchaseDetailEntity;}).collect(Collectors.toList());purchaseDetailService.updateBatchById(collect);});}


7.模拟员工完成采购单

分析

  • 因为采购单中包含多个采购需求,因此需要对每一项采购结果判断处理
  • 采购完成调用远程的服务procduct完成sku数量的更新
 /*** 员工完成采购单* @param doneVo*/@Transactional@Overridepublic void donePurchases(PurchaseDoneVo doneVo) {Long id = doneVo.getId();//2、改变采购项的状态Boolean flag = true;List<PurchaseItemDoneVo> items = doneVo.getItems();List<PurchaseDetailEntity> updates = new ArrayList<>();for (PurchaseItemDoneVo item : items) {PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();// 某个采购需求有异常if(item.getStatus() == WareConstant.PurchaseDetailStatEnum.HASERROR.getCode()){flag = false;detailEntity.setStatus(item.getStatus());}else{// 全部采购成功detailEntity.setStatus(WareConstant.PurchaseDetailStatEnum.FINISH.getCode());3、将成功采购的进行入库PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId());wareSkuService.addStock(entity.getSkuId(),entity.getWareId(),entity.getSkuNum());}detailEntity.setId(item.getItemId());updates.add(detailEntity);}purchaseDetailService.updateBatchById(updates);//1、改变采购单状态PurchaseEntity purchaseEntity = new PurchaseEntity();purchaseEntity.setId(id);purchaseEntity.setStatus(flag?WareConstant.PurchaseStatEnum.FINISH.getCode():WareConstant.PurchaseStatEnum.HASERROR.getCode());purchaseEntity.setUpdateTime(new Date());this.updateById(purchaseEntity);}

商品入库

/*** 采购单完成,需要远程调用* @param skuId* @param wareId* @param skuNum*/@Overridepublic void addStock(Long skuId, Long wareId, Integer skuNum) {//1、判断如果还没有这个库存记录新增List<WareSkuEntity> entities = wareSkuDao.selectList(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));if(entities == null || entities.size() == 0){WareSkuEntity skuEntity = new WareSkuEntity();skuEntity.setSkuId(skuId);skuEntity.setStock(skuNum);skuEntity.setWareId(wareId);skuEntity.setStockLocked(0);//TODO 远程查询sku的名字,如果失败,整个事务无需回滚//1、自己catch异常//TODO 还可以用什么办法让异常出现以后不回滚?高级try {R info = productFeignService.info(skuId);Map<String,Object> data = (Map<String, Object>) info.get("skuInfo");if(info.getCode() == 0){skuEntity.setSkuName((String) data.get("skuName"));}}catch (Exception e){}wareSkuDao.insert(skuEntity);}else{wareSkuDao.addStock(skuId,wareId,skuNum);}}


五、分布式基础篇完结

报错:报错1_本地手动检验Valid字段校验不生效解决方法升级hibernate-validator依赖的版本

前端部分知识点记录:Vue常用API小结_谷粒商城分布式基础篇项目前端API知识小记

谷粒商城项目篇6_分布式基础完结篇_商品服务模块(品牌管理、平台属性、新增商品)、仓储服务模块(仓库管理)相关推荐

  1. 谷粒商城项目笔记之分布式基础(一)

    谷粒商城项目之分布式基础 目录 谷粒商城项目之分布式基础 前言 1 项目简介 1.1 项目背景 1.1.1 电商模式 1.1.2 谷粒商城 1.2 项目架构图 1.2.1 项目微服务架构图 1.2.2 ...

  2. 谷粒商城项目笔记之分布式基础(三)

    目录 6.3 属性服务 6.3.1 spu和sku 6.3.2 基本属性[规格参数]与销售属性 6.3.3 属性分组准备工作 1.前端组件 2.父子组件传递数据 6.3.4 获取分类属性分组 1.修改 ...

  3. 《谷粒商城基础篇》分布式基础环境搭建

    前沿:思考一个问题,为啥要做笔记? 为了知识更有条理,为了自己学过之后下次遇到立刻可以想起来,即使想不起,也可以通过自己的笔记快速定位~ 毕竟互联网的知识迭代速度非常之快 笔记更是知识输入的一条路径, ...

  4. M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档

    M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档 分布式基础篇 一.环境搭建 各种开发软件的安装 虚拟机: docker,mysql,redis 主机: Maven, idea(后端),Vs ...

  5. 谷粒商城基础篇-1.分布式基础概念架构图与功能模块图

    一.分布式基础概念 1.微服务: 把一个单独的应用程序开发我i一套小服务,每个小服务运行在自己的进程中,并使用轻量级通信,如http API.这些服务围绕业务能力搭建,并通过完全自动化部署机制独立部署 ...

  6. 谷粒商城项目学-分布式基础

    项目框架图 分布式基础概念 • 微服务.注册中心.配置中心.远程调用.Feign.网关 • 2.基础开发 • SpringBoot2.0.SpringCloud.Mybatis-Plus.Vue组件化 ...

  7. GuLi商城-简介-项目介绍、分布式基础概念、微服务架构图

    一.项目简介 1 .项目背景 1 ).电商模式 市面上有 5 种常见的电商模式 B2B.B2C.C2B.C2C.O2O: 1 . B2B 模式 B2B (Business to Business), ...

  8. 谷粒商城-基础篇-商品服务2-品牌管理(P59-P69)+(P75)

    目录 一.商品服务-API-品牌管理 1.使用逆向工程的前后端代码 2.效果优化及显示开关 3.云存储开通与使用 (1)阿里云对象存储oss (2)oss整合测试 (3)SpringCloud Ali ...

  9. 谷粒商城项目搭建思路

    文章目录 基础篇 核心技术点 1. 搭建环境 1.1 安装Linux虚拟机 1.2 安装Docker 1.3 统一开发环境 1.4 搭建后台管理项目 1.5 逆向工程 1.6 测试商品服务功能 1.7 ...

最新文章

  1. IOS开发----生成静态库(.a)
  2. Hexo博客NexT主题美化之顶部加载进度条
  3. node爬取app数据_node爬取拉勾网数据并导出为excel文件
  4. 即日起更新机器学习相关博客
  5. Linux运维工程师必学必备的8项IT技能
  6. php 调用python 脚本
  7. 所有关于php上传,关于php文件上传
  8. 有向图的强联通分量 Tarjan算法模板
  9. WINDOWS 2008Server 配置nginx 反向代理服务器 安装成服务
  10. sda、sdb 在linux中是什么意思
  11. oracle清楚表空间碎片,ORACLE表空间的碎片整理
  12. 信息检索1.3.学术搜索引擎--谷歌学术搜索引擎
  13. Linux 命令(159)—— hostname 命令
  14. python基础教程: 利用turtle库绘制笑脸和哭脸的例子
  15. 思科交换机的登录、密码恢复与应用
  16. 栈内存和堆内存的区别
  17. 查看文章 mysql:表注释和字段注释
  18. 【Java高级程序设计学习笔记】深入理解jdk动态代理
  19. 采购订单管理的四种常见类型
  20. vuejs+d3.js开发的轨道图+饼图

热门文章

  1. 协议转换网关 通用服务器,数据采集、协议转换网关
  2. Kettle问题:脚本在本地运行正常,但上传服务器后运行失败
  3. Vue + Element UI——大学课程表(包括普通课和实践课)解决方案
  4. 人人都能成为闪电网络节点:第5章lightning-cli详解
  5. skywalking链路追踪实战(docker)
  6. w10系统 pycharm 如何使用docker开发
  7. python计算趋肤深度
  8. 2-CO-COPC-实际成本
  9. S32K142的lin组件使用
  10. 模式识别学习笔记(5)——最大似然和贝叶斯参数估计