Browse Source

Merge branch 'specific_drawType'

zoujiajian 3 years ago
parent
commit
0e199c58b6
26 changed files with 630 additions and 148 deletions
  1. 15 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 23 0
      netflix-dao/src/main/java/com/cyksj/mapper/market/draw/LuckyDrawSpecificChanceMapper.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/market/draw/LuckyDrawSpecificChanceRecordMapper.java
  4. 17 0
      netflix-dao/src/main/java/com/cyksj/model/entity/LuckyDraw.java
  5. 4 0
      netflix-dao/src/main/java/com/cyksj/model/entity/LuckyDrawRecord.java
  6. 21 0
      netflix-dao/src/main/java/com/cyksj/model/entity/LuckyDrawSpecificChance.java
  7. 26 0
      netflix-dao/src/main/java/com/cyksj/model/entity/LuckyDrawSpecificChanceRecord.java
  8. 3 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/GroupsRelationView.java
  9. 6 1
      netflix-dao/src/main/java/com/cyksj/model/request/LuckyDrawReq.java
  10. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/LuckyDrawRecordView.java
  11. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/LuckyDrawView.java
  12. 0 2
      netflix-service/src/main/java/com/cyksj/service/corp/CorpService.java
  13. 48 3
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpEventActionServiceImpl.java
  14. 0 29
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java
  15. 2 3
      netflix-service/src/main/java/com/cyksj/service/mange/coupon/CouponCommonService.java
  16. 2 43
      netflix-service/src/main/java/com/cyksj/service/mange/coupon/impl/CouponCommonServiceImpl.java
  17. 16 1
      netflix-service/src/main/java/com/cyksj/service/market/MarketFrontService.java
  18. 8 0
      netflix-service/src/main/java/com/cyksj/service/market/draw/impl/LuckyDrawServiceImpl.java
  19. 264 49
      netflix-service/src/main/java/com/cyksj/service/market/impl/MarketFrontServiceImpl.java
  20. 39 4
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  21. 2 0
      netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java
  22. 36 4
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  23. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java
  24. 45 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java
  25. 27 3
      netflix-web/src/main/java/com/cyksj/web/controller/market/LuckyDrawFrontController.java
  26. 0 4
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

+ 15 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -30,4 +30,19 @@ public interface Constant {
 	 * 默认头像
 	 */
 	String DEFAULT_HEAD_IMG = "https://cdn.sxfoundation.com/picture/f6ee11101c4f5f0bc48d88aca7a5dbfd-1666945673391.png";
+
+	/**
+	 * 普通奖池积分配置key
+	 */
+	String LOTTERY_POINTS_LIMIT = "lottery_points_limit";
+
+	/**
+	 * 特定奖池平台配置key
+	 */
+	String LOTTERY_SPECIFIC_GOODS = "lottery_specific_goods";
+
+	/**
+	 * 特定订单有效时间
+	 */
+	String LOTTERY_SPECIFIC_ORDER_EFFECTIVE_TIME = "lottery_specific_order_effective_time";
 }

+ 23 - 0
netflix-dao/src/main/java/com/cyksj/mapper/market/draw/LuckyDrawSpecificChanceMapper.java

