第13天-仓储服务(仓库管理,采购管理 ,SPU规格维护)

文章详细介绍了Gmall仓储服务的配置,包括加入Nacos注册中心、配置网关路由、启用MyBatisPlus分页插件以及主启动类的功能。同时,阐述了采购流程,如采购需求的创建、查询、合并及采购单的管理,包括新建、分配、领取、完成等环节。此外,还涉及了商品库存管理和SPU规格维护的相关API及实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.仓储服务开发配置



1.1.加入到Nacos注册中心

spring:
  application:
    name: gmall-ware
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.139.10:8848
        namespace: 36854647-e68c-409b-9233-708a2d41702c


1.2.配置网关路由

spring:
  cloud:
    gateway:
      routes:
      - id: ware_route
        uri: lb://gmall-ware
        predicates:
        - Path=/api/ware/**
        filters:
        - RewritePath=/api/(?<segment>.*), /$\{segment}


1.3.主启动类开启相关功能

package com.atguigu.gmall.ware;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class GmallWareApplication {

    public static void main(String[] args) {
        SpringApplication.run(GmallWareApplication.class, args);
    }

}


1.4.MyBatisPlus分页插件配置

package com.atguigu.gmall.ware.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * MyBatisPlus 配置类 {@link MybatisPlusConfig}
 * @author zhangwen
 * @email: 1466787185@qq.com
 */
@Configuration
//开启事务
@EnableTransactionManagement
@MapperScan("com.atguigu.gmall.ware.dao")
public class MybatisPlusConfig {
    /**
     * 引入分页插件
     * @return 分页插件拦截器实例
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求,默认false
        paginationInterceptor.setOverflow(true);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInterceptor.setLimit(100);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
}


2.仓库维护CRUD

  • 逆向工程已经实现了CRUD,只需要对查询进行修改
  • 添加仓库信息

在这里插入图片描述



3.采购单维护



3.1.采购流程

  1. 创建采购需求
  2. 创建采购单
  3. 为采购单分配采购人员
  4. 领取采购单
  5. 完成采购单
  6. 商品入库

采购流程图如下:
在这里插入图片描述



3.2.采购需求

采购需求生成方式:

  • 人工创建采购需求(人工)
  • 库存预警自动创建采购需求(自动化)

3.2.1.采购需求-人工新增


3.2.2.采购需求-查询

在这里插入图片描述

GET /ware/purchasedetail/list

//请求参数
{
	page: 1, // 当前页码
	limit: 10, // 每页记录数
	sidx: 'id', // 排序字段
	order: 'asc/desc', // 排序方式
	key: '华为', // 检索关键字
	status: 0, // 状态
	wareId: 1, // 仓库id
}

//响应数据
{
	"msg": "success",
	"code": 0,
	"page": {
		"totalCount": 0,
		"pageSize": 10,
		"totalPage": 0,
		"currPage": 1,
		"list": [{
			"id": 2,
			"purchaseId": 1,
			"skuId": 1,
			"skuNum": 2,
			"skuPrice": 22.0000,
			"wareId": 1,
			"status": 1
		}]
	}
}

PurchaseDetailController

/**
 * 采购需求列表
 */
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
    PageUtils page = purchaseDetailService.queryPage(params);

    return R.ok().put("page", page);
}

PurchaseDetailServiceImpl

/**
 * 采购需求列表查询
 * @param params
 * @return
 */
@Override
public PageUtils queryPage(Map<String, Object> params) {
    QueryWrapper<PurchaseDetailEntity> queryWrapper = new QueryWrapper<>();

    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)) {
        queryWrapper.eq("status", status);
    }

    String wareId = (String) params.get("wareId");
    if (!StringUtils.isEmpty(wareId)) {
        queryWrapper.eq("ware_id", wareId);
    }

    IPage<PurchaseDetailEntity> page = this.page(
            new Query<PurchaseDetailEntity>().getPage(params),
            queryWrapper
    );

    return new PageUtils(page);
}

3.2.3.合并采购单

在这里插入图片描述
合并采购单有两种方式

  • 选择一个采购单
  • 若没有选择一个采购单,系统自动创建一个新的采购单进行合并

3.2.4.查询未领取的采购单

采购单状态:

  • CREATED(0, “新建”)
  • ASSIGNED(1, “已分配”)
  • RECEIVED(2, “已领取”)
  • FINISHED(3, “已完成”)
  • ERROR(4, “有异常”)

