八、生成订单
一个是需要生成订单信息一个是需要生成订单项信息。具体的核心代码为
/*** 创建订单的方法* @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) {// 创建OrderEntityOrderEntity 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;}
锁定库存的操作,需要操作ware仓储服务。
/*** 锁定库存的操作* @param vo* @return*/@Transactional@Overridepublic 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;}
没有库存或者锁定库存失败我们通过自定义的异常抛出
/*** 自定义异常:锁定库存失败的情况下产生的异常信*/
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;}
}
如果下订单操作成功(订单数据和订单项数据)我们就会操作锁库存的行为
锁定库存失败通过抛异常来使订单操作回滚