谷粒商城项目篇6_分布式基础完结篇_商品服务模块(品牌管理、平台属性、新增商品)、仓储服务模块(仓库管理)
目录
- 商品服务模块
- 品牌管理
- 品牌对应三级目录的增删改查
- 平台属性
- 数据库表关系
- 规格参数
- 增删改查
- 销售属性
- 属性分组
- 新增商品
- 获取三级分类及品牌
- 商品json存储格式
- 数据库表设计
- 商品服务调用优惠券服务
- 多条件查询
- 日期格式处理
- 品牌管理
- 仓储服务模块
- 仓库管理
- 数据库表设计
- 仓库查询
- 仓库、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信息需要
- 保存基本信息 spu_info
- 保存图片集
- 保存详细描述
- 保存规格参数
- 保存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.2 谷粒商城 1.2 项目架构图 1.2.1 项目微服务架构图 1.2.2 ...
- 谷粒商城项目笔记之分布式基础(三)
目录 6.3 属性服务 6.3.1 spu和sku 6.3.2 基本属性[规格参数]与销售属性 6.3.3 属性分组准备工作 1.前端组件 2.父子组件传递数据 6.3.4 获取分类属性分组 1.修改 ...
- 《谷粒商城基础篇》分布式基础环境搭建
前沿:思考一个问题,为啥要做笔记? 为了知识更有条理,为了自己学过之后下次遇到立刻可以想起来,即使想不起,也可以通过自己的笔记快速定位~ 毕竟互联网的知识迭代速度非常之快 笔记更是知识输入的一条路径, ...
- M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档
M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档 分布式基础篇 一.环境搭建 各种开发软件的安装 虚拟机: docker,mysql,redis 主机: Maven, idea(后端),Vs ...
- 谷粒商城基础篇-1.分布式基础概念架构图与功能模块图
一.分布式基础概念 1.微服务: 把一个单独的应用程序开发我i一套小服务,每个小服务运行在自己的进程中,并使用轻量级通信,如http API.这些服务围绕业务能力搭建,并通过完全自动化部署机制独立部署 ...
- 谷粒商城项目学-分布式基础
项目框架图 分布式基础概念 • 微服务.注册中心.配置中心.远程调用.Feign.网关 • 2.基础开发 • SpringBoot2.0.SpringCloud.Mybatis-Plus.Vue组件化 ...
- GuLi商城-简介-项目介绍、分布式基础概念、微服务架构图
一.项目简介 1 .项目背景 1 ).电商模式 市面上有 5 种常见的电商模式 B2B.B2C.C2B.C2C.O2O: 1 . B2B 模式 B2B (Business to Business), ...
- 谷粒商城-基础篇-商品服务2-品牌管理(P59-P69)+(P75)
目录 一.商品服务-API-品牌管理 1.使用逆向工程的前后端代码 2.效果优化及显示开关 3.云存储开通与使用 (1)阿里云对象存储oss (2)oss整合测试 (3)SpringCloud Ali ...
- 谷粒商城项目搭建思路
文章目录 基础篇 核心技术点 1. 搭建环境 1.1 安装Linux虚拟机 1.2 安装Docker 1.3 统一开发环境 1.4 搭建后台管理项目 1.5 逆向工程 1.6 测试商品服务功能 1.7 ...
最新文章
- IOS开发----生成静态库(.a)
- Hexo博客NexT主题美化之顶部加载进度条
- node爬取app数据_node爬取拉勾网数据并导出为excel文件
- 即日起更新机器学习相关博客
- Linux运维工程师必学必备的8项IT技能
- php 调用python 脚本
- 所有关于php上传,关于php文件上传
- 有向图的强联通分量 Tarjan算法模板
- WINDOWS 2008Server 配置nginx 反向代理服务器 安装成服务
- sda、sdb 在linux中是什么意思
- oracle清楚表空间碎片,ORACLE表空间的碎片整理
- 信息检索1.3.学术搜索引擎--谷歌学术搜索引擎
- Linux 命令(159)—— hostname 命令
- python基础教程: 利用turtle库绘制笑脸和哭脸的例子
- 思科交换机的登录、密码恢复与应用
- 栈内存和堆内存的区别
- 查看文章 mysql:表注释和字段注释
- 【Java高级程序设计学习笔记】深入理解jdk动态代理
- 采购订单管理的四种常见类型
- vuejs+d3.js开发的轨道图+饼图