Explorar o código

Merge remote-tracking branch 'origin/master_rule_engine' into master_rule_engine

yumeng %!s(int64=4) %!d(string=hai) anos
pai
achega
f844f48676

+ 47 - 28
jeecg-boot-module-system/src/test/java/org/jeecg/SampleTest.java

@@ -1,10 +1,15 @@
 package org.jeecg;
 
+import cn.com.ctop.alarm.modules.service.IRuleGroupService;
 import cn.com.ctop.common.module.entity.BindAccountLogin;
 import cn.com.ctop.common.module.entity.CtopOauthToken;
 import cn.com.ctop.common.module.entity.UserAllocation;
 import cn.com.ctop.common.module.message.handle.impl.EmailSendMsgHandle;
-import cn.com.ctop.common.module.service.*;
+import cn.com.ctop.common.module.service.IBindAccountLoginService;
+import cn.com.ctop.common.module.service.ICtopOauthTokenService;
+import cn.com.ctop.common.module.service.IUReportExportService;
+import cn.com.ctop.common.module.service.IUReportService;
+import cn.com.ctop.common.module.service.IUserAllocationService;
 import cn.com.ctop.common.module.utils.CtopAdConstant;
 import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouDailyReportTaskService;
 import cn.com.ctop.kuaishou.modules.batch.service.IKuaiShouHistoryReportTaskService;
@@ -119,10 +124,10 @@ public class SampleTest {
     }
 
     @Test
