瀏覽代碼

Merge branch 'distribute'

# Conflicts:
#	netflix-service/src/main/java/com/cyksj/service/mange/statistics/impl/StatisticsDataServiceImpl.java
zoujiajian 3 年之前
父節點
當前提交
57f9428a1e
共有 49 個文件被更改,包括 1641 次插入22 次删除
  1. 8 0
      netflix-dao/src/main/java/com/cyksj/mapper/UserMapper.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/DistributeMoneyApplyMapper.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/DistributePointsExchangeMoneyMapper.java
  4. 18 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/DistributeWaitingSendPointsMapper.java
  5. 14 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/UserDistributeMapper.java
  6. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/UserDistributeSharedMapper.java
  7. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/UserPlatDistributeRateMapper.java
  8. 10 0
      netflix-dao/src/main/java/com/cyksj/model/entity/AbstractBackData.java
  9. 65 0
      netflix-dao/src/main/java/com/cyksj/model/entity/DistributeMoneyApply.java
  10. 28 0
      netflix-dao/src/main/java/com/cyksj/model/entity/DistributePointsExchangeMoney.java
  11. 54 0
      netflix-dao/src/main/java/com/cyksj/model/entity/DistributeWaitingSendPoints.java
  12. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java
  13. 10 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java
  14. 3 0
      netflix-dao/src/main/java/com/cyksj/model/entity/User.java
  15. 25 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserDistribute.java
  16. 24 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserDistributeShared.java
  17. 27 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserPlatDistributeRate.java
  18. 4 1
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSpuInsert.java
  19. 5 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/GoodsDonViewer.java
  20. 19 2
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UserView.java
  21. 21 0
      netflix-dao/src/main/java/com/cyksj/model/request/ApplyMoneyReq.java
  22. 32 0
      netflix-dao/src/main/java/com/cyksj/model/request/DistributeApplyMoneyReq.java
  23. 5 0
      netflix-dao/src/main/java/com/cyksj/model/request/LoginPhoneReq.java
  24. 31 0
      netflix-dao/src/main/java/com/cyksj/model/request/UserDistributeReq.java
  25. 42 1
      netflix-dao/src/main/java/com/cyksj/model/views/BackgroundDataView.java
  26. 57 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributeMoneyApplyView.java
  27. 36 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributeOrdersView.java
  28. 64 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributePopularizeOrdersView.java
  29. 46 0
      netflix-dao/src/main/java/com/cyksj/model/views/DistributePopularizeView.java
  30. 21 0
      netflix-dao/src/main/java/com/cyksj/model/views/MoneyApplyView.java
  31. 35 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeView.java
  32. 57 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeViews.java
  33. 3 1
      netflix-dao/src/main/resources/mapper/AppleOneDataMapper.xml
  34. 1 1
      netflix-dao/src/main/resources/mapper/OrderDonMapper.xml
  35. 3 1
      netflix-dao/src/main/resources/mapper/StreamingAccountDataMapper.xml
  36. 15 0
      netflix-dao/src/main/resources/mapper/UserDistributeMapper.xml
  37. 15 0
      netflix-service/src/main/java/com/cyksj/service/distribute/DistributeService.java
  38. 78 0
      netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java
  39. 56 4
      netflix-service/src/main/java/com/cyksj/service/mange/statistics/impl/StatisticsDataServiceImpl.java
  40. 96 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  41. 1 1
      netflix-service/src/main/java/com/cyksj/service/user/UserService.java
  42. 22 2
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
  43. 47 0
      netflix-service/src/main/java/com/cyksj/task/Scheduler.java
  44. 11 3
      netflix-service/src/main/java/com/cyksj/task/StatisticsDataScheduler.java
  45. 10 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsUserController.java
  46. 238 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributeController.java
  47. 23 4
      netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java
  48. 203 0
      netflix-web/src/main/java/com/cyksj/web/controller/user/DistributePopularizeController.java
  49. 1 1
      netflix-web/src/main/resources/application.yml

+ 8 - 0
netflix-dao/src/main/java/com/cyksj/mapper/UserMapper.java

@@ -5,6 +5,8 @@ import com.cyksj.model.entity.User;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Update;
 
