first commit
This commit is contained in:
93
app/Services/Reports/ServiceAllocationService.php
Normal file
93
app/Services/Reports/ServiceAllocationService.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Reports;
|
||||
|
||||
use App\Models\Department;
|
||||
use App\Models\ReportPeriod;
|
||||
use App\Models\ServiceCatalog;
|
||||
use App\Models\ServiceEntry;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class ServiceAllocationService
|
||||
{
|
||||
/**
|
||||
* Build a provider sheet for the given period and service.
|
||||
*
|
||||
* @param Collection<int, Department> $recipientDepartments
|
||||
* @return array<int, array<string, float>>
|
||||
*/
|
||||
public function entriesForProviderPeriodService(
|
||||
ReportPeriod $period,
|
||||
Department $providerDepartment,
|
||||
ServiceCatalog $serviceCatalog,
|
||||
Collection $recipientDepartments,
|
||||
): array {
|
||||
$entries = ServiceEntry::query()
|
||||
->whereBelongsTo($period)
|
||||
->whereBelongsTo($serviceCatalog)
|
||||
->where('provider_department_id', $providerDepartment->id)
|
||||
->whereIn('recipient_department_id', $recipientDepartments->pluck('id'))
|
||||
->get()
|
||||
->keyBy('recipient_department_id');
|
||||
|
||||
return $recipientDepartments->mapWithKeys(function (Department $recipientDepartment) use ($entries, $serviceCatalog): array {
|
||||
/** @var ServiceEntry|null $entry */
|
||||
$entry = $entries->get($recipientDepartment->id);
|
||||
|
||||
$quantity = (float) ($entry?->quantity ?? 0);
|
||||
$unitPrice = (float) ($entry?->unit_price ?? $serviceCatalog->default_price);
|
||||
|
||||
return [$recipientDepartment->id => [
|
||||
'quantity' => $quantity,
|
||||
'unitPrice' => $unitPrice,
|
||||
'totalAmount' => round($quantity * $unitPrice, 2),
|
||||
]];
|
||||
})->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregate incoming services by recipient department.
|
||||
*
|
||||
* @param Collection<int, Department> $departments
|
||||
* @param Collection<int, ServiceCatalog> $serviceCatalogs
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public function incomingAllocationsForPeriod(
|
||||
ReportPeriod $period,
|
||||
Collection $departments,
|
||||
Collection $serviceCatalogs,
|
||||
): array {
|
||||
$entries = ServiceEntry::query()
|
||||
->with('serviceCatalog:id,code')
|
||||
->whereBelongsTo($period)
|
||||
->whereIn('recipient_department_id', $departments->pluck('id'))
|
||||
->whereIn('service_catalog_id', $serviceCatalogs->pluck('id'))
|
||||
->get()
|
||||
->groupBy('recipient_department_id');
|
||||
|
||||
return $departments->mapWithKeys(function (Department $department) use ($entries, $serviceCatalogs): array {
|
||||
/** @var Collection<int, ServiceEntry> $recipientEntries */
|
||||
$recipientEntries = $entries->get($department->id, collect());
|
||||
|
||||
$services = $serviceCatalogs->mapWithKeys(function (ServiceCatalog $serviceCatalog) use ($recipientEntries): array {
|
||||
$matchingEntries = $recipientEntries->filter(
|
||||
fn (ServiceEntry $entry) => $entry->service_catalog_id === $serviceCatalog->id
|
||||
);
|
||||
|
||||
$quantity = round((float) $matchingEntries->sum(fn (ServiceEntry $entry) => (float) $entry->quantity), 2);
|
||||
$amount = round((float) $matchingEntries->sum(fn (ServiceEntry $entry) => $entry->totalAmount()), 2);
|
||||
|
||||
return [$serviceCatalog->code => [
|
||||
'quantity' => $quantity,
|
||||
'amount' => $amount,
|
||||
]];
|
||||
})->all();
|
||||
|
||||
return [$department->id => [
|
||||
'services' => $services,
|
||||
'totalQuantity' => round((float) collect($services)->sum('quantity'), 2),
|
||||
'totalAmount' => round((float) collect($services)->sum('amount'), 2),
|
||||
]];
|
||||
})->all();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user