package cn.lili.modules.promotion.serviceimpl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.text.CharSequenceUtil; import cn.lili.cache.Cache; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.common.vo.PageVO; import cn.lili.modules.lmk.enums.general.AdminRoleEnum; import cn.lili.modules.order.order.entity.dto.CouponExportDetailDTO; import cn.lili.modules.order.order.entity.dto.OrderExportDTO; import cn.lili.modules.order.order.entity.dto.OrderExportDetailDTO; import cn.lili.modules.permission.service.AdminUserService; import cn.lili.modules.promotion.entity.dos.Coupon; import cn.lili.modules.promotion.entity.dos.MemberCoupon; import cn.lili.modules.promotion.entity.dto.search.MemberCouponSearchParams; import cn.lili.modules.promotion.entity.enums.CouponGetEnum; import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum; import cn.lili.modules.promotion.entity.enums.PromotionsScopeTypeEnum; import cn.lili.modules.promotion.entity.enums.PromotionsStatusEnum; import cn.lili.modules.promotion.entity.vos.MemberCouponVO; import cn.lili.modules.promotion.mapper.MemberCouponMapper; import cn.lili.modules.promotion.service.CouponService; import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.modules.promotion.tools.PromotionTools; import cn.lili.mybatis.util.PageUtil; import cn.lili.utils.CommonUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.net.URLEncoder; import java.util.*; /** * 会员优惠券业务层实现 * * @author Chopper * @since 2020/8/21 */ @Service @CacheConfig(cacheNames = "{MemberCoupon}") public class MemberCouponServiceImpl extends ServiceImpl implements MemberCouponService { /** * 优惠券 */ @Autowired private CouponService couponService; @Autowired private AdminUserService adminUserService; /** * 缓存 */ @Autowired private Cache cache; @Override public void checkCouponLimit(String couponId, String memberId) { Coupon coupon = couponService.getById(couponId); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() .eq(MemberCoupon::getCouponId, couponId) .eq(MemberCoupon::getMemberId, memberId); long haveCoupons = this.count(queryWrapper); if (!PromotionsStatusEnum.START.name().equals(coupon.getPromotionStatus())) { throw new ServiceException(ResultCode.COUPON_RECEIVE_ERROR); } if (coupon.getPublishNum() != 0 && coupon.getReceivedNum() >= coupon.getPublishNum()) { throw new ServiceException(ResultCode.COUPON_NUM_INSUFFICIENT_ERROR); } if (!coupon.getCouponLimitNum().equals(0) && haveCoupons >= coupon.getCouponLimitNum()) { throw new ServiceException(ResultCode.COUPON_LIMIT_ERROR, "此优惠券最多领取" + coupon.getCouponLimitNum() + "张"); } } /** * 领取优惠券 * * @param couponId 优惠券编号 * @param memberId 会员 * @param memberName 会员名称 */ @Override @CacheEvict(key = "#memberId") @Transactional(rollbackFor = Exception.class) public void receiveBuyerCoupon(String couponId, String memberId, String memberName) { Coupon coupon = couponService.getById(couponId); if (coupon != null && !CouponGetEnum.FREE.name().equals(coupon.getGetType())) { throw new ServiceException(ResultCode.COUPON_DO_NOT_RECEIVER); } else if (coupon != null) { this.receiverCoupon(couponId, memberId, memberName, coupon); } } @Override @CacheEvict(key = "#memberId") @Transactional(rollbackFor = Exception.class) public void receiveCoupon(String couponId, String memberId, String memberName) { Coupon coupon = couponService.getById(couponId); if (coupon != null) { this.receiverCoupon(couponId, memberId, memberName, coupon); } else { throw new ServiceException(ResultCode.COUPON_NOT_EXIST); } } @Override public IPage getMemberCoupons(MemberCouponSearchParams param, PageVO pageVo) { QueryWrapper queryWrapper = param.queryWrapper(); Page page = this.page(PageUtil.initPage(pageVo), queryWrapper); if (page.getRecords() != null && page.getRecords().size() > 0) { if (page.getRecords().stream().anyMatch(i -> i.getEndTime().before(new Date()))) { this.expireInvalidMemberCoupon(param.getMemberId()); return this.page(PageUtil.initPage(pageVo), queryWrapper); } } return page; } /** * 获取会员优惠券列表 * * @param param 查询参数 * @return 会员优惠券列表 */ @Override public List getMemberCoupons(MemberCouponSearchParams param) { List list = this.list(param.queryWrapper()); if (list.stream().anyMatch(i -> i.getEndTime().before(new Date()))) { this.expireInvalidMemberCoupon(param.getMemberId()); return this.list(param.queryWrapper()); } return list; } /** * 获取当前用户的优惠券列表(优先读取缓存) * * @param memberId 会员id * @return 会员优惠券列表 */ @Override @Cacheable(key = "#memberId") public List getMemberCoupons(String memberId) { MemberCouponSearchParams searchParams = new MemberCouponSearchParams(); searchParams.setMemberId(Objects.requireNonNull(UserContext.getCurrentUser()).getId()); searchParams.setMemberCouponStatus(MemberCouponStatusEnum.NEW.name()); searchParams.setPromotionStatus(PromotionsStatusEnum.START.name()); return this.getMemberCoupons(searchParams); } /** * 获取会员优惠券列表 * * @param param 查询参数 * @param pageVo 分页参数 * @return 会员优惠券列表 */ @Override public IPage getMemberCouponsByCanUse(MemberCouponSearchParams param, Double totalPrice, PageVO pageVo) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); List storeIds = new ArrayList<>(Arrays.asList(param.getStoreId().split(","))); storeIds.add(PromotionTools.PLATFORM_ID); queryWrapper.in(MemberCoupon::getStoreId, storeIds); queryWrapper.eq(MemberCoupon::getMemberId, param.getMemberId()); queryWrapper.and( i -> i.like(MemberCoupon::getScopeId, param.getScopeId()) .or(j -> j.eq(MemberCoupon::getScopeType, PromotionsScopeTypeEnum.ALL.name()))); queryWrapper.eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name()); queryWrapper.le(MemberCoupon::getConsumeThreshold, totalPrice); queryWrapper.ge(MemberCoupon::getEndTime, new Date()); return this.page(PageUtil.initPage(pageVo), queryWrapper); } /** * 获取当前会员当前商品可用的会员优惠券 * * @param memberId 会员Id * @param couponIds 优惠券id列表 * @return 会员优惠券列表 */ @Override public List getCurrentGoodsCanUse(String memberId, List couponIds, Double totalPrice) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(MemberCoupon::getMemberId, memberId); queryWrapper.eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name()); queryWrapper.in(MemberCoupon::getCouponId, couponIds); queryWrapper.ne(MemberCoupon::getScopeType, PromotionsScopeTypeEnum.ALL.name()); queryWrapper.le(MemberCoupon::getConsumeThreshold, totalPrice); queryWrapper.ge(MemberCoupon::getEndTime, new Date()); return this.list(queryWrapper); } /** * 获取当前会员全品类优惠券 * * @param memberId 会员Id * @param storeId 店铺id * @return 会员优惠券列表 */ @Override public List getAllScopeMemberCoupon(String memberId, List storeId) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(MemberCoupon::getMemberId, memberId); queryWrapper.eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name()); queryWrapper.eq(MemberCoupon::getScopeType, PromotionsScopeTypeEnum.ALL.name()); queryWrapper.ge(MemberCoupon::getEndTime, new Date()).and(i -> i.in(MemberCoupon::getStoreId, storeId).or(j -> j.eq(MemberCoupon::getPlatformFlag, true))); return this.list(queryWrapper); } /** * 获取当前会员全品类优惠券 * * @param param 查询参数 * @return 会员优惠券列表 */ @Override public MemberCoupon getMemberCoupon(MemberCouponSearchParams param) { return this.getOne(param.queryWrapper(), false); } @Override public long getMemberCouponsNum() { AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser()); QueryWrapper queryWrapper = Wrappers.query(); queryWrapper.eq("member_id", authUser.getId()); queryWrapper.eq("member_coupon_status", MemberCouponStatusEnum.NEW.name()); queryWrapper.eq("delete_flag", false); return this.count(queryWrapper); } @Override @CacheEvict(key = "#memberId") @Transactional(rollbackFor = Exception.class) public void used(String memberId, List ids) { if (ids != null && !ids.isEmpty()) { List memberCoupons = this.listByIds(ids); //如果查出来的优惠券数量不一致 if (memberCoupons.size() != ids.size()) { throw new ServiceException(ResultCode.COUPON_EXPIRED); } //循环处理 memberCoupons.forEach(item -> { if (!item.getMemberCouponStatus().equals(MemberCouponStatusEnum.NEW.name())) { throw new ServiceException(ResultCode.COUPON_EXPIRED); } item.setMemberCouponStatus(MemberCouponStatusEnum.USED.name()); item.setConsumptionTime(new Date()); }); this.updateBatchById(memberCoupons); } } /** * 作废当前会员优惠券 * * @param id id */ @Override @CacheEvict(key = "#memberId") @Transactional(rollbackFor = Exception.class) public void cancellation(String memberId, String id) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(MemberCoupon::getId, id); updateWrapper.set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.CLOSED.name()); this.update(updateWrapper); } /** * 关闭会员优惠券 * * @param couponIds 优惠券id集合 */ @Override @Transactional(rollbackFor = Exception.class) public void closeMemberCoupon(List couponIds) { LambdaUpdateWrapper memberCouponLambdaUpdateWrapper = new LambdaUpdateWrapper() .in(MemberCoupon::getCouponId, couponIds) .set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.CLOSED.name()); this.cache.vagueDel("{MemberCoupon}"); this.update(memberCouponLambdaUpdateWrapper); } @Override public boolean recoveryMemberCoupon(List memberCouponIds) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.in(MemberCoupon::getId, memberCouponIds); updateWrapper.set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name()); updateWrapper.set(MemberCoupon::getConsumptionTime, null); return this.update(updateWrapper); } @Override public void voidCoupon(String couponId) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.in(MemberCoupon::getCouponId, couponId); updateWrapper.set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.CLOSED.name()); updateWrapper.set(MemberCoupon::getDeleteFlag, true); this.update(updateWrapper); } public List getMemberCouponsPageExport(MemberCouponSearchParams param){ QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getMemberId()), "mc.member_id", param.getMemberId()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getStoreId()), "c.store_id", param.getStoreId()); queryWrapper.like(CharSequenceUtil.isNotEmpty(param.getMemberName()), "mc.member_name", param.getMemberName()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getCouponId()), "mc.coupon_id", param.getCouponId()); queryWrapper.like(CharSequenceUtil.isNotEmpty(param.getCouponName()), "c.coupon_name", param.getCouponName()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getGetType()), "mc.get_type", param.getGetType()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getScopeType()), "mc.scope_type", param.getPromotionStatus()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getCouponType()), "mc.coupon_type", param.getCouponType()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getMemberCouponStatus()), "mc.member_coupon_status", param.getMemberCouponStatus()); if (param.getStartTime() != null) { queryWrapper.ge("mc.start_time", new Date(param.getStartTime())); } if (param.getEndTime() != null) { queryWrapper.le("mc.end_time", new Date(param.getEndTime())); } return this.baseMapper.getMemberCouponsExport(queryWrapper); } @Override public Page getMemberCouponsPage(Page page, MemberCouponSearchParams param) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getMemberId()), "mc.member_id", param.getMemberId()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getStoreId()), "c.store_id", param.getStoreId()); queryWrapper.like(CharSequenceUtil.isNotEmpty(param.getMemberName()), "mc.member_name", param.getMemberName()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getCouponId()), "mc.coupon_id", param.getCouponId()); queryWrapper.like(CharSequenceUtil.isNotEmpty(param.getCouponName()), "c.coupon_name", param.getCouponName()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getGetType()), "mc.get_type", param.getGetType()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getScopeType()), "mc.scope_type", param.getPromotionStatus()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getCouponType()), "mc.coupon_type", param.getCouponType()); queryWrapper.eq(CharSequenceUtil.isNotEmpty(param.getMemberCouponStatus()), "mc.member_coupon_status", param.getMemberCouponStatus()); if (param.getStartTime() != null) { queryWrapper.ge("mc.start_time", new Date(param.getStartTime())); } if (param.getEndTime() != null) { queryWrapper.le("mc.end_time", new Date(param.getEndTime())); } return this.baseMapper.getMemberCoupons(page, queryWrapper); } @Override public void queryExportCoupon(HttpServletResponse response, MemberCouponSearchParams searchParams) { List records = this.getMemberCouponsPageExport(searchParams); XSSFWorkbook workbook = initCouponExportData(records); try { // 设置响应头 String fileName = URLEncoder.encode("优惠券领取记录", "UTF-8"); response.setContentType("application/vnd.ms-excel;charset=UTF-8"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx"); ServletOutputStream out = response.getOutputStream(); workbook.write(out); } catch (Exception e) { e.printStackTrace(); } finally { try { workbook.close(); } catch (Exception e) { e.printStackTrace(); } } } private XSSFWorkbook initCouponExportData(List list){ List couponExportDetailDTOS = new ArrayList<>(); for (MemberCoupon memberCoupon : list){ CouponExportDetailDTO dto = new CouponExportDetailDTO(); BeanUtil.copyProperties(memberCoupon, dto); couponExportDetailDTOS.add(dto); } System.out.println("-----------------------"); System.out.println(couponExportDetailDTOS); XSSFWorkbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("优惠券领取记录"); Row header = sheet.createRow(0); String[] headers = {"会员名称","优惠券名称","发布店铺","面额/折扣","使用门槛","获取方式" ,"会员优惠券状态","优惠券类型","品类描述","使用起始时间","截止时间"}; for(int i= 0 ;i< headers.length;i++){ Cell cell = header.createCell(i); cell.setCellValue(headers[i]); } //填充数据 for (int i =0 ;i< couponExportDetailDTOS.size();i++){ CouponExportDetailDTO dto = couponExportDetailDTOS.get(i); Row row = sheet.createRow(i+1); row.createCell(0).setCellValue(dto.getMemberName()); row.createCell(1).setCellValue(dto.getCouponName()); if ("platform".equals(dto.getStoreName())){ row.createCell(2).setCellValue("平台"); }else { row.createCell(2).setCellValue(dto.getStoreName()); } if (dto.getDiscount() != null){ row.createCell(3).setCellValue(dto.getDiscount()+"折"); } if (dto.getPrice()!=null){ row.createCell(3).setCellValue(dto.getPrice()+"¥"); } row.createCell(4).setCellValue(dto.getConsumeThreshold()); if("FREE".equals(dto.getGetType())){ row.createCell(5).setCellValue("免费获取"); }else if("ACTIVITY".equals(dto.getGetType())){ row.createCell(5).setCellValue("活动获取"); }else if("lime".equals(dto.getGetType())){ row.createCell(5).setCellValue("内购"); }else if("purple".equals(dto.getGetType())){ row.createCell(5).setCellValue("未知"); } if("NEW".equals(dto.getMemberCouponStatus())){ row.createCell(6).setCellValue("已领取"); }else if("USED".equals(dto.getMemberCouponStatus())){ row.createCell(6).setCellValue("已使用"); }else if("EXPIRE".equals(dto.getMemberCouponStatus())){ row.createCell(6).setCellValue("已过期"); }else if("CLOSED".equals(dto.getMemberCouponStatus())){ row.createCell(6).setCellValue("已作废"); } if("DISCOUNT".equals(dto.getCouponType())){ row.createCell(7).setCellValue("打折"); }else if("PRICE".equals(dto.getCouponType())){ row.createCell(7).setCellValue("减免现金"); }else{ row.createCell(7).setCellValue("未知"); } if ("ALL".equals(dto.getScopeType())) { row.createCell(8).setCellValue("全品类"); }else if ("PORTION_GOODS_CATEGORY".equals(dto.getScopeType())) { row.createCell(8).setCellValue("商品分类"); } else if ("PORTION_SHOP_CATEGORY".equals(dto.getScopeType())) { row.createCell(8).setCellValue("店铺分类"); } else if ("PORTION_GOODS".equals(dto.getScopeType())) { row.createCell(8).setCellValue("指定商品"); } row.createCell(9).setCellValue(DateUtil.formatDateTime(dto.getStartTime())); row.createCell(10).setCellValue(DateUtil.formatDateTime(dto.getEndTime())); } return workbook; } @Override public long getMemberCouponNum(String memberId, String couponId) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(MemberCoupon::getMemberId, memberId); queryWrapper.eq(MemberCoupon::getCouponId, couponId); return this.count(queryWrapper); } /** * 清除无效的会员优惠券 * * @return 是否操作成功 */ @Override @CacheEvict(key = "#memberId") public boolean expireInvalidMemberCoupon(String memberId) { //将过期优惠券变更为过期状体 LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() .eq(CharSequenceUtil.isNotEmpty(memberId), MemberCoupon::getMemberId, memberId) .eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name()) .le(MemberCoupon::getEndTime, new Date()) .set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.EXPIRE.name()); return this.update(updateWrapper); } private void receiverCoupon(String couponId, String memberId, String memberName, Coupon coupon) { this.checkCouponLimit(couponId, memberId); MemberCoupon memberCoupon = new MemberCoupon(coupon); memberCoupon.setMemberId(memberId); memberCoupon.setMemberName(memberName); memberCoupon.setMemberCouponStatus(MemberCouponStatusEnum.NEW.name()); memberCoupon.setPlatformFlag((PromotionTools.PLATFORM_ID).equals(coupon.getStoreId())); this.save(memberCoupon); couponService.receiveCoupon(couponId, 1); } }