127 lines
4.7 KiB
PHP
127 lines
4.7 KiB
PHP
<?php
|
||
|
||
namespace App\Services\Reports;
|
||
|
||
use App\Models\Department;
|
||
use App\Models\ReportPeriod;
|
||
use App\Models\ServiceCatalog;
|
||
use App\Models\Team;
|
||
use Illuminate\Support\Collection;
|
||
|
||
class AnalysisReportService
|
||
{
|
||
/**
|
||
* Create a new service instance.
|
||
*/
|
||
public function __construct(
|
||
protected ServiceAllocationService $serviceAllocationService,
|
||
protected MedicationExpenseService $medicationExpenseService,
|
||
) {}
|
||
|
||
/**
|
||
* Build the analysis report for the given team and period.
|
||
*
|
||
* @return array<string, mixed>
|
||
*/
|
||
public function build(Team $team, int $year, int $month): array
|
||
{
|
||
$period = ReportPeriod::query()
|
||
->whereBelongsTo($team)
|
||
->where('year', $year)
|
||
->where('month', $month)
|
||
->first();
|
||
|
||
$departments = Department::query()
|
||
->with('departmentProfile:id,name')
|
||
->where('is_active', true)
|
||
->orderBy('name')
|
||
->get();
|
||
|
||
$serviceCatalogs = ServiceCatalog::query()
|
||
->where('is_active', true)
|
||
->orderBy('sort_order')
|
||
->orderBy('name')
|
||
->get();
|
||
|
||
if ($period === null) {
|
||
return [
|
||
'period' => null,
|
||
'columns' => $this->columns($serviceCatalogs),
|
||
'rows' => [],
|
||
'meta' => [
|
||
'status' => null,
|
||
'statusLabel' => null,
|
||
'updatedAt' => null,
|
||
'canEditSources' => false,
|
||
],
|
||
];
|
||
}
|
||
|
||
$serviceMatrix = $this->serviceAllocationService->incomingAllocationsForPeriod($period, $departments, $serviceCatalogs);
|
||
$expenseMatrix = $this->medicationExpenseService->calculateForDepartments($period, $departments);
|
||
|
||
$rows = $departments->map(function (Department $department) use ($serviceMatrix, $expenseMatrix): array {
|
||
return [
|
||
'department' => [
|
||
'id' => $department->id,
|
||
'name' => $department->name,
|
||
'profileName' => $department->departmentProfile->name,
|
||
],
|
||
'services' => $serviceMatrix[$department->id]['services'] ?? [],
|
||
'serviceTotals' => [
|
||
'total_quantity' => $serviceMatrix[$department->id]['totalQuantity'] ?? 0,
|
||
'total_amount' => $serviceMatrix[$department->id]['totalAmount'] ?? 0,
|
||
],
|
||
'expense' => $expenseMatrix[$department->id]['totals'],
|
||
];
|
||
})->values()->all();
|
||
|
||
return [
|
||
'period' => [
|
||
'id' => $period->id,
|
||
'year' => $period->year,
|
||
'month' => $period->month,
|
||
'label' => $period->label(),
|
||
],
|
||
'columns' => $this->columns($serviceCatalogs),
|
||
'rows' => $rows,
|
||
'meta' => [
|
||
'status' => $period->status->value,
|
||
'statusLabel' => $period->status->label(),
|
||
'updatedAt' => $period->updated_at?->toIso8601String(),
|
||
'canEditSources' => $period->isEditable(),
|
||
],
|
||
];
|
||
}
|
||
|
||
/**
|
||
* Get the visible analysis columns for the active services.
|
||
*
|
||
* @param Collection<int, ServiceCatalog> $serviceCatalogs
|
||
* @return array<int, array<string, string>>
|
||
*/
|
||
protected function columns(Collection $serviceCatalogs): array
|
||
{
|
||
return [
|
||
...$serviceCatalogs->flatMap(fn (ServiceCatalog $serviceCatalog): array => [
|
||
[
|
||
'key' => "services.{$serviceCatalog->code}.quantity",
|
||
'label' => "{$serviceCatalog->name} (кол-во)",
|
||
'unit' => $serviceCatalog->unit ?? '',
|
||
],
|
||
[
|
||
'key' => "services.{$serviceCatalog->code}.amount",
|
||
'label' => "{$serviceCatalog->name} (затраты)",
|
||
'unit' => 'руб.',
|
||
],
|
||
])->all(),
|
||
['key' => 'serviceTotals.total_quantity', 'label' => 'Всего услуг', 'unit' => 'усл.'],
|
||
['key' => 'serviceTotals.total_amount', 'label' => 'Затраты по услугам', 'unit' => 'руб.'],
|
||
['key' => 'expense.total_without_dressing', 'label' => 'Без перевязки', 'unit' => 'руб.'],
|
||
['key' => 'expense.total_dressing', 'label' => 'Перевязка / ИМН', 'unit' => 'руб.'],
|
||
['key' => 'expense.total_expense', 'label' => 'Общий расход', 'unit' => 'руб.'],
|
||
['key' => 'expense.without_budget_total', 'label' => 'Без бюджета', 'unit' => 'руб.'],
|
||
];
|
||
}
|
||
}
|