Fix semester context, attendance rosters, and billing workflows
- load global semester helpers consistently and use date-based semester defaults - fix grading and daily attendance duplicate student/section rows - keep attendance violations scoped to the current semester by default - update invoice, refund, discount, payment, and financial aid flows - add configuration cleanup migrations for duplicate calendar/semester keys - refresh parent registration/report-card and print request handling - update related models, services, views, cron notes, and test coverage
This commit is contained in:
@@ -73,6 +73,21 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.enrollment-withdraw-control {
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
gap: .5rem;
|
||||
justify-content: flex-end;
|
||||
min-width: max-content;
|
||||
padding-left: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.enrollment-withdraw-control .form-check-input {
|
||||
flex: 0 0 auto;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.enrollment-modal-footer {
|
||||
gap: .5rem;
|
||||
}
|
||||
@@ -150,6 +165,18 @@
|
||||
.enrollment-status-table td > * {
|
||||
max-width: 58%;
|
||||
}
|
||||
|
||||
.enrollment-status-table td[data-label="Withdraw"] {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.enrollment-status-table td[data-label="Withdraw"] > * {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.enrollment-status-table td[data-label="Withdraw"] .enrollment-withdraw-control {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<?= $this->endSection() ?>
|
||||
@@ -217,24 +244,6 @@ foreach (($students ?? []) as $student) {
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<?php if ($familyFinancialSummary !== []): ?>
|
||||
<div class="border rounded p-3 mb-3 bg-light">
|
||||
<div class="fw-semibold mb-2">Family Account Information</div>
|
||||
<div class="row g-2">
|
||||
<div class="col-md-4"><span class="text-muted">Previous-year carry-over balance:</span> <strong data-financial-value="carry_over_balance"><?= esc($money($familyFinancialSummary['carry_over_balance'] ?? 0)) ?></strong></div>
|
||||
<div class="col-md-4"><span class="text-muted">Registration fee:</span> <strong data-financial-value="registration_fee"><?= esc($money($familyFinancialSummary['registration_fee'] ?? 0)) ?></strong></div>
|
||||
<div class="col-md-4"><span class="text-muted">Tuition due now:</span> <strong data-financial-value="tuition_due_at_registration"><?= esc($money($familyFinancialSummary['tuition_due_at_registration'] ?? 0)) ?></strong></div>
|
||||
<div class="col-md-4"><span class="text-muted">Mandatory fees:</span> <strong data-financial-value="mandatory_fees"><?= esc($money($familyFinancialSummary['mandatory_fees'] ?? 0)) ?></strong></div>
|
||||
<div class="col-md-4"><span class="text-muted">Current-year account balance:</span> <strong data-financial-value="current_balance"><?= esc($money($familyFinancialSummary['current_balance'] ?? 0)) ?></strong></div>
|
||||
<div class="col-md-4"><span class="text-muted">Total currently due:</span> <strong data-financial-value="amount_due"><?= esc($money($familyFinancialSummary['amount_due'] ?? 0)) ?></strong></div>
|
||||
</div>
|
||||
<?php if (!empty($familyFinancialSummary['policy_message'])): ?>
|
||||
<div class="small text-muted mt-2"><?= esc($familyFinancialSummary['policy_message']) ?></div>
|
||||
<?php endif; ?>
|
||||
<div class="small mt-2"><a href="<?= site_url('parent/financial-aid') ?>">Request financial aid</a></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($students)): ?>
|
||||
<form action="<?= base_url('/parent/enroll_classes_handler') ?>" method="post" id="enrollmentFlowForm">
|
||||
<?= csrf_field() ?>
|
||||
@@ -297,7 +306,7 @@ foreach (($students ?? []) as $student) {
|
||||
<td data-label="Status"><?= $statusBadge($student['enrollment_status'] ?? '') ?></td>
|
||||
<td data-label="Withdraw">
|
||||
<?php if (($student['enrollment_status'] ?? '') === 'enrolled'): ?>
|
||||
<div class="form-check form-switch m-0">
|
||||
<div class="form-check form-switch m-0 enrollment-withdraw-control">
|
||||
<input class="form-check-input" type="checkbox" name="withdraw[]" value="<?= esc($student['id']) ?>" id="withdraw-<?= esc($student['id']) ?>" <?= !$isEditable ? 'disabled' : '' ?>>
|
||||
<label class="form-check-label small" for="withdraw-<?= esc($student['id']) ?>">Request</label>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,68 @@ $disableEmergencyBtn = count($emergencies) >= $maxEmergency;
|
||||
?>
|
||||
|
||||
<?= $this->extend('layout/main_layout') ?>
|
||||
<?= $this->section('styles') ?>
|
||||
<style>
|
||||
@media (max-width: 575.98px) {
|
||||
.parent-register-stack-table {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.parent-register-stack-table thead {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.parent-register-stack-table tbody,
|
||||
.parent-register-stack-table tr,
|
||||
.parent-register-stack-table td {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.parent-register-stack-table tr {
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 8px;
|
||||
margin-bottom: .85rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.parent-register-stack-table td {
|
||||
align-items: flex-start;
|
||||
border-bottom: 1px solid #eef1f3;
|
||||
display: flex;
|
||||
gap: .75rem;
|
||||
justify-content: space-between;
|
||||
padding: .75rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.parent-register-stack-table td:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.parent-register-stack-table td::before {
|
||||
color: #6c757d;
|
||||
content: attr(data-label);
|
||||
flex: 0 0 42%;
|
||||
font-size: .8rem;
|
||||
font-weight: 700;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.parent-register-stack-table td > * {
|
||||
max-width: 58%;
|
||||
}
|
||||
|
||||
.parent-register-stack-table td[data-label="Action"] {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.parent-register-stack-table td[data-label="Action"] .btn {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<?= $this->endSection() ?>
|
||||
<?= $this->section('content') ?>
|
||||
<div class="container my-5">
|
||||
<h3 class="text-center text-success mb-3" style="font-family: Arial, sans-serif;">Student Registration</h3>
|
||||
@@ -67,7 +129,7 @@ $disableEmergencyBtn = count($emergencies) >= $maxEmergency;
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($existingKids)): ?>
|
||||
<h5>Student Information</h5>
|
||||
<table class="table table-bordered">
|
||||
<table class="table table-bordered parent-register-stack-table">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>School ID</th>
|
||||
@@ -83,12 +145,12 @@ $disableEmergencyBtn = count($emergencies) >= $maxEmergency;
|
||||
<tbody>
|
||||
<?php foreach ($existingKids as $kid): ?>
|
||||
<tr>
|
||||
<td><?= esc($kid['school_id']) ?></td>
|
||||
<td><?= esc($kid['firstname']) ?></td>
|
||||
<td><?= esc($kid['lastname']) ?></td>
|
||||
<td><?= esc((new DateTime($kid['dob']))->format('m-d-Y')) ?></td>
|
||||
<td><?= esc($kid['registration_grade']) ?></td>
|
||||
<td>
|
||||
<td data-label="School ID"><?= esc($kid['school_id']) ?></td>
|
||||
<td data-label="First Name"><?= esc($kid['firstname']) ?></td>
|
||||
<td data-label="Last Name"><?= esc($kid['lastname']) ?></td>
|
||||
<td data-label="DOB"><?= esc((new DateTime($kid['dob']))->format('m-d-Y')) ?></td>
|
||||
<td data-label="Grade"><?= esc($kid['registration_grade']) ?></td>
|
||||
<td data-label="Medical Conditions">
|
||||
<?php
|
||||
$mc = is_array($kid['medical_conditions'] ?? null)
|
||||
? $kid['medical_conditions']
|
||||
@@ -99,7 +161,7 @@ $disableEmergencyBtn = count($emergencies) >= $maxEmergency;
|
||||
echo implode('<br>', array_map('esc', $mc));
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<td data-label="Allergies">
|
||||
<?php
|
||||
$al = is_array($kid['allergies'] ?? null)
|
||||
? $kid['allergies']
|
||||
@@ -109,7 +171,7 @@ $disableEmergencyBtn = count($emergencies) >= $maxEmergency;
|
||||
echo implode('<br>', array_map('esc', $al));
|
||||
?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<td class="text-center" data-label="Action">
|
||||
<?php if ($isEditable && !empty($kid['can_delete'])): ?>
|
||||
<form action="<?= base_url('/parent/delete_student/' . $kid['id']) ?>"
|
||||
method="post"
|
||||
@@ -141,7 +203,7 @@ $disableEmergencyBtn = count($emergencies) >= $maxEmergency;
|
||||
|
||||
<?php if (!empty($emergencies)): ?>
|
||||
<h5 class="mt-4">Emergency Contacts</h5>
|
||||
<table class="table table-bordered">
|
||||
<table class="table table-bordered parent-register-stack-table">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>First Name</th>
|
||||
@@ -159,10 +221,10 @@ $disableEmergencyBtn = count($emergencies) >= $maxEmergency;
|
||||
$lastName = $nameParts[1] ?? '';
|
||||
?>
|
||||
<tr>
|
||||
<td><?= esc($firstName) ?></td>
|
||||
<td><?= esc($lastName) ?></td>
|
||||
<td><?= esc($contact['cellphone']) ?></td>
|
||||
<td><?= esc($contact['relation']) ?></td>
|
||||
<td data-label="First Name"><?= esc($firstName) ?></td>
|
||||
<td data-label="Last Name"><?= esc($lastName) ?></td>
|
||||
<td data-label="Phone"><?= esc($contact['cellphone']) ?></td>
|
||||
<td data-label="Relation"><?= esc($contact['relation']) ?></td>
|
||||
</tr>
|
||||
<?php include(APPPATH . 'Views/parent/edit_emergency_contact.php'); ?>
|
||||
<?php endforeach; ?>
|
||||
|
||||
@@ -1,4 +1,81 @@
|
||||
<?= $this->extend('layout/main_layout') ?>
|
||||
<?= $this->section('styles') ?>
|
||||
<style>
|
||||
@media (max-width: 575.98px) {
|
||||
.parent-report-cards-table {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.parent-report-cards-table thead {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.parent-report-cards-table tbody,
|
||||
.parent-report-cards-table tr,
|
||||
.parent-report-cards-table td {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.parent-report-cards-table tr {
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 8px;
|
||||
margin-bottom: .85rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.parent-report-cards-table td {
|
||||
align-items: flex-start;
|
||||
border-bottom: 1px solid #eef1f3;
|
||||
display: flex;
|
||||
gap: .75rem;
|
||||
justify-content: space-between;
|
||||
padding: .75rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.parent-report-cards-table td:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.parent-report-cards-table td::before {
|
||||
color: #6c757d;
|
||||
content: attr(data-label);
|
||||
flex: 0 0 38%;
|
||||
font-size: .8rem;
|
||||
font-weight: 700;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.parent-report-cards-table td > * {
|
||||
max-width: 62%;
|
||||
}
|
||||
|
||||
.parent-report-cards-table td[data-label="Action"] {
|
||||
display: block;
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
.parent-report-cards-table td[data-label="Action"]::before {
|
||||
display: block;
|
||||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
.parent-report-cards-table td[data-label="Action"] > * {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.parent-report-cards-table td[data-label="Action"] form {
|
||||
align-items: stretch !important;
|
||||
display: flex !important;
|
||||
flex-direction: column;
|
||||
margin-left: 0 !important;
|
||||
margin-top: .5rem;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<?= $this->endSection() ?>
|
||||
<?= $this->section('content') ?>
|
||||
<?php
|
||||
$isEditable = (bool) ($isEditable ?? true);
|
||||
@@ -30,7 +107,7 @@
|
||||
<div class="alert alert-info">No students available for report cards.</div>
|
||||
<?php else: ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered align-middle">
|
||||
<table class="table table-striped table-bordered align-middle parent-report-cards-table">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Student</th>
|
||||
@@ -51,10 +128,10 @@
|
||||
$hasReport = !empty(($reportAvailableMap ?? [])[$sid]);
|
||||
?>
|
||||
<tr>
|
||||
<td><?= esc(trim(($student['firstname'] ?? '') . ' ' . ($student['lastname'] ?? ''))) ?></td>
|
||||
<td><?= esc($student['class_section_name'] ?? 'N/A') ?></td>
|
||||
<td><?= $viewedAt ? esc(local_datetime($viewedAt, 'm-d-Y H:i')) : 'Not viewed' ?></td>
|
||||
<td>
|
||||
<td data-label="Student"><?= esc(trim(($student['firstname'] ?? '') . ' ' . ($student['lastname'] ?? ''))) ?></td>
|
||||
<td data-label="Class Section"><?= esc($student['class_section_name'] ?? 'N/A') ?></td>
|
||||
<td data-label="Viewed"><?= $viewedAt ? esc(local_datetime($viewedAt, 'm-d-Y H:i')) : 'Not viewed' ?></td>
|
||||
<td data-label="Signature">
|
||||
<?php if ($signedAt): ?>
|
||||
<?= esc($signedName ?: 'Signed') ?><br>
|
||||
<small class="text-muted"><?= esc(local_datetime($signedAt, 'm-d-Y H:i')) ?></small>
|
||||
@@ -62,7 +139,7 @@
|
||||
<span class="text-muted">Not signed</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<td class="text-end" data-label="Action">
|
||||
<?php if ($hasReport): ?>
|
||||
<a class="btn btn-sm btn-outline-primary" target="_blank" href="<?= base_url('parent/report-cards/view/' . $sid) ?>">View Report</a>
|
||||
<?php else: ?>
|
||||
|
||||
Reference in New Issue
Block a user