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

【第八篇】商城系统-库存管理_第1张图片

库存管理

1. 仓库列表维护

1.1 注册中心配置

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

【第八篇】商城系统-库存管理_第2张图片

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

【第八篇】商城系统-库存管理_第3张图片

1.2 网关路由配置

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

【第八篇】商城系统-库存管理_第4张图片

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

【第八篇】商城系统-库存管理_第5张图片

1.3 关键字查询

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

【第八篇】商城系统-库存管理_第6张图片

【第八篇】商城系统-库存管理_第7张图片

2.商品库存管理

添加对应的检索条件

【第八篇】商城系统-库存管理_第8张图片

效果展示

【第八篇】商城系统-库存管理_第9张图片

3.采购流程

完整的采购流程

【第八篇】商城系统-库存管理_第10张图片

3.1 采购需求维护

【第八篇】商城系统-库存管理_第11张图片

3.2 采购需求合并

3.2.1 查询分配的采购单

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

【第八篇】商城系统-库存管理_第12张图片

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

【第八篇】商城系统-库存管理_第13张图片

对应的需要创建接口

【第八篇】商城系统-库存管理_第14张图片

【第八篇】商城系统-库存管理_第15张图片

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

3.2.2 采购需求合并

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

@Data
public class MergeVO {
    //{ purchaseId: this.purchaseId, items: items }
    private Long purchaseId;
    private List<Long> items;
}

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

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

添加对应的接口

【第八篇】商城系统-库存管理_第16张图片

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

    /**
     * 完成采购需求的合单操作
     * @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;
    }

【第八篇】商城系统-库存管理_第17张图片

3.3 领取采购单

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

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

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

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

   /**
     * 领取采购单
     * @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发送请求测试

【第八篇】商城系统-库存管理_第18张图片

数据状态更新

【第八篇】商城系统-库存管理_第19张图片

【第八篇】商城系统-库存管理_第20张图片

搞定

3.4 完成采购操作

3.4.1 VO对象

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

/**
 * 采购项的VO数据
 */
@Data
public class PurchaseItemDoneVO {

    private Long itemId;
    private Integer status;
    private String reason;
}
/**
 * 采购单的VO数据
 */
@Data
public class PurchaseDoneVO {

    private Long id;

    private List<PurchaseItemDoneVO> items;

}

3.4.2 OpenFeign配置

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

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

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

在启动类中添加Enable注解

【第八篇】商城系统-库存管理_第21张图片

不要忘了添加对应的依赖

【第八篇】商城系统-库存管理_第22张图片

3.4.3 业务代码实现

首先是Controller接口的创建

【第八篇】商城系统-库存管理_第23张图片

然后对应的service逻辑的处理

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

    }

然后就是入库的逻辑操作

    /**
     * 入库操作
     * @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代码

@Mapper
public interface WareSkuDao extends BaseMapper<WareSkuEntity> {

    void addStock(@Param("skuId") Long skuId, @Param("wareId") Long wareId, @Param("skuNum") Integer skuNum);
}
    <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来测试完成操作

【第八篇】商城系统-库存管理_第24张图片

{
    "id":3,
    "items":[
        {"itemId":4,"status":3,"reason":""}
        ,{"itemId":5,"status":3,"reason":""}
    ]
}

商品库存

【第八篇】商城系统-库存管理_第25张图片

采购单

【第八篇】商城系统-库存管理_第26张图片

采购项

【第八篇】商城系统-库存管理_第27张图片

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

你可能感兴趣的:(商城项目,商品库存,Java项目,商城,SKU,SPU)