Ver Fonte

规则引擎2.0定时执行逻辑

zhaoxian há 3 anos atrás
pai
commit
882f319307
18 ficheiros alterados com 1067 adições e 110 exclusões
  1. 65 16
      jeecg-boot-module-system/src/main/java/org/jeecg/modules/ctop/controller/TestController.java
  2. 12 1
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/constant/MatchLogic.java
  3. 142 0
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/entity/AlarmRuleOperationRecord.java
  4. 12 0
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/entity/RuleAccountThreshold.java
  5. 4 0
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/entity/RuleBase.java
  6. 15 1
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/entity/RuleGroup.java
  7. 5 0
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/entity/RuleIndicator.java
  8. 15 0
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/mapper/AlarmRuleOperationRecordMapper.java
  9. 5 0
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/mapper/xml/AlarmRuleOperationRecordMapper.xml
  10. 17 0
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/service/ExternalLinkService.java
  11. 15 0
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/service/IAlarmRuleOperationRecordService.java
  12. 19 0
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/service/impl/AlarmRuleOperationRecordServiceImpl.java
  13. 42 0
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/service/impl/ExternalLinkServiceImpl.java
  14. 567 82
      module-alarm/src/main/java/cn/com/ctop/alarm/modules/service/impl/RuleGroupServiceImpl.java
  15. 13 4
      module-common/src/main/java/cn/com/ctop/common/module/service/impl/RuleDataAccountKuaishouServiceImpl.java
  16. 13 4
      module-common/src/main/java/cn/com/ctop/common/module/service/impl/RuleDataAccountServiceImpl.java
  17. 106 0
      module-job-bytedance/src/main/java/cn/com/ctop/job/bytedance/handler/AlarmRuleRebackJob.java
  18. 0 2
      module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaiShouUpdateServiceImpl.java

+ 65 - 16
jeecg-boot-module-system/src/main/java/org/jeecg/modules/ctop/controller/TestController.java

@@ -1,11 +1,37 @@
 package org.jeecg.modules.ctop.controller;
 
-import cn.com.ctop.common.module.entity.*;
+import cn.com.ctop.alarm.modules.entity.AlarmRuleOperationRecord;
+import cn.com.ctop.alarm.modules.mapper.AlarmRuleOperationRecordMapper;
+import cn.com.ctop.common.module.entity.CtopOauthToken;
+import cn.com.ctop.common.module.entity.MaterialAscription;
+import cn.com.ctop.common.module.entity.MaterialImageInfo;
+import cn.com.ctop.common.module.entity.MaterialInfo;
+import cn.com.ctop.common.module.entity.MaterialParameter;
+import cn.com.ctop.common.module.entity.MaterialTag;
+import cn.com.ctop.common.module.entity.MusicInfo;
+import cn.com.ctop.common.module.entity.UserAllocation;
 import cn.com.ctop.common.module.mapper.CtopOauthTokenMapper;
 import cn.com.ctop.common.module.mapper.MailLogMapper;
 import cn.com.ctop.common.module.mapper.UserAllocationMapper;
-import cn.com.ctop.common.module.service.*;
-import cn.com.ctop.common.module.utils.*;
+import cn.com.ctop.common.module.service.IBindAccountAuthService;
+import cn.com.ctop.common.module.service.ICtopOauthTokenService;
+import cn.com.ctop.common.module.service.IMaterialAscriptionService;
+import cn.com.ctop.common.module.service.IMaterialCutFrameService;
+import cn.com.ctop.common.module.service.IMaterialImageInfoService;
+import cn.com.ctop.common.module.service.IMaterialInfoService;
+import cn.com.ctop.common.module.service.IMaterialParameterService;
+import cn.com.ctop.common.module.service.IMaterialTagService;
+import cn.com.ctop.common.module.service.IUserAllocationService;
+import cn.com.ctop.common.module.service.MusicInfoService;
+import cn.com.ctop.common.module.utils.Check;
+import cn.com.ctop.common.module.utils.CorpWexinUtils;
+import cn.com.ctop.common.module.utils.CosUtils;
+import cn.com.ctop.common.module.utils.CtopAdConstant;
+import cn.com.ctop.common.module.utils.HttpUtils;
+import cn.com.ctop.common.module.utils.KuaishouInterfaceConstant;
+import cn.com.ctop.common.module.utils.LoadFileUtil;
+import cn.com.ctop.common.module.utils.ResultMapUtils;
+import cn.com.ctop.common.module.utils.StatusCode;
 import cn.com.ctop.common.module.vo.ResFileDTO;
 import cn.com.ctop.crawler.modules.core.entity.CrawlerDouyinMusicTask;
 import cn.com.ctop.crawler.modules.core.service.CrawlerDouyinMusicTaskService;
@@ -15,8 +41,24 @@ import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaishouAdvertiserStrategyServ
 import cn.com.ctop.kuaishou.modules.ai.service.IAiKuaishouCreateCreativeService;
 import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouCreative;
 import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouGroup;
+import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouVideoGet;
 import cn.com.ctop.kuaishou.modules.batch.entity.KuaishouProgramCreative;
-import cn.com.ctop.kuaishou.modules.batch.service.*;
+import cn.com.ctop.kuaishou.modules.batch.service.IBatchService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouCampaignService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouCommentService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouCreativeService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouDailyReportTaskService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouGroupService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouHistoryReportTaskService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouReportDailyMaterialService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouUpdateService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouVideoGetService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouInterfaceService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouInterfaceService2;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouProgramCreativeService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouStrategyService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouTemplateService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouVideoRelateCreativesService;
 import cn.com.ctop.kuaishou.modules.graphql.service.IKuaishouWebInterfaceService;
 import cn.com.ctop.kuaishou.modules.material.entity.KuaishouAccessToken;
 import cn.com.ctop.kuaishou.modules.material.entity.KuaishouResultToken;
@@ -29,10 +71,16 @@ import cn.com.ctop.toutiao.modules.link.service.IETLReportBytedanceVideoService;
 import cn.com.ctop.toutiao.modules.material.service.IByteDanceAdvertiserDataService;
 import cn.com.ctop.toutiao.modules.material.service.IBytedanceEffectVideoInfoService;
 import cn.com.ctop.toutiao.modules.report.entity.BytedanceCheckReportTaskInfo;
-import cn.com.ctop.toutiao.modules.report.service.*;
+import cn.com.ctop.toutiao.modules.report.service.IBytedanceCheckReportTaskInfoService;
+import cn.com.ctop.toutiao.modules.report.service.IBytedanceInterfaceService;
+import cn.com.ctop.toutiao.modules.report.service.IBytedancePlanHourlyReportService;
+import cn.com.ctop.toutiao.modules.report.service.IBytedanceReportService;
+import cn.com.ctop.toutiao.modules.report.service.IBytedanceVideoReportService;
+import cn.com.ctop.toutiao.modules.report.service.IReportService;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.xxl.job.core.context.XxlJobHelper;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.ibatis.annotations.Param;
@@ -41,7 +89,12 @@ import org.jeecg.common.util.DateUtils;
 import org.quartz.JobExecutionException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import java.io.IOException;
