Files
alrahma_sunday_school/app/Controllers/View/TuitionForecastController.php
2026-06-07 00:27:27 -04:00

140 lines
6.1 KiB
PHP

<?php
namespace App\Controllers\View;
use App\Controllers\BaseController;
use App\Libraries\Tuition\TuitionForecastService;
class TuitionForecastController extends BaseController
{
protected TuitionForecastService $forecastService;
public function __construct()
{
$this->forecastService = new TuitionForecastService();
helper(['url']);
}
public function index()
{
$schoolYear = trim((string) ($this->request->getGet('school_year') ?? ''));
$semester = trim((string) ($this->request->getGet('semester') ?? ''));
$mode = (string) ($this->request->getGet('calculator_mode') ?? 'compare');
$filters = $this->buildOptionsFromRequest('get');
$result = $this->forecastService->calculate($schoolYear, $semester, $mode, $filters);
return view('administrator/tuition_forecast', [
'title' => 'Tuition Collection Forecast',
'schoolYears' => $this->forecastService->getAvailableSchoolYears(),
'semesters' => $this->forecastService->getAvailableSemesters(),
'filters' => [
'school_year' => $result['school_year'],
'semester' => $result['semester'],
'calculator_mode' => $result['calculator_mode'],
] + $result['options'],
'result' => $result,
]);
}
public function calculate()
{
$schoolYear = trim((string) ($this->request->getPost('school_year') ?? ''));
$semester = trim((string) ($this->request->getPost('semester') ?? ''));
$mode = (string) ($this->request->getPost('calculator_mode') ?? 'compare');
return $this->response->setJSON(
$this->forecastService->calculate($schoolYear, $semester, $mode, $this->buildOptionsFromRequest('post'))
);
}
public function exportCsv()
{
$schoolYear = trim((string) ($this->request->getGet('school_year') ?? ''));
$semester = trim((string) ($this->request->getGet('semester') ?? ''));
$mode = (string) ($this->request->getGet('calculator_mode') ?? 'compare');
$result = $this->forecastService->calculate($schoolYear, $semester, $mode, $this->buildOptionsFromRequest('get'));
$filename = sprintf(
'tuition_forecast_%s_%s_%s.csv',
preg_replace('/[^A-Za-z0-9_-]+/', '-', $result['school_year']) ?: 'school-year',
preg_replace('/[^A-Za-z0-9_-]+/', '-', $result['semester']) ?: 'all-year',
$result['calculator_mode']
);
$handle = fopen('php://temp', 'w+');
if ($handle === false) {
throw new \RuntimeException('Unable to create CSV export.');
}
fputcsv($handle, ['School Year', $result['school_year']]);
fputcsv($handle, ['Semester', $result['semester'] !== '' ? $result['semester'] : 'All Year']);
fputcsv($handle, ['Calculator Mode', $result['calculator_mode']]);
fputcsv($handle, []);
fputcsv($handle, ['Summary']);
fputcsv($handle, ['Families', 'Students', 'Billable Students', 'Grade Unit Price', 'Youth Unit Price', 'Old Projected Income', 'New Projected Income', 'Difference']);
fputcsv($handle, [
$result['summary']['family_count'],
$result['summary']['student_count'],
$result['summary']['billable_student_count'],
$result['summary']['unit_price'],
$result['summary']['youth_unit_price'],
$result['summary']['old_projected_income'] ?? $result['summary']['old_projected_tuition'],
$result['summary']['new_projected_income'] ?? $result['summary']['new_projected_tuition'],
$result['summary']['difference'],
]);
fputcsv($handle, []);
fputcsv($handle, ['Families']);
fputcsv($handle, ['Parent/Family', 'Student Count', 'Billable Student Count', 'Old Tuition Total', 'New Tuition Total', 'Difference', 'Warnings']);
foreach ($result['families'] as $family) {
fputcsv($handle, [
$family['parent_name'] ?? '',
$family['student_count'] ?? 0,
$family['billable_student_count'] ?? 0,
$family['old_total'] ?? '0.00',
$family['new_total'] ?? '0.00',
$family['difference'] ?? '0.00',
implode(' | ', $family['warnings'] ?? []),
]);
fputcsv($handle, ['Student Name', 'Grade', 'Billable', 'Excluded Reason', 'Old Rule', 'Old Amount', 'New Rule', 'New Amount']);
foreach ($family['student_details'] as $detail) {
fputcsv($handle, [
$detail['student_name'] ?? '',
$detail['grade_level'] ?? '',
!empty($detail['billable']) ? 'Yes' : 'No',
$detail['excluded_reason'] ?? '',
$detail['old_rule'] ?? '',
$detail['old_amount'] ?? '0.00',
$detail['new_rule'] ?? '',
$detail['new_amount'] ?? '0.00',
]);
}
fputcsv($handle, []);
}
rewind($handle);
$csv = stream_get_contents($handle) ?: '';
fclose($handle);
return $this->response
->setHeader('Content-Type', 'text/csv; charset=UTF-8')
->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"')
->setBody($csv);
}
protected function buildOptionsFromRequest(string $method): array
{
$source = $method === 'post' ? 'getPost' : 'getGet';
return [
'include_withdrawn_mode' => (string) ($this->request->{$source}('include_withdrawn_mode') ?? 'refund_deadline'),
'include_payment_pending' => $this->request->{$source}('include_payment_pending') ?? '0',
'include_event_only' => $this->request->{$source}('include_event_only') ?? '0',
'include_paid_invoices' => $this->request->{$source}('include_paid_invoices') ?? '0',
'unit_price' => $this->request->{$source}('unit_price') ?? '',
'youth_unit_price' => $this->request->{$source}('youth_unit_price') ?? '',
];
}
}