Browse Source

小小训练营活动
直播间商品

zouxuan 3 years ago
parent
commit
f15ef90129

+ 7 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/LiveGoodsDao.java

@@ -2,8 +2,14 @@ package com.ym.mec.biz.dal.dao;
 
 import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.biz.dal.entity.LiveGoods;
+import org.apache.ibatis.annotations.Param;
 
 public interface LiveGoodsDao extends BaseDAO<Integer, LiveGoods> {
 
-	
+
+    LiveGoods getLock(Integer liveGoodsId);
+
+    int reduceStock(@Param("liveGoodsId") Integer liveGoodsId);
+
+    void addStock(@Param("liveGoodsId") Integer liveGoodsId);
 }

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/TempBuyFreeLiveTheoryCourseDao.java

@@ -0,0 +1,11 @@
+package com.ym.mec.biz.dal.dao;
+
+import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.biz.dal.entity.TempBuyFreeLiveTheoryCourse;
+import org.apache.ibatis.annotations.Param;
+
+public interface TempBuyFreeLiveTheoryCourseDao extends BaseDAO<Integer, TempBuyFreeLiveTheoryCourse> {
+
+
+    int countByUserId(@Param("userId") Integer userId);
+}

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/RedisKeyConstant.java

@@ -0,0 +1,11 @@
+package com.ym.mec.biz.dal.dto;
+
+public interface RedisKeyConstant {
+
+    //直播间商品库存缓存key
+    String LIVE_GOODS_STOCK_CACHE_KEY = "live_goods_stock:";
+    //直播间商品冻结库存缓存key
+    String LIVE_GOODS_FROZEN_CACHE_KEY = "live_goods_frozen_stock:";
+    //购买了0元直播课的学员
+    String LIVE_GOODS_ZERO_CACHE_KEY = "live_goods_zero:";
+}

+ 63 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/TempBuyFreeLiveTheoryCourse.java

@@ -0,0 +1,63 @@
+package com.ym.mec.biz.dal.entity;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+/**
+ * 对应数据库表(temp_buy_free_live_theory_course):
+ */
+public class TempBuyFreeLiveTheoryCourse {
+
+	/**  */
+	private Integer id;
+	
+	/**  */
+	private Integer userId;
+	
+	/**  */
+	private java.util.Date createTime;
+	
+	/**  */
+	private java.util.Date updateTime;
+
+	public TempBuyFreeLiveTheoryCourse(Integer userId) {
+		this.userId = userId;
+	}
+
+	public void setId(Integer id){
+		this.id = id;
+	}
+	
+	public Integer getId(){
+		return this.id;
+	}
+			
+	public void setUserId(Integer userId){
+		this.userId = userId;
+	}
+	
+	public Integer getUserId(){
+		return this.userId;
+	}
+			
+	public void setCreateTime(java.util.Date createTime){
+		this.createTime = createTime;
+	}
+	
+	public java.util.Date getCreateTime(){
+		return this.createTime;
+	}
+			
+	public void setUpdateTime(java.util.Date updateTime){
+		this.updateTime = updateTime;
+	}
+	
+	public java.util.Date getUpdateTime(){
+		return this.updateTime;
+	}
+			
+	@Override
+	public String toString() {
+		return ToStringBuilder.reflectionToString(this);
+	}
+
+}

+ 34 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/vo/ImLiveBroadcastRoomDetailVo.java

