From a159a983a2da801b654c84f74f34645e073902fd Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 15 Aug 2023 21:19:13 +0800 Subject: [PATCH] 订单: 1. 拆分读写 OrderService,避免单 Service 逻辑过重。 --- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java | 6 +++--- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java | 17 ++++++++++------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java | 34 +++++++++++++++++----------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java | 3 ++- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java | 23 +++++++++++++---------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java | 190 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java | 682 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java | 598 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java | 4 ++-- yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java | 314 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java | 314 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 1226 insertions(+), 1228 deletions(-) delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java delete mode 100644 yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java index 1909f71..7895386 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.trade.api.order; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -20,12 +20,12 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_ITEM_ public class TradeOrderApiImpl implements TradeOrderApi { @Resource - private TradeOrderService tradeOrderService; + private TradeOrderQueryService tradeOrderQueryService; @Override public Long validateOrder(Long userId, Long orderItemId) { // 校验订单项,订单项存在订单就存在 - TradeOrderItemDO item = tradeOrderService.getOrderItem(userId, orderItemId); + TradeOrderItemDO item = tradeOrderQueryService.getOrderItem(userId, orderItemId); if (item == null) { throw exception(ORDER_ITEM_NOT_FOUND); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java index 6dc8f2b..786be10 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/TradeOrderController.java @@ -14,7 +14,8 @@ import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReq import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -39,7 +40,9 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti public class TradeOrderController { @Resource - private TradeOrderService tradeOrderService; + private TradeOrderUpdateService tradeOrderUpdateService; + @Resource + private TradeOrderQueryService tradeOrderQueryService; @Resource private ProductPropertyValueApi productPropertyValueApi; @@ -51,7 +54,7 @@ public class TradeOrderController { @PreAuthorize("@ss.hasPermission('trade:order:query')") public CommonResult> getOrderPage(TradeOrderPageReqVO reqVO) { // 查询订单 - PageResult pageResult = tradeOrderService.getOrderPage(reqVO); + PageResult pageResult = tradeOrderQueryService.getOrderPage(reqVO); if (CollUtil.isEmpty(pageResult.getList())) { return success(PageResult.empty()); } @@ -59,7 +62,7 @@ public class TradeOrderController { // 查询用户信息 Map userMap = memberUserApi.getUserMap(convertSet(pageResult.getList(), TradeOrderDO::getUserId));; // 查询订单项 - List orderItems = tradeOrderService.getOrderItemListByOrderId( + List orderItems = tradeOrderQueryService.getOrderItemListByOrderId( convertSet(pageResult.getList(), TradeOrderDO::getId)); // 查询商品属性 List propertyValueDetails = productPropertyValueApi @@ -74,9 +77,9 @@ public class TradeOrderController { @PreAuthorize("@ss.hasPermission('trade:order:query')") public CommonResult getOrderDetail(@RequestParam("id") Long id) { // 查询订单 - TradeOrderDO order = tradeOrderService.getOrder(id); + TradeOrderDO order = tradeOrderQueryService.getOrder(id); // 查询订单项 - List orderItems = tradeOrderService.getOrderItemListByOrderId(id); + List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id); // 查询商品属性 List propertyValueDetails = productPropertyValueApi .getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems)); @@ -90,7 +93,7 @@ public class TradeOrderController { @Operation(summary = "发货订单") @PreAuthorize("@ss.hasPermission('trade:order:delivery')") public CommonResult deliveryOrder(@RequestBody TradeOrderDeliveryReqVO deliveryReqVO) { - tradeOrderService.deliveryOrder(getLoginUserId(), deliveryReqVO); + tradeOrderUpdateService.deliveryOrder(getLoginUserId(), deliveryReqVO); return success(true); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java index 2de3527..6456db1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java @@ -17,7 +17,7 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; import com.google.common.collect.Maps; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -44,7 +44,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti public class AppTradeOrderController { @Resource - private TradeOrderService tradeOrderService; + private TradeOrderUpdateService tradeOrderUpdateService; @Resource private TradeOrderQueryService tradeOrderQueryService; @Resource @@ -60,21 +60,21 @@ public class AppTradeOrderController { @Operation(summary = "获得订单结算信息") @PreAuthenticated public CommonResult settlementOrder(@Valid AppTradeOrderSettlementReqVO settlementReqVO) { - return success(tradeOrderService.settlementOrder(getLoginUserId(), settlementReqVO)); + return success(tradeOrderUpdateService.settlementOrder(getLoginUserId(), settlementReqVO)); } @PostMapping("/create") @Operation(summary = "创建订单") @PreAuthenticated public CommonResult createOrder(@RequestBody AppTradeOrderCreateReqVO createReqVO) { - TradeOrderDO order = tradeOrderService.createOrder(getLoginUserId(), getClientIP(), createReqVO); + TradeOrderDO order = tradeOrderUpdateService.createOrder(getLoginUserId(), getClientIP(), createReqVO); return success(new AppTradeOrderCreateRespVO().setId(order.getId()).setPayOrderId(order.getPayOrderId())); } @PostMapping("/update-paid") @Operation(summary = "更新订单为已支付") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob public CommonResult updateOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) { - tradeOrderService.updateOrderPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()), + tradeOrderUpdateService.updateOrderPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()), notifyReqDTO.getPayOrderId()); return success(true); } @@ -84,13 +84,13 @@ public class AppTradeOrderController { @Parameter(name = "id", description = "交易订单编号") public CommonResult getOrder(@RequestParam("id") Long id) { // 查询订单 - TradeOrderDO order = tradeOrderService.getOrder(getLoginUserId(), id); + TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id); if (order == null) { return success(null); } // 查询订单项 - List orderItems = tradeOrderService.getOrderItemListByOrderId(order.getId()); + List orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId()); // 查询商品属性 List propertyValueDetails = productPropertyValueApi .getPropertyValueDetailList(TradeOrderConvert.INSTANCE.convertPropertyValueIds(orderItems)); @@ -114,9 +114,9 @@ public class AppTradeOrderController { @Operation(summary = "获得交易订单分页") public CommonResult> getOrderPage(AppTradeOrderPageReqVO reqVO) { // 查询订单 - PageResult pageResult = tradeOrderService.getOrderPage(getLoginUserId(), reqVO); + PageResult pageResult = tradeOrderQueryService.getOrderPage(getLoginUserId(), reqVO); // 查询订单项 - List orderItems = tradeOrderService.getOrderItemListByOrderId( + List orderItems = tradeOrderQueryService.getOrderItemListByOrderId( convertSet(pageResult.getList(), TradeOrderDO::getId)); // 查询商品属性 List propertyValueDetails = productPropertyValueApi @@ -130,18 +130,18 @@ public class AppTradeOrderController { public CommonResult> getOrderCount() { Map orderCount = Maps.newLinkedHashMapWithExpectedSize(5); // 全部 - orderCount.put("allCount", tradeOrderService.getOrderCount(getLoginUserId(), null, null)); + orderCount.put("allCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), null, null)); // 待付款(未支付) - orderCount.put("unpaidCount", tradeOrderService.getOrderCount(getLoginUserId(), + orderCount.put("unpaidCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.UNPAID.getStatus(), null)); // 待发货 - orderCount.put("undeliveredCount", tradeOrderService.getOrderCount(getLoginUserId(), + orderCount.put("undeliveredCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.UNDELIVERED.getStatus(), null)); // 待收货 - orderCount.put("deliveredCount", tradeOrderService.getOrderCount(getLoginUserId(), + orderCount.put("deliveredCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.DELIVERED.getStatus(), null)); // 待评价 - orderCount.put("uncommentedCount", tradeOrderService.getOrderCount(getLoginUserId(), + orderCount.put("uncommentedCount", tradeOrderQueryService.getOrderCount(getLoginUserId(), TradeOrderStatusEnum.COMPLETED.getStatus(), false)); return success(orderCount); } @@ -150,7 +150,7 @@ public class AppTradeOrderController { @Operation(summary = "确认交易订单收货") @Parameter(name = "id", description = "交易订单编号") public CommonResult takeOrder(@RequestParam("id") Long id) { - tradeOrderService.receiveOrder(getLoginUserId(), id); + tradeOrderUpdateService.receiveOrder(getLoginUserId(), id); return success(true); } @@ -176,14 +176,14 @@ public class AppTradeOrderController { @Operation(summary = "获得交易订单项") @Parameter(name = "id", description = "交易订单项编号") public CommonResult getOrderItem(@RequestParam("id") Long id) { - TradeOrderItemDO item = tradeOrderService.getOrderItem(getLoginUserId(), id); + TradeOrderItemDO item = tradeOrderQueryService.getOrderItem(getLoginUserId(), id); return success(TradeOrderConvert.INSTANCE.convert03(item)); } @PostMapping("/item/create-comment") @Operation(summary = "创建交易订单项的评价") public CommonResult createOrderItemComment(@RequestBody AppTradeOrderItemCommentCreateReqVO createReqVO) { - return success(tradeOrderService.createOrderItemComment(createReqVO)); + return success(tradeOrderUpdateService.createOrderItemComment(getLoginUserId(), createReqVO)); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java index 553bd56..ee8b8b1 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/order/TradeOrderItemMapper.java @@ -31,9 +31,10 @@ public interface TradeOrderItemMapper extends BaseMapperX { .eq(TradeOrderItemDO::getSkuId, skuIds)); } - default TradeOrderItemDO selectOrderItemByIdAndUserId(Long orderItemId, Long loginUserId) { + default TradeOrderItemDO selectByIdAndUserId(Long orderItemId, Long loginUserId) { return selectOne(new LambdaQueryWrapperX() .eq(TradeOrderItemDO::getId, orderItemId) .eq(TradeOrderItemDO::getUserId, loginUserId)); } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java index ab94fb7..f7c93d5 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java @@ -27,7 +27,8 @@ import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @@ -54,7 +55,9 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSaleLogService { @Resource - private TradeOrderService tradeOrderService; + private TradeOrderUpdateService tradeOrderUpdateService; + @Resource + private TradeOrderQueryService tradeOrderQueryService; @Resource private TradeAfterSaleMapper tradeAfterSaleMapper; @@ -92,7 +95,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa */ private TradeOrderItemDO validateOrderItemApplicable(Long userId, AppTradeAfterSaleCreateReqVO createReqVO) { // 校验订单项存在 - TradeOrderItemDO orderItem = tradeOrderService.getOrderItem(userId, createReqVO.getOrderItemId()); + TradeOrderItemDO orderItem = tradeOrderQueryService.getOrderItem(userId, createReqVO.getOrderItemId()); if (orderItem == null) { throw exception(ORDER_ITEM_NOT_FOUND); } @@ -108,7 +111,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa } // 校验订单存在 - TradeOrderDO order = tradeOrderService.getOrder(userId, orderItem.getOrderId()); + TradeOrderDO order = tradeOrderQueryService.getOrder(userId, orderItem.getOrderId()); if (order == null) { throw exception(ORDER_NOT_FOUND); } @@ -136,7 +139,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa afterSale.setNo(RandomUtil.randomString(10)); // TODO 芋艿:优化 no 生成逻辑 afterSale.setStatus(TradeAfterSaleStatusEnum.APPLY.getStatus()); // 标记是售中还是售后 - TradeOrderDO order = tradeOrderService.getOrder(orderItem.getUserId(), orderItem.getOrderId()); + TradeOrderDO order = tradeOrderQueryService.getOrder(orderItem.getUserId(), orderItem.getOrderId()); afterSale.setOrderNo(order.getNo()); // 记录 orderNo 订单流水,方便后续检索 afterSale.setType(TradeOrderStatusEnum.isCompleted(order.getStatus()) ? TradeAfterSaleTypeEnum.AFTER_SALE.getType() : TradeAfterSaleTypeEnum.IN_SALE.getType()); @@ -144,7 +147,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa tradeAfterSaleMapper.insert(afterSale); // 更新交易订单项的售后状态 - tradeOrderService.updateOrderItemAfterSaleStatus(orderItem.getId(), + tradeOrderUpdateService.updateOrderItemAfterSaleStatus(orderItem.getId(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), null); @@ -196,7 +199,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa // TODO 发送售后消息 // 更新交易订单项的售后状态为【未申请】 - tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), + tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null); } @@ -291,7 +294,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa // TODO 发送售后消息 // 更新交易订单项的售后状态为【未申请】 - tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), + tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null); } @@ -339,7 +342,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa // TODO 发送售后消息 // 更新交易订单项的售后状态为【已完成】 - tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), + tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus(), afterSale.getRefundPrice()); } @@ -381,7 +384,7 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa // TODO 发送售后消息 // 更新交易订单项的售后状态为【未申请】 - tradeOrderService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), + tradeOrderUpdateService.updateOrderItemAfterSaleStatus(afterSale.getOrderItemId(), TradeOrderItemAfterSaleStatusEnum.APPLY.getStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus(), null); } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java index 8ef513c..0c03802 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryService.java @@ -1,9 +1,17 @@ package cn.iocoder.yudao.module.trade.service.order; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO; +import java.util.Collection; import java.util.List; +import static java.util.Collections.singleton; + /** * 交易订单【读】 Service 接口 * @@ -11,6 +19,52 @@ import java.util.List; */ public interface TradeOrderQueryService { + // =================== Order =================== + + /** + * 获得指定编号的交易订单 + * + * @param id 交易订单编号 + * @return 交易订单 + */ + TradeOrderDO getOrder(Long id); + + /** + * 获得指定用户,指定的交易订单 + * + * @param userId 用户编号 + * @param id 交易订单编号 + * @return 交易订单 + */ + TradeOrderDO getOrder(Long userId, Long id); + + /** + * 【管理员】获得交易订单分页 + * + * @param reqVO 分页请求 + * @return 交易订单 + */ + PageResult getOrderPage(TradeOrderPageReqVO reqVO); + + /** + * 【会员】获得交易订单分页 + * + * @param userId 用户编号 + * @param reqVO 分页请求 + * @return 交易订单 + */ + PageResult getOrderPage(Long userId, AppTradeOrderPageReqVO reqVO); + + /** + * 【会员】获得交易订单数量 + * + * @param userId 用户编号 + * @param status 订单状态。如果为空,则不进行筛选 + * @param commonStatus 评价状态。如果为空,则不进行筛选 + * @return 订单数量 + */ + Long getOrderCount(Long userId, Integer status, Boolean commonStatus); + /** * 获得订单的物流轨迹 * @@ -20,4 +74,41 @@ public interface TradeOrderQueryService { */ List getExpressTrackList(Long id, Long userId); + // =================== Order Item =================== + + /** + * 获得指定用户,指定的交易订单项 + * + * @param userId 用户编号 + * @param itemId 交易订单项编号 + * @return 交易订单项 + */ + TradeOrderItemDO getOrderItem(Long userId, Long itemId); + + /** + * 根据交易订单项编号数组,查询交易订单项 + * + * @param ids 交易订单项编号数组 + * @return 交易订单项数组 + */ + List getOrderItemList(Collection ids); + + /** + * 根据交易订单编号,查询交易订单项 + * + * @param orderId 交易订单编号 + * @return 交易订单项数组 + */ + default List getOrderItemListByOrderId(Long orderId) { + return getOrderItemListByOrderId(singleton(orderId)); + } + + /** + * 根据交易订单编号数组,查询交易订单项 + * + * @param orderIds 交易订单编号数组 + * @return 交易订单项数组 + */ + List getOrderItemListByOrderId(Collection orderIds); + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java index 20dc074..9fb2384 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java @@ -1,7 +1,17 @@ package cn.iocoder.yudao.module.trade.service.order; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClientFactory; import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO; @@ -10,10 +20,10 @@ import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; import org.springframework.stereotype.Service; import javax.annotation.Resource; -import java.util.Collections; -import java.util.List; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_NOT_EXISTS; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND; @@ -30,10 +40,64 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { @Resource private TradeOrderMapper tradeOrderMapper; + @Resource + private TradeOrderItemMapper tradeOrderItemMapper; @Resource private DeliveryExpressService deliveryExpressService; + @Resource + private MemberUserApi memberUserApi; + + // =================== Order =================== + + @Override + public TradeOrderDO getOrder(Long id) { + return tradeOrderMapper.selectById(id); + } + + @Override + public TradeOrderDO getOrder(Long userId, Long id) { + TradeOrderDO order = tradeOrderMapper.selectById(id); + if (order != null + && ObjectUtil.notEqual(order.getUserId(), userId)) { + return null; + } + return order; + } + + @Override + public PageResult getOrderPage(TradeOrderPageReqVO reqVO) { + // 获得 userId 相关的查询 + Set userIds = new HashSet<>(); + if (StrUtil.isNotEmpty(reqVO.getUserMobile())) { + MemberUserRespDTO user = memberUserApi.getUserByMobile(reqVO.getUserMobile()); + if (user == null) { // 没查询到用户,说明肯定也没他的订单 + return new PageResult<>(); + } + userIds.add(user.getId()); + } + if (StrUtil.isNotEmpty(reqVO.getUserNickname())) { + List users = memberUserApi.getUserListByNickname(reqVO.getUserNickname()); + if (CollUtil.isEmpty(users)) { // 没查询到用户,说明肯定也没他的订单 + return new PageResult<>(); + } + userIds.addAll(convertSet(users, MemberUserRespDTO::getId)); + } + // 分页查询 + return tradeOrderMapper.selectPage(reqVO, userIds); + } + + @Override + public PageResult getOrderPage(Long userId, AppTradeOrderPageReqVO reqVO) { + return tradeOrderMapper.selectPage(reqVO, userId); + } + + @Override + public Long getOrderCount(Long userId, Integer status, Boolean commentStatus) { + return tradeOrderMapper.selectCountByUserIdAndStatus(userId, status, commentStatus); + } + @Override public List getExpressTrackList(Long id, Long userId) { // 查询订单 @@ -57,4 +121,29 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { .setPhone(order.getReceiverMobile())); } + // =================== Order Item =================== + + @Override + public TradeOrderItemDO getOrderItem(Long userId, Long itemId) { + TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(itemId); + if (orderItem != null + && ObjectUtil.notEqual(orderItem.getUserId(), userId)) { + return null; + } + return orderItem; + } + + @Override + public List getOrderItemList(Collection ids) { + return tradeOrderItemMapper.selectBatchIds(ids); + } + + @Override + public List getOrderItemListByOrderId(Collection orderIds) { + if (CollUtil.isEmpty(orderIds)) { + return Collections.emptyList(); + } + return tradeOrderItemMapper.selectListByOrderId(orderIds); + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java deleted file mode 100644 index c61ca8a..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java +++ /dev/null @@ -1,190 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.order; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; - -import java.util.Collection; -import java.util.List; - -import static java.util.Collections.singleton; - -/** - * 交易订单 Service 接口 - * - * @author LeeYan9 - * @since 2022-08-26 - */ -public interface TradeOrderService { - - // =================== Order =================== - - /** - * 获得订单结算信息 - * - * @param userId 登录用户 - * @param settlementReqVO 订单结算请求 - * @return 订单结算结果 - */ - AppTradeOrderSettlementRespVO settlementOrder(Long userId, AppTradeOrderSettlementReqVO settlementReqVO); - - /** - * 【会员】创建交易订单 - * - * @param userId 登录用户 - * @param userIp 用户 IP 地址 - * @param createReqVO 创建交易订单请求模型 - * @return 交易订单的 - */ - TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO); - - /** - * 更新交易订单已支付 - * - * @param id 交易订单编号 - * @param payOrderId 支付订单编号 - */ - void updateOrderPaid(Long id, Long payOrderId); - - /** - * 【管理员】发货交易订单 - * - * @param userId 管理员编号 - * @param deliveryReqVO 发货请求 - */ - void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO); - - /** - * 【会员】收货交易订单 - * - * @param userId 用户编号 - * @param id 订单编号 - */ - void receiveOrder(Long userId, Long id); - - /** - * 获得指定编号的交易订单 - * - * @param id 交易订单编号 - * @return 交易订单 - */ - TradeOrderDO getOrder(Long id); - - /** - * 获得指定用户,指定的交易订单 - * - * @param userId 用户编号 - * @param id 交易订单编号 - * @return 交易订单 - */ - TradeOrderDO getOrder(Long userId, Long id); - - /** - * 【管理员】获得交易订单分页 - * - * @param reqVO 分页请求 - * @return 交易订单 - */ - PageResult getOrderPage(TradeOrderPageReqVO reqVO); - - /** - * 【会员】获得交易订单分页 - * - * @param userId 用户编号 - * @param reqVO 分页请求 - * @return 交易订单 - */ - PageResult getOrderPage(Long userId, AppTradeOrderPageReqVO reqVO); - - /** - * 【会员】获得交易订单数量 - * - * @param userId 用户编号 - * @param status 订单状态。如果为空,则不进行筛选 - * @param commonStatus 评价状态。如果为空,则不进行筛选 - * @return 订单数量 - */ - Long getOrderCount(Long userId, Integer status, Boolean commonStatus); - - // =================== Order Item =================== - - /** - * 获得指定用户,指定的交易订单项 - * - * @param userId 用户编号 - * @param itemId 交易订单项编号 - * @return 交易订单项 - */ - TradeOrderItemDO getOrderItem(Long userId, Long itemId); - - /** - * 更新交易订单项的售后状态 - * - * @param id 交易订单项编号 - * @param oldAfterSaleStatus 当前售后状态;如果不符,更新后会抛出异常 - * @param newAfterSaleStatus 目标售后状态 - * @param refundPrice 退款金额;当订单项退款成功时,必须传递该值 - */ - void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, - Integer newAfterSaleStatus, Integer refundPrice); - - /** - * 根据交易订单项编号数组,查询交易订单项 - * - * @param ids 交易订单项编号数组 - * @return 交易订单项数组 - */ - List getOrderItemList(Collection ids); - - /** - * 根据交易订单编号,查询交易订单项 - * - * @param orderId 交易订单编号 - * @return 交易订单项数组 - */ - default List getOrderItemListByOrderId(Long orderId) { - return getOrderItemListByOrderId(singleton(orderId)); - } - - /** - * 根据交易订单编号数组,查询交易订单项 - * - * @param orderIds 交易订单编号数组 - * @return 交易订单项数组 - */ - List getOrderItemListByOrderId(Collection orderIds); - - /** - * 得到订单项通过 订单项 id 和用户 id - * - * @param orderItemId 订单项 id - * @param loginUserId 登录用户 id - * @return 得到订单项 - */ - TradeOrderItemDO getOrderItemByIdAndUserId(Long orderItemId, Long loginUserId); - - /** - * 得到订单通过 id 和 用户 id - * - * @param orderId 订单 id - * @param loginUserId 登录用户 id - * @return 得到订单 - */ - TradeOrderDO getOrderByIdAndUserId(Long orderId, Long loginUserId); - - /** - * 创建订单项的评论 - * - * @param createReqVO 创建请求 - * @return 得到评价 id - */ - Long createOrderItemComment(AppTradeOrderItemCommentCreateReqVO createReqVO); - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java deleted file mode 100644 index 377e7a9..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java +++ /dev/null @@ -1,682 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.order; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.enums.TerminalEnum; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.module.member.api.address.AddressApi; -import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.member.api.user.MemberUserApi; -import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; -import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; -import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; -import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; -import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; -import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; -import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; -import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; -import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; -import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; -import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; -import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; -import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; -import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; -import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; -import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; -import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; -import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; -import cn.iocoder.yudao.module.trade.enums.order.*; -import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; -import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; -import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; -import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; -import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO; -import cn.iocoder.yudao.module.trade.service.price.TradePriceService; -import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; -import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.annotation.Resource; -import java.time.LocalDateTime; -import java.util.*; - -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; - -/** - * 交易订单 Service 实现类 - * - * @author LeeYan9 - * @since 2022-08-26 - */ -@Service -@Slf4j -public class TradeOrderServiceImpl implements TradeOrderService { - - @Resource - private TradeOrderMapper tradeOrderMapper; - @Resource - private TradeOrderItemMapper tradeOrderItemMapper; - - @Resource - private TradeCartService tradeCartService; - @Resource - private TradePriceService tradePriceService; - @Resource - private DeliveryExpressService deliveryExpressService; - - @Resource - private ProductSkuApi productSkuApi; - @Resource - private PayOrderApi payOrderApi; - @Resource - private AddressApi addressApi; - @Resource - private CouponApi couponApi; - @Resource - private MemberUserApi memberUserApi; - @Resource - private ProductCommentApi productCommentApi; - @Resource - private TradeMessageService tradeMessageService; - @Resource - private TradeOrderProperties tradeOrderProperties; - - @Resource - private CombinationRecordApi combinationRecordApi; - - @Resource - private BargainRecordApi bargainRecordApi; - - // =================== Order =================== - - @Override - public AppTradeOrderSettlementRespVO settlementOrder(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) { - // 1. 获得收货地址 - AddressRespDTO address = getAddress(userId, settlementReqVO.getAddressId()); - if (address != null) { - settlementReqVO.setAddressId(address.getId()); - } - - // 2. 计算价格 - TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, settlementReqVO); - - // 3. 拼接返回 - return TradeOrderConvert.INSTANCE.convert(calculateRespBO, address); - } - - /** - * 获得用户地址 - * - * @param userId 用户编号 - * @param addressId 地址编号 - * @return 地址 - */ - private AddressRespDTO getAddress(Long userId, Long addressId) { - if (addressId != null) { - return addressApi.getAddress(addressId, userId); - } - return addressApi.getDefaultAddress(userId); - } - - /** - * 计算订单价格 - * - * @param userId 用户编号 - * @param settlementReqVO 结算信息 - * @return 订单价格 - */ - private TradePriceCalculateRespBO calculatePrice(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) { - // 1. 如果来自购物车,则获得购物车的商品 - List cartList = tradeCartService.getCartList(userId, - convertSet(settlementReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId)); - - // 2. 计算价格 - TradePriceCalculateReqBO calculateReqBO = TradeOrderConvert.INSTANCE.convert(userId, settlementReqVO, cartList); - calculateReqBO.getItems().forEach(item -> Assert.isTrue(item.getSelected(), // 防御性编程,保证都是选中的 - "商品({}) 未设置为选中", item.getSkuId())); - return tradePriceService.calculatePrice(calculateReqBO); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) { - // 2. 价格计算 - TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO); - // 3.1 插入 TradeOrderDO 订单 - TradeOrderDO order = createTradeOrder(userId, userIp, createReqVO, calculateRespBO); - // 3.2 插入 TradeOrderItemDO 订单项 - List orderItems = createTradeOrderItems(order, calculateRespBO); - // 订单创建完后的逻辑 - afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO); - // 3.3 校验订单类型 - // 拼团 - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { - MemberUserRespDTO user = memberUserApi.getUser(userId); - List recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId()); - // TODO 拼团一次应该只能选择一种规格的商品 - TradeOrderItemDO orderItemDO = orderItems.get(0); - if (CollUtil.isNotEmpty(recordRespDTOS)) { - List skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); - List tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS, - CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); - combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(), - CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount()); - } - - combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user)); - } - // TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除 - if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) { - - } - - // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! - return order; - } - - /** - * 校验收件地址是否存在 - * - * @param userId 用户编号 - * @param addressId 收件地址编号 - * @return 收件地址 - */ - private AddressRespDTO validateAddress(Long userId, Long addressId) { - AddressRespDTO address = addressApi.getAddress(addressId, userId); - if (address == null) { - throw exception(ErrorCodeConstants.ORDER_CREATE_ADDRESS_NOT_FOUND); - } - return address; - } - - private TradeOrderDO createTradeOrder(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO, - TradePriceCalculateRespBO calculateRespBO) { - // 用户选择物流配送的时候才需要填写收货地址 - AddressRespDTO address = new AddressRespDTO(); - if (Objects.equals(createReqVO.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getMode())) { - // 用户收件地址的校验 - address = validateAddress(userId, createReqVO.getAddressId()); - } - TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, calculateRespBO, address); - order.setType(validateActivity(createReqVO)); - order.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @LeeYan9: 思考下, 怎么生成好点哈; 这个是会展示给用户的; - order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); - order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); - order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum)); - order.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源? - // 支付信息 - order.setAdjustPrice(0).setPayStatus(false); - // 物流信息 - order.setDeliveryType(createReqVO.getDeliveryType()); - // 退款信息 - order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0); - tradeOrderMapper.insert(order); - return order; - } - - /** - * 校验活动,并返回订单类型 - * - * @param createReqVO 请求参数 - * @return 订单类型 - */ - private Integer validateActivity(AppTradeOrderCreateReqVO createReqVO) { - if (createReqVO.getSeckillActivityId() != null) { - return TradeOrderTypeEnum.SECKILL.getType(); - } - if (createReqVO.getCombinationActivityId() != null) { - return TradeOrderTypeEnum.COMBINATION.getType(); - } - // TODO 砍价敬请期待 - return TradeOrderTypeEnum.NORMAL.getType(); - } - - private List createTradeOrderItems(TradeOrderDO tradeOrderDO, TradePriceCalculateRespBO calculateRespBO) { - List orderItems = TradeOrderConvert.INSTANCE.convertList(tradeOrderDO, calculateRespBO); - tradeOrderItemMapper.insertBatch(orderItems); - return orderItems; - } - - /** - * 执行创建完创建完订单后的逻辑 - * - * 例如说:优惠劵的扣减、积分的扣减、支付单的创建等等 - * - * @param userId 用户编号 - * @param createReqVO 创建订单请求 - * @param tradeOrderDO 交易订单 - * @param calculateRespBO 订单价格计算结果 - */ - private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, - TradeOrderDO tradeOrderDO, List orderItems, - TradePriceCalculateRespBO calculateRespBO) { - // 下单时扣减商品库存 - productSkuApi.updateSkuStock(new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(orderItems))); - - // 删除购物车商品 TODO 芋艿:待实现 - - // 扣减积分,抵扣金额 TODO 芋艿:待实现 - - // 有使用优惠券时更新 - if (createReqVO.getCouponId() != null) { - couponApi.useCoupon(new CouponUseReqDTO().setId(createReqVO.getCouponId()).setUserId(userId) - .setOrderId(tradeOrderDO.getId())); - } - - // 生成预支付 - createPayOrder(tradeOrderDO, orderItems, calculateRespBO); - - // 增加订单日志 TODO 芋艿:待实现 - } - - private void createPayOrder(TradeOrderDO order, List orderItems, TradePriceCalculateRespBO calculateRespBO) { - // 创建支付单,用于后续的支付 - PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert( - order, orderItems, calculateRespBO, tradeOrderProperties); - Long payOrderId = payOrderApi.createOrder(payOrderCreateReqDTO); - - // 更新到交易单上 - tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setPayOrderId(payOrderId)); - order.setPayOrderId(payOrderId); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateOrderPaid(Long id, Long payOrderId) { - // 校验并获得交易订单(可支付) - KeyValue orderResult = validateOrderPayable(id, payOrderId); - TradeOrderDO order = orderResult.getKey(); - PayOrderRespDTO payOrder = orderResult.getValue(); - - // 更新 TradeOrderDO 状态为已支付,等待发货 - int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), - new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayStatus(true) - .setPayTime(LocalDateTime.now()).setPayChannelCode(payOrder.getChannelCode())); - if (updateCount == 0) { - throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); - } - // 校验活动 - // 1、拼团活动 - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { - // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 - combinationRecordApi.updateCombinationRecordStatus(new CombinationRecordUpdateStatusReqDTO().setUserId(order.getUserId()) - .setOrderId(order.getId()).setStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()).setStartTime(LocalDateTime.now())); - } - // TODO 芋艿:发送订单变化的消息 - - // TODO 芋艿:发送站内信 - - // TODO 芋艿:OrderLog - } - - /** - * 校验交易订单满足被支付的条件 - * - * 1. 交易订单未支付 - * 2. 支付单已支付 - * - * @param id 交易订单编号 - * @param payOrderId 支付订单编号 - * @return 交易订单 - */ - private KeyValue validateOrderPayable(Long id, Long payOrderId) { - // 校验订单是否存在 - TradeOrderDO order = tradeOrderMapper.selectById(id); - if (order == null) { - throw exception(ORDER_NOT_FOUND); - } - // 校验订单未支付 - if (!TradeOrderStatusEnum.isUnpaid(order.getStatus()) || order.getPayStatus()) { - log.error("[validateOrderPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]", - id, JsonUtils.toJsonString(order)); - throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); - } - // 校验支付订单匹配 - if (ObjectUtil.notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号 - log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]", - id, payOrderId, JsonUtils.toJsonString(order)); - throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); - } - - // 校验支付单是否存在 - PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); - if (payOrder == null) { - log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); - throw exception(ORDER_NOT_FOUND); - } - // 校验支付单已支付 - if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { - log.error("[validateOrderPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]", - id, payOrderId, JsonUtils.toJsonString(payOrder)); - throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS); - } - // 校验支付金额一致 - if (ObjectUtil.notEqual(payOrder.getPrice(), order.getPayPrice())) { - log.error("[validateOrderPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]", - id, payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder)); - throw exception(ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH); - } - // 校验支付订单匹配(二次) - if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), id.toString())) { - log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]", - id, payOrderId, JsonUtils.toJsonString(payOrder)); - throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); - } - return new KeyValue<>(order, payOrder); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) { - // TODO @puhui999:只有选择快递的,才可以发货 - // 1.1 校验并获得交易订单(可发货) - TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId()); - TradeOrderDO updateOrderObj = new TradeOrderDO(); - // 判断发货类型 - // 2.1 快递发货 - if (Objects.equals(deliveryReqVO.getType(), DeliveryTypeEnum.EXPRESS.getMode())) { - // 校验快递公司 - DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId()); - if (deliveryExpress == null) { - throw exception(EXPRESS_NOT_EXISTS); - } - if (deliveryExpress.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { - throw exception(EXPRESS_STATUS_NOT_ENABLE); - } - updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()).setDeliveryType(DeliveryTypeEnum.EXPRESS.getMode()); - } - // TODO @puhui999:无需发货时,更新 logisticsId 为 0; - // 2.2 无需发货 - if (Objects.equals(deliveryReqVO.getType(), DeliveryTypeEnum.NULL.getMode())) { - updateOrderObj.setLogisticsId(null).setLogisticsNo("").setDeliveryType(DeliveryTypeEnum.NULL.getMode()); - } - - // 更新 TradeOrderDO 状态为已发货,等待收货 - updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()); - int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj); - if (updateCount == 0) { - throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); - } - // TODO 芋艿:发送订单变化的消息 - - // 发送站内信 - tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO().setOrderId(order.getId()) - .setUserId(userId).setMessage(null)); - - // TODO 芋艿:OrderLog - // TODO 设计:lili:是不是发货后,才支持售后? - } - - /** - * 校验交易订单满足被发货的条件 - * - * 1. 交易订单未发货 - * - * @param id 交易订单编号 - * @return 交易订单 - */ - private TradeOrderDO validateOrderDeliverable(Long id) { - // 校验订单是否存在 - TradeOrderDO order = tradeOrderMapper.selectById(id); - if (order == null) { - throw exception(ORDER_NOT_FOUND); - } - // 校验订单是否是待发货状态 - if (!TradeOrderStatusEnum.isUndelivered(order.getStatus())) { - throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); - } - // 校验订单是否退款 - if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { - throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE); - } - // 订单类型:拼团 - if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { - // 校验订单拼团是否成功 - if (combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) { - throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); - } - } - // 订单类类型:砍价 - if (Objects.equals(TradeOrderTypeEnum.BARGAIN.getType(), order.getType())) { - // 校验订单砍价是否成功 - if (bargainRecordApi.isBargainRecordSuccess(order.getUserId(), order.getId())) { - throw exception(ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS); - } - } - return order; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void receiveOrder(Long userId, Long id) { - // 校验并获得交易订单(可收货) - TradeOrderDO order = validateOrderReceivable(userId, id); - - // 更新 TradeOrderDO 状态为已完成 - int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), - new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()).setReceiveTime(LocalDateTime.now())); - if (updateCount == 0) { - throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); - } - // TODO 芋艿:OrderLog - - // TODO 芋艿:lili 发送订单变化的消息 - - // TODO 芋艿:lili 发送商品被购买完成的数据 - } - - /** - * 校验交易订单满足可售货的条件 - * - * 1. 交易订单待收货 - * - * @param userId 用户编号 - * @param id 交易订单编号 - * @return 交易订单 - */ - private TradeOrderDO validateOrderReceivable(Long userId, Long id) { - // 校验订单是否存在 - TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId); - if (order == null) { - throw exception(ORDER_NOT_FOUND); - } - // 校验订单是否是待收货状态 - if (!TradeOrderStatusEnum.isDelivered(order.getStatus())) { - throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); - } - return order; - } - - @Override - public TradeOrderDO getOrder(Long id) { - return tradeOrderMapper.selectById(id); - } - - @Override - public TradeOrderDO getOrder(Long userId, Long id) { - TradeOrderDO order = tradeOrderMapper.selectById(id); - if (order != null - && ObjectUtil.notEqual(order.getUserId(), userId)) { - return null; - } - return order; - } - - @Override - public PageResult getOrderPage(TradeOrderPageReqVO reqVO) { - // 获得 userId 相关的查询 - Set userIds = new HashSet<>(); - if (StrUtil.isNotEmpty(reqVO.getUserMobile())) { - MemberUserRespDTO user = memberUserApi.getUserByMobile(reqVO.getUserMobile()); - if (user == null) { // 没查询到用户,说明肯定也没他的订单 - return new PageResult<>(); - } - userIds.add(user.getId()); - } - if (StrUtil.isNotEmpty(reqVO.getUserNickname())) { - List users = memberUserApi.getUserListByNickname(reqVO.getUserNickname()); - if (CollUtil.isEmpty(users)) { // 没查询到用户,说明肯定也没他的订单 - return new PageResult<>(); - } - userIds.addAll(convertSet(users, MemberUserRespDTO::getId)); - } - // 分页查询 - return tradeOrderMapper.selectPage(reqVO, userIds); - } - - @Override - public PageResult getOrderPage(Long userId, AppTradeOrderPageReqVO reqVO) { - return tradeOrderMapper.selectPage(reqVO, userId); - } - - @Override - public Long getOrderCount(Long userId, Integer status, Boolean commentStatus) { - return tradeOrderMapper.selectCountByUserIdAndStatus(userId, status, commentStatus); - } - - // =================== Order Item =================== - - @Override - public TradeOrderItemDO getOrderItem(Long userId, Long itemId) { - TradeOrderItemDO orderItem = tradeOrderItemMapper.selectById(itemId); - if (orderItem != null - && ObjectUtil.notEqual(orderItem.getUserId(), userId)) { - return null; - } - return orderItem; - } - - @Override - public void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, Integer refundPrice) { - // 如果退款成功,则 refundPrice 非空 - if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus()) - && refundPrice == null) { - throw new IllegalArgumentException(StrUtil.format("id({}) 退款成功,退款金额不能为空", id)); - } - - // 更新订单项 - int updateCount = tradeOrderItemMapper.updateAfterSaleStatus(id, oldAfterSaleStatus, newAfterSaleStatus); - if (updateCount <= 0) { - throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL); - } - - // 如果有退款金额,则需要更新订单 - if (refundPrice == null) { - return; - } - // 计算总的退款金额 - TradeOrderDO order = tradeOrderMapper.selectById(tradeOrderItemMapper.selectById(id).getOrderId()); - Integer orderRefundPrice = order.getRefundPrice() + refundPrice; - if (isAllOrderItemAfterSaleSuccess(order.getId())) { // 如果都售后成功,则需要取消订单 - tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) - .setRefundStatus(TradeOrderRefundStatusEnum.ALL.getStatus()).setRefundPrice(orderRefundPrice) - .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); - - // TODO 芋艿:记录订单日志 - - // TODO 芋艿:站内信? - } else { // 如果部分售后,则更新退款金额 - tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) - .setRefundStatus(TradeOrderRefundStatusEnum.PART.getStatus()).setRefundPrice(orderRefundPrice)); - } - - // TODO 芋艿:未来如果有分佣,需要更新相关分佣订单为已失效 - } - - @Override - public List getOrderItemList(Collection ids) { - return tradeOrderItemMapper.selectBatchIds(ids); - } - - @Override - public List getOrderItemListByOrderId(Collection orderIds) { - if (CollUtil.isEmpty(orderIds)) { - return Collections.emptyList(); - } - return tradeOrderItemMapper.selectListByOrderId(orderIds); - } - - @Override - public TradeOrderItemDO getOrderItemByIdAndUserId(Long orderItemId, Long loginUserId) { - return tradeOrderItemMapper.selectOrderItemByIdAndUserId(orderItemId, loginUserId); - } - - @Override - public TradeOrderDO getOrderByIdAndUserId(Long orderId, Long loginUserId) { - return tradeOrderMapper.selectOrderByIdAndUserId(orderId, loginUserId); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Long createOrderItemComment(AppTradeOrderItemCommentCreateReqVO createReqVO) { - Long loginUserId = getLoginUserId(); - // 先通过订单项 ID,查询订单项是否存在 - TradeOrderItemDO orderItem = getOrderItemByIdAndUserId(createReqVO.getOrderItemId(), loginUserId); - if (orderItem == null) { - throw exception(ORDER_ITEM_NOT_FOUND); - } - // 校验订单相关状态 - TradeOrderDO order = getOrderByIdAndUserId(orderItem.getOrderId(), loginUserId); - if (order == null) { - throw exception(ORDER_NOT_FOUND); - } - if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus())) { - throw exception(ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED); - } - if (ObjectUtil.notEqual(order.getCommentStatus(), Boolean.FALSE)) { - throw exception(ORDER_COMMENT_STATUS_NOT_FALSE); - } - - // 创建评价 - ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItem); - Long comment = productCommentApi.createComment(productCommentCreateReqDTO); - // 更新订单项评价状态 - tradeOrderItemMapper.updateById(new TradeOrderItemDO().setId(orderItem.getId()).setCommentStatus(Boolean.TRUE)); - List orderItems = getOrderItemListByOrderId(CollUtil.newArrayList(order.getId())); - if (!anyMatch(orderItems, item -> Objects.equals(item.getCommentStatus(), Boolean.FALSE))) { - // 对于 order 来说,就是评论完,把 order 更新完合理的 status 等字段。 - tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setCommentStatus(Boolean.TRUE)); - } - return comment; - } - - /** - * 判断指定订单的所有订单项,是不是都售后成功 - * - * @param id 订单编号 - * @return 是否都售后成功 - */ - private boolean isAllOrderItemAfterSaleSuccess(Long id) { - List orderItems = tradeOrderItemMapper.selectListByOrderId(id); - return orderItems.stream().allMatch(orderItem -> Objects.equals(orderItem.getAfterSaleStatus(), - TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus())); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java new file mode 100644 index 0000000..92183ef --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.trade.service.order; + +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; + +/** + * 交易订单【写】Service 接口 + * + * @author LeeYan9 + * @since 2022-08-26 + */ +public interface TradeOrderUpdateService { + + // =================== Order =================== + + /** + * 获得订单结算信息 + * + * @param userId 登录用户 + * @param settlementReqVO 订单结算请求 + * @return 订单结算结果 + */ + AppTradeOrderSettlementRespVO settlementOrder(Long userId, AppTradeOrderSettlementReqVO settlementReqVO); + + /** + * 【会员】创建交易订单 + * + * @param userId 登录用户 + * @param userIp 用户 IP 地址 + * @param createReqVO 创建交易订单请求模型 + * @return 交易订单的 + */ + TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO); + + /** + * 更新交易订单已支付 + * + * @param id 交易订单编号 + * @param payOrderId 支付订单编号 + */ + void updateOrderPaid(Long id, Long payOrderId); + + /** + * 【管理员】发货交易订单 + * + * @param userId 管理员编号 + * @param deliveryReqVO 发货请求 + */ + void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO); + + /** + * 【会员】收货交易订单 + * + * @param userId 用户编号 + * @param id 订单编号 + */ + void receiveOrder(Long userId, Long id); + + // =================== Order Item =================== + + /** + * 更新交易订单项的售后状态 + * + * @param id 交易订单项编号 + * @param oldAfterSaleStatus 当前售后状态;如果不符,更新后会抛出异常 + * @param newAfterSaleStatus 目标售后状态 + * @param refundPrice 退款金额;当订单项退款成功时,必须传递该值 + */ + void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, + Integer newAfterSaleStatus, Integer refundPrice); + + /** + * 创建订单项的评论 + * + * @param userId 用户编号 + * @param createReqVO 创建请求 + * @return 得到评价 id + */ + Long createOrderItemComment(Long userId, AppTradeOrderItemCommentCreateReqVO createReqVO); + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java new file mode 100644 index 0000000..5137c3c --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -0,0 +1,598 @@ +package cn.iocoder.yudao.module.trade.service.order; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.core.KeyValue; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.enums.TerminalEnum; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.member.api.address.AddressApi; +import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; +import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; +import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; +import cn.iocoder.yudao.module.promotion.api.bargain.BargainRecordApi; +import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordUpdateStatusReqDTO; +import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; +import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO; +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; +import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; +import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; +import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; +import cn.iocoder.yudao.module.trade.enums.order.*; +import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; +import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; +import cn.iocoder.yudao.module.trade.service.message.TradeMessageService; +import cn.iocoder.yudao.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO; +import cn.iocoder.yudao.module.trade.service.price.TradePriceService; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.ORDER_NOT_FOUND; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; + +/** + * 交易订单【写】Service 实现类 + * + * @author LeeYan9 + * @since 2022-08-26 + */ +@Service +@Slf4j +public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { + + @Resource + private TradeOrderMapper tradeOrderMapper; + @Resource + private TradeOrderItemMapper tradeOrderItemMapper; + + @Resource + private TradeCartService tradeCartService; + @Resource + private TradePriceService tradePriceService; + @Resource + private DeliveryExpressService deliveryExpressService; + + @Resource + private ProductSkuApi productSkuApi; + @Resource + private PayOrderApi payOrderApi; + @Resource + private AddressApi addressApi; + @Resource + private CouponApi couponApi; + @Resource + private MemberUserApi memberUserApi; + @Resource + private ProductCommentApi productCommentApi; + @Resource + private TradeMessageService tradeMessageService; + @Resource + private TradeOrderProperties tradeOrderProperties; + + @Resource + private CombinationRecordApi combinationRecordApi; + + @Resource + private BargainRecordApi bargainRecordApi; + + // =================== Order =================== + + @Override + public AppTradeOrderSettlementRespVO settlementOrder(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) { + // 1. 获得收货地址 + AddressRespDTO address = getAddress(userId, settlementReqVO.getAddressId()); + if (address != null) { + settlementReqVO.setAddressId(address.getId()); + } + + // 2. 计算价格 + TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, settlementReqVO); + + // 3. 拼接返回 + return TradeOrderConvert.INSTANCE.convert(calculateRespBO, address); + } + + /** + * 获得用户地址 + * + * @param userId 用户编号 + * @param addressId 地址编号 + * @return 地址 + */ + private AddressRespDTO getAddress(Long userId, Long addressId) { + if (addressId != null) { + return addressApi.getAddress(addressId, userId); + } + return addressApi.getDefaultAddress(userId); + } + + /** + * 计算订单价格 + * + * @param userId 用户编号 + * @param settlementReqVO 结算信息 + * @return 订单价格 + */ + private TradePriceCalculateRespBO calculatePrice(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) { + // 1. 如果来自购物车,则获得购物车的商品 + List cartList = tradeCartService.getCartList(userId, + convertSet(settlementReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId)); + + // 2. 计算价格 + TradePriceCalculateReqBO calculateReqBO = TradeOrderConvert.INSTANCE.convert(userId, settlementReqVO, cartList); + calculateReqBO.getItems().forEach(item -> Assert.isTrue(item.getSelected(), // 防御性编程,保证都是选中的 + "商品({}) 未设置为选中", item.getSkuId())); + return tradePriceService.calculatePrice(calculateReqBO); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public TradeOrderDO createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) { + // 2. 价格计算 + TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO); + // 3.1 插入 TradeOrderDO 订单 + TradeOrderDO order = createTradeOrder(userId, userIp, createReqVO, calculateRespBO); + // 3.2 插入 TradeOrderItemDO 订单项 + List orderItems = createTradeOrderItems(order, calculateRespBO); + // 订单创建完后的逻辑 + afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO); + // 3.3 校验订单类型 + // 拼团 + if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { + MemberUserRespDTO user = memberUserApi.getUser(userId); + List recordRespDTOS = combinationRecordApi.getRecordListByUserIdAndActivityId(userId, createReqVO.getCombinationActivityId()); + // TODO 拼团一次应该只能选择一种规格的商品 + TradeOrderItemDO orderItemDO = orderItems.get(0); + if (CollUtil.isNotEmpty(recordRespDTOS)) { + List skuIds = convertList(recordRespDTOS, CombinationRecordRespDTO::getSkuId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())); + List tradeOrderItemDOS = tradeOrderItemMapper.selectListByOrderIdAnSkuId(convertList(recordRespDTOS, + CombinationRecordRespDTO::getOrderId, item -> ObjectUtil.equals(item.getStatus(), CombinationRecordStatusEnum.SUCCESS.getStatus())), skuIds); + combinationRecordApi.validateCombinationLimitCount(createReqVO.getCombinationActivityId(), + CollectionUtils.getSumValue(tradeOrderItemDOS, TradeOrderItemDO::getCount, Integer::sum), orderItemDO.getCount()); + } + + combinationRecordApi.createCombinationRecord(TradeOrderConvert.INSTANCE.convert(order, orderItemDO, createReqVO, user)); + } + // TODO 秒杀扣减库存是下单就扣除还是等待订单支付成功再扣除 + if (Objects.equals(TradeOrderTypeEnum.SECKILL.getType(), order.getType())) { + + } + + // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! + return order; + } + + /** + * 校验收件地址是否存在 + * + * @param userId 用户编号 + * @param addressId 收件地址编号 + * @return 收件地址 + */ + private AddressRespDTO validateAddress(Long userId, Long addressId) { + AddressRespDTO address = addressApi.getAddress(addressId, userId); + if (address == null) { + throw exception(ErrorCodeConstants.ORDER_CREATE_ADDRESS_NOT_FOUND); + } + return address; + } + + private TradeOrderDO createTradeOrder(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO, + TradePriceCalculateRespBO calculateRespBO) { + // 用户选择物流配送的时候才需要填写收货地址 + AddressRespDTO address = new AddressRespDTO(); + if (Objects.equals(createReqVO.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getMode())) { + // 用户收件地址的校验 + address = validateAddress(userId, createReqVO.getAddressId()); + } + TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, calculateRespBO, address); + order.setType(validateActivity(createReqVO)); + order.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @LeeYan9: 思考下, 怎么生成好点哈; 这个是会展示给用户的; + order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); + order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); + order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum)); + order.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源? + // 支付信息 + order.setAdjustPrice(0).setPayStatus(false); + // 物流信息 + order.setDeliveryType(createReqVO.getDeliveryType()); + // 退款信息 + order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0); + tradeOrderMapper.insert(order); + return order; + } + + /** + * 校验活动,并返回订单类型 + * + * @param createReqVO 请求参数 + * @return 订单类型 + */ + private Integer validateActivity(AppTradeOrderCreateReqVO createReqVO) { + if (createReqVO.getSeckillActivityId() != null) { + return TradeOrderTypeEnum.SECKILL.getType(); + } + if (createReqVO.getCombinationActivityId() != null) { + return TradeOrderTypeEnum.COMBINATION.getType(); + } + // TODO 砍价敬请期待 + return TradeOrderTypeEnum.NORMAL.getType(); + } + + private List createTradeOrderItems(TradeOrderDO tradeOrderDO, TradePriceCalculateRespBO calculateRespBO) { + List orderItems = TradeOrderConvert.INSTANCE.convertList(tradeOrderDO, calculateRespBO); + tradeOrderItemMapper.insertBatch(orderItems); + return orderItems; + } + + /** + * 执行创建完创建完订单后的逻辑 + * + * 例如说:优惠劵的扣减、积分的扣减、支付单的创建等等 + * + * @param userId 用户编号 + * @param createReqVO 创建订单请求 + * @param tradeOrderDO 交易订单 + * @param calculateRespBO 订单价格计算结果 + */ + private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, + TradeOrderDO tradeOrderDO, List orderItems, + TradePriceCalculateRespBO calculateRespBO) { + // 下单时扣减商品库存 + productSkuApi.updateSkuStock(new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(orderItems))); + + // 删除购物车商品 TODO 芋艿:待实现 + + // 扣减积分,抵扣金额 TODO 芋艿:待实现 + + // 有使用优惠券时更新 + if (createReqVO.getCouponId() != null) { + couponApi.useCoupon(new CouponUseReqDTO().setId(createReqVO.getCouponId()).setUserId(userId) + .setOrderId(tradeOrderDO.getId())); + } + + // 生成预支付 + createPayOrder(tradeOrderDO, orderItems, calculateRespBO); + + // 增加订单日志 TODO 芋艿:待实现 + } + + private void createPayOrder(TradeOrderDO order, List orderItems, TradePriceCalculateRespBO calculateRespBO) { + // 创建支付单,用于后续的支付 + PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert( + order, orderItems, calculateRespBO, tradeOrderProperties); + Long payOrderId = payOrderApi.createOrder(payOrderCreateReqDTO); + + // 更新到交易单上 + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setPayOrderId(payOrderId)); + order.setPayOrderId(payOrderId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateOrderPaid(Long id, Long payOrderId) { + // 校验并获得交易订单(可支付) + KeyValue orderResult = validateOrderPayable(id, payOrderId); + TradeOrderDO order = orderResult.getKey(); + PayOrderRespDTO payOrder = orderResult.getValue(); + + // 更新 TradeOrderDO 状态为已支付,等待发货 + int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), + new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayStatus(true) + .setPayTime(LocalDateTime.now()).setPayChannelCode(payOrder.getChannelCode())); + if (updateCount == 0) { + throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); + } + // 校验活动 + // 1、拼团活动 + if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { + // 更新拼团状态 TODO puhui999:订单支付失败或订单支付过期删除这条拼团记录 + combinationRecordApi.updateCombinationRecordStatus(new CombinationRecordUpdateStatusReqDTO().setUserId(order.getUserId()) + .setOrderId(order.getId()).setStatus(CombinationRecordStatusEnum.IN_PROGRESS.getStatus()).setStartTime(LocalDateTime.now())); + } + // TODO 芋艿:发送订单变化的消息 + + // TODO 芋艿:发送站内信 + + // TODO 芋艿:OrderLog + } + + /** + * 校验交易订单满足被支付的条件 + * + * 1. 交易订单未支付 + * 2. 支付单已支付 + * + * @param id 交易订单编号 + * @param payOrderId 支付订单编号 + * @return 交易订单 + */ + private KeyValue validateOrderPayable(Long id, Long payOrderId) { + // 校验订单是否存在 + TradeOrderDO order = tradeOrderMapper.selectById(id); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + // 校验订单未支付 + if (!TradeOrderStatusEnum.isUnpaid(order.getStatus()) || order.getPayStatus()) { + log.error("[validateOrderPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]", + id, JsonUtils.toJsonString(order)); + throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID); + } + // 校验支付订单匹配 + if (ObjectUtil.notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号 + log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]", + id, payOrderId, JsonUtils.toJsonString(order)); + throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); + } + + // 校验支付单是否存在 + PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId); + if (payOrder == null) { + log.error("[validateOrderPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId); + throw exception(ORDER_NOT_FOUND); + } + // 校验支付单已支付 + if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) { + log.error("[validateOrderPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]", + id, payOrderId, JsonUtils.toJsonString(payOrder)); + throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS); + } + // 校验支付金额一致 + if (ObjectUtil.notEqual(payOrder.getPrice(), order.getPayPrice())) { + log.error("[validateOrderPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]", + id, payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder)); + throw exception(ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH); + } + // 校验支付订单匹配(二次) + if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), id.toString())) { + log.error("[validateOrderPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]", + id, payOrderId, JsonUtils.toJsonString(payOrder)); + throw exception(ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR); + } + return new KeyValue<>(order, payOrder); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) { + // TODO @puhui999:只有选择快递的,才可以发货 + // 1.1 校验并获得交易订单(可发货) + TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId()); + TradeOrderDO updateOrderObj = new TradeOrderDO(); + // 判断发货类型 + // 2.1 快递发货 + if (Objects.equals(deliveryReqVO.getType(), DeliveryTypeEnum.EXPRESS.getMode())) { + // 校验快递公司 + DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId()); + if (deliveryExpress == null) { + throw exception(EXPRESS_NOT_EXISTS); + } + if (deliveryExpress.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { + throw exception(EXPRESS_STATUS_NOT_ENABLE); + } + updateOrderObj.setLogisticsId(deliveryReqVO.getLogisticsId()).setLogisticsNo(deliveryReqVO.getLogisticsNo()).setDeliveryType(DeliveryTypeEnum.EXPRESS.getMode()); + } + // TODO @puhui999:无需发货时,更新 logisticsId 为 0; + // 2.2 无需发货 + if (Objects.equals(deliveryReqVO.getType(), DeliveryTypeEnum.NULL.getMode())) { + updateOrderObj.setLogisticsId(null).setLogisticsNo("").setDeliveryType(DeliveryTypeEnum.NULL.getMode()); + } + + // 更新 TradeOrderDO 状态为已发货,等待收货 + updateOrderObj.setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()).setDeliveryTime(LocalDateTime.now()); + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj); + if (updateCount == 0) { + throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); + } + // TODO 芋艿:发送订单变化的消息 + + // 发送站内信 + tradeMessageService.sendMessageWhenDeliveryOrder(new TradeOrderMessageWhenDeliveryOrderReqBO().setOrderId(order.getId()) + .setUserId(userId).setMessage(null)); + + // TODO 芋艿:OrderLog + // TODO 设计:lili:是不是发货后,才支持售后? + } + + /** + * 校验交易订单满足被发货的条件 + * + * 1. 交易订单未发货 + * + * @param id 交易订单编号 + * @return 交易订单 + */ + private TradeOrderDO validateOrderDeliverable(Long id) { + // 校验订单是否存在 + TradeOrderDO order = tradeOrderMapper.selectById(id); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + // 校验订单是否是待发货状态 + if (!TradeOrderStatusEnum.isUndelivered(order.getStatus())) { + throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); + } + // 校验订单是否退款 + if (ObjectUtil.notEqual(TradeOrderRefundStatusEnum.NONE.getStatus(), order.getRefundStatus())) { + throw exception(ORDER_DELIVERY_FAIL_REFUND_STATUS_NOT_NONE); + } + // 订单类型:拼团 + if (Objects.equals(TradeOrderTypeEnum.COMBINATION.getType(), order.getType())) { + // 校验订单拼团是否成功 + if (combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) { + throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); + } + } + // 订单类类型:砍价 + if (Objects.equals(TradeOrderTypeEnum.BARGAIN.getType(), order.getType())) { + // 校验订单砍价是否成功 + if (bargainRecordApi.isBargainRecordSuccess(order.getUserId(), order.getId())) { + throw exception(ORDER_DELIVERY_FAIL_BARGAIN_RECORD_STATUS_NOT_SUCCESS); + } + } + return order; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void receiveOrder(Long userId, Long id) { + // 校验并获得交易订单(可收货) + TradeOrderDO order = validateOrderReceivable(userId, id); + + // 更新 TradeOrderDO 状态为已完成 + int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), + new TradeOrderDO().setStatus(TradeOrderStatusEnum.COMPLETED.getStatus()).setReceiveTime(LocalDateTime.now())); + if (updateCount == 0) { + throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); + } + // TODO 芋艿:OrderLog + + // TODO 芋艿:lili 发送订单变化的消息 + + // TODO 芋艿:lili 发送商品被购买完成的数据 + } + + /** + * 校验交易订单满足可售货的条件 + * + * 1. 交易订单待收货 + * + * @param userId 用户编号 + * @param id 交易订单编号 + * @return 交易订单 + */ + private TradeOrderDO validateOrderReceivable(Long userId, Long id) { + // 校验订单是否存在 + TradeOrderDO order = tradeOrderMapper.selectByIdAndUserId(id, userId); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + // 校验订单是否是待收货状态 + if (!TradeOrderStatusEnum.isDelivered(order.getStatus())) { + throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); + } + return order; + } + + // =================== Order Item =================== + + @Override + public void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, Integer refundPrice) { + // 如果退款成功,则 refundPrice 非空 + if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus()) + && refundPrice == null) { + throw new IllegalArgumentException(StrUtil.format("id({}) 退款成功,退款金额不能为空", id)); + } + + // 更新订单项 + int updateCount = tradeOrderItemMapper.updateAfterSaleStatus(id, oldAfterSaleStatus, newAfterSaleStatus); + if (updateCount <= 0) { + throw exception(ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL); + } + + // 如果有退款金额,则需要更新订单 + if (refundPrice == null) { + return; + } + // 计算总的退款金额 + TradeOrderDO order = tradeOrderMapper.selectById(tradeOrderItemMapper.selectById(id).getOrderId()); + Integer orderRefundPrice = order.getRefundPrice() + refundPrice; + if (isAllOrderItemAfterSaleSuccess(order.getId())) { // 如果都售后成功,则需要取消订单 + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) + .setRefundStatus(TradeOrderRefundStatusEnum.ALL.getStatus()).setRefundPrice(orderRefundPrice) + .setCancelType(TradeOrderCancelTypeEnum.AFTER_SALE_CLOSE.getType()).setCancelTime(LocalDateTime.now())); + + // TODO 芋艿:记录订单日志 + + // TODO 芋艿:站内信? + } else { // 如果部分售后,则更新退款金额 + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()) + .setRefundStatus(TradeOrderRefundStatusEnum.PART.getStatus()).setRefundPrice(orderRefundPrice)); + } + + // TODO 芋艿:未来如果有分佣,需要更新相关分佣订单为已失效 + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createOrderItemComment(Long userId, AppTradeOrderItemCommentCreateReqVO createReqVO) { + // 先通过订单项 ID,查询订单项是否存在 + TradeOrderItemDO orderItem = tradeOrderItemMapper.selectByIdAndUserId(createReqVO.getOrderItemId(), userId); + if (orderItem == null) { + throw exception(ORDER_ITEM_NOT_FOUND); + } + // 校验订单相关状态 + TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderItem.getOrderId(), userId); + if (order == null) { + throw exception(ORDER_NOT_FOUND); + } + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus())) { + throw exception(ORDER_COMMENT_FAIL_STATUS_NOT_COMPLETED); + } + if (ObjectUtil.notEqual(order.getCommentStatus(), Boolean.FALSE)) { + throw exception(ORDER_COMMENT_STATUS_NOT_FALSE); + } + + // 1. 创建评价 + ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItem); + Long comment = productCommentApi.createComment(productCommentCreateReqDTO); + + // 2. 更新订单项评价状态 + tradeOrderItemMapper.updateById(new TradeOrderItemDO().setId(orderItem.getId()).setCommentStatus(Boolean.TRUE)); + List orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId()); + if (!anyMatch(orderItems, item -> Objects.equals(item.getCommentStatus(), Boolean.FALSE))) { + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setCommentStatus(Boolean.TRUE)); + } + return comment; + } + + /** + * 判断指定订单的所有订单项,是不是都售后成功 + * + * @param id 订单编号 + * @return 是否都售后成功 + */ + private boolean isAllOrderItemAfterSaleSuccess(Long id) { + List orderItems = tradeOrderItemMapper.selectListByOrderId(id); + return orderItems.stream().allMatch(orderItem -> Objects.equals(orderItem.getAfterSaleStatus(), + TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus())); + } + +} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java index 68efd67..c1224d2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceTest.java @@ -18,7 +18,7 @@ import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; -import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; +import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; @@ -52,7 +52,7 @@ public class TradeAfterSaleServiceTest extends BaseDbUnitTest { private TradeAfterSaleLogMapper tradeAfterSaleLogMapper; @MockBean - private TradeOrderService tradeOrderService; + private TradeOrderUpdateService tradeOrderService; @MockBean private PayRefundApi payRefundApi; diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java deleted file mode 100644 index f9dc071..0000000 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java +++ /dev/null @@ -1,314 +0,0 @@ -package cn.iocoder.yudao.module.trade.service.order; - -import cn.iocoder.yudao.framework.common.enums.TerminalEnum; -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.member.api.address.AddressApi; -import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; -import cn.iocoder.yudao.module.member.api.user.MemberUserApi; -import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; -import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; -import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; -import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; -import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; -import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; -import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; -import cn.iocoder.yudao.module.promotion.api.price.PriceApi; -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; -import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; -import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; -import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; -import cn.iocoder.yudao.module.trade.enums.order.*; -import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig; -import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; - -import javax.annotation.Resource; -import java.time.Duration; -import java.util.Arrays; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static java.util.Collections.singletonList; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -/** - * {@link TradeOrderServiceImpl} 的单元测试类 - * - * @author LeeYan9 - * @since 2022-09-07 - */ -@Import({TradeOrderServiceImpl.class, TradeOrderConfig.class}) -public class TradeOrderServiceTest extends BaseDbUnitTest { - - @Resource - private TradeOrderServiceImpl tradeOrderService; - - @Resource - private TradeOrderMapper tradeOrderMapper; - @Resource - private TradeOrderItemMapper tradeOrderItemMapper; - - @MockBean - private MemberUserApi memberUserApi; - @MockBean - private ProductSpuApi productSpuApi; - @MockBean - private ProductSkuApi productSkuApi; - @MockBean - private PriceApi priceApi; - @MockBean - private PayOrderApi payOrderApi; - @MockBean - private AddressApi addressApi; - @MockBean - private CouponApi couponApi; - - @MockBean - private TradeOrderProperties tradeOrderProperties; - - @BeforeEach - public void setUp() { - when(tradeOrderProperties.getAppId()).thenReturn(888L); - when(tradeOrderProperties.getExpireTime()).thenReturn(Duration.ofDays(1)); - } - - @Test - public void testCreateTradeOrder_success() { - // 准备参数 - Long userId = 100L; - String userIp = "127.0.0.1"; -// AppTradeOrderCreateReqVO reqVO = new AppTradeOrderCreateReqVO() -// .setAddressId(10L).setCouponId(101L).setRemark("我是备注").setFromCart(true) -// .setItems(Arrays.asList(new AppTradeOrderCreateReqVO.Item().setSkuId(1L).setCount(3), -// new AppTradeOrderCreateReqVO.Item().setSkuId(2L).setCount(4))); - AppTradeOrderCreateReqVO reqVO = null; - // TODO 芋艿:重新高下 - // mock 方法(商品 SKU 检查) - ProductSkuRespDTO sku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(1L).setSpuId(11L) - .setPrice(50).setStock(100) - .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(111L).setValueId(222L)))); - ProductSkuRespDTO sku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(2L).setSpuId(21L) - .setPrice(20).setStock(50)) - .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(333L).setValueId(444L))); - when(productSkuApi.getSkuList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(sku01, sku02)); - // mock 方法(商品 SPU 检查) - ProductSpuRespDTO spu01 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(11L) - .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()).setName("商品 1")); - ProductSpuRespDTO spu02 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(21L) - .setStatus(ProductSpuStatusEnum.ENABLE.getStatus())); - when(productSpuApi.getSpuList(eq(asSet(11L, 21L)))).thenReturn(Arrays.asList(spu01, spu02)); - // mock 方法(用户收件地址的校验) - AddressRespDTO addressRespDTO = new AddressRespDTO().setId(10L).setUserId(userId).setName("芋艿") - .setMobile("15601691300").setAreaId(3306).setDetailAddress("土豆村"); - when(addressApi.getAddress(eq(10L), eq(userId))).thenReturn(addressRespDTO); - // mock 方法(价格计算) - PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem() - .setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50) - .setDiscountPrice(20).setPayPrice(130).setOrderPartPrice(7).setOrderDividePrice(35); - PriceCalculateRespDTO.OrderItem priceOrderItem02 = new PriceCalculateRespDTO.OrderItem() - .setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20) - .setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25); - PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order() - .setTotalPrice(230).setDiscountPrice(0).setCouponPrice(30) - .setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30) - .setItems(Arrays.asList(priceOrderItem01, priceOrderItem02)); - when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> { - assertEquals(priceCalculateReqDTO.getUserId(), 100L); - assertEquals(priceCalculateReqDTO.getCouponId(), 101L); - assertEquals(priceCalculateReqDTO.getItems().get(0).getSkuId(), 1L); - assertEquals(priceCalculateReqDTO.getItems().get(0).getCount(), 3); - assertEquals(priceCalculateReqDTO.getItems().get(1).getSkuId(), 2L); - assertEquals(priceCalculateReqDTO.getItems().get(1).getCount(), 4); - return true; - }))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder)); - // mock 方法(创建支付单) - when(payOrderApi.createOrder(argThat(createReqDTO -> { - assertEquals(createReqDTO.getAppId(), 888L); - assertEquals(createReqDTO.getUserIp(), userIp); - assertNotNull(createReqDTO.getMerchantOrderId()); // 由于 tradeOrderId 后生成,只能校验非空 - assertEquals(createReqDTO.getSubject(), "商品 1 等多件"); - assertNull(createReqDTO.getBody()); - assertEquals(createReqDTO.getPrice(), 80); - assertNotNull(createReqDTO.getExpireTime()); - return true; - }))).thenReturn(1000L); - - // 调用方法 - TradeOrderDO order = tradeOrderService.createOrder(userId, userIp, reqVO); - // 断言 TradeOrderDO 订单 - List tradeOrderDOs = tradeOrderMapper.selectList(); - assertEquals(tradeOrderDOs.size(), 1); - TradeOrderDO tradeOrderDO = tradeOrderDOs.get(0); - assertEquals(tradeOrderDO.getId(), order.getId()); - assertNotNull(tradeOrderDO.getNo()); - assertEquals(tradeOrderDO.getType(), TradeOrderTypeEnum.NORMAL.getType()); - assertEquals(tradeOrderDO.getTerminal(), TerminalEnum.H5.getTerminal()); - assertEquals(tradeOrderDO.getUserId(), userId); - assertEquals(tradeOrderDO.getUserIp(), userIp); - assertEquals(tradeOrderDO.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus()); - assertEquals(tradeOrderDO.getProductCount(), 7); - assertNull(tradeOrderDO.getFinishTime()); - assertNull(tradeOrderDO.getCancelTime()); - assertNull(tradeOrderDO.getCancelType()); - assertEquals(tradeOrderDO.getUserRemark(), "我是备注"); - assertNull(tradeOrderDO.getRemark()); - assertFalse(tradeOrderDO.getPayStatus()); - assertNull(tradeOrderDO.getPayTime()); - assertEquals(tradeOrderDO.getTotalPrice(), 230); - assertEquals(tradeOrderDO.getDiscountPrice(), 0); - assertEquals(tradeOrderDO.getAdjustPrice(), 0); - assertEquals(tradeOrderDO.getPayPrice(), 80); - assertEquals(tradeOrderDO.getPayOrderId(), 1000L); - assertNull(tradeOrderDO.getPayChannelCode()); - assertNull(tradeOrderDO.getLogisticsId()); - assertNull(tradeOrderDO.getDeliveryTime()); - assertNull(tradeOrderDO.getReceiveTime()); - assertEquals(tradeOrderDO.getReceiverName(), "芋艿"); - assertEquals(tradeOrderDO.getReceiverMobile(), "15601691300"); - assertEquals(tradeOrderDO.getReceiverAreaId(), 3306); - assertEquals(tradeOrderDO.getReceiverDetailAddress(), "土豆村"); - assertEquals(tradeOrderDO.getRefundStatus(), TradeOrderRefundStatusEnum.NONE.getStatus()); - assertEquals(tradeOrderDO.getRefundPrice(), 0); - assertEquals(tradeOrderDO.getCouponPrice(), 30); - assertEquals(tradeOrderDO.getPointPrice(), 10); - // 断言 TradeOrderItemDO 订单(第 1 个) - List tradeOrderItemDOs = tradeOrderItemMapper.selectList(); - assertEquals(tradeOrderItemDOs.size(), 2); - TradeOrderItemDO tradeOrderItemDO01 = tradeOrderItemDOs.get(0); - assertNotNull(tradeOrderItemDO01.getId()); - assertEquals(tradeOrderItemDO01.getUserId(), userId); - assertEquals(tradeOrderItemDO01.getOrderId(), order.getId()); - assertEquals(tradeOrderItemDO01.getSpuId(), 11L); - assertEquals(tradeOrderItemDO01.getSkuId(), 1L); - assertEquals(tradeOrderItemDO01.getProperties().size(), 1); - assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L); - assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L); - //assertEquals(tradeOrderItemDO01.getSpuName(), sku01.getSpuName()); TODO 找不到spuName - assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl()); - assertEquals(tradeOrderItemDO01.getCount(), 3); -// assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150); - assertEquals(tradeOrderItemDO01.getPrice(), 50); - assertEquals(tradeOrderItemDO01.getDiscountPrice(), 20); - assertEquals(tradeOrderItemDO01.getPayPrice(), 130); - assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); - // 断言 TradeOrderItemDO 订单(第 2 个) - TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1); - assertNotNull(tradeOrderItemDO02.getId()); - assertEquals(tradeOrderItemDO02.getUserId(), userId); - assertEquals(tradeOrderItemDO02.getOrderId(), order.getId()); - assertEquals(tradeOrderItemDO02.getSpuId(), 21L); - assertEquals(tradeOrderItemDO02.getSkuId(), 2L); - assertEquals(tradeOrderItemDO02.getProperties().size(), 1); - assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L); - assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L); - //assertEquals(tradeOrderItemDO02.getSpuName(), sku02.getSpuName()); TODO 找不到spuName - assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl()); - assertEquals(tradeOrderItemDO02.getCount(), 4); -// assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80); - assertEquals(tradeOrderItemDO02.getPrice(), 20); - assertEquals(tradeOrderItemDO02.getDiscountPrice(), 40); - assertEquals(tradeOrderItemDO02.getPayPrice(), 40); - assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); - // 校验调用 - verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> { - assertEquals(updateStockReqDTO.getItems().size(), 2); - assertEquals(updateStockReqDTO.getItems().get(0).getId(), 1L); - assertEquals(updateStockReqDTO.getItems().get(0).getIncrCount(), 3); - assertEquals(updateStockReqDTO.getItems().get(1).getId(), 2L); - assertEquals(updateStockReqDTO.getItems().get(1).getIncrCount(), 4); - return true; - })); - verify(couponApi).useCoupon(argThat(reqDTO -> { - assertEquals(reqDTO.getId(), reqVO.getCouponId()); - assertEquals(reqDTO.getUserId(), userId); - assertEquals(reqDTO.getOrderId(), order.getId()); - return true; - })); - } - - @Test - public void testUpdateOrderPaid() { - // mock 数据(TradeOrder) - TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { - o.setId(1L).setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); - o.setPayOrderId(10L).setPayStatus(false).setPayPrice(100).setPayTime(null); - }); - tradeOrderMapper.insert(order); - // 准备参数 - Long id = 1L; - Long payOrderId = 10L; - // mock 方法(支付单) - when(payOrderApi.getOrder(eq(10L))).thenReturn(randomPojo(PayOrderRespDTO.class, - o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()).setChannelCode("wx_pub") - .setMerchantOrderId("1")).setPrice(100)); - - // 调用 - tradeOrderService.updateOrderPaid(id, payOrderId); - // 断言 - TradeOrderDO dbOrder = tradeOrderMapper.selectById(id); - assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus()); - assertTrue(dbOrder.getPayStatus()); - assertNotNull(dbOrder.getPayTime()); - assertEquals(dbOrder.getPayChannelCode(), "wx_pub"); - } - - @Test - public void testDeliveryOrder() { - // mock 数据(TradeOrder) - TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { - o.setId(1L).setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()); - o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null); - }); - tradeOrderMapper.insert(order); - // 准备参数 - TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO().setId(1L) - .setLogisticsId(10L).setLogisticsNo("100"); - // mock 方法(支付单) - - // 调用 - tradeOrderService.deliveryOrder(randomLongId(), deliveryReqVO); - // 断言 - TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L); - assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus()); - assertPojoEquals(dbOrder, deliveryReqVO); - assertNotNull(dbOrder.getDeliveryTime()); - } - - @Test - public void testReceiveOrder() { - // mock 数据(TradeOrder) - TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { - o.setId(1L).setUserId(10L).setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()); - o.setReceiveTime(null); - }); - tradeOrderMapper.insert(order); - // 准备参数 - Long id = 1L; - Long userId = 10L; - // mock 方法(支付单) - - // 调用 - tradeOrderService.receiveOrder(userId, id); - // 断言 - TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L); - assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); - assertNotNull(dbOrder.getReceiveTime()); - } - -} diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java new file mode 100644 index 0000000..313d187 --- /dev/null +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceTest.java @@ -0,0 +1,314 @@ +package cn.iocoder.yudao.module.trade.service.order; + +import cn.iocoder.yudao.framework.common.enums.TerminalEnum; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.member.api.address.AddressApi; +import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; +import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; +import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; +import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; +import cn.iocoder.yudao.module.promotion.api.price.PriceApi; +import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; +import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; +import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; +import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; +import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; +import cn.iocoder.yudao.module.trade.enums.order.*; +import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig; +import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.time.Duration; +import java.util.Arrays; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static java.util.Collections.singletonList; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * {@link TradeOrderUpdateServiceImpl} 的单元测试类 + * + * @author LeeYan9 + * @since 2022-09-07 + */ +@Import({TradeOrderUpdateServiceImpl.class, TradeOrderConfig.class}) +public class TradeOrderUpdateServiceTest extends BaseDbUnitTest { + + @Resource + private TradeOrderUpdateServiceImpl tradeOrderUpdateService; + + @Resource + private TradeOrderMapper tradeOrderMapper; + @Resource + private TradeOrderItemMapper tradeOrderItemMapper; + + @MockBean + private MemberUserApi memberUserApi; + @MockBean + private ProductSpuApi productSpuApi; + @MockBean + private ProductSkuApi productSkuApi; + @MockBean + private PriceApi priceApi; + @MockBean + private PayOrderApi payOrderApi; + @MockBean + private AddressApi addressApi; + @MockBean + private CouponApi couponApi; + + @MockBean + private TradeOrderProperties tradeOrderProperties; + + @BeforeEach + public void setUp() { + when(tradeOrderProperties.getAppId()).thenReturn(888L); + when(tradeOrderProperties.getExpireTime()).thenReturn(Duration.ofDays(1)); + } + + @Test + public void testCreateTradeOrder_success() { + // 准备参数 + Long userId = 100L; + String userIp = "127.0.0.1"; +// AppTradeOrderCreateReqVO reqVO = new AppTradeOrderCreateReqVO() +// .setAddressId(10L).setCouponId(101L).setRemark("我是备注").setFromCart(true) +// .setItems(Arrays.asList(new AppTradeOrderCreateReqVO.Item().setSkuId(1L).setCount(3), +// new AppTradeOrderCreateReqVO.Item().setSkuId(2L).setCount(4))); + AppTradeOrderCreateReqVO reqVO = null; + // TODO 芋艿:重新高下 + // mock 方法(商品 SKU 检查) + ProductSkuRespDTO sku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(1L).setSpuId(11L) + .setPrice(50).setStock(100) + .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(111L).setValueId(222L)))); + ProductSkuRespDTO sku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(2L).setSpuId(21L) + .setPrice(20).setStock(50)) + .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(333L).setValueId(444L))); + when(productSkuApi.getSkuList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(sku01, sku02)); + // mock 方法(商品 SPU 检查) + ProductSpuRespDTO spu01 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(11L) + .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()).setName("商品 1")); + ProductSpuRespDTO spu02 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(21L) + .setStatus(ProductSpuStatusEnum.ENABLE.getStatus())); + when(productSpuApi.getSpuList(eq(asSet(11L, 21L)))).thenReturn(Arrays.asList(spu01, spu02)); + // mock 方法(用户收件地址的校验) + AddressRespDTO addressRespDTO = new AddressRespDTO().setId(10L).setUserId(userId).setName("芋艿") + .setMobile("15601691300").setAreaId(3306).setDetailAddress("土豆村"); + when(addressApi.getAddress(eq(10L), eq(userId))).thenReturn(addressRespDTO); + // mock 方法(价格计算) + PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem() + .setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50) + .setDiscountPrice(20).setPayPrice(130).setOrderPartPrice(7).setOrderDividePrice(35); + PriceCalculateRespDTO.OrderItem priceOrderItem02 = new PriceCalculateRespDTO.OrderItem() + .setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20) + .setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25); + PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order() + .setTotalPrice(230).setDiscountPrice(0).setCouponPrice(30) + .setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30) + .setItems(Arrays.asList(priceOrderItem01, priceOrderItem02)); + when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> { + assertEquals(priceCalculateReqDTO.getUserId(), 100L); + assertEquals(priceCalculateReqDTO.getCouponId(), 101L); + assertEquals(priceCalculateReqDTO.getItems().get(0).getSkuId(), 1L); + assertEquals(priceCalculateReqDTO.getItems().get(0).getCount(), 3); + assertEquals(priceCalculateReqDTO.getItems().get(1).getSkuId(), 2L); + assertEquals(priceCalculateReqDTO.getItems().get(1).getCount(), 4); + return true; + }))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder)); + // mock 方法(创建支付单) + when(payOrderApi.createOrder(argThat(createReqDTO -> { + assertEquals(createReqDTO.getAppId(), 888L); + assertEquals(createReqDTO.getUserIp(), userIp); + assertNotNull(createReqDTO.getMerchantOrderId()); // 由于 tradeOrderId 后生成,只能校验非空 + assertEquals(createReqDTO.getSubject(), "商品 1 等多件"); + assertNull(createReqDTO.getBody()); + assertEquals(createReqDTO.getPrice(), 80); + assertNotNull(createReqDTO.getExpireTime()); + return true; + }))).thenReturn(1000L); + + // 调用方法 + TradeOrderDO order = tradeOrderUpdateService.createOrder(userId, userIp, reqVO); + // 断言 TradeOrderDO 订单 + List tradeOrderDOs = tradeOrderMapper.selectList(); + assertEquals(tradeOrderDOs.size(), 1); + TradeOrderDO tradeOrderDO = tradeOrderDOs.get(0); + assertEquals(tradeOrderDO.getId(), order.getId()); + assertNotNull(tradeOrderDO.getNo()); + assertEquals(tradeOrderDO.getType(), TradeOrderTypeEnum.NORMAL.getType()); + assertEquals(tradeOrderDO.getTerminal(), TerminalEnum.H5.getTerminal()); + assertEquals(tradeOrderDO.getUserId(), userId); + assertEquals(tradeOrderDO.getUserIp(), userIp); + assertEquals(tradeOrderDO.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus()); + assertEquals(tradeOrderDO.getProductCount(), 7); + assertNull(tradeOrderDO.getFinishTime()); + assertNull(tradeOrderDO.getCancelTime()); + assertNull(tradeOrderDO.getCancelType()); + assertEquals(tradeOrderDO.getUserRemark(), "我是备注"); + assertNull(tradeOrderDO.getRemark()); + assertFalse(tradeOrderDO.getPayStatus()); + assertNull(tradeOrderDO.getPayTime()); + assertEquals(tradeOrderDO.getTotalPrice(), 230); + assertEquals(tradeOrderDO.getDiscountPrice(), 0); + assertEquals(tradeOrderDO.getAdjustPrice(), 0); + assertEquals(tradeOrderDO.getPayPrice(), 80); + assertEquals(tradeOrderDO.getPayOrderId(), 1000L); + assertNull(tradeOrderDO.getPayChannelCode()); + assertNull(tradeOrderDO.getLogisticsId()); + assertNull(tradeOrderDO.getDeliveryTime()); + assertNull(tradeOrderDO.getReceiveTime()); + assertEquals(tradeOrderDO.getReceiverName(), "芋艿"); + assertEquals(tradeOrderDO.getReceiverMobile(), "15601691300"); + assertEquals(tradeOrderDO.getReceiverAreaId(), 3306); + assertEquals(tradeOrderDO.getReceiverDetailAddress(), "土豆村"); + assertEquals(tradeOrderDO.getRefundStatus(), TradeOrderRefundStatusEnum.NONE.getStatus()); + assertEquals(tradeOrderDO.getRefundPrice(), 0); + assertEquals(tradeOrderDO.getCouponPrice(), 30); + assertEquals(tradeOrderDO.getPointPrice(), 10); + // 断言 TradeOrderItemDO 订单(第 1 个) + List tradeOrderItemDOs = tradeOrderItemMapper.selectList(); + assertEquals(tradeOrderItemDOs.size(), 2); + TradeOrderItemDO tradeOrderItemDO01 = tradeOrderItemDOs.get(0); + assertNotNull(tradeOrderItemDO01.getId()); + assertEquals(tradeOrderItemDO01.getUserId(), userId); + assertEquals(tradeOrderItemDO01.getOrderId(), order.getId()); + assertEquals(tradeOrderItemDO01.getSpuId(), 11L); + assertEquals(tradeOrderItemDO01.getSkuId(), 1L); + assertEquals(tradeOrderItemDO01.getProperties().size(), 1); + assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L); + assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L); + //assertEquals(tradeOrderItemDO01.getSpuName(), sku01.getSpuName()); TODO 找不到spuName + assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl()); + assertEquals(tradeOrderItemDO01.getCount(), 3); +// assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150); + assertEquals(tradeOrderItemDO01.getPrice(), 50); + assertEquals(tradeOrderItemDO01.getDiscountPrice(), 20); + assertEquals(tradeOrderItemDO01.getPayPrice(), 130); + assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); + // 断言 TradeOrderItemDO 订单(第 2 个) + TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1); + assertNotNull(tradeOrderItemDO02.getId()); + assertEquals(tradeOrderItemDO02.getUserId(), userId); + assertEquals(tradeOrderItemDO02.getOrderId(), order.getId()); + assertEquals(tradeOrderItemDO02.getSpuId(), 21L); + assertEquals(tradeOrderItemDO02.getSkuId(), 2L); + assertEquals(tradeOrderItemDO02.getProperties().size(), 1); + assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L); + assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L); + //assertEquals(tradeOrderItemDO02.getSpuName(), sku02.getSpuName()); TODO 找不到spuName + assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl()); + assertEquals(tradeOrderItemDO02.getCount(), 4); +// assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80); + assertEquals(tradeOrderItemDO02.getPrice(), 20); + assertEquals(tradeOrderItemDO02.getDiscountPrice(), 40); + assertEquals(tradeOrderItemDO02.getPayPrice(), 40); + assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); + // 校验调用 + verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> { + assertEquals(updateStockReqDTO.getItems().size(), 2); + assertEquals(updateStockReqDTO.getItems().get(0).getId(), 1L); + assertEquals(updateStockReqDTO.getItems().get(0).getIncrCount(), 3); + assertEquals(updateStockReqDTO.getItems().get(1).getId(), 2L); + assertEquals(updateStockReqDTO.getItems().get(1).getIncrCount(), 4); + return true; + })); + verify(couponApi).useCoupon(argThat(reqDTO -> { + assertEquals(reqDTO.getId(), reqVO.getCouponId()); + assertEquals(reqDTO.getUserId(), userId); + assertEquals(reqDTO.getOrderId(), order.getId()); + return true; + })); + } + + @Test + public void testUpdateOrderPaid() { + // mock 数据(TradeOrder) + TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { + o.setId(1L).setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); + o.setPayOrderId(10L).setPayStatus(false).setPayPrice(100).setPayTime(null); + }); + tradeOrderMapper.insert(order); + // 准备参数 + Long id = 1L; + Long payOrderId = 10L; + // mock 方法(支付单) + when(payOrderApi.getOrder(eq(10L))).thenReturn(randomPojo(PayOrderRespDTO.class, + o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()).setChannelCode("wx_pub") + .setMerchantOrderId("1")).setPrice(100)); + + // 调用 + tradeOrderUpdateService.updateOrderPaid(id, payOrderId); + // 断言 + TradeOrderDO dbOrder = tradeOrderMapper.selectById(id); + assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus()); + assertTrue(dbOrder.getPayStatus()); + assertNotNull(dbOrder.getPayTime()); + assertEquals(dbOrder.getPayChannelCode(), "wx_pub"); + } + + @Test + public void testDeliveryOrder() { + // mock 数据(TradeOrder) + TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { + o.setId(1L).setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()); + o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null); + }); + tradeOrderMapper.insert(order); + // 准备参数 + TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO().setId(1L) + .setLogisticsId(10L).setLogisticsNo("100"); + // mock 方法(支付单) + + // 调用 + tradeOrderUpdateService.deliveryOrder(randomLongId(), deliveryReqVO); + // 断言 + TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L); + assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus()); + assertPojoEquals(dbOrder, deliveryReqVO); + assertNotNull(dbOrder.getDeliveryTime()); + } + + @Test + public void testReceiveOrder() { + // mock 数据(TradeOrder) + TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> { + o.setId(1L).setUserId(10L).setStatus(TradeOrderStatusEnum.DELIVERED.getStatus()); + o.setReceiveTime(null); + }); + tradeOrderMapper.insert(order); + // 准备参数 + Long id = 1L; + Long userId = 10L; + // mock 方法(支付单) + + // 调用 + tradeOrderUpdateService.receiveOrder(userId, id); + // 断言 + TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L); + assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); + assertNotNull(dbOrder.getReceiveTime()); + } + +} -- libgit2 0.21.4