fix events logic

This commit is contained in:
root
2026-04-11 20:08:47 -04:00
parent 7bc999643a
commit 4e2d12e524
14 changed files with 588 additions and 343 deletions
+11 -55
View File
@@ -93,58 +93,6 @@ class EventController extends ResourceController
'created_by' => session()->get('user_id'), 'created_by' => session()->get('user_id'),
]); ]);
if ($eventId) {
$amount = (float) $this->request->getPost('amount');
$semester = (string) $this->request->getPost('semester');
$schoolYear = (string) $this->request->getPost('school_year');
$userId = (int) (session()->get('user_id') ?? 0);
$enrollments = $this->enrollmentModel
->select('enrollments.student_id, students.parent_id')
->join('students', 'students.id = enrollments.student_id', 'left')
->where('enrollments.school_year', $schoolYear)
->whereIn('enrollments.enrollment_status', ['enrolled', 'payment pending'])
->findAll();
$parentIds = [];
foreach ($enrollments as $row) {
$studentId = (int) ($row['student_id'] ?? 0);
$parentId = (int) ($row['parent_id'] ?? 0);
if ($studentId <= 0 || $parentId <= 0) {
continue;
}
$exists = $this->eventChargesModel
->where('event_id', $eventId)
->where('student_id', $studentId)
->where('school_year', $schoolYear)
->where('semester', $semester)
->first();
if ($exists) {
continue;
}
$this->eventChargesModel->insert([
'event_id' => $eventId,
'parent_id' => $parentId,
'student_id' => $studentId,
'participation' => 'yes',
'charged' => $amount,
'school_year' => $schoolYear,
'semester' => $semester,
'updated_by' => $userId ?: null,
]);
$parentIds[] = $parentId;
}
$parentIds = array_unique($parentIds);
foreach ($parentIds as $pid) {
$this->invoiceController->generateInvoice((string) $pid);
}
}
return redirect()->to('/administrator/events')->with('success', 'Event created successfully'); return redirect()->to('/administrator/events')->with('success', 'Event created successfully');
} }
@@ -240,17 +188,24 @@ class EventController extends ResourceController
$parents = $this->userModel->getParents(); $parents = $this->userModel->getParents();
$events = $this->eventModel->getActiveEvents($this->schoolYear); $events = $this->eventModel->getActiveEvents($this->schoolYear);
$filterEventId = (int) ($this->request->getGet('event_id') ?? 0);
$charges = $this->eventChargesModel $chargesBuilder = $this->eventChargesModel
->select('event_charges.*, ->select('event_charges.*,
users.firstname AS parent_firstname, users.lastname AS parent_lastname, users.firstname AS parent_firstname, users.lastname AS parent_lastname,
students.firstname AS student_firstname, students.lastname AS student_lastname, students.firstname AS student_firstname, students.lastname AS student_lastname,
events.event_name') events.event_name, events.description AS event_description, events.amount AS event_amount')
->join('users', 'users.id = event_charges.parent_id', 'left') ->join('users', 'users.id = event_charges.parent_id', 'left')
->join('students', 'students.id = event_charges.student_id', 'left') ->join('students', 'students.id = event_charges.student_id', 'left')
->join('events', 'events.id = event_charges.event_id', 'left') ->join('events', 'events.id = event_charges.event_id', 'left')
->where('event_charges.school_year', $schoolYear) ->where('event_charges.school_year', $schoolYear)
->where('event_charges.semester', $semester) ->where('event_charges.semester', $semester);
if ($filterEventId > 0) {
$chargesBuilder->where('event_charges.event_id', $filterEventId);
}
$charges = $chargesBuilder
->orderBy('event_charges.created_at', 'DESC') ->orderBy('event_charges.created_at', 'DESC')
->findAll(); ->findAll();
@@ -260,6 +215,7 @@ class EventController extends ResourceController
'events' => $events, 'events' => $events,
'school_year' => $schoolYear, 'school_year' => $schoolYear,
'semester' => $semester, 'semester' => $semester,
'filterEventId' => $filterEventId,
]); ]);
} }
+55 -13
View File
@@ -216,25 +216,28 @@ public function financialReport()
$schoolYears[] = (string)$schoolYear; $schoolYears[] = (string)$schoolYear;
} }
$eventFeesTotal = $this->getEventFeesTotal($schoolYear, $dateFrom, $dateTo);
// JSON API support // JSON API support
if ($this->wantsJson() || strtolower((string)($this->request->getGet('format') ?? '')) === 'json') { if ($this->wantsJson() || strtolower((string)($this->request->getGet('format') ?? '')) === 'json') {
return $this->response->setJSON([ return $this->response->setJSON([
'ok' => true, 'ok' => true,
'selectedYear' => $schoolYear, 'selectedYear' => $schoolYear,
'dateFrom' => $dateFrom, 'dateFrom' => $dateFrom,
'dateTo' => $dateTo, 'dateTo' => $dateTo,
'schoolYears' => $schoolYears, 'schoolYears' => $schoolYears,
'invoices' => $invoices, 'invoices' => $invoices,
'payments' => $payments, 'payments' => $payments,
'paymentBreakdown' => $paymentBreakdown, 'paymentBreakdown' => $paymentBreakdown,
'paymentTotals' => $paymentTotals, 'paymentTotals' => $paymentTotals,
'refunds' => $refunds, 'refunds' => $refunds,
'expenses' => $expenses, 'expenses' => $expenses,
'reimbursements' => $reimbursements, 'reimbursements' => $reimbursements,
'discounts' => $discounts, 'discounts' => $discounts,
'csrf_token' => csrf_token(), 'eventFeesTotal' => $eventFeesTotal,
'csrf_hash' => csrf_hash(), 'csrf_token' => csrf_token(),
]); 'csrf_hash' => csrf_hash(),
]);
} }
return view('payment/financial_report', [ return view('payment/financial_report', [
@@ -246,6 +249,7 @@ public function financialReport()
'expenses' => $expenses, 'expenses' => $expenses,
'reimbursements' => $reimbursements, 'reimbursements' => $reimbursements,
'discounts' => $discounts, 'discounts' => $discounts,
'eventFeesTotal' => $eventFeesTotal,
'selectedYear' => $schoolYear, 'selectedYear' => $schoolYear,
'schoolYears' => $schoolYears, 'schoolYears' => $schoolYears,
'dateFrom' => $dateFrom, 'dateFrom' => $dateFrom,
@@ -1058,6 +1062,7 @@ public function financialReport()
$amountCollected = $totalPaid; $amountCollected = $totalPaid;
$netAmount = ($totalCharges - $totalDiscounts - $totalRefunds); $netAmount = ($totalCharges - $totalDiscounts - $totalRefunds);
$totalEventFees = $this->getEventFeesTotal($schoolYear, $invoiceDateFrom, $invoiceDateTo);
return [ return [
'schoolYear' => $schoolYear, 'schoolYear' => $schoolYear,
'dateFrom' => $dateFrom, 'dateFrom' => $dateFrom,
@@ -1073,9 +1078,28 @@ public function financialReport()
'amountCollected' => $amountCollected, 'amountCollected' => $amountCollected,
'totalUnpaid' => $totalUnpaid, 'totalUnpaid' => $totalUnpaid,
'netAmount' => $netAmount, 'netAmount' => $netAmount,
'totalEventFees' => $totalEventFees,
]; ];
} }
private function getEventFeesTotal(?string $schoolYear, ?string $dateFrom, ?string $dateTo): float
{
$db = \Config\Database::connect();
$builder = $db->table('event_charges ec')
->select('COALESCE(SUM(ec.charged),0) AS amount', false);
if (!empty($schoolYear)) {
$builder->where('ec.school_year', $schoolYear);
}
if (!empty($dateFrom)) {
$builder->where('DATE(ec.created_at) >=', $dateFrom);
}
if (!empty($dateTo)) {
$builder->where('DATE(ec.created_at) <=', $dateTo);
}
$row = $builder->get()->getRowArray();
return $row ? (float)($row['amount'] ?? 0) : 0.0;
}
/** /**
* Management page: list parents with outstanding balances (> 0) for a school year. * Management page: list parents with outstanding balances (> 0) for a school year.
@@ -1226,6 +1250,23 @@ public function financialReport()
$byParent[$pid]['total_balance'] += $extra; $byParent[$pid]['total_balance'] += $extra;
} }
$eventFeesPerParent = [];
try {
$eventFeesRows = $db->table('event_charges ec')
->select('ec.parent_id, COALESCE(SUM(ec.charged),0) AS event_fees', false)
->where('ec.school_year', $schoolYear)
->groupBy('ec.parent_id')
->get()
->getResultArray();
foreach ($eventFeesRows as $row) {
$pid = (int)($row['parent_id'] ?? 0);
if ($pid <= 0) continue;
$eventFeesPerParent[$pid] = (float)($row['event_fees'] ?? 0);
}
} catch (\Throwable $e) {
// ignore, fallback to no event fees data
}
// Reduce into rows list; only parents with positive balance // Reduce into rows list; only parents with positive balance
// Also compute remaining installments and suggested monthly amount // Also compute remaining installments and suggested monthly amount
$rows = []; $rows = [];
@@ -1305,7 +1346,7 @@ public function financialReport()
} }
} }
$dataRows = array_map(function(array $r) use ($hasPayments, $paidTotals, $paymentCounts, $nextInstallmentYmd) { $dataRows = array_map(function(array $r) use ($hasPayments, $paidTotals, $paymentCounts, $nextInstallmentYmd, $eventFeesPerParent) {
$pid = (int)($r['parent_id'] ?? 0); $pid = (int)($r['parent_id'] ?? 0);
$name = trim((string)($r['firstname'] ?? '') . ' ' . (string)($r['lastname'] ?? '')); $name = trim((string)($r['firstname'] ?? '') . ' ' . (string)($r['lastname'] ?? ''));
return [ return [
@@ -1322,6 +1363,7 @@ public function financialReport()
'payment_count' => isset($paymentCounts[$pid]) ? (int)$paymentCounts[$pid] : 0, 'payment_count' => isset($paymentCounts[$pid]) ? (int)$paymentCounts[$pid] : 0,
'has_installment'=> isset($hasPayments[$pid]) ? 1 : 0, 'has_installment'=> isset($hasPayments[$pid]) ? 1 : 0,
'next_installment' => $nextInstallmentYmd, 'next_installment' => $nextInstallmentYmd,
'event_fees' => (float)($eventFeesPerParent[$pid] ?? 0),
]; ];
}, $rows); }, $rows);
+1 -1
View File
@@ -30,7 +30,7 @@ class EventChargesModel extends Model
public function getChargesWithEventInfo($parentId = null, $schoolYear = null, $semester = null) public function getChargesWithEventInfo($parentId = null, $schoolYear = null, $semester = null)
{ {
$builder = $this->select('event_charges.*, events.event_name, events.amount') $builder = $this->select('event_charges.*, events.event_name, events.amount AS event_amount, events.description AS event_description')
->join('events', 'events.id = event_charges.event_id', 'left'); ->join('events', 'events.id = event_charges.event_id', 'left');
if ($parentId) { if ($parentId) {
@@ -4,6 +4,11 @@
<div class="container mt-4"> <div class="container mt-4">
<h2>Create Event</h2> <h2>Create Event</h2>
<?php
$defaultCategories = ['Fun Event-1', 'Fun Event-2', 'Fun Event-3'];
$existingCategories = array_map('strval', $categories ?? []);
$allCategories = array_unique(array_merge($defaultCategories, $existingCategories));
?>
<form method="post" action="<?= site_url('administrator/events/create') ?>" enctype="multipart/form-data"> <form method="post" action="<?= site_url('administrator/events/create') ?>" enctype="multipart/form-data">
<?= csrf_field() ?> <?= csrf_field() ?>
<div class="mb-3"> <div class="mb-3">
@@ -15,7 +20,7 @@
<label class="form-label">Category</label> <label class="form-label">Category</label>
<select name="event_category" class="form-control" required> <select name="event_category" class="form-control" required>
<option value="" selected disabled>Select category</option> <option value="" selected disabled>Select category</option>
<?php foreach (($categories ?? []) as $category): ?> <?php foreach ($allCategories as $category): ?>
<option value="<?= esc($category) ?>"><?= esc(ucwords($category)) ?></option> <option value="<?= esc($category) ?>"><?= esc(ucwords($category)) ?></option>
<?php endforeach; ?> <?php endforeach; ?>
</select> </select>
+102 -45
View File
@@ -11,44 +11,85 @@
<div class="alert alert-danger"><?= session()->getFlashdata('error') ?></div> <div class="alert alert-danger"><?= session()->getFlashdata('error') ?></div>
<?php endif; ?> <?php endif; ?>
<?php
$selectedEvent = null;
if (!empty($filterEventId)) {
foreach ($events as $event) {
if ((int)$event['id'] === (int)$filterEventId) {
$selectedEvent = $event;
break;
}
}
}
?>
<!-- Add New Charge Form --> <!-- Add New Charge Form -->
<form action="<?= site_url('payment/event_charges') ?>" method="post"> <div class="card mb-4">
<?= csrf_field() ?> <div class="card-body">
<div class="row"> <form action="<?= site_url('payment/event_charges') ?>" method="post">
<div class="col-md-3 mt-3"> <?= csrf_field() ?>
<label for="event_id" class="form-label">Select Event</label> <div class="row g-3">
<select name="event_id" id="event_id" class="form-select" required> <div class="col-md-4">
<option value="">-- Select Event --</option> <label for="event_id" class="form-label">Select Event</label>
<?php foreach ($events as $event): ?> <select name="event_id" id="event_id" class="form-select" required>
<option value="<?= esc($event['id']) ?>"> <option value="">-- All events --</option>
<?= esc($event['event_name']) ?> <?php foreach ($events as $event): ?>
</option> <option value="<?= esc($event['id']) ?>" <?= isset($filterEventId) && $filterEventId == $event['id'] ? 'selected' : '' ?>>
<?php endforeach; ?> <?= esc($event['event_name']) ?>
</select> </option>
</div> <?php endforeach; ?>
</select>
</div>
<div class="col-md-3 mt-3"> <?php if ($selectedEvent): ?>
<label for="parent_id" class="form-label">Parent</label> <div class="col-md-8">
<select id="parent_id" name="parent_id" class="form-select" required> <div class="border rounded bg-light p-3 h-100">
<option value="">-- Select Parent --</option> <div class="d-flex justify-content-between align-items-center mb-2">
<?php foreach ($parents as $parent): ?> <h6 class="m-0"><?= esc($selectedEvent['event_name']) ?></h6>
<option value="<?= $parent['id'] ?>"> <span class="badge bg-info text-dark">
<?= esc($parent['firstname'] . ' ' . $parent['lastname']) ?> (<?= esc($parent['school_id']) ?>) $<?= esc(number_format($selectedEvent['amount'] ?? 0, 2)) ?> fee
</option> </span>
<?php endforeach; ?> </div>
</select> <p class="mb-1 text-muted small">
</div> <?= esc($selectedEvent['description'] ?: 'No description provided for this event.') ?>
</p>
<?php if (!empty($selectedEvent['expiration_date'])): ?>
<small class="text-secondary">
Expires: <?= esc(local_date($selectedEvent['expiration_date'], 'm-d-Y')) ?>
</small>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<div class="col-12 mt-3" id="studentCheckboxContainer" style="display: none;"> </div>
<label>Select Students:</label>
<div id="studentList" class="row"></div> <div class="row g-3 mt-2">
</div> <div class="col-md-4">
<label for="parent_id" class="form-label">Parents List</label>
<select id="parent_id" name="parent_id" class="form-select" required>
<option value="">-- Select Parent --</option>
<?php foreach ($parents as $parent): ?>
<option value="<?= $parent['id'] ?>">
<?= esc($parent['firstname'] . ' ' . $parent['lastname']) ?> (<?= esc($parent['school_id']) ?>)
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="mt-4" id="studentCheckboxContainer" style="display: none;">
<label class="form-label">Select Students:</label>
<div id="studentList" class="row g-3"></div>
</div>
<div class="d-flex flex-wrap gap-2 mt-3">
<button type="submit" class="btn btn-primary">Submit</button>
<a href="<?= site_url('administrator/events') ?>" class="btn btn-success">Event List</a>
</div>
</form>
</div> </div>
</div>
<button type="submit" class="btn btn-primary mt-3">Submit</button>
<a href="<?= site_url('administrator/events') ?>" class="btn btn-success mt-3">Event List</a>
</form>
<br>
<!-- Charge Tables grouped by event --> <!-- Charge Tables grouped by event -->
<?php <?php
$grouped = []; $grouped = [];
@@ -70,16 +111,18 @@
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-bordered table-striped mb-0 no-mgmt-sticky"> <table class="table table-bordered table-striped mb-0 no-mgmt-sticky">
<thead class="table-light"> <thead class="table-light">
<tr> <tr>
<th>ID</th> <th>ID</th>
<th>Parent Name</th> <th>Parent Name</th>
<th>Student Name</th> <th>Student Name</th>
<th>Charged Amount</th> <th>Charged Amount</th>
<th>Is Participating</th> <th>Is Participating</th>
<th>Semester</th> <th>Semester</th>
<th>Year</th> <th>Year</th>
<th>Created</th> <th>Created</th>
</tr> <th>Description</th>
<th>Event Fees</th>
</tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($rows as $charge): ?> <?php foreach ($rows as $charge): ?>
@@ -100,6 +143,8 @@
<td><?= esc($charge['semester'] ?? '-') ?></td> <td><?= esc($charge['semester'] ?? '-') ?></td>
<td><?= esc($charge['school_year'] ?? '-') ?></td> <td><?= esc($charge['school_year'] ?? '-') ?></td>
<td><?= esc(!empty($charge['created_at']) ? local_datetime($charge['created_at'], 'm-d-Y H:i') : '') ?></td> <td><?= esc(!empty($charge['created_at']) ? local_datetime($charge['created_at'], 'm-d-Y H:i') : '') ?></td>
<td><?= esc($charge['event_description'] ?? '—') ?></td>
<td>$<?= esc(number_format($charge['event_amount'] ?? 0, 2)) ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</tbody> </tbody>
@@ -156,7 +201,19 @@ function loadStudentsWithCharges() {
} }
} }
$('#parent_id').on('change', loadStudentsWithCharges); $(function() {
$('#event_id').on('change', loadStudentsWithCharges); $('#parent_id').on('change', loadStudentsWithCharges);
$('#event_id').on('change', function() {
let eventId = $(this).val();
let url = new URL(window.location.href);
if (eventId) {
url.searchParams.set('event_id', eventId);
} else {
url.searchParams.delete('event_id');
}
window.location.href = url.toString();
});
});
</script> </script>
<?= $this->endSection() ?> <?= $this->endSection() ?>
@@ -21,7 +21,8 @@
<tr> <tr>
<th>Event Name</th> <th>Event Name</th>
<th>Category</th> <th>Category</th>
<th>Amount</th> <th>Description</th>
<th>Event Fees</th>
<th>Expiration Date</th> <th>Expiration Date</th>
<th>Semester</th> <th>Semester</th>
<th>School Year</th> <th>School Year</th>
@@ -33,7 +34,8 @@
<tr> <tr>
<td><?= esc($event['event_name']) ?></td> <td><?= esc($event['event_name']) ?></td>
<td><?= esc($event['event_category'] ?? '—') ?></td> <td><?= esc($event['event_category'] ?? '—') ?></td>
<td><?= esc($event['amount']) ?></td> <td><?= esc(!empty($event['description']) ? $event['description'] : '—') ?></td>
<td>$<?= esc(number_format($event['amount'], 2)) ?></td>
<td><?= esc(!empty($event['expiration_date']) ? local_date($event['expiration_date'], 'm-d-Y') : '') ?></td> <td><?= esc(!empty($event['expiration_date']) ? local_date($event['expiration_date'], 'm-d-Y') : '') ?></td>
<td><?= esc($event['semester']) ?></td> <td><?= esc($event['semester']) ?></td>
<td><?= esc($event['school_year']) ?></td> <td><?= esc($event['school_year']) ?></td>
+370 -203
View File
@@ -23,6 +23,41 @@
<div class="card-body"> <div class="card-body">
<?php <?php
$termExamLabel = (isset($semester) && strtolower((string) $semester) === 'spring') ? 'Final' : 'Midterm'; $termExamLabel = (isset($semester) && strtolower((string) $semester) === 'spring') ? 'Final' : 'Midterm';
$lowProgressSectionIds = $lowProgressSectionIds ?? [];
$flaggedClasses = count($lowProgressSectionIds);
$pageNotifications = [];
if ($missingItemsCount > 0) {
$pageNotifications[] = [
'level' => 'danger',
'message' => "{$missingItemsCount} missing item" . ($missingItemsCount === 1 ? '' : 's') . " awaiting teacher uploads.",
];
}
if ($completionPercent < 70) {
$pageNotifications[] = [
'level' => 'warning',
'message' => "Submission completion is below 70% — follow up with remaining teachers.",
];
}
if ($flaggedClasses > 0) {
$pageNotifications[] = [
'level' => 'warning',
'message' => "Progress is under 50% for {$flaggedClasses} class section" . ($flaggedClasses === 1 ? '' : 's') . ".",
];
}
if (empty($rows)) {
$pageNotifications[] = [
'level' => 'info',
'message' => 'No class-section assignments submitted yet; encourage teachers to upload drafts.',
];
}
if (empty($pageNotifications)) {
$pageNotifications[] = [
'level' => 'info',
'message' => 'All tracked classes are current. Use the controls below to send reminders.',
];
}
$examDraftDeadlineConfig = $examDraftDeadlineConfig ?? '';
$examDraftDeadlineFormatted = $examDraftDeadlineFormatted ?? '';
?> ?>
<?php if (session()->getFlashdata('success')): ?> <?php if (session()->getFlashdata('success')): ?>
<div class="alert alert-success"> <div class="alert alert-success">
@@ -37,218 +72,278 @@
<?= esc(session()->getFlashdata('info')) ?> <?= esc(session()->getFlashdata('info')) ?>
</div> </div>
<?php endif; ?> <?php endif; ?>
<?php $lowProgressSectionIds = $lowProgressSectionIds ?? []; ?> <?php
<?php if (!empty($lowProgressSectionIds)): ?> $groupedRows = [];
<div class="alert alert-warning"> foreach ($rows as $idx => $row) {
Showing teachers for class sections with progress submissions below 50%. $classKey = (string) ($row['class_section_id'] ?? $row['class_section'] ?? 'class_' . $idx);
</div> $groupedRows[$classKey][] = $row;
<?php endif; ?> }
<div class="border rounded-3 p-3 mb-4 bg-light"> ?>
<div class="d-flex flex-wrap gap-4 align-items-center"> <div class="row g-3 mb-4 align-items-stretch">
<div> <div class="col-lg-8">
<div class="text-uppercase small text-muted">Submission completion</div> <div class="row g-3 summary-row">
<div class="h4 fw-semibold mb-1"><?= esc($completionPercent) ?>%</div> <div class="col-12 col-sm-6 col-xl-3">
<div class="progress" style="height:6px;"> <div class="summary-card h-100 shadow-sm border-0">
<div <div class="summary-card-body">
class="progress-bar bg-primary" <div class="summary-label text-uppercase">Completion</div>
role="progressbar" <div class="summary-value"><?= esc($completionPercent) ?>%</div>
style="width: <?= esc($completionPercent) ?>%;" <div class="progress summary-progress">
aria-valuenow="<?= esc($completionPercent) ?>" <div
aria-valuemin="0" class="progress-bar"
aria-valuemax="100" role="progressbar"
></div> style="width: <?= esc($completionPercent) ?>%;"
aria-valuenow="<?= esc($completionPercent) ?>"
aria-valuemin="0"
aria-valuemax="100"
></div>
</div>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="summary-card h-100 shadow-sm border-0">
<div class="summary-card-body">
<div class="summary-label text-uppercase">Missing items</div>
<div class="summary-value <?= $missingItemsCount > 0 ? 'text-danger' : '' ?>"><?= esc($missingItemsCount) ?></div>
<div class="summary-note"><?= esc($submittedItems) ?> submitted / <?= esc($totalItems) ?> total</div>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="summary-card h-100 shadow-sm border-0">
<div class="summary-card-body">
<div class="summary-label text-uppercase">Submissions</div>
<div class="summary-value"><?= esc($submittedItems) ?></div>
<div class="summary-note"><?= esc($totalItems) ?> teachers tracked</div>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="summary-card h-100 shadow-sm border-0">
<div class="summary-card-body">
<div class="summary-label text-uppercase">Flagged</div>
<div class="summary-value"><?= esc($flaggedClasses) ?></div>
<div class="summary-note">Sections under 50% complete</div>
</div>
</div>
</div> </div>
</div> </div>
<div> </div>
<div class="text-uppercase small text-muted">Missing items</div> <div class="col-lg-4">
<div class="h4 fw-semibold text-danger mb-0"><?= esc($missingItemsCount) ?></div> <div class="card page-notifications-card h-100 shadow-sm">
</div> <div class="card-header d-flex justify-content-between align-items-center">
<div class="text-muted small"> <span>Page notifications</span>
<?= esc($submittedItems) ?> submitted / <?= esc($totalItems) ?> total items <span class="badge bg-light text-dark"><?= count($pageNotifications) ?> alerts</span>
</div>
<div class="card-body">
<ul class="page-notifications-list mb-0">
<?php foreach ($pageNotifications as $notification): ?>
<li class="page-notification-item page-notification-<?= esc($notification['level']) ?>">
<span class="notification-indicator" aria-hidden="true"></span>
<span><?= esc($notification['message']) ?></span>
</li>
<?php endforeach; ?>
</ul>
</div>
</div> </div>
</div> </div>
</div> </div>
<form method="post" action="<?= site_url('administrator/teacher-submissions/notify') ?>"> <form method="post" action="<?= site_url('administrator/teacher-submissions/notify') ?>">
<?= csrf_field() ?> <?= csrf_field() ?>
<div class="table-responsive"> <?php if (empty($rows)): ?>
<table <p class="text-center text-muted mt-4">No teacher-class assignments found for this term.</p>
class="table table-striped table-bordered m-0 align-middle teacher-submissions-table" <?php else: ?>
data-no-mgmt-sticky <div class="table-control-bar mb-3 d-flex flex-wrap align-items-center gap-3">
data-no-dt-fixedheader <div class="d-flex flex-wrap align-items-center gap-3">
> <label class="form-check form-check-inline mb-0">
<thead class="table-light"> <input class="form-check-input" type="checkbox" name="notify_midterm_score" value="1">
<tr> <span class="form-check-label small">Include <?= esc($termExamLabel) ?> score</span>
<th>Class-Section</th> </label>
<th>Teachers Name</th> <label class="form-check form-check-inline mb-0">
<th class="text-center"> <input class="form-check-input" type="checkbox" name="notify_midterm_comment" value="1">
<?= esc($termExamLabel) ?> Score <span class="form-check-label small">Include <?= esc($termExamLabel) ?> comment</span>
<div class="form-check d-inline-flex align-items-center gap-1 ms-2"> </label>
<input class="form-check-input" type="checkbox" name="notify_midterm_score" id="notifyMidtermScore" value="1"> <label class="form-check form-check-inline mb-0">
<label class="form-check-label small" for="notifyMidtermScore">Include</label> <input class="form-check-input" type="checkbox" name="notify_participation" value="1">
</div> <span class="form-check-label small">Include participation</span>
</th> </label>
<th class="text-center"> <label class="form-check form-check-inline mb-0">
<?= esc($termExamLabel) ?> Comment <input class="form-check-input" type="checkbox" name="notify_ptap_comment" value="1">
<div class="form-check d-inline-flex align-items-center gap-1 ms-2"> <span class="form-check-label small">Include PTAP comment</span>
<input class="form-check-input" type="checkbox" name="notify_midterm_comment" id="notifyMidtermComment" value="1"> </label>
<label class="form-check-label small" for="notifyMidtermComment">Include</label> <label class="form-check form-check-inline mb-0">
</div> <input class="form-check-input" type="checkbox" name="notify_class_progress" value="1">
</th> <span class="form-check-label small">Include class progress</span>
<th class="text-center"> </label>
Participation <label class="form-check form-check-inline mb-0">
<div class="form-check d-inline-flex align-items-center gap-1 ms-2"> <input class="form-check-input" type="checkbox" name="notify_exam_draft" value="1">
<input class="form-check-input" type="checkbox" name="notify_participation" id="notifyParticipation" value="1"> <span class="form-check-label small">Include exam draft</span>
<label class="form-check-label small" for="notifyParticipation">Include</label> </label>
</div> <label class="form-check form-check-inline mb-0">
</th> <input class="form-check-input" type="checkbox" name="homework_notify_all" value="1">
<th class="text-center"> <span class="form-check-label small">Include homework</span>
PTAP Comment </label>
<div class="form-check d-inline-flex align-items-center gap-1 ms-2"> </div>
<input class="form-check-input" type="checkbox" name="notify_ptap_comment" id="notifyPtapComment" value="1"> <div class="small text-muted">
<label class="form-check-label small" for="notifyPtapComment">Include</label> <span class="text-uppercase" style="font-size:0.65rem;">Exam draft deadline</span><br>
</div> <?php if ($examDraftDeadlineConfig !== ''): ?>
</th> <?= esc($examDraftDeadlineConfig) ?>
<th class="text-center"> <?php if ($examDraftDeadlineFormatted !== ''): ?>
Class Progress <span class="text-muted"> → <?= esc($examDraftDeadlineFormatted) ?></span>
<div class="form-check d-inline-flex align-items-center gap-1 ms-2"> <?php endif; ?>
<input class="form-check-input" type="checkbox" name="notify_class_progress" id="notifyClassProgress" value="1">
<label class="form-check-label small" for="notifyClassProgress">Include</label>
</div>
</th>
<th class="text-center">
Exam Draft
<div class="form-check d-inline-flex align-items-center gap-1 ms-2">
<input class="form-check-input" type="checkbox" name="notify_exam_draft" id="notifyExamDraft" value="1">
<label class="form-check-label small" for="notifyExamDraft">Include</label>
</div>
<?php
$examDraftDeadlineConfig = $examDraftDeadlineConfig ?? '';
$examDraftDeadlineFormatted = $examDraftDeadlineFormatted ?? '';
?>
<div class="small fw-normal text-muted mt-2 text-wrap">
<span class="text-uppercase" style="font-size:0.65rem;">exam_draft_deadline</span><br>
<?php if ($examDraftDeadlineConfig !== ''): ?>
<?= esc($examDraftDeadlineConfig) ?>
<?php if ($examDraftDeadlineFormatted !== ''): ?>
<span class="text-muted"> → <?= esc($examDraftDeadlineFormatted) ?></span>
<?php endif; ?>
<?php else: ?>
<span class="text-warning">Not set</span>
<?php endif; ?>
</div>
</th>
<th class="text-center">
Homework
<div class="form-check d-inline-flex align-items-center gap-1 ms-2">
<input class="form-check-input" type="checkbox" name="homework_notify_all" id="homeworkNotifyAll" value="1">
<label class="form-check-label small" for="homeworkNotifyAll">Include</label>
</div>
</th>
<th class="text-center">Notifications</th>
</tr>
</thead>
<tbody>
<?php if (!empty($rows)): ?>
<?php $homeworkToggleRendered = false; ?>
<?php foreach ($rows as $row): ?>
<tr>
<td><?= esc($row['class_section']) ?></td>
<td>
<?php if (!empty($row['teachers'])): ?>
<?php foreach ($row['teachers'] as $teacher): ?>
<div><?= esc($teacher['label'] ?? 'Teacher') ?></div>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted small">Unassigned</span>
<?php endif; ?>
</td>
<?php foreach ([
'midterm_score_status',
'midterm_comment_status',
'participation_status',
'ptap_comment_status',
'class_progress_status',
'exam_draft_status',
] as $statusKey): ?>
<?php $status = $row[$statusKey] ?? ['label' => 'N/A', 'badge' => 'bg-secondary']; ?>
<td class="text-center">
<span class="badge <?= esc($status['badge'] ?? 'bg-secondary') ?>">
<?= esc($status['label'] ?? 'N/A') ?>
</span>
<?php if (!empty($status['detail'])): ?>
<div class="small text-muted"><?= esc($status['detail']) ?></div>
<?php endif; ?>
</td>
<?php endforeach; ?>
<?php $homeworkStatus = $row['homework_status'] ?? ['label' => 'N/A', 'badge' => 'bg-secondary']; ?>
<td class="text-center">
<span class="badge <?= esc($homeworkStatus['badge'] ?? 'bg-secondary') ?>">
<?= esc($homeworkStatus['label'] ?? 'N/A') ?>
</span>
<?php if (!empty($homeworkStatus['detail'])): ?>
<div class="small text-muted"><?= esc($homeworkStatus['detail']) ?></div>
<?php endif; ?>
</td>
<td>
<?php if (!empty($row['teachers'])): ?>
<?php $missingPayload = base64_encode(json_encode($row['missing_items'] ?? [])); ?>
<?php foreach ($row['teachers'] as $teacher): ?>
<?php $history = $notificationHistory[$row['class_section_id']][$teacher['id']] ?? []; ?>
<?php $lastEntry = $history[0] ?? null; ?>
<div class="mb-2">
<label class="d-flex align-items-center gap-2 mb-1">
<input
type="checkbox"
class="form-check-input"
name="notify[<?= esc($row['class_section_id']) ?>][<?= esc($teacher['id']) ?>]"
value="1"
/>
<span class="fw-semibold"><?= esc($teacher['label'] ?? 'Teacher') ?></span>
</label>
<input
type="hidden"
name="missing_items[<?= esc($row['class_section_id']) ?>][<?= esc($teacher['id']) ?>]"
value="<?= esc($missingPayload) ?>"
/>
<div class="small text-muted">
<?php if ($lastEntry !== null): ?>
<span>
Last <?= esc($lastEntry['status'] === 'sent' ? 'sent' : 'attempted') ?> on <?= esc($lastEntry['sent_at_text'] ?: 'N/A') ?>
by <?= esc($lastEntry['admin_name'] ?? '') ?>
</span>
<?php if (count($history) > 1): ?>
<div>History: <?= count($history) ?> entries</div>
<?php endif; ?>
<?php else: ?>
<span>No notifications sent yet</span>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted small">No teacher assigned</span>
<?php endif; ?>
<?php if (!empty($row['missing_items'])): ?>
<div class="small text-danger mt-1">
Outstanding: <?= esc(implode(', ', $row['missing_items'])) ?>
</div>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
<?php else: ?> <?php else: ?>
<tr> <span class="text-warning">Not set</span>
<td colspan="7" class="text-center">No teacher-class assignments found for this term.</td>
</tr>
<?php endif; ?> <?php endif; ?>
</tbody> </div>
</table> </div>
</div> <div class="accordion" id="teacherSubmissionAccordion">
<div class="mt-3 text-end"> <?php foreach ($groupedRows as $sectionKey => $sectionRows): ?>
<button type="submit" class="btn btn-primary" <?= empty($rows) ? 'disabled' : '' ?>> <?php
Send notifications to selected teachers $firstRow = $sectionRows[0] ?? [];
</button> $sectionLabel = esc($firstRow['class_section'] ?? 'Class section');
</div> $collapseId = 'teacherSectionCollapse_' . md5($sectionKey);
$badgeStatus = count($sectionRows) === 1 ? 'submission' : 'submissions';
?>
<div class="accordion-item">
<h2 class="accordion-header" id="heading_<?= esc($collapseId) ?>">
<button
class="accordion-button collapsed d-flex justify-content-between align-items-center"
type="button"
data-bs-toggle="collapse"
data-bs-target="#<?= esc($collapseId) ?>"
aria-expanded="false"
aria-controls="<?= esc($collapseId) ?>"
>
<div>
<strong><?= $sectionLabel ?></strong>
<div class="small text-muted"><?= esc(count($sectionRows)) ?> <?= $badgeStatus ?></div>
</div>
<span class="badge bg-primary-subtle text-primary"><?= count($sectionRows) ?> rows</span>
</button>
</h2>
<div id="<?= esc($collapseId) ?>" class="accordion-collapse collapse" aria-labelledby="heading_<?= esc($collapseId) ?>">
<div class="accordion-body p-0">
<div class="table-responsive">
<table
class="table table-striped table-bordered m-0 align-middle teacher-submissions-table mb-0"
data-no-mgmt-sticky
data-no-dt-fixedheader
>
<thead class="table-light">
<tr>
<th>Class-Section</th>
<th>Teachers Name</th>
<th class="text-center"><?= esc($termExamLabel) ?> Score</th>
<th class="text-center"><?= esc($termExamLabel) ?> Comment</th>
<th class="text-center">Participation</th>
<th class="text-center">PTAP Comment</th>
<th class="text-center">Class Progress</th>
<th class="text-center">Exam Draft</th>
<th class="text-center">Homework</th>
<th class="text-center">Notifications</th>
</tr>
</thead>
<tbody>
<?php foreach ($sectionRows as $row): ?>
<tr>
<td><?= esc($row['class_section']) ?></td>
<td>
<?php if (!empty($row['teachers'])): ?>
<?php foreach ($row['teachers'] as $teacher): ?>
<div><?= esc($teacher['label'] ?? 'Teacher') ?></div>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted small">Unassigned</span>
<?php endif; ?>
</td>
<?php foreach ([
'midterm_score_status',
'midterm_comment_status',
'participation_status',
'ptap_comment_status',
'class_progress_status',
'exam_draft_status',
] as $statusKey): ?>
<?php $status = $row[$statusKey] ?? ['label' => 'N/A', 'badge' => 'bg-secondary']; ?>
<td class="text-center">
<span class="badge <?= esc($status['badge'] ?? 'bg-secondary') ?>">
<?= esc($status['label'] ?? 'N/A') ?>
</span>
<?php if (!empty($status['detail'])): ?>
<div class="small text-muted"><?= esc($status['detail']) ?></div>
<?php endif; ?>
</td>
<?php endforeach; ?>
<?php $homeworkStatus = $row['homework_status'] ?? ['label' => 'N/A', 'badge' => 'bg-secondary']; ?>
<td class="text-center">
<span class="badge <?= esc($homeworkStatus['badge'] ?? 'bg-secondary') ?>">
<?= esc($homeworkStatus['label'] ?? 'N/A') ?>
</span>
<?php if (!empty($homeworkStatus['detail'])): ?>
<div class="small text-muted"><?= esc($homeworkStatus['detail']) ?></div>
<?php endif; ?>
</td>
<td>
<?php if (!empty($row['teachers'])): ?>
<?php $missingPayload = base64_encode(json_encode($row['missing_items'] ?? [])); ?>
<?php foreach ($row['teachers'] as $teacher): ?>
<?php $history = $notificationHistory[$row['class_section_id']][$teacher['id']] ?? []; ?>
<?php $lastEntry = $history[0] ?? null; ?>
<div class="mb-2">
<label class="d-flex align-items-center gap-2 mb-1">
<input
type="checkbox"
class="form-check-input"
name="notify[<?= esc($row['class_section_id']) ?>][<?= esc($teacher['id']) ?>]"
value="1"
/>
<span class="fw-semibold"><?= esc($teacher['label'] ?? 'Teacher') ?></span>
</label>
<input
type="hidden"
name="missing_items[<?= esc($row['class_section_id']) ?>][<?= esc($teacher['id']) ?>]"
value="<?= esc($missingPayload) ?>"
/>
<div class="small text-muted">
<?php if ($lastEntry !== null): ?>
<span>
Last <?= esc($lastEntry['status'] === 'sent' ? 'sent' : 'attempted') ?> on <?= esc($lastEntry['sent_at_text'] ?: 'N/A') ?>
by <?= esc($lastEntry['admin_name'] ?? '') ?>
</span>
<?php if (count($history) > 1): ?>
<div>History: <?= count($history) ?> entries</div>
<?php endif; ?>
<?php else: ?>
<span>No notifications sent yet</span>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<span class="text-muted small">No teacher assigned</span>
<?php endif; ?>
<?php if (!empty($row['missing_items'])): ?>
<div class="small text-danger mt-1">
Outstanding: <?= esc(implode(', ', $row['missing_items'])) ?>
</div>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="mt-3 text-end">
<button type="submit" class="btn btn-primary">
Send notifications to selected teachers
</button>
</div>
<?php endif; ?>
</form> </form>
</div> </div>
</div> </div>
@@ -280,5 +375,77 @@
.card-body .table-responsive .teacher-submissions-table td { .card-body .table-responsive .teacher-submissions-table td {
white-space: normal; white-space: normal;
} }
.summary-card {
background: var(--bs-white);
border-radius: 0.75rem;
}
.summary-card-body {
padding: 1.25rem;
}
.summary-label {
font-size: 0.7rem;
letter-spacing: 0.08em;
color: #6c757d;
}
.summary-value {
font-size: 1.75rem;
font-weight: 600;
margin-top: 0.35rem;
}
.summary-note {
font-size: 0.85rem;
color: #6c757d;
}
.summary-progress {
height: 6px;
margin-top: 0.65rem;
}
.summary-progress .progress-bar {
background: var(--bs-primary);
}
.page-notifications-card {
border-radius: 0.75rem;
}
.page-notifications-list {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.page-notification-item {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.85rem;
}
.page-notification-info .notification-indicator {
background: #0dcaf0;
}
.page-notification-warning .notification-indicator {
background: #ffc107;
}
.page-notification-danger .notification-indicator {
background: #dc3545;
}
.notification-indicator {
width: 0.75rem;
height: 0.75rem;
border-radius: 50%;
display: inline-block;
}
.table-control-bar {
border: 1px solid rgba(0,0,0,0.08);
border-radius: 0.75rem;
padding: 0.75rem 1rem;
background: #f8f9fa;
}
.table-control-bar .form-check-label {
font-size: 0.8rem;
margin-left: 0.15rem;
text-transform: none;
}
</style> </style>
<?= $this->endSection() ?> <?= $this->endSection() ?>
+9 -8
View File
@@ -42,9 +42,6 @@
<?php endif; ?> <?php endif; ?>
</div> </div>
<!-- Event Description -->
<p class="card-text"><?= esc($event['description']) ?></p>
<!-- Participation Table --> <!-- Participation Table -->
<form method="post" action="<?= site_url('parent/updateParticipation') ?>"> <form method="post" action="<?= site_url('parent/updateParticipation') ?>">
<?= csrf_field() ?> <?= csrf_field() ?>
@@ -53,11 +50,13 @@
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-sm table-bordered"> <table class="table table-sm table-bordered">
<thead class="table-light"> <thead class="table-light">
<tr> <tr>
<th>Student First Name</th> <th>Student First Name</th>
<th>Student Last Name</th> <th>Student Last Name</th>
<th class="text-center">Participate</th> <th class="text-center">Participate</th>
</tr> <th>Description</th>
<th>Event Fees</th>
</tr>
</thead> </thead>
<tbody> <tbody>
<?php foreach ($yourStudents as $student): ?> <?php foreach ($yourStudents as $student): ?>
@@ -84,6 +83,8 @@
</div> </div>
</div> </div>
</td> </td>
<td><?= esc($event['description'] ?: 'No description') ?></td>
<td class="text-nowrap">$<?= esc(number_format((float) ($event['amount'] ?? 0), 2)) ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</tbody> </tbody>
+5
View File
@@ -54,6 +54,11 @@
<button class="btn btn-primary" onclick="window.print()">Print Report</button> <button class="btn btn-primary" onclick="window.print()">Print Report</button>
<a id="summaryReportLink" href="<?= base_url('financial-report/financialReportSummary') ?>" class="btn btn-info">Display Summary Report</a> <a id="summaryReportLink" href="<?= base_url('financial-report/financialReportSummary') ?>" class="btn btn-info">Display Summary Report</a>
</div> </div>
<?php if (isset($eventFeesTotal)): ?>
<div class="alert alert-info mb-3">
<strong>Event fees total:</strong> $<?= number_format((float)$eventFeesTotal, 2) ?>
</div>
<?php endif; ?>
<div class="table-responsive"> <div class="table-responsive">
<table id="invoicesTable" class="table table-bordered table-striped align-middle w-100"> <table id="invoicesTable" class="table table-bordered table-striped align-middle w-100">
<thead> <thead>
+10 -5
View File
@@ -32,6 +32,7 @@
</thead> </thead>
<tbody id="summaryBody"> <tbody id="summaryBody">
<tr><td>Total Charges</td><td class="text-right" id="sumCharges">$0.00</td></tr> <tr><td>Total Charges</td><td class="text-right" id="sumCharges">$0.00</td></tr>
<tr><td>Event Fees</td><td class="text-right" id="sumEventFees">$0.00</td></tr>
<tr><td>Total Extra Charges</td><td class="text-right" id="sumExtraCharges">$0.00</td></tr> <tr><td>Total Extra Charges</td><td class="text-right" id="sumExtraCharges">$0.00</td></tr>
<tr><td>Total Discounts</td><td class="text-right" id="sumDiscounts">$0.00</td></tr> <tr><td>Total Discounts</td><td class="text-right" id="sumDiscounts">$0.00</td></tr>
<tr><td>Total Refunds</td><td class="text-right" id="sumRefunds">$0.00</td></tr> <tr><td>Total Refunds</td><td class="text-right" id="sumRefunds">$0.00</td></tr>
@@ -98,6 +99,9 @@ function loadSummary(){
if (!d || d.ok !== true) return; if (!d || d.ok !== true) return;
document.getElementById('summaryPeriod').textContent = 'Report for School Year: ' + (d.schoolYear||''); document.getElementById('summaryPeriod').textContent = 'Report for School Year: ' + (d.schoolYear||'');
document.getElementById('sumCharges').textContent = fmt(d.totalCharges); document.getElementById('sumCharges').textContent = fmt(d.totalCharges);
if (document.getElementById('sumEventFees')) {
document.getElementById('sumEventFees').textContent = fmt(d.totalEventFees || 0);
}
if (document.getElementById('sumExtraCharges')) { if (document.getElementById('sumExtraCharges')) {
document.getElementById('sumExtraCharges').textContent = fmt(d.totalExtraCharges || 0); document.getElementById('sumExtraCharges').textContent = fmt(d.totalExtraCharges || 0);
} }
@@ -127,10 +131,10 @@ function renderCharts(d){
const summaryCtx = document.getElementById('summaryChart').getContext('2d'); const summaryCtx = document.getElementById('summaryChart').getContext('2d');
window._summaryChart = new Chart(summaryCtx, { window._summaryChart = new Chart(summaryCtx, {
type: 'bar', type: 'bar',
data: { labels: ['Charges','Paid','Unpaid','Discounts','Refunds','Expenses','Reimbursements','Net'], data: { labels: ['Charges','Event Fees','Paid','Unpaid','Discounts','Refunds','Expenses','Reimbursements','Net'],
datasets: [{ label:'Amount (USD)', data:[ datasets: [{ label:'Amount (USD)', data:[
d.totalCharges||0, d.totalPaid||0, d.totalUnpaid||0, d.totalDiscounts||0, d.totalRefunds||0, d.totalExpenses||0, d.totalReimbursements||0, d.netAmount||0 d.totalCharges||0, d.totalEventFees||0, d.totalPaid||0, d.totalUnpaid||0, d.totalDiscounts||0, d.totalRefunds||0, d.totalExpenses||0, d.totalReimbursements||0, d.netAmount||0
], backgroundColor: ['#007bff','#28a745','#ffc107','#17a2b8','#ffc107','#dc3545','#6f42c1','#20c997']}] }, ], backgroundColor: ['#007bff','#6610f2','#28a745','#ffc107','#17a2b8','#ffc107','#dc3545','#6f42c1','#20c997']}] },
options: { responsive:true, scales:{ y:{ beginAtZero:true }}} options: { responsive:true, scales:{ y:{ beginAtZero:true }}}
}); });
@@ -177,11 +181,12 @@ document.addEventListener("DOMContentLoaded", function() {
window._summaryChart = new Chart(summaryCtx, { window._summaryChart = new Chart(summaryCtx, {
type: 'bar', type: 'bar',
data: { data: {
labels: ['Charges', 'Paid', 'Unpaid', 'Discounts', 'Refunds', 'Expenses', 'Reimbursements', 'Net'], labels: ['Charges', 'Event Fees', 'Paid', 'Unpaid', 'Discounts', 'Refunds', 'Expenses', 'Reimbursements', 'Net'],
datasets: [{ datasets: [{
label: 'Amount (USD)', label: 'Amount (USD)',
data: [ data: [
<?= (float)$totalCharges ?>, <?= (float)$totalCharges ?>,
<?= (float)($totalEventFees ?? 0) ?>,
<?= (float)$totalPaid ?>, <?= (float)$totalPaid ?>,
<?= (float)$totalUnpaid ?>, <?= (float)$totalUnpaid ?>,
<?= (float)$totalDiscounts ?>, <?= (float)$totalDiscounts ?>,
@@ -191,7 +196,7 @@ document.addEventListener("DOMContentLoaded", function() {
<?= (float)$netAmount ?> <?= (float)$netAmount ?>
], ],
backgroundColor: [ backgroundColor: [
'#007bff', '#28a745', '#ffc107', '#17a2b8', '#ffc107', '#dc3545', '#6f42c1', '#20c997' '#007bff', '#6610f2', '#28a745', '#ffc107', '#17a2b8', '#ffc107', '#dc3545', '#6f42c1', '#20c997'
] ]
}] }]
}, },
+15 -10
View File
@@ -47,6 +47,7 @@
<button class="btn btn-primary btn-sm" type="submit">Send Reminders (All)</button> <button class="btn btn-primary btn-sm" type="submit">Send Reminders (All)</button>
</form> </form>
</div> </div>
<?php $sumEventFees = 0.0; ?>
<div class="table-responsive"> <div class="table-responsive">
<table id="unpaidTable" class="table table-sm align-middle no-mgmt-sticky" data-no-mgmt-sticky> <table id="unpaidTable" class="table table-sm align-middle no-mgmt-sticky" data-no-mgmt-sticky>
<thead> <thead>
@@ -54,6 +55,7 @@
<th>Parent</th> <th>Parent</th>
<th class="text-center">Nbr of Installements</th> <th class="text-center">Nbr of Installements</th>
<th>Type</th> <th>Type</th>
<th class="text-end">Event Fees</th>
<th class="text-end">Invoice Amount</th> <th class="text-end">Invoice Amount</th>
<th class="text-end">Applied Discount</th> <th class="text-end">Applied Discount</th>
<th class="text-end">Paid Amount</th> <th class="text-end">Paid Amount</th>
@@ -67,7 +69,7 @@
</thead> </thead>
<tbody> <tbody>
<?php if (empty($rows)): ?> <?php if (empty($rows)): ?>
<tr><td colspan="12" class="text-center text-muted py-4">No parents with outstanding balance.</td></tr> <tr><td colspan="13" class="text-center text-muted py-4">No parents with outstanding balance.</td></tr>
<?php else: ?> <?php else: ?>
<?php <?php
$sumInvoice = 0.0; $sumInvoice = 0.0;
@@ -86,18 +88,20 @@
</td> </td>
<td class="text-center"><?= (int)($r['payment_count'] ?? 0) ?></td> <td class="text-center"><?= (int)($r['payment_count'] ?? 0) ?></td>
<td> <td>
<?php if (($r['type'] ?? '') === 'no_payment'): ?> <?php if (($r['type'] ?? '') === 'no_payment'): ?>
<span class="badge bg-danger badge-type">no payment</span> <span class="badge bg-danger badge-type">no payment</span>
<?php else: ?> <?php else: ?>
<span class="badge bg-success badge-type">installment</span> <span class="badge bg-success badge-type">installment</span>
<?php endif; ?> <?php endif; ?>
</td> </td>
<?php $sumInvoice += (float)($r['total_invoice'] ?? 0); ?> <?php $sumInvoice += (float)($r['total_invoice'] ?? 0); ?>
<?php $sumPaid += (float)($r['total_paid'] ?? 0); ?> <?php $sumEventFees += (float)($r['event_fees'] ?? 0); ?>
<?php $sumPaid += (float)($r['total_paid'] ?? 0); ?>
<?php $sumDisc += (float)($r['total_discount'] ?? 0); ?> <?php $sumDisc += (float)($r['total_discount'] ?? 0); ?>
<?php $sumInstAmt += (float)($r['installment_amount'] ?? 0); ?> <?php $sumInstAmt += (float)($r['installment_amount'] ?? 0); ?>
<?php $sumBal += (float)($r['total_balance'] ?? 0); ?> <?php $sumBal += (float)($r['total_balance'] ?? 0); ?>
<td class="text-end">$<?= number_format((float)($r['total_invoice'] ?? 0), 2) ?></td> <td class="text-end">$<?= number_format((float)($r['event_fees'] ?? 0), 2) ?></td>
<td class="text-end">$<?= number_format((float)($r['total_invoice'] ?? 0), 2) ?></td>
<td class="text-end text-success">-$<?= number_format((float)($r['total_discount'] ?? 0), 2) ?></td> <td class="text-end text-success">-$<?= number_format((float)($r['total_discount'] ?? 0), 2) ?></td>
<td class="text-end">$<?= number_format((float)($r['total_paid'] ?? 0), 2) ?></td> <td class="text-end">$<?= number_format((float)($r['total_paid'] ?? 0), 2) ?></td>
<td class="text-center"><?= (int)($r['remaining_installments'] ?? 0) ?></td> <td class="text-center"><?= (int)($r['remaining_installments'] ?? 0) ?></td>
@@ -129,6 +133,7 @@
<tfoot> <tfoot>
<tr> <tr>
<th colspan="3" class="text-end">Totals:</th> <th colspan="3" class="text-end">Totals:</th>
<th class="text-end">$<?= number_format($sumEventFees, 2) ?></th>
<th class="text-end">$<?= number_format($sumInvoice, 2) ?></th> <th class="text-end">$<?= number_format($sumInvoice, 2) ?></th>
<th class="text-end text-success">-$<?= number_format($sumDisc, 2) ?></th> <th class="text-end text-success">-$<?= number_format($sumDisc, 2) ?></th>
<th class="text-end">$<?= number_format($sumPaid, 2) ?></th> <th class="text-end">$<?= number_format($sumPaid, 2) ?></th>
Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB