13.仓储服务-API-仓库管理

1 添加进注册中心

将ware模块添加进注册中心,配置application.yml

cloud:
  nacos:
    discovery:
      server-addr: nacos地址:8848
application:
  name: gulimall-ware

添加服务发现注解

@SpringBootApplication
@EnableDiscoveryClient
public class GulimallWareApplication {

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

}

启动服务

2 配置网关

配置仓储服务的路由,重启网关

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

3 仓库模糊查询

1、修改WareInfoController里的queryPage方法

@Override
public PageUtils queryPage(Map<String, Object> params) {
    
    QueryWrapper<WareInfoEntity> wareInfoEntityQueryWrapper = new QueryWrapper<>();
    String key = (String) params.get("key");
    if (!StringUtils.isEmpty(key)) {
        wareInfoEntityQueryWrapper.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),
            wareInfoEntityQueryWrapper
    );

    return new PageUtils(page);
}

2、修改ware服务日志打印等级

logging:
  level: 
    com.atguigu: debug

3、重启ware服务

坑:ware一直在报错[NACOS ConnectException httpPost] currentServerAddr: http://127.0.0.1:8848, err : Connection refused: connect

问题分析:

由于ware导入了nacos-config的依赖,而没有在配置文件中配置nacos-config的地址,从而去连接默认的nacos地址,也就是本地的8848端口。

解决方法:

在nacos新建ware的命名空间

在ware的resources目录下新建bootstrap.yml

spring:
  application:
    name: gulimall-ware
  cloud:
    nacos:
      config:
        server-addr: nacos的IP地址:8848
        namespace: ware服务的命名空间id

4、测试

新增几条仓储数据,查看数据库是否有数据增加

image-20220428192105139

模糊查询测试

image-20220428192121803

4 查询库存

修改WareSkuServiceImpl的queryPage方法

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


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

    return new PageUtils(page);
}

重启服务测试

5 查询采购需求

修改PurchaseDetailServiceImplqueryPage方法

@Override
public PageUtils queryPage(Map<String, Object> params) {
    QueryWrapper<PurchaseDetailEntity> queryWrapper = new QueryWrapper<>();

    String key = (String) params.get("key");
    if (!StringUtils.isEmpty(key)) {
        //purchase_id  sku_id
        queryWrapper.and(w -> {
            w.eq("purchase_id", key).or().eq("sku_id", key);
        });
    }

    String status = (String) params.get("status");
    if (!StringUtils.isEmpty(status)) {
        //purchase_id  sku_id
        queryWrapper.eq("status", status);
    }

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

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

    return new PageUtils(page);
}

重启服务测试

6 合并采购需求

6.1 采购流程图

image-20220428203750177

6.2 创建采购单

创建采购单,分配采购人员

image-20220428204400458

image-20220428204409249

6.3 查询未领取的采购单

1、在PurchaseController创建unReceiveList方法

@RequestMapping("/unreceive/list")
public R unReceiveList(@RequestParam Map<String, Object> params) {
    PageUtils page = purchaseService.queryPageUnReceivePurchase(params);

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

2、实现queryPageUnReceivePurchase方法

@Override
public PageUtils queryPageUnReceivePurchase(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、重启服务

6.4 合并采购需求

1、创建MergeVo

@Data
public class MergeVo {

    private Long purchaseId; //整单id
    private List<Long> items;//[1,2,3,4] //合并项集合
}

2、创建vo

3、创建ware常量类

package com.atguigu.common.constant;

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、在PurchaseController里创建merge方法

@RequestMapping("/merge")
public R merge(@RequestBody MergeVo mergeVo) {

    purchaseService.mergePurchase(mergeVo);
    return R.ok();
}

3、实现mergePurchase方法

@Autowired
PurchaseDetailService purchaseDetailService;

@Transactional
@Override
public void mergePurchase(MergeVo mergeVo) {
    Long purchaseId = mergeVo.getPurchaseId(); // 采购单id
    // 如果没有传递采购单id,则新建一个采购单
    if (purchaseId == null) {
        PurchaseEntity purchaseEntity = new PurchaseEntity();

        purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode());
        purchaseEntity.setCreateTime(new Date());
        purchaseEntity.setUpdateTime(new Date());
        this.save(purchaseEntity); // 保存采购单记录
        purchaseId = purchaseEntity.getId(); // 获取保存后生成的id

    }

    // 获取所有采购需求的id
    List<Long> items = mergeVo.getItems();
    // 局部内部类里面使用外部变量的时候,这个变量需要是final类型的或者是没有被修改过值的变量,但是purchaseId判空时有可能会修改,所以另外赋值给finalPurchaseId
    Long finalPurchaseId = purchaseId;
    // 根据id更新所有的采购需求记录的purchase_id和状态
    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);
}