+import java.math.BigDecimal;
+
 /**
  * @author chan
  * @date 2021/10/10 下午3:28
@@ -16,4 +18,10 @@ public interface UserMapper extends BaseMapper<User> {
 
     @Update("update user set lottery_time = lottery_time + 1 where id = #{id}")
     void incrLotteryTime(@Param("id") Long userId);
+
+    @Update("update user set points = points - #{points} where id = #{id} and points >= #{points} and points > 0")
+    Integer subPoints(@Param("id") Long id, @Param("points") BigDecimal points);
+
+    @Update("update user set points = points + #{addPoints} where id = #{id} and points = #{originalPoints} and points >=0")
+    Integer updatePoints(@Param("id") Long id, @Param("originalPoints") BigDecimal originalPoints, @Param("addPoints") BigDecimal addPoints);
 }

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.distribute;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.DistributeMoneyApply;
+
+/*
+ *项目名: netflix
+ *文件名: DistributeMoneyApplyMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/14 14:00
+ */
+public interface DistributeMoneyApplyMapper extends BaseMapper<DistributeMoneyApply> {
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.distribute;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.DistributePointsExchangeMoney;
+
+/*
+ *项目名: netflix
+ *文件名: DistributePointsExchangeMoneyMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/14 15:55
+ */
+public interface DistributePointsExchangeMoneyMapper extends BaseMapper<DistributePointsExchangeMoney> {
+}

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/DistributeWaitingSendPointsMapper.java

@@ -0,0 +1,18 @@
+package com.cyksj.mapper.manage.distribute;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.DistributeWaitingSendPoints;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+/*
+ *项目名: netflix
+ *文件名: DistributeWaitingSendPointsMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/15 12:10
+ */
+public interface DistributeWaitingSendPointsMapper extends BaseMapper<DistributeWaitingSendPoints> {
+
+	@Update("update distribute_waiting_send_points set send_status = #{status} where order_id = #{orderId}")
+	void updateOrderStatus(@Param("orderId") Long orderId, @Param("status") DistributeWaitingSendPoints.Status status);
+}

+ 14 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/distribute/UserDistributeMapper.java

@@ -0,0 +1,14 @@
+package com.cyksj.mapper.manage.distribute;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserDistribute;
+
+/*
+ *项目名: netflix
+ *文件名: UserDistributeMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/14 12:18
+ */
+public interface UserDistributeMapper extends BaseMapper<UserDistribute> {
+	Integer count(Long userId);
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.distribute;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserDistributeShared;
+
+/*
+ *项目名: netflix
+ *文件名: UserDistributeSharedMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/15 11:51
+ */
+public interface UserDistributeSharedMapper extends BaseMapper<UserDistributeShared> {
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.manage.distribute;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserPlatDistributeRate;
+
+/*
+ *项目名: netflix
+ *文件名: UserPlatDistributeRateMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/14 12:23
+ */
+public interface UserPlatDistributeRateMapper extends BaseMapper<UserPlatDistributeRate> {
+}

+ 10 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/AbstractBackData.java

@@ -52,6 +52,16 @@ public abstract class AbstractBackData {
 	 */
 	private Integer numOfYearOrder;
 
+	/**
+	 * 分销单数
+	 */
+	private Integer numOfDistributeOrder;
+
+	/**
+	 * 分销金额
+	 */
+	private BigDecimal distributeOrderMoney;
+
 	private Date statisticsDate;
 
 	/**

+ 65 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/DistributeMoneyApply.java

@@ -0,0 +1,65 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+
+/*
+ *项目名: netflix
+ *文件名: DistributeMoneyApply
+ *创建者: JavaZou
+ *创建时间:2022/11/14 14:00
+ */
+@Getter
+@Setter
+public class DistributeMoneyApply extends BaseEntity {
+
+	private Long userId;
+
+	private BigDecimal money;
+
+	private String reason;
+
+	private BigDecimal points;
+
+	private Status verifyStatus;
+
+	private Type type;
+
+	private String account;
+
+	private String realName;
+
+	private String img;
+
+	@Getter
+	public enum Type {
+		zfb("支付宝"),
+		wechat("微信"),
+		;
+		String desc;
+
+		Type(String desc) {
+			this.desc = desc;
+		}
+	}
+
+	@Getter
+	public enum Status {
+		success("审核成功"),
+		fail("审核失败"),
+		verifying("审核中"),
+		;
+		String desc;
+
+		Status(String desc) {
+			this.desc = desc;
+		}
+
+		public static Status checkStatus(String status) {
+			return Arrays.stream(Status.values()).filter(st -> st.name().equals(status)).findFirst().orElse(null);
+		}
+	}
+}

+ 28 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/DistributePointsExchangeMoney.java

@@ -0,0 +1,28 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: DistributePointsExchangeMoney
+ *创建者: JavaZou
+ *创建时间:2022/11/14 15:56
+ */
+@Getter
+@Setter
+public class DistributePointsExchangeMoney extends BaseEntity{
+	/**
+	 * 积分门槛
+	 */
+	private Integer minPoints;
+
+	/**
+	 * 多少积分兑换金额
+	 */
+	private Integer points;
+
+	private BigDecimal money;
+}

+ 54 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/DistributeWaitingSendPoints.java

@@ -0,0 +1,54 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: DistributeWaitingSendPoints
+ *创建者: JavaZou
+ *创建时间:2022/11/15 12:11
+ */
+@Getter
+@Setter
+public class DistributeWaitingSendPoints extends BaseEntity{
+	/**
+	 * 分销订单产生用户id
+	 */
+	private Long userId;
+
+	/**
+	 * 积分待发人
+	 */
+	private Long sharedId;
+
+	private Long orderId;
+
+	private BigDecimal points;
+
+	/**
+	 * 退款状态不再发
+	 */
+	private Status sendStatus;
+
+	private Integer version;
+
+	private Date sendTime;
+
+	@Getter
+	public enum Status{
+		close("分销订单关闭,积分奖励不分发"),
+		success("积分发送成功"),
+		waiting("积分等待发送"),
+		not_exist("用户不存在,导致发送失败"),
+		;
+		String desc;
+
+		Status(String desc) {
+			this.desc = desc;
+		}
+	}
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java

@@ -72,6 +72,11 @@ public class GoodsDon extends BaseEntity {
 
     private String banner;
 
+    /**
+     * 平台分销比例
+     */
+    private Integer rate;
+
     @TableField(exist = false)
     @DbIgnore
     private Integer accountCount;

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

@@ -76,6 +76,16 @@ public class OrderDon extends BaseEntity implements Serializable {
      */
     private Date payTime;
 
+    /**
+     * 是否是分销订单
+     */
+    private Boolean isDistribute;
+
+    /**
+     * 是否是固定推广者分销
+     */
+    private Boolean isFixedDistribute;
+
     public enum Status {
         /**
          * 订单状态

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/User.java

@@ -5,6 +5,7 @@ import lombok.Setter;
 import lombok.experimental.Accessors;
 
 import java.io.Serializable;
+import java.math.BigDecimal;
 
 /**
  * @author chan
@@ -42,5 +43,7 @@ public class User extends BaseEntity implements Serializable{
 
     /** 性别;性别 */
     private Integer sex ;
+
+    private BigDecimal points;
 }
 

+ 25 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserDistribute.java

@@ -0,0 +1,25 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: UserDistribute
+ *创建者: JavaZou
+ *创建时间:2022/11/14 12:10
+ */
+@Getter
+@Setter
+public class UserDistribute extends BaseEntity{
+	private Long userId;
+
+	/**
+	 * 备注
+	 */
+	private String remark;
+
+	@TableLogic(value = "1", delval = "0")
+	private Boolean deleted;
+}

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

@@ -0,0 +1,24 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: UserDistributeShared
+ *创建者: JavaZou
+ *创建时间:2022/11/15 11:51
+ */
+@Getter
+@Setter
+public class UserDistributeShared extends BaseEntity{
+	/**
+	 * 被分享人id
+	 */
+	private Long userId;
+
+	/**
+	 * 分享人id
+	 */
+	private Long sharedId;
+}

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserPlatDistributeRate.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: UserPlatDistributeRate
+ *创建者: JavaZou
+ *创建时间:2022/11/14 12:12
+ */
+@Getter
+@Setter
+public class UserPlatDistributeRate extends BaseEntity{
+	private Long goodsId;
+
+	/**
+	 * 固定用户分销id
+	 */
+	private Long distributeId;
+
+	/**
+	 * 分销比例
+	 */
+	private Integer rate;
+}
+

+ 4 - 1
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSpuInsert.java

@@ -75,5 +75,8 @@ public class ReqGoodsSpuInsert {
      */
     private Integer secondType;
 
-
+    /**
+     * 平台分销比例
+     */
+    private Integer rate;
 }

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/GoodsDonViewer.java

@@ -118,6 +118,11 @@ public class GoodsDonViewer {
     @DbField("g.second_type")
     private Integer secondType;
 
+    /**
+     * banner
+     */
+    @DbField("g.rate")
+    private Integer rate;
 
     @DbIgnore
     private List<GoodsDonSku> skus;

+ 19 - 2
netflix-dao/src/main/java/com/cyksj/model/manage/views/UserView.java

@@ -1,6 +1,5 @@
 package com.cyksj.model.manage.views;
 
-import com.cyksj.model.entity.BaseEntity;
 import com.ejlchina.searcher.bean.DbField;
 import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
@@ -13,7 +12,7 @@ import lombok.Setter;
  */
 @Getter
 @Setter
-@SearchBean(tables = "user u")
+@SearchBean(tables = "user u left join user_distribute_shared usd on usd.user_id = u.id")
 public class UserView {
 
     /**
@@ -57,4 +56,22 @@ public class UserView {
      */
     @DbIgnore
     private Integer accountNum;
+
+    /**
+     * 邀请人id
+     */
+    @DbField("usd.shared_id")
+    private Long sharedId;
+
+    /**
+     * 邀请人名称
+     */
+    @DbIgnore
+    private String sharedNickName;
+
+    /**
+     * 邀请人头像
+     */
+    @DbIgnore
+    private String sharedHeadimgurl;
 }

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/request/ApplyMoneyReq.java

@@ -0,0 +1,21 @@
+package com.cyksj.model.request;
+
+import com.cyksj.model.entity.DistributeMoneyApply;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: ApplyMoneyReq
+ *创建者: JavaZou
+ *创建时间:2022/11/16 9:58
+ */
+@Getter
+@Setter
+public class ApplyMoneyReq {
+	private String account;
+
+	private DistributeMoneyApply.Type type;
+
+	private String realName;
+}

+ 32 - 0
netflix-dao/src/main/java/com/cyksj/model/request/DistributeApplyMoneyReq.java

@@ -0,0 +1,32 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+/*
+ *项目名: netflix
+ *文件名: DistributeApplyMoneyReq
+ *创建者: JavaZou
+ *创建时间:2022/11/15 9:50
+ */
+@Getter
+@Setter
+public class DistributeApplyMoneyReq {
+	@NotNull(message = "id错误")
+	@Min(value = 1, message = "id错误")
+	private Long id;
+
+	@NotEmpty(message = "审核状态为空")
+	private String verifyStatus;
+
+	private String reason;
+
+	/**
+	 * 成功打款图片
+	 */
+	private String img;
+}

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

@@ -18,4 +18,9 @@ public class LoginPhoneReq {
 	 * 验证码
 	 */
 	private String code;
+
+	/**
+	 * 分销人用户id
+	 */
+	private Long sharedId;
 }

+ 31 - 0
netflix-dao/src/main/java/com/cyksj/model/request/UserDistributeReq.java

@@ -0,0 +1,31 @@
+package com.cyksj.model.request;
+
+import com.cyksj.model.entity.UserPlatDistributeRate;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: UserDistributeReq
+ *创建者: JavaZou
+ *创建时间:2022/11/14 12:15
+ */
+@Getter
+@Setter
+public class UserDistributeReq {
+
+	private Long id;
+
+	@NotNull(message = "请添加用户")
+	private Long userId;
+
+	private String remark;
+
+	/**
+	 * 平台分销比例
+	 */
+	private List<UserPlatDistributeRate> rates;
+}

+ 42 - 1
netflix-dao/src/main/java/com/cyksj/model/views/BackgroundDataView.java

@@ -54,6 +54,48 @@ public class BackgroundDataView {
 	 */
 	private Integer totalExpiredAccountNum;
 
+
+
+
+	/**
+	 * 分销单数
+	 */
+	private Integer distributeOrders;
+
+
+	/**
+	 * 固定推广者分销单数
+	 */
+	private Integer distributePopularizeOrders;
+
+	/**
+	 * 普通分销单数
+	 */
+	private Integer distributeOriginalOrders;
+
+	/**
+	 * 固定推广者分销金额
+	 */
+	private BigDecimal distributePopularizeMoney;
+
+	/**
+	 * 普通分销金额
+	 */
+	private BigDecimal distributeOriginalMoney;
+
+	/**
+	 * 已提现分销金额
+	 */
+	private BigDecimal distributeGotMoney;
+
+	/**
+	 * 待审核提现分销金额
+	 */
+	private BigDecimal distributeVerifyingMoney;
+
+
+
+
 	/**
 	 * 待注册账号数
 	 */
@@ -78,5 +120,4 @@ public class BackgroundDataView {
 	 * 实物数据
 	 */
 	private List<RealGoodsData> realGoodsDataViews;
-
 }

+ 57 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DistributeMoneyApplyView.java

@@ -0,0 +1,57 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.DistributeMoneyApply;
+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
+ *文件名: DistributeMoneyApplyView
+ *创建者: JavaZou
+ *创建时间:2022/11/15 9:28
+ */
+@Getter
+@Setter
+@SearchBean(tables = "distribute_money_apply dma left join user u on u.id = dma.user_id")
+public class DistributeMoneyApplyView {
+	@DbField("dma.id")
+	private Long id;
+
+	@DbField("dma.user_id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("dma.money")
+	private BigDecimal money;
+
+	@DbField("dma.reason")
+	private String reason;
+
+	@DbField("dma.points")
+	private BigDecimal points;
+
+	@DbField("dma.real_name")
+	private String realName;
+
+	@DbField("dma.type")
+	private DistributeMoneyApply.Type type;
+
+	@DbField("dma.account")
+	private String account;
+
+	@DbField("dma.verify_status")
+	private DistributeMoneyApply.Status verifyStatus;
+
+	@DbField("dma.img")
+	private String img;
+
+	@DbField("dma.created_time")
+	private Date createdTime;
+}

+ 36 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DistributeOrdersView.java

@@ -0,0 +1,36 @@
+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
+ *文件名: DistributeOrders
+ *创建者: JavaZou
+ *创建时间:2022/11/15 10:52
+ */
+@Getter
+@Setter
+@SearchBean(tables = "order_don od left join distribute_waiting_send_points dp on dp.order_id = od.id",
+		where = "od.is_distribute is true and od.status not in ('close','noPayment')")
+public class DistributeOrdersView {
+	@DbField("od.id")
+	private Long id;
+
+	@DbField("od.money")
+	private BigDecimal money;
+
+	@DbField("od.status")
+	private String status;
+
+	@DbField("od.is_fixed_distribute")
+	private Boolean isFixedDistribute;
+
+	@DbField("od.created_time")
+	private Date createdTime;
+}

+ 64 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DistributePopularizeOrdersView.java

@@ -0,0 +1,64 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.OrderDon;
+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;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: DistributePopularizeOrdersView
+ *创建者: JavaZou
+ *创建时间:2022/11/15 14:28
+ */
+@Getter
+@Setter
+@SearchBean(tables = "distribute_waiting_send_points dw left join order_don od on od.id = dw.order_id" +
+		" left join user u on u.id = od.user_id ",
+		where = "od.is_distribute is true")
+public class DistributePopularizeOrdersView {
+	@DbField("od.id")
+	private Long orderId;
+
+	@DbField("od.goods_id")
+	@JsonIgnore
+	private Long goodsId;
+
+	@DbField("od.sku_id")
+	@JsonIgnore
+	private Long skuId;
+
+	@DbField("od.money")
+	private BigDecimal money;
+
+	@DbField("dw.shared_id")
+	@JsonIgnore
+	private Long sharedId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("dw.points")
+	private BigDecimal points;
+
+	@DbField("dw.send_status")
+	private String sendStatus;
+
+	@DbIgnore
+	private String goodsTitle;
+
+	@DbField("od.status")
+	private OrderDon.Status orderStatus;
+
+	@DbIgnore
+	private String specVal;
+
+	@DbField("od.created_time")
+	private Date createdTime;
+}

+ 46 - 0
netflix-dao/src/main/java/com/cyksj/model/views/DistributePopularizeView.java

@@ -0,0 +1,46 @@
+package com.cyksj.model.views;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: DistributePopularizeView
+ *创建者: JavaZou
+ *创建时间:2022/11/15 14:04
+ */
+@Getter
+@Setter
+public class DistributePopularizeView {
+	/**
+	 * 分销链接
+	 */
+	private String url;
+
+	/**
+	 * 分销链接二维码
+	 */
+	private String urlCode;
+
+	/**
+	 * 目前积分
+	 */
+	private BigDecimal gotPoints;
+
+	/**
+	 * 带入账积分
+	 */
+	private BigDecimal waitingSendPoints;
+
+	/**
+	 * 分销单数
+	 */
+	private Integer distributeOrders;
+
+	/**
+	 * 最高返现比例
+	 */
+	private Integer highestRate;
+}

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/views/MoneyApplyView.java

@@ -0,0 +1,21 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.DistributePointsExchangeMoney;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: MoneyApplyView
+ *创建者: JavaZou
+ *创建时间:2022/11/15 9:42
+ */
+@Getter
+@Setter
+public class MoneyApplyView {
+	private BigDecimal gotMoney;
+
+	private DistributePointsExchangeMoney threshold;
+}

+ 35 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeView.java

@@ -0,0 +1,35 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: UserDistributeView
+ *创建者: JavaZou
+ *创建时间:2022/11/15 16:27
+ */
+@Getter
+@Setter
+@SearchBean(tables = "user_plat_distribute_rate up left join goods_don gd on gd.id = up.goods_id")
+public class UserDistributeView {
+	@DbField("up.id")
+	private Long id;
+
+	@DbField("up.distribute_id")
+	@JsonIgnore
+	private Long distribute_id;
+
+	@DbField("gd.id")
+	private Long goodsId;
+
+	@DbField("gd.title")
+	private String title;
+
+	@DbField("up.rate")
+	private Integer rate;
+
+}

+ 57 - 0
netflix-dao/src/main/java/com/cyksj/model/views/UserDistributeViews.java

@@ -0,0 +1,57 @@
+package com.cyksj.model.views;
+
+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.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: UserDistributeViews
+ *创建者: JavaZou
+ *创建时间:2022/11/14 13:49
+ */
+@Getter
+@Setter
+@SearchBean(tables = "user_distribute ud left join user u on u.id = ud.user_id",
+where = "ud.deleted is true")
+public class UserDistributeViews {
+
+	@DbField("ud.id")
+	private Long id;
+
+	@DbField("ud.user_id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("ud.remark")
+	private String remark;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private Integer orders;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private BigDecimal availableMoney;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private BigDecimal gotMoney;
+
+	@DbField("u.points")
+	private BigDecimal points;
+
+	@DbField("ud.created_time")
+	private Date createdTime;
+
+	@DbField("ud.update_time")
+	private Date updateTime;
+}

+ 3 - 1
netflix-dao/src/main/resources/mapper/AppleOneDataMapper.xml

@@ -11,7 +11,9 @@
         sum(num_of_month_order) as num_of_month_order,
         sum(num_of_season_order) as num_of_season_order,
         sum(num_of_year_order) as num_of_year_order,
-        sum(num_of_code_order) as num_of_code_order
+        sum(num_of_code_order) as num_of_code_order,
+        sum(num_of_distribute_order) as numOfDistributeOrder,
+        sum(distribute_order_money) as distributeOrderMoney
         from `apple_one_data`
         <where>
             <if test="startDate != null">

+ 1 - 1
netflix-dao/src/main/resources/mapper/OrderDonMapper.xml

@@ -19,7 +19,7 @@
     </select>
 
     <select id="getAppleOneOrderDons" resultType="com.cyksj.model.entity.OrderDon">
-        select distinct s.* from (select id,sku_id,user_id,money from `order_don`
+        select distinct s.* from (select id,sku_id,user_id,money,is_distribute from `order_don`
         where sku_id in
         <foreach collection="skuIds" item="item" open="(" separator="," close=")">
             #{item}

+ 3 - 1
netflix-dao/src/main/resources/mapper/StreamingAccountDataMapper.xml

@@ -12,7 +12,9 @@
                sum(num_of_month_order) as num_of_month_order,
                sum(num_of_season_order) as num_of_season_order,
                sum(num_of_year_order) as num_of_year_order,
-               sum(num_of_code_order) as num_of_code_order
+               sum(num_of_code_order) as num_of_code_order,
+               sum(num_of_distribute_order) as numOfDistributeOrder,
+               sum(distribute_order_money) as distributeOrderMoney
         from `streaming_account_data`
         <where>
             <if test="startDate != null">

+ 15 - 0
netflix-dao/src/main/resources/mapper/UserDistributeMapper.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.cyksj.mapper.manage.distribute.UserDistributeMapper">
+
+    <select id="count" resultType="java.lang.Integer">
+        select count(*)
+        from `user_distribute_shared` us
+                 inner join `order_don` od
+                            on od.user_id = us.user_id
+                 inner join `distribute_waiting_send_points` dp
+                            on dp.order_id = od.id
+        where us.shared_id = #{userId}
+          and od.status not in ('close', 'noPayment')
+    </select>
+</mapper>

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/DistributeService.java

@@ -0,0 +1,15 @@
+package com.cyksj.service.distribute;
+
+import com.cyksj.model.request.UserDistributeReq;
+
+/*
+ *项目名: netflix
+ *文件名: DistributeService
+ *创建者: JavaZou
+ *创建时间:2022/11/14 12:21
+ */
+public interface DistributeService {
+	void insertDistribute(UserDistributeReq userDistributeReq);
+
+	void editDistribute(UserDistributeReq userDistributeReq);
+}

+ 78 - 0
netflix-service/src/main/java/com/cyksj/service/distribute/impl/DistributeServiceImpl.java

@@ -0,0 +1,78 @@
+package com.cyksj.service.distribute.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.GoodsDonMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
+import com.cyksj.mapper.manage.distribute.UserPlatDistributeRateMapper;
+import com.cyksj.model.entity.GoodsDon;
+import com.cyksj.model.entity.UserDistribute;
+import com.cyksj.model.entity.UserPlatDistributeRate;
+import com.cyksj.model.request.UserDistributeReq;
+import com.cyksj.service.distribute.DistributeService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/*
+ *项目名: netflix
+ *文件名: DistributeServiceImpl
+ *创建者: JavaZou
+ *创建时间:2022/11/14 12:21
+ */
+@Service
+@RequiredArgsConstructor
+public class DistributeServiceImpl implements DistributeService {
+	private final UserDistributeMapper userDistributeMapper;
+
+	private final UserPlatDistributeRateMapper userPlatDistributeRateMapper;
+
+	private final GoodsDonMapper goodsDonMapper;
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public void insertDistribute(UserDistributeReq userDistributeReq) {
+		UserDistribute exists = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, userDistributeReq.getUserId()).eq(UserDistribute::getDeleted, true).last("limit 1"));
+		if (exists != null) {
+			throw BusinessRuntimeException.getInstance("该推广者已添加");
+		}
+		UserDistribute userDistribute = new UserDistribute();
+		userDistribute.setUserId(userDistributeReq.getUserId());
+		userDistribute.setRemark(userDistributeReq.getRemark());
+		userDistributeMapper.insert(userDistribute);
+
+		for (UserPlatDistributeRate rate : userDistributeReq.getRates()) {
+			if (rate.getRate() <0 || rate.getRate() > 100) {
+				throw new BusinessRuntimeException("比例错误");
+			}
+			GoodsDon goodsDon = goodsDonMapper.selectById(rate.getGoodsId());
+			if (goodsDon == null || !goodsDon.getDeleted() || goodsDon.getType() == 2) {
+				throw new BusinessRuntimeException("平台错误");
+			}
+			rate.setDistributeId(userDistribute.getId());
+			userPlatDistributeRateMapper.insert(rate);
+		}
+	}
+
+	@Override
+	public void editDistribute(UserDistributeReq userDistributeReq) {
+		if (userDistributeReq.getId() == null || userDistributeReq.getId() < 1) {
+			throw BusinessRuntimeException.getInstance("id错误");
+		}
+		UserDistribute userDistribute = new UserDistribute();
+		userDistribute.setId(userDistributeReq.getId());
+		userDistribute.setRemark(userDistributeReq.getRemark());
+		userDistributeMapper.updateById(userDistribute);
+		for (UserPlatDistributeRate rate : userDistributeReq.getRates()) {
+			if (rate.getRate() <0 || rate.getRate() > 100) {
+				throw new BusinessRuntimeException("比例错误");
+			}
+			GoodsDon goodsDon = goodsDonMapper.selectById(rate.getGoodsId());
+			if (goodsDon == null || !goodsDon.getDeleted() || goodsDon.getType() == 2) {
+				throw new BusinessRuntimeException("平台错误");
+			}
+			rate.setDistributeId(userDistribute.getId());
+			userPlatDistributeRateMapper.updateById(rate);
+		}
+	}
+}

+ 56 - 4
netflix-service/src/main/java/com/cyksj/service/mange/statistics/impl/StatisticsDataServiceImpl.java

@@ -15,6 +15,7 @@ import com.cyksj.mapper.manage.statistics.RealGoodsDataMapper;
 import com.cyksj.mapper.manage.statistics.StreamingAccountDataMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.views.BackgroundDataView;
+import com.cyksj.model.views.DistributeOrdersView;
 import com.cyksj.model.views.ExpiredAccountDataView;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.mange.CmsAccountService;
@@ -29,10 +30,7 @@ import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /*
@@ -183,5 +181,59 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 				.onlySelect(RegisterOrderDon ::getId)
 				.build());
 		backgroundDataView.setFailRegisterNum(errorRegisterNum.intValue());
+		//分销金额数据统计
+		distribute(backgroundDataView, startDate, endDate);
+	}
+
+	/**
+	 * 分销金额信息补充
+	 * @param backgroundDataView
+	 */
+	public void distribute(BackgroundDataView backgroundDataView, Date startDate, Date endDate) {
+		List<DistributeOrdersView> distributeOrders = Optional.ofNullable(beanSearcher.searchAll(DistributeOrdersView.class, MapUtils.builder()
+				.field(DistributeOrdersView::getCreatedTime, startDate, endDate).op(Operator.Between)
+				.build())).orElse(new ArrayList<>());
+		backgroundDataView.setDistributeOrders(distributeOrders.size());
+		//固定推广者订单
+		List<DistributeOrdersView> distributePopularizeOrders = Optional.ofNullable(beanSearcher.searchAll(DistributeOrdersView.class, MapUtils.builder()
+				.field(DistributeOrdersView::getIsFixedDistribute,true).op(Operator.Equal)
+				.field(DistributeOrdersView::getCreatedTime, startDate, endDate).op(Operator.Between)
+				.build())).orElse(new ArrayList<>());
+		backgroundDataView.setDistributePopularizeOrders(distributePopularizeOrders.size());
+		//普通分销单数
+		List<DistributeOrdersView> distributeOriginalOrders = Optional.ofNullable(beanSearcher.searchAll(DistributeOrdersView.class, MapUtils.builder()
+				.field(DistributeOrdersView::getIsFixedDistribute,false).op(Operator.Equal)
+				.field(DistributeOrdersView::getCreatedTime, startDate, endDate).op(Operator.Between)
+				.build())).orElse(new ArrayList<>());
+		backgroundDataView.setDistributeOriginalOrders(distributeOriginalOrders.size());
+		//固定推广者订单金额
+		Optional<BigDecimal> popularizeMoney = distributePopularizeOrders.stream().map(DistributeOrdersView::getMoney).reduce(BigDecimal::add);
+		//普通分销订单金额
+		Optional<BigDecimal> originalMoney = distributeOriginalOrders.stream().map(DistributeOrdersView::getMoney).reduce(BigDecimal::add);
+		backgroundDataView.setDistributePopularizeMoney(popularizeMoney.isPresent() ? popularizeMoney.get().divide(BigDecimal.valueOf(100)) : BigDecimal.ZERO);
+		backgroundDataView.setDistributeOriginalMoney(originalMoney.isPresent() ? originalMoney.get().divide(BigDecimal.valueOf(100)) : BigDecimal.ZERO);
+
+		List<DistributeMoneyApply> distributeMoneyApplies = Optional.ofNullable(beanSearcher.searchAll(DistributeMoneyApply.class, MapUtils.builder().field(DistributeMoneyApply::getCreatedTime, startDate, endDate).op(Operator.Between).build())).orElse(new ArrayList<>());
+		Map<DistributeMoneyApply.Status, List<DistributeMoneyApply>> collect = distributeMoneyApplies.stream().collect(Collectors.groupingBy(DistributeMoneyApply::getVerifyStatus));
+		collect.forEach((k, v) -> {
+			if (DistributeMoneyApply.Status.fail == k) {
+				return;
+			}
+			Optional<BigDecimal> reduce = v.stream().map(DistributeMoneyApply::getMoney).reduce(BigDecimal::add);
+			BigDecimal money = reduce.isPresent() ? reduce.get().divide(BigDecimal.valueOf(100)) : BigDecimal.ZERO;
+			if (DistributeMoneyApply.Status.success == k) {
+				backgroundDataView.setDistributeGotMoney(money);
+			}
+			if (DistributeMoneyApply.Status.verifying == k) {
+				backgroundDataView.setDistributeVerifyingMoney(money);
+			}
+		});
+		if (backgroundDataView.getDistributeGotMoney() == null) {
+			backgroundDataView.setDistributeGotMoney(BigDecimal.ZERO);
+		}
+
+		if (backgroundDataView.getDistributeVerifyingMoney() == null) {
+			backgroundDataView.setDistributeVerifyingMoney(BigDecimal.ZERO);
+		}
 	}
 }

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

@@ -34,6 +34,7 @@ import com.cyksj.dto.RedisKey;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.*;
+import com.cyksj.mapper.manage.distribute.*;
 import com.cyksj.model.dto.AliPayParams;
 import com.cyksj.model.dto.H5JsPayParams;
 import com.cyksj.model.dto.WxMpTemplateData;
@@ -120,6 +121,16 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final RefundOrderDonMapper refundOrderDonMapper;
 
+	private final UserDistributeSharedMapper userDistributeSharedMapper;
+
+	private final DistributeWaitingSendPointsMapper distributeWaitingSendPointsMapper;
+
+	private final DistributePointsExchangeMoneyMapper distributePointsExchangeMoneyMapper;
+
+	private final UserDistributeMapper userDistributeMapper;
+
+	private final UserPlatDistributeRateMapper userPlatDistributeRateMapper;
+
 
 	@Transactional(rollbackFor = Throwable.class)
 	@Override
@@ -210,6 +221,17 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		orderDon.setStatus(OrderDon.Status.noPayment);
 		orderDon.setUserId(user.getId());
 		orderDon.setType(OrderDon.Type.getType(payRequest.getType()));
+		//虚拟商品订单,是否是分销订单
+		if (goodsDon.getType() == 1) {
+			UserDistributeShared userDistributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class).eq(UserDistributeShared::getUserId, user.getId()).last("limit 1"));
+			if (userDistributeShared != null) {
+				orderDon.setIsDistribute(true);
+				UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, user.getId()));
+				if (userDistribute != null) {
+					orderDon.setIsFixedDistribute(true);
+				}
+			}
+		}
 		this.saveOrUpdate(orderDon);
 
 
@@ -327,6 +349,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		updateCarParkAndSendMsg(goodsDon, sku, order);
 		order.setType(OrderDon.Type.WeChat);
+		if (order.getMoney().compareTo(BigDecimal.ZERO) > 0 && order.getIsDistribute()) {
+			TASK_POOL.execute(() -> distributeWaitingSendPointsRecord(order));
+		}
 		this.updateById(order);
 	}
 
@@ -469,6 +494,13 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		orderDon.setStatus(OrderDon.Status.noPayment);
 		orderDon.setUserId(user.getId());
 		orderDon.setGoodsId(goodsDon.getId());
+		//虚拟商品订单,是否是分销订单
+		if (goodsDon.getType() == 1) {
+			UserDistributeShared userDistributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class).eq(UserDistributeShared::getUserId, user.getId()).last("limit 1"));
+			if (userDistributeShared != null) {
+				orderDon.setIsDistribute(true);
+			}
+		}
 		this.saveOrUpdate(orderDon);
 
 		jobManager.addJob(EXPIRY_TIME, () -> {
@@ -537,6 +569,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//修改车位状态并发送模板消息
 		updateCarParkAndSendMsg(goodsDon, sku, orderDon);
 		orderDon.setType(OrderDon.Type.ALI_PAY);
+		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0 && orderDon.getIsDistribute()) {
+			TASK_POOL.execute(() -> distributeWaitingSendPointsRecord(orderDon));
+		}
 		this.updateById(orderDon);
 	}
 
@@ -578,6 +613,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//修改订单状态
 		orderDon.setStatus(OrderDon.Status.refund);
 		orderDon.setRefundMoney(wxOrderRefundReq.getRefundMoney());
+		if (orderDon.getIsDistribute()) {
+			distributeWaitingSendPointsMapper.updateOrderStatus(orderDon.getId(), DistributeWaitingSendPoints.Status.close);
+		}
 		orderDonMapper.updateById(orderDon);
 		//记录退款信息
 		final String outNo = outRefundNo;
@@ -643,6 +681,9 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				AliPayRefundRep.AlipayTradeRefundResponse res = aliPayRefundRep.getResponse();
 				orderDon.setRefundMoney(res.getRefundFee().multiply(BigDecimal.valueOf(100)));
 			} else orderDon.setRefundMoney(BigDecimal.ZERO);
+			if (orderDon.getIsDistribute()) {
+				distributeWaitingSendPointsMapper.updateOrderStatus(orderDon.getId(), DistributeWaitingSendPoints.Status.close);
+			}
 			orderDonMapper.updateById(orderDon);
 			//记录退款信息
 			THREAD_POOL_TASK_EXECUTOR.execute(()->{
@@ -765,6 +806,12 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			orderDon.setRefundMoney(refundMoney);
 			orderDonMapper.updateById(orderDon);
 		}
+		if (orderDon.getIsDistribute()) {
+			DistributeWaitingSendPoints distributeWaitingSendPoints = distributeWaitingSendPointsMapper.selectOne(Wrappers.lambdaQuery(DistributeWaitingSendPoints.class).eq(DistributeWaitingSendPoints::getOrderId, orderDon.getId()).last("limit 1"));
+			if (distributeWaitingSendPoints != null && distributeWaitingSendPoints.getSendStatus() != DistributeWaitingSendPoints.Status.close) {
+				distributeWaitingSendPointsMapper.updateOrderStatus(orderDon.getId(), DistributeWaitingSendPoints.Status.close);
+			}
+		}
 		log.info("微信退款: 退款单号[{}] 退款成功.", outRefundNo);
 	}
 
@@ -936,4 +983,53 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			}
 		});
 	}
