前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【第八篇】商城系统-库存管理

【第八篇】商城系统-库存管理

作者头像
用户4919348
发布2022-09-21 21:02:35
5460
发布2022-09-21 21:02:35
举报
文章被收录于专栏:波波烤鸭
在这里插入图片描述
在这里插入图片描述

库存管理

1. 仓库列表维护

1.1 注册中心配置

首先我们需要把库存服务注册到注册中心中。

image.png
image.png

然后在nacos中发现注册的服务

image.png
image.png

1.2 网关路由配置

客户端首先访问的都是网关服务,所以需要配置对应的路由规则

image.png
image.png

就可以完成对仓库列表的处理了

image.png
image.png

1.3 关键字查询

然后实现仓库列表的关键字查询

image.png
image.png
image.png
image.png

2.商品库存管理

添加对应的检索条件

image.png
image.png

效果展示

image.png
image.png

3.采购流程

完整的采购流程

image.png
image.png

3.1 采购需求维护

image.png
image.png

3.2 采购需求合并

3.2.1 查询分配的采购单

合并采购需求时我们需要把这些采购需求合并到一个采购单中,所以首先需要创建采购单

image.png
image.png

然后在整合时我们需要查询出状态为 新建 或者 已分配 的采购单

image.png
image.png

对应的需要创建接口

image.png
image.png
image.png
image.png

然后就可以实现整合处理了。

3.2.2 采购需求合并

接收传递的信息创建对应的VO对象

代码语言:javascript
复制
@Data
public class MergeVO {
    //{ purchaseId: this.purchaseId, items: items }
    private Long purchaseId;
    private List<Long> items;
}

创建对应的枚举类型的常量

代码语言:javascript
复制
package com.msb.common.constant;

/**
 * 库存模块的常量
 *
 */
public class WareConstant {

    /**
     * 采购单状态
     */
    public enum PurchaseStatusEnum{
        CREATED(0,"新建")
        ,ASSIGED(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,"新建")
        ,ASSIGED(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;
        }
    }
}

添加对应的接口

image.png
image.png

然后在service中完成对应的业务处理

代码语言:javascript
复制
    /**
     * 完成采购需求的合单操作
     * @param mergeVO
     * @return
     */
    @Transactional
    @Override
    public Integer merge(MergeVO mergeVO) {
        Long purchaseId = mergeVO.getPurchaseId();
        if(purchaseId == null){
           // 新建采购单
            PurchaseEntity purchaseEntity = new PurchaseEntity();
            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode());
            purchaseEntity.setCreateTime(new Date());
            purchaseEntity.setUpdateTime(new Date());
            this.save(purchaseEntity);
            purchaseId = purchaseEntity.getId();
        }

        // 整合菜单需求单
        List<Long> items = mergeVO.getItems();
        final long finalPurchaseId = purchaseId;
        List<PurchaseDetailEntity> list = items.stream().map(i -> {
            PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();
            // 更新每一条 需求单的 采购单编号
            detailEntity.setId(i);
            detailEntity.setPurchaseId(finalPurchaseId);
            detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGED.getCode());
            return detailEntity;
        }).collect(Collectors.toList());

        detailService.updateBatchById(list);
        // 更新对应的采购单的更新时间
        PurchaseEntity entity = new PurchaseEntity();
        entity.setId(purchaseId);
        entity.setUpdateTime(new Date());
        this.updateById(entity);
        return null;
    }
image.png
image.png

3.3 领取采购单

采购单合单完成后,采购人员需要对应的领取采购单来执行后续的流程

先创建对应的领取采购单的接口

代码语言:javascript
复制
    /**
     * 领取采购单
     * [2,3,4]
     * @return
     */
    @PostMapping("/receive")
    public R receive(@RequestBody List<Long> ids){
        purchaseService.received(ids);
        return R.ok();
    }

在service中实现领取采购单的业务

代码语言:javascript
复制
   /**
     * 领取采购单
     * @param ids
     */
    @Transactional
    @Override
    public void received(List<Long> ids) {
        // 1.领取的采购单的状态只能是新建或者已分配的采购单 其他的是不能领取的
        List<PurchaseEntity> list = ids.stream().map(id -> {
            return this.getById(id);
        }).filter(item -> {

            if (item.getStatus() == WareConstant.PurchaseStatusEnum.CREATED.getCode() ||
                    item.getStatus() == WareConstant.PurchaseStatusEnum.ASSIGED.getCode()) {

                return true;
            }
            return false;
        }).map(item->{
            item.setUpdateTime(new Date()); // 设置更新时间
            // 更新采购单的状态为 已领取
            item.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());
            return item;
        }).collect(Collectors.toList());
        // 2.更新采购单的状态为 已领取
        this.updateBatchById(list);
        // 3.更新采购项的状态为 正在采购

        for (Long id : ids) {
            // 根据采购单id 找到对应的采购项对象
            List<PurchaseDetailEntity> detailEntities = detailService.listDetailByPurchaseId(id);
            List<PurchaseDetailEntity> collect = detailEntities.stream().map(item -> {
                PurchaseDetailEntity entity = new PurchaseDetailEntity();
                entity.setId(item.getId());
                entity.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());
                return entity;
            }).collect(Collectors.toList());
            // 批量更新采购项
            detailService.updateBatchById(collect);
        }
    }

postman发送请求测试

image.png
image.png

数据状态更新

image.png
image.png
image.png
image.png

搞定

3.4 完成采购操作

3.4.1 VO对象

创建对应的VO对象来接收传递的数据