@@ -0,0 +1,23 @@
+package com.cyksj.mapper.market.draw;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.LuckyDrawSpecificChance;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+/*
+ *项目名: netflix
+ *文件名: LuckyDrawSpecificChanceMapper
+ *创建者: JavaZou
+ *创建时间:2023/2/20 15:36
+ */
+public interface LuckyDrawSpecificChanceMapper extends BaseMapper<LuckyDrawSpecificChance> {
+	@Update("update lucky_draw_specific_chance set num = num - 1 where user_id = #{userId} and num = #{num} and num > 0")
+	Integer subChanceNum(@Param("userId") Long userId, @Param("num") Integer num);
+
+	@Update("update lucky_draw_specific_chance set num = num - 1 where user_id = #{userId} and num > 0")
+	Integer subChanceNumNoRepeat(@Param("userId") Long userId);
+
+	@Update("update lucky_draw_specific_chance set num = num + 1 where user_id = #{userId} and num >= 0")
+	void addChanceNum(Long userId);
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/market/draw/LuckyDrawSpecificChanceRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.market.draw;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.LuckyDrawSpecificChanceRecord;
+
+/*
+ *项目名: netflix
+ *文件名: LuckyDrawSpecificChanceRecordMapper
+ *创建者: JavaZou
+ *创建时间:2023/2/20 15:36
+ */
+public interface LuckyDrawSpecificChanceRecordMapper extends BaseMapper<LuckyDrawSpecificChanceRecord> {
+}

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/LuckyDraw.java

@@ -30,6 +30,8 @@ public class LuckyDraw extends BaseEntity {
 
 	private Long skuId;
 
+	private Integer days;
+
 	private Integer cost;
 
 	private Integer num;
@@ -42,6 +44,8 @@ public class LuckyDraw extends BaseEntity {
 
 	private String picture;
 
+	private LuckyDraw.DrawType drawType;
+
 	private Boolean status;
 
 	private Boolean deleted;
@@ -52,6 +56,7 @@ public class LuckyDraw extends BaseEntity {
 		coupon("优惠券"),
 		realGoods("实物"),
 		virtualGoods("虚物"),
+		duration("车票时长"),
 		;
 		String desc;
 
@@ -59,4 +64,16 @@ public class LuckyDraw extends BaseEntity {
 			this.desc = desc;
 		}
 	}
+
+	@Getter
+	public enum DrawType {
+		normal("普通奖池"),
+		specific("特定奖池"),
+		;
+		String desc;
+
+		DrawType(String desc) {
+			this.desc = desc;
+		}
+	}
 }

+ 4 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/LuckyDrawRecord.java

@@ -30,6 +30,8 @@ public class LuckyDrawRecord extends BaseEntity{
 
 	private Long skuId;
 
+	private Integer days;
+
 	private Integer cost;
 
 	/**
@@ -39,6 +41,8 @@ public class LuckyDrawRecord extends BaseEntity{
 
 	private String picture;
 
+	private LuckyDraw.DrawType drawType;
+
 	private Status status;
 
 	@Getter

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/LuckyDrawSpecificChance.java

@@ -0,0 +1,21 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: LuckyDrawSpecificChance
+ *创建者: JavaZou
+ *创建时间:2023/2/20 15:34
+ */
+@Getter
+@Setter
+public class LuckyDrawSpecificChance extends BaseEntity{
+	private Long userId;
+
+	/**
+	 * 抽奖次数
+	 */
+	private Integer num;
+}

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/LuckyDrawSpecificChanceRecord.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: LuckyDrawSpecificChanceRecord
+ *创建者: JavaZou
+ *创建时间:2023/2/20 15:35
+ */
+@Getter
+@Setter
+public class LuckyDrawSpecificChanceRecord extends BaseEntity{
+	private Long userId;
+
+	private Long orderId;
+
+	private Long goodsId;
+
+	private Long skuId;
+
+	private Date refundTime;
+}

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/GroupsRelationView.java

@@ -36,6 +36,9 @@ public class GroupsRelationView {
     @DbField("g.id")
     private Long goodsId;
 
+    @DbField("g.logo")
+    private String logo;
+
     @DbField("gr.groups_id")
     private Long groupsId;
 

+ 6 - 1
netflix-dao/src/main/java/com/cyksj/model/request/LuckyDrawReq.java

@@ -18,9 +18,14 @@ public class LuckyDrawReq {
 	/**
 	 * 地址id
 	 */
-	@NotNull
 	private Long addressId;
 
 	@NotNull
 	private Long recordId;
+
+	/**
+	 * 座位号
+	 */
+	@NotNull
+	private Long relationId;
 }

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/views/LuckyDrawRecordView.java

@@ -69,6 +69,12 @@ public class LuckyDrawRecordView {
 	@DbField("lr.cost")
 	private Integer cost;
 
+	@DbField("lr.days")
+	private Integer days;
+
+	@DbField("lr.draw_type")
+	private LuckyDraw.DrawType drawType;
+
 	@DbField("lr.status")
 	private LuckyDrawRecord.Status status;
 

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/views/LuckyDrawView.java

@@ -71,12 +71,18 @@ public class LuckyDrawView {
 	@DbField("ld.probability")
 	private BigDecimal probability;
 
+	@DbField("ld.days")
+	private Integer days;
+
 	@DbField("ld.num")
 	private Integer num;
 
 	@DbField("ld.picture")
 	private String picture;
 
+	@DbField("ld.draw_type")
+	private LuckyDraw.DrawType drawType;
+
 	@DbField("ld.status")
 	private Boolean status;
 

+ 0 - 2
netflix-service/src/main/java/com/cyksj/service/corp/CorpService.java

@@ -28,6 +28,4 @@ public interface CorpService {
 	String getAgentJsTicket(String corpId, String agentId) throws Exception;
 
 	YHLXUserDetailView getUserDetailView(String externalUserid, String corpId) throws Exception;
-
-	Boolean isJoinCorpWx(Long userId, Boolean isJoin);
 }

+ 48 - 3
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpEventActionServiceImpl.java

@@ -1,8 +1,13 @@
 package com.cyksj.service.corp.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.util.Jsons;
 import com.cyksj.config.corp.WeChatCorpFactory;
+import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.corp.*;
 import com.cyksj.model.entity.*;
@@ -12,10 +17,13 @@ import com.cyksj.model.response.CorpExternalContactInfo;
 import com.cyksj.model.response.CorpUserExternalTagGroupList;
 import com.cyksj.model.response.ExternalContact;
 import com.cyksj.model.response.FollowedUser;
-import com.cyksj.service.corp.CorpService;
 import com.cyksj.service.corp.WxCorpOps;
 import com.cyksj.service.corp.msg.CorpEventActionService;
+import com.cyksj.service.market.MarketFrontService;
+import com.cyksj.service.relation.GroupRelationFrontService;
+import com.cyksj.service.sys.SysConfigService;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -31,6 +39,7 @@ import java.util.stream.Stream;
  */
 @Service
 @RequiredArgsConstructor
+@Slf4j
 public class CorpEventActionServiceImpl implements CorpEventActionService {
 
 	private final WxCorpOps wxCorpOps;
@@ -49,7 +58,13 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 
 	private final CorpUserAuthMapper corpUserAuthMapper;
 
-	private final CorpService corpService;
+	private final GroupRelationFrontService groupRelationFrontService;
+
+	private final SysConfigService sysConfigService;
+
+	private final OrderDonMapper orderDonMapper;
+
+	private final MarketFrontService marketFrontService;
 
 	/**
 	 * 客户添加成员
@@ -82,7 +97,9 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 			if (user != null) {
 				corpUser.setUserId(user.getId());
 				//加入企业微信后发放优惠券
-				corpService.isJoinCorpWx(user.getId(), true);
+				groupRelationFrontService.isJoinCorpWx(user.getId(), true, false);
+				//发放抽奖机会
+				sendSpecificChanceNum(user.getId());
 			}
 			corpUserMapper.insert(corpUser);
 		} else {
@@ -113,6 +130,34 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 		return null;
 	}
 
+	private void sendSpecificChanceNum(Long userId) throws Exception {
+		SysConfig lottery_specific_goods = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_SPECIFIC_GOODS).last("limit 1"));
+		if (lottery_specific_goods == null) {
+			return;
+		}
+		String sysValue = lottery_specific_goods.getSysValue();
+		if (sysValue == null) {
+			return;
+		}
+		List<Long> goodsIdList = Jsons.parseList(sysValue, Long.class);
+		SysConfig timeSys = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_SPECIFIC_ORDER_EFFECTIVE_TIME).last("limit 1"));
+		Integer effectiveTime = timeSys == null ? 1 : Integer.parseInt(Optional.ofNullable(timeSys.getSysValue()).orElse("1"));
+		List<OrderDon> orderDons = orderDonMapper.selectList(Wrappers.lambdaQuery(OrderDon.class)
+				.eq(OrderDon::getUserId, userId)
+				.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
+				.ge(OrderDon::getCreatedTime, DateUtil.offsetDay(DateTime.now(), -effectiveTime))
+				.select(OrderDon::getId, OrderDon::getGoodsId, OrderDon::getSkuId, OrderDon::getUserId));
+		orderDons.forEach(order -> {
+			if (goodsIdList.isEmpty() || goodsIdList.contains(order.getGoodsId())) {
+				try {
+					marketFrontService.addSpecificChanceNumNoWxCorp(order.getUserId(), order.getId(), order.getGoodsId(), order.getSkuId());
+				} catch (Exception e) {
+					log.error("加入企业微信发放特定抽奖机会错误,orderId:{},e:{}", order.getId(), e);
+				}
+			}
+		});
+	}
+
 	/**
 	 * 修改外部联系人的备注、手机号或标签
 	 */

+ 0 - 29
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java

@@ -354,33 +354,4 @@ public class CorpServiceImpl implements CorpService {
 		}
 		return view;
 	}
-
-	@Override
-	public Boolean isJoinCorpWx(Long userId, Boolean isJoin) {
-		if (!isJoin) {
-			User user = userMapper.selectById(userId);
-			if (StrUtil.isEmpty(user.getUnionid())) {
-				return true;
-			}
-			CorpUser corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class)
-					.ne(CorpUser::getUnionid, "")
-					.eq(CorpUser::getUnionid, user.getUnionid())
-					.last("limit 1")
-					.select(CorpUser::getId)
-			);
-			if (corpUser == null) {
-				return false;
-			}
-		}
-		//用户是否买了奈飞车票
-		Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder()
-				.field(RenewalView::getUserId, userId)
-				.field(RenewalView::getGoodsId, 1)
-				.field(RenewalView::getStatus, List.of("validity", "overdue")).op(Operator.InList)
-				.build());
-		if (number.intValue() > 0) {
-			couponCommonService.sendCouponToUser(userId, 34l, 0l, 0l, 0l, CouponUser.Channel.manual);
-		}
-		return true;
-	}
 }

+ 2 - 3
netflix-service/src/main/java/com/cyksj/service/mange/coupon/CouponCommonService.java

@@ -3,7 +3,6 @@ package com.cyksj.service.mange.coupon;
 import com.cyksj.model.entity.Coupon;
 import com.cyksj.model.entity.CouponDistributePopularize;
 import com.cyksj.model.entity.CouponUser;
-import com.cyksj.model.request.CorpCouponSendReq;
 import com.cyksj.model.request.CouponActiveReq;
 import com.cyksj.model.request.CouponDistributeReq;
 
@@ -59,10 +58,10 @@ public interface CouponCommonService {
 	/**
 	 * 发放优惠券
 	 */
-	void corpSendCoupon(CorpCouponSendReq corpCouponSendReq) throws Exception;
+	void corpSendCoupon(String unionid, Long couponId) throws Exception;
 
 	/**
 	 * 发放优惠券至用户
 	 */
 	Boolean sendCouponToUser(Long userId, Long couponId, Long couponActiveId, Long recommendId, Long popularizeId, CouponUser.Channel channel);
-}
+}

+ 2 - 43
netflix-service/src/main/java/com/cyksj/service/mange/coupon/impl/CouponCommonServiceImpl.java

@@ -1,23 +1,16 @@
 package com.cyksj.service.mange.coupon.impl;
 
 import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
-import com.cyksj.config.corp.WeChatCorpFactory;
-import com.cyksj.config.corp.YHLXWxCorpConfig;
 import com.cyksj.mapper.GoodsDonMapper;
 import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.UserMapper;
-import com.cyksj.mapper.corp.CorpUserAuthMapper;
-import com.cyksj.mapper.corp.CorpUserMapper;
 import com.cyksj.mapper.manage.coupon.*;
 import com.cyksj.model.entity.*;
-import com.cyksj.model.request.CorpCouponSendReq;
 import com.cyksj.model.request.CouponActiveReq;
 import com.cyksj.model.request.CouponDistributeReq;
-import com.cyksj.service.corp.msg.CorpEventActionService;
 import com.cyksj.service.coupon.CouponFontService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import lombok.RequiredArgsConstructor;
@@ -52,12 +45,6 @@ public class CouponCommonServiceImpl implements CouponCommonService {
 
 	private final CouponSkuMapper couponSkuMapper;
 
-	private final CorpUserMapper corpUserMapper;
-
-	private final CorpEventActionService corpEventActionService;
-
-	private final YHLXWxCorpConfig yhlXWxCorpConfig;
-
 	private final UserMapper userMapper;
 
 	private final CouponUserMapper couponUserMapper;
@@ -66,8 +53,6 @@ public class CouponCommonServiceImpl implements CouponCommonService {
 
 	private final CouponFontService couponFontService;
 
-	private final CorpUserAuthMapper corpUserAuthMapper;
-
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public void saveCoupon(Coupon coupon) throws Exception {
@@ -164,43 +149,17 @@ public class CouponCommonServiceImpl implements CouponCommonService {
 	}
 
 	@Override
-	public void corpSendCoupon(CorpCouponSendReq corpCouponSendReq) throws Exception {
-		WxCorpApp wxCorpApp = WeChatCorpFactory.getCorpConfigStrategy(corpCouponSendReq.getCorpId());
-		String externalUserId = corpCouponSendReq.getExternalUserId();
-		LambdaQueryWrapper<CorpUserAuth> corpUserAuthWrapper = Wrappers.lambdaQuery(CorpUserAuth.class)
-				.eq(CorpUserAuth::getExternalUserid, externalUserId)
-				.eq(CorpUserAuth::getWxCorpId, wxCorpApp.getId()).last("limit 1");
-		CorpUserAuth corpUserAuth = corpUserAuthMapper.selectOne(corpUserAuthWrapper);
-		CorpUser corpUser = null;
-		if (corpUserAuth == null) {
-			//尝试添加客户
-			corpEventActionService.addExternalContact(wxCorpApp.getCorpId(), null, externalUserId, null, null);
-			corpUserAuth = corpUserAuthMapper.selectOne(corpUserAuthWrapper);
-			if (corpUserAuth != null) {
-				corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class).eq(CorpUser::getId, corpUserAuth.getCorpUserId()).last("limit 1"));
-			}
-		} else {
-			corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class).eq(CorpUser::getId, corpUserAuth.getCorpUserId()).last("limit 1"));
-		}
-		if (corpUser == null) {
-			log.info("该客户{}不存在", externalUserId);
-			throw BusinessRuntimeException.getInstance("该企业微信用户不存在..");
-		}
-		String unionid = corpUser.getUnionid();
-		if (StrUtil.isEmpty(unionid)) {
-			throw BusinessRuntimeException.getInstance("该用户不是微信用户");
-		}
+	public void corpSendCoupon(String unionid, Long couponId) throws Exception {
 		User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getUnionid, unionid).select(User::getId).last("limit 1"));
 		if (user == null) {
 			throw BusinessRuntimeException.getInstance("该用户未在银河录像注册");
 		}