+
+	/**
+	 * 分销待发积分记录
+	 */
+	public void distributeWaitingSendPointsRecord(OrderDon order) {
+		DistributeWaitingSendPoints distributeWaitingSendPoints = new DistributeWaitingSendPoints();
+		distributeWaitingSendPoints.setOrderId(order.getId());
+		distributeWaitingSendPoints.setUserId(order.getUserId());
+		BigDecimal orderMoney = order.getMoney();
+		BigDecimal points = null;
+		BigDecimal returnMoney = null;
+		UserDistributeShared userDistributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class).eq(UserDistributeShared::getUserId, order.getUserId()).last("limit 1"));
+		if (userDistributeShared != null) {
+			distributeWaitingSendPoints.setSharedId(userDistributeShared.getSharedId());
+			DistributePointsExchangeMoney distributePointsExchangeMoney = distributePointsExchangeMoneyMapper.selectOne(Wrappers.lambdaQuery(DistributePointsExchangeMoney.class).orderByDesc(DistributePointsExchangeMoney::getPoints).last("limit 1"));
+			if (distributePointsExchangeMoney == null) {
+				log.info("分销兑换积分比例未配置");
+			} else {
+				UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, userDistributeShared.getSharedId()).eq(UserDistribute::getDeleted, true).last("limit 1"));
+				if (userDistribute == null) {
+					//普通分销
+					GoodsDon goodsDon = goodsDonMapper.selectById(order.getGoodsId());
+					if (goodsDon != null) {
+						returnMoney = orderMoney.multiply(BigDecimal.valueOf(goodsDon.getRate())).divide(BigDecimal.valueOf(100));
+					}
+				}else {
+					//固定推广分销
+					UserPlatDistributeRate userPlatDistributeRate = userPlatDistributeRateMapper.selectOne(Wrappers.lambdaQuery(UserPlatDistributeRate.class)
+							.eq(UserPlatDistributeRate::getGoodsId, order.getGoodsId())
+							.eq(UserPlatDistributeRate::getDistributeId, userDistribute.getId())
+							.last("limit 1"));
+					if (userPlatDistributeRate != null) {
+						returnMoney = orderMoney.multiply(BigDecimal.valueOf(userPlatDistributeRate.getRate())).divide(BigDecimal.valueOf(100));
+					}
+				}
+				if (returnMoney != null) {
+					BigDecimal returnPoints = returnMoney.multiply(BigDecimal.valueOf(distributePointsExchangeMoney.getPoints())).divide(distributePointsExchangeMoney.getMoney(), 2, RoundingMode.HALF_DOWN);
+					points = returnPoints;
+				}
+				distributeWaitingSendPoints.setPoints(points);
+				if (points != null && points.compareTo(BigDecimal.ZERO) > 0) {
+					log.info("用户{}邀请{},产生分销订单分发积分记录入库", userDistributeShared.getUserId(), order.getUserId());
+					distributeWaitingSendPoints.setSendStatus(DistributeWaitingSendPoints.Status.waiting);
+					distributeWaitingSendPoints.setSendTime(DateUtil.offsetDay(order.getPayTime(), 7));
+					distributeWaitingSendPointsMapper.insert(distributeWaitingSendPoints);
+				}
+			}
+		}
+	}
 }

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/user/UserService.java

