Commit 636b14cccec2b8f5d30db81e18817d23c31aaf73

Authored by YunaiV
1 parent 2a9a869e

mall + trade:创建订单逻辑,接入新的价格接口

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,27 +8,22 @@ GET {{appApi}}/trade/order/settlement?type=0&items[0].cartId=50&couponId=1
8 Authorization: Bearer {{appToken}} 8 Authorization: Bearer {{appToken}}
9 tenant-id: {{appTenentId}} 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 POST {{appApi}}/trade/order/create 12 POST {{appApi}}/trade/order/create
18 Content-Type: application/json 13 Content-Type: application/json
19 Authorization: Bearer {{appToken}} 14 Authorization: Bearer {{appToken}}
20 tenant-id: {{appTenentId}} 15 tenant-id: {{appTenentId}}
21 16
22 { 17 {
  18 + "type": 0,
23 "addressId": 21, 19 "addressId": 21,
24 - "remark": "我是备注",  
25 - "fromCart": false,  
26 "items": [ 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,7 +22,6 @@ import org.springframework.validation.annotation.Validated;
22 import org.springframework.web.bind.annotation.*; 22 import org.springframework.web.bind.annotation.*;
23 23
24 import javax.annotation.Resource; 24 import javax.annotation.Resource;
25 -import javax.servlet.http.HttpServletRequest;  
26 import javax.validation.Valid; 25 import javax.validation.Valid;
27 import java.util.HashMap; 26 import java.util.HashMap;
28 import java.util.List; 27 import java.util.List;
@@ -30,6 +29,7 @@ import java.util.Map; @@ -30,6 +29,7 @@ import java.util.Map;
30 29
31 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 30 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
32 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 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 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 33 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
34 34
35 @Tag(name = "用户 App - 交易订单") 35 @Tag(name = "用户 App - 交易订单")
@@ -58,15 +58,9 @@ public class AppTradeOrderController { @@ -58,15 +58,9 @@ public class AppTradeOrderController {
58 @PostMapping("/create") 58 @PostMapping("/create")
59 @Operation(summary = "创建订单") 59 @Operation(summary = "创建订单")
60 @PreAuthenticated 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 @PostMapping("/update-paid") 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,26 +3,9 @@ package cn.iocoder.yudao.module.trade.controller.app.order.vo;
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 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 @Schema(description = "用户 App - 交易订单创建 Request VO") 6 @Schema(description = "用户 App - 交易订单创建 Request VO")
11 @Data 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 @Schema(description = "备注", example = "这个是我的订单哟") 10 @Schema(description = "备注", example = "这个是我的订单哟")
28 private String remark; 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,11 +9,8 @@ import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
9 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; 9 import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
10 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; 10 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
11 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; 11 import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
12 -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;  
13 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 12 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
14 -import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;  
15 import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; 13 import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
16 -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;  
17 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; 14 import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO;
18 import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; 15 import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO;
19 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO; 16 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO;
@@ -50,32 +47,32 @@ public interface TradeOrderConvert { @@ -50,32 +47,32 @@ public interface TradeOrderConvert {
50 @Mapping(source = "createReqVO.couponId", target = "couponId"), 47 @Mapping(source = "createReqVO.couponId", target = "couponId"),
51 @Mapping(target = "remark", ignore = true), 48 @Mapping(target = "remark", ignore = true),
52 @Mapping(source = "createReqVO.remark", target = "userRemark"), 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 @Mapping(source = "address.name", target = "receiverName"), 57 @Mapping(source = "address.name", target = "receiverName"),
54 @Mapping(source = "address.mobile", target = "receiverMobile"), 58 @Mapping(source = "address.mobile", target = "receiverMobile"),
55 @Mapping(source = "address.areaId", target = "receiverAreaId"), 59 @Mapping(source = "address.areaId", target = "receiverAreaId"),
56 @Mapping(source = "address.detailAddress", target = "receiverDetailAddress"), 60 @Mapping(source = "address.detailAddress", target = "receiverDetailAddress"),
57 }) 61 })
58 TradeOrderDO convert(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO, 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 @Mapping(source = "userId" , target = "userId") 77 @Mapping(source = "userId" , target = "userId")
81 PriceCalculateReqDTO convert(AppTradeOrderCreateReqVO createReqVO, Long userId); 78 PriceCalculateReqDTO convert(AppTradeOrderCreateReqVO createReqVO, Long userId);
@@ -87,19 +84,20 @@ public interface TradeOrderConvert { @@ -87,19 +84,20 @@ public interface TradeOrderConvert {
87 ProductSkuUpdateStockReqDTO.Item convert(TradeOrderItemDO bean); 84 ProductSkuUpdateStockReqDTO.Item convert(TradeOrderItemDO bean);
88 List<ProductSkuUpdateStockReqDTO.Item> convertList(List<TradeOrderItemDO> list); 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 PayOrderCreateReqDTO createReqDTO = new PayOrderCreateReqDTO() 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 subject += " 等多件"; 95 subject += " 等多件";
99 } 96 }
100 createReqDTO.setSubject(subject); 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 return createReqDTO; 101 return createReqDTO;
104 } 102 }
105 103
@@ -113,6 +111,7 @@ public interface TradeOrderConvert { @@ -113,6 +111,7 @@ public interface TradeOrderConvert {
113 .collect(Collectors.toSet()); 111 .collect(Collectors.toSet());
114 } 112 }
115 113
  114 + // TODO 芋艿:可简化
116 default PageResult<TradeOrderPageItemRespVO> convertPage(PageResult<TradeOrderDO> pageResult, List<TradeOrderItemDO> orderItems, 115 default PageResult<TradeOrderPageItemRespVO> convertPage(PageResult<TradeOrderDO> pageResult, List<TradeOrderItemDO> orderItems,
117 List<ProductPropertyValueDetailRespDTO> propertyValueDetails) { 116 List<ProductPropertyValueDetailRespDTO> propertyValueDetails) {
118 Map<Long, List<TradeOrderItemDO>> orderItemMap = convertMultiMap(orderItems, TradeOrderItemDO::getOrderId); 117 Map<Long, List<TradeOrderItemDO>> orderItemMap = convertMultiMap(orderItems, TradeOrderItemDO::getOrderId);
@@ -149,6 +148,7 @@ public interface TradeOrderConvert { @@ -149,6 +148,7 @@ public interface TradeOrderConvert {
149 TradeOrderPageItemRespVO convert(TradeOrderDO order, List<TradeOrderItemDO> items); 148 TradeOrderPageItemRespVO convert(TradeOrderDO order, List<TradeOrderItemDO> items);
150 ProductPropertyValueDetailRespVO convert(ProductPropertyValueDetailRespDTO bean); 149 ProductPropertyValueDetailRespVO convert(ProductPropertyValueDetailRespDTO bean);
151 150
  151 + // TODO 芋艿:可简化
152 default TradeOrderDetailRespVO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems, 152 default TradeOrderDetailRespVO convert(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
153 List<ProductPropertyValueDetailRespDTO> propertyValueDetails, MemberUserRespDTO user) { 153 List<ProductPropertyValueDetailRespDTO> propertyValueDetails, MemberUserRespDTO user) {
154 TradeOrderDetailRespVO orderVO = convert2(order, orderItems); 154 TradeOrderDetailRespVO orderVO = convert2(order, orderItems);
@@ -179,6 +179,7 @@ public interface TradeOrderConvert { @@ -179,6 +179,7 @@ public interface TradeOrderConvert {
179 TradeOrderDetailRespVO convert2(TradeOrderDO order, List<TradeOrderItemDO> items); 179 TradeOrderDetailRespVO convert2(TradeOrderDO order, List<TradeOrderItemDO> items);
180 MemberUserRespVO convert(MemberUserRespDTO bean); 180 MemberUserRespVO convert(MemberUserRespDTO bean);
181 181
  182 + // TODO 芋艿:可简化
182 default PageResult<AppTradeOrderPageItemRespVO> convertPage02(PageResult<TradeOrderDO> pageResult, List<TradeOrderItemDO> orderItems, 183 default PageResult<AppTradeOrderPageItemRespVO> convertPage02(PageResult<TradeOrderDO> pageResult, List<TradeOrderItemDO> orderItems,
183 List<ProductPropertyValueDetailRespDTO> propertyValueDetails) { 184 List<ProductPropertyValueDetailRespDTO> propertyValueDetails) {
184 Map<Long, List<TradeOrderItemDO>> orderItemMap = convertMultiMap(orderItems, TradeOrderItemDO::getOrderId); 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,11 +167,24 @@ public class TradeOrderItemDO extends BaseDO {
167 */ 167 */
168 private Long propertyId; 168 private Long propertyId;
169 /** 169 /**
  170 + * 属性名字
  171 + *
  172 + * 关联 ProductPropertyDO 的 name 字段
  173 + */
  174 + private String propertyName;
  175 +
  176 + /**
170 * 属性值编号 177 * 属性值编号
171 * 178 *
172 * 关联 ProductPropertyValueDO 的 id 编号 179 * 关联 ProductPropertyValueDO 的 id 编号
173 */ 180 */
174 private Long valueId; 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 package cn.iocoder.yudao.module.trade.service.order; 1 package cn.iocoder.yudao.module.trade.service.order;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.lang.Assert;
4 import cn.hutool.core.util.IdUtil; 5 import cn.hutool.core.util.IdUtil;
5 import cn.hutool.core.util.ObjectUtil; 6 import cn.hutool.core.util.ObjectUtil;
6 import cn.hutool.core.util.StrUtil; 7 import cn.hutool.core.util.StrUtil;
7 import cn.iocoder.yudao.framework.common.core.KeyValue; 8 import cn.iocoder.yudao.framework.common.core.KeyValue;
8 import cn.iocoder.yudao.framework.common.enums.TerminalEnum; 9 import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
9 import cn.iocoder.yudao.framework.common.pojo.PageResult; 10 import cn.iocoder.yudao.framework.common.pojo.PageResult;
10 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;  
11 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 11 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
12 import cn.iocoder.yudao.module.member.api.address.AddressApi; 12 import cn.iocoder.yudao.module.member.api.address.AddressApi;
13 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; 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,15 +18,9 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
18 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; 18 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
19 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; 19 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
20 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; 20 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
21 -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;  
22 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; 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 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; 22 import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
27 import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; 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 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; 24 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
31 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; 25 import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
32 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; 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,6 +34,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
40 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; 34 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
41 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; 35 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
42 import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants; 36 import cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants;
  37 +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
43 import cn.iocoder.yudao.module.trade.enums.order.*; 38 import cn.iocoder.yudao.module.trade.enums.order.*;
44 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; 39 import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
45 import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; 40 import cn.iocoder.yudao.module.trade.service.cart.TradeCartService;
@@ -55,7 +50,8 @@ import java.time.LocalDateTime; @@ -55,7 +50,8 @@ import java.time.LocalDateTime;
55 import java.util.*; 50 import java.util.*;
56 51
57 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 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 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND; 55 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_ORDER_NOT_FOUND;
60 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*; 56 import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
61 57
@@ -80,12 +76,8 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -80,12 +76,8 @@ public class TradeOrderServiceImpl implements TradeOrderService {
80 private TradePriceService tradePriceService; 76 private TradePriceService tradePriceService;
81 77
82 @Resource 78 @Resource
83 - private PriceApi priceApi;  
84 - @Resource  
85 private ProductSkuApi productSkuApi; 79 private ProductSkuApi productSkuApi;
86 @Resource 80 @Resource
87 - private ProductSpuApi productSpuApi;  
88 - @Resource  
89 private PayOrderApi payOrderApi; 81 private PayOrderApi payOrderApi;
90 @Resource 82 @Resource
91 private AddressApi addressApi; 83 private AddressApi addressApi;
@@ -142,53 +134,29 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -142,53 +134,29 @@ public class TradeOrderServiceImpl implements TradeOrderService {
142 134
143 // 2. 计算价格 135 // 2. 计算价格
144 TradePriceCalculateReqBO calculateReqBO = TradeOrderConvert.INSTANCE.convert(userId, settlementReqVO, cartList); 136 TradePriceCalculateReqBO calculateReqBO = TradeOrderConvert.INSTANCE.convert(userId, settlementReqVO, cartList);
  137 + calculateReqBO.getItems().forEach(item -> Assert.isTrue(item.getSelected(), // 防御性编程,保证都是选中的
  138 + "商品({}) 未设置为选中", item.getSkuId()));
145 return tradePriceService.calculatePrice(calculateReqBO); 139 return tradePriceService.calculatePrice(calculateReqBO);
146 } 140 }
147 141
148 @Override 142 @Override
149 @Transactional(rollbackFor = Exception.class) 143 @Transactional(rollbackFor = Exception.class)
150 public Long createOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) { 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 AddressRespDTO address = validateAddress(userId, createReqVO.getAddressId()); 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 // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! 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,33 +168,35 @@ public class TradeOrderServiceImpl implements TradeOrderService {
200 */ 168 */
201 private AddressRespDTO validateAddress(Long userId, Long addressId) { 169 private AddressRespDTO validateAddress(Long userId, Long addressId) {
202 AddressRespDTO address = addressApi.getAddress(addressId, userId); 170 AddressRespDTO address = addressApi.getAddress(addressId, userId);
203 - if (Objects.isNull(address)) { 171 + if (address == null) {
204 throw exception(ErrorCodeConstants.ORDER_CREATE_ADDRESS_NOT_FOUND); 172 throw exception(ErrorCodeConstants.ORDER_CREATE_ADDRESS_NOT_FOUND);
205 } 173 }
206 return address; 174 return address;
207 } 175 }
208 176
209 private TradeOrderDO createTradeOrder(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO, 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,12 +207,13 @@ public class TradeOrderServiceImpl implements TradeOrderService {
237 * @param userId 用户编号 207 * @param userId 用户编号
238 * @param createReqVO 创建订单请求 208 * @param createReqVO 创建订单请求
239 * @param tradeOrderDO 交易订单 209 * @param tradeOrderDO 交易订单
  210 + * @param calculateRespBO 订单价格计算结果
240 */ 211 */
241 private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, 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 // 删除购物车商品 TODO 芋艿:待实现 218 // 删除购物车商品 TODO 芋艿:待实现
248 219
@@ -255,20 +226,19 @@ public class TradeOrderServiceImpl implements TradeOrderService { @@ -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 // 增加订单日志 TODO 芋艿:待实现 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 PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert( 236 PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert(
267 - tradeOrderDO, tradeOrderItemDOs, spus, tradeOrderProperties); 237 + order, orderItems, calculateRespBO, tradeOrderProperties);
268 Long payOrderId = payOrderApi.createOrder(payOrderCreateReqDTO); 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 @Override 244 @Override