-		Long couponId = corpCouponSendReq.getCouponId();
 		Coupon coupon = couponMapper.selectById(couponId);
 		if (coupon == null || !coupon.getDeleted()) {
 			throw BusinessRuntimeException.getInstance("该优惠券已被删除");
 		}
 		//发放优惠券给用户
-		this.sendCouponToUser(user.getId(), couponId, null, null,null, CouponUser.Channel.wxCorp);
+		this.sendCouponToUser(user.getId(), couponId, null, null, null, CouponUser.Channel.wxCorp);
 	}
 
 	@Override

+ 16 - 1
netflix-service/src/main/java/com/cyksj/service/market/MarketFrontService.java

@@ -1,12 +1,17 @@
 package com.cyksj.service.market;
 
 
+import com.cyksj.model.entity.LuckyDraw;
 import com.cyksj.model.entity.SignUser;
+import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.LuckyDrawReq;
 import com.cyksj.model.request.TaskFollowReq;
 import com.cyksj.model.views.LuckyDrawView;
 import com.cyksj.model.views.TaskFrontView;
 
+import java.util.Date;
+import java.util.List;
+
 public interface MarketFrontService {
 	SignUser signByUserId(Long userId);
 
@@ -17,7 +22,7 @@ public interface MarketFrontService {
 	 */
 	void pointsRecord(Long userId, Integer points, String remark, Boolean isLottery);
 
-	LuckyDrawView lottery(Long userId);
+	LuckyDrawView lottery(Long userId, LuckyDraw.DrawType drawType) throws Exception;
 
 	void receivedLuckyDraw(Long userId, LuckyDrawReq luckyDrawReq);
 
@@ -28,4 +33,14 @@ public interface MarketFrontService {
 	void toCompleteFollowTask(TaskFollowReq taskFollowReq);
 
 	void updateFailFollowTask(TaskFollowReq taskFollowReq);
+
+	Integer getSpecificChanceNum(Long userId);
+
+	List<GroupsRelationView> getSpecificTickets(Long userId) throws Exception;
+
+	void addSpecificChanceNum(Long userId, Long orderId, Long goodsId, Long skuId) throws Exception;
+
+	void addSpecificChanceNumNoWxCorp(Long userId, Long orderId, Long goodsId, Long skuId) throws Exception;
+
+	void subSpecificChanceNum(Long userId, Long orderId, Long goodsId, Date refundTime) throws Exception;
 }

+ 8 - 0
netflix-service/src/main/java/com/cyksj/service/market/draw/impl/LuckyDrawServiceImpl.java

@@ -97,6 +97,13 @@ public class LuckyDrawServiceImpl implements LuckyDrawService {
 			if (luckyDraw.getPoints() == null || luckyDraw.getPoints() < 0) {
 				throw BusinessRuntimeException.getInstance("积分为空");
 			}
+		} else if (luckyDraw.getType() == LuckyDraw.Type.duration) {
+			if (luckyDraw.getDays() == null || luckyDraw.getDays() < 1) {
+				throw BusinessRuntimeException.getInstance("时长要大于0");
+			}
+			if (luckyDraw.getDrawType() != LuckyDraw.DrawType.specific) {
+				throw BusinessRuntimeException.getInstance("该奖池下不允许配置该奖品类型");
+			}
 		} else {
 			GoodsDonSkuView goodsDonSkuView = beanSearcher.searchFirst(GoodsDonSkuView.class, MapUtils.builder()
 					.field(GoodsDonSkuView::getGoodsId, luckyDraw.getGoodsId()).op(Operator.Equal)
@@ -113,6 +120,7 @@ public class LuckyDrawServiceImpl implements LuckyDrawService {
 		//先找出所有已上架的商品
 		List<LuckyDraw> luckyDraws = luckyDrawMapper.selectList(Wrappers.lambdaQuery(LuckyDraw.class)
 				.eq(LuckyDraw::getStatus, true)
+				.eq(LuckyDraw::getDrawType, entity.getDrawType())
 				.ne(LuckyDraw::getId, entity.getId()));
 		List<Integer> self = Jsons.parseList(entity.getPosition(), Integer.class);
 		for (LuckyDraw luckyDraw : luckyDraws) {

+ 264 - 49
netflix-service/src/main/java/com/cyksj/service/market/impl/MarketFrontServiceImpl.java

@@ -11,14 +11,14 @@ import com.cyksj.common.constant.PointsRecordConst;
 import com.cyksj.common.constant.TaskTypeEnum;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.snowflake.Sequence;
-import com.cyksj.mapper.AddressMapper;
-import com.cyksj.mapper.OrderDonMapper;
-import com.cyksj.mapper.OrderDonTransportMapper;
-import com.cyksj.mapper.UserMapper;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.mapper.*;
 import com.cyksj.mapper.corp.CorpUserMapper;
 import com.cyksj.mapper.manage.coupon.CouponUserMapper;
 import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
 import com.cyksj.mapper.market.draw.LuckyDrawRecordMapper;
+import com.cyksj.mapper.market.draw.LuckyDrawSpecificChanceMapper;
+import com.cyksj.mapper.market.draw.LuckyDrawSpecificChanceRecordMapper;
 import com.cyksj.mapper.market.sign.SignConfigMapper;
 import com.cyksj.mapper.market.sign.SignUserMapper;
 import com.cyksj.mapper.market.sign.UserPointsRecordMapper;
@@ -26,6 +26,7 @@ import com.cyksj.mapper.market.task.TaskFollowPlatVerifyMapper;
 import com.cyksj.mapper.market.task.TaskUserCompleteRecordMapper;
 import com.cyksj.mapper.market.task.UserBindPhoneMapper;
 import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.LuckyDrawReq;
 import com.cyksj.model.request.TaskFollowReq;
 import com.cyksj.model.views.LuckyDrawView;
@@ -34,9 +35,11 @@ import com.cyksj.redis.RedisService;
 import com.cyksj.service.exchange.ExchangeCodeService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.cyksj.service.market.MarketFrontService;
+import com.cyksj.service.relation.GroupRelationFrontService;
 import com.cyksj.service.sys.SysConfigService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -45,6 +48,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.concurrent.ThreadLocalRandom;
@@ -93,6 +97,14 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 
 	private final TaskFollowPlatVerifyMapper taskFollowPlatVerifyMapper;
 
+	private final GroupsRelationMapper groupsRelationMapper;
+
+	private final LuckyDrawSpecificChanceMapper luckyDrawSpecificChanceMapper;
+
+	private final LuckyDrawSpecificChanceRecordMapper luckyDrawSpecificChanceRecordMapper;
+
+	private final GroupRelationFrontService groupRelationFrontService;
+
 	@Override
 	public SignUser signByUserId(Long userId) {
 		//第一次签到
@@ -147,21 +159,16 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
-	public LuckyDrawView lottery(Long userId) {
-		SysConfig lottery_points_limit = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, "lottery_points_limit").last("limit 1"));
-		User user = userMapper.selectById(userId);
-		BigDecimal subPoints = BigDecimal.valueOf(Long.parseLong(lottery_points_limit.getSysValue()));
-		if (user.getActivePoints().compareTo(subPoints) < 0) {
-			throw BusinessRuntimeException.getInstance("积分不足");
-		}
-		//扣减积分
-		Integer sub = userMapper.subActivePoints(userId, subPoints);
-		if (sub != 1) {
-			throw BusinessRuntimeException.getInstance("积分不足");
+	public LuckyDrawView lottery(Long userId, LuckyDraw.DrawType drawType) throws Exception {
+		List<Long> goodsIdList = null;
+		if (drawType == LuckyDraw.DrawType.normal) {
+			luckyDrawNormalCheck(userId);
+		} else {
+			goodsIdList = luckyDrawSpecificCheck(userId);
 		}
-		pointsRecord(userId, -subPoints.intValue(), PointsRecordConst.POINTS_LOTTERY, true);
 		List<LuckyDrawView> drawViews = beanSearcher.searchAll(LuckyDrawView.class, MapUtils.builder()
 				.field(LuckyDrawView::getStatus, true).op(Operator.Equal)
+				.field(LuckyDrawView::getDrawType, drawType.name())
 				.orderBy(LuckyDrawView::getProbability).asc()
 				.build());
 		if (drawViews.isEmpty()) {
@@ -172,7 +179,7 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 			throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重新操作");
 		}
 		LuckyDrawView luckyDraw = drawViews.get(index);
-		if (luckyDraw.getType() != LuckyDraw.Type.points) {
+		if (luckyDraw.getType() != LuckyDraw.Type.points && luckyDraw.getType() != LuckyDraw.Type.duration) {
 			Integer num = 1;
 			luckyDraw = randomNum(luckyDraw, drawViews, num, userId);
 			if (luckyDraw == null) {
@@ -199,6 +206,23 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 			record.setStatus(LuckyDrawRecord.Status.pending);
 		} else if (luckyDraw.getType() == LuckyDraw.Type.realGoods) {
 			record.setStatus(LuckyDrawRecord.Status.pending);
+		} else if (luckyDraw.getType() == LuckyDraw.Type.duration) {
+			MapBuilder builder = MapUtils.builder()
+					.field(GroupsRelationView::getUserId, userId)
+					.field(GroupsRelationView::getStatus, "validity")
+					.field(GroupsRelationView::getExpiryTime).op(Operator.NotNull);
+			if (goodsIdList != null && goodsIdList.size() > 0) {
+				builder.field(GroupsRelationView::getGoodsId, goodsIdList).op(Operator.InList);
+			}
+			//若对应平台车票仅有一张且已发车,直接增加车票时长
+			List<GroupsRelationView> relations = beanSearcher.searchAll(GroupsRelationView.class, builder.build());
+			if (relations != null && relations.size() == 1) {
+				Long relationId = relations.get(0).getId();
+				updateRelationExpiryTime(userId, relationId, luckyDraw.getDays());
+				record.setStatus(LuckyDrawRecord.Status.success);
+			} else {
+				record.setStatus(LuckyDrawRecord.Status.pending);
+			}
 		}
 		record.setUserId(userId);
 		record.setDrawId(luckyDraw.getId());
@@ -218,39 +242,16 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 		if (record.getStatus() == LuckyDrawRecord.Status.success) {
 			throw BusinessRuntimeException.getInstance("您已领取该中奖奖品");
 		}
-		User user = userMapper.selectById(userId);
-		/* 生成订单 */
-		String donNo = SEQUENCE.nextId().toString();
-		OrderDon orderDon = new OrderDon();
-		orderDon.setOrderNo(donNo);
-		orderDon.setOpenId(user.getOpenId());
-		BigDecimal zero = BigDecimal.ZERO;
-		orderDon.setMoney(zero);
-		orderDon.setRealMoney(zero);
-		orderDon.setSkuId(record.getSkuId());
-		orderDon.setRelationId(0L);
-		orderDon.setNum(1);
-		orderDon.setGoodsId(record.getGoodsId());
-		orderDon.setStatus(record.getType() == LuckyDraw.Type.realGoods ? OrderDon.Status.hasPayment : OrderDon.Status.complete);
-		orderDon.setUserId(user.getId());
-		orderDon.setType(OrderDon.Type.LOTTERY);
-		orderDonMapper.insert(orderDon);
-
-		Address address = addressMapper.selectById(luckyDrawReq.getAddressId());
-		if (address == null) {
-			throw new BusinessRuntimeException("请添加收货地址.");
+		Long orderId = null;
+		if (record.getType() == LuckyDraw.Type.realGoods) {
+			orderId = receiveRealGoodsReward(userId, record, luckyDrawReq.getAddressId());
+		} else if (record.getType() == LuckyDraw.Type.duration) {
+			updateRelationExpiryTime(userId, luckyDrawReq.getRelationId(), record.getDays());
 		}
-		OrderDonTransport transport = new OrderDonTransport();
-		transport.setOrderId(orderDon.getId());
-		transport.setReceiver(address.getReceiver());
-		transport.setPhone(address.getPhone());
-		transport.setProvince(address.getProvince());
-		transport.setCity(address.getCity());
-		transport.setDistrict(address.getDistrict());
-		transport.setAddress(address.getAddress());
-		orderDonTransportMapper.insert(transport);
-
-		Integer update = luckyDrawRecordMapper.updateStatus(record.getId(), orderDon.getId(), LuckyDrawRecord.Status.success);
+		if (orderId == null) {
+			orderId = 0l;;
+		}
+		Integer update = luckyDrawRecordMapper.updateStatus(record.getId(), orderId, LuckyDrawRecord.Status.success);
 		if (update != 1) {
 			throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重新操作");
 		}
@@ -564,4 +565,218 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 			}
 		}
 	}
+
+	public void luckyDrawNormalCheck(Long userId) {
+		SysConfig lottery_points_limit = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_POINTS_LIMIT).last("limit 1"));
+		User user = userMapper.selectById(userId);
+		BigDecimal subPoints = BigDecimal.valueOf(Long.parseLong(lottery_points_limit.getSysValue()));
+		if (user.getActivePoints().compareTo(subPoints) < 0) {
+			throw BusinessRuntimeException.getInstance("积分不足");
+		}
+		//扣减积分
+		Integer sub = userMapper.subActivePoints(userId, subPoints);
+		if (sub != 1) {
+			throw BusinessRuntimeException.getInstance("积分不足");
+		}
+		pointsRecord(userId, -subPoints.intValue(), PointsRecordConst.POINTS_LOTTERY, true);
+	}
+
+	public List<Long> luckyDrawSpecificCheck(Long userId) throws Exception {
+		SysConfig lottery_specific_goods = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_SPECIFIC_GOODS).last("limit 1"));
+		if (lottery_specific_goods == null) {
+			throw BusinessRuntimeException.getInstance("暂未配置特定奖池平台,请联系客服");
+		}
+		String sysValue = lottery_specific_goods.getSysValue();
+		if (sysValue == null) {
+			throw BusinessRuntimeException.getInstance("");
+		}
+		List<Long> goodsIdList = Jsons.parseList(sysValue, Long.class);
+		Integer num = getSpecificChanceNum(userId);
+		if (num <= 0) {
+			throw BusinessRuntimeException.getInstance("您的抽奖次数为0");
+		}
+		Integer update = luckyDrawSpecificChanceMapper.subChanceNum(userId, num);
+		if (update != 1) {
+			throw BusinessRuntimeException.getInstance("操作频繁,请稍后再试");
+		}
+		return goodsIdList;
+	}
+
+	@Override
+	public Integer getSpecificChanceNum(Long userId) {
+		//是否有特定奖池抽奖机会
+		LuckyDrawSpecificChance chance = luckyDrawSpecificChanceMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawSpecificChance.class)
+				.eq(LuckyDrawSpecificChance::getUserId, userId).last("limit 1").select(LuckyDrawSpecificChance::getNum));
+		Integer num = 0;
+		if (chance == null) {
+			return num;
+		}
+		num = chance.getNum();
+		return num;
+	}
+
+
+	@Override
+	public List<GroupsRelationView> getSpecificTickets(Long userId) throws Exception {
+		SysConfig lottery_specific_goods = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_SPECIFIC_GOODS).last("limit 1"));
+		if (lottery_specific_goods == null) {
+			return new ArrayList<>();
+		}
+		String sysValue = lottery_specific_goods.getSysValue();
+		if (sysValue == null) {
+			return new ArrayList<>();
+		}
+		List<Long> goodsIdList = Jsons.parseList(sysValue, Long.class);
+		MapBuilder builder = MapUtils.builder()
+				.field(GroupsRelationView::getUserId, userId)
+				.field(GroupsRelationView::getStatus, "validity")
+				.field(GroupsRelationView::getExpiryTime).op(Operator.NotNull);
+		if (goodsIdList != null && goodsIdList.size() > 0) {
+			builder.field(GroupsRelationView::getGoodsId, goodsIdList).op(Operator.InList);
+		}
+		List<GroupsRelationView> relations = beanSearcher.searchAll(GroupsRelationView.class, builder.build());
+		return relations;
+	}
+
+	public Long receiveRealGoodsReward(Long userId, LuckyDrawRecord record, Long addressId) {
+		if (addressId == null) {
+			throw new BusinessRuntimeException("请添加收货地址.");
+		}
+		User user = userMapper.selectById(userId);
+		/* 生成订单 */
+		String donNo = SEQUENCE.nextId().toString();
+		OrderDon orderDon = new OrderDon();
+		orderDon.setOrderNo(donNo);
+		orderDon.setOpenId(user.getOpenId());
+		BigDecimal zero = BigDecimal.ZERO;
+		orderDon.setMoney(zero);
+		orderDon.setRealMoney(zero);
+		orderDon.setSkuId(record.getSkuId());
+		orderDon.setRelationId(0L);
+		orderDon.setNum(1);
+		orderDon.setGoodsId(record.getGoodsId());
+		orderDon.setStatus(record.getType() == LuckyDraw.Type.realGoods ? OrderDon.Status.hasPayment : OrderDon.Status.complete);
+		orderDon.setUserId(user.getId());
+		orderDon.setType(OrderDon.Type.LOTTERY);
+		orderDonMapper.insert(orderDon);
+
+		Address address = addressMapper.selectById(addressId);
+		if (address == null) {
+			throw new BusinessRuntimeException("请添加收货地址.");
+		}
+		OrderDonTransport transport = new OrderDonTransport();
+		transport.setOrderId(orderDon.getId());
+		transport.setReceiver(address.getReceiver());
+		transport.setPhone(address.getPhone());
+		transport.setProvince(address.getProvince());
+		transport.setCity(address.getCity());
+		transport.setDistrict(address.getDistrict());
+		transport.setAddress(address.getAddress());
+		orderDonTransportMapper.insert(transport);
+
+		return orderDon.getId();
+	}
+
+	public void updateRelationExpiryTime(Long userId, Long relationId, Integer days) {
+		//增加续费时长
+		GroupsRelation relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
+				.eq(GroupsRelation::getUserId, userId)
+				.eq(GroupsRelation::getId, relationId)
+				.eq(GroupsRelation::getStatus, GroupsRelation.Status.validity)
+				.last("limit 1"));
+		if (relation == null) {
+			throw BusinessRuntimeException.getInstance("该车票不存在");
+		}
+		if (relation.getExpiryTime() == null) {
+			throw BusinessRuntimeException.getInstance("该车位未发车,请在发车后延长车票时长");
+		}
+		Date expiryTime = relation.getExpiryTime();
+		relation.setExpiryTime(DateUtil.offsetDay(expiryTime, days));
+		groupsRelationMapper.updateById(relation);
+	}
+
+	@Override
+	public void addSpecificChanceNum(Long userId, Long orderId, Long goodsId, Long skuId) throws Exception {
+		if (!checkSpecificGoods(goodsId)) {
+			return;
+		}
+		//加入企微之后 发放抽奖机会
+		if (groupRelationFrontService.isJoinCorpWx(userId, false, true)) {
+			addSpecificChanceNumNoWxCorp(userId, orderId, goodsId, skuId);
+		}
+	}
+
+	@Override
+	public void addSpecificChanceNumNoWxCorp(Long userId, Long orderId, Long goodsId, Long skuId) {
+		if (saveChanceRecord(userId, orderId, goodsId, skuId)) {
+			LuckyDrawSpecificChance chance = luckyDrawSpecificChanceMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawSpecificChance.class)
+					.eq(LuckyDrawSpecificChance::getUserId, userId).last("limit 1").select(LuckyDrawSpecificChance::getNum));
+			if (chance == null) {
+				try {
+					LuckyDrawSpecificChance entity = new LuckyDrawSpecificChance();
+					entity.setUserId(userId);
+					entity.setNum(1);
+					luckyDrawSpecificChanceMapper.insert(entity);
+				} catch (DuplicateKeyException e) {
+					luckyDrawSpecificChanceMapper.addChanceNum(userId);
+				}
+			} else {
+				luckyDrawSpecificChanceMapper.addChanceNum(userId);
+			}
+		}
+	}
+
+	@Override
+	public void subSpecificChanceNum(Long userId, Long orderId, Long goodsId, Date refundTime) throws Exception {
+		if (!checkSpecificGoods(goodsId)) {
+			return;
+		}
+		LuckyDrawSpecificChance chance = luckyDrawSpecificChanceMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawSpecificChance.class)
+				.eq(LuckyDrawSpecificChance::getUserId, userId).last("limit 1").select(LuckyDrawSpecificChance::getNum));
+		if (chance == null) {
+			return;
+		}
+		LuckyDrawSpecificChanceRecord record = luckyDrawSpecificChanceRecordMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawSpecificChanceRecord.class)
+				.eq(LuckyDrawSpecificChanceRecord::getOrderId, orderId)
+				.eq(LuckyDrawSpecificChanceRecord::getUserId, userId)
+				.last("limit 1"));
+		record.setRefundTime(refundTime);
+		luckyDrawSpecificChanceRecordMapper.updateById(record);
+		luckyDrawSpecificChanceMapper.subChanceNumNoRepeat(userId);
+	}
+
+	public Boolean checkSpecificGoods(Long goodsId) throws Exception {
+		SysConfig lottery_specific_goods = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_SPECIFIC_GOODS).last("limit 1"));
+		if (lottery_specific_goods == null) {
+			return false;
+		}
+		String sysValue = lottery_specific_goods.getSysValue();
+		if (sysValue == null) {
+			return false;
+		}
+		List<Long> goodsIdList = Jsons.parseList(sysValue, Long.class);
+		if (goodsIdList.isEmpty() || goodsIdList.contains(goodsId)) {
+			return true;
+		}
+		return false;
+	}
+
+	public Boolean saveChanceRecord(Long userId, Long orderId, Long goodsId, Long skuId) {
+		try {
+			LuckyDrawSpecificChanceRecord en = luckyDrawSpecificChanceRecordMapper.selectOne(Wrappers.lambdaQuery(LuckyDrawSpecificChanceRecord.class)
+					.eq(LuckyDrawSpecificChanceRecord::getOrderId, orderId).last("limit 1"));
+			if (en == null) {
+				LuckyDrawSpecificChanceRecord record = new LuckyDrawSpecificChanceRecord();
+				record.setUserId(userId);
+				record.setOrderId(orderId);
+				record.setGoodsId(goodsId);
+				record.setSkuId(skuId);
+				luckyDrawSpecificChanceRecordMapper.insert(record);
+				return true;
+			}
+			return false;
+		} catch (DuplicateKeyException e) {
+			return false;
+		}
+	}
 }

