谷粒商城基础篇------仓储服务(gulimall-ware) - 仓库管理


仓储服务对应于gulimall-ware服务,首先需要将该服务注册进nacos注册中心

① 配置nacos的注册中心地址:(application.yml),增加一些配置

server:
  port: 11000
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.146.129:3306/gulimall_wms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
  application:
    name: gulimall-ware
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml
  global-config:
    db-config:
      id-type: auto
      logic-delete-value: 1
      logic-not-delete-value: 0
logging:
  level:
    com.atguigu: debug

②配置bootstrap.properties文件

spring.application.name=gulimall-ware
spring.cloud.nacos.config.server-addr=localhost:8848
spring.cloud.nacos.config.namespace=e64cac44-a064-4d89-9608-3f98dbab2232
spring.cloud.nacos.config.extension-configs[0].data-id=gulimall-ware.yml
spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[0].refresh=true

③gulimall-ware主启动类:开启服务注册与发现,事务

package com.atguigu.gulimall.ware;
@EnableTransactionManagement
@MapperScan("com.atguigu.gulimall.ware.dao")
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallWareApplication {
    public static void main(String[] args) {
        SpringApplication.run(GulimallWareApplication.class, args);
    }
}

④gulimall-gateway中配置路由网关

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

10.1查询 仓库维护 列表(模糊查询)wms_ware_info

前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/mZgdqOWe

需要根据条件进行模糊检索:

①gulimall-ware : WareInfoController

@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
    PageUtils page = wareInfoService.queryPage(params);
    return R.ok().put("page", page);
}

②gulimall-ware : WareInfoServiceImpl

@Override
public PageUtils queryPage(Map<String, Object> params) {
    QueryWrapper<WareInfoEntity> queryWrapper = new QueryWrapper<>();
    String key = (String) params.get("key");
    if(!StringUtils.isEmpty(key)){
        queryWrapper.and((wrapper)->{
            wrapper.eq("id",key)//前端界面只有一个白框,关键字key (参数名)
                    .or().like("name",key)
                    .or().like("address",key)
                    .or().like("areacode",key);
        });
    }
    IPage<WareInfoEntity> page = this.page(
            new Query<WareInfoEntity>().getPage(params),queryWrapper);
    return new PageUtils(page);
}

③测试:模糊查询
在这里插入图片描述

10.2 查询 商品库存 列表 wms_ware_sku

前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/hwXrEXBZ

①gulimall-ware : WareSkuController

@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params){
    PageUtils page = wareSkuService.queryPage(params);

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

②gulimall-ware : WareSkuServiceImpl

@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);//前端界面有sku_id选项,不再是关键字key (参数名)
    }
    String wareId = (String) params.get("wareId");//前端界面有ware_id选项,
    if(!StringUtils.isEmpty(wareId)){
        queryWrapper.eq("ware_id",wareId);
    }
    IPage<WareSkuEntity> page = this.page(
            new Query<WareSkuEntity>().getPage(params),queryWrapper);

    return new PageUtils(page);
}

③测试查询
在这里插入图片描述

10.3 查询新增 采购需求 wms_purchase_detail

前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/Ss4zsV7R

①gulimall-ware : PurchaseDetailController

@RequestMapping("/list")
    //@RequiresPermissions("ware:purchasedetail:list")
    public R list(@RequestParam Map<String, Object> params){
        PageUtils page = purchaseDetailService.queryPage(params);

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

②gulimall-ware : PurchaseDetailServiceImpl

@Override
public PageUtils queryPage(Map<String, Object> params) {
    //   key: '华为',//检索关键字
    //   status: 0,//状态
    //   wareId: 1,//仓库id
    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);
}

③测试
在这里插入图片描述

10.4 采购单维护栏

主要就是两个栏目 采购单和采购需求
在这里插入图片描述

1、查询采购单(自己添加)

连接:ware/purchase/list

①gulimall-ware : PurchaseController

@RequestMapping("/list")
    //@RequiresPermissions("ware:purchase:list")
    public R list(@RequestParam Map<String, Object> params){
        PageUtils page = purchaseService.queryPage(params);

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

②gulimall-ware : PurchaseServiceImpl

@Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<PurchaseEntity> queryWrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            queryWrapper.and((wrapper)->{
                wrapper.eq("id",key).or().like("assignee_name",key);
            });
        }
        String status = (String) params.get("status");
        if(!StringUtils.isEmpty(status)){
            queryWrapper.eq("status", status);
        }

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

        return new PageUtils(page);
    }

③前端添加状态status,在purchase.vue中添加**status: this.dataForm.status,**因为原先没有这个语句,所以后端写了判断status的语句查询也不行,所以加上前端这句,params就会携带数据到后端处理,当再次返回页面就能模糊查询status相关的。

