296 lines
8.6 KiB
PHP
Executable File
296 lines
8.6 KiB
PHP
Executable File
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace mirzaev\ebala\models;
|
||
|
||
// Файлы проекта
|
||
use mirzaev\ebala\models\traits\status;
|
||
|
||
// Фреймворк ArangoDB
|
||
use mirzaev\arangodb\collection,
|
||
mirzaev\arangodb\document;
|
||
|
||
// Библиотека для ArangoDB
|
||
use ArangoDBClient\Document as _document;
|
||
|
||
// System libraries
|
||
use datetime,
|
||
exception;
|
||
|
||
/**
|
||
* Модель заданий
|
||
*
|
||
* @package mirzaev\ebala\models
|
||
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
|
||
*/
|
||
final class task extends core
|
||
{
|
||
use status;
|
||
|
||
/**
|
||
* Collection name in ArangoDB
|
||
*/
|
||
final public const COLLECTION = 'task';
|
||
|
||
/**
|
||
* Инстанция документа в базе данных
|
||
*/
|
||
protected readonly _document $document;
|
||
|
||
/**
|
||
* Create task in ArangoDB
|
||
*
|
||
* @param string|int|null $date
|
||
* @param ?string $worker
|
||
* @param ?string $work
|
||
* @param ?string $start
|
||
* @param ?string $end
|
||
* @param ?string $market
|
||
* @param bool $confirmed
|
||
* @param bool $published
|
||
* @param bool $hided
|
||
* @param bool $problematic
|
||
* @param bool $completed
|
||
* @param ?string $commentary
|
||
* @param array $errors
|
||
*
|
||
* @return ?string Identificator of instance of ArangoDB
|
||
*/
|
||
public static function create(
|
||
string|int|null $date = null,
|
||
?string $worker = null,
|
||
?string $work = null,
|
||
?string $start = null,
|
||
?string $end = null,
|
||
?string $market = null,
|
||
bool $confirmed = false,
|
||
bool $published = false,
|
||
bool $hided = false,
|
||
bool $problematic = false,
|
||
bool $completed = false,
|
||
?string $commentary = null,
|
||
array &$errors = []
|
||
): ?string {
|
||
try {
|
||
if (
|
||
collection::init(static::$arangodb->session, self::COLLECTION)
|
||
&& collection::init(static::$arangodb->session, worker::COLLECTION)
|
||
&& collection::init(static::$arangodb->session, market::COLLECTION)
|
||
) {
|
||
// Инициализированы коллекции
|
||
|
||
// Запись документа в базу данны и возврат (успех)
|
||
return document::write(static::$arangodb->session, self::COLLECTION, [
|
||
'date' => (int) ($date ?? strtotime('+1 day')),
|
||
'worker' => $worker,
|
||
'work' => $work,
|
||
'start' => $start,
|
||
'end' => $end,
|
||
'market' => $market,
|
||
'confirmed' => $confirmed,
|
||
'published' => $published,
|
||
'hided' => $hided,
|
||
'problematic' => $problematic,
|
||
'completed' => $completed,
|
||
'commentary' => $commentary,
|
||
]);
|
||
} else throw new exception('Не удалось инициализировать коллекции');
|
||
} catch (exception $e) {
|
||
// Write to the errors registry
|
||
$errors[] = [
|
||
'text' => $e->getMessage(),
|
||
'file' => $e->getFile(),
|
||
'line' => $e->getLine(),
|
||
'stack' => $e->getTrace()
|
||
];
|
||
}
|
||
|
||
// Exit (fail)
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Read tasks from ArangoDB
|
||
*
|
||
* @param ?string $before Injection of AQL-code before search of worker and market
|
||
* @param ?string $after Injection of AQL-code after search of worker and market
|
||
* @param int $amount Amount of tasks
|
||
* @param int $page Offset by amount
|
||
* @param string $target Collection or view name
|
||
* @param array $binds Binds for query
|
||
* @param array $errors Errors registry
|
||
*
|
||
* @return array Instances from ArangoDB
|
||
*
|
||
* @TODO
|
||
* 1. Remake task.worker with task.market to separate documents (edges) (not important)
|
||
*/
|
||
public static function list(
|
||
?string $before = '',
|
||
?string $after = '',
|
||
int $amount = 100,
|
||
int $page = 1,
|
||
string $sort = 'task.date DESC, task.created DESC, task._key DESC',
|
||
string $target = self::COLLECTION,
|
||
array $binds = [],
|
||
array &$errors = []
|
||
): array {
|
||
try {
|
||
if (
|
||
collection::init(static::$arangodb->session, self::COLLECTION)
|
||
&& collection::init(static::$arangodb->session, worker::COLLECTION)
|
||
&& collection::init(static::$arangodb->session, market::COLLECTION)
|
||
) {
|
||
// Инициализированы коллекции
|
||
|
||
// Search the session data in ArangoDB with VIEW (LET можно заменить на поиск по рёбрам но тут и так сойдёт)
|
||
$tasks = collection::search(static::$arangodb->session, sprintf(
|
||
<<<AQL
|
||
FOR task IN %s
|
||
%s
|
||
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 != null && market.id LIKE task.market SORT market.created DESC, market.id DESC LIMIT 1 RETURN market)[0]
|
||
%s
|
||
SORT %s
|
||
LIMIT %d, %d
|
||
RETURN {task, worker, market}
|
||
AQL,
|
||
$target,
|
||
$before,
|
||
worker::COLLECTION,
|
||
market::COLLECTION,
|
||
$after,
|
||
$sort,
|
||
--$page <= 0 ? 0 : $amount * $page,
|
||
$amount
|
||
), $binds);
|
||
|
||
// Exit (success)
|
||
return empty($tasks) ? [] : (is_array($tasks) ? $tasks : [$tasks]);
|
||
} else throw new exception('Не удалось инициализировать коллекции');
|
||
} catch (exception $e) {
|
||
// Write to the errors registry
|
||
$errors[] = [
|
||
'text' => $e->getMessage(),
|
||
'file' => $e->getFile(),
|
||
'line' => $e->getLine(),
|
||
'stack' => $e->getTrace()
|
||
];
|
||
}
|
||
|
||
// Exit (fail)
|
||
return [];
|
||
}
|
||
|
||
/**
|
||
* Посчитать количество часов работы
|
||
*
|
||
* @param string $start Начало работы (H:i)
|
||
* @param string $end Конец работы (H:i)
|
||
* @param array $errors Errors registry
|
||
*
|
||
* @return ?float Количество часов, если удалось расчитать
|
||
*/
|
||
public static function hours(string $start, string $end, array &$errors = []): ?float
|
||
{
|
||
try {
|
||
if (
|
||
!empty($start = datetime::createFromFormat('H:i', (string) $start)) && $start instanceof datetime
|
||
&& !empty($end = datetime::createFromFormat('H:i', (string) $end)) && $end instanceof datetime
|
||
) {
|
||
// Инициализированы $start и $end
|
||
|
||
// Расчёт часов работы
|
||
$hours = (float) $start->diff($end)->format('%R%H.%i');
|
||
if ($hours < 0) $hours += 24;
|
||
if ($hours >= 6.5 && $hours < 9) $hours -= 0.5;
|
||
else if ($hours >= 9 && $hours < 12.5) $hours -= 1;
|
||
else if ($hours >= 12.5) $hours -= 1.5;
|
||
|
||
// Выход (успех)
|
||
return $hours;
|
||
}
|
||
} catch (exception $e) {
|
||
// Write to the errors registry
|
||
$errors[] = [
|
||
'text' => $e->getMessage(),
|
||
'file' => $e->getFile(),
|
||
'line' => $e->getLine(),
|
||
'stack' => $e->getTrace()
|
||
];
|
||
}
|
||
|
||
// Выход (провал)
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 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
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Create a transaction for work on a task
|
||
*
|
||
* @param string $task
|
||
* @param string $worker
|
||
* @param int $amount
|
||
* @param array $errors
|
||
*
|
||
* @return ?string Identificator of instance of ArangoDB
|
||
*/
|
||
public static function transaction(
|
||
string $task,
|
||
string $worker,
|
||
int $amount = 0,
|
||
array &$errors = []
|
||
): ?string {
|
||
try {
|
||
if (
|
||
collection::init(static::$arangodb->session, self::COLLECTION)
|
||
&& collection::init(static::$arangodb->session, worker::COLLECTION)
|
||
&& collection::init(static::$arangodb->session, 'transaction', true)
|
||
) {
|
||
// Инициализированы коллекции
|
||
|
||
// Запись документа в базу данны и возврат (успех)
|
||
return document::write(static::$arangodb->session, 'transaction', [
|
||
'_from' => $task,
|
||
'_to' => $worker,
|
||
'amount' => $amount,
|
||
'processed' => 0,
|
||
]);
|
||
} else throw new exception('Не удалось инициализировать коллекции');
|
||
} catch (exception $e) {
|
||
// Write to the errors registry
|
||
$errors[] = [
|
||
'text' => $e->getMessage(),
|
||
'file' => $e->getFile(),
|
||
'line' => $e->getLine(),
|
||
'stack' => $e->getTrace()
|
||
];
|
||
}
|
||
|
||
// Exit (fail)
|
||
return null;
|
||
}
|
||
|
||
}
|