+ 39 - 4
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -56,6 +56,7 @@ import com.cyksj.redis.RedisService;
 import com.cyksj.service.coupon.CouponFontService;
 import com.cyksj.service.exchange.ExchangeCodeService;
 import com.cyksj.service.mange.stock.GoodsDonStockService;
+import com.cyksj.service.market.MarketFrontService;
 import com.cyksj.service.market.task.TaskService;
 import com.cyksj.service.order.OrderDonService;
 import com.cyksj.service.template.TemplateCommonService;
@@ -167,6 +168,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final TemplateCommonService templateCommonService;
 
+	private final MarketFrontService marketFrontService;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -477,6 +480,14 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		this.updateById(order);
 
+		//配置了特定奖池,增加抽奖机会
+		TASK_POOL.execute(() -> {
+			try {
+				marketFrontService.addSpecificChanceNum(order.getUserId(), order.getId(), order.getGoodsId(), order.getSkuId());
+			} catch (Exception e) {
+				log.error("wx增加抽奖机会错误,orderId:{},error:{}", order.getId(), e);
+			}
+		});
 	}
 
 	@Override
@@ -542,7 +553,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
 	public OrderDon renewal(OrderPayRequest payRequest) throws Exception {
-		User user = userMapper.selectById(payRequest.getUserId());
+		Long userId = payRequest.getUserId();
+		User user = userMapper.selectById(userId);
 		CouponUser couponUser = null;
 		if (StrUtil.isNotBlank(payRequest.getCouponExCode()) || payRequest.getCouponId() != null) {
 			checkCouponStatus(payRequest.getSkuId(), payRequest.getCouponExCode(), payRequest.getCouponId(), payRequest.getUserId(), true);
@@ -560,9 +572,10 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
         if (relation == null) {
             throw new BusinessRuntimeException("");
         }
-        if (!relation.getUserId().equals(user.getId())) {
-            throw new BusinessRuntimeException("");
-        }
+
+		if (!relation.getUserId().equals(user.getId())) {
+			throw new BusinessRuntimeException("");
+		}
         GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
 
 		GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
@@ -737,6 +750,15 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			handleServiceRenewOrder(orderDon);
 		}
 		this.updateById(orderDon);
+
+		//配置了特定奖池,增加抽奖机会
+		TASK_POOL.execute(() -> {
+			try {
+				marketFrontService.addSpecificChanceNum(orderDon.getUserId(), orderDon.getId(), orderDon.getGoodsId(), orderDon.getSkuId());
+			} catch (Exception e) {
+				log.error("zfb增加抽奖机会错误,orderId:{},error:{}", orderDon.getId(), e);
+			}
+		});
 	}
 
 	@Override