@@ -49,7 +102,12 @@ import java.io.InputStream;
 import java.math.BigDecimal;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -244,15 +302,6 @@ public class TestController {
         list.add(10299241L);
 
 
-
-
-
-
-
-
-
-
-
         for (int i = 0; i < list.size(); i++) {
             Long accountId = list.get(i);
             CtopOauthToken token = oauthTokenService.getTokenByAccountId(accountId);

+ 12 - 1
module-alarm/src/main/java/cn/com/ctop/alarm/modules/constant/MatchLogic.java

@@ -42,8 +42,19 @@ public class MatchLogic {
             }
             obj.put("isNull", false);
             if ("number".equals(type)) {
-                BigDecimal bigThr = new BigDecimal(threshold);
                 BigDecimal bigVal = new BigDecimal(value);
+                if (threshold.contains("~")) {
+                    String[] split = threshold.split("~");
+                    BigDecimal min = new BigDecimal(split[0]);
+                    BigDecimal max = new BigDecimal(split[1]);
+                    //bigVal介于min与max之间,即:min<=bigVal<=max
+                    if (max.compareTo(bigVal) > -1 && bigVal.compareTo(min) > -1) {
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+                BigDecimal bigThr = new BigDecimal(threshold);
                 switch (condition) {
                     case "equal":
                         return bigVal.compareTo(bigThr) == 0;

+ 142 - 0
module-alarm/src/main/java/cn/com/ctop/alarm/modules/entity/AlarmRuleOperationRecord.java

@@ -0,0 +1,142 @@
+package cn.com.ctop.alarm.modules.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.util.Date;
+
+/**
+ * 预警操作记录表
+ *
+ * @author jeecg-boot
+ * @version V1.0
+ * @date 2021-08-10
+ */
+@Data
+@TableName("ctop_alarm_rule_operation_record")
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "ctop_alarm_rule_operation_record对象", description = "预警操作记录表")
+public class AlarmRuleOperationRecord {
+
+    /**
+     * 主键id
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+    /**
+     * 账户ID
+     */
+    @Excel(name = "账户ID", width = 15)
+    @ApiModelProperty(value = "账户ID")
+    private Long accountId;
+    /**
+     * 计划ID
+     */
+    @Excel(name = "计划ID", width = 15)
+    @ApiModelProperty(value = "计划ID")
+    private Long planId;
+    /**
+     * 组ID
+     */
+    @Excel(name = "组ID", width = 15)
+    @ApiModelProperty(value = "组ID")
+    private Long unitId;
+    /**
+     * 规则组id
+     */
+    @Excel(name = "规则组id", width = 15)
+    @ApiModelProperty(value = "规则组id")
+    private Long groupId;
+    /**
+     * 指标code
+     */
+    @Excel(name = "指标code", width = 15)
+    @ApiModelProperty(value = "指标code")
+    private String indicatorCode;
+    /**
+     * 操作记录
+     */
+    private String message;
+    /**
+     * 修改前的值
+     */
+    @Excel(name = "修改前的值", width = 15)
+    @ApiModelProperty(value = "修改前的值")
+    private String beforeValue;
+    /**
+     * 操作类型:up-提高,down-降低,to-调整至
+     */
+    @Excel(name = "操作类型:up-提高,down-降低,to-调整至", width = 15)
+    @ApiModelProperty(value = "操作类型:up-提高,down-降低,to-调整至")
+    private String operationType;
+    /**
+     * 操作内容:price-金额,percent-百分数
+     */
+    @Excel(name = "操作内容:price-金额,percent-百分数", width = 15)
+    @ApiModelProperty(value = "操作内容:price-金额,percent-百分数")
+    private String operationValue;
+    /**
+     * 修改后的值
+     */
+    @Excel(name = "修改后的值", width = 15)
+    @ApiModelProperty(value = "修改后的值")
+    private String afterValue;
+    /**
+     * 操作阈值
+     */
+    @Excel(name = "操作阈值", width = 15)
+    @ApiModelProperty(value = "操作阈值")
+    private String operationThreshold;
+    /**
+     * 峰值
+     */
+    @Excel(name = "峰值", width = 15)
+    @ApiModelProperty(value = "峰值")
+    private String MaxValue;
+    /**
+     * 峰值
+     */
+    @Excel(name = "最小值", width = 15)
+    @ApiModelProperty(value = "最小值")
+    private String minValue;
+    /**
+     * 操作时间
+     */
+    @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 String valueTime;
+    /**
+     * 媒体类型
+     */
+    @Excel(name = "媒体类型", width = 15)
+    @ApiModelProperty(value = "媒体类型")
+    private String mediaType;
+    /**
+     * createTime
+     */
+    @Excel(name = "createTime", 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 = "createTime")
+    private Date createTime;
+    /**
+     * updateTime
+     */
+    @Excel(name = "updateTime", 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 = "updateTime")
+    private Date updateTime;
+}

+ 12 - 0
module-alarm/src/main/java/cn/com/ctop/alarm/modules/entity/RuleAccountThreshold.java

@@ -55,6 +55,18 @@ public class RuleAccountThreshold {
     @ApiModelProperty(value = "阈值")
     private String threshold;
     /**
+     * 操作阈值
+     */
+    private String operationThreshold;
+    /**
+     * 峰值
+     */
+    private String maxValue;
+    /**
+     * 低值
+     */
+    private String minValue;
+    /**
      * createTime
      */
     @ApiModelProperty(value = "createTime")

+ 4 - 0
module-alarm/src/main/java/cn/com/ctop/alarm/modules/entity/RuleBase.java

@@ -48,6 +48,10 @@ public class RuleBase {
     @ApiModelProperty(value = "指标code")
     private String indicatorCode;
     /**
+     * 比较指标code
+     */
+    private String cindicatorCode;
+    /**
      * 判断条件 大于 等于 小于等
      */
     @Excel(name = "判断条件 大于 等于 小于等", width = 15)

+ 15 - 1
module-alarm/src/main/java/cn/com/ctop/alarm/modules/entity/RuleGroup.java

@@ -55,9 +55,23 @@ public class RuleGroup {
     @ApiModelProperty(value = "规则关系 当rule_type 为group时必填 and同时命中  or 命中一条")
     private String ruleRelationship;
     /**
-     * 操作内容:SEND发送,PAUSE关停并发送
+     * 操作内容:SEND-发送,PAUSE-关停并发送,BUDGET-修改预算,BID-出价,TIME-投放时间
      */
     private String operate;
+
+    /**
+     * 是否有后续操作,0无,1有
+     */
+    private Integer operation;
+
+    /**
+     * 操作类型:up-提高,down-降低,to-调整至
+     */
+    private String operationType;
+    /**
+     * 操作内容:price-金额,percent-百分数
+     */
+    private String operationValue;
     /**
      * 预警发送方式: SMS:短信,WeChat:企业微信,EMAIL:电子邮件,TEL:电话
      */

+ 5 - 0
module-alarm/src/main/java/cn/com/ctop/alarm/modules/entity/RuleIndicator.java

@@ -38,6 +38,11 @@ public class RuleIndicator {
     @Excel(name = "1:头条2:快手", width = 15)
     @ApiModelProperty(value = "1:头条2:快手")
     private Integer mediaType;
+
+    /**
+     * 是否可操作指标,0否,1是
+     */
+    private Integer operation;
     /**
      * 指标名称
      */

+ 15 - 0
module-alarm/src/main/java/cn/com/ctop/alarm/modules/mapper/AlarmRuleOperationRecordMapper.java

@@ -0,0 +1,15 @@
+package cn.com.ctop.alarm.modules.mapper;
+
+import cn.com.ctop.alarm.modules.entity.AlarmRuleOperationRecord;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * 预警操作记录表
+ *
+ * @author jeecg-boot
+ * 2021-08-10
+ * @version V1.0
+ */
+public interface AlarmRuleOperationRecordMapper extends BaseMapper<AlarmRuleOperationRecord> {
+
+}

+ 5 - 0
module-alarm/src/main/java/cn/com/ctop/alarm/modules/mapper/xml/AlarmRuleOperationRecordMapper.xml

@@ -0,0 +1,5 @@
+<?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.alarm.modules.mapper.AlarmRuleOperationRecordMapper">
+
+</mapper>

+ 17 - 0
module-alarm/src/main/java/cn/com/ctop/alarm/modules/service/ExternalLinkService.java

@@ -0,0 +1,17 @@
+package cn.com.ctop.alarm.modules.service;
+
+import cn.com.ctop.alarm.modules.entity.RuleCondition;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.math.BigDecimal;
+
+/**
+ * @Description: 调用外部接口
+ * @Author: jeecg-boot
+ * @Date: 2020-11-16
+ * @Version: V1.0
+ */
+public interface ExternalLinkService {
+
+    String editBytedancePlanCpaBidOrBudget(Long accountId, String adId, BigDecimal cpaBid, String adScheduleTime,Long budget);
+}

+ 15 - 0
module-alarm/src/main/java/cn/com/ctop/alarm/modules/service/IAlarmRuleOperationRecordService.java

@@ -0,0 +1,15 @@
+package cn.com.ctop.alarm.modules.service;
+
+import cn.com.ctop.alarm.modules.entity.AlarmRuleOperationRecord;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * 预警操作记录表
+ *
+ * @author jeecg-boot
+ * 2021-08-10
+ * @version V1.0
+ */
+public interface IAlarmRuleOperationRecordService extends IService<AlarmRuleOperationRecord> {
+
+}

+ 19 - 0
module-alarm/src/main/java/cn/com/ctop/alarm/modules/service/impl/AlarmRuleOperationRecordServiceImpl.java

@@ -0,0 +1,19 @@
+package cn.com.ctop.alarm.modules.service.impl;
+
+import cn.com.ctop.alarm.modules.entity.AlarmRuleOperationRecord;
+import cn.com.ctop.alarm.modules.mapper.AlarmRuleOperationRecordMapper;
+import cn.com.ctop.alarm.modules.service.IAlarmRuleOperationRecordService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * 预警操作记录表
+ *
+ * @author jeecg-boot
+ * 2021-08-10
+ * @version V1.0
+ */
+@Service
+public class AlarmRuleOperationRecordServiceImpl extends ServiceImpl<AlarmRuleOperationRecordMapper, AlarmRuleOperationRecord> implements IAlarmRuleOperationRecordService {
+
+}

+ 42 - 0
module-alarm/src/main/java/cn/com/ctop/alarm/modules/service/impl/ExternalLinkServiceImpl.java

@@ -0,0 +1,42 @@
+package cn.com.ctop.alarm.modules.service.impl;
+
+import cn.com.ctop.alarm.modules.service.ExternalLinkService;
+import cn.com.ctop.common.module.utils.Check;
+import cn.com.ctop.common.module.utils.HttpUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+
+/**
+ * 调取外部接口
+ */
+@Slf4j
+@Service
+public class ExternalLinkServiceImpl implements ExternalLinkService {
+    //修改头条CPABID出价,投放时间
+    private static final String URL_UPDATE_CPABID = "";
+//    private static final String URLPREFIX = "http://118.24.244.213:8808/bytedance-api/advertiser/aiBytedanceAdvertiserStrategy/autoCreateCreative?hour=";
+
+
+    @Override
+    public String editBytedancePlanCpaBidOrBudget(Long accountId, String adId, BigDecimal cpaBid, String adScheduleTime, Long budget) {
+        StringBuffer buf = new StringBuffer();
+        buf.append("?accountId=").append(accountId).append("&adId=").append(adId);
+        if (!Check.isNull(cpaBid)) {
+            buf.append("&cpaBid=").append(cpaBid);
+        }
+        if (!Check.isNull(adScheduleTime)) {
+            buf.append("&adScheduleTime=").append(adScheduleTime);
+        }
+        if (!Check.isNull(budget)) {
+            buf.append("&budget=").append(budget);
+        }
+        log.info("调用微服务接口,修改头条计划出价、预算、投放时间段。。。。。。start");
+        HttpUtils.httpGet(URL_UPDATE_CPABID + buf.toString(), null, null);
+        log.info("调用微服务接口,修改头条计划出价、预算、投放时间段。。。。。。end");
+        return null;
+    }
+
+
+}

+ 567 - 82
module-alarm/src/main/java/cn/com/ctop/alarm/modules/service/impl/RuleGroupServiceImpl.java

@@ -2,6 +2,7 @@ package cn.com.ctop.alarm.modules.service.impl;
 
 import cn.com.ctop.alarm.modules.constant.MatchLogic;
 import cn.com.ctop.alarm.modules.entity.AlarmEventSend;
+import cn.com.ctop.alarm.modules.entity.AlarmRuleOperationRecord;
 import cn.com.ctop.alarm.modules.entity.AlarmRuleRecord;
 import cn.com.ctop.alarm.modules.entity.RuleAccountTemplate;
 import cn.com.ctop.alarm.modules.entity.RuleAccountThreshold;
@@ -11,12 +12,14 @@ import cn.com.ctop.alarm.modules.entity.RuleIndicator;
 import cn.com.ctop.alarm.modules.entity.RuleTemplate;
 import cn.com.ctop.alarm.modules.enums.ConditEnum;
 import cn.com.ctop.alarm.modules.mapper.AlarmEventSendMapper;
+import cn.com.ctop.alarm.modules.mapper.AlarmRuleOperationRecordMapper;
 import cn.com.ctop.alarm.modules.mapper.RuleAccountTemplateMapper;
 import cn.com.ctop.alarm.modules.mapper.RuleAccountThresholdMapper;
 import cn.com.ctop.alarm.modules.mapper.RuleBaseMapper;
 import cn.com.ctop.alarm.modules.mapper.RuleGroupMapper;
 import cn.com.ctop.alarm.modules.mapper.RuleIndicatorMapper;
 import cn.com.ctop.alarm.modules.mapper.RuleTemplateMapper;
+import cn.com.ctop.alarm.modules.service.ExternalLinkService;
 import cn.com.ctop.alarm.modules.service.IAlarmRuleRecordService;
 import cn.com.ctop.alarm.modules.service.IRuleAccountTemplateService;
 import cn.com.ctop.alarm.modules.service.IRuleGroupService;
@@ -30,7 +33,12 @@ import cn.com.ctop.common.module.service.IRuleDataAccountService;
 import cn.com.ctop.common.module.service.ISendMessageService;
 import cn.com.ctop.common.module.utils.Check;
 import cn.com.ctop.common.module.utils.SendMailUtil;
+import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouGroup;
+import cn.com.ctop.kuaishou.modules.batch.entity.KuaiShouGroupBid;
+import cn.com.ctop.kuaishou.modules.batch.mapper.KuaiShouGroupBidMapper;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouGroupService;
 import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouUpdateService;
+import cn.com.ctop.toutiao.modules.material.entity.ByteDanceAdvertisePlan;
 import cn.com.ctop.toutiao.modules.material.service.IByteDanceAdvertisePlanService;
 import cn.com.ctop.toutiao.modules.material.service.IByteDanceCreativeService;
 import com.alibaba.fastjson.JSONArray;
@@ -39,9 +47,12 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.xxl.job.core.enums.NoEn;
 import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.util.DateUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
@@ -63,6 +74,11 @@ import java.util.concurrent.Executors;
 @Service
 public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup> implements IRuleGroupService {
 
+    //修改头条CPABID出价,投放时间
+    private static final String URL_UPDATE_CPABID = "";
+    //修改头条预算
+    private static final String URL_UPDATE_BUDGET = "";
+
     @Autowired
     private RuleBaseMapper ruleBaseMapper;
     @Autowired
@@ -101,6 +117,14 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
     private IAlarmRuleRecordService alarmRuleRecordService;
     @Autowired
     private ICtopOauthTokenService tokenService;
+    @Autowired
+    private IKuaiShouGroupService kuaiShouGroupService;
+    @Resource
+    private KuaiShouGroupBidMapper groupBidMapper;
+    @Resource
+    private AlarmRuleOperationRecordMapper ruleOperationRecordMapper;
+    @Resource
+    private ExternalLinkService externalLinkService;
 
     private JSONObject userObj = null;
     private final static String ACCOUNT = "account";
@@ -197,7 +221,7 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
         } else {
             matchData = getRuleData(templates.getAccountId(), "KS");
         }
-        if (Check.isNull(matchData)) {
+        if (Check.isNull(matchData) || matchData.isEmpty()) {
             log.warn("获取匹配数据失败");
             return;
         }
@@ -247,64 +271,464 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
         for (RuleGroup ruleGroup : ruleGroups) {
             JSONArray complianceList = new JSONArray();
             List<RuleBase> ruleBaseList = ruleGroup.getRuleBaseList();
+            if (Check.isNull(ruleBaseList)) {
+                continue;
+            }
             //存储触发预警的数据
             List<AlarmRuleRecord> recordList = new ArrayList<>();
-            if (Check.isNull(ruleBaseList)) {
+            //是否有后续操作
+            Integer operation = ruleGroup.getOperation();
+            if (!Check.isNull(operation) && operation == 1) {
+                //有后续操作
+                checkRuleGroupsForOperation(isCopy, thresholdObj, ruleGroup, indicators, matchData, complianceList, type, ruleBaseList, accountName);
+            } else {
+                //复制逻辑
+                if (isCopy) {
+                    JSONObject batchNo = thresholdObj.getJSONObject(ruleGroup.getId().toString());
+                    for (Map.Entry<String, Object> entry : batchNo.entrySet()) {
+                        JSONObject thresholdJn = (JSONObject) entry.getValue();
+                        if (!Check.isNull(thresholdJn)) {
+                            CombinationRule(ruleGroup, thresholdJn, indicators, matchData, complianceList, type, recordList);
+                        }
+                    }
+                } else {
+                    boolean isGroup = "group".equals(ruleGroup.getRuleType());
+                    //匹配组合规则
+                    if (isGroup) {
+                        CombinationRule(ruleGroup, thresholdObj, indicators, matchData, complianceList, type, recordList);
+                        //匹配单规则
+                    } else {
+                        RuleBase ruleBase = ruleBaseList.get(0);
+                        if (Check.isNull(ruleBase)) {
+                            continue;
+                        }
+                        //指标对象
+                        JSONObject indicator = indicators.getJSONObject(ruleBase.getIndicatorCode());
+                        //阈值对象
+                        JSONObject thresholdJson = thresholdObj.getJSONObject(ruleBase.getId().toString());
+                        if (Check.isNull(thresholdJson) || thresholdJson.isEmpty()) {
+                            continue;
+                        }
+                        //阈值
+                        String threshold = thresholdJson.getString("threshold");
+                        //阈值为空时,或者阈值为“unlimited”(不限),不执行该规则
+                        if (Check.isNull(threshold) || threshold.contains("unlimited")) {
+                            continue;
+                        }
+                        //维度数据
+                        JSONArray dimensionData = matchData.getJSONArray(ruleBase.getRuleDimension());
+                        if (!Check.isNull(dimensionData)) {
+                            for (int i = 0; i < dimensionData.size(); i++) {
+                                JSONObject obj = dimensionData.getJSONObject(i);
+                                String value = obj.getString(ruleBase.getIndicatorCode());
+                                if (MatchLogic.matchCondition(indicator, ruleBase.getRuleCondition(), threshold, value, obj, ruleBase.getIndicatorCode())) {
+                                    alarmRuleRecord(obj, ruleGroup, ruleBase, indicator, type, threshold, recordList);
+                                    complianceList.add(obj);
+                                }
+                            }
+                        }
+                    }
+                }
+                if (!Check.isNull(complianceList)) {
+                    getAndSendMessag(complianceList, ruleGroup, accountName, type, false);
+                    Thread thread = new Thread() {
+                        @Override
+                        public void run() {
+                            alarmRuleRecordService.saveBatch(recordList);
+                        }
+                    };
+                    thread.start();
+                }
+            }
+        }
+    }
+
+    /**
+     * B 含操作的规则匹配逻辑
+     */
+    private void checkRuleGroupsForOperation(boolean isCopy, JSONObject thresholdObj, RuleGroup ruleGroup, JSONObject indicators, JSONObject matchData, JSONArray complianceList, Integer type, List<RuleBase> ruleBaseList, String accountName) {
+        //存储触发预警的数据
+        List<AlarmRuleRecord> recordList = new ArrayList<>();
+        String indicatorCode = "";
+        //复制逻辑
+        if (isCopy) {
+            JSONObject batchNo = thresholdObj.getJSONObject(ruleGroup.getId().toString());
+            for (Map.Entry<String, Object> entry : batchNo.entrySet()) {
+                JSONObject thresholdJn = (JSONObject) entry.getValue();
+                if (!Check.isNull(thresholdJn)) {
+                    CombinationRule(ruleGroup, thresholdJn, indicators, matchData, complianceList, type, recordList);
+                }
+            }
+        } else {
+            boolean isGroup = "group".equals(ruleGroup.getRuleType());
+            //匹配组合规则
+            if (isGroup) {
+                CombinationRule(ruleGroup, thresholdObj, indicators, matchData, complianceList, type, recordList);
+                //匹配单规则
+            } else {
+                RuleBase ruleBase = ruleBaseList.get(0);
+                if (Check.isNull(ruleBase)) {
+                    return;
+                }
+                indicatorCode = ruleBase.getIndicatorCode();
+                //比较指标
+                String cindicatorCode = ruleBase.getCindicatorCode();
+                //指标对象
+                JSONObject indicator = indicators.getJSONObject(indicatorCode);
+                //阈值对象
+                JSONObject thresholdJson = thresholdObj.getJSONObject(ruleBase.getId().toString());
+                if (Check.isNull(thresholdJson) || thresholdJson.isEmpty()) {
+                    return;
+                }
+                //阈值
+                String threshold = thresholdJson.getString("threshold");
+                //阈值为空时,或者阈值为“unlimited”(不限),不执行该规则
+                if (Check.isNull(threshold) || threshold.contains("unlimited")) {
+                    return;
+                }
+                //维度数据
+                JSONArray dimensionData = matchData.getJSONArray(ruleBase.getRuleDimension());
+                if (!Check.isNull(dimensionData)) {
+                    for (int i = 0; i < dimensionData.size(); i++) {
+                        JSONObject obj = dimensionData.getJSONObject(i);
+                        String value = obj.getString(indicatorCode);
+                        String othreshold = "";
+                        if (threshold.contains("~")) {
+                            othreshold = threshold;
+                        } else {
+                            othreshold = getThresholdForOperation(obj, ruleBase, threshold, type);
+                        }
+                        if (MatchLogic.matchCondition(indicator, ruleBase.getRuleCondition(), othreshold, value, obj, ruleBase.getIndicatorCode())) {
+                            alarmRuleRecord(obj, ruleGroup, ruleBase, indicator, type, othreshold, recordList);
+                            obj.put("thresholdJson", thresholdJson);
+                            complianceList.add(obj);
+                        }
+                    }
+                }
+            }
+        }
+        if (!Check.isNull(complianceList)) {
+            performOperation(ruleGroup, complianceList, type, accountName);
+            Thread thread = new Thread() {
+                @Override
+                public void run() {
+                    alarmRuleRecordService.saveBatch(recordList);
+                }
+            };
+            thread.start();
+        }
+    }
+
+    /**
+     * 获取操作阈值
+     */
+    private String getThresholdForOperation(JSONObject obj, RuleBase ruleBase, String threshold, Integer type) {
+        String othreshold = "";
+        Long accountId = obj.getLong("accountId");
+        //比较指标
+        String cindicatorCode = ruleBase.getCindicatorCode();
+        String indicatorCode = ruleBase.getIndicatorCode();
+        if (type == 1 || type == 3) {
+            //头条
+            Long planId = obj.getLong("planId");
+            ByteDanceAdvertisePlan byteDancePlan = byteDanceAdvertisePlanService.getById(planId);
+            if ("bid".equals(cindicatorCode)) {
+                BigDecimal bid = byteDancePlan.getBid();
+                if ("PRICING_OCPC".equals(byteDancePlan.getPricing()) || "PRICING_OCPM".equals(byteDancePlan.getPricing())) {
+                    bid = byteDancePlan.getCpaBid();
+                }
+                //转化成本
+                if ("convertCost".equals(indicatorCode)) {
+                    //倍数计算, 转化成本 高于or低于当前倍数时,预警
+                    othreshold = bid.multiply(new BigDecimal(threshold)).toString();
+                }
+            } else {
+                othreshold = threshold;
+            }
+            if ("dayBudget".equals(cindicatorCode)) {
+                if ("cost".equals(indicatorCode)) {
+                    //倍数计算, 转化成本 高于or低于当前倍数时,预警
+                    threshold = new BigDecimal(String.valueOf(byteDancePlan.getBudget())).multiply(new BigDecimal(threshold)).toString();
+                }
+            } else {
+                othreshold = threshold;
+            }
+        } else {
+            //快手
+            Long unitId = obj.getLong("unitId");
+            KuaiShouGroup kuaiShouGroup = kuaiShouGroupService.selectGroupByUnitId(accountId, unitId);
+            if ("bid".equals(cindicatorCode)) {
+                Long bid = kuaiShouGroup.getBid();
+                if (kuaiShouGroup.getBidType() == 10) {
+                    bid = kuaiShouGroup.getCpaBid();
+                }
+                //转化成本
+                if ("convertCost".equals(indicatorCode)) {
+                    //倍数计算, 转化成本 高于or低于当前倍数时,预警
+                    othreshold = new BigDecimal(String.valueOf(bid)).multiply(new BigDecimal(threshold)).toString();
+                }
+            } else {
+                othreshold = threshold;
+            }
+            if ("dayBudget".equals(cindicatorCode)) {
+                if ("charge".equals(indicatorCode)) {
+                    //倍数计算, 转化成本 高于or低于当前倍数时,预警
+                    othreshold = new BigDecimal(String.valueOf(kuaiShouGroup.getDayBudget())).multiply(new BigDecimal(threshold)).toString();
+                }
+            } else {
+                othreshold = threshold;
+            }
+        }
+        return othreshold;
+    }
+
+    /**
+     * 执行操作
+     */
+    private void performOperation(RuleGroup ruleGroup, JSONArray complianceList, Integer type, String accountName) {
+        String operationType = ruleGroup.getOperationType();
+        String operationValue = ruleGroup.getOperationValue();
+        String operate = ruleGroup.getOperate();
+        String ruleType = ruleGroup.getRuleType();
+        Long accountId = complianceList.getJSONObject(0).getLong("accountId");
+        CtopOauthToken token = tokenService.getTokenByAccountId(accountId);
+        //已操作成功的list
+        JSONArray alreadyOperatedList = new JSONArray();
+        for (int i = 0; i < complianceList.size(); i++) {
+            JSONObject obj = complianceList.getJSONObject(i);
+            AlarmRuleOperationRecord recordEntity = null;
+            JSONObject thresholdJson = obj.getJSONObject("thresholdJson");
+            if (Check.isNull(thresholdJson) || thresholdJson.isEmpty()) {
                 continue;
             }
-            //复制逻辑
-            if (isCopy) {
-                JSONObject batchNo = thresholdObj.getJSONObject(ruleGroup.getId().toString());
-                for (Map.Entry<String, Object> entry : batchNo.entrySet()) {
-                    JSONObject thresholdJn = (JSONObject) entry.getValue();
-                    if (!Check.isNull(thresholdJn)) {
-                        CombinationRule(ruleGroup, thresholdJn, indicators, matchData, complianceList, type, recordList);
+            //后续 操作阈值
+            String operationThreshold = thresholdJson.getString("operationThreshold");
+            //峰值
+            String maxValue = thresholdJson.getString("maxValue");
+            String minValue = thresholdJson.getString("minValue");
+
+            if (type == 1 || type == 3) {
+                Long planId = obj.getLong("planId");//头条
+                if (Check.isNull(planId)) {
+                    continue;
+                }
+                ByteDanceAdvertisePlan byteDancePlan = byteDanceAdvertisePlanService.getById(planId);
+                if (Check.isNull(byteDancePlan)) {
+                    continue;
+                }
+                //修改出价
+                if ("BID".equals(operate)) {
+                    BigDecimal oldBid = byteDancePlan.getBid();
+                    if ("PRICING_OCPC".equals(byteDancePlan.getPricing()) || "PRICING_OCPM".equals(byteDancePlan.getPricing())) {
+                        oldBid = byteDancePlan.getCpaBid();
+                    }
+                    if (("up".equals(operationType) && oldBid.compareTo(new BigDecimal(maxValue)) == 0) || ("down".equals(operationType) && oldBid.compareTo(new BigDecimal(minValue)) == 0)) {
+                        continue;
+                    }
+                    Long newBid = calculatedValue(oldBid, operationType, operationValue, operationThreshold, maxValue, minValue);
+                    //TODO
+                    String code = externalLinkService.editBytedancePlanCpaBidOrBudget(accountId, planId.toString(), new BigDecimal(newBid.toString()), null, null);
+                    String message = "success";
+                    if (code.equals("")) {
+                        alreadyOperatedList.add(obj);
+                    } else {
+                        message = "fail";
+                        log.error("(头条)规则引擎修改出价失败,accountId={},unitId={}", accountId, planId);
+                    }
+                    recordEntity = getOperationRecordEntity(accountId, ruleGroup, maxValue, minValue, operate, null, planId, operationThreshold, oldBid.toString(), newBid.toString(), message, "头条");
+                    //修改预算
+                } else if ("BUDGET".equals(operate)) {
+                    BigDecimal oldBudget = byteDancePlan.getBudget();
+                    if (("up".equals(operationType) && oldBudget.compareTo(new BigDecimal(maxValue)) == 0) || ("down".equals(operationType) && oldBudget.compareTo(new BigDecimal(minValue)) == 0)) {
+                        continue;
+                    }
+                    Long newBudget = calculatedValue(oldBudget, operationType, operationValue, operationThreshold, maxValue, minValue);
+                    //TODO
+                    String code = externalLinkService.editBytedancePlanCpaBidOrBudget(accountId, planId.toString(), null, null, newBudget);
+                    String message = "success";
+                    if (code.equals("")) {
+                        alreadyOperatedList.add(obj);
+                    } else {
+                        message = "fail";
+                        log.error("(头条)规则引擎修改预算失败,accountId={},unitId={}", accountId, planId);
+                    }
+                    recordEntity = getOperationRecordEntity(accountId, ruleGroup, maxValue, minValue, operate, null, planId, operationThreshold, oldBudget.toString(), newBudget.toString(), message, "头条");
+                    //修改投放时间
+                } else if ("TIME".equals(operate) && !byteDancePlan.getScheduleTime().equals(operationThreshold)) {
+                    //TODO
+                    String code = externalLinkService.editBytedancePlanCpaBidOrBudget(accountId, planId.toString(), null, operationThreshold, null);
+                    String message = "success";
+                    if (code.equals("")) {
+                        alreadyOperatedList.add(obj);
+                    } else {
+                        message = "fail";
+                        log.error("规则引擎修改投放时间段失败,accountId={},unitId={}", accountId, planId);
                     }
+                    recordEntity = getOperationRecordEntity(accountId, ruleGroup, maxValue, minValue, operate, null, planId, operationThreshold, byteDancePlan.getScheduleTime(), operationThreshold, message, "头条");
                 }
+
             } else {
-                boolean isGroup = "group".equals(ruleGroup.getRuleType());
-                //匹配组合规则
-                if (isGroup) {
-                    CombinationRule(ruleGroup, thresholdObj, indicators, matchData, complianceList, type, recordList);
-                    //匹配单规则
-                } else {
-                    RuleBase ruleBase = ruleBaseList.get(0);
-                    if (Check.isNull(ruleBase)) {
+                Long unitId = obj.getLong("unitId");//快手
+                if (Check.isNull(unitId)) {
+                    continue;
+                }
+                KuaiShouGroup kuaiShouGroup = kuaiShouGroupService.selectGroupByUnitId(accountId, unitId);
+                if (Check.isNull(kuaiShouGroup)) {
+                    continue;
+                }
+                //修改出价
+                if ("BID".equals(operate)) {
+                    Integer bidType = kuaiShouGroup.getBidType();
+                    Long oldBid = Check.isNull(kuaiShouGroup.getBid()) ? 0L : kuaiShouGroup.getBid();
+                    if (bidType == 10) {
+                        oldBid = kuaiShouGroup.getCpaBid();
+                    }
+                    if (("up".equals(operationType) && oldBid - Long.valueOf(maxValue) == 0) || ("down".equals(operationType) && oldBid - Long.valueOf(minValue) == 0)) {
                         continue;
                     }
-                    //指标对象
-                    JSONObject indicator = indicators.getJSONObject(ruleBase.getIndicatorCode());
-                    //指标阈值
-                    String threshold = thresholdObj.getString(ruleBase.getId().toString());
-                    //阈值为空时,或者阈值为“unlimited”(不限),不执行该规则
-                    if (Check.isNull(threshold) || threshold.contains("unlimited")) {
+                    Long newBid = calculatedValue(new BigDecimal(oldBid.toString()), operationType, operationValue, operationThreshold, maxValue, minValue);
+                    JSONObject unitJson = new JSONObject();
+                    unitJson.put("advertiser_id", accountId);
+                    unitJson.put("unit_id", unitId);
+                    String msg = "规则引擎修改bid";
+                    if (bidType == 2) {
+                        unitJson.put("bid", newBid);
+                    } else if (bidType == 10) {
+                        unitJson.put("cpa_bid", newBid);
+                        msg = "规则引擎修改cpa_bid";
+                    }
+                    JSONObject jsonObject = kuaiShouUpdateService.updateUnit(token.getAccessToken(), unitJson);
+                    Integer code = jsonObject.getInteger("code");
+                    String message = "success";
+                    if (code == 0) {
+                        alreadyOperatedList.add(obj);
+                        //添加改价记录
+                        KuaiShouGroupBid groupBid = new KuaiShouGroupBid();
+                        groupBid.setAccountId(accountId);
+                        groupBid.setUnitId(unitId);
+                        groupBid.setBid(newBid);
+                        groupBid.setUpdateBid(oldBid);
+                        groupBid.setUserId(msg);
+                        groupBidMapper.insert(groupBid);
+                        kuaiShouGroupService.getGroupByUnitId(token.getAccessToken(), accountId, unitId);
+                    } else {
+                        message = "fail," + jsonObject.getString("message");
+                        log.error("(快手)规则引擎修改出价失败,accountId={},unitId={},{}", accountId, unitId, jsonObject.getString("message"));
+                    }
+                    recordEntity = getOperationRecordEntity(accountId, ruleGroup, maxValue, minValue, operate, unitId, null, operationThreshold, oldBid.toString(), newBid.toString(), message, "快手");
+                    //修改预算
+                } else if ("BUDGET".equals(operate)) {
+                    Long oldBudget = Check.isNull(kuaiShouGroup.getDayBudget()) ? 0L : kuaiShouGroup.getDayBudget();
+                    if (("up".equals(operationType) && oldBudget - Long.valueOf(maxValue) == 0) || ("down".equals(operationType) && oldBudget - Long.valueOf(minValue) == 0)) {
                         continue;
                     }
-                    //维度数据
-                    JSONArray dimensionData = matchData.getJSONArray(ruleBase.getRuleDimension());
-                    if (!Check.isNull(dimensionData)) {
-                        for (int i = 0; i < dimensionData.size(); i++) {
-                            JSONObject obj = dimensionData.getJSONObject(i);
-                            String value = obj.getString(ruleBase.getIndicatorCode());
-                            if (MatchLogic.matchCondition(indicator, ruleBase.getRuleCondition(), threshold, value, obj, ruleBase.getIndicatorCode())) {
-                                alarmRuleRecord(obj, ruleGroup, ruleBase, indicator, type, threshold, recordList);
-                                complianceList.add(obj);
-                            }
-                        }
+                    Long newBudget = calculatedValue(new BigDecimal(oldBudget.toString()), operationType, operationValue, operationThreshold, maxValue, minValue);
+                    Map<String, Object> updateMap = kuaiShouUpdateService.updateUnitDayBudget(token.getAccessToken(), accountId, unitId, newBudget, "规则引擎修改预算");
+                    String message = "success";
+                    if ((Integer) updateMap.get("code") == 0) {
+                        alreadyOperatedList.add(obj);
+                        kuaiShouGroupService.getGroupByUnitId(token.getAccessToken(), accountId, unitId);
+                    } else {
+                        message = "fail," + updateMap.get("message");
+                        log.error("(快手)规则引擎修改预算失败,accountId={},unitId={},{}", accountId, unitId, updateMap.get("message"));
+                    }
+                    recordEntity = getOperationRecordEntity(accountId, ruleGroup, maxValue, minValue, operate, unitId, null, operationThreshold, oldBudget.toString(), newBudget.toString(), message, "快手");
+                    //修改投放时间
+                } else if ("TIME".equals(operate) && !kuaiShouGroup.getScheduleTime().equals(operationThreshold)) {
+                    JSONObject unitJson = new JSONObject();
+                    unitJson.put("advertiser_id", accountId);
+                    unitJson.put("unit_id", unitId);
+                    unitJson.put("schedule_time", operationThreshold);
+                    JSONObject jsonObject = kuaiShouUpdateService.updateUnit(token.getAccessToken(), unitJson);
+                    Integer code = jsonObject.getInteger("code");
+                    String message = "success";
+                    if (code == 0) {
+                        alreadyOperatedList.add(obj);
+                        kuaiShouGroupService.getGroupByUnitId(token.getAccessToken(), accountId, unitId);
+                    } else {
+                        message = "fail," + jsonObject.getString("message");
+                        log.error("(快手)规则引擎修改投放时间段失败,accountId={},unitId={},{}", accountId, unitId, jsonObject.getString("message"));
                     }
+                    recordEntity = getOperationRecordEntity(accountId, ruleGroup, maxValue, minValue, operate, unitId, null, operationThreshold, kuaiShouGroup.getScheduleTime(), operationThreshold, message, "快手");
                 }
             }
-            if (!Check.isNull(complianceList)) {
-                getAndSendMessag(complianceList, ruleGroup, accountName, type);
-                Thread thread = new Thread() {
-                    @Override
-                    public void run() {
-                        alarmRuleRecordService.saveBatch(recordList);
-                    }
-                };
-                thread.start();
+            if (!Check.isNull(recordEntity)) {
+                ruleOperationRecordMapper.insert(recordEntity);
             }
         }
+        if (alreadyOperatedList.size() > 0) {
+            getAndSendMessag(alreadyOperatedList, ruleGroup, accountName, type, true);
+        }
+    }
+
+    /**
+     * 整合操作记录实体类
+     */
+    private AlarmRuleOperationRecord getOperationRecordEntity(Long accountId, RuleGroup ruleGroup, String maxValue, String minValue, String indicatorCode, Long unitId, Long planId, String operationThreshold, String oldValue, String newValue, String msg, String mediaType) {
+        AlarmRuleOperationRecord record = new AlarmRuleOperationRecord();
+        record.setAccountId(accountId);
+        record.setOperationType(ruleGroup.getOperationType());
+        record.setOperationValue(ruleGroup.getOperationValue());
+        record.setMaxValue(maxValue);
+        record.setMinValue(minValue);
+        record.setUnitId(unitId);
+        record.setPlanId(planId);
+        record.setGroupId(ruleGroup.getId());
+        record.setIndicatorCode(indicatorCode);
+        record.setBeforeValue(oldValue);
+        record.setAfterValue(newValue);
+        record.setOperationThreshold(operationThreshold);
+        record.setMediaType(mediaType);
+        record.setMessage(msg);
+        record.setValueTime(DateUtils.formatDate(new Date()));
+        return record;
+    }
+
+    /**
+     * 计算待调整数值
+     * <p>
+     * 广告组bid_type为CPC和eCPC时:不得低于0.2元,不得高于100元,单位:厘;广告组bid_type为OCPC时:行为出价不得低于1元;激活出价不得低于5元(白名单用户不得低于2元),单位:厘
+     *
+     * @param goalValue          目标值
+     * @param operationType      操作类型:up-提高,down-降低,to-调整至
+     * @param operationValue     操作内容:price-金额,percent-百分数
+     * @param operationThreshold 操作阈值
+     * @param fmaxValue          目标值的峰值
+     * @param fminValue          目标值的最低值
+     * @return
+     * @throws
+     */
+    private static Long calculatedValue(BigDecimal goal, String operationType, String operationValue, String operationThreshold, String fmaxValue, String fminValue) {
+        BigDecimal threshold = new BigDecimal(operationThreshold);
+        BigDecimal maxValue = new BigDecimal(fmaxValue);
+        BigDecimal minValue = new BigDecimal(fminValue);
+        BigDecimal value = null;
+        //操作金额
+        if ("price".equals(operationValue)) {
+            if ("up".equals(operationType)) {
+                value = goal.add(threshold);
+            } else if ("down".equals(operationType)) {
+                value = goal.subtract(threshold);
+            } else if ("to".equals(operationType)) {
+                value = threshold;
+            }
+        } else {
+            //操作百分数
+            if ("up".equals(operationType)) {
+                value = goal.add(goal.multiply(threshold));
+            } else if ("down".equals(operationType)) {
+                value = goal.subtract(goal.multiply(threshold));
+            } else if ("to".equals(operationType)) {
+                value = goal.multiply(threshold);
+            }
+        }
+        if (value.compareTo(maxValue) == 1) {
+            value = maxValue;
+        }
+        if (value.compareTo(minValue) == -1) {
+            value = minValue;
+        }
+        return value.longValue();
     }
 
     /**
@@ -315,7 +739,8 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
      * @throws
      * @author ZHAOXA
      */
-    private void alarmRuleRecord(JSONObject obj, RuleGroup ruleGroup, RuleBase ruleBase, JSONObject indicator, Integer mediaType, String threshold, List<AlarmRuleRecord> recordList) {
+    private void alarmRuleRecord(JSONObject obj, RuleGroup ruleGroup, RuleBase ruleBase, JSONObject
+            indicator, Integer mediaType, String threshold, List<AlarmRuleRecord> recordList) {
         try {
             Long planId = obj.getLong("planId");
             Long unidId = null;
@@ -363,7 +788,8 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
      * @throws
      * @author ZHAOXA
      */
-    private void CombinationRule(RuleGroup ruleGroup, JSONObject thresholdObj, JSONObject indicators, JSONObject matchData, JSONArray complianceList, Integer type, List<AlarmRuleRecord> recordList) {
+    private void CombinationRule(RuleGroup ruleGroup, JSONObject thresholdObj, JSONObject indicators, JSONObject
+            matchData, JSONArray complianceList, Integer type, List<AlarmRuleRecord> recordList) {
         List<RuleBase> ruleBaseList = ruleGroup.getRuleBaseList();
         //符合规则的数据集
         JSONArray groupDatas = new JSONArray();
@@ -374,8 +800,13 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
         for (RuleBase ruleBase : ruleBaseList) {
             //指标对象
             JSONObject indicator = indicators.getJSONObject(ruleBase.getIndicatorCode());
-            //指标阈值
-            String threshold = thresholdObj.getString(ruleBase.getId().toString());
+            //阈值对象
+            JSONObject thresholdJson = thresholdObj.getJSONObject(ruleBase.getId().toString());
+            if (Check.isNull(thresholdJson) || thresholdJson.isEmpty()) {
+                continue;
+            }
+            //阈值
+            String threshold = thresholdJson.getString("threshold");
             //阈值为空时,或者阈值为“unlimited”(不限),不执行该规则
             if (Check.isNull(threshold) || threshold.contains("unlimited")) {
                 if (!Check.isNull(accountDatas)) {
@@ -395,7 +826,9 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                 }
                 break;
             }
-            JSONArray dimensionData = matchData.getJSONArray(ruleBase.getRuleDimension());
+            //获取维度数据
+            String ruleDimension = ruleBase.getRuleDimension();
+            JSONArray dimensionData = matchData.getJSONArray(ruleDimension);
             if (Check.isNull(dimensionData)) {
                 if (!Check.isNull(accountDatas)) {
                     accountDatas = null;
@@ -415,7 +848,7 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                 break;
             }
             //账户维度数据
-            if (ACCOUNT.equals(ruleBase.getRuleDimension())) {
+            if (ACCOUNT.equals(ruleDimension)) {
                 JSONObject accountEntity = dimensionData.getJSONObject(0);
                 if (MatchLogic.matchCondition(indicator, ruleBase.getRuleCondition(), threshold, accountEntity.getString(ruleBase.getIndicatorCode()), accountEntity, ruleBase.getIndicatorCode())) {
                     if (Check.isNull(accountDatas)) {
@@ -440,8 +873,8 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                     }
                     break;
                 }
-            } else if (PLAN.equals(ruleBase.getRuleDimension())) {
-                planDatas = getOKData(planDatas, dimensionData, ruleBase, indicator, threshold, ruleGroup, type, recordList);
+            } else if (PLAN.equals(ruleDimension)) {
+                planDatas = getOKData(planDatas, dimensionData, ruleBase, indicator, thresholdJson, ruleGroup, type, recordList);
                 if (Check.isNull(planDatas)) {
                     if (!Check.isNull(accountDatas)) {
                         accountDatas = null;
@@ -460,8 +893,8 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                     }
                     break;
                 }
-            } else if (CREATIVE.equals(ruleBase.getRuleDimension())) {
-                creativeDatas = getOKData(creativeDatas, dimensionData, ruleBase, indicator, threshold, ruleGroup, type, recordList);
+            } else if (CREATIVE.equals(ruleDimension)) {
+                creativeDatas = getOKData(creativeDatas, dimensionData, ruleBase, indicator, thresholdJson, ruleGroup, type, recordList);
                 if (Check.isNull(creativeDatas)) {
                     if (!Check.isNull(accountDatas)) {
                         accountDatas = null;
@@ -480,8 +913,8 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                     }
                     break;
                 }
-            } else if ("target".equals(ruleBase.getRuleDimension())) {
-                targetDatas = getOKData(targetDatas, dimensionData, ruleBase, indicator, threshold, ruleGroup, type, recordList);
+            } else if ("target".equals(ruleDimension)) {
+                targetDatas = getOKData(targetDatas, dimensionData, ruleBase, indicator, thresholdJson, ruleGroup, type, recordList);
                 if (Check.isNull(targetDatas)) {
                     if (!Check.isNull(accountDatas)) {
                         accountDatas = null;
@@ -500,8 +933,8 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                     }
                     break;
                 }
-            } else if (UNIT.equals(ruleBase.getRuleDimension())) {
-                groupDatas = getOKData(groupDatas, dimensionData, ruleBase, indicator, threshold, ruleGroup, type, recordList);
+            } else if (UNIT.equals(ruleDimension)) {
+                groupDatas = getOKData(groupDatas, dimensionData, ruleBase, indicator, thresholdJson, ruleGroup, type, recordList);
                 if (Check.isNull(groupDatas)) {
                     if (!Check.isNull(accountDatas)) {
                         accountDatas = null;
@@ -544,14 +977,25 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
      * @throws
      * @author ZHAOXA
      */
-    private JSONArray getOKData(JSONArray ruleDatas, JSONArray dimensionData, RuleBase ruleBase, JSONObject indicator, String threshold, RuleGroup ruleGroup, Integer type, List<AlarmRuleRecord> recordList) {
+    private JSONArray getOKData(JSONArray ruleDatas, JSONArray dimensionData, RuleBase ruleBase, JSONObject
+            indicator, JSONObject thresholdJson, RuleGroup ruleGroup, Integer type, List<AlarmRuleRecord> recordList) {
+        String threshold = thresholdJson.getString("threshold");
         if (!Check.isNull(ruleDatas)) {
             JSONArray okData = new JSONArray();
             for (int i = 0; i < ruleDatas.size(); i++) {
                 JSONObject obj = ruleDatas.getJSONObject(i);
                 String value = obj.getString(ruleBase.getIndicatorCode());
-                if (MatchLogic.matchCondition(indicator, ruleBase.getRuleCondition(), threshold, value, obj, ruleBase.getIndicatorCode())) {
-                    alarmRuleRecord(obj, ruleGroup, ruleBase, indicator, type, threshold, recordList);
+                String othreshold = "";
+                if (threshold.contains("~")) {
+                    othreshold = threshold;
+                } else {
+                    othreshold = getThresholdForOperation(obj, ruleBase, threshold, type);
+                }
+                if (MatchLogic.matchCondition(indicator, ruleBase.getRuleCondition(), othreshold, value, obj, ruleBase.getIndicatorCode())) {
+                    alarmRuleRecord(obj, ruleGroup, ruleBase, indicator, type, othreshold, recordList);
+                    if (groupThresholdFromIndicator(thresholdJson, ruleGroup.getOperate())) {
+                        obj.put("thresholdJson", thresholdJson);
+                    }
                     okData.add(obj);
                 }
             }
@@ -560,15 +1004,48 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
         for (int i = 0; i < dimensionData.size(); i++) {
             JSONObject obj = dimensionData.getJSONObject(i);
             String value = obj.getString(ruleBase.getIndicatorCode());
-            if (MatchLogic.matchCondition(indicator, ruleBase.getRuleCondition(), threshold, value, obj, ruleBase.getIndicatorCode())) {
-                alarmRuleRecord(obj, ruleGroup, ruleBase, indicator, type, threshold, recordList);
+            String othreshold = "";
+            if (threshold.contains("~")) {
+                othreshold = threshold;
+            } else {
+                othreshold = getThresholdForOperation(obj, ruleBase, threshold, type);
+            }
+            if (MatchLogic.matchCondition(indicator, ruleBase.getRuleCondition(), othreshold, value, obj, ruleBase.getIndicatorCode())) {
+                alarmRuleRecord(obj, ruleGroup, ruleBase, indicator, type, othreshold, recordList);
+                if (groupThresholdFromIndicator(thresholdJson, ruleGroup.getOperate())) {
+                    obj.put("thresholdJson", thresholdJson);
+                }
                 ruleDatas.add(obj);
             }
         }
         return ruleDatas;
     }
 
-    private void getAndSendMessag(JSONArray complianceList, RuleGroup ruleGroup, String accountName, Integer mediaType) {
+    private boolean groupThresholdFromIndicator(JSONObject thresholdJson, String operate) {
+        if ("SEND".equals(operate) || "PAUSE".equals(operate)) {
+            return false;
+        }
+        RuleBase base = ruleBaseMapper.selectById(thresholdJson.getLong("ruleId"));
+        String code = base.getIndicatorCode();
+        if ("BID".equals(operate)) {
+            return "charge".equals(code) || "cost".equals(code);
+        } else if ("BUDGET".equals(operate)) {
+            return "convertCost".equals(code);
+        } else if ("TIME".equals(operate)) {
+            return "scheduleTime".equals(code);
+        }
+        return false;
+    }
+
+    /**
+     * @param complianceList 触发规则数据
+     * @param ruleGroup      触发的规则组
+     * @param accountName    账户名称
+     * @param mediaType      媒体类型
+     * @param isOperation    是否有后续操作(仅做发送内容变更)
+     * @throws
+     */
+    private void getAndSendMessag(JSONArray complianceList, RuleGroup ruleGroup, String accountName, Integer mediaType, boolean isOperation) {
         Long accountId = complianceList.getJSONObject(0).getLong("accountId");
         if (Check.isNull(accountId)) {
             return;
@@ -592,7 +1069,7 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                         isNullCreativeJoiner.add(obj.getString("creativeId"));
                     } else {
                         String message = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, CREATIVE, isNullCreativeJoiner.toString(), isNull);
-                        sendMsg(message, ruleGroup, user, CREATIVE, isNullCreativeJoiner.toString(), accountId, mediaType);
+                        sendMsg(message, ruleGroup, user, CREATIVE, isNullCreativeJoiner.toString(), accountId, mediaType, isOperation);
                         isNullCreativeJoiner = new StringJoiner(",");
                         isNullCreativeJoiner.add(obj.getString("creativeId"));
                     }
@@ -601,13 +1078,13 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                         isNullPlanJoiner.add(obj.getString("planId"));
                     } else {
                         String msg = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, PLAN, isNullPlanJoiner.toString(), isNull);
-                        sendMsg(msg, ruleGroup, user, PLAN, isNullPlanJoiner.toString(), accountId, mediaType);
+                        sendMsg(msg, ruleGroup, user, PLAN, isNullPlanJoiner.toString(), accountId, mediaType, isOperation);
                         isNullPlanJoiner = new StringJoiner(",");
                         isNullPlanJoiner.add(obj.getString("planId"));
                     }
                 } else {
                     String msg = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, null, null, isNull);
-                    sendMsg(msg, ruleGroup, user, ACCOUNT, null, accountId, mediaType);
+                    sendMsg(msg, ruleGroup, user, ACCOUNT, null, accountId, mediaType, isOperation);
                 }
             } else {
                 if (!Check.isNull(obj.getString("creativeId"))) {
@@ -616,7 +1093,7 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                         creativeJoiner.add(obj.getString("creativeId"));
                     } else {
                         String message = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, CREATIVE, creativeJoiner.toString(), isNull);
-                        sendMsg(message, ruleGroup, user, CREATIVE, creativeJoiner.toString(), accountId, mediaType);
+                        sendMsg(message, ruleGroup, user, CREATIVE, creativeJoiner.toString(), accountId, mediaType, isOperation);
                         creativeJoiner = new StringJoiner(",");
                         creativeJoiner.add(obj.getString("creativeId"));
                     }
@@ -625,7 +1102,7 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                         unitJoiner.add(obj.getString("unitId"));
                     } else {
                         String msg = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, UNIT, unitJoiner.toString(), isNull);
-                        sendMsg(msg, ruleGroup, user, UNIT, unitJoiner.toString(), accountId, mediaType);
+                        sendMsg(msg, ruleGroup, user, UNIT, unitJoiner.toString(), accountId, mediaType, isOperation);
                         unitJoiner = new StringJoiner(",");
                         unitJoiner.add(obj.getString("unitId"));
                     }
@@ -634,35 +1111,35 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                         planJoiner.add(obj.getString("planId"));
                     } else {
                         String msg = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, PLAN, planJoiner.toString(), isNull);
-                        sendMsg(msg, ruleGroup, user, PLAN, planJoiner.toString(), accountId, mediaType);
+                        sendMsg(msg, ruleGroup, user, PLAN, planJoiner.toString(), accountId, mediaType, isOperation);
                         planJoiner = new StringJoiner(",");
                         planJoiner.add(obj.getString("planId"));
                     }
                 } else {
                     String msg = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, null, null, isNull);
-                    sendMsg(msg, ruleGroup, user, ACCOUNT, null, accountId, mediaType);
+                    sendMsg(msg, ruleGroup, user, ACCOUNT, null, accountId, mediaType, isOperation);
                 }
             }
         }
         if (!Check.isNull(creativeJoiner.toString())) {
             String creativeMsg = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, CREATIVE, creativeJoiner.toString(), false);
-            sendMsg(creativeMsg, ruleGroup, user, CREATIVE, creativeJoiner.toString(), accountId, mediaType);
+            sendMsg(creativeMsg, ruleGroup, user, CREATIVE, creativeJoiner.toString(), accountId, mediaType, isOperation);
         }
         if (!Check.isNull(unitJoiner.toString())) {
             String creativeMsg = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, UNIT, unitJoiner.toString(), false);
-            sendMsg(creativeMsg, ruleGroup, user, UNIT, unitJoiner.toString(), accountId, mediaType);
+            sendMsg(creativeMsg, ruleGroup, user, UNIT, unitJoiner.toString(), accountId, mediaType, isOperation);
         }
         if (!Check.isNull(planJoiner.toString())) {
             String planMsg = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, PLAN, planJoiner.toString(), false);
-            sendMsg(planMsg, ruleGroup, user, PLAN, planJoiner.toString(), accountId, mediaType);
+            sendMsg(planMsg, ruleGroup, user, PLAN, planJoiner.toString(), accountId, mediaType, isOperation);
         }
         if (!Check.isNull(isNullCreativeJoiner.toString())) {
             String isNullCreativeMsg = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, CREATIVE, isNullCreativeJoiner.toString(), true);
-            sendMsg(isNullCreativeMsg, ruleGroup, user, CREATIVE, isNullCreativeJoiner.toString(), accountId, mediaType);
+            sendMsg(isNullCreativeMsg, ruleGroup, user, CREATIVE, isNullCreativeJoiner.toString(), accountId, mediaType, isOperation);
         }
         if (!Check.isNull(isNullPlanJoiner.toString())) {
             String isNullPlanMsg = MatchLogic.getMessage(ruleGroup.getGroupName(), accountId, accountName, PLAN, isNullPlanJoiner.toString(), true);
-            sendMsg(isNullPlanMsg, ruleGroup, user, PLAN, isNullPlanJoiner.toString(), accountId, mediaType);
+            sendMsg(isNullPlanMsg, ruleGroup, user, PLAN, isNullPlanJoiner.toString(), accountId, mediaType, isOperation);
         }
     }
 
@@ -677,7 +1154,7 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
      * @throws
      * @author ZHAOXA
      */
-    private void sendMsg(String msg, RuleGroup ruleGroup, JSONObject user, String type, String ids, Long accountId, Integer mediaType) {
+    private void sendMsg(String msg, RuleGroup ruleGroup, JSONObject user, String type, String ids, Long accountId, Integer mediaType, boolean isOperation) {
         try {
             boolean isPause = "PAUSE".equals(ruleGroup.getOperate());
             if (isPause) {
@@ -691,10 +1168,18 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                     msg = msg.replace(",", ",");
                 }
                 if (ACCOUNT.equals(type)) {
-                    msg += "请您及时查看并调整";
+                    msg += "请您及时查看并调整";
                 }
             } else {
-                msg += "请您及时查看并调整!";
+                msg += "请您及时查看并调整";
+            }
+            if (isOperation) {
+                msg = msg.replace("请您及时查看并调整", "系统已按照设置调整出价,请您及时查看");
+                if ("BUDGET".equals(ruleGroup.getOperate())) {
+                    msg = msg.replace("出价", "预算");
+                } else if ("TIME".equals(ruleGroup.getOperate())) {
+                    msg = msg.replace("出价", "投放时间");
+                }
             }
             String sendType = ruleGroup.getSendType();
             if ("SMS".equals(sendType)) {
@@ -704,8 +1189,8 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                 SendMailUtil.sendMail(mailList, ruleGroup.getGroupName() + "预警", msg);
             } else if ("TEL".equals(sendType)) {
             } else {
-//                sendMessageService.sendMessage("1b3deb8258e84df994f1371a51cfc14a", msg);
-                sendMessageService.sendMessage(user.getString("id"), msg);
+                sendMessageService.sendMessage("1b3deb8258e84df994f1371a51cfc14a", msg);
+//                sendMessageService.sendMessage(user.getString("id"), msg);
                 Thread.sleep(100);
             }
             if (!Check.isNull(msg)) {
@@ -861,7 +1346,7 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                             return null;
                         }
                         for (RuleAccountThreshold threshold : thresholdList) {
-                            batchNoObj.put(String.valueOf(threshold.getRuleId()), threshold.getThreshold());
+                            batchNoObj.put(String.valueOf(threshold.getRuleId()), threshold);
                         }
                         groupIdObj.put(batchNo.toString(), batchNoObj);
                     }
@@ -873,7 +1358,7 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                     return null;
                 }
                 for (RuleAccountThreshold threshold : thresholdList) {
-                    obj.put(String.valueOf(threshold.getRuleId()), threshold.getThreshold());
+                    obj.put(String.valueOf(threshold.getRuleId()), threshold);
                 }
             }
         } catch (Exception e) {

+ 13 - 4
module-common/src/main/java/cn/com/ctop/common/module/service/impl/RuleDataAccountKuaishouServiceImpl.java

@@ -9,6 +9,7 @@ import cn.com.ctop.common.module.mapper.RuleDataTargetKuaishouMapper;
 import cn.com.ctop.common.module.mapper.RuleDatePlanKuaishouMapper;
 import cn.com.ctop.common.module.mapper.RuleDateUnitKuaishouMapper;
 import cn.com.ctop.common.module.service.IRuleDataAccountKuaishouService;
+import cn.com.ctop.common.module.utils.Check;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.xxl.job.core.enums.NoEn;
@@ -45,13 +46,21 @@ public class RuleDataAccountKuaishouServiceImpl extends ServiceImpl<RuleDataAcco
         map.put("account_id", accountId);
         map.put("status", NoEn.NO1.valueInt());
         List<RuleDataAccountKuaishou> accountList = ruleDataAccountKuaishouMapper.selectByMap(map);
-        obj.put("account", accountList);
+        if (!Check.isNull(accountList)) {
+            obj.put("account", accountList);
+        }
         List<RuleDateUnitKuaishou> unitKuaishous = ruleDateUnitKuaishouMapper.selectByMap(map);
-        obj.put("unit", unitKuaishous);
+        if (!Check.isNull(unitKuaishous)) {
+            obj.put("unit", unitKuaishous);
+        }
         List<RuleDataTargetKuaishou> targetKuaishous = ruleDataTargetKuaishouMapper.selectByMap(map);
-        obj.put("target", targetKuaishous);
+        if (!Check.isNull(targetKuaishous)) {
+            obj.put("target", targetKuaishous);
+        }
         List<RuleDatePlanKuaishou> planKuaishous = ruleDatePlanKuaishouMapper.selectByMap(map);
-        obj.put("plan", planKuaishous);
+        if (!Check.isNull(planKuaishous)) {
+            obj.put("plan", planKuaishous);
+        }
         return obj;
     }
 }

+ 13 - 4
module-common/src/main/java/cn/com/ctop/common/module/service/impl/RuleDataAccountServiceImpl.java

@@ -9,6 +9,7 @@ import cn.com.ctop.common.module.mapper.RuleDataCreativeMapper;
 import cn.com.ctop.common.module.mapper.RuleDataPlanMapper;
 import cn.com.ctop.common.module.mapper.RuleDataTargetMapper;
 import cn.com.ctop.common.module.service.IRuleDataAccountService;
+import cn.com.ctop.common.module.utils.Check;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.xxl.job.core.enums.NoEn;
@@ -48,13 +49,21 @@ public class RuleDataAccountServiceImpl extends ServiceImpl<RuleDataAccountMappe
         map.put("account_id", accountId);
         map.put("status", NoEn.NO1.valueInt());
         List<RuleDataAccount> ruleDataAccounts = ruleDataAccountMapper.selectByMap(map);
-        obj.put("account", ruleDataAccounts);
+        if (!Check.isNull(ruleDataAccounts)) {
+            obj.put("account", ruleDataAccounts);
+        }
         List<RuleDataPlan> ruleDataPlans = ruleDataPlanMapper.selectByMap(map);
-        obj.put("plan", ruleDataPlans);
+        if (!Check.isNull(ruleDataPlans)) {
+            obj.put("plan", ruleDataPlans);
+        }
         List<RuleDataTarget> ruleDataTargets = ruleDataTargetMapper.selectByMap(map);
-        obj.put("target", ruleDataTargets);
+        if (!Check.isNull(ruleDataTargets)) {
+            obj.put("target", ruleDataTargets);
+        }
         List<RuleDataCreative> ruleDataCreatives = ruleDataCreativeMapper.selectByMap(map);
-        obj.put("creative", ruleDataCreatives);
+        if (!Check.isNull(ruleDataCreatives)) {
+            obj.put("creative", ruleDataCreatives);
+        }
         return obj;
     }
 }

+ 106 - 0
module-job-bytedance/src/main/java/cn/com/ctop/job/bytedance/handler/AlarmRuleRebackJob.java

@@ -0,0 +1,106 @@
+package cn.com.ctop.job.bytedance.handler;
+
+
+import cn.com.ctop.alarm.modules.entity.AlarmRuleOperationRecord;
+import cn.com.ctop.alarm.modules.mapper.AlarmRuleOperationRecordMapper;
+import cn.com.ctop.alarm.modules.service.ExternalLinkService;
+import cn.com.ctop.common.module.entity.CtopOauthToken;
+import cn.com.ctop.common.module.service.ICtopOauthTokenService;
+import cn.com.ctop.common.module.utils.Check;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouGroupService;
+import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouUpdateService;
+import com.alibaba.fastjson.JSONObject;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import org.jeecg.common.util.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@Component
+public class AlarmRuleRebackJob {
+    @Autowired
+    private ICtopOauthTokenService tokenService;
+    @Autowired
+    private AlarmRuleOperationRecordMapper ruleOperationRecordMapper;
+    @Autowired
+    private IKuaiShouUpdateService kuaiShouUpdateService;
+    @Autowired
+    private IKuaiShouGroupService kuaiShouGroupService;
+    @Resource
+    private ExternalLinkService externalLinkService;
+
+    static ExecutorService executorKSService = Executors.newFixedThreadPool(5);
+    static ExecutorService executorTTService = Executors.newFixedThreadPool(5);
+
+    /**
+     * 每日回退修改投放时段定时任务
+     * @param
+     * @return
+     * @throws
+     * @author ZHAOXA
+     */
+    @XxlJob("alarmRuleRebackJob")
+    public void execute() throws Exception {
+        rebackKuaiShou();
+        rebackByteDance();
+    }
+
+    private void rebackKuaiShou() {
+        Map<String, Object> map = new HashMap<>();
+        //0状态为启动
+        map.put("message", "success");
+        map.put("value_time", DateUtils.getLastDay(DateUtils.formatDate(new Date()), 1));
+        map.put("indicator_code", "TIME");
+        map.put("media_type", "快手");
+        List<AlarmRuleOperationRecord> ruleAccountTemplates = ruleOperationRecordMapper.selectByMap(map);
+        if (!Check.isNull(ruleAccountTemplates)) {
+            ruleAccountTemplates.forEach(operationRecord -> {
+                CtopOauthToken token = tokenService.getTokenByAccountId(operationRecord.getAccountId());
+                executorKSService.submit(new Runnable() {
+                    @Override
+                    public void run() {
+                        JSONObject unitJson = new JSONObject();
+                        unitJson.put("advertiser_id", operationRecord.getAccountId());
+                        unitJson.put("unit_id", operationRecord.getUnitId());
+                        unitJson.put("schedule_time", operationRecord.getBeforeValue());
+                        JSONObject jsonObject = kuaiShouUpdateService.updateUnit(token.getAccessToken(), unitJson);
+                        Integer code = jsonObject.getInteger("code");
+                        String message = "success";
+                        if (code == 0) {
+                            kuaiShouGroupService.getGroupByUnitId(token.getAccessToken(), operationRecord.getAccountId(), operationRecord.getUnitId());
+                        }
+                    }
+                });
+            });
+        }
+    }
+
+    private void rebackByteDance() {
+        Map<String, Object> map = new HashMap<>();
+        //0状态为启动
+        map.put("message", "success");
+        map.put("value_time", DateUtils.getLastDay(DateUtils.formatDate(new Date()), 1));
+        map.put("indicator_code", "TIME");
+        map.put("media_type", "头条");
+        List<AlarmRuleOperationRecord> ruleAccountTemplates = ruleOperationRecordMapper.selectByMap(map);
+        if (!Check.isNull(ruleAccountTemplates)) {
+            ruleAccountTemplates.forEach(operationRecord -> {
+                CtopOauthToken token = tokenService.getTokenByAccountId(operationRecord.getAccountId());
+                executorTTService.submit(new Runnable() {
+                    @Override
+                    public void run() {
+                        JSONObject unitJson = new JSONObject();
+                        String code = externalLinkService.editBytedancePlanCpaBidOrBudget(operationRecord.getAccountId(), operationRecord.getPlanId().toString(), null, operationRecord.getBeforeValue(), null);
+                    }
+                });
+            });
+        }
+    }
+}

+ 0 - 2
module-kuaishou/src/main/java/cn/com/ctop/kuaishou/modules/batch/service/impl/KuaiShouUpdateServiceImpl.java

@@ -608,8 +608,6 @@ public class KuaiShouUpdateServiceImpl implements IKuaiShouUpdateService {
             Map<String, String> headers = new HashMap<>();
             headers.put("Access-Token", accessToken);
             headers.put("Content-Type", "application/json");
-            System.err.println("修改广告组入参:" + unitJson);
-            System.err.println("修改广告组head:" + headers);
             String result = HttpUtils.kuaiShouhttpPostRequest(url, unitJson.toJSONString(), headers);
             JSONObject resultJson = JSONObject.parseObject(result);
             log.info("修改广告组返回信息:{}", resultJson);