Ver código fonte

Merge branch 'equipment_distribute'

# Conflicts:
#	netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
#	netflix-dao/src/main/java/com/cyksj/model/dto/AuthRedirect.java
#	netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java
#	netflix-service/src/main/java/com/cyksj/service/user/UserService.java
#	netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
#	netflix-service/src/main/java/com/cyksj/service/wechat/WeChatService.java
#	netflix-service/src/main/java/com/cyksj/service/wechat/impl/WeChatServiceImpl.java
#	netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java
zoujiajian 3 anos atrás
pai
commit
3f9d0797e8
43 arquivos alterados com 1390 adições e 91 exclusões
  1. 5 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 23 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/equipment/EquipmentUserChanceMapper.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/equipment/EquipmentUserChanceRecordMapper.java
  4. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/equipment/EquipmentUserDistributeInviteRecordMapper.java
  5. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/equipment/EquipmentUserReceiveBenefitsRecordMapper.java
  6. 28 0
      netflix-dao/src/main/java/com/cyksj/model/dto/EquipmentConfigDto.java
  7. 1 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CouponUser.java
  8. 18 0
      netflix-dao/src/main/java/com/cyksj/model/entity/EquipmentUserChance.java
  9. 64 0
      netflix-dao/src/main/java/com/cyksj/model/entity/EquipmentUserChanceRecord.java
  10. 24 0
      netflix-dao/src/main/java/com/cyksj/model/entity/EquipmentUserDistributeInviteRecord.java
  11. 51 0
      netflix-dao/src/main/java/com/cyksj/model/entity/EquipmentUserReceiveBenefitsRecord.java
  12. 9 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GroupsRelation.java
  13. 1 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java
  14. 4 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/GroupsRelationView.java
  15. 3 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonView.java
  16. 5 0
      netflix-dao/src/main/java/com/cyksj/model/request/LoginPhoneReq.java
  17. 24 0
      netflix-dao/src/main/java/com/cyksj/model/request/ReceiveBenefitsReq.java
  18. 51 0
      netflix-dao/src/main/java/com/cyksj/model/views/EquipmentBenefitsView.java
  19. 24 0
      netflix-dao/src/main/java/com/cyksj/model/views/EquipmentCouponView.java
  20. 20 0
      netflix-dao/src/main/java/com/cyksj/model/views/EquipmentDistributeView.java
  21. 67 0
      netflix-dao/src/main/java/com/cyksj/model/views/EquipmentUserDistributeDetailView.java
  22. 39 0
      netflix-dao/src/main/java/com/cyksj/model/views/EquipmentUserDistributeViews.java
  23. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonPopularizeView.java
  24. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuView.java
  25. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  26. 13 0
      netflix-service/src/main/java/com/cyksj/service/distribute/equipment/EquipmentDistributeFrontService.java
  27. 28 0
      netflix-service/src/main/java/com/cyksj/service/distribute/equipment/EquipmentDistributeService.java
  28. 103 0
      netflix-service/src/main/java/com/cyksj/service/distribute/equipment/impl/EquipmentDistributeFrontServiceImpl.java
  29. 204 0
      netflix-service/src/main/java/com/cyksj/service/distribute/equipment/impl/EquipmentDistributeServiceImpl.java
  30. 8 0
      netflix-service/src/main/java/com/cyksj/service/exchange/ExchangeCodeService.java
  31. 8 5
      netflix-service/src/main/java/com/cyksj/service/exchange/impl/ExchangeCodeServiceImpl.java
  32. 14 1
      netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java
  33. 16 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  34. 17 0
      netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationClearService.java
  35. 73 0
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationClearServiceImpl.java
  36. 2 0
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  37. 43 34
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
  38. 3 45
      netflix-service/src/main/java/com/cyksj/task/Scheduler.java
  39. 12 0
      netflix-web/src/main/java/com/cyksj/web/controller/coupon/CouponFrontController.java
  40. 233 0
      netflix-web/src/main/java/com/cyksj/web/controller/distribute/EquipmentDistributeController.java
  41. 15 6
      netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java
  42. 85 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/EquipmentController.java
  43. 3 0
      netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

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

@@ -52,4 +52,9 @@ public interface Constant {
 	 * 固定客服key
 	 */
 	String CORP_FIXED_CUSTOMER = "corp_fixed_customer";
+
+	/**
+	 * 实物分销配置
+	 */
+	String EQUIPMENT_DISTRIBUTE_KEY = "equipment_distribute_key";
 }

+ 23 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/equipment/EquipmentUserChanceMapper.java

