仓储服务-采购业务

在这里插入图片描述

1.合并采购需求

请求参数

{
  purchaseId: 1, //整单id
  items:[1,2,3,4] //合并项集合
}

(1) 合并时如果未选择合并的采购单,则先新建采购单然后合并到新建的采购单
在这里插入图片描述
新建的采购单,可以手动给采购单分配人员
在这里插入图片描述

(2)合并时选中了采购单就直接合并
在这里插入图片描述
(3)合并之后设置采购单id并且设置状态为已分配
在这里插入图片描述

合并成功采购单状态无需更改
在这里插入图片描述

/**
     * 合并采购需求/ware/purchase/merge
     * {
     *   purchaseId: 1, //整单id
     *   items:[1,2,3,4] //合并项集合
     * }
     */
    @Transactional
    @Override
    public void mergePurchase(MergeVo mergeVo) {
        //purchaseId不存在(未选择采购单),则自动创建新采购单进行合并,purchaseId存在,则直接赋值即可,并修改状态 (新建 -> 已分配)
        Long purchaseId = mergeVo.getPurchaseId();
        if (mergeVo.getPurchaseId() == null){
            //创建新采购单
            PurchaseEntity purchaseEntity = new PurchaseEntity();
            purchaseEntity.setCreateTime(new Date());
            purchaseEntity.setUpdateTime(new Date());
            //设置状态为:新建
            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATE.getCode());
            this.save(purchaseEntity);
            purchaseId = purchaseEntity.getId();
        }

        //TODO 正在采购中的采购需求不能进行合并,确认采购单是0或1才可以合并
        //purchaseId存在(已选择采购单),则直接赋值即可,并修改状态 (新建 -> 已分配)
        Long finalPurchaseId = purchaseId;//拿到采购单Id
        List<PurchaseDetailEntity> collect = mergeVo.getItems().stream().filter(item -> {
            //筛选出状态为新建的采购需求的item
            PurchaseDetailEntity purchaseDetailEntity = purchaseDetailDao.selectById(item);
            return purchaseDetailEntity.getStatus() == WareConstant.PurchaseDetailStatusEnum.CREATE.getCode();
        }).map(item -> {
            PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
            purchaseDetailEntity.setId(item);
            //更新采购单id
            purchaseDetailEntity.setPurchaseId(finalPurchaseId);
            //更新状态为已分配
            purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
            return purchaseDetailEntity;
        }).collect(Collectors.toList());
        purchaseDetailService.updateBatchById(collect);
    }

2.领取采购单

请求参数

[1,2,3,4]//采购单id

(1)筛选出采购单状态为 新建或者已领取的采购单
在这里插入图片描述
(2)修改采购单状态为 已领取
在这里插入图片描述
(3)根据采购单id查出采购需求,修改采购需求的状态为正在采购
在这里插入图片描述

/**
     * 领取采购单
     * [1,2,3,4]//采购单id
     */
    @Transactional
    @Override
    public void received(List<Long> ids) {
        //1.修改采购单
        List<PurchaseEntity> collect = ids.stream().map(id -> {
            PurchaseEntity purchaseEntity = this.getById(id);
            return purchaseEntity;
        }).filter(purchaseEntity -> {
            //筛选出采购单状态为 新建或者已领取的采购单
            if (purchaseEntity.getStatus() == WareConstant.PurchaseStatusEnum.CREATE.getCode()
                    || purchaseEntity.getStatus() == WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()) {
                return true;
            }
            return false;
        }).map(purchaseEntity -> {
            //修改采购单状态为 已领取
            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());
            purchaseEntity.setUpdateTime(new Date());
            return purchaseEntity;
        }).collect(Collectors.toList());
        //修改采购单
        this.updateBatchById(collect);

        /**
         * 需要转换list集合时使用steam流,只需要去list集合中的元素使用增强for即可
         */
        //2.修改采购需求
        collect.forEach(item -> {
            //根据采购单id查出采购需求
            List<PurchaseDetailEntity> list = purchaseDetailService.queryByPurchaseIds(item.getId());
            //修改采购需求的状态为正在采购
            List<PurchaseDetailEntity> detailEntities = list.stream().map(purchaseDetailEntity -> {
                PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();
                detailEntity.setId(purchaseDetailEntity.getId());
                detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());
                return detailEntity;
            }).collect(Collectors.toList());
            //修改采购需求
            purchaseDetailService.updateBatchById(detailEntities);
        });
    }