@@ -863,6 +885,11 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			THREAD_POOL_TASK_EXECUTOR.execute(()->{
 				refundRecord(orderDon, goodsDon, sku, outNo);
 				goodsDonStockService.upStockRelate(null, orderDon.getId(),"refund");
+				try {
+					marketFrontService.subSpecificChanceNum(orderDon.getUserId(), orderDon.getId(), orderDon.getGoodsId(), orderDon.getUpdateTime());
+				} catch (Exception e) {
+					log.error("zfb减少抽奖机会错误,orderId:{},error:{}", orderDon.getId(), e);
+				}
 			});
 			//虚物订单退款,清出车队,车票变为已过期
 			clearUnrealGoodsDetail(orderDon, goodsDon, sku);
@@ -1054,6 +1081,14 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			}
 		}
 		log.info("微信退款: 退款单号[{}] 退款成功.", outRefundNo);
+
+		TASK_POOL.execute(()->{
+			try {
+				marketFrontService.subSpecificChanceNum(orderDon.getUserId(), orderDon.getId(), orderDon.getGoodsId(), orderDon.getUpdateTime());
+			} catch (Exception e) {
+				log.error("wx减少抽奖机会错误,orderId:{},error:{}", orderDon.getId(), e);
+			}
+		});
 	}
 
 	public void setRelation(Long relationId, Long userId, Long goodsId, Boolean isLoginPopularize) {

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java

@@ -12,4 +12,6 @@ import java.util.List;
  */
 public interface GroupRelationFrontService {
 	List<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize);
+
+	Boolean isJoinCorpWx(Long userId, Boolean isJoin, Boolean noCoupon);
 }

