package com.kym.service.miniapp.impl; import cn.dev33.satoken.stp.StpUtil; import com.github.pagehelper.PageHelper; import com.github.yulichang.base.MPJBaseServiceImpl; import com.github.yulichang.toolkit.JoinWrappers; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.kym.common.exception.BusinessException; import com.kym.common.utils.CommUtil; import com.kym.entity.admin.Coupon; import com.kym.entity.admin.queryParams.CouponQueryParam; import com.kym.entity.common.PageBean; import com.kym.entity.common.RedisKeys; import com.kym.entity.miniapp.OrderCoupon; import com.kym.entity.miniapp.User; import com.kym.entity.miniapp.UserCoupon; import com.kym.entity.miniapp.vo.UserCouponVo; import com.kym.entity.miniapp.vo.UserOrderCouponVo; import com.kym.mapper.miniapp.UserCouponMapper; import com.kym.service.admin.ActivityService; import com.kym.service.admin.CouponService; import com.kym.service.miniapp.UserCouponService; import com.kym.service.miniapp.UserService; import org.springframework.beans.BeanUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** *

* 用户优惠券关联表 服务实现类 *

* * @author skyline * @since 2024-04-29 */ @Service public class UserCouponServiceImpl extends MPJBaseServiceImpl implements UserCouponService { private final RedisTemplate redisTemplate; private final ActivityService activityService; private final UserService userService; private final CouponService couponService; public UserCouponServiceImpl(RedisTemplate redisTemplate, ActivityService activityService, UserService userService, CouponService couponService) { this.redisTemplate = redisTemplate; this.activityService = activityService; this.userService = userService; this.couponService = couponService; } @Override public PageBean listUserCoupons(CouponQueryParam params) { var users = userService.lambdaQuery() .like(CommUtil.isNotEmptyAndNull(params.getMobilePhone()), User::getMobilePhone, params.getMobilePhone()) .list(); var userId2Mobile = users.stream().collect(Collectors.toMap(User::getId, User::getMobilePhone)); var userIds = users.stream().map(User::getId).toList(); PageHelper.startPage(params.getPageNum(), params.getPageSize()); var list = lambdaQuery() .in(CommUtil.isNotEmptyAndNull(userIds), UserCoupon::getUserId, userIds) .eq(CommUtil.isNotEmptyAndNull(params.getActivityId()), UserCoupon::getId, params.getCouponId()) .like(CommUtil.isNotEmptyAndNull(params.getActivityName()), UserCoupon::getActivityName, params.getActivityName()) .eq(CommUtil.isNotEmptyAndNull(params.getCouponId()), UserCoupon::getId, params.getCouponId()) .like(CommUtil.isNotEmptyAndNull(params.getCouponName()), UserCoupon::getCouponName, params.getCouponName()) .eq(CommUtil.isNotEmptyAndNull(params.getCouponType()), UserCoupon::getCouponType, params.getCouponType()) .eq(CommUtil.isNotEmptyAndNull(params.getUsageStatus()), UserCoupon::getUsageStatus, params.getUsageStatus()) .orderByDesc(UserCoupon::getId) .list(); var voList = list.stream().map(userCoupon -> { var vo = new UserCouponVo(); BeanUtils.copyProperties(userCoupon, vo); vo.setMobilePhone(userId2Mobile.get(userCoupon.getUserId())); return vo; }).toList(); var res = new PageBean<>(voList); return new PageBean<>(voList).setList(res); } @Override public void collectCoupon(Long couponId) { // 优惠券状态校验 var coupon = couponService.lambdaQuery() .eq(Coupon::getId, couponId) .in(Coupon::getStatus, Coupon.STATUS_未开始, Coupon.STATUS_进行中) .one(); if (coupon == null) { throw new BusinessException("优惠券不存在或已失效!"); } if (coupon.getClaimedQuantity() >= coupon.getQuantity() && coupon.getQuantity() > 0) { throw new BusinessException("优惠券已领完!"); } // 重复领取校验 var userId = StpUtil.getLoginIdAsLong(); var exist = redisTemplate.opsForSet().isMember(RedisKeys.COUPON_ID_TO_USERS, couponId + ":" + userId); if (Boolean.TRUE.equals(exist)) { throw new BusinessException("优惠券已领取,请勿重复领取!"); } // 活动 var activity = activityService.getById(coupon.getActivityId()); // 更新优惠券已领取数量 coupon.setClaimedQuantity(coupon.getClaimedQuantity() + 1); // 校验优惠券数量是否已领完 if (coupon.getClaimedQuantity() >= coupon.getQuantity() && coupon.getQuantity() > 0) { coupon.setStatus(Coupon.STATUS_已结束); } couponService.updateById(coupon); // 存入缓存和数据库 redisTemplate.opsForSet().add(RedisKeys.COUPON_ID_TO_USERS, couponId + ":" + userId); var userCoupon = new UserCoupon(); userCoupon.setActivityId(coupon.getActivityId()); userCoupon.setActivityName(activity.getName()); userCoupon.setCouponId(coupon.getId()); userCoupon.setCouponName(coupon.getName()); userCoupon.setUserId(userId); userCoupon.setStartTime(LocalDateTime.now()); userCoupon.setEndTime(LocalDateTime.now().with(LocalTime.MAX).plusDays(coupon.getValidity() - 1)); userCoupon.setValidity(coupon.getValidity()); userCoupon.setCouponType(coupon.getCouponType()); userCoupon.setDiscount(coupon.getDiscount()); userCoupon.setMinServiceMoney(coupon.getMinServiceMoney()); userCoupon.setAllowStacke(coupon.getAllowStacke()); userCoupon.setStatus(UserCoupon.STATUS_有效); userCoupon.setRemark(coupon.getRemark()); // userCouponSender.sendMessage(userCoupon); save(userCoupon); // todo 优惠券活动终止时处理redis数据,优惠券失效或者使用之后该做什么操作? } /** * 通过订单号查询订单使用的优惠券信息 * * @param startChargeSeq * @return */ @Override public UserOrderCouponVo getUserOrderCoupon(String startChargeSeq) { var userId = StpUtil.getLoginIdAsLong(); MPJLambdaWrapper wrapper = JoinWrappers.lambda(UserCoupon.class) .selectAsClass(UserCoupon.class, UserOrderCouponVo.class) .selectAs(OrderCoupon::getStartChargeSeq, UserOrderCouponVo::getStartChargeSeq) .selectAs(OrderCoupon::getDiscountAmount, UserOrderCouponVo::getOrderDiscountAmount) .rightJoin(OrderCoupon.class, on -> on.eq(OrderCoupon::getCouponId, UserCoupon::getCouponId).eq(OrderCoupon::getUserId, UserCoupon::getUserId)) .eq(OrderCoupon::getStartChargeSeq, startChargeSeq) .eq(OrderCoupon::getUserId, userId) .eq(OrderCoupon::getStatus, OrderCoupon.STATUS_使用成功); return selectJoinOne(UserOrderCouponVo.class, wrapper); } @Override public List listStationAvailableCoupons(Map params) { return baseMapper.listStationAvailableCoupons(params); } }