未领取的采购单:新建和已分配

GET /ware/purchase/unreceive/list

PurchaseController

/**
 * 查询未领取的采购单
 */
 @RequestMapping("/unreceive/list")
 public R listUnReceive(@RequestParam Map<String, Object> params){
     PageUtils page = purchaseService.queryPageUnReceivePurchase(params);
     return R.ok().put("page", page);
 }

PurchaseServiceImpl

 /**
  * 查询未领取的采购单
  * @param params
  * @return
  */
 @Override
 public PageUtils queryPageUnReceivePurchase(Map<String, Object> params) {
     IPage<PurchaseEntity> page = this.page(
             new Query<PurchaseEntity>().getPage(params),
             new QueryWrapper<PurchaseEntity>()
                     .eq("status",
                             WareConstant.PurchaseStatusEnum.CREATED.getCode()).or()
                     .eq("status",
                             WareConstant.PurchaseStatusEnum.ASSIGNED.getCode())
     );
     return new PageUtils(page);
 }

3.2.5.合并采购需求

在这里插入图片描述

POST /ware/purchase/merge

//请求参数
{
	purchaseId: 1, // 整单id
	items: [1,2,3] // 合并项集合
}

PurchaseController

/**
 * 合并采购需求-采购单
 * @return
 */
 @PostMapping("/merge")
 public R merge(@RequestBody MergeVO mergeVO) {
     purchaseService.mergePurchase(mergeVO);
     return R.ok();
 }

purchaseServiceImpl

/**
 * 合并采购需求-采购单
 * @param mergeVO
 */
@Transactional(rollbackFor = Exception.class)
@Override
public void mergePurchase(MergeVO mergeVO) {
    Long purchaseId = mergeVO.getPurchaseId();
    if (StringUtils.isEmpty(purchaseId)) {
        // 新增
        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> detailEntities = items.stream().map(item -> {
        PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
        purchaseDetailEntity.setId(item);
        purchaseDetailEntity.setPurchaseId(finalPurchaseId);
        purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailEnum.ASSIGNED.getCode());
        return purchaseDetailEntity;
    }).collect(Collectors.toList());
    detailService.updateBatchById(detailEntities);

    // 采购单更新时间
    PurchaseEntity purchaseEntity = new PurchaseEntity();
    purchaseEntity.setId(purchaseId);
    purchaseEntity.setUpdateTime(new Date());
    this.updateById(purchaseEntity);
}

4.采购单

菜单路径:库存系统 -> 采购单维护 -> 采购单



4.1.新建采购单-人工新增



4.2.查询采购单



4.3.分配采购人员

为采购单分配采购人员,采购人员从系统用户表中查询

在这里插入图片描述



4.4.领取采购单


4.4.1.API

POST /ware/purchase/received

//请求参数
[1,2,3,4] //采购单id

4.4.2.后台接口实现

PurchaseController

/**
 * 领取采购单
 * @param ids 采购单id集合
 * @return
 */
 @PostMapping("/received")
 public R receive(@RequestBody List<Long> ids) {
     purchaseService.receivePurchase(ids);
     return R.ok();
 }

PurchaseServiceImpl

/**
 * 领取采购单
 * @param ids 采购单id集合
 */
@Transactional(rollbackFor = Exception.class)
@Override
public void receivePurchase(List<Long> ids) {
    // 1.确认当前采购单是新建或已分配状态
    List<PurchaseEntity> purchaseEntities = ids.stream().map(id -> {
        PurchaseEntity purchaseEntity = this.getById(id);
        return purchaseEntity;
    }).filter(purchaseEntity -> {
        if (purchaseEntity.getStatus() ==
        WareConstant.PurchaseStatusEnum.CREATED.getCode() ||
                purchaseEntity.getStatus() ==
        WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()) {
            return true;
        }
        return false;
    }).map(purchaseEntity -> {
        // 设置采购单的状态为已领取
        purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.RECEIVED.getCode());
        purchaseEntity.setUpdateTime(new Date());
        return purchaseEntity;
    }).collect(Collectors.toList());
    
    // 2.批量修改采购单的状态
    this.updateBatchById(purchaseEntities);
    
    // 3.修改采购项的状态
    purchaseEntities.forEach(purchaseEntity -> {
        // 根据采购单id获取采购项
        List<PurchaseDetailEntity> detailEntities =
                detailService.listDetailByPurchaseId(purchaseEntity.getId());
        List<PurchaseDetailEntity> collect =
                detailEntities.stream().map(detailEntity ->{
            PurchaseDetailEntity entity = new PurchaseDetailEntity();
            entity.setId(detailEntity.getId());
            entity.setStatus(WareConstant.PurchaseDetailEnum.BUYING.getCode());
            return entity;
        }).collect(Collectors.toList());
        // 批量修改采购项状态
        detailService.updateBatchById(collect);
    });
}

