diff --git a/jzo2o-api/src/main/java/com/jzo2o/api/market/CouponApi.java b/jzo2o-api/src/main/java/com/jzo2o/api/market/CouponApi.java new file mode 100644 index 0000000..3875cb0 --- /dev/null +++ b/jzo2o-api/src/main/java/com/jzo2o/api/market/CouponApi.java @@ -0,0 +1,22 @@ +package com.jzo2o.api.market; + +import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 内部接口 - 优惠卷相关接口 + * @author JIAN + */ +@FeignClient(contextId = "jzo2o-market", value = "jzo2o-market", path = "/market/inner/coupon") +public interface CouponApi { + /** + * 根据订单金额获取当前用户可用优惠卷 + */ + @GetMapping("/getAvailable") + List getAvailableCoupon(@RequestParam BigDecimal totalAmount); +} \ No newline at end of file diff --git a/jzo2o-api/src/main/java/com/jzo2o/api/market/dto/response/AvailableCouponsResDTO.java b/jzo2o-api/src/main/java/com/jzo2o/api/market/dto/response/AvailableCouponsResDTO.java index eca6906..71e2c3e 100644 --- a/jzo2o-api/src/main/java/com/jzo2o/api/market/dto/response/AvailableCouponsResDTO.java +++ b/jzo2o-api/src/main/java/com/jzo2o/api/market/dto/response/AvailableCouponsResDTO.java @@ -3,12 +3,17 @@ package com.jzo2o.api.market.dto.response; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import lombok.experimental.Accessors; import java.math.BigDecimal; import java.time.LocalDateTime; +/** + * @author JIAN + */ @Data @ApiModel("优惠券信息") +@Accessors(chain = true) public class AvailableCouponsResDTO { @ApiModelProperty("优惠券id") private Long id; @@ -16,34 +21,34 @@ public class AvailableCouponsResDTO { /** * 优惠券名称 */ - @ApiModelProperty(value = "活动名称",required = true) + @ApiModelProperty(value = "活动名称", required = true) private String name; /** * 活动id */ - @ApiModelProperty(value = "活动id",required = true) + @ApiModelProperty(value = "活动id", required = true) private Long activityId; - @ApiModelProperty(value = "使用类型,1:满减,2:折扣",required = true) + @ApiModelProperty(value = "使用类型,1:满减,2:折扣", required = true) private Integer type; /** * 折扣 */ - @ApiModelProperty(value = "折扣",required = false) + @ApiModelProperty(value = "折扣") private Integer discountRate; /** * 优惠金额 */ - @ApiModelProperty(value = "优惠金额",required = false) + @ApiModelProperty(value = "优惠金额") private BigDecimal discountAmount; /** * 满减金额 */ - @ApiModelProperty(value = "满减条件,0:表示无门槛",required = true) + @ApiModelProperty(value = "满减条件,0:表示无门槛", required = true) private BigDecimal amountCondition; /** @@ -51,4 +56,4 @@ public class AvailableCouponsResDTO { */ @ApiModelProperty("优惠券过期时间") private LocalDateTime validityTime; -} +} \ No newline at end of file diff --git a/jzo2o-market/src/main/java/com/jzo2o/market/controller/inner/CouponController.java b/jzo2o-market/src/main/java/com/jzo2o/market/controller/inner/CouponController.java new file mode 100644 index 0000000..59bc83b --- /dev/null +++ b/jzo2o-market/src/main/java/com/jzo2o/market/controller/inner/CouponController.java @@ -0,0 +1,39 @@ +package com.jzo2o.market.controller.inner; + +import com.jzo2o.api.market.CouponApi; +import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO; +import com.jzo2o.market.service.ICouponService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.List; + +/** + * 内部接口 - 优惠卷管理控制器 + * @author JIAN + */ +@Slf4j +@RestController("innerCouponController") +@RequestMapping("/inner/coupon") +public class CouponController implements CouponApi { + @Resource + private ICouponService couponService; + + /** + * 根据订单金额获取当前用户可用优惠卷 + */ + @Override + @GetMapping("/getAvailable") + @ApiOperation("获取可用优惠券列表") + @ApiImplicitParam(name = "totalAmount", value = "总金额,单位分", required = true, dataTypeClass = BigDecimal.class) + public List getAvailableCoupon(@RequestParam BigDecimal totalAmount) { + return couponService.getAvailableCoupon(totalAmount); + } +} \ No newline at end of file diff --git a/jzo2o-market/src/main/java/com/jzo2o/market/service/ICouponService.java b/jzo2o-market/src/main/java/com/jzo2o/market/service/ICouponService.java index b4b5853..fe4a955 100644 --- a/jzo2o-market/src/main/java/com/jzo2o/market/service/ICouponService.java +++ b/jzo2o-market/src/main/java/com/jzo2o/market/service/ICouponService.java @@ -1,6 +1,7 @@ package com.jzo2o.market.service; import com.baomidou.mybatisplus.extension.service.IService; +import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO; import com.jzo2o.common.model.PageResult; import com.jzo2o.market.enums.CouponStatusEnum; import com.jzo2o.market.model.domain.Coupon; @@ -8,6 +9,7 @@ import com.jzo2o.market.model.dto.request.CouponPageQueryDTO; import com.jzo2o.market.model.dto.response.CouponPageInfoResDTO; import com.jzo2o.market.model.dto.response.CouponSimpleInfoResDTO; +import java.math.BigDecimal; import java.util.List; /** @@ -37,4 +39,9 @@ public interface ICouponService extends IService { * 同步优惠卷数据到数据库中 */ void syncCouponRecord(long activityId, long userId); + + /** + * 根据订单金额获取当前用户可用优惠卷 + */ + List getAvailableCoupon(BigDecimal totalAmount); } \ No newline at end of file diff --git a/jzo2o-market/src/main/java/com/jzo2o/market/service/impl/CouponServiceImpl.java b/jzo2o-market/src/main/java/com/jzo2o/market/service/impl/CouponServiceImpl.java index 21caa0f..d857892 100644 --- a/jzo2o-market/src/main/java/com/jzo2o/market/service/impl/CouponServiceImpl.java +++ b/jzo2o-market/src/main/java/com/jzo2o/market/service/impl/CouponServiceImpl.java @@ -1,18 +1,21 @@ package com.jzo2o.market.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.jzo2o.api.customer.CommonUserApi; import com.jzo2o.api.customer.dto.response.CommonUserResDTO; +import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO; import com.jzo2o.common.expcetions.BadRequestException; +import com.jzo2o.common.expcetions.CommonException; import com.jzo2o.common.expcetions.DBException; import com.jzo2o.common.model.PageResult; import com.jzo2o.common.utils.BeanUtils; import com.jzo2o.common.utils.CollUtils; +import com.jzo2o.common.utils.ObjectUtils; import com.jzo2o.market.enums.CouponStatusEnum; +import com.jzo2o.market.enums.CouponTypeEnum; import com.jzo2o.market.mapper.CouponMapper; import com.jzo2o.market.model.domain.Activity; import com.jzo2o.market.model.domain.Coupon; @@ -28,9 +31,12 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -137,4 +143,54 @@ public class CouponServiceImpl extends ServiceImpl impleme throw new DBException("更新活动库存失败"); } } + + @Override + public List getAvailableCoupon(BigDecimal totalAmount) { + Long userId = Optional + .ofNullable(UserContext.currentUserId()) + .orElseThrow(() -> new CommonException("用户信息不存在")); + + List couponList = lambdaQuery() + .eq(Coupon::getUserId, userId) + .le(Coupon::getAmountCondition, totalAmount) + .eq(Coupon::getStatus, CouponStatusEnum.NO_USE) + .ge(Coupon::getValidityTime, LocalDateTime.now()) + .and(and -> and + .isNull(Coupon::getDiscountAmount) + .or(or -> or.le(Coupon::getDiscountAmount, totalAmount))) + .list(); + + if (CollUtils.isEmpty(couponList)) { + return new ArrayList<>(); + } + + return couponList.stream() + .map(coupon -> BeanUtils + .toBean(coupon, AvailableCouponsResDTO.class) + .setType(coupon.getType().getType()) + .setDiscountAmount(this.calcDiscountAmount(coupon, totalAmount))) + // 默认BigDecimal的比较器排序从小到大 需要按优惠金额从大到小排序 + .sorted(Comparator.comparing(AvailableCouponsResDTO::getDiscountAmount).reversed()) + .collect(Collectors.toList()); + } + + /** + * 计算优惠卷的优惠价格 + * @param coupon 优惠卷信息 + * @param totalAmount 订单总金额 + */ + private BigDecimal calcDiscountAmount(Coupon coupon, BigDecimal totalAmount) { + CouponTypeEnum type = coupon.getType(); + BigDecimal discountAmount = BigDecimal.ZERO; + + if (type == CouponTypeEnum.AMOUNT_DISCOUNT) { + discountAmount = coupon.getDiscountAmount(); + } else if (type == CouponTypeEnum.RATE_DISCOUNT) { + // 1 <= coupon.getDiscountRate() <= 99 + BigDecimal discountRate = new BigDecimal(String.format("0.%02d", 100 - coupon.getDiscountRate())); + discountAmount = totalAmount.multiply(discountRate); + } + + return discountAmount; + } } \ No newline at end of file