diff --git a/mirzaev/ebala/system/controllers/session.php b/mirzaev/ebala/system/controllers/session.php index 7e4d95e..afb44fc 100755 --- a/mirzaev/ebala/system/controllers/session.php +++ b/mirzaev/ebala/system/controllers/session.php @@ -364,8 +364,8 @@ final class session extends core // Проверка параметров на соответствование требованиям if ($length === 0) throw new exception('Идентификатор аккаунта аккаунта не может быть пустым'); - if ($length > 40) throw new exception('Идентификатор аккаунта аккаунта должен иметь не более 40 символов'); - if (preg_match_all('/[^\d\(\)\-\s\r\n\t\0]+/u', $parameters['market'], $matches) > 0) throw new exception('Нельзя использовать символы: ' . implode(', ', ...$matches ?? [])); + if ($length > 3) throw new exception('Идентификатор аккаунта аккаунта должен иметь не более 3 символов'); + if (preg_match_all('/[^\d]+/u', $parameters['market'], $matches) > 0) throw new exception('Нельзя использовать символы: ' . implode(', ', ...$matches ?? [])); if ($remember = isset($parameters['remember']) && $parameters['remember'] === '1') { // Запрошено запоминание diff --git a/mirzaev/ebala/system/controllers/task.php b/mirzaev/ebala/system/controllers/task.php index be0569d..26e47e7 100755 --- a/mirzaev/ebala/system/controllers/task.php +++ b/mirzaev/ebala/system/controllers/task.php @@ -542,8 +542,46 @@ final class task extends core // Заявка подтверждена? if ($task->confirmed) throw new exception('Запрещено редактировать подтверждённую заявку'); - // Заявка завершена? - if ($this->account->type === 'market' && $task->completed) 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) + throw new exception('Запрещено редактировать начатую заявку'); + + // Заявка уже прошла? + if (time() - $end > 0) + throw new exception('Запрещено редактировать прошедшую заявку'); + + // Заявка уже завершена? + 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'])) { // Передан сотрудник @@ -786,7 +824,7 @@ final class task extends core 'd._key == "' . $parameters['task'] . '"', return: $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 }' - : '{_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 }' + : '{_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 }' )->getAll(); // Заявка не принадлежит запросившему магазину? @@ -821,7 +859,18 @@ final class task extends core // Перевод ключей на русский язык foreach ($this->view->task as $key => $value) - if (match ($key) { + if ($key === 'updates') + foreach ($value as $key => $value) $buffer['updates'][$key] = [ + 'label' => match ($key) { + 'operator' => 'Оператор', + 'market' => 'Магазин', + 'administrator' => 'Администратор', + 'worker' => 'Сотрудник', + default => $key + }, + 'value' => $value + ]; + else if (match ($key) { 'created', 'updated', 'confirmed', 'hided', 'completed', '_key' => true, 'start', 'end' => $passed, // Только для завершённой заявки default => false @@ -909,7 +958,6 @@ final class task extends core } } - /** * Прочитать данные сотрудника * @@ -958,6 +1006,7 @@ final class task extends core 'tax' => 'ИНН', 'city' => 'Город', 'payment' => 'Форма оплаты', + 'works' => 'Формы работ', default => $key }, 'value' => $value @@ -1158,6 +1207,12 @@ final class task extends core // Изменение статуса подтверждения $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)) { // Записано изменение в базу данных @@ -1277,6 +1332,12 @@ final class task extends core } } + // Запись в ресстре последних обновивших + $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)) { // Записано изменение в базу данных @@ -1409,6 +1470,12 @@ final class task extends core $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)) { // Записано изменение в базу данных @@ -1500,6 +1567,12 @@ final class task extends core // Изменение статуса скрытия $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)) { // Записано изменение в базу данных @@ -1591,28 +1664,40 @@ final class task extends core // Заявка подтверждена? if ($task->confirmed) throw new exception('Запрещено удалять подтверждённую заявку'); - // Инициализация даты - $date = (new DateTime('@' . $task->date))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk')); + if ($this->account->type === 'market') { + // Магазин - // Инициализация времени - $start = datetime::createFromFormat('H:i', (string) $task->start); - $end = datetime::createFromFormat('H:i', (string) $task->end); + // Инициализация даты + $date = (new DateTime('@' . $task->date))->setTimezone(new DateTimeZone('Asia/Krasnoyarsk')); - // Перенос времени в дату - $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'); + // Инициализация времени + $start = datetime::createFromFormat('H:i', (string) $task->start); + $end = datetime::createFromFormat('H:i', (string) $task->end); - // Заявка уже начата - if ($this->account->type === 'market' and time() - $start > 0) - throw new exception('Запрещено удалять начатую заявку'); + // Перенос времени в дату + $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 $task->completed === true || time() - $end > 0) - throw new exception('Запрещено удалять завершённую заявку'); + // Заявка уже начата? + if (time() - $start > 0) + throw new exception('Запрещено удалять начатую заявку'); - // Прошло более 30 минут после создания заявки? (1800 секунд = 30 минут) - if ($this->account->type === 'market' and time() - $task->created > 1800) - throw new exception('Запрещено удалять заявку спустя 30 минут после создания'); + // Заявка уже прошла? + if (time() - $end > 0) + throw new exception('Запрещено удалять прошедшую заявку'); + + // Заявка уже завершена? + 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) { // Найдена заявка @@ -1620,6 +1705,12 @@ final class task extends core // Изменение статуса $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)) { // Помечено как удалённое @@ -1761,7 +1852,6 @@ final class task extends core } } - /** * Прочитать данные работ для * @@ -1985,6 +2075,12 @@ final class task extends core 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 @@ -2101,6 +2197,12 @@ final class task extends core // Изменение статуса $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 @@ -2212,6 +2314,12 @@ final class task extends core 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 @@ -2299,6 +2407,12 @@ final class task extends core // Запись комментария $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 @@ -2386,6 +2500,12 @@ final class task extends core // Запись статуса о публикации $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 @@ -2473,6 +2593,12 @@ final class task extends core // Запись статуса о публикации $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 @@ -2822,6 +2948,12 @@ final class task extends core $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 @@ -2894,6 +3026,12 @@ final class task extends core $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 @@ -2907,7 +3045,6 @@ final class task extends core // Инициализация буфера вывода ob_start(); - // Генерация ответа echo json_encode( [ diff --git a/mirzaev/ebala/system/public/css/popup.css b/mirzaev/ebala/system/public/css/popup.css index f7c444d..95f28c5 100644 --- a/mirzaev/ebala/system/public/css/popup.css +++ b/mirzaev/ebala/system/public/css/popup.css @@ -296,3 +296,10 @@ div#popup>section.list>section.main>div.column>section.row.message>textarea+butt div#popup>section.list.errors>section.body>dl>dd { margin-left: 20px; } + +div#popup > section.list .separator { + border-top: 2px solid var(--separator, var(--cloud)); + padding-top: 10px; + margin-top: 10px; + margin-bottom: 10px; +} diff --git a/mirzaev/ebala/system/public/js/tasks.js b/mirzaev/ebala/system/public/js/tasks.js index 66e979f..e8e4d3c 100755 --- a/mirzaev/ebala/system/public/js/tasks.js +++ b/mirzaev/ebala/system/public/js/tasks.js @@ -2210,9 +2210,37 @@ if (typeof window.tasks !== "function") { }); }); + // Инициализация оболочки для кнопок + const buttons_worker = document.createElement("div"); + buttons_worker.classList.add("row", "buttons", "divided", "merged"); + + // Инициализация кнопки подтверждения + const ban = document.createElement("button"); + if (true) { + // Забанен сотрудник + + ban.classList.add("earth", "stretched"); + ban.innerText = "Разблокировать"; + ban.setAttribute('title', 'Сотрудник снова сможет записываться на ваши заявки'); + ban.setAttribute( + "onclick", + `tasks.unban(this, this.parentElement.previousElementSibling.previousElementSibling.children[0], this.parentElement.previousElementSibling, document.getElementById('${task}'))` + ); + } else { + // Не забанен сотрудник + + ban.classList.add("clay", "stretched"); + ban.innerText = "Заблокировать"; + ban.setAttribute('title', 'Сотрудник не сможет записываться на ваши заявки'); + ban.setAttribute( + "onclick", + `tasks.ban(this, this.parentElement.previousElementSibling.previousElementSibling.children[0], this.parentElement.previousElementSibling, document.getElementById('${task}'))` + ); + } + // Инициализация оболочки для кнопок const buttons = document.createElement("div"); - buttons.classList.add("row", "buttons"); + buttons.classList.add("row", "buttons", "merged"); // Инициализация кнопки заявления о проблеме const problem = document.createElement("button"); @@ -2297,6 +2325,9 @@ if (typeof window.tasks !== "function") { if (data.completed !== true) { // Зявка не завершена + buttons_worker.appendChild(ban); + column.appendChild(buttons_worker); + buttons.appendChild(problem); buttons.appendChild(complete); column.appendChild(buttons); diff --git a/mirzaev/ebala/system/views/elements/lists/market.html b/mirzaev/ebala/system/views/elements/lists/market.html index 899f8ec..f28b03d 100644 --- a/mirzaev/ebala/system/views/elements/lists/market.html +++ b/mirzaev/ebala/system/views/elements/lists/market.html @@ -1,5 +1,5 @@ -{% for key, data in market | filter((data, key) => key != 'id') -%} +{% for key, data in market | filter((data, key) => key != 'id' and key != '_key') -%} {% if key == 'created' or key == 'updated' %} {{ data.label }}:{{ data.value is empty ? 'Никогда' : data.value|date('Y.m.d H:i:s') }} diff --git a/mirzaev/ebala/system/views/elements/lists/task/actual.html b/mirzaev/ebala/system/views/elements/lists/task/actual.html index ea8e4d6..cdf7c79 100644 --- a/mirzaev/ebala/system/views/elements/lists/task/actual.html +++ b/mirzaev/ebala/system/views/elements/lists/task/actual.html @@ -1,5 +1,5 @@ -{% for key, data in task | filter((data, key) => key != '_key') -%} +{% for key, data in task | filter((data, key) => key != '_key' and key != 'updates') -%} {% if (key == 'created' or key == 'updated') %} {{ data.label }}:{{ data.value is empty ? 'Никогда' : data.value|date('d.m.Y H:i') }} @@ -11,3 +11,8 @@ data.value is same as(false) %}Нет{% elseif data.value is empty %}{% else %}{{ data.value }}{% endif %} {% endif %} {% endfor %} +{% if account.type == 'administrator' or account.type == 'operator' %} +{% for key, data in task.updates %} +{{ data.label }}:{% if data.value is empty %}{% else %}{{ data.value }}{% endif %} +{% endfor %} +{% endif %} diff --git a/mirzaev/ebala/system/views/elements/lists/task/passed.html b/mirzaev/ebala/system/views/elements/lists/task/passed.html index 34b2e75..773af38 100644 --- a/mirzaev/ebala/system/views/elements/lists/task/passed.html +++ b/mirzaev/ebala/system/views/elements/lists/task/passed.html @@ -1,5 +1,5 @@ -{% for key, data in task | filter((data, key) => key != '_key') -%} +{% for key, data in task | filter((data, key) => key != '_key' and key != 'updates') -%} {% if (key == 'created' or key == 'updated' or key == 'start' or key == 'end') %} {{ data.label }}:{{ data.value is empty ? 'Никогда' : data.value|date('d.m.Y H:i') }} @@ -11,3 +11,9 @@ data.value is same as(false) %}Нет{% elseif data.value is empty %}{% else %}{{ data.value }}{% endif %} {% endif %} {% endfor %} +{% if account.type == 'administrator' or account.type == 'operator' %} +