4.4.3.Postman模拟领取采购单

使用Postman发送领取采购单请求

POST /ware/purchase/received

//请求参数
[1,2,3,4] //采购单id

领取成功后,采购单状态更新为 已领取

在这里插入图片描述

采购需求状态更新为 正在采购

在这里插入图片描述



4.5.完成采购单


4.5.1.API

POST /ware/purchase/done

// 请求参数
{
	"id":1, // 采购单id
	// itemId 采购项id,status 采购状态,reason 采购情况说明
	"items":[
		{"itemId":1,"status":3,"reason":"完成"},
		{"itemId":2,"status":3,"reason":"完成"},
		{"itemId":3,"status":3,"reason":"完成"}
	]
}

4.5.2.后台接口实现

PurchaseController

 /**
  * 完成采购单
  * @param purchaseDoneVO
  * @return
  */
  @PostMapping("/done")
  public R finished(@RequestBody PurchaseDoneVO purchaseDoneVO) {
      purchaseService.done(purchaseDoneVO);
      return R.ok();
  }

PurchaseServiceImpl

/**
 * 完成采购单
 * @param purchaseDoneVO
 */
@Transactional(rollbackFor = Exception.class)
@Override
public void done(PurchaseDoneVO purchaseDoneVO) {
    // 1.修改采购项状态
    List<PurchaseDetailEntity> updateList = new ArrayList<>();
    boolean flag = true;
    for (PurchaseItemDoneVO itemDoneVO : purchaseDoneVO.getItems()) {
        PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
        if (itemDoneVO.getStatus() ==
        WareConstant.PurchaseDetailEnum.FAILED.getCode()) {
            flag = false;
            purchaseDetailEntity.setStatus(itemDoneVO.getStatus());
        } else {
            purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailEnum.FINISHED.getCode());

            // 2.将成功采购的商品入库
            PurchaseDetailEntity detailEntity =
                    detailService.getById(itemDoneVO.getItemId());
            wareSkuService.addStock(detailEntity.getSkuId(),
                    detailEntity.getWareId(), detailEntity.getSkuNum());
        }
        purchaseDetailEntity.setId(itemDoneVO.getItemId());
        updateList.add(purchaseDetailEntity);
    }
    detailService.updateBatchById(updateList);
    
    // 3.修改采购单状态
    PurchaseEntity purchaseEntity = new PurchaseEntity();
    purchaseEntity.setId(purchaseDoneVO.getId());
    purchaseEntity.setStatus(flag ?
            WareConstant.PurchaseStatusEnum.FINISHED.getCode()
            : WareConstant.PurchaseStatusEnum.ERROR.getCode());
    purchaseEntity.setUpdateTime(new Date());
    this.updateById(purchaseEntity);
}

4.5.3.Postman模拟完成采购单

使用Postman发送完成采购单请求

POST /ware/purchase/done

// 请求参数
{
	"id":1, // 采购单id
	"items": [
		// itemId 采购项id,status 采购状态, reason 采购说明
		{"itemId":1,"status":3,"reason":"完成"},
		{"itemId":2,"status":3,"reason":"完成"}
	]
}

完成采购单后

采购单状态更新为 已完成

在这里插入图片描述

采购商品状态更新为 已完成

在这里插入图片描述

商品库存更新

在这里插入图片描述



5.商品库存



5.1.入库方式

  • 手动新增库存(不能直接新增,只能作为补偿手段)

  • 采购入库(常规)

    1、发起商品采购需求
    2、创建采购单
    3、采购人员领取采购单,进行商品采购(对接采购系统)
    4、完成采购
    5、商品入库



5.2.库存查询


5.2.1.API

GET /ware/waresku/list

