Commit 8d13ecc9c89014c336c92269249da23e948aa410

Authored by puhui999
1 parent f23e1b85

fix:优化订单发货逻辑使其支持一单分发

yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApi.java
... ... @@ -19,6 +19,14 @@ public interface CombinationApi {
19 19 void createRecord(@Valid CombinationRecordReqDTO reqDTO);
20 20  
21 21 /**
  22 + * 获取开团记录状态
  23 + *
  24 + * @param userId 用户编号
  25 + * @param orderId 订单编号
  26 + */
  27 + Integer getRecordStatus(Long userId, Long orderId);
  28 +
  29 + /**
22 30 * 更新开团记录状态
23 31 *
24 32 * @param userId 用户编号
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationApiImpl.java
... ... @@ -23,6 +23,11 @@ public class CombinationApiImpl implements CombinationApi {
23 23 }
24 24  
25 25 @Override
  26 + public Integer getRecordStatus(Long userId, Long orderId) {
  27 + return activityService.getRecordStatus(userId, orderId);
  28 + }
  29 +
  30 + @Override
26 31 public void updateRecordStatus(Long userId, Long orderId, Integer status) {
27 32 activityService.updateRecordStatusByUserIdAndOrderId(userId, orderId, status);
28 33 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
... ... @@ -109,4 +109,12 @@ public interface CombinationActivityService {
109 109 */
110 110 void createRecord(CombinationRecordReqDTO reqDTO);
111 111  
  112 + /**
  113 + * 获得拼团状态
  114 + *
  115 + * @param userId 用户编号
  116 + * @param orderId 订单编号
  117 + * @return 拼团状态
  118 + */
  119 + Integer getRecordStatus(Long userId, Long orderId);
112 120 }
... ...
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
... ... @@ -248,4 +248,10 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
248 248 recordMapper.insert(recordDO);
249 249 }
250 250  
  251 + @Override
  252 + public Integer getRecordStatus(Long userId, Long orderId) {
  253 + CombinationRecordDO recordDO = validateCombinationRecord(userId, orderId);
  254 + return recordDO.getStatus();
  255 + }
  256 +
251 257 }
... ...
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
... ... @@ -28,8 +28,9 @@ public interface ErrorCodeConstants {
28 28 ErrorCode ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED = new ErrorCode(1011000017, "交易订单发货失败,订单不是【待发货】状态");
29 29 ErrorCode ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1011000018, "交易订单收货失败,订单不是【待收货】状态");
30 30 ErrorCode ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED = new ErrorCode(1011000019, "创建交易订单项的评价失败,订单不是【已完成】状态");
31   - ErrorCode ORDER_COMMENT_STATUS_NOT_FALSE = new ErrorCode(1011000019, "创建交易订单项的评价失败,订单已评价");
32   - ErrorCode ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE = new ErrorCode(1011000017, "交易订单发货失败,订单已退款或部分退款");
  31 + ErrorCode ORDER_COMMENT_STATUS_NOT_FALSE = new ErrorCode(1011000020, "创建交易订单项的评价失败,订单已评价");
  32 + ErrorCode ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE = new ErrorCode(1011000021, "交易订单发货失败,订单已退款或部分退款");
  33 + ErrorCode ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS = new ErrorCode(1011000022, "交易订单发货失败,拼团未成功");
33 34  
34 35 // ========== After Sale 模块 1011000100 ==========
35 36 ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在");
... ... @@ -66,8 +67,10 @@ public interface ErrorCodeConstants {
66 67 ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011005001, "运费模板不存在");
67 68  
68 69 // ========== 物流 PICK_UP 模块 1011006000 ==========
69   -
70 70 ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在");
71 71  
72   -
  72 + // ========== 物流 PICK_UP 模块 1011007000 ==========
  73 + ErrorCode ORDER_DELIVERY_FAILED_ITEMS_NOT_EMPTY = new ErrorCode(1011007000, "订单发货失败,请选择发货商品");
  74 + ErrorCode ORDER_DELIVERY_FAILED_ITEM_NOT_EXISTS = new ErrorCode(1011007001, "订单发货失败,所选发货商品不存在");
  75 + ErrorCode ORDER_DELIVERY_FAILED_ITEM_ALREADY_DELIVERY = new ErrorCode(1011007001, "订单发货失败,所选商品已发货");
73 76 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderDeliveryReqVO.java
... ... @@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
6 6 import lombok.Data;
7 7  
8 8 import javax.validation.constraints.NotNull;
  9 +import java.util.List;
