前言
本系列博客基于B站谷粒商城,只作为本人学习总结使用。这里我会比较注重业务逻辑的编写和相关配置的流程。有问题可以评论或者联系我互相交流。原视频地址谷粒商城雷丰阳版。本人git仓库地址Draknessssw的谷粒商城
仓库查询
首先得配置好nacos配置中心和路由规则
实现类
查询条件模糊匹配id,名称,地址,区域编码
@Override
public PageUtils queryPage(Map<String, Object> params) {
QueryWrapper<WareInfoEntity> queryWrapper = new QueryWrapper<>();
String key = (String) params.get("key");
if (!StringUtils.isEmpty(key)) {
queryWrapper.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),
queryWrapper
);
仓库信息查询
/**
* 列表
*/
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = wareSkuService.queryPage(params);
return R.ok().put("page", page);
}
实现类
根据仓库信息id和仓库id查询仓库信息。
@Override
public PageUtils queryPage(Map<String, Object> params) {
QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
String skuId = (String) params.get("skuId");
if (!StringUtils.isEmpty(skuId) && !"0".equalsIgnoreCase(skuId)) {
queryWrapper.eq("sku_id",skuId);
}
String wareId = (String) params.get("wareId");
if (!StringUtils.isEmpty(wareId) && !"0".equalsIgnoreCase(wareId)) {
queryWrapper.eq("ware_id",wareId);
}
IPage<WareSkuEntity> page = this.page(
new Query<WareSkuEntity>().getPage(params),
queryWrapper
);
return new PageUtils(page);
}
查询采购单
/**
* 列表
*/
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = purchaseDetailService.queryPage(params);
return R.ok().put("page", page);
}
实现类
模糊匹配采购单id和仓库信息id。再附带查询采购单状态和仓库id。
@Override
public PageUtils queryPage(Map<String, Object> params) {
QueryWrapper<PurchaseDetailEntity> queryWrapper = new QueryWrapper<PurchaseDetailEntity>();
String key = (String) params.get("key");
if (!StringUtils.isEmpty(key)) {
queryWrapper.and(wrapper -> {
wrapper.eq("purchase_id",key).or().eq("sku_id",key);
});
}
String status = (String) params.get("status");
if (!StringUtils.isEmpty(status) && !"0".equalsIgnoreCase(status)) {
queryWrapper.eq("status",status);
}
String wareId = (String) params.get("wareId");
if (!StringUtils.isEmpty(wareId) && !"0".equalsIgnoreCase(wareId)) {
queryWrapper.eq("ware_id",wareId);
}
IPage<PurchaseDetailEntity> page = this.page(
new Query<PurchaseDetailEntity>().getPage(params),
queryWrapper
);
return new PageUtils(page);
}
合并采购单
查询未合并的采购单
///ware/purchase/unreceive/list
@GetMapping(value = "/unreceive/list")
public R unreceiveList(@RequestParam Map<String, Object> params){
PageUtils page = purchaseService.queryPageUnreceive(params);
return R.ok().put("page", page);
}
实现类
匹配采购单的两种状态即可
/**
* 查询未领取的采购单
* @param params
* @return
*/
@Override
public PageUtils queryPageUnreceive(Map<String, Object> params) {
QueryWrapper<PurchaseEntity> queryWrapper = new QueryWrapper<PurchaseEntity>()
.eq("status",0).or().eq("status",1);
IPage<PurchaseEntity> page = this.page(
new Query<PurchaseEntity>().getPage(params),
queryWrapper
);
return new PageUtils(page);
}
合并采购单
新建VO
package com.xxxx.gulimall.ware.vo;
import lombok.Data;
import java.util.List;
@Data
public class MergeVo {
private Long purchaseId;
private List<Long> items;
}
/**
* 合并整单
* @param mergeVo
* @return
*/
///ware/purchase/merge
@PostMapping(value = "/merge")
public R merge(@RequestBody MergeVo mergeVo) {
purchaseService.mergePurchase(mergeVo);
return R.ok();
}
首先获取页面回传Vo中的采购单id,若是没有就新建一个采购单。设置它的采购状态为新建,设置创建时间和更新时间后保存。再获取新建的采购单id
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);
//获取新建采购单的id
purchaseId = purchaseEntity.getId();
}
关于状态的公共枚举类
package com.xxxx.common.constant;
public class WareConstant {
public enum PurchaseStatusEnum {
CREATED(0,"新建"),
ASSIGNED(1,"已分配"),
RECEIVE(2,"已领取"),
FINISH(3,"已完成"),
HASERROR(4,"有异常"),
;
private int code;
private String msg;
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
PurchaseStatusEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
public enum PurchaseDetailStatusEnum {
CREATED(0,"新建"),
ASSIGNED(1,"已分配"),
BUYING(2,"正在采购"),
FINISH(3,"已完成"),
HASERROR(4,"采购失败"),
;
private int code;
private String msg;
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
PurchaseDetailStatusEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
}
获得Vo的采购项id,当采购单详情的状态不是新建和已分配。那就直接抛出自定义异常,不能分配这些采购单
List<Long> items = mergeVo.getItems();
//TODO 确认采购单状态是0,1才可以合并
Collection<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailService.listByIds(items);
purchaseDetailEntities.forEach((item) -> {
if (!item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.CREATED.getCode())
&& !item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode())) {
throw new IllegalArgumentException("正在采购,无法进行分配");
}
});
接入采购单的id,新建采购项,设置它的id和采购单id,以及它的状态为已分配。然后批量修改采购项。
Long finalPurchaseId = purchaseId;
List<PurchaseDetailEntity> collect = items.stream().map(i -> {
PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
purchaseDetailEntity.setId(i);
purchaseDetailEntity.setPurchaseId(finalPurchaseId);
purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
return purchaseDetailEntity;
}).collect(Collectors.toList());
//批量修改
purchaseDetailService.updateBatchById(collect);
接着再根据采购单id修改采购单的更新时间
PurchaseEntity purchaseEntity = new PurchaseEntity();
purchaseEntity.setId(purchaseId);
purchaseEntity.setUpdateTime(new Date());
this.updateById(purchaseEntity);
最终效果如下
@Autowired
private PurchaseDetailService purchaseDetailService;
/**
* 合并采购需求
* @param mergeVo
*/
@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);
//获取新建采购单的id
purchaseId = purchaseEntity.getId();
}
List<Long> items = mergeVo.getItems();
//TODO 确认采购单状态是0,1才可以合并
Collection<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailService.listByIds(items);
purchaseDetailEntities.forEach((item) -> {
if (!item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.CREATED.getCode())
&& !item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode())) {
throw new IllegalArgumentException("正在采购,无法进行分配");
}
});
Long finalPurchaseId = purchaseId;
List<PurchaseDetailEntity> collect = items.stream().map(i -> {
PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
purchaseDetailEntity.setId(i);
purchaseDetailEntity.setPurchaseId(finalPurchaseId);
purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
return purchaseDetailEntity;
}).collect(Collectors.toList());
//批量修改
purchaseDetailService.updateBatchById(collect);
PurchaseEntity purchaseEntity = new PurchaseEntity();
purchaseEntity.setId(purchaseId);
purchaseEntity.setUpdateTime(new Date());
this.updateById(purchaseEntity);
}
领取采购单
/**
* 领取采购单
* @param ids
* @return
*/
@PostMapping(value = "/received")
public R received(@RequestBody List<Long> ids) {
purchaseService.received(ids);
return R.ok();
}
实现类
首先根据需要领取的采购单id获取采购单信息。确认采购单是新建或者已分配状态,然后筛选出这些采购单之后,将采购单状态改成已领取
//1、确认当前采购单是新建或者是已分配状态
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());
批量更新采购单状态
//2、改变采购单的状态
this.updateBatchById(collect);
查出已领取的采购单的id,然后根据这些采购单id设置采购项的采购单id和设置正在采购状态。然后批量保存这些采购单项。
//3、改变采购项的状态
collect.forEach((item) -> {
List<PurchaseDetailEntity> list = purchaseDetailService.listDetailByPurchaseId(item.getId());
List<PurchaseDetailEntity> detailEntities = list.stream().map(entity -> {
PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
purchaseDetailEntity.setId(entity.getId());
purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());
return purchaseDetailEntity;
}).collect(Collectors.toList());
purchaseDetailService.updateBatchById(detailEntities);
});
查询已领取采购单的实现方法
@Override
public List<PurchaseDetailEntity> listDetailByPurchaseId(Long id) {
List<PurchaseDetailEntity> purchaseId = this.list(
new QueryWrapper<PurchaseDetailEntity>().eq("purchase_id", id));
return purchaseId;
}
最终效果如下
@Autowired
private PurchaseDetailService purchaseDetailService;
/**
* 合并采购需求
* @param mergeVo
*/
@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);
//获取新建采购单的id
purchaseId = purchaseEntity.getId();
}
List<Long> items = mergeVo.getItems();
//TODO 确认采购单状态是0,1才可以合并
Collection<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailService.listByIds(items);
purchaseDetailEntities.forEach((item) -> {
if (!item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.CREATED.getCode())
&& !item.getStatus().equals(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode())) {
throw new IllegalArgumentException("正在采购,无法进行分配");
}
});
Long finalPurchaseId = purchaseId;
List<PurchaseDetailEntity> collect = items.stream().map(i -> {
PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
purchaseDetailEntity.setId(i);
purchaseDetailEntity.setPurchaseId(finalPurchaseId);
purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
return purchaseDetailEntity;
}).collect(Collectors.toList());
//批量修改
purchaseDetailService.updateBatchById(collect);
PurchaseEntity purchaseEntity = new PurchaseEntity();
purchaseEntity.setId(purchaseId);
purchaseEntity.setUpdateTime(new Date());
this.updateById(purchaseEntity);
}
完成采购单
采购完成Vo,里面封装了采购项Vo
package com.xxxx.gulimall.ware.vo;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class PurchaseDoneVo {
@NotNull(message = "id不允许为空")
private Long id;
private List<PurchaseItemDoneVo> items;
}
采购项Vo
package com.xxxx.gulimall.ware.vo;
import lombok.Data;
@Data
public class PurchaseItemDoneVo {
private Long itemId;
private Integer status;
private String reason;
}
/**
* 完成采购单
* @param doneVo
* @return
*/
@PostMapping(value = "/done")
public R finish(@RequestBody PurchaseDoneVo doneVo) {
purchaseService.done(doneVo);
return R.ok();
}
实现类
先获取需要完成采购的采购单id
Long id = doneVo.getId();
遍历页面回传的已完成采购项,如果页面回传的Vo中采购项状态为采购失败,设置采购项的状态为失败,采购项状态标记数据置为false。
否则,其他所有的采购项状态在设置已完成时都可以置为已完成。接着查询出当前成功完成的采购项详细信息,调用远程服务入库。
设置完采购项的状态之后,设置id。添加这个采购项数据到采购项list中去。此时可以根据这个采购项list数据批量更新采购项数据
for (PurchaseItemDoneVo item : items) {
PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
if (item.getStatus() == WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()) {
flag = false;
purchaseDetailEntity.setStatus(item.getStatus());
} else {
purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode());
//3、将成功采购的进行入库
//查出当前采购项的详细信息
//PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId());
PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId());
wareSkuService.addStock(entity.getSkuId(),entity.getWareId(),entity.getSkuNum());
}
purchaseDetailEntity.setId(item.getItemId());
updates.add(purchaseDetailEntity);
}
//批量更新
purchaseDetailService.updateBatchById(updates);
接着根据采购单id和采购成功与否的标识boolean值来更新采购单信息。
//2、改变采购单状态
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);
最终效果如下
@Autowired
private PurchaseDetailService purchaseDetailService;
@Autowired
private WareSkuService wareSkuService;
@Transactional
@Override
public void done(PurchaseDoneVo doneVo) {
Long id = doneVo.getId();
//1、改变采购项的状态
Boolean flag = true;
List<PurchaseItemDoneVo> items = doneVo.getItems();
List<PurchaseDetailEntity> updates = new ArrayList<>();
for (PurchaseItemDoneVo item : items) {
PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
if (item.getStatus() == WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()) {
flag = false;
purchaseDetailEntity.setStatus(item.getStatus());
} else {
purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode());
//3、将成功采购的进行入库
//查出当前采购项的详细信息
//PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId());
PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId());
wareSkuService.addStock(entity.getSkuId(),entity.getWareId(),entity.getSkuNum());
}
purchaseDetailEntity.setId(item.getItemId());
updates.add(purchaseDetailEntity);
}
//批量更新
purchaseDetailService.updateBatchById(updates);
//2、改变采购单状态
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);
}
添加库存的远程服务方法如下
判读库存表中是否存在这个库存记录
List<WareSkuEntity> wareSkuEntities = wareSkuDao.selectList(
new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
要是不存在库存记录就新增,存在就修改库存信息
新增库存时,名字需要远程查询库存信息的名字
远程feign方法
package com.xxxx.gulimall.ware.feign;
import com.xxxx.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "gulimall-product")
public interface ProductFeignService {
/**
* /product/skuinfo/info/{skuId}
*
*
* 1)、让所有请求过网关;
* 1、@FeignClient("gulimall-gateway"):给gulimall-gateway所在的机器发请求
* 2、/api/product/skuinfo/info/{skuId}
* 2)、直接让后台指定服务处理
* 1、@FeignClient("gulimall-product")
* 2、/product/skuinfo/info/{skuId}
*
* @return
*/
@RequestMapping("/product/skuinfo/info/{skuId}")
public R info(@PathVariable("skuId") Long skuId);
}
最终效果为
@Autowired
private WareSkuDao wareSkuDao;
@Transactional
@Override
public void addStock(Long skuId, Long wareId, Integer skuNum) {
//1、判读如果没有这个库存记录新增
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.setStock(skuNum);
wareSkuEntity.setWareId(wareId);
wareSkuEntity.setStockLocked(0);
//TODO 远程查询sku的名字,如果失败整个事务无需回滚
//1、自己catch异常
try{
R info = productFeignService.info(skuId);
Map<String,Object> data = (Map<String, Object>) info.get("skuInfo");
if (info.getCode() == 0) {
wareSkuEntity.setSkuName((String) data.get("skuName"));
}
} catch (Exception e) {
}
//添加库存信息
wareSkuDao.insert(wareSkuEntity);
} else {
//修改库存信息
wareSkuDao.addStock(skuId,wareId,skuNum);
}
}
修改库存信息的sql
<update id="addStock">
UPDATE
wms_ware_sku
SET
stock = stock + #{skuNum}
WHERE
sku_id = #{skuId}
AND
ware_id = #{wareId}
</update>