+ 36 - 4
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -5,13 +5,12 @@ import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.corp.CorpUserMapper;
 import com.cyksj.mapper.market.task.UserBindPhoneMapper;
-import com.cyksj.model.entity.GoodsDonSku;
-import com.cyksj.model.entity.GoodsDonSpec;
-import com.cyksj.model.entity.User;
-import com.cyksj.model.entity.UserBindPhone;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.views.GoodsDonViews;
 import com.cyksj.model.views.RenewalView;
+import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.cyksj.service.relation.GroupRelationFrontService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.param.Operator;
@@ -39,6 +38,10 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 
 	private final BeanSearcher beanSearcher;
 
+	private final CorpUserMapper corpUserMapper;
+
+	private final CouponCommonService couponCommonService;
+
 	@Override
 	public List<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize) {
 		User u = userMapper.selectById(userId);
@@ -92,4 +95,33 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 		}).collect(Collectors.toList());
 		return collect;
 	}
+
+	@Override
+	public Boolean isJoinCorpWx(Long userId, Boolean isJoin, Boolean noCoupon) {
+		if (!isJoin) {
+			User user = userMapper.selectById(userId);
+			if (StrUtil.isEmpty(user.getUnionid())) {
+				return true;
+			}
+			CorpUser corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class)
+					.ne(CorpUser::getUnionid, "")
+					.eq(CorpUser::getUnionid, user.getUnionid())
+					.last("limit 1")
+					.select(CorpUser::getId)
+			);
+			if (corpUser == null) {
+				return false;
+			}
+		}
+		//用户是否买了奈飞车票
+		Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder()
+				.field(RenewalView::getUserId, userId)
+				.field(RenewalView::getGoodsId, 1)
+				.field(RenewalView::getStatus, List.of("validity", "overdue")).op(Operator.InList)
+				.build());
+		if (number.intValue() > 0 && !noCoupon) {
+			couponCommonService.sendCouponToUser(userId, 34l, 0l, 0l, 0l, CouponUser.Channel.manual);
+		}
+		return true;
+	}
 }

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java

