예제 #1
0
 public static function check($manager_id)
 {
     global $mysqli;
     // print_r( self::$levels);
     // ЗАДАЧА
     // скрипт проверяет время прошедшее с момента последнего выполненого действия(status=done) или с момента первой
     // записи status=init и если время превышает лимит, передает даные обработчику раздающему предупрежедения и т.п.
     // также отслеживает были ли по истечению t количества времени выставленны новые планы после того как действия
     // получило статус done или была сделана запись со статусом init
     //
     // ЭТАПЫ
     //  1. Определяем клиентов по которым вообще нет записей ( чтобы затем внести по ним запись в таблицу со статусом init):
     //     получаем массив id всех клиентов относяшихся к менеджеру, затем делаем выборку по этому массиву (оператором IN)
     //     по каждому событию в отдельности, тем самым выясняя по каким событиям ведутся записи, сохраняем данные в многомерный
     //     с ключами равными именам отслеживаемых событий, затем сравниваем полученные подмассивы по array_diff - с массивом id
     //     всех клиентов менеджера в результате получаем многомерный массив id клентов по с разделением по событиям, по которым
     //     не ведутся записи
     //     -- предпринимаем НЕОБХОДИМЫЕ ДЕЙСТВИЯ
     //
     //  2. Определяем события по которым будем показывать оповещения:
     //     нам надо сравнить период с момента последнего выполненого события данного типа или момента создания клиента
     //     с "спокойным периодом" по данному типу события, если период превышен сохраням данные и работаем с ними дальше
     //     -- предпринимаем НЕОБХОДИМЫЕ ДЕЙСТВИЯ
     $cur_time = time();
     // этап  1.
     // массив id-шников всех клиентов закрепленных за менеджером
     //**--**
     //echo $manager_id.'-------------';
     $clients_ids_arr = self::get_related_clients_ids($manager_id);
     //**--**
     //echo'<pre>clients_ids_arr<br>';print_r($clients_ids_arr); echo'<pre>';
     // Получаем данные об отложенных оповещениях
     // REMAINDER_PROTOCOL таблица содержащая данные о том на сколько перенесено какое-либо уведомление
     // вытаскиваем данные по менеджеру, если есть будем их потом сравнивать с текущим временем
     // поле details в таблице  REMAINDER_PROTOCOL имеет следующий вид - {"level":"value","event_type":"value"}
     // где level- тип оповещения ,event_type -тип записи в таблице PLANNER, пример - {"level":"expired_event","event_type":"звонок"}
     $query = "SELECT * FROM `" . REMAINDER_PROTOCOL . "` WHERE `client_id` IN('" . implode("','", $clients_ids_arr) . "') AND `manager_id` = '" . (int) $manager_id . "'  AND `sourse` = 'REMAIND_AFTER' ORDER BY `date_time` ASC";
     $result = $mysqli->query($query) or die($mysqli->error);
     $delayed_remainds = array();
     // массив дат до которых отложенны оповещения по конкретному кленту по конкретному событию
     if ($result->num_rows > 0) {
         while ($row = $result->fetch_assoc()) {
             $remaind_details = json_decode($row['details']);
             //echo $row['details']; echo'<br>';
             //echo'<pre>';print_r($remaind_details); echo'<pre>';
             if (isset($remaind_details->level, $remaind_details->event_type)) {
                 $delayed_remainds[$row['client_id']][$remaind_details->level][$remaind_details->event_type] = $row['date_time'];
             }
         }
     }
     //**--**
     //echo'<pre>delayed_remainds<br>';echo $query;print_r($delayed_remainds); echo'<pre>';
     //  вычисляем по каким из всех клиентов менеджера не ведутся записи в таблице PLANNER с разделение на типы
     //  ( не берем строки со значением status=init эти записи вносит система, не менеджер )
     // массив клиентов по которым записи еще не велись
     // по этим клиентам надо выводить сообщение что необходимо запланировать действие (несколько раз, затем создавать атоматически?)
     // и еще сделать запись со значением init (если она еще не сделана) от неё будет вестись отчет первого периода
     foreach (self::$event_types['traced'] as $type) {
         $query = "SELECT `client_id` FROM `" . PLANNER . "` WHERE `client_id` IN('" . implode("','", $clients_ids_arr) . "') AND `manager_id` = '" . (int) $manager_id . "' AND `type` = '" . $type . "' GROUP BY `client_id`";
         //echo $query;
         $result = $mysqli->query($query) or die($mysqli->error);
         $traced_clients_ids_arr = array();
         if ($result->num_rows > 0) {
             while ($row = $result->fetch_assoc()) {
                 $traced_clients_ids_arr[] = $row['client_id'];
             }
             //**--**
             //echo'<pre>traced_clients_ids_arr '.$result->num_rows.'  '.$type.'<br>';print_r($traced_clients_ids_arr); echo'<pre>';
         }
         $untraced_clients_ids_arr[$type] = array_diff($clients_ids_arr, $traced_clients_ids_arr);
     }
     //**--**
     //echo'<pre>untraced_clients_ids_arr<br>';print_r($untraced_clients_ids_arr); echo'<pre>';
     if (!empty($untraced_clients_ids_arr)) {
         self::set_init_row($manager_id, $untraced_clients_ids_arr);
     }
     // этап  2
     // Выбираем самые последние записи со значением поля  `status` = 'done' или 'init'
     // для каждого клиента по отслеживаемым типам события
     // массив который будет содержать данные об уровнях оповещений
     $alarms_data_arr = array();
     foreach (self::$event_types['traced'] as $type) {
         $query = "SELECT *, MAX(exec_datetime) AS `max_exec_datetime` FROM `" . PLANNER . "`\n\t\t\t\t\t\t\t\t\t   WHERE `client_id` IN('" . implode("','", $clients_ids_arr) . "') AND `manager_id` = '" . (int) $manager_id . "'\n\t\t\t\t\t\t\t\t\t\tAND( `type` = '" . $type . "' AND ( `status` = 'done' OR `status` = 'init' ) )\n\t\t\t\t\t\t\t\t\t\t GROUP BY `client_id`";
         // ORDER BY `id` DESC
         //echo $query;
         $result = $mysqli->query($query) or die($mysqli->error);
         if ($result->num_rows > 0) {
             while ($row = $result->fetch_assoc()) {
                 // если есть ограничение по выводу оповещений определенного типа для данного менеджера,
                 // не добавляем их в массив, пропуская дальнейшее выполнение цикла
                 if (in_array($manager_id, self::$parted_output_limit_for_id[$type])) {
                     continue;
                 }
                 // проверяем есть ли отсрочка по данному кленту по данному типу события
                 // если есть сравниваем с текущей датой, если текущая дата меньше не добавляем это событие в оповещения
                 // это событие в оповещения в данном случае пропускаем дальнейшее выполнение цикла
                 //echo $delayed_remainds[$row['client_id']]['expired_event'][$row['type']].'<br>';
                 if (isset($delayed_remainds[$row['client_id']]['expired_event'][$type]) && $cur_time < strtotime($delayed_remainds[$row['client_id']]['expired_event'][$type])) {
                     continue;
                 }
                 // вычисляем количество дней прошедших с "начала периода"
                 $range = round(($cur_time - strtotime($row['max_exec_datetime'])) / (24 * 60 * 60));
                 // передаем величину дней прошедших с "начала периода" в обработчик
                 // определяющий есть ли превышение допустимой величины и до какого уровня
                 if ($level = self::level_detector($range, $type)) {
                     // ограничение на количество элементов в итоговом массиве ( для отладки )
                     if (self::$limit_output_elements) {
                         if (isset($alarms_data_arr[$level][$row['type']]) && count($alarms_data_arr[$level][$row['type']]) >= self::$limit_output_elements) {
                             continue;
                         }
                     }
                     /*
                     // вспомогательные данные (на время разработки);
                     if(isset($_GET['short'])){ 
                         $row['--max_exec_datetime'] = $row['max_exec_datetime'];
                     							   unset($row['max_exec_datetime']);
                     							   $row['--range'] = $range;
                     							   $output_row = array(
                     											   "type" => $row['type'],
                     											   "status" => $row['status'],
                     											   "client_id" => $row['client_id'],
                     											   "num_of_remind" => $row['num_of_remind'],
                     											   "--max_exec_datetime" => $row['--max_exec_datetime'],
                     											   "--range" => $row['--range']
                     											   ); 
                     }
                     else  $output_row = $row; 
                     */
                     $client = new Client($row['client_id']);
                     $output_row = array("client_id" => $row['client_id'], "manager_id" => $row['manager_id'], "client_name" => $client->name);
                     $alarms_data_arr[$level][$row['type']][] = $output_row;
                 }
             }
         }
     }
     //**--**
     // echo'<pre>alarms_data_arr<br>';print_r($alarms_data_arr); echo'<pre>';
     // Определяем по каким клиентам не поставлено новое событие после выполнения предыдущего или инициализации
     // для этого делаем сортировку под дате выполнения события, и складываем в двухуровневый массив с ключами client_id , type
     // в итоге в массиве осядет запись максимально последняя по значению exec_datetime, затем мы проходим по массиву и проверяем -
     // имеет ли поле `status` значение 'done' или 'init' если да то значит это было последней записью соответсвенно новых событий
     // еще небыло запланированно  - отправляем этого клиента на оповещение
     foreach (self::$event_types['traced'] as $type) {
         $sub_query_arr[] = "`type` = '" . $type . "'";
     }
     $query = "SELECT * FROM `" . PLANNER . "`\n\t\t\t                       WHERE `client_id` IN('" . implode("','", $clients_ids_arr) . "') AND `manager_id` = '" . (int) $manager_id . "'\n\t\t\t                        AND (" . implode(" OR ", $sub_query_arr) . ")\n\t\t\t\t\t\t\t\t\t  ORDER BY exec_datetime ASC";
     // echo $query;
     //echo $query;
     $result = $mysqli->query($query) or die($mysqli->error);
     $arr = array();
     if ($result->num_rows > 0) {
         while ($row = $result->fetch_assoc()) {
             // проверяем есть ли отсрочка по данному кленту по данному типу события
             // если есть сравниваем с текущей датой, если текущая дата меньше не добавляем это событие в оповещения
             // это событие в оповещения в данном случае пропускаем дальнейшее выполнение цикла
             if (isset($delayed_remainds[$row['client_id']]['need_new_event'][$row['type']]) && $cur_time < strtotime($delayed_remainds[$row['client_id']]['need_new_event'][$row['type']])) {
                 continue;
             }
             $arr[$row['client_id']][$row['type']] = array('exec_datetime' => $row['exec_datetime'], 'status' => $row['status'], 'client_id' => $row['client_id'], 'manager_id' => $row['manager_id'], 'num_of_remind' => $row['num_of_remind']);
         }
     }
     //**--**
     //echo'<pre>arr<br>';print_r($arr); echo'<pre>';
     foreach ($arr as $client => $row) {
         foreach ($row as $event_type => $data) {
             // если есть ограничение по выводу оповещений определенного типа для данного менеджера, не добавляем их в массив
             if (in_array($manager_id, self::$parted_output_limit_for_id[$event_type])) {
                 continue;
             }
             // ограничение на количество элементов в итоговом массиве ( для отладки )
             if (self::$limit_output_elements) {
                 if (isset($alarms_data_arr['need_new_event'][$event_type]) && count($alarms_data_arr['need_new_event'][$event_type]) >= self::$limit_output_elements) {
                     continue;
                 }
             }
             if ($data['status'] == 'done' || $data['status'] == 'init') {
                 // добавляем клиента в оповещения если с момента последнего выполненого действия или инициализации прошло
                 // более $N дней (промежуток без оповещений) и менее периода установленного для КРАСНОГО
                 // уровня опвещения данного типа
                 $N = 1;
                 // по идее должно быть больше 0 если подразумевается что подсказка должна отображаться не в первый день
                 $range = round(($cur_time - strtotime($data['exec_datetime'])) / (24 * 60 * 60));
                 // echo $data['client_id']. '  '.$cur_time. '  '.$event_type. '  '.$data['status']. '  '.strtotime($data['exec_datetime']). '  '.self::$levels_alarm_periods['red'][$event_type].' - '. $range.'<br>' ;
                 if ($range > $N && $range < self::$levels_alarm_periods['red'][$event_type]) {
                     $client = new Client($data['client_id']);
                     $alarms_data_arr['need_new_event'][$event_type][] = array("client_id" => $data['client_id'], "client_name" => $client->name, "manager_id" => $data['manager_id']);
                 }
             }
         }
     }
     //echo '<pre>'; print_r($alarms_data_arr); echo '<pre>';
     self::$warnings = $alarms_data_arr;
 }