9 10  
10 11 @Schema(description = "管理后台 - 订单发货 Request VO")
11 12 @Data
... ... @@ -26,6 +27,12 @@ public class TradeOrderDeliveryReqVO {
26 27 @Schema(description = "发货物流单号", example = "SF123456789")
27 28 private String logisticsNo;
28 29  
  30 + // TODO 订单项商品单独发货
  31 +
  32 + @Schema(description = "发货订单项", example = "[1,2,3]")
  33 + @NotNull(message = "发货订单项不能为空")
  34 + private List<Long> orderItemIds;
  35 +
29 36 // =============== 同城配送 ================
30 37 // TODO
31 38  
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
... ... @@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
18 18 import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
19 19 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
20 20 import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
  21 +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
21 22 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO;
22 23 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageItemRespVO;
23 24 import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO;
... ... @@ -26,6 +27,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderI
26 27 import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
27 28 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
28 29 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
  30 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;
29 31 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
30 32 import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
31 33 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
... ... @@ -334,4 +336,15 @@ public interface TradeOrderConvert {
334 336 })
335 337 CombinationRecordReqDTO convert(TradeOrderDO order, TradeOrderItemDO orderItem, AppTradeOrderCreateReqVO createReqVO, MemberUserRespDTO user);
336 338  
  339 + TradeOrderDeliveryDO covert(Long orderId, Long orderItemId, Long userId, Integer deliveryType, Long logisticsId, String logisticsNo);
  340 +
  341 + default List<TradeOrderDeliveryDO> covert(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {
  342 + ArrayList<TradeOrderDeliveryDO> arrayList = new ArrayList<>();
  343 + deliveryReqVO.getOrderItemIds().forEach(item -> {
  344 + arrayList.add(covert(order.getId(), item, order.getUserId(), deliveryReqVO.getType(),
  345 + deliveryReqVO.getLogisticsId(), deliveryReqVO.getLogisticsNo()));
  346 + });
  347 + return arrayList;
  348 + }
  349 +
337 350 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDeliveryDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.dal.dataobject.order;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
  5 +import com.baomidou.mybatisplus.annotation.KeySequence;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +
  10 +/**
  11 + * 交易订单发货记录 DO
  12 + *
  13 + * @author HUIHUI
  14 + */
  15 +@TableName("trade_order_delivery")
  16 +@KeySequence("trade_order_delivery_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class TradeOrderDeliveryDO extends BaseDO {
  24 +
  25 + /**
  26 + * 订单发货记录 id
  27 + */
  28 + private Long id;
  29 + /**
  30 + * 订单 id
  31 + */
  32 + private Long orderId;
  33 + /**
  34 + * 订单项 id TODO 要不要一个发货记录可对应多个订单项?
  35 + */
  36 + private Long orderItemId;
  37 + /**
  38 + * 用户编号
  39 + *
  40 + * 关联 MemberUserDO 的 id 编号
  41 + */
  42 + private Long userId;
  43 + /**
  44 + * 配送方式
  45 + *
  46 + * 枚举 {@link DeliveryTypeEnum}
  47 + */
  48 + private Integer deliveryType;
  49 + /**
  50 + * 发货物流公司编号
  51 + */
  52 + private Long logisticsId;
  53 + /**
  54 + * 发货物流单号
  55 + */
  56 + private String logisticsNo;
  57 +
  58 + // TODO 同城配送
  59 +
  60 +}
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderDeliveryMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.dal.mysql.order;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  5 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;
  6 +import org.apache.ibatis.annotations.Mapper;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * 交易订单发货记录 Mapper
  12 + *
  13 + * @author HUIHUI
  14 + */
  15 +@Mapper
  16 +public interface TradeOrderDeliveryMapper extends BaseMapperX<TradeOrderDeliveryDO> {
  17 +
  18 + default List<TradeOrderDeliveryDO> selsectListByOrderIdAndItemIds(Long orderId, List<Long> orderItemIds) {
  19 + return selectList(new LambdaQueryWrapperX<TradeOrderDeliveryDO>()
  20 + .eq(TradeOrderDeliveryDO::getOrderId, orderId).in(TradeOrderDeliveryDO::getOrderItemId, orderItemIds));
  21 + }
  22 +
  23 +}
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
... ... @@ -38,7 +38,9 @@ import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
38 38 import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO;
39 39 import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO;
40 40 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
  41 +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDeliveryDO;
41 42 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
  43 +import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderDeliveryMapper;
42 44 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
43 45 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
44 46 import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants;
... ... @@ -107,6 +109,8 @@ public class TradeOrderServiceImpl implements TradeOrderService {
107 109  
108 110 @Resource
109 111 private CombinationApi combinationApi;
  112 + @Resource
  113 + private TradeOrderDeliveryMapper orderDeliveryMapper;
110 114 // =================== Order ===================
111 115  
112 116 @Override
... ... @@ -243,7 +247,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
243 247  
244 248 /**
245 249 * 执行创建完创建完订单后的逻辑
246   - * <p>
  250 + *
247 251 * 例如说:优惠劵的扣减、积分的扣减、支付单的创建等等
248 252 *
249 253 * @param userId 用户编号
... ... @@ -256,7 +260,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
256 260 TradePriceCalculateRespBO calculateRespBO) {
257 261 // 下单时扣减商品库存
258 262 productSkuApi.updateSkuStock(new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(orderItems)));
259   -
  263 + // TODO puhui:扣减活动库存
260 264 // 删除购物车商品 TODO 芋艿:待实现
261 265  
262 266 // 扣减积分,抵扣金额 TODO 芋艿:待实现
... ... @@ -267,7 +271,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
267 271 .setOrderId(tradeOrderDO.getId()));
268 272 }
269 273  
270   - // 生成预支付
  274 + // 生成预支付 TODO puhui: 活动支付金额怎么算?
271 275 createPayOrder(tradeOrderDO, orderItems, calculateRespBO);
272 276  
273 277 // 增加订单日志 TODO 芋艿:待实现
... ... @@ -313,7 +317,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
313 317  
314 318 /**
315 319 * 校验交易订单满足被支付的条件
316   - * <p>
  320 + *
317 321 * 1. 交易订单未支付
318 322 * 2. 支付单已支付
319 323 *
... ... @@ -367,29 +371,50 @@ public class TradeOrderServiceImpl implements TradeOrderService {
367 371 return new KeyValue<>(order, payOrder);
368 372 }
369 373  
370   - // TODO 芋艿:如果无需发货,需要怎么存储? fix:更改订单发货类型为无需发货更改发货类型为等待自提,等待用户自提后更改订单状态为已完成
371 374 @Override
  375 + @Transactional(rollbackFor = Exception.class)
372 376 public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) {
373 377 // 校验并获得交易订单(可发货)
374 378 TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId());
375   - // TODO 判断发货类型,根据发货类型发货
376   - DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId());
377   - if (deliveryExpress == null) {
378   - throw exception(EXPRESS_NOT_EXISTS);
  379 +
  380 + TradeOrderDO tradeOrderDO = new TradeOrderDO();
  381 + List<TradeOrderDeliveryDO> deliveryDOs = new ArrayList<>();
  382 + /* TODO
  383 + * fix: 首先需要店铺设置配送方式如: 自提 、配送、物流-配送、物流-配送-自提、商家配送
  384 + * 1.如果店铺有设置配送方式用户只填写收货地址的情况下店家后台自己选择配送方式
  385 + * 2.如果店铺只支持到店自提那么下单后默认发货不需要物流
  386 + * 3.如果店铺支持 物流-配送-自提 的情况下后台不需要选择配送方式按前端用户选择的配送方式发货即可
  387 + */
  388 + // 判断发货类型
  389 + // 快递发货
  390 + if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.EXPRESS.getMode())) {
  391 + deliveryDOs = express(order, deliveryReqVO);
  392 + tradeOrderDO.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo());
  393 + }
  394 + // 用户自提
  395 + if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.PICK_UP.getMode())) {
  396 + deliveryDOs = pickUp(order, deliveryReqVO);
  397 + // 重置一下确保快递公司和快递单号为空
  398 + tradeOrderDO.setLogisticsId(null).setLogisticsNo("");
  399 + }
  400 + // TODO 芋艿:如果无需发货,需要怎么存储?
  401 + if (ObjectUtil.equal(deliveryReqVO.getType(), DeliveryTypeEnum.NULL.getMode())) {
  402 + // TODO 情况一:正常走发货逻辑和用户自提有点像 不同点:不需要自提门店只需要用户确认收货
  403 + // TODO 情况二:用户下单付款后直接确认收货或等待用户确认收货
379 404 }
380 405  
381 406 // 更新 TradeOrderDO 状态为已发货,等待收货
382   - int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(),
383   - new TradeOrderDO().setStatus(TradeOrderStatusEnum.DELIVERED.getStatus())
384   - .setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo())
385   - .setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()));
  407 + tradeOrderDO.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus())
  408 + .setDeliveryStatus(TradeOrderDeliveryStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now());
  409 + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), tradeOrderDO);
