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,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 |