Commit 636b14cccec2b8f5d30db81e18817d23c31aaf73
1 parent
2a9a869e
mall + trade:创建订单逻辑,接入新的价格接口
Showing
6 changed files
with
96 additions
and
140 deletions
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.http
| ... | ... | @@ -8,27 +8,22 @@ GET {{appApi}}/trade/order/settlement?type=0&items[0].cartId=50&couponId=1 |
| 8 | 8 | Authorization: Bearer {{appToken}} |
| 9 | 9 | tenant-id: {{appTenentId}} |
| 10 | 10 | |
| 11 | -### /trade-order/confirm-create-order-info-from-cart 基于购物车,确认创建订单 | |
| 12 | -GET {{shop-api-base-url}}/trade-order/confirm-create-order-info-from-cart | |
| 13 | -Content-Type: application/x-www-form-urlencoded | |
| 14 | -Authorization: Bearer {{user-access-token}} | |
| 15 | - | |
| 16 | -### /trade-order/create 基于商品,创建订单 | |
| 11 | +### /trade-order/create 创建订单(基于商品) | |
| 17 | 12 | POST {{appApi}}/trade/order/create |
| 18 | 13 | Content-Type: application/json |
| 19 | 14 | Authorization: Bearer {{appToken}} |
| 20 | 15 | tenant-id: {{appTenentId}} |
| 21 | 16 | |
| 22 | 17 | { |
| 18 | + "type": 0, | |
| 23 | 19 | "addressId": 21, |
| 24 | - "remark": "我是备注", | |
| 25 | - "fromCart": false, | |
| 26 | 20 | "items": [ |
| 27 | 21 | { |
| 28 | - "skuId": 29, | |
| 29 | - "count": 1 | |
| 22 | + "skuId": 1, | |
| 23 | + "count": 2 | |
| 30 | 24 | } |
| 31 | - ] | |
| 25 | + ], | |
| 26 | + "remark": "我是备注" | |
| 32 | 27 | } |
| 33 | 28 | |
| 34 | 29 | ### 获得订单交易的分页 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
| ... | ... | @@ -22,7 +22,6 @@ import org.springframework.validation.annotation.Validated; |
| 22 | 22 | import org.springframework.web.bind.annotation.*; |
| 23 | 23 | |
| 24 | 24 | import javax.annotation.Resource; |
| 25 | -import javax.servlet.http.HttpServletRequest; | |
| 26 | 25 | import javax.validation.Valid; |
| 27 | 26 | import java.util.HashMap; |
| 28 | 27 | import java.util.List; |
| ... | ... | @@ -30,6 +29,7 @@ import java.util.Map; |
| 30 | 29 | |
| 31 | 30 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 32 | 31 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 32 | +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; | |
| 33 | 33 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| 34 | 34 | |
| 35 | 35 | @Tag(name = "用户 App - 交易订单") |
| ... | ... | @@ -58,15 +58,9 @@ public class AppTradeOrderController { |
| 58 | 58 | @PostMapping("/create") |
| 59 | 59 | @Operation(summary = "创建订单") |
| 60 | 60 | @PreAuthenticated |
| 61 | - public CommonResult<Long> createOrder(@RequestBody AppTradeOrderCreateReqVO createReqVO, | |
| 62 | - HttpServletRequest servletRequest) { | |
| 63 | - return success(1L); | |
| 64 | -// // 获取登录用户、用户 IP 地址 | |
| 65 | -// Long loginUserId = getLoginUserId(); | |
| 66 | -// String clientIp = ServletUtils.getClientIP(servletRequest); | |
| 67 | -// // 创建交易订单,预支付记录 | |
| 68 | -// Long orderId = tradeOrderService.createOrder(loginUserId, clientIp, createReqVO); | |
| 69 | -// return success(orderId); | |
| 61 | + public CommonResult<Long> createOrder(@RequestBody AppTradeOrderCreateReqVO createReqVO) { | |
| 62 | + Long orderId = tradeOrderService.createOrder(getLoginUserId(), getClientIP(), createReqVO); | |
| 63 | + return success(orderId); | |
| 70 | 64 | } |
| 71 | 65 | |
| 72 | 66 | @PostMapping("/update-paid") | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderCreateReqVO.java
| ... | ... | @@ -3,26 +3,9 @@ package cn.iocoder.yudao.module.trade.controller.app.order.vo; |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | -import javax.validation.constraints.NotEmpty; | |
| 7 | -import javax.validation.constraints.NotNull; | |
| 8 | -import java.util.List; | |
| 9 | - | |
| 10 | 6 | @Schema(description = "用户 App - 交易订单创建 Request VO") |
| 11 | 7 | @Data |
| 12 | -public class AppTradeOrderCreateReqVO { | |
| 13 | - | |
| 14 | - @Schema(description = "收件地址编号", required = true, example = "1") | |
| 15 | - @NotNull(message = "收件地址不能为空") | |
| 16 | - private Long addressId; | |
| 17 | - | |
| 18 | - @Schema(description = "优惠劵编号", example = "1024") | |
| 19 | - private Long couponId; | |
| 20 | - | |
| 21 | - @Schema(description = "购物车项的编号数组", required = true, example = "true") | |
| 22 | - @NotEmpty(message = "购物车项不能为空") | |
| 23 | - private List<Long> cartIds; | |
| 24 | - | |
| 25 | - // ========== 非 AppTradeOrderSettlementReqVO 字段 ========== | |
| 8 | +public class AppTradeOrderCreateReqVO extends AppTradeOrderSettlementReqVO { | |
| 26 | 9 | |
| 27 | 10 | @Schema(description = "备注", example = "这个是我的订单哟") |
| 28 | 11 | private String remark; | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
| ... | ... | @@ -9,11 +9,8 @@ import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; |
| 9 | 9 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; |
| 10 | 10 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; |
| 11 | 11 | import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; |
| 12 | -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | |
| 13 | 12 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; |
| 14 | -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | |
| 15 | 13 | import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; |
| 16 | -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; | |
| 17 | 14 | import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; |
| 18 | 15 | import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; |
| 19 | 16 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO; |
| ... | ... | @@ -50,32 +47,32 @@ public interface TradeOrderConvert { |
| 50 | 47 | @Mapping(source = "createReqVO.couponId", target = "couponId"), |
| 51 | 48 | @Mapping(target = "remark", ignore = true), |
| 52 | 49 | @Mapping(source = "createReqVO.remark", target = "userRemark"), |
| 50 | + @Mapping(source = "createReqVO.type", target = "type"), | |
| 51 | + @Mapping(source = "calculateRespBO.price.totalPrice", target = "totalPrice"), | |
| 52 | + @Mapping(source = "calculateRespBO.price.discountPrice", target = "discountPrice"), | |
| 53 | + @Mapping(source = "calculateRespBO.price.deliveryPrice", target = "deliveryPrice"), | |
| 54 | + @Mapping(source = "calculateRespBO.price.couponPrice", target = "couponPrice"), | |
| 55 | + @Mapping(source = "calculateRespBO.price.pointPrice", target = "pointPrice"), | |
| 56 | + @Mapping(source = "calculateRespBO.price.payPrice", target = "payPrice"), | |
| 53 | 57 | @Mapping(source = "address.name", target = "receiverName"), |
| 54 | 58 | @Mapping(source = "address.mobile", target = "receiverMobile"), |
| 55 | 59 | @Mapping(source = "address.areaId", target = "receiverAreaId"), |
| 56 | 60 | @Mapping(source = "address.detailAddress", target = "receiverDetailAddress"), |
| 57 | 61 | }) |
| 58 | 62 | TradeOrderDO convert(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO, |
| 59 | - PriceCalculateRespDTO.Order order, AddressRespDTO address); | |
| 63 | + TradePriceCalculateRespBO calculateRespBO, AddressRespDTO address); | |
| 60 | 64 | |
| 61 | - @Mappings({ | |
| 62 | - @Mapping(target = "id", ignore = true), | |
| 63 | - @Mapping(source = "sku.spuId", target = "spuId"), | |
| 64 | - }) | |
| 65 | - TradeOrderItemDO convert(PriceCalculateRespDTO.OrderItem orderItem, ProductSkuRespDTO sku); | |
| 66 | - | |
| 67 | - default List<TradeOrderItemDO> convertList(TradeOrderDO tradeOrderDO, | |
| 68 | - List<PriceCalculateRespDTO.OrderItem> orderItems, List<ProductSkuRespDTO> skus) { | |
| 69 | - Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId); | |
| 70 | - return CollectionUtils.convertList(orderItems, orderItem -> { | |
| 71 | - TradeOrderItemDO tradeOrderItemDO = convert(orderItem, skuMap.get(orderItem.getSkuId())); | |
| 72 | - tradeOrderItemDO.setOrderId(tradeOrderDO.getId()); | |
| 73 | - tradeOrderItemDO.setUserId(tradeOrderDO.getUserId()); | |
| 74 | - tradeOrderItemDO.setAfterSaleStatus(TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); // 退款信息 | |
| 75 | -// tradeOrderItemDO.setCommented(false); | |
| 76 | - return tradeOrderItemDO; | |
| 65 | + default List<TradeOrderItemDO> convertList(TradeOrderDO tradeOrderDO, TradePriceCalculateRespBO calculateRespBO) { | |
| 66 | + return CollectionUtils.convertList(calculateRespBO.getItems(), item -> { | |
| 67 | + TradeOrderItemDO orderItem = convert(item); | |
| 68 | + orderItem.setOrderId(tradeOrderDO.getId()); | |
| 69 | + orderItem.setUserId(tradeOrderDO.getUserId()); | |
| 70 | + orderItem.setAfterSaleStatus(TradeOrderItemAfterSaleStatusEnum.NONE.getStatus()); | |
| 71 | + orderItem.setCommentStatus(false); | |
| 72 | + return orderItem; | |
| 77 | 73 | }); |
| 78 | 74 | } |
| 75 | + TradeOrderItemDO convert(TradePriceCalculateRespBO.OrderItem item); | |
| 79 | 76 | |
| 80 | 77 | @Mapping(source = "userId" , target = "userId") |
| 81 | 78 | PriceCalculateReqDTO convert(AppTradeOrderCreateReqVO createReqVO, Long userId); |
| ... | ... | @@ -87,19 +84,20 @@ public interface TradeOrderConvert { |
| 87 | 84 | ProductSkuUpdateStockReqDTO.Item convert(TradeOrderItemDO bean); |
| 88 | 85 | List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list); |
| 89 | 86 | |
| 90 | - default PayOrderCreateReqDTO convert(TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> tradeOrderItemDOs, | |
| 91 | - List<ProductSpuRespDTO> spus, TradeOrderProperties tradeOrderProperties) { | |
| 87 | + default PayOrderCreateReqDTO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems, | |
| 88 | + TradePriceCalculateRespBO calculateRespBO, TradeOrderProperties orderProperties) { | |
| 92 | 89 | PayOrderCreateReqDTO createReqDTO = new PayOrderCreateReqDTO() |
| 93 | - .setAppId(tradeOrderProperties.getAppId()).setUserIp(tradeOrderDO.getUserIp()); | |
| 90 | + .setAppId(orderProperties.getAppId()).setUserIp(order.getUserIp()); | |
| 94 | 91 | // 商户相关字段 |
| 95 | - createReqDTO.setMerchantOrderId(String.valueOf(tradeOrderDO.getId())); | |
| 96 | - String subject = spus.get(0).getName(); | |
| 97 | - if (spus.size() > 1) { | |
| 92 | + createReqDTO.setMerchantOrderId(String.valueOf(order.getId())); | |
| 93 | + String subject = calculateRespBO.getItems().get(0).getSpuName(); | |
| 94 | + if (calculateRespBO.getItems().size() > 1) { | |
| 98 | 95 | subject += " 等多件"; |
| 99 | 96 | } |
| 100 | 97 | createReqDTO.setSubject(subject); |
| 98 | + createReqDTO.setBody(subject); // TODO 芋艿:临时写死 | |
| 101 | 99 | // 订单相关字段 |
| 102 | - createReqDTO.setAmount(tradeOrderDO.getPayPrice()).setExpireTime(addTime(tradeOrderProperties.getExpireTime())); | |
| 100 | + createReqDTO.setAmount(order.getPayPrice()).setExpireTime(addTime(orderProperties.getExpireTime())); | |
| 103 | 101 | return createReqDTO; |
| 104 | 102 | } |
| 105 | 103 | |
| ... | ... | @@ -113,6 +111,7 @@ public interface TradeOrderConvert { |
| 113 | 111 | .collect(Collectors.toSet()); |
| 114 | 112 | } |
| 115 | 113 | |
| 114 | + // TODO 芋艿:可简化 | |
| 116 | 115 | default PageResult<TradeOrderPageItemRespVO> convertPage(PageResult<TradeOrderDO> pageResult, List<TradeOrderItemDO> orderItems, |
| 117 | 116 | List<ProductPropertyValueDetailRespDTO> propertyValueDetails) { |
| 118 | 117 | Map<Long, List<TradeOrderItemDO>> orderItemMap = convertMultiMap(orderItems, TradeOrderItemDO::getOrderId); |
| ... | ... | @@ -149,6 +148,7 @@ public interface TradeOrderConvert { |
| 149 | 148 | TradeOrderPageItemRespVO convert(TradeOrderDO order, List<TradeOrderItemDO> items); |
| 150 | 149 | ProductPropertyValueDetailRespVO convert(ProductPropertyValueDetailRespDTO bean); |
| 151 | 150 | |
| 151 | + // TODO 芋艿:可简化 | |
| 152 | 152 | default TradeOrderDetailRespVO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems, |
| 153 | 153 | List<ProductPropertyValueDetailRespDTO> propertyValueDetails, MemberUserRespDTO user) { |
| 154 | 154 | TradeOrderDetailRespVO orderVO = convert2(order, orderItems); |
| ... | ... | @@ -179,6 +179,7 @@ public interface TradeOrderConvert { |
| 179 | 179 | TradeOrderDetailRespVO convert2(TradeOrderDO order, List<TradeOrderItemDO> items); |
| 180 | 180 | MemberUserRespVO convert(MemberUserRespDTO bean); |
| 181 | 181 | |
| 182 | + // TODO 芋艿:可简化 | |
| 182 | 183 | default PageResult<AppTradeOrderPageItemRespVO> convertPage02(PageResult<TradeOrderDO> pageResult, List<TradeOrderItemDO> orderItems, |
| 183 | 184 | List<ProductPropertyValueDetailRespDTO> propertyValueDetails) { |
| 184 | 185 | Map<Long, List<TradeOrderItemDO>> orderItemMap = convertMultiMap(orderItems, TradeOrderItemDO::getOrderId); | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java
| ... | ... | @@ -167,11 +167,24 @@ public class TradeOrderItemDO extends BaseDO { |
| 167 | 167 | */ |
| 168 | 168 | private Long propertyId; |
| 169 | 169 | /** |
| 170 | + * 属性名字 | |
| 171 | + * | |
| 172 | + * 关联 ProductPropertyDO 的 name 字段 | |
| 173 | + */ | |
| 174 | + private String propertyName; | |
| 175 | + | |
| 176 | + /** | |
| 170 | 177 | * 属性值编号 |
| 171 | 178 | * |
| 172 | 179 | * 关联 ProductPropertyValueDO 的 id 编号 |
| 173 | 180 | */ |
| 174 | 181 | private Long valueId; |
| 182 | + /** | |
| 183 | + * 属性值名字 | |
| 184 | + * | |
| 185 | + * 关联 ProductPropertyValueDO 的 name 字段 | |
| 186 | + */ | |
| 187 | + private String valueName; | |
| 175 | 188 | |
| 176 | 189 | } |
| 177 | 190 | ... | ... |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.trade.service.order; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.lang.Assert; | |
| 4 | 5 | import cn.hutool.core.util.IdUtil; |
| 5 | 6 | import cn.hutool.core.util.ObjectUtil; |
| 6 | 7 | import cn.hutool.core.util.StrUtil; |
| 7 | 8 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| 8 | 9 | import cn.iocoder.yudao.framework.common.enums.TerminalEnum; |
| 9 | 10 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 10 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | |
| 11 | 11 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 12 | 12 | import cn.iocoder.yudao.module.member.api.address.AddressApi; |
| 13 | 13 | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; |
| ... | ... | @@ -18,15 +18,9 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; |
| 18 | 18 | import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; |
| 19 | 19 | import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; |
| 20 | 20 | import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; |
| 21 | -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | |
| 22 | 21 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; |
| 23 | -import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | |
| 24 | -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | |
| 25 | -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; | |
| 26 | 22 | import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; |
| 27 | 23 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; |
| 28 | -import cn.iocoder.yudao.module.promotion.api.price.PriceApi; | |
| 29 | -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; | |
| 30 | 24 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; |
| 31 | 25 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; |
| 32 | 26 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; |
| ... | ... | @@ -40,6 +34,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| 40 | 34 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; |
| 41 | 35 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; |
| 42 | 36 | import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; |
| 37 | +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; | |
| 43 | 38 | import cn.iocoder.yudao.module.trade.enums.order.*; |
| 44 | 39 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; |
| 45 | 40 | import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; |
| ... | ... | @@ -55,7 +50,8 @@ import java.time.LocalDateTime; |
| 55 | 50 | import java.util.*; |
| 56 | 51 | |
| 57 | 52 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 58 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | |
| 53 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 54 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; | |
| 59 | 55 | import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND; |
| 60 | 56 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; |
| 61 | 57 | |
| ... | ... | @@ -80,12 +76,8 @@ public class TradeOrderServiceImpl implements TradeOrderService { |
| 80 | 76 | private TradePriceService tradePriceService; |
| 81 | 77 | |
| 82 | 78 | @Resource |
| 83 | - private PriceApi priceApi; | |
| 84 | - @Resource | |
| 85 | 79 | private ProductSkuApi productSkuApi; |
| 86 | 80 | @Resource |
| 87 | - private ProductSpuApi productSpuApi; | |
| 88 | - @Resource | |
| 89 | 81 | private PayOrderApi payOrderApi; |
| 90 | 82 | @Resource |
| 91 | 83 | private AddressApi addressApi; |
| ... | ... | @@ -142,53 +134,29 @@ public class TradeOrderServiceImpl implements TradeOrderService { |
| 142 | 134 | |
| 143 | 135 | // 2. 计算价格 |
| 144 | 136 | TradePriceCalculateReqBO calculateReqBO = TradeOrderConvert.INSTANCE.convert(userId, settlementReqVO, cartList); |
| 137 | + calculateReqBO.getItems().forEach(item -> Assert.isTrue(item.getSelected(), // 防御性编程,保证都是选中的 | |
| 138 | + "商品({}) 未设置为选中", item.getSkuId())); | |
| 145 | 139 | return tradePriceService.calculatePrice(calculateReqBO); |
| 146 | 140 | } |
| 147 | 141 | |
| 148 | 142 | @Override |
| 149 | 143 | @Transactional(rollbackFor = Exception.class) |
| 150 | 144 | public Long createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) { |
| 151 | - // 商品 SKU 检查:可售状态、库存 | |
| 152 | -// List<ProductSkuRespDTO> skus = validateSkuSaleable(createReqVO.getItems()); // TODO 芋艿,临时关闭。 | |
| 153 | - List<ProductSkuRespDTO> skus = null; | |
| 154 | - // 商品 SPU 检查:可售状态 | |
| 155 | - List<ProductSpuRespDTO> spus = validateSpuSaleable(convertSet(skus, ProductSkuRespDTO::getSpuId)); | |
| 156 | - // 用户收件地址的校验 | |
| 145 | + // 1. 用户收件地址的校验 | |
| 157 | 146 | AddressRespDTO address = validateAddress(userId, createReqVO.getAddressId()); |
| 158 | 147 | |
| 159 | - // 价格计算 | |
| 160 | - PriceCalculateRespDTO priceResp = priceApi.calculatePrice(TradeOrderConvert.INSTANCE.convert(createReqVO, userId)); | |
| 148 | + // 2. 价格计算 | |
| 149 | + TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO); | |
| 161 | 150 | |
| 162 | - // 插入 TradeOrderDO 订单 | |
| 163 | - TradeOrderDO tradeOrderDO = createTradeOrder(userId, userIp, createReqVO, priceResp.getOrder(), address); | |
| 164 | - // 插入 TradeOrderItemDO 订单项 | |
| 165 | - List<TradeOrderItemDO> tradeOrderItems = createTradeOrderItems(tradeOrderDO, priceResp.getOrder().getItems(), skus); | |
| 151 | + // 3.1 插入 TradeOrderDO 订单 | |
| 152 | + TradeOrderDO order = createTradeOrder(userId, userIp, createReqVO, calculateRespBO, address); | |
| 153 | + // 3.2 插入 TradeOrderItemDO 订单项 | |
| 154 | + List<TradeOrderItemDO> orderItems = createTradeOrderItems(order, calculateRespBO); | |
| 166 | 155 | |
| 167 | 156 | // 订单创建完后的逻辑 |
| 168 | - afterCreateTradeOrder(userId, createReqVO, tradeOrderDO, tradeOrderItems, spus); | |
| 157 | + afterCreateTradeOrder(userId, createReqVO, order, orderItems, calculateRespBO); | |
| 169 | 158 | // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! |
| 170 | - return tradeOrderDO.getId(); | |
| 171 | - } | |
| 172 | - | |
| 173 | - /** | |
| 174 | - * 校验商品 SPU 是否可出售 | |
| 175 | - * | |
| 176 | - * @param spuIds 商品 SPU 编号数组 | |
| 177 | - * @return 商品 SPU 数组 | |
| 178 | - */ | |
| 179 | - private List<ProductSpuRespDTO> validateSpuSaleable(Set<Long> spuIds) { | |
| 180 | - List<ProductSpuRespDTO> spus = productSpuApi.getSpuList(spuIds); | |
| 181 | - // SPU 不存在 | |
| 182 | - if (spus.size() != spuIds.size()) { | |
| 183 | - throw exception(ORDER_CREATE_SPU_NOT_FOUND); | |
| 184 | - } | |
| 185 | - // 校验是否存在禁用的 SPU | |
| 186 | - ProductSpuRespDTO spu = CollectionUtils.findFirst(spus, | |
| 187 | - spuDTO -> ObjectUtil.notEqual(ProductSpuStatusEnum.ENABLE.getStatus(), spuDTO.getStatus())); | |
| 188 | - if (spu != null) { | |
| 189 | - throw exception(ErrorCodeConstants.ORDER_CREATE_SPU_NOT_SALE); | |
| 190 | - } | |
| 191 | - return spus; | |
| 159 | + return order.getId(); | |
| 192 | 160 | } |
| 193 | 161 | |
| 194 | 162 | /** |
| ... | ... | @@ -200,33 +168,35 @@ public class TradeOrderServiceImpl implements TradeOrderService { |
| 200 | 168 | */ |
| 201 | 169 | private AddressRespDTO validateAddress(Long userId, Long addressId) { |
| 202 | 170 | AddressRespDTO address = addressApi.getAddress(addressId, userId); |
| 203 | - if (Objects.isNull(address)) { | |
| 171 | + if (address == null) { | |
| 204 | 172 | throw exception(ErrorCodeConstants.ORDER_CREATE_ADDRESS_NOT_FOUND); |
| 205 | 173 | } |
| 206 | 174 | return address; |
| 207 | 175 | } |
| 208 | 176 | |
| 209 | 177 | private TradeOrderDO createTradeOrder(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO, |
| 210 | - PriceCalculateRespDTO.Order order, AddressRespDTO address) { | |
| 211 | - TradeOrderDO tradeOrderDO = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, order, address); | |
| 212 | - tradeOrderDO.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @LeeYan9: 思考下, 怎么生成好点哈; 这个是会展示给用户的; | |
| 213 | - tradeOrderDO.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); | |
| 214 | - tradeOrderDO.setType(TradeOrderTypeEnum.NORMAL.getType()); | |
| 215 | - tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); | |
| 216 | - tradeOrderDO.setProductCount(getSumValue(order.getItems(), PriceCalculateRespDTO.OrderItem::getCount, Integer::sum)); | |
| 217 | - tradeOrderDO.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源? | |
| 218 | - tradeOrderDO.setAdjustPrice(0).setPayed(false); // 支付信息 | |
| 219 | - tradeOrderDO.setDeliveryStatus(TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus()); // 物流信息 | |
| 220 | - tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0); // 退款信息 | |
| 221 | - tradeOrderMapper.insert(tradeOrderDO); | |
| 222 | - return tradeOrderDO; | |
| 178 | + TradePriceCalculateRespBO calculateRespBO, AddressRespDTO address) { | |
| 179 | + TradeOrderDO order = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, calculateRespBO, address); | |
| 180 | + order.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @LeeYan9: 思考下, 怎么生成好点哈; 这个是会展示给用户的; | |
| 181 | + order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); | |
| 182 | + order.setType(TradeOrderTypeEnum.NORMAL.getType()); | |
| 183 | + order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); | |
| 184 | + order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum)); | |
| 185 | + order.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源? | |
| 186 | + // 支付信息 | |
| 187 | + order.setAdjustPrice(0).setPayed(false); | |
| 188 | + // 物流信息 TODO 芋艿:暂时写死物流方式;应该是前端选择的 | |
| 189 | + order.setDeliveryType(DeliveryTypeEnum.EXPRESS.getMode()).setDeliveryStatus(TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus()); | |
| 190 | + // 退款信息 | |
| 191 | + order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0); | |
| 192 | + tradeOrderMapper.insert(order); | |
| 193 | + return order; | |
| 223 | 194 | } |
| 224 | 195 | |
| 225 | - private List<TradeOrderItemDO> createTradeOrderItems(TradeOrderDO tradeOrderDO, | |
| 226 | - List<PriceCalculateRespDTO.OrderItem> orderItems, List<ProductSkuRespDTO> skus) { | |
| 227 | - List<TradeOrderItemDO> tradeOrderItemDOs = TradeOrderConvert.INSTANCE.convertList(tradeOrderDO, orderItems, skus); | |
| 228 | - tradeOrderItemMapper.insertBatch(tradeOrderItemDOs); | |
| 229 | - return tradeOrderItemDOs; | |
| 196 | + private List<TradeOrderItemDO> createTradeOrderItems(TradeOrderDO tradeOrderDO, TradePriceCalculateRespBO calculateRespBO) { | |
| 197 | + List<TradeOrderItemDO> orderItems = TradeOrderConvert.INSTANCE.convertList(tradeOrderDO, calculateRespBO); | |
| 198 | + tradeOrderItemMapper.insertBatch(orderItems); | |
| 199 | + return orderItems; | |
| 230 | 200 | } |
| 231 | 201 | |
| 232 | 202 | /** |
| ... | ... | @@ -237,12 +207,13 @@ public class TradeOrderServiceImpl implements TradeOrderService { |
| 237 | 207 | * @param userId 用户编号 |
| 238 | 208 | * @param createReqVO 创建订单请求 |
| 239 | 209 | * @param tradeOrderDO 交易订单 |
| 210 | + * @param calculateRespBO 订单价格计算结果 | |
| 240 | 211 | */ |
| 241 | 212 | private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, |
| 242 | - TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> tradeOrderItemDOs, | |
| 243 | - List<ProductSpuRespDTO> spus) { | |
| 213 | + TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> orderItems, | |
| 214 | + TradePriceCalculateRespBO calculateRespBO) { | |
| 244 | 215 | // 下单时扣减商品库存 |
| 245 | - productSkuApi.updateSkuStock(new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(tradeOrderItemDOs))); | |
| 216 | + productSkuApi.updateSkuStock(new ProductSkuUpdateStockReqDTO(TradeOrderConvert.INSTANCE.convertList(orderItems))); | |
| 246 | 217 | |
| 247 | 218 | // 删除购物车商品 TODO 芋艿:待实现 |
| 248 | 219 | |
| ... | ... | @@ -255,20 +226,19 @@ public class TradeOrderServiceImpl implements TradeOrderService { |
| 255 | 226 | } |
| 256 | 227 | |
| 257 | 228 | // 生成预支付 |
| 258 | - createPayOrder(tradeOrderDO, tradeOrderItemDOs, spus); | |
| 229 | + createPayOrder(tradeOrderDO, orderItems, calculateRespBO); | |
| 259 | 230 | |
| 260 | 231 | // 增加订单日志 TODO 芋艿:待实现 |
| 261 | 232 | } |
| 262 | 233 | |
| 263 | - private void createPayOrder(TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> tradeOrderItemDOs, | |
| 264 | - List<ProductSpuRespDTO> spus) { | |
| 234 | + private void createPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems, TradePriceCalculateRespBO calculateRespBO) { | |
| 265 | 235 | // 创建支付单,用于后续的支付 |
| 266 | 236 | PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert( |
| 267 | - tradeOrderDO, tradeOrderItemDOs, spus, tradeOrderProperties); | |
| 237 | + order, orderItems, calculateRespBO, tradeOrderProperties); | |
| 268 | 238 | Long payOrderId = payOrderApi.createOrder(payOrderCreateReqDTO); |
| 269 | 239 | |
| 270 | 240 | // 更新到交易单上 |
| 271 | - tradeOrderMapper.updateById(new TradeOrderDO().setId(tradeOrderDO.getId()).setPayOrderId(payOrderId)); | |
| 241 | + tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setPayOrderId(payOrderId)); | |
| 272 | 242 | } |
| 273 | 243 | |
| 274 | 244 | @Override | ... | ... |