From 9d043d9b8ca8600e4163b40d8ae3a0b683675765 Mon Sep 17 00:00:00 2001 From: wqy <1191068887@qq.com> Date: Thu, 28 Mar 2024 17:06:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=B8=E7=9A=84=E5=85=91=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../act/controller/H5CouponController.java | 46 ++++++-- .../act/domain/entity/MemberCoupon.java | 4 + .../act/domain/query/MemberCouponQuery.java | 3 + .../act/mapper/CouponActivityMapper.java | 6 +- .../act/service/CouponActivityService.java | 111 ++++++++++++++++-- .../act/service/MemberCouponService.java | 39 +++++- .../ums/mapper/MemberAccountMapper.java | 2 + .../mapper/act/CouponActivityMapper.xml | 3 + .../mapper/ums/MemberAccountMapper.xml | 4 + sql/database-20240322.sql | 33 ++++-- 10 files changed, 217 insertions(+), 34 deletions(-) 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 index c7611a4..7ded087 100644 --- 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 @@ -1,22 +1,21 @@ package com.cyl.manager.act.controller; import com.cyl.manager.act.domain.entity.CouponActivity; -import com.cyl.manager.act.domain.entity.IntegralHistory; -import com.cyl.manager.act.domain.query.CouponActivityQuery; -import com.cyl.manager.act.domain.query.IntegralHistoryQuery; +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.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import java.util.List; - @Api(description = "优惠券接口列表") @RestController @RequestMapping("/h5/coupon") @@ -24,6 +23,10 @@ public class H5CouponController { @Autowired private CouponActivityService couponActivityService; + @Autowired + private RedisService redisService; + @Autowired + private MemberCouponService memberCouponService; @ApiOperation("优惠券活动列表") @PostMapping("/activity/list") @@ -33,8 +36,35 @@ public class H5CouponController { } @GetMapping("/activity/get") - public ResponseEntity getDetail(Long id) { - CouponActivity detail = couponActivityService.getDetail(id); + 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/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/service/CouponActivityService.java b/ruoyi-mall/src/main/java/com/cyl/manager/act/service/CouponActivityService.java index 8ea6f29..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,13 +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; @@ -24,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业务层处理 @@ -38,6 +45,10 @@ public class CouponActivityService { private MemberCouponMapper memberCouponMapper; @Autowired private ProductMapper productMapper; + @Autowired + private MemberAccountMapper memberAccountMapper; + @Autowired + private IntegralHistoryMapper integralHistoryMapper; /** * 查询优惠券活动表 @@ -111,18 +122,21 @@ public class CouponActivityService { } - public CouponActivity getDetail(Long id) { - return couponActivityMapper.selectById(id); -// if (couponActivity == null) { -// return null; -// } -// CouponActivityVO res = new CouponActivityVO(); -// BeanUtils.copyProperties(couponActivity,res); -// if (Arrays.asList(2, 3).contains(couponActivity.getUseScope()) && StringUtils.isNotEmpty(couponActivity.getProductIds())) { -// List products = productMapper.selectBatchIds(Arrays.stream(couponActivity.getProductIds().split(",")).map(item -> Long.parseLong(item)).collect(Collectors.toSet())); -// res.setProductList(products); -// } -// return res; + 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; } /** @@ -194,4 +208,77 @@ public class CouponActivityService { 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/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/sql/database-20240322.sql b/sql/database-20240322.sql index b358ec5..8dc189c 100644 --- a/sql/database-20240322.sql +++ b/sql/database-20240322.sql @@ -18,15 +18,26 @@ CREATE TABLE `act_coupon_activity` PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='优惠券活动表'; -CREATE TABLE `act_integral_history` +ALTER TABLE `act_integral_history` + MODIFY COLUMN `sub_op_type` int (11) NULL DEFAULT NULL COMMENT '子类型:11签到 12消费获得 21退款扣除积分 22 兑换优惠券' AFTER `op_type`; + +CREATE TABLE `act_member_coupon` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `member_id` bigint(20) NOT NULL, - `amount` decimal(10, 2) NOT NULL COMMENT '变动金额', - `op_type` int(11) NOT NULL COMMENT '类型 1:收入 2:支出 3:其他', - `sub_op_type` int(11) DEFAULT NULL COMMENT '子类型:11签到 12消费获得 21退款扣除积分', - `order_amount` decimal(10, 2) DEFAULT NULL COMMENT '订单金额', - `order_id` bigint(20) DEFAULT NULL COMMENT '订单id', - `create_time` datetime(3) DEFAULT NULL COMMENT '创建时间', - PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=87 DEFAULT CHARSET=utf8mb4 COMMENT='积分流水表'; \ No newline at end of file + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `coupon_activity_id` bigint(20) NOT NULL COMMENT '活动id', + `member_id` bigint(20) DEFAULT NULL COMMENT '用户id', + `title` varchar(255) NOT NULL COMMENT '活动名称', + `use_scope` int(11) NOT NULL COMMENT '使用范围 1全场通用 2指定商品可用 3指定商品不可用', + `product_ids` varchar(255) DEFAULT NULL COMMENT '商品id集合,逗号分隔', + `coupon_amount` decimal(10, 2) NOT NULL COMMENT '优惠券金额', + `min_amount` decimal(10, 2) DEFAULT NULL COMMENT '最低消费金额', + `use_integral` decimal(10, 2) DEFAULT NULL COMMENT '要兑换的积分', + `coupon_type` int(11) NOT NULL DEFAULT '1' COMMENT '1免费兑换 2积分兑换', + `begin_time` datetime(3) NOT NULL COMMENT '券开始时间', + `end_time` datetime(3) NOT NULL COMMENT '券结束时间', + `use_status` int(11) NOT NULL DEFAULT '0' COMMENT '0未使用 1已使用', + `order_id` bigint(20) DEFAULT NULL COMMENT '订单id', + `use_time` datetime(3) DEFAULT NULL COMMENT '使用时间', + `create_time` datetime(3) DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户领券记录'; \ No newline at end of file