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:
@@ -86,7 +86,7 @@ class ParentController extends BaseController
|
||||
$this->schoolStartDate = $this->configModel->getConfig('fall_semester_start');
|
||||
$this->withdrawalDeadline = $this->configModel->getConfig('refund_deadline');
|
||||
$this->schoolYear = $this->configModel->getConfig('school_year');
|
||||
$this->semester = $this->configModel->getConfig('semester');
|
||||
$this->semester = getSemester();
|
||||
$this->dateAgeReference = $this->configModel->getConfig('date_age_reference');
|
||||
$this->maxChilds = (int) $this->configModel->getConfig('max_kids') ?? 0;
|
||||
$this->maxEmergency = (int) $this->configModel->getConfig('max_emergency') ?? 0;
|
||||
@@ -548,7 +548,7 @@ class ParentController extends BaseController
|
||||
|
||||
if ($existingEnrollment['is_withdrawn'] == 1) {
|
||||
// Reactivate the enrollment if the student was previously withdrawn
|
||||
$this->enrollmentModel->where('id', $existingEnrollment['id'])->update($update);
|
||||
$this->enrollmentModel->update((int) $existingEnrollment['id'], $update);
|
||||
log_message('info', "{$studentData[$studentId]['firstname']} {$studentData[$studentId]['lastname']} (ID $studentId) has been re-enrolled in enrollment ID {$existingEnrollment['id']}.");
|
||||
// Apply promotion-based class placement for the upcoming year
|
||||
$this->applyPromotionAssignment((int)$studentId, $selectedYear, $isReturningReEnrollment);
|
||||
@@ -557,7 +557,7 @@ class ParentController extends BaseController
|
||||
if ($currentStatus === 'enrolled') {
|
||||
$update['admission_status'] = 'accepted';
|
||||
}
|
||||
$this->enrollmentModel->where('id', $existingEnrollment['id'])->update($update);
|
||||
$this->enrollmentModel->update((int) $existingEnrollment['id'], $update);
|
||||
log_message('info', "{$studentData[$studentId]['firstname']} {$studentData[$studentId]['lastname']} (ID $studentId) is already actively enrolled.");
|
||||
$this->applyPromotionAssignment((int)$studentId, $selectedYear, $isReturningReEnrollment);
|
||||
}
|
||||
@@ -642,7 +642,7 @@ class ParentController extends BaseController
|
||||
|
||||
if ($enrollment !== null) {
|
||||
// Update enrollment as withdrawn
|
||||
$this->enrollmentModel->where('id', $enrollment['id'])->update([
|
||||
$this->enrollmentModel->update((int) $enrollment['id'], [
|
||||
'withdrawal_date' => local_date(utc_now(), 'Y-m-d'),
|
||||
'enrollment_status' => 'withdraw under review', // Withdrawal needs review
|
||||
'updated_at' => utc_now()
|
||||
@@ -660,6 +660,12 @@ class ParentController extends BaseController
|
||||
|
||||
if ($invoice !== null) {
|
||||
$invoiceId = $invoice['id'];
|
||||
$studentsForRefund = $this->enrollmentModel
|
||||
->where('parent_id', $parentId)
|
||||
->where('school_year', $this->schoolYear)
|
||||
->findAll();
|
||||
$refundAmount = $refundService->calculateRefund($studentsForRefund, (int) $parentId);
|
||||
$refundCents = max(0, (int) round($refundAmount * 100));
|
||||
|
||||
$refundTable = $this->db->table('refunds');
|
||||
|
||||
@@ -667,21 +673,29 @@ class ParentController extends BaseController
|
||||
->where('parent_id', $parentId)
|
||||
->where('invoice_id', $invoiceId)
|
||||
->where('school_year', $this->schoolYear)
|
||||
->whereIn('status', ['Pending', 'Approved', 'Partial', 'pending', 'requested', 'approved', 'partial', 'partially_paid'])
|
||||
->get()
|
||||
->getRow();
|
||||
|
||||
if ($existingRefund) {
|
||||
// Only update the fields that should change
|
||||
$updateData = [
|
||||
'refund_amount' => $refundAmount,
|
||||
'requested_amount_cents' => $refundCents,
|
||||
'currency' => 'USD',
|
||||
'reason' => 'Withdrawal under review for student ID ' . $studentId,
|
||||
'note' => null,
|
||||
'request' => 'tuition',
|
||||
'source_type' => 'tuition_withdrawal',
|
||||
'source_id' => (int) $invoiceId,
|
||||
'status' => 'Pending',
|
||||
'updated_by' => session()->get('user_id'), // optionally track updates
|
||||
// Add other fields if *and only if* they must be changed
|
||||
];
|
||||
|
||||
$refundTable
|
||||
->where('id', $existingRefund->id)
|
||||
->update($updateData);
|
||||
->update($this->filterPayloadByTableColumns($updateData, 'refunds'));
|
||||
|
||||
log_message('info', "Refund record updated for invoice ID {$invoiceId}, student ID {$studentId}.");
|
||||
} else {
|
||||
@@ -689,16 +703,22 @@ class ParentController extends BaseController
|
||||
$insertData = [
|
||||
'parent_id' => $parentId,
|
||||
'invoice_id' => $invoiceId,
|
||||
'refund_amount' => $refundAmount,
|
||||
'requested_amount_cents' => $refundCents,
|
||||
'approved_amount_cents' => null,
|
||||
'currency' => 'USD',
|
||||
'requested_at' => utc_now(),
|
||||
'school_year' => $this->schoolYear,
|
||||
'status' => 'Pending review',
|
||||
'status' => 'Pending',
|
||||
'reason' => 'Withdrawal under review for student ID ' . $studentId,
|
||||
'request' => 'new',
|
||||
'request' => 'tuition',
|
||||
'source_type' => 'tuition_withdrawal',
|
||||
'source_id' => (int) $invoiceId,
|
||||
'semester' => $this->semester,
|
||||
'refund_paid_amount' => 0.0,
|
||||
];
|
||||
|
||||
$refundTable->insert($insertData);
|
||||
$refundTable->insert($this->filterPayloadByTableColumns($insertData, 'refunds'));
|
||||
|
||||
log_message('info', "Refund record created for invoice ID {$invoiceId}, student ID {$studentId}.");
|
||||
}
|
||||
@@ -893,9 +913,14 @@ class ParentController extends BaseController
|
||||
}
|
||||
|
||||
private function filterEnrollmentPayloadByColumns(array $payload): array
|
||||
{
|
||||
return $this->filterPayloadByTableColumns($payload, 'enrollments');
|
||||
}
|
||||
|
||||
private function filterPayloadByTableColumns(array $payload, string $table): array
|
||||
{
|
||||
foreach (array_keys($payload) as $column) {
|
||||
if (! $this->db->fieldExists($column, 'enrollments')) {
|
||||
if (! $this->db->fieldExists($column, $table)) {
|
||||
unset($payload[$column]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user