package com.mzl.flower.service.impl.coupon;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mzl.flower.config.exception.ValidationException;
import com.mzl.flower.config.security.SecurityUtils;
import com.mzl.flower.constant.Constants;
import com.mzl.flower.dto.request.coupon.*;
import com.mzl.flower.dto.response.coupon.CouponPointStatisVO;
import com.mzl.flower.dto.response.coupon.CouponTemplateCustomerVO;
import com.mzl.flower.dto.response.coupon.CouponTemplateVO;
import com.mzl.flower.entity.coupon.CouponRecordDO;
import com.mzl.flower.entity.coupon.CouponTemplateCustomerDO;
import com.mzl.flower.entity.coupon.CouponTemplateDO;
import com.mzl.flower.entity.customer.Customer;
import com.mzl.flower.entity.menber.Member;
import com.mzl.flower.entity.point.CustomerPoint;
import com.mzl.flower.entity.point.CustomerPointDetail;
import com.mzl.flower.enums.*;
import com.mzl.flower.mapper.coupon.CouponTemplateMapper;
import com.mzl.flower.mapper.coupon.CouponTemplateMapperCustom;
import com.mzl.flower.mapper.customer.CustomerMapper;
import com.mzl.flower.mapper.point.CustomerPointDetailMapper;
import com.mzl.flower.mapper.point.CustomerPointMapper;
import com.mzl.flower.service.coupon.CouponRecordService;
import com.mzl.flower.service.coupon.CouponTemplateCustomerService;
import com.mzl.flower.service.coupon.CouponTemplateService2;
import com.mzl.flower.service.menber.MemberService;
import com.mzl.flower.service.payment.RedisLockService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
*
* 服务实现类
*
*
* @author @TaoJie
* @since 2024-08-22
*/
@Service
public class CouponTemplateServiceImpl2 extends ServiceImpl implements CouponTemplateService2 {
@Autowired
private CouponTemplateMapperCustom couponTemplateMapperCustom;
@Autowired
private CouponTemplateCustomerService pointCustomReService;
@Autowired
private CouponRecordService couponRecordService;
@Autowired
private CustomerMapper customerMapper;
@Autowired
private CustomerPointMapper customerPointMapper;
@Autowired
private CouponTemplateService2 couponTemplateService;
@Autowired
private CustomerPointDetailMapper customerPointDetailMapper;
@Autowired
private MemberService memberService;
@Autowired
private RedisLockService lockService;
@Transactional
@Override
public boolean createCouponTemplate(CreateCouponTemplateBO dto) {
CouponTemplateDO couponTemplateDO = new CouponTemplateDO();
BeanUtils.copyProperties(dto, couponTemplateDO);
// 设置id,关联使用到的id
couponTemplateDO.setId(IdUtil.simpleUUID());
couponTemplateDO.create(SecurityUtils.getUserId());
if (StringUtils.isBlank(dto.getStatus())) {
// 优惠券状态 初始化为未激活状态
couponTemplateDO.setStatus(CouponStatusEnum.INACTIVE.getStatus());
}
// 指定会员:需要添加制定用户的关联信息
if (CollectionUtils.isNotEmpty(dto.getPointCostomIdList())) {
final List couponCustomList = dto.getPointCostomIdList().stream().map(customId -> {
CouponTemplateCustomerDO customReDO = new CouponTemplateCustomerDO();
// 解决本地不加ID不报错,线上报错问题
customReDO.setId(IdUtil.simpleUUID());
customReDO.setCouponId(couponTemplateDO.getId());
customReDO.setCustomId(customId);
return customReDO;
}).collect(Collectors.toList());
// 批量插入 优惠券与指定用户关联关系
pointCustomReService.saveBatch(couponCustomList);
// 设置优惠券的数量
couponTemplateDO.setCouponAmount(dto.getPointCostomIdList().size());
}
return baseMapper.insert(couponTemplateDO) > 0;
}
@Transactional
@Override
public boolean updateCouponTemplate(CreateCouponTemplateBO dto) {
CouponTemplateDO couponTemplateDO = baseMapper.selectById(dto.getId());
BeanUtils.copyProperties(dto, couponTemplateDO);
couponTemplateDO.update(SecurityUtils.getUserId());
if (CollectionUtils.isNotEmpty(dto.getPointCostomIdList())) {
// 根据优惠券的信息删除关联信息
pointCustomReService.deleteByCouponTemplateId(couponTemplateDO.getId());
}
// 指定会员:需要添加制定用户的关联信息
if (CollectionUtils.isNotEmpty(dto.getPointCostomIdList())) {
final List couponCustomList = dto.getPointCostomIdList().stream().map(customId -> {
CouponTemplateCustomerDO customReDO = new CouponTemplateCustomerDO();
// 解决本地不加ID不报错,线上报错问题
customReDO.setId(IdUtil.simpleUUID());
customReDO.setCouponId(couponTemplateDO.getId());
customReDO.setCustomId(customId);
return customReDO;
}).collect(Collectors.toList());
// 批量插入 优惠券与指定用户关联关系
pointCustomReService.saveBatch(couponCustomList);
// 设置优惠券总数当前人数
couponTemplateDO.setCouponAmount(couponCustomList.size());
}
return baseMapper.updateById(couponTemplateDO) > 0;
}
@Override
public List getList(QueryCouponDTO dto) {
List list =new ArrayList<>();
if(StringUtils.isNotBlank(dto.getCategory())
&& dto.getCategory().equals(CouponCategoryEnum.MEMBER.getStatus())
){
// 会员优惠券
list = couponTemplateMapperCustom.getVipList(dto);
}else{
list = couponTemplateMapperCustom.getList(dto);
}
return list;
}
@Override
public Page getPage(Page page, QueryCouponDTO dto) {
List result =new ArrayList<>();
if(StringUtils.isNotBlank(dto.getCategory())
&& dto.getCategory().equals(CouponCategoryEnum.MEMBER.getStatus())
){
// 会员优惠券
result = couponTemplateMapperCustom.getCouponTemplateVipPage(page, dto);
}else{
result = couponTemplateMapperCustom.getCouponTemplatePage(page, dto);
}
return page.setRecords(result);
}
@Override
public CouponTemplateVO getDetailById(String id) {
QueryCouponDTO dto = new QueryCouponDTO();
dto.setId(id);
final List list = getList(dto);
if (CollectionUtils.isNotEmpty(list)) {
CouponTemplateVO vo =list.get(0);
// 用户获取
if(StringUtils.isNotBlank(vo.getCategory())
&& vo.getCategory().equals(CouponCategoryEnum.USER.getStatus())){
List customerList= couponTemplateMapperCustom.getCouponCustomerList(id);
vo.setCustomerList(customerList);
}
// 会员等级
if(StringUtils.isNotBlank(vo.getCategory()) && null!=vo.getMemberId()
&& vo.getCategory().equals(CouponCategoryEnum.MEMBER.getStatus())){
final Member member = memberService.getById(vo.getMemberId());
if(null!=member){
vo.setMember(member);
vo.setMemberName(member.getName());
}
}
return vo;
}
return null;
}
@Transactional
@Override
public boolean deleteCouponTemplate(String id) {
return baseMapper.deleteById(id) > 0;
}
@Transactional
@Override
public boolean activeCouponTemplate(String id) {
CouponTemplateDO couponTemplateDO = baseMapper.selectById(id);
couponTemplateDO.setStatus(CouponStatusEnum.ACTIVE.getStatus());
// 判断当前的优惠券的用户类型是指定用户还是全部用户,如果是指定用户的情况下需要发布优惠券
if (StringUtils.isNotBlank(couponTemplateDO.getGetUserType())
&& StringUtils.isNotBlank(couponTemplateDO.getCategory())
&& couponTemplateDO.getGetUserType().equals(CouponGetUserTypeEnum.TARGET.getType())
&& couponTemplateDO.getCategory().equals(CouponCategoryEnum.USER.getStatus())
) {
// 获取当前优惠券下的指定人员信息
List couponTemplateCustomerDOList = pointCustomReService.getPointCustomReList(id);
if (CollectionUtils.isNotEmpty(couponTemplateCustomerDOList)) {
// 根据发放后有效期来设置时间
if (couponTemplateDO.getUsageTimeNum() == null || couponTemplateDO.getUsageTimeNum() <= 0) {
throw new ValidationException("使用时间数量必须为正整数");
}
LocalDateTime currentTime = LocalDateTime.now();
couponTemplateDO.setUsageStartDate(currentTime);
if (couponTemplateDO.getUsageTimeType().equals(CouponUsageTimeTypeEnum.DAY.getType())) {
// 天
couponTemplateDO.setUsageEndDate(currentTime.plusDays(couponTemplateDO.getUsageTimeNum()));
}
if (couponTemplateDO.getUsageTimeType().equals(CouponUsageTimeTypeEnum.HOUR.getType())) {
// 小时
couponTemplateDO.setUsageEndDate(currentTime.plusHours(couponTemplateDO.getUsageTimeNum()));
}
if (couponTemplateDO.getUsageTimeType().equals(CouponUsageTimeTypeEnum.MINUTE.getType())) {
// 分钟
couponTemplateDO.setUsageEndDate(currentTime.plusMinutes(couponTemplateDO.getUsageTimeNum()));
}
// 优惠券的总数等于下发人员的总数
couponTemplateDO.setCouponAmount(couponTemplateCustomerDOList.size());
List couponUsageDOList = couponTemplateCustomerDOList.stream().map(pointCustomRe -> {
CouponRecordDO couponRecordDO = new CouponRecordDO();
couponRecordDO.setId(IdUtil.simpleUUID());
couponRecordDO.setCouponId(pointCustomRe.getCouponId());
couponRecordDO.setCustomerId(pointCustomRe.getCustomId());
final Customer customer = customerMapper.selectById(pointCustomRe.getCustomId());
if (null != customer && StringUtils.isNotBlank(customer.getUserId())) {
// 设置所属用户id
couponRecordDO.setUserId(customer.getUserId());
}
couponRecordDO.setStatus(CouponUsedStatusEnum.UNUSED.getType());
// 设置优惠券的使用开始时间
couponRecordDO.setEffectiveStart(couponTemplateDO.getUsageStartDate());
// 设置优惠券的使用结束时间
couponRecordDO.setEffectiveEnd(couponTemplateDO.getUsageEndDate());
// 优惠券的冗余字段
couponRecordDO.setCouponCode(couponTemplateDO.getCouponCode());
couponRecordDO.setCouponName(couponTemplateDO.getCouponName());
// 优惠券种类
couponRecordDO.setCategory(couponTemplateDO.getCategory());
couponRecordDO.setMinOrderAmount(couponTemplateDO.getMinOrderAmount());
couponRecordDO.setCouponDiscountValue(couponTemplateDO.getCouponDiscountValue());
couponRecordDO.setGetType(couponTemplateDO.getGetType());
couponRecordDO.setCouponDiscountType(couponTemplateDO.getCouponDiscountType());
couponRecordDO.setGetUserType(couponTemplateDO.getGetUserType());
couponRecordDO.setPoint(couponTemplateDO.getPoint());
couponRecordDO.setMemberId(couponTemplateDO.getMemberId());
couponRecordDO.setImageUrl(couponTemplateDO.getImageUrl());
// 创建相关信息
couponRecordDO.create(SecurityUtils.getUserId());
// 查看当前优惠券是不是已经存在,存在的话则不能添加,防止同一人员重复下发同一张指定的优惠券
if(!couponRecordService.checkUserCouponExists(pointCustomRe.getCouponId(),pointCustomRe.getCustomId())){
return couponRecordDO;
}else{
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
// 批量保存优惠券信息
couponRecordService.saveBatch(couponUsageDOList);
}
}
// 如果是活动优惠券且领取渠道是Home类型的,那么只能设置当前优惠券为激活状态,其他优惠券是激活状态的设置为下架状态
if (StringUtils.isNotBlank(couponTemplateDO.getCategory()) && couponTemplateDO.getCategory().equals(CouponCategoryEnum.ACTIVITY.getStatus())
&& StringUtils.isNotBlank(couponTemplateDO.getGetType()) && couponTemplateDO.getGetType().equals(CouponGetTypeEnum.HOME.getType())
) {
couponTemplateMapperCustom.expireHomeActivityCouponTemplate();
}
return baseMapper.updateById(couponTemplateDO) > 0;
}
@Transactional
@Override
public boolean expireCouponTemplate(String id) {
CouponTemplateDO couponTemplateDO = baseMapper.selectById(id);
couponTemplateDO.setStatus(CouponStatusEnum.EXPIRED.getStatus());
return baseMapper.updateById(couponTemplateDO) > 0;
}
/**
* 获取所有会员优惠券模版
*
* @return
*/
@Transactional
@Override
public List getVipCouponTemplate() {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.lambda()
.eq(CouponTemplateDO::getDeleted, TrueOrFalseEnum.FALSE.isFlag())
.eq(CouponTemplateDO::getCategory, CouponCategoryEnum.MEMBER.getStatus())
.eq(CouponTemplateDO::getStatus, CouponStatusEnum.ACTIVE.getStatus());
return baseMapper.selectList(queryWrapper);
}
@Transactional
@Override
public boolean deleteBatchCouponTemplate(BatchCouponTemplateDTO dto) {
if (CollectionUtils.isNotEmpty(dto.getIdList())) {
dto.setUpdateBy(SecurityUtils.getUserId());
return couponTemplateMapperCustom.deleteBatchCouponTemplate(dto) > 0;
}
return false;
}
@Transactional
@Override
public boolean activeBatchCouponTemplate(BatchCouponTemplateDTO dto) {
if (CollectionUtils.isNotEmpty(dto.getIdList())) {
dto.setUpdateBy(SecurityUtils.getUserId());
return couponTemplateMapperCustom.activeBatchCouponTemplate(dto) > 0;
}
return false;
}
@Transactional
@Override
public boolean expireBatchCouponTemplate(BatchCouponTemplateDTO dto) {
if (CollectionUtils.isNotEmpty(dto.getIdList())) {
dto.setUpdateBy(SecurityUtils.getUserId());
return couponTemplateMapperCustom.expireBatchCouponTemplate(dto) > 0;
}
return false;
}
@Override
public CouponPointStatisVO statisCouponTemplatePoint(QueryCouponStatisticsBO queryCouponStatisticsBO) {
CouponPointStatisVO vo=new CouponPointStatisVO();
//优惠券总数
vo.setTotalAmount(couponRecordService.statisCouponTemplateCount(queryCouponStatisticsBO));
// 本月兑换优惠券总数
vo.setCurMonExchangeAmount(couponRecordService.statisCouponTemplateCurMonCount(queryCouponStatisticsBO));
// 本月兑换积分总数
vo.setCurMonExchangePointAmount(couponRecordService.statisCouponPointCurMonPontAmonut(queryCouponStatisticsBO));
return vo;
}
@Override
public List getPointList(QueryActivePointCouponDTO dto) {
if(StringUtils.isBlank(dto.getOrderStr())){
dto.setOrderStr(" create_time desc ");
}
return couponTemplateMapperCustom.getCouponPointList(dto);
}
@Override
public Page getPointPage(Page page, QueryActivePointCouponDTO dto) {
if(StringUtils.isBlank(dto.getOrderStr())){
dto.setOrderStr(" create_time desc ");
}
return couponTemplateMapperCustom.getPointPage(page,dto);
}
@Override
public void exchangeCoupon(ExchangeCouponDTO dto) {
String key="EXCHANGE_COUPON:"+dto.getCouponId()+":"+SecurityUtils.getUserId();
boolean lock = lockService.getObjectLock(key, "");
if(!lock){
throw new ValidationException("系统操作频繁,请稍后重试");
}
try {
dto.setNum(1);
final CouponTemplateDO couponTemplateDO = couponTemplateService.getById(dto.getCouponId());
if(couponTemplateDO==null){
throw new ValidationException("优惠券不存在");
}
if(couponTemplateDO.getCouponAmount()<=0 ){
throw new ValidationException("优惠券已兑换完");
}
CustomerPoint cp = customerPointMapper.selectOne(new LambdaQueryWrapper()
.eq(CustomerPoint::getUserId, SecurityUtils.getUserId()));
if(cp == null || (cp.getTotalPoint()-cp.getUsedPoint()-cp.getExpiredPoint()- cp.getExpiredPoint()) < couponTemplateDO.getPoint() * dto.getNum()){
throw new ValidationException("积分不足");
}
CreateCouponRecordDTO recordDTO =new CreateCouponRecordDTO();
recordDTO.setCouponId(dto.getCouponId());
recordDTO.setUserId(SecurityUtils.getUserId());
Customer customer = customerMapper.selectOne(new LambdaQueryWrapper()
.eq(Customer::getUserId, SecurityUtils.getUserId()));
if(customer == null){
throw new ValidationException("商户不存在");
}
recordDTO.setCustomerId(customer.getId());
couponRecordService.createCouponRecord(recordDTO);
// //更新优惠券数量
// couponTemplateDO.setCouponAmount(couponTemplateDO.getCouponAmount()-dto.getNum());
// couponTemplateService.updateById(couponTemplateDO);
//更新积分汇总
cp.setUsedPoint(cp.getUsedPoint()+couponTemplateDO.getPoint());
customerPointMapper.updateById(cp);
//记录积分明细
CustomerPointDetail detail = new CustomerPointDetail();
detail.setUserId(customer.getUserId());
detail.setCustomerId(customer.getId());
detail.setPoint(couponTemplateDO.getPoint());
detail.setChangeType(Constants.POINT_CHANGE_TYPE.reduce.name());
detail.setType(Constants.POINT_TYPE.exchange.name());
detail.setRecordDate(LocalDate.now());
detail.setRemarks(couponTemplateDO.getCouponName());
detail.create(SecurityUtils.getUserId());
customerPointDetailMapper.insert(detail);
}finally {
lockService.releaseObjectLock(key,"");
}
}
@Override
public CouponTemplateVO getHomeActivityEffectAlert(QueryActivityEffectCouponDTO dto) {
// 存在用户是空的情况
final CouponTemplateVO homeActivityEffectAlert = couponTemplateMapperCustom.getHomeActivityEffectAlert(dto);
if(null!=homeActivityEffectAlert ){
if(StringUtils.isNotBlank(SecurityUtils.getUserId()) ){
// 查看当前已经领取了几张
final Integer getCnt = couponRecordService.getUserGainCouponRecordAmountByUserId(homeActivityEffectAlert.getId(), SecurityUtils.getUserId());
// 如果当前领取的数量小于限制领取的数量的时候,可以再次领取
if(null!=homeActivityEffectAlert.getGetLimit() && null!=getCnt
&& homeActivityEffectAlert.getGetLimit().compareTo(getCnt)>0){
return homeActivityEffectAlert;
}
}else{
return homeActivityEffectAlert;
}
}
return null;
}
@Override
public List getActivityEffectList(QueryActivityEffectCouponDTO dto) {
return couponTemplateMapperCustom.getActivityEffectList(dto);
}
}