仓储服务
一、仓储服务-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:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
- id: ware_route
uri: lb://gulimall-ware
predicates:
- Path=/api/ware/**
filters:
- 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)合并采购需求
比如一个仓库的东西可以合并到一起,让采购人员一趟采购完
- 查询未领取的采购单:
/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);
}
- 采购单
wms_purchase 采购单,里面有创建时间和分类人员等信息wms_purchase_detail 采购单详情表,指明采购单每项要采购的sku,可以自己新增采购单,然后让新的采购需求合并到已有采购单里。
采购单状态:只有新建、已分配的时候才能合并采购单
新建 0 已分配 1 已领取(正在采购) 2 已完成 3 有异常(采购失败) 4
- 合并采购需求:
/ware/purchase/merge
请求数据: { purchaseId: 1, # 采购单id,没有携带就新建采购单 items: [1, 2] # 采购商品 }
注:如果不选择整单直接点击确定,将弹出提示。
流程:
- 如果没有带过来采购单id,先新建采购单
- 然后修改【采购需求】里对应的【采购单id、采购需求状态】,即
purchase_detail 表 - 采购需求是
purchase_detail 表、采购单是purchase 表。采购单由多个采购需求组成 - 采购单页面分配采购需求成功后应该刷新页面,或者说不能重复分配采购需求给不同的采购单(或者说是一个更新操作)
PurchaseServiceImpl
@Transactional
@Override
public void mergePurchase(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();
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
@Override
public void received(List<Long> ids) {
List<PurchaseEntity> collect = ids.stream().map(id -> {
PurchaseEntity byId = this.getById(id);
return byId;
}).filter(item -> {
if (item.getStatus() == WareConstant.PurchaseStatusEnum.CREATED.getCode() || item.getStatus() == WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()) {
return true;
}
return false;
}).map(item -> {
item.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());
item.setUpdateTime(new Date());
return item;
}).collect(Collectors.toList());
this.updateBatchById(collect);
collect.forEach((item) -> {
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());
detailService.updateBatchById(detailEntities);
});
}
(4)完成采购,添加到库存
可以多选采购单里哪些采购项(需求)完成了
API信息:同样相关页面也省略,通过POSTMAN发送,代表采购员采购回来了,提交信息
@Transactional
@Override
public void done(PurchaseDoneVo doneVo) {
Long id = doneVo.getId();
Boolean flag = true;
List<PurchaseItemDoneVo> items = doneVo.getItems();
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());
PurchaseDetailEntity entity = detailService.getById(item.getItemId());
wareSkuService.addStock(entity.getSkuId(), entity.getWareId(), entity.getSkuNum());
}
detailEntity.setId(item.getItemId());
updates.add(detailEntity);
}
detailService.updateBatchById(updates);
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) {
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);
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);
}
}
|