64 lines
2.1 KiB
PHP
64 lines
2.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Reports;
|
|
|
|
use App\Models\Department;
|
|
use App\Services\DateRange;
|
|
use Closure;
|
|
|
|
readonly class ReportSource
|
|
{
|
|
/**
|
|
* @param array<string,string> $columns ключ колонки => подпись (все колонки, доступные для этого источника)
|
|
* @param array<string,array{label:string,options:?array<int|string,string>}> $filterableFields allow-list полей, по которым можно фильтровать в конструкторе шаблонов
|
|
* @param Closure(Department,DateRange,array<int,string>,array<int,array{field:string,value:mixed}>):array<int,array<string,mixed>> $resolver
|
|
*/
|
|
public function __construct(
|
|
public string $key,
|
|
public string $label,
|
|
public array $columns,
|
|
public array $filterableFields,
|
|
private Closure $resolver,
|
|
) {}
|
|
|
|
/**
|
|
* @param array<int,string> $columns ключи выбранных колонок (по умолчанию — все)
|
|
* @param array<int,array{field:string,value:mixed}> $filters
|
|
* @return array<int,array<string,mixed>>
|
|
*/
|
|
public function rows(Department $department, DateRange $dateRange, ?array $columns = null, array $filters = []): array
|
|
{
|
|
$columns ??= array_keys($this->columns);
|
|
|
|
return ($this->resolver)($department, $dateRange, $columns, $filters);
|
|
}
|
|
|
|
public function toSection(
|
|
Department $department,
|
|
DateRange $dateRange,
|
|
?array $columns = null,
|
|
array $filters = [],
|
|
?string $title = null,
|
|
): ReportSection {
|
|
$columns ??= array_keys($this->columns);
|
|
|
|
$columnDefs = [];
|
|
foreach ($columns as $key) {
|
|
if (isset($this->columns[$key])) {
|
|
$columnDefs[$key] = $this->columns[$key];
|
|
}
|
|
}
|
|
|
|
if (empty($columnDefs)) {
|
|
$columnDefs = $this->columns;
|
|
$columns = array_keys($this->columns);
|
|
}
|
|
|
|
return new ReportSection(
|
|
$title ?? $this->label,
|
|
$columnDefs,
|
|
$this->rows($department, $dateRange, $columns, $filters),
|
|
);
|
|
}
|
|
}
|