@@ -0,0 +1,23 @@
+package com.cyksj.mapper.manage.distribute.equipment;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.EquipmentUserChance;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentUserChanceMapper
+ *创建者: JavaZou
+ *创建时间:2023/2/23 13:34
+ */
+public interface EquipmentUserChanceMapper extends BaseMapper<EquipmentUserChance> {
+	@Update("update equipment_user_chance set num = num + 1 where user_id = #{userId} and num >= 0")
+	void addUserChance(Long userId);
+
+	@Update("update equipment_user_chance set num = num - 1 where user_id = #{userId} and num >= 1")
+	Integer subUserChance(Long userId);
+
+	@Update("update equipment_user_chance set num = num - 1 where user_id = #{userId} and num = #{num} and num >= 1")
+	Integer subUserChanceNoRepeat(@Param("userId") Long userId, @Param("num") Integer num);
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/equipment/EquipmentUserChanceRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.distribute.equipment;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.EquipmentUserChanceRecord;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentUserChanceRecordMapper
+ *创建者: JavaZou
+ *创建时间:2023/2/23 13:35
+ */
+public interface EquipmentUserChanceRecordMapper extends BaseMapper<EquipmentUserChanceRecord> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/equipment/EquipmentUserDistributeInviteRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.distribute.equipment;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.EquipmentUserDistributeInviteRecord;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentUserDistributeInviteRecordMapper
+ *创建者: JavaZou
+ *创建时间:2023/2/23 13:32
+ */
+public interface EquipmentUserDistributeInviteRecordMapper extends BaseMapper<EquipmentUserDistributeInviteRecord> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/equipment/EquipmentUserReceiveBenefitsRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.distribute.equipment;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.EquipmentUserReceiveBenefitsRecord;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentUserReceiveBenefitsRecordMapper
+ *创建者: JavaZou
+ *创建时间:2023/2/23 13:40
+ */
+public interface EquipmentUserReceiveBenefitsRecordMapper extends BaseMapper<EquipmentUserReceiveBenefitsRecord> {
+}

+ 28 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/EquipmentConfigDto.java

@@ -0,0 +1,28 @@
+package com.cyksj.model.dto;
+
+import com.cyksj.model.entity.GoodsDonSku;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+import java.util.Set;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentConfigDto
+ *创建者: JavaZou
+ *创建时间:2023/2/23 15:56
+ */
+@Getter
+@Setter
+public class EquipmentConfigDto {
+	/**
+	 * 新人可活得优惠券id配置
+	 */
+	private Set<Long> couponIds;
+
+	/**
+	 * 车票时长权益配置
+	 */
+	private List<GoodsDonSku> skuList;
+}

+ 1 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CouponUser.java

@@ -59,6 +59,7 @@ public class CouponUser extends BaseEntity {
 		manual("manual","手动发放"),
 		lottery("lottery","抽奖"),
 		task("task","完成任务"),
+		equipment("equipment","实物设备分销"),
 		;
 		private String channel;
 		private String desc;

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/EquipmentUserChance.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentUserChance
+ *创建者: JavaZou
+ *创建时间:2023/2/23 13:32
+ */
+@Getter
+@Setter
+public class EquipmentUserChance extends BaseEntity{
+	private Long userId;
+
+	private Integer num;
+}

+ 64 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/EquipmentUserChanceRecord.java

@@ -0,0 +1,64 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentUserChanceRecord
+ *创建者: JavaZou
+ *创建时间:2023/2/23 13:34
+ */
+@Getter
+@Setter
+@SearchBean(tables = "equipment_user_chance_record er")
+public class EquipmentUserChanceRecord extends BaseEntity{
+	/**
+	 * 受益人id
+	 */
+	@DbField("er.share_id")
+	private Long shareId;
+
+	/**
+	 * 被邀请人id
+	 */
+	@DbField("er.user_id")
+	private Long userId;
+
+	@DbField("er.order_id")
+	private Long orderId;
+
+	@DbField("er.status")
+	private Status status;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private String nickname;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private Date payTime;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private String headImg;
+
+
+	@Getter
+	public enum Status {
+		hasPayment("已购买"),
+		refund("已退款"),
+		;
+		String msg;
+
+		Status(String msg) {
+			this.msg = msg;
+		}
+	}
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/EquipmentUserDistributeInviteRecord.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentUserDistributeInviteRecord
+ *创建者: JavaZou
+ *创建时间:2023/2/23 11:24
+ */
+@Getter
+@Setter
+public class EquipmentUserDistributeInviteRecord extends BaseEntity{
+	/**
+	 * 邀请人id
+	 */
+	private Long shareId;
+
+	/**
+	 * 被邀请人id
+	 */
+	private Long userId;
+}

+ 51 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/EquipmentUserReceiveBenefitsRecord.java

@@ -0,0 +1,51 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentUserReceiveBenefitsRecord
+ *创建者: JavaZou
+ *创建时间:2023/2/23 13:37
+ */
+@Getter
+@Setter
+public class EquipmentUserReceiveBenefitsRecord extends BaseEntity{
+	private Long userId;
+
+	/**
+	 * 时长
+	 */
+	private Integer days;
+
+	/**
+	 * 规格
+	 */
+	private Long skuId;
+
+	/**
+	 * 月数
+	 */
+	private Integer num;
+
+	/**
+	 * 权益对应车票座位
+	 */
+	private Long relationId;
+
+	/**
+	 * 生成车票的订单id
+	 */
+	private Long orderId;
+
+	/**
+	 * 对方退款后订单id
+	 */
+	private Long refundOrderId;
+
+	/**
+	 * 默认1成功,退款后0
+	 */
+	private Integer statusCode;
+}

+ 9 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GroupsRelation.java

@@ -1,5 +1,7 @@
 package com.cyksj.model.entity;
 
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbIgnore;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Setter;
@@ -51,6 +53,13 @@ public class GroupsRelation extends BaseEntity {
      */
     private String customerService;
 
+    /**
+     * 获取权益时的订单id
+     */
+    @TableField(exist = false)
+    @DbIgnore
+    private Long orderId;
+
 
     @AllArgsConstructor
     @Getter

+ 1 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java

@@ -167,6 +167,7 @@ public class OrderDon extends BaseEntity implements Serializable {
         ALI_PAY("zfb","支付宝"),
         EX_CODE("exchange_code","兑换码"),
         LOTTERY("lottery","抽奖"),
+        EQUIPMENT("equipment", "实物设备分销"),
         ;
         String type;
         String desc;

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

@@ -2,6 +2,7 @@ package com.cyksj.model.manage.views;
 
 import com.cyksj.model.entity.GroupsRelation;
 import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.Getter;
@@ -99,4 +100,7 @@ public class GroupsRelationView {
     @DbField("gr.account")
     private String account;
 
+    @DbIgnore
+    private Date updateExpiryTime;
+
 }

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

@@ -55,6 +55,9 @@ public class OrderDonView {
     @DbField("g.type")
     private Integer goodsDonType;
 
+    @DbField("g.second_type")
+    private Integer secondType;
+
     @DbField("o.order_no")
     private String orderNo;
 

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/request/LoginPhoneReq.java

@@ -34,6 +34,11 @@ public class LoginPhoneReq {
 	 */
 	private Integer type;
 
+	/**
+	 * 1、虚物,2、实物
+	 */
+	private Integer dsType;
+
 	/**
 	 * 推广id
 	 */

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/request/ReceiveBenefitsReq.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotNull;
+
+/*
+ *项目名: netflix
+ *文件名: ReceiveBenefitsReq
+ *创建者: JavaZou
+ *创建时间:2023/2/27 16:16
+ */
+@Getter
+@Setter
+public class ReceiveBenefitsReq {
+	@NotNull
+	private Long goodsId;
+
+	@NotNull
+	private Long skuId;
+
+	private Long relationId;
+}

+ 51 - 0
netflix-dao/src/main/java/com/cyksj/model/views/EquipmentBenefitsView.java

@@ -0,0 +1,51 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentBenefitsView
+ *创建者: JavaZou
+ *创建时间:2023/2/24 10:46
+ */
+@Getter
+@Setter
+@SearchBean(tables = "equipment_user_receive_benefits_record er left join goods_don_sku sku on sku.id = er.sku_id" +
+		" left join goods_don gd on gd.id = sku.goods_id")
+public class EquipmentBenefitsView {
+	@DbField("gd.id")
+	private Long goodsId;
+
+	@DbField("sku.id")
+	private Long skuId;
+
+	@DbField("gd.title")
+	private String goodsTitle;
+
+	@DbField("gd.type")
+	private Integer type;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("sku.price")
+	private BigDecimal money;
+
+	@DbField("er.user_id")
+	private Long sharId;
+
+	@DbField("er.status_code")
+	private Integer statusCode;
+
+	@DbField("er.created_time")
+	private Date createdTime;
+
+	@DbField("er.update_time")
+	private Date updateTime;
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/views/EquipmentCouponView.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentCouponView
+ *创建者: JavaZou
+ *创建时间:2023/3/2 11:31
+ */
+@Getter
+@Setter
+public class EquipmentCouponView {
+	private Long userId;
+
+	private String nickname;
+
+	private String headImg;
+
+	private List<CouponUserView> couponList;
+}

+ 20 - 0
netflix-dao/src/main/java/com/cyksj/model/views/EquipmentDistributeView.java

@@ -0,0 +1,20 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentDistributeView
+ *创建者: JavaZou
+ *创建时间:2023/2/23 15:43
+ */
+@Getter
+@Setter
+public class EquipmentDistributeView {
+	private Integer num;
+
+	private String url;
+
+	private String equipmentConfig;
+}

+ 67 - 0
netflix-dao/src/main/java/com/cyksj/model/views/EquipmentUserDistributeDetailView.java

@@ -0,0 +1,67 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.EquipmentUserChanceRecord;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentUserDistributeDetailView
+ *创建者: JavaZou
+ *创建时间:2023/2/24 10:56
+ */
+@Getter
+@Setter
+@SearchBean(tables = "equipment_user_chance_record ecr left join order_don od on od.id = ecr.order_id")
+public class EquipmentUserDistributeDetailView {
+	@DbField("ecr.id")
+	private Long recordId;
+
+	@DbField("ecr.share_id")
+	private Long shareId;
+
+	/**
+	 * 被分销人id
+	 */
+	@DbField("ecr.user_id")
+	private Long userId;
+
+	/**
+	 * 被分销人昵称
+	 */
+	@DbIgnore
+	private String nickname;
+
+	@DbField("od.id")
+	private Long orderId;
+
+	@DbField("od.coupon_user_id")
+	private Long couponUserId;
+
+	/**
+	 * 优惠券名称
+	 */
+	@DbIgnore
+	private String couponName;
+
+	@DbField("ecr.status")
+	private EquipmentUserChanceRecord.Status status;
+
+	@DbIgnore
+	private String specVal;
+
+	@DbField("od.sku_id")
+	private Long skuId;
+
+	@DbField("od.money")
+	private BigDecimal money;
+
+	@DbField("od.pay_time")
+	private Date payTime;
+}

+ 39 - 0
netflix-dao/src/main/java/com/cyksj/model/views/EquipmentUserDistributeViews.java

@@ -0,0 +1,39 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentUserDistributeViews
+ *创建者: JavaZou
+ *创建时间:2023/2/24 9:44
+ */
+@Getter
+@Setter
+@SearchBean(tables = "equipment_user_chance ec")
+public class EquipmentUserDistributeViews {
+	@DbField("ec.user_id")
+	private Long shareId;
+
+	@DbIgnore
+	private String nickname;
+
+	/**
+	 * 分销记录数
+	 */
+	@DbIgnore
+	private Integer recordNum;
+
+	@DbIgnore
+	private List<EquipmentBenefitsView> benefitsViews;
+
+	@DbField("ec.created_time")
+	private Date createdTime;
+}

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

@@ -58,6 +58,9 @@ public class GoodsDonPopularizeView {
 	@DbField("g.type")
 	private Integer type;
 
+	@DbField("g.second_type")
+	private Integer secondType;
+
 	/**
 	 * true 上架 / false 下架
 	 */

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

@@ -20,6 +20,9 @@ public class GoodsDonSkuView {
 	@DbField("gd.id")
 	private Long goodsId;
 
+	@DbField("gd.logo")
+	private String logo;
+
 	@DbField("gd.title")
 	private String goodsTitle;
 
@@ -32,6 +35,9 @@ public class GoodsDonSkuView {
 	@DbField("gdk.spec_val")
 	private String specVal;
 
+	@DbField("gdk.months")
+	private Integer months;
+
 	@DbField("gdk.price")
 	private BigDecimal money;
 

+ 1 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -595,6 +595,7 @@ public class RedisService {
         TASK_TIME_LIMIT_KEY("task_time_limit:%s", "一次性任务key", 30),
         WX_GZH_QRCODE_LOGIN("wx_gzh_qrcode_login:%s", "微信公众号扫码登录key", 60),
         WX_GZH_QRCODE_SHARED_LOGIN("wx_gzh_qrcode_shared_login:%s", "微信公众号扫码分享邀请key", 60),
+        EQUIPMENT_DISTRIBUTE_COUPON_KEY("equipment_distribute_coupon_key:%s", "实物设备分销新用户优惠券展示key", 60),
         ;
 
         private String name;

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/equipment/EquipmentDistributeFrontService.java

@@ -0,0 +1,13 @@
+package com.cyksj.service.distribute.equipment;
+
+import com.cyksj.model.manage.views.GroupsRelationView;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentDistributeFrontService
+ *创建者: JavaZou
+ *创建时间:2023/2/23 16:19
+ */
+public interface EquipmentDistributeFrontService {
+	GroupsRelationView useBenefits(Long userId, Long goodsId, Long skuId, Long relationId);
+}

+ 28 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/equipment/EquipmentDistributeService.java

@@ -0,0 +1,28 @@
+package com.cyksj.service.distribute.equipment;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentDistributeService
+ *创建者: JavaZou
+ *创建时间:2023/2/23 13:41
+ */
+public interface EquipmentDistributeService {
+
+	/**
+	 * 保存分销邀请记录
+	 * sharedId: 邀请人
+	 * isNewUser: 新用户
+	 * userId: 被邀请人
+	 */
+	void saveDistributionInvitation(Long sharedId, Boolean isNewUser, Long userId);
+
+	/**
+	 * 领取权益次数增加
+	 */
+	void addDistributeBenefitsChance(Long userId, Long orderId);
+
+	/**
+	 * 减少权益次数
+	 */
+	void subDistributeBenefitsChance(Long userId, Long orderId);
+}

+ 103 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/equipment/impl/EquipmentDistributeFrontServiceImpl.java

@@ -0,0 +1,103 @@
+package com.cyksj.service.distribute.equipment.impl;
+
+import cn.hutool.core.date.DateField;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.manage.distribute.equipment.EquipmentUserChanceMapper;
+import com.cyksj.mapper.manage.distribute.equipment.EquipmentUserReceiveBenefitsRecordMapper;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.service.distribute.equipment.EquipmentDistributeFrontService;
+import com.cyksj.service.exchange.ExchangeCodeService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentDistributeFrontServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/2/23 16:20
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class EquipmentDistributeFrontServiceImpl implements EquipmentDistributeFrontService {
+	private final GroupsRelationMapper groupsRelationMapper;
+
+	private final BeanSearcher beanSearcher;
+
+	private final ExchangeCodeService exchangeCodeService;
+
+	private final GoodsDonSkuMapper goodsDonSkuMapper;
+
+	private final EquipmentUserChanceMapper equipmentUserChanceMapper;
+
+	private final EquipmentUserReceiveBenefitsRecordMapper equipmentUserReceiveBenefitsRecordMapper;
+
+	@Override
+	public GroupsRelationView useBenefits(Long userId, Long goodsId, Long skuId, Long relationId) {
+		//减少获取权益机会
+		EquipmentUserChance chance = equipmentUserChanceMapper.selectOne(Wrappers.lambdaQuery(EquipmentUserChance.class)
+				.eq(EquipmentUserChance::getUserId, userId).last("limit 1"));
+		if (chance == null || chance.getNum() <= 0) {
+			throw BusinessRuntimeException.getInstance("可领取次数为0");
+		}
+		Integer num = chance.getNum();
+		Integer update = equipmentUserChanceMapper.subUserChanceNoRepeat(userId, num);
+		if (update != 1) {
+			throw BusinessRuntimeException.getInstance("操作频繁,请刷新页面后重试");
+		}
+		GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
+				.field(GroupsRelationView::getGoodsId, goodsId)
+				.field(GroupsRelationView::getId, relationId)
+				.orderBy(GroupsRelationView::getExpiryTime).asc()
+				.field(GroupsRelationView::getUserId, userId)
+				.build());
+		GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(skuId);
+		Long orderId = null;
+		if (goodsDonSku == null || !goodsDonSku.getGoodsId().equals(goodsId)) {
+			throw BusinessRuntimeException.getInstance("");
+		}
+		if (groupsRelationView == null) {
+			//领取权益时,没有车票的用户自动上车,获得对应车票
+			GroupsRelation relation = exchangeCodeService.getGroupTripsTicket(goodsDonSku, userId, null, OrderDon.Type.EQUIPMENT);
+			relationId = relation.getId();
+			orderId = relation.getOrderId();
+		} else {
+			Date expiryTime = groupsRelationView.getExpiryTime();
+			if (expiryTime == null) {
+				throw BusinessRuntimeException.getInstance("该车位暂未发车,请发车后再领取权益");
+			}
+			DateTime updateExpiryTime = DateUtil.offset(expiryTime, DateField.MONTH, goodsDonSku.getMonths());
+			groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+					.eq(GroupsRelation::getId, groupsRelationView.getId())
+					.eq(GroupsRelation::getUserId, userId)
+					.set(GroupsRelation::getExpiryTime, updateExpiryTime));
+			groupsRelationView.setUpdateExpiryTime(updateExpiryTime);
+			relationId = groupsRelationView.getId();
+		}
+		//记录领取记录
+		saveReceiveBenefitsRecord(userId, skuId, goodsDonSku.getMonths(), relationId, orderId, 1);
+		return groupsRelationView;
+	}
+
+	public void saveReceiveBenefitsRecord(Long userId, Long skuId, Integer num, Long relationId, Long orderId, Integer statusCode) {
+		EquipmentUserReceiveBenefitsRecord record = new EquipmentUserReceiveBenefitsRecord();
+		record.setUserId(userId);
+		record.setSkuId(skuId);
+		record.setNum(num);
+		record.setOrderId(orderId);
+		record.setRelationId(relationId);
+		record.setStatusCode(statusCode);
+		equipmentUserReceiveBenefitsRecordMapper.insert(record);
+	}
+}

+ 204 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/equipment/impl/EquipmentDistributeServiceImpl.java

@@ -0,0 +1,204 @@
+package com.cyksj.service.distribute.equipment.impl;
+
+import cn.hutool.core.date.DateField;
+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.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.mapper.manage.distribute.equipment.EquipmentUserChanceMapper;
+import com.cyksj.mapper.manage.distribute.equipment.EquipmentUserChanceRecordMapper;
+import com.cyksj.mapper.manage.distribute.equipment.EquipmentUserDistributeInviteRecordMapper;
+import com.cyksj.mapper.manage.distribute.equipment.EquipmentUserReceiveBenefitsRecordMapper;
+import com.cyksj.model.dto.EquipmentConfigDto;
+import com.cyksj.model.entity.*;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
+import com.cyksj.service.mange.coupon.CouponCommonService;
+import com.cyksj.service.relation.GroupRelationClearService;
+import com.cyksj.service.sys.SysConfigService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.Optional;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentDistributeServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/2/23 13:42
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class EquipmentDistributeServiceImpl implements EquipmentDistributeService {
+
+	private final EquipmentUserDistributeInviteRecordMapper inviteRecordMapper;
+
+	private final EquipmentUserChanceMapper equipmentUserChanceMapper;
+
+	private final EquipmentUserChanceRecordMapper equipmentUserChanceRecordMapper;
+
+	private final EquipmentUserReceiveBenefitsRecordMapper equipmentUserReceiveBenefitsRecordMapper;
+
+	private final GroupsRelationMapper groupsRelationMapper;
+
+	private final GroupRelationClearService groupRelationClearService;
+
+	private final SysConfigService sysConfigService;
+
+	private final CouponCommonService couponCommonService;
+
+	private final RedisService redisService;
+
+	private final OrderDonMapper orderDonMapper;
+
+	@Override
+	public void saveDistributionInvitation(Long sharedId, Boolean isNewUser, Long userId) {
+		if (sharedId.equals(userId)) {
+			return;
+		}
+		EquipmentUserDistributeInviteRecord exists = inviteRecordMapper.selectOne(Wrappers.lambdaQuery(EquipmentUserDistributeInviteRecord.class)
+				.eq(EquipmentUserDistributeInviteRecord::getUserId, userId).last("limit 1"));
+		if (exists == null) {
+			EquipmentUserDistributeInviteRecord record = new EquipmentUserDistributeInviteRecord();
+			record.setShareId(sharedId);
+			//存在分销
+			record.setUserId(userId);
+			try {
+				inviteRecordMapper.insert(record);
+				//发放新用户福利优惠券
+				if (isNewUser) {
+					sendInvitedUserEquipmentCoupon(userId);
+				}
+			} catch (DuplicateKeyException e) {
+				log.info("实物分销被邀请人id:{}重复插入", userId);
+			} catch (Exception e) {
+			}
+		}
+	}
+
+	@Override
+	public void addDistributeBenefitsChance(Long userId, Long orderId) {
+		EquipmentUserDistributeInviteRecord record = getDistributeRecord(userId);
+		if (record != null) {
+			Long sharId = record.getShareId();
+			if (saveInviteRecord(sharId, userId, orderId, EquipmentUserChanceRecord.Status.hasPayment)) {
+				EquipmentUserChance chance = equipmentUserChanceMapper.selectOne(Wrappers.lambdaQuery(EquipmentUserChance.class)
+						.eq(EquipmentUserChance::getUserId, sharId)
+						.last("limit 1"));
+				if (chance == null) {
+					try {
+						chance = new EquipmentUserChance();
+						chance.setUserId(sharId);
+						chance.setNum(1);
+						equipmentUserChanceMapper.insert(chance);
+					} catch (DuplicateKeyException e) {
+						equipmentUserChanceMapper.addUserChance(sharId);
+					}
+				} else {
+					equipmentUserChanceMapper.addUserChance(sharId);
+				}
+			}
+		}
+	}
+
+	@Override
+	public void subDistributeBenefitsChance(Long userId, Long orderId) {
+		EquipmentUserDistributeInviteRecord record = getDistributeRecord(userId);
+		if (record != null) {
+			Long sharId = record.getShareId();
+			if (saveInviteRecord(sharId, userId, orderId, EquipmentUserChanceRecord.Status.refund)) {
+				Integer update = equipmentUserChanceMapper.subUserChance(sharId);
+				if (update == 0) {
+					//扣除权益
+					deductUserBenefits(sharId, orderId);
+				}
+			}
+		}
+	}
+
+	public EquipmentUserDistributeInviteRecord getDistributeRecord(Long userId) {
+		//是否有实物分销邀请记录
+		EquipmentUserDistributeInviteRecord record = inviteRecordMapper.selectOne(Wrappers.lambdaQuery(EquipmentUserDistributeInviteRecord.class)
+				.eq(EquipmentUserDistributeInviteRecord::getUserId, userId)
+				.last("limit 1"));
+		if (record == null) {
+			return null;
+		}
+		return record;
+	}
+
+	public Boolean saveInviteRecord(Long sharId, Long userId, Long orderId, EquipmentUserChanceRecord.Status status) {
+		EquipmentUserChanceRecord record = equipmentUserChanceRecordMapper.selectOne(Wrappers.lambdaQuery(EquipmentUserChanceRecord.class)
+				.eq(EquipmentUserChanceRecord::getUserId, userId)
+				.eq(EquipmentUserChanceRecord::getStatus, status)
+				.eq(EquipmentUserChanceRecord::getOrderId, orderId)
+				.last("limit 1"));
+		if (record != null) {
+			return false;
+		}
+		record = new EquipmentUserChanceRecord();
+		record.setShareId(sharId);
+		record.setUserId(userId);
+		record.setStatus(status);
+		record.setOrderId(orderId);
+		equipmentUserChanceRecordMapper.insert(record);
+		return true;
+	}
+
+	public void deductUserBenefits(Long userId, Long orderId) {
+		EquipmentUserReceiveBenefitsRecord receiveBenefitsRecord = equipmentUserReceiveBenefitsRecordMapper.selectOne(Wrappers.lambdaQuery(EquipmentUserReceiveBenefitsRecord.class)
+				.eq(EquipmentUserReceiveBenefitsRecord::getStatusCode, 1)
+				.eq(EquipmentUserReceiveBenefitsRecord::getUserId, userId)
+				.orderByDesc(EquipmentUserReceiveBenefitsRecord::getId).last("limit 1"));
+		if (receiveBenefitsRecord == null) {
+			return;
+		}
+		Integer months = receiveBenefitsRecord.getNum();
+		Long relationId = receiveBenefitsRecord.getRelationId();
+		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"));
+		Date expiryTime = relation.getExpiryTime();
+		if (relation == null || expiryTime == null) {
+			return;
+		}
+		DateTime now = DateTime.now();
+		Date finalDate = DateUtil.offset(expiryTime, DateField.MONTH, -months);
+		if (now.isAfter(finalDate)) {
+			//过期 直接清除车票
+			groupRelationClearService.clearTicket(relation);
+		} else {
+			relation.setExpiryTime(finalDate);
+			groupsRelationMapper.updateById(relation);
+		}
+		Optional.ofNullable(receiveBenefitsRecord.getOrderId()).ifPresent(selfOrderId->{
+			orderDonMapper.update(null, Wrappers.lambdaUpdate(OrderDon.class).eq(OrderDon::getId, selfOrderId)
+					.set(OrderDon::getStatus, OrderDon.Status.refund));
+		});
+		receiveBenefitsRecord.setRefundOrderId(orderId);
+		equipmentUserReceiveBenefitsRecordMapper.updateById(receiveBenefitsRecord);
+	}
+
+	public void sendInvitedUserEquipmentCoupon(Long userId) throws Exception {
+		SysConfig config = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.EQUIPMENT_DISTRIBUTE_KEY).last("limit 1"));
+		Optional.ofNullable(config).ifPresent(cf->{
+			EquipmentConfigDto equipmentConfigDto = null;
+			try {
+				equipmentConfigDto = Jsons.parseObject(config.getSysValue(), EquipmentConfigDto.class);
+				equipmentConfigDto.getCouponIds().forEach(couponId->{
+					couponCommonService.sendCouponToUser(userId, couponId, null, null, null, CouponUser.Channel.equipment);
+				});
+				redisService.set(RedisService.key.EQUIPMENT_DISTRIBUTE_COUPON_KEY.getNameFormat(userId), userId, RedisService.key.EQUIPMENT_DISTRIBUTE_COUPON_KEY.getTimeout());
+			} catch (Exception e) {
+			}
+		});
+	}
+}

+ 8 - 0
netflix-service/src/main/java/com/cyksj/service/exchange/ExchangeCodeService.java

@@ -3,6 +3,9 @@ package com.cyksj.service.exchange;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.cyksj.dto.Result;
 import com.cyksj.model.entity.ExchangeCode;
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.entity.GroupsRelation;
+import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.excel.ExcelExchangeCodeData;
 import com.cyksj.model.request.ExchangeCodeReq;
 import com.cyksj.model.request.ExchangeCodeTicket;
@@ -30,4 +33,9 @@ public interface ExchangeCodeService extends IService<ExchangeCode> {
 	 * 获取兑换码
 	 */
 	String getExCode(Long goodsId, Long skuId, Integer type);
+
+	/**
+	 * 获取车票
+	 */
+	GroupsRelation getGroupTripsTicket(GoodsDonSku sku, Long userId, OrderDon exCodeOrderDon, OrderDon.Type orderDonTye);
 }

+ 8 - 5
netflix-service/src/main/java/com/cyksj/service/exchange/impl/ExchangeCodeServiceImpl.java

@@ -154,7 +154,7 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 			throw BusinessRuntimeException.getInstance("您的订单已退款,无法使用该兑换码");
 		}
 		//生成车票订单
-		getGroupTripsTicket(goodsDonSkuMapper.selectById(exchangeCode.getSkuId()), userId, orderDon);
+		getGroupTripsTicket(goodsDonSkuMapper.selectById(exchangeCode.getSkuId()), userId, orderDon, OrderDon.Type.EX_CODE);
 		log.info("用户:{}通过兑换码:{}兑换成功", userId, exchangeCodeTicket.getCode());
 		if (exchangeCode.getType() == 1) {
 			luckyDrawRecordMapper.updateExCodeStatus(userId, exchangeCode.getCode());
@@ -211,7 +211,8 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 	/**
 	 * 获取车位
 	 */
-	private void getGroupTripsTicket(GoodsDonSku sku, Long userId, OrderDon exCodeOrderDon) {
+	@Override
+	public GroupsRelation getGroupTripsTicket(GoodsDonSku sku, Long userId, OrderDon exCodeOrderDon, OrderDon.Type orderDonTye) {
 		if (sku == null) {
 			throw BusinessRuntimeException.getInstance("规格不存在,请联系客服");
 		}
@@ -248,7 +249,7 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 			setRelation(relation.getId(), userId);
 		} catch (Exception e) {
 			//失败重新给他分配车位
-			getGroupTripsTicket(sku, userId, exCodeOrderDon);
+			getGroupTripsTicket(sku, userId, exCodeOrderDon, orderDonTye);
 		}
 		relation.setUserId(userId);
 		relation.setStatus(GroupsRelation.Status.validity);
@@ -280,7 +281,7 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 			orderDon.setGoodsId(sku.getGoodsId());
 			orderDon.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
 			//兑换码兑换
-			orderDon.setType(OrderDon.Type.EX_CODE);
+			orderDon.setType(orderDonTye);
 			orderDon.setUserId(user.getId());
 			orderDonMapper.insert(orderDon);
 		}
@@ -290,7 +291,7 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 				try {
 					if (StrUtil.isNotEmpty(user.getOpenId())) {
 						log.info("用户{}兑换车位成功,发送新订单模板消息", user.getId());
-						templateCommonService.newOderSendMsgByType(orderDon, goodsDon, sku, user,user.getOpenId());
+						templateCommonService.newOderSendMsgByType(orderDon, goodsDon, sku, user, user.getOpenId());
 					}
 				} catch (Exception e) {
 					log.info("用户{}兑换车位成功,发送消息失败:{}", user.getId(), e);
@@ -310,6 +311,8 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 				log.error("向客服发送用户{}兑换码兑换车票成功,发送消息失败:{}", user.getId(), e);
 			}
 		});
+		relation.setOrderId(orderDon.getId());
+		return relation;
 	}
 
 	private void setRelation(Long relationId, Long userId) {

+ 14 - 1
netflix-service/src/main/java/com/cyksj/service/gzh/factory/EventMsgService.java

@@ -20,6 +20,7 @@ import com.cyksj.model.entity.WxApp;
 import com.cyksj.model.entity.WxSyncLog;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.distribute.DistributeService;
+import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
 import com.cyksj.service.user.UserService;
 import com.cyksj.service.wechat.WeChatService;
 import lombok.RequiredArgsConstructor;
@@ -51,6 +52,8 @@ public class EventMsgService implements GzhMsgService {
 
 	private final DistributeService distributeService;
 
+	private final EquipmentDistributeService equipDistributeService;
+
 	private final UserService userService;
 
 	private final WeChatConfig weChatConfig;
@@ -117,7 +120,9 @@ public class EventMsgService implements GzhMsgService {
 				}
 			}
 		}
+		Boolean isNewUser = false;
 		if (user == null) {
+			isNewUser = true;
 			user = new User();
 			user.setNickname(String.format("%s%s", Constant.DEFAULT_NAME, Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.MD5).setStringData(RandomUtil.randomString(10)).toHexString().substring(0, 6)))
 					.setSex(info.getSex())
@@ -155,10 +160,18 @@ public class EventMsgService implements GzhMsgService {
 		if (StrUtil.isNotEmpty(sceneKey)) {
 			redisService.set(RedisService.key.WX_GZH_QRCODE_LOGIN.getNameFormat(sceneKey), user.getId(), RedisService.key.WX_GZH_QRCODE_LOGIN.getTimeout());
 		}
+		if (gzhDto != null) {
+			Long sharedId = gzhDto.getSharedId();
+			Integer dsType = gzhDto.getDsType();
+			//新旧用户都可实物分销
+			if (dsType != null && dsType == 2) {
+				equipDistributeService.saveDistributionInvitation(sharedId, isNewUser, user.getId());
+			}
+		}
 		return true;
 	}
 
-	private void saveGzhUserRelation(MsgEvent msgEvent, Long userId, String openId, String unionid,String sceneKey) {
+	private void saveGzhUserRelation(MsgEvent msgEvent, Long userId, String openId, String unionid, String sceneKey) {
 		WxApp wxApp = wxAppMapper.selectOne(Wrappers.lambdaQuery(WxApp.class)
 				.eq(WxApp::getGzhOriginalId, msgEvent.getToUserName()).last("limit 1"));
 		if (wxApp != null) {

+ 16 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -55,6 +55,7 @@ import com.cyksj.model.views.CouponNewUserView;
 import com.cyksj.model.views.CouponUserView;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.coupon.CouponFontService;
+import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
 import com.cyksj.service.exchange.ExchangeCodeService;
 import com.cyksj.service.mange.stock.GoodsDonStockService;
 import com.cyksj.service.market.MarketFrontService;
@@ -171,6 +172,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final MarketFrontService marketFrontService;
 
+	private final EquipmentDistributeService equipmentDistributeService;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -492,6 +495,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		TASK_POOL.execute(() -> {
 			try {
 				marketFrontService.addSpecificChanceNum(order.getUserId(), order.getId(), order.getGoodsId(), order.getSkuId());
+				if (goodsDon.getType() == 2) {
+					equipmentDistributeService.addDistributeBenefitsChance(order.getUserId(), order.getId());
+				}
 			} catch (Exception e) {
 				log.error("wx增加抽奖机会错误,orderId:{},error:{}", order.getId(), e);
 			}
@@ -763,6 +769,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		TASK_POOL.execute(() -> {
 			try {
 				marketFrontService.addSpecificChanceNum(orderDon.getUserId(), orderDon.getId(), orderDon.getGoodsId(), orderDon.getSkuId());
+				if (goodsDon.getType() == 2) {
+					equipmentDistributeService.addDistributeBenefitsChance(orderDon.getUserId(), orderDon.getId());
+				}
 			} catch (Exception e) {
 				log.error("zfb增加抽奖机会错误,orderId:{},error:{}", orderDon.getId(), e);
 			}
@@ -895,6 +904,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				goodsDonStockService.upStockRelate(null, orderDon.getId(),"refund");
 				try {
 					marketFrontService.subSpecificChanceNum(orderDon.getUserId(), orderDon.getId(), orderDon.getGoodsId(), orderDon.getUpdateTime());
+					if (goodsDon.getType() == 2) {
+						equipmentDistributeService.subDistributeBenefitsChance(orderDon.getUserId(), orderDon.getId());
+					}
 				} catch (Exception e) {
 					log.error("zfb减少抽奖机会错误,orderId:{},error:{}", orderDon.getId(), e);
 				}
@@ -1093,6 +1105,10 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		TASK_POOL.execute(()->{
 			try {
 				marketFrontService.subSpecificChanceNum(orderDon.getUserId(), orderDon.getId(), orderDon.getGoodsId(), orderDon.getUpdateTime());
+				GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
+				if (goodsDon.getType() == 2) {
+					equipmentDistributeService.subDistributeBenefitsChance(orderDon.getUserId(), orderDon.getId());
+				}
 			} catch (Exception e) {
 				log.error("wx减少抽奖机会错误,orderId:{},error:{}", orderDon.getId(), e);
 			}

+ 17 - 0
netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationClearService.java

@@ -0,0 +1,17 @@
+package com.cyksj.service.relation;
+
+import com.cyksj.model.entity.GroupsRelation;
+
+/*
+ *项目名: netflix
+ *文件名: GroupRelationClearService
+ *创建者: JavaZou
+ *创建时间:2023/2/23 15:31
+ */
+public interface GroupRelationClearService {
+
+	/**
+	 * 清除车票
+	 */
+	void clearTicket(GroupsRelation relation);
+}

+ 73 - 0
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationClearServiceImpl.java

@@ -0,0 +1,73 @@
+package com.cyksj.service.relation.impl;
+
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.GroupsMapper;
+import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.UserTicketClearedRecordMapper;
+import com.cyksj.model.entity.GroupsRelation;
+import com.cyksj.model.entity.UserTicketClearedRecord;
+import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.service.relation.GroupRelationClearService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: GroupRelationClearServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/2/23 15:31
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class GroupRelationClearServiceImpl implements GroupRelationClearService {
+	private final GroupsRelationMapper groupsRelationMapper;
+
+	private final GroupsMapper groupsMapper;
+
+	private final BeanSearcher beanSearcher;
+
+	private final UserTicketClearedRecordMapper userTicketClearedRecordMapper;
+
+	@Override
+	public void clearTicket(GroupsRelation relation) {
+			Long relationId = relation.getId();
+			Long userId = relation.getUserId();
+			Date startTime = relation.getStartTime();
+			Date expireTime = relation.getExpiryTime();
+			relation.setStartTime(null);
+			relation.setExpiryTime(null);
+			relation.setUserId(0l);
+			relation.setStatus(GroupsRelation.Status.none);
+			relation.setIsHandle(false);
+			relation.setRenewStatus(false);
+			relation.setAccount(null);
+			Integer success = groupsRelationMapper.updateExpiryTime(relation, expireTime);
+			if (success == 1) {
+				log.info("开始清除过期子账号,座位号:{}", relation.getId());
+				int count = groupsMapper.incrAvailableNum(relation.getGroupsId());
+				if (count == 0) {
+					log.error("车位异常 groupId:{}", relation.getGroupsId());
+					throw new BusinessRuntimeException("车位异常");
+				}
+				//记录用户被清除车票历史记录
+				GroupsRelationView groupsTrips = beanSearcher.searchFirst(GroupsRelationView.class,
+						MapUtils.builder().field(GroupsRelationView::getId, relationId).build());
+				if (groupsTrips != null) {
+					UserTicketClearedRecord userTicketClearedRecord = new UserTicketClearedRecord();
+					userTicketClearedRecord.setRelationId(relationId);
+					userTicketClearedRecord.setUserId(userId);
+					userTicketClearedRecord.setGoodsId(groupsTrips.getGoodsId());
+					userTicketClearedRecord.setSkuId(groupsTrips.getSkuId());
+					userTicketClearedRecord.setStartTime(startTime);
+					userTicketClearedRecord.setExpiryTime(expireTime);
+					userTicketClearedRecordMapper.insert(userTicketClearedRecord);
+				}
+			}
+	}
+}

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

@@ -4,6 +4,7 @@ import cn.hutool.core.date.DateTime;
 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.mapper.UserMapper;
 import com.cyksj.mapper.corp.CorpUserMapper;
 import com.cyksj.mapper.market.task.UserBindPhoneMapper;
@@ -45,6 +46,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 	@Override
 	public List<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize) {
 		User u = userMapper.selectById(userId);
+		if (u == null) throw BusinessRuntimeException.getInstance("用户信息失效,请重新登录");
 		Boolean isPcUser = false;
 		if (StrUtil.isNotBlank(u.getLoginPhone())) {
 			isPcUser = true;

+ 43 - 34
netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java

@@ -16,6 +16,7 @@ import com.cyksj.model.entity.User;
 import com.cyksj.model.entity.UserTransferLog;
 import com.cyksj.model.entity.WxSyncLog;
 import com.cyksj.service.distribute.DistributeService;
+import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
 import com.cyksj.service.user.UserService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -40,6 +41,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 
     private final DistributeService distributeService;
 
+    private final EquipmentDistributeService equipDistributeService;
+
     @Override
     public User saveAuth(GzhOAuth2UserInfo info, Long sharedId, Integer dsType, Long pid) {
         final String unionid = info.getUnionid();
@@ -50,44 +53,50 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                 .eq(WxSyncLog::getToAppid, weChatConfig.getAppid())
                 .eq(WxSyncLog::getNewOpenid, info.getOpenid()).last("limit 1"));
 
-        User user = getSyncUser(info.getOpenid(), info.getUnionid(), wxSyncLog);
+		User user = getSyncUser(info.getOpenid(), info.getUnionid(), wxSyncLog);
 
-        user = Optional.ofNullable(user).orElseGet(() -> new User()
-                .setUnionid(unionid));
-        user.setNickname(info.getNickname())
-                .setSex(info.getSex())
-                .setCountry(info.getCountry())
-                .setProvince(info.getProvince())
-                .setCity(info.getCity())
-                .setHeadimgurl(info.getHeadimgurl());
-        if (!user.getUnionid().equals(unionid)) {
-            UserTransferLog log = new UserTransferLog();
-            if (wxSyncLog != null) {
-                log.setType("公众号迁移");
-            } else {
-                log.setType("绑定开发者账号");
-            }
-            log.setOldAppId(weChatConfig.getOldAppid());
-            log.setNewAppId(weChatConfig.getAppid());
-            log.setUserId(user.getId());
-            log.setOldUnionid(user.getUnionid());
-            log.setNewUnionid(info.getUnionid());
-            userTransferLogMapper.insert(log);
-        }
-        user.setUnionid(unionid);
-        user.setOpenId(info.getOpenid());
+		user = Optional.ofNullable(user).orElseGet(() -> new User()
+				.setUnionid(unionid));
+		user.setNickname(info.getNickname())
+				.setSex(info.getSex())
+				.setCountry(info.getCountry())
+				.setProvince(info.getProvince())
+				.setCity(info.getCity())
+				.setHeadimgurl(info.getHeadimgurl());
+		if (!user.getUnionid().equals(unionid)) {
+			UserTransferLog log = new UserTransferLog();
+			if (wxSyncLog != null) {
+				log.setType("公众号迁移");
+			} else {
+				log.setType("绑定开发者账号");
+			}
+			log.setOldAppId(weChatConfig.getOldAppid());
+			log.setNewAppId(weChatConfig.getAppid());
+			log.setUserId(user.getId());
+			log.setOldUnionid(user.getUnionid());
+			log.setNewUnionid(info.getUnionid());
+			userTransferLogMapper.insert(log);
+		}
+		user.setUnionid(unionid);
+		user.setOpenId(info.getOpenid());
 
-        Boolean isNewUser = false;
-        if (user.getId() == null) {
-            isNewUser = true;
+		Boolean isNewUser = false;
+		if (user.getId() == null) {
+			isNewUser = true;
             user.setPopularizeId(pid);
         }
-        this.saveOrUpdate(user);
-        if (sharedId != null && isNewUser) {
-            distributeService.saveDistributionInvitation(sharedId, user.getId());
-        }
-        return user;
-    }
+		this.saveOrUpdate(user);
+		if (sharedId != null && isNewUser) {
+			if (dsType == null || dsType == 1) {
+				distributeService.saveDistributionInvitation(sharedId, user.getId());
+			}
+		}
+		//新旧用户都可实物分销
+		if (sharedId != null && dsType != null && dsType == 2) {
+			equipDistributeService.saveDistributionInvitation(sharedId, isNewUser, user.getId());
+		}
+		return user;
+	}
 
     @Override
     public UserWhoami whoami(long userId) {

+ 3 - 45
netflix-service/src/main/java/com/cyksj/task/Scheduler.java

@@ -5,7 +5,6 @@ import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.constant.TemplateEnum;
-import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.RedisKey;
 import com.cyksj.mapper.*;
@@ -13,16 +12,14 @@ import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
 import com.cyksj.model.dto.WxMpTemplateData;
 import com.cyksj.model.dto.WxMpTemplateMessage;
 import com.cyksj.model.entity.*;
-import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.views.WxAppTemplateView;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.order.OrderDonService;
 import com.cyksj.service.register.RegisterOrderDonService;
 import com.cyksj.service.register.SpotifyService;
+import com.cyksj.service.relation.GroupRelationClearService;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.wechat.WeChatService;
-import com.ejlchina.searcher.BeanSearcher;
-import com.ejlchina.searcher.util.MapUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.dao.DuplicateKeyException;
@@ -74,9 +71,7 @@ public class Scheduler {
 
         private final TemplateCommonService templateCommonService;
 
-        private final UserTicketClearedRecordMapper userTicketClearedRecordMapper;
-
-        private final BeanSearcher beanSearcher;
+        private final GroupRelationClearService groupRelationClearService;
 
 
     /**
@@ -89,7 +84,7 @@ public class Scheduler {
         List<GroupsRelation> expiryList = groupsRelationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class).le(GroupsRelation::getExpiryTime, now));
         log.info("定时清理过期账号start ===> 数量:{}", expiryList.size());
         //过期账号清楚有效期
-        expiryList.forEach(relation -> delRelation(relation));
+        expiryList.forEach(relation -> groupRelationClearService.clearTicket(relation));
     }
 
     @Scheduled(cron = "0 0 9 * * ?")
@@ -154,43 +149,6 @@ public class Scheduler {
 
     }
 
-    private void delRelation(GroupsRelation relation) {
-        Long relationId = relation.getId();
-        Long userId = relation.getUserId();
-        Date startTime = relation.getStartTime();
-        Date expireTime = relation.getExpiryTime();
-        relation.setStartTime(null);
-        relation.setExpiryTime(null);
-        relation.setUserId(0l);
-        relation.setStatus(GroupsRelation.Status.none);
-        relation.setIsHandle(false);
-        relation.setRenewStatus(false);
-        relation.setAccount(null);
-        Integer success = groupsRelationMapper.updateExpiryTime(relation, expireTime);
-        if (success == 1) {
-            log.info("开始清除过期子账号,座位号:{}", relation.getId());
-            int count = groupsMapper.incrAvailableNum(relation.getGroupsId());
-            if (count == 0) {
-                log.error("车位异常 groupId:{}", relation.getGroupsId());
-                throw new BusinessRuntimeException("车位异常");
-            }
-            //记录用户被清除车票历史记录
-            GroupsRelationView groupsTrips = beanSearcher.searchFirst(GroupsRelationView.class,
-                    MapUtils.builder().field(GroupsRelationView::getId, relationId).build());
-            if (groupsTrips != null) {
-                UserTicketClearedRecord userTicketClearedRecord = new UserTicketClearedRecord();
-                userTicketClearedRecord.setRelationId(relationId);
-                userTicketClearedRecord.setUserId(userId);
-                userTicketClearedRecord.setGoodsId(groupsTrips.getGoodsId());
-                userTicketClearedRecord.setSkuId(groupsTrips.getSkuId());
-                userTicketClearedRecord.setStartTime(startTime);
-                userTicketClearedRecord.setExpiryTime(expireTime);
-                userTicketClearedRecordMapper.insert(userTicketClearedRecord);
-            }
-        }
-    }
-
-
     /**
      * 定时关闭订单
      */

+ 12 - 0
netflix-web/src/main/java/com/cyksj/web/controller/coupon/CouponFrontController.java

@@ -266,4 +266,16 @@ public class CouponFrontController {
 		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult(dto);
 	}
+
+	/**
+	 * 查询优惠券
+	 */
+	@GetMapping("/get/couponList")
+	public Result<List<CouponView>> getCouponList(@RequestParam(value = "couponIds") List<Long> couponIds) {
+		if (couponIds.isEmpty()) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult();
+		}
+		List<CouponView> couponViews = beanSearcher.searchAll(CouponView.class, MapUtils.builder().field(CouponView::getId, couponIds).op(Operator.InList).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(couponViews);
+	}
 }

+ 233 - 0
netflix-web/src/main/java/com/cyksj/web/controller/distribute/EquipmentDistributeController.java

@@ -0,0 +1,233 @@
+package com.cyksj.web.controller.distribute;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.EnvCommonService;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.manage.distribute.equipment.EquipmentUserChanceMapper;
+import com.cyksj.mapper.manage.distribute.equipment.EquipmentUserDistributeInviteRecordMapper;
+import com.cyksj.model.dto.EquipmentConfigDto;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.model.request.LoginPhoneReq;
+import com.cyksj.model.request.ReceiveBenefitsReq;
+import com.cyksj.model.views.CouponUserView;
+import com.cyksj.model.views.EquipmentCouponView;
+import com.cyksj.model.views.EquipmentDistributeView;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.distribute.equipment.EquipmentDistributeFrontService;
+import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
+import com.cyksj.service.sys.SysConfigService;
+import com.cyksj.web.util.StpUserUtil;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentDistributeController
+ *创建者: JavaZou
+ *创建时间:2023/2/23 15:41
+ */
+@RestController
+@RequestMapping("/applets/equipment")
+@RequiredArgsConstructor
+public class EquipmentDistributeController {
+	private final EquipmentUserChanceMapper equipmentUserChanceMapper;
+
+	private final EnvCommonService envCommonService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final SysConfigService sysConfigService;
+
+	private final EquipmentDistributeFrontService equipmentDistributeFrontService;
+
+	private final RedisService redisService;
+
+	private final UserMapper userMapper;
+
+	private final OrderDonMapper orderDonMapper;
+
+	private final EquipmentDistributeService equipDistributeService;
+
+	private final EquipmentUserDistributeInviteRecordMapper inviteRecordMapper;
+
+	/**
+	 * 个人实物分销详情
+	 */
+	@GetMapping("/personal")
+	public Result<EquipmentDistributeView> getPersonalDetail() {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		EquipmentUserChance chance = equipmentUserChanceMapper.selectOne(Wrappers.lambdaQuery(EquipmentUserChance.class)
+				.eq(EquipmentUserChance::getUserId, userId).last("limit 1"));
+		EquipmentDistributeView view = new EquipmentDistributeView();
+		view.setNum(chance == null ? 0 : chance.getNum());
+		String equipDistributeUrl = String.format("%syinhe/web/detail/15?sharedId=%s&dsType=%s", envCommonService.getDomain(), userId, 2);
+		view.setUrl(equipDistributeUrl);
+		SysConfig config = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.EQUIPMENT_DISTRIBUTE_KEY).last("limit 1"));
+		if (config != null) {
+			view.setEquipmentConfig(config.getSysValue());
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(view);
+	}
+
+	/**
+	 * 邀请好友明细
+	 */
+	@GetMapping("/get/invite/record")
+	public Result<SearchResult<EquipmentUserChanceRecord>> getInviteRecord() {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		SearchResult<EquipmentUserChanceRecord> search = beanSearcher.search(EquipmentUserChanceRecord.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(EquipmentUserChanceRecord::getShareId, userId)
+				.build());
+		search.getDataList().forEach(data -> {
+			Optional.ofNullable(userMapper.selectById(data.getUserId())).ifPresent(user -> {
+				data.setNickname(user.getNickname());
+				data.setHeadImg(user.getHeadimgurl());
+			});
+			Optional.ofNullable(orderDonMapper.selectById(data.getOrderId())).ifPresent(oder -> data.setPayTime(oder.getPayTime()));
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 增加权益的车票
+	 */
+	@GetMapping("/get/benefits/ticket")
+	public Result<List<GroupsRelationView>> getBenefitsTicket() throws Exception {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		SysConfig config = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.EQUIPMENT_DISTRIBUTE_KEY).last("limit 1"));
+		List<Long> goodsIds = null;
+		if (config != null) {
+			String sysValue = config.getSysValue();
+			if (StrUtil.isNotBlank(sysValue)) {
+				goodsIds = Jsons.parseObject(sysValue, EquipmentConfigDto.class).getSkuList().stream().map(GoodsDonSku::getGoodsId).collect(Collectors.toList());
+			}
+		}
+		MapBuilder builder = MapUtils.builder()
+				.field(GroupsRelationView::getUserId, userId)
+				.field(GroupsRelationView::getGoodsType, 1)
+				.field(GroupsRelationView::getGoodsSecondType, 2)
+				.field(GroupsRelationView::getStatus, "validity")
+				.field(GroupsRelationView::getExpiryTime).op(Operator.NotNull);
+		if (!goodsIds.isEmpty()) {
+			builder.field(GroupsRelationView::getGoodsId, goodsIds).op(Operator.InList);
+		}
+		List<GroupsRelationView> list = beanSearcher.searchAll(GroupsRelationView.class, builder.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+	}
+
+	/**
+	 * 领取权益
+	 */
+	@PostMapping("/use/benefits")
+	public Result<GroupsRelationView> useBenefits(@RequestBody @Validated ReceiveBenefitsReq req) throws Exception {
+		Long goodsId = req.getGoodsId(), skuId = req.getSkuId(), relationId = req.getRelationId();
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		SysConfig config = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.EQUIPMENT_DISTRIBUTE_KEY).last("limit 1"));
+		String sysValue = config.getSysValue();
+		if (StrUtil.isEmpty(sysValue)) {
+			throw BusinessRuntimeException.getInstance("");
+		}
+		EquipmentConfigDto equipmentConfigDto = Jsons.parseObject(sysValue, EquipmentConfigDto.class);
+		Optional<GoodsDonSku> first = equipmentConfigDto.getSkuList().stream().filter(goodsDonSku -> {
+			if (goodsDonSku.getId().equals(skuId)) {
+				return true;
+			}
+			return false;
+		}).findFirst();
+		if (first.isEmpty()) {
+			throw BusinessRuntimeException.getInstance("暂无该车票权益");
+		}
+		GroupsRelationView groupsRelationView = equipmentDistributeFrontService.useBenefits(userId, goodsId, skuId, relationId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(groupsRelationView);
+	}
+
+	/**
+	 * 新用户领取后分销优惠券后弹窗
+	 */
+	@GetMapping("/get/couponList")
+	public Result<EquipmentCouponView> getEquipmentCouponList() {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		Object value = redisService.get(RedisService.key.EQUIPMENT_DISTRIBUTE_COUPON_KEY.getNameFormat(userId));
+		if (value != null) {
+			EquipmentCouponView equipmentCouponView = new EquipmentCouponView();
+			List<CouponUserView> couponUserViews = beanSearcher.searchAll(CouponUserView.class, MapUtils.builder()
+					.field(CouponUserView::getUserId, userId)
+					.field(CouponUserView::getChannel, CouponUser.Channel.equipment.name())
+					.orderBy(CouponUserView::getOrderBy).asc()
+					.build());
+			EquipmentUserDistributeInviteRecord record = inviteRecordMapper.selectOne(Wrappers.lambdaQuery(EquipmentUserDistributeInviteRecord.class)
+					.eq(EquipmentUserDistributeInviteRecord::getUserId, userId).last("limit 1"));
+			if (record != null) {
+				User user = userMapper.selectById(record.getShareId());
+				Optional.ofNullable(user).ifPresent(u->{
+					equipmentCouponView.setNickname(u.getNickname());
+					equipmentCouponView.setUserId(u.getId());
+					equipmentCouponView.setHeadImg(u.getHeadimgurl());
+				});
+			}
+			equipmentCouponView.setCouponList(couponUserViews);
+			return GatewayResponse.SUCCESS.newBuilder().toResult(equipmentCouponView);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 已登录的用户 实物分销
+	 */
+	@PostMapping("/hasLogged")
+	public Result<String> hasLogged(@RequestBody LoginPhoneReq req) {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		DateTime now = DateTime.now();
+		User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getId, userId)
+				.between(User::getCreatedTime, DateUtil.beginOfDay(now), DateUtil.endOfDay(now)).last("limit 1"));
+		Boolean isNewUser = user != null ? true : false;
+		Long sharedId = req.getSharedId();
+		Integer dsType = req.getDsType();
+		//新旧用户都可实物分销
+		if (sharedId != null && dsType != null && dsType == 2) {
+			equipDistributeService.saveDistributionInvitation(sharedId, isNewUser, user.getId());
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 是否是新用户
+	 */
+	@GetMapping("/get/isNewUser")
+	public Result<Boolean> isNewUser() {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		DateTime now = DateTime.now();
+		User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getId, userId)
+				.between(User::getCreatedTime, DateUtil.beginOfDay(now), DateUtil.endOfDay(now)).last("limit 1"));
+		if (user == null) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult(false);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(true);
+	}
+}

+ 15 - 6
netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java

@@ -16,14 +16,12 @@ import com.cyksj.model.views.GoodsDonSkuView;
 import com.cyksj.model.views.GoodsDonViews;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.SearchResult;
+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;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
@@ -172,6 +170,17 @@ public class GoodsDonController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(views);
     }
 
-
-
+    /**
+     * 获取商品多规格列表
+     */
+    @GetMapping("/get/sku")
+    public Result<List<GoodsDonSkuView>> getGoodsDonSkuView(@RequestParam(value = "skuIds") List<Long> skuIds) {
+        if (skuIds.isEmpty()) {
+            return GatewayResponse.SUCCESS.newBuilder().toResult();
+        }
+        List<GoodsDonSkuView> views = beanSearcher.searchAll(GoodsDonSkuView.class, MapUtils.builder()
+                .field(GoodsDonSkuView::getSkuId, skuIds).op(Operator.InList)
+                .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(views);
+    }
 }

+ 85 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/EquipmentController.java

@@ -0,0 +1,85 @@
+package com.cyksj.web.controller.manage.distribute;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.manage.coupon.CouponMapper;
+import com.cyksj.mapper.manage.distribute.equipment.EquipmentUserChanceRecordMapper;
+import com.cyksj.model.entity.EquipmentUserChanceRecord;
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.entity.User;
+import com.cyksj.model.views.EquipmentBenefitsView;
+import com.cyksj.model.views.EquipmentUserDistributeDetailView;
+import com.cyksj.model.views.EquipmentUserDistributeViews;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Optional;
+
+/*
+ *项目名: netflix
+ *文件名: EquipmentController
+ *创建者: JavaZou
+ *创建时间:2023/2/24 9:39
+ */
+@RestController
+@RequestMapping("/manage/equipment/distribute")
+@RequiredArgsConstructor
+public class EquipmentController {
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final UserMapper userMapper;
+
+	private final CouponMapper couponMapper;
+
+	private final EquipmentUserChanceRecordMapper equipmentUserChanceRecordMapper;
+
+	private final GoodsDonSkuMapper goodsDonSkuMapper;
+
+	/**
+	 * 实物分销列表
+	 */
+	@GetMapping("/get")
+	public Result<SearchResult<EquipmentUserDistributeViews>> getEquipmentDistribute() {
+		SearchResult<EquipmentUserDistributeViews> search = beanSearcher.search(EquipmentUserDistributeViews.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		search.getDataList().forEach(data->{
+			User user = userMapper.selectById(data.getShareId());
+			Optional.ofNullable(user).ifPresent(u -> data.setNickname(u.getNickname()));
+			data.setRecordNum(equipmentUserChanceRecordMapper.selectCount(Wrappers.lambdaQuery(EquipmentUserChanceRecord.class)
+					.eq(EquipmentUserChanceRecord::getShareId, data.getShareId())));
+			data.setBenefitsViews(beanSearcher.searchAll(EquipmentBenefitsView.class, MapUtils.builder().field(EquipmentBenefitsView::getSharId, data.getShareId()).build()));
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 分销明细
+	 */
+	@GetMapping("/get/detail/{shareId}")
+	public Result<SearchResult<EquipmentUserDistributeDetailView>> getDistributeDetail(@PathVariable Long shareId) {
+		SearchResult<EquipmentUserDistributeDetailView> search = beanSearcher.search(EquipmentUserDistributeDetailView.class,
+				MapUtils.flatBuilder(request.getParameterMap())
+						.field(EquipmentUserDistributeDetailView::getShareId, shareId)
+						.build());
+		search.getDataList().forEach(data -> {
+			User user = userMapper.selectById(data.getUserId());
+			Optional.ofNullable(user).ifPresent(u -> data.setNickname(u.getNickname()));
+			String couponName = couponMapper.getCouponNameByCouponUserId(data.getCouponUserId());
+			data.setCouponName(couponName);
+			GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(data.getSkuId());
+			Optional.ofNullable(goodsDonSku).ifPresent(sku -> data.setSpecVal(sku.getSpecVal()));
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+}

+ 3 - 0
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -34,6 +34,7 @@ import com.cyksj.model.response.WxGzhQrCodeTicketRep;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.authorization.AuthorizationService;
 import com.cyksj.service.distribute.DistributeService;
+import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
 import com.cyksj.service.template.TemplateCommonService;
 import com.cyksj.service.user.UserService;
 import com.cyksj.service.wechat.WeChatService;
@@ -90,6 +91,8 @@ public class AuthorizationController {
 
     private final DistributeService distributeService;
 
+    private final EquipmentDistributeService equipDistributeService;
+
     @GetMapping(value = "/weChat")
     public void base(String url, Long sharedId, Integer dsType, Long popularizeId, String authType, HttpServletResponse response) throws Exception {