3.完成采购

请求参数

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

(1)只要采购需求全部都完成,才可以修改采购单的状态为 已完成,否则是 有异常

在这里插入图片描述
在这里插入图片描述
(2)采购需求全部完成则设置采购单状态为已完成
请求参数

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

在这里插入图片描述
在这里插入图片描述

//完成采购
    @Transactional
    @Override
    public void done(PurchaseDoneVo purchaseDoneVo) throws Exception {
        /**
         * {
         *    id: 123,//采购单id
         *    items: [ {itemId:1,status:3,reason:""},{itemId:2,status:4,reason:"无货"} ] // reason:完成/失败的需求详情
         *
         * }
         */
        //只要采购需求全部都完成,才可以修改采购单的状态为 已完成,否则是 有异常
        Long id = purchaseDoneVo.getId();
        Boolean flag = true;
        List<PurchaseItemDoneVo> items = purchaseDoneVo.getItems();
        //遍历 采购需求
        List<PurchaseDetailEntity> detailEntityList = new ArrayList<>();
        for (PurchaseItemDoneVo item : items) {
            PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
            //只要采购需求的状态 != 采购失败 就是 已完成
            if (item.getStatus() == WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()){
                purchaseDetailEntity.setStatus(item.getStatus());
                flag = false;
            }else {
                //此条采购需求完成
                purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode());
                //将成功采购的入库
                PurchaseDetailEntity detailEntity = purchaseDetailService.getById(item.getItemId());
                //传入 商品id、仓库id、商品数量
                wareSkuService.addStock(detailEntity.getSkuId(),detailEntity.getWareId(),detailEntity.getSkuNum());
            }
            purchaseDetailEntity.setId(item.getItemId());
            purchaseDetailEntity.setPurchaseId(id);
            detailEntityList.add(purchaseDetailEntity);
        }
        //批量更新 采购需求
        purchaseDetailService.updateBatchById(detailEntityList);

        PurchaseEntity purchaseEntity = new PurchaseEntity();
        purchaseEntity.setId(id);
        purchaseEntity.setUpdateTime(new Date());
        purchaseEntity.setStatus(flag?WareConstant.PurchaseStatusEnum.FINISH.getCode() : WareConstant.PurchaseStatusEnum.HASERROR.getCode());
        this.updateById(purchaseEntity);


    }

4.商品入库

