diff --git a/app/Controllers/View/EventController.php b/app/Controllers/View/EventController.php index 87e6e07..fb86f3a 100644 --- a/app/Controllers/View/EventController.php +++ b/app/Controllers/View/EventController.php @@ -13,6 +13,7 @@ use App\Models\InvoiceModel; use App\Models\InvoiceEventModel; use App\Models\ClassSectionModel; use App\Models\PaymentModel; +use Config\Database; #use ??? use App\Controllers\View\InvoiceController; use CodeIgniter\RESTful\ResourceController; @@ -34,6 +35,7 @@ class EventController extends ResourceController protected $semester; protected $categories; protected $enrollmentModel; + private ?bool $eventChargesHasCreatedBy = null; public function __construct() { @@ -60,6 +62,22 @@ class EventController extends ResourceController ]; } + private function eventChargesSupportsCreatedBy(): bool + { + if ($this->eventChargesHasCreatedBy !== null) { + return $this->eventChargesHasCreatedBy; + } + + try { + $db = Database::connect(); + $this->eventChargesHasCreatedBy = $db->fieldExists('created_by', 'event_charges'); + } catch (\Throwable $e) { + $this->eventChargesHasCreatedBy = false; + } + + return $this->eventChargesHasCreatedBy; + } + public function index() { $eventModel = new EventModel(); @@ -216,7 +234,7 @@ class EventController extends ResourceController $semester = $this->request->getGet('semester') ?? $this->semester; $parents = $this->userModel->getParents(); - $events = $this->eventModel->getActiveEvents($this->schoolYear); + $events = $this->eventModel->getActiveEvents($schoolYear); $filterEventId = (int) ($this->request->getGet('event_id') ?? 0); $filterParentId = (int) ($this->request->getGet('parent_id') ?? 0); @@ -324,13 +342,24 @@ class EventController extends ResourceController $parentId = $this->request->getPost('parent_id'); $eventId = $this->request->getPost('event_id'); $participations = $this->request->getPost('participation') ?? []; + $externalParticipants = $this->request->getPost('external_participants') ?? []; - if (!$parentId || !$eventId || empty($participations)) { + // Allow "external only" submissions (no enrolled students selected). + if (!$eventId || (empty($participations) && empty($externalParticipants))) { return redirect()->back()->with('error', 'Missing required information.'); } + if (!empty($participations) && !$parentId) { + return redirect()->back()->with('error', 'Select a parent when adding enrolled students.'); + } $userId = session()->get('user_id'); $event = $this->eventModel->getEvent($eventId, $schoolYear); + if (!$event) { + return redirect()->back()->with('error', 'Selected event not found for the chosen school year.'); + } + + $parentsForInvoice = []; + $supportsCreatedBy = $this->eventChargesSupportsCreatedBy(); foreach ($participations as $studentId => $value) { $existing = $this->eventChargesModel->where([ @@ -363,7 +392,7 @@ class EventController extends ResourceController $this->eventChargesModel->update($existing['id'], $updateData); continue; } else { - $this->eventChargesModel->insert([ + $insertData = [ 'parent_id' => $parentId, 'student_id' => $studentId, 'event_id' => $eventId, @@ -373,15 +402,113 @@ class EventController extends ResourceController 'class_section_id' => $classSectionId, 'school_year' => $schoolYear, 'semester' => $semester, - 'created_by' => $userId, 'updated_by' => $userId - ]); + ]; + if ($supportsCreatedBy) { + $insertData['created_by'] = $userId; + } + $this->eventChargesModel->insert($insertData); } } - $this->invoiceController->generateInvoice($parentId); + foreach ($externalParticipants as $pieces) { + $firstname = $this->normalizeExternalName($pieces['firstname'] ?? ''); + $lastname = $this->normalizeExternalName($pieces['lastname'] ?? ''); + $note = trim($pieces['note'] ?? ''); + $parentFirst = $this->normalizeExternalName($pieces['parent_firstname'] ?? ''); + $parentLast = $this->normalizeExternalName($pieces['parent_lastname'] ?? ''); + $parentPhone = trim($pieces['parent_phone'] ?? ''); + $parentEmail = trim((string)($pieces['parent_email'] ?? '')); + $markPaid = (string)($pieces['paid'] ?? '0') === '1'; - $this->fixInvoiceStatusAfterCharge($parentId, $schoolYear); + if (!$firstname && !$lastname) { + continue; + } + + $matchedParentId = $this->findExistingParentIdByExternalContact( + $parentFirst, + $parentLast, + $parentEmail, + $parentPhone + ); + + // Match external participants by kid name + event context. + // Parent contact info can change (or be fixed later) and should be updated, not used for matching. + $matchConditions = [ + 'event_id' => $eventId, + 'external_firstname' => $firstname, + 'external_lastname' => $lastname, + 'school_year' => $schoolYear, + 'semester' => $semester, + ]; + if ($matchedParentId) { + $matchConditions['parent_id'] = $matchedParentId; + } else { + // External-only parent: match by external parent contact to avoid duplicates. + $matchConditions['parent_id'] = null; + $matchConditions['external_parent_firstname'] = $parentFirst ?: null; + $matchConditions['external_parent_lastname'] = $parentLast ?: null; + $matchConditions['external_parent_phone'] = $parentPhone ?: null; + $matchConditions['external_parent_email'] = $parentEmail ?: null; + } + $existingExternal = $this->eventChargesModel->where($matchConditions)->first(); + + if ($existingExternal) { + $this->eventChargesModel->update($existingExternal['id'], [ + 'participation' => 'yes', + 'charged' => $event['amount'], + 'updated_by' => $userId, + // Preserve existing payment status; only update contact fields when provided. + 'external_note' => $note !== '' ? $note : ($existingExternal['external_note'] ?? null), + 'external_parent_firstname' => $parentFirst !== '' ? $parentFirst : ($existingExternal['external_parent_firstname'] ?? null), + 'external_parent_lastname' => $parentLast !== '' ? $parentLast : ($existingExternal['external_parent_lastname'] ?? null), + 'external_parent_phone' => $parentPhone !== '' ? $parentPhone : ($existingExternal['external_parent_phone'] ?? null), + 'external_parent_email' => $parentEmail !== '' ? $parentEmail : ($existingExternal['external_parent_email'] ?? null), + ]); + continue; + } + + $insertData = [ + 'parent_id' => $matchedParentId ?: null, + 'student_id' => null, + 'event_id' => $eventId, + 'participation' => 'yes', + 'charged' => $event['amount'], + 'event_paid' => $markPaid ? 1 : 0, + 'external_firstname' => $firstname, + 'external_lastname' => $lastname, + 'external_note' => $note, + 'external_parent_firstname' => $parentFirst, + 'external_parent_lastname' => $parentLast, + 'external_parent_phone' => $parentPhone, + 'external_parent_email' => $parentEmail, + 'school_year' => $schoolYear, + 'semester' => $semester, + 'updated_by' => $userId, + ]; + if ($supportsCreatedBy) { + $insertData['created_by'] = $userId; + } + $this->eventChargesModel->insert($insertData); + + $newChargeId = (int)$this->eventChargesModel->getInsertID(); + if ($markPaid && $newChargeId > 0) { + $this->applyEventPaymentStatus($newChargeId, true); + } + + if ($matchedParentId && $this->parentHasEnrollment($matchedParentId, (string)$schoolYear)) { + $parentsForInvoice[$matchedParentId] = true; + } + } + + if ($parentId && $this->parentHasEnrollment((int)$parentId, (string)$schoolYear)) { + $parentsForInvoice[(int)$parentId] = true; + } + + foreach (array_keys($parentsForInvoice) as $pid) { + $this->invoiceController->generateInvoice((string)$pid, (string)$schoolYear, (string)$semester, false); + $this->fixInvoiceStatusAfterCharge((int)$pid, (string)$schoolYear); + } return redirect()->back()->with('success', 'Event charges updated successfully.'); } @@ -403,7 +530,9 @@ class EventController extends ResourceController } $this->eventChargesModel->delete($chargeId); - $this->invoiceController->generateInvoice($charge['parent_id']); + if (!empty($charge['parent_id']) && $this->parentHasEnrollment((int)$charge['parent_id'], (string)($charge['school_year'] ?? ''))) { + $this->invoiceController->generateInvoice((string)$charge['parent_id'], (string)($charge['school_year'] ?? $this->schoolYear), (string)($charge['semester'] ?? $this->semester), false); + } return redirect()->back()->with('success', 'Participation removed, invoices updated.'); } @@ -414,42 +543,209 @@ class EventController extends ResourceController return redirect()->back()->with('error', 'Invalid charge.'); } - $charge = $this->eventChargesModel->find($chargeId); - if (!$charge) { + $isPaid = $this->request->getPost('paid') === '1'; + $meta = $this->applyEventPaymentStatus((int)$chargeId, $isPaid); + if (!$meta) { return redirect()->back()->with('error', 'Charge not found.'); } - $isPaid = $this->request->getPost('paid') === '1'; + if (!empty($meta['invoice_id'])) { + $this->invoiceController->generateInvoice((string)$meta['parent_id'], (string)$meta['school_year'], (string)($meta['semester'] ?? $this->semester), false); + $this->fixInvoiceStatusAfterCharge((int)$meta['parent_id'], (string)$meta['school_year']); + } + + return redirect()->back()->with('success', 'Event payment status updated.'); + } + + private function parentHasEnrollment(int $parentId, string $schoolYear): bool + { + if ($parentId <= 0 || $schoolYear === '') { + return false; + } + + try { + return $this->enrollmentModel + ->where('parent_id', $parentId) + ->where('school_year', $schoolYear) + ->countAllResults() > 0; + } catch (\Throwable $e) { + return false; + } + } + + private function findExistingParentIdByExternalContact(string $first, string $last, string $email, string $phone): ?int + { + $first = trim($first); + $last = trim($last); + $email = trim($email); + $phoneDigits = preg_replace('/\D+/', '', (string)$phone); + + if ($first === '' || $last === '' || $email === '' || $phoneDigits === '') { + return null; + } + + try { + $db = Database::connect(); + $expr = "REPLACE(REPLACE(REPLACE(REPLACE(cellphone, '(', ''), ')', ''), '-', ''), ' ', '') ="; + + $row = $this->userModel + ->select('id') + ->where('LOWER(firstname)', strtolower($first)) + ->where('LOWER(lastname)', strtolower($last)) + ->where('LOWER(email)', strtolower($email)) + ->where($expr, $db->escapeString($phoneDigits), false) + ->first(); + + $id = (int)($row['id'] ?? 0); + return $id > 0 ? $id : null; + } catch (\Throwable $e) { + log_message('error', 'Failed to match external parent to users: ' . $e->getMessage()); + return null; + } + } + + private function syncInvoicePaymentSummary(int $invoiceId): void + { + if ($invoiceId <= 0) { + return; + } + + $invoice = $this->invoiceModel->find($invoiceId); + if (!$invoice) { + return; + } + + $db = \Config\Database::connect(); + $exclude = ['void', 'voided', 'refunded', 'failed', 'chargeback', 'declined', 'reversed', 'canceled', 'cancelled']; + + $paidSum = 0.0; + try { + $qb = $db->table('payments') + ->select('COALESCE(SUM(paid_amount),0) AS tot') + ->where('invoice_id', $invoiceId) + ->where('paid_amount >', 0); + + if ($db->fieldExists('status', 'payments')) { + $qb->groupStart() + ->whereNotIn('status', $exclude) + ->orWhere('status IS NULL', null, false) + ->groupEnd(); + } + if ($db->fieldExists('is_void', 'payments')) { + $qb->groupStart() + ->where('is_void', 0) + ->orWhere('is_void IS NULL', null, false) + ->groupEnd(); + } + + $row = $qb->get()->getRowArray(); + $paidSum = (float)($row['tot'] ?? 0.0); + } catch (\Throwable $e) { + log_message('error', 'Failed to sum payments for invoice ' . $invoiceId . ': ' . $e->getMessage()); + } + + $discountSum = 0.0; + try { + $row = $db->table('discount_usages') + ->select('COALESCE(SUM(discount_amount),0) AS tot') + ->where('invoice_id', $invoiceId) + ->get() + ->getRowArray(); + $discountSum = (float)($row['tot'] ?? 0.0); + } catch (\Throwable $e) { + log_message('error', 'Failed to sum discounts for invoice ' . $invoiceId . ': ' . $e->getMessage()); + } + + $refundSum = 0.0; + try { + $row = $db->table('refunds') + ->select('COALESCE(SUM(refund_paid_amount),0) AS tot') + ->where('invoice_id', $invoiceId) + ->whereIn('status', ['Partial', 'Paid']) + ->get() + ->getRowArray(); + $refundSum = (float)($row['tot'] ?? 0.0); + } catch (\Throwable $e) { + log_message('error', 'Failed to sum refunds for invoice ' . $invoiceId . ': ' . $e->getMessage()); + } + + $total = (float)($invoice['total_amount'] ?? 0.0); + $newBalance = round($total - $discountSum - $refundSum - $paidSum, 2); + $newStatus = ($newBalance <= 0.00001) + ? 'Paid' + : (($paidSum > 0) ? 'Partially Paid' : 'Unpaid'); + + $this->invoiceModel->update($invoiceId, [ + 'paid_amount' => $paidSum, + 'balance' => $newBalance, + 'status' => $newStatus, + 'updated_at' => utc_now(), + ]); + } + + private function applyEventPaymentStatus(int $chargeId, bool $isPaid): ?array + { + if ($chargeId <= 0) { + return null; + } + + $charge = $this->eventChargesModel->find($chargeId); + if (!$charge) { + return null; + } + $event = $this->eventModel->find($charge['event_id']); $eventAmount = max(0.0, (float)($event['amount'] ?? 0)); $paymentId = (int)($charge['event_payment_id'] ?? 0); - $parentId = $charge['parent_id']; - $schoolYear = $charge['school_year'] ?? $this->schoolYear; + $parentId = (int)($charge['parent_id'] ?? 0); + $schoolYear = (string)($charge['school_year'] ?? $this->schoolYear); + $semester = (string)($charge['semester'] ?? $this->semester); - if (!empty($eventAmount)) { - $invoice = $this->invoiceModel + if ($parentId > 0 && $eventAmount > 0) { + $hasEnrollment = $this->parentHasEnrollment($parentId, $schoolYear); + $invoiceQuery = $this->invoiceModel ->where('parent_id', $parentId) ->where('school_year', $schoolYear) - ->orderBy('id', 'DESC') - ->first(); + ->orderBy('id', 'DESC'); + $invoice = $invoiceQuery->first(); - if (!$invoice) { - $this->invoiceController->generateInvoice($parentId); - $invoice = $this->invoiceModel - ->where('parent_id', $parentId) - ->where('school_year', $schoolYear) - ->orderBy('id', 'DESC') - ->first(); + if (!$invoice && $hasEnrollment) { + $this->invoiceController->generateInvoice((string)$parentId, $schoolYear, $semester, false); + $invoice = $invoiceQuery->first(); } if ($invoice) { + $invoiceId = (int)($invoice['id'] ?? 0); + if ($invoiceId > 0) { + $this->syncInvoicePaymentSummary($invoiceId); + $invoice = $this->invoiceModel->find($invoiceId) ?? $invoice; + } + if ($isPaid && !$paymentId) { - $paymentId = $this->createEventPayment($parentId, (int)$invoice['id'], $eventAmount, $schoolYear, $charge['semester'] ?? $this->semester); + $paymentSchoolYear = (string)($invoice['school_year'] ?? $schoolYear); + $paymentSemester = (string)($invoice['semester'] ?? $semester); + $paymentId = (int)($this->createEventPayment( + $parentId, + (int)$invoice['id'], + $eventAmount, + $paymentSchoolYear, + $paymentSemester, + (float)($invoice['total_amount'] ?? 0.0), + (float)($invoice['paid_amount'] ?? 0.0), + (float)($invoice['balance'] ?? 0.0) + ) ?? 0); } elseif (!$isPaid && $paymentId > 0) { $this->paymentModel->delete($paymentId); $paymentId = 0; } + + if (!empty($invoiceId)) { + $this->syncInvoicePaymentSummary($invoiceId); + } + } elseif (!$hasEnrollment) { + // External-only parent: do not create an invoice/payment row; just persist the paid flag on the charge. + $paymentId = 0; } } @@ -459,10 +755,12 @@ class EventController extends ResourceController 'event_payment_id' => $paymentId > 0 ? $paymentId : null, ]); - $this->invoiceController->generateInvoice($parentId); - $this->fixInvoiceStatusAfterCharge($parentId, $schoolYear); - - return redirect()->back()->with('success', 'Event payment status updated.'); + return [ + 'parent_id' => $parentId, + 'school_year' => $schoolYear, + 'semester' => $semester, + 'invoice_id' => isset($invoiceId) && $invoiceId > 0 ? $invoiceId : null, + ]; } @@ -506,25 +804,48 @@ class EventController extends ResourceController return $this->response->setJSON($data); } - private function createEventPayment(int $parentId, int $invoiceId, float $amount, string $schoolYear, ?string $semester): ?int + private function createEventPayment( + int $parentId, + int $invoiceId, + float $amount, + string $schoolYear, + ?string $semester, + float $invoiceTotal = 0.0, + float $invoicePaid = 0.0, + float $invoiceBalance = 0.0 + ): ?int { if ($amount <= 0 || $invoiceId <= 0 || $parentId <= 0) { return null; } $monthSemester = $semester ?: $this->semester; + $newPaid = (float)$invoicePaid + $amount; + $newBalance = (float)$invoiceBalance - $amount; + $paymentStatus = ($newBalance <= 0.00001) + ? 'Paid' + : (($newPaid > 0) ? 'Partially Paid' : 'Unpaid'); + + $exclude = ['void', 'voided', 'refunded', 'failed', 'chargeback', 'declined', 'reversed', 'canceled', 'cancelled']; + $priorCount = $this->paymentModel + ->where('invoice_id', $invoiceId) + ->where('paid_amount >', 0) + ->whereNotIn('status', $exclude) + ->countAllResults(); + $installmentSeq = $priorCount + 1; + $data = [ 'parent_id' => $parentId, 'invoice_id' => $invoiceId, - 'total_amount' => $amount, + 'total_amount' => $invoiceTotal > 0 ? $invoiceTotal : $amount, 'paid_amount' => $amount, - 'balance' => 0.0, - 'number_of_installments' => 1, - 'payment_method' => 'Cash', + 'balance' => $newBalance, + 'number_of_installments' => $installmentSeq, + 'payment_method' => 'cash', 'payment_date' => utc_now(), 'school_year' => $schoolYear, 'semester' => $monthSemester, - 'status' => 'Paid', + 'status' => $paymentStatus, 'transaction_id' => $this->paymentModel->generateNewTransactionId(), 'updated_by' => session()->get('user_id'), ]; @@ -537,6 +858,23 @@ class EventController extends ResourceController return (int)$this->paymentModel->getInsertID(); } + private function normalizeExternalName(?string $value): string + { + $raw = trim((string)$value); + if ($raw === '') { + return ''; + } + $parts = preg_split('/\s+/', $raw); + $formatted = array_map(function ($part) { + $part = trim($part); + if ($part === '') { + return ''; + } + return mb_strtoupper(mb_substr($part, 0, 1)) . mb_strtolower(mb_substr($part, 1)); + }, $parts); + return implode(' ', array_filter($formatted, fn($p) => $p !== '')); + } + private function fixInvoiceStatusAfterCharge($parentId, $schoolYear) { if (!$parentId || !$schoolYear) { diff --git a/app/Controllers/View/FinancialController.php b/app/Controllers/View/FinancialController.php index d537820..43c2939 100644 --- a/app/Controllers/View/FinancialController.php +++ b/app/Controllers/View/FinancialController.php @@ -68,17 +68,45 @@ public function financialReport() } // === Invoices === - $invoices = $invoiceModel - ->select("invoices.*, CONCAT(users.firstname, ' ', users.lastname) AS parent_name") - ->join('users', 'users.id = invoices.parent_id') - ->findAll(); + // Business rule: one active invoice per parent per school year. + // If legacy data has multiple invoices, show only the latest one to avoid reporting older invoices as "Unpaid" + // after new charges/payments update the current invoice. + $db = \Config\Database::connect(); + if (!empty($schoolYear)) { + $latestSub = $db->table('invoices') + ->select('parent_id, MAX(id) AS max_id') + ->where('school_year', $schoolYear) + ->groupBy('parent_id') + ->getCompiledSelect(); + + $invBuilder = $db->table('invoices') + ->select("invoices.*, CONCAT(users.firstname, ' ', users.lastname) AS parent_name", false) + ->join("($latestSub) latest", 'latest.max_id = invoices.id', 'inner', false) + ->join('users', 'users.id = invoices.parent_id', 'left'); + + if ($hasFrom) { + $invBuilder->where('DATE(COALESCE(invoices.issue_date, invoices.created_at)) >=', $dateFrom); + } + if ($hasTo) { + $invBuilder->where('DATE(COALESCE(invoices.issue_date, invoices.created_at)) <=', $dateTo); + } + + $invoices = $invBuilder->get()->getResultArray(); + } else { + $invoices = $invoiceModel + ->select("invoices.*, CONCAT(users.firstname, ' ', users.lastname) AS parent_name") + ->join('users', 'users.id = invoices.parent_id') + ->findAll(); + } + + $invoiceIds = array_values(array_unique(array_filter(array_map(static function ($inv) { + $id = (int)($inv['id'] ?? 0); + return $id > 0 ? $id : null; + }, $invoices)))); // Helper to build a fresh, filtered PaymentModel each time (so filters don't get lost between queries) $buildPaymentModel = function () use ($schoolYear, $dateFrom, $dateTo) { $pm = new PaymentModel(); - if ($schoolYear) { - $pm->where('school_year', $schoolYear); - } if (!empty($dateFrom)) { $pm->where('DATE(payment_date) >=', $dateFrom); } @@ -114,7 +142,13 @@ public function financialReport() }; // === Payments aggregated by invoice_id (for the "Paid" column) === - $payments = $applyPaymentFilters($buildPaymentModel()) + $paymentsQuery = $applyPaymentFilters($buildPaymentModel()); + if (!empty($invoiceIds)) { + $paymentsQuery->whereIn('invoice_id', $invoiceIds); + } else { + $paymentsQuery->where('invoice_id', -1); + } + $payments = $paymentsQuery ->select('invoice_id, SUM(paid_amount) AS paid_amount') ->where('invoice_id IS NOT NULL') ->groupBy('invoice_id') @@ -138,6 +172,7 @@ public function financialReport() SUM(paid_amount) AS amount ") ->where('invoice_id IS NOT NULL') + ->whereIn('invoice_id', $invoiceIds ?: [-1]) ->groupBy('invoice_id, method') ->findAll(); @@ -161,6 +196,7 @@ public function financialReport() SUM(CASE WHEN LOWER(TRIM(payment_method)) IN ('credit','card','credit card','debit','debit card','visa','mastercard') THEN paid_amount ELSE 0 END) AS total_credit ") ->where('invoice_id IS NOT NULL') + ->whereIn('invoice_id', $invoiceIds ?: [-1]) ->first() ?? []; $paymentTotals = [ diff --git a/app/Controllers/View/InvoiceController.php b/app/Controllers/View/InvoiceController.php index 04232d4..077571c 100644 --- a/app/Controllers/View/InvoiceController.php +++ b/app/Controllers/View/InvoiceController.php @@ -381,18 +381,24 @@ class InvoiceController extends ResourceController return false; } - public function generateInvoice(string $parentId = null) + public function generateInvoice( + string $parentId = null, + ?string $schoolYearOverride = null, + ?string $semesterOverride = null, + bool $recalculateDiscounts = true + ) { $isAjax = $this->request->isAJAX() || str_contains(strtolower($this->request->getHeaderLine('Accept')), 'application/json'); if ($parentId == null) { $parentId = (int)$this->request->getPost('parent_id'); } - $schoolYear = (string) $this->schoolYear; + $schoolYear = (string) ($schoolYearOverride ?: $this->schoolYear); + $semester = (string) ($semesterOverride ?: $this->semester); // Fetch enrolled + withdrawn students $enrollments = $this->enrollmentModel ->where('parent_id', $parentId) - ->where('school_year', $this->schoolYear) + ->where('school_year', $schoolYear) ->findAll(); if (empty($enrollments)) { @@ -444,21 +450,23 @@ class InvoiceController extends ResourceController $tuitionFee = $fees['tuition_fee']; // ✅ Fetch event charges - $eventsList = $this->chargesModel->getChargesWithEventInfo($parentId, $this->schoolYear); + $eventsList = $this->chargesModel->getChargesWithEventInfo($parentId, $schoolYear); $eventchargeTotal = array_sum(array_column($eventsList, 'charged')); - $totalDiscount = $this->recalculateAndUpdateDiscount( - $parentId, - $this->schoolYear, - $tuitionFee, - $enrollments - ); + $totalDiscount = 0.0; + if ($recalculateDiscounts) { + $totalDiscount = $this->recalculateAndUpdateDiscount( + $parentId, + $schoolYear, + $tuitionFee, + $enrollments + ); + } - $semester = $this->semester; // ✅ Refunds PAID to the parent for this year (Partial/Paid) - $refundPaid = (float) $this->refundModel->getTotalApprovedRefundByParentIdAndSchoolYear($parentId, $this->schoolYear); + $refundPaid = (float) $this->refundModel->getTotalApprovedRefundByParentIdAndSchoolYear($parentId, $schoolYear); - $totalPaid = $this->paymentModel->getTotalPaidByParentId($parentId, $this->schoolYear); + $totalPaid = $this->paymentModel->getTotalPaidByParentId($parentId, $schoolYear); $discountedTuition = max(0, $tuitionFee); $totalAmount = $discountedTuition + $eventchargeTotal; @@ -469,17 +477,22 @@ class InvoiceController extends ResourceController - $refundPaid // approved refunds paid to parent - $totalPaid; // payments received - // Your invoice fetch - $existingInvoices = $this->invoiceModel->getInvoicesByParentId($parentId, $this->schoolYear); + // Business rule: single invoice per parent per school year. + // If legacy duplicates exist, prefer the invoice that already has a discount applied, + // otherwise use the latest invoice for the parent/year. + $invoice = $this->selectActiveInvoiceForParentYear((int)$parentId, $schoolYear); $updated = false; - $updatedIds = []; - if (!empty($existingInvoices)) { - foreach ($existingInvoices as $invoice) { - if (!isset($invoice['id'])) { - continue; - } + if (!empty($invoice) && isset($invoice['id'])) { + $paymentExclude = ['void', 'voided', 'refunded', 'failed', 'chargeback', 'declined', 'reversed', 'canceled', 'cancelled']; + $paymentsHasStatus = false; + $paymentsHasVoid = false; + try { + $paymentsHasStatus = $this->db->fieldExists('status', 'payments'); + $paymentsHasVoid = $this->db->fieldExists('is_void', 'payments'); + } catch (\Throwable $e) { + } // Preserve applied additional charges and recalc this invoice only $extrasSum = 0.0; @@ -487,7 +500,7 @@ class InvoiceController extends ResourceController $rows = $this->db->table('additional_charges') ->select('charge_type, amount') ->where('invoice_id', (int)$invoice['id']) - ->where('school_year', $this->schoolYear) + ->where('school_year', $schoolYear) ->where('status', 'applied') ->get()->getResultArray(); foreach ($rows as $r) { @@ -520,7 +533,7 @@ class InvoiceController extends ResourceController $r = $this->db->table('refunds') ->select('COALESCE(SUM(refund_paid_amount),0) AS tot') ->where('invoice_id', (int)$invoice['id']) - ->where('school_year', $this->schoolYear) + ->where('school_year', $schoolYear) ->whereIn('status', ['Partial','Paid']) ->get()->getRowArray(); $invRefunds = (float)($r['tot'] ?? 0.0); @@ -528,8 +541,33 @@ class InvoiceController extends ResourceController log_message('error', 'refund sum failed for invoice ' . (int)$invoice['id'] . ': ' . $e->getMessage()); } - // Payments recorded on this invoice (denormalized field kept in sync by PaymentController) - $paidOnInv = (float)($invoice['paid_amount'] ?? 0.0); + // Payments recorded on this invoice (sum payments to avoid stale invoice.paid_amount) + $paidOnInv = 0.0; + try { + $qb = $this->db->table('payments') + ->select('COALESCE(SUM(paid_amount),0) AS tot') + ->where('invoice_id', (int)$invoice['id']) + ->where('paid_amount >', 0); + + if ($paymentsHasStatus) { + $qb->groupStart() + ->whereNotIn('status', $paymentExclude) + ->orWhere('status IS NULL', null, false) + ->groupEnd(); + } + if ($paymentsHasVoid) { + $qb->groupStart() + ->where('is_void', 0) + ->orWhere('is_void IS NULL', null, false) + ->groupEnd(); + } + + $row = $qb->get()->getRowArray(); + $paidOnInv = (float)($row['tot'] ?? 0.0); + } catch (\Throwable $e) { + log_message('error', 'payment sum failed for invoice ' . (int)$invoice['id'] . ': ' . $e->getMessage()); + $paidOnInv = (float)($invoice['paid_amount'] ?? 0.0); + } $newBalance = $newTotal - $invDiscount - $invRefunds - $paidOnInv; $newStatus = ($newBalance <= 0.00001) @@ -547,7 +585,6 @@ class InvoiceController extends ResourceController $updatedIds[] = (int)$invoice['id']; log_message('info', "Updated invoice ID {$invoice['id']} for parent ID {$parentId}."); $updated = true; - } } else { // Generate invoice number $schoolId = $this->userModel->getSchoolIdByUserId($parentId); @@ -578,7 +615,7 @@ class InvoiceController extends ResourceController // Initial balance equals the created total; discounts/refunds/payments will adjust later 'balance' => $totalAmount, 'status' => 'Unpaid', - 'school_year' => $this->schoolYear, + 'school_year' => $schoolYear, 'semester' => $semester, 'issue_date' => $issueUtc, 'due_date' => $dueUtc, @@ -615,6 +652,47 @@ class InvoiceController extends ResourceController ->with('success', $updated ? 'Invoice updated.' : 'Invoice created.'); } + private function selectActiveInvoiceForParentYear(int $parentId, string $schoolYear): ?array + { + if ($parentId <= 0 || $schoolYear === '') { + return null; + } + + // Prefer invoices flagged as having discounts. + $invoice = $this->invoiceModel + ->where('parent_id', $parentId) + ->where('school_year', $schoolYear) + ->where('has_discount', 1) + ->orderBy('id', 'DESC') + ->first(); + if (!empty($invoice)) { + return $invoice; + } + + // Fallback: prefer invoices with discount_usages rows. + try { + $row = $this->db->table('invoices i') + ->select('i.*') + ->join('discount_usages du', 'du.invoice_id = i.id', 'inner') + ->where('i.parent_id', $parentId) + ->where('i.school_year', $schoolYear) + ->orderBy('i.id', 'DESC') + ->get() + ->getRowArray(); + if (!empty($row)) { + return $row; + } + } catch (\Throwable $e) { + } + + // Final fallback: latest invoice for parent/year. + return $this->invoiceModel + ->where('parent_id', $parentId) + ->where('school_year', $schoolYear) + ->orderBy('id', 'DESC') + ->first(); + } + private function recalculateAndUpdateDiscount( int $parentId, string $schoolYear, @@ -1266,6 +1344,12 @@ class InvoiceController extends ResourceController } } } + if ($studentName === 'N/A') { + $externalName = trim((string)($event['external_firstname'] ?? '') . ' ' . (string)($event['external_lastname'] ?? '')); + if ($externalName !== '') { + $studentName = $externalName . ' (external)'; + } + } $dt = $toLocal($event['created_at'] ?? null, false); $amount = (float)($event['charged'] ?? 0.0); diff --git a/app/Database/Migrations/2026-04-13-000004_AddExternalParticipantFieldsToEventCharges.php b/app/Database/Migrations/2026-04-13-000004_AddExternalParticipantFieldsToEventCharges.php new file mode 100644 index 0000000..14e346e --- /dev/null +++ b/app/Database/Migrations/2026-04-13-000004_AddExternalParticipantFieldsToEventCharges.php @@ -0,0 +1,43 @@ + [ + 'type' => 'VARCHAR', + 'constraint' => 150, + 'null' => true, + 'after' => 'event_payment_id', + ], + 'external_lastname' => [ + 'type' => 'VARCHAR', + 'constraint' => 150, + 'null' => true, + ], + 'external_note' => [ + 'type' => 'VARCHAR', + 'constraint' => 254, + 'null' => true, + ], + ]; + + if (! $this->db->fieldExists('external_firstname', 'event_charges')) { + $this->forge->addColumn('event_charges', $fields); + } + } + + public function down() + { + foreach (['external_firstname', 'external_lastname', 'external_note'] as $field) { + if ($this->db->fieldExists($field, 'event_charges')) { + $this->forge->dropColumn('event_charges', $field); + } + } + } +} diff --git a/app/Database/Migrations/2026-04-13-000005_AddExternalParentInfoToEventCharges.php b/app/Database/Migrations/2026-04-13-000005_AddExternalParentInfoToEventCharges.php new file mode 100644 index 0000000..6341d01 --- /dev/null +++ b/app/Database/Migrations/2026-04-13-000005_AddExternalParentInfoToEventCharges.php @@ -0,0 +1,43 @@ + [ + 'type' => 'VARCHAR', + 'constraint' => 150, + 'null' => true, + 'after' => 'external_note', + ], + 'external_parent_lastname' => [ + 'type' => 'VARCHAR', + 'constraint' => 150, + 'null' => true, + ], + 'external_parent_phone' => [ + 'type' => 'VARCHAR', + 'constraint' => 50, + 'null' => true, + ], + ]; + + if (! $this->db->fieldExists('external_parent_firstname', 'event_charges')) { + $this->forge->addColumn('event_charges', $fields); + } + } + + public function down() + { + foreach (['external_parent_firstname', 'external_parent_lastname', 'external_parent_phone'] as $field) { + if ($this->db->fieldExists($field, 'event_charges')) { + $this->forge->dropColumn('event_charges', $field); + } + } + } +} diff --git a/app/Database/Migrations/2026-04-17-000001_AddExternalParentEmailToEventCharges.php b/app/Database/Migrations/2026-04-17-000001_AddExternalParentEmailToEventCharges.php new file mode 100644 index 0000000..0e09fca --- /dev/null +++ b/app/Database/Migrations/2026-04-17-000001_AddExternalParentEmailToEventCharges.php @@ -0,0 +1,32 @@ + [ + 'type' => 'VARCHAR', + 'constraint' => 254, + 'null' => true, + 'after' => 'external_parent_phone', + ], + ]; + + if (! $this->db->fieldExists('external_parent_email', 'event_charges')) { + $this->forge->addColumn('event_charges', $fields); + } + } + + public function down() + { + if ($this->db->fieldExists('external_parent_email', 'event_charges')) { + $this->forge->dropColumn('event_charges', 'external_parent_email'); + } + } +} + diff --git a/app/Models/EventChargesModel.php b/app/Models/EventChargesModel.php index aadd00d..426d641 100644 --- a/app/Models/EventChargesModel.php +++ b/app/Models/EventChargesModel.php @@ -18,8 +18,16 @@ class EventChargesModel extends Model 'event_paid', 'event_payment_id', 'class_section_id', + 'external_firstname', + 'external_lastname', + 'external_note', + 'external_parent_firstname', + 'external_parent_lastname', + 'external_parent_phone', + 'external_parent_email', 'semester', 'school_year', + 'created_by', 'updated_by', 'created_at', 'updated_at' diff --git a/app/Views/administrator/events/event_charges.php b/app/Views/administrator/events/event_charges.php index c28c292..db72985 100644 --- a/app/Views/administrator/events/event_charges.php +++ b/app/Views/administrator/events/event_charges.php @@ -73,13 +73,15 @@
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ + +
+ + + + + endSection() ?> @@ -295,7 +395,20 @@ function loadStudentsWithCharges() { } } -$(function() { + const capitalizeName = (value) => { + if (!value) return ''; + return value + .split(' ') + .map(part => { + const trimmed = part.trim(); + if (!trimmed) return ''; + return trimmed.charAt(0).toUpperCase() + trimmed.slice(1).toLowerCase(); + }) + .filter(Boolean) + .join(' '); + }; + + $(function() { $('#parent_id').on('change', loadStudentsWithCharges); $('#event_id').on('change', function() { @@ -312,6 +425,277 @@ $(function() { if ($('#event_id').val() && $('#parent_id').val()) { loadStudentsWithCharges(); } + + const $externalHidden = $('#externalParticipantsHidden'); + const storageKey = 'eventChargesExternalParticipants'; + let externalDrafts = []; + let editingKey = null; + + const escapeHtml = (value) => { + const s = String(value ?? ''); + return s.replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + }; + + function buildExternalRow(entry) { + const key = entry.key; + const isPaid = !!entry.paid; + const firstEsc = escapeHtml(entry.firstname); + const lastEsc = escapeHtml(entry.lastname); + const noteEsc = escapeHtml(entry.note); + const parentFirstEsc = escapeHtml(entry.parentFirstname); + const parentLastEsc = escapeHtml(entry.parentLastname); + const parentPhoneEsc = escapeHtml(entry.parentPhone); + const parentEmailEsc = escapeHtml(entry.parentEmail); + const label = (firstEsc || lastEsc) + ? `${firstEsc || ''} ${lastEsc || ''}`.trim() + : 'Unnamed participant'; + const parentLabel = (parentFirstEsc || parentLastEsc) + ? `
Parent: ${parentFirstEsc} ${parentLastEsc}
` + : ''; + const phoneLabel = parentPhoneEsc + ? `
${parentPhoneEsc}
` + : ''; + const parentNameForRow = entry.parentDisplayName || '—'; + const amountDisplay = ((entry.eventAmount ?? 0) || 0.0).toFixed(2); + + const $wrapper = $(` +
+ + + + + + + + +
+ `); + $externalHidden.append($wrapper); + + const $tableBody = $(`#eventTable_${entry.eventId} tbody`); + if (!$tableBody.length) { + return; + } + const createdDisplay = new Date().toLocaleString(); + const $previewRow = $(` + + — + ${escapeHtml(parentNameForRow)} + + ${label} + ${noteEsc ? `
${noteEsc}
` : ''} + + + ${phoneLabel} + ${phoneLabel ? '' : ''} + + External + $${amountDisplay} + ${createdDisplay} + + Pending + ${isPaid ? 'Paid on save' : 'Paid on save'} + + +
+ + On save +
+ + + + + + + `); + $tableBody.append($previewRow); + } + + function persistDrafts() { + localStorage.setItem(storageKey, JSON.stringify(externalDrafts)); + } + + function saveExternalDraft(entry) { + entry.key = entry.key ?? `${Date.now()}_${Math.random().toString(36).slice(2)}`; + entry.paid = !!entry.paid; + removeExternalEntryFromDom(entry.key); + externalDrafts = externalDrafts.filter((existing) => existing.key !== entry.key); + externalDrafts.push(entry); + persistDrafts(); + buildExternalRow(entry); + } + + function removeExternalEntryFromDom(key) { + $(`tr.external-preview[data-key="${key}"]`).remove(); + $externalHidden.find(`div[data-key="${key}"]`).remove(); + } + + function removeDraft(key) { + externalDrafts = externalDrafts.filter((entry) => entry.key !== key); + persistDrafts(); + } + + function loadDrafts() { + const raw = localStorage.getItem(storageKey); + if (!raw) { + return; + } + try { + const saved = JSON.parse(raw); + if (!Array.isArray(saved)) { + return; + } + externalDrafts = saved; + const currentEvent = $('#event_id').val(); + externalDrafts.forEach((entry) => { + if (String(entry.eventId) === String(currentEvent)) { + buildExternalRow(entry); + } + }); + } catch (e) { + console.error('Failed to load external drafts', e); + } + } + + function getDraftByKey(key) { + return externalDrafts.find((entry) => entry.key === key); + } + + function openExternalModalForEntry(key) { + const entry = getDraftByKey(key); + if (!entry) { + return; + } + editingKey = key; + $('#modalExternalFirstName').val(entry.firstname); + $('#modalExternalLastName').val(entry.lastname); + $('#modalExternalNote').val(entry.note); + $('#modalParentFirstName').val(entry.parentFirstname); + $('#modalParentLastName').val(entry.parentLastname); + $('#modalParentPhone').val(entry.parentPhone); + $('#modalParentEmail').val(entry.parentEmail); + if (modalInstance) { + modalInstance.show(); + } + } + + const modalElement = document.getElementById('externalParticipantModal'); + const modalInstance = modalElement ? new bootstrap.Modal(modalElement) : null; + if (modalElement) { + modalElement.addEventListener('hidden.bs.modal', () => { + editingKey = null; + }); + } + function clearModalInputs() { + $('#modalExternalFirstName').val(''); + $('#modalExternalLastName').val(''); + $('#modalExternalNote').val(''); + $('#modalParentFirstName').val(''); + $('#modalParentLastName').val(''); + $('#modalParentPhone').val(''); + $('#modalParentEmail').val(''); + } + + $('#externalParticipantSave').on('click', function() { + const firstName = capitalizeName($('#modalExternalFirstName').val().trim()); + const lastName = capitalizeName($('#modalExternalLastName').val().trim()); + const note = $('#modalExternalNote').val().trim(); + if (!firstName && !lastName) { + alert('Please provide at least a first or last name for the non-school participant.'); + return; + } + const parentFirst = capitalizeName($('#modalParentFirstName').val().trim()); + const parentLast = capitalizeName($('#modalParentLastName').val().trim()); + const parentPhone = $('#modalParentPhone').val().trim(); + const parentEmail = $('#modalParentEmail').val().trim(); + const eventId = $('#event_id').val(); + if (!eventId) { + alert('Select an event before adding a non-school participant.'); + return; + } + const eventAmount = parseFloat($('#event_id option:selected').data('amount')) || 0; + const explicitParentName = `${parentFirst} ${parentLast}`.trim(); + if (!explicitParentName) { + alert('Please enter the external kid parent name.'); + return; + } + if (!parentEmail) { + alert('Please enter the external kid parent email.'); + return; + } + const parentName = explicitParentName; + const draftEntry = editingKey ? getDraftByKey(editingKey) : null; + const entry = { + firstname: firstName, + lastname: lastName, + note: note, + parentFirstname: parentFirst, + parentLastname: parentLast, + parentPhone: parentPhone, + parentEmail: parentEmail, + eventId: (draftEntry && draftEntry.eventId) ? draftEntry.eventId : eventId, + eventAmount: (draftEntry && draftEntry.eventAmount) ? draftEntry.eventAmount : eventAmount, + parentDisplayName: (draftEntry && draftEntry.parentDisplayName) ? draftEntry.parentDisplayName : parentName, + paid: (draftEntry && typeof draftEntry.paid !== 'undefined') ? !!draftEntry.paid : false, + }; + if (editingKey) { + entry.key = editingKey; + } + saveExternalDraft(entry); + editingKey = null; + clearModalInputs(); + if (modalInstance) { + modalInstance.hide(); + } + }); + + $(document).on('click', '.remove-external-participant', function() { + const $entry = $(this).closest('[data-key]'); + const key = $entry.data('key'); + removeExternalEntryFromDom(key); + if (key) { + removeDraft(key); + } + }); + $(document).on('click', '.edit-external-participant', function() { + const key = $(this).data('key'); + if (key) { + openExternalModalForEntry(key); + } + }); + $(document).on('change', '.external-paid-toggle', function() { + const key = $(this).data('key'); + const paid = !!this.checked; + if (!key) { + return; + } + const entry = getDraftByKey(key); + if (entry) { + entry.paid = paid; + persistDrafts(); + } + $externalHidden + .find(`div[data-key="${key}"] input[name="external_participants[${key}][paid]"]`) + .val(paid ? '1' : '0'); + const $badge = $(`tr.external-preview[data-key="${key}"] .external-paid-badge`); + if (paid) { + $badge.removeClass('d-none').addClass('bg-success').text('Paid on save'); + } else { + $badge.addClass('d-none'); + } + }); + $('#event-participant-form').on('submit', function() { + localStorage.removeItem(storageKey); + }); + loadDrafts(); }); endSection() ?> diff --git a/app/Views/parent/invoice_payment.php b/app/Views/parent/invoice_payment.php index 64a1e29..927d573 100644 --- a/app/Views/parent/invoice_payment.php +++ b/app/Views/parent/invoice_payment.php @@ -168,6 +168,12 @@ $deadline = parseDbDateTime($dueDate, 'UTC', $displayTz); // format either DATE 0.00001) { + $status = 'Partially Paid'; + $statusClass = 'bg-warning text-dark'; + } else { + $status = 'Unpaid'; + $statusClass = 'bg-danger'; + } ?> @@ -376,8 +384,15 @@ const total = Number(inv.total_amount || 0); let balance = total - paid - discounted - refunded; if (!Number.isFinite(balance) || balance < 0) balance = 0; - const status = balance === 0 ? 'Paid' : 'Unpaid'; - const statusClass = balance === 0 ? 'bg-success' : 'bg-danger'; + let status = 'Unpaid'; + let statusClass = 'bg-danger'; + if (balance <= 0.00001) { + status = 'Paid'; + statusClass = 'bg-success'; + } else if (paid > 0.00001) { + status = 'Partially Paid'; + statusClass = 'bg-warning text-dark'; + } const tr = document.createElement('tr'); const parentHtml = (inv.parent_id && Number(inv.parent_id) > 0) ? `${inv.parent_name||''}` : diff --git a/public/uploads/event_flyers/1776466394_69fd609d553ad9567fff.png b/public/uploads/event_flyers/1776466394_69fd609d553ad9567fff.png new file mode 100644 index 0000000..bdb2be8 Binary files /dev/null and b/public/uploads/event_flyers/1776466394_69fd609d553ad9567fff.png differ diff --git a/public/uploads/event_flyers/1776518547_33303159a59091c99a11.png b/public/uploads/event_flyers/1776518547_33303159a59091c99a11.png new file mode 100644 index 0000000..bdb2be8 Binary files /dev/null and b/public/uploads/event_flyers/1776518547_33303159a59091c99a11.png differ diff --git a/public/uploads/event_flyers/1776519375_8e79db33942f8863aab4.png b/public/uploads/event_flyers/1776519375_8e79db33942f8863aab4.png new file mode 100644 index 0000000..bdb2be8 Binary files /dev/null and b/public/uploads/event_flyers/1776519375_8e79db33942f8863aab4.png differ diff --git a/public/uploads/event_flyers/1776519695_a478f09020f4ada6efec.png b/public/uploads/event_flyers/1776519695_a478f09020f4ada6efec.png new file mode 100644 index 0000000..bdb2be8 Binary files /dev/null and b/public/uploads/event_flyers/1776519695_a478f09020f4ada6efec.png differ diff --git a/public/uploads/event_flyers/1776520038_62e3486473d283393d66.png b/public/uploads/event_flyers/1776520038_62e3486473d283393d66.png new file mode 100644 index 0000000..bdb2be8 Binary files /dev/null and b/public/uploads/event_flyers/1776520038_62e3486473d283393d66.png differ diff --git a/writable/cache/navbar_cd1336c7da8c3f064f0b3b9e0c0a2232 b/writable/cache/navbar_cd1336c7da8c3f064f0b3b9e0c0a2232 index b447566..c9e7595 100644 --- a/writable/cache/navbar_cd1336c7da8c3f064f0b3b9e0c0a2232 +++ b/writable/cache/navbar_cd1336c7da8c3f064f0b3b9e0c0a2232 @@ -1 +1 @@ -a:3:{s:4:"time";i:1774928767;s:3:"ttl";i:300;s:4:"data";a:18:{i:0;a:12:{s:2:"id";s:2:"63";s:14:"menu_parent_id";N;s:5:"label";s:6:"Family";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-09 15:22:56";s:10:"updated_at";s:19:"2025-10-26 06:33:11";s:10:"deleted_at";N;s:8:"children";a:2:{i:0;a:12:{s:2:"id";s:2:"64";s:14:"menu_parent_id";s:2:"63";s:5:"label";s:16:"Family Managment";s:3:"url";s:12:"family/index";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-09 15:23:49";s:10:"updated_at";s:19:"2025-10-26 06:28:34";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"74";s:14:"menu_parent_id";s:2:"63";s:5:"label";s:13:"Family Update";s:3:"url";s:22:"families/import-legacy";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:29:11";s:10:"updated_at";s:19:"2025-10-26 06:29:11";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:1;a:12:{s:2:"id";s:2:"67";s:14:"menu_parent_id";N;s:5:"label";s:9:"Inventory";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-11 06:24:37";s:10:"updated_at";s:19:"2025-09-16 16:48:58";s:10:"deleted_at";N;s:8:"children";a:6:{i:0;a:12:{s:2:"id";s:2:"56";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:5:"Books";s:3:"url";s:14:"inventory/book";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-08 19:13:48";s:10:"updated_at";s:19:"2025-10-05 03:43:38";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"72";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:26:"Update Inventory Movements";s:3:"url";s:19:"inventory/movements";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-02 06:07:53";s:10:"updated_at";s:19:"2025-10-05 03:42:08";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"55";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:19:"Classroom Equipment";s:3:"url";s:9:"inventory";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-08 18:56:08";s:10:"updated_at";s:19:"2025-09-16 16:47:32";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"57";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:16:"Kitchen Supplies";s:3:"url";s:17:"inventory/kitchen";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-08 19:14:24";s:10:"updated_at";s:19:"2025-09-16 16:48:23";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"58";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:15:"Office Supplies";s:3:"url";s:16:"inventory/office";s:10:"icon_class";N;s:6:"target";s:6:"_blank";s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-08 19:14:53";s:10:"updated_at";s:19:"2025-09-10 22:17:05";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:5;a:12:{s:2:"id";s:2:"66";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:7:"Summary";s:3:"url";s:21:"inventory/summary-all";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-11 05:56:10";s:10:"updated_at";s:19:"2025-09-11 06:28:41";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:2;a:12:{s:2:"id";s:2:"83";s:14:"menu_parent_id";N;s:5:"label";s:15:"TimeOff Request";s:3:"url";s:22:"/administrator/absence";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-11-01 20:58:55";s:10:"updated_at";s:19:"2025-11-01 20:58:55";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"88";s:14:"menu_parent_id";N;s:5:"label";s:23:"Notification Management";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-13 19:48:58";s:10:"updated_at";s:19:"2026-01-13 19:48:58";s:10:"deleted_at";N;s:8:"children";a:1:{i:0;a:12:{s:2:"id";s:2:"89";s:14:"menu_parent_id";s:2:"88";s:5:"label";s:18:"Notification Setup";s:3:"url";s:35:"/administrator/notifications_alerts";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-13 19:49:35";s:10:"updated_at";s:19:"2026-01-13 19:49:35";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:4;a:12:{s:2:"id";s:2:"92";s:14:"menu_parent_id";N;s:5:"label";s:10:"Curriculum";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-18 07:23:26";s:10:"updated_at";s:19:"2026-01-18 07:23:26";s:10:"deleted_at";N;s:8:"children";a:3:{i:0;a:12:{s:2:"id";s:2:"94";s:14:"menu_parent_id";s:2:"92";s:5:"label";s:19:"Teacher Submissions";s:3:"url";s:33:"administrator/teacher-submissions";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-25 22:20:24";s:10:"updated_at";s:19:"2026-03-29 18:12:27";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"93";s:14:"menu_parent_id";s:2:"92";s:5:"label";s:18:"Curriculum Subject";s:3:"url";s:32:"administrator/subject-curriculum";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-18 07:25:26";s:10:"updated_at";s:19:"2026-01-18 07:25:26";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"91";s:14:"menu_parent_id";s:2:"92";s:5:"label";s:14:"Class Progress";s:3:"url";s:14:"admin/progress";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-15 04:38:48";s:10:"updated_at";s:19:"2026-01-18 07:24:37";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:5;a:12:{s:2:"id";s:2:"95";s:14:"menu_parent_id";N;s:5:"label";s:5:"Exams";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-29 01:51:29";s:10:"updated_at";s:19:"2026-01-29 01:51:29";s:10:"deleted_at";N;s:8:"children";a:1:{i:0;a:12:{s:2:"id";s:2:"96";s:14:"menu_parent_id";s:2:"95";s:5:"label";s:12:"Exams Drafts";s:3:"url";s:26:"/administrator/exam-drafts";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-29 01:52:20";s:10:"updated_at";s:19:"2026-01-29 01:52:20";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:6;a:12:{s:2:"id";s:2:"86";s:14:"menu_parent_id";N;s:5:"label";s:11:"Competition";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-11 07:40:32";s:10:"updated_at";s:19:"2026-01-11 07:40:32";s:10:"deleted_at";N;s:8:"children";a:1:{i:0;a:12:{s:2:"id";s:2:"87";s:14:"menu_parent_id";s:2:"86";s:5:"label";s:17:"Competition Setup";s:3:"url";s:19:"competition-winners";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-11 07:41:19";s:10:"updated_at";s:19:"2026-01-11 07:41:19";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:7;a:12:{s:2:"id";s:1:"1";s:14:"menu_parent_id";N;s:5:"label";s:5:"Users";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"10";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:6:{i:0;a:12:{s:2:"id";s:2:"12";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:20:"Active Notifications";s:3:"url";s:20:"notifications/active";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"13";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:21:"Deleted Notifications";s:3:"url";s:21:"notifications/deleted";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"14";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:14:"Login Activity";s:3:"url";s:19:"user/login_activity";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:55:24";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"15";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:9:"User List";s:3:"url";s:14:"user/user_list";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"52";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:14:"Navbar Builder";s:3:"url";s:11:"nav-builder";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"5";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:34:01";s:10:"updated_at";s:19:"2025-09-05 21:57:09";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:5;a:12:{s:2:"id";s:2:"76";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:13:"IP Management";s:3:"url";s:21:"administrator/ip_bans";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"5";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:34:35";s:10:"updated_at";s:19:"2025-10-26 06:34:35";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:8;a:12:{s:2:"id";s:1:"2";s:14:"menu_parent_id";N;s:5:"label";s:5:"Roles";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"20";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:56:34";s:10:"deleted_at";N;s:8:"children";a:3:{i:0;a:12:{s:2:"id";s:2:"16";s:14:"menu_parent_id";s:1:"2";s:5:"label";s:16:"Assign User Role";s:3:"url";s:26:"rolepermission/assign_role";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:11:09";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"17";s:14:"menu_parent_id";s:1:"2";s:5:"label";s:15:"Role Management";s:3:"url";s:20:"rolepermission/roles";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:55:43";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"53";s:14:"menu_parent_id";s:1:"2";s:5:"label";s:21:"Permission Management";s:3:"url";s:31:"rolepermission/list_permissions";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-08 05:25:02";s:10:"updated_at";s:19:"2025-09-12 07:24:13";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:9;a:12:{s:2:"id";s:1:"3";s:14:"menu_parent_id";N;s:5:"label";s:13:"Configuration";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"30";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:54:57";s:10:"deleted_at";N;s:8:"children";a:2:{i:0;a:12:{s:2:"id";s:2:"84";s:14:"menu_parent_id";s:1:"3";s:5:"label";s:24:"Edit attendance Comments";s:3:"url";s:34:"administrator/attendance-templates";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-04 04:17:02";s:10:"updated_at";s:19:"2026-01-04 04:17:02";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"18";s:14:"menu_parent_id";s:1:"3";s:5:"label";s:22:"Add/Edit Configuration";s:3:"url";s:32:"configuration/configuration_view";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:52:20";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:10;a:12:{s:2:"id";s:1:"4";s:14:"menu_parent_id";N;s:5:"label";s:8:"Staffing";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"40";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:3:{i:0;a:12:{s:2:"id";s:2:"71";s:14:"menu_parent_id";s:1:"4";s:5:"label";s:16:"Staff Attendance";s:3:"url";s:30:"admin/teacher-attendance/month";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-27 04:29:24";s:10:"updated_at";s:19:"2025-09-28 05:39:08";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"19";s:14:"menu_parent_id";s:1:"4";s:5:"label";s:13:"Staff Profile";s:3:"url";s:11:"staff/index";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"20";s:14:"menu_parent_id";s:1:"4";s:5:"label";s:24:"Teacher Class Assignment";s:3:"url";s:38:"administrator/teacher_class_assignment";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:11;a:12:{s:2:"id";s:1:"5";s:14:"menu_parent_id";N;s:5:"label";s:7:"Parents";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"50";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:1:{i:0;a:12:{s:2:"id";s:2:"21";s:14:"menu_parent_id";s:1:"5";s:5:"label";s:14:"Parent Profile";s:3:"url";s:29:"administrator/parent_profiles";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:12;a:12:{s:2:"id";s:1:"6";s:14:"menu_parent_id";N;s:5:"label";s:15:"Student-Affairs";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"60";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:16:{i:0;a:12:{s:2:"id";s:2:"90";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:14:"Remove Student";s:3:"url";s:31:"/administrator/removed_students";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-14 03:53:43";s:10:"updated_at";s:19:"2026-01-14 03:53:43";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"97";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:14:"Placement Test";s:3:"url";s:17:"grading/placement";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-02-06 03:08:29";s:10:"updated_at";s:19:"2026-02-06 03:08:29";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"22";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:21:"Attendance Management";s:3:"url";s:30:"administrator/daily_attendance";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-27 05:10:47";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"23";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:26:"Attendance Tracking System";s:3:"url";s:21:"attendance/violations";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-10-12 15:13:51";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"24";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:16:"Attendance Scans";s:3:"url";s:16:"rfid_coming_soon";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:5;a:12:{s:2:"id";s:2:"25";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:12:"Classes List";s:3:"url";s:30:"administrator/class_assignment";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:6;a:12:{s:2:"id";s:2:"78";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:16:"Early Dismissals";s:3:"url";s:27:"attendance/early-dismissals";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:40:01";s:10:"updated_at";s:19:"2025-10-26 14:57:41";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:7;a:12:{s:2:"id";s:2:"26";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:17:"Emergency Contact";s:3:"url";s:31:"administrator/emergency_contact";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"5";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:56:05";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:8;a:12:{s:2:"id";s:2:"27";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:21:"Enrollment-Withdrawal";s:3:"url";s:37:"enroll_withdraw/enrollment_withdrawal";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"6";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-19 06:23:25";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:9;a:12:{s:2:"id";s:2:"28";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:20:"Incidents Management";s:3:"url";s:22:"flags/flags_management";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"7";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2026-01-29 04:26:10";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:10;a:12:{s:2:"id";s:2:"29";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:15:"School Calendar";s:3:"url";s:27:"administrator/calendar_view";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"8";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:11;a:12:{s:2:"id";s:2:"77";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:18:"Late Slips History";s:3:"url";s:13:"slips/preview";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"8";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:38:42";s:10:"updated_at";s:19:"2025-10-26 06:38:42";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:12;a:12:{s:2:"id";s:2:"30";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:14:"Score Analysis";s:3:"url";s:15:"report/combined";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"9";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2026-01-26 05:12:17";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:13;a:12:{s:2:"id";s:2:"31";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:16:"Score Management";s:3:"url";s:7:"grading";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"10";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2026-01-26 05:11:48";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:14;a:12:{s:2:"id";s:2:"32";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:24:"Student Class Assignment";s:3:"url";s:38:"administrator/student_class_assignment";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"11";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:15;a:12:{s:2:"id";s:2:"33";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:15:"Student Profile";s:3:"url";s:30:"administrator/student_profiles";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"12";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:13;a:12:{s:2:"id";s:1:"7";s:14:"menu_parent_id";N;s:5:"label";s:7:"Classes";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"70";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:3:{i:0;a:12:{s:2:"id";s:2:"79";s:14:"menu_parent_id";s:1:"7";s:5:"label";s:16:"Class Distribute";s:3:"url";s:38:"administrator/sections/auto-distribute";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:41:13";s:10:"updated_at";s:19:"2025-10-26 06:41:13";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"34";s:14:"menu_parent_id";s:1:"7";s:5:"label";s:12:"Classes List";s:3:"url";s:30:"administrator/class_assignment";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:08:21";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"80";s:14:"menu_parent_id";s:1:"7";s:5:"label";s:22:"Section Auto Generator";s:3:"url";s:39:"administrator/sections/promotion-totals";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:42:02";s:10:"updated_at";s:19:"2025-10-26 06:42:02";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:14;a:12:{s:2:"id";s:1:"8";s:14:"menu_parent_id";N;s:5:"label";s:13:"Communication";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"80";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:46:08";s:10:"deleted_at";N;s:8:"children";a:7:{i:0;a:12:{s:2:"id";s:2:"98";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:16:"Below 60 Summary";s:3:"url";s:16:"grading/below-60";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-03-01 21:50:13";s:10:"updated_at";s:19:"2026-03-01 21:50:13";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"65";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:12:"New Students";s:3:"url";s:29:"admin/enrollment/new-students";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-11 03:44:37";s:10:"updated_at";s:19:"2025-09-16 16:45:27";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"73";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:24:"Whatsapp Link Management";s:3:"url";s:9:"whatsapp/";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-11 22:58:29";s:10:"updated_at";s:19:"2025-10-11 22:58:29";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"35";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:22:"Parent Email Extractor";s:3:"url";s:29:"emails/parent_email_extractor";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:08:44";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"36";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:14:"Parent Profile";s:3:"url";s:29:"administrator/parent_profiles";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:44:58";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:5;a:12:{s:2:"id";s:2:"37";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:15:"Student Profile";s:3:"url";s:30:"administrator/student_profiles";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:09:19";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:6;a:12:{s:2:"id";s:2:"81";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:16:"Grading Tracking";s:3:"url";s:25:"grading/homework-tracking";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:43:11";s:10:"updated_at";s:19:"2025-10-26 14:35:52";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:15;a:12:{s:2:"id";s:1:"9";s:14:"menu_parent_id";N;s:5:"label";s:9:"Financial";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"90";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:56:16";s:10:"deleted_at";N;s:8:"children";a:11:{i:0;a:12:{s:2:"id";s:2:"68";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:17:"Add Extra Charges";s:3:"url";s:13:"admin/charges";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-21 05:05:12";s:10:"updated_at";s:19:"2025-09-21 05:05:12";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"69";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:14:"Manual Payment";s:3:"url";s:18:"payment/manual_pay";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-21 05:06:53";s:10:"updated_at";s:19:"2025-09-21 05:06:53";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"82";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:16:"Payment Tracking";s:3:"url";s:22:"payment/unpaid-parents";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-11-01 16:23:39";s:10:"updated_at";s:19:"2025-12-07 16:19:30";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"38";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:19:"Discount Management";s:3:"url";s:14:"discounts/list";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:52:38";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"39";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:19:"Expenses Management";s:3:"url";s:14:"expenses/index";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:57:45";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:5;a:12:{s:2:"id";s:2:"40";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:16:"Financial Report";s:3:"url";s:24:"payment/financial_report";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:58:15";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:6;a:12:{s:2:"id";s:2:"41";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:19:"Invoices Management";s:3:"url";s:34:"invoice_payment/invoice_management";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:57:07";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:7;a:12:{s:2:"id";s:2:"42";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:14:"Manual Payment";s:3:"url";s:18:"payment/manual_pay";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"5";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:58:41";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:8;a:12:{s:2:"id";s:2:"43";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:18:"PaypalTransactions";s:3:"url";s:33:"administrator/paypal_transactions";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"6";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:9;a:12:{s:2:"id";s:2:"44";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:17:"Refund Management";s:3:"url";s:12:"refunds/list";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"7";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 17:02:17";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:10;a:12:{s:2:"id";s:2:"45";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:24:"Reimbursement Management";s:3:"url";s:20:"reimbursements/index";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"8";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 17:01:41";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:16;a:12:{s:2:"id";s:2:"10";s:14:"menu_parent_id";N;s:5:"label";s:10:"Printables";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:3:"100";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:5:{i:0;a:12:{s:2:"id";s:2:"85";s:14:"menu_parent_id";s:2:"10";s:5:"label";s:17:"Print for teacher";s:3:"url";s:20:"admin/print-requests";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-07 04:29:16";s:10:"updated_at";s:19:"2026-01-07 04:29:16";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"46";s:14:"menu_parent_id";s:2:"10";s:5:"label";s:6:"Badges";s:3:"url";s:29:"printables_reports/badge_form";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:18:24";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"47";s:14:"menu_parent_id";s:2:"10";s:5:"label";s:10:"Class Prep";s:3:"url";s:10:"class-prep";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-27 04:31:03";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"48";s:14:"menu_parent_id";s:2:"10";s:5:"label";s:12:"Report Cards";s:3:"url";s:30:"printables_reports/report_card";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"49";s:14:"menu_parent_id";s:2:"10";s:5:"label";s:8:"Stickers";s:3:"url";s:27:"printables_reports/stickers";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:17;a:12:{s:2:"id";s:2:"11";s:14:"menu_parent_id";N;s:5:"label";s:16:"Event Management";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:3:"110";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:2:{i:0;a:12:{s:2:"id";s:2:"50";s:14:"menu_parent_id";s:2:"11";s:5:"label";s:8:"Calendar";s:3:"url";s:22:"administrator/calendar";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:20:09";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"51";s:14:"menu_parent_id";s:2:"11";s:5:"label";s:6:"Events";s:3:"url";s:20:"administrator/events";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}}}}} \ No newline at end of file +a:3:{s:4:"time";i:1776520433;s:3:"ttl";i:300;s:4:"data";a:18:{i:0;a:12:{s:2:"id";s:2:"63";s:14:"menu_parent_id";N;s:5:"label";s:6:"Family";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-09 15:22:56";s:10:"updated_at";s:19:"2025-10-26 06:33:11";s:10:"deleted_at";N;s:8:"children";a:2:{i:0;a:12:{s:2:"id";s:2:"64";s:14:"menu_parent_id";s:2:"63";s:5:"label";s:16:"Family Managment";s:3:"url";s:12:"family/index";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-09 15:23:49";s:10:"updated_at";s:19:"2025-10-26 06:28:34";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"74";s:14:"menu_parent_id";s:2:"63";s:5:"label";s:13:"Family Update";s:3:"url";s:22:"families/import-legacy";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:29:11";s:10:"updated_at";s:19:"2025-10-26 06:29:11";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:1;a:12:{s:2:"id";s:2:"67";s:14:"menu_parent_id";N;s:5:"label";s:9:"Inventory";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-11 06:24:37";s:10:"updated_at";s:19:"2025-09-16 16:48:58";s:10:"deleted_at";N;s:8:"children";a:6:{i:0;a:12:{s:2:"id";s:2:"56";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:5:"Books";s:3:"url";s:14:"inventory/book";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-08 19:13:48";s:10:"updated_at";s:19:"2025-10-05 03:43:38";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"72";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:26:"Update Inventory Movements";s:3:"url";s:19:"inventory/movements";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-02 06:07:53";s:10:"updated_at";s:19:"2025-10-05 03:42:08";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"55";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:19:"Classroom Equipment";s:3:"url";s:9:"inventory";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-08 18:56:08";s:10:"updated_at";s:19:"2025-09-16 16:47:32";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"57";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:16:"Kitchen Supplies";s:3:"url";s:17:"inventory/kitchen";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-08 19:14:24";s:10:"updated_at";s:19:"2025-09-16 16:48:23";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"58";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:15:"Office Supplies";s:3:"url";s:16:"inventory/office";s:10:"icon_class";N;s:6:"target";s:6:"_blank";s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-08 19:14:53";s:10:"updated_at";s:19:"2025-09-10 22:17:05";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:5;a:12:{s:2:"id";s:2:"66";s:14:"menu_parent_id";s:2:"67";s:5:"label";s:7:"Summary";s:3:"url";s:21:"inventory/summary-all";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-11 05:56:10";s:10:"updated_at";s:19:"2025-09-11 06:28:41";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:2;a:12:{s:2:"id";s:2:"83";s:14:"menu_parent_id";N;s:5:"label";s:15:"TimeOff Request";s:3:"url";s:22:"/administrator/absence";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-11-01 20:58:55";s:10:"updated_at";s:19:"2025-11-01 20:58:55";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"88";s:14:"menu_parent_id";N;s:5:"label";s:23:"Notification Management";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-13 19:48:58";s:10:"updated_at";s:19:"2026-01-13 19:48:58";s:10:"deleted_at";N;s:8:"children";a:1:{i:0;a:12:{s:2:"id";s:2:"89";s:14:"menu_parent_id";s:2:"88";s:5:"label";s:18:"Notification Setup";s:3:"url";s:35:"/administrator/notifications_alerts";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-13 19:49:35";s:10:"updated_at";s:19:"2026-01-13 19:49:35";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:4;a:12:{s:2:"id";s:2:"92";s:14:"menu_parent_id";N;s:5:"label";s:10:"Curriculum";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-18 07:23:26";s:10:"updated_at";s:19:"2026-01-18 07:23:26";s:10:"deleted_at";N;s:8:"children";a:3:{i:0;a:12:{s:2:"id";s:2:"94";s:14:"menu_parent_id";s:2:"92";s:5:"label";s:19:"Teacher Submissions";s:3:"url";s:33:"administrator/teacher-submissions";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-25 22:20:24";s:10:"updated_at";s:19:"2026-03-29 15:58:33";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"93";s:14:"menu_parent_id";s:2:"92";s:5:"label";s:18:"Curriculum Subject";s:3:"url";s:32:"administrator/subject-curriculum";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-18 07:25:26";s:10:"updated_at";s:19:"2026-01-18 07:25:26";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"91";s:14:"menu_parent_id";s:2:"92";s:5:"label";s:14:"Class Progress";s:3:"url";s:14:"admin/progress";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-15 04:38:48";s:10:"updated_at";s:19:"2026-01-18 07:24:37";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:5;a:12:{s:2:"id";s:2:"95";s:14:"menu_parent_id";N;s:5:"label";s:5:"Exams";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-29 01:51:29";s:10:"updated_at";s:19:"2026-01-29 01:51:29";s:10:"deleted_at";N;s:8:"children";a:1:{i:0;a:12:{s:2:"id";s:2:"96";s:14:"menu_parent_id";s:2:"95";s:5:"label";s:12:"Exams Drafts";s:3:"url";s:26:"/administrator/exam-drafts";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-29 01:52:20";s:10:"updated_at";s:19:"2026-01-29 01:52:20";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:6;a:12:{s:2:"id";s:2:"86";s:14:"menu_parent_id";N;s:5:"label";s:11:"Competition";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-11 07:40:32";s:10:"updated_at";s:19:"2026-01-11 07:40:32";s:10:"deleted_at";N;s:8:"children";a:1:{i:0;a:12:{s:2:"id";s:2:"87";s:14:"menu_parent_id";s:2:"86";s:5:"label";s:17:"Competition Setup";s:3:"url";s:19:"competition-winners";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-11 07:41:19";s:10:"updated_at";s:19:"2026-01-11 07:41:19";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:7;a:12:{s:2:"id";s:1:"1";s:14:"menu_parent_id";N;s:5:"label";s:5:"Users";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"10";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:6:{i:0;a:12:{s:2:"id";s:2:"12";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:20:"Active Notifications";s:3:"url";s:20:"notifications/active";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"13";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:21:"Deleted Notifications";s:3:"url";s:21:"notifications/deleted";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"14";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:14:"Login Activity";s:3:"url";s:19:"user/login_activity";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:55:24";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"15";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:9:"User List";s:3:"url";s:14:"user/user_list";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"52";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:14:"Navbar Builder";s:3:"url";s:11:"nav-builder";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"5";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:34:01";s:10:"updated_at";s:19:"2025-09-05 21:57:09";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:5;a:12:{s:2:"id";s:2:"76";s:14:"menu_parent_id";s:1:"1";s:5:"label";s:13:"IP Management";s:3:"url";s:21:"administrator/ip_bans";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"5";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:34:35";s:10:"updated_at";s:19:"2025-10-26 06:34:35";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:8;a:12:{s:2:"id";s:1:"2";s:14:"menu_parent_id";N;s:5:"label";s:5:"Roles";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"20";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:56:34";s:10:"deleted_at";N;s:8:"children";a:3:{i:0;a:12:{s:2:"id";s:2:"16";s:14:"menu_parent_id";s:1:"2";s:5:"label";s:16:"Assign User Role";s:3:"url";s:26:"rolepermission/assign_role";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:11:09";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"17";s:14:"menu_parent_id";s:1:"2";s:5:"label";s:15:"Role Management";s:3:"url";s:20:"rolepermission/roles";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:55:43";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"53";s:14:"menu_parent_id";s:1:"2";s:5:"label";s:21:"Permission Management";s:3:"url";s:31:"rolepermission/list_permissions";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-08 05:25:02";s:10:"updated_at";s:19:"2025-09-12 07:24:13";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:9;a:12:{s:2:"id";s:1:"3";s:14:"menu_parent_id";N;s:5:"label";s:13:"Configuration";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"30";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:54:57";s:10:"deleted_at";N;s:8:"children";a:2:{i:0;a:12:{s:2:"id";s:2:"84";s:14:"menu_parent_id";s:1:"3";s:5:"label";s:24:"Edit attendance Comments";s:3:"url";s:34:"administrator/attendance-templates";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-04 04:17:02";s:10:"updated_at";s:19:"2026-01-04 04:17:02";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"18";s:14:"menu_parent_id";s:1:"3";s:5:"label";s:22:"Add/Edit Configuration";s:3:"url";s:32:"configuration/configuration_view";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:52:20";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:10;a:12:{s:2:"id";s:1:"4";s:14:"menu_parent_id";N;s:5:"label";s:8:"Staffing";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"40";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:3:{i:0;a:12:{s:2:"id";s:2:"71";s:14:"menu_parent_id";s:1:"4";s:5:"label";s:16:"Staff Attendance";s:3:"url";s:30:"admin/teacher-attendance/month";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-27 04:29:24";s:10:"updated_at";s:19:"2025-09-28 05:39:08";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"19";s:14:"menu_parent_id";s:1:"4";s:5:"label";s:13:"Staff Profile";s:3:"url";s:11:"staff/index";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"20";s:14:"menu_parent_id";s:1:"4";s:5:"label";s:24:"Teacher Class Assignment";s:3:"url";s:38:"administrator/teacher_class_assignment";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:11;a:12:{s:2:"id";s:1:"5";s:14:"menu_parent_id";N;s:5:"label";s:7:"Parents";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"50";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:1:{i:0;a:12:{s:2:"id";s:2:"21";s:14:"menu_parent_id";s:1:"5";s:5:"label";s:14:"Parent Profile";s:3:"url";s:29:"administrator/parent_profiles";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:12;a:12:{s:2:"id";s:1:"6";s:14:"menu_parent_id";N;s:5:"label";s:15:"Student-Affairs";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"60";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:16:{i:0;a:12:{s:2:"id";s:2:"90";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:14:"Remove Student";s:3:"url";s:31:"/administrator/removed_students";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-14 03:53:43";s:10:"updated_at";s:19:"2026-01-14 03:53:43";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"97";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:14:"Placement Test";s:3:"url";s:17:"grading/placement";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-02-06 03:08:29";s:10:"updated_at";s:19:"2026-02-06 03:08:29";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"22";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:21:"Attendance Management";s:3:"url";s:30:"administrator/daily_attendance";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-27 05:10:47";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"23";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:26:"Attendance Tracking System";s:3:"url";s:21:"attendance/violations";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-10-12 15:13:51";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"24";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:16:"Attendance Scans";s:3:"url";s:16:"rfid_coming_soon";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:5;a:12:{s:2:"id";s:2:"25";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:12:"Classes List";s:3:"url";s:30:"administrator/class_assignment";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:6;a:12:{s:2:"id";s:2:"78";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:16:"Early Dismissals";s:3:"url";s:27:"attendance/early-dismissals";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:40:01";s:10:"updated_at";s:19:"2025-10-26 14:57:41";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:7;a:12:{s:2:"id";s:2:"26";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:17:"Emergency Contact";s:3:"url";s:31:"administrator/emergency_contact";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"5";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:56:05";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:8;a:12:{s:2:"id";s:2:"27";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:21:"Enrollment-Withdrawal";s:3:"url";s:37:"enroll_withdraw/enrollment_withdrawal";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"6";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-19 06:23:25";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:9;a:12:{s:2:"id";s:2:"28";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:20:"Incidents Management";s:3:"url";s:22:"flags/flags_management";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"7";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2026-01-29 04:26:10";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:10;a:12:{s:2:"id";s:2:"29";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:15:"School Calendar";s:3:"url";s:27:"administrator/calendar_view";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"8";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:11;a:12:{s:2:"id";s:2:"77";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:18:"Late Slips History";s:3:"url";s:13:"slips/preview";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"8";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:38:42";s:10:"updated_at";s:19:"2025-10-26 06:38:42";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:12;a:12:{s:2:"id";s:2:"30";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:14:"Score Analysis";s:3:"url";s:15:"report/combined";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"9";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2026-01-26 05:12:17";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:13;a:12:{s:2:"id";s:2:"31";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:16:"Score Management";s:3:"url";s:7:"grading";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"10";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2026-01-26 05:11:48";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:14;a:12:{s:2:"id";s:2:"32";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:24:"Student Class Assignment";s:3:"url";s:38:"administrator/student_class_assignment";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"11";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:15;a:12:{s:2:"id";s:2:"33";s:14:"menu_parent_id";s:1:"6";s:5:"label";s:15:"Student Profile";s:3:"url";s:30:"administrator/student_profiles";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"12";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:13;a:12:{s:2:"id";s:1:"7";s:14:"menu_parent_id";N;s:5:"label";s:7:"Classes";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"70";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:3:{i:0;a:12:{s:2:"id";s:2:"79";s:14:"menu_parent_id";s:1:"7";s:5:"label";s:16:"Class Distribute";s:3:"url";s:38:"administrator/sections/auto-distribute";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:41:13";s:10:"updated_at";s:19:"2025-10-26 06:41:13";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"34";s:14:"menu_parent_id";s:1:"7";s:5:"label";s:12:"Classes List";s:3:"url";s:30:"administrator/class_assignment";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:08:21";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"80";s:14:"menu_parent_id";s:1:"7";s:5:"label";s:22:"Section Auto Generator";s:3:"url";s:39:"administrator/sections/promotion-totals";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:42:02";s:10:"updated_at";s:19:"2025-10-26 06:42:02";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:14;a:12:{s:2:"id";s:1:"8";s:14:"menu_parent_id";N;s:5:"label";s:13:"Communication";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"80";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:46:08";s:10:"deleted_at";N;s:8:"children";a:7:{i:0;a:12:{s:2:"id";s:2:"98";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:16:"Below 60 Summary";s:3:"url";s:16:"grading/below-60";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-03-01 21:50:13";s:10:"updated_at";s:19:"2026-03-01 21:50:13";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"65";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:12:"New Students";s:3:"url";s:29:"admin/enrollment/new-students";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-11 03:44:37";s:10:"updated_at";s:19:"2025-09-16 16:45:27";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"73";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:24:"Whatsapp Link Management";s:3:"url";s:9:"whatsapp/";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-11 22:58:29";s:10:"updated_at";s:19:"2025-10-11 22:58:29";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"35";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:22:"Parent Email Extractor";s:3:"url";s:29:"emails/parent_email_extractor";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:08:44";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"36";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:14:"Parent Profile";s:3:"url";s:29:"administrator/parent_profiles";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:44:58";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:5;a:12:{s:2:"id";s:2:"37";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:15:"Student Profile";s:3:"url";s:30:"administrator/student_profiles";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:09:19";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:6;a:12:{s:2:"id";s:2:"81";s:14:"menu_parent_id";s:1:"8";s:5:"label";s:16:"Grading Tracking";s:3:"url";s:25:"grading/homework-tracking";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-10-26 06:43:11";s:10:"updated_at";s:19:"2025-10-26 14:35:52";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:15;a:12:{s:2:"id";s:1:"9";s:14:"menu_parent_id";N;s:5:"label";s:9:"Financial";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:2:"90";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:56:16";s:10:"deleted_at";N;s:8:"children";a:11:{i:0;a:12:{s:2:"id";s:2:"68";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:17:"Add Extra Charges";s:3:"url";s:13:"admin/charges";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-21 05:05:12";s:10:"updated_at";s:19:"2025-09-21 05:05:12";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"69";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:14:"Manual Payment";s:3:"url";s:18:"payment/manual_pay";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-21 05:06:53";s:10:"updated_at";s:19:"2025-09-21 05:06:53";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"82";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:16:"Payment Tracking";s:3:"url";s:22:"payment/unpaid-parents";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-11-01 16:23:39";s:10:"updated_at";s:19:"2025-12-07 16:19:30";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"38";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:19:"Discount Management";s:3:"url";s:14:"discounts/list";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 02:52:38";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"39";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:19:"Expenses Management";s:3:"url";s:14:"expenses/index";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:57:45";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:5;a:12:{s:2:"id";s:2:"40";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:16:"Financial Report";s:3:"url";s:24:"payment/financial_report";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:58:15";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:6;a:12:{s:2:"id";s:2:"41";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:19:"Invoices Management";s:3:"url";s:34:"invoice_payment/invoice_management";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:57:07";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:7;a:12:{s:2:"id";s:2:"42";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:14:"Manual Payment";s:3:"url";s:18:"payment/manual_pay";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"5";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 16:58:41";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:8;a:12:{s:2:"id";s:2:"43";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:18:"PaypalTransactions";s:3:"url";s:33:"administrator/paypal_transactions";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"6";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:9;a:12:{s:2:"id";s:2:"44";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:17:"Refund Management";s:3:"url";s:12:"refunds/list";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"7";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 17:02:17";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:10;a:12:{s:2:"id";s:2:"45";s:14:"menu_parent_id";s:1:"9";s:5:"label";s:24:"Reimbursement Management";s:3:"url";s:20:"reimbursements/index";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"8";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-16 17:01:41";s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:16;a:12:{s:2:"id";s:2:"10";s:14:"menu_parent_id";N;s:5:"label";s:10:"Printables";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:3:"100";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:5:{i:0;a:12:{s:2:"id";s:2:"85";s:14:"menu_parent_id";s:2:"10";s:5:"label";s:17:"Print for teacher";s:3:"url";s:20:"admin/print-requests";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"0";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2026-01-07 04:29:16";s:10:"updated_at";s:19:"2026-01-07 04:29:16";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"46";s:14:"menu_parent_id";s:2:"10";s:5:"label";s:6:"Badges";s:3:"url";s:29:"printables_reports/badge_form";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:18:24";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:2;a:12:{s:2:"id";s:2:"47";s:14:"menu_parent_id";s:2:"10";s:5:"label";s:10:"Class Prep";s:3:"url";s:10:"class-prep";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-27 04:31:03";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:3;a:12:{s:2:"id";s:2:"48";s:14:"menu_parent_id";s:2:"10";s:5:"label";s:12:"Report Cards";s:3:"url";s:30:"printables_reports/report_card";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"3";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}i:4;a:12:{s:2:"id";s:2:"49";s:14:"menu_parent_id";s:2:"10";s:5:"label";s:8:"Stickers";s:3:"url";s:27:"printables_reports/stickers";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"4";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}}}i:17;a:12:{s:2:"id";s:2:"11";s:14:"menu_parent_id";N;s:5:"label";s:16:"Event Management";s:3:"url";N;s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:3:"110";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:2:{i:0;a:12:{s:2:"id";s:2:"50";s:14:"menu_parent_id";s:2:"11";s:5:"label";s:8:"Calendar";s:3:"url";s:22:"administrator/calendar";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"1";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";s:19:"2025-09-09 03:20:09";s:10:"deleted_at";N;s:8:"children";a:0:{}}i:1;a:12:{s:2:"id";s:2:"51";s:14:"menu_parent_id";s:2:"11";s:5:"label";s:6:"Events";s:3:"url";s:20:"administrator/events";s:10:"icon_class";N;s:6:"target";N;s:10:"sort_order";s:1:"2";s:10:"is_enabled";s:1:"1";s:10:"created_at";s:19:"2025-09-05 17:23:56";s:10:"updated_at";N;s:10:"deleted_at";N;s:8:"children";a:0:{}}}}}} \ No newline at end of file