代码语言:javascript
复制
/**
 * 采购项的VO数据
 */
@Data
public class PurchaseItemDoneVO {

    private Long itemId;
    private Integer status;
    private String reason;
}
代码语言:javascript
复制
/**
 * 采购单的VO数据
 */
@Data
public class PurchaseDoneVO {

    private Long id;

    private List<PurchaseItemDoneVO> items;

}
3.4.2 OpenFeign配置

OpenFeign的配置-在商品入库的时候我们需要通过OpenFegin来调用商品服务的接口来查询sku的名称

代码语言:javascript
复制
@FeignClient("mall-product")
public interface ProductFeignService {

    /**
     * 当然我们也可以通过网关来调用商品服务
     * @param skuId
     * @return
     */
    @RequestMapping("/product/skuinfo/info/{skuId}")
    public R info(@PathVariable("skuId") Long skuId);
}

在启动类中添加Enable注解

image.png
image.png

不要忘了添加对应的依赖

image.png
image.png
3.4.3 业务代码实现

首先是Controller接口的创建

image.png
image.png

然后对应的service逻辑的处理

代码语言:javascript
复制
    @Transactional
    @Override
    public void done(PurchaseDoneVO vo) {
        // 获取采购单编号
        Long id = vo.getId();
        // 2.改变采购项的状态
        Boolean flag = true; // 记录采购的状态 默认为 完成
        // 获取所有的采购项
        List<PurchaseItemDoneVO> items = vo.getItems();
        List<PurchaseDetailEntity> list = 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 detailEntity1 = detailService.getById(item.getItemId());
                wareSkuService.addStock(detailEntity1.getSkuId(),detailEntity1.getWareId(),detailEntity1.getSkuNum());

            }
            detailEntity.setId(item.getItemId());
            //detailService.updateById(detailEntity);
            list.add(detailEntity);
        }
        detailService.updateBatchById(list); // 批量更新 采购项

        // 1.改变采购单的状态
        PurchaseEntity purchaseEntity = new PurchaseEntity();
        purchaseEntity.setId(id);
        purchaseEntity.setStatus(flag?WareConstant.PurchaseStatusEnum.FINISH.getCode()
                : WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode());
        purchaseEntity.setUpdateTime(new Date());
        this.updateById(purchaseEntity);

    }

然后就是入库的逻辑操作

代码语言:javascript
复制
    /**
     * 入库操作
     * @param skuId 商品编号
     * @param wareId 仓库编号
     * @param skuNum  采购商品的数量
     */
    @Override
    public void addStock(Long skuId, Long wareId, Integer skuNum) {
        // 判断是否有改商品和仓库的入库记录
        List<WareSkuEntity> list = skuDao.selectList(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
        if(list == null || list.size() == 0){
            // 如果没有就新增商品库存记录
            WareSkuEntity entity = new WareSkuEntity();
            entity.setSkuId(skuId);
            entity.setWareId(wareId);
            entity.setStock(skuNum);
            entity.setStockLocked(0);
            try {
                // 动态的设置商品的名称
                R info = productFeignService.info(skuId); // 通过Feign远程调用商品服务的接口
                Map<String,Object> data = (Map<String, Object>) info.get("skuInfo");
                if(info.getCode() == 0){
                    entity.setSkuName((String) data.get("skuName"));
                }
            }catch (Exception e){

            }
            skuDao.insert(entity); // 插入商品库存记录
        }else{
            // 如果有就更新库存
            skuDao.addStock(skuId,wareId,skuNum);
        }


    }

然后对应的Dao接口和Mapper的SQL代码

代码语言:javascript
复制
@Mapper
public interface WareSkuDao extends BaseMapper<WareSkuEntity> {

    void addStock(@Param("skuId") Long skuId, @Param("wareId") Long wareId, @Param("skuNum") Integer skuNum);
}
代码语言:javascript
复制
    <insert id="addStock">
        UPDATE wms_ware_sku SET stock=stock+#{skuNum} WHERE sku_id=#{skuId} AND ware_id=#{wareId}
    </insert>
3.4.4 PostMan测试

最后通过PostMan来测试完成操作

image.png
image.png
代码语言:javascript
复制
{
    "id":3,
    "items":[
        {"itemId":4,"status":3,"reason":""}
        ,{"itemId":5,"status":3,"reason":""}
    ]
}

商品库存

image.png
image.png

采购单

image.png
image.png

采购项

image.png
image.png

4.阶段性总结

4.1 分布式的概念

微服务(SpringCloudAlibaba)

注册中心,配置中心,远程调用,网关,负载均衡,链路追踪…

4.2 技术栈

SpringBoot2.4.12 SpringCloud MyBatis-Plus MySQL Vue ElementUI 人人fast,阿里云对象存储

4.3 环境

Docker Linux Vagrant MySQL Redis 人人开源

4.4 开发规范

数据校验JSR303 全局跨域 R全局统一返回,全局异常处理 枚举状态 业务状态,VO、DTO、PO划分,逻辑删除,Lombok

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 库存管理
    • 1. 仓库列表维护
      • 1.1 注册中心配置
      • 1.2 网关路由配置
      • 1.3 关键字查询
    • 2.商品库存管理
      • 3.采购流程
        • 3.1 采购需求维护
        • 3.2 采购需求合并
        • 3.3 领取采购单
        • 3.4 完成采购操作
      • 4.阶段性总结
        • 4.1 分布式的概念
        • 4.2 技术栈
        • 4.3 环境
        • 4.4 开发规范
    相关产品与服务
    云数据库 SQL Server
    腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档