4、修改PurchaseController里的save方法

@RequestMapping("/save")
public R save(@RequestBody PurchaseEntity purchase) {
    purchase.setUpdateTime(new Date());
    purchase.setCreateTime(new Date());
    purchaseService.save(purchase);
    return R.ok();
}

5、添加日期格式转换配置

jackson:
  date-format: yyyy-MM-dd HH:mm:ss

6、重启服务测试

新增两个采购需求

image-20220428205512848

点击批量合并,采购需求变化

image-20220429001342347

采购单变化

image-20220429001357933

7 领取采购单

1、在PurchaseController里创建received方法

@PostMapping("/received")
public R received(@RequestBody List<Long> ids) {
    purchaseService.received(ids);
    return R.ok();
}

2、实现received方法

@Override
public void received(List<Long> ids) {
    // 1、确认当前采购单是否是新建或者是已分配状态
    List<PurchaseEntity> purchaseEntities = ids.stream().map(id -> {
        // 1.1、根据id查询出purchaseEntity
        PurchaseEntity purchaseEntity = this.getById(id);
        return purchaseEntity;
    }).filter(purchaseEntity -> {
        // 1.2、过滤掉状态不是0和1的purchaseEntity
        if (purchaseEntity.getStatus() == WareConstant.PurchaseStatusEnum.CREATED.getCode() ||
                purchaseEntity.getStatus() == WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()) {
            return true;
        }
        return false;
    }).map(purchaseEntity -> {
        // 设置purchaseEntity状态为已领取,并更新时间
        purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());
        purchaseEntity.setUpdateTime(new Date());
        return purchaseEntity;
    }).collect(Collectors.toList());

    // 2、改变采购单的状态
    this.updateBatchById(purchaseEntities);

    // 3、改变采购需求的状态
    purchaseEntities.forEach(purchaseEntity -> {
        // 3.1、查询到对应的所有采购需求
        List<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailService.listDetailByPurChaseId(purchaseEntity.getId());
        // 3.2、修改所有采购需求的状态
        purchaseDetailEntities.forEach(purchaseDetailEntity -> {
            purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());
        });
        purchaseDetailService.updateBatchById(purchaseDetailEntities);
    });

}

3、实现listDetailByPurChaseId方法

@Override
public List<PurchaseDetailEntity> listDetailByPurChaseId(Long id) {

    List<PurchaseDetailEntity> purchaseDetailEntities = this.list(new QueryWrapper<PurchaseDetailEntity>().eq("purchase_id", id));

    return purchaseDetailEntities;

}

4、重启服务测试

postman发送请求

image-20220429135931235

查看前端页面变化

image-20220429135952710

image-20220429135959005

8 完成采购

8.1 创建vo

1、创建PurchaseItemDoneVo

@Data
public class PurchaseItemDoneVo {
    private Long itemId;
    private Integer status;
    private String reason;
}

2、创建PurchaseDoneVo

@Data
public class PurchaseDoneVo {

    @NotNull
    private Long id;//采购单id

    private List<PurchaseItemDoneVo> items;
}

8.2 controller

1、在PurchaseController创建finish方法

@PostMapping("/done")
public R finish(@RequestBody PurchaseDoneVo doneVo) {
    purchaseService.done(doneVo);
    return R.ok();
}

8.3 实现done方法

@Transactional
@Autowired
WareSkuService wareSkuService;