Последние изменения

+{% for key, data in task.updates %} +{{ data.label }}:{% if data.value is empty %}{% else %}{{ data.value }}{% endif %} +{% endfor %} +{% endif %} diff --git a/mirzaev/ebala/system/views/elements/lists/worker.html b/mirzaev/ebala/system/views/elements/lists/worker.html index 29b6762..66e7b23 100644 --- a/mirzaev/ebala/system/views/elements/lists/worker.html +++ b/mirzaev/ebala/system/views/elements/lists/worker.html @@ -1,5 +1,5 @@ -{% for key, data in worker | filter((data, key) => key != 'id') -%} +{% for key, data in worker | filter((data, key) => key != 'id' and key != '_key') -%} {% if key == 'created' or key == 'updated' %} {{ data.label }}:{{ data.value is empty ? 'Никогда' : data.value|date('Y.m.d H:i:s') }} diff --git a/mirzaev/ebala/system/views/pages/entry/market.html b/mirzaev/ebala/system/views/pages/entry/market.html index 202d5f0..5bb1720 100755 --- a/mirzaev/ebala/system/views/pages/entry/market.html +++ b/mirzaev/ebala/system/views/pages/entry/market.html @@ -25,7 +25,7 @@ class="icon arrow right"> {% for account in accounts %} - {% endfor %} @@ -74,7 +74,7 @@ fields.password.button = fields.password.label.getElementsByTagName('button')[0]; // Инициализация маски идентификатора магазина - fields.market.input.mask = IMask(fields.market.input, {mask: '000000000000'}); + fields.market.input.mask = IMask(fields.market.input, {mask: '000'}); /** * Отправить входной псевдоним на сервер