// 获取数据列表
params: this.$http.adornParams({
          page: this.pageIndex,
          limit: this.pageSize,
          status: this.dataForm.status,
          key: this.dataForm.key
        })

④测试
在这里插入图片描述

2、查询未领取的 采购单(分配采购单)wms_purchase

:https://easydoc.xyz/s/78237135/ZUqEdvA4/hI12DNrH

①gulimall-ware : PurchaseController

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

②gulimall-ware : PurchaseServiceImpl

@Override
public PageUtils queryPageUnreceivedPurchase(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);
}

③采购单(新增和分配)测试

首选新增采购单,接着添加一个管理员,其次点击分配采购人员
在这里插入图片描述
在这里插入图片描述

3、合并 采购需求 到采购单

:https://easydoc.xyz/s/78237135/ZUqEdvA4/cUlv9QvK

将下面的两个采购需求合并为一个采购单:

在这里插入图片描述
①gulimall-ware : PurchaseController

@PostMapping("/merge")
public R merge(@RequestBody MergeVo mergeVo){
    purchaseService.mergePurchase(mergeVo);
    return R.ok();
}

②gulimall-ware : 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);
        //得到采购单id
        purchaseId = purchaseEntity.getId();
    }else{//如果选择采购单,则执行下面步骤
        List<Long> items = mergeVo.getItems();
        Long finalPurchaseId = purchaseId;
        List<PurchaseDetailEntity> collect = items.stream().map((item) -> {
            //新建采购需求实体类
            PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
            purchaseDetailEntity.setId(item);
            purchaseDetailEntity.setPurchaseId(finalPurchaseId);
            purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
            return purchaseDetailEntity;
        }).collect(Collectors.toList());
        purchaseDetailService.updateBatchById(collect);

        //在合并完采购单后,希望新的采购单时间显示是正确的
        PurchaseEntity purchaseEntity = new PurchaseEntity();
        purchaseEntity.setCreateTime(new Date());
        purchaseEntity.setUpdateTime(new Date());
        purchaseEntity.setId(purchaseId);
        this.updateById(purchaseEntity);
    }
}

③测试结果:
在这里插入图片描述
在这里插入图片描述

10.5 领取采购单

  • 当领取采购单之后,采购需求的采购状态应该变为正在采购
    在这里插入图片描述
  • 采购员领取采购单之后,采购单状态应该变为已领取,并且采购单不能再分配其他人采购:

领取采购单前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/vXMBBgw1

①gulimall-ware : PurchaseController

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

②gulimall-ware : PurchaseServiceImpl

/**
     *领取采购单
     * @param ids 采购单id
     * */
    @Override
    public void received(List<Long> ids) {
        //1、确认当前采购单是新建或者已分配状态
        List<PurchaseEntity> collect = ids.stream().map(id -> {
            PurchaseEntity byId = this.getById(id);
            return byId;
        }).filter(item -> {//过滤:当采购单的状态是新建和已分配时,就返回true
            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);

        //3、改变采购项(采购需求)的状态
        collect.forEach((item)->{
            //entities:采购需求的集合
            List<PurchaseDetailEntity> entities = purchaseDetailService.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());
            //更新采购需求
            purchaseDetailService.updateBatchById(detailEntities);
        });
    }

上面调用的方法PurchaseDetailServiceImpl中

@Override
public List<PurchaseDetailEntity> listDetailByPurchaseId(Long id) {
    List<PurchaseDetailEntity> purchaseId
            = this.list(new QueryWrapper<PurchaseDetailEntity>().eq("purchase_id", id));
    return purchaseId;
}

③测试:模仿采购人员的第三方APP
在这里插入图片描述
采购需求--------正在采购
在这里插入图片描述
采购单-------已领取
在这里插入图片描述
此时思考一个问题:当采购单的状态不再是新建和已分配时,还能再合并 采购需求到采购单吗

修改原先的mergePurchase方法,进行状态判断

//TODO 确认采购单状态是0,1才可以合并
        PurchaseEntity purchaseEntity1 = purchaseDao.selectById(purchaseId);
        if (purchaseEntity1.getStatus()==WareConstant.PurchaseStatusEnum.CREATED.getCode()||
            purchaseEntity1.getStatus()==WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()) {
            List<Long> items = mergeVo.getItems();
            Long finalPurchaseId = purchaseId;
            List<PurchaseDetailEntity> collect = items.stream().map((item) -> {
                //新建采购需求实体类
                PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
                purchaseDetailEntity.setId(item);
                purchaseDetailEntity.setPurchaseId(finalPurchaseId);
                purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());
                return purchaseDetailEntity;
            }).collect(Collectors.toList());
            purchaseDetailService.updateBatchById(collect);