// 请求参数
{
	page: 1, // 当前页码
	limit: 10, // 每页记录数
	sidx: 'id', // 排序字段
	order: 'asc/desc', // 排序方式
	wareId: 123, // 仓库id
	skuId: 123 // 商品id
}

//响应数据
{
	"msg": "success",
	"code": 0,
	"page": {
		"totalCount": 0,
		"pageSize": 10,
		"totalPage": 0,
		"currPage": 1,
		"list": [{
			"id": 1,
			"skuId": 1,
			"wareId": 1,
			"stock": 1,
			"skuName": "dd",
			"stockLocked": 1
		}]
	}
}

5.2.2.后台接口实现

WareSkuController

/**
 * 商品库存查询
 */
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
    PageUtils page = wareSkuService.queryPage(params);

    return R.ok().put("page", page);
}

WareSkuServiceImpl

/**
 * 查询商品库存
 * @param params
 * @return
 */
@Override
public PageUtils queryPage(Map<String, Object> params) {
    QueryWrapper<WareSkuEntity> queryWrapper = new QueryWrapper<>();
    
    String skuId = (String) params.get("skuId");
    if (!StringUtils.isEmpty(skuId)) {
        queryWrapper.eq("sku_id", skuId);
    }

    String wareId = (String) params.get("wareId");
    if (!StringUtils.isEmpty(skuId)) {
        queryWrapper.eq("ware_id", wareId);
    }

    IPage<WareSkuEntity> page = this.page(
            new Query<WareSkuEntity>().getPage(params),
            queryWrapper
    );

    return new PageUtils(page);
}


6.SPU规格维护



6.1.获取SPU规格

在这里插入图片描述

6.1.1.API

GET /product/attr/base/listforspu/{spuId}

//响应数据
{
	"msg": "success",
	"code": 0,
	"data": [{
		"id": 43,
		"spuId": 11,
		"attrId": 7,
		"attrName": "入网型号",
		"attrValue": "LIO-AL00",
		"attrSort": null,
		"quickShow": 1
	}]
}

6.1.2.后台接口实现

AttrController

/**
 * 获取SPU规格属性
 * @param spuId
 * @return
 */
 @GetMapping("/base/listforspu/{spuId}")
 public R listBaseAttrForSpu(@PathVariable("spuId") Long spuId) {
     List<ProductAttrValueEntity> entities = productAttrValueService.listBaseAttrForSpu(spuId);
     return R.ok().put("data", entities);
 }

ProductAttrValueServiceImpl

/**
 * 获取SPU规格属性
 * @param spuId
 * @return
 */
@Override
public List<ProductAttrValueEntity> listBaseAttrForSpu(Long spuId) {
    List<ProductAttrValueEntity> attrValueEntities = this.list(
            new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
    return attrValueEntities;
}


6.2.修改SPU规格


6.2.1.API

POST /product/attr/update/{spuId}

// 请求参数
[{
	"attrId": 7,
	"attrName": "入网型号",
	"attrValue": "LIO-AL00",
	"quickShow": 1
}, {
	"attrId": 14,
	"attrName": "机身材质工艺",
	"attrValue": "玻璃",
	"quickShow": 0
}, {
	"attrId": 16,
	"attrName": "CPU型号",
	"attrValue": "HUAWEI Kirin 980",
	"quickShow": 1
}]

6.2.2.后台接口实现

AttrController

/**
 * 修改SPU规格属性
 * @param spuId
 * @param entities
 * @return
 */
 @PostMapping("/update/{spuId}")
 public R updateSpuAttr(@PathVariable("spuId") Long spuId, @RequestBody List<ProductAttrValueEntity> entities){
     productAttrValueService.updateSpuAttr(spuId, entities);
     return R.ok();
 }

ProductAttrValueServiceImpl

/**
 * 修改SPU规格属性
 * @param spuId
 * @param entities
 */
@Transactional(rollbackFor = Exception.class)
@Override
public void updateSpuAttr(Long spuId, List<ProductAttrValueEntity> entities) {
    // 删除spu之前对应的所有规格属性
    this.remove(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id",spuId));

    //插入spu新的规格属性
    List<ProductAttrValueEntity> ProductAttrValueEntities = entities.stream().map(entity -> {
        entity.setSpuId(spuId);
        return entity;
    }).collect(Collectors.toList());
    this.saveBatch(ProductAttrValueEntities);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值