|
@@ -64,6 +64,8 @@ import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
import java.util.UUID;
|
|
import java.util.UUID;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
+import java.util.concurrent.locks.Lock;
|
|
|
|
|
+import java.util.concurrent.locks.ReentrantLock;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
@Slf4j
|
|
@Slf4j
|
|
@@ -82,6 +84,11 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoDao, OrderInfoEnt
|
|
|
private final RabbitTemplate rabbitTemplate;
|
|
private final RabbitTemplate rabbitTemplate;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
|
+ * 本地订单锁
|
|
|
|
|
+ */
|
|
|
|
|
+ private final Lock orderLock = new ReentrantLock(true);
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
* 订单提交令牌 key 前缀
|
|
* 订单提交令牌 key 前缀
|
|
|
*/
|
|
*/
|
|
|
private static final String ORDER_SUBMIT_TOKEN_PREFIX = "order:submit:%s";
|
|
private static final String ORDER_SUBMIT_TOKEN_PREFIX = "order:submit:%s";
|
|
@@ -321,43 +328,52 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoDao, OrderInfoEnt
|
|
|
List<Long> skuIds = dto.getOrderDetails().stream().filter(e -> ObjectUtil.isNotNull(e.getSkuId())).map(CreateOrderDTO.CreateOrderDetailDTO::getSkuId).collect(Collectors.toList());
|
|
List<Long> skuIds = dto.getOrderDetails().stream().filter(e -> ObjectUtil.isNotNull(e.getSkuId())).map(CreateOrderDTO.CreateOrderDetailDTO::getSkuId).collect(Collectors.toList());
|
|
|
List<GoodsSkuEntity> skuInfos = skuIds.size() > 0 ? goodsSkuService.listByIds(skuIds) : ListUtil.empty();
|
|
List<GoodsSkuEntity> skuInfos = skuIds.size() > 0 ? goodsSkuService.listByIds(skuIds) : ListUtil.empty();
|
|
|
|
|
|
|
|
- // 校验商品信息和支付价格
|
|
|
|
|
- Map<String, BigDecimal> checkResult = checkGoodAndPrice(dto, goodsArray, skuInfos);
|
|
|
|
|
- BigDecimal discountAmount = checkResult.get("discountAmount");
|
|
|
|
|
- BigDecimal deliveryFee = checkResult.get("deliveryFee");
|
|
|
|
|
- BigDecimal totalAmount = checkResult.get("totalAmount");
|
|
|
|
|
-
|
|
|
|
|
- // 构建订单表
|
|
|
|
|
- OrderInfoEntity orderInfo = addOrder(dto, totalAmount, deliveryFee, discountAmount);
|
|
|
|
|
- // 构建订单详情表
|
|
|
|
|
- orderDetailService.addDetail(orderInfo.getId(), goodsArray, skuInfos, dto);
|
|
|
|
|
- // 构建订单收货人表
|
|
|
|
|
- orderConsigneeInfoService.add(orderInfo.getId(), userAddress);
|
|
|
|
|
-
|
|
|
|
|
- // 构建返回参数
|
|
|
|
|
- CreateOrderVO vo = new CreateOrderVO();
|
|
|
|
|
- vo.setOrderId(orderInfo.getId());
|
|
|
|
|
- vo.setOrderAmount(orderInfo.getOrderActualPrice());
|
|
|
|
|
-
|
|
|
|
|
- // 删除购物车对应的商品
|
|
|
|
|
- String type = dto.getSubmitType();
|
|
|
|
|
- if ("2".equals(type)) {
|
|
|
|
|
- List<String> keys = dto.getOrderDetails().stream().map(e -> {
|
|
|
|
|
- String key;
|
|
|
|
|
- if (ObjectUtil.isNull(e.getSkuId())) {
|
|
|
|
|
- key = e.getGoodsId().toString();
|
|
|
|
|
- } else {
|
|
|
|
|
- key = String.format("%s-%s", e.getGoodsId(), e.getSkuId());
|
|
|
|
|
- }
|
|
|
|
|
- return key;
|
|
|
|
|
- }).collect(Collectors.toList());
|
|
|
|
|
- cartService.deleteItems(keys);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ orderLock.lock();
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 校验商品信息和支付价格
|
|
|
|
|
+ Map<String, BigDecimal> checkResult = checkGoodAndPrice(dto, goodsArray, skuInfos);
|
|
|
|
|
+ BigDecimal discountAmount = checkResult.get("discountAmount");
|
|
|
|
|
+ BigDecimal deliveryFee = checkResult.get("deliveryFee");
|
|
|
|
|
+ BigDecimal totalAmount = checkResult.get("totalAmount");
|
|
|
|
|
+
|
|
|
|
|
+ // 更新库存、销量
|
|
|
|
|
+ goodsService.updateBatchById(goodsArray);
|
|
|
|
|
+ goodsSkuService.updateBatchById(skuInfos);
|
|
|
|
|
+
|
|
|
|
|
+ // 构建订单表
|
|
|
|
|
+ OrderInfoEntity orderInfo = addOrder(dto, totalAmount, deliveryFee, discountAmount);
|
|
|
|
|
+ // 构建订单详情表
|
|
|
|
|
+ orderDetailService.addDetail(orderInfo.getId(), goodsArray, skuInfos, dto);
|
|
|
|
|
+ // 构建订单收货人表
|
|
|
|
|
+ orderConsigneeInfoService.add(orderInfo.getId(), userAddress);
|
|
|
|
|
+
|
|
|
|
|
+ // 构建返回参数
|
|
|
|
|
+ CreateOrderVO vo = new CreateOrderVO();
|
|
|
|
|
+ vo.setOrderId(orderInfo.getId());
|
|
|
|
|
+ vo.setOrderAmount(orderInfo.getOrderActualPrice());
|
|
|
|
|
+
|
|
|
|
|
+ // 删除购物车对应的商品
|
|
|
|
|
+ String type = dto.getSubmitType();
|
|
|
|
|
+ if ("2".equals(type)) {
|
|
|
|
|
+ List<String> keys = dto.getOrderDetails().stream().map(e -> {
|
|
|
|
|
+ String key;
|
|
|
|
|
+ if (ObjectUtil.isNull(e.getSkuId())) {
|
|
|
|
|
+ key = e.getGoodsId().toString();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ key = String.format("%s-%s", e.getGoodsId(), e.getSkuId());
|
|
|
|
|
+ }
|
|
|
|
|
+ return key;
|
|
|
|
|
+ }).collect(Collectors.toList());
|
|
|
|
|
+ cartService.deleteItems(keys);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 订单创建成功通知
|
|
|
|
|
- rabbitTemplate.convertAndSend(MQConstant.ORDER_EXCHANGE, MQConstant.ORDER_CREATE_ROUTE_KEY, vo);
|
|
|
|
|
|
|
+ // 订单创建成功通知
|
|
|
|
|
+ rabbitTemplate.convertAndSend(MQConstant.ORDER_EXCHANGE, MQConstant.ORDER_CREATE_ROUTE_KEY, vo);
|
|
|
|
|
|
|
|
- return vo;
|
|
|
|
|
|
|
+ return vo;
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ orderLock.unlock();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -377,43 +393,6 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoDao, OrderInfoEnt
|
|
|
orderInfo.setState("2");
|
|
orderInfo.setState("2");
|
|
|
|
|
|
|
|
this.updateById(orderInfo);
|
|
this.updateById(orderInfo);
|
|
|
-
|
|
|
|
|
- // 更新库存、销量
|
|
|
|
|
- try {
|
|
|
|
|
- addSaleNumAndReducesStock(orderDetailService.getByOrderId(orderId));
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("库存扣减、销量新增操作失败,失败原因【{}】", e.getMessage());
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 加销量、减库存
|
|
|
|
|
- * @param orderDetails
|
|
|
|
|
- */
|
|
|
|
|
- private void addSaleNumAndReducesStock(List<OrderDetailEntity> orderDetails) {
|
|
|
|
|
- List<Long> goodsIds = orderDetails.stream().map(e -> e.getGoodsId()).distinct().collect(Collectors.toList());
|
|
|
|
|
- List<Long> skuIds = orderDetails.stream().filter(e -> ObjectUtil.isNotNull(e.getSkuId())).distinct().map(e -> e.getSkuId()).collect(Collectors.toList());
|
|
|
|
|
- Map<Long, Integer> goodsMap = orderDetails.stream().collect(Collectors.toMap(OrderDetailEntity::getGoodsId, OrderDetailEntity::getGoodsCount, Integer::sum));
|
|
|
|
|
- Map<Long, Integer> skuMap = orderDetails.stream().filter(e -> ObjectUtil.isNotNull(e.getSkuId())).collect(Collectors.toMap(OrderDetailEntity::getSkuId, OrderDetailEntity::getGoodsCount));
|
|
|
|
|
-
|
|
|
|
|
- List<GoodsEntity> goodsEntities = goodsService.getByIds(goodsIds);
|
|
|
|
|
- goodsEntities.forEach(goods -> {
|
|
|
|
|
- Integer num = goodsMap.get(goods.getId());
|
|
|
|
|
- goods.setSaleCnt(goods.getSaleCnt() + num);
|
|
|
|
|
- goods.setStockNum(goods.getStockNum() - num);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- goodsService.updateBatchById(goodsEntities);
|
|
|
|
|
-
|
|
|
|
|
- if (ObjectUtil.isNotEmpty(skuIds)) {
|
|
|
|
|
- List<GoodsSkuEntity> goodsSkuEntities = goodsSkuService.listByIds(skuIds);
|
|
|
|
|
- goodsSkuEntities.forEach(sku -> {
|
|
|
|
|
- Integer num = skuMap.get(sku.getId());
|
|
|
|
|
- sku.setStockNum(sku.getStockNum() - num);
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- goodsSkuService.updateBatchById(goodsSkuEntities);
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Transactional
|
|
@Transactional
|
|
@@ -463,12 +442,16 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoDao, OrderInfoEnt
|
|
|
this.updateById(orderInfo);
|
|
this.updateById(orderInfo);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Transactional
|
|
|
@Override
|
|
@Override
|
|
|
public void autoCancelOrderIfNotPay(Long orderId) {
|
|
public void autoCancelOrderIfNotPay(Long orderId) {
|
|
|
OrderInfoEntity orderInfo = this.getById(orderId);
|
|
OrderInfoEntity orderInfo = this.getById(orderId);
|
|
|
if (orderInfo != null && "1".equals(orderInfo.getState())) {
|
|
if (orderInfo != null && "1".equals(orderInfo.getState())) {
|
|
|
orderInfo.setState("6");
|
|
orderInfo.setState("6");
|
|
|
this.updateById(orderInfo);
|
|
this.updateById(orderInfo);
|
|
|
|
|
+
|
|
|
|
|
+ // 释放库存
|
|
|
|
|
+ releaseStockNum(orderId);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -551,10 +534,14 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoDao, OrderInfoEnt
|
|
|
throw new RRException(BizCodeEnum.PARAMETER_ERROR, "商品:" + goods.getId() + " 不存在");
|
|
throw new RRException(BizCodeEnum.PARAMETER_ERROR, "商品:" + goods.getId() + " 不存在");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (goods.getStockNum().intValue() <= 0) {
|
|
|
|
|
|
|
+ int newStockNum = goods.getStockNum().intValue() - orderDetail.getGoodsCount().intValue();
|
|
|
|
|
+ if (newStockNum < 0) {
|
|
|
throw new RRException(BizCodeEnum.PARAMETER_ERROR, "商品:" + goods.getName() + " 库存不足");
|
|
throw new RRException(BizCodeEnum.PARAMETER_ERROR, "商品:" + goods.getName() + " 库存不足");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ goods.setStockNum(newStockNum);
|
|
|
|
|
+ goods.setSaleCnt(goods.getSaleCnt() + orderDetail.getGoodsCount());
|
|
|
|
|
+
|
|
|
totalAmount = totalAmount.add(goods.getPrice().multiply(new BigDecimal(orderDetail.getGoodsCount())));
|
|
totalAmount = totalAmount.add(goods.getPrice().multiply(new BigDecimal(orderDetail.getGoodsCount())));
|
|
|
}
|
|
}
|
|
|
// 否则用sku数据
|
|
// 否则用sku数据
|
|
@@ -564,10 +551,17 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoDao, OrderInfoEnt
|
|
|
throw new RRException(BizCodeEnum.PARAMETER_ERROR, "sku:" + orderDetail.getSkuId() + " 不存在");
|
|
throw new RRException(BizCodeEnum.PARAMETER_ERROR, "sku:" + orderDetail.getSkuId() + " 不存在");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (sku.getStockNum().intValue() <= 0) {
|
|
|
|
|
|
|
+ int newStockNum = sku.getStockNum().intValue() - orderDetail.getGoodsCount().intValue();
|
|
|
|
|
+
|
|
|
|
|
+ if (newStockNum < 0) {
|
|
|
throw new RRException(BizCodeEnum.PARAMETER_ERROR, "sku:" + sku.getSkuName() + " 库存不足");
|
|
throw new RRException(BizCodeEnum.PARAMETER_ERROR, "sku:" + sku.getSkuName() + " 库存不足");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ sku.setStockNum(newStockNum);
|
|
|
|
|
+
|
|
|
|
|
+ GoodsEntity goods = goodsMap.get(sku.getGoodsId());
|
|
|
|
|
+ goods.setSaleCnt(goods.getSaleCnt() + orderDetail.getGoodsCount());
|
|
|
|
|
+
|
|
|
totalAmount = totalAmount.add(sku.getPrice().multiply(new BigDecimal(orderDetail.getGoodsCount())));
|
|
totalAmount = totalAmount.add(sku.getPrice().multiply(new BigDecimal(orderDetail.getGoodsCount())));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -733,4 +727,38 @@ public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoDao, OrderInfoEnt
|
|
|
throw new RRException(BizCodeEnum.PARAMETER_ERROR, "skuId:" + notInNoSaleGoods.get(0).getId() + "为非销售状态sku");
|
|
throw new RRException(BizCodeEnum.PARAMETER_ERROR, "skuId:" + notInNoSaleGoods.get(0).getId() + "为非销售状态sku");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 释放库存
|
|
|
|
|
+ * @param orderId 订单id
|
|
|
|
|
+ */
|
|
|
|
|
+ private void releaseStockNum(Long orderId) {
|
|
|
|
|
+ List<OrderDetailEntity> orderDetails = orderDetailService.getByOrderId(orderId);
|
|
|
|
|
+ List<Long> goodsIds = orderDetails.stream().map(e -> e.getGoodsId()).distinct().collect(Collectors.toList());
|
|
|
|
|
+ List<Long> skuIds = orderDetails.stream().filter(e -> ObjectUtil.isNotNull(e.getSkuId())).distinct().map(e -> e.getSkuId()).collect(Collectors.toList());
|
|
|
|
|
+ Map<Long, Integer> goodsMap = orderDetails.stream().collect(Collectors.toMap(OrderDetailEntity::getGoodsId, OrderDetailEntity::getGoodsCount, Integer::sum));
|
|
|
|
|
+ Map<Long, Integer> skuMap = orderDetails.stream().filter(e -> ObjectUtil.isNotNull(e.getSkuId())).collect(Collectors.toMap(OrderDetailEntity::getSkuId, OrderDetailEntity::getGoodsCount));
|
|
|
|
|
+
|
|
|
|
|
+ List<GoodsEntity> goodsEntities = goodsService.getByIds(goodsIds);
|
|
|
|
|
+ goodsEntities.forEach(goods -> {
|
|
|
|
|
+ Integer num = goodsMap.get(goods.getId());
|
|
|
|
|
+ goods.setSaleCnt(goods.getSaleCnt() - num);
|
|
|
|
|
+ if (!ObjectUtil.equal(goods.getEnableSku(), "1")) {
|
|
|
|
|
+ goods.setStockNum(goods.getStockNum() + num);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ goodsService.updateBatchById(goodsEntities);
|
|
|
|
|
+
|
|
|
|
|
+ if (ObjectUtil.isNotEmpty(skuIds)) {
|
|
|
|
|
+ List<GoodsSkuEntity> goodsSkuEntities = goodsSkuService.listByIds(skuIds);
|
|
|
|
|
+ goodsSkuEntities.forEach(sku -> {
|
|
|
|
|
+ Integer num = skuMap.get(sku.getId());
|
|
|
|
|
+ sku.setStockNum(sku.getStockNum() + num);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ goodsSkuService.updateBatchById(goodsSkuEntities);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|