导航:
目录
仓库管理
0、预览
商家先在采购需求界面新增需求,新增时查询了商品、仓库等列表便于选择,然后根据需求新增采购单,采购完毕后将采购单和采购需求的状态字段设为“已完成”对应字典库的代码。
“仓库维护”界面展示仓库的名字、地址,“商品库存”界面展示sku和库存的关系,每个sku所在的每个仓库、以及该仓库下sku数量。
采购单维护-采购需求:
采购单维护-采购单:
仓库维护:
库存工作单:
商品库存:
1、数据表的说明
gulimall_wms数据库
表wms_ware_info
,表示仓库信息
表wms_ware_sku
,绑定仓库id和sku_id的关系
2、整合仓库服务
1、要整合仓库服务,首先把仓库服务注册到nacos中
2、配置网关
- id: ware_route
uri: lb://gulimall-ware
predicates:
- Path=/api/ware/**
filters:
- RewritePath=/api/(?<segment>.*),/$\{segment}
3、配置后测试仓库维护
4、实现仓库模糊查询功能
点击查询,查看url
http://localhost:88/api/ware/wareinfo/list?t=1633696575331&page=1&limit=10&key=
WareInfoController.java
@RequestMapping("/list")
//@RequiresPermissions("ware:wareinfo:list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = wareInfoService.queryPageByCondition(params);
return R.ok().put("page", page);
}
WareInfoServiceImpl.java
@Override
public PageUtils queryPageByCondition(Map<String, Object> params) {
QueryWrapper<WareInfoEntity> wrapper = new QueryWrapper<>();
String key = (String) params.get("key");
if (!StringUtils.isNullOrEmpty(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);
}
设置日志输出级别,方便查看sql语句
logging:
level:
com.xmh: debug
测试成功
3、查询库存的模糊查询
1、库存系统02,url:/ware/waresku/list
2、实现库存模糊查询功能,WareSkuServiceImpl.java
@Override
public PageUtils queryPage(Map<String, Object> params) {
QueryWrapper<WareSkuEntity> wrapper = new QueryWrapper<>();
String wareId = (String) params.get("wareId");
if (!StringUtils.isNullOrEmpty(wareId)){
wrapper.eq("ware_id", wareId);
}
String skuId = (String) params.get("skuId");
if (!StringUtils.isNullOrEmpty(skuId)){
wrapper.eq("sku_id", skuId);
}
IPage<WareSkuEntity> page = this.page(
new Query<WareSkuEntity>().getPage(params),
wrapper
);
return new PageUtils(page);
}
4、采购需求的模糊查询
1、库存系统03,url:/ware/purchasedetail/list
2、PurchaseDetailServiceImpl.java
@Override
public PageUtils queryPage(Map<String, Object> params) {
QueryWrapper<PurchaseDetailEntity> wrapper = new QueryWrapper<>();
String key = (String) params.get("key");
if (!StringUtils.isNullOrEmpty(key)){
wrapper.and(w -> {
w.eq("sku_id", key).or().eq("purchase_id", key);
});
}
String status = (String) params.get("status");
if (!StringUtils.isNullOrEmpty(status)){
wrapper.eq("status", status);
}
String wareId = (String) params.get("wareId");
if (!StringUtils.isNullOrEmpty(wareId)){
wrapper.eq("ware_id", wareId);
}
IPage<PurchaseDetailEntity> page = this.page(
new Query<PurchaseDetailEntity>().getPage(params),
wrapper
);
return new PageUtils(page);
}
5、合并采购流程
1、采购逻辑,新建采购需求后还要可以提供合并采购单,比如一个仓库的东西可以合并到一起,让采购人员一趟采购完
新建采购需求后还要可以提供合并采购单,比如一个仓库的东西可以合并到一起,让采购人员一趟采购完
新建采购单,可以在采购单后面分配给员工,员工可以在系统管理->管理员列表中新建
6、查询未领取的采购单
1、库存系统05、url:/ware/purchase/unreceive/list
, 查询未领取的采购单
2、PurchaseController.java
@RequestMapping("/unreceive/list")
//@RequiresPermissions("ware:purchase:list")
public R unreceiveList(@RequestParam Map<String, Object> params){
PageUtils page = purchaseService.queryPageUnreceive(params);
return R.ok().put("page", page);
}
3、新建常量枚举类constant.WareConstant
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;
}
}
}
4、queryPageUnreceive.java
@Override
public PageUtils queryPageUnreceive(Map<String, Object> params) {
QueryWrapper<PurchaseEntity> wrapper = new QueryWrapper<>();
wrapper.eq("status", WareConstant.PurchaseStatusEnum.CREATED.getCode()).or().eq("status", WareConstant.PurchaseStatusEnum.ASSIGNED.getCode());
IPage<PurchaseEntity> page = this.page(
new Query<PurchaseEntity>().getPage(params),
wrapper
);
return new PageUtils(page);
}
5、测试成功
7、合并采购需求
1、库存系统04,url:/ware/purchase/merge
选择要合并的采购需求,然后合并到整单
如果不选择整单id,则自动创建新的采购单
2、新建MergerVo.java
@Data
public class MergerVo {
private Long purchaseId; //整单id
private List<Long> items; //合并项集合
}
3、分配,就是修改【采购需求】里对应的【采购单id、采购需求状态】,即purchase_detail表
并且不能重复分配采购需求给不同的采购单
,如果还没去采购,或者采购失败,就可以修改
PurchaseController.java
@PostMapping("/merge")
//@RequiresPermissions("ware:purchase:list")
public R merge(@RequestBody MergeVo mergeVo){
purchaseService.mergePurchase(mergeVo);
return R.ok();
}
PurchaseServiceImpl.java
@Autowired
private PurchaseDetailService detailService;
@Transactional
@Override
public void mergePurchase(MergeVo mergeVo) {
Long purchaseId = mergeVo.getPurchaseId();
// 如果采购id为null 说明没选采购单
if (purchaseId == null){
//新建采购单
PurchaseEntity purchaseEntity = new PurchaseEntity();
purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode());
this.save(purchaseEntity);
purchaseId = purchaseEntity.getId();
}
//合并采购需求
List<Long> items = mergeVo.getItems();
Long finalPurchaseId = purchaseId;
List<PurchaseDetailEntity> list = detailService.getBaseMapper().selectBatchIds(items).stream().filter(entity -> {
//如果还没去采购,或者采购失败,就可以修改
return entity.getStatus() < WareConstant.PurchaseDetailStatusEnum.BUYING.getCode()
|| entity.getStatus() == WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode();
}).map(entity -> {
//修改状态,以及采购单id
entity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
entity.setPurchaseId(finalPurchaseId);
return entity;
}).collect(Collectors.toList());
detailService.updateBatchById(list);
}
对采购单的创建时间、更新时间进行自动填充
在PurchaseEntity
中添加注解
/**
* 创建日期
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 更新日期
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
新建MyMetaObjectHandler
对注解进行处理
@Slf4j
@Component // 一定不要忘记把处理器加到IOC容器中!
public class MyMetaObjectHandler implements MetaObjectHandler {
// 插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill.....");
// setFieldValByName(String fieldName, Object fieldVal, MetaObject
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
// 更新时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill.....");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
在配置文件中对时间json进行格式化
jackson:
date-format: yyyy-MM-dd HH:mm:ss
测试成功
8、领取采购单
采购单分配给了采购人员,采购人员在手机端领取采购单,此时的采购单应该为新建
或已分配
状态,在采购人员领取后采购单
的状态变为已领取
,采购需求
的状态变为正在采购
1、库存系统06、url:/ware/purchase/received
2、PurchaseController.java
/**
* 领取采购单/ware/purchase/received
*/
@PostMapping("/received")
//@RequiresPermissions("ware:purchase:list")
public R received(@RequestBody List<Long> ids){
purchaseService.received(ids);
return R.ok();
}
3、PurchaseServiceImpl.java
@Transactional
@Override
public void received(List<Long> ids) {
// 没有采购需求直接返回,否则会破坏采购单
if (ids == null || ids.size() == 0) {
return;
}
List<PurchaseEntity> list = this.getBaseMapper().selectBatchIds(ids).stream().filter(entity -> {
//确保采购单的状态是新建或者已分配
return entity.getStatus() <= WareConstant.PurchaseStatusEnum.ASSIGNED.getCode();
}).map(entity -> {
//修改采购单的状态为已领取
entity.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());
return entity;
}).collect(Collectors.toList());
this.updateBatchById(list);
//修改该采购单下的所有采购需求的状态为正在采购
UpdateWrapper<PurchaseDetailEntity> updateWrapper = new UpdateWrapper<>();
updateWrapper.in("purchase_id", ids);
PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());
detailService.update(purchaseDetailEntity, updateWrapper);
}
4、用idea自带的HTTP Client发送post请求,模拟采购人员领取采购单,进行测试
POST http://localhost:88/api//ware/purchase/received
Content-Type: application/json
[3]
5、测试成功
9、完成采购
完成采购的步骤:
- 判断所有采购需求的状态,采购需求全部完成时,采购单状态才为完成
- 采购项完成的时候,增加库存(调用远程获取skuName)
- 加上分页插件
1、库存系统07,url:/ware/purchase/done
2、新建PurchaseItemDoneVo
,PurchaseDoneVo
@Data
public class PurchaseItemDoneVo {
private Long itemId;
private Integer status;
private String reason;
}
@Data
public class PurchaseDoneVo {
private Long id;
private List<PurchaseItemDoneVo> items;
}
3、PurchaseController.java
/**
* 完成采购
*/
@PostMapping("/done")
//@RequiresPermissions("ware:purchase:list")
public R received(@RequestBody PurchaseDoneVo vo){
purchaseService.done(vo);
return R.ok();
}
4、PurchaseServiceImpl.java
@Autowired
private WareSkuService wareSkuService;
@Autowired
private ProductFeignService productFeignService;
@Override
public void done(PurchaseDoneVo vo) {
//1、根据前端发过来的信息,更新采购需求的状态
List<PurchaseItemDoneVo> items = vo.getItems();
List<PurchaseDetailEntity> updateList = new ArrayList<>();
boolean flag = true;
for (PurchaseItemDoneVo item : items){
Long detailId = item.getItemId();
PurchaseDetailEntity detailEntity = detailService.getById(detailId);
detailEntity.setStatus(item.getStatus());
//采购需求失败
if (item.getStatus() == WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()){
flag = false;
}else {
//3、根据采购需求的状态,更新库存
// sku_id, sku_num, ware_id
// sku_id, ware_id, stock sku_name(调用远程服务获取), stock_locked(先获取已经有的库存,再加上新购买的数量)
String skuName = "";
try {
R info = productFeignService.info(detailEntity.getSkuId());
if(info.getCode() == 0){
Map<String,Object> data=(Map<String,Object>)info.get("skuInfo");
skuName = (String) data.get("skuName");
}
} catch (Exception e) {
}
//更新库存
wareSkuService.addStock(detailEntity.getSkuId(), detailEntity.getWareId(), skuName, detailEntity.getSkuNum());
}
updateList.add(detailEntity);
}
//保存采购需求
detailService.updateBatchById(updateList);
//2、根据采购需求的状态,更新采购单的状态
PurchaseEntity purchaseEntity = new PurchaseEntity();
purchaseEntity.setId(vo.getId());
purchaseEntity.setStatus(flag ? WareConstant.PurchaseStatusEnum.FINISH.getCode() : WareConstant.PurchaseStatusEnum.HASERROR.getCode());
this.updateById(purchaseEntity);
}
5、新建feign.ProductFeignService
接口,用来远程获取skuName
ProductFeignService.java
@FeignClient("gulimall-product")
public interface ProductFeignService {
@RequestMapping("/product/skuinfo/info/{skuId}")
R info(@PathVariable("skuId") Long skuId);
}
6、主启动类加上注解@EnableFeignClients
7、WareSkuServiceImpl.java
实现入库操作
@Override
public void addStock(Long skuId, Long wareId, String skuName, Integer skuNum) {
WareSkuEntity wareSkuEntity = this.baseMapper.selectOne(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
if (wareSkuEntity == null){
//新增
wareSkuEntity = new WareSkuEntity();
wareSkuEntity.setStock(skuNum);
}else {
wareSkuEntity.setStock(wareSkuEntity.getStock() + skuNum);
}
wareSkuEntity.setSkuName(skuName);
wareSkuEntity.setWareId(wareId);
wareSkuEntity.setSkuId(skuId);
this.saveOrUpdate(wareSkuEntity);
}
8、添加分页插件,复制product服务中的即可
9、测试
POST http://localhost:88/api/ware/purchase/done
Content-Type: application/json
{
"id": 7,
"items": [
{"itemId":6,"status":3,"reason":"完成"},
{"itemId":7,"status":3,"reason":"完成"}
]
}
测试成功
10、获取spu规格
1、商品系统22、url:/product/attr/base/listforspu/{spuId}
2、AttrController.java
@Autowired
private ProductAttrValueService productAttrValueService;
@GetMapping("/base/listforspu/{spuId}")
public R baseListforspu(@PathVariable("spuId") Long spuId){
List<ProductAttrValueEntity> entityList = productAttrValueService.baseAttrlistForSpu(spuId);
return R.ok().put("data", entityList);
}
3、ProductAttrValueServiceImpl.java
@Override
public List<ProductAttrValueEntity> baseAttrlistForSpu(Long spuId) {
List<ProductAttrValueEntity> entities = this.baseMapper.selectList(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
return entities;
}
测试,点击规格
如果此时出现400页面,向gulimall_admin中的sys_menu表中添加一条数据即可
11、修改商品规格
1、商品系统23,url:/product/attr/update/{spuId}
2、AttrController.java
@PostMapping("/update/{spuId}")
public R updateSpuAttr(@PathVariable("spuId") Long spuId, @RequestBody List<ProductAttrValueEntity> entities){
productAttrValueService.updateSpuAttr(spuId, entities);
return R.ok();
}
3、ProductAttrValueServiceImpl.java
因为修改的时候,有新增有修改有删除。 所以就先把spuId对应的所有属性都删了,再新增
@Override
public void updateSpuAttr(Long spuId, List<ProductAttrValueEntity> entities) {
//1、删除这个spuId对应的所有属性
this.baseMapper.delete(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
//2、新增回去
for (ProductAttrValueEntity entity : entities){
entity.setSpuId(spuId);
}
this.saveBatch(entities);
}