Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
6c4c0b1ada | |||
5641a686a2 | |||
da90b0c533 | |||
db9c99390e |
@@ -2,4 +2,6 @@
|
|||||||
Site-registry of tasks for outsourced employees
|
Site-registry of tasks for outsourced employees
|
||||||
|
|
||||||
From this project i earned **700 000** Russian rubles</br>
|
From this project i earned **700 000** Russian rubles</br>
|
||||||
*As long as commits appear in the repository, this means that i continue paid development*
|
*As long as commits appear in the repository, this means that i continue paid development*</br>
|
||||||
|
</br>
|
||||||
|
I am selling this site to **capitalist scum** for a lot of money, but you, friend, can use my code **for free** ✌️
|
||||||
|
@@ -34,7 +34,7 @@ final class task extends core
|
|||||||
/**
|
/**
|
||||||
* Создать
|
* Создать
|
||||||
*
|
*
|
||||||
* @param array $parameters Параметры запроса
|
* @param array $parameters Параметры запроса (json в php://input)
|
||||||
*
|
*
|
||||||
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
|
* @return void В буфер вывода JSON-документ с запрашиваемыми параметрами
|
||||||
*/
|
*/
|
||||||
@@ -47,33 +47,50 @@ final class task extends core
|
|||||||
// Инициализация буфера ошибок
|
// Инициализация буфера ошибок
|
||||||
$this->errors['tasks'] ??= [];
|
$this->errors['tasks'] ??= [];
|
||||||
|
|
||||||
// Создание строк
|
if (!empty($json = json_decode(file_get_contents('php://input'), true, 4))) {
|
||||||
for ($i = 0, $parameters['cashiers'] = (int) $parameters['cashiers']; $i < $parameters['cashiers']; ++$i) model::create(work: 'Кассир', market: $this->account->type === 'market' ? account::market($this->account->getId())?->id : null, start: $parameters['start'], end: $parameters['end'], date: $parameters['date'], errors: $this->errors['tasks']);
|
|
||||||
for ($i = 0, $parameters['displayers'] = (int) $parameters['displayers']; $i < $parameters['displayers']; ++$i) model::create(work: 'Выкладчик', market: $this->account->type === 'market' ? account::market($this->account->getId())?->id : null, start: $parameters['start'], end: $parameters['end'], date: $parameters['date'], errors: $this->errors['tasks']);
|
|
||||||
for ($i = 0, $parameters['loaders'] = (int) $parameters['loaders']; $i < $parameters['loaders']; ++$i) model::create(work: 'Грузчик', market: $this->account->type === 'market' ? account::market($this->account->getId())?->id : null, start: $parameters['start'], end: $parameters['end'], date: $parameters['date'], errors: $this->errors['tasks']);
|
|
||||||
for ($i = 0, $parameters['gastronomes'] = (int) $parameters['gastronomes']; $i < $parameters['gastronomes']; ++$i) model::create(work: 'Гастроном', market: $this->account->type === 'market' ? account::market($this->account->getId())?->id : null, start: $parameters['start'], end: $parameters['end'], date: $parameters['date'], errors: $this->errors['tasks']);
|
|
||||||
|
|
||||||
// Запись заголовков ответа
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
header('Content-Encoding: none');
|
|
||||||
header('X-Accel-Buffering: no');
|
|
||||||
|
|
||||||
// Инициализация буфера вывода
|
foreach ($json as $work => $tasks) {
|
||||||
ob_start();
|
// Перебор категорий (колонок)
|
||||||
|
|
||||||
// Генерация ответа
|
foreach ($tasks as $task) {
|
||||||
echo json_encode(
|
// Перебор заявок
|
||||||
[
|
|
||||||
'errors' => self::parse_only_text($this->errors)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Запись заголовков ответа
|
// Создание заявки
|
||||||
header('Content-Length: ' . ob_get_length());
|
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']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Отправка и деинициализация буфера вывода
|
// Запись заголовков ответа
|
||||||
ob_end_flush();
|
header('Content-Type: application/json');
|
||||||
flush();
|
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('Вы не авторизованы');
|
} else throw new exception('Вы не авторизованы');
|
||||||
} catch (exception $e) {
|
} catch (exception $e) {
|
||||||
// Запись в реестр ошибок
|
// Запись в реестр ошибок
|
||||||
@@ -443,7 +460,8 @@ final class task extends core
|
|||||||
$link->task['start'] instanceof datetime
|
$link->task['start'] instanceof datetime
|
||||||
&& $link->task['end'] instanceof datetime
|
&& $link->task['end'] instanceof datetime
|
||||||
) {
|
) {
|
||||||
$generated['hours'] = (float) $link->task['end']->diff($link->task['start'])->format('%H.%i');
|
$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;
|
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'] >= 9 && $generated['hours'] < 12.5) $generated['hours'] -= 1;
|
||||||
else if ($generated['hours'] >= 12.5) $generated['hours'] -= 1.5;
|
else if ($generated['hours'] >= 12.5) $generated['hours'] -= 1.5;
|
||||||
@@ -1757,7 +1775,7 @@ final class task extends core
|
|||||||
// Найдена заявка
|
// Найдена заявка
|
||||||
|
|
||||||
// Инициализация списка работ
|
// Инициализация списка работ
|
||||||
$this->view->works = ['Кассир', 'Выкладчик', 'Грузчик', 'Гастроном'];
|
$this->view->works = ['Кассир', 'Выкладчик', 'Гастроном', 'Бригадир', 'Грузчик', 'Мобильный грузчик', 'Мобильный универсал'];
|
||||||
|
|
||||||
// Проверка на существование записанной в задаче работы в списке существующих работ и запись об этом в глобальную переменную шаблонизатора
|
// Проверка на существование записанной в задаче работы в списке существующих работ и запись об этом в глобальную переменную шаблонизатора
|
||||||
foreach ($this->view->works as $work) if ($this->view->task->work === $work) $this->view->exist = true;
|
foreach ($this->view->works as $work) if ($this->view->task->work === $work) $this->view->exist = true;
|
||||||
|
@@ -135,7 +135,7 @@ final class account extends core
|
|||||||
if (!empty($session->buffer['market']['entry']['password'])) {
|
if (!empty($session->buffer['market']['entry']['password'])) {
|
||||||
// Найден пароль в буфере сессии
|
// Найден пароль в буфере сессии
|
||||||
|
|
||||||
if (($account = market::account(market::read('d.id == "' . $session->buffer['market']['entry']['id'] . '"', amount: 1)?->getId())) instanceof _document) {
|
if (($account = market::account(market::read('d.id == "' . $session->buffer['market']['entry']['id'] . '"', amount: 1)?->getId()) ?? null) instanceof _document) {
|
||||||
// Найден аккаунт (игнорируются ошибки)
|
// Найден аккаунт (игнорируются ошибки)
|
||||||
|
|
||||||
if (sodium_crypto_pwhash_str_verify($account->password, $session->buffer['market']['entry']['password'])) {
|
if (sodium_crypto_pwhash_str_verify($account->password, $session->buffer['market']['entry']['password'])) {
|
||||||
|
@@ -40,7 +40,7 @@ final class task extends core
|
|||||||
/**
|
/**
|
||||||
* Create task in ArangoDB
|
* Create task in ArangoDB
|
||||||
*
|
*
|
||||||
* @param ?string $date
|
* @param string|int|null $date
|
||||||
* @param ?string $worker
|
* @param ?string $worker
|
||||||
* @param ?string $work
|
* @param ?string $work
|
||||||
* @param ?string $start
|
* @param ?string $start
|
||||||
@@ -51,12 +51,13 @@ final class task extends core
|
|||||||
* @param bool $hided
|
* @param bool $hided
|
||||||
* @param bool $problematic
|
* @param bool $problematic
|
||||||
* @param bool $completed
|
* @param bool $completed
|
||||||
|
* @param ?string $commentary
|
||||||
* @param array $errors
|
* @param array $errors
|
||||||
*
|
*
|
||||||
* @return ?string Identificator of instance of ArangoDB
|
* @return ?string Identificator of instance of ArangoDB
|
||||||
*/
|
*/
|
||||||
public static function create(
|
public static function create(
|
||||||
?string $date = null,
|
string|int|null $date = null,
|
||||||
?string $worker = null,
|
?string $worker = null,
|
||||||
?string $work = null,
|
?string $work = null,
|
||||||
?string $start = null,
|
?string $start = null,
|
||||||
@@ -67,6 +68,7 @@ final class task extends core
|
|||||||
bool $hided = false,
|
bool $hided = false,
|
||||||
bool $problematic = false,
|
bool $problematic = false,
|
||||||
bool $completed = false,
|
bool $completed = false,
|
||||||
|
?string $commentary = null,
|
||||||
array &$errors = []
|
array &$errors = []
|
||||||
): ?string {
|
): ?string {
|
||||||
try {
|
try {
|
||||||
@@ -90,6 +92,7 @@ final class task extends core
|
|||||||
'hided' => $hided,
|
'hided' => $hided,
|
||||||
'problematic' => $problematic,
|
'problematic' => $problematic,
|
||||||
'completed' => $completed,
|
'completed' => $completed,
|
||||||
|
'commentary' => $commentary,
|
||||||
]);
|
]);
|
||||||
} else throw new exception('Не удалось инициализировать коллекции');
|
} else throw new exception('Не удалось инициализировать коллекции');
|
||||||
} catch (exception $e) {
|
} catch (exception $e) {
|
||||||
@@ -145,8 +148,8 @@ final class task extends core
|
|||||||
<<<AQL
|
<<<AQL
|
||||||
FOR task IN %s
|
FOR task IN %s
|
||||||
%s
|
%s
|
||||||
LET worker = (FOR worker in %s FILTER worker.id LIKE task.worker SORT worker.created DESC, worker.id DESC LIMIT 1 RETURN worker)[0]
|
LET worker = (FOR worker in %s FILTER worker.id != null && worker.id LIKE task.worker SORT worker.created DESC, worker.id DESC LIMIT 1 RETURN worker)[0]
|
||||||
LET market = (FOR market in %s FILTER market.id LIKE task.market SORT market.created DESC, market.id DESC LIMIT 1 RETURN market)[0]
|
LET market = (FOR market in %s FILTER market.id != null && market.id LIKE task.market SORT market.created DESC, market.id DESC LIMIT 1 RETURN market)[0]
|
||||||
%s
|
%s
|
||||||
SORT %s
|
SORT %s
|
||||||
LIMIT %d, %d
|
LIMIT %d, %d
|
||||||
@@ -180,4 +183,25 @@ final class task extends core
|
|||||||
// Exit (fail)
|
// Exit (fail)
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate work type label in Russian
|
||||||
|
*
|
||||||
|
* @param string $work Type of work
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function label(string $work): string
|
||||||
|
{
|
||||||
|
return match (mb_strtolower($work)) {
|
||||||
|
'cashiers', 'cashier', 'кассиры', 'кассир' => 'Кассир',
|
||||||
|
'displayers', 'displayer', 'выкладчики', 'выкладчик' => 'Выкладчик',
|
||||||
|
'gastronomes', 'gastronome', 'гастрономы', 'гастроном' => 'Гастроном',
|
||||||
|
'brigadiers', 'brigadier', 'бригадиры', 'бригадир' => 'Бригадир',
|
||||||
|
'loaders', 'loader', 'грузчики', 'грузчик' => 'Грузчик',
|
||||||
|
'loaders_mobile', 'loader_mobile', 'мобильные грузчики', 'мобильный грузчик' => 'Мобильный грузчик',
|
||||||
|
'universals_mobile', 'universal_mobile', 'мобильные универсалы', 'мобильный универсал' => 'Мобильный универсал',
|
||||||
|
default => $work
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -90,6 +90,45 @@ final class worker extends core
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate identifier
|
||||||
|
*
|
||||||
|
* @param array &$errors Реестр ошибок
|
||||||
|
*
|
||||||
|
* @return int Идентиикатор (свободный)
|
||||||
|
*/
|
||||||
|
public static function id(array &$errors = []): int
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (collection::init(static::$arangodb->session, static::COLLECTION)) {
|
||||||
|
// Инициализирована коллекция
|
||||||
|
|
||||||
|
// Exit (success)
|
||||||
|
return collection::search(
|
||||||
|
static::$arangodb->session,
|
||||||
|
sprintf(
|
||||||
|
<<<'AQL'
|
||||||
|
RETURN MAX((FOR d in %s RETURN +d.id))
|
||||||
|
AQL,
|
||||||
|
$collection ?? static::COLLECTION
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else throw new exception('Не удалось инициализировать коллекцию');
|
||||||
|
} catch (exception $e) {
|
||||||
|
// Запись в реестр ошибок
|
||||||
|
$errors[] = [
|
||||||
|
'text' => $e->getMessage(),
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
'stack' => $e->getTrace()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit (fail)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Записать
|
* Записать
|
||||||
*
|
*
|
||||||
|
@@ -302,12 +302,14 @@ label * {
|
|||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
|
--padding-x: 12px;
|
||||||
|
--padding-y: 8px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-width: calc(100% - 24px);
|
min-width: calc(100% - 24px);
|
||||||
min-height: 120px;
|
min-height: 120px;
|
||||||
max-width: calc(100% - 24px);
|
max-width: calc(100% - 24px);
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
padding: 8px 12px;
|
padding: var(--padding-y, 8px) var(--padding-x, 12px);
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
@@ -44,9 +44,12 @@ div#popup>section.calculated {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div#popup>section.list {
|
div#popup>section.list {
|
||||||
|
max-width: max(70vw, 1300px);
|
||||||
|
max-height: max(62vh, 600px);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
|
overflow-y: scroll;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,17 +68,30 @@ div#popup>section.list h4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div#popup>section.list>section.main {
|
div#popup>section.list>section.main {
|
||||||
|
--gap: 15px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 15px;
|
flex-flow: row wrap;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: var(--gap, 15px);
|
||||||
}
|
}
|
||||||
|
|
||||||
div#popup>section.list>section.main>div.column {
|
div#popup>section.list>section.main>div.column {
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div#popup>section.list>section.main.flow>div.column:not(:only-child) {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#popup>section.list>section.main>div.column:not(:only-child)[data-column="buttons"]:last-of-type {
|
||||||
|
margin-left: auto;
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
div#popup>section.list>section.main>div.column:only-child {
|
div#popup>section.list>section.main>div.column:only-child {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -140,7 +156,21 @@ div#popup>section.list>section.main>div.column> :is(div, select).row.buttons {
|
|||||||
|
|
||||||
div#popup>section.list>section.main>div.column> :is(div, select).row:not(.buttons, .stretchable, .endless),
|
div#popup>section.list>section.main>div.column> :is(div, select).row:not(.buttons, .stretchable, .endless),
|
||||||
div#popup>section.list>section.main>div.column> :is(div, select).row:not(.buttons, .stretchable, .endless)>button {
|
div#popup>section.list>section.main>div.column> :is(div, select).row:not(.buttons, .stretchable, .endless)>button {
|
||||||
height: 29px;
|
--height: 29px;
|
||||||
|
height: var(--height, 29px);
|
||||||
|
}
|
||||||
|
|
||||||
|
div#popup>section.list>section.main>div.column> :is(div, select).row:not(.buttons .endless).stretchable,
|
||||||
|
div#popup>section.list>section.main>div.column> :is(div, select).row:not(.buttons, .endless).stretchable>button {
|
||||||
|
--height: 29px;
|
||||||
|
height: max(var(--height, 29px), fit-content);
|
||||||
|
}
|
||||||
|
|
||||||
|
div#popup>section.list>section.main>div.column> :is(div, select).row:not(.buttons .endless).stretchable>textarea {
|
||||||
|
/* min-height: calc(var(--height, 29px) - var(--padding-y, 8ox) * 2); */
|
||||||
|
min-height: 1rem;
|
||||||
|
max-height: 3rem;
|
||||||
|
height: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#popup>section.list>section.main>div.column>:is(div, section).row:not(.merged)+:is(div, section).row.merged {
|
div#popup>section.list>section.main>div.column>:is(div, section).row:not(.merged)+:is(div, section).row.merged {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -2,37 +2,46 @@
|
|||||||
{% for row in rows %}
|
{% for row in rows %}
|
||||||
<div id="{{ row.account._key }}"
|
<div id="{{ row.account._key }}"
|
||||||
class="row{% if row.account.active is same as(true) %} active{% else %} hided{% endif %}" data-row="worker">
|
class="row{% if row.account.active is same as(true) %} active{% else %} hided{% endif %}" data-row="worker">
|
||||||
<span class="unselectable interactive" data-column="account" title="Настройки аккаунта" onclick="workers.account.update(this.parentElement)">{{
|
<span class="unselectable interactive" data-column="account" title="Настройки аккаунта"
|
||||||
|
onclick="workers.account.update(this.parentElement)">{{
|
||||||
row.account._key }}</span>
|
row.account._key }}</span>
|
||||||
<span class="unselectable interactive" data-column="worker" title="Настройки сотрудника" onclick="workers.update(this.parentElement)">{{
|
<span class="unselectable interactive" data-column="worker" title="Настройки сотрудника"
|
||||||
|
onclick="workers.update(this.parentElement)">{{
|
||||||
row.worker.id }}</span>
|
row.worker.id }}</span>
|
||||||
<span class="unselectable interactive" data-column="name"
|
<span class="unselectable interactive" data-column="name"
|
||||||
title="{% if row.worker.name.first is not empty %}{{ row.worker.name.first }}{% endif %}{% if row.worker.name.second is not empty %} {{ row.worker.name.second }}{% endif %}{% if row.worker.name.last is not empty %} {{ row.worker.name.last }}{% endif %}{% if row.worker.birth is not empty %} {{ row.worker.birth|date('d.m.Y') }}{% endif %}" onclick="navigator.clipboard.writeText('{% if row.worker.name.first is not empty %}{{ row.worker.name.first }}{% endif %}{% if row.worker.name.second is not empty %} {{ row.worker.name.second }}{% endif %}{% if row.worker.name.last is not empty %} {{ row.worker.name.last }}{% endif %}{% if row.worker.birth is not empty %} {{ row.worker.birth|date('d.m.Y') }}{% endif %}')">{%
|
title="{% if row.worker.name.first is not empty %}{{ row.worker.name.first }}{% endif %}{% if row.worker.name.second is not empty %} {{ row.worker.name.second }}{% endif %}{% if row.worker.name.last is not empty %} {{ row.worker.name.last }}{% endif %}{% if row.worker.birth is not empty %} {{ row.worker.birth|date('d.m.Y') }}{% endif %}"
|
||||||
|
onclick="navigator.clipboard.writeText('{% if row.worker.name.first is not empty %}{{ row.worker.name.first }}{% endif %}{% if row.worker.name.second is not empty %} {{ row.worker.name.second }}{% endif %}{% if row.worker.name.last is not empty %} {{ row.worker.name.last }}{% endif %}{% if row.worker.birth is not empty %} {{ row.worker.birth|date('d.m.Y') }}{% endif %}')">{%
|
||||||
if row.worker.name.first is not empty %}{{
|
if row.worker.name.first is not empty %}{{
|
||||||
row.worker.name.first|slice(0, 1)|upper }}.{% endif %}{% if row.worker.name.last is not empty %} {{
|
row.worker.name.first|slice(0, 1)|upper }}.{% endif %}{% if row.worker.name.last is not empty %} {{
|
||||||
row.worker.name.last|slice(0, 1)|upper }}.{% endif %}{% if row.worker.name.second is not empty %} {{
|
row.worker.name.last|slice(0, 1)|upper }}.{% endif %}{% if row.worker.name.second is not empty %} {{
|
||||||
row.worker.name.second }}{% endif %}</span>
|
row.worker.name.second }}{% endif %}</span>
|
||||||
<span class="unselectable interactive" data-column="number"><a href="tel:{{ row.worker.number }}"
|
<span class="unselectable interactive" data-column="number"><a href="tel:{{ row.worker.number }}" title="Позвонить">{{
|
||||||
title="Позвонить">{{ row.worker.number|storaged_number_to_readable }}</a></span>
|
row.worker.number|storaged_number_to_readable }}</a></span>
|
||||||
<span class="unselectable interactive" data-column="mail"><a href="mailto:{{ row.worker.mail }}"
|
<span class="unselectable interactive" data-column="mail"><a href="mailto:{{ row.worker.mail }}" title="Написать">{{
|
||||||
title="Написать">{{ row.worker.mail }}</a></span>
|
row.worker.mail }}</a></span>
|
||||||
<span class="unselectable interactive" data-column="address"
|
<span class="unselectable interactive" data-column="address"
|
||||||
title="{{ (row.worker.city ~ ' ' ~ row.worker.district ~ ' ' ~ row.worker.address)|trim }}"
|
title="{{ (row.worker.city ~ ' ' ~ row.worker.district ~ ' ' ~ row.worker.address)|trim }}"
|
||||||
onclick="navigator.clipboard.writeText('{{ row.worker.city ~ ' ' ~ row.worker.district ~ ' ' ~ row.worker.address }}')">{% if row.worker.city is not empty and row.worker.district is not
|
onclick="navigator.clipboard.writeText('{{ row.worker.city ~ ' ' ~ row.worker.district ~ ' ' ~ row.worker.address }}')">{%
|
||||||
|
if row.worker.city is not empty and row.worker.district is not
|
||||||
empty and row.worker.district is not null %}{{ row.worker.city|slice(0,4) ~ '. ' ~ row.worker.district|slice(0,3) ~
|
empty and row.worker.district is not null %}{{ row.worker.city|slice(0,4) ~ '. ' ~ row.worker.district|slice(0,3) ~
|
||||||
'. ' ~ row.worker.address }}{% else %}{{ row.worker.city ~ ' ' ~ row.worker.district ~ ' ' ~ row.worker.address }}{%
|
'. ' ~ row.worker.address }}{% else %}{{ row.worker.city ~ ' ' ~ row.worker.district ~ ' ' ~ row.worker.address }}{%
|
||||||
endif %}</span>
|
endif %}</span>
|
||||||
<span class="unselectable interactive" data-column="passport"
|
<span class="unselectable interactive" data-column="passport"
|
||||||
title="{{ (row.worker.passport ~ ', ' ~ row.worker.issued|date('d.m.Y') ~ ', ' ~ row.worker.department.number ~ ', ' ~ row.worker.department.address)|trim(', ') }}"
|
title="{{ (row.worker.passport ~ ', ' ~ row.worker.issued|date('d.m.Y') ~ ', ' ~ row.worker.department.number ~ ', ' ~ row.worker.department.address)|trim(', ') }}"
|
||||||
onclick="navigator.clipboard.writeText('{{ (row.worker.passport ~ ', ' ~ row.worker.issued|date('d.m.Y') ~ ', ' ~ row.worker.department.number ~ ', ' ~ row.worker.department.address)|trim(', ') }}')">{{ (row.worker.passport ~ ', ' ~ row.worker.issued|date('d.m.Y') ~ ', ' ~ row.worker.department.number ~ ', ' ~
|
onclick="navigator.clipboard.writeText('{{ (row.worker.passport ~ ', ' ~ row.worker.issued|date('d.m.Y') ~ ', ' ~ row.worker.department.number ~ ', ' ~ row.worker.department.address)|trim(', ') }}')">{{
|
||||||
|
(row.worker.passport ~ ', ' ~ row.worker.issued|date('d.m.Y') ~ ', ' ~ row.worker.department.number ~ ', ' ~
|
||||||
row.worker.department.address)|trim(', ') }}</span>
|
row.worker.department.address)|trim(', ') }}</span>
|
||||||
<span class="unselectable interactive" data-column="tax" onclick="navigator.clipboard.writeText('{{ row.worker.tax }}')">{{ row.worker.tax }}</span>
|
<span class="unselectable interactive" data-column="tax"
|
||||||
|
onclick="navigator.clipboard.writeText('{{ row.worker.tax }}')">{{ row.worker.tax }}</span>
|
||||||
<span class="unselectable interactive" data-column="requisites"
|
<span class="unselectable interactive" data-column="requisites"
|
||||||
title="{% if row.worker.requisites is not empty and row.worker.payment is not empty %}{{ row.worker.requisites }} ({{ row.worker.payment }}){% else %}{{ row.worker.payment }}{% endif %}"
|
title="{% if row.worker.requisites is not empty and row.worker.payment is not empty %}{{ row.worker.requisites }} ({{ row.worker.payment }}){% else %}{{ row.worker.requisites }} {{ row.worker.payment }}{% endif %}"
|
||||||
onclick="navigator.clipboard.writeText('{{ row.worker.requisites|storaged_requisites_to_card }}')">{% if
|
onclick="navigator.clipboard.writeText('{{ row.worker.requisites|storaged_requisites_to_card }}')">
|
||||||
row.worker.requisites is not empty and row.worker.payment is not empty %}{{
|
{% if row.worker.requisites is not empty and row.worker.payment is not empty %}
|
||||||
row.worker.requisites|storaged_requisites_preview }} ({{
|
{{ row.worker.requisites|storaged_requisites_preview }} ({{ row.worker.payment }})
|
||||||
row.worker.payment }}){% else %}{{ row.worker.payment }}{% endif %}</span>
|
{% else %}
|
||||||
|
{{ row.worker.requisites }} {{ row.worker.payment }}
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
<span class="unselectable interactive" data-column="commentary" title="{{ row.account.commentary }}"
|
<span class="unselectable interactive" data-column="commentary" title="{{ row.account.commentary }}"
|
||||||
onclick="navigator.clipboard.writeText('{{ row.account.commentary }}')">{{ row.account.commentary }}</span>
|
onclick="navigator.clipboard.writeText('{{ row.account.commentary }}')">{{ row.account.commentary }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user