This repository has been archived on 2024-10-16. You can view files and clone it, but cannot push or open issues or pull requests.
ebala/mirzaev/ebala/system/controllers/task.php

3298 lines
130 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace mirzaev\ebala\controllers;
// Файлы проекта
use mirzaev\ebala\controllers\core,
mirzaev\ebala\controllers\traits\errors,
mirzaev\ebala\models\task as model,
mirzaev\ebala\models\account,
mirzaev\ebala\models\worker,
mirzaev\ebala\models\market,
mirzaev\ebala\models\payments,
mirzaev\ebala\models\core as _core;
// Библиотека для ArangoDB
use ArangoDBClient\Document as _document;
// System libraries
use datetime,
datetimezone,
exception;
/**
* Контроллер задания
*
* @package mirzaev\ebala\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class task extends core
{
use errors;
/**
* Типы работ
*/
final public const WORKS = ['Кассир', 'Выкладчик', 'Гастроном', 'Бригадир', 'Грузчик', 'Мобильный грузчик', 'Мобильный универсал'];
/**
* Создать
*
* @param array $parameters Параметры запроса (json в php://input)
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function create(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора, оператора или магазина
// Инициализация буфера ошибок
$this->errors['tasks'] ??= [];
if (!empty($json = json_decode(file_get_contents('php://input'), true, 4))) {
// Найден и декодирован json-документ с данными для создания заявок
foreach ($json as $work => $tasks) {
// Перебор категорий (колонок)
foreach ($tasks as $task) {
// Перебор заявок
// Создание заявки
model::create(
work: model::label($work),
market: $this->account->type === 'market' ? account::market($this->account->getId())?->id : null,
start: $task['start'],
end: $task['end'],
date: $task['date'],
commentary: $task['commentary'],
errors: $this->errors['tasks']
);
}
}
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось инициализировать JSON-документ с данными заявок');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Прочитать
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function read(array $parameters = []): void
{
try {
if ($this->account->status()) {
// Авторизован аккаунт
// Инициализация буфера AQL-выражения для инъекции фильтра по интервалу
$interval = '';
foreach (['from', 'to'] as $name) {
// Перебор фильтров временного промежутка (И)
// Инициализация значения (приоритет у cookie)
if (empty($value = (int) ($_COOKIE["tasks_filter_$name"] ?? @$this->session->buffer[$_SERVER['INTERFACE']]['tasks']['filters'][$name] ?? (($name === 'from') ? time() : strtotime('+1 month'))))) continue;
// Генерация AQL-выражения для инъекции в строку запроса
if ($name === 'from') $interval .= " && task.date >= $value";
else if ($name === 'to') $interval .= " && task.date <= $value";
}
// Очистка от бинарных операторов сравнения с только одним операндом (крайние)
$interval = trim(trim(trim($interval), '&&'));
// Инициализация буфера AQL-выражения для инъекции фильтра по интервалу
$polysemantic = '';
foreach (['rating'] as $name) {
// Перебор фильтров с произвольными значениями (И)
// Инициализация значения (приоритет у cookie)
$value = $_COOKIE["tasks_filter_$name"] ?? @$this->session->buffer[$_SERVER['INTERFACE']]['tasks']['filters'][$name] ?? null;
// Найдено значение?
if ($value === null) continue;
// Генерация AQL-выражения для инъекции в строку запроса
if ($name === 'rating' && $value > 0) $polysemantic .= " && task.rating >= $value";
}
// Очистка от бинарных операторов сравнения с только одним операндом (крайние)
$polysemantic = trim(trim(trim($polysemantic), '&&'));
// Инициализация буферов AQL-выражений для инъекции фильтра по статусам
$statuses_and = '';
$statuses_or = '';
foreach (['confirmed', 'waiting', 'published', 'unpublished', 'problematic', 'hided', 'completed'] as $name) {
// Перебор фильтров по статусам
// Инициализация значения (приоритет у cookie) (отсутствие значения или значение 0 вызывают continue)
if (empty($value = $_COOKIE["tasks_filter_$name"] ?? @$this->session->buffer[$_SERVER['INTERFACE']]['tasks']['filters'][$name] ?? 0)) continue;
// Конвертация ярлыков
$converted = match ($name) {
'waiting' => 'confirmed',
'unpublished' => 'published',
default => $name
};
// Генерация выражения
$expression = "task.$converted == " . ($name === 'unpublished' || $name === 'waiting' ? 'false' : 'true');
// Генерация AQL-выражения для инъекции в строку запроса
if ($value === '1') $statuses_and .= " && " . $expression;
else if ($value === '2') $statuses_or .= " || " . $expression;
}
// Очистка от бинарных операторов сравнения с только одним операндом (крайние)
$statuses_and = trim(trim(trim($statuses_and), '&&'));
$statuses_or = trim(trim(trim($statuses_or), '||'));
// Инициализация буфера с объёдинёнными буферами c AQL-выражениям "И" и "ИЛИ"
$statuses_merged = (empty($statuses_and) ? '' : "($statuses_and)") . (empty($statuses_or) ? '' : (empty($statuses_and) ? '' : ' || ') . "($statuses_or)");
// Инициализация общего буфера с AQL-выражениями
$filters = '';
// Объединение фильров в единую строку с AQL-выражениями для инъекции
if (!empty($interval)) $filters .= $interval;
if (!empty($statuses_merged)) $filters .= empty($filters) ? $statuses_merged : " && ($statuses_merged)";
if (!empty($polysemantic)) $filters .= empty($filters) ? $polysemantic : " && $polysemantic";
if (isset($parameters['row'])) {
// Запрошена строка
// Добавление идентификатора строки в фильтр
$filters .= ' && task._key == "' . $parameters['row'] . '"';
// Инициализация данных для генерации HTML-документа с таблицей
if ($_SERVER['INTERFACE'] === 'worker')
$this->view->rows = model::list(before: 'FILTER task.worker == "' . account::worker($this->account->getId())?->id . '"' . " && ($filters)");
else if ($_SERVER['INTERFACE'] === 'operator')
$this->view->rows = model::list(before: "FILTER ($filters)");
else if ($_SERVER['INTERFACE'] === 'market')
$this->view->rows = model::list(before: 'FILTER task.market == "' . account::market($this->account->getId())?->id . '"' . " && ($filters)");
else if ($_SERVER['INTERFACE'] === 'administrator')
$this->view->rows = model::list(before: "FILTER ($filters)");
else $this->view->rows = [];
} else {
// Запрошена страница (множество строк)
// Реинициализация номера актуальной страницы
if (isset($parameters['page'])) $this->session->write(['tasks' => ['page' => $parameters['page']]]);
else if (empty($this->session->buffer[$_SERVER['INTERFACE']]['tasks']['page'])) $this->session->write(['tasks' => ['page' => 1]]);
// Инициализация строки поиска
$search = $_COOKIE["tasks_filter_search"] ?? @$this->session->buffer[$_SERVER['INTERFACE']]['tasks']['filters']['search'] ?? '';
if (mb_strlen($search) < 3) $search = null;
$search_query = empty($search)
? null
: <<<AQL
SEARCH
task.commentary IN TOKENS(@search, 'text_ru')
|| STARTS_WITH(task._key, @search)
|| STARTS_WITH(task.worker, @search)
|| STARTS_WITH(task.market, @search)
|| (LENGTH(@search) > 6 && LEVENSHTEIN_MATCH(task._key, TOKENS(@search, 'text_en')[0], 2, true))
|| (LENGTH(@search) > 6 && LEVENSHTEIN_MATCH(task.worker, TOKENS(@search, 'text_en')[0], 2, true))
|| (LENGTH(@search) > 6 && LEVENSHTEIN_MATCH(task.market, TOKENS(@search, 'text_en')[0], 2, true))
AQL;
// Инициализация данных для генерации HTML-документа с таблицей
if ($_SERVER['INTERFACE'] === 'worker') {
// Сотрудник
$this->view->rows = model::list(
before: sprintf(
<<<AQL
%s
FILTER task.deleted != true && task.worker == @worker%s
AQL,
$search_query,
empty($filters) ? null : " && ($filters)"
),
after: 'COLLECT x = worker, y = market, z = task OPTIONS { method: "sorted" }',
page: (int) $this->session->buffer['worker']['tasks']['page'],
sort: 'z.date DESC, z.created DESC, z._key DESC, x.created DESC, y.created DESC, x._key DESC, y._key DESC',
target: empty($search) ? model::COLLECTION : 'registry_tasks',
return: '{task: z, worker: x, market: y}',
binds: ['worker' => account::worker($this->account->getId())?->id] + (empty($search) ? [] : ['search' => $search])
);
} else if ($_SERVER['INTERFACE'] === 'market') {
// Магазин
$this->view->rows = model::list(
before: sprintf(
<<<AQL
%s
FILTER task.deleted != true && task.market == @market%s
AQL,
$search_query,
empty($filters) ? null : " && ($filters)"
),
after: 'COLLECT x = worker, y = market, z = task OPTIONS { method: "sorted" }',
page: (int) $this->session->buffer['market']['tasks']['page'],
sort: 'z.date DESC, z.created DESC, z._key DESC, x.created DESC, y.created DESC, x._key DESC, y._key DESC',
target: empty($search) ? model::COLLECTION : 'registry_tasks',
return: '{task: z, worker: x, market: y}',
binds: ['market' => account::market($this->account->getId())?->id] + (empty($search) ? [] : ['search' => $search])
);
} else if ($_SERVER['INTERFACE'] === 'operator') {
// Оператор
$this->view->rows = model::list(
before: sprintf(
<<<AQL
%s
FILTER task.deleted != true%s
AQL,
$search_query,
empty($filters) ? null : " && ($filters)"
),
after: 'COLLECT x = worker, y = market, z = task OPTIONS { method: "sorted" }',
page: (int) $this->session->buffer['operator']['tasks']['page'],
sort: 'z.date DESC, z.created DESC, z._key DESC, x.created DESC, y.created DESC, x._key DESC, y._key DESC',
target: empty($search) ? model::COLLECTION : 'registry_tasks',
return: '{task: z, worker: x, market: y}',
binds: empty($search) ? [] : [
'search' => $search
]
);
} else if ($_SERVER['INTERFACE'] === 'administrator') {
// Администратор
$this->view->rows = model::list(
before: sprintf(
<<<AQL
%s
FILTER task.deleted != true%s
AQL,
$search_query,
empty($filters) ? null : " && ($filters)"
),
after: 'COLLECT x = worker, y = market, z = task OPTIONS { method: "sorted" }',
page: (int) $this->session->buffer['administrator']['tasks']['page'],
sort: 'z.date DESC, z.created DESC, z._key DESC, x.created DESC, y.created DESC, x._key DESC, y._key DESC',
target: empty($search) ? model::COLLECTION : 'registry_tasks',
return: '{task: z, worker: x, market: y}',
binds: empty($search) ? [] : [
'search' => $search
]
);
} else $this->view->rows = [];
// Запись в cookie
setcookie(
'tasks_page',
(string) $this->session->buffer[$_SERVER['INTERFACE']]['tasks']['page'],
[
'expires' => strtotime('+1 hour'),
'path' => '/',
'secure' => true,
'httponly' => false,
'samesite' => 'strict'
]
);
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы
$this->view->page = $parameters['page'];
};
// Предобработка строк перед генерацией документа
$this->view->rows = static::preprocessing($this->account, $this->view->rows);
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'rows' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Предобработка строк перед генерацией документа
*
* @param account $account Аккаунт
* @param array $rows Строки
*
* @return array Обработанные строки
*
* @todo Переделать в model::hours($from, $to);
*/
protected static function preprocessing(account $account, array $rows): array
{
// Инициализация буфера прочитанных из базы данных строк
$buffer = $rows;
foreach ($rows as $number => $row) {
// Перебор прочитанных из базы данных строк
// Инициализация ярлыка
$link = &$buffer[$number];
if (!empty($row->task['start'])) {
// Найдено начало
// Инициализация даты
$date = (new DateTime('@' . $row->task['date']))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'));
// Инициализация времени
$start = datetime::createFromFormat('H:i', (string) $row->task['start']);
// Перенос времени в дату
$start = $date->setTime((int) $start->format('H'), (int) $start->format('i'));
// Запись в буфер
$link->task = ['start' => $start] + $link->task;
}
if (!empty($row->task['end'])) {
// Найден конец
// Инициализация даты
$date = (new DateTime('@' . $row->task['date']))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'));
// Инициализация времени
$end = datetime::createFromFormat('H:i', (string) $row->task['end']);
// Перенос времени в дату
$end = $date->setTime((int) $end->format('H'), (int) $end->format('i'));
// Запись в буфер
$link->task = ['end' => $end] + $link->task;
}
// Инициализация данных заблокировавшего аккаунта
if (isset($link->task['block']) && $link->task['block']['expires'] > time() && $link->task['block']['account'] !== (int) $account->getKey())
$link->task = ['block' => ['_account' => account::read('d._key == "' . $link->task['block']['account'] . '"')] + $link->task['block']] + $link->task;
else $link->task = ['block' => null] + $link->task;
// Инициализация буфера сгенерированных данных работы для шаблонизатора
$generated = [];
// Генерация данных работы для шаблонизатора
if (
$link->task['start'] instanceof datetime
&& $link->task['end'] instanceof datetime
) {
$generated['hours'] = (float) $link->task['start']->diff($link->task['end'])->format('%R%H.%i');
if ($generated['hours'] < 0) $generated['hours'] += 24;
if ($generated['hours'] >= 6.5 && $generated['hours'] < 9) $generated['hours'] -= 0.5;
else if ($generated['hours'] >= 9 && $generated['hours'] < 12.5) $generated['hours'] -= 1;
else if ($generated['hours'] >= 12.5) $generated['hours'] -= 1.5;
}
if ($link->task['start'] instanceof datetime) $generated['start'] = $link->task['start']->format('H:i');
if ($link->task['end'] instanceof datetime) $generated['end'] = $link->task['end']->format('H:i');
// Инициализация счётчика непрочитанных сообщений
$generated['chat'] = [
'unreaded' => 0
];
if ($account->type === 'worker') {
// Сотрудник
foreach ($link->task['chats']['worker'] ?? [] as $message) {
// Перебор сообщений из чата: СОТРУДНИК <-> ОПЕРАТОР
// Подсчёт непрочитанных сообщений
if (!array_key_exists((string) $account->getKey(), $message['readed'] ?? [])) ++$generated['chat']['unreaded'];
}
} else if ($account->type === 'market') {
// Магазин
foreach ($link->task['chats']['market'] ?? [] as $message) {
// Перебор сообщений из чата: МАГАЗИН <-> ОПЕРАТОР
// Подсчёт непрочитанных сообщений
if (!array_key_exists((string) $account->getKey(), $message['readed'] ?? [])) ++$generated['chat']['unreaded'];
}
} else if ($account->type === 'operator' || $account->type === 'administrator') {
// Оператор или администратор
foreach ($link->task['chats'] ?? [] as $chat)
foreach ($chat as $message) {
// Перебор сообщений из всех чатов
// Подсчёт непрочитанных сообщений
if (!array_key_exists((string) $account->getKey(), $message['readed'] ?? [])) ++$generated['chat']['unreaded'];
}
}
// Запись из буфера сгенерированных данных работы для шаблонизатора в буфер переменных окружения шаблонизатора
$link->task = ['generated' => $generated] + $link->task;
}
// Трансфер строк из модифицированного буфера процесса в буфер вывода
return $buffer;
}
/**
* Заменить сотрудника или магазин
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function update(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора, оператора или магазина
if (($task = model::read('d._key == "' . $parameters['task'] . '"', amount: 1)) instanceof _document) {
// Найдена заявка
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $task->market !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для редактирования этой заявки');
// Заявка подтверждена?
if ($task->confirmed) throw new exception('Запрещено редактировать подтверждённую заявку');
if ($this->account->type === 'market') {
// Магазин
// Инициализация даты
$date = (new DateTime('@' . $task->date))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'));
// Инициализация времени
$start = datetime::createFromFormat('H:i', (string) $task->start);
$end = datetime::createFromFormat('H:i', (string) $task->end);
// Перенос времени в дату
$start = $date->setTime((int) $start->format('H'), (int) $start->format('i'))->format('U');
$end = $date->setTime((int) $end->format('H'), (int) $end->format('i'))->format('U');
// Заявка уже начата?
if (time() - $start > 0 && time() - $end < 0)
throw new exception('Запрещено редактировать начатую заявку');
// Заявка уже прошла?
else if (time() - $end > 0 && $task->completed !== true)
throw new exception('Запрещено редактировать прошедшую заявку');
// Заявка уже завершена?
else if ($task->completed === true)
throw new exception('Запрещено редактировать завершённую заявку');
// Прошло более 30 минут после создания заявки? (1800 секунд = 30 минут)
/* if (time() - $task->created > 1800)
throw new exception('Запрещено редактировать заявку спустя 30 минут после создания'); */
// До начала заявки осталось менее 16 часов? (57600 секунд = 16 часов)
if ($start - time() < 57600)
throw new exception('Запрещено редактировать заявку за менее 16 часов до её начала');
}
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (!empty($parameters['worker'])) {
// Передан сотрудник
if ($parameters['worker'] === 'delete') {
// Удалить сотрудника
// Удаление сотрудника
$task->worker = null;
if (_core::update($task)) {
// Записано изменение в базу данных
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы (отключение)
$this->view->page = null;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'updated' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось записать изменения в базу данных');
} else {
// Записать нового сотрудника
if (($worker = worker::read('d.id == "' . $parameters['worker'] . '" && d.active == true', amount: 1)) instanceof _document) {
// Найден сотрудник (запрашиваемый для записи сотрудник существует в базе данных)
if (!$worker->fired) {
// Не уволен сотрудник
if (in_array($task->work, $worker->works, true)) {
// Работа соответствует подходящим сотруднику
if ((($age = (new DateTime)->diff(DateTime::createFromFormat('d.m.Y', $worker->birth))->y) > 15 && ($task->work === 'Выкладчик' || $task->work === 'Гастроном')) || $age > 17) {
// Подходит по возрасту сотрудник
if ($task->worker !== $parameters['worker']) {
// Идентификатор запрашиваемого сотрудника не равен актуальному
// Запись сотрудника
$task->worker = $worker->id;
// Снятие с публикации
$task->published = false;
if (_core::update($task)) {
// Записано изменение в базу данных
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы (отключение)
$this->view->page = null;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'updated' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось записать изменения в базу данных');
} else throw new exception('Сотрудник уже назначен');
} else throw new exception('Сотрудник не подходит по возрасту');
} else throw new exception('Заявка не подходит по типу работы для сотрудника');
} else throw new exception('Нельзя назначить уволенного сотрудника');
} else throw new exception('Не найден сотрудник');
}
} else if (!empty($parameters['market'])) {
// Передан магазин
// Магазин пытается перезаписать магазин?
if ($this->account->type === 'market') throw new exception('Вы не авторизованы переназначать магазин заявки');
if ($parameters['market'] === 'delete') {
// Удалить магазин
// Удаление магазина
$task->market = null;
if (_core::update($task)) {
// Записано изменение в базу данных
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы (отключение)
$this->view->page = null;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'updated' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось записать изменения в базу данных');
} else {
// Записать новый магазин
if (($market = market::read('d.id == "' . $parameters['market'] . '" && d.active == true', amount: 1)) instanceof _document) {
// Найден магазин (запрашиваемый для записи магазин существует в базе данных)
if ($task->market !== $parameters['market']) {
// Идентификатор запрашиваемого сотрудника не равен актуальному
// Запись магазина
$task->market = $market->id;
if (_core::update($task)) {
// Записано изменение в базу данных
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы (отключение)
$this->view->page = null;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'updated' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось записать изменения в базу данных');
} else throw new exception('Магазин уже назначен');
} else throw new exception('Не найден магазин');
}
} else throw new exception('Не получены данные для записи');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'updated' => false,
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Прочитать данные задачи
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function task(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора, оператора или магазина
// Инициализация данных сотрудника
$this->view->task = model::read(
'd._key == "' . $parameters['task'] . '"',
return: match ($this->account->type) {
'market' => '{_key: d._key, created: d.created, updated: d.updated, date: d.date, start: d.start, end: d.end, market: d.market, confirmed: d.confirmed, completed: d.completed }',
'administrator', 'operator' => '{_key: d._key, created: d.created, updated: d.updated, date: d.date, start: d.start, end: d.end, market: d.market, confirmed: d.confirmed, completed: d.completed, hided: d.hided, updates: d.updates }',
default => 'd'
}
)->getAll();
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $this->view->task['market'] !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для чтения этой заявки');
// Удаление данных из выдачи
$this->view->task = ['market' => null] + $this->view->task;
if (!empty($this->view->task)) {
// Найдены данные задачи
// Инициализация даты
$date = (new DateTime('@' . $this->view->task['date']))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'));
// Инициализация времени
$start = datetime::createFromFormat('H:i', (string) $this->view->task['start']);
$end = datetime::createFromFormat('H:i', (string) $this->view->task['end']);
// Перенос времени в дату
$start = $date->setTime((int) $start->format('H'), (int) $start->format('i'))->format('U');
$end = $date->setTime((int) $end->format('H'), (int) $end->format('i'))->format('U');
// Деинициализация неактуальных параметров
$this->view->task = ['date' => null, 'start' => null, 'end' => null] + $this->view->task;
// Заявка уже началась? (в том числе может и завершена)
$passed = (new DateTime())->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'))->format('U') - $start >= 0;
// Инициализация буфера данных задачи
$buffer = [];
// Перевод ключей на русский язык
foreach ($this->view->task as $key => $value)
if ($key === 'updates')
foreach ($value ?? [] as $key => $value) $buffer['updates'][$key] = [
'label' => match ($key) {
'operator' => 'Оператор',
'market' => 'Магазин',
'administrator' => 'Администратор',
'worker' => 'Сотрудник',
default => $key
},
'value' => [
'id' => $value
] + account::read("d._key == \"$value\"", amount: 1)?->name ?? []
];
else if (match ($key) {
'created', 'updated', 'confirmed', 'hided', 'completed', '_key' => true,
'start', 'end' => $passed, // Только для завершённой заявки
default => false
}) $buffer[$key] = [
'label' => match ($key) {
'created' => 'Создано',
'updated' => 'Обновлено',
'confirmed' => 'Подтверждено',
'hided' => 'Скрыто',
'completed' => 'Завершено',
'start' => 'Начало',
'end' => 'Конец',
default => $key
},
'value' => $value
];
if ($passed) {
// Начатая заявка (в том числе завершённая)
// Конвертация времени в дату
$buffer['start']['value'] = $start;
$buffer['end']['value'] = $end;
}
// Запись из буфера данных задачи
$this->view->task = $buffer;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode([
'start' => $start,
'end' => $end,
'task' => $this->view->render(
DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'lists' . DIRECTORY_SEPARATOR . 'task' . DIRECTORY_SEPARATOR . ($passed ? 'passed.html' : 'actual.html')
),
'errors' => self::parse_only_text($this->errors)
]);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Прочитать данные сотрудника
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function worker(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных сотрудника
$this->view->worker = worker::read(
'd.id == "' . $parameters['worker'] . '"',
return: $this->account->type === 'market'
? '{id: d.id, created: d.created, updated: d.updated, name: d.name, number: d.number, mail: d.mail, birth: d.birth, rating: d.rating}'
: 'd'
)->getAll();
if (!empty($this->view->worker)) {
// Найдены данные сотрудника
// Инициализация буфера данных сотрудника
$buffer = [];
// Перевод ключей на русский язык
foreach ($this->view->worker as $key => $value) $buffer[$key] = [
'label' => match ($key) {
'created' => 'Создано',
'updated' => 'Обновлено',
'name' => 'ФИО',
'number' => 'Номер',
'mail' => 'Почта',
'birth' => 'Дата рождения',
'address' => 'Адрес',
'rating' => 'Рейтинг',
'passport' => 'Паспорт',
'issued' => 'Место выдачи',
'hiring' => 'Дата найма',
'district' => 'Адрес регистрации',
'department' => 'Отделение',
'requisites' => 'Реквизиты',
'fired' => 'Уволен',
'tax' => 'ИНН',
'city' => 'Город',
'payment' => 'Форма оплаты',
'works' => 'Типы работ',
default => $key
},
'value' => $value
];
// Удаление ненужных параметров из выдачи
foreach ($buffer as $key => $value) if (match ($key) {
'type', 'active' => true,
default => false
}) unset($buffer[$key]);
// Запись из буфера данных
$this->view->worker = $buffer;
// Возврат (успех)
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'worker' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'lists' . DIRECTORY_SEPARATOR . 'worker.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Прочитать данные магазина
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function market(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных
$this->view->market = market::read('d.id == "' . $parameters['market'] . '"')?->getAll();
if (!empty($this->view->market)) {
// Найдены данные магазина
// Инициализация буфера данных
$buffer = [];
// Перевод ключей на русский язык
foreach ($this->view->market as $key => $value) $buffer[$key] = [
'label' => match ($key) {
'created' => 'Создано',
'updated' => 'Обновлено',
'name' => 'ФИО',
'type' => 'Тип',
'director' => 'Директор',
'address' => 'Адрес',
'city' => 'Город',
'number' => 'Номер',
'mail' => 'Почта',
'commentary' => 'Комментарий',
'bans' => 'Заблокированные',
default => $key
},
'value' => $value
];
// Удаление ненужных параметров из выдачи
foreach ($buffer as $key => $value) if (match ($key) {
'active' => true,
default => false
}) unset($buffer[$key]);
// Запись из буфера данных
$this->view->market = $buffer;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'market' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'lists' . DIRECTORY_SEPARATOR . 'market.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Подтвердить (отклонить)
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function confirm(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
if ($task instanceof _document) {
// Найдена заявка
// Изменение статуса подтверждения
$task->confirmed = !$task->confirmed;
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано изменение в базу данных
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы (отключение)
$this->view->page = null;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'confirmed' => $this->view->rows[0]->task['confirmed'] ?? null,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Добавить статус проблемы (убрать статус проблемы)
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function problem(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора, оператора и магазина
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $task->market !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для заявления о проблеме с этой заявкой');
// Инициализация даты
$date = (new DateTime('@' . $task->date))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'));
// Инициализация времени
$start = datetime::createFromFormat('H:i', (string) $task->start);
$end = datetime::createFromFormat('H:i', (string) $task->end);
// Перенос времени в дату
$start = $date->setTime((int) $start->format('H'), (int) $start->format('i'))->format('U');
$end = $date->setTime((int) $end->format('H'), (int) $end->format('i'))->format('U');
if ($task instanceof _document) {
// Найдена заявка
if ($task->problematic) {
// Проблемная заявка (запрошена отмена статуса проблемной заявки)
// Изменение статуса наличия проблемы
$task->problematic = false;
} else {
// Не проблемная заявка (запрошена установка статуса проблемной заявки)
if (empty($parameters['text'])) throw new exception('Необходимо передать текст с объяснением проблемы');
else {
// Получен текст с описанием проблемы
// Изменение статуса наличия проблемы
$task->problematic = true;
}
}
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано изменение в базу данных
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы (отключение)
$this->view->page = null;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'problematic' => $this->view->rows[0]->task['problematic'],
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Завершить
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function complete(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора, оператора и магазина
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $task->market !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для завершения этой заявки');
// Заявка завершена?
if ($task->completed) throw new exception('Заявка уже завершена');
// Инициализация даты
$date = (new DateTime('@' . $task->date))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'));
// Инициализация времени
$start = datetime::createFromFormat('H:i', (string) $task->start);
$end = datetime::createFromFormat('H:i', (string) $task->end);
// Перенос времени в дату
$start = $date->setTime((int) $start->format('H'), (int) $start->format('i'))->format('U');
$end = $date->setTime((int) $end->format('H'), (int) $end->format('i'))->format('U');
// Заявка ещё не начата
if ($this->account->type === 'market' and time() - $start < 0)
throw new exception('Запрещено завершать не начатую заявку');
if ($task instanceof _document) {
// Найдена заявка
if (empty($parameters['rating'])) throw new exception('Необходимо передать оценку');
else if (($parameters['rating'] = (int) $parameters['rating']) < 1) throw new exception('Оценка должна быть не менее 1');
else if ($parameters['rating'] > 5) throw new exception('Оценка должна быть не более 5');
else {
// Получена оценка
// Запись оценки
$task->rating = $parameters['rating'];
if (!empty($parameters['review'])) {
// Получен отзыв
// Запись отзыва
$task->review = $parameters['review'];
}
// Запись статуса завершения
$task->completed = true;
// Снятие с публикации
$task->published = false;
// Иниализация сотрудника
$worker = worker::read('d.id == "' . $task->worker . '"');
if ($worker instanceof _document) {
// Найден сотрудник
// Инициализация магазина
$market = market::read('d.id == "' . $task->market . '"');
if ($market instanceof _document) {
// Найден магазин
// Подсчёт часов работы
$hours = model::hours($task->start, $task->end, $this->errors);
// Инициализация цены работы сотрудника за 1 час
$hour = payments::hour('worker', $market->city, $task->work);
// Подсчёт оплаты за работу
$payment = $hour * $hours;
// Инициализация штрафа
$penalty = payments::penalty($task->rating ?? null);
if ($penalty === null) $penalty = -$payment;
// Инициализация премии
$bonus = payments::bonus($task->rating ?? null);
// Запись результатов
$task->result = [
'hours' => $hours,
'hour' => $hour,
'penalty' => $penalty,
'bonus' => $bonus,
'processed' => false
];
}
}
}
// Запись в реcстре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано изменение в базу данных
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы (отключение)
$this->view->page = null;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'completed' => $this->view->rows[0]->task['completed'],
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'completed' => $task->completed ?? false,
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Скрыть (показать)
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function hide(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
if ($task instanceof _document) {
// Найдена заявка
// Изменение статуса скрытия
$task->hided = !$task->hided;
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано изменение в базу данных
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы (отключение)
$this->view->page = null;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'hided' => $this->view->rows[0]->task['hided'] ?? null,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Сгенерировать строку
*
* Используется тогда, когда нужно получить HTML-код строки заявки
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function row(array $parameters = []): void
{
try {
if ($this->account->status()) {
// Авторизован аккаунт
// Инициализация строки в глобальную переменную шаблонизатора
if ($this->account->type === 'worker')
$this->view->rows = model::list(before: 'FILTER task._key == "' . $parameters['task'] . '" && task.worker == "' . account::worker($this->account->getId())?->id . '"');
else if ($this->account->type === 'operator')
$this->view->rows = model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"');
else if ($this->account->type === 'market')
$this->view->rows = model::list(before: 'FILTER task._key == "' . $parameters['task'] . '" && task.market == "' . account::market($this->account->getId())?->id . '"');
else if ($this->account->type === 'administrator')
$this->view->rows = model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"');
else $this->view->rows = [];
// Генерация данных для генерации строки
$this->view->rows = static::preprocessing($this->account, $this->view->rows);
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы (отключение)
$this->view->page = null;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Удалить
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function remove(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора, оператора и магазина
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $task->market !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для редактирования типа работы этой заявки');
// Заявка подтверждена?
if ($task->confirmed) throw new exception('Запрещено удалять подтверждённую заявку');
if ($this->account->type === 'market') {
// Магазин
// Инициализация даты
$date = (new DateTime('@' . $task->date))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'));
// Инициализация времени
$start = datetime::createFromFormat('H:i', (string) $task->start);
$end = datetime::createFromFormat('H:i', (string) $task->end);
// Перенос времени в дату
$start = $date->setTime((int) $start->format('H'), (int) $start->format('i'))->format('U');
$end = $date->setTime((int) $end->format('H'), (int) $end->format('i'))->format('U');
// Заявка уже начата?
if (time() - $start > 0 && time() - $end < 0)
throw new exception('Запрещено удалять начатую заявку');
// Заявка уже прошла?
else if (time() - $end > 0 && $task->completed !== true)
throw new exception('Запрещено удалять прошедшую заявку');
// Заявка уже завершена?
else if ($task->completed === true)
throw new exception('Запрещено удалять завершённую заявку');
// Прошло более 30 минут после создания заявки? (1800 секунд = 30 минут)
/* if (time() - $task->created > 1800)
throw new exception('Запрещено удалять заявку спустя 30 минут после создания'); */
// До начала заявки осталось менее 16 часов? (57600 секунд = 16 часов)
if ($start - time() < 57600)
throw new exception('Запрещено удалять заявку за менее 16 часов до её начала');
}
if ($task instanceof _document) {
// Найдена заявка
// Изменение статуса
$task->status = 'deleted';
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Помечено как удалённое
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'deleted' => true,
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Прочитать значение по идентификатору
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function value(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора, оператора или магазина
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $task->market !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для чтения параметров этой заявки');
if ($task instanceof _document) {
// Найдена заявка
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'value' => $task->{$parameters['name']} ?? null,
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Прочитать данные работ для <datalist>
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function works(array $parameters = []): void
{
try {
if (!empty($parameters['task'])) {
// Запрошены данные работ по заявке
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market' || $this->account->type === 'worker')) {
// Авторизован аккаунт администратора, оператора или магазина
// Инициализация данных
$this->view->task = model::read('d._key == "' . $parameters['task'] . '"');
if ($this->view->task instanceof _document) {
// Найдена заявка
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $this->view->task->market !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для просмотра типа работы этой заявки');
// Заявка не принадлежит запросившему сотруднику?
if ($this->account->type === 'worker' and $this->view->task->worker !== account::worker($this->account->getId())?->id)
throw new exception('Вы не авторизованы для просмотра типа работы этой заявки');
// Инициализация списка работ
$this->view->works = static::WORKS;
// Проверка на существование записанной в задаче работы в списке существующих работ и запись об этом в глобальную переменную шаблонизатора
foreach ($this->view->works as $work)
if (in_array($work, $this->view->worker->works)) $this->view->exist = true;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'works' => $this->view->render(DIRECTORY_SEPARATOR . 'lists' . DIRECTORY_SEPARATOR . 'works.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} else if (!empty($parameters['worker'])) {
// Запрошены данные работ по сотруднику
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'worker')) {
// Авторизован аккаунт администратора, оператора или магазина
// Инициализация данных
$this->view->worker = worker::read('d.id == "' . $parameters['worker'] . '"');
if ($this->view->worker instanceof _document) {
// Найден сотрудник
// Сотрудник не принадлежит запросившему аккаунту?
if ($this->account->type === 'worker' and $this->view->worker->id !== account::worker($this->account->getId())?->id)
throw new exception('Вы не авторизованы для просмотра типа работы этого сотрудника');
// Инициализация списка работ
$this->view->works = static::WORKS;
// Проверка на существование записанной в задаче работы в списке существующих работ и запись об этом в глобальную переменную шаблонизатора
foreach ($this->view->works as $work)
if (in_array($work, $this->view->worker->works)) $this->view->exist = true;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'works' => $this->view->render(DIRECTORY_SEPARATOR . 'lists' . DIRECTORY_SEPARATOR . 'works.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не найден сотрудник');
} else throw new exception('Вы не авторизованы');
} else {
// Запрошен список работ
if ($this->account->status()) {
// Авторизован аккаунт
// Инициализация списка работ
$this->view->works = ['Кассир', 'Выкладчик', 'Гастроном', 'Бригадир', 'Грузчик', 'Мобильный грузчик', 'Мобильный универсал'];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'works' => $this->view->render(DIRECTORY_SEPARATOR . 'lists' . DIRECTORY_SEPARATOR . 'works.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Вы не авторизованы');
}
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Записать тип работы
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function work(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора, оператора или магазина
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $task->market !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для редактирования типа работы этой заявки');
// Заявка подтверждена?
if ($task->confirmed) throw new exception('Запрещено редактировать тип работы у подтверждённой заявки');
if ($this->account->type === 'market') {
// Магазин
// Инициализация даты
$date = (new DateTime('@' . $task->date))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'));
// Инициализация времени
$start = datetime::createFromFormat('H:i', (string) $task->start);
$end = datetime::createFromFormat('H:i', (string) $task->end);
// Перенос времени в дату
$start = $date->setTime((int) $start->format('H'), (int) $start->format('i'))->format('U');
$end = $date->setTime((int) $end->format('H'), (int) $end->format('i'))->format('U');
// Заявка уже начата?
if (time() - $start > 0 && time() - $end < 0)
throw new exception('Запрещено редактировать тип работы начатой заявки');
// Заявка уже прошла?
else if (time() - $end > 0 && $task->completed !== true)
throw new exception('Запрещено редактировать тип работы прошедшей заявки');
// Заявка уже завершена?
else if ($task->completed === true)
throw new exception('Запрещено редактировать тип работы завершённой заявки');
// Прошло более 30 минут после создания заявки? (1800 секунд = 30 минут)
/* if (time() - $task->created > 1800)
throw new exception('Запрещено редактировать заявку спустя 30 минут после создания'); */
// До начала заявки осталось менее 16 часов? (57600 секунд = 16 часов)
if ($start - time() < 57600)
throw new exception('Запрещено редактировать тип работы заявки за менее 16 часов до её начала');
}
if ($task instanceof _document) {
// Найдена заявка
// Изменение статуса
$task->work = match ($parameters['work']) {
'Кассир', 'Выкладчик', 'Грузчик', 'Гастроном' => $parameters['work'],
default => 'Кассир'
};
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано в ArangoDB
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись в глобальную переменную шаблонизатора обрабатываемой страницы (отключение)
$this->view->page = null;
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'writed' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Записать описание
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function description(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора, оператора или магазина
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $task->market !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для редактирования описания этой заявки');
// Заявка подтверждена?
if ($task->confirmed) throw new exception('Запрещено редактировать описание у подтверждённой заявки');
// Инициализация даты
$date = (new DateTime('@' . $task->date))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'));
// Инициализация времени
$start = datetime::createFromFormat('H:i', (string) $task->start);
$end = datetime::createFromFormat('H:i', (string) $task->end);
// Перенос времени в дату
$start = $date->setTime((int) $start->format('H'), (int) $start->format('i'))->format('U');
$end = $date->setTime((int) $end->format('H'), (int) $end->format('i'))->format('U');
// Заявка уже начата
if ($this->account->type === 'market' and time() - $start > 0)
throw new exception('Запрещено редактировать описание начатой заявки');
// Заявка уже завершена
if ($this->account->type === 'market' and $task->completed === true || time() - $end > 0)
throw new exception('Запрещено редактировать описание завершённой заявки');
if ($task instanceof _document) {
// Найдена заявка
// Изменение статуса
$task->description = $parameters['description'];
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано в ArangoDB
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'writed' => true,
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Записать дату и время
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function date(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator' || $this->account->type === 'market')) {
// Авторизован аккаунт администратора, оператора или магазина
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
// Заявка не принадлежит запросившему магазину?
if ($this->account->type === 'market' and $task->market !== account::market($this->account->getId())?->id)
throw new exception('Вы не авторизованы для редактирования даты и времени этой заявки');
// Заявка подтверждена?
if ($task->confirmed) throw new exception('Запрещено редактировать дату и время у подтверждённой заявки');
if ($this->account->type === 'market') {
// Магазин
// Инициализация даты
$date = (new DateTime('@' . $task->date))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk'));
// Инициализация времени
$start = datetime::createFromFormat('H:i', (string) $task->start);
$end = datetime::createFromFormat('H:i', (string) $task->end);
// Перенос времени в дату
$start = $date->setTime((int) $start->format('H'), (int) $start->format('i'))->format('U');
$end = $date->setTime((int) $end->format('H'), (int) $end->format('i'))->format('U');
// Заявка уже начата?
if (time() - $start > 0 && time() - $end < 0)
throw new exception('Запрещено редактировать дату и время начатой заявки');
// Заявка уже прошла?
else if (time() - $end > 0 && $task->completed !== true)
throw new exception('Запрещено редактировать дату и время прошедшей заявки');
// Заявка уже завершена?
else if ($task->completed === true)
throw new exception('Запрещено редактировать дату и время завершённой заявки');
// Прошло более 30 минут после создания заявки? (1800 секунд = 30 минут)
/* if (time() - $task->created > 1800)
throw new exception('Запрещено редактировать заявку спустя 30 минут после создания'); */
// До начала заявки осталось менее 16 часов? (57600 секунд = 16 часов)
if ($start - time() < 57600)
throw new exception('Запрещено редактировать дату и время заявки за менее 16 часов до её начала');
}
if ($task instanceof _document) {
// Найдена заявка
// Запись даты и времени
if (!empty($parameters['date'])) $task->date = +$parameters['date'];
if (!empty($parameters['start'])) $task->start = $parameters['start'];
if (!empty($parameters['end'])) $task->end = $parameters['end'];
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано в ArangoDB
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'writed' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Записать комментарий
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function commentary(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
if ($task instanceof _document) {
// Найдена заявка
// Запись комментария
$task->commentary = $parameters['commentary'];
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано в ArangoDB
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'writed' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Опубликовать
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function publish(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
if ($task instanceof _document) {
// Найдена заявка
// Запись статуса о публикации
$task->published = true;
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано в ArangoDB
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'published' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Снять с публикации
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function unpublish(array $parameters = []): void
{
try {
if ($this->account->status() && ($this->account->type === 'administrator' || $this->account->type === 'operator')) {
// Авторизован аккаунт администратора или оператора
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
if ($task instanceof _document) {
// Найдена заявка
// Запись статуса о публикации
$task->published = false;
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано в ArangoDB
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'unpublished' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось обновить заявку');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Сгенерировать чат
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function chat(array $parameters = []): void
{
try {
if ($this->account->status()) {
// Авторизован аккаунт (любой)
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
if ($task instanceof _document) {
// Найдена заявка
// Инициализация функции сортировки сообщений по дате
function sort(array $a, array $b)
{
if ($a['date'] === $b['date']) return 0;
return $a['date'] > $b['date'] ? 1 : -1;
}
if ($parameters['chat'] === 'worker') {
// Сотрудник
if (
$this->account->type === 'operator'
|| $this->account->type === 'administrator'
|| ($this->account->type === 'worker' && $task->worker === account::worker($this->account->getId())?->id)
) {
// Авторизован аккаунт (если сотрудник, то назначен на эту заявку)
// Инициализация буфера чата
$chat = $task->chats;
if ($this->account->type === 'worker') {
// Сотрудник
foreach ($task->chats['worker'] ?? [] as $key => $message) {
// Перебор сообщений
// Запись статуса о прочтении сообщения
$chat = [
'worker' => [
$key => [
'readed' => [
$this->account->getKey() => true
] + ($chat['worker'][$key]['readed'] ?? [])
] + $chat['worker'][$key]
] + $chat['worker']
] + $chat;
}
} else if ($this->account->type === 'operator' || $this->account->type === 'administrator') {
// Оператор или администратор
// Из-за того, что отправляется сразу 2 запроса, то не успевает записаться как прочитанный чат либо сотрудника, либо магазина
foreach ($task->chats ?? [] as $name => $messages)
foreach ($messages as $key => $message) {
// Перебор сообщений
// Запись статуса о прочтении сообщения
$chat = [
$name => [
$key => [
'readed' => [
$this->account->getKey() => true
] + ($chat[$name][$key]['readed'] ?? [])
] + $chat[$name][$key]
] + $chat[$name]
] + $chat;
}
}
// Запись чата из буфера
$task->chats = $chat;
// Запись данных чтения сообщений в ArangoDB
if (!_core::update($task)) throw new exception('Не удалось прочитать сообщения');
// Запись сообщений в буфер сортировки
$buffer = $task->chats['worker'] ?? [];
// Сортировка
if (count($buffer) > 1) uasort($buffer, __NAMESPACE__ . '\sort');
// Запись из буфера сортировки в буфер шаблонизатора
$this->view->messages = $buffer;
} else throw new exception('Вы не авторизованы для чтения этого чата');
} else if ($parameters['chat'] === 'market') {
// Магазин
if (
$this->account->type === 'operator'
|| $this->account->type === 'administrator'
|| ($this->account->type === 'market' && $task->market === account::market($this->account->getId())?->id)
) {
// Авторизован аккаунт (если магазин, то назначен на эту заявку)
// Инициализация буфера чата
$chat = $task->chats;
if ($this->account->type === 'market') {
// Магазин
foreach ($task->chats['market'] ?? [] as $key => $message) {
// Перебор сообщений
// Запись статуса о прочтении сообщения
$chat = [
'market' => [
$key => [
'readed' => [
$this->account->getKey() => true
] + $chat['market'][$key]['readed'] ?? []
] + $chat['market'][$key]
] + $chat['market']
] + $chat;
}
} else if ($this->account->type === 'operator' || $this->account->type === 'administrator') {
// Оператор или администратор
// Из-за того, что отправляется сразу 2 запроса, то не успевает записаться как прочитанный чат либо сотрудника, либо магазина
foreach ($task->chats ?? [] as $name => $messages)
foreach ($messages as $key => $message) {
// Перебор сообщений
// Запись статуса о прочтении сообщения
$chat = [
$name => [
$key => [
'readed' => [
$this->account->getKey() => true
] + ($chat[$name][$key]['readed'] ?? [])
] + $chat[$name][$key]
] + $chat[$name]
] + $chat;
}
}
// Запись чата из буфера
$task->chats = $chat;
// Запись данных чтения сообщений в ArangoDB
if (!_core::update($task)) throw new exception('Не удалось прочитать сообщения');
// Запись сообщений в буфер сортировки
$buffer = $task->chats['market'] ?? [];
// Сортировка
if (count($buffer) > 1) uasort($buffer, __NAMESPACE__ . '\sort');
// Запись из буфера сортировки в буфер шаблонизатора
$this->view->messages = $buffer;
} else throw new exception('Вы не авторизованы для чтения этого чата');
}
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'chat' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'chat.html'),
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
/**
* Записать сообщение
*
* @param array $parameters Параметры запроса
*
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
*/
public function message(array $parameters = []): void
{
try {
if ($this->account->status()) {
// Авторизован аккаунт (любой)
// Инициализация данных
$task = model::read('d._key == "' . $parameters['task'] . '"');
if ($task instanceof _document) {
// Найдена заявка
if (mb_strlen($parameters['text']) > 0) {
// Получено сообщение
if ($parameters['chat'] === 'worker') {
// Сотрудник
if (
$this->account->type === 'operator'
|| $this->account->type === 'administrator'
|| ($this->account->type === 'worker' && $task->worker === account::worker($this->account->getId())?->id)
) {
// Авторизован аккаунт (если сотрудник, то назначен на эту заявку)
// Инициализация значения по умолчанию
if (!isset($task->chats['worker'])) $task->chats = ['worker' => []] + ($task->chats ?? []);
// Запись сообщения
$task->chats = [
'worker' => [
count($task->chats['worker']) => [
'from' => [
'_key' => $this->account->getKey(),
'type' => $this->account->type
] + ($this->account->type === 'worker' ? ['id' => $task->worker] : []),
'type' => $parameters['type'] ?? 'message',
'text' => $parameters['text'],
'readed' => [$this->account->getKey() => 0],
'date' => time()
]
] + $task->chats['worker']
] + $task->chats;
if ($parameters['type'] === 'problem') {
// Сообщение о проблеме
// Изменение статуса наличия проблемы
$task->problematic = true;
} else if ($parameters['type'] === 'solution') {
// Сообщение о решении проблемы
// Изменение статуса наличия проблемы
$task->problematic = false;
}
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано в ArangoDB
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'sended' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось отправить сообщение');
} else throw new exception('Вы не авторизованы для чтения этого чата');
} else if ($parameters['chat'] === 'market') {
// Магазин
if (
$this->account->type === 'operator'
|| $this->account->type === 'administrator'
|| ($this->account->type === 'market' && $task->market === account::market($this->account->getId())?->id)
) {
// Авторизован аккаунт (если магазин, то назначен на эту заявку)
// Инициализация значения по умолчанию
if (!isset($task->chats['market'])) $task->chats = ['market' => []] + ($task->chats ?? []);
// Запись сообщения
$task->chats = [
'market' => [
count($task->chats['market']) => [
'from' => [
'_key' => $this->account->getKey(),
'type' => $this->account->type
] + ($this->account->type === 'market' ? ['id' => $task->market] : []),
'type' => $parameters['type'] ?? 'message',
'text' => $parameters['text'],
'readed' => [$this->account->getKey() => 0],
'date' => time()
]
] + $task->chats['market']
] + $task->chats;
if ($parameters['type'] === 'problem') {
// Сообщение о проблеме
// Изменение статуса наличия проблемы
$task->problematic = true;
} else if ($parameters['type'] === 'solution') {
// Сообщение о решении проблемы
// Изменение статуса наличия проблемы
$task->problematic = false;
}
// Запись в реестре последних обновивших
$task->updates = [$this->account->type => match ($this->account->type) {
'worker', 'market' => account::{$this->account->type}($this->account->getId())?->id,
default => $this->account->getKey()
}] + ($task->updates ?? []);
if (_core::update($task)) {
// Записано в ArangoDB
// Инициализация строки в глобальную переменную шаблонизатора
$this->view->rows = static::preprocessing($this->account, model::list(before: 'FILTER task._key == "' . $parameters['task'] . '"', amount: 1));
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'sended' => true,
'row' => $this->view->render(DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR . 'tasks.html'),
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
} else throw new exception('Не удалось отправить сообщение');
} else throw new exception('Вы не авторизованы для чтения этого чата');
}
} else throw new exception('Необходимо передать сообщение');
} else throw new exception('Не найдена заявка');
} else throw new exception('Вы не авторизованы');
} catch (exception $e) {
// Запись в реестр ошибок
$this->errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
// Запись заголовков ответа
header('Content-Type: application/json');
header('Content-Encoding: none');
header('X-Accel-Buffering: no');
// Инициализация буфера вывода
ob_start();
// Генерация ответа
echo json_encode(
[
'sended' => false,
'errors' => self::parse_only_text($this->errors)
]
);
// Запись заголовков ответа
header('Content-Length: ' . ob_get_length());
// Отправка и деинициализация буфера вывода
ob_end_flush();
flush();
}
}
}