Ver código fonte

快手时段消耗预警 改内网

zhaoxian 11 meses atrás
pai
commit
7b915be06a
24 arquivos alterados com 1448 adições e 7 exclusões
  1. 5 1
      job-kuaishou/pom.xml
  2. 15 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/controller/KuaishouController.java
  3. 153 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/entity/Project.java
  4. 170 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/entity/UserAllocation.java
  5. 16 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/KuaishouReportHourlyAccountMapper.java
  6. 3 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/OauthTokenMapper.java
  7. 72 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/UserAllocationMapper.java
  8. 23 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/WexinConfigMapper.java
  9. 19 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/xml/KuaishouReportHourlyAccountMapper.xml
  10. 24 1
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/xml/OauthTokenMapper.xml
  11. 269 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/xml/UserAllocationMapper.xml
  12. 32 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/xml/WexinConfigMapper.xml
  13. 7 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/IAccountWarningService.java
  14. 4 2
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/IOauthTokenService.java
  15. 65 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/IUserAllocationService.java
  16. 22 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/IWexinConfigService.java
  17. 111 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/impl/AccountWarningServiceImpl.java
  18. 5 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/impl/OauthTokenServiceImpl.java
  19. 150 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/impl/UserAllocationServiceImpl.java
  20. 31 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/impl/WexinConfigServiceImpl.java
  21. 92 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/utils/weixin/CorpWexinUtils.java
  22. 86 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/utils/weixin/WexinConfig.java
  23. 50 0
      job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/handler/KuaishouHourlyAccountWarningLoadJob.java
  24. 24 3
      xxl-job-core/src/main/java/com/xxl/job/core/util/DateUtil.java

+ 5 - 1
job-kuaishou/pom.xml

@@ -71,7 +71,11 @@
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>com.github.binarywang</groupId>
+            <artifactId>weixin-java-cp</artifactId>
+            <version>3.6.0</version>
+        </dependency>
         <!-- mybatis-plus -->
         <dependency>
             <groupId>com.baomidou</groupId>

+ 15 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/controller/KuaishouController.java

@@ -1,6 +1,7 @@
 package cn.com.ctop.job.kuaishou.controller;
 
 import cn.com.ctop.job.kuaishou.data.mapper.KuaishouAccountReportHourlyMapper;
+import cn.com.ctop.job.kuaishou.data.service.IAccountWarningService;
 import cn.com.ctop.job.kuaishou.data.service.IAdUnitReportService;
 import cn.com.ctop.job.kuaishou.data.service.IKuaishouAccountReportDailyService;
 import cn.com.ctop.job.kuaishou.data.service.IKuaishouAccountReportHourlyService;
@@ -17,6 +18,8 @@ import cn.com.ctop.job.kuaishou.data.utils.DateUtils;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.google.common.collect.Lists;
+import com.xxl.job.core.context.XxlJobHelper;
+import com.xxl.job.core.util.DateUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.SneakyThrows;
@@ -249,4 +252,16 @@ public class KuaishouController {
         kuaishouAccountReportDailyService.liveComponentReport(accountId, token, yesterday, yesterday);
     }
 
+    @Autowired
+    private IAccountWarningService accountWarningService;
+
+    @GetMapping(value = "testD")
+    public void testD(Long accountId) throws Exception {
+        List<JSONObject> tokens = tokenService.selectKuaiShouToken();
+        String todayStr = DateUtil.formatDate(new Date());
+        Integer todayInt = DateUtil.getIntegerDate(todayStr);
+        Integer yesterdayInt = DateUtil.getIntegerDate(DateUtil.getAnotherDay("yyyy-MM-dd", todayStr, -1));
+        tokens.forEach(token -> accountWarningService.kuaiShouAccountWarning(token.getLong("accountId"), todayInt, yesterdayInt));
+    }
+
 }

+ 153 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/entity/Project.java

