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