在这里插入图片描述

10.6 完成采购

前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/cTQHGXbK

在gulimall-ware里创建vo并添加2个文件

PurchaseDoneVo、PurchaseItemDoneVo

①gulimall-ware:PurchaseController

/**
     * 完成采购
     * */
    @PostMapping("/done")
    public R finish(@RequestBody PurchaseDoneVo purchaseDoneVo){
        purchaseService.done(purchaseDoneVo);
        return R.ok();
    }

②gulimall-ware:PurchaseServiceImpl

@Transactional
    @Override
    public void done(PurchaseDoneVo purchaseDoneVo) {
        //1、改变采购单每一个采购项(采购需求)的状态
        Boolean flag = true;
        List<PurchaseItemDoneVo> items = purchaseDoneVo.getItems();
        List<PurchaseDetailEntity> list = 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());
                //将成功采购的进行入库
                PurchaseDetailEntity entity = purchaseDetailService.getById(item.getItemId());
                //这个方法是入库wms_ware_sku,进入WareSkuServiceImpl
                wareSkuService.addStock(entity.getSkuId(),entity.getWareId(),entity.getSkuNum());
            }
            purchaseDetailEntity.setId(item.getItemId());
            list.add(purchaseDetailEntity);
        }
        //批量更新采购项的状态
        purchaseDetailService.updateBatchById(list);

        //2、改变采购单状态
        PurchaseEntity purchaseEntity = new PurchaseEntity();
        purchaseEntity.setId(purchaseDoneVo.getId());
        if(flag==true){
            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.FINISH.getCode());
        }else{
            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.HASERROR.getCode());
        }
        purchaseEntity.setUpdateTime(new Date());
        this.updateById(purchaseEntity);
    }

③gulimall–ware:WareSkuServiceImpl

@Override
    public void addStock(Long skuId, Long wareId, Integer skuNum) {
        //1、判断如果还没有这个库存记录新增
        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);
            //TODO 远程查询sku的名字,如果失败,整个事务无需回滚
            //1、自己catch异常
            //TODO 还可以用什么办法让异常出现以后不回滚?高级
            try {
                //远程调用gulimall-product
                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);
        }

    }

④WareSkuDao

@Mapper
public interface WareSkuDao extends BaseMapper<WareSkuEntity> {

    void addStock(@Param("skuId") Long skuId, @Param("wareId") Long wareId, @Param("skuNum") Integer skuNum);
}

⑤mapper:WareSkuDao

<update id="addStock">
        UPDATE `wms_ware_sku` SET stock=stock+#{skuNum} WHERE sku_id=#{skuId} AND ware_id=#{wareId}
    </update>

⑥远程调用gulimall-product

Feign接口

@FeignClient("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);
}

ware主启动类添加**@EnableFeignClients注解**

⑦测试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

商品服务 - Spu管理

11.1 获取spu规格

在这里插入图片描述
前端接口:https://easydoc.xyz/s/78237135/ZUqEdvA4/GhhJhkg7

①gulimall-product:AttrController

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

②gulimall-product:ProductAttrValueServiceImpl

@Override
public List<ProductAttrValueEntity> baseAttrlistforspu(Long spuId) {
    List<ProductAttrValueEntity> entities
            = this.baseMapper.selectList(new QueryWrapper<ProductAttrValueEntity>()
            .eq("spu_id", spuId));
    return entities;
}

③测试

发现报400的错误
在这里插入图片描述
原因是sys_menu表少了一行数据

解决办法:数据库中gulimall-admin中的sys_menu表中添加一行数据:

在这里插入图片描述
重启前端项目和后端项目后,再次点击spu管理中的规格回显:
在这里插入图片描述

11.2 修改商品规格

前端:https://easydoc.xyz/s/78237135/ZUqEdvA4/GhnJ0L85

①gulimall-product:AttrController

@PostMapping("/update/{spuId}")
public R updateSpuAttr(@PathVariable("spuId") Long spuId,
                       @RequestBody List<ProductAttrValueEntity> entities){
    productAttrValueService.updateSpuAttr(spuId,entities);
    return R.ok();
}

②gulimall-product:ProductAttrValueServiceImpl

@Transactional
@Override
public void updateSpuAttr(Long spuId, List<ProductAttrValueEntity> entities) {
    //1、删除这个spuId之前对应的所有属性
    this.baseMapper.delete(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id",spuId));
    
    List<ProductAttrValueEntity> collect = entities.stream().map((item) -> {
        item.setSpuId(spuId);
        return item;
    }).collect(Collectors.toList());
    this.saveBatch(collect);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值