diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/act/controller/H5CouponController.java b/ruoyi-mall/src/main/java/com/cyl/manager/act/controller/H5CouponController.java new file mode 100644 index 0000000..7ded087 --- /dev/null +++ b/ruoyi-mall/src/main/java/com/cyl/manager/act/controller/H5CouponController.java @@ -0,0 +1,70 @@ +package com.cyl.manager.act.controller; + +import com.cyl.manager.act.domain.entity.CouponActivity; +import com.cyl.manager.act.domain.entity.MemberCoupon; +import com.cyl.manager.act.domain.query.MemberCouponQuery; +import com.cyl.manager.act.domain.vo.CouponActivityVO; +import com.cyl.manager.act.domain.vo.MemberCouponVO; +import com.cyl.manager.act.service.CouponActivityService; +import com.cyl.manager.act.service.MemberCouponService; +import com.ruoyi.common.core.redis.RedisService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@Api(description = "优惠券接口列表") +@RestController +@RequestMapping("/h5/coupon") +public class H5CouponController { + + @Autowired + private CouponActivityService couponActivityService; + @Autowired + private RedisService redisService; + @Autowired + private MemberCouponService memberCouponService; + + @ApiOperation("优惠券活动列表") + @PostMapping("/activity/list") + public ResponseEntity> list(Pageable page) { + //获取所有未过期且运行中的活动 + return ResponseEntity.ok(couponActivityService.selectListByH5(page)); + } + + @GetMapping("/activity/get") + public ResponseEntity getDetail(Long id) { + CouponActivityVO detail = couponActivityService.getDetail(id); + return ResponseEntity.ok(detail); + } + + @PostMapping("/receive") + public ResponseEntity receiveCoupon(Long id) { + String redisKey = "h5_receive_coupon" + id; + String redisValue = id + "_" + System.currentTimeMillis(); + try { + redisService.lock(redisKey, redisValue, 60); + return ResponseEntity.ok(couponActivityService.receiveCoupon(id)); + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } finally { + try { + redisService.unLock(redisKey, redisValue); + } catch (Exception e) { + + } + } + } + + + @ApiOperation("优惠券活动列表") + @PostMapping("/list") + public ResponseEntity> list(@RequestBody MemberCouponQuery query, Pageable page) { + //获取所有未过期且运行中的活动 + return ResponseEntity.ok(memberCouponService.selectListByH5(query,page)); + } + +} diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/entity/MemberCoupon.java b/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/entity/MemberCoupon.java index cb3f51d..24b6884 100644 --- a/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/entity/MemberCoupon.java +++ b/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/entity/MemberCoupon.java @@ -2,6 +2,8 @@ package com.cyl.manager.act.domain.entity; import java.math.BigDecimal; import java.time.LocalDateTime; + +import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.common.annotation.Excel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -59,9 +61,11 @@ public class MemberCoupon { @ApiModelProperty("券开始时间") @Excel(name = "券开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime beginTime; @ApiModelProperty("券结束时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @Excel(name = "券结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") private LocalDateTime endTime; diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/query/MemberCouponQuery.java b/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/query/MemberCouponQuery.java index 731b3f6..7b71c95 100644 --- a/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/query/MemberCouponQuery.java +++ b/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/query/MemberCouponQuery.java @@ -23,5 +23,8 @@ public class MemberCouponQuery { @ApiModelProperty("0未使用 1已使用 精确匹配") private Integer useStatus; + //1已领取 2已使用 3已过期 + private Integer type; + } diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/vo/CouponActivityVO.java b/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/vo/CouponActivityVO.java index 0ebd274..2734339 100644 --- a/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/vo/CouponActivityVO.java +++ b/ruoyi-mall/src/main/java/com/cyl/manager/act/domain/vo/CouponActivityVO.java @@ -93,5 +93,11 @@ public class CouponActivityVO { private List productList; + //使用的张数 private Integer useCount; + + private Boolean canGet; + + //获取的张数 + private Integer getCount; } diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/act/mapper/CouponActivityMapper.java b/ruoyi-mall/src/main/java/com/cyl/manager/act/mapper/CouponActivityMapper.java index c0da5fa..6fb2f8b 100644 --- a/ruoyi-mall/src/main/java/com/cyl/manager/act/mapper/CouponActivityMapper.java +++ b/ruoyi-mall/src/main/java/com/cyl/manager/act/mapper/CouponActivityMapper.java @@ -1,12 +1,14 @@ package com.cyl.manager.act.mapper; import java.util.List; + import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.cyl.manager.act.domain.entity.CouponActivity; +import org.apache.ibatis.annotations.Param; /** * 优惠券活动表Mapper接口 - * + * * @author zcc */ public interface CouponActivityMapper extends BaseMapper { @@ -17,4 +19,6 @@ public interface CouponActivityMapper extends BaseMapper { * @return 优惠券活动表集合 */ List selectByEntity(CouponActivity couponActivity); + + void receiveCoupon(@Param("id") Long id); } diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/act/mapper/MemberCouponMapper.java b/ruoyi-mall/src/main/java/com/cyl/manager/act/mapper/MemberCouponMapper.java index fe2d5bb..c9b8a87 100644 --- a/ruoyi-mall/src/main/java/com/cyl/manager/act/mapper/MemberCouponMapper.java +++ b/ruoyi-mall/src/main/java/com/cyl/manager/act/mapper/MemberCouponMapper.java @@ -2,6 +2,7 @@ package com.cyl.manager.act.mapper; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.stream.Stream; import com.baomidou.mybatisplus.core.mapper.BaseMapper; @@ -24,4 +25,6 @@ public interface MemberCouponMapper extends BaseMapper { List selectByEntity(MemberCoupon memberCoupon); List countUseCoupon(@Param("couponIds") Collection couponIds); + + List countGetCoupon(@Param("couponIds") Set ids, @Param("memberId") Long memberId); } diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/act/service/CouponActivityService.java b/ruoyi-mall/src/main/java/com/cyl/manager/act/service/CouponActivityService.java index c63226d..1a65ab1 100644 --- a/ruoyi-mall/src/main/java/com/cyl/manager/act/service/CouponActivityService.java +++ b/ruoyi-mall/src/main/java/com/cyl/manager/act/service/CouponActivityService.java @@ -7,12 +7,19 @@ import java.util.stream.Collectors; import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.cyl.h5.config.SecurityUtil; +import com.cyl.manager.act.domain.entity.IntegralHistory; import com.cyl.manager.act.domain.entity.MemberCoupon; import com.cyl.manager.act.domain.vo.CouponActivityVO; +import com.cyl.manager.act.mapper.IntegralHistoryMapper; import com.cyl.manager.act.mapper.MemberCouponMapper; import com.cyl.manager.pms.domain.entity.Product; import com.cyl.manager.pms.mapper.ProductMapper; +import com.cyl.manager.ums.domain.entity.MemberAccount; +import com.cyl.manager.ums.mapper.MemberAccountMapper; import com.github.pagehelper.PageHelper; +import com.ruoyi.framework.web.domain.server.Mem; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; @@ -23,6 +30,7 @@ import org.springframework.stereotype.Service; import com.cyl.manager.act.mapper.CouponActivityMapper; import com.cyl.manager.act.domain.entity.CouponActivity; import com.cyl.manager.act.domain.query.CouponActivityQuery; +import org.springframework.transaction.annotation.Transactional; /** * 优惠券活动表Service业务层处理 @@ -37,6 +45,10 @@ public class CouponActivityService { private MemberCouponMapper memberCouponMapper; @Autowired private ProductMapper productMapper; + @Autowired + private MemberAccountMapper memberAccountMapper; + @Autowired + private IntegralHistoryMapper integralHistoryMapper; /** * 查询优惠券活动表 @@ -87,14 +99,14 @@ public class CouponActivityService { //查找商品列表 Map productMap = new HashMap<>(); if (productIds.size() > 0) { - productMap = productMapper.selectBatchIds(productIds).stream().collect(Collectors.toMap(it->it.getId(),it->it)); + productMap = productMapper.selectBatchIds(productIds).stream().collect(Collectors.toMap(it -> it.getId(), it -> it)); } for (CouponActivity couponActivity : list) { CouponActivityVO vo = new CouponActivityVO(); - BeanUtils.copyProperties(couponActivity,vo); + BeanUtils.copyProperties(couponActivity, vo); Integer integer = useCountMap.get(couponActivity.getId()); vo.setUseCount(integer == null ? 0 : integer); - if (Arrays.asList(2, 3).contains(couponActivity.getUseScope()) && StringUtils.isNotEmpty(couponActivity.getProductIds())){ + if (Arrays.asList(2, 3).contains(couponActivity.getUseScope()) && StringUtils.isNotEmpty(couponActivity.getProductIds())) { List products = new ArrayList<>(); for (String s : couponActivity.getProductIds().split(",")) { Product product = productMap.get(Long.parseLong(s)); @@ -109,6 +121,24 @@ public class CouponActivityService { return new PageImpl<>(resList, page, total); } + + public CouponActivityVO getDetail(Long id) { + CouponActivity couponActivity = couponActivityMapper.selectById(id); + CouponActivityVO res = new CouponActivityVO(); + BeanUtils.copyProperties(couponActivity,res); + //判断领的有没有超 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("member_id", SecurityUtil.getLocalMember().getId()) + .eq("coupon_activity_id", id); + Integer count = memberCouponMapper.selectCount(queryWrapper); + if (count != null && count >= couponActivity.getUserLimit()) { + res.setCanGet(false); + } else { + res.setCanGet(true); + } + return res; + } + /** * 新增优惠券活动表 * @@ -129,7 +159,7 @@ public class CouponActivityService { */ public int update(CouponActivity couponActivity) { CouponActivity dbActivity = couponActivityMapper.selectById(couponActivity.getId()); - if (dbActivity==null) { + if (dbActivity == null) { return 0; } couponActivity.setLeftCount(dbActivity.getLeftCount()); @@ -146,4 +176,109 @@ public class CouponActivityService { public int deleteById(Long id) { return couponActivityMapper.deleteById(id); } + + public Page selectListByH5(Pageable page) { + PageHelper.startPage(page.getPageNumber() + 1, page.getPageSize()); + QueryWrapper qw = new QueryWrapper<>(); + LocalDateTime now = LocalDateTime.now(); + qw.lt("begin_time", now) + .gt("end_time", now); + List list = couponActivityMapper.selectList(qw); + if (CollectionUtil.isEmpty(list)) { + return new PageImpl<>(Collections.emptyList(), page, 0); + } + long total = ((com.github.pagehelper.Page) list).getTotal(); + //看用户已领取的张数 + Set ids = list.stream().map(it -> it.getId()).collect(Collectors.toSet()); + Map countMap = memberCouponMapper.countGetCoupon(ids, SecurityUtil.getLocalMember().getId()).stream().collect(Collectors.toMap(it -> it.getId(), it -> it.getGetCount())); + List resList = new ArrayList<>(); + for (CouponActivity it : list) { + CouponActivityVO vo = new CouponActivityVO(); + BeanUtils.copyProperties(it, vo); + Integer integer = countMap.get(it.getId()); + if (integer == null || integer < it.getUserLimit()) { + vo.setGetCount(integer == null ? 0 : integer); + vo.setCanGet(true); + } else { + vo.setGetCount(integer); + vo.setCanGet(false); + } + resList.add(vo); + } + + return new PageImpl<>(resList, page, total); + } + + @Transactional + public Boolean receiveCoupon(Long id) { + CouponActivity couponActivity = couponActivityMapper.selectById(id); + if (couponActivity == null) { + throw new RuntimeException("未找到活动"); + } + //判断有没有余量 + if (couponActivity.getLeftCount() < 1) { + throw new RuntimeException("活动已没有余额"); + } + //判断时间有没有超 + LocalDateTime now = LocalDateTime.now(); + if (couponActivity.getBeginTime().isAfter(now) || couponActivity.getEndTime().isBefore(now)) { + throw new RuntimeException("活动已过期"); + } + Long memberId = SecurityUtil.getLocalMember().getId(); + //判断领的有没有超 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("member_id", memberId) + .eq("coupon_activity_id", id); + Integer count = memberCouponMapper.selectCount(queryWrapper); + if (count != null && count >= couponActivity.getUserLimit()) { + throw new RuntimeException("您已达到领取额度"); + } + //如果是积分兑换 + if (Objects.equals(2, couponActivity.getCouponType())) { + //判断积分是否够 + MemberAccount memberAccount = memberAccountMapper.selectById(memberId); + if (memberAccount.getIntegralBalance().compareTo(couponActivity.getUseIntegral()) < 0) { + throw new RuntimeException("您的积分不足"); + } + + //扣除积分 + memberAccountMapper.updateIntegral(couponActivity.getUseIntegral(), memberId); + //记录日志 + insertIntegralHistory(couponActivity.getUseIntegral(), couponActivity.getCouponAmount(), memberId); + } + + //兑换券 + couponActivityMapper.receiveCoupon(id); + int saveCount = saveMemberCoupon(couponActivity, memberId); + + return saveCount > 0; + } + + private int saveMemberCoupon(CouponActivity activity, Long memberId) { + MemberCoupon memberCoupon = new MemberCoupon(); + memberCoupon.setCouponActivityId(activity.getId()); + memberCoupon.setTitle(activity.getTitle()); + memberCoupon.setUseScope(activity.getUseScope()); + memberCoupon.setProductIds(activity.getProductIds()); + memberCoupon.setCouponAmount(activity.getCouponAmount()); + memberCoupon.setMinAmount(activity.getMinAmount()); + memberCoupon.setUseIntegral(activity.getUseIntegral()); + memberCoupon.setCouponType(activity.getCouponType()); + memberCoupon.setBeginTime(LocalDateTime.now()); + memberCoupon.setEndTime(activity.getEndTime()); + memberCoupon.setCreateTime(LocalDateTime.now()); + memberCoupon.setMemberId(memberId); + return memberCouponMapper.insert(memberCoupon); + } + + private void insertIntegralHistory(BigDecimal amount, BigDecimal couponAmount, Long memberId) { + IntegralHistory history = new IntegralHistory(); + history.setOpType(2); + history.setSubOpType(22); + history.setAmount(amount); + history.setOrderAmount(couponAmount); + history.setMemberId(memberId); + history.setCreateTime(LocalDateTime.now()); + integralHistoryMapper.insert(history); + } } diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/act/service/MemberCouponService.java b/ruoyi-mall/src/main/java/com/cyl/manager/act/service/MemberCouponService.java index 5a908ee..c4fb366 100644 --- a/ruoyi-mall/src/main/java/com/cyl/manager/act/service/MemberCouponService.java +++ b/ruoyi-mall/src/main/java/com/cyl/manager/act/service/MemberCouponService.java @@ -5,11 +5,16 @@ import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.cyl.h5.config.SecurityUtil; import com.cyl.manager.act.domain.vo.MemberCouponVO; import com.cyl.manager.ums.domain.entity.Member; import com.cyl.manager.ums.mapper.MemberMapper; import com.github.pagehelper.PageHelper; +import com.google.gson.JsonObject; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; @@ -24,7 +29,6 @@ import com.cyl.manager.act.domain.query.MemberCouponQuery; /** * 用户领券记录Service业务层处理 * - * * @author zcc */ @Service @@ -48,7 +52,7 @@ public class MemberCouponService { * 查询用户领券记录列表 * * @param query 查询条件 - * @param page 分页条件 + * @param page 分页条件 * @return 用户领券记录 */ public Page selectList(MemberCouponQuery query, Pageable page) { @@ -122,4 +126,35 @@ public class MemberCouponService { public int deleteById(Long id) { return memberCouponMapper.deleteById(id); } + + public Page selectListByH5(MemberCouponQuery query, Pageable page) { + PageHelper.startPage(page.getPageNumber() + 1, page.getPageSize()); + QueryWrapper qw = new QueryWrapper<>(); + qw.eq("member_id", SecurityUtil.getLocalMember().getId()); + LocalDateTime now = LocalDateTime.now(); + if (query.getType() != null) { + switch (query.getType()) { + case 1: + //已领取 + qw.eq("use_status", 0) + .ge("end_time", now) + .le("begin_time", now); + break; + case 2: + //已使用 + qw.eq("use_status", 1); + break; + case 3: + //已过期 + qw.eq("use_status", 0); + qw.and(it -> it.le("end_time", now).or().ge("begin_time", now)); + break; + default: + break; + } + } + List list = memberCouponMapper.selectList(qw); + return new PageImpl<>(list, page, ((com.github.pagehelper.Page) list).getTotal()); + } + } diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/pms/domain/query/ProductQuery.java b/ruoyi-mall/src/main/java/com/cyl/manager/pms/domain/query/ProductQuery.java index 342ca39..06441f1 100644 --- a/ruoyi-mall/src/main/java/com/cyl/manager/pms/domain/query/ProductQuery.java +++ b/ruoyi-mall/src/main/java/com/cyl/manager/pms/domain/query/ProductQuery.java @@ -75,4 +75,6 @@ public class ProductQuery { //排查的id private List excludeProductIds; + private List ids; + } diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/pms/service/ProductService.java b/ruoyi-mall/src/main/java/com/cyl/manager/pms/service/ProductService.java index c570caf..6007056 100644 --- a/ruoyi-mall/src/main/java/com/cyl/manager/pms/service/ProductService.java +++ b/ruoyi-mall/src/main/java/com/cyl/manager/pms/service/ProductService.java @@ -98,6 +98,9 @@ public class ProductService { if (CollectionUtil.isNotEmpty(query.getExcludeProductIds())) { qw.notIn("id",query.getExcludeProductIds()); } + if (CollectionUtil.isNotEmpty(query.getIds())) { + qw.in("id",query.getIds()); + } return productMapper.selectList(qw); } diff --git a/ruoyi-mall/src/main/java/com/cyl/manager/ums/mapper/MemberAccountMapper.java b/ruoyi-mall/src/main/java/com/cyl/manager/ums/mapper/MemberAccountMapper.java index 9a75b06..2ced8ee 100644 --- a/ruoyi-mall/src/main/java/com/cyl/manager/ums/mapper/MemberAccountMapper.java +++ b/ruoyi-mall/src/main/java/com/cyl/manager/ums/mapper/MemberAccountMapper.java @@ -21,4 +21,6 @@ public interface MemberAccountMapper extends BaseMapper { List selectByEntity(MemberAccount memberAccount); int updateIntegralBalance(@Param("amount") BigDecimal amount, @Param("memberId") Long memberId); + + int updateIntegral(@Param("useIntegral") BigDecimal useIntegral, @Param("memberId") Long memberId); } diff --git a/ruoyi-mall/src/main/resources/mapper/act/CouponActivityMapper.xml b/ruoyi-mall/src/main/resources/mapper/act/CouponActivityMapper.xml index c17b6a3..06b0146 100644 --- a/ruoyi-mall/src/main/resources/mapper/act/CouponActivityMapper.xml +++ b/ruoyi-mall/src/main/resources/mapper/act/CouponActivityMapper.xml @@ -24,6 +24,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" select id, title, use_scope, product_ids, total_count, left_count, user_limit, coupon_amount, min_amount, use_integral, coupon_type, begin_time, end_time, create_time from act_coupon_activity + + update act_coupon_activity set left_count = left_count -1,update_time = now() where id = #{id} + + diff --git a/ruoyi-mall/src/main/resources/mapper/ums/MemberAccountMapper.xml b/ruoyi-mall/src/main/resources/mapper/ums/MemberAccountMapper.xml index 896bce5..d167701 100644 --- a/ruoyi-mall/src/main/resources/mapper/ums/MemberAccountMapper.xml +++ b/ruoyi-mall/src/main/resources/mapper/ums/MemberAccountMapper.xml @@ -19,6 +19,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update ums_member_account set integral_balance = integral_balance + #{amount},total_integral_balance = total_integral_balance + #{amount},update_time = now() where member_id = #{memberId} + + update ums_member_account set integral_balance = integral_balance - #{useIntegral},update_time = now() + where member_id = #{memberId} +