144 lines
5.9 KiB
PHP
144 lines
5.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Reports;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Reports\StoreServiceCatalogRequest;
|
|
use App\Http\Requests\Reports\StoreServiceEntriesRequest;
|
|
use App\Models\Department;
|
|
use App\Models\ReportPeriod;
|
|
use App\Models\ServiceCatalog;
|
|
use App\Models\ServiceEntry;
|
|
use App\Models\Team;
|
|
use App\Services\Reports\ServiceAllocationService;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Inertia\Inertia;
|
|
use Inertia\Response;
|
|
|
|
class OperationalReportController extends Controller
|
|
{
|
|
/**
|
|
* Display the operational values page.
|
|
*/
|
|
public function index(Request $request, Team $current_team, ServiceAllocationService $serviceAllocationService): Response
|
|
{
|
|
$periods = ReportPeriod::query()
|
|
->whereBelongsTo($current_team)
|
|
->orderByDesc('year')
|
|
->orderByDesc('month')
|
|
->get();
|
|
|
|
$departments = Department::query()
|
|
->where('is_active', true)
|
|
->orderBy('name')
|
|
->get();
|
|
|
|
$serviceCatalogs = ServiceCatalog::query()
|
|
->orderBy('sort_order')
|
|
->orderBy('name')
|
|
->get();
|
|
|
|
/** @var ReportPeriod|null $selectedPeriod */
|
|
$selectedPeriod = $periods->firstWhere('id', $request->integer('period', $periods->first()?->id));
|
|
/** @var Department|null $selectedProviderDepartment */
|
|
$selectedProviderDepartment = $departments->firstWhere('id', $request->integer('provider_department', $departments->first()?->id));
|
|
/** @var ServiceCatalog|null $selectedServiceCatalog */
|
|
$selectedServiceCatalog = $serviceCatalogs->firstWhere('id', $request->integer('service', $serviceCatalogs->first()?->id));
|
|
$recipientDepartments = $departments
|
|
->reject(fn (Department $department) => $department->id === $selectedProviderDepartment?->id)
|
|
->values();
|
|
|
|
return Inertia::render('reports/operations/Index', [
|
|
'periods' => $periods->map(fn (ReportPeriod $period) => [
|
|
'id' => $period->id,
|
|
'label' => $period->label(),
|
|
'status' => $period->status->value,
|
|
'statusLabel' => $period->status->label(),
|
|
'isEditable' => $period->isEditable(),
|
|
])->values(),
|
|
'departments' => $departments->map(fn (Department $department) => [
|
|
'id' => $department->id,
|
|
'name' => $department->name,
|
|
])->values(),
|
|
'serviceCatalogs' => $serviceCatalogs->map(fn (ServiceCatalog $serviceCatalog) => [
|
|
'id' => $serviceCatalog->id,
|
|
'code' => $serviceCatalog->code,
|
|
'name' => $serviceCatalog->name,
|
|
'unit' => $serviceCatalog->unit,
|
|
'defaultPrice' => (float) $serviceCatalog->default_price,
|
|
'sortOrder' => $serviceCatalog->sort_order,
|
|
'isActive' => $serviceCatalog->is_active,
|
|
])->values(),
|
|
'selectedPeriodId' => $selectedPeriod?->id,
|
|
'selectedProviderDepartmentId' => $selectedProviderDepartment?->id,
|
|
'selectedServiceCatalogId' => $selectedServiceCatalog?->id,
|
|
'recipientDepartments' => $recipientDepartments->map(fn (Department $department) => [
|
|
'id' => $department->id,
|
|
'name' => $department->name,
|
|
])->values(),
|
|
'entries' => $selectedPeriod && $selectedProviderDepartment && $selectedServiceCatalog
|
|
? $serviceAllocationService->entriesForProviderPeriodService(
|
|
$selectedPeriod,
|
|
$selectedProviderDepartment,
|
|
$selectedServiceCatalog,
|
|
$recipientDepartments,
|
|
)
|
|
: [],
|
|
'canEdit' => $selectedPeriod?->isEditable() ?? false,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Store a new service catalog item.
|
|
*/
|
|
public function storeService(StoreServiceCatalogRequest $request, Team $current_team): RedirectResponse
|
|
{
|
|
ServiceCatalog::create([
|
|
...$request->validated(),
|
|
'sort_order' => $request->integer('sort_order'),
|
|
'is_active' => $request->boolean('is_active'),
|
|
'default_price' => (float) $request->input('default_price', 0),
|
|
]);
|
|
|
|
return to_route('reports.operations.index', $current_team);
|
|
}
|
|
|
|
/**
|
|
* Store service entries for a provider department and period.
|
|
*/
|
|
public function storeEntries(StoreServiceEntriesRequest $request, Team $current_team): RedirectResponse
|
|
{
|
|
$period = ReportPeriod::query()
|
|
->whereBelongsTo($current_team)
|
|
->findOrFail($request->integer('report_period_id'));
|
|
|
|
abort_unless($period->isEditable(), 422);
|
|
|
|
$providerDepartment = Department::query()->findOrFail($request->integer('provider_department_id'));
|
|
$serviceCatalog = ServiceCatalog::query()->findOrFail($request->integer('service_catalog_id'));
|
|
|
|
foreach ($request->array('entries') as $recipientDepartmentId => $entry) {
|
|
$quantity = (float) ($entry['quantity'] ?? 0);
|
|
$unitPrice = (float) ($entry['unit_price'] ?? $serviceCatalog->default_price);
|
|
|
|
ServiceEntry::updateOrCreate([
|
|
'report_period_id' => $period->id,
|
|
'service_catalog_id' => $serviceCatalog->id,
|
|
'provider_department_id' => $providerDepartment->id,
|
|
'recipient_department_id' => (int) $recipientDepartmentId,
|
|
], [
|
|
'quantity' => $quantity,
|
|
'unit_price' => $unitPrice,
|
|
]);
|
|
}
|
|
|
|
return to_route('reports.operations.index', [
|
|
'current_team' => $current_team,
|
|
'period' => $period->id,
|
|
'provider_department' => $providerDepartment->id,
|
|
'service' => $serviceCatalog->id,
|
|
]);
|
|
}
|
|
}
|