@@ -11,7 +11,7 @@ import com.cyksj.model.entity.User;
  */
 public interface UserService extends IService<User> {
 
-    User saveAuth(GzhOAuth2UserInfo userinfo);
+    User saveAuth(GzhOAuth2UserInfo userinfo, Long sharedId);
 
     UserWhoami whoami(long userId);
 }

+ 22 - 2
netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java

@@ -4,13 +4,16 @@ import cn.hutool.core.bean.BeanUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
 import com.cyksj.model.dto.GzhOAuth2UserInfo;
 import com.cyksj.model.dto.UserWhoami;
 import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.UserDistributeShared;
 import com.cyksj.service.user.UserService;
 import com.cyksj.service.wechat.WeChatService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.stereotype.Service;
 import org.springframework.util.Assert;
 
@@ -28,8 +31,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 
     private final WeChatService weChatService;
 
+    private final UserDistributeSharedMapper userDistributeSharedMapper;
+
     @Override
-    public User saveAuth(GzhOAuth2UserInfo info) {
+    public User saveAuth(GzhOAuth2UserInfo info, Long sharedId) {
         final String unionid = info.getUnionid();
 
         // 查询用户是否存在
@@ -48,8 +53,23 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 
         user.setUnionid(unionid);
         user.setOpenId(info.getOpenid());
-
+        UserDistributeShared userDistributeShared = null;
+        if (user.getId() == null) {
+            User shared = this.getById(sharedId);
+            if (shared != null) {
+                userDistributeShared = new UserDistributeShared();
+                userDistributeShared.setSharedId(sharedId);
+            }
+        }
         this.saveOrUpdate(user);
+        if (userDistributeShared != null) {
+            userDistributeShared.setUserId(user.getId());
+            try {
+                userDistributeSharedMapper.insert(userDistributeShared);
+            } catch (DuplicateKeyException e) {
+                log.info("分销被邀请人重复插入");
+            }
+        }
         return user;
     }
 

+ 47 - 0
netflix-service/src/main/java/com/cyksj/task/Scheduler.java

@@ -8,6 +8,7 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.RedisKey;
 import com.cyksj.mapper.*;
+import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
 import com.cyksj.model.dto.WxMpTemplateData;
 import com.cyksj.model.dto.WxMpTemplateMessage;
 import com.cyksj.model.entity.*;
@@ -21,8 +22,10 @@ import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Optional;
 
 import static com.cyksj.common.constant.WeChatTemplateConst.EXPIRY_TEMPLATE;
 
@@ -57,6 +60,8 @@ public class Scheduler {
 
         private final SysConfigMapper sysConfigMapper;
 
+        private final DistributeWaitingSendPointsMapper distributeWaitingSendPointsMapper;
+
 
     /**
      * 每5分钟清理过期账号
@@ -191,4 +196,46 @@ public class Scheduler {
         redisService.set(RedisKey.SPOTIFY_FREE_NUM, Long.parseLong(register_free_num.getSysValue()));
         log.info("每日重置 spotify 免单账户数 [end] 数量:{}",register_free_num.getSysValue());
     }
+
+    /**
+     * 分销订单积分奖励分发
+     */
+    @Scheduled(cron = "0 0 0/2 * * ?")
+    @Transactional(rollbackFor = Throwable.class)
+    public void distributeOrdersSendPoints() {
+        List<DistributeWaitingSendPoints> waitingSendPoints = Optional.ofNullable(distributeWaitingSendPointsMapper.selectList(Wrappers.lambdaQuery(DistributeWaitingSendPoints.class)
+                .eq(DistributeWaitingSendPoints::getSendStatus, DistributeWaitingSendPoints.Status.waiting)
+                .lt(DistributeWaitingSendPoints::getSendTime, DateTime.now())
+                .select(DistributeWaitingSendPoints::getId,
+                        DistributeWaitingSendPoints::getOrderId,
+                        DistributeWaitingSendPoints::getPoints,
+                        DistributeWaitingSendPoints::getUserId,
+                        DistributeWaitingSendPoints::getSendTime))).orElse(new ArrayList<>());
+        log.info("查询分销订单积分分发记录开始,条数:{}=======》", waitingSendPoints.size());
+        waitingSendPoints.forEach(wait -> {
+            //积分待发人
+            Long sharedId = wait.getSharedId();
+            User user = userMapper.selectById(sharedId);
+            if (user == null) {
+                wait.setSendStatus(DistributeWaitingSendPoints.Status.not_exist);
+                log.info("分销订单,发送积分用户不存在");
+                distributeWaitingSendPointsMapper.updateById(wait);
+            } else {
+                wait.setSendStatus(DistributeWaitingSendPoints.Status.success);
+                log.info("更新用户积分开始=====>");
+                while (true) {
+                    user = userMapper.selectById(sharedId);
+                    if (user == null) {
+                        break;
+                    }
+                    Integer update = userMapper.updatePoints(user.getId(), wait.getPoints(), user.getPoints());
+                    if (update == 1) {
+                        distributeWaitingSendPointsMapper.updateById(wait);
+                        log.info("分销积分表订单id:{}发放积分success", wait.getOrderId());
+                        break;
+                    }
+                }
+            }
+        });
+    }
 }

+ 11 - 3
netflix-service/src/main/java/com/cyksj/task/StatisticsDataScheduler.java

@@ -50,9 +50,7 @@ public class StatisticsDataScheduler {
 	public static List<String> noOrderStatus = List.of("close", "noPayment");
 
 	public static List<String> payType = List.of("月", "季", "年");
-
-	private final static List<String> APPLE_ONE_AREA = List.of("美区", "马来西亚区");
-
+	
 	private static Long DAY_MILLS = 86400000l;
 
 	private final GoodsDonMapper goodsDonMapper;
@@ -125,6 +123,12 @@ public class StatisticsDataScheduler {
 			if (money.isPresent()) {
 				appleOne.setMoney(money.get());
 			} else appleOne.setMoney(BigDecimal.ZERO);
+
+			List<OrderDon> distributeOrders = Optional.ofNullable(orderDons.stream().filter(ord -> ord.getIsDistribute()).collect(Collectors.toList())).orElse(new ArrayList<>());
+			appleOne.setNumOfDistributeOrder(distributeOrders.size());
+			Optional<BigDecimal> distributeMoney = distributeOrders.stream().map(OrderDon::getMoney).reduce(BigDecimal::add);
+			appleOne.setDistributeOrderMoney(distributeMoney.isPresent() ? distributeMoney.get() : BigDecimal.ZERO);
+
 			getNumOfOrderByPayType(orderDons, appleOne);
 		}
 		appleOneSave.add(appleOne);
@@ -215,6 +219,10 @@ public class StatisticsDataScheduler {
 			}
 			//金额
 			streamingAccountData.setMoney(totalMoney);
+			List<OrderDon> distributeOrders = Optional.ofNullable(orderDons.stream().filter(ord -> ord.getIsDistribute()).collect(Collectors.toList())).orElse(new ArrayList<>());
+			streamingAccountData.setNumOfDistributeOrder(distributeOrders.size());
+			Optional<BigDecimal> distributeMoney = distributeOrders.stream().map(OrderDon::getMoney).reduce(BigDecimal::add);
+			streamingAccountData.setDistributeOrderMoney(distributeMoney.isPresent() ? distributeMoney.get() : BigDecimal.ZERO);
 		}
 		dataSave.add(streamingAccountData);
 	}

