config->getSchoolYear(); } $schoolYears = DB::table('invoices') ->select('school_year') ->distinct() ->orderBy('school_year', 'DESC') ->pluck('school_year') ->map(fn ($val) => (string) $val) ->filter(fn ($val) => $val !== '') ->values() ->all(); if (empty($schoolYears)) { $schoolYears = [$schoolYear]; } $invoiceData = []; $parents = User::getUsersByRoleAndSchoolYear('parent', $schoolYear); foreach ($parents as $parent) { $students = Student::query() ->where('parent_id', $parent['id']) ->get() ->map(fn ($r) => $r->toArray()) ->all(); $parentData = [ 'parent_name' => trim(($parent['firstname'] ?? '').' '.($parent['lastname'] ?? '')), 'parent_id' => (int) $parent['id'], 'enrolledKids' => [], 'withdrawnKids' => [], 'invoice_amount' => 0, 'refund_amount' => 0, 'last_updated' => null, 'invoice_date' => null, 'invoice_id' => null, ]; $invoices = Invoice::getInvoicesByParentId((int) $parent['id'], $schoolYear); foreach ($invoices as $invoice) { if (! $invoice) { continue; } $parentData['invoice_amount'] = (float) ($invoice['total_amount'] ?? 0); $parentData['last_updated'] = $invoice['updated_at'] ?? null; $parentData['invoice_id'] = $invoice['id'] ?? null; if (! empty($invoice['issue_date'])) { $tzName = $this->config->getTimezone(); $parentData['invoice_date'] = (new \DateTimeImmutable($invoice['issue_date'], new \DateTimeZone('UTC'))) ->setTimezone(new \DateTimeZone($tzName)) ->format('Y-m-d H:i:s'); } else { $parentData['invoice_date'] = ! empty($invoice['updated_at']) ? date('Y-m-d H:i:s', strtotime($invoice['updated_at'])) : null; } $refund = DB::table('refunds') ->selectRaw('COALESCE(SUM(refund_paid_amount),0) AS refund_paid_amount') ->where('parent_id', $parent['id']) ->where('school_year', $schoolYear) ->whereIn('status', ['Partial', 'Paid']) ->first(); $parentData['refund_amount'] = (float) ($refund->refund_paid_amount ?? 0.0); break; } foreach ($students as $student) { $grade = 'N/A'; $studentClass = DB::table('student_class') ->where('student_id', $student['id']) ->where('school_year', $schoolYear) ->first(); if ($studentClass && isset($studentClass->class_section_id)) { $classSection = DB::table('classSection') ->where('class_section_id', $studentClass->class_section_id) ->first(); if ($classSection && isset($classSection->class_section_name)) { $grade = $classSection->class_section_name; } } $enrollments = Enrollment::query() ->where('student_id', $student['id']) ->where('school_year', $schoolYear) ->get() ->map(fn ($r) => $r->toArray()) ->all(); foreach ($enrollments as $enrollment) { $kid = [ 'name' => trim(($student['firstname'] ?? '').' '.($student['lastname'] ?? '')), 'grade' => $grade, 'tuition_fee' => (float) ($enrollment['tuition_fee'] ?? 0), ]; switch ($enrollment['enrollment_status']) { case 'payment pending': case 'enrolled': $parentData['enrolledKids'][] = $kid; break; case 'withdraw under review': case 'withdrawn': case 'refund pending': $parentData['withdrawnKids'][] = $kid; break; default: break; } } } if (! empty($parentData['enrolledKids']) || ! empty($parentData['withdrawnKids'])) { $invoiceData[] = $parentData; } } return [ 'schoolYear' => $schoolYear, 'schoolYears' => $schoolYears, 'invoices' => $invoiceData, ]; } }