@Override
public void done(PurchaseDoneVo doneVo) {
    // 1、改变采购项的状态
    AtomicBoolean flag = new AtomicBoolean(true);
    List<PurchaseItemDoneVo> purchaseItemDoneVos = doneVo.getItems(); // 获取采购需求信息反馈

    // 将purchaseItemDoneVos转变成purchaseDetailEntities
    List<PurchaseDetailEntity> purchaseDetailEntities = purchaseItemDoneVos.stream().map(item -> {
        // 根据id查询出采购需求记录实体类
        PurchaseDetailEntity purchaseDetailEntity = purchaseDetailService.getById(item.getItemId());
        if (item.getStatus() == WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()) {
            flag.set(false);
            purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode());
        } else {
            purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode());
            // 2、将成功采购的进行入库
            wareSkuService.addStock(purchaseDetailEntity.getSkuId(), purchaseDetailEntity.getWareId(), purchaseDetailEntity.getSkuNum());

        }
        return purchaseDetailEntity;
    }).collect(Collectors.toList());

    // 更新采购需求信息
    purchaseDetailService.updateBatchById(purchaseDetailEntities);

    // 2、改变采购单状态
    PurchaseEntity purchaseEntity = this.getById(doneVo.getId());
    purchaseEntity.setStatus(flag.get() ? WareConstant.PurchaseStatusEnum.FINISH.getCode() : WareConstant.PurchaseStatusEnum.HASERROR.getCode());
    purchaseEntity.setUpdateTime(new Date());
    this.updateById(purchaseEntity);
}

8.4 实现addStock方法

1、在WareSkuServiceImpl里创建addStock方法

@Autowired
WareSkuDao wareSkuDao;

@Autowired
ProductFeignService productFeignService;

@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异常
        //TODO 还可以用什么办法让异常出现以后不回滚?高级
        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 ignored) {

        }
        wareSkuDao.insert(wareSkuEntity);
    } else {
        wareSkuDao.addStock(skuId, wareId, skuNum);
    }
}

2、实现wareSkuDao.addStock

创建接口

@Mapper
public interface WareSkuDao extends BaseMapper<WareSkuEntity> {

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

生成SQL语句

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.atguigu.gulimall.ware.dao.WareSkuDao">

   <!-- 可根据自己的需求,是否要使用 -->
    <resultMap type="com.atguigu.gulimall.ware.entity.WareSkuEntity" id="wareSkuMap">
        <result property="id" column="id"/>
        <result property="skuId" column="sku_id"/>
        <result property="wareId" column="ware_id"/>
        <result property="stock" column="stock"/>
        <result property="skuName" column="sku_name"/>
        <result property="stockLocked" column="stock_locked"/>
    </resultMap>
    <update id="addStock">
        UPDATE `wms_ware_sku` SET stock=stock+#{skuNum} WHERE sku_id=#{skuId} AND ware_id=#{wareId}
    </update>
</mapper>

8.5 远程调用服务

1、创建feign.ProductFeignService

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

2、开启远程服务注解

@EnableFeignClients(basePackages = "com.atguigu.gulimall.ware.feign")
@SpringBootApplication
@EnableDiscoveryClient
public class GulimallWareApplication {

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

}

8.6 MyBatis配置

创建config.MyBatis

@EnableTransactionManagement
@MapperScan("com.atguigu.gulimall.ware.dao")
@Configuration
public class MyBatisConfig {

    //引入分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
//        paginationInterceptor.setOverflow(true);
//        // 设置最大单页限制数量,默认 500 条,-1 不受限制
//        paginationInterceptor.setLimit(1000);
        return paginationInterceptor;
    }
}

8.7 测试

postman发送请求

localhost:88/api/ware/purchase/done

注意id与数据库wms_purchase表中的id对应,itemId与数据库wms_purchase_detail表中的id对应

{
    "id": 1, "items": [
        {"itemId": 1, "status": 3, "reason": ""}, 
        {"itemId": 2, "status": 4, "reason": "无货"}
    ]
}

image-20220429151524704

采购单

image-20220429151551542

采购需求

image-20220429151601799

商品库存

image-20220429151618405

数据表wms_ware_sku

如果sku_name是null,查看采购需求的sku_id是否和商品信息里的sku_id对应

image-20220429152914341

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值