券的兑换

pull/1/head
wqy 2 years ago
parent 04a2e5f34e
commit 9d043d9b8c

@ -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<CouponActivity> getDetail(Long id) {
CouponActivity detail = couponActivityService.getDetail(id);
public ResponseEntity<CouponActivityVO> getDetail(Long id) {
CouponActivityVO detail = couponActivityService.getDetail(id);
return ResponseEntity.ok(detail);
}
@PostMapping("/receive")
public ResponseEntity<Boolean> 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<Page<MemberCoupon>> list(@RequestBody MemberCouponQuery query, Pageable page) {
//获取所有未过期且运行中的活动
return ResponseEntity.ok(memberCouponService.selectListByH5(query,page));
}
}

@ -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;

@ -23,5 +23,8 @@ public class MemberCouponQuery {
@ApiModelProperty("0未使用 1已使用 精确匹配")
private Integer useStatus;
//1已领取 2已使用 3已过期
private Integer type;
}

@ -1,8 +1,10 @@
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
@ -17,4 +19,6 @@ public interface CouponActivityMapper extends BaseMapper<CouponActivity> {
* @return
*/
List<CouponActivity> selectByEntity(CouponActivity couponActivity);
void receiveCoupon(@Param("id") Long id);
}

@ -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<Product> 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<MemberCoupon> 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<MemberCoupon> 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);
}
}

@ -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
@ -122,4 +126,35 @@ public class MemberCouponService {
public int deleteById(Long id) {
return memberCouponMapper.deleteById(id);
}
public Page<MemberCoupon> selectListByH5(MemberCouponQuery query, Pageable page) {
PageHelper.startPage(page.getPageNumber() + 1, page.getPageSize());
QueryWrapper<MemberCoupon> 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<MemberCoupon> list = memberCouponMapper.selectList(qw);
return new PageImpl<>(list, page, ((com.github.pagehelper.Page) list).getTotal());
}
}

@ -21,4 +21,6 @@ public interface MemberAccountMapper extends BaseMapper<MemberAccount> {
List<MemberAccount> selectByEntity(MemberAccount memberAccount);
int updateIntegralBalance(@Param("amount") BigDecimal amount, @Param("memberId") Long memberId);
int updateIntegral(@Param("useIntegral") BigDecimal useIntegral, @Param("memberId") Long memberId);
}

@ -24,6 +24,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectCouponActivityVo">
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
</sql>
<update id="receiveCoupon">
update act_coupon_activity set left_count = left_count -1,update_time = now() where id = #{id}
</update>
<select id="selectByEntity" parameterType="CouponActivity" resultMap="CouponActivityResult">
<include refid="selectCouponActivityVo"/>

@ -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>
<update id="updateIntegral">
update ums_member_account set integral_balance = integral_balance - #{useIntegral},update_time = now()
where member_id = #{memberId}
</update>
<select id="selectByEntity" parameterType="MemberAccount" resultMap="MemberAccountResult">
<include refid="selectMemberAccountVo"/>

@ -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 '订单金额',
`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`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=87 DEFAULT CHARSET=utf8mb4 COMMENT='积分流水表';
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户领券记录';
Loading…
Cancel
Save