invoiceModel = new InvoiceModel(); $this->invoiceLedgerService = new InvoiceLedgerService(); $this->refundEligibilityService = new RefundEligibilityService(); } public function getParentProjection(int $parentId, string $schoolYear, ?string $semester = null): array { $invoices = $this->loadInvoices($parentId, $schoolYear, $semester); $grossChargesCents = 0; $discountCents = 0; $netInvoiceChargesCents = 0; $validPaymentCents = 0; $completedRefundCents = 0; $balanceDueCents = 0; $customerCreditCents = 0; $approvedRefundReservationCents = 0; $availableRefundableCreditCents = 0; $invoiceProjections = []; foreach ($invoices as $invoice) { $invoiceId = (int)($invoice['id'] ?? 0); if ($invoiceId <= 0) { continue; } $ledger = $this->ledgerForInvoice($invoiceId); $eligibility = $this->eligibilityForSource( $parentId, $invoiceId, 'invoice_overpayment', $invoiceId ); $invoiceGrossCents = (int)($ledger['totalAmountCents'] ?? 0); $invoiceDiscountCents = (int)($ledger['discountCents'] ?? 0); $grossChargesCents += $invoiceGrossCents; $discountCents += $invoiceDiscountCents; $netInvoiceChargesCents += max(0, $invoiceGrossCents - $invoiceDiscountCents); $validPaymentCents += (int)($ledger['paidCents'] ?? 0); $completedRefundCents += (int)($ledger['completedRefundCents'] ?? 0); $balanceDueCents += (int)($ledger['balanceDueCents'] ?? 0); $customerCreditCents += (int)($ledger['customerCreditCents'] ?? 0); $approvedRefundReservationCents += $eligibility->reservedAmountCents; $availableRefundableCreditCents += $eligibility->availableAmountCents; $invoiceProjections[] = [ 'invoice_id' => $invoiceId, 'invoice_number' => (string)($invoice['invoice_number'] ?? ''), 'grossChargesCents' => $invoiceGrossCents, 'discountCents' => $invoiceDiscountCents, 'netInvoiceChargesCents' => max(0, $invoiceGrossCents - $invoiceDiscountCents), 'validPaymentCents' => (int)($ledger['paidCents'] ?? 0), 'completedRefundCents' => (int)($ledger['completedRefundCents'] ?? 0), 'balanceDueCents' => (int)($ledger['balanceDueCents'] ?? 0), 'customerCreditCents' => (int)($ledger['customerCreditCents'] ?? 0), 'approvedRefundReservationCents' => $eligibility->reservedAmountCents, 'availableRefundableCreditCents' => $eligibility->availableAmountCents, 'status' => (string)($ledger['status'] ?? ''), ]; } return [ 'parent_id' => $parentId, 'school_year' => $schoolYear, 'semester' => $semester, 'grossChargesCents' => $grossChargesCents, 'discountCents' => $discountCents, 'netInvoiceChargesCents' => $netInvoiceChargesCents, 'validPaymentCents' => $validPaymentCents, 'completedRefundCents' => $completedRefundCents, 'balanceDueCents' => $balanceDueCents, 'customerCreditCents' => $customerCreditCents, 'approvedRefundReservationCents' => $approvedRefundReservationCents, 'availableRefundableCreditCents' => $availableRefundableCreditCents, 'gross_charges' => $this->fromCents($grossChargesCents), 'discounts' => $this->fromCents($discountCents), 'net_invoice_charges' => $this->fromCents($netInvoiceChargesCents), 'valid_payments' => $this->fromCents($validPaymentCents), 'completed_refunds' => $this->fromCents($completedRefundCents), 'balance_due' => $this->fromCents($balanceDueCents), 'customer_credit' => $this->fromCents($customerCreditCents), 'approved_refund_reservations' => $this->fromCents($approvedRefundReservationCents), 'available_refundable_credit' => $this->fromCents($availableRefundableCreditCents), 'invoices' => $invoiceProjections, ]; } protected function loadInvoices(int $parentId, string $schoolYear, ?string $semester): array { $query = $this->invoiceModel ->where('parent_id', $parentId) ->where('school_year', $schoolYear); if ($semester !== null && $semester !== '') { $query->where('semester', $semester); } return $query->orderBy('id', 'ASC')->findAll(); } protected function ledgerForInvoice(int $invoiceId): array { return $this->invoiceLedgerService->calculateInvoice($invoiceId); } protected function eligibilityForSource( int $parentId, ?int $invoiceId, string $sourceType, int $sourceId ): RefundEligibilityResult { return $this->refundEligibilityService->calculateAvailableCredit( $parentId, $invoiceId, $sourceType, $sourceId ); } private function fromCents(int $cents): string { return number_format($cents / 100, 2, '.', ''); } }