• 【业务功能篇99】微服务-springcloud-springboot-电商订单模块-生成订单服务-锁定库存


    八、生成订单

    image.png

    一个是需要生成订单信息一个是需要生成订单项信息。具体的核心代码为

    /**
         * 创建订单的方法
         * @param vo
         * @return
         */
        private OrderCreateTO createOrder(OrderSubmitVO vo) {
            OrderCreateTO createTO = new OrderCreateTO();
            // 创建订单
            OrderEntity orderEntity = buildOrder(vo);
            createTO.setOrderEntity(orderEntity);
            // 创建OrderItemEntity 订单项
            List<OrderItemEntity> orderItemEntitys = buildOrderItems(orderEntity.getOrderSn());
            createTO.setOrderItemEntitys(orderItemEntitys);
            return createTO;
        }
    
        /**
         * 通过购物车中选中的商品来创建对应的购物项信息
         * @return
         */
        private List<OrderItemEntity> buildOrderItems(String orderSN) {
            List<OrderItemEntity> orderItemEntitys = new ArrayList<>();
            // 获取购物车中的商品信息 选中的
            List<OrderItemVo> userCartItems = cartFeginService.getUserCartItems();
            if(userCartItems != null && userCartItems.size() > 0){
                // 统一根据SKUID查询出对应的SPU的信息
                List<Long> spuIds = new ArrayList<>();
                for (OrderItemEntity orderItemEntity : orderItemEntitys) {
                    if(!spuIds.contains(orderItemEntity.getSpuId())){
                        spuIds.add(orderItemEntity.getOrderId());
                    }
                }
                // 远程调用商品服务获取到对应的SPU信息
                List<OrderItemSpuInfoVO> spuInfos = productService.getOrderItemSpuInfoBySpuId((Long[]) spuIds.toArray());
                Map<Long, OrderItemSpuInfoVO> map = spuInfos.stream().collect(Collectors.toMap(OrderItemSpuInfoVO::getId, item -> item));
                for (OrderItemVo userCartItem : userCartItems) {
                    // 获取到商品信息对应的 SPU信息
                    OrderItemSpuInfoVO spuInfo  = map.get(userCartItem.getSpuId());
                    OrderItemEntity orderItemEntity = buildOrderItem(userCartItem,spuInfo);
                    // 绑定对应的订单编号
                    orderItemEntity.setOrderSn(orderSN);
                    orderItemEntitys.add(orderItemEntity);
                }
            }
    
            return orderItemEntitys;
        }
    
        /**
         * 根据一个购物车中的商品创建对应的 订单项
         * @param userCartItem
         * @return
         */
        private OrderItemEntity buildOrderItem(OrderItemVo userCartItem,OrderItemSpuInfoVO spuInfo) {
            OrderItemEntity entity = new OrderItemEntity();
            // SKU信息
            entity.setSkuId(userCartItem.getSkuId());
            entity.setSkuName(userCartItem.getTitle());
            entity.setSkuPic(userCartItem.getImage());
            entity.setSkuQuantity(userCartItem.getCount());
            List<String> skuAttr = userCartItem.getSkuAttr();
            String skuAttrStr = StringUtils.collectionToDelimitedString(skuAttr, ";");
            entity.setSkuAttrsVals(skuAttrStr);
            // SPU信息
            entity.setSpuId(spuInfo.getId());
            entity.setSpuBrand(spuInfo.getBrandName());
            entity.setCategoryId(spuInfo.getCatalogId());
            entity.setSpuPic(spuInfo.getImg());
            // 优惠信息 忽略
            // 积分信息
            entity.setGiftGrowth(userCartItem.getPrice().intValue());
            entity.setGiftIntegration(userCartItem.getPrice().intValue());
            return entity;
        }
    
        private OrderEntity buildOrder(OrderSubmitVO vo) {
            // 创建OrderEntity
            OrderEntity orderEntity = new OrderEntity();
            // 创建订单编号
            String orderSn = IdWorker.getTimeId();
            orderEntity.setOrderSn(orderSn);
            MemberVO memberVO = (MemberVO) AuthInterceptor.threadLocal.get();
            // 设置会员相关的信息
            orderEntity.setMemberId(memberVO.getId());
            orderEntity.setMemberUsername(memberVO.getUsername());
            // 根据收获地址ID获取收获地址的详细信息
            MemberAddressVo memberAddressVo = memberFeginService.getAddressById(vo.getAddrId());
            orderEntity.setReceiverCity(memberAddressVo.getCity());
            orderEntity.setReceiverDetailAddress(memberAddressVo.getDetailAddress());
            orderEntity.setReceiverName(memberAddressVo.getName());
            orderEntity.setReceiverPhone(memberAddressVo.getPhone());
            orderEntity.setReceiverPostCode(memberAddressVo.getPostCode());
            orderEntity.setReceiverRegion(memberAddressVo.getRegion());
            orderEntity.setReceiverProvince(memberAddressVo.getProvince());
            // 设置订单的状态
            orderEntity.setStatus(OrderConstant.OrderStateEnum.FOR_THE_PAYMENT.getCode());
            return orderEntity;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    锁定库存的操作,需要操作ware仓储服务。

       /**
         * 锁定库存的操作
         * @param vo
         * @return
         */
        @Transactional
        @Override
        public Boolean orderLockStock(WareSkuLockVO vo) {
            List<OrderItemVo> items = vo.getItems();
            // 首先找到具有库存的仓库
            List<SkuWareHasStock> collect = items.stream().map(item -> {
                SkuWareHasStock skuWareHasStock = new SkuWareHasStock();
                skuWareHasStock.setSkuId(item.getSkuId());
                List<WareSkuEntity> wareSkuEntities = this.baseMapper.listHashStock(item.getSkuId());
                skuWareHasStock.setWareSkuEntities(wareSkuEntities);
                skuWareHasStock.setNum(item.getCount());
                return skuWareHasStock;
            }).collect(Collectors.toList());
            // 尝试锁定库存
            for (SkuWareHasStock skuWareHasStock : collect) {
                Long skuId = skuWareHasStock.getSkuId();
                List<WareSkuEntity> wareSkuEntities = skuWareHasStock.wareSkuEntities;
                if(wareSkuEntities == null && wareSkuEntities.size() == 0){
                    // 当前商品没有库存了
                    throw new NoStockExecption(skuId);
                }
                // 当前需要锁定的商品的梳理
                Integer count = skuWareHasStock.getNum();
                Boolean skuStocked = false; // 表示当前SkuId的库存没有锁定完成
                for (WareSkuEntity wareSkuEntity : wareSkuEntities) {
                    // 循环获取到对应的 仓库,然后需要锁定库存
                    // 获取当前仓库能够锁定的库存数
                    Integer canStock = wareSkuEntity.getStock() - wareSkuEntity.getStockLocked();
                    if(count <= canStock){
                        // 表示当前的skuId的商品的数量小于等于需要锁定的数量
                        Integer i = this.baseMapper.lockSkuStock(skuId,wareSkuEntity.getWareId(),count);
                        count = 0;
                        skuStocked = true;
                    }else{
                        // 需要锁定的库存大于 可以锁定的库存 就按照已有的库存来锁定
                        Integer i = this.baseMapper.lockSkuStock(skuId,wareSkuEntity.getWareId(),canStock);
                        count = count - canStock;
                    }
                    if(count <= 0 ){
                        // 表示所有的商品都锁定了
                        break;
                    }
                }
                if(count > 0){
                    // 说明库存没有锁定完
                    throw new NoStockExecption(skuId);
                }
                if(skuStocked == false){
                    // 表示上一个商品的没有锁定库存成功
                    throw new NoStockExecption(skuId);
                }
            }
            return true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    没有库存或者锁定库存失败我们通过自定义的异常抛出

    /**
     * 自定义异常:锁定库存失败的情况下产生的异常信
     */
    public class NoStockExecption extends RuntimeException{
    
        private Long skuId;
    
        public NoStockExecption(Long skuId){
            super("当前商品["+skuId+"]没有库存了");
            this.skuId = skuId;
    
        }
    
        public Long getSkuId() {
            return skuId;
        }
    
        public void setSkuId(Long skuId) {
            this.skuId = skuId;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    如果下订单操作成功(订单数据和订单项数据)我们就会操作锁库存的行为

    image.png

    锁定库存失败通过抛异常来使订单操作回滚

    image.png

  • 相关阅读:
    献给阿尔吉侬的花束( 入门级bfs查找 + 模版解读 + 错误示范)
    腾讯云短信告警
    【Filament】材质系统
    MVC、能力成熟度模型、分层体系结构、三层体系结构、体系风格
    政安晨:【Keras机器学习示例演绎】(十七)—— 用于图像分类的 RandAugment 可提高鲁棒性
    解锁新技能《Redis ACL SETUSER命令》
    Linux - 实现一个简单的 shell
    RCE(Pikachu)
    图解 | 聊聊 MyBatis 缓存
    Deepin下vsftp服务安装配置虚拟用户
  • 原文地址:https://blog.csdn.net/studyday1/article/details/132710366