(1)将采购需求中完成的需求进行入库,入库参数:商品id、仓库id、商品数量,商品名称从gulimall-product服务查出
在这里插入图片描述

 @Override
    public void addStock(Long skuId, Long wareId, Integer skuNum) throws Exception {
        List<WareSkuEntity> wareSkuEntities = wareSkuDao.selectList(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
        if (wareSkuEntities == null || wareSkuEntities.size() == 0) {
            WareSkuEntity wareSkuEntity = new WareSkuEntity();
            wareSkuEntity.setSkuId(skuId);
            wareSkuEntity.setWareId(wareId);
            wareSkuEntity.setStock(skuNum);
            //锁定库存
            wareSkuEntity.setStockLocked(0);
            //远程查询商品名称
            //TODO 1.自己处理异常,查询名称错误不影响整个入库操作
            // 2.向上抛出异常,外层接收异常并回滚
            // 3.还有什么方法出现异常不回滚
            try {
                R r = productFeignService.info(skuId);
                if (r.getCode() == 0){
                    //LinkedHashMap无法转换实体类,类型转换异常
                    /**
                     * 远程传参和接收参数时一定要指定泛型!!!!!
                     *
                     * 因为rpc远程调用在底层还是使用的HTTPClient
                     * 所以在传递参数的时候,必定要有个顺序,当你传递map的时候map里面的值也要有顺序,
                     * 不然服务层在接的时候就出问题了,所以它才会从map转为linkedhashMap
                     * !spring 有一个类叫ModelMap,继承了linkedhashMap public class ModelMap extends LinkedHashMap ,
                     * 所以一个接口返回的结果就可以直接用ModelMap来接,注意ModelMap是没有泛型的,不管你返回的结果是什么类型的map,
                     * 泛型是多复杂的map,都可以直接new一个Modelmap,用它来接返回的结果
                     */
//                    Map<String,Object> map = (Map<String, Object>) r.get("skuInfo");
//                    String skuName = (String) map.get("skuName");
//                    wareSkuEntity.setSkuName(skuName);

                    Object obj = r.get("skuInfo");
                    ObjectMapper objectMapper = new ObjectMapper();
                    SkuInfoEntity skuInfoEntity = objectMapper.convertValue(obj, SkuInfoEntity.class);
                    wareSkuEntity.setSkuName(skuInfoEntity.getSkuName());
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new Exception();
            }
            wareSkuDao.insert(wareSkuEntity);
        } else {
            wareSkuDao.addStock(skuId, wareId, skuNum);
        }
    }

5.遇到问题:

使用feign调用远程服务时,会出现feign返回值LinkedHashMap无法转换实体类异常,因为feign使用的httpClient是用LinkedHashMap封装数据的,所以无法直接强转,可以直接从LinkedHashMap中取值使用,或者使用ObjectMapper转换类型
(1)

ObjectMapper objectMapper = new ObjectMapper();
XxxEntity xxx = objectMapper.convertValue(feign返回的实体类型,需要转换的类型);

(2)
或者使用工具类进行序列化->反序列化操作,与上面操作相似原文链接
这里r会r.get(“data”),实战中根据需求修改

XxxEntity xxx = FeignUtil.formatClass(R r, Class<T> tClass)
import com.google.common.base.Strings;
import com.leicx.guli.common.exception.RRException;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * @author daxiong
 * @date 2021/8/16 下午10:15
 */
public class FeignUtil {
 
    public static <T> T formatClass(R r, Class<T> tClass) {
        String jsonString = getResultJson(r);
        if (Strings.isNullOrEmpty(jsonString)) {
            return null;
        }
        return JsonUtil.parseObject(jsonString, tClass);
    }
 
    private static String getResultJson(R r) {
        if (!r.success()) {
            throw new RRException(r.get("msg").toString());
        }
        return JsonUtil.toJsonString(r.get("data"));
    }
 
    public static <T> List<T> formatListClass(R r, Class<T> tClass) {
        String jsonString = getResultJson(r);
        if (Strings.isNullOrEmpty(jsonString)) {
            return new ArrayList<>();
        }
        return JsonUtil.parseList(jsonString, tClass);
    }
}
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
 
import java.io.IOException;
import java.util.List;
 
/**
 * @author daxiong
 * @date 2021/8/16 下午10:12
 */
@Slf4j
public class JsonUtil {
 
    static final ObjectMapper objectMapper = new ObjectMapper();
 
    public static <T> T parseObject(String jsonStr, Class<T> tClass) {
        try {
            return objectMapper.readValue(jsonStr, tClass);
        } catch (IOException e) {
            log.error(e.getMessage());
            return null;
        }
    }
 
    public static <T> List<T> parseList(String text, Class<T> clazz) {
        JavaType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, clazz);
        try {
            return objectMapper.readValue(text, javaType);
        } catch (IOException e) {
            log.error(e.getMessage());
            return null;
        }
    }
 
    /**
     * json序列化
     *
     * @param obj 需要序列化的对象
     * @return
     */
    public static String toJsonString(Object obj) {
        try {
 
            return objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error(e.getMessage());
            return null;
        }
    }
 
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/25207.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ansible基础五——条件语句、循环语句、handlers、任务失败处理

文章目录 一、 循环语句1.1 单量循环1.2 多量循环1.3 老版本用法1.4 loopregister 二、条件判断2.1 根据变量状态判断2.2 根据变量是否存在判断2.3 根据事实判断2.4 多条件判断2.4.1 and用法2.4.2 or用法 2.5 循环判断2.6 根据上个任务结果判断 三、handlers处理程序四、任务失…

C4d渲染农场的定义、应用领域和未来发展趋势

Cinema 4D&#xff08;C4D&#xff09;是一款常用于3D动画、建模和渲染的软件&#xff0c;由Maxon Computer开发。随着CG行业的不断发展和应用场景的多样化&#xff0c;C4D渲染农场成为了CG制作中不可或缺的一环。本文将深入介绍C4D渲染农场的概念、特点、应用以及未来发展趋势…

MYSQL索引连环18问(上)

MYSQL索引连环18问&#xff08;上&#xff09; 1.索引是什么&#xff1f; 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分)&#xff0c;它们包含着对数据表里所有记录的引用指针。索引是一种数据结构。数据库索引&#xff0c;是数据库管理系统中一个排序的…

使用electron套壳vue实现跨平台桌面应用

electron和vue是什么就不用多说了&#xff0c;前端都知道 先展示一波demo 传送门 前提条件 要有一个vue项目&#xff0c;老项目跳过 vue create hello-world改造vue项目 在根目录新建一个background.js文件&#xff0c;也可以叫其他名字&#xff0c;作为package.json的main…

如何查看mysql里面的锁(详细)

通过查询表统计信息查看 information_schema库下相关事务表和锁相关信息表介绍innodb_trx存储了当前正在执行的事务信息trx_id&#xff1a;事务ID。trx_state&#xff1a;事务状态&#xff0c;有以下几种状态&#xff1a;RUNNING、LOCK WAIT、ROLLING BACK 和 COMMITTING。trx…

shell变量的使用 rhce(25)

目录 1.总结变量的类型及含义&#xff1f; 2.实现课堂案例计算长方形面积&#xff1f;&#xff08;6种方式&#xff09; 3.定义变量urlhttps://blog.csdn.net/weixin_45029822/article/details/103568815&#xff08;通过多种方法实现&#xff09; &#xff08;1&#xff0…

企业级帮助中心编写方案

随着互联网的飞速发展&#xff0c;越来越多的企业开始将客户服务转向线上服务。在这个过程中&#xff0c;企业级帮助中心因其高效的自助服务和低成本的维护方式受到越来越多企业的青睐。下文将从如何编写一个高质量的企业级帮助中心入手&#xff0c;为您介绍具体步骤。 一、明…

Coursera—Andrew Ng机器学习—课程笔记 Lecture 5 Octave Tutorial

5.1 基本操作 参考视频: 5 - 1 - Basic Operations (14 控制输出格式的长短 min).mkv 5.1.1 简单运算 不等于符号的写法是这个波浪线加上等于符号 ( ~ )&#xff0c;而不是等于感叹号加等号( ! ) 1 1 1   % 判断相等 2 1 ~ 2   % 判断不等 3 1 && 0   …

jsp基于 JavaWeb+springboot 的校园快递驿站管理系统

不同的系统提供的服务也不相同&#xff0c;其对应的功能也不相同&#xff0c;所以&#xff0c;系统开工前&#xff0c;需要明确其用途&#xff0c;确定其功能。由此&#xff0c;才可以进行各个任务的开展。 校园驿站管理系统经过分析&#xff0c;确定了其需要设置管理员的角色&…

聚焦2023北京安博会,超高清安防应用将成潮流

&#xff08;1&#xff09;2023北京安博会 中国安全防范产品行业协会主办并承办的第十六届&#xff08;2023&#xff09;中国国际社会公共安全产品博览会&#xff08;Security China 2023&#xff09;&#xff0c;将于2023年6月7&#xff5e;10日在北京首钢会展中心开幕。安博…

前端vscode插件bito

GPT-4和ChatGPT越来越火&#xff0c;前端人员是否也能在日常工作中尝试体验其带来的乐趣呢&#xff1f; 答案是可以的&#xff01;安排&#xff01;&#xff01; 今天介绍一款vscode的插件 【bito】。 安装 安装后只需要自己注册一下&#xff0c;创建一个workspace就可以使用…

实验室信息系统源码,LIS源码

实验室信息系统源码&#xff0c;LIS源码 技术细节&#xff1a; SaaS架构的Client/Server应用 体系结构&#xff1a;Client/Server架构 客户端&#xff1a;WPFWindows Forms 服务端&#xff1a;C# .Net 数据库&#xff1a;Oracle 接口技术&#xff1a;RESTful API HttpW…

全面解析Linux指令和权限管理

目录 一.指令再讲解1.时间相关的指令2.find等搜索指令与grep指令3.打包和压缩相关的指令4.一些其他指令与热键二.Linux权限1.Linux的权限管理2.文件类型与权限设置3.目录的权限与粘滞位 一.指令再讲解 1.时间相关的指令 date指令: date 用法&#xff1a;date [OPTION]… [FOR…

如何在Linux中更改SSH端口?

SSH&#xff08;Secure Shell&#xff09;是一种安全的远程登录协议&#xff0c;它允许您通过网络远程连接到Linux系统并进行管理操作。默认情况下&#xff0c;SSH使用22端口进行通信。然而&#xff0c;为了增强系统的安全性&#xff0c;有时候我们需要更改SSH端口&#xff0c;…

linux 找回root密码(CentOS7.6)

linux 找回root密码(CentOS7.6) 首先&#xff0c;启动系统&#xff0c;进入开机界面&#xff0c;在界面中按“e”进入编辑界面。如图 2. 进入编辑界面&#xff0c;使用键盘上的上下键把光标往下移动&#xff0c;找到以““Linux16”开头内容所在的行数”&#xff0c;在行的最后…

C4D R26 渲染学习笔记 建模篇(2):手动建模

文章目录 前文回顾介绍篇建模篇 手动建模建模快捷键手动模型快捷键大全常用操作N系快捷键K系快捷键U系快捷键 结尾 前文回顾 介绍篇 C4D R26 渲染学习笔记&#xff08;1&#xff09;&#xff1a;C4D版本选择和初始UI框介绍 C4D R26 渲染学习笔记&#xff08;2&#xff09;&am…

Dubbo高可用

1.zookeeper宕机与dubbo直连 1.1.现象&#xff1a;zookeeper注册中心宕机&#xff0c;还可以消费dubbo暴露的服务。 原因&#xff1a; 监控中心宕掉不影响使用&#xff0c;只是丢失部分采样数据数据库宕掉后&#xff0c;注册中心仍能通过缓存提供服务列表查询&#xff0c;但…

软考A计划-试题模拟含答案解析-卷十二

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

AB Test数学原理及金融风控应用

1 什么是AB Test AB测试是一种常用的实验设计方法&#xff0c;用于比较两个或多个不同处理或策略的效果&#xff0c;以确定哪个处理或策略在某个指标上表现更好。在AB测试中&#xff0c;将随机选择一部分用户或样本&#xff0c;将其分为两个或多个组&#xff0c;每个组应用不同…

Java: IO流

1.定义 IO流:存储和读取数据的解决方案 用于读写文件中的数据&#xff08;可以读写文件&#xff0c;或网络中的数据...) 2.IO流的分类 1.按着流的方向 1.输入流&#xff1a;读取 2.输出流&#xff1a;写出 2.按照操作文件类型 1.字节流&#xff1a;所有类型文件 体系&…