diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 2120aaa..c359189 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -537,6 +537,7 @@ $routes->post('payment/event_charges', 'View\EventController::eventUpdate'); $routes->get('administrator/event-charges', 'View\EventController::eventShow'); $routes->post('administrator/event-charges/remove/(:num)', 'View\EventController::removeCharge/$1'); $routes->post('administrator/event-charges/payment/(:num)', 'View\EventController::toggleEventPayment/$1'); +$routes->post('administrator/event-charges/waiver/(:num)', 'View\EventController::toggleWaiverStatus/$1'); $routes->get('administrator/get-students-with-charges', 'View\EventController::getStudentsWithCharges'); $routes->get('parent/events', 'View\ParentController::parentEventPage', ['filter' => 'auth:parent']); diff --git a/app/Controllers/View/EventController.php b/app/Controllers/View/EventController.php index 9bb09a1..5e3caf1 100644 --- a/app/Controllers/View/EventController.php +++ b/app/Controllers/View/EventController.php @@ -41,6 +41,7 @@ class EventController extends ResourceController protected $categories; protected $enrollmentModel; private ?bool $eventChargesHasCreatedBy = null; + private ?bool $eventChargesHasWaiverSigned = null; public function __construct() { @@ -85,6 +86,41 @@ class EventController extends ResourceController return $this->eventChargesHasCreatedBy; } + private function eventChargesSupportsWaiverSigned(): bool + { + if ($this->eventChargesHasWaiverSigned !== null) { + return $this->eventChargesHasWaiverSigned; + } + + try { + $db = Database::connect(); + $this->eventChargesHasWaiverSigned = $db->fieldExists('waiver_signed', 'event_charges'); + } catch (\Throwable $e) { + $this->eventChargesHasWaiverSigned = false; + } + + return $this->eventChargesHasWaiverSigned; + } + + private function getEventChargesReturnTo(): string + { + $fallback = site_url('administrator/event-charges'); + $returnTo = trim((string) ($this->request->getPost('return_to') ?? '')); + if ($returnTo === '') { + return $fallback; + } + + $base = rtrim((string) base_url(), '/'); + if (str_starts_with($returnTo, '/')) { + return $returnTo; + } + if ($base !== '' && str_starts_with($returnTo, $base)) { + return $returnTo; + } + + return $fallback; + } + public function index() { $eventModel = new EventModel(); @@ -570,6 +606,7 @@ class EventController extends ResourceController $parentsForInvoice = []; $supportsCreatedBy = $this->eventChargesSupportsCreatedBy(); + $supportsWaiverSigned = $this->eventChargesSupportsWaiverSigned(); foreach ($participations as $studentId => $value) { $existing = $this->eventChargesModel->where([ @@ -596,6 +633,9 @@ class EventController extends ResourceController 'updated_by' => $userId, 'class_section_id'=> $classSectionId, ]; + if ($supportsWaiverSigned) { + $updateData['waiver_signed'] = (int) ($existing['waiver_signed'] ?? 0); + } if (isset($event['amount']) && ((float)$event['amount'] !== (float)($existing['charged'] ?? 0))) { $updateData['charged'] = $event['amount']; } @@ -614,6 +654,9 @@ class EventController extends ResourceController 'semester' => $semester, 'updated_by' => $userId ]; + if ($supportsWaiverSigned) { + $insertData['waiver_signed'] = 0; + } if ($supportsCreatedBy) { $insertData['created_by'] = $userId; } @@ -630,6 +673,7 @@ class EventController extends ResourceController $parentPhone = trim($pieces['parent_phone'] ?? ''); $parentEmail = trim((string)($pieces['parent_email'] ?? '')); $markPaid = (string)($pieces['paid'] ?? '0') === '1'; + $waiverSigned = (string)($pieces['waiver_signed'] ?? '0') === '1'; if (!$firstname && !$lastname) { continue; @@ -664,7 +708,7 @@ class EventController extends ResourceController $existingExternal = $this->eventChargesModel->where($matchConditions)->first(); if ($existingExternal) { - $this->eventChargesModel->update($existingExternal['id'], [ + $updateData = [ 'participation' => 'yes', 'charged' => $event['amount'], 'updated_by' => $userId, @@ -674,7 +718,11 @@ class EventController extends ResourceController '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), - ]); + ]; + if ($supportsWaiverSigned) { + $updateData['waiver_signed'] = $waiverSigned ? 1 : 0; + } + $this->eventChargesModel->update($existingExternal['id'], $updateData); continue; } @@ -696,6 +744,9 @@ class EventController extends ResourceController 'semester' => $semester, 'updated_by' => $userId, ]; + if ($supportsWaiverSigned) { + $insertData['waiver_signed'] = $waiverSigned ? 1 : 0; + } if ($supportsCreatedBy) { $insertData['created_by'] = $userId; } @@ -725,13 +776,14 @@ class EventController extends ResourceController public function removeCharge($chargeId = null) { + $returnTo = $this->getEventChargesReturnTo(); if (!$chargeId) { - return redirect()->back()->with('error', 'Invalid charge.'); + return redirect()->to($returnTo)->with('error', 'Invalid charge.'); } $charge = $this->eventChargesModel->find($chargeId); if (!$charge) { - return redirect()->back()->with('error', 'Charge not found.'); + return redirect()->to($returnTo)->with('error', 'Charge not found.'); } $paymentId = (int)($charge['event_payment_id'] ?? 0); @@ -744,19 +796,20 @@ class EventController extends ResourceController $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.'); + return redirect()->to($returnTo)->with('success', 'Participation removed, invoices updated.'); } public function toggleEventPayment($chargeId = null) { + $returnTo = $this->getEventChargesReturnTo(); if (!$chargeId) { - return redirect()->back()->with('error', 'Invalid charge.'); + return redirect()->to($returnTo)->with('error', 'Invalid charge.'); } $isPaid = $this->request->getPost('paid') === '1'; $meta = $this->applyEventPaymentStatus((int)$chargeId, $isPaid); if (!$meta) { - return redirect()->back()->with('error', 'Charge not found.'); + return redirect()->to($returnTo)->with('error', 'Charge not found.'); } if (!empty($meta['invoice_id'])) { @@ -764,7 +817,33 @@ class EventController extends ResourceController $this->fixInvoiceStatusAfterCharge((int)$meta['parent_id'], (string)$meta['school_year']); } - return redirect()->back()->with('success', 'Event payment status updated.'); + return redirect()->to($returnTo)->with('success', 'Event payment status updated.'); + } + + public function toggleWaiverStatus($chargeId = null) + { + $returnTo = $this->getEventChargesReturnTo(); + if (!$chargeId) { + return redirect()->to($returnTo)->with('error', 'Invalid charge.'); + } + + if (!$this->eventChargesSupportsWaiverSigned()) { + return redirect()->to($returnTo)->with('error', 'Waiver tracking is not available until the database migration is applied.'); + } + + $charge = $this->eventChargesModel->find($chargeId); + if (!$charge) { + return redirect()->to($returnTo)->with('error', 'Charge not found.'); + } + + $signed = $this->request->getPost('waiver_signed') === '1'; + + $this->eventChargesModel->update((int) $chargeId, [ + 'waiver_signed' => $signed ? 1 : 0, + 'updated_by' => session()->get('user_id'), + ]); + + return redirect()->to($returnTo)->with('success', $signed ? 'Waiver marked as signed.' : 'Waiver marked as unsigned.'); } private function parentHasEnrollment(int $parentId, string $schoolYear): bool diff --git a/app/Database/Migrations/2026-04-19-000001_AddWaiverSignedToEventCharges.php b/app/Database/Migrations/2026-04-19-000001_AddWaiverSignedToEventCharges.php new file mode 100644 index 0000000..26e5ac4 --- /dev/null +++ b/app/Database/Migrations/2026-04-19-000001_AddWaiverSignedToEventCharges.php @@ -0,0 +1,31 @@ + [ + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 0, + 'after' => 'charged', + ], + ]; + + if (! $this->db->fieldExists('waiver_signed', 'event_charges')) { + $this->forge->addColumn('event_charges', $fields); + } + } + + public function down() + { + if ($this->db->fieldExists('waiver_signed', 'event_charges')) { + $this->forge->dropColumn('event_charges', 'waiver_signed'); + } + } +} diff --git a/app/Models/EventChargesModel.php b/app/Models/EventChargesModel.php index 426d641..e0a61fc 100644 --- a/app/Models/EventChargesModel.php +++ b/app/Models/EventChargesModel.php @@ -15,6 +15,7 @@ class EventChargesModel extends Model 'student_id', 'participation', 'charged', + 'waiver_signed', 'event_paid', 'event_payment_id', 'class_section_id', diff --git a/app/Views/administrator/events/event_charges.php b/app/Views/administrator/events/event_charges.php index a9f9c17..e1a762b 100644 --- a/app/Views/administrator/events/event_charges.php +++ b/app/Views/administrator/events/event_charges.php @@ -183,6 +183,7 @@