From d418855f0d08ede07784a5e6245b81b36bbbd5bc Mon Sep 17 00:00:00 2001 From: xhxu Date: Sat, 30 Jan 2021 10:54:01 +0800 Subject: [PATCH] sql --- .../java/com/iformall/common/ErrorCode.java | 1 + .../domain/vo/MerchantCreditRankingVo.java | 7 ++ .../java/com/iformall/enums/EnumCacheKey.java | 3 +- .../impl/WxActivityJoinServiceImpl.java | 103 +++++++++++++----- .../service/impl/WxActivityServiceImpl.java | 30 ++++- .../java/com/iformall/utils/RedisLock.java | 27 +++++ .../mapper/WxCreditHistoryMapper.xml | 4 +- 7 files changed, 137 insertions(+), 38 deletions(-) diff --git a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java index 0ce1b674e..44409512e 100644 --- a/mallinkService/src/main/java/com/iformall/common/ErrorCode.java +++ b/mallinkService/src/main/java/com/iformall/common/ErrorCode.java @@ -549,6 +549,7 @@ public enum ErrorCode{ ACTIVITY_JOIN_IS_SIGNIN(30014, "用户已签到!"), ACTIVITY_JOIN_NOT_FOND(30015, "活动报名未找到!"), ACTIVITY_NOT_UPDATE(30016, "下线状态,不允许修改!"), + ACTIVITY_TIME_END(30017, "活动已结束"), /** * 文件上传 diff --git a/mallinkService/src/main/java/com/iformall/domain/vo/MerchantCreditRankingVo.java b/mallinkService/src/main/java/com/iformall/domain/vo/MerchantCreditRankingVo.java index 0d01f3b86..7d3274c49 100644 --- a/mallinkService/src/main/java/com/iformall/domain/vo/MerchantCreditRankingVo.java +++ b/mallinkService/src/main/java/com/iformall/domain/vo/MerchantCreditRankingVo.java @@ -1,5 +1,6 @@ package com.iformall.domain.vo; +import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; @Data @@ -7,6 +8,12 @@ public class MerchantCreditRankingVo { private Long merchantId; + @io.swagger.annotations.ApiModelProperty(value="租户ID",name="tenantId") + protected String tenantId; + + @io.swagger.annotations.ApiModelProperty(value="父租户ID",name="parentTenantId") + protected String parentTenantId; + @io.swagger.annotations.ApiModelProperty(value = "商户名", name = "merchantName") private String merchantName; diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumCacheKey.java b/mallinkService/src/main/java/com/iformall/enums/EnumCacheKey.java index 0f55628e9..6d608fd99 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumCacheKey.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumCacheKey.java @@ -9,7 +9,8 @@ import java.util.Map; public enum EnumCacheKey { C_INDEX_PAGE_LIST(0, "couponChannelList_"), - COUPON_STOCK(1,"couponStock:couponStock_") + COUPON_STOCK(1,"couponStock:couponStock_"), + ACTIVITY_STOCK(2,"activityStock:activityStock_") ; private static Map map = new HashMap(); static { diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxActivityJoinServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxActivityJoinServiceImpl.java index cdfb9c8f1..50ef2aa0c 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxActivityJoinServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxActivityJoinServiceImpl.java @@ -9,16 +9,17 @@ import com.iformall.common.IdWorker; import com.iformall.common.Result; import com.iformall.common.ResultData; import com.iformall.domain.po.*; -import com.iformall.domain.po.base.TenantEntity; import com.iformall.domain.po.msg.WxMsgRecord; import com.iformall.domain.vo.WxActivityJoinQuestionAnswer; import com.iformall.enums.*; +import com.iformall.exception.MallinkException; import com.iformall.mapper.*; import com.iformall.mq.MqBaseProducer; import com.iformall.service.ExcelService; import com.iformall.service.WxActivityJoinService; import com.iformall.service.WxCreditHistoryService; import com.iformall.utils.DateUtils; +import com.iformall.utils.RedisLock; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,8 +40,12 @@ import java.util.Map; */ @Service public class WxActivityJoinServiceImpl implements WxActivityJoinService { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + @Autowired + RedisLock redisLock; + @Autowired WxActivityJoinMapper wxActivityJoinMapper; @@ -72,29 +77,26 @@ public class WxActivityJoinServiceImpl implements WxActivityJoinService { } @Override + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class}) public ResultData modifyStatus(WxActivityJoin wxActivityJoin) { WxActivityJoin wxActivityJoin1 = wxActivityJoinMapper.selectById(wxActivityJoin.getId()); if(wxActivityJoin1 == null){ return new ResultData(ErrorCode.ACTIVITY_JOIN_NOT_FOND); } if (wxActivityJoin.getStatus().equals(EnumActivityJoinStatus.CONFIRMED.getCode())) { - WxActivity wxActivity = wxActivityMapper.selectById(wxActivityJoin.getActivityId()); - Integer personLimit = wxActivity.getPersonLimit(); - WxActivityJoin params = new WxActivityJoin(); - params.updateTenantInfo(wxActivity); - params.setActivityId(wxActivity.getId()); - params.setStatus(EnumActivityJoinStatus.CONFIRMED.getCode()); - int count = wxActivityJoinMapper.selectCount(new QueryWrapper(params)); - if (personLimit.equals(count)) { - return new ResultData(ErrorCode.ACTIVITY_PERSON_LIMITED, count); - } + activityJoinRedisLock(wxActivityJoin.getActivityId()); }else{ if(wxActivityJoin1.getSignIn().equals(EnumActivityJoinSignStatus.YES.getCode())){ return new ResultData(ErrorCode.ACTIVITY_JOIN_IS_SIGNIN); } } - wxActivityJoinMapper.updateById(wxActivityJoin); + if(wxActivityJoin.getStatus().equals(EnumActivityJoinStatus.CONFIRMED.getCode())){ + long stock = redisLock.decrease(EnumCacheKey.ACTIVITY_STOCK.getMessage()+wxActivityJoin.getActivityId(), 1); + if (stock < 0 ) { + throw new MallinkException(ErrorCode.ACTIVITY_PERSON_LIMITED.getCode(),"活动报名人数已满!"); + } + } return new ResultData(Result.SUCCESS, "操作成功"); } @@ -172,8 +174,8 @@ public class WxActivityJoinServiceImpl implements WxActivityJoinService { } - @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class}) @Override + @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class}) public ResultData join(WxActivityJoin wxActivityJoin) { WxActivity wxActivity = wxActivityMapper.selectById(wxActivityJoin.getActivityId()); if(wxActivity == null){ @@ -192,7 +194,6 @@ public class WxActivityJoinServiceImpl implements WxActivityJoinService { return new ResultData(ErrorCode.ACTIVITY_NOT_JOIN); } - WxActivityJoin joinQuery = new WxActivityJoin(); joinQuery.setUserId(wxActivityJoin.getUserId()); joinQuery.setActivityId(wxActivityJoin.getActivityId()); @@ -203,18 +204,24 @@ public class WxActivityJoinServiceImpl implements WxActivityJoinService { if(wxActivity.getSignupExamine().equals(EnumDelFlag.YES.getCode())){ wxActivityJoin.setStatus(EnumActivityJoinStatus.NOT_CONFIRMED.getCode()); }else{ - WxActivityJoin params = new WxActivityJoin(); - params.updateTenantInfo(wxActivity); - params.setActivityId(wxActivity.getId()); - params.setStatus(EnumActivityJoinStatus.CONFIRMED.getCode()); - int joinCount = wxActivityJoinMapper.selectCount(new QueryWrapper(params)); - if (joinCount >= wxActivity.getPersonLimit().intValue()) { - return new ResultData(ErrorCode.ACTIVITY_PERSON_LIMITED, joinCount); - } + activityJoinRedisLock(wxActivityJoin.getActivityId()); wxActivityJoin.setStatus(EnumActivityJoinStatus.CONFIRMED.getCode()); } - WxCUserBasicInfo user = wxCUserBasicInfoMapper.selectById(wxActivityJoin.getUserId(),wxActivityJoin.getFinalTenantId()); + //保存到报名表中 + final IdWorker idWorker = IdWorker.get(); + wxActivityJoin.setId(idWorker.nextId()); + wxActivityJoin.setPhone(user.getPhone()); + wxActivityJoin.setCreateTime(date); + wxActivityJoin.setUpdateTime(date); + wxActivityJoinMapper.insert(wxActivityJoin); + if(wxActivityJoin.getStatus().equals(EnumActivityJoinStatus.CONFIRMED.getCode())){ + long stock = redisLock.decrease(EnumCacheKey.ACTIVITY_STOCK.getMessage()+wxActivityJoin.getActivityId(), 1); + if (stock < 0 ) { + throw new MallinkException(ErrorCode.ACTIVITY_PERSON_LIMITED.getCode(),"活动报名人数已满!"); + } + } + //查询是否消耗积分 if (wxActivity.getUseCredit().equals(EnumActivityUseCreditStatus.YES.getCode())) { Integer credit = wxActivity.getCredit(); @@ -232,13 +239,6 @@ public class WxActivityJoinServiceImpl implements WxActivityJoinService { wxCreditHistoryService.saveOrUpdate(wxCreditHistory,wxActivity.getTenantId()); } - //保存到报名表中 - final IdWorker idWorker = IdWorker.get(); - wxActivityJoin.setId(idWorker.nextId()); - wxActivityJoin.setPhone(user.getPhone()); - wxActivityJoin.setCreateTime(date); - wxActivityJoin.setUpdateTime(date); - wxActivityJoinMapper.insert(wxActivityJoin); return new ResultData(); } @@ -291,4 +291,47 @@ public class WxActivityJoinServiceImpl implements WxActivityJoinService { } + private void activityJoinRedisLock(Long activityId){ + + if(!redisLock.hasCouponStockCache(activityId)) { + //此处需要加锁,防止并发设置 + long time = System.currentTimeMillis() + RedisLock.TIMEOUT; + String timeStr = String.valueOf(time); + boolean stocksetlock = redisLock.lock("activityLockStockSet_" + activityId, timeStr); + if (stocksetlock) { + if (!redisLock.hasActivityStockCache(activityId)) { + WxActivity wxActivity = wxActivityMapper.selectById(activityId); + if (wxActivity != null && wxActivity.getPersonLimit() != null) { + Integer personLimit = wxActivity.getPersonLimit(); + WxActivityJoin params = new WxActivityJoin(); + params.updateTenantInfo(wxActivity); + params.setActivityId(wxActivity.getId()); + params.setStatus(EnumActivityJoinStatus.CONFIRMED.getCode()); + int count = wxActivityJoinMapper.selectCount(new QueryWrapper(params)); + int i = personLimit.intValue() - count; + try { + redisLock.setActivityStock(activityId, i ); + } catch (Exception e) { + logger.error("set activitystock to redis fail.", e); + throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(), "redis设置活动报名失败" + activityId); + } finally { + redisLock.unlock("activityLockStockSet_" + activityId, timeStr); + } + } else { + redisLock.unlock("activityLockStockSet_" + activityId, timeStr); + throw new MallinkException(ErrorCode.ACTIVITY_NOT_FOND.getCode(),"活动未找到或不需要报名!"+activityId); + } + }else{ + redisLock.unlock("activityLockStockSet_" + activityId, timeStr); + } + } + } + long redisStock = redisLock.getActivityStock(activityId); + if (redisStock <= 0) { + throw new MallinkException(ErrorCode.ACTIVITY_PERSON_LIMITED.getCode(),"报名人数已满!:"+activityId); + } + + } + + } diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxActivityServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxActivityServiceImpl.java index ea55ea653..ff1e79530 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxActivityServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxActivityServiceImpl.java @@ -158,10 +158,20 @@ public class WxActivityServiceImpl implements WxActivityService { if (activity == null) { return new ResultData(ErrorCode.SYS_PARAMETER_ERROR); } - if (wxActivity.getStatus().equals(EnumActivityStatus.INJECT_ONLINE.getCode()) - && activity.getEndTime().before(new Date())) { - return new ResultData(ErrorCode.ACTIVITY_JOIN_TIME_END); + if (wxActivity.getStatus().equals(EnumActivityStatus.INJECT_ONLINE.getCode())){ + if(wxActivity.getActivityType().equals(EnumDelFlag.YES.getCode())){ + if (wxActivity.getEndTime().before(new Date())) { + throw new MallinkException(ErrorCode.ACTIVITY_JOIN_TIME_END); + } + }else if(wxActivity.getActivityType().equals(EnumDelFlag.NO.getCode())){ + if (wxActivity.getActivityEndTime().before(new Date())) { + throw new MallinkException(ErrorCode.ACTIVITY_TIME_END); + } + }else{ + return new ResultData(ErrorCode.SYS_PARAMETER_ERROR,"activityType"); + } } + wxActivity.setUpdateTime(new Date()); wxActivityMapper.updateById(wxActivity); if (wxActivity.getStatus().equals(EnumActivityStatus.STATUS_TAKE_OFFF.getCode())) { @@ -212,8 +222,18 @@ public class WxActivityServiceImpl implements WxActivityService { } //修改投放状态 WxActivity wxActivity = wxActivityMapper.selectById(id); - if (wxActivity.getEndTime().before(new Date())) { - return new ResultData(ErrorCode.ACTIVITY_JOIN_TIME_END); + if (wxActivity.getStatus().equals(EnumActivityStatus.INJECT_ONLINE.getCode())){ + if(wxActivity.getActivityType().equals(EnumDelFlag.YES.getCode())){ + if (wxActivity.getEndTime().before(new Date())) { + throw new MallinkException(ErrorCode.ACTIVITY_JOIN_TIME_END); + } + }else if(wxActivity.getActivityType().equals(EnumDelFlag.NO.getCode())){ + if (wxActivity.getActivityEndTime().before(new Date())) { + throw new MallinkException(ErrorCode.ACTIVITY_TIME_END); + } + }else{ + return new ResultData(ErrorCode.SYS_PARAMETER_ERROR,"activityType"); + } } if(!wxActivity.getStatus().equals(EnumActivityStatus.INJECT_ONLINE.getCode())){ return new ResultData(ErrorCode.ACTIVITY_SEND_ERROR_NOONLINE); diff --git a/mallinkService/src/main/java/com/iformall/utils/RedisLock.java b/mallinkService/src/main/java/com/iformall/utils/RedisLock.java index c90d1cceb..9dddc9788 100644 --- a/mallinkService/src/main/java/com/iformall/utils/RedisLock.java +++ b/mallinkService/src/main/java/com/iformall/utils/RedisLock.java @@ -154,5 +154,32 @@ public class RedisLock { Long rs = stringRedisTemplate.opsForValue().increment("orderGroup:complete:"+String.valueOf(orderGroupId), 1); return rs <= 1L; } + + + //------------------------------------------------------------------------------------------------------- + // 时间紧迫,,,后面再做封装 + + public boolean hasActivityStockCache(long activityId) { + //如果库存为零,这个时候同步一下数据库的库存,因为有的时候系统报错事务会胡滚,但是redis扣减库存执行了,所以为0的时候,跟数据库的同步一下 + boolean booleanHasCache = stringRedisTemplate.hasKey(EnumCacheKey.ACTIVITY_STOCK.getMessage()+String.valueOf(activityId)); + if (booleanHasCache) { + long stockvalue = getActivityStock(activityId); + if (stockvalue > 0) { + return true; + }else { + return false; + } + } + return false; + } + + public long getActivityStock(long activityId) { + String longstr = stringRedisTemplate.opsForValue().get(EnumCacheKey.ACTIVITY_STOCK.getMessage()+String.valueOf(activityId)); + return Long.parseLong(longstr); + } + + public void setActivityStock(long activityId,int number) { + stringRedisTemplate.opsForValue().set(EnumCacheKey.ACTIVITY_STOCK.getMessage()+String.valueOf(activityId), String.valueOf(number)); + } } diff --git a/mallinkService/src/main/resources/mapper/WxCreditHistoryMapper.xml b/mallinkService/src/main/resources/mapper/WxCreditHistoryMapper.xml index b28c73bc9..2db0f2d08 100644 --- a/mallinkService/src/main/resources/mapper/WxCreditHistoryMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxCreditHistoryMapper.xml @@ -307,12 +307,12 @@