eventSubtotalsByStudent($parentId, $schoolYear)), 2); } /** * @return array student_id => amount */ public function eventSubtotalsByStudent(int $parentId, string $schoolYear): array { $byStudent = []; try { $events = EventCharges::getChargesWithEventInfo($parentId, $schoolYear) ?? []; foreach ($events as $event) { $amount = (float) ($event['charged'] ?? 0); if ($amount <= 0) { continue; } $studentId = (int) ($event['student_id'] ?? 0); if ($studentId > 0) { $byStudent[$studentId] = ($byStudent[$studentId] ?? 0.0) + $amount; } else { $byStudent[0] = ($byStudent[0] ?? 0.0) + $amount; } } } catch (\Throwable $e) { Log::warning('Failed to sum event charges.', ['error' => $e->getMessage()]); } foreach ($byStudent as $studentId => $amount) { $byStudent[$studentId] = round($amount, 2); } return $byStudent; } public function additionalSubtotal(int $invoiceId, ?string $schoolYear = null): float { return $this->sumAdditionalChargeRows( $this->fetchAdditionalChargeRows(invoiceId: $invoiceId, schoolYear: $schoolYear) ); } public function additionalSubtotalByParent(int $parentId, string $schoolYear): float { return $this->sumAdditionalChargeRows( $this->fetchAdditionalChargeRows(parentId: $parentId, schoolYear: $schoolYear) ); } /** * @return array */ private function fetchAdditionalChargeRows( ?int $parentId = null, ?int $invoiceId = null, ?string $schoolYear = null ): array { $rows = []; try { $builder = DB::table((new AdditionalCharge)->getTable()) ->select('charge_type', 'amount') ->where('status', 'applied'); if ($parentId !== null) { $builder->where('parent_id', $parentId); } if ($invoiceId !== null) { $builder->where('invoice_id', $invoiceId); } if ($schoolYear !== null && $schoolYear !== '') { $builder->where('school_year', $schoolYear); } $rows = $builder->get()->map(fn ($row) => (array) $row)->all(); } catch (\Throwable $e) { Log::warning('Failed to load additional charges.', ['error' => $e->getMessage()]); } return $rows; } /** * @param array $rows */ private function sumAdditionalChargeRows(array $rows): float { $additionalSubtotal = 0.0; foreach ($rows as $row) { $amount = (float) ($row['amount'] ?? 0); $type = strtolower((string) ($row['charge_type'] ?? 'add')); if (in_array($type, ['deduct', 'previous'], true)) { $amount = -abs($amount); } else { $amount = abs($amount); } $additionalSubtotal += $amount; } return round($additionalSubtotal, 2); } }