Commit 840cfad84aa45e70b1ec11f6ce7529b5f6e2a247
1 parent
30fd7996
【功能优化】商城:价格计算时,返回可用 + 不可用的优惠劵
Showing
21 changed files
with
240 additions
and
263 deletions
pom.xml
| @@ -15,12 +15,12 @@ | @@ -15,12 +15,12 @@ | ||
| 15 | <!-- 各种 module 拓展 --> | 15 | <!-- 各种 module 拓展 --> |
| 16 | <module>yudao-module-system</module> | 16 | <module>yudao-module-system</module> |
| 17 | <module>yudao-module-infra</module> | 17 | <module>yudao-module-infra</module> |
| 18 | - <module>yudao-module-member</module> | 18 | +<!-- <module>yudao-module-member</module>--> |
| 19 | <!-- <module>yudao-module-bpm</module>--> | 19 | <!-- <module>yudao-module-bpm</module>--> |
| 20 | <!-- <module>yudao-module-report</module>--> | 20 | <!-- <module>yudao-module-report</module>--> |
| 21 | <!-- <module>yudao-module-mp</module>--> | 21 | <!-- <module>yudao-module-mp</module>--> |
| 22 | - <module>yudao-module-pay</module> | ||
| 23 | - <module>yudao-module-mall</module> | 22 | +<!-- <module>yudao-module-pay</module>--> |
| 23 | +<!-- <module>yudao-module-mall</module>--> | ||
| 24 | <!-- <module>yudao-module-crm</module>--> | 24 | <!-- <module>yudao-module-crm</module>--> |
| 25 | <!-- <module>yudao-module-erp</module>--> | 25 | <!-- <module>yudao-module-erp</module>--> |
| 26 | <!-- <module>yudao-module-ai</module>--> | 26 | <!-- <module>yudao-module-ai</module>--> |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.coupon; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.coupon; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | 3 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; |
| 4 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; | 4 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; |
| 5 | -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | ||
| 6 | import jakarta.validation.Valid; | 5 | import jakarta.validation.Valid; |
| 7 | 6 | ||
| 8 | import java.util.List; | 7 | import java.util.List; |
| @@ -16,6 +15,15 @@ import java.util.Map; | @@ -16,6 +15,15 @@ import java.util.Map; | ||
| 16 | public interface CouponApi { | 15 | public interface CouponApi { |
| 17 | 16 | ||
| 18 | /** | 17 | /** |
| 18 | + * 获得用户的优惠劵列表 | ||
| 19 | + * | ||
| 20 | + * @param userId 用户编号 | ||
| 21 | + * @param status 优惠劵状态 | ||
| 22 | + * @return 优惠劵列表 | ||
| 23 | + */ | ||
| 24 | + List<CouponRespDTO> getCouponListByUserId(Long userId, Integer status); | ||
| 25 | + | ||
| 26 | + /** | ||
| 19 | * 使用优惠劵 | 27 | * 使用优惠劵 |
| 20 | * | 28 | * |
| 21 | * @param useReqDTO 使用请求 | 29 | * @param useReqDTO 使用请求 |
| @@ -30,14 +38,6 @@ public interface CouponApi { | @@ -30,14 +38,6 @@ public interface CouponApi { | ||
| 30 | void returnUsedCoupon(Long id); | 38 | void returnUsedCoupon(Long id); |
| 31 | 39 | ||
| 32 | /** | 40 | /** |
| 33 | - * 校验优惠劵 | ||
| 34 | - * | ||
| 35 | - * @param validReqDTO 校验请求 | ||
| 36 | - * @return 优惠劵 | ||
| 37 | - */ | ||
| 38 | - CouponRespDTO validateCoupon(@Valid CouponValidReqDTO validReqDTO); | ||
| 39 | - | ||
| 40 | - /** | ||
| 41 | * 【管理员】给指定用户批量发送优惠券 | 41 | * 【管理员】给指定用户批量发送优惠券 |
| 42 | * | 42 | * |
| 43 | * @param giveCoupons key: 优惠劵模版编号,value:对应的数量 | 43 | * @param giveCoupons key: 优惠劵模版编号,value:对应的数量 |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java deleted
| 1 | -package cn.iocoder.yudao.module.promotion.api.coupon.dto; | ||
| 2 | - | ||
| 3 | -import lombok.Data; | ||
| 4 | - | ||
| 5 | -import jakarta.validation.constraints.NotNull; | ||
| 6 | - | ||
| 7 | -/** | ||
| 8 | - * 优惠劵使用 Request DTO | ||
| 9 | - * | ||
| 10 | - * @author 芋道源码 | ||
| 11 | - */ | ||
| 12 | -@Data | ||
| 13 | -public class CouponValidReqDTO { | ||
| 14 | - | ||
| 15 | - /** | ||
| 16 | - * 优惠劵编号 | ||
| 17 | - */ | ||
| 18 | - @NotNull(message = "优惠劵编号不能为空") | ||
| 19 | - private Long id; | ||
| 20 | - | ||
| 21 | - /** | ||
| 22 | - * 用户编号 | ||
| 23 | - */ | ||
| 24 | - @NotNull(message = "用户编号不能为空") | ||
| 25 | - private Long userId; | ||
| 26 | - | ||
| 27 | -} |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
| @@ -20,8 +20,6 @@ public interface ErrorCodeConstants { | @@ -20,8 +20,6 @@ public interface ErrorCodeConstants { | ||
| 20 | ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在"); | 20 | ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在"); |
| 21 | 21 | ||
| 22 | // ========== Coupon 相关 1-013-003-000 ============ | 22 | // ========== Coupon 相关 1-013-003-000 ============ |
| 23 | - ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1_013_003_000, "优惠劵没有可使用的商品!"); | ||
| 24 | - ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1_013_003_001, "所结算的商品中未满足使用的金额"); | ||
| 25 | 23 | ||
| 26 | // ========== 优惠劵模板 1-013-004-000 ========== | 24 | // ========== 优惠劵模板 1-013-004-000 ========== |
| 27 | ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_004_000, "优惠劵模板不存在"); | 25 | ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_004_000, "优惠劵模板不存在"); |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java
| 1 | package cn.iocoder.yudao.module.promotion.api.coupon; | 1 | package cn.iocoder.yudao.module.promotion.api.coupon; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 4 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | 5 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; |
| 5 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; | 6 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; |
| 6 | -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | ||
| 7 | -import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; | ||
| 8 | -import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | ||
| 9 | import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; | 7 | import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; |
| 10 | import jakarta.annotation.Resource; | 8 | import jakarta.annotation.Resource; |
| 11 | import org.springframework.stereotype.Service; | 9 | import org.springframework.stereotype.Service; |
| @@ -27,6 +25,11 @@ public class CouponApiImpl implements CouponApi { | @@ -27,6 +25,11 @@ public class CouponApiImpl implements CouponApi { | ||
| 27 | private CouponService couponService; | 25 | private CouponService couponService; |
| 28 | 26 | ||
| 29 | @Override | 27 | @Override |
| 28 | + public List<CouponRespDTO> getCouponListByUserId(Long userId, Integer status) { | ||
| 29 | + return BeanUtils.toBean(couponService.getCouponList(userId, status), CouponRespDTO.class); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + @Override | ||
| 30 | public void useCoupon(CouponUseReqDTO useReqDTO) { | 33 | public void useCoupon(CouponUseReqDTO useReqDTO) { |
| 31 | couponService.useCoupon(useReqDTO.getId(), useReqDTO.getUserId(), | 34 | couponService.useCoupon(useReqDTO.getId(), useReqDTO.getUserId(), |
| 32 | useReqDTO.getOrderId()); | 35 | useReqDTO.getOrderId()); |
| @@ -38,12 +41,6 @@ public class CouponApiImpl implements CouponApi { | @@ -38,12 +41,6 @@ public class CouponApiImpl implements CouponApi { | ||
| 38 | } | 41 | } |
| 39 | 42 | ||
| 40 | @Override | 43 | @Override |
| 41 | - public CouponRespDTO validateCoupon(CouponValidReqDTO validReqDTO) { | ||
| 42 | - CouponDO coupon = couponService.validCoupon(validReqDTO.getId(), validReqDTO.getUserId()); | ||
| 43 | - return CouponConvert.INSTANCE.convert(coupon); | ||
| 44 | - } | ||
| 45 | - | ||
| 46 | - @Override | ||
| 47 | public List<Long> takeCouponsByAdmin(Map<Long, Integer> giveCoupons, Long userId) { | 44 | public List<Long> takeCouponsByAdmin(Map<Long, Integer> giveCoupons, Long userId) { |
| 48 | return couponService.takeCouponsByAdmin(giveCoupons, userId); | 45 | return couponService.takeCouponsByAdmin(giveCoupons, userId); |
| 49 | } | 46 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java
| @@ -5,7 +5,9 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; | @@ -5,7 +5,9 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; | 7 | import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; |
| 8 | -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.*; | 8 | +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO; |
| 9 | +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO; | ||
| 10 | +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponTakeReqVO; | ||
| 9 | import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; | 11 | import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; |
| 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | 12 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 11 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | 13 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; |
| @@ -15,13 +17,12 @@ import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService; | @@ -15,13 +17,12 @@ import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService; | ||
| 15 | import io.swagger.v3.oas.annotations.Operation; | 17 | import io.swagger.v3.oas.annotations.Operation; |
| 16 | import io.swagger.v3.oas.annotations.Parameter; | 18 | import io.swagger.v3.oas.annotations.Parameter; |
| 17 | import io.swagger.v3.oas.annotations.tags.Tag; | 19 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 20 | +import jakarta.annotation.Resource; | ||
| 21 | +import jakarta.validation.Valid; | ||
| 18 | import org.springframework.validation.annotation.Validated; | 22 | import org.springframework.validation.annotation.Validated; |
| 19 | import org.springframework.web.bind.annotation.*; | 23 | import org.springframework.web.bind.annotation.*; |
| 20 | 24 | ||
| 21 | -import jakarta.annotation.Resource; | ||
| 22 | -import jakarta.validation.Valid; | ||
| 23 | import java.util.Collections; | 25 | import java.util.Collections; |
| 24 | -import java.util.List; | ||
| 25 | 26 | ||
| 26 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 27 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 27 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | 28 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| @@ -56,14 +57,6 @@ public class AppCouponController { | @@ -56,14 +57,6 @@ public class AppCouponController { | ||
| 56 | return success(canTakeAgain); | 57 | return success(canTakeAgain); |
| 57 | } | 58 | } |
| 58 | 59 | ||
| 59 | - @GetMapping("/match-list") | ||
| 60 | - @Operation(summary = "获得匹配指定商品的优惠劵列表", description = "用于下单页,展示优惠劵列表") | ||
| 61 | - public CommonResult<List<AppCouponMatchRespVO>> getMatchCouponList(AppCouponMatchReqVO matchReqVO) { | ||
| 62 | - // todo: 优化:优惠金额倒序 | ||
| 63 | - List<CouponDO> list = couponService.getMatchCouponList(getLoginUserId(), matchReqVO); | ||
| 64 | - return success(BeanUtils.toBean(list, AppCouponMatchRespVO.class)); | ||
| 65 | - } | ||
| 66 | - | ||
| 67 | @GetMapping("/page") | 60 | @GetMapping("/page") |
| 68 | @Operation(summary = "我的优惠劵列表") | 61 | @Operation(summary = "我的优惠劵列表") |
| 69 | @PreAuthenticated | 62 | @PreAuthenticated |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; | ||
| 2 | - | ||
| 3 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | -import lombok.Data; | ||
| 5 | - | ||
| 6 | -import jakarta.validation.constraints.NotEmpty; | ||
| 7 | -import jakarta.validation.constraints.NotNull; | ||
| 8 | -import java.util.List; | ||
| 9 | - | ||
| 10 | -@Schema(description = "用户 App - 优惠劵的匹配 Request VO") | ||
| 11 | -@Data | ||
| 12 | -public class AppCouponMatchReqVO { | ||
| 13 | - | ||
| 14 | - @Schema(description = "商品金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 15 | - @NotNull(message = "商品金额不能为空") | ||
| 16 | - private Integer price; | ||
| 17 | - | ||
| 18 | - @Schema(description = "商品 SPU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]") | ||
| 19 | - @NotEmpty(message = "商品 SPU 编号不能为空") | ||
| 20 | - private List<Long> spuIds; | ||
| 21 | - | ||
| 22 | - @Schema(description = "商品 SKU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]") | ||
| 23 | - @NotEmpty(message = "商品 SKU 编号不能为空") | ||
| 24 | - private List<Long> skuIds; | ||
| 25 | - | ||
| 26 | - @Schema(description = "分类编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[10, 20]") | ||
| 27 | - @NotEmpty(message = "分类编号不能为空") | ||
| 28 | - private List<Long> categoryIds; | ||
| 29 | - | ||
| 30 | -} |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchRespVO.java deleted
| 1 | -package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; | ||
| 2 | - | ||
| 3 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | -import lombok.Data; | ||
| 5 | - | ||
| 6 | -@Schema(description = "用户 App - 优惠劵 Response VO") | ||
| 7 | -@Data | ||
| 8 | -public class AppCouponMatchRespVO extends AppCouponRespVO { | ||
| 9 | - | ||
| 10 | - @Schema(description = "是否匹配", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 11 | - private Boolean match; | ||
| 12 | - | ||
| 13 | - @Schema(description = "匹配条件的提示", example = "所结算商品没有符合条件的商品") | ||
| 14 | - private String description; | ||
| 15 | - | ||
| 16 | -} |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; | ||
| 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 jakarta.validation.constraints.Min; | ||
| 7 | import java.time.LocalDateTime; | 6 | import java.time.LocalDateTime; |
| 8 | import java.util.List; | 7 | import java.util.List; |
| 9 | 8 | ||
| @@ -42,7 +41,6 @@ public class AppCouponRespVO { | @@ -42,7 +41,6 @@ public class AppCouponRespVO { | ||
| 42 | private Integer discountPercent; | 41 | private Integer discountPercent; |
| 43 | 42 | ||
| 44 | @Schema(description = "优惠金额", example = "10") | 43 | @Schema(description = "优惠金额", example = "10") |
| 45 | - @Min(value = 0, message = "优惠金额需要大于等于 0") | ||
| 46 | private Integer discountPrice; | 44 | private Integer discountPrice; |
| 47 | 45 | ||
| 48 | @Schema(description = "折扣上限", example = "100") // 单位:分,仅在 discountType 为 PERCENT 使用 | 46 | @Schema(description = "折扣上限", example = "100") // 单位:分,仅在 discountType 为 PERCENT 使用 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java
| @@ -4,9 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | @@ -4,9 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | 4 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; |
| 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO; | 5 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; |
| 7 | -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO; | ||
| 8 | import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO; |
| 9 | -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO; | ||
| 10 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 11 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; |
| 12 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; | 10 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; |
| @@ -16,7 +14,6 @@ import org.mapstruct.factory.Mappers; | @@ -16,7 +14,6 @@ import org.mapstruct.factory.Mappers; | ||
| 16 | 14 | ||
| 17 | import java.time.LocalDateTime; | 15 | import java.time.LocalDateTime; |
| 18 | import java.util.Collection; | 16 | import java.util.Collection; |
| 19 | -import java.util.List; | ||
| 20 | 17 | ||
| 21 | /** | 18 | /** |
| 22 | * 优惠劵 Convert | 19 | * 优惠劵 Convert |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java
| 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.coupon; | 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.coupon; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.map.MapUtil; | 3 | import cn.hutool.core.map.MapUtil; |
| 4 | -import cn.hutool.core.util.StrUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 7 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 8 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; | 7 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; |
| 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 10 | -import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | ||
| 11 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 9 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 12 | import com.github.yulichang.toolkit.MPJWrappers; | 10 | import com.github.yulichang.toolkit.MPJWrappers; |
| 13 | import org.apache.ibatis.annotations.Mapper; | 11 | import org.apache.ibatis.annotations.Mapper; |
| @@ -16,8 +14,6 @@ import java.time.LocalDateTime; | @@ -16,8 +14,6 @@ import java.time.LocalDateTime; | ||
| 16 | import java.util.Collection; | 14 | import java.util.Collection; |
| 17 | import java.util.List; | 15 | import java.util.List; |
| 18 | import java.util.Map; | 16 | import java.util.Map; |
| 19 | -import java.util.function.Function; | ||
| 20 | -import java.util.stream.Collectors; | ||
| 21 | 17 | ||
| 22 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | 18 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| 23 | 19 | ||
| @@ -84,22 +80,6 @@ public interface CouponMapper extends BaseMapperX<CouponDO> { | @@ -84,22 +80,6 @@ public interface CouponMapper extends BaseMapperX<CouponDO> { | ||
| 84 | return convertMap(list, map -> MapUtil.getLong(map, templateIdAlias), map -> MapUtil.getInt(map, countAlias)); | 80 | return convertMap(list, map -> MapUtil.getLong(map, templateIdAlias), map -> MapUtil.getInt(map, countAlias)); |
| 85 | } | 81 | } |
| 86 | 82 | ||
| 87 | - default List<CouponDO> selectListByUserIdAndStatusAndUsePriceLeAndProductScope( | ||
| 88 | - Long userId, Integer status, Integer usePrice, List<Long> spuIds, List<Long> categoryIds) { | ||
| 89 | - Function<List<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream() | ||
| 90 | - .map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id)) | ||
| 91 | - .collect(Collectors.joining(" OR ")); | ||
| 92 | - return selectList(new LambdaQueryWrapperX<CouponDO>() | ||
| 93 | - .eq(CouponDO::getUserId, userId) | ||
| 94 | - .eq(CouponDO::getStatus, status) | ||
| 95 | - .le(CouponDO::getUsePrice, usePrice) // 价格小于等于,满足价格使用条件 | ||
| 96 | - .and(w -> w.eq(CouponDO::getProductScope, PromotionProductScopeEnum.ALL.getScope()) // 商品范围一:全部 | ||
| 97 | - .or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.SPU.getScope()) // 商品范围二:满足指定商品 | ||
| 98 | - .apply(productScopeValuesFindInSetFunc.apply(spuIds))) | ||
| 99 | - .or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.CATEGORY.getScope()) // 商品范围三:满足指定分类 | ||
| 100 | - .apply(productScopeValuesFindInSetFunc.apply(categoryIds))))); | ||
| 101 | - } | ||
| 102 | - | ||
| 103 | default List<CouponDO> selectListByStatusAndValidEndTimeLe(Integer status, LocalDateTime validEndTime) { | 83 | default List<CouponDO> selectListByStatusAndValidEndTimeLe(Integer status, LocalDateTime validEndTime) { |
| 104 | return selectList(new LambdaQueryWrapperX<CouponDO>() | 84 | return selectList(new LambdaQueryWrapperX<CouponDO>() |
| 105 | .eq(CouponDO::getStatus, status) | 85 | .eq(CouponDO::getStatus, status) |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
| @@ -30,15 +30,9 @@ public interface RewardActivityMapper extends BaseMapperX<RewardActivityDO> { | @@ -30,15 +30,9 @@ public interface RewardActivityMapper extends BaseMapperX<RewardActivityDO> { | ||
| 30 | .orderByDesc(RewardActivityDO::getId)); | 30 | .orderByDesc(RewardActivityDO::getId)); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | - default List<RewardActivityDO> selectListByProductScopeAndStatus(Integer productScope, Integer status) { | ||
| 34 | - return selectList(new LambdaQueryWrapperX<RewardActivityDO>() | ||
| 35 | - .eq(RewardActivityDO::getProductScope, productScope) | ||
| 36 | - .eq(RewardActivityDO::getStatus, status)); | ||
| 37 | - } | ||
| 38 | - | ||
| 39 | default List<RewardActivityDO> selectListBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { | 33 | default List<RewardActivityDO> selectListBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) { |
| 40 | Function<Collection<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream() | 34 | Function<Collection<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream() |
| 41 | - .map(id -> StrUtil.format("FIND_IN_SET({}, product_spu_ids) ", id)) | 35 | + .map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id)) |
| 42 | .collect(Collectors.joining(" OR ")); | 36 | .collect(Collectors.joining(" OR ")); |
| 43 | return selectList(new QueryWrapper<RewardActivityDO>() | 37 | return selectList(new QueryWrapper<RewardActivityDO>() |
| 44 | .eq("status", status) | 38 | .eq("status", status) |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java
| @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; | @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; | ||
| 4 | import cn.hutool.core.map.MapUtil; | 4 | import cn.hutool.core.map.MapUtil; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; |
| 7 | -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; | ||
| 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | 7 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 9 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | 8 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; |
| 10 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; | 9 | import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; |
| @@ -19,26 +18,6 @@ import java.util.*; | @@ -19,26 +18,6 @@ import java.util.*; | ||
| 19 | public interface CouponService { | 18 | public interface CouponService { |
| 20 | 19 | ||
| 21 | /** | 20 | /** |
| 22 | - * 校验优惠劵,包括状态、有限期 | ||
| 23 | - * <p> | ||
| 24 | - * 1. 如果校验通过,则返回优惠劵信息 | ||
| 25 | - * 2. 如果校验不通过,则直接抛出业务异常 | ||
| 26 | - * | ||
| 27 | - * @param id 优惠劵编号 | ||
| 28 | - * @param userId 用户编号 | ||
| 29 | - * @return 优惠劵信息 | ||
| 30 | - */ | ||
| 31 | - CouponDO validCoupon(Long id, Long userId); | ||
| 32 | - | ||
| 33 | - /** | ||
| 34 | - * 校验优惠劵,包括状态、有限期 | ||
| 35 | - * | ||
| 36 | - * @param coupon 优惠劵 | ||
| 37 | - * @see #validCoupon(Long, Long) 逻辑相同,只是入参不同 | ||
| 38 | - */ | ||
| 39 | - void validCoupon(CouponDO coupon); | ||
| 40 | - | ||
| 41 | - /** | ||
| 42 | * 使用优惠劵 | 21 | * 使用优惠劵 |
| 43 | * | 22 | * |
| 44 | * @param id 优惠劵编号 | 23 | * @param id 优惠劵编号 |
| @@ -172,15 +151,6 @@ public interface CouponService { | @@ -172,15 +151,6 @@ public interface CouponService { | ||
| 172 | } | 151 | } |
| 173 | 152 | ||
| 174 | /** | 153 | /** |
| 175 | - * 获取用户匹配的优惠券列表 | ||
| 176 | - * | ||
| 177 | - * @param userId 用户编号 | ||
| 178 | - * @param matchReqVO 匹配参数 | ||
| 179 | - * @return 优惠券列表 | ||
| 180 | - */ | ||
| 181 | - List<CouponDO> getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO); | ||
| 182 | - | ||
| 183 | - /** | ||
| 184 | * 获取用户是否可以领取优惠券 | 154 | * 获取用户是否可以领取优惠券 |
| 185 | * | 155 | * |
| 186 | * @param userId 用户编号 | 156 | * @param userId 用户编号 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
| @@ -12,7 +12,6 @@ import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | @@ -12,7 +12,6 @@ import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | ||
| 12 | import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | 12 | import cn.iocoder.yudao.module.member.api.user.MemberUserApi; |
| 13 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | 13 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; |
| 14 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; | 14 | import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; |
| 15 | -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; | ||
| 16 | import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; | 15 | import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; |
| 17 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; | 16 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; |
| 18 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; | 17 | import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; |
| @@ -56,18 +55,9 @@ public class CouponServiceImpl implements CouponService { | @@ -56,18 +55,9 @@ public class CouponServiceImpl implements CouponService { | ||
| 56 | private MemberUserApi memberUserApi; | 55 | private MemberUserApi memberUserApi; |
| 57 | 56 | ||
| 58 | @Override | 57 | @Override |
| 59 | - public CouponDO validCoupon(Long id, Long userId) { | ||
| 60 | - CouponDO coupon = couponMapper.selectByIdAndUserId(id, userId); | ||
| 61 | - if (coupon == null) { | ||
| 62 | - throw exception(COUPON_NOT_EXISTS); | ||
| 63 | - } | ||
| 64 | - validCoupon(coupon); | ||
| 65 | - return coupon; | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | - @Override | ||
| 69 | - public void validCoupon(CouponDO coupon) { | 58 | + public void useCoupon(Long id, Long userId, Long orderId) { |
| 70 | // 校验状态 | 59 | // 校验状态 |
| 60 | + CouponDO coupon = couponMapper.selectByIdAndUserId(id, userId); | ||
| 71 | if (ObjectUtil.notEqual(coupon.getStatus(), CouponStatusEnum.UNUSED.getStatus())) { | 61 | if (ObjectUtil.notEqual(coupon.getStatus(), CouponStatusEnum.UNUSED.getStatus())) { |
| 72 | throw exception(COUPON_STATUS_NOT_UNUSED); | 62 | throw exception(COUPON_STATUS_NOT_UNUSED); |
| 73 | } | 63 | } |
| @@ -75,12 +65,6 @@ public class CouponServiceImpl implements CouponService { | @@ -75,12 +65,6 @@ public class CouponServiceImpl implements CouponService { | ||
| 75 | if (!LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime())) { | 65 | if (!LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime())) { |
| 76 | throw exception(COUPON_VALID_TIME_NOT_NOW); | 66 | throw exception(COUPON_VALID_TIME_NOT_NOW); |
| 77 | } | 67 | } |
| 78 | - } | ||
| 79 | - | ||
| 80 | - @Override | ||
| 81 | - public void useCoupon(Long id, Long userId, Long orderId) { | ||
| 82 | - // 校验优惠劵 | ||
| 83 | - validCoupon(id, userId); | ||
| 84 | 68 | ||
| 85 | // 更新状态 | 69 | // 更新状态 |
| 86 | int updateCount = couponMapper.updateByIdAndStatus(id, CouponStatusEnum.UNUSED.getStatus(), | 70 | int updateCount = couponMapper.updateByIdAndStatus(id, CouponStatusEnum.UNUSED.getStatus(), |
| @@ -355,16 +339,6 @@ public class CouponServiceImpl implements CouponService { | @@ -355,16 +339,6 @@ public class CouponServiceImpl implements CouponService { | ||
| 355 | } | 339 | } |
| 356 | 340 | ||
| 357 | @Override | 341 | @Override |
| 358 | - public List<CouponDO> getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO) { | ||
| 359 | - List<CouponDO> list = couponMapper.selectListByUserIdAndStatusAndUsePriceLeAndProductScope(userId, | ||
| 360 | - CouponStatusEnum.UNUSED.getStatus(), | ||
| 361 | - matchReqVO.getPrice(), matchReqVO.getSpuIds(), matchReqVO.getCategoryIds()); | ||
| 362 | - // 兜底逻辑:如果 CouponExpireJob 未执行,status 未变成 EXPIRE ,但是 validEndTime 已经过期了,需要进行过滤 | ||
| 363 | - list.removeIf(coupon -> !LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime())); | ||
| 364 | - return list; | ||
| 365 | - } | ||
| 366 | - | ||
| 367 | - @Override | ||
| 368 | public Map<Long, Boolean> getUserCanCanTakeMap(Long userId, List<CouponTemplateDO> templates) { | 342 | public Map<Long, Boolean> getUserCanCanTakeMap(Long userId, List<CouponTemplateDO> templates) { |
| 369 | // 1. 未登录时,都显示可以领取 | 343 | // 1. 未登录时,都显示可以领取 |
| 370 | Map<Long, Boolean> userCanTakeMap = convertMap(templates, CouponTemplateDO::getId, templateId -> true); | 344 | Map<Long, Boolean> userCanTakeMap = convertMap(templates, CouponTemplateDO::getId, templateId -> true); |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
| @@ -61,7 +61,7 @@ public interface ErrorCodeConstants { | @@ -61,7 +61,7 @@ public interface ErrorCodeConstants { | ||
| 61 | ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1_011_003_004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵"); | 61 | ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1_011_003_004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵"); |
| 62 | ErrorCode PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT = new ErrorCode(1_011_003_005, "参与秒杀的商品,超过了秒杀总限购数量"); | 62 | ErrorCode PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT = new ErrorCode(1_011_003_005, "参与秒杀的商品,超过了秒杀总限购数量"); |
| 63 | ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TYPE_ILLEGAL = new ErrorCode(1_011_003_006, "计算快递运费异常,配送方式不匹配"); | 63 | ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TYPE_ILLEGAL = new ErrorCode(1_011_003_006, "计算快递运费异常,配送方式不匹配"); |
| 64 | - ErrorCode PRICE_CALCULATE_COUPON_PRICE_TOO_MUCH = new ErrorCode(1_011_003_007, "该优惠劵无法使用,原因:优惠金额超过订单金额"); | 64 | + ErrorCode PRICE_CALCULATE_COUPON_CAN_NOT_USE = new ErrorCode(1_011_003_007, "该优惠劵无法使用,原因:{}」"); |
| 65 | 65 | ||
| 66 | // ========== 物流 Express 模块 1-011-004-000 ========== | 66 | // ========== 物流 Express 模块 1-011-004-000 ========== |
| 67 | ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在"); | 67 | ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在"); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java
| @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.trade.controller.app.order.vo; | @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.trade.controller.app.order.vo; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO; | 3 | import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO; |
| 4 | import io.swagger.v3.oas.annotations.media.Schema; | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | -import jakarta.validation.constraints.NotNull; | ||
| 6 | import lombok.AllArgsConstructor; | 5 | import lombok.AllArgsConstructor; |
| 7 | import lombok.Data; | 6 | import lombok.Data; |
| 8 | import lombok.NoArgsConstructor; | 7 | import lombok.NoArgsConstructor; |
| 9 | 8 | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | import java.util.List; | 10 | import java.util.List; |
| 11 | 11 | ||
| 12 | @Schema(description = "用户 App - 交易订单结算信息 Response VO") | 12 | @Schema(description = "用户 App - 交易订单结算信息 Response VO") |
| @@ -19,6 +19,9 @@ public class AppTradeOrderSettlementRespVO { | @@ -19,6 +19,9 @@ public class AppTradeOrderSettlementRespVO { | ||
| 19 | @Schema(description = "购物项数组", requiredMode = Schema.RequiredMode.REQUIRED) | 19 | @Schema(description = "购物项数组", requiredMode = Schema.RequiredMode.REQUIRED) |
| 20 | private List<Item> items; | 20 | private List<Item> items; |
| 21 | 21 | ||
| 22 | + @Schema(description = "优惠劵数组", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 23 | + private List<Coupon> coupons; // 可用 + 不可用 | ||
| 24 | + | ||
| 22 | @Schema(description = "费用", requiredMode = Schema.RequiredMode.REQUIRED) | 25 | @Schema(description = "费用", requiredMode = Schema.RequiredMode.REQUIRED) |
| 23 | private Price price; | 26 | private Price price; |
| 24 | 27 | ||
| @@ -109,7 +112,6 @@ public class AppTradeOrderSettlementRespVO { | @@ -109,7 +112,6 @@ public class AppTradeOrderSettlementRespVO { | ||
| 109 | private String mobile; | 112 | private String mobile; |
| 110 | 113 | ||
| 111 | @Schema(description = "地区编号", requiredMode = Schema.RequiredMode.REQUIRED) | 114 | @Schema(description = "地区编号", requiredMode = Schema.RequiredMode.REQUIRED) |
| 112 | - @NotNull(message = "地区编号不能为空") | ||
| 113 | private Long areaId; | 115 | private Long areaId; |
| 114 | @Schema(description = "地区名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海上海市普陀区") | 116 | @Schema(description = "地区名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海上海市普陀区") |
| 115 | private String areaName; | 117 | private String areaName; |
| @@ -122,4 +124,43 @@ public class AppTradeOrderSettlementRespVO { | @@ -122,4 +124,43 @@ public class AppTradeOrderSettlementRespVO { | ||
| 122 | 124 | ||
| 123 | } | 125 | } |
| 124 | 126 | ||
| 127 | + @Schema(description = "优惠劵信息") | ||
| 128 | + @Data | ||
| 129 | + public static class Coupon { | ||
| 130 | + | ||
| 131 | + @Schema(description = "优惠劵编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 132 | + private Long id; | ||
| 133 | + | ||
| 134 | + @Schema(description = "优惠劵名", requiredMode = Schema.RequiredMode.REQUIRED, example = "春节送送送") | ||
| 135 | + private String name; | ||
| 136 | + | ||
| 137 | + @Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 单位:分;0 - 不限制 | ||
| 138 | + private Integer usePrice; | ||
| 139 | + | ||
| 140 | + @Schema(description = "固定日期 - 生效开始时间") | ||
| 141 | + private LocalDateTime validStartTime; | ||
| 142 | + | ||
| 143 | + @Schema(description = "固定日期 - 生效结束时间") | ||
| 144 | + private LocalDateTime validEndTime; | ||
| 145 | + | ||
| 146 | + @Schema(description = "优惠类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 147 | + private Integer discountType; | ||
| 148 | + | ||
| 149 | + @Schema(description = "折扣百分比", example = "80") // 例如说,80% 为 80 | ||
| 150 | + private Integer discountPercent; | ||
| 151 | + | ||
| 152 | + @Schema(description = "优惠金额", example = "10") | ||
| 153 | + private Integer discountPrice; | ||
| 154 | + | ||
| 155 | + @Schema(description = "折扣上限", example = "100") // 单位:分,仅在 discountType 为 PERCENT 使用 | ||
| 156 | + private Integer discountLimitPrice; | ||
| 157 | + | ||
| 158 | + @Schema(description = "是否可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") | ||
| 159 | + private Boolean match; | ||
| 160 | + | ||
| 161 | + @Schema(description = "不可用原因", example = "优惠劵已过期") | ||
| 162 | + private String mismatchReason; | ||
| 163 | + | ||
| 164 | + } | ||
| 165 | + | ||
| 125 | } | 166 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
| @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | ||
| 5 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | 5 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 6 | import lombok.Data; | 6 | import lombok.Data; |
| 7 | 7 | ||
| 8 | +import java.time.LocalDateTime; | ||
| 8 | import java.util.List; | 9 | import java.util.List; |
| 9 | import java.util.Map; | 10 | import java.util.Map; |
| 10 | 11 | ||
| @@ -45,9 +46,13 @@ public class TradePriceCalculateRespBO { | @@ -45,9 +46,13 @@ public class TradePriceCalculateRespBO { | ||
| 45 | private List<Promotion> promotions; | 46 | private List<Promotion> promotions; |
| 46 | 47 | ||
| 47 | /** | 48 | /** |
| 48 | - * 优惠劵编号 | 49 | + * 使用的优惠劵编号 |
| 49 | */ | 50 | */ |
| 50 | private Long couponId; | 51 | private Long couponId; |
| 52 | + /** | ||
| 53 | + * 用户的优惠劵列表(可用 + 不可用) | ||
| 54 | + */ | ||
| 55 | + private List<Coupon> coupons; | ||
| 51 | 56 | ||
| 52 | /** | 57 | /** |
| 53 | * 会员剩余积分 | 58 | * 会员剩余积分 |
| @@ -339,4 +344,62 @@ public class TradePriceCalculateRespBO { | @@ -339,4 +344,62 @@ public class TradePriceCalculateRespBO { | ||
| 339 | 344 | ||
| 340 | } | 345 | } |
| 341 | 346 | ||
| 347 | + /** | ||
| 348 | + * 优惠劵信息 | ||
| 349 | + */ | ||
| 350 | + @Data | ||
| 351 | + public static class Coupon { | ||
| 352 | + | ||
| 353 | + /** | ||
| 354 | + * 优惠劵编号 | ||
| 355 | + */ | ||
| 356 | + private Long id; | ||
| 357 | + /** | ||
| 358 | + * 优惠劵名 | ||
| 359 | + */ | ||
| 360 | + private String name; | ||
| 361 | + | ||
| 362 | + /** | ||
| 363 | + * 是否设置满多少金额可用,单位:分 | ||
| 364 | + */ | ||
| 365 | + private Integer usePrice; | ||
| 366 | + | ||
| 367 | + /** | ||
| 368 | + * 生效开始时间 | ||
| 369 | + */ | ||
| 370 | + private LocalDateTime validStartTime; | ||
| 371 | + /** | ||
| 372 | + * 生效结束时间 | ||
| 373 | + */ | ||
| 374 | + private LocalDateTime validEndTime; | ||
| 375 | + | ||
| 376 | + /** | ||
| 377 | + * 优惠类型 | ||
| 378 | + */ | ||
| 379 | + private Integer discountType; | ||
| 380 | + /** | ||
| 381 | + * 折扣百分比 | ||
| 382 | + */ | ||
| 383 | + private Integer discountPercent; | ||
| 384 | + /** | ||
| 385 | + * 优惠金额,单位:分 | ||
| 386 | + */ | ||
| 387 | + private Integer discountPrice; | ||
| 388 | + /** | ||
| 389 | + * 折扣上限,单位:分 | ||
| 390 | + */ | ||
| 391 | + private Integer discountLimitPrice; | ||
| 392 | + | ||
| 393 | + /** | ||
| 394 | + * 是否匹配 | ||
| 395 | + */ | ||
| 396 | + private Boolean match; | ||
| 397 | + /** | ||
| 398 | + * 不匹配的原因 | ||
| 399 | + */ | ||
| 400 | + private String mismatchReason; | ||
| 401 | + | ||
| 402 | + } | ||
| 403 | + | ||
| 404 | + | ||
| 342 | } | 405 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java
| 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; | 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | -import cn.hutool.core.lang.Assert; | ||
| 5 | import cn.hutool.core.util.ObjectUtil; | 4 | import cn.hutool.core.util.ObjectUtil; |
| 6 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 6 | +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | ||
| 7 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | ||
| 7 | import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; | 8 | import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; |
| 8 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | 9 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; |
| 9 | -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | ||
| 10 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; | 10 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; |
| 11 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | 11 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; |
| 12 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | 12 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; |
| 13 | +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; | ||
| 13 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | 14 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 14 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 15 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 15 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 16 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 17 | +import jakarta.annotation.Resource; | ||
| 16 | import org.springframework.core.annotation.Order; | 18 | import org.springframework.core.annotation.Order; |
| 17 | import org.springframework.stereotype.Component; | 19 | import org.springframework.stereotype.Component; |
| 18 | 20 | ||
| 19 | -import jakarta.annotation.Resource; | ||
| 20 | import java.util.List; | 21 | import java.util.List; |
| 21 | import java.util.function.Predicate; | 22 | import java.util.function.Predicate; |
| 22 | 23 | ||
| 23 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 24 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 25 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 24 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; | 26 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; |
| 25 | -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_MIN_PRICE; | ||
| 26 | -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_SPU; | 27 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_COUPON_CAN_NOT_USE; |
| 27 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER; | 28 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER; |
| 28 | -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_COUPON_PRICE_TOO_MUCH; | ||
| 29 | 29 | ||
| 30 | /** | 30 | /** |
| 31 | * 优惠劵的 {@link TradePriceCalculator} 实现类 | 31 | * 优惠劵的 {@link TradePriceCalculator} 实现类 |
| @@ -41,34 +41,37 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { | @@ -41,34 +41,37 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { | ||
| 41 | 41 | ||
| 42 | @Override | 42 | @Override |
| 43 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | 43 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { |
| 44 | - // 1.1 校验优惠劵 | ||
| 45 | - if (param.getCouponId() == null) { | ||
| 46 | - return; | ||
| 47 | - } | ||
| 48 | - CouponRespDTO coupon = couponApi.validateCoupon(new CouponValidReqDTO() | ||
| 49 | - .setId(param.getCouponId()).setUserId(param.getUserId())); | ||
| 50 | - Assert.notNull(coupon, "校验通过的优惠劵({}),不能为空", param.getCouponId()); | ||
| 51 | - // 1.2 只有【普通】订单,才允许使用优惠劵 | 44 | + // 只有【普通】订单,才允许使用优惠劵 |
| 52 | if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { | 45 | if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { |
| 53 | - throw exception(PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER); | 46 | + if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { |
| 47 | + throw exception(PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER); | ||
| 48 | + } | ||
| 49 | + return; | ||
| 54 | } | 50 | } |
| 55 | 51 | ||
| 56 | - // 2.1 获得匹配的商品 SKU 数组 | ||
| 57 | - List<TradePriceCalculateRespBO.OrderItem> orderItems = filterMatchCouponOrderItems(result, coupon); | ||
| 58 | - if (CollUtil.isEmpty(orderItems)) { | ||
| 59 | - throw exception(COUPON_NO_MATCH_SPU); | 52 | + // 1.1 加载用户的优惠劵列表 |
| 53 | + List<CouponRespDTO> coupons = couponApi.getCouponListByUserId(param.getUserId(), CouponStatusEnum.UNUSED.getStatus()); | ||
| 54 | + coupons.removeIf(coupon -> LocalDateTimeUtils.beforeNow(coupon.getValidEndTime())); | ||
| 55 | + // 1.2 计算优惠劵的使用条件 | ||
| 56 | + result.setCoupons(calculateCoupons(coupons, result)); | ||
| 57 | + | ||
| 58 | + // 2. 校验优惠劵是否可用 | ||
| 59 | + if (param.getCouponId() == null) { | ||
| 60 | + return; | ||
| 60 | } | 61 | } |
| 61 | - // 2.2 计算是否满足优惠劵的使用金额 | ||
| 62 | - Integer totalPayPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); | ||
| 63 | - if (totalPayPrice < coupon.getUsePrice()) { | ||
| 64 | - throw exception(COUPON_NO_MATCH_MIN_PRICE); | 62 | + TradePriceCalculateRespBO.Coupon couponBO = CollUtil.findOne(result.getCoupons(), item -> item.getId().equals(param.getCouponId())); |
| 63 | + CouponRespDTO coupon = CollUtil.findOne(coupons, item -> item.getId().equals(param.getCouponId())); | ||
| 64 | + if (couponBO == null || coupon == null) { | ||
| 65 | + throw exception(PRICE_CALCULATE_COUPON_CAN_NOT_USE, "优惠劵不存在"); | ||
| 66 | + } | ||
| 67 | + if (Boolean.FALSE.equals(couponBO.getMatch())) { | ||
| 68 | + throw exception(PRICE_CALCULATE_COUPON_CAN_NOT_USE, couponBO.getMismatchReason()); | ||
| 65 | } | 69 | } |
| 66 | 70 | ||
| 67 | // 3.1 计算可以优惠的金额 | 71 | // 3.1 计算可以优惠的金额 |
| 72 | + List<TradePriceCalculateRespBO.OrderItem> orderItems = filterMatchCouponOrderItems(result, coupon); | ||
| 73 | + Integer totalPayPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); | ||
| 68 | Integer couponPrice = getCouponPrice(coupon, totalPayPrice); | 74 | Integer couponPrice = getCouponPrice(coupon, totalPayPrice); |
| 69 | - if (couponPrice <= totalPayPrice) { | ||
| 70 | - throw exception(PRICE_CALCULATE_COUPON_PRICE_TOO_MUCH); | ||
| 71 | - } | ||
| 72 | // 3.2 计算分摊的优惠金额 | 75 | // 3.2 计算分摊的优惠金额 |
| 73 | List<Integer> divideCouponPrices = TradePriceCalculatorHelper.dividePrice(orderItems, couponPrice); | 76 | List<Integer> divideCouponPrices = TradePriceCalculatorHelper.dividePrice(orderItems, couponPrice); |
| 74 | 77 | ||
| @@ -76,7 +79,7 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { | @@ -76,7 +79,7 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { | ||
| 76 | result.setCouponId(param.getCouponId()); | 79 | result.setCouponId(param.getCouponId()); |
| 77 | // 4.2 记录优惠明细 | 80 | // 4.2 记录优惠明细 |
| 78 | TradePriceCalculatorHelper.addPromotion(result, orderItems, | 81 | TradePriceCalculatorHelper.addPromotion(result, orderItems, |
| 79 | - param.getCouponId(), coupon.getName(), PromotionTypeEnum.COUPON.getType(), | 82 | + param.getCouponId(), couponBO.getName(), PromotionTypeEnum.COUPON.getType(), |
| 80 | StrUtil.format("优惠劵:省 {} 元", TradePriceCalculatorHelper.formatPrice(couponPrice)), | 83 | StrUtil.format("优惠劵:省 {} 元", TradePriceCalculatorHelper.formatPrice(couponPrice)), |
| 81 | divideCouponPrices); | 84 | divideCouponPrices); |
| 82 | // 4.3 更新 SKU 优惠金额 | 85 | // 4.3 更新 SKU 优惠金额 |
| @@ -88,6 +91,43 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { | @@ -88,6 +91,43 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { | ||
| 88 | TradePriceCalculatorHelper.recountAllPrice(result); | 91 | TradePriceCalculatorHelper.recountAllPrice(result); |
| 89 | } | 92 | } |
| 90 | 93 | ||
| 94 | + /** | ||
| 95 | + * 计算用户的优惠劵列表(可用 + 不可用) | ||
| 96 | + * | ||
| 97 | + * @param coupons 优惠劵 | ||
| 98 | + * @param result 计算结果 | ||
| 99 | + * @return 优惠劵列表 | ||
| 100 | + */ | ||
| 101 | + private List<TradePriceCalculateRespBO.Coupon> calculateCoupons(List<CouponRespDTO> coupons, | ||
| 102 | + TradePriceCalculateRespBO result) { | ||
| 103 | + return convertList(coupons, coupon -> { | ||
| 104 | + TradePriceCalculateRespBO.Coupon matchCoupon = BeanUtils.toBean(coupon, TradePriceCalculateRespBO.Coupon.class); | ||
| 105 | + // 1.1 优惠劵未到使用时间 | ||
| 106 | + if (LocalDateTimeUtils.afterNow(coupon.getValidStartTime())) { | ||
| 107 | + return matchCoupon.setMatch(false).setMismatchReason("优惠劵未到使用时间"); | ||
| 108 | + } | ||
| 109 | + // 1.2 优惠劵没有匹配的商品 | ||
| 110 | + List<TradePriceCalculateRespBO.OrderItem> orderItems = filterMatchCouponOrderItems(result, coupon); | ||
| 111 | + if (CollUtil.isEmpty(orderItems)) { | ||
| 112 | + return matchCoupon.setMatch(false).setMismatchReason("优惠劵没有匹配的商品"); | ||
| 113 | + } | ||
| 114 | + // 1.3 差 %1$,.2f 元可用优惠劵 | ||
| 115 | + Integer totalPayPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); | ||
| 116 | + if (totalPayPrice < coupon.getUsePrice()) { | ||
| 117 | + return matchCoupon.setMatch(false) | ||
| 118 | + .setMismatchReason(String.format("差 %1$,.2f 元可用优惠劵", (coupon.getUsePrice() - totalPayPrice) / 100D)); | ||
| 119 | + } | ||
| 120 | + // 1.4 优惠金额超过订单金额 | ||
| 121 | + Integer couponPrice = getCouponPrice(coupon, totalPayPrice); | ||
| 122 | + if (couponPrice >= totalPayPrice) { | ||
| 123 | + return matchCoupon.setMatch(false).setMismatchReason("优惠金额超过订单金额"); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + // 2. 满足条件 | ||
| 127 | + return matchCoupon.setMatch(true); | ||
| 128 | + }); | ||
| 129 | + } | ||
| 130 | + | ||
| 91 | private Integer getCouponPrice(CouponRespDTO coupon, Integer totalPayPrice) { | 131 | private Integer getCouponPrice(CouponRespDTO coupon, Integer totalPayPrice) { |
| 92 | if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价 | 132 | if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价 |
| 93 | return coupon.getDiscountPrice(); | 133 | return coupon.getDiscountPrice(); |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculatorTest.java
| 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; | 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.ListUtil; | ||
| 3 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | 4 | import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; |
| 4 | import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; | 5 | import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; |
| 5 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | 6 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; |
| 6 | -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | ||
| 7 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; | 7 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; |
| 8 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | 8 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; |
| 9 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | 9 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; |
| 10 | +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; | ||
| 10 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | 11 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 13 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| @@ -14,8 +15,10 @@ import org.junit.jupiter.api.Test; | @@ -14,8 +15,10 @@ import org.junit.jupiter.api.Test; | ||
| 14 | import org.mockito.InjectMocks; | 15 | import org.mockito.InjectMocks; |
| 15 | import org.mockito.Mock; | 16 | import org.mockito.Mock; |
| 16 | 17 | ||
| 18 | +import java.time.Duration; | ||
| 17 | import java.util.ArrayList; | 19 | import java.util.ArrayList; |
| 18 | 20 | ||
| 21 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime; | ||
| 19 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | 22 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; |
| 20 | import static java.util.Arrays.asList; | 23 | import static java.util.Arrays.asList; |
| 21 | import static org.junit.jupiter.api.Assertions.assertEquals; | 24 | import static org.junit.jupiter.api.Assertions.assertEquals; |
| @@ -69,8 +72,10 @@ public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest { | @@ -69,8 +72,10 @@ public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest { | ||
| 69 | CouponRespDTO coupon = randomPojo(CouponRespDTO.class, o -> o.setId(1024L).setName("程序员节") | 72 | CouponRespDTO coupon = randomPojo(CouponRespDTO.class, o -> o.setId(1024L).setName("程序员节") |
| 70 | .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)) | 73 | .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)) |
| 71 | .setUsePrice(350).setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()) | 74 | .setUsePrice(350).setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()) |
| 72 | - .setDiscountPercent(50).setDiscountLimitPrice(70)); | ||
| 73 | - when(couponApi.validateCoupon(eq(new CouponValidReqDTO().setId(1024L).setUserId(233L)))).thenReturn(coupon); | 75 | + .setDiscountPercent(50).setDiscountLimitPrice(70)) |
| 76 | + .setValidStartTime(addTime(Duration.ofDays(1))).setValidEndTime(addTime(Duration.ofDays(2))); | ||
| 77 | + when(couponApi.getCouponListByUserId(eq(233L), eq(CouponStatusEnum.UNUSED.getStatus()))) | ||
| 78 | + .thenReturn(ListUtil.toList(coupon)); | ||
| 74 | 79 | ||
| 75 | // 调用 | 80 | // 调用 |
| 76 | tradeCouponPriceCalculator.calculate(param, result); | 81 | tradeCouponPriceCalculator.calculate(param, result); |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java
| @@ -144,7 +144,7 @@ public class OAuth2TokenServiceImplTest extends BaseDbAndRedisUnitTest { | @@ -144,7 +144,7 @@ public class OAuth2TokenServiceImplTest extends BaseDbAndRedisUnitTest { | ||
| 144 | // 调用,并断言 | 144 | // 调用,并断言 |
| 145 | assertServiceException(() -> oauth2TokenService.refreshAccessToken(refreshToken, clientId), | 145 | assertServiceException(() -> oauth2TokenService.refreshAccessToken(refreshToken, clientId), |
| 146 | new ErrorCode(401, "刷新令牌已过期")); | 146 | new ErrorCode(401, "刷新令牌已过期")); |
| 147 | - assertEquals(0, oauth2RefreshTokenMapper.selectCount()); | 147 | + assertEquals(0, oauth2AccessTokenMapper.selectCount()); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | @Test | 150 | @Test |
yudao-server/pom.xml
| @@ -33,11 +33,11 @@ | @@ -33,11 +33,11 @@ | ||
| 33 | </dependency> | 33 | </dependency> |
| 34 | 34 | ||
| 35 | <!-- 会员中心。默认注释,保证编译速度 --> | 35 | <!-- 会员中心。默认注释,保证编译速度 --> |
| 36 | - <dependency> | ||
| 37 | - <groupId>cn.iocoder.boot</groupId> | ||
| 38 | - <artifactId>yudao-module-member-biz</artifactId> | ||
| 39 | - <version>${revision}</version> | ||
| 40 | - </dependency> | 36 | +<!-- <dependency>--> |
| 37 | +<!-- <groupId>cn.iocoder.boot</groupId>--> | ||
| 38 | +<!-- <artifactId>yudao-module-member-biz</artifactId>--> | ||
| 39 | +<!-- <version>${revision}</version>--> | ||
| 40 | +<!-- </dependency>--> | ||
| 41 | 41 | ||
| 42 | <!-- 数据报表。默认注释,保证编译速度 --> | 42 | <!-- 数据报表。默认注释,保证编译速度 --> |
| 43 | <!-- <dependency>--> | 43 | <!-- <dependency>--> |
| @@ -52,11 +52,11 @@ | @@ -52,11 +52,11 @@ | ||
| 52 | <!-- <version>${revision}</version>--> | 52 | <!-- <version>${revision}</version>--> |
| 53 | <!-- </dependency>--> | 53 | <!-- </dependency>--> |
| 54 | <!-- 支付服务。默认注释,保证编译速度 --> | 54 | <!-- 支付服务。默认注释,保证编译速度 --> |
| 55 | - <dependency> | ||
| 56 | - <groupId>cn.iocoder.boot</groupId> | ||
| 57 | - <artifactId>yudao-module-pay-biz</artifactId> | ||
| 58 | - <version>${revision}</version> | ||
| 59 | - </dependency> | 55 | +<!-- <dependency>--> |
| 56 | +<!-- <groupId>cn.iocoder.boot</groupId>--> | ||
| 57 | +<!-- <artifactId>yudao-module-pay-biz</artifactId>--> | ||
| 58 | +<!-- <version>${revision}</version>--> | ||
| 59 | +<!-- </dependency>--> | ||
| 60 | 60 | ||
| 61 | <!-- 微信公众号模块。默认注释,保证编译速度 --> | 61 | <!-- 微信公众号模块。默认注释,保证编译速度 --> |
| 62 | <!-- <dependency>--> | 62 | <!-- <dependency>--> |
| @@ -66,26 +66,26 @@ | @@ -66,26 +66,26 @@ | ||
| 66 | <!-- </dependency>--> | 66 | <!-- </dependency>--> |
| 67 | 67 | ||
| 68 | <!-- 商城相关模块。默认注释,保证编译速度--> | 68 | <!-- 商城相关模块。默认注释,保证编译速度--> |
| 69 | - <dependency> | ||
| 70 | - <groupId>cn.iocoder.boot</groupId> | ||
| 71 | - <artifactId>yudao-module-promotion-biz</artifactId> | ||
| 72 | - <version>${revision}</version> | ||
| 73 | - </dependency> | ||
| 74 | - <dependency> | ||
| 75 | - <groupId>cn.iocoder.boot</groupId> | ||
| 76 | - <artifactId>yudao-module-product-biz</artifactId> | ||
| 77 | - <version>${revision}</version> | ||
| 78 | - </dependency> | ||
| 79 | - <dependency> | ||
| 80 | - <groupId>cn.iocoder.boot</groupId> | ||
| 81 | - <artifactId>yudao-module-trade-biz</artifactId> | ||
| 82 | - <version>${revision}</version> | ||
| 83 | - </dependency> | ||
| 84 | - <dependency> | ||
| 85 | - <groupId>cn.iocoder.boot</groupId> | ||
| 86 | - <artifactId>yudao-module-statistics-biz</artifactId> | ||
| 87 | - <version>${revision}</version> | ||
| 88 | - </dependency> | 69 | +<!-- <dependency>--> |
| 70 | +<!-- <groupId>cn.iocoder.boot</groupId>--> | ||
| 71 | +<!-- <artifactId>yudao-module-promotion-biz</artifactId>--> | ||
| 72 | +<!-- <version>${revision}</version>--> | ||
| 73 | +<!-- </dependency>--> | ||
| 74 | +<!-- <dependency>--> | ||
| 75 | +<!-- <groupId>cn.iocoder.boot</groupId>--> | ||
| 76 | +<!-- <artifactId>yudao-module-product-biz</artifactId>--> | ||
| 77 | +<!-- <version>${revision}</version>--> | ||
| 78 | +<!-- </dependency>--> | ||
| 79 | +<!-- <dependency>--> | ||
| 80 | +<!-- <groupId>cn.iocoder.boot</groupId>--> | ||
| 81 | +<!-- <artifactId>yudao-module-trade-biz</artifactId>--> | ||
| 82 | +<!-- <version>${revision}</version>--> | ||
| 83 | +<!-- </dependency>--> | ||
| 84 | +<!-- <dependency>--> | ||
| 85 | +<!-- <groupId>cn.iocoder.boot</groupId>--> | ||
| 86 | +<!-- <artifactId>yudao-module-statistics-biz</artifactId>--> | ||
| 87 | +<!-- <version>${revision}</version>--> | ||
| 88 | +<!-- </dependency>--> | ||
| 89 | 89 | ||
| 90 | <!-- CRM 相关模块。默认注释,保证编译速度 --> | 90 | <!-- CRM 相关模块。默认注释,保证编译速度 --> |
| 91 | <!-- <dependency>--> | 91 | <!-- <dependency>--> |