@@ -4,6 +4,7 @@ import com.ym.mec.biz.dal.entity.ImLiveRoomVideo;
 import io.swagger.annotations.ApiModelProperty;
 
 import java.io.Serializable;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -33,8 +34,41 @@ public class ImLiveBroadcastRoomDetailVo implements Serializable {
     @ApiModelProperty(value = "直播时长")
     private Integer totalLiveTime;
 
+    @ApiModelProperty(value = "直播开始时间")
+    private Date liveStartTime;
+
+    @ApiModelProperty(value = "直播结束时间")
+    private Date liveEndTime;
+
+    @ApiModelProperty(value = "直播状态 0未开始 1开始 2已结束")
+    private Integer liveState;
+
     private List<ImLiveRoomVideo> videoList;
 
+    public Date getLiveStartTime() {
+        return liveStartTime;
+    }
+
+    public void setLiveStartTime(Date liveStartTime) {
+        this.liveStartTime = liveStartTime;
+    }
+
+    public Date getLiveEndTime() {
+        return liveEndTime;
+    }
+
+    public void setLiveEndTime(Date liveEndTime) {
+        this.liveEndTime = liveEndTime;
+    }
+
+    public Integer getLiveState() {
+        return liveState;
+    }
+
+    public void setLiveState(Integer liveState) {
+        this.liveState = liveState;
+    }
+
     public String getRoomUid() {
         return roomUid;
     }

+ 15 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/LiveGoodsService.java

@@ -8,4 +8,19 @@ public interface LiveGoodsService extends BaseService<Integer, LiveGoods> {
     void updateLiveGoods(LiveGoods liveGoods);
 
     void deleteLiveGoods(Integer goodsId);
+
+    //初始化商品缓存
+    void initGoodsStockCache(Integer liveGoodsId, String liveId);
+
+    //商品库存+1
+    void addGoodsStock(Integer liveGoodsId, String liveId);
+
+    //商品库存-1
+    void reduceGoodsStock(Integer liveGoodsId, String liveId);
+
+    //商品冻结库存+1
+    void addGoodsFreezeStock(Integer liveGoodsId, String liveId);
+
+    //商品冻结库存-1
+    void reduceGoodsFreezeStock(Integer liveGoodsId, String liveId);
 }

+ 20 - 7
mec-biz/src/main/java/com/ym/mec/biz/service/impl/LiveGoodsMapperServiceImpl.java

@@ -3,12 +3,13 @@ package com.ym.mec.biz.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.ym.mec.biz.dal.dao.LiveGoodsMapperDao;
 import com.ym.mec.biz.dal.dto.LiveGoodsMapperDto;
+import com.ym.mec.biz.dal.dto.RedisKeyConstant;
 import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoom;
-import com.ym.mec.biz.dal.entity.LiveGoods;
 import com.ym.mec.biz.dal.entity.LiveGoodsMapper;
 import com.ym.mec.biz.dal.page.LiveGoodsMapperQueryInfo;
 import com.ym.mec.biz.service.ImLiveBroadcastRoomService;
 import com.ym.mec.biz.service.LiveGoodsMapperService;
+import com.ym.mec.biz.service.LiveGoodsService;
 import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.common.entity.ImRoomMessage;
 import com.ym.mec.common.exception.BizException;
@@ -16,6 +17,7 @@ import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
 import com.ym.mec.im.ImFeignService;
 import com.ym.mec.util.collection.MapUtil;
+import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -26,11 +28,16 @@ import java.util.*;
 public class LiveGoodsMapperServiceImpl extends BaseServiceImpl<Integer, LiveGoodsMapper>  implements LiveGoodsMapperService {
 	
 	@Autowired
+	private LiveGoodsService liveGoodsService;
+	@Autowired
 	private LiveGoodsMapperDao liveGoodsMapperDao;
 	@Autowired
 	private ImFeignService imFeignService;
 	@Autowired
 	private ImLiveBroadcastRoomService imLiveBroadcastRoomService;
+	@Autowired
+	private RedissonClient redissonClient;
+
 
 	@Override
 	public BaseDAO<Integer, LiveGoodsMapper> getDAO() {
@@ -41,9 +48,6 @@ public class LiveGoodsMapperServiceImpl extends BaseServiceImpl<Integer, LiveGoo
 	@Transactional(rollbackFor = Exception.class)
     public void add(List<LiveGoodsMapper> liveGoodsMappers) {
 		liveGoodsMapperDao.batchInsert(liveGoodsMappers);
-//		liveGoodsMapperDao.insert(liveGoodsMapper);
-//		通知上架
-//		if (liveGoodsMapper.getStatus()) this.upGoods(liveGoodsMapper.getGoodsId(),liveGoodsMapper.getLiveId());
     }
 
 	@Override
@@ -53,8 +57,10 @@ public class LiveGoodsMapperServiceImpl extends BaseServiceImpl<Integer, LiveGoo
 		ImLiveBroadcastRoom imLiveBroadcastRoom = Optional
 				.of(imLiveBroadcastRoomService.getBaseMapper().selectOne(new QueryWrapper<ImLiveBroadcastRoom>().eq("room_uid_",liveId))).
 				orElseThrow(() -> new RuntimeException("直播间不存在"));
-		//通知直播间商品上架
+		//通知直播间商品信息变更
 		this.publishRoomMsg(imLiveBroadcastRoom);
+		//商品上架,更新缓存
+		liveGoodsService.initGoodsStockCache(liveGoodsId,liveId);
 	}
 
 	@Override
@@ -110,8 +116,15 @@ public class LiveGoodsMapperServiceImpl extends BaseServiceImpl<Integer, LiveGoo
 		}
 		//下架直播间商品
 		liveGoodsMapperDao.updateStatus(liveId,liveGoodsId,false);
-		//通知直播间,商品下架
+		//通知直播间,商品信息变更
 		this.publishRoomMsg(imLiveBroadcastRoom);
+		//商品下架后,将缓存的库存设置为0
+		redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_STOCK_CACHE_KEY + liveId + liveGoodsId).set(0);
+		//如果下架的是免费的直播课商品,清空购买的学员的缓存记录
+		if(liveGoodsId.equals(2)){
+			//删除当前直播间免费直播课的购买记录缓存
+			redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_ZERO_CACHE_KEY + liveId).delete();
+		}
 	}
 
 	@Override
