} if ($_POST['ajax_reminder'] == "window_set_minimize") { // при клике менеджером на кнопку "СВЕРНУТЬ ОКНО" Planner::window_set_minimize($_POST['client_id'], $_POST['window_type'], $_POST['event_type'], $_POST['window_set_minimize']); exit; } if ($_POST['ajax_reminder'] == "show_help") { // при клике менеджером на кнопку "?" echo getHelp('warnings.planner.terms'); exit; } if ($_POST['ajax_reminder'] == "session_was_shown") { // отправляется клиентом когда очередная сессия оповещений была показа первый раз // яваскрипт отправляет запрос после того как были выгруженны окна оповещений // здесь в любом случае передаем id реального юзера (да же если админом в другом месте используется фейковый id для отладки) Planner::remaind_counter($_SESSION['access']['user_id']); exit; } } } if (isset($_GET['add_data_to_rt_from_basket'])) { include_once ROOT . '/libs/php/classes/rt_class.php'; //echo $_GET['client_data'].' - '.$_GET['manager_login']; echo RT::add_data_from_basket_directly($_GET['client_data'], $_GET['dop_info'], $_GET['manager_login']); exit; } if (isset($_GET['subquery_for_planner_window'])) { include_once ROOT . '/libs/php/classes/client_class.php'; echo Client::cont_faces_list($_GET['client_id']); exit; }
/** * @return \yii\db\ActiveQuery */ public function getPlanners() { return $this->hasMany(Planner::className(), ['user_id' => 'id']); }
/** * This is the standard DeltaBlue benchmark. A long chain of equality * constraints is constructed with a stay constraint on one end. An * edit constraint is then added to the opposite end and the time is * measured for adding and removing this constraint, and extracting * and executing a constraint satisfaction plan. There are two cases. * In case 1, the added constraint is stronger than the stay * constraint and values must propagate down the entire length of the * chain. In case 2, the added constraint is weaker than the stay * constraint so it cannot be accomodated. The cost in this case is, * of course, very low. Typical situations lie somewhere between these * two extremes. */ function chainTest($n) { global $planner; $planner = new Planner(); $prev = null; $first = null; $last = null; // Build chain of n equality constraints for ($i = 0; $i <= $n; $i++) { $name = "v{$i}"; $v = new Variable($name); if ($prev != null) { new EqualityConstraint($prev, $v, Strength::Required()); } if ($i == 0) { $first = $v; } if ($i == $n) { $last = $v; } $prev = $v; } new StayConstraint($last, Strength::StrongDefault()); $edit = new EditConstraint($first, Strength::Preferred()); $edits = new OrderedCollection(); $edits->add($edit); $plan = $planner->extractPlanFromConstraints($edits); for ($i = 0; $i < 100; $i++) { $first->value = $i; $plan->execute(); if ($last->value != $i) { alert("Chain test failed."); } } }
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; }