386 410 if (updateCount == 0) {
387 411 throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED);
388 412 }
389   -
  413 + // 发货成功记录发货表
  414 + orderDeliveryMapper.insertBatch(deliveryDOs);
390 415 // TODO 芋艿:发送订单变化的消息
391 416  
392   - // TODO 芋艿:发送站内信 fix
  417 + // 发送站内信
393 418 // 1、构造消息
394 419 Map<String, Object> msgMap = new HashMap<>();
395 420 msgMap.put("orderId", deliveryReqVO.getId());
... ... @@ -400,16 +425,59 @@ public class TradeOrderServiceImpl implements TradeOrderService {
400 425 .setUserId(userId)
401 426 .setTemplateCode("order_delivery")
402 427 .setTemplateParams(msgMap));
403   - // TODO 芋艿:OrderLog
404 428  
405   - // TODO 设计:like:是否要单独一个 delivery 发货单表??? fix: 确实单独一张发货表就能解决整单发货和单独发货的问题
406   - // TODO 设计:niu:要不要支持一个订单下,多个 order item 单独发货,类似有赞
  429 + // TODO 芋艿:OrderLog
407 430 // TODO 设计:lili:是不是发货后,才支持售后?
408 431 }
409 432  
  433 + private List<TradeOrderDeliveryDO> express(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {
  434 + // 校验快递公司
  435 + DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId());
  436 + if (deliveryExpress == null) {
  437 + throw exception(EXPRESS_NOT_EXISTS);
  438 + }
  439 + // 校验发货商品
  440 + validateDeliveryOrderItem(order, deliveryReqVO);
  441 + // 创建发货记录
  442 + return TradeOrderConvert.INSTANCE.covert(order, deliveryReqVO);
  443 + }
  444 +
  445 + private List<TradeOrderDeliveryDO> pickUp(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {
  446 + // TODO 校验自提门店是否存在
  447 + // 重置一下确保快递公司和快递单号为空
  448 + deliveryReqVO.setLogisticsId(null);
  449 + deliveryReqVO.setLogisticsNo("");
  450 + // 校验发货商品
  451 + validateDeliveryOrderItem(order, deliveryReqVO);
  452 + // 创建发货记录
  453 + return TradeOrderConvert.INSTANCE.covert(order, deliveryReqVO);
  454 + }
  455 +
  456 + private void validateDeliveryOrderItem(TradeOrderDO order, TradeOrderDeliveryReqVO deliveryReqVO) {
  457 + // TODO 设计:like:是否要单独一个 delivery 发货单表??? fix: 多商品可分开单独发货,添加 trade_order_delivery 交易订单发货日志表关联发货所选订单项设置物流单号
  458 + // TODO 设计:niu:要不要支持一个订单下,多个 order item 单独发货,类似有赞 fix
  459 + // 校验发货商品
  460 + if (CollUtil.isEmpty(deliveryReqVO.getOrderItemIds())) {
  461 + throw exception(ORDER_DELIVERY_FAILED_ITEMS_NOT_EMPTY);
  462 + }
  463 + // 校验发货商品是否存在
  464 + List<TradeOrderItemDO> orderItemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId());
  465 + Set<Long> itemIds = convertSet(orderItemDOs, TradeOrderItemDO::getId);
  466 + if (!itemIds.containsAll(deliveryReqVO.getOrderItemIds())) {
  467 + throw exception(ORDER_DELIVERY_FAILED_ITEM_NOT_EXISTS);
  468 + }
  469 + // 校验所选订单项是否存在有已发货的
  470 + List<TradeOrderDeliveryDO> deliveryDOList = orderDeliveryMapper.selsectListByOrderIdAndItemIds(order.getId(), deliveryReqVO.getOrderItemIds());
  471 + if (CollUtil.isNotEmpty(deliveryDOList)) {
  472 + HashSet<Long> hashSet = CollUtil.newHashSet(deliveryReqVO.getOrderItemIds());
  473 + hashSet.retainAll(convertSet(deliveryDOList, TradeOrderDeliveryDO::getOrderItemId));
  474 + throw exception(ORDER_DELIVERY_FAILED_ITEM_ALREADY_DELIVERY);
  475 + }
  476 + }
  477 +
410 478 /**
411 479 * 校验交易订单满足被发货的条件
412   - * <p>
  480 + *
413 481 * 1. 交易订单未发货
414 482 *
415 483 * @param id 交易订单编号
... ... @@ -432,7 +500,10 @@ public class TradeOrderServiceImpl implements TradeOrderService {
432 500 }
433 501 // 校验订单拼团是否成功
434 502 if (ObjectUtil.equal(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) {
435   -
  503 + // TODO 用户 ID 使用当前登录用户的还是订单保存的?
  504 + if (ObjectUtil.notEqual(combinationApi.getRecordStatus(order.getUserId(), order.getId()), CombinationRecordStatusEnum.SUCCESS.getStatus())) {
  505 + throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS);
  506 + }
436 507 }
437 508 // TODO puhui999: 校验订单砍价是否成功
438 509 return order;
... ... @@ -466,7 +537,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
466 537  
467 538 /**
468 539 * 校验交易订单满足可售货的条件
469   - * <p>
  540 + *
470 541 * 1. 交易订单待收货
471 542 *
472 543 * @param userId 用户编号
... ...