IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 谷粒商城-基础篇-仓储服务(P95-P99) -> 正文阅读

[Java知识库]谷粒商城-基础篇-仓储服务(P95-P99)


仓储服务

一、仓储服务-API

库存信息表:

wms_ware_info 包括仓库所在地区等仓库信息(与商品无关)
wms_ware_sku:具体商品的库存量和所在仓库
wms_purchase_detail:采购需求
wms_purchase:采购单
wms_ware_order_task:库存工作单
wms_ware_order_task_detail:库存工作单详情


1、整合ware服务

gulimall-ware:

  • 创建项目后nacos注册、网关重写等
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
		#ware服务路由
        - id: ware_route
          uri: lb://gulimall-ware
          predicates:
            - Path=/api/ware/**
          filters:
            # 把/api/* 去掉,剩下的留下来
            - RewritePath=/api/(?<segment>.*),/$\{segment}


2、仓库维护

提供模糊查询的仓库信息:
在这里插入图片描述

 @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、商品库存

功能:查询sku+库存id+库存数等信息

在这里插入图片描述

数据库表:wms_ware_sku 指明每个仓库有什么sku
在这里插入图片描述

手动新增库存:商品库存页面/新增,然后填写 sku_id+仓库+库存数 等信息
在这里插入图片描述

自动新增库存:需要通过采购完成


4、采购单维护


(1)采购需求

采购需求的生成方式可能有两种:

  • 人工新增
  • 系统检测到库存量低时自动创建

流程:
在这里插入图片描述


(2)合并采购需求

比如一个仓库的东西可以合并到一起,让采购人员一趟采购完

  1. 查询未领取的采购单:/ware/purchase/unreceive/list
  @Override
    public 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);
    }
  1. 采购单
  • wms_purchase采购单,里面有创建时间和分类人员等信息
  • wms_purchase_detail采购单详情表,指明采购单每项要采购的sku,可以自己新增采购单,然后让新的采购需求合并到已有采购单里。

采购单状态:只有新建、已分配的时候才能合并采购单

新建 0
已分配 1
已领取(正在采购) 2
已完成 3
有异常(采购失败) 4

  1. 合并采购需求:/ware/purchase/merge

请求数据:
{
purchaseId: 1, # 采购单id,没有携带就新建采购单
items: [1, 2] # 采购商品
}

注:如果不选择整单直接点击确定,将弹出提示。

在这里插入图片描述

流程:

  • 如果没有带过来采购单id,先新建采购单
  • 然后修改【采购需求】里对应的【采购单id、采购需求状态】,即purchase_detail
  • 采购需求是purchase_detail表、采购单是purchase表。采购单由多个采购需求组成
  • 采购单页面分配采购需求成功后应该刷新页面,或者说不能重复分配采购需求给不同的采购单(或者说是一个更新操作)

PurchaseServiceImpl

  /**
     * 合并采购需求
     *
     * @param mergeVo
     */
    @Transactional
    @Override
    public void mergePurchase(MergeVo mergeVo) {

        Long purchaseId = mergeVo.getPurchaseId();
        // 一、判断是否有采购单,没有的话新建一个
        if (purchaseId == null) {
            //1、新建一个
            PurchaseEntity purchaseEntity = new PurchaseEntity();
            //2、修改对应转态
            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode());
            purchaseEntity.setCreateTime(new Date());
            purchaseEntity.setUpdateTime(new Date());

            this.save(purchaseEntity);
            purchaseId = purchaseEntity.getId();
        }

        //TODO 确认采购单状态是0,1才可以合并

        // 二、有采购单id,进行合并
        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());
        this.updateById(purchaseEntity);

    }

采购需求状态枚举:

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;
        }
    }
}


(3)领取采购单

请求地址:/ware/purchase/received

  • 某个人领取了采购单后,先看采购单是否处于未分配状态,只有采购单是新建或以领取状态时,才更新采购单的状态
  • 领取后确认采购单的状态、采购单人员等是否相符
  • 更改采购单状态、更改采购需求状态

后台系统里没有领取采购单这个功能,我们暂时通过postman手动领取采购单

  • http://localhost:88/api/ware/purchase/received
 /**
     * 领取采购单
     * ids:采购单id
     * 过滤采购需求,并同步采购需求的状态
     */
    @Override
    public void received(List<Long> ids) {

        //1、确认当前采购单是新建或者已分配状态
        List<PurchaseEntity> collect = ids.stream().map(id -> {
            // 1.1 查出采购单详细信息
            PurchaseEntity byId = this.getById(id);
            return byId;
        }).filter(item -> {
            // 1.2 过滤出新建过着已分配的采购单
            if (item.getStatus() == WareConstant.PurchaseStatusEnum.CREATED.getCode() || item.getStatus() == WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()) {
                return true;
            }
            return false;
        }).map(item -> {
            // 1.3 设置最新状态
            item.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());
            item.setUpdateTime(new Date());
            return item;
        }).collect(Collectors.toList());

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

        //3、改变采购需求的状态
        collect.forEach((item) -> {
            // 3.1 找到采购项(采购需求)
            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());
            // 3.2 批量更新状态
            detailService.updateBatchById(detailEntities);
        });
    }

(4)完成采购,添加到库存

在这里插入图片描述

可以多选采购单里哪些采购项(需求)完成了

  • 采购项都完成的时候采购单为完成,否则为有异常

在这里插入图片描述

  • 采购项完成时增加到库存
    在这里插入图片描述

  • 增加库存时要判断原来是否有库存以区分insert和update

API信息:同样相关页面也省略,通过POSTMAN发送,代表采购员采购回来了,提交信息

 /**
     * 完成采购
     *
     * @param doneVo
     */
    @Transactional
    @Override
    public void done(PurchaseDoneVo doneVo) {

        Long id = doneVo.getId();

        //2、改变采购项(需求)的状态
        Boolean flag = true;
        List<PurchaseItemDoneVo> items = doneVo.getItems();
        // 2.1 收集要更新的信息
        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、将成功采购的进行入库
                // 3.1 先查出采购项
                PurchaseDetailEntity entity = detailService.getById(item.getItemId());
                wareSkuService.addStock(entity.getSkuId(), entity.getWareId(), entity.getSkuNum());

            }
            detailEntity.setId(item.getItemId());
            // 更新信息
            updates.add(detailEntity);
        }

        // 2.2 更新信息
        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);

    }

完成采购增加库存时,需要涉及到设置SKU的name信息到仓库中,这是通过feign远程调用“gulimall-product”服务来实现根据sku_id查询得到sku_name的。

只要异常被捕获,事务是不会滚的(这里需要优化,是高级篇消息队列实现一致性事务的内容)

  @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);
        }

    }

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-06-01 15:02:20  更:2022-06-01 15:06:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:01:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码