mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 18:28:43 +08:00 
			
		
		
		
	trade:优化创建订单接口的后端实现
This commit is contained in:
		| @@ -1,6 +1,6 @@ | |||||||
| package cn.iocoder.yudao.module.product.api.spu; | package cn.iocoder.yudao.module.product.api.spu; | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.module.product.api.spu.dto.SpuInfoRespDTO; | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | ||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| @@ -19,6 +19,6 @@ public interface ProductSpuApi { | |||||||
|      * @param ids SPU 编号列表 |      * @param ids SPU 编号列表 | ||||||
|      * @return SPU 数组 |      * @return SPU 数组 | ||||||
|      */ |      */ | ||||||
|     List<SpuInfoRespDTO> getSpuList(Collection<Long> ids); |     List<ProductSpuRespDTO> getSpuList(Collection<Long> ids); | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,11 +9,13 @@ import java.util.List; | |||||||
| 
 | 
 | ||||||
| // TODO @LeeYan9: ProductSpuRespDTO | // TODO @LeeYan9: ProductSpuRespDTO | ||||||
| /** | /** | ||||||
|  |  * 商品 SPU 信息 Response DTO | ||||||
|  |  * | ||||||
|  * @author LeeYan9 |  * @author LeeYan9 | ||||||
|  * @since 2022-08-26 |  * @since 2022-08-26 | ||||||
|  */ |  */ | ||||||
| @Data | @Data | ||||||
| public class SpuInfoRespDTO { | public class ProductSpuRespDTO { | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * 商品 SPU 编号,自增 |      * 商品 SPU 编号,自增 | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| package cn.iocoder.yudao.module.product.api.spu; | package cn.iocoder.yudao.module.product.api.spu; | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||||
| import cn.iocoder.yudao.module.product.api.spu.dto.SpuInfoRespDTO; | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | ||||||
| import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | ||||||
| import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | ||||||
| import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; | import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; | ||||||
| @@ -27,7 +27,7 @@ public class ProductSpuApiImpl implements ProductSpuApi { | |||||||
|     private ProductSpuMapper productSpuMapper; |     private ProductSpuMapper productSpuMapper; | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public List<SpuInfoRespDTO> getSpuList(Collection<Long> spuIds) { |     public List<ProductSpuRespDTO> getSpuList(Collection<Long> spuIds) { | ||||||
|         // TODO TODO LeeYan9: AllEmpty? |         // TODO TODO LeeYan9: AllEmpty? | ||||||
|         if (CollectionUtils.isAnyEmpty(spuIds)) { |         if (CollectionUtils.isAnyEmpty(spuIds)) { | ||||||
|             return Collections.emptyList(); |             return Collections.emptyList(); | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| package cn.iocoder.yudao.module.product.convert.spu; | package cn.iocoder.yudao.module.product.convert.spu; | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
| import cn.iocoder.yudao.module.product.api.spu.dto.SpuInfoRespDTO; | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | ||||||
| import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; | ||||||
| import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO; | ||||||
| import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO; | ||||||
| @@ -35,7 +35,7 @@ public interface ProductSpuConvert { | |||||||
|  |  | ||||||
|     AppSpuPageRespVO convertAppResp(ProductSpuDO list); |     AppSpuPageRespVO convertAppResp(ProductSpuDO list); | ||||||
|  |  | ||||||
|     List<SpuInfoRespDTO> convertList2(List<ProductSpuDO> list); |     List<ProductSpuRespDTO> convertList2(List<ProductSpuDO> list); | ||||||
|  |  | ||||||
|     List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list); |     List<ProductSpuSimpleRespVO> convertList02(List<ProductSpuDO> list); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -22,17 +22,17 @@ public interface ErrorCodeConstants { | |||||||
|  |  | ||||||
|     // ========== Coupon 相关 1003003000 ============ |     // ========== Coupon 相关 1003003000 ============ | ||||||
|     ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1003003000, "优惠劵没有可使用的商品!"); |     ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1003003000, "优惠劵没有可使用的商品!"); | ||||||
|     ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1003003000, "不满足优惠劵使用的最低金额"); |     ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1003003000, "所结算的商品中未满足使用的金额"); | ||||||
|  |  | ||||||
|     // ========== 优惠劵模板 1003004000 ========== |     // ========== 优惠劵模板 1003004000 ========== | ||||||
|     ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1003004000, "优惠劵模板不存在"); |     ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1003004000, "优惠劵模板不存在"); | ||||||
|     ErrorCode COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL = new ErrorCode(1003004001, "发放数量不能小于已领取数量({})"); |     ErrorCode COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL = new ErrorCode(1003004001, "发放数量不能小于已领取数量({})"); | ||||||
|  |  | ||||||
|     // ========== 优惠劵模板 1003005000 ========== |     // ========== 优惠劵模板 1003005000 ========== | ||||||
|     ErrorCode COUPON_NOT_EXISTS = new ErrorCode(1003005000, "优惠劵不存在"); |     ErrorCode COUPON_NOT_EXISTS = new ErrorCode(1003005000, "优惠券不存在"); | ||||||
|     ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1003005001, "回收优惠劵失败,优惠劵已被使用"); |     ErrorCode COUPON_DELETE_FAIL_USED = new ErrorCode(1003005001, "回收优惠劵失败,优惠劵已被使用"); | ||||||
|     ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1006003003, "优惠劵不处于待使用状态"); |     ErrorCode COUPON_STATUS_NOT_UNUSED = new ErrorCode(1006003003, "优惠劵不处于待使用状态"); | ||||||
|     ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1006003004, "优惠劵不在有效期内"); |     ErrorCode COUPON_VALID_TIME_NOT_NOW = new ErrorCode(1006003004, "优惠券不在使用时间范围内"); | ||||||
|  |  | ||||||
|     // ========== 满减送活动 1003006000 ========== |     // ========== 满减送活动 1003006000 ========== | ||||||
|     ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1003006000, "满减送活动不存在"); |     ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1003006000, "满减送活动不存在"); | ||||||
|   | |||||||
| @@ -116,7 +116,8 @@ public class PriceServiceImpl implements PriceService { | |||||||
|                 assert originPrice != null; |                 assert originPrice != null; | ||||||
|                 if (originPrice < coupon.getUsePrice()) { |                 if (originPrice < coupon.getUsePrice()) { | ||||||
|                     return couponMeetRespDTO.setMeet(false) |                     return couponMeetRespDTO.setMeet(false) | ||||||
|                             .setMeetTip(String.format("差 %s 元可用优惠劵", formatPrice(coupon.getUsePrice() - originPrice))); | //                            .setMeetTip(String.format("差 %s 元可用优惠劵", formatPrice(coupon.getUsePrice() - originPrice))); | ||||||
|  |                             .setMeetTip("所结算的商品中未满足使用的金额"); | ||||||
|                 } |                 } | ||||||
|             } catch (ServiceException serviceException) { |             } catch (ServiceException serviceException) { | ||||||
|                 couponMeetRespDTO.setMeet(false); |                 couponMeetRespDTO.setMeet(false); | ||||||
|   | |||||||
| @@ -12,10 +12,12 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | |||||||
| public interface ErrorCodeConstants { | public interface ErrorCodeConstants { | ||||||
|  |  | ||||||
|     // ==========  Order 模块 1-011-000-000 ========== |     // ==========  Order 模块 1-011-000-000 ========== | ||||||
|     ErrorCode ORDER_SKU_NOT_FOUND = new ErrorCode(1011000001, "商品不存在"); |     ErrorCode ORDER_CREATE_SKU_NOT_FOUND = new ErrorCode(1011000001, "商品 SKU 不存在"); | ||||||
|     ErrorCode ORDER_SPU_NOT_SALE = new ErrorCode(1011000002, "商品不可售卖"); |     ErrorCode ORDER_CREATE_SPU_NOT_SALE = new ErrorCode(1011000002, "商品 SPU 不可售卖"); | ||||||
|     ErrorCode ORDER_SKU_NOT_SALE = new ErrorCode(1011000003, "商品Sku不可售卖"); |     ErrorCode ORDER_CREATE_SKU_NOT_SALE = new ErrorCode(1011000003, "商品 SKU 不可售卖"); | ||||||
|     ErrorCode ORDER_SKU_STOCK_NOT_ENOUGH = new ErrorCode(1011000004, "商品库存不足"); |     ErrorCode ORDER_CREATE_SKU_STOCK_NOT_ENOUGH = new ErrorCode(1011000004, "商品 SKU 库存不足"); | ||||||
|  |     ErrorCode ORDER_CREATE_SPU_NOT_FOUND = new ErrorCode(1011000005, "商品 SPU 不可售卖"); | ||||||
|  |     ErrorCode ORDER_CREATE_ADDRESS_NOT_FOUND = new ErrorCode(1011000006, "收货地址不存在"); | ||||||
|  |  | ||||||
|     // ==========  Cart 模块 1-011-001-000 ========== |     // ==========  Cart 模块 1-011-001-000 ========== | ||||||
|     ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1001001000, "购物车项不存在"); |     ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1001001000, "购物车项不存在"); | ||||||
|   | |||||||
| @@ -29,18 +29,21 @@ | |||||||
|             <artifactId>yudao-module-product-api</artifactId> |             <artifactId>yudao-module-product-api</artifactId> | ||||||
|             <version>${revision}</version> |             <version>${revision}</version> | ||||||
|         </dependency> |         </dependency> | ||||||
|  |  | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>cn.iocoder.boot</groupId> |             <groupId>cn.iocoder.boot</groupId> | ||||||
|             <artifactId>yudao-module-pay-api</artifactId> |             <artifactId>yudao-module-pay-api</artifactId> | ||||||
|             <version>${revision}</version> |             <version>${revision}</version> | ||||||
|         </dependency> |         </dependency> | ||||||
|  |  | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>cn.iocoder.boot</groupId> |             <groupId>cn.iocoder.boot</groupId> | ||||||
|             <artifactId>yudao-module-promotion-api</artifactId> |             <artifactId>yudao-module-promotion-api</artifactId> | ||||||
|             <version>${revision}</version> |             <version>${revision}</version> | ||||||
|         </dependency> |         </dependency> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>cn.iocoder.boot</groupId> | ||||||
|  |             <artifactId>yudao-module-member-api</artifactId> | ||||||
|  |             <version>${revision}</version> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|         <!-- 业务组件 --> |         <!-- 业务组件 --> | ||||||
|         <dependency> |         <dependency> | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty; | |||||||
| import lombok.Data; | import lombok.Data; | ||||||
|  |  | ||||||
| import javax.validation.constraints.Min; | import javax.validation.constraints.Min; | ||||||
|  | import javax.validation.constraints.NotEmpty; | ||||||
| import javax.validation.constraints.NotNull; | import javax.validation.constraints.NotNull; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  |  | ||||||
| @@ -14,7 +15,7 @@ public class AppTradeOrderCreateReqVO { | |||||||
|  |  | ||||||
|     @ApiModelProperty(name = "收件地址编号", required = true, example = "1") |     @ApiModelProperty(name = "收件地址编号", required = true, example = "1") | ||||||
|     @NotNull(message = "收件地址不能为空") |     @NotNull(message = "收件地址不能为空") | ||||||
|     private Integer addressId; |     private Long addressId; | ||||||
|  |  | ||||||
|     @ApiModelProperty(name = "优惠劵编号", example = "1024") |     @ApiModelProperty(name = "优惠劵编号", example = "1024") | ||||||
|     private Long couponId; |     private Long couponId; | ||||||
| @@ -29,7 +30,7 @@ public class AppTradeOrderCreateReqVO { | |||||||
|     /** |     /** | ||||||
|      * 订单商品项列表 |      * 订单商品项列表 | ||||||
|      */ |      */ | ||||||
|     @NotNull(message = "必须选择购买的商品") |     @NotEmpty(message = "必须选择购买的商品") | ||||||
|     private List<Item> items; |     private List<Item> items; | ||||||
|  |  | ||||||
|     @ApiModel(value = "订单商品项") |     @ApiModel(value = "订单商品项") | ||||||
|   | |||||||
| @@ -1,24 +1,58 @@ | |||||||
| package cn.iocoder.yudao.module.trade.convert.order; | package cn.iocoder.yudao.module.trade.convert.order; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||||
|  | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; | ||||||
|  | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | ||||||
| import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; | import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; | ||||||
| import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; | ||||||
| import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | ||||||
|  | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | ||||||
|  | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemRefundStatusEnum; | ||||||
| import org.mapstruct.Mapper; | import org.mapstruct.Mapper; | ||||||
| import org.mapstruct.Mapping; | import org.mapstruct.Mapping; | ||||||
| import org.mapstruct.Mappings; | import org.mapstruct.Mappings; | ||||||
| import org.mapstruct.factory.Mappers; | import org.mapstruct.factory.Mappers; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
|  | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | ||||||
|  |  | ||||||
| @Mapper | @Mapper | ||||||
| public interface TradeOrderConvert { | public interface TradeOrderConvert { | ||||||
|  |  | ||||||
|     TradeOrderConvert INSTANCE = Mappers.getMapper(TradeOrderConvert.class); |     TradeOrderConvert INSTANCE = Mappers.getMapper(TradeOrderConvert.class); | ||||||
|  |  | ||||||
|     @Mappings({ |     @Mappings({ | ||||||
|             @Mapping(source = "order.couponId", target = "couponId"), |             @Mapping(source = "createReqVO.couponId", target = "couponId"), | ||||||
|             @Mapping(target = "remark", ignore = true), |             @Mapping(target = "remark", ignore = true), | ||||||
|             @Mapping(source = "createVO.remark", target = "userRemark"), |             @Mapping(source = "createReqVO.remark", target = "userRemark"), | ||||||
|             @Mapping(source = "createVO.addressId", target = "receiverAreaId") |             @Mapping(source = "address.name", target = "receiverName"), | ||||||
|  |             @Mapping(source = "address.mobile", target = "receiverMobile"), | ||||||
|  |             @Mapping(source = "address.areaId", target = "receiverAreaId"), | ||||||
|  |             @Mapping(source = "address.postCode", target = "receiverPostCode"), | ||||||
|  |             @Mapping(source = "address.detailAddress", target = "receiverDetailAddress"), | ||||||
|     }) |     }) | ||||||
|     TradeOrderDO convert(AppTradeOrderCreateReqVO createVO, PriceCalculateRespDTO.Order order); |     TradeOrderDO convert(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO, | ||||||
|  |                          PriceCalculateRespDTO.Order order, AddressRespDTO address); | ||||||
|  |  | ||||||
|  |     @Mappings({ | ||||||
|  |             @Mapping(target = "id", ignore = true), | ||||||
|  |             @Mapping(source = "sku.spuId", target = "spuId"), | ||||||
|  |     }) | ||||||
|  |     TradeOrderItemDO convert(PriceCalculateRespDTO.OrderItem orderItem, ProductSkuRespDTO sku); | ||||||
|  |  | ||||||
|  |     default List<TradeOrderItemDO> convertList(TradeOrderDO tradeOrderDO, | ||||||
|  |                                                List<PriceCalculateRespDTO.OrderItem> orderItems, List<ProductSkuRespDTO> skus) { | ||||||
|  |         Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId); | ||||||
|  |         return CollectionUtils.convertList(orderItems, orderItem -> { | ||||||
|  |             TradeOrderItemDO tradeOrderItemDO = convert(orderItem, skuMap.get(orderItem.getSkuId())); | ||||||
|  |             tradeOrderItemDO.setOrderId(tradeOrderDO.getId()); | ||||||
|  |             tradeOrderItemDO.setUserId(tradeOrderDO.getUserId()); | ||||||
|  |             tradeOrderItemDO.setRefundStatus(TradeOrderItemRefundStatusEnum.NONE.getStatus()); | ||||||
|  | //            tradeOrderItemDO.setCommented(false); | ||||||
|  |             return tradeOrderItemDO; | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,17 +0,0 @@ | |||||||
| package cn.iocoder.yudao.module.trade.convert.order; |  | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; |  | ||||||
| import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |  | ||||||
| import org.mapstruct.Mapper; |  | ||||||
| import org.mapstruct.factory.Mappers; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| @Mapper |  | ||||||
| public interface TradeOrderItemConvert { |  | ||||||
|  |  | ||||||
|     TradeOrderItemConvert INSTANCE = Mappers.getMapper(TradeOrderItemConvert.class); |  | ||||||
|  |  | ||||||
|     List<TradeOrderItemDO> convertList(List<PriceCalculateRespDTO.OrderItem> items); |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -70,13 +70,13 @@ public class TradeOrderItemDO extends BaseDO { | |||||||
|      * 购买数量 |      * 购买数量 | ||||||
|      */ |      */ | ||||||
|     private Integer count; |     private Integer count; | ||||||
|     /** | //    /** | ||||||
|      * 是否评论 TODO | //     * 是否评论 TODO | ||||||
|      * | //     * | ||||||
|      * false - 未评论 | //     * false - 未评论 | ||||||
|      * true - 已评论 | //     * true - 已评论 | ||||||
|      */ | //     */ | ||||||
|     private Boolean commented; | //    private Boolean commented; | ||||||
|  |  | ||||||
|     // ========== 价格 + 支付基本信息 ========== |     // ========== 价格 + 支付基本信息 ========== | ||||||
|  |  | ||||||
| @@ -138,19 +138,19 @@ public class TradeOrderItemDO extends BaseDO { | |||||||
|      * 枚举 {@link TradeOrderItemRefundStatusEnum} |      * 枚举 {@link TradeOrderItemRefundStatusEnum} | ||||||
|      */ |      */ | ||||||
|     private Integer refundStatus; // TODO 芋艿:可以考虑去查 |     private Integer refundStatus; // TODO 芋艿:可以考虑去查 | ||||||
|     // 如上字段,举个例子: | //    // 如上字段,举个例子: | ||||||
|     // 假设购买三个,即 stock = 3 。 | //    // 假设购买三个,即 stock = 3 。 | ||||||
|     // originPrice = 15 | //    // originPrice = 15 | ||||||
|     // 使用限时折扣(单品优惠)8 折,buyPrice = 12 | //    // 使用限时折扣(单品优惠)8 折,buyPrice = 12 | ||||||
|     // 开始算总的价格 | //    // 开始算总的价格 | ||||||
|     // buyTotal = buyPrice * stock = 12 * 3 = 36 | //    // buyTotal = buyPrice * stock = 12 * 3 = 36 | ||||||
|     // discountTotal ,假设有满减送(分组优惠)满 20 减 10 ,并且使用优惠劵满 1.01 减 1 ,则 discountTotal = 10 + 1 = 11 | //    // discountTotal ,假设有满减送(分组优惠)满 20 减 10 ,并且使用优惠劵满 1.01 减 1 ,则 discountTotal = 10 + 1 = 11 | ||||||
|     // presentTotal = buyTotal - discountTotal = 24 - 11 = 13 | //    // presentTotal = buyTotal - discountTotal = 24 - 11 = 13 | ||||||
|     // 最终 presentPrice = presentTotal / stock = 13 / 3 = 4.33 | //    // 最终 presentPrice = presentTotal / stock = 13 / 3 = 4.33 | ||||||
|     /** | //    /** | ||||||
|      * 退款总金额,单位:分 TODO | //     * 退款总金额,单位:分 TODO | ||||||
|      */ | //     */ | ||||||
|     private Integer refundTotal; | //    private Integer refundTotal; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 商品属性 |      * 商品属性 | ||||||
|   | |||||||
| @@ -3,29 +3,27 @@ package cn.iocoder.yudao.module.trade.service.order; | |||||||
| import cn.hutool.core.bean.BeanUtil; | import cn.hutool.core.bean.BeanUtil; | ||||||
| import cn.hutool.core.text.StrBuilder; | import cn.hutool.core.text.StrBuilder; | ||||||
| import cn.hutool.core.util.IdUtil; | import cn.hutool.core.util.IdUtil; | ||||||
|  | import cn.hutool.core.util.ObjectUtil; | ||||||
| import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||||
| import cn.iocoder.yudao.framework.common.enums.TerminalEnum; | import cn.iocoder.yudao.framework.common.enums.TerminalEnum; | ||||||
| import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |  | ||||||
| import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||||||
| import cn.iocoder.yudao.framework.common.util.string.StrUtils; | import cn.iocoder.yudao.framework.common.util.string.StrUtils; | ||||||
| import cn.iocoder.yudao.module.promotion.api.price.PriceApi; | import cn.iocoder.yudao.module.member.api.address.AddressApi; | ||||||
| import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; | ||||||
| import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; |  | ||||||
| import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; | import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; | ||||||
| import cn.iocoder.yudao.module.pay.api.order.PayOrderInfoCreateReqDTO; | import cn.iocoder.yudao.module.pay.api.order.PayOrderInfoCreateReqDTO; | ||||||
| import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | ||||||
| import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | ||||||
| import cn.iocoder.yudao.module.product.api.sku.dto.SkuDecrementStockBatchReqDTO; |  | ||||||
| import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | ||||||
| import cn.iocoder.yudao.module.product.api.spu.dto.SpuInfoRespDTO; | import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | ||||||
| import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; | import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; | ||||||
|  | import cn.iocoder.yudao.module.promotion.api.price.PriceApi; | ||||||
|  | import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; | ||||||
|  | import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO; | ||||||
| import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; | ||||||
| import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO.Item; | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO.Item; | ||||||
| import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; | ||||||
| import cn.iocoder.yudao.module.trade.convert.order.TradeOrderItemConvert; |  | ||||||
| import cn.iocoder.yudao.module.trade.convert.pay.PayOrderConvert; |  | ||||||
| import cn.iocoder.yudao.module.trade.convert.price.PriceConvert; | import cn.iocoder.yudao.module.trade.convert.price.PriceConvert; | ||||||
| import cn.iocoder.yudao.module.trade.convert.sku.ProductSkuConvert; |  | ||||||
| import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | ||||||
| import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | ||||||
| import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper; | ||||||
| @@ -43,6 +41,12 @@ import javax.annotation.Resource; | |||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.Objects; | import java.util.Objects; | ||||||
|  | import java.util.Set; | ||||||
|  |  | ||||||
|  | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||||
|  | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | ||||||
|  | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_SKU_NOT_SALE; | ||||||
|  | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_SPU_NOT_FOUND; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 交易订单 Service 实现类 |  * 交易订单 Service 实现类 | ||||||
| @@ -70,66 +74,51 @@ public class TradeOrderServiceImpl implements TradeOrderService { | |||||||
|     private ProductSpuApi productSpuApi; |     private ProductSpuApi productSpuApi; | ||||||
|     @Resource |     @Resource | ||||||
|     private PayOrderApi payOrderApi; |     private PayOrderApi payOrderApi; | ||||||
|  |     @Resource | ||||||
|  |     private AddressApi addressApi; | ||||||
|  |  | ||||||
|     @Resource |     @Resource | ||||||
|     private TradeOrderProperties tradeOrderProperties; |     private TradeOrderProperties tradeOrderProperties; | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     @Transactional(rollbackFor = Exception.class) |     @Transactional(rollbackFor = Exception.class) | ||||||
|     public Long createTradeOrder(Long loginUserId, String clientIp, AppTradeOrderCreateReqVO createReqVO) { |     public Long createTradeOrder(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO) { | ||||||
|         List<Item> items = createReqVO.getItems(); |         // 商品 SKU 检查:可售状态、库存 | ||||||
|         // 商品SKU检查 sku可售状态,库存 |         List<ProductSkuRespDTO> skus = validateSkuSaleable(createReqVO.getItems()); | ||||||
|         List<ProductSkuRespDTO> skuInfos = productSkuApi.getSkuList(CollectionUtils.convertSet(items, Item::getSkuId)); |         // 商品 SPU 检查:可售状态 | ||||||
|         Map<Long, ProductSkuRespDTO> skuInfoMap = CollectionUtils.convertMap(skuInfos, ProductSkuRespDTO::getId); |         List<ProductSpuRespDTO> spus = validateSpuSaleable(convertSet(skus, ProductSkuRespDTO::getSpuId)); | ||||||
|         checkSaleableAndStockFromSpu(skuInfoMap, items); |         // 用户收件地址的校验 | ||||||
|  |         AddressRespDTO address = validateAddress(userId, createReqVO.getAddressId()); | ||||||
|         // 商品SPU检查 sku可售状态,库存 |  | ||||||
|         List<SpuInfoRespDTO> spuInfos = productSpuApi.getSpuList(CollectionUtils.convertSet(skuInfos, ProductSkuRespDTO::getSpuId)); |  | ||||||
|         checkSaleableFromSpu(spuInfos); |  | ||||||
|  |  | ||||||
|         // 价格计算 |         // 价格计算 | ||||||
|         PriceCalculateReqDTO priceCalculateReqDTO = PriceConvert.INSTANCE.convert(createReqVO, loginUserId); |         PriceCalculateReqDTO priceCalculateReqDTO = PriceConvert.INSTANCE.convert(createReqVO, userId); | ||||||
|         PriceCalculateRespDTO priceResp = priceApi.calculatePrice(priceCalculateReqDTO); |         PriceCalculateRespDTO priceResp = priceApi.calculatePrice(priceCalculateReqDTO); | ||||||
|         // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! |  | ||||||
|  |  | ||||||
|         // 订单信息记录 |         // 插入 TradeOrderDO 订单 | ||||||
|         TradeOrderDO tradeOrderDO = TradeOrderConvert.INSTANCE.convert(createReqVO, priceResp.getOrder()); |         TradeOrderDO tradeOrderDO = createTradeOrder(userId, clientIp, createReqVO, priceResp.getOrder(), address); | ||||||
|         fillTradeOrderInfoFromReqInfo(tradeOrderDO,createReqVO,loginUserId, clientIp); // TODO @LeeYan9: tradeOrderDO, createReqVO, loginUserId, clientIp |         // 插入 TradeOrderItemDO 订单项 | ||||||
|         tradeOrderMapper.insert(tradeOrderDO); |         createTradeOrderItems(tradeOrderDO, priceResp.getOrder().getItems(), skus); | ||||||
|  |  | ||||||
|         // 订单项信息记录 |         // 下单时扣减商品库存 TODO | ||||||
|         List<TradeOrderItemDO> tradeOrderItems = TradeOrderItemConvert.INSTANCE.convertList(priceResp.getOrder().getItems()); | //        List<SkuDecrementStockBatchReqDTO.Item> skuDecrementStockItems = ProductSkuConvert.INSTANCE.convert(tradeOrderItems); | ||||||
|         // 填充订单项-SKU信息 | //        productSkuApi.decrementStockBatch(SkuDecrementStockBatchReqDTO.of(skuDecrementStockItems)); | ||||||
|         fillItemsInfoFromSkuAndOrder(tradeOrderDO, tradeOrderItems, skuInfoMap); |  | ||||||
|         tradeOrderItemMapper.insertBatch(tradeOrderItems); |  | ||||||
|  |  | ||||||
|         // TODO @LeeYan9: 先扣减库存哈; 可能会扣减失败; 毕竟 get 和 update 之间, 会有并发的可能性 |         // 删除购物车商品 TODO 芋艿:待实现 | ||||||
|         // 库存扣减 |  | ||||||
|         List<SkuDecrementStockBatchReqDTO.Item> skuDecrementStockItems = ProductSkuConvert.INSTANCE.convert(tradeOrderItems); |         // 扣减积分,抵扣金额 TODO 芋艿:待实现 | ||||||
|         productSkuApi.decrementStockBatch(SkuDecrementStockBatchReqDTO.of(skuDecrementStockItems)); |  | ||||||
|  |         // 有使用优惠券时更新 | ||||||
|  |  | ||||||
|  |         // 增加订单日志 TODO 芋艿:待实现 | ||||||
|  |  | ||||||
|         // 构建预支付请求参数 |         // 构建预支付请求参数 | ||||||
|         // TODO @LeeYan9: 需要更新到订单上 |         // TODO @LeeYan9: 需要更新到订单上 | ||||||
|         PayOrderInfoCreateReqDTO payOrderCreateReqDTO = PayOrderConvert.INSTANCE.convert(tradeOrderDO); | //        PayOrderInfoCreateReqDTO payOrderCreateReqDTO = PayOrderConvert.INSTANCE.convert(tradeOrderDO); | ||||||
|         fillPayOrderInfoFromItems(payOrderCreateReqDTO, tradeOrderItems); | //        fillPayOrderInfoFromItems(payOrderCreateReqDTO, tradeOrderItems); | ||||||
|         // 生成预支付 |         // 生成预支付 | ||||||
|         return payOrderApi.createPayOrder(payOrderCreateReqDTO); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // TODO @LeeYan9: 填充就好, 不用 from 哈; |         // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! | ||||||
|     private void fillTradeOrderInfoFromReqInfo(TradeOrderDO tradeOrderDO, AppTradeOrderCreateReqVO createReqVO, |         return tradeOrderDO.getId(); | ||||||
|                                                Long loginUserId, String clientIp) { |  | ||||||
|         tradeOrderDO.setUserId(loginUserId); |  | ||||||
|         tradeOrderDO.setUserIp(clientIp); |  | ||||||
|         tradeOrderDO.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @LeeYan9: 思考下, 怎么生成好点哈; 这个是会展示给用户的; |  | ||||||
|         tradeOrderDO.setStatus(TradeOrderStatusEnum.WAITING_PAYMENT.getStatus()); |  | ||||||
|         tradeOrderDO.setType(TradeOrderTypeEnum.NORMAL.getType()); |  | ||||||
|         tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); |  | ||||||
|         tradeOrderDO.setProductCount(CollectionUtils.getSumValue(createReqVO.getItems(), Item::getCount,Integer::sum)); |  | ||||||
|         // todo 地址&用户信息解析 |  | ||||||
|  |  | ||||||
|         // todo 数据来源? |  | ||||||
|         tradeOrderDO.setTerminal(TerminalEnum.H5.getTerminal()); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void fillPayOrderInfoFromItems(PayOrderInfoCreateReqDTO payOrderInfoCreateReqDTO, |     private void fillPayOrderInfoFromItems(PayOrderInfoCreateReqDTO payOrderInfoCreateReqDTO, | ||||||
| @@ -157,7 +146,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | |||||||
|         payOrderInfoCreateReqDTO.setBody(StrUtils.maxLength(body.subString(1), 128)); |         payOrderInfoCreateReqDTO.setBody(StrUtils.maxLength(body.subString(1), 128)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void fillItemsInfoFromSkuAndOrder(TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> tradeOrderItems, |     private void xfillItemsInfoFromSkuAndOrder(TradeOrderDO tradeOrderDO, List<TradeOrderItemDO> tradeOrderItems, | ||||||
|                                               Map<Long, ProductSkuRespDTO> spuInfos) { |                                               Map<Long, ProductSkuRespDTO> spuInfos) { | ||||||
|         for (TradeOrderItemDO tradeOrderItem : tradeOrderItems) { |         for (TradeOrderItemDO tradeOrderItem : tradeOrderItems) { | ||||||
|             // 填充订单信息 |             // 填充订单信息 | ||||||
| @@ -176,32 +165,87 @@ public class TradeOrderServiceImpl implements TradeOrderService { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void checkSaleableFromSpu(List<SpuInfoRespDTO> spuInfos) { |     /** | ||||||
|         SpuInfoRespDTO spu = CollectionUtils.findFirst(spuInfos, |      * 校验商品 SKU 是否可出售 | ||||||
|                 spuInfoDTO -> !Objects.equals(ProductSpuStatusEnum.ENABLE.getStatus(), spuInfoDTO.getStatus())); |      * | ||||||
|  |      * @param items 商品 SKU | ||||||
|  |      * @return 商品 SKU 数组 | ||||||
|  |      */ | ||||||
|  |     private List<ProductSkuRespDTO> validateSkuSaleable(List<Item> items) { | ||||||
|  |         List<ProductSkuRespDTO> skus = productSkuApi.getSkuList(convertSet(items, Item::getSkuId)); | ||||||
|  |         // SKU 不存在 | ||||||
|  |         if (items.size() != skus.size()) { | ||||||
|  |             throw exception(ErrorCodeConstants.ORDER_CREATE_SKU_NOT_FOUND); | ||||||
|  |         } | ||||||
|  |         // 校验是否禁用 or 库存不足 | ||||||
|  |         Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId); | ||||||
|  |         items.forEach(item -> { | ||||||
|  |             ProductSkuRespDTO sku = skuMap.get(item.getSkuId()); | ||||||
|  |             // SKU 禁用 | ||||||
|  |             if (ObjectUtil.notEqual(CommonStatusEnum.ENABLE.getStatus(), sku.getStatus())) { | ||||||
|  |                 throw exception(ORDER_CREATE_SKU_NOT_SALE); | ||||||
|  |             } | ||||||
|  |             // SKU 库存不足 | ||||||
|  |             if (item.getCount() > sku.getStock()) { | ||||||
|  |                 throw exception(ErrorCodeConstants.ORDER_CREATE_SKU_STOCK_NOT_ENOUGH); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |         return skus; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 校验商品 SPU 是否可出售 | ||||||
|  |      * | ||||||
|  |      * @param spuIds 商品 SPU 编号数组 | ||||||
|  |      * @return 商品 SPU 数组 | ||||||
|  |      */ | ||||||
|  |     private List<ProductSpuRespDTO> validateSpuSaleable(Set<Long> spuIds) { | ||||||
|  |         List<ProductSpuRespDTO> spus = productSpuApi.getSpuList(spuIds); | ||||||
|  |         // SPU 不存在 | ||||||
|  |         if (spus.size() != spuIds.size()) { | ||||||
|  |             throw exception(ORDER_CREATE_SPU_NOT_FOUND); | ||||||
|  |         } | ||||||
|  |         // 校验是否存在禁用的 SPU | ||||||
|  |         ProductSpuRespDTO spu = CollectionUtils.findFirst(spus, | ||||||
|  |                 spuDTO -> ObjectUtil.notEqual(ProductSpuStatusEnum.ENABLE.getStatus(), spuDTO.getStatus())); | ||||||
|         if (Objects.isNull(spu)) { |         if (Objects.isNull(spu)) { | ||||||
|             throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_SPU_NOT_SALE); |             throw exception(ErrorCodeConstants.ORDER_CREATE_SPU_NOT_SALE); | ||||||
|         } |         } | ||||||
|  |         return spus; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // TODO @LeeYan9: checkSpuXXX 会不会好点哈? ps: 这个貌似是 sku 哈 |     /** | ||||||
|     private void checkSaleableAndStockFromSpu(Map<Long, ProductSkuRespDTO> skuInfoMap, |      * 校验收件地址是否存在 | ||||||
|                                               List<Item> items) { |      * | ||||||
|         // sku 不存在 |      * @param userId 用户编号 | ||||||
|         if (items.size() != skuInfoMap.size()) { |      * @param addressId 收件地址编号 | ||||||
|             throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_SKU_NOT_FOUND); |      * @return 收件地址 | ||||||
|  |      */ | ||||||
|  |     private AddressRespDTO validateAddress(Long userId, Long addressId) { | ||||||
|  |         AddressRespDTO address = addressApi.getAddress(userId, addressId); | ||||||
|  |         if (Objects.isNull(address)) { | ||||||
|  |             throw exception(ErrorCodeConstants.ORDER_CREATE_ADDRESS_NOT_FOUND); | ||||||
|         } |         } | ||||||
|         for (Item item : items) { |         return address; | ||||||
|             ProductSkuRespDTO skuInfoDTO = skuInfoMap.get(item.getSkuId()); |  | ||||||
|             // sku禁用 |  | ||||||
|             if (!Objects.equals(CommonStatusEnum.ENABLE.getStatus(), skuInfoDTO.getStatus())) { |  | ||||||
|                 throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_SKU_NOT_SALE); |  | ||||||
|             } |  | ||||||
|             // sku库存不足 |  | ||||||
|             if (item.getCount() > skuInfoDTO.getStock()) { |  | ||||||
|                 throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_SKU_STOCK_NOT_ENOUGH); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private TradeOrderDO createTradeOrder(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO, | ||||||
|  |                                           PriceCalculateRespDTO.Order order, AddressRespDTO address) { | ||||||
|  |         TradeOrderDO tradeOrderDO = TradeOrderConvert.INSTANCE.convert(userId, clientIp, createReqVO, order, address); | ||||||
|  |         tradeOrderDO.setNo(IdUtil.getSnowflakeNextId() + ""); // TODO @LeeYan9: 思考下, 怎么生成好点哈; 这个是会展示给用户的; | ||||||
|  |         tradeOrderDO.setStatus(TradeOrderStatusEnum.WAITING_PAYMENT.getStatus()); | ||||||
|  |         tradeOrderDO.setType(TradeOrderTypeEnum.NORMAL.getType()); | ||||||
|  |         tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); | ||||||
|  |         tradeOrderDO.setProductCount(getSumValue(order.getItems(),  PriceCalculateRespDTO.OrderItem::getCount, Integer::sum)); | ||||||
|  |         tradeOrderDO.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源? | ||||||
|  |         tradeOrderMapper.insert(tradeOrderDO); | ||||||
|  |         return tradeOrderDO; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void createTradeOrderItems(TradeOrderDO tradeOrderDO, | ||||||
|  |                                        List<PriceCalculateRespDTO.OrderItem> orderItems, List<ProductSkuRespDTO> skus) { | ||||||
|  |         List<TradeOrderItemDO> tradeOrderItemDOs = TradeOrderConvert.INSTANCE.convertList(tradeOrderDO, orderItems, skus); | ||||||
|  |         tradeOrderItemMapper.insertBatch(tradeOrderItemDOs); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,21 @@ | |||||||
|  | package cn.iocoder.yudao.module.member.api.address; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 用户收件地址 API 接口 | ||||||
|  |  * | ||||||
|  |  * @author 芋道源码 | ||||||
|  |  */ | ||||||
|  | public interface AddressApi { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获得用户收件地址 | ||||||
|  |      * | ||||||
|  |      * @param id 收件地址编号 | ||||||
|  |      * @param userId 用户编号 | ||||||
|  |      * @return 用户收件地址 | ||||||
|  |      */ | ||||||
|  |     AddressRespDTO getAddress(Long id, Long userId); | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,48 @@ | |||||||
|  | package cn.iocoder.yudao.module.member.api.address.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 用户收件地址 Response DTO | ||||||
|  |  * | ||||||
|  |  * @author 芋道源码 | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class AddressRespDTO { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 编号 | ||||||
|  |      */ | ||||||
|  |     private Long id; | ||||||
|  |     /** | ||||||
|  |      * 用户编号 | ||||||
|  |      */ | ||||||
|  |     private Long userId; | ||||||
|  |     /** | ||||||
|  |      * 收件人名称 | ||||||
|  |      */ | ||||||
|  |     private String name; | ||||||
|  |     /** | ||||||
|  |      * 手机号 | ||||||
|  |      */ | ||||||
|  |     private String mobile; | ||||||
|  |     /** | ||||||
|  |      * 地区编号 | ||||||
|  |      */ | ||||||
|  |     private Long areaId; | ||||||
|  |     /** | ||||||
|  |      * 邮编 | ||||||
|  |      */ | ||||||
|  |     private String postCode; | ||||||
|  |     /** | ||||||
|  |      * 收件详细地址 | ||||||
|  |      */ | ||||||
|  |     private String detailAddress; | ||||||
|  |     /** | ||||||
|  |      * 是否默认 | ||||||
|  |      * | ||||||
|  |      * true - 默认收件地址 | ||||||
|  |      */ | ||||||
|  |     private Boolean defaulted; | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,28 @@ | |||||||
|  | package cn.iocoder.yudao.module.member.api.address; | ||||||
|  |  | ||||||
|  | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; | ||||||
|  | import cn.iocoder.yudao.module.member.convert.address.AddressConvert; | ||||||
|  | import cn.iocoder.yudao.module.member.service.address.AddressService; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  | import org.springframework.validation.annotation.Validated; | ||||||
|  |  | ||||||
|  | import javax.annotation.Resource; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 用户收件地址 API 实现类 | ||||||
|  |  * | ||||||
|  |  * @author 芋道源码 | ||||||
|  |  */ | ||||||
|  | @Service | ||||||
|  | @Validated | ||||||
|  | public class AddressApiImpl implements AddressApi { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private AddressService addressService; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public AddressRespDTO getAddress(Long id, Long userId) { | ||||||
|  |         return AddressConvert.INSTANCE.convert02(addressService.getAddress(userId, id)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,13 +1,15 @@ | |||||||
| package cn.iocoder.yudao.module.member.convert.address; | package cn.iocoder.yudao.module.member.convert.address; | ||||||
|  |  | ||||||
| import java.util.*; |  | ||||||
|  |  | ||||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||||
|  | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; | ||||||
|  | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressCreateReqVO; | ||||||
|  | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressRespVO; | ||||||
|  | import cn.iocoder.yudao.module.member.controller.app.address.vo.AppAddressUpdateReqVO; | ||||||
|  | import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; | ||||||
| import org.mapstruct.Mapper; | import org.mapstruct.Mapper; | ||||||
| import org.mapstruct.factory.Mappers; | import org.mapstruct.factory.Mappers; | ||||||
| import cn.iocoder.yudao.module.member.controller.app.address.vo.*; |  | ||||||
| import cn.iocoder.yudao.module.member.dal.dataobject.address.AddressDO; | import java.util.List; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 用户收件地址 Convert |  * 用户收件地址 Convert | ||||||
| @@ -29,4 +31,6 @@ public interface AddressConvert { | |||||||
|  |  | ||||||
|     PageResult<AppAddressRespVO> convertPage(PageResult<AddressDO> page); |     PageResult<AppAddressRespVO> convertPage(PageResult<AddressDO> page); | ||||||
|  |  | ||||||
|  |     AddressRespDTO convert02(AddressDO bean); | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV