首先我们需要把库存服务注册到注册中心中。
然后在nacos中发现注册的服务
客户端首先访问的都是网关服务,所以需要配置对应的路由规则
就可以完成对仓库列表的处理了
然后实现仓库列表的关键字查询
添加对应的检索条件
效果展示
完整的采购流程
合并采购需求时我们需要把这些采购需求合并到一个采购单中,所以首先需要创建采购单
然后在整合时我们需要查询出状态为 新建 或者 已分配 的采购单
对应的需要创建接口
然后就可以实现整合处理了。
接收传递的信息创建对应的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;
}
}
}
添加对应的接口
然后在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;
}
采购单合单完成后,采购人员需要对应的领取采购单来执行后续的流程
先创建对应的领取采购单的接口
/**
* 领取采购单
* [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发送请求测试
数据状态更新
搞定
创建对应的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;
}
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注解
不要忘了添加对应的依赖
首先是Controller接口的创建
然后对应的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>
最后通过PostMan来测试完成操作
{
"id":3,
"items":[
{"itemId":4,"status":3,"reason":""}
,{"itemId":5,"status":3,"reason":""}
]
}
商品库存
采购单
采购项
微服务(SpringCloudAlibaba)
注册中心,配置中心,远程调用,网关,负载均衡,链路追踪…
SpringBoot2.4.12 SpringCloud MyBatis-Plus MySQL Vue ElementUI 人人fast,阿里云对象存储
Docker Linux Vagrant MySQL Redis 人人开源
数据校验JSR303 全局跨域 R全局统一返回,全局异常处理 枚举状态 业务状态,VO、DTO、PO划分,逻辑删除,Lombok