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