@@ -121,7 +134,7 @@ public class LiveGoodsMapperServiceImpl extends BaseServiceImpl<Integer, LiveGoo
 		if(liveGoodsMappers.size()>0){
 			//下架直播间商品
 			liveGoodsMapperDao.updateStatus(null,liveGoodsId,false);
-			//通知直播间,商品下架
+			//通知直播间,商品信息变更
 			for (LiveGoodsMapper liveGoodsMapper : liveGoodsMappers) {
 				ImLiveBroadcastRoom imLiveBroadcastRoom = Optional
 						.of(imLiveBroadcastRoomService.getBaseMapper().selectOne(new QueryWrapper<ImLiveBroadcastRoom>().eq("room_uid_",liveGoodsMapper.getLiveId()))).

+ 109 - 2
mec-biz/src/main/java/com/ym/mec/biz/service/impl/LiveGoodsServiceImpl.java

@@ -1,16 +1,23 @@
 package com.ym.mec.biz.service.impl;
 
 import com.ym.mec.biz.dal.dao.LiveGoodsDao;
+import com.ym.mec.biz.dal.dto.RedisKeyConstant;
 import com.ym.mec.biz.dal.entity.LiveGoods;
 import com.ym.mec.biz.service.LiveGoodsMapperService;
 import com.ym.mec.biz.service.LiveGoodsService;
 import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.common.exception.BizException;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
+import org.redisson.api.RBucket;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiConsumer;
 
 @Service
 public class LiveGoodsServiceImpl extends BaseServiceImpl<Integer, LiveGoods>  implements LiveGoodsService {
@@ -19,6 +26,8 @@ public class LiveGoodsServiceImpl extends BaseServiceImpl<Integer, LiveGoods>  i
 	private LiveGoodsDao liveGoodsDao;
 	@Autowired
 	private LiveGoodsMapperService liveGoodsMapperService;
+	@Autowired
+	private RedissonClient redissonClient;
 
 	@Override
 	public BaseDAO<Integer, LiveGoods> getDAO() {
@@ -29,12 +38,16 @@ public class LiveGoodsServiceImpl extends BaseServiceImpl<Integer, LiveGoods>  i
 	@Transactional(rollbackFor = Exception.class)
     public void updateLiveGoods(LiveGoods liveGoods) {
 		Optional.of(liveGoodsDao.get(liveGoods.getId())).orElseThrow(() -> new RuntimeException("商品信息不存在"));
+		//如果商品已在直播间上架,那么不允许变更商品信息
+		if (liveGoodsMapperService.findByLiveGoodsIdAndStatus(liveGoods.getId(),true).size() > 0) {
+			throw new BizException("商品已在直播间上架,不能修改");
+		}
 		//下架直播间商品,并通知直播间
 //		if (!liveGoods.getStatus()) liveGoodsMapperService.downGoods(liveGoods.getId());
 		//更新商品信息
 		liveGoodsDao.update(liveGoods);
 		//通知直播间
-		liveGoodsMapperService.downGoods(liveGoods.getId());
+//		liveGoodsMapperService.downGoods(liveGoods.getId());
 	}
 
 	@Override
@@ -42,8 +55,102 @@ public class LiveGoodsServiceImpl extends BaseServiceImpl<Integer, LiveGoods>  i
 	public void deleteLiveGoods(Integer goodsId) {
 		//如果商品没有被直播间使用,则删除商品
 		if (liveGoodsMapperService.findByLiveGoodsIdAndStatus(goodsId,null).size() > 0) {
-			throw new RuntimeException("商品已被直播间使用,不能删除");
+			throw new BizException("商品已被直播间使用,不能删除");
 		}
 		liveGoodsDao.delete(goodsId);
 	}
+
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void initGoodsStockCache(Integer liveGoodsId, String liveId) {
+		//更新缓存
+		LiveGoods liveGoods = liveGoodsDao.getLock(liveGoodsId);
+		if (liveGoods == null) throw new BizException("商品不存在");
+		redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_STOCK_CACHE_KEY + liveId + liveGoodsId).set(liveGoods.getStockCount(),1, TimeUnit.DAYS);
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void addGoodsStock(Integer liveGoodsId, String liveId) {
+		liveGoodsDao.addStock(liveGoodsId);
+//		RBucket<Integer> bucket = redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_STOCK_CACHE_KEY + liveId + liveGoodsId);
+//		boolean exists = bucket.isExists();
+//		if (exists) {
+//			Integer frozenStock = bucket.get();
+//			bucket.set(++frozenStock);
+//		}else {
+//			bucket.set(1);
+//		}
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void reduceGoodsStock(Integer liveGoodsId, String liveId) {
+		int i = liveGoodsDao.reduceStock(liveGoodsId);
+		if (i == 0) throw new BizException("商品库存不足");
+//		RBucket<Integer> bucket = redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_STOCK_CACHE_KEY + liveId + liveGoodsId);
+//		boolean exists = bucket.isExists();
+//		if (exists) {
+//			Integer stock = bucket.get() - 1;
+//			if (stock < 0) {
+//				throw new BizException("哎呀,手慢了,商品已经卖完了");
+//			}else if(stock == 0){
+//				//如果库存为0,则定时删除缓存
+//				bucket.set(stock,1,TimeUnit.HOURS);
+//			}else {
+//				bucket.set(stock);
+//			}
+//		}else {
+//			LiveGoods liveGoods = liveGoodsDao.getLock(liveGoodsId);
+//			redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_STOCK_CACHE_KEY + liveId + liveGoodsId).set(liveGoods.getStockCount(),1, TimeUnit.DAYS);
+//		}
+//		//增加冻结库存
+//		this.addGoodsFreezeStock(liveGoodsId,liveId);
+	}
+
+	@Override
+	public void addGoodsFreezeStock(Integer liveGoodsId, String liveId) {
+		RBucket<Integer> bucket = redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_FROZEN_CACHE_KEY + liveId + liveGoodsId);
+		boolean exists = bucket.isExists();
+		if (exists) {
+			Integer frozenStock = bucket.get();
+			bucket.set(++frozenStock);
+		}else {
+			bucket.set(1);
+		}
+	}
+
+	@Override
+	public void reduceGoodsFreezeStock(Integer liveGoodsId, String liveId) {
+		RBucket<Integer> bucket = redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_FROZEN_CACHE_KEY + liveId + liveGoodsId);
+		boolean exists = bucket.isExists();
+		if (exists) {
+			Integer frozenStock = bucket.get() - 1;
+			if (frozenStock < 0) {
+				throw new BizException("订单库存扣减失败");
+			}else if(frozenStock == 0){
+				//如果冻结库存为0,则定时删除缓存
+				bucket.set(frozenStock,1,TimeUnit.HOURS);
+			}else {
+				bucket.set(frozenStock);
+			}
+		}else {
+			throw new BizException("订单库存扣减失败");
+		}
+	}
+
+	public void stockLock(String lockKey, BiConsumer<Integer,String> consumer, Integer liveGoodsId, String liveId) {
+		RLock lock = redissonClient.getLock(lockKey);
+		try{
+			lock.lock();
+			consumer.accept(liveGoodsId,liveId);
+		}catch(Exception e){
+			e.printStackTrace();
+		}finally {
+			lock.unlock();
+		}
+
+	}
+
 }

+ 50 - 18
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MemberRankSettingServiceImpl.java

@@ -6,6 +6,7 @@ import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.*;
 import com.ym.mec.biz.dal.dto.Cloud2022ActivityDto;
 import com.ym.mec.biz.dal.dto.MemberPayParamDto;
+import com.ym.mec.biz.dal.dto.RedisKeyConstant;
 import com.ym.mec.biz.dal.entity.*;
 import com.ym.mec.biz.dal.enums.*;
 import com.ym.mec.biz.service.*;
@@ -84,6 +85,10 @@ public class MemberRankSettingServiceImpl extends BaseServiceImpl<Integer, Membe
     private MemberFeeSettingService memberFeeSettingService;
     @Autowired
     private TeacherDao teacherDao;
+    @Autowired
+    private LiveGoodsService liveGoodsService;
+    @Autowired
+    private TempBuyFreeLiveTheoryCourseDao tempBuyFreeLiveTheoryCourseDao;
 
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
@@ -228,22 +233,6 @@ public class MemberRankSettingServiceImpl extends BaseServiceImpl<Integer, Membe
     @Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)
     public HttpResponseResult activeBuy(MemberPayParamDto memberPayParamDto) throws Exception {
         SysUser sysUser = Optional.of(sysUserFeignService.queryUserInfo()).orElseThrow(()-> new BizException("请登录"));
-        String activeConfig = sysConfigDao.findConfigValue("cloud_teacher_active_config");
-        List<Cloud2022ActivityDto> cloud2022ActivityDtos = JSONArray.parseArray(activeConfig, Cloud2022ActivityDto.class);
-        Cloud2022ActivityDto activityDto = cloud2022ActivityDtos.stream().filter(e -> e.getOrganId().contains(sysUser.getOrganId().toString())).findFirst().get();
-        if(Objects.isNull(activityDto)){
-            throw new BizException("当前分部暂未开通活动");
-        }
-        //是否还有购买资格
-        Integer activityId = Integer.parseInt(activityDto.getActivityId());
-        VipGroupActivity vipGroupActivity = Optional.of(vipGroupActivityDao.get(activityId)).orElseThrow(()-> new BizException("活动不存在"));
-        if(vipGroupActivity.getStudentMaxUsedTimes() != -1){
-            //获取活动购买次数
-            int activityBuyNum = activityUserMapperDao.countActivityBuyNum(vipGroupActivity.getId(),sysUser.getId());
-            if(activityBuyNum >= vipGroupActivity.getStudentMaxUsedTimes()){
-                throw new BizException("您已达到购买次数上限");
-            }
-        }
         //判断用户是否已存在订单
         List<StudentPaymentOrder> memberIngOrders = studentPaymentOrderService.queryByCondition(GroupType.ACTIVITY,null,sysUser.getId(), DealStatusEnum.ING,OrderTypeEnum.MEMBER);
         if (CollectionUtils.isNotEmpty(memberIngOrders)) {
@@ -252,13 +241,56 @@ public class MemberRankSettingServiceImpl extends BaseServiceImpl<Integer, Membe
                 return result;
             }
         }
+        //判断当前商品是否可以购买(库存、上架状态、是否购买过)
+        //如果是云教练商品,那么只能购买一次、如果是免费直播课,那么每次上架只能买一次,总共只能买2次
+        if(memberPayParamDto.getLiveGoodsId() == 1){
+            String activeConfig = sysConfigDao.findConfigValue("cloud_teacher_active_config");
+            List<Cloud2022ActivityDto> cloud2022ActivityDtos = JSONArray.parseArray(activeConfig, Cloud2022ActivityDto.class);
+            Cloud2022ActivityDto activityDto = cloud2022ActivityDtos.stream().filter(e -> e.getOrganId().contains(sysUser.getOrganId().toString())).findFirst().get();
+            if(Objects.isNull(activityDto)){
+                throw new BizException("当前分部暂未开通活动");
+            }
+            //是否还有购买资格
+            Integer activityId = Integer.parseInt(activityDto.getActivityId());
+            VipGroupActivity vipGroupActivity = Optional.of(vipGroupActivityDao.get(activityId)).orElseThrow(()-> new BizException("活动不存在"));
+            if(vipGroupActivity.getStudentMaxUsedTimes() != -1){
+                //获取活动购买次数
+                int activityBuyNum = activityUserMapperDao.countActivityBuyNum(vipGroupActivity.getId(),sysUser.getId());
+                if(activityBuyNum >= vipGroupActivity.getStudentMaxUsedTimes()){
+                    throw new BizException("您已达到购买次数上限");
+                }
+            }
+            //扣减库存
+            liveGoodsService.reduceGoodsStock(memberPayParamDto.getLiveGoodsId(),memberPayParamDto.getLiveId());
+        } else if (memberPayParamDto.getLiveGoodsId() == 2){
+            RBucket<List<Integer>> bucket = redissonClient.getBucket(RedisKeyConstant.LIVE_GOODS_ZERO_CACHE_KEY + memberPayParamDto.getLiveId());
+            List<Integer> list = bucket.get();
+            //当前用户是否购买过免费直播课
+            if(list.contains(sysUser.getId())){
+                throw new BizException("您已购买过本轮免费直播课");
+            }
+            //购买次数是否超过2次
+            int count = tempBuyFreeLiveTheoryCourseDao.countByUserId(sysUser.getId());
+            if(count >= 2){
+                throw new BizException("免费直播课已达到购买次数上限");
+            }
+            //扣减库存
+            liveGoodsService.reduceGoodsStock(memberPayParamDto.getLiveGoodsId(),memberPayParamDto.getLiveId());
+            list.add(sysUser.getId());
+            bucket.set(list);
+            //保存购买记录
+            tempBuyFreeLiveTheoryCourseDao.insert(new TempBuyFreeLiveTheoryCourse(sysUser.getId()));
+            return BaseController.succeed();
+        }else {
+            throw new BizException("当前商品不可购买");
+        }
         //优惠券使用范围
         String[] checkCoupon = CouponDetailTypeEnum.getAllowType(MEMBER);
         //校验优惠券
-        StudentPaymentOrder studentPaymentOrder = sysCouponCodeService.use(memberPayParamDto.getCouponIdList(), vipGroupActivity.getMarketPrice(), true, checkCoupon);
+        StudentPaymentOrder studentPaymentOrder = sysCouponCodeService.use(memberPayParamDto.getCouponIdList(),BigDecimal.ZERO, true, checkCoupon);
         studentPaymentOrder.setUserId(sysUser.getId());
         studentPaymentOrder.setOrganId(sysUser.getOrganId());
-        studentPaymentOrder.setMemo("小小训练营活动购买");
+        studentPaymentOrder.setMemo("小小训练营云教练购买");
         studentPaymentOrder.setGroupType(GroupType.ACTIVITY);
         Map<String, Object> result = getMap(memberPayParamDto.getAmount(), memberPayParamDto.getUseBalancePayment(),studentPaymentOrder);
         return BaseController.succeed(result);

+ 4 - 1
mec-biz/src/main/resources/config/mybatis/ImLiveBroadcastRoomDataMapper.xml

@@ -35,7 +35,10 @@
                r.live_remark_              AS liveRemark,
                ifnull(a.total_user_num_, 0) AS totalLookNum,
                ifnull(a.like_num_, 0)      as totalLikeNum,
-               ifnull(a.live_time_, 0)     as totalLiveTime
+               ifnull(a.live_time_, 0)     as totalLiveTime,
+               r.live_start_time_      as liveStartTime,
+               r.live_end_time_      as liveEndTime,
+               r.live_state_      as liveState
         from im_live_broadcast_room_data as a
                  left join im_live_broadcast_room AS r on a.room_uid_ = r.room_uid_
                  left join sys_user AS b on r.speaker_id_ = b.id_

+ 11 - 2
mec-biz/src/main/resources/config/mybatis/LiveGoodsMapper.xml

@@ -40,7 +40,10 @@
 		VALUES(#{name},#{image},#{stockCount},#{sellCount},#{currentPrice},
 		       #{originalPrice},#{goodsDetailUrl},#{desc},NOW(),NOW(),#{tenantId})
 	</insert>
-	
+	<insert id="addStock">
+		UPDATE live_goods SET stock_count_ = stock_count_ + 1 WHERE id_ = #{liveGoodsId}
+	</insert>
+
 	<!-- 根据主键查询一条记录 -->
 	<update id="update" parameterType="com.ym.mec.biz.dal.entity.LiveGoods">
 		UPDATE live_goods <set>
@@ -74,7 +77,10 @@
 		update_time_ = NOW()
 	</set> WHERE id_ = #{id}
 	</update>
-	
+	<update id="reduceStock">
+		UPDATE live_goods SET stock_count_ = stock_count_ - 1 WHERE id_ = #{liveGoodsId} AND stock_count_ > 0
+	</update>
+
 	<!-- 根据主键删除一条记录 -->
 	<delete id="delete" >
 		DELETE FROM live_goods WHERE id_ = #{id} 
@@ -100,4 +106,7 @@
 		SELECT COUNT(*) FROM live_goods
 		<include refid="queryPageSql" />
 	</select>
+	<select id="getLock" resultMap="LiveGoods">
+		SELECT * FROM live_goods WHERE id_ = #{id} FOR UPDATE LIMIT 1
+	</select>
 </mapper>

+ 60 - 0
mec-biz/src/main/resources/config/mybatis/TempBuyFreeLiveTheoryCourseMapper.xml

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<!--
+这个文件是自动生成的。
+不要修改此文件。所有改动将在下次重新自动生成时丢失。
+-->
+<mapper namespace="com.ym.mec.biz.dal.dao.TempBuyFreeLiveTheoryCourseDao">
+	
+	<resultMap type="com.ym.mec.biz.dal.entity.TempBuyFreeLiveTheoryCourse" id="TempBuyFreeLiveTheoryCourse">
+		<result column="id_" property="id" />
+		<result column="user_id_" property="userId" />
+		<result column="create_time_" property="createTime" />
+		<result column="update_time_" property="updateTime" />
+	</resultMap>
+	
+	<!-- 根据主键查询一条记录 -->
+	<select id="get" resultMap="TempBuyFreeLiveTheoryCourse" >
+		SELECT * FROM temp_buy_free_live_theory_course WHERE id_ = #{id} 
+	</select>
+	
+	<!-- 全查询 -->
+	<select id="findAll" resultMap="TempBuyFreeLiveTheoryCourse">
+		SELECT * FROM temp_buy_free_live_theory_course ORDER BY id_
+	</select>
+	
+	<!-- 向数据库增加一条记录 -->
+	<insert id="insert" parameterType="com.ym.mec.biz.dal.entity.TempBuyFreeLiveTheoryCourse" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+		INSERT INTO temp_buy_free_live_theory_course (user_id_,create_time_,update_time_) VALUES(#{userId},NOW(),NOW())
+	</insert>
+	
+	<!-- 根据主键查询一条记录 -->
+	<update id="update" parameterType="com.ym.mec.biz.dal.entity.TempBuyFreeLiveTheoryCourse">
+		UPDATE temp_buy_free_live_theory_course <set>
+		<if test="userId != null">
+		user_id_ = #{userId},
+		</if>
+		<if test="updateTime != null">
+		update_time_ = #{updateTime},
+		</if>
+		</set> WHERE id_ = #{id}
+	</update>
+	
+	<!-- 根据主键删除一条记录 -->
+	<delete id="delete" >
+		DELETE FROM temp_buy_free_live_theory_course WHERE id_ = #{id} 
+	</delete>
+	
+	<!-- 分页查询 -->
+	<select id="queryPage" resultMap="TempBuyFreeLiveTheoryCourse" parameterType="map">
+		SELECT * FROM temp_buy_free_live_theory_course ORDER BY id_ <include refid="global.limit"/>
+	</select>
+	
+	<!-- 查询当前表的总记录数 -->
+	<select id="queryCount" resultType="int">
+		SELECT COUNT(*) FROM temp_buy_free_live_theory_course
+	</select>
+	<select id="countByUserId" resultType="java.lang.Integer">
+		SELECT COUNT(user_id_) FROM temp_buy_free_live_theory_course WHERE user_id_ = #{userId}
+	</select>
+</mapper>