@@ -87,7 +87,7 @@ public class GroupRelationController {
     @GetMapping("/check/joinCorpWx")
     public Result<Boolean> isJoinCorpWx() {
         long userId = StpUserUtil.getLoginIdAsLong();
-        Boolean flag = corpService.isJoinCorpWx(userId, false);
+        Boolean flag = groupRelationFrontService.isJoinCorpWx(userId, false, false);
         return GatewayResponse.SUCCESS.newBuilder().toResult(flag);
     }
 }

+ 45 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java

@@ -1,9 +1,14 @@
 package com.cyksj.web.controller.manage.coupon;
 
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.config.corp.WeChatCorpFactory;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.corp.CorpUserAuthMapper;
+import com.cyksj.mapper.corp.CorpUserMapper;
 import com.cyksj.mapper.manage.coupon.*;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.CorpCouponSendReq;
@@ -13,11 +18,13 @@ import com.cyksj.model.views.CouponActiveView;
 import com.cyksj.model.views.CouponDistributePopularizeView;
 import com.cyksj.model.views.CouponRecommendView;
 import com.cyksj.model.views.CouponView;
+import com.cyksj.service.corp.msg.CorpEventActionService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -38,6 +45,7 @@ import java.util.stream.Collectors;
 @RestController
 @RequestMapping("/manage/coupon")
 @RequiredArgsConstructor
