$recipientDepartments * @return array> */ 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 $departments * @param Collection $serviceCatalogs * @return array> */ 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 $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(); } }