|
@@ -189,6 +189,8 @@ import static com.yc.ship.module.trade.enums.ErrorCodeConstants.*;
|
|
|
@Slf4j
|
|
@Slf4j
|
|
|
public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
|
|
public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
|
|
|
|
|
|
|
|
|
|
+ private static final String MERGE_ORDER_AMOUNT_ERROR = "订单金额合并失败:";
|
|
|
|
|
+
|
|
|
@Resource
|
|
@Resource
|
|
|
private StoreApi storeApi;
|
|
private StoreApi storeApi;
|
|
|
@Resource
|
|
@Resource
|
|
@@ -4537,6 +4539,128 @@ public class OtcTradeOrderServiceImpl implements OtcTradeOrderService {
|
|
|
return tradeOrderMapper.getValidSimpleOrderInfoByVoyageId(voyageId);
|
|
return tradeOrderMapper.getValidSimpleOrderInfoByVoyageId(voyageId);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
|
|
+ public void mergeOrderAmount(LoginUser loginUser, MergeOrderAmountReqVO reqVO) {
|
|
|
|
|
+ LinkedHashSet<Long> orderIdSet = new LinkedHashSet<>(reqVO.getOrderIds());
|
|
|
|
|
+ Asserts.isTrue(orderIdSet.size() >= 2, MERGE_ORDER_AMOUNT_ERROR + "至少选择两个不同的订单");
|
|
|
|
|
+ Asserts.isTrue(orderIdSet.contains(reqVO.getTargetOrderId()),
|
|
|
|
|
+ MERGE_ORDER_AMOUNT_ERROR + "目标订单必须在已选订单中");
|
|
|
|
|
+
|
|
|
|
|
+ // 按主键顺序逐行加锁,既避免租户拦截器生成 FOR UPDATE ORDER BY 非法 SQL,也固定并发加锁顺序。
|
|
|
|
|
+ List<Long> sortedOrderIds = orderIdSet.stream().sorted().collect(Collectors.toList());
|
|
|
|
|
+ List<TradeOrderDO> orders = sortedOrderIds.stream()
|
|
|
|
|
+ .map(orderId -> tradeOrderMapper.selectOne(new LambdaQueryWrapper<TradeOrderDO>()
|
|
|
|
|
+ .eq(TradeOrderDO::getId, orderId)
|
|
|
|
|
+ .last("FOR UPDATE")))
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ Asserts.isTrue(orders.size() == sortedOrderIds.size(), MERGE_ORDER_AMOUNT_ERROR + "部分订单不存在或无权操作");
|
|
|
|
|
+ Asserts.isTrue(orders.stream().allMatch(order -> order.getOrderStatus() != null && order.getOrderStatus() >= 0),
|
|
|
|
|
+ MERGE_ORDER_AMOUNT_ERROR + "只允许合并订单状态大于等于 0 的订单");
|
|
|
|
|
+ Asserts.isTrue(orders.stream().allMatch(order -> Objects.equals(order.getPayStatus(), 0)),
|
|
|
|
|
+ MERGE_ORDER_AMOUNT_ERROR + "只允许合并未支付订单");
|
|
|
|
|
+ TradeOrderDO firstOrder = orders.get(0);
|
|
|
|
|
+ Asserts.isTrue(orders.stream().allMatch(order -> Objects.equals(order.getVoyageId(), firstOrder.getVoyageId())),
|
|
|
|
|
+ MERGE_ORDER_AMOUNT_ERROR + "只允许合并同一航次的订单");
|
|
|
|
|
+ Asserts.isTrue(orders.stream().allMatch(order -> Objects.equals(order.getSourceId(), firstOrder.getSourceId())),
|
|
|
|
|
+ MERGE_ORDER_AMOUNT_ERROR + "只允许合并同一来源的订单");
|
|
|
|
|
+
|
|
|
|
|
+ List<TradeOrderTotalDO> orderTotals = sortedOrderIds.stream()
|
|
|
|
|
+ .map(orderId -> tradeOrderTotalMapper.selectOne(new LambdaQueryWrapper<TradeOrderTotalDO>()
|
|
|
|
|
+ .eq(TradeOrderTotalDO::getOldOrderId, orderId)
|
|
|
|
|
+ .last("FOR UPDATE")))
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+ Asserts.isTrue(orderTotals.size() == sortedOrderIds.size(), MERGE_ORDER_AMOUNT_ERROR + "部分订单汇总信息不存在");
|
|
|
|
|
+
|
|
|
|
|
+ Map<Long, TradeOrderDO> orderMap = CollectionUtils.convertMap(orders, TradeOrderDO::getId);
|
|
|
|
|
+ Map<Long, TradeOrderTotalDO> orderTotalMap = CollectionUtils.convertMap(
|
|
|
|
|
+ orderTotals, TradeOrderTotalDO::getOldOrderId);
|
|
|
|
|
+ Asserts.isTrue(orderTotalMap.size() == sortedOrderIds.size()
|
|
|
|
|
+ && orderTotalMap.keySet().containsAll(sortedOrderIds),
|
|
|
|
|
+ MERGE_ORDER_AMOUNT_ERROR + "订单汇总信息不完整");
|
|
|
|
|
+ TradeOrderDO targetOrder = orderMap.get(reqVO.getTargetOrderId());
|
|
|
|
|
+ Asserts.isTrue(targetOrder != null, MERGE_ORDER_AMOUNT_ERROR + "目标订单不存在");
|
|
|
|
|
+
|
|
|
|
|
+ BigDecimal mergedAmount = orders.stream()
|
|
|
|
|
+ .map(TradeOrderDO::getAmount)
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
|
+ BigDecimal mergedPayAmount = orders.stream()
|
|
|
|
|
+ .map(TradeOrderDO::getPayAmount)
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
|
+ BigDecimal mergedOrderMoney = orderTotals.stream()
|
|
|
|
|
+ .map(TradeOrderTotalDO::getOrderMoney)
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
|
+ BigDecimal mergedRealMoney = orderTotals.stream()
|
|
|
|
|
+ .map(TradeOrderTotalDO::getRealMoney)
|
|
|
|
|
+ .filter(Objects::nonNull)
|
|
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
|
|
+ BigDecimal runningAmount = ObjectUtil.defaultIfNull(targetOrder.getPayAmount(), BigDecimal.ZERO);
|
|
|
|
|
+
|
|
|
|
|
+ for (Long sourceOrderId : orderIdSet) {
|
|
|
|
|
+ if (Objects.equals(sourceOrderId, targetOrder.getId())) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ TradeOrderDO sourceOrder = orderMap.get(sourceOrderId);
|
|
|
|
|
+ BigDecimal sourceAmount = ObjectUtil.defaultIfNull(sourceOrder.getPayAmount(), BigDecimal.ZERO);
|
|
|
|
|
+ runningAmount = runningAmount.add(sourceAmount);
|
|
|
|
|
+
|
|
|
|
|
+ TradeOrderDO sourceUpdate = new TradeOrderDO();
|
|
|
|
|
+ sourceUpdate.setId(sourceOrder.getId());
|
|
|
|
|
+ sourceUpdate.setAmount(BigDecimal.ZERO);
|
|
|
|
|
+ sourceUpdate.setPayAmount(BigDecimal.ZERO);
|
|
|
|
|
+ tradeOrderMapper.updateById(sourceUpdate);
|
|
|
|
|
+
|
|
|
|
|
+ TradeOrderTotalDO sourceTotalUpdate = new TradeOrderTotalDO();
|
|
|
|
|
+ sourceTotalUpdate.setId(orderTotalMap.get(sourceOrderId).getId());
|
|
|
|
|
+ sourceTotalUpdate.setOrderMoney(BigDecimal.ZERO);
|
|
|
|
|
+ sourceTotalUpdate.setRealMoney(BigDecimal.ZERO);
|
|
|
|
|
+ tradeOrderTotalMapper.updateById(sourceTotalUpdate);
|
|
|
|
|
+
|
|
|
|
|
+ insertMergeOrderLog(loginUser, targetOrder, sourceOrder, sourceAmount, runningAmount, true);
|
|
|
|
|
+ insertMergeOrderLog(loginUser, sourceOrder, targetOrder, sourceAmount, BigDecimal.ZERO, false);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ TradeOrderDO targetUpdate = new TradeOrderDO();
|
|
|
|
|
+ targetUpdate.setId(targetOrder.getId());
|
|
|
|
|
+ targetUpdate.setAmount(mergedAmount);
|
|
|
|
|
+ targetUpdate.setPayAmount(mergedPayAmount);
|
|
|
|
|
+ tradeOrderMapper.updateById(targetUpdate);
|
|
|
|
|
+
|
|
|
|
|
+ TradeOrderTotalDO targetTotalUpdate = new TradeOrderTotalDO();
|
|
|
|
|
+ targetTotalUpdate.setId(orderTotalMap.get(targetOrder.getId()).getId());
|
|
|
|
|
+ targetTotalUpdate.setOrderMoney(mergedOrderMoney);
|
|
|
|
|
+ targetTotalUpdate.setRealMoney(mergedRealMoney);
|
|
|
|
|
+ tradeOrderTotalMapper.updateById(targetTotalUpdate);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void insertMergeOrderLog(LoginUser loginUser, TradeOrderDO logOrder, TradeOrderDO relatedOrder,
|
|
|
|
|
+ BigDecimal amount, BigDecimal newAmount, boolean targetLog) {
|
|
|
|
|
+ TradeOrderLogDO logDO = new TradeOrderLogDO();
|
|
|
|
|
+ logDO.setId(IdWorker.getId());
|
|
|
|
|
+ logDO.setOrderId(logOrder.getId());
|
|
|
|
|
+ logDO.setUserId(loginUser.getId());
|
|
|
|
|
+ logDO.setUserType(loginUser.getUserType());
|
|
|
|
|
+ logDO.setBeforeStatus(logOrder.getOrderStatus());
|
|
|
|
|
+ logDO.setAfterStatus(logOrder.getOrderStatus());
|
|
|
|
|
+ logDO.setOperateType(TradeOrderOperateTypeEnum.ORDER_MERGE.getType());
|
|
|
|
|
+ if (targetLog) {
|
|
|
|
|
+ logDO.setContent(StrUtil.format(TradeOrderOperateTypeEnum.ORDER_MERGE.getContent(),
|
|
|
|
|
+ MapUtil.<String, Object>builder()
|
|
|
|
|
+ .put("orderId", relatedOrder.getOrderNo())
|
|
|
|
|
+ .put("payAmount", amount)
|
|
|
|
|
+ .put("newPayAmount", newAmount)
|
|
|
|
|
+ .build()));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ logDO.setContent("订单金额" + amount + "已合并至订单" + relatedOrder.getOrderNo() + ",合并后为" + newAmount);
|
|
|
|
|
+ }
|
|
|
|
|
+ tradeOrderLogMapper.insert(logDO);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.HAND_ORDER_REFUND)
|
|
@TradeOrderLog(operateType = TradeOrderOperateTypeEnum.HAND_ORDER_REFUND)
|