+@Slf4j
 public class CouponController {
 	private final CouponCommonService couponCommonService;
 
@@ -55,6 +63,12 @@ public class CouponController {
 
 	private final CouponSkuMapper couponSkuMapper;
 
+	private final CorpUserMapper corpUserMapper;
+
+	private final CorpEventActionService corpEventActionService;
+
+	private final CorpUserAuthMapper corpUserAuthMapper;
+
 	/**
 	 * 新增优惠券
 	 */
@@ -287,8 +301,38 @@ public class CouponController {
 	 */
 	@PostMapping("/corp/send")
 	public Result<String> corpSendCoupon(@RequestBody @Validated CorpCouponSendReq corpCouponSendReq) throws Exception {
-		couponCommonService.corpSendCoupon(corpCouponSendReq);
+		String corpId = corpCouponSendReq.getCorpId();
+		String externalUserId = corpCouponSendReq.getExternalUserId();
+		String unionid = getUnionId(corpId, externalUserId);
+		Long couponId = corpCouponSendReq.getCouponId();
+		if (StrUtil.isEmpty(unionid)) {
+			throw BusinessRuntimeException.getInstance("该用户不是微信用户");
+		}
+		couponCommonService.corpSendCoupon(unionid, couponId);
 		return GatewayResponse.SUCCESS.newBuilder().toResult("发放优惠券成功");
 	}
 
+	public String getUnionId(String corpId, String externalUserId) throws Exception {
+		WxCorpApp wxCorpApp = WeChatCorpFactory.getCorpConfigStrategy(corpId);
+		LambdaQueryWrapper<CorpUserAuth> corpUserAuthWrapper = Wrappers.lambdaQuery(CorpUserAuth.class)
+				.eq(CorpUserAuth::getExternalUserid, externalUserId)
+				.eq(CorpUserAuth::getWxCorpId, wxCorpApp.getId()).last("limit 1");
+		CorpUserAuth corpUserAuth = corpUserAuthMapper.selectOne(corpUserAuthWrapper);
+		CorpUser corpUser = null;
+		if (corpUserAuth == null) {
+			//尝试添加客户
+			corpEventActionService.addExternalContact(wxCorpApp.getCorpId(), null, externalUserId, null, null);
+			corpUserAuth = corpUserAuthMapper.selectOne(corpUserAuthWrapper);
+			if (corpUserAuth != null) {
+				corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class).eq(CorpUser::getId, corpUserAuth.getCorpUserId()).last("limit 1"));
+			}
+		} else {
+			corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class).eq(CorpUser::getId, corpUserAuth.getCorpUserId()).last("limit 1"));
+		}
+		if (corpUser == null) {
+			log.info("该客户{}不存在", externalUserId);
+			throw BusinessRuntimeException.getInstance("该企业微信用户不存在..");
+		}
+		return corpUser.getUnionid();
+	}
 }

+ 27 - 3
netflix-web/src/main/java/com/cyksj/web/controller/market/LuckyDrawFrontController.java

@@ -7,7 +7,9 @@ import com.cyksj.common.util.StringUtil;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.UserMapper;
+import com.cyksj.model.entity.LuckyDraw;
 import com.cyksj.model.entity.User;
+import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.LuckyDrawReq;
 import com.cyksj.model.views.LuckyDrawRecordView;
 import com.cyksj.model.views.LuckyDrawView;
@@ -44,12 +46,14 @@ public class LuckyDrawFrontController {
 
 	private final UserMapper userMapper;
 
+	private final HttpServletRequest request;
+
 	/**
 	 * 奖品列表
 	 */
 	@GetMapping("/get")
 	public Result<List<LuckyDrawView>> getLuckyDraw(@RequestParam(defaultValue = "true") Boolean isRepeat) throws Exception {
-		List<LuckyDrawView> drawViews = beanSearcher.searchAll(LuckyDrawView.class, MapUtils.builder()
+		List<LuckyDrawView> drawViews = beanSearcher.searchAll(LuckyDrawView.class, MapUtils.flatBuilder(request.getParameterMap())
 				.field(LuckyDrawView::getStatus, true).op(Operator.Equal).build());
 		if (drawViews.isEmpty()) {
 			throw BusinessRuntimeException.getInstance("暂未配置奖品");
@@ -86,14 +90,34 @@ public class LuckyDrawFrontController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}
 
+	/**
+	 * 特定抽奖机会
+	 */
+	@GetMapping("/get/specific/num")
+	public Result<Integer> getSpecificNum() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		Integer num = marketFrontService.getSpecificChanceNum(userId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(num);
+	}
+
+	/**
+	 * 特定奖池 可选平台车票
+	 */
+	@GetMapping("/get/specific/tickets")
+	public Result<List<GroupsRelationView>> getSpecificTickets() throws Exception {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<GroupsRelationView> result = marketFrontService.getSpecificTickets(userId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(result);
+	}
+
 	/**
 	 * 抽奖
 	 */
 	@PostMapping("/lottery")
 	@NoSubmit
-	public Result<LuckyDrawView> lottery() {
+	public Result<LuckyDrawView> lottery(@RequestParam(defaultValue = "normal") LuckyDraw.DrawType drawType) throws Exception {
 		Long userId = StpUserUtil.getLoginIdAsLong();
-		LuckyDrawView luckyDrawView = marketFrontService.lottery(userId);
+		LuckyDrawView luckyDrawView = marketFrontService.lottery(userId, drawType);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(luckyDrawView);
 	}
 

+ 0 - 4
netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

@@ -3,7 +3,6 @@ package com.cyksj.web.controller.payment;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.extra.qrcode.QrCodeUtil;
 import cn.hutool.extra.qrcode.QrConfig;
-import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.IoKit;
 import com.cyksj.common.util.Xmls;
@@ -60,9 +59,6 @@ public class OrderController {
     @Resource
     private HttpServletRequest request;
 
-    @Autowired
-    private EnvCommonService envCommonService;
-
     @Autowired
     private OrderDonMapper orderDonMapper;