diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/config/DatabaseConfiguration.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/config/DatabaseConfiguration.java deleted file mode 100644 index 04b70216d..000000000 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/config/DatabaseConfiguration.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.mall.promotion.biz.config; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -@Configuration -@MapperScan("cn.iocoder.mall.promotion.biz.dao") // 扫描对应的 Mapper 接口 -@EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理。为什么使用 proxyTargetClass 参数,参见 https://blog.csdn.net/huang_550/article/details/76492600 -//@EnableConfigurationProperties(DataSourceProperties.class) -public class DatabaseConfiguration { - - // 数据源,使用 HikariCP - -} diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/config/ServiceExceptionConfiguration.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/config/ServiceExceptionConfiguration.java deleted file mode 100644 index 8435e0fa7..000000000 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/config/ServiceExceptionConfiguration.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.mall.promotion.biz.config; - -import cn.iocoder.common.framework.util.ServiceExceptionUtil; -import cn.iocoder.mall.promotion.api.enums.PromotionErrorCodeEnum; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.event.EventListener; - -@Configuration -public class ServiceExceptionConfiguration { - - @EventListener(ApplicationReadyEvent.class) // 可参考 https://www.cnblogs.com/ssslinppp/p/7607509.html - public void initMessages() { -// 从 service_exception_message.properties 加载错误码的方案 -// Properties properties; -// try { -// properties = PropertiesLoaderUtils.loadAllProperties("classpath:service_exception_message.properties"); -// } catch (IOException e) { -// throw new RuntimeException(e); -// } - for (PromotionErrorCodeEnum item : PromotionErrorCodeEnum.values()) { - ServiceExceptionUtil.put(item.getCode(), item.getMessage()); - } - } - -} \ No newline at end of file diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponCardConvert.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponCardConvert.java deleted file mode 100644 index b69663b9f..000000000 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponCardConvert.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.mall.promotion.biz.convert; - -import cn.iocoder.mall.promotion.api.bo.CouponCardAvailableBO; -import cn.iocoder.mall.promotion.api.bo.CouponCardBO; -import cn.iocoder.mall.promotion.api.bo.CouponCardDetailBO; -import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO; -import org.mapstruct.Mapper; -import org.mapstruct.Mappings; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface CouponCardConvert { - - CouponCardConvert INSTANCE = Mappers.getMapper(CouponCardConvert.class); - -// @Mappings({}) -// CouponCardBO convertToBO(CouponCardDO banner); -// - @Mappings({}) - List convertToBO(List cardList); - - @Mappings({}) - CouponCardBO convert(CouponCardDO card); - - @Mappings({}) - CouponCardDetailBO convert2(CouponCardDO card); - - @Mappings({}) - CouponCardAvailableBO convert2(CouponCardDO card, boolean x); // TODO 芋艿,临时用来解决 mapstruct 无法正确匹配方法的问题 - -} diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponTemplateConvert.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponTemplateConvert.java deleted file mode 100644 index 3c24e0112..000000000 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/convert/CouponTemplateConvert.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.mall.promotion.biz.convert; - -import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO; -import cn.iocoder.mall.promotion.api.dto.CouponCardTemplateAddDTO; -import cn.iocoder.mall.promotion.api.dto.CouponCardTemplateUpdateDTO; -import cn.iocoder.mall.promotion.api.dto.CouponCodeTemplateAddDTO; -import cn.iocoder.mall.promotion.api.dto.CouponCodeTemplateUpdateDTO; -import cn.iocoder.mall.promotion.biz.dataobject.CouponTemplateDO; -import org.mapstruct.Mapper; -import org.mapstruct.Mappings; -import org.mapstruct.factory.Mappers; - -import java.util.List; - -@Mapper -public interface CouponTemplateConvert { - - CouponTemplateConvert INSTANCE = Mappers.getMapper(CouponTemplateConvert.class); - -// @Mappings({}) -// CouponTemplateBO convertToBO(CouponTemplateDO banner); -// - @Mappings({}) - List convertToBO(List templateList); - - @Mappings({}) - CouponTemplateDO convert(CouponCodeTemplateUpdateDTO template); - - @Mappings({}) - CouponTemplateDO convert(CouponCardTemplateAddDTO template); - - @Mappings({}) - CouponTemplateDO convert(CouponCardTemplateUpdateDTO template); - - @Mappings({}) - CouponTemplateDO convert(CouponCodeTemplateAddDTO template); - - @Mappings({}) - CouponTemplateBO convert(CouponTemplateDO template); - -} diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dataobject/PromotionActivityDO.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dataobject/PromotionActivityDO.java deleted file mode 100644 index e987a7871..000000000 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/dataobject/PromotionActivityDO.java +++ /dev/null @@ -1,187 +0,0 @@ -package cn.iocoder.mall.promotion.biz.dataobject; - -import cn.iocoder.mall.mybatis.core.dataobject.BaseDO; -import lombok.Data; -import lombok.experimental.Accessors; - -import java.util.Date; -import java.util.List; - -/** - * 促销活动 DO - */ -@Data -@Accessors(chain = true) -public class PromotionActivityDO extends BaseDO { - - /** - * 活动编号 - */ - private Integer id; - /** - * 活动标题 - */ - private String title; - /** - * 活动类型 - * - * 参见 {@link cn.iocoder.mall.promotion.api.enums.PromotionActivityTypeEnum} 枚举 - */ - private Integer activityType; -// /** -// * 促销类型 -// * // TODO 芋艿 https://jos.jd.com/api/complexTemplate.htm?webPamer=promotion_v_o&groupName=%E4%BF%83%E9%94%80API&id=54&restName=jingdong.seller.promotion.list&isMulti=false 促销类型,可选值:单品促销(1),赠品促销(4),套装促销(6),总价促销(10) -// */ -// private Integer promotionType; - /** - * 活动状态 - * - * 参见 {@link cn.iocoder.mall.promotion.api.enums.PromotionActivityStatusEnum} 枚举 - */ - private Integer status; - /** - * 开始时间 - */ - private Date startTime; - /** - * 结束时间 - */ - private Date endTime; - /** - * 失效时间 - */ - private Date invalidTime; - /** - * 删除时间 - */ - private Date deleteTime; - /** - * 限制折扣字符串,使用 JSON 序列化成字符串存储 - */ - private TimeLimitedDiscount timeLimitedDiscount; - /** - * 满减送字符串,使用 JSON 序列化成字符串存储 - */ - private FullPrivilege fullPrivilege; - - /** - * 限制折扣 - */ - @Data - @Accessors(chain = true) - public static class TimeLimitedDiscount { - - /** - * 商品折扣 - */ - @Data - @Accessors(chain = true) - public static class Item { - - /** - * 商品 SPU 编号 - */ - private Integer spuId; - /** - * 优惠类型 - */ - private Integer preferentialType; - /** - * 优惠值 - */ - private Integer preferentialValue; - - } - - /** - * 每人每种限购多少 - * - * 当 quota = 0 时,表示不限购 - */ - private Integer quota; - /** - * 商品折扣数组 - */ - private List items; - - } - - /** - * 满减送 - */ - @Data - @Accessors(chain = true) - public static class FullPrivilege { - - /** - * 优惠 - */ - @Data - @Accessors(chain = true) - public static class Privilege { - - /** - * 满足类型 - * - * 1 - 金额 - * 2 - 件数 - */ - private Integer meetType; - /** - * 满足值 - */ - private Integer meetValue; - /** - * 优惠类型 - */ - private Integer preferentialType; - /** - * 优惠值 - */ - private Integer preferentialValue; -// /** -// * 是否包邮 -// */ -// private Boolean isPostage; -// /** -// * 积分 -// */ -// private Integer score; -// /** -// * 优惠劵(码)分组编号 -// */ -// private Integer couponTemplateId; -// /** -// * 优惠劵(码)数量 -// */ -// private Integer couponNum; -// /** -// * 赠品编号 -// */ -// private Integer presentId; - - } - - /** - * 可用范围的类型 - * - * 参见 {@link cn.iocoder.mall.promotion.api.enums.RangeTypeEnum} 枚举 - * 暂时只用 “所有可用” + “PRODUCT_INCLUDE_PRT” - */ - private Integer rangeType; - /** - * 指定可用商品列表 - */ - private List rangeValues; - /** - * 是否循环 - */ - private Boolean cycled; - /** - * 优惠数组 - */ - private List privileges; - - } - -} diff --git a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java index ab857af28..4cf2bcf2a 100644 --- a/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java +++ b/promotion/promotion-service-impl/src/main/java/cn/iocoder/mall/promotion/biz/service/CouponServiceImpl.java @@ -27,8 +27,6 @@ public class CouponServiceImpl implements CouponService { @Autowired private CouponTemplateMapper couponTemplateMapper; - @Autowired - private CouponCardMapper couponCardMapper; // ========== 优惠劵(码)模板 ========== @@ -164,209 +162,4 @@ public class CouponServiceImpl implements CouponService { return true; } - // ========== 优惠劵 ========== - - @Override - public CouponCardPageBO getCouponCardPage(CouponCardPageDTO couponCardPageDTO) { - CouponCardPageBO pageBO = new CouponCardPageBO(); - // 查询分页数据 - int offset = (couponCardPageDTO.getPageNo() - 1) * couponCardPageDTO.getPageSize(); - pageBO.setList(CouponCardConvert.INSTANCE.convertToBO(couponCardMapper.selectListByPage( - couponCardPageDTO.getUserId(), couponCardPageDTO.getStatus(), - offset, couponCardPageDTO.getPageSize()))); - // 查询分页总数 - pageBO.setTotal(couponCardMapper.selectCountByPage( - couponCardPageDTO.getUserId(), couponCardPageDTO.getStatus())); - return pageBO; - } - - @Override - @Transactional - public CouponCardBO addCouponCard(Integer userId, Integer couponTemplateId) { - // 校验 CouponCardTemplate 存在 - CouponTemplateDO template = couponTemplateMapper.selectById(couponTemplateId); - if (template == null) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_TEMPLATE_NOT_EXISTS.getCode()); - } - // 校验 CouponCardTemplate 是 CARD - if (!CouponTemplateTypeEnum.CARD.getValue().equals(template.getType())) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_TEMPLATE_NOT_CARD.getCode()); - } - // 校验 CouponCardTemplate 状态是否开启 - if (!CouponTemplateStatusEnum.ENABLE.getValue().equals(template.getStatus())) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_TEMPLATE_STATUS_NOT_ENABLE.getCode()); - } - // 校验 CouponCardTemplate 是否到达可领取的上限 - if (template.getStatFetchNum() > template.getTotal()) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_TEMPLATE_TOTAL_NOT_ENOUGH.getCode()); - } - // 校验单人可领取优惠劵是否到达上限 - if (couponCardMapper.selectCountByUserIdAndTemplateId(userId, couponTemplateId) > template.getQuota()) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode()); - } - // 增加优惠劵已领取量 - int updateTemplateCount = couponTemplateMapper.updateStatFetchNumIncr(couponTemplateId); - if (updateTemplateCount == 0) { // 超过 CouponCardTemplate 发放量 - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode()); - } - // 创建优惠劵 - // 1. 基本信息 + 领取情况 - CouponCardDO card = new CouponCardDO() - .setTemplateId(couponTemplateId) - .setTitle(template.getTitle()) - .setStatus(CouponCardStatusEnum.UNUSED.getValue()) - .setUserId(userId) - .setTakeType(CouponCardTakeTypeEnum.BY_USER.getValue()); // TODO 需要改 - // 2. 使用规则 - card.setPriceAvailable(template.getPriceAvailable()); - setCouponCardValidTime(card, template); - // 3. 使用效果 - card.setPreferentialType(template.getPreferentialType()) - .setPriceOff(template.getPriceOff()) - .setPercentOff(template.getPercentOff()).setDiscountPriceLimit(template.getDiscountPriceLimit()); - // 保存优惠劵模板到数据库 - card.setCreateTime(new Date()); - couponCardMapper.insert(card); - // 返回成功 - return CouponCardConvert.INSTANCE.convert(card); - } - - @Override - public Boolean useCouponCard(Integer userId, Integer couponCardId) { - // 查询优惠劵 - CouponCardDO card = couponCardMapper.selectById(couponCardId); - if (card == null) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_NOT_EXISTS.getCode()); - } - if (!userId.equals(card.getUserId())) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_ERROR_USER.getCode()); - } - if (!CouponCardStatusEnum.UNUSED.getValue().equals(card.getStatus())) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_STATUS_NOT_UNUSED.getCode()); - } - if (DateUtil.isBetween(card.getValidStartTime(), card.getValidEndTime())) { // 为避免定时器没跑,实际优惠劵已经过期 - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_STATUS_NOT_UNUSED.getCode()); - } - // 更新优惠劵已使用 - int updateCount = couponCardMapper.updateByIdAndStatus(card.getId(), CouponCardStatusEnum.UNUSED.getValue(), - new CouponCardDO().setStatus(CouponCardStatusEnum.USED.getValue()).setUsedTime(new Date())); - if (updateCount == 0) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_STATUS_NOT_UNUSED.getCode()); - } - return true; - } - - @Override - public Boolean cancelUseCouponCard(Integer userId, Integer couponCardId) { - // 查询优惠劵 - CouponCardDO card = couponCardMapper.selectById(couponCardId); - if (card == null) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_NOT_EXISTS.getCode()); - } - if (!userId.equals(card.getUserId())) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_ERROR_USER.getCode()); - } - if (!CouponCardStatusEnum.USED.getValue().equals(card.getStatus())) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_STATUS_NOT_USED.getCode()); - } - // 更新优惠劵已使用 - int updateCount = couponCardMapper.updateByIdAndStatus(card.getId(), CouponCardStatusEnum.USED.getValue(), - new CouponCardDO().setStatus(CouponCardStatusEnum.UNUSED.getValue())); // TODO 芋艿,usedTime 未设置空,后面处理。 - if (updateCount == 0) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_STATUS_NOT_USED.getCode()); - } - // 有一点要注意,更新会未使用时,优惠劵可能已经过期了,直接让定时器跑过期,这里不做处理。 - return true; - } - - @Override - public CouponCardDetailBO getCouponCardDetail(Integer userId, Integer couponCardId) { - // 查询优惠劵 - CouponCardDO card = couponCardMapper.selectById(couponCardId); - if (card == null) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_NOT_EXISTS.getCode()); - } - if (!userId.equals(card.getUserId())) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_CARD_ERROR_USER.getCode()); - } - // 查询优惠劵模板 - CouponTemplateDO template = couponTemplateMapper.selectById(card.getTemplateId()); - if (template == null) { - throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.COUPON_TEMPLATE_NOT_EXISTS.getCode()); - } - // 拼接结果 - CouponCardDetailBO detail = CouponCardConvert.INSTANCE.convert2(card); - detail.setRangeType(template.getRangeType()); - detail.setRangeValues(StringUtil.splitToInt(template.getRangeValues(), ",")); - return detail; - } - - @Override - public List getCouponCardList(Integer userId, List spus) { - // 查询用户未使用的优惠劵列表 - List cards = couponCardMapper.selectListByUserIdAndStatus(userId, CouponCardStatusEnum.UNUSED.getValue()); - if (cards.isEmpty()) { - return Collections.emptyList(); - } - // 查询优惠劵模板集合 - Map templates = couponTemplateMapper.selectListByIds(cards.stream().map(CouponCardDO::getTemplateId).collect(Collectors.toSet())) - .stream().collect(Collectors.toMap(CouponTemplateDO::getId, template -> template)); - // 逐个判断是否可用 - List availableCards = cards.stream().map(card -> { - CouponCardAvailableBO availableCard = CouponCardConvert.INSTANCE.convert2(card, true); - availableCard.setUnavailableReason(isMatch(card, templates.get(card.getTemplateId()), spus)); - availableCard.setAvailable(availableCard.getUnavailableReason() == null); - return availableCard; - }).collect(Collectors.toList()); - // 返回结果 - return availableCards; - } - - private void setCouponCardValidTime(CouponCardDO card, CouponTemplateDO template) { - if (CouponTemplateDateTypeEnum.FIXED_DATE.getValue().equals(template.getDateType())) { - card.setValidStartTime(template.getValidStartTime()).setValidEndTime(template.getValidEndTime()); - } else if (CouponTemplateDateTypeEnum.FIXED_TERM.getValue().equals(template.getDateType())) { - Date validStartTime = DateUtil.getDayBegin(new Date()); - card.setValidStartTime(DateUtil.addDate(validStartTime, Calendar.DAY_OF_YEAR, template.getFixedStartTerm())); - Date validEndTime = DateUtil.getDayEnd(card.getValidStartTime()); - card.setValidEndTime(DateUtil.addDate(validEndTime, Calendar.DAY_OF_YEAR, template.getFixedEndTerm() - 1)); - } - } - - // 如果匹配,则返回 null 即可。 - private String isMatch(CouponCardDO card, CouponTemplateDO template, List spus) { - int totalPrice = 0; - if (RangeTypeEnum.ALL.getValue().equals(template.getRangeType())) { - totalPrice = spus.stream().mapToInt(spu -> spu.getPrice() * spu.getQuantity()).sum(); - } else if (RangeTypeEnum.PRODUCT_INCLUDE_PART.getValue().equals(template.getRangeType())) { - List spuIds = StringUtil.splitToInt(template.getRangeValues(), ","); - totalPrice = spus.stream().mapToInt(spu -> spuIds.contains(spu.getSpuId()) ? spu.getPrice() * spu.getQuantity() : 0).sum(); - } else if (RangeTypeEnum.PRODUCT_EXCLUDE_PART.getValue().equals(template.getRangeType())) { - List spuIds = StringUtil.splitToInt(template.getRangeValues(), ","); - totalPrice = spus.stream().mapToInt(spu -> !spuIds.contains(spu.getSpuId()) ? spu.getPrice() * spu.getQuantity() : 0).sum(); - } else if (RangeTypeEnum.CATEGORY_INCLUDE_PART.getValue().equals(template.getRangeType())) { - List spuIds = StringUtil.splitToInt(template.getRangeValues(), ","); - totalPrice = spus.stream().mapToInt(spu -> spuIds.contains(spu.getCategoryId()) ? spu.getPrice() * spu.getQuantity() : 0).sum(); - } else if (RangeTypeEnum.CATEGORY_EXCLUDE_PART.getValue().equals(template.getRangeType())) { - List spuIds = StringUtil.splitToInt(template.getRangeValues(), ","); - totalPrice = spus.stream().mapToInt(spu -> !spuIds.contains(spu.getCategoryId()) ? spu.getPrice() * spu.getQuantity() : 0).sum(); - } - // 总价为 0 时,说明优惠劵丫根不匹配 - if (totalPrice == 0) { - return "优惠劵不匹配"; - } - // 如果不满足金额 - if (totalPrice < card.getPriceAvailable()) { - return String.format("差 %1$,.2f 元可用优惠劵", (card.getPriceAvailable() - totalPrice) / 100D); - } - return null; - } - - // ========== 优惠码 ========== - - @Override - public CouponCardBO useCouponCode(Integer userId, String code) { - return null; - } - }