-    public void testLoadRulePlanData(){
+    public void testLoadRulePlanData() {
         List<CtopOauthToken> tokens = tokenService.selectToutiaoToken();
-        for(CtopOauthToken token :tokens){
-            reportService.getAdvertiserPlanRuleData(token,new Date(),new Date(),CtopAdConstant.BYTEDANCE_REPORT_TYPE_DAILY);
+        for (CtopOauthToken token : tokens) {
+            reportService.getAdvertiserPlanRuleData(token, new Date(), new Date(), CtopAdConstant.BYTEDANCE_REPORT_TYPE_DAILY);
         }
     }
 
@@ -131,20 +136,20 @@ public class SampleTest {
 
     @Test
     public void testLoadBytedanceData() {
-        List<UserAllocation>allocations = allocationService.getByParams(273L,null,0);
-        if(null!=allocations&&!allocations.isEmpty()){
-            for(UserAllocation allocation:allocations){
+        List<UserAllocation> allocations = allocationService.getByParams(273L, null, 0);
+        if (null != allocations && !allocations.isEmpty()) {
+            for (UserAllocation allocation : allocations) {
                 CtopOauthToken token = tokenService.getTokenByAccountId(allocation.getAccountId());
                 String startDate = "2020-11-05";
                 String endDate = "2020-11-09";
-                reportService.getAdvertiserPlanReport(token, DateUtils.parseDate(startDate,"yyyy-MM-dd"), DateUtils.parseDate(endDate,"yyyy-MM-dd"), CtopAdConstant.BYTEDANCE_REPORT_TYPE_DAILY);
+                reportService.getAdvertiserPlanReport(token, DateUtils.parseDate(startDate, "yyyy-MM-dd"), DateUtils.parseDate(endDate, "yyyy-MM-dd"), CtopAdConstant.BYTEDANCE_REPORT_TYPE_DAILY);
             }
         }
         System.out.println("任务结束");
     }
 
     @Test
-    public void loadBytedancePlanData(){
+    public void loadBytedancePlanData() {
         CtopOauthToken token = tokenService.getTokenByAccountId(100198696723L);
 //        advertiserDataService.getAdvertiserPlan(token, "", null, null);
         Date getDate = DateUtils.addDay(new Date(), 0);
@@ -153,15 +158,16 @@ public class SampleTest {
 
     @Autowired
     private IBytedanceFundDailyService bytedanceFundDailyService;
+
     @Test
     public void loadFoudData() {
         List<CtopOauthToken> tokens = tokenService.selectToutiaoToken();
         for (CtopOauthToken token : tokens) {
-            System.out.println(token.getAccountId()+"############################");
-            for(int i=20;i<130;i++){
-                Date date = DateUtils.addDay(new Date(),-i);
-                bytedanceFundDailyService.loadFundDataByPage(token, DateUtils.formatDate(date), DateUtils.formatDate(date),1);
-                System.out.println(i+"############################");
+            System.out.println(token.getAccountId() + "############################");
+            for (int i = 20; i < 130; i++) {
+                Date date = DateUtils.addDay(new Date(), -i);
+                bytedanceFundDailyService.loadFundDataByPage(token, DateUtils.formatDate(date), DateUtils.formatDate(date), 1);
+                System.out.println(i + "############################");
             }
         }
     }
@@ -173,9 +179,9 @@ public class SampleTest {
      * 测试获取快手图片消耗数据任务
      */
     @Test
-    public void loadKuaishouImageTask(){
+    public void loadKuaishouImageTask() {
         List<CtopOauthToken> tokens = tokenService.selectKuaiShouToken();
-        for(int i=1;i<130;i++) {
+        for (int i = 1; i < 130; i++) {
             Date getDate = DateUtils.addDay(new Date(), -i);
             String getDateStr = DateUtils.formatDate(getDate);
             tokens.forEach(token -> reportTaskService.createTask(token.getAccountId(), token.getAccessToken(), getDateStr, getDateStr, CtopAdConstant.KUAISHOU_LOAD_JOB_TYPE_DAILY));
@@ -184,14 +190,15 @@ public class SampleTest {
 
     @Autowired
     private IKuaiShouDailyReportTaskService dailyReportTaskService;
+
     /**
      * 测试获取快手图片消耗数据入库
      */
     @Test
-    public void loadKuaishouImageTaskFile(){
+    public void loadKuaishouImageTaskFile() {
         String nowDate = DateUtils.getDate("yyyy-MM-dd");
         List<CtopOauthToken> tokens = tokenService.selectKuaiShouToken();
-        for(int i=1;i<15;i++){
+        for (int i = 1; i < 15; i++) {
             String statDate = getAnotherDay("yyyy-MM-dd", nowDate, -i);
             tokens.forEach(token -> dailyReportTaskService.getTaskList(token.getAccountId(), token.getAccessToken(), statDate));
         }
@@ -199,15 +206,15 @@ public class SampleTest {
     }
 
     @Test
-    public void testLoadBytedanceImageData(){
-        List<CtopOauthToken>tokens = tokenService.selectToutiaoToken();
+    public void testLoadBytedanceImageData() {
+        List<CtopOauthToken> tokens = tokenService.selectToutiaoToken();
         countDownLatch = new CountDownLatch(tokens.size());
         executorService = Executors.newFixedThreadPool(8);
-        tokens.forEach(token->executorService.submit(()->{
+        tokens.forEach(token -> executorService.submit(() -> {
             try {
                 advertiserDataService.getMaterialList(token);
-            }catch (Exception e){
-            }finally {
+            } catch (Exception e) {
+            } finally {
                 countDownLatch.countDown();
             }
         }));
@@ -219,10 +226,12 @@ public class SampleTest {
         System.out.println("素材数据获取完成");
 
     }
+
     @Autowired
     private KuaishouAgentAccountMapper kuaishouAgentAccountMapper;
     @Autowired
     private IKuaishouReportDailyAgentService kuaishouReportDailyAgentService;
+
     @Test
     public void loadKuaishouAgentData() throws JsonProcessingException {
         kuaishouReportDailyAgentService.loginAgent();
@@ -239,6 +248,7 @@ public class SampleTest {
             e.printStackTrace();
         }
     }
+
     @Autowired
     private IKuaishouInterfaceService kuaishouInterfaceService;
 
@@ -261,10 +271,10 @@ public class SampleTest {
     IUReportService uReportService;
 
     @Test
-    public void loadBytedanceData(){
+    public void loadBytedanceData() {
         List<CtopOauthToken> tokens = tokenService.selectToutiaoToken();
-        for (int i=0;i<tokens.size();i++) {
-            for(int j=0;j<4;j++){
+        for (int i = 0; i < tokens.size(); i++) {
+            for (int j = 0; j < 4; j++) {
                 String getDate = DateUtils.formatDate(DateUtils.addDay(new Date(), -j));
                 bytedanceReportService.bytedanceVideoMaterialReport(tokens.get(i), getDate, getDate);
             }
@@ -273,9 +283,10 @@ public class SampleTest {
 
     @Autowired
     private IBytedanceReportService bytedanceReportService;
+
     @Test
-    public void loadMatData(){
-        List<UserAllocation> allocations = allocationService.getByParams(289L,null,0);
+    public void loadMatData() {
+        List<UserAllocation> allocations = allocationService.getByParams(289L, null, 0);
         countDownLatch = new CountDownLatch(allocations.size());
         executorService = Executors.newFixedThreadPool(2);
         allocations.forEach(allocation -> {
@@ -301,4 +312,12 @@ public class SampleTest {
         }
         XxlJobLogger.log("物料数据同步完成");
     }
+
+    @Autowired
+    private IRuleGroupService ruleGroupService;
+
+    @Test
+    public void checkRules() {
+        ruleGroupService.checkRules();
+    }
 }

+ 128 - 59
module-alarm/src/main/java/cn/com/ctop/alarm/modules/constant/MatchLogic.java

@@ -1,6 +1,6 @@
 package cn.com.ctop.alarm.modules.constant;
 
-import cn.com.ctop.alarm.modules.entity.AlarmEventRule;
+import cn.com.ctop.alarm.modules.entity.RuleGroup;
 import cn.com.ctop.common.module.utils.Check;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -30,55 +30,64 @@ public class MatchLogic {
      * @author ZHAOXA
      */
     public static boolean matchCondition(String type, String condition, String threshold, String value) {
-        if ("number".equals(type)) {
-            BigDecimal bigThr = new BigDecimal(threshold);
-            BigDecimal bigVal = new BigDecimal(value);
-            switch (condition) {
-                case "equal":
-                    return bigVal.compareTo(bigThr) == 0;
-                case "not_equal":
-                    return bigVal.compareTo(bigThr) != 0;
-                case "greater":
-                    return bigVal.compareTo(bigThr) > 0;
-                case "less":
-                    return bigVal.compareTo(bigThr) < 0;
-                case "greater_equal":
-                    return bigVal.compareTo(bigThr) >= 0;
-                case "less_equal":
-                    return bigVal.compareTo(bigThr) <= 0;
-                default:
-                    log.warn("关系不匹配");
-                    break;
-            }
-        } else if ("string".equals(type)) {
-            switch (condition) {
-                case "equal":
-                    return value.equals(threshold);
-                case "not_equal":
-                    return !value.equals(threshold);
-                case "contain":
-                    return !value.contains(threshold);
-                case "no_contain":
-                    return !value.contains(threshold);
-                default:
-                    log.warn("关系不匹配");
-                    break;
-            }
-        } else {
-            List<String> strings = strToList(threshold);
-            if ("contain".equals(condition)) {
-                for (String string : strings) {
-                    if (value.contains(string)) {
-                        return true;
-                    }
+        try {
+            if ("number".equals(type)) {
+                BigDecimal bigThr = new BigDecimal(threshold);
+                BigDecimal bigVal = new BigDecimal(value);
+                switch (condition) {
+                    case "equal":
+                        return bigVal.compareTo(bigThr) == 0;
+                    case "not_equal":
+                        return bigVal.compareTo(bigThr) != 0;
+                    case "greater":
+                        return bigVal.compareTo(bigThr) > 0;
+                    case "less":
+                        return bigVal.compareTo(bigThr) < 0;
+                    case "greater_equal":
+                        return bigVal.compareTo(bigThr) >= 0;
+                    case "less_equal":
+                        return bigVal.compareTo(bigThr) <= 0;
+                    default:
+                        log.warn("关系不匹配");
+                        break;
+                }
+            } else if ("string".equals(type)) {
+                switch (condition) {
+                    case "equal":
+                        return value.equals(threshold);
+                    case "not_equal":
+                        return !value.equals(threshold);
+                    case "contain":
+                        return !value.contains(threshold);
+                    case "no_contain":
+                        return !value.contains(threshold);
+                    default:
+                        log.warn("关系不匹配");
+                        break;
                 }
             } else {
-                for (String string : strings) {
-                    if (!value.contains(string)) {
-                        return true;
+                List<String> thresholdArr = strToList(threshold);
+                List<String> values = strToList(value);
+                if ("contain".equals(condition)) {
+                    for (String t : thresholdArr) {
+                        for (String v : values) {
+                            if (v.contains(t)) {
+                                return true;
+                            }
+                        }
+                    }
+                } else {
+                    for (String t : thresholdArr) {
+                        for (String v : values) {
+                            if (!v.contains(t)) {
+                                return true;
+                            }
+                        }
                     }
                 }
             }
+        } catch (Exception e) {
+            log.error("条件匹配", e);
         }
         return false;
     }
@@ -86,26 +95,23 @@ public class MatchLogic {
     /**
      * 整理发送的消息
      */
-    public static String getMsg(String level, String detail, JSONObject cost, AlarmEventRule rule) {
+    public static String getMsg(RuleGroup ruleGroup, JSONObject user, Long accountId, Long planId, Long creativeId, boolean isPause) {
         StringBuffer header = new StringBuffer();
-        header.append(rule.getMetricValueName()).append("预警").append("<br/>").
-                append("您的账户:").append(cost.getString("accountId")).append(",授权名称为:").append(rule.getAccountName()).append("<br/>");
-        if ("ACCOUNT".equals(level)) {
-            header.append(detail);
-        } else if ("CAMPAIGN".equals(level)) {
-            header.append("计划ID:").append(rule.getCampaignId()).append(",计划名称为:").append(rule.getCampaignName()).append("<br/>").append(detail);
-        } else {
-            header.append("计划ID:").append(rule.getCampaignId()).append(",计划名称为:").append(rule.getCampaignName()).append("<br/>")
-                    .append("组ID:").append(rule.getUnitId()).append(",组名称为:").append(rule.getUnitName()).append("<br/>").append(detail);
+        header.append(ruleGroup.getGroupName()).append("预警").append("<br/>").
+                append("预警账户:").append(accountId).append("<br/>");
+        if (!Check.isNull(planId) && !Check.isNull(creativeId)) {
+            header.append("预警计划:").append(planId).append("<br/>").append("预警创意:").append(creativeId).append("<br/>");
+        } else if (!Check.isNull(creativeId) && Check.isNull(creativeId)) {
+            header.append("预警计划:").append(planId).append("<br/>");
+        } else if (!Check.isNull(creativeId)) {
+            header.append("预警创意:").append(creativeId).append("<br/>");
         }
-        String msg = null;
-        if ("PAUSE".equals(rule.getProcessMethod())) {
+        if (isPause) {
             header.append("现已被关停,请您及时查看并调整!");
         } else {
             header.append("请您及时查看并调整!");
-            msg = header.toString();
         }
-        return msg;
+        return header.toString();
     }
 
     //拆分逗号拼接数据
@@ -127,4 +133,67 @@ public class MatchLogic {
         }
         return ids;
     }
+
+    public static JSONArray getSendData(JSONArray accountDatas, JSONArray planDatas, JSONArray creativeDatas, JSONArray targetDatas) {
+        JSONArray sendData = new JSONArray();
+        if (!Check.isNull(accountDatas) && Check.isNull(planDatas) && Check.isNull(creativeDatas) && Check.isNull(targetDatas)) {
+            sendData = accountDatas;
+        } else {
+            if (!Check.isNull(planDatas) && Check.isNull(creativeDatas) && Check.isNull(targetDatas)) {
+                sendData = planDatas;
+            } else if (!Check.isNull(creativeDatas) && Check.isNull(planDatas) && Check.isNull(targetDatas)) {
+                sendData = creativeDatas;
+            } else if (!Check.isNull(targetDatas) && Check.isNull(planDatas) && Check.isNull(creativeDatas)) {
+                sendData = targetDatas;
+            } else if (!Check.isNull(planDatas) && !Check.isNull(creativeDatas) && !Check.isNull(targetDatas)) {
+                for (int i = 0; i < planDatas.size(); i++) {
+                    Long pplanId = planDatas.getJSONObject(i).getLong("planId");
+                    for (int k = 0; k < targetDatas.size(); k++) {
+                        Long tplanId = targetDatas.getJSONObject(k).getLong("planId");
+                        for (int j = 0; j < creativeDatas.size(); j++) {
+                            Long cplanId = creativeDatas.getJSONObject(j).getLong("planId");
+                            if (cplanId == tplanId && cplanId == pplanId) {
+                                sendData.add(creativeDatas.getJSONObject(j));
+                            }
+                        }
+                    }
+                }
+            } else if (!Check.isNull(planDatas) && !Check.isNull(targetDatas) && Check.isNull(creativeDatas)) {
+                for (int i = 0; i < planDatas.size(); i++) {
+                    Long pplanId = planDatas.getJSONObject(i).getLong("planId");
+                    for (int k = 0; k < targetDatas.size(); k++) {
+                        Long tplanId = targetDatas.getJSONObject(k).getLong("planId");
+                        if (tplanId == pplanId) {
+                            sendData.add(targetDatas.getJSONObject(k));
+                        }
+                    }
+                }
+            } else if (!Check.isNull(planDatas) && Check.isNull(targetDatas) && !Check.isNull(creativeDatas)) {
+                for (int i = 0; i < planDatas.size(); i++) {
+                    Long pplanId = planDatas.getJSONObject(i).getLong("planId");
+                    for (int k = 0; k < creativeDatas.size(); k++) {
+                        Long cplanId = creativeDatas.getJSONObject(k).getLong("planId");
+                        if (cplanId == pplanId) {
+                            sendData.add(creativeDatas.getJSONObject(k));
+                        }
+                    }
+                }
+            } else if (Check.isNull(planDatas) && !Check.isNull(targetDatas) && !Check.isNull(creativeDatas)) {
+                for (int i = 0; i < targetDatas.size(); i++) {
+                    Long tplanId = targetDatas.getJSONObject(i).getLong("planId");
+                    for (int k = 0; k < creativeDatas.size(); k++) {
+                        Long cplanId = creativeDatas.getJSONObject(k).getLong("planId");
+                        if (cplanId == tplanId) {
+                            sendData.add(creativeDatas.getJSONObject(k));
+                        }
+                    }
+                }
+            }
+        }
+        return sendData;
+
+
+    }
+
+
 }

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

@@ -6,6 +6,7 @@ import cn.com.ctop.alarm.modules.mapper.*;
 import cn.com.ctop.alarm.modules.service.IRuleAccountTemplateService;
 import cn.com.ctop.alarm.modules.service.IRuleGroupService;
 import cn.com.ctop.common.module.entity.CtopOauthToken;
+import cn.com.ctop.common.module.mapper.SysUserMapper;
 import cn.com.ctop.common.module.service.ICtopOauthTokenService;
 import cn.com.ctop.common.module.service.IRuleDataAccountService;
 import cn.com.ctop.common.module.service.ISendMessageService;
@@ -20,7 +21,6 @@ import lombok.extern.slf4j.Slf4j;
 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;
@@ -49,6 +49,8 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
     @Autowired
     private RuleTemplateMapper ruleTemplateMapper;
     @Autowired
+    private SysUserMapper sysUserMapper;
+    @Autowired
     private IRuleGroupService ruleGroupService;
     @Autowired
     private IRuleAccountTemplateService ruleAccountTemplateService;
@@ -60,6 +62,7 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
     private ICtopOauthTokenService oauthTokenService;
     @Autowired
     private IRuleDataAccountService ruleDataAccountService;
+    private JSONObject userObj = null;
 
     @Override
     public void checkRules() {
@@ -98,14 +101,19 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
      * @author ZHAOXA
      */
     private void matchAlarmRules(List<RuleGroup> ruleGroups, JSONObject thresholdObj, JSONObject indicators, Long accountId) {
+        userObj = new JSONObject();
         //查询匹配数据
         JSONObject matchData = getRuleData(accountId);
         if (Check.isNull(matchData)) {
             log.warn("查询匹配数据失败");
             return;
         }
+        log.info("已获取账户({})的数据,开始匹配规则", accountId);
         for (RuleGroup ruleGroup : ruleGroups) {
             List<RuleBase> ruleBaseList = ruleGroup.getRuleBaseList();
+            if (Check.isNull(ruleBaseList)) {
+                continue;
+            }
             boolean isBase = "base".equals(ruleGroup.getRuleType());
             //匹配单规则
             if (isBase) {
@@ -116,6 +124,7 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                 String threshold = thresholdObj.getString(ruleBase.getId().toString());
                 //阈值为空时,或者阈值为“unlimited”(不限),不执行该规则
                 if (Check.isNull(threshold) || "unlimited".equals(threshold)) {
+                    log.warn("阈值为空/不限,该规则({})不执行", ruleBase.getId());
                     continue;
                 }
                 //维度数据
@@ -125,64 +134,93 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
                         JSONObject obj = dimensionData.getJSONObject(i);
                         String value = obj.getString(ruleBase.getIndicatorCode());
                         if (MatchLogic.matchCondition(indicator.getString("dataType"), ruleBase.getRuleCondition(), threshold, value)) {
-                            sendMsg(ruleGroup);
+                            sendMsg(ruleGroup, obj);
                         }
                     }
                 }
                 //匹配组合规则
             } else {
-                // 是否为and全部匹配
-                boolean isAllTrue = "and".equals(ruleGroup.getRuleRelationship());
                 boolean flag = false;
-                List<JSONObject> targetDatas = new ArrayList<>();
-                List<JSONObject> planDatas = new ArrayList<>();
-                List<JSONObject> creativeDatas = new ArrayList<>();
-                List<JSONObject> lostCostDatas = new ArrayList<>();
+                //符合规则的数据集
+                JSONArray targetDatas = new JSONArray();
+                JSONArray planDatas = new JSONArray();
+                JSONArray creativeDatas = new JSONArray();
+                JSONArray accountDatas = new JSONArray();
                 for (RuleBase ruleBase : ruleBaseList) {
                     //指标对象
                     JSONObject indicator = indicators.getJSONObject(ruleBase.getIndicatorCode());
+                    //阈值类型
+                    String dataType = indicator.getString("dataType");
                     //指标阈值
                     String threshold = thresholdObj.getString(ruleBase.getId().toString());
                     //阈值为空时,或者阈值为“unlimited”(不限),不执行该规则
                     if (Check.isNull(threshold) || "unlimited".equals(threshold)) {
                         continue;
                     }
-                    //and关系,全部匹配规则
-                    if (isAllTrue) {
-                        JSONArray dimensionData = matchData.getJSONArray(ruleBase.getRuleDimension());
-                        if ("account".equals(ruleBase.getRuleDimension())) {
-                            //and关系时如果账户级不匹配则跳出本规则。
-                            String value = dimensionData.getJSONObject(0).getString(ruleBase.getIndicatorCode());
-                            if (!MatchLogic.matchCondition(indicator.getString("dataType"), ruleBase.getRuleCondition(), threshold, value)) {
-                                break;
-                            }
+                    JSONArray dimensionData = matchData.getJSONArray(ruleBase.getRuleDimension());
+                    //账户维度数据
+                    if ("account".equals(ruleBase.getRuleDimension())) {
+                        JSONObject accountEntity = dimensionData.getJSONObject(0);
+                        if (MatchLogic.matchCondition(dataType, ruleBase.getRuleCondition(), threshold, accountEntity.getString(ruleBase.getIndicatorCode()))) {
+                            accountDatas.add(accountEntity);
                         } else {
-                            for (int i = 0; i < dimensionData.size(); i++) {
-                                JSONObject obj = dimensionData.getJSONObject(i);
-                                String value = obj.getString(ruleBase.getIndicatorCode());
-                                if (MatchLogic.matchCondition(indicator.getString("dataType"), ruleBase.getRuleCondition(), threshold, value)) {
-//                                    okData.add(obj);
-                                }
-                            }
-                        }
-
-                    } else {
-                        //or关系,任一阈值匹配,则跳出循环
-//                        flag = MatchLogic.matchCondition(indicator.getString("dataType"), ruleBase.getRuleCondition(), threshold, value);
-                        if (flag) {
+                            log.warn("判断规则组({}),账户规则不符合", ruleGroup.getId());
                             break;
                         }
+                    } else if ("plan".equals(ruleBase.getRuleDimension())) {
+                        planDatas = getOKData(planDatas, dimensionData, ruleBase, dataType, threshold);
+                    } else if ("creative".equals(ruleBase.getRuleDimension())) {
+                        creativeDatas = getOKData(creativeDatas, dimensionData, ruleBase, dataType, threshold);
+                    } else if ("target".equals(ruleBase.getRuleDimension())) {
+                        targetDatas = getOKData(targetDatas, dimensionData, ruleBase, dataType, threshold);
                     }
+
                 }
-                //执行发送
-                if (flag) {
-                    sendMsg(ruleGroup);
+                //获取达标可发送的数据
+                JSONArray sendData = MatchLogic.getSendData(accountDatas, planDatas, creativeDatas, targetDatas);
+                if (!Check.isNull(sendData)) {
+                    //执行发送
+                    for (int i = 0; i < sendData.size(); i++) {
+                        sendMsg(ruleGroup, sendData.getJSONObject(i));
+                    }
                 }
             }
         }
     }
 
     /**
+     * @param ruleDatas     达标数据集
+     * @param dimensionData 匹配数据
+     * @param ruleBase      规则
+     * @param type          数据类型
+     * @param threshold     阈值
+     * @return void
+     * @throws
+     * @author ZHAOXA
+     */
+    private JSONArray getOKData(JSONArray ruleDatas, JSONArray dimensionData, RuleBase ruleBase, String type, String threshold) {
+        if (ruleDatas.size() > 0) {
+            JSONArray okData = new JSONArray();
+            for (int i = 0; i < ruleDatas.size(); i++) {
+                JSONObject targetEntity = dimensionData.getJSONObject(i);
+                String value = targetEntity.getString(ruleBase.getIndicatorCode());
+                if (MatchLogic.matchCondition(type, ruleBase.getRuleCondition(), threshold, value)) {
+                    okData.add(targetEntity);
+                }
+            }
+            return okData;
+        }
+        for (int i = 0; i < dimensionData.size(); i++) {
+            JSONObject targetEntity = dimensionData.getJSONObject(i);
+            String value = targetEntity.getString(ruleBase.getIndicatorCode());
+            if (MatchLogic.matchCondition(type, ruleBase.getRuleCondition(), threshold, value)) {
+                ruleDatas.add(targetEntity);
+            }
+        }
+        return ruleDatas;
+    }
+
+    /**
      * 发送消息
      *
      * @param
@@ -190,26 +228,38 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
      * @throws
      * @author ZHAOXA
      */
-    private void sendMsg(RuleGroup ruleGroup) {
+    private void sendMsg(RuleGroup ruleGroup, JSONObject obj) {
+        Long creativeId = obj.getLong("creativeId");
+        Long planId = obj.getLong("planId");
+        Long accountId = obj.getLong("accountId");
+        JSONObject user = getUserByAccountId(accountId);
         boolean isPause = "PAUSE".equals(ruleGroup.getOperate());
         if (isPause) {
-            //关停操作 TODO
-//                    shutDown();
+            if (shutDown(accountId, planId, creativeId, user.getString("id"))) {
+                isPause = true;
+            }
         }
-        //TODO
-        String msg = MatchLogic.getMsg(null, null, null, null);
+        String msg = MatchLogic.getMsg(ruleGroup, user, accountId, planId, creativeId, isPause);
         String sendType = ruleGroup.getSendType();
         if ("SMS".equals(sendType)) {
 
-        } else if ("WeChat".equals(sendType)) {
-            sendMessageService.sendMessage("", msg);
         } else if ("EMAIL".equals(sendType)) {
 
         } else if ("TEL".equals(sendType)) {
 
         } else {
+            sendMessageService.sendMessage(user.getString("id"), msg);
+        }
+    }
 
+    private JSONObject getUserByAccountId(Long accountId) {
+        JSONObject obj = userObj.getJSONObject(accountId.toString());
+        if (Check.isNull(obj)) {
+            JSONObject user = sysUserMapper.selectUserByAccount(accountId);
+            obj.put(accountId.toString(), user);
+            return user;
         }
+        return obj;
     }
 
     /**
@@ -220,16 +270,16 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
      * @throws
      * @author ZHAOXA
      */
-    private boolean shutDown(AlarmEventRule rule, String level) {
-        CtopOauthToken token = oauthTokenService.getTokenByAccountId(rule.getAccountId());
+    private boolean shutDown(Long accountId, Long planId, Long creativeId, String userId) {
+        CtopOauthToken token = oauthTokenService.getTokenByAccountId(accountId);
         Map<String, Object> updateMap = new HashMap<>();
         if (!Check.isNull(token)) {
-            if ("CAMPAIGN".equals(level)) {
-                updateMap = kuaiShouUpdateService.updateCampaignStatus(token.getAccessToken(), rule.getAccountId(), rule.getCampaignId(), NoEn.NO2.valueInt(), rule.getUserId());
-                log.info("---------规则关停快手计划:{}", rule.getCampaignId());
-            } else if ("UNIT".equals(level)) {
-                updateMap = kuaiShouUpdateService.updateUnitStatus(token.getAccessToken(), rule.getAccountId(), rule.getUnitId(), NoEn.NO2.valueInt(), rule.getUserId());
-                log.info("---------规则关停快手组:{}", rule.getUnitId());
+            if (!Check.isNull(creativeId)) {
+                updateMap = kuaiShouUpdateService.updateCreativeStatus(token.getAccessToken(), accountId, creativeId, NoEn.NO2.valueInt(), userId);
+                log.info("---------规则关停创意:{}", creativeId);
+            } else if (!Check.isNull(planId) && Check.isNull(creativeId)) {
+                updateMap = kuaiShouUpdateService.updateCampaignStatus(token.getAccessToken(), accountId, planId, NoEn.NO2.valueInt(), userId);
+                log.info("---------规则关停计划:{}", planId);
             }
         }
         return (boolean) updateMap.get("success");
@@ -273,24 +323,23 @@ public class RuleGroupServiceImpl extends ServiceImpl<RuleGroupMapper, RuleGroup
         Map<Long, List<RuleGroup>> map = new HashMap<>();
         List<RuleTemplate> ruleTemplates = ruleTemplateMapper.selectByMap(null);
         ruleTemplates.forEach(tem -> {
-            List<String> groupIds = MatchLogic.strToList(tem.getGroupIds());
-            if (!Check.isNull(groupIds)) {
-                List<RuleGroup> ruleGroups = ruleGroupMapper.selectBatchIds(groupIds);
-                for (RuleGroup group : ruleGroups) {
-                    List<String> ruleIds = MatchLogic.strToList(group.getRuleIds());
-                    if (!Check.isNull(ruleIds)) {
-                        group.setRuleBaseList(ruleBaseMapper.selectBatchIds(ruleIds));
-                    }
-                }
-                map.put(tem.getId(), ruleGroups);
+            QueryWrapper<RuleGroup> groupWrapper = new QueryWrapper<>();
+            groupWrapper.eq("template_id", tem.getId());
+            List<RuleGroup> ruleGroups = ruleGroupMapper.selectList(groupWrapper);
+            for (RuleGroup group : ruleGroups) {
+                QueryWrapper<RuleBase> baseWrapper = new QueryWrapper<>();
+                baseWrapper.eq("group_id", group.getId());
+                baseWrapper.orderByDesc("is_unlimited");
+                group.setRuleBaseList(ruleBaseMapper.selectList(baseWrapper));
             }
+            map.put(tem.getId(), ruleGroups);
         });
         return null;
     }
 
 
     /**
-     * TODO 获取指标数据
+     * 获取指标数据
      *
      * @param
      * @return java.util.List<org.json.JSONObject>

+ 112 - 96
module-common/src/main/java/cn/com/ctop/common/module/mapper/SysUserMapper.java

@@ -4,6 +4,7 @@ import cn.com.ctop.common.module.entity.SysUser;
 import cn.com.ctop.common.module.model.SysUserSysDepartModel;
 import cn.com.ctop.common.module.vo.SysUserDepVo;
 import cn.com.ctop.common.module.vo.SysUserVo;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -23,76 +24,85 @@ import java.util.Map;
  * @since 2018-12-20
  */
 public interface SysUserMapper extends BaseMapper<SysUser> {
-	List<SysUser> selectAllUser();
-	/**
-	  * 通过用户账号查询用户信息
-	 * @param username
-	 * @return
-	 */
-	 SysUser getUserByName(@Param("username") String username);
-
-	/**
-	 *  根据部门Id查询用户信息
-	 * @param page
-	 * @param departId
-	 * @return
-	 */
-	IPage<SysUser> getUserByDepId(Page page, @Param("departId") String departId, @Param("username") String username);
-
-	/**
-	 *  根据用户Ids,查询用户所属部门名称信息
-	 * @param userIds
-	 * @return
-	 */
-	List<SysUserDepVo> getDepNamesByUserIds(@Param("userIds") List<String> userIds);
-
-	/**
-	 *  根据部门Ids,查询部门下用户信息
-	 * @param page
-	 * @param departIds
-	 * @return
-	 */
-	IPage<SysUser> getUserByDepIds(Page page, @Param("departIds") List<String> departIds, @Param("username") String username);
-
-	/**
-	 * 根据角色Id查询用户信息
-	 * @param page
-	 * @param
-	 * @return
-	 */
-	IPage<SysUser> getUserByRoleId(Page page, @Param("roleId") String roleId, @Param("username") String username);
-
-	/**
-	 * 根据用户名设置部门ID
-	 * @param username
-	 * @param orgCode
-	 */
-	void updateUserDepart(@Param("username") String username, @Param("orgCode") String orgCode);
-
-	/**
-	 * 根据手机号查询用户信息
-	 * @param phone
-	 * @return
-	 */
-	SysUser getUserByPhone(@Param("phone") String phone);
-
-
-	/**
-	 * 根据邮箱查询用户信息
-	 * @param email
-	 * @return
-	 */
-	SysUser getUserByEmail(@Param("email") String email);
-
-	/**
-	 * 根据 orgCode 查询用户,包括子部门下的用户
-	 *
-	 * @param page 分页对象, xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
-	 * @param orgCode
-	 * @param userParams 用户查询条件,可为空
-	 * @return
-	 */
-	List<SysUserSysDepartModel> getUserByOrgCode(IPage page, @Param("orgCode") String orgCode, @Param("userParams") SysUser userParams);
+    List<SysUser> selectAllUser();
+
+    /**
+     * 通过用户账号查询用户信息
+     *
+     * @param username
+     * @return
+     */
+    SysUser getUserByName(@Param("username") String username);
+
+    /**
+     * 根据部门Id查询用户信息
+     *
+     * @param page
+     * @param departId
+     * @return
+     */
+    IPage<SysUser> getUserByDepId(Page page, @Param("departId") String departId, @Param("username") String username);
+
+    /**
+     * 根据用户Ids,查询用户所属部门名称信息
+     *
+     * @param userIds
+     * @return
+     */
+    List<SysUserDepVo> getDepNamesByUserIds(@Param("userIds") List<String> userIds);
+
+    /**
+     * 根据部门Ids,查询部门下用户信息
+     *
+     * @param page
+     * @param departIds
+     * @return
+     */
+    IPage<SysUser> getUserByDepIds(Page page, @Param("departIds") List<String> departIds, @Param("username") String username);
+
+    /**
+     * 根据角色Id查询用户信息
+     *
+     * @param page
+     * @param
+     * @return
+     */
+    IPage<SysUser> getUserByRoleId(Page page, @Param("roleId") String roleId, @Param("username") String username);
+
+    /**
+     * 根据用户名设置部门ID
+     *
+     * @param username
+     * @param orgCode
+     */
+    void updateUserDepart(@Param("username") String username, @Param("orgCode") String orgCode);
+
+    /**
+     * 根据手机号查询用户信息
+     *
+     * @param phone
+     * @return
+     */
+    SysUser getUserByPhone(@Param("phone") String phone);
+
+
+    /**
+     * 根据邮箱查询用户信息
+     *
+     * @param email
+     * @return
+     */
+    SysUser getUserByEmail(@Param("email") String email);
+
+    /**
+     * 根据 orgCode 查询用户,包括子部门下的用户
+     *
+     * @param page       分页对象, xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
+     * @param orgCode
+     * @param userParams 用户查询条件,可为空
+     * @return
+     */
+    List<SysUserSysDepartModel> getUserByOrgCode(IPage page, @Param("orgCode") String orgCode, @Param("userParams") SysUser userParams);
 
 
     /**
@@ -109,46 +119,52 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
      * @Date 2019/12/13 16:10
      * @Description: 批量删除角色与用户关系
      */
-	void deleteBathRoleUserRelation(@Param("roleIdArray") String[] roleIdArray);
+    void deleteBathRoleUserRelation(@Param("roleIdArray") String[] roleIdArray);
 
     /**
      * @Author scott
      * @Date 2019/12/13 16:10
      * @Description: 批量删除角色与权限关系
      */
-	void deleteBathRolePermissionRelation(@Param("roleIdArray") String[] roleIdArray);
+    void deleteBathRolePermissionRelation(@Param("roleIdArray") String[] roleIdArray);
 
-	/**
-	 * 查询被逻辑删除的用户
-	 */
-	List<SysUser> selectLogicDeleted(@Param(Constants.WRAPPER) Wrapper<SysUser> wrapper);
+    /**
+     * 查询被逻辑删除的用户
+     */
+    List<SysUser> selectLogicDeleted(@Param(Constants.WRAPPER) Wrapper<SysUser> wrapper);
 
-	/**
-	 * 还原被逻辑删除的用户
-	 */
-	int revertLogicDeleted(@Param("userIds") String userIds, @Param("entity") SysUser entity);
+    /**
+     * 还原被逻辑删除的用户
+     */
+    int revertLogicDeleted(@Param("userIds") String userIds, @Param("entity") SysUser entity);
 
-	/**
-	 * 彻底删除被逻辑删除的用户
-	 */
-	int deleteLogicDeleted(@Param("userIds") String userIds);
+    /**
+     * 彻底删除被逻辑删除的用户
+     */
+    int deleteLogicDeleted(@Param("userIds") String userIds);
 
-    /** 更新空字符串为null【此写法有sql注入风险,禁止随便用】 */
+    /**
+     * 更新空字符串为null【此写法有sql注入风险,禁止随便用】
+     */
     int updateNullByEmptyString(@Param("fieldName") String fieldName);
 
-	/**
-	 *  根据部门Ids,查询部门下用户信息
-	 * @param departIds
-	 * @return
-	 */
-	List<SysUser> queryByDepIds(@Param("departIds") List<String> departIds, @Param("username") String username);
-	Map<String, Object> queryRoleCode(@Param("userId") String userId);
+    /**
+     * 根据部门Ids,查询部门下用户信息
+     *
+     * @param departIds
+     * @return
+     */
+    List<SysUser> queryByDepIds(@Param("departIds") List<String> departIds, @Param("username") String username);
+
+    Map<String, Object> queryRoleCode(@Param("userId") String userId);
+
+    List<SysUserVo> getAllUser(@Param("userName") String userName);
 
-	List<SysUserVo> getAllUser(@Param("userName") String userName);
+    List<SysUserVo> getUserListByCompany(@Param("companyId") String companyId, @Param("userName") String userName);
 
-	List<SysUserVo> getUserListByCompany(@Param("companyId") String companyId,@Param("userName") String userName);
+    List<SysUserVo> getAllSale();
 
-	List<SysUserVo> getAllSale();
+    List<SysUserVo> getAllSalesByCompanyId(@Param("companyId") String companyId);
 
-	List<SysUserVo> getAllSalesByCompanyId(@Param("companyId") String companyId);
+    JSONObject selectUserByAccount(@Param("accountId") Long accountId);
 }

+ 7 - 0
module-common/src/main/java/cn/com/ctop/common/module/mapper/xml/SysUserMapper.xml

@@ -242,4 +242,11 @@ SELECT
             and username != #{username}
         </if>
     </select>
+
+    <select id="selectUserByAccount" resultType="com.alibaba.fastjson.JSONObject">
+        SELECT *
+        FROM  sys_user t1
+        INNER JOIN  ctop_user_allocation t2 ON t1.id = t2.user_id
+        WHERE t2.account_id = #{accountId}
+    </select>
 </mapper>