zoukankan      html  css  js  c++  java
  • 谷粒商城分布式基础(十一)—— 仓储服务API—仓库管理

    一、仓储服务

    1、整合ware服务

    (1)将gulimall-ware(仓储服务)加到注册中心nacos中
      (a)修改application.yml

      (b)开启服务注册发现功能

        顺便开启事务注解

      (c)启动gulimall-ware,观察nacos-server 

      至此,服务注册成功 

      注意:启动报错是配置中心的错误,暂时全部不用管,后期统一处理

    2)配置网关路由
      修改gulimall-gateway的application.yml
    - id: ware_route
    uri: lb://gulimall-ware
    predicates:
    - Path=/api/ware/**
    filters:
    - RewritePath=/api/(?<segment>/?.*),/$\{segment}

      修改完毕后,重启网关服务,查看

    2、获取仓库列表

    1)修改gulimall-ware的application.yml,设置日志打印级别

     (2)修改com.atguigu.gulimall.ware.service.impl.WareInfoServiceImpl 的 queryPage 方法

    @Override
    public 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、查询库存

    1)修改com.atguigu.gulimall.ware.service.impl.WareSkuServiceImpl的 queryPage 方法
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
    QueryWrapper<WareSkuEntity> wrapper = new QueryWrapper<>();
    String skuId = (String) params.get("skuId");
    if(!StringUtils.isEmpty(skuId)){
    wrapper.eq("sku_id",skuId);
    }
    String wareId = (String) params.get("wareId");
    if(!StringUtils.isEmpty(wareId)){
    wrapper.eq("ware_id",wareId);
    }
    IPage<WareSkuEntity> page = this.page(
    new Query<WareSkuEntity>().getPage(params),
    wrapper
    );
    return new PageUtils(page);
    }

    4、查询采购需求

    1)修改com.atguigu.gulimall.ware.service.impl.PurchaseDetailServiceImpl的 queryPage 方法
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
    QueryWrapper<PurchaseDetailEntity> wrapper = new QueryWrapper<>();
    String key = (String) params.get("key");
    if(!StringUtils.isEmpty(key)){
    wrapper.and(w->{
    w.eq("purchase_id",key).or().eq("sku_id",key);
    });
    }
    String status = (String) params.get("status");
    if(!StringUtils.isEmpty(status)){
    wrapper.eq("status",status);
    }
    String wareId = (String) params.get("wareId");
    if(!StringUtils.isEmpty(wareId)){
    wrapper.eq("ware_id",wareId);
    }
    IPage<PurchaseDetailEntity> page = this.page(
    new Query<PurchaseDetailEntity>().getPage(params),
    wrapper
    );
    return new PageUtils(page);
    }

    5、合并采购需求

    1)采购简要流程
     
    2)查询未领取的采购单
      (a)com.atguigu.gulimall.ware.controller.PurchaseController 新加方法 unreceivelist
    /**
    * 查询未领取的采购单
    * @param params
    * @return
    */
    ///ware/purchase/unreceive/list
    @RequestMapping("/unreceive/list")
    //@RequiresPermissions("ware:purchase:list")
    public R unreceivelist(@RequestParam Map<String, Object> params){
    PageUtils page = purchaseService.queryUnreceivePage(params);
    return R.ok().put("page", page);
    }
      (b)新增接口和实现方法 queryUnreceivePage
    /**
    * 查询未领取的采购单
    * @param params
    * @return
    */
    @Override
    public PageUtils queryUnreceivePage(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);
    }
    效果
    3)合并采购需求
      (a)gulimall-common 新增文件 com.atguigu.common.constant.WareConstant
    package com.atguigu.common.constant;

    public class WareConstant {
    public enum PurchaseStatusEnum{
    CREATED(0,"新建"),ASSIGNED(1,"已分配"),
    RECEIVE(2,"已领取"),FINISH(3,"已完成"),
    HASERROR(4,"有异常");
    private int code;
    private String msg;

    PurchaseStatusEnum(int code,String msg){
    this.code = code;
    this.msg = msg;
    }

    public int getCode() {
    return code;
    }

    public String getMsg() {
    return msg;
    }
    }

    public enum PurchaseDetailStatusEnum{
    CREATED(0,"新建"),ASSIGNED(1,"已分配"),
    BUYING(2,"正在采购"),FINISH(3,"已完成"),
    HASERROR(4,"采购失败");
    private int code;
    private String msg;

    PurchaseDetailStatusEnum(int code,String msg){
    this.code = code;
    this.msg = msg;
    }

    public int getCode() {
    return code;
    }

    public String getMsg() {
    return msg;
    }
    }
    }
      (b)新建文件 com.atguigu.gulimall.ware.vo.MergeVo
    package com.atguigu.gulimall.ware.vo;

    import lombok.Data;
    import java.util.List;

    @Data
    public class MergeVo {
    private Long purchaseId; //整单id
    private List<Long> items;//[1,2,3,4] //合并项集合
    }
      (c)com.atguigu.gulimall.ware.controller.PurchaseController 新加方法 merge
    /**
    * 合并采购需求
    * @param mergeVo
    * @return
    */
    ///ware/purchase/merge
    @PostMapping("/merge")
    public R merge(@RequestBody MergeVo mergeVo){
    purchaseService.mergePurchase(mergeVo);
    return R.ok();
    }

      (d)新增接口和实现方法 mergePurchase
    /**
    * 合并采购需求
    * @param mergeVo
    * @return
    */
    @Override
    @Transactional
    public void mergePurchase(MergeVo mergeVo) {
    Long purchaseId = mergeVo.getPurchaseId();
    if(purchaseId==null){
         //1、新建一个
    PurchaseEntity purchaseEntity = new PurchaseEntity();
    purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode());
    purchaseEntity.setCreateTime(new Date());
    purchaseEntity.setUpdateTime(new Date());
    this.save(purchaseEntity);
    purchaseId = purchaseEntity.getId();
    }
      //TODO 确认采购单状态是0或者1才可以合并
    List<Long> items = mergeVo.getItems();
    Long finalPurchaseId = purchaseId;
    List<PurchaseDetailEntity> collect = items.stream().map(i -> {
    PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();
    detailEntity.setId(i);
    detailEntity.setPurchaseId(finalPurchaseId);
    detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
    return detailEntity;
    }).collect(Collectors.toList());
    detailService.updateBatchById(collect);

    PurchaseEntity purchaseEntity = new PurchaseEntity();
    purchaseEntity.setId(purchaseId);
    purchaseEntity.setUpdateTime(new Date());
    purchaseEntity.setCreateTime(new Date());
    this.updateById(purchaseEntity);
    }
      (e)修改application.yml

    6、领取采购单

    1)com.atguigu.gulimall.ware.controller.PurchaseController 新加方法 received
    /**
    * 领取采购单
    * @param ids
    * @return
    */
    ///ware/purchase/received
    @PostMapping("/received")
    public R received(@RequestBody List<Long> ids){
    purchaseService.received(ids);
    return R.ok();
    }

    (2)新增接口和实现方法 received
    /**
    * 领取采购单
    * @param ids:采购单id
    */
    @Override
    @Transactional
    public void received(List<Long> ids) {
    //1、确认当前采购单是新建或者已分配状态
    List<PurchaseEntity> collect = ids.stream().map(id -> {
    PurchaseEntity byId = this.getById(id);
    return byId;
    }).filter(item -> {
    if (item.getStatus() == WareConstant.PurchaseDetailStatusEnum.CREATED.getCode() ||
    item.getStatus() == WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode()) {
    return true;
    }
    return false;
    }).map(item->{
    item.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());
    item.setUpdateTime(new Date());
    return item;
    }).collect(Collectors.toList());

    //2、改变采购单的状态
    this.updateBatchById(collect);

    //3、改变采购项的状态
    collect.forEach((item)->{
    List<PurchaseDetailEntity> entities = detailService.listDetailByPurchaseId(item.getId());
    List<PurchaseDetailEntity> detailEntities = entities.stream().map(entity -> {
    PurchaseDetailEntity entity1 = new PurchaseDetailEntity();
    entity1.setId(entity.getId());
    entity1.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());
    return entity1;
    }).collect(Collectors.toList());
    detailService.updateBatchById(detailEntities);
    });
    }

    (3)com.atguigu.gulimall.ware.service.PurchaseDetailService 新增方法 listDetailByPurchaseId
    /**
    * 根据采购单查询采购项
    * @param id
    * @return
    */
    @Override
    public List<PurchaseDetailEntity> listDetailByPurchaseId(Long id) {
    List<PurchaseDetailEntity> purchaseId = this.list(new QueryWrapper<PurchaseDetailEntity>().eq("purchase_id", id));
    return purchaseId;
    }
    (4)测试

    7、完成采购

    1)处理分页问题
      新建文件 com.atguigu.gulimall.ware.config.MyBatisConfig
    package com.atguigu.gulimall.ware.config;

    import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.transaction.annotation.EnableTransactionManagement;

    @Configuration
    @EnableTransactionManagement
    @MapperScan("com.atguigu.gulimall.ware.dao")
    public class MyBatisConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
    PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
    // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
    paginationInterceptor.setOverflow(true);
    // 设置最大单页限制数量,默认 500 条,-1 不受限制
    paginationInterceptor.setLimit(1000);
    // 开启 count 的 join 优化,只针对部分 left join
    paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
    return paginationInterceptor;
    }
    }
    2)新建远程调用接口 com.atguigu.gulimall.ware.feign.ProductFeignService
    package com.atguigu.gulimall.ware.feign;

    import com.atguigu.common.utils.R;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;

    @FeignClient("gulimall-product")
    public interface ProductFeignService {

    /**
    * /product/skuinfo/info/{skuId}
    *
    *
    * 1)、让所有请求过网关;
    * 1、@FeignClient("gulimall-gateway"):给gulimall-gateway所在的机器发请求
    * 2、/api/product/skuinfo/info/{skuId}
    * 2)、直接让后台指定服务处理
    * 1、@FeignClient("gulimall-gateway")
    * 2、/product/skuinfo/info/{skuId}
    *
    * @return
    */
    @RequestMapping("/product/skuinfo/info/{skuId}")
    public R info(@PathVariable("skuId") Long skuId);
    }
    3)开启远程调用服务功能
    (4)新增文件 com.atguigu.gulimall.ware.vo.PurchaseDoneVo
    package com.atguigu.gulimall.ware.vo;

    import lombok.Data;
    import javax.validation.constraints.NotNull;
    import java.util.List;

    @Data
    public class PurchaseDoneVo {

    @NotNull
    private Long id;//采购单id

    private List<PurchaseItemDoneVo> items;
    }
    5)新增文件 com.atguigu.gulimall.ware.vo.PurchaseItemDoneVo
    package com.atguigu.gulimall.ware.vo;

    import lombok.Data;

    @Data
    public class PurchaseItemDoneVo {
    //{itemId:1,status:4,reason:""}
    private Long itemId;
    private Integer status;
    private String reason;
    }
    (6)com.atguigu.gulimall.ware.controller.PurchaseController 新加方法 done
    /**
     * 完成采购
     * @param doneVo
     * @return
     */
    ///ware/purchase/done
    @PostMapping("/done")
    public R done(@RequestBody PurchaseDoneVo doneVo){
        purchaseService.done(doneVo);
        return R.ok();
    }
    (7)com.atguigu.gulimall.ware.service.impl.PurchaseServiceImpl 新增接口和实现类
    /**
    * 完成采购
    * @param doneVo
    */
    @Override
    @Transactional
    public void done(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.PurchaseDetailStatusEnum.HASERROR.getCode()){
    flag = false;
    detailEntity.setStatus(item.getStatus());
    }else{
    detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode());
    ////3、将成功采购的进行入库
    PurchaseDetailEntity entity = detailService.getById(item.getItemId());
    wareSkuService.addStock(entity.getSkuId(),entity.getWareId(),entity.getSkuNum());
    }
    detailEntity.setId(item.getItemId());
    updates.add(detailEntity);
    }

    detailService.updateBatchById(updates);

    //1、改变采购单状态
    PurchaseEntity purchaseEntity = new PurchaseEntity();
    purchaseEntity.setId(id);
    purchaseEntity.setStatus(flag?WareConstant.PurchaseStatusEnum.FINISH.getCode():WareConstant.PurchaseStatusEnum.HASERROR.getCode());
    purchaseEntity.setUpdateTime(new Date());
    this.updateById(purchaseEntity);
    }
    8)com.atguigu.gulimall.ware.service.impl.WareSkuServiceImpl 新增接口和实现方法
    /**
    * 入库
    * @param skuId
    * @param wareId
    * @param skuNum
    */
    @Override
    public 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);
    }
    }
    9)com.atguigu.gulimall.ware.dao.WareSkuDao 新增接口 addStock
    void addStock(@Param("skuId") Long skuId, @Param("wareId") Long wareId, @Param("skuNum") Integer skuNum);
    10)WareSkuDao.xml 新增xml方法
    <update id="addStock">
    UPDATE wms_ware_sku SET stock=stock+#{skuNum} WHERE sku_id=#{skuId} AND ware_id=#{wareId}
    </update>

    二、商品管理

    1、SPU规格维护

    1)解决spu管理规格点击404

      点规格,404,前端改一下:

      /src/router/index.js 在mainRoutes->children【】里面加上:

      { path: '/product-attrupdate', component: _import('modules/product/attrupdate'), name: 'attr-update', meta: { title: '规格维护', isTab: true } }

      修改后:

    2)获取spu规格
      (a)com.atguigu.gulimall.product.controller.AttrController 新增方法 baseAttrlistforspu
    /**
    * 获取spu规格
    * @param spuId
    * @return
    */
    ///product/attr/base/listforspu/{spuId}
    @GetMapping("/base/listforspu/{spuId}")
    public R baseAttrlistforspu(@PathVariable("spuId") Long spuId){
    List<ProductAttrValueEntity> entities = productAttrValueService.baseAttrlistforspu(spuId);
    return R.ok().put("data",entities);
    }
      (b)新增接口和实现类方法 baseAttrlistforspu
    /**
    * 获取spu规格
    * @param spuId
    * @return
    */
    @Override
    public List<ProductAttrValueEntity> baseAttrlistforspu(Long spuId) {
    List<ProductAttrValueEntity> spu_id = this.baseMapper.selectList(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
    return spu_id;
    }
    效果:

      回显成功

    3)修改商品规格
      (a)com.atguigu.gulimall.product.controller.AttrController 新增方法 updateSpuAttr
    /**
    * 修改商品规格
    * @param spuId
    * @param entities
    * @return
    */
    ///product/attr/update/{spuId}
    @RequestMapping("/update/{spuId}")
    public R updateSpuAttr(@PathVariable("spuId") Long spuId, @RequestBody List<ProductAttrValueEntity> entities){
    productAttrValueService.updateSpuAttr(spuId, entities);
    return R.ok();
    }
      (b)新增接口和实现类方法
    @Transactional
    @Override
    public void updateSpuAttr(Long spuId, List<ProductAttrValueEntity> entities) {
    //1、删除这个spuId之前对应的所有属性
    this.baseMapper.delete(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id",spuId));

    List<ProductAttrValueEntity> collect = entities.stream().map(item -> {
    item.setSpuId(spuId);
    return item;
    }).collect(Collectors.toList());
    this.saveBatch(collect);
    }
  • 相关阅读:
    iOS AFNetworking 2.6.0框架导入报错解决方法
    GitHub 上都有哪些值得关注学习的 iOS 开源项目?
    iOS开发ARC机制下的内存管理技术要点
    UIColor延伸:判断两个颜色是否相等
    iOS中的单例模式
    明天再整理,睡觉!
    pushViewController:animated:的问题
    解决UINavigationController在pushViewController时出现的"卡顿"问题
    在某OC字符串中,搜索指定的某字符串:-rangeOfString:
    SSH整合redis和MongoDB错误笔记
  • 原文地址:https://www.cnblogs.com/javahr/p/15697225.html
Copyright © 2011-2022 走看看