+ 10 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsUserController.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.UserMapper;
 import com.cyksj.model.entity.GroupsRelation;
 import com.cyksj.model.entity.User;
 import com.cyksj.model.manage.views.UserView;
@@ -34,12 +35,21 @@ public class CmsUserController{
 
     private final GroupsRelationMapper relationMapper;
 
+    private final UserMapper userMapper;
+
 
     @GetMapping("/get")
     public Result<SearchResult<UserView>> get(){
         SearchResult<UserView> search = beanSearcher.search(UserView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
         search.getDataList().forEach((userView)->{
             userView.setAccountNum(relationMapper.selectCount(Wrappers.lambdaQuery(GroupsRelation.class).eq(GroupsRelation::getUserId,userView.getId())));
+            if (userView.getSharedId() != null) {
+                User user = userMapper.selectById(userView.getSharedId());
+                if (user != null) {
+                    userView.setSharedNickName(user.getNickname());
+                    userView.setSharedHeadimgurl(user.getHeadimgurl());
+                }
+            }
         });
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }

+ 238 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/distribute/DistributeController.java

@@ -0,0 +1,238 @@
+package com.cyksj.web.controller.manage.distribute;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GoodsDonMapper;
+import com.cyksj.mapper.OrderDonMapper;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.manage.distribute.DistributeMoneyApplyMapper;
+import com.cyksj.mapper.manage.distribute.DistributePointsExchangeMoneyMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.DistributeApplyMoneyReq;
+import com.cyksj.model.request.UserDistributeReq;
+import com.cyksj.model.views.DistributeMoneyApplyView;
+import com.cyksj.model.views.MoneyApplyView;
+import com.cyksj.model.views.UserDistributeView;
+import com.cyksj.model.views.UserDistributeViews;
+import com.cyksj.service.distribute.DistributeService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+import java.util.Optional;
+
+/*
+ *项目名: netflix
+ *文件名: DistributeController
+ *创建者: JavaZou
+ *创建时间:2022/11/14 12:06
+ */
+@RestController
+@RequestMapping("/manage/distribute")
+@RequiredArgsConstructor
+@Slf4j
+public class DistributeController {
+
+	private final DistributeService distributeService;
+
+	private final UserDistributeMapper userDistributeMapper;
+
+	private final BeanSearcher beanSearcher;
+
+	private final OrderDonMapper orderDonMapper;
+
+	private final DistributeMoneyApplyMapper distributeMoneyApplyMapper;
+
+	private final DistributePointsExchangeMoneyMapper distributePointsExchangeMoneyMapper;
+
+	private final GoodsDonMapper goodsDonMapper;
+
+	private final UserMapper userMapper;
+
+	/**
+	 * 添加固定推广者
+	 */
+	@PostMapping
+	public Result<String> saveDistributes(@RequestBody @NotNull UserDistributeReq userDistributeReq) {
+		distributeService.insertDistribute(userDistributeReq);
+		return GatewayResponse.SUCCESS.newBuilder().toResult("添加成功");
+	}
+
+	/**
+	 * 删除固定推广者
+	 */
+	@DeleteMapping("/del/{id}")
+	public Result<String> deleteDistributesById(@PathVariable Long id) {
+		if (id == null || id < 1) {
+			throw BusinessRuntimeException.getInstance("id不存在");
+		}
+		userDistributeMapper.deleteById(id);
+		return GatewayResponse.SUCCESS.newBuilder().toResult("删除成功");
+	}
+
+	/**
+	 * 推广者编辑
+	 */
+	@PutMapping
+	public Result<String> editDistribute(@RequestBody UserDistributeReq userDistributeReq) {
+		distributeService.editDistribute(userDistributeReq);
+		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
+	}
+
+	/**
+	 * 固定推广者详情
+	 */
+	@GetMapping("/get/detail/{id}")
+	public Result<List<UserDistributeView>> getDetailById(@PathVariable Long id) {
+		return GatewayResponse.SUCCESS.newBuilder().toResult(beanSearcher.searchAll(UserDistributeView.class, MapUtils.builder()
+				.field(UserDistributeView::getDistribute_id, id).op(Operator.Equal)
+				.orderBy(UserDistributeView::getGoodsId).asc()
+				.build()));
+	}
+
+	/**
+	 * 固定推广者列表
+	 */
+	@GetMapping
+	public Result<SearchResult<UserDistributeViews>> distributeList(HttpServletRequest request) {
+		SearchResult<UserDistributeViews> search = beanSearcher.search(UserDistributeViews.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		DistributePointsExchangeMoney pointsMoneyRate = distributePointsExchangeMoneyMapper.selectOne(null);
+		Optional.ofNullable(search.getDataList()).ifPresent(list -> list.forEach(view -> {
+			BigDecimal num = view.getPoints().divide(BigDecimal.valueOf(pointsMoneyRate.getPoints()), RoundingMode.DOWN);
+			view.setAvailableMoney(pointsMoneyRate.getMoney().multiply(num));
+			List<DistributeMoneyApply> moneyApplies = distributeMoneyApplyMapper.selectList(Wrappers.lambdaQuery(DistributeMoneyApply.class).eq(DistributeMoneyApply::getVerifyStatus, DistributeMoneyApply.Status.success).eq(DistributeMoneyApply::getUserId, view.getUserId()).select(DistributeMoneyApply::getMoney));
+			Optional<BigDecimal> money = moneyApplies.stream().map(apply -> apply.getMoney()).reduce(BigDecimal::add);
+			view.setGotMoney(money.isPresent() ? money.get() : BigDecimal.ZERO);
+			Integer orders = userDistributeMapper.count(view.getUserId());
+			view.setOrders(orders);
+		}));
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 获取平台分销比例
+	 */
+	@GetMapping("/get/plat")
+	public Result<List<GoodsDon>> getGoodsDistributeRate() {
+		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonMapper.selectList(Wrappers.lambdaQuery(GoodsDon.class).eq(GoodsDon::getType, 1).eq(GoodsDon::getDeleted, true).orderByAsc(GoodsDon::getId).select(GoodsDon::getId, GoodsDon::getTitle, GoodsDon::getRate)));
+	}
+
+	/**
+	 * 平台分销比例修改
+	 */
+	@PutMapping("/put/goods/rate")
+	public Result<String> editGoodsDistributeRate(@RequestBody UserDistributeReq userDistributeReq) {
+		for (UserPlatDistributeRate rate : userDistributeReq.getRates()) {
+			if (rate.getRate() < 0 || rate.getRate() > 100) {
+				throw new BusinessRuntimeException("比例错误");
+			}
+			GoodsDon goodsDon = goodsDonMapper.selectById(rate.getGoodsId());
+			if (goodsDon == null || goodsDon.getType() == 2) {
+				throw new BusinessRuntimeException("平台错误");
+			}
+			goodsDon.setRate(rate.getRate());
+			goodsDonMapper.updateById(goodsDon);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
+	}
+
+	/**
+	 * 提现title
+	 */
+	@GetMapping("/get/applyMoney/title")
+	public Result<MoneyApplyView> applyMoneyTitle() {
+		MoneyApplyView moneyApplyView = new MoneyApplyView();
+		moneyApplyView.setThreshold(distributePointsExchangeMoneyMapper.selectOne(null));
+		List<DistributeMoneyApply> distributeMoneyApplies = distributeMoneyApplyMapper.selectList(Wrappers.lambdaQuery(DistributeMoneyApply.class).eq(DistributeMoneyApply::getVerifyStatus, DistributeMoneyApply.Status.success).select(DistributeMoneyApply::getMoney));
+		Optional<BigDecimal> reduce = distributeMoneyApplies.stream().map(DistributeMoneyApply::getMoney).reduce(BigDecimal::add);
+		moneyApplyView.setGotMoney(reduce.isPresent() ? reduce.get() : BigDecimal.ZERO);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(moneyApplyView);
+	}
+
+	/**
+	 * 提现列表
+	 */
+	@GetMapping("/get/applyMoney/list")
+	public Result<SearchResult<DistributeMoneyApplyView>> applyMoneyList(HttpServletRequest request) {
+		SearchResult<DistributeMoneyApplyView> search = beanSearcher.search(DistributeMoneyApplyView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 提现审核
+	 */
+	@PutMapping("/verify/applyMoney")
+	public Result<String> verifyApplyMoney(@RequestBody @Validated DistributeApplyMoneyReq distributeApplyMoneyReq) {
+		DistributeMoneyApply.Status status = DistributeMoneyApply.Status.checkStatus(distributeApplyMoneyReq.getVerifyStatus());
+		if (status == null || status == DistributeMoneyApply.Status.verifying) {
+			throw BusinessRuntimeException.getInstance("审核状态错误");
+		}
+		DistributeMoneyApply distributeMoneyApply = distributeMoneyApplyMapper.selectById(distributeApplyMoneyReq.getId());
+		if (distributeMoneyApply == null) {
+			throw BusinessRuntimeException.getInstance("提现记录不存在");
+		}
+		if (distributeMoneyApply.getVerifyStatus() != DistributeMoneyApply.Status.verifying) {
+			throw BusinessRuntimeException.getInstance("该提现记录已处理,无法再进行审核");
+		}
+		distributeMoneyApply.setVerifyStatus(status);
+		if (DistributeMoneyApply.Status.fail.name().equals(distributeApplyMoneyReq.getVerifyStatus()) && StrUtil.isEmpty(distributeApplyMoneyReq.getReason())) {
+			throw BusinessRuntimeException.getInstance("拒绝原因为空");
+		}
+		if (DistributeMoneyApply.Status.fail.name().equals(distributeApplyMoneyReq.getVerifyStatus())) {
+			distributeMoneyApply.setReason(distributeApplyMoneyReq.getReason());
+			while (true) {
+				User user = userMapper.selectById(distributeMoneyApply.getUserId());
+				if (user == null) {
+					break;
+				}
+				BigDecimal points = user.getPoints();
+				Integer update = userMapper.updatePoints(user.getId(), points, distributeMoneyApply.getPoints());
+				if (update == 1) {
+					log.info("归还积分:{}至用户{}结束", distributeMoneyApply.getPoints(), user.getId());
+					break;
+				}
+			}
+		}
+		if (DistributeMoneyApply.Status.success.name().equals(distributeApplyMoneyReq.getVerifyStatus())) {
+			if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {
+				throw BusinessRuntimeException.getInstance("审核成功时,打款图片不存在");
+			}
+			distributeMoneyApply.setImg(distributeApplyMoneyReq.getImg());
+		}
+		distributeMoneyApplyMapper.updateById(distributeMoneyApply);
+		return GatewayResponse.SUCCESS.newBuilder().toResult("审核操作成功");
+	}
+
+	/**
+	 * 审核成功,编辑打款截图
+	 */
+	@PutMapping("/verify/applyMoney/img")
+	public Result<String> putApplyMoneyImg(@RequestBody @Validated DistributeApplyMoneyReq distributeApplyMoneyReq) {
+		DistributeMoneyApply entity = distributeMoneyApplyMapper.selectById(distributeApplyMoneyReq.getId());
+		if (entity == null || entity.getVerifyStatus() != DistributeMoneyApply.Status.success) {
+			throw BusinessRuntimeException.getInstance("审核记录错误");
+		}
+		if (StrUtil.isBlank(distributeApplyMoneyReq.getImg())) {
+			throw BusinessRuntimeException.getInstance("打款截图为空");
+		}
+		DistributeMoneyApply apply = new DistributeMoneyApply();
+		apply.setImg(distributeApplyMoneyReq.getImg());
+		apply.setId(distributeApplyMoneyReq.getId());
+		distributeMoneyApplyMapper.updateById(apply);
+		return GatewayResponse.SUCCESS.newBuilder().toResult("编辑成功");
+	}
+}

+ 23 - 4
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -19,12 +19,14 @@ import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.PhoneCodeMapper;
 import com.cyksj.mapper.WxAppMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
 import com.cyksj.model.dto.AuthRedirect;
 import com.cyksj.model.dto.AuthToken;
 import com.cyksj.model.dto.GzhOAuth2UserInfo;
 import com.cyksj.model.dto.JsSdkTicket;
 import com.cyksj.model.entity.PhoneCode;
 import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.UserDistributeShared;
 import com.cyksj.model.request.LoginPhoneReq;
 import com.cyksj.model.response.LoginPhoneRep;
 import com.cyksj.redis.RedisService;
@@ -36,6 +38,7 @@ import com.cyksj.web.util.StpUserUtil;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.dao.DuplicateKeyException;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
@@ -83,10 +86,10 @@ public class AuthorizationController {
 
     private final PhoneCodeMapper phoneCodeMapper;
 
-
+    private final UserDistributeSharedMapper userDistributeSharedMapper;
 
     @GetMapping(value = "/weChat")
-    public void base(String url,Long shared, String authType, HttpServletResponse response) throws Exception {
+    public void base(String url,Long sharedId, String authType, HttpServletResponse response) throws Exception {
 
         log.info("微信授权转跳. url: {},authType:{}",url,authType);
 
@@ -96,7 +99,7 @@ public class AuthorizationController {
 
         Long mappingId = SEQUENCE.nextId();
         redisService.set(mappingId.toString(),url,60*60*24L);
-        AuthRedirect redirect = new AuthRedirect().setMappingId(mappingId).setSharedId(shared);
+        AuthRedirect redirect = new AuthRedirect().setMappingId(mappingId).setSharedId(sharedId);
         String state = Codec.DoBase64.custom().setData(Jsons.toJson(redirect)).encodeAsText();
 
         response.sendRedirect(authorizationService.createUrl(state,authType));
@@ -122,7 +125,7 @@ public class AuthorizationController {
         GzhOAuth2UserInfo userinfo = weChatService.getUserInfo(token.getAccessToken(), token.getOpenid());
 
         //保存用户信息
-        User user = userService.saveAuth(userinfo);
+        User user = userService.saveAuth(userinfo, re.getSharedId());
 
         //写回登陆信息
         StpUserUtil.login(user.getId());
@@ -309,6 +312,8 @@ public class AuthorizationController {
         }
         //保存用户信息
         User user = userService.getOne(Wrappers.lambdaQuery(User.class).eq(User::getLoginPhone, loginPhoneReq.getPhone()).last("limit 1"));
+        UserDistributeShared userDistributeShared = null;
+        Long sharedId = loginPhoneReq.getSharedId();
         if (user == null) {
             user = new User();
             user.setLoginPhone(loginPhoneReq.getPhone());
@@ -316,10 +321,24 @@ public class AuthorizationController {
             //默认头像
             user.setHeadimgurl("https://cdn.sxfoundation.com/picture/f6ee11101c4f5f0bc48d88aca7a5dbfd-1666945673391.png");
             userService.save(user);
+            //新用户分销
+            if (sharedId != null) {
+                userDistributeShared = new UserDistributeShared();
+                userDistributeShared.setSharedId(loginPhoneReq.getSharedId());
+            }
         }
         //写回登陆信息
         StpUserUtil.login(user.getId());
         LoginPhoneRep loginPhoneRep = new LoginPhoneRep(StpUserUtil.getTokenValue(), user.getId(), user.getNickname(), user.getHeadimgurl());
+        //存在分销
+        if (userDistributeShared != null) {
+            userDistributeShared.setUserId(user.getId());
+            try {
+                userDistributeSharedMapper.insert(userDistributeShared);
+            } catch (DuplicateKeyException e) {
+                log.info("分销被邀请人重复插入");
+            }
+        }
         return GatewayResponse.SUCCESS.newBuilder().toResult(loginPhoneRep);
     }
 }

+ 203 - 0
netflix-web/src/main/java/com/cyksj/web/controller/user/DistributePopularizeController.java

@@ -0,0 +1,203 @@
+package com.cyksj.web.controller.user;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.extra.qrcode.QrCodeUtil;
+import cn.hutool.extra.qrcode.QrConfig;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.EnvCommonService;
+import com.cyksj.common.annotation.NoSubmit;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GoodsDonMapper;
+import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.manage.distribute.DistributeMoneyApplyMapper;
+import com.cyksj.mapper.manage.distribute.DistributePointsExchangeMoneyMapper;
+import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.ApplyMoneyReq;
+import com.cyksj.model.views.DistributeMoneyApplyView;
+import com.cyksj.model.views.DistributePopularizeOrdersView;
+import com.cyksj.model.views.DistributePopularizeView;
+import com.cyksj.model.views.UserDistributeView;
+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.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+import java.util.Optional;
+
+/*
+ *项目名: netflix
+ *文件名: DistributePopularizeController
+ *创建者: JavaZou
+ *创建时间:2022/11/15 13:59
+ * 服务端-》我的分发推广controller
+ */
+@RestController
+@RequestMapping("/distribute/popularize")
+@RequiredArgsConstructor
+public class DistributePopularizeController {
+	private final EnvCommonService envCommonService;
+
+	private final UserMapper userMapper;
+
+	private final BeanSearcher beanSearcher;
+
+	private final GoodsDonMapper goodsDonMapper;
+
+	private final GoodsDonSkuMapper goodsDonSkuMapper;
+
+	private final DistributePointsExchangeMoneyMapper distributePointsExchangeMoneyMapper;
+
+	private final DistributeMoneyApplyMapper distributeMoneyApplyMapper;
+
+	private final UserDistributeMapper userDistributeMapper;
+
+	private final DistributeWaitingSendPointsMapper distributeWaitingSendPointsMapper;
+
+	/**
+	 * 推广订单明细
+	 */
+	@GetMapping("/orders/detail")
+	public Result<SearchResult<DistributePopularizeOrdersView>> getOrdersView(HttpServletRequest request) {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		SearchResult<DistributePopularizeOrdersView> search = beanSearcher.search(DistributePopularizeOrdersView.class,
+				MapUtils.flatBuilder(request.getParameterMap())
+						.field(DistributePopularizeOrdersView::getSharedId, userId)
+						.build());
+		search.getDataList().forEach(data -> {
+			GoodsDon goodsDon = goodsDonMapper.selectById(data.getGoodsId());
+			GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(data.getSkuId());
+			data.setGoodsTitle(goodsDon.getTitle());
+			data.setSpecVal(goodsDonSku.getSpecVal());
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 提现明细
+	 */
+	@GetMapping("/applyMoney/detail")
+	public Result<SearchResult<DistributeMoneyApplyView>> getApplyMoneyView(HttpServletRequest request) {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		SearchResult<DistributeMoneyApplyView> search = beanSearcher.search(DistributeMoneyApplyView.class,
+				MapUtils.flatBuilder(request.getParameterMap())
+						.field(DistributeMoneyApplyView::getUserId, userId).op(Operator.Equal)
+						.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 个人推广详情
+	 */
+	@GetMapping("/get/detail")
+	public Result<DistributePopularizeView> getDetail() {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		DistributePopularizeView distributePopularizeView = new DistributePopularizeView();
+		String domain = envCommonService.getHost();
+//		distributePopularizeView.setUrl(String.format("https://%s/8081/api/auth/weChat?url=https://%s/yinhe/web&sharedId=%s", domain, domain, userId));
+		distributePopularizeView.setUrl(String.format("https://%s/yinhe/web?sharedId=%s", domain, userId));
+		distributePopularizeView.setUrlCode(QrCodeUtil.generateAsBase64(distributePopularizeView.getUrl(), QrConfig.create(), "png"));
+		User user = userMapper.selectById(userId);
+		distributePopularizeView.setGotPoints(user.getPoints());
+		Integer orders = userDistributeMapper.count(userId);
+		distributePopularizeView.setDistributeOrders(orders);
+		UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, userId).select(UserDistribute::getId).last("limit 1"));
+		if (userDistribute != null) {
+			//是否是固定推广者
+			UserDistributeView userDistributeView = beanSearcher.searchFirst(UserDistributeView.class, MapUtils.builder()
+					.field(UserDistributeView::getDistribute_id, userDistribute.getId()).op(Operator.Equal)
+					.orderBy(UserDistributeView::getRate).desc()
+					.build());
+			//最高平台比例
+			distributePopularizeView.setHighestRate(userDistributeView.getRate());
+		}else {
+			GoodsDon goodsDon = goodsDonMapper.selectOne(Wrappers.lambdaQuery(GoodsDon.class).orderByDesc(GoodsDon::getRate).select(GoodsDon::getRate).last("limit 1"));
+			distributePopularizeView.setHighestRate(goodsDon.getRate());
+		}
+		List<DistributeWaitingSendPoints> distributeWaitingSendPoints = distributeWaitingSendPointsMapper.selectList(Wrappers.lambdaQuery(DistributeWaitingSendPoints.class).eq(DistributeWaitingSendPoints::getSendStatus, DistributeWaitingSendPoints.Status.waiting).eq(DistributeWaitingSendPoints::getSharedId, userId).select(DistributeWaitingSendPoints::getPoints));
+		BigDecimal waitingPoints = BigDecimal.ZERO;
+		if (!distributeWaitingSendPoints.isEmpty()) {
+			Optional<BigDecimal> points = distributeWaitingSendPoints.stream().map(DistributeWaitingSendPoints::getPoints).reduce(BigDecimal::add);
+			if (points.isPresent()) {
+				waitingPoints = points.get();
+			}
+		}
+		distributePopularizeView.setWaitingSendPoints(waitingPoints);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(distributePopularizeView);
+	}
+
+	/**
+	 * 提现
+	 */
+	@NoSubmit
+	@PostMapping("/post/applyMoney")
+	@Transactional(rollbackFor = Throwable.class)
+	public Result<Integer> applyMoney(@RequestBody ApplyMoneyReq applyMoneyReq) {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		User user = userMapper.selectById(userId);
+		if (user == null) {
+			throw BusinessRuntimeException.getInstance("请先授权登录");
+		}
+		if (ObjectUtil.hasEmpty(applyMoneyReq.getAccount(), applyMoneyReq.getRealName())) {
+			throw BusinessRuntimeException.getInstance("必填项不能为空");
+		}
+		DistributePointsExchangeMoney distributePointsExchangeMoney = distributePointsExchangeMoneyMapper.selectOne(Wrappers.lambdaQuery(DistributePointsExchangeMoney.class).orderByDesc(DistributePointsExchangeMoney::getPoints).last("limit 1"));
+		BigDecimal minPoints = BigDecimal.valueOf(distributePointsExchangeMoney.getMinPoints());
+		BigDecimal min = BigDecimal.valueOf(distributePointsExchangeMoney.getPoints());
+		if (user.getPoints().compareTo(minPoints) < 0) {
+			throw BusinessRuntimeException.getInstance("您当前积分未达到积分门槛,无法提现");
+		}
+		//今日是否已提现
+		DistributeMoneyApply apply = distributeMoneyApplyMapper.selectOne(Wrappers.lambdaQuery(DistributeMoneyApply.class).eq(DistributeMoneyApply::getUserId, userId).between(DistributeMoneyApply::getCreatedTime, DateUtil.beginOfDay(DateTime.now()), DateUtil.endOfDay(DateTime.now())).last("limit 1"));
+		if (apply != null) {
+			throw BusinessRuntimeException.getInstance("今日已提现,请明日再进行操作");
+		}
+		BigDecimal num = user.getPoints().divide(min, RoundingMode.DOWN);
+		BigDecimal points = min.multiply(num);
+		Integer update = userMapper.subPoints(user.getId(), points);
+		if (update == 1) {
+			DistributeMoneyApply distributeMoneyApply = new DistributeMoneyApply();
+			distributeMoneyApply.setUserId(userId);
+			distributeMoneyApply.setPoints(points);
+			distributeMoneyApply.setMoney(num.multiply(distributePointsExchangeMoney.getMoney()));
+			distributeMoneyApply.setVerifyStatus(DistributeMoneyApply.Status.verifying);
+			distributeMoneyApply.setAccount(applyMoneyReq.getAccount());
+			distributeMoneyApply.setRealName(applyMoneyReq.getRealName());
+			distributeMoneyApplyMapper.insert(distributeMoneyApply);
+			return GatewayResponse.SUCCESS.newBuilder().toResult(distributeMoneyApply.getMoney().intValue());
+		}
+		throw BusinessRuntimeException.getInstance("系统异常,请重新提交提现申请");
+	}
+
+	/**
+	 * 获取积分兑换门槛
+	 */
+	@GetMapping("/applyMoney/threshold")
+	public Result<DistributePointsExchangeMoney> getThreshold() {
+		return GatewayResponse.SUCCESS.newBuilder().toResult(distributePointsExchangeMoneyMapper.selectOne(Wrappers.lambdaQuery(DistributePointsExchangeMoney.class).last("limit 1")));
+	}
+
+	/**
+	 * 提现缓存数据
+	 */
+	@GetMapping("/get/applyMoney/detail")
+	public Result<DistributeMoneyApply> getLastApplyDetail() {
+		Long userId = StpUserUtil.getLoginIdAsLong();
+		DistributeMoneyApply apply = distributeMoneyApplyMapper.selectOne(Wrappers.lambdaQuery(DistributeMoneyApply.class).eq(DistributeMoneyApply::getUserId, userId).orderByDesc(DistributeMoneyApply::getId).last("limit 1"));
+		return GatewayResponse.SUCCESS.newBuilder().toResult(apply);
+	}
+}

+ 1 - 1
netflix-web/src/main/resources/application.yml

@@ -1 +1 @@
-spring:
  profiles:
    active:
    - ${activeProfile}
    
+spring:
  profiles:
    active:
      - ${activeProfile}