@@ -0,0 +1,153 @@
+package cn.com.ctop.job.kuaishou.data.entity;
+
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目
+ *
+ * @author jeecg-boot
+ * @version V1.0
+ * @date 2019-11-19
+ */
+@Data
+@TableName("ctop_project")
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "ctop_project对象", description = "项目")
+public class Project {
+    /**
+     * id
+     */
+    @TableId(type = IdType.AUTO)
+    @ApiModelProperty(value = "id")
+    private Long id;
+    /**
+     * 项目名称
+     */
+    @Excel(name = "项目名称", width = 15)
+    @ApiModelProperty(value = "项目名称")
+    private String projectName;
+    /**
+     * 广告主id
+     */
+    @Excel(name = "广告主id", width = 15)
+    @ApiModelProperty(value = "广告主id")
+    private String advertiserId;
+
+
+    @Excel(name = "产品id", width = 15)
+    @ApiModelProperty(value = "广告主id")
+    private Long productId;
+
+    /**
+     * 创建人
+     */
+    @Excel(name = "创建人", width = 15)
+    @ApiModelProperty(value = "创建人")
+    private String userId;
+    /**
+     * 负责人id
+     */
+    @Excel(name = "负责人id", width = 15)
+    @ApiModelProperty(value = "负责人id")
+    private String responsibleId;
+
+
+    @Excel(name = "设计负责人", width = 15)
+    @ApiModelProperty(value = "设计负责人")
+    private String designResponsibleId;
+
+
+    @Excel(name = "公司id", width = 15)
+    @ApiModelProperty(value = "公司id")
+    private String companyId;
+    /**
+     * 媒体类型
+     */
+    @Excel(name = "媒体类型", width = 15)
+    @ApiModelProperty(value = "媒体类型")
+    private String mediaId;
+
+    /**
+     * 最高出价
+     */
+    private Long maxBid;
+
+    private String supplierCode;
+
+
+    // 销售
+    private String saleId;
+    /**
+     * 最高深度转化出价
+     */
+    private BigDecimal maxDeepCpaBid;
+    private Integer checkLink;
+    private Integer materialShare;
+    /**
+     * 创建时间
+     */
+    @Excel(name = "创建时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+    /**
+     * 修改时间
+     */
+    @Excel(name = "修改时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "修改时间")
+    private Date updateTime;
+
+
+    //优化目标出价类型
+    private String bidType;
+
+    //转化目标
+    private String ocpxActionType;
+
+    //深度转化目标
+    private String deepConversionType;
+
+    @TableField(exist = false)
+    private String responsibleId_dictText; // 运营负责人
+
+    @TableField(exist = false)
+    private String saleId_dictText; // 销售
+
+    @TableField(exist = false)
+    private String designResponsibleId_dictText; // 设计负责人
+    @TableField(exist = false)
+    private String advertiserId_dictText; // 广告主名称
+    @TableField(exist = false)
+    private String productId_dictText; // 产品名称
+    @TableField(exist = false)
+    private Integer needExamine;
+    @TableField(exist = false)
+    private String supplierCode_dictText;
+
+    //转化目标
+    @TableField(exist = false)
+    private JSONArray ocpxActionTypeArray;
+
+    //深度转化目标
+    @TableField(exist = false)
+    private JSONArray deepConversionTypeArray;
+}

+ 170 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/entity/UserAllocation.java

@@ -0,0 +1,170 @@
+package cn.com.ctop.job.kuaishou.data.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 用户分配
+ *
+ * @author jeecg-boot
+ * @version V1.0
+ * @date 2019-08-08
+ */
+@Data
+@TableName("ctop_user_allocation")
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "ctop_user_allocation对象", description = "用户分配")
+public class UserAllocation {
+
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
+    @ApiModelProperty(value = "主键ID")
+    private Long id;
+    /**
+     * 登陆人id
+     */
+    @Excel(name = "登陆人id", width = 15)
+    @ApiModelProperty(value = "登陆人id")
+    private String userId;
+
+
+    @Excel(name = "登陆人名称", width = 15)
+    @ApiModelProperty(value = "登陆人名称")
+    private String userName;
+
+    /**
+     * 账户id --授权
+     */
+    @Excel(name = "账户id --授权", width = 15)
+    @ApiModelProperty(value = "账户id --授权")
+    private Long accountId;
+    /**
+     * 广告主ID
+     */
+    @Excel(name = "广告主ID", width = 15)
+    @ApiModelProperty(value = "广告主ID")
+    private String advertiserId;
+
+    private String systemType;
+
+    /**
+     * 项目id
+     */
+    private Long projectId;
+
+    /**
+     * 输入账号  --登陆
+     */
+    @Excel(name = "输入账号  --登陆", width = 15)
+    @ApiModelProperty(value = "输入账号  --登陆")
+    private String accountName;
+
+    /**
+     * 预警 金额
+     */
+    private BigDecimal warningAmount;
+
+    /**
+     * 预警 比例
+     */
+    private BigDecimal warningProportion;
+
+    /**
+     * 创建时间
+     */
+    @Excel(name = "创建时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    /**
+     * 授权名称
+     */
+    @Excel(name = "授权名称", width = 15)
+    @ApiModelProperty(value = "授权名称")
+    private String authName;
+
+    /**
+     * 授权开始时间
+     */
+    @Excel(name = "授权开始时间", width = 15)
+    @ApiModelProperty(value = "授权开始时间")
+    private String authBeginTime;
+
+
+    /**
+     * 0 启动
+     * 1 禁用
+     */
+    private Integer accountStatus;
+
+    /**
+     * 检测链接预警
+     * 0 启动
+     * 1 禁用
+     */
+    private Integer monitoringLink;
+
+    /**
+     * 检测链接预警
+     * 0 启动
+     * 1 禁用
+     */
+    private Integer landingPage;
+
+    /**
+     * 是否开启删评论
+     * 0 启动
+     * 1 禁用
+     */
+    private Integer deleteComment;
+    /**
+     * 自动投放,0关闭,1开启
+     */
+    private Integer autoDelivery;
+    /**
+     * 物料类型 0-不同步,1应用包,(2人群包,3定向包)
+     */
+    private String materialType;
+
+    /**
+     * 修改时间
+     */
+    @Excel(name = "修改时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "修改时间")
+    private Date updateTime;
+    /**
+     * 平台类型 1 头条 2快手
+     */
+    @Excel(name = "平台类型 1 头条 2快手", width = 15)
+    @ApiModelProperty(value = "平台类型 1 头条 2快手")
+    private String mediaId;
+
+
+
+
+   /* @TableField(exist = false)
+    private String advertiserName;
+
+    @TableField(exist = false)
+    private String projectName;*/
+
+}

+ 16 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/KuaishouReportHourlyAccountMapper.java

@@ -0,0 +1,16 @@
+package cn.com.ctop.job.kuaishou.data.mapper;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+public interface KuaishouReportHourlyAccountMapper {
+
+    Integer selectMaxHour(@Param("accountId") Long accountId, @Param("statDate") Integer statDate);
+
+    BigDecimal getCost(@Param("accountId") Long accountId, @Param("statHour") Integer statHour, @Param("statDate") Integer statDate);
+}

+ 3 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/OauthTokenMapper.java

@@ -14,9 +14,12 @@ import java.util.List;
  * @version V1.0
  */
 public interface OauthTokenMapper extends BaseMapper<OauthToken> {
+
     String getByAccountId(@Param("accountId") Long accountId);
 
     List<JSONObject> getByProjectId(@Param("projectId") Long projectId);
 
     List<Long> getAllAccountIds();
+
+    List<JSONObject> selectKuaiShouToken();
 }

+ 72 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/UserAllocationMapper.java

@@ -0,0 +1,72 @@
+package cn.com.ctop.job.kuaishou.data.mapper;
+
+import cn.com.ctop.job.kuaishou.data.entity.Project;
+import cn.com.ctop.job.kuaishou.data.entity.UserAllocation;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @Description: 用户分配
+ * @Author: jeecg-boot
+ * @Date: 2019-08-08
+ * @Version: V1.0
+ */
+public interface UserAllocationMapper extends BaseMapper<UserAllocation> {
+    List<UserAllocation> selectAccountListByProjectId(@Param("projectId") Long projectId);
+
+    String queryAdvertiserId(@Param("accountId") Long accountId);
+
+    String queryUserIdByAccountId(@Param("accountId") Long accountId);
+
+    List<JSONObject> getAccountListByProject(@Param("projectId") Long projectId);
+
+    List<JSONObject> getUserIdListByProjectId(@Param("projectId") Long projectId);
+
+    List<JSONObject> getAccountIdListByUserId(@Param("userId") String userId);
+
+    List<JSONObject> getAccountIdsByUserId(@Param("userId") String userId);
+
+    List<JSONObject> getAllAccountIdsByMediaId(@Param("mediaId") String mediaId);
+
+    Long getProjectIdByAccountId(@Param("accountId") Long accountId);
+
+    UserAllocation getUserAllocation(@Param("accountId") Long accountId);
+
+    JSONObject getSwitchStatusByAccount(@Param("accountId") Long accountId);
+
+    List<Long> queryAccountsByDeleteComment();
+
+    String getCompanyNameByUserId(@Param("planId") String planId);
+
+    List<UserAllocation> listByMediaId(@Param("mediaId") String mediaId, @Param("accountStatus") Integer accountStatus);
+
+    List<JSONObject> getAccountListByProjectList(@Param("list") List list);
+
+    List<Long> getValidProjectIds(@Param("mediaId") Integer mediaId);
+
+    List<UserAllocation> getAccountListByUserIdAndProductId(@Param("userId") String userId, @Param("projectId") Long projectId, @Param("productId") Long productId);
+
+    List<JSONObject> getUserIdListByProductId(@Param("productId") Long productId);
+
+    List<JSONObject> getByAccountIds(@Param("accountIds") JSONArray accountIds);
+
+    List<Long> getKuaiShouUserIdListByProjectId(@Param("projectId") Long projectId);
+
+    List<JSONObject> selectAccountsByKuaishouUserId(@Param("userId") Long userId);
+
+    int updateProjectStrategyStatus(@Param("accountId") Long accountId, @Param("projectStrategy") Integer projectStrategy);
+
+    List<Long> queryAutomaticAccounts(@Param("projectId") Long projectId);
+
+    List<Long> getIdList();
+
+    JSONObject getProjectByAccountId(Long accountId);
+
+    Project getProjectEntity(Long projectId);
+
+    UserAllocation getOneByAccountId(Long accountId);
+}

+ 23 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/WexinConfigMapper.java

@@ -0,0 +1,23 @@
+package cn.com.ctop.job.kuaishou.data.mapper;
+
+import cn.com.ctop.job.kuaishou.data.utils.weixin.WexinConfig;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 企业微信配置信息
+ *
+ * @author jeecg-boot
+ * 2021-06-17
+ * @version V1.0
+ */
+public interface WexinConfigMapper extends BaseMapper<WexinConfig> {
+
+    List<WexinConfig> getAll();
+
+    List<JSONObject> selectUsersByAccountId(@Param("accountId") Long accountId);
+
+}

+ 19 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/xml/KuaishouReportHourlyAccountMapper.xml

@@ -0,0 +1,19 @@
+<?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="cn.com.ctop.job.kuaishou.data.mapper.KuaishouReportHourlyAccountMapper">
+    <select id="selectMaxHour" resultType="java.lang.Integer">
+        select max(`hour`)
+        from application.kuaishou_account_report_hourly_dw
+        where account_id = #{accountId}
+          and stat_date = #{statDate}
+    </select>
+
+    <select id="getCost" resultType="java.math.BigDecimal">
+        select charge
+        from application.kuaishou_account_report_hourly_dw
+        where account_id = #{accountId}
+          and stat_date = #{statDate}
+          and `hour` = #{statHour}
+    </select>
+
+</mapper>

+ 24 - 1
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/xml/OauthTokenMapper.xml

@@ -3,7 +3,7 @@
 <mapper namespace="cn.com.ctop.job.kuaishou.data.mapper.OauthTokenMapper">
 
     <select id="getByAccountId" resultType="java.lang.String">
-        SELECT (CASE
+        SELECT (CasE
                     WHEN
                         t2.access_token IS NOT NULL
                         THEN t2.access_token
@@ -35,4 +35,27 @@
           and account_status = 0
     </select>
 
+    <select id="selectKuaiShouToken" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT
+            t1.id as 'id',
+            t1.media_id as 'mediaId',
+            t1.advertiser_id as 'advertiser_id',
+            t1.account_id as 'accountId',
+            (CasE WHEN t3.access_token IS NOT NULL THEN t3.access_token ELSE t1.access_token END ) as 'accessToken',
+            (CasE WHEN t3.refresh_token IS NOT NULL THEN t3.refresh_token ELSE t1.refresh_token END ) as 'refreshToken',
+            t1.agent_type as 'agentType',
+            t1.app_id as 'appId',
+            t1.access_token_expires_in as 'accessTokenExpiresIn',
+            t1.refresh_token_expires_in as 'refreshTokenExpiresIn',
+            t1.create_time as 'createTime',
+            t1.update_time as 'updateTime'
+        FROM
+            `jeecg-boot`.ctop_oauth_token t1
+                LEFT JOIN  `jeecg-boot`.ctop_user_allocation t2 ON t1.account_id = t2.account_id
+                LEFT JOIN  `jeecg-boot`.ctop_oauth_agent_token t3 ON t1.app_id = t3.app_id
+        WHERE
+            t2.account_status = 0
+          AND t1.media_id = 2;
+    </select>
+
 </mapper>

+ 269 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/xml/UserAllocationMapper.xml

@@ -0,0 +1,269 @@
+<?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="cn.com.ctop.job.kuaishou.data.mapper.UserAllocationMapper">
+
+    <select id="selectAccountListByProjectId" resultType="cn.com.ctop.job.kuaishou.data.entity.UserAllocation">
+        select a.user_id    as userId,
+               a.user_name  as userName,
+               a.auth_name  as authName,
+               a.account_id as accountId
+        from `jeecg-boot`.ctop_user_allocation a
+                 left join `jeecg-boot`.ctop_project b on a.project_id = b.id
+        where b.id = #{projectId}
+          and account_status = 0
+    </select>
+    <select id="getAccountListByUserIdAndProductId" resultType="cn.com.ctop.job.kuaishou.data.entity.UserAllocation">
+        select cua.account_id, cua.auth_name, cua.user_name
+        from `jeecg-boot`.ctop_user_allocation cua
+        left join `jeecg-boot`.ctop_project cp on cua.project_id = cp.id
+        where
+        cua.project_id = #{projectId}
+        and
+        cp.product_id=#{productId}
+        <if test="userId != null and userId != ''">
+            and cua.user_id = #{userId}
+        </if>
+
+    </select>
+
+    <select id="getOneByAccountId" resultType="cn.com.ctop.job.kuaishou.data.entity.UserAllocation">
+        select id,
+               user_id,
+               user_name,
+               account_id,
+               advertiser_id,
+               advertiser_name,
+               project_id,
+               project_name,
+               account_name,
+               warning_amount,
+               warning_proportion,
+               account_status,
+               auth_name,
+               system_type,
+               monitoring_link,
+               landing_page,
+               delete_comment,
+               project_strategy,
+               auto_delivery,
+               material_type,
+               media_id,
+               create_time,
+               update_time,
+               delivery_point,
+               auth_begin_time,
+               manager,
+               project_media_id
+        from `jeecg-boot`.ctop_user_allocation
+        where account_id = #{accountId}
+        Limit 1
+    </select>
+
+    <select id="queryAdvertiserId" resultType="String">
+        select distinct advertiser_id
+        from `jeecg-boot`.ctop_user_allocation
+        where account_id = #{accountId}
+    </select>
+    <select id="queryUserIdByAccountId" resultType="String">
+        select distinct user_id
+        from `jeecg-boot`.ctop_user_allocation
+        where account_id = #{accountId}
+    </select>
+
+    <select id="getAccountListByProject" resultType="com.alibaba.fastjson.JSONObject">
+        select t1.account_id as 'accountId', (select realname from `jeecg-boot`.sys_user where id = t1.user_id) as 'userName', t1.auth_name as 'authName'
+        from `jeecg-boot`.ctop_user_allocation t1
+        where t1.project_id = #{projectId}
+        order by t1.create_time desc
+    </select>
+
+    <select id="getAccountListByProjectList" resultType="com.alibaba.fastjson.JSONObject">
+        select
+        t1.project_id as 'projectId',
+        t1.account_id as 'accountId',
+        (select realname from `jeecg-boot`.sys_user where id = t1.user_id ) as 'userName',
+        t1.auth_name as 'authName',
+        t1.account_status as 'accountStatus'
+        from `jeecg-boot`.ctop_user_allocation t1
+        where t1.project_id in
+        <foreach collection="list" item="item" separator=","
+                 open="(" close=")">
+            #{item}
+        </foreach>
+        order by t1.create_time desc
+    </select>
+
+
+    <select id="getUserIdListByProjectId" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT t1.user_id as 'userId', t1.account_id as 'accountId', t1.user_name as 'userName'
+        from `jeecg-boot`.ctop_kuaishou_advertiser_base_info t1
+                 LEFT JOIN
+             `jeecg-boot`.ctop_user_allocation t2
+             ON t1.account_id = t2.account_id
+        WHERE t2.project_id = #{projectId}
+          AND t2.account_status = 0
+        GROUP BY t1.user_id;
+    </select>
+    <select id="getUserIdListByProductId" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT t1.user_id as 'userId', t1.account_id as 'accountId', t1.user_name as 'userName'
+        from `jeecg-boot`.ctop_kuaishou_advertiser_base_info t1
+                 LEFT JOIN `jeecg-boot`.ctop_user_allocation t2
+                           ON t1.account_id = t2.account_id
+                 LEFT JOIN `jeecg-boot`.ctop_project t3
+                           ON t2.project_id = t3.id
+        WHERE t3.product_id = #{productId}
+          AND t2.account_status = 0
+        GROUP BY t1.user_id;
+    </select>
+
+    <select id="getValidProjectIds" resultType="java.lang.Long">
+        SELECT project_id FROM `jeecg-boot`.ctop_user_allocation t1
+        where account_status = 0
+        <if test="mediaId != null">
+            AND media_id = #{mediaId}
+        </if>
+        GROUP BY project_id
+    </select>
+
+
+    <select id="getAccountIdListByUserId" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT t1.account_id as 'accountId', t1.auth_name as 'authName', t1.user_name as 'userName'
+        from `jeecg-boot`.ctop_user_allocation t1
+                 LEFT JOIN `jeecg-boot`.ctop_kuaishou_advertiser_base_info t2
+                           ON t1.account_id = t2.account_id
+        WHERE t2.user_id = #{userId}
+          AND t1.account_status = 0
+    </select>
+
+    <select id="getAccountIdsByUserId" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT allocation.account_id,
+               allocation.auth_name,
+               project.project_name as project_name
+        FROM `jeecg-boot`.ctop_user_allocation allocation
+                 left join `jeecg-boot`.ctop_project project on allocation.project_id = project.id
+        WHERE allocation.user_id = #{userId}
+          and allocation.account_status = 0
+    </select>
+
+
+    <select id="getAllAccountIdsByMediaId" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT account_id,
+               auth_name,
+               project_name
+        FROM `jeecg-boot`.ctop_user_allocation
+        WHERE media_id = #{mediaId}
+          and account_status = 0
+    </select>
+
+    <select id="getProjectIdByAccountId" resultType="java.lang.Long">
+        select project_id
+        from `jeecg-boot`.ctop_user_allocation
+        where account_id = #{accountId} limit 1
+    </select>
+
+    <select id="getUserAllocation" resultType="cn.com.ctop.job.kuaishou.data.entity.UserAllocation">
+        select *
+        from `jeecg-boot`.ctop_user_allocation
+        where account_id = #{accountId} limit 1
+    </select>
+
+    <select id="getSwitchStatusByAccount" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT monitoring_link,
+               landing_page
+        FROM `jeecg-boot`.ctop_user_allocation
+        WHERE account_id = #{accountId}
+    </select>
+
+    <select id="queryAccountsByDeleteComment" resultType="java.lang.Long">
+        SELECT account_id
+        FROM `jeecg-boot`.ctop_user_allocation
+        WHERE media_id = 2
+          AND account_status = 0
+          AND delete_comment = 0
+    </select>
+    <select id="getCompanyNameByUserId" resultType="java.lang.String">
+        select company_name
+        from `jeecg-boot`.user_company
+        where user_id = #{planId} limit 1
+    </select>
+    <select id="listByMediaId" resultType="cn.com.ctop.job.kuaishou.data.entity.UserAllocation">
+        select a.* from `jeecg-boot`.ctop_user_allocation a
+        left join `jeecg-boot`.ctop_project p on p.id = a.project_id
+        where
+        1=1
+        <if test="null!=accountStatus">
+            and a.account_status = #{accountStatus}
+        </if>
+        <if test="null!=mediaId">
+            and p.media_id = #{mediaId}
+        </if>
+    </select>
+    <select id="getByAccountIds" resultType="com.alibaba.fastjson.JSONObject">
+        select
+        account_id as 'accountId',
+        auth_name as 'authName'
+        from `jeecg-boot`.ctop_user_allocation where
+        account_id in
+        <foreach collection="accountIds" item="item" separator=","
+                 open="(" close=")">
+            #{item}
+        </foreach>
+
+
+    </select>
+    <select id="getKuaiShouUserIdListByProjectId" resultType="java.lang.Long">
+        select t2.user_id
+        from `jeecg-boot`.ctop_user_allocation t1
+                 left join `jeecg-boot`.ctop_kuaishou_advertiser_base_info t2
+                           on t1.account_id = t2.account_id
+        where t1.project_id = #{projectId}
+        group by t2.user_id
+    </select>
+    <select id="selectAccountsByKuaishouUserId" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT t2.account_id AS 'accountId', t2.user_name AS 'userName', t2.auth_name AS 'authName', t2.account_status AS 'accountStatus'
+        FROM `jeecg-boot`.ctop_kuaishou_advertiser_base_info t1
+                 LEFT JOIN `jeecg-boot`.ctop_user_allocation t2 ON t1.account_id = t2.account_id
+        WHERE t1.user_id = #{userId}
+          AND t2.id IS NOT NULL;
+
+    </select>
+
+    <update id="updateProjectStrategyStatus">
+        update `jeecg-boot`.ctop_user_allocation
+        set auto_delivery = #{projectStrategy}
+        where account_id = #{accountId}
+    </update>
+
+    <select id="queryAutomaticAccounts" resultType="java.lang.Long">
+        select account_id
+        from `jeecg-boot`.ctop_user_allocation
+        where project_id = #{projectId}
+          AND auto_delivery = 1
+    </select>
+    <select id="getIdList" resultType="java.lang.Long">
+        SELECT account_id
+        FROM `jeecg-boot`.ctop_track_monitor_configure
+        where status = 0
+
+    </select>
+
+
+    <select id="getProjectByAccountId" resultType="com.alibaba.fastjson.JSONObject">
+        select id 'projectId', project_name 'projectName', max_bid 'maxBid', bid_type 'bidType', ocpx_action_type 'ocpxActionType', deep_conversion_type 'deepConversionType'
+        from `jeecg-boot`.ctop_project
+        where id = (
+            select project_id
+            from `jeecg-boot`.ctop_user_allocation
+            where account_id = #{accountId}
+            limit 1
+            )
+    </select>
+
+    <select id="getProjectEntity" resultType="cn.com.ctop.job.kuaishou.data.entity.Project">
+        select *
+        from `jeecg-boot`.ctop_project
+        where id = #{projectId}
+    </select>
+
+
+</mapper>

+ 32 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/mapper/xml/WexinConfigMapper.xml

@@ -0,0 +1,32 @@
+<?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="cn.com.ctop.job.kuaishou.data.mapper.WexinConfigMapper">
+
+    <select id="getAll" resultType="cn.com.ctop.job.kuaishou.data.utils.weixin.WexinConfig">
+        select *
+        from `jeecg-boot`.ctop_wexin_config
+    </select>
+
+    <!-- 获取用户微信id -->
+    <select id="selectUsersByAccountId" resultType="com.alibaba.fastjson.JSONObject">
+        select wexin_id, corp_id, wexin_name
+        from `jeecg-boot`.ctop_corp_wexin_user
+        where user_id = (select ctop_user_allocation.user_id
+                         from `jeecg-boot`.ctop_user_allocation
+                         where account_id = #{accountId} limit 1)
+        union all
+        select wexin_id, corp_id, wexin_name
+        from `jeecg-boot`.ctop_corp_wexin_user
+        where user_id = (select leader_id
+                         from `jeecg-boot`.sys_user
+                         where id = (SELECT ctop_user_allocation.user_id
+                                     FROM `jeecg-boot`.ctop_user_allocation
+                                     WHERE account_id = #{accountId}
+            LIMIT 1))
+        union all
+        select wexin_id, corp_id, wexin_name
+        from `jeecg-boot`.ctop_corp_wexin_user
+        where user_id = 'b07f2bdd0f914f1dab2b4e841764911f';
+    </select>
+
+</mapper>

+ 7 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/IAccountWarningService.java

@@ -0,0 +1,7 @@
+package cn.com.ctop.job.kuaishou.data.service;
+
+public interface IAccountWarningService {
+
+    void kuaiShouAccountWarning(Long account, Integer today, Integer yesterday);
+
+}

+ 4 - 2
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/IOauthTokenService.java

@@ -14,9 +14,11 @@ import java.util.List;
  */
 public interface IOauthTokenService extends IService<OauthToken> {
 
-  String getByAccountId(Long accountId);
+    String getByAccountId(Long accountId);
 
     List<JSONObject> getByProjectId(Long projectId);
 
-  List<Long> getAllAccountIds();
+    List<Long> getAllAccountIds();
+
+  List<JSONObject> selectKuaiShouToken();
 }

+ 65 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/IUserAllocationService.java

@@ -0,0 +1,65 @@
+package cn.com.ctop.job.kuaishou.data.service;
+
+import cn.com.ctop.job.kuaishou.data.entity.Project;
+import cn.com.ctop.job.kuaishou.data.entity.UserAllocation;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 用户分配
+ * @Author: jeecg-boot
+ * @Date: 2019-08-08
+ * @Version: V1.0
+ */
+public interface IUserAllocationService extends IService<UserAllocation> {
+
+    UserAllocation getByAccountId(Long accountId);
+
+    List<UserAllocation> listByMediaId(String mediaId, int accountStatus);
+
+    String getAdvertiserIdByAccountId(Long accountId);
+
+    List<JSONObject> getAccountListByProject(Long projectId);
+
+    List<JSONObject> getUserIdListByProjectId(Long projectId);
+
+    List<JSONObject> getAccountIdListByUserId(String userId);
+
+    JSONObject getSwitchStatusByAccount(Long accountId);
+
+    List<Long> getAccountsByDeleteComment();
+
+    List<UserAllocation> getAccountListByUserIdAndProductId(String userId, Long projectId, Long productId);
+
+    Map<Long, List<JSONObject>> getAccountListByProjectList(List<JSONObject> projectList);
+
+    List<JSONObject> getUserIdListByProductId(Long productId);
+
+    /**
+     * 获取有效的项目ID集合
+     *
+     * @param mediaId 平台类型 1 头条 2快手
+     * @throws
+     */
+    List<Long> getValidProjectIds(Integer mediaId);
+
+    List<JSONObject> getByAccountIds(JSONArray accountIds);
+
+    List<Long> getKuaiShouUserIdListByProjectId(Long projectId);
+
+    List<JSONObject> selectAccountsByKuaishouUserId(Long userId);
+
+    boolean updateProjectStrategyStatus(Long accountId, Integer projectStrategy);
+
+    List<Long> queryAutomaticAccounts(Long projectId);
+
+    List<Long> getIdList();
+
+    JSONObject getProjectByAccountId(Long accountId);
+
+    Project getProjectEntity(Long projectId);
+}

+ 22 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/IWexinConfigService.java

@@ -0,0 +1,22 @@
+package cn.com.ctop.job.kuaishou.data.service;
+
+import cn.com.ctop.job.kuaishou.data.utils.weixin.WexinConfig;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 企业微信配置信息
+ *
+ * @author jeecg-boot
+ * 2021-06-17
+ * @version V1.0
+ */
+public interface IWexinConfigService extends IService<WexinConfig> {
+
+    List<WexinConfig> getAll();
+
+    List<JSONObject> selectUsersByAccountId(Long accountId);
+}

+ 111 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/impl/AccountWarningServiceImpl.java

@@ -0,0 +1,111 @@
+package cn.com.ctop.job.kuaishou.data.service.impl;
+
+import cn.com.ctop.job.kuaishou.data.entity.Project;
+import cn.com.ctop.job.kuaishou.data.entity.UserAllocation;
+import cn.com.ctop.job.kuaishou.data.mapper.KuaishouReportHourlyAccountMapper;
+import cn.com.ctop.job.kuaishou.data.service.IAccountWarningService;
+import cn.com.ctop.job.kuaishou.data.service.IUserAllocationService;
+import cn.com.ctop.job.kuaishou.data.service.IWexinConfigService;
+import cn.com.ctop.job.kuaishou.data.utils.Check;
+import cn.com.ctop.job.kuaishou.data.utils.weixin.CorpWexinUtils;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+
+@Service
+@Slf4j
+public class AccountWarningServiceImpl implements IAccountWarningService {
+    @Autowired
+    private KuaishouReportHourlyAccountMapper hourlyAccountMapper;
+    @Autowired
+    private IUserAllocationService userAllocationService;
+    @Autowired
+    private CorpWexinUtils corpWexinUtils;
+    @Resource
+    private IWexinConfigService wexinService;
+
+
+    /**
+     * 快手账户 出价预警
+     *
+     * @param accountId
+     */
+    @Override
+    public void kuaiShouAccountWarning(Long accountId, Integer today, Integer yesterday) {
+        try {
+            Integer maxHour = hourlyAccountMapper.selectMaxHour(accountId, today);
+            if (Check.isNull(maxHour)) {
+                return;
+            }
+            UserAllocation userAllocation = userAllocationService.getByAccountId(accountId);
+            if (Check.isNull(userAllocation)) {
+                return;
+            }
+            if (userAllocation.getAccountStatus() == 1) {
+                return;
+            }
+            Project project = userAllocationService.getProjectEntity(userAllocation.getProjectId());
+            BigDecimal warningAmount = userAllocation.getWarningAmount();
+            BigDecimal warningProportion = userAllocation.getWarningProportion();
+            BigDecimal nowCost = hourlyAccountMapper.getCost(accountId, maxHour, today);
+            if (maxHour != 0) {
+                if (!Check.isNull(nowCost) && nowCost.compareTo(new BigDecimal(0)) != 0) {
+                    BigDecimal lastHourCost = hourlyAccountMapper.getCost(accountId, maxHour - 1, today);
+                    if (!Check.isNull(lastHourCost) && lastHourCost.compareTo(new BigDecimal(0)) != 0) {
+                        BigDecimal subtract = nowCost.subtract(lastHourCost);
+                        BigDecimal divide = nowCost.divide(lastHourCost, 2, RoundingMode.HALF_UP);
+                        if (subtract.compareTo(warningAmount) > -1 && divide.compareTo(warningProportion) > -1) {
+                            sendMessage(accountId, userAllocation.getAuthName(), maxHour, nowCost, userAllocation.getProjectId(), project.getProjectName(), userAllocation.getUserName());
+                        }
+                    }
+                }
+            }
+            if (!Check.isNull(nowCost) && nowCost.compareTo(new BigDecimal(0)) != 0) {
+                BigDecimal yesterdayHourCost = hourlyAccountMapper.getCost(accountId, maxHour, yesterday);
+                if (!Check.isNull(yesterdayHourCost) && yesterdayHourCost.compareTo(new BigDecimal(0)) != 0) {
+                    BigDecimal subtract = nowCost.subtract(yesterdayHourCost);
+                    BigDecimal divide = nowCost.divide(yesterdayHourCost, 2, RoundingMode.HALF_UP);
+                    if (subtract.compareTo(warningAmount) > -1 && divide.compareTo(warningProportion) > -1) {
+                        sendYesterdayMessage(accountId, userAllocation.getAuthName(), maxHour, nowCost, userAllocation.getProjectId(), project.getProjectName(), userAllocation.getUserName());
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    private void sendYesterdayMessage(Long accountId, String authName, Integer maxHour, BigDecimal nowCost, Long projectId, String projectName, String userName) {
+        StringBuilder text = new StringBuilder();
+        text.append("较昨日同时段消耗预警").append("<br/>")
+                .append("您的项目:" + projectName + "下的,").append("<br/>")
+                .append("账号:").append(accountId + ",").append("授权名称为:" + authName).append("<br/>")
+                .append("账户所属人:" + userName).append("<br/>")
+                .append("相较于昨日 " + maxHour + "时").append("<br/>")
+                .append("出现消耗暴涨,").append("消耗金额为:" + nowCost).append("<br/>")
+                .append("请您及时查看!");
+        List<JSONObject> wexinIds = wexinService.selectUsersByAccountId(accountId);
+        corpWexinUtils.sendMessage(wexinIds, text.toString());
+    }
+
+    private void sendMessage(Long accountId, String authName, Integer hour, BigDecimal amount, Long projectId, String projectName, String userName) {
+        StringBuilder text = new StringBuilder();
+        text.append("较上时段消耗预警").append("<br/>")
+                .append("您的项目:" + projectName + " 下的").append("<br/>")
+                .append("账号:").append(accountId + ",").append("授权名称为:" + authName).append("<br/>")
+                .append("账户所属人:" + userName).append("<br/>")
+                .append(hour + " 时").append("相较于 " + (hour - 1) + " 时").append("<br/>")
+                .append("出现消耗暴涨,").append("消耗金额为:" + amount).append("<br/>")
+                .append("请您及时查看!");
+        List<JSONObject> wexinIds = wexinService.selectUsersByAccountId(accountId);
+        corpWexinUtils.sendMessage(wexinIds, text.toString());
+    }
+
+}

+ 5 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/impl/OauthTokenServiceImpl.java

@@ -35,4 +35,9 @@ public class OauthTokenServiceImpl extends ServiceImpl<OauthTokenMapper, OauthTo
   public List<Long> getAllAccountIds() {
     return tokenMapper.getAllAccountIds();
   }
+
+  @Override
+  public List<JSONObject> selectKuaiShouToken() {
+    return tokenMapper.selectKuaiShouToken();
+  }
 }

+ 150 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/impl/UserAllocationServiceImpl.java

@@ -0,0 +1,150 @@
+package cn.com.ctop.job.kuaishou.data.service.impl;
+
+import cn.com.ctop.job.kuaishou.data.entity.Project;
+import cn.com.ctop.job.kuaishou.data.entity.UserAllocation;
+import cn.com.ctop.job.kuaishou.data.mapper.UserAllocationMapper;
+import cn.com.ctop.job.kuaishou.data.service.IUserAllocationService;
+import cn.com.ctop.job.kuaishou.data.utils.Check;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 用户分配
+ */
+@Service
+public class UserAllocationServiceImpl extends ServiceImpl<UserAllocationMapper, UserAllocation> implements IUserAllocationService {
+
+    @Autowired
+    UserAllocationMapper userAllocationMapper;
+
+    @Override
+    public UserAllocation getByAccountId(Long accountId) {
+        return userAllocationMapper.getOneByAccountId(accountId);
+    }
+
+    @Override
+    public List<UserAllocation> listByMediaId(String mediaId, int accountStatus) {
+        return userAllocationMapper.listByMediaId(mediaId, accountStatus);
+    }
+
+    @Override
+    public String getAdvertiserIdByAccountId(Long accountId) {
+        return userAllocationMapper.queryAdvertiserId(accountId);
+    }
+
+    @Override
+    public List<JSONObject> getAccountListByProject(Long projectId) {
+        return userAllocationMapper.getAccountListByProject(projectId);
+    }
+
+    /**
+     * 获取项目下的所有userId
+     *
+     * @param projectId
+     * @return
+     */
+    @Override
+    public List<JSONObject> getUserIdListByProjectId(Long projectId) {
+        return userAllocationMapper.getUserIdListByProjectId(projectId);
+    }
+
+    @Override
+    public List<JSONObject> getAccountIdListByUserId(String userId) {
+        return userAllocationMapper.getAccountIdListByUserId(userId);
+    }
+
+    @Override
+    public JSONObject getSwitchStatusByAccount(Long accountId) {
+        return userAllocationMapper.getSwitchStatusByAccount(accountId);
+    }
+
+    @Override
+    public List<Long> getAccountsByDeleteComment() {
+        return userAllocationMapper.queryAccountsByDeleteComment();
+    }
+
+    @Override
+    public List<UserAllocation> getAccountListByUserIdAndProductId(String userId, Long projectId, Long productId) {
+        return userAllocationMapper.getAccountListByUserIdAndProductId(userId, projectId, productId);
+    }
+
+    @Override
+    public Map<Long, List<JSONObject>> getAccountListByProjectList(List<JSONObject> projectList) {
+        Map<Long, List<JSONObject>> map = new HashMap<>();
+        List list = new ArrayList();
+        for (int i = 0; i < projectList.size(); i++) {
+            JSONObject jsonObject = projectList.get(i);
+            if (!Check.isNull(jsonObject)) {
+                list.add(jsonObject.getLong("projectId"));
+                map.put(jsonObject.getLong("projectId"), new ArrayList<>());
+            }
+        }
+        List<JSONObject> jsonList = userAllocationMapper.getAccountListByProjectList(list);
+        for (int i = 0; i < jsonList.size(); i++) {
+            JSONObject jsonObject = jsonList.get(i);
+            Long projectId = jsonObject.getLong("projectId");
+            List<JSONObject> jsonObjects = map.get(projectId);
+            jsonObjects.add(jsonObject);
+        }
+        return map;
+    }
+
+    @Override
+    public List<JSONObject> getUserIdListByProductId(Long productId) {
+        return userAllocationMapper.getUserIdListByProductId(productId);
+    }
+
+    @Override
+    public List<Long> getValidProjectIds(Integer mediaId) {
+        return userAllocationMapper.getValidProjectIds(mediaId);
+    }
+
+    @Override
+    public List<JSONObject> getByAccountIds(JSONArray accountIds) {
+        return userAllocationMapper.getByAccountIds(accountIds);
+    }
+
+    @Override
+    public List<Long> getKuaiShouUserIdListByProjectId(Long projectId) {
+        return userAllocationMapper.getKuaiShouUserIdListByProjectId(projectId);
+    }
+
+    @Override
+    public List<JSONObject> selectAccountsByKuaishouUserId(Long userId) {
+        return userAllocationMapper.selectAccountsByKuaishouUserId(userId);
+    }
+
+    @Override
+    public boolean updateProjectStrategyStatus(Long accountId, Integer projectStrategy) {
+        int num = userAllocationMapper.updateProjectStrategyStatus(accountId, projectStrategy);
+        return num > 0;
+    }
+
+    @Override
+    public List<Long> queryAutomaticAccounts(Long projectId) {
+        return userAllocationMapper.queryAutomaticAccounts(projectId);
+    }
+
+    @Override
+    public List<Long> getIdList() {
+        return userAllocationMapper.getIdList();
+    }
+
+    @Override
+    public JSONObject getProjectByAccountId(Long accountId) {
+        return baseMapper.getProjectByAccountId(accountId);
+    }
+
+    @Override
+    public Project getProjectEntity(Long projectId) {
+        return userAllocationMapper.getProjectEntity(projectId);
+    }
+}

+ 31 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/service/impl/WexinConfigServiceImpl.java

@@ -0,0 +1,31 @@
+package cn.com.ctop.job.kuaishou.data.service.impl;
+
+import cn.com.ctop.job.kuaishou.data.mapper.WexinConfigMapper;
+import cn.com.ctop.job.kuaishou.data.service.IWexinConfigService;
+import cn.com.ctop.job.kuaishou.data.utils.weixin.WexinConfig;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 企业微信配置信息
+ *
+ * @author jeecg-boot
+ * 2021-06-17
+ * @version V1.0
+ */
+@Service
+public class WexinConfigServiceImpl extends ServiceImpl<WexinConfigMapper, WexinConfig> implements IWexinConfigService {
+
+    @Override
+    public List<WexinConfig> getAll() {
+        return baseMapper.getAll();
+    }
+
+    @Override
+    public List<JSONObject> selectUsersByAccountId(Long accountId) {
+        return baseMapper.selectUsersByAccountId(accountId);
+    }
+}

+ 92 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/utils/weixin/CorpWexinUtils.java

@@ -0,0 +1,92 @@
+package cn.com.ctop.job.kuaishou.data.utils.weixin;
+
+import cn.com.ctop.job.kuaishou.data.service.IWexinConfigService;
+import cn.com.ctop.job.kuaishou.data.utils.Check;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import lombok.val;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.api.WxCpService;
+import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
+import me.chanjar.weixin.cp.bean.WxCpMessage;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+@Slf4j
+public class CorpWexinUtils {
+    @Resource
+    private IWexinConfigService wexinConfigService;
+
+    private static Map<String, WexinConfig> configMap = new HashMap<>();
+
+    private Map<String, WexinConfig> getConfigMap() {
+        List<WexinConfig> list = wexinConfigService.getAll();
+        for (WexinConfig config : list) {
+            WxCpService wxCpService = new WxCpServiceImpl();
+            val configStorage = new WxCpDefaultConfigImpl();
+            configStorage.setCorpId(config.getCorpId());
+            configStorage.setAgentId(config.getAgentId());
+            configStorage.setCorpSecret(config.getCorpSecret());
+            configStorage.setToken(config.getToken());
+            configStorage.setAesKey(config.getAesKey());
+            wxCpService.setWxCpConfigStorage(configStorage);
+            config.setWxCpService(wxCpService);
+            configMap.put(config.getCorpId(), config);
+        }
+        return configMap;
+    }
+
+    public void sendMessage(List<JSONObject> wxUserList, String content) {
+        if (Check.isNullMap(configMap)) {
+            getConfigMap();
+        }
+        if (wxUserList != null && wxUserList.size() > 0) {
+            for (JSONObject userInfo : wxUserList) {
+                WxCpMessage message = new WxCpMessage();
+                message.setMsgType("text");
+                message.setContent(content);
+                message.setAgentId(1000002);
+//                message.setToUser(userInfo.getString("wexin_id"));
+                //测试 id  ZhaoXiAn
+                message.setToUser("ZhaoXiAn");
+                try {
+                    WexinConfig config = configMap.get(userInfo.getString("corp_id"));
+                    WxCpService wxCpService = config.getWxCpService();
+                    wxCpService.messageSend(message);
+                } catch (WxErrorException e) {
+                    log.error("发送信息失败,userId:{}", userInfo.getString("wexin_id"));
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    public void sendMessageByWeChatId(JSONObject weChatInfo, String content) {
+        if (Check.isNullMap(configMap)) {
+            this.getConfigMap();
+        }
+        if (!Check.isNull(weChatInfo)) {
+            WxCpMessage message = new WxCpMessage();
+            message.setMsgType("text");
+            message.setContent(content);
+            message.setAgentId(1000002);
+//            message.setToUser(weChatInfo.getString("wexin_id"));
+            //测试 id  ZhaoXiAn
+            message.setToUser("ZhaoXiAn");
+            try {
+                WexinConfig config = configMap.get(weChatInfo.getString("corp_id"));
+                WxCpService wxCpService = config.getWxCpService();
+                wxCpService.messageSend(message);
+            } catch (WxErrorException e) {
+                log.error("发送信息失败,userId:{}", weChatInfo.getString("wexin_id"));
+                e.printStackTrace();
+            }
+        }
+    }
+}

+ 86 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/data/utils/weixin/WexinConfig.java

@@ -0,0 +1,86 @@
+package cn.com.ctop.job.kuaishou.data.utils.weixin;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import me.chanjar.weixin.cp.api.WxCpService;
+import org.jeecgframework.poi.excel.annotation.Excel;
+
+import java.util.Date;
+
+/**
+ * 企业微信配置信息
+ *
+ * @author jeecg-boot
+ * @version V1.0
+ * @date 2021-06-17
+ */
+@Data
+@TableName("ctop_wexin_config")
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "ctop_wexin_config对象", description = "企业微信配置信息")
+public class WexinConfig {
+
+    /**
+     * id
+     */
+    @TableId(type = IdType.UUID)
+    @ApiModelProperty(value = "id")
+    private Integer id;
+    /**
+     * corpId
+     */
+    @Excel(name = "corpId", width = 15)
+    @ApiModelProperty(value = "corpId")
+    private String corpId;
+    /**
+     * agentId
+     */
+    @Excel(name = "agentId", width = 15)
+    @ApiModelProperty(value = "agentId")
+    private Integer agentId;
+    /**
+     * corpSecret
+     */
+    @Excel(name = "corpSecret", width = 15)
+    @ApiModelProperty(value = "corpSecret")
+    private String corpSecret;
+    /**
+     * aesKey
+     */
+    @Excel(name = "aesKey", width = 15)
+    @ApiModelProperty(value = "aesKey")
+    private String aesKey;
+    /**
+     * token
+     */
+    @Excel(name = "token", width = 15)
+    @ApiModelProperty(value = "token")
+    private String token;
+    /**
+     * remarks
+     */
+    @Excel(name = "remarks", width = 15)
+    @ApiModelProperty(value = "remarks")
+    private String remarks;
+    /**
+     * createTime
+     */
+    @ApiModelProperty(value = "createTime")
+    private Date createTime;
+    /**
+     * updateTime
+     */
+    @ApiModelProperty(value = "updateTime")
+    private Date updateTime;
+
+    @TableField(exist = false)
+    private WxCpService wxCpService;
+}

+ 50 - 0
job-kuaishou/src/main/java/cn/com/ctop/job/kuaishou/handler/KuaishouHourlyAccountWarningLoadJob.java

@@ -0,0 +1,50 @@
+package cn.com.ctop.job.kuaishou.handler;
+
+import cn.com.ctop.job.kuaishou.data.service.IAccountWarningService;
+import cn.com.ctop.job.kuaishou.data.service.IOauthTokenService;
+import com.alibaba.fastjson.JSONObject;
+import com.xxl.job.core.context.XxlJobHelper;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import com.xxl.job.core.util.DateUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+
+/**
+ * @author 于蒙
+ */
+@Component
+public class KuaishouHourlyAccountWarningLoadJob {
+    @Autowired
+    private IOauthTokenService tokenService;
+    @Autowired
+    private IAccountWarningService accountWarningService;
+    static ExecutorService executorService = Executors.newFixedThreadPool(3);
+
+    /**
+     * 快手时段消耗预警
+     *
+     * @throws Exception
+     */
+    @XxlJob("kuaishouHourlyAccountWarning")
+    public void execute() throws Exception {
+        XxlJobHelper.log("开始时段消耗预警定时任务");
+        long l = System.currentTimeMillis();
+        List<JSONObject> tokens = tokenService.selectKuaiShouToken();
+        if (null == tokens || tokens.size() <= 0) {
+            XxlJobHelper.log("定时获取快手数据异常:未获取到可用的token");
+            XxlJobHelper.handleFail();
+            return;
+        }
+        String todayStr = DateUtil.formatDate(new Date());
+        Integer todayInt = DateUtil.getIntegerDate(todayStr);
+        Integer yesterdayInt = DateUtil.getIntegerDate(DateUtil.getAnotherDay("yyyy-MM-dd", todayStr, -1));
+        tokens.forEach(token -> executorService.submit(() -> accountWarningService.kuaiShouAccountWarning(token.getLong("accountId"), todayInt, yesterdayInt)));
+        XxlJobHelper.log("异步时段消耗预警定时任务执行完毕,耗时:{} ms", System.currentTimeMillis() - l);
+    }
+}

+ 24 - 3
xxl-job-core/src/main/java/com/xxl/job/core/util/DateUtil.java

@@ -25,13 +25,14 @@ public class DateUtil {
     private static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
 
     private static final ThreadLocal<Map<String, DateFormat>> dateFormatThreadLocal = new ThreadLocal<Map<String, DateFormat>>();
+
     private static DateFormat getDateFormat(String pattern) {
-        if (pattern==null || pattern.trim().length()==0) {
+        if (pattern == null || pattern.trim().length() == 0) {
             throw new IllegalArgumentException("pattern cannot be empty.");
         }
 
         Map<String, DateFormat> dateFormatMap = dateFormatThreadLocal.get();
-        if(dateFormatMap!=null && dateFormatMap.containsKey(pattern)){
+        if (dateFormatMap != null && dateFormatMap.containsKey(pattern)) {
             return dateFormatMap.get(pattern);
         }
 
@@ -57,6 +58,26 @@ public class DateUtil {
         return format(date, DATE_FORMAT);
     }
 
+    public static Integer getIntegerDate(String date) {
+        return Integer.valueOf(date.replace("-", ""));
+    }
+
+    public static String getAnotherDay(String format, String date, Integer num) {
+
+        SimpleDateFormat sdf = new SimpleDateFormat(format);
+        Date getDate = null;
+        try {
+            getDate = sdf.parse(date);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(getDate);
+        calendar.add(Calendar.DAY_OF_MONTH, num);
+        Date resultDate = calendar.getTime();
+        return sdf.format(resultDate);
+    }
+
     /**
      * format date. like "yyyy-MM-dd HH:mm:ss"
      *
@@ -87,7 +108,7 @@ public class DateUtil {
      * @return
      * @throws ParseException
      */
-    public static Date parseDate(String dateString){
+    public static Date parseDate(String dateString) {
         return parse(dateString, DATE_FORMAT);
     }