Files
alrahma_sunday_school/app/Views/parent/invoice_payment.php
T
2026-04-13 01:38:40 -04:00

223 lines
9.7 KiB
PHP

<?= $this->extend('layout/main_layout') ?>
<?= $this->section('content') ?>
<?php
// ---- Local helper: parse DB date/datetime safely and convert to display TZ ----
if (!function_exists('parseDbDateTime')) {
/**
* @param mixed $raw String "Y-m-d H:i:s" or "Y-m-d", DateTimeInterface, or null
* @param string $sourceTz Timezone of stored value (DB). Default: UTC
* @param string|null $displayTz Target timezone (defaults to user_timezone() or configured school timezone)
* @param string|null $defaultTime If $raw is date-only, set this default time ("HH:MM:SS") or null to keep 00:00:00
*/
function parseDbDateTime($raw, string $sourceTz = 'UTC', ?string $displayTz = null, ?string $defaultTime = null): ?DateTime
{
if (!$raw) return null;
// Resolve display timezone dynamically if not provided
if ($displayTz === null || $displayTz === '') {
try {
$displayTz = (string) (config('School')->attendance['timezone'] ?? user_timezone());
} catch (Throwable $e) {
$displayTz = user_timezone();
}
}
if ($raw instanceof DateTimeInterface) {
$dt = new DateTime('@' . $raw->getTimestamp());
return $dt->setTimezone(new DateTimeZone($displayTz));
}
$s = trim((string)$raw);
if ($s === '' || preg_match('/^0{4}-0{2}-0{2}/', $s)) return null;
$srcTz = new DateTimeZone($sourceTz);
$outTz = new DateTimeZone($displayTz);
// Try full datetime first
$dt = DateTime::createFromFormat('Y-m-d H:i:s', $s, $srcTz);
if ($dt !== false) {
return $dt->setTimezone($outTz);
}
// Try date-only
$d = DateTime::createFromFormat('Y-m-d', $s, $srcTz);
if ($d !== false) {
if ($defaultTime) {
[$H, $i, $sec] = array_map('intval', explode(':', $defaultTime));
$d->setTime($H, $i, $sec);
} // else leave 00:00:00
return $d->setTimezone($outTz);
}
// Fallback parser
try {
$fallback = new DateTime($s, $srcTz);
return $fallback->setTimezone($outTz);
} catch (Throwable $e) {
return null;
}
}
}
?>
<div class="container my-5">
<h3 class="text-center text-success" style="font-family: Arial, sans-serif;">Invoices and Payments</h3>
</div>
<!-- School Year Filter -->
<form action="<?= base_url('/parent/invoice_payment') ?>" method="get" class="form-inline mb-3">
<div class="d-flex align-items-center justify-content-center">
<select name="school_year" id="school_year" class="form-control me-3">
<?php foreach ($schoolYears as $year): ?>
<option value="<?= esc($year['school_year']) ?>"
<?= ($selectedYear === $year['school_year']) ? 'selected' : '' ?>
<?= ($currentSchoolYear === $year['school_year']) ? 'data-current="true"' : '' ?>>
<?= esc($year['school_year']) ?><?= ($currentSchoolYear === $year['school_year']) ? ' (Current)' : '' ?>
</option>
<?php endforeach; ?>
</select>
<button type="submit" class="btn btn-success">Filter</button>
</div>
</form>
<!-- Display Payment Notice / Deadline -->
<?php
$displayTz = user_timezone();
$deadline = parseDbDateTime($dueDate, 'UTC', $displayTz); // format either DATE or DATETIME safely
?>
<div class="alert alert-info mb-3 d-inline-block" style="display: inline-block; width: auto; padding: 10px;">
<ul class="mb-0">
<li>
This website release version does not have an option to pay your invoice online.
All payments this school year will be made in person on first day of school
(<strong><?= esc($deadline ? $deadline->format('m-d-Y') : 'TBD') ?></strong>).
</li>
<li>
Cash, checks and debit/credit cards are all accepted forms of payment. However, if you elect to pay in
installments, only cash and checks will be accepted.
</li>
</ul>
</div>
<!-- Invoice Table -->
<?php if (!empty($invoices)): ?>
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>#</th>
<th>Invoice Number</th>
<th>Issue Date</th>
<th>Due Date</th>
<th>Balance</th>
<th>Last Payment Amount</th>
<th>Last Payment Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($invoices as $index => $invoice): ?>
<?php
$issueDt = parseDbDateTime($invoice['issue_date'] ?? null, 'UTC', $displayTz); // assume stored UTC
$dueDt = parseDbDateTime($invoice['due_date'] ?? null, 'UTC', $displayTz, '12:00:00'); // if date-only, set noon
$lastPay = parseDbDateTime($invoice['last_payment_date'] ?? null, 'UTC', $displayTz);
?>
<tr>
<td><?= (int)$index + 1 ?></td>
<td><?= esc($invoice['invoice_number']) ?></td>
<td><?= $issueDt ? esc($issueDt->format('m-d-Y h:i A')) : '—' ?></td>
<td><?= $dueDt ? esc($dueDt->format('m-d-Y')) : '—' ?></td>
<td>$<?= number_format((float)($invoice['balance'] ?? 0), 2) ?></td>
<td>$<?= number_format((float)($invoice['last_paid_amount'] ?? 0), 2) ?></td>
<td><?= $lastPay ? esc($lastPay->format('m-d-Y h:i A')) : '—' ?></td>
<td><?= esc($invoice['status'] ?? '') ?></td>
<td>
<a href="<?= base_url('invoice/pdf/' . (int)($invoice['id'] ?? 0)) ?>" target="_blank"
class="btn btn-info btn-sm external-link">View/Print PDF</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php if (!empty($invoiceEventCharges)): ?>
<?php foreach ($invoices as $invoice): ?>
<?php $charges = $invoiceEventCharges[(int)($invoice['id'] ?? 0)] ?? []; ?>
<?php if (empty($charges)): ?>
<?php continue; ?>
<?php endif; ?>
<div class="card mb-3 shadow-sm">
<div class="card-header">
<strong>Event charges for Invoice #<?= esc($invoice['invoice_number'] ?? '#'.$invoice['id']) ?></strong>
</div>
<div class="card-body p-0">
<div class="table-responsive mb-0">
<table class="table table-sm table-bordered mb-0">
<thead class="table-light">
<tr>
<th>Event</th>
<th>Student</th>
<th>Fee</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<?php foreach ($charges as $charge): ?>
<?php
$studentName = trim(($charge['student_firstname'] ?? '') . ' ' . ($charge['student_lastname'] ?? ''));
$eventName = $charge['event_name'] ?? '—';
$paid = !empty($charge['event_paid']) || ((float)($charge['charged'] ?? 0) <= 0);
$badgeClass = $paid ? 'success' : 'danger';
?>
<tr>
<td><?= esc($eventName) ?></td>
<td><?= esc($studentName ?: '—') ?></td>
<td>$<?= number_format((float)($charge['event_amount'] ?? 0), 2) ?></td>
<td>
<span class="badge bg-<?= $badgeClass ?>">
<?= $paid ? 'Paid' : 'Unpaid' ?>
</span>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
<?php else: ?>
<div class="alert alert-info mb-3 d-inline-block">
No invoice found for the selected school year.
</div>
<?php endif; ?>
<?php $invoiceEventCharges = $invoiceEventCharges ?? []; ?>
<?= $this->endSection() ?>
<?= $this->section('scripts') ?>
<script>
document.addEventListener('DOMContentLoaded', function() {
const dropdown = document.getElementById('school_year');
const options = dropdown.options;
for (let i = 0; i < options.length; i++) {
if (options[i].dataset.current === "true") {
options[i].style.fontWeight = 'bold';
if (!dropdown.value) dropdown.selectedIndex = i;
break;
}
}
});
function showPaymentDevelopmentMessage(event) {
event.preventDefault();
alert('The payment method is currently under development. Please contact the school administration at alrahma.isgl@gmail.com');
}
</script>
<?= $this->endSection() ?>