mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 01:01:52 +08:00
【功能新增】商城: 满减送活动下单后,赠送优惠劵
This commit is contained in:
parent
e0d9f7cfba
commit
3e66a922bf
@ -3,9 +3,10 @@ package cn.iocoder.yudao.module.promotion.api.coupon;
|
|||||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO;
|
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
|
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
|
||||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO;
|
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO;
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优惠劵 API 接口
|
* 优惠劵 API 接口
|
||||||
*
|
*
|
||||||
@ -35,4 +36,13 @@ public interface CouponApi {
|
|||||||
*/
|
*/
|
||||||
CouponRespDTO validateCoupon(@Valid CouponValidReqDTO validReqDTO);
|
CouponRespDTO validateCoupon(@Valid CouponValidReqDTO validReqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【管理员】给指定用户批量发送优惠券
|
||||||
|
*
|
||||||
|
* @param templateIds 优惠劵编号的数组
|
||||||
|
* @param counts 优惠券数量的数组
|
||||||
|
* @param userId 用户编号
|
||||||
|
*/
|
||||||
|
void takeCouponsByAdmin(List<Long> templateIds, List<Integer> counts, Long userId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,11 @@ import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO;
|
|||||||
import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
|
import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
|
||||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优惠劵 API 实现类
|
* 优惠劵 API 实现类
|
||||||
@ -41,4 +42,9 @@ public class CouponApiImpl implements CouponApi {
|
|||||||
return CouponConvert.INSTANCE.convert(coupon);
|
return CouponConvert.INSTANCE.convert(coupon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void takeCouponsByAdmin(List<Long> templateIds, List<Integer> counts, Long userId) {
|
||||||
|
couponService.takeCouponsByAdmin(templateIds, counts, userId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,15 @@ public interface CouponService {
|
|||||||
takeCoupon(templateId, userIds, CouponTakeTypeEnum.ADMIN);
|
takeCoupon(templateId, userIds, CouponTakeTypeEnum.ADMIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【管理员】给指定用户批量发送优惠券
|
||||||
|
*
|
||||||
|
* @param templateIds 优惠劵编号的数组
|
||||||
|
* @param counts 优惠券数量的数组
|
||||||
|
* @param userId 用户编号
|
||||||
|
*/
|
||||||
|
void takeCouponsByAdmin(List<Long> templateIds, List<Integer> counts, Long userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 【会员】领取优惠券
|
* 【会员】领取优惠券
|
||||||
*
|
*
|
||||||
|
@ -19,19 +19,19 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponMapper;
|
|||||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum;
|
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
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.framework.common.util.collection.CollectionUtils.*;
|
||||||
|
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
|
||||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
|
||||||
@ -175,10 +175,34 @@ public class CouponServiceImpl implements CouponService {
|
|||||||
// 3. 批量保存优惠劵
|
// 3. 批量保存优惠劵
|
||||||
couponMapper.insertBatch(convertList(userIds, userId -> CouponConvert.INSTANCE.convert(template, userId)));
|
couponMapper.insertBatch(convertList(userIds, userId -> CouponConvert.INSTANCE.convert(template, userId)));
|
||||||
|
|
||||||
// 3. 增加优惠劵模板的领取数量
|
// 4. 增加优惠劵模板的领取数量
|
||||||
couponTemplateService.updateCouponTemplateTakeCount(templateId, userIds.size());
|
couponTemplateService.updateCouponTemplateTakeCount(templateId, userIds.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void takeCouponsByAdmin(List<Long> templateIds, List<Integer> counts, Long userId) {
|
||||||
|
// 1. 获得优惠券模版
|
||||||
|
List<CouponTemplateDO> templateList = couponTemplateService.getCouponTemplateList(templateIds);
|
||||||
|
if (CollUtil.isEmpty(templateList)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Long, CouponTemplateDO> templateMap = convertMap(templateList, CouponTemplateDO::getId);
|
||||||
|
// 2.1 批量构建优惠券
|
||||||
|
List<CouponDO> couponList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < templateIds.size(); i++) {
|
||||||
|
int finalI = i;
|
||||||
|
findAndThen(templateMap, templateIds.get(i), template -> {
|
||||||
|
for (int j = 0; j < counts.get(finalI); j++) {
|
||||||
|
couponList.add(CouponConvert.INSTANCE.convert(template, userId)
|
||||||
|
.setTakeType(CouponTakeTypeEnum.ADMIN.getValue()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 2.2 批量保存优惠券
|
||||||
|
couponMapper.insertBatch(couponList);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void takeCouponByRegister(Long userId) {
|
public void takeCouponByRegister(Long userId) {
|
||||||
|
@ -16,6 +16,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
|
|||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 交易订单 DO
|
* 交易订单 DO
|
||||||
@ -290,6 +291,18 @@ public class TradeOrderDO extends BaseDO {
|
|||||||
* VIP 减免金额,单位:分
|
* VIP 减免金额,单位:分
|
||||||
*/
|
*/
|
||||||
private Integer vipPrice;
|
private Integer vipPrice;
|
||||||
|
/**
|
||||||
|
* 赠送的优惠劵编号的数组
|
||||||
|
*
|
||||||
|
* 目的:用于后续取消或者售后订单时,需要扣减赠送
|
||||||
|
*/
|
||||||
|
private List<Long> couponIds;
|
||||||
|
/**
|
||||||
|
* 赠送的优惠券数量的数组
|
||||||
|
*
|
||||||
|
* 目的:用于后续取消或者售后订单时,需要扣减赠送
|
||||||
|
*/
|
||||||
|
private List<Integer> couponCounts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 秒杀活动编号
|
* 秒杀活动编号
|
||||||
|
@ -160,19 +160,6 @@ public class TradeOrderItemDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
private Integer vipPrice;
|
private Integer vipPrice;
|
||||||
|
|
||||||
/**
|
|
||||||
* 赠送的优惠劵编号的数组
|
|
||||||
*
|
|
||||||
* 目的:用于后续取消或者售后订单时,需要扣减赠送
|
|
||||||
*/
|
|
||||||
private List<Long> couponIds;
|
|
||||||
/**
|
|
||||||
* 赠送的优惠券数量的数组
|
|
||||||
*
|
|
||||||
* 目的:用于后续取消或者售后订单时,需要扣减赠送
|
|
||||||
*/
|
|
||||||
private List<Integer> couponCounts;
|
|
||||||
|
|
||||||
// ========== 售后基本信息 ==========
|
// ========== 售后基本信息 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -201,6 +201,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
|||||||
order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus());
|
order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus());
|
||||||
order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum));
|
order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum));
|
||||||
order.setUserIp(getClientIP()).setTerminal(getTerminal());
|
order.setUserIp(getClientIP()).setTerminal(getTerminal());
|
||||||
|
// 优惠券
|
||||||
|
order.setCouponIds(calculateRespBO.getCouponIds()).setCouponCounts(calculateRespBO.getCouponCounts());
|
||||||
// 支付 + 退款信息
|
// 支付 + 退款信息
|
||||||
order.setAdjustPrice(0).setPayStatus(false);
|
order.setAdjustPrice(0).setPayStatus(false);
|
||||||
order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0);
|
order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.iocoder.yudao.module.trade.service.order.handler;
|
package cn.iocoder.yudao.module.trade.service.order.handler;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
|
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
|
||||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
|
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
|
||||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||||
@ -32,16 +33,25 @@ public class TradeCouponOrderHandler implements TradeOrderHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
|
public void afterPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
|
||||||
|
if (CollUtil.isEmpty(order.getCouponIds())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 赠送优惠券
|
||||||
|
couponApi.takeCouponsByAdmin(order.getCouponIds(), order.getCouponCounts(), order.getUserId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
|
public void afterCancelOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
|
||||||
if (order.getCouponId() == null || order.getCouponId() <= 0) {
|
// 情况一:退还订单使用的优惠券
|
||||||
|
if (order.getCouponId() != null && order.getCouponId() > 0) {
|
||||||
|
// 退回优惠劵
|
||||||
|
couponApi.returnUsedCoupon(order.getCouponId());
|
||||||
|
}
|
||||||
|
// 情况二:收回赠送的优惠券
|
||||||
|
if (CollUtil.isEmpty(order.getCouponIds())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 退回优惠劵
|
// TODO @puhui999: 收回优惠券再考虑一下,是直接删除券还是改个状态
|
||||||
couponApi.returnUsedCoupon(order.getCouponId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,6 @@ public class TradePriceCalculateRespBO {
|
|||||||
*/
|
*/
|
||||||
private Boolean freeDelivery;
|
private Boolean freeDelivery;
|
||||||
|
|
||||||
// TODO @puhui999: 订单保存时需要保存
|
|
||||||
/**
|
/**
|
||||||
* 赠送的优惠劵编号的数组
|
* 赠送的优惠劵编号的数组
|
||||||
*/
|
*/
|
||||||
|
@ -19,6 +19,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
|
||||||
@ -105,8 +106,18 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
|
|||||||
}
|
}
|
||||||
// 4.3 记录赠送的优惠券
|
// 4.3 记录赠送的优惠券
|
||||||
if (rule.getGiveCoupon()) {
|
if (rule.getGiveCoupon()) {
|
||||||
// TODO @puhui999: 需要考虑赠送的优惠券是否重叠,重叠则对数量进行累加
|
for (int i = 0; i < rule.getCouponIds().size(); i++) {
|
||||||
result.setCouponIds(rule.getCouponIds()).setCouponCounts(rule.getCouponCounts());
|
Long couponId = result.getCouponIds().get(i);
|
||||||
|
Integer couponCount = result.getCouponCounts().get(i);
|
||||||
|
int index = CollUtil.indexOf(result.getCouponIds(), id -> Objects.equals(couponId, id));
|
||||||
|
if (index != -1) { // 情况一:别的满减活动送过同类优惠券,则直接增加数量
|
||||||
|
List<Integer> couponCounts = result.getCouponCounts();
|
||||||
|
couponCounts.set(index, couponCounts.get(index) + couponCount);
|
||||||
|
result.setCouponCounts(couponCounts);
|
||||||
|
} else { // 情况二:还没有赠送的优惠券
|
||||||
|
result.setCouponIds(rule.getCouponIds()).setCouponCounts(rule.getCouponCounts());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user