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:
@@ -51,6 +51,7 @@ class PrintRequests extends BaseController
|
||||
$schoolYear = $context->yearName();
|
||||
|
||||
$printRequestsQuery = $this->printRequestModel
|
||||
->distinct()
|
||||
->select('print_requests.*, admins.firstname as admin_firstname, admins.lastname as admin_lastname')
|
||||
->join('users as admins', 'admins.id = print_requests.admin_id', 'left')
|
||||
->join('classSection cs', 'cs.class_section_id = print_requests.class_id', 'left')
|
||||
@@ -67,6 +68,8 @@ class PrintRequests extends BaseController
|
||||
$data['sundays'] = $dateOptions['sundays'];
|
||||
$data['times'] = $dateOptions['times'];
|
||||
$data['isSchoolYearReadonly'] = $context->isReadonly();
|
||||
$data['printRequestToken'] = $this->issuePrintRequestToken('print');
|
||||
$data['copyRequestToken'] = $this->issuePrintRequestToken('copy');
|
||||
|
||||
return view('print_requests/teacher_index', $data);
|
||||
}
|
||||
@@ -77,6 +80,7 @@ class PrintRequests extends BaseController
|
||||
$schoolYear = $context->yearName();
|
||||
|
||||
$printRequestsQuery = $this->printRequestModel
|
||||
->distinct()
|
||||
->select('
|
||||
print_requests.*,
|
||||
u.firstname,
|
||||
@@ -125,6 +129,10 @@ class PrintRequests extends BaseController
|
||||
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
|
||||
if (! $this->consumePrintRequestToken('print')) {
|
||||
return redirect()->to('teacher/print-requests')->with('error', 'This print request was already submitted. Please refresh the page before submitting another request.');
|
||||
}
|
||||
|
||||
$teacher_id = session()->get('user_id');
|
||||
|
||||
$file = $this->request->getFile('file');
|
||||
@@ -346,6 +354,10 @@ class PrintRequests extends BaseController
|
||||
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
|
||||
if (! $this->consumePrintRequestToken('copy')) {
|
||||
return redirect()->to('teacher/print-requests')->with('error', 'This copy request was already submitted. Please refresh the page before submitting another request.');
|
||||
}
|
||||
|
||||
$teacher_id = session()->get('user_id');
|
||||
|
||||
$data = [
|
||||
@@ -402,6 +414,54 @@ class PrintRequests extends BaseController
|
||||
];
|
||||
}
|
||||
|
||||
private function issuePrintRequestToken(string $type): string
|
||||
{
|
||||
$key = $this->printRequestTokenSessionKey($type);
|
||||
$tokens = session()->get($key);
|
||||
|
||||
if (! is_array($tokens)) {
|
||||
$tokens = [];
|
||||
}
|
||||
|
||||
$token = bin2hex(random_bytes(16));
|
||||
$tokens[$token] = time();
|
||||
|
||||
if (count($tokens) > 20) {
|
||||
asort($tokens);
|
||||
$tokens = array_slice($tokens, -20, null, true);
|
||||
}
|
||||
|
||||
session()->set($key, $tokens);
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
private function consumePrintRequestToken(string $type): bool
|
||||
{
|
||||
$token = (string) $this->request->getPost('request_token');
|
||||
|
||||
if ($token === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$key = $this->printRequestTokenSessionKey($type);
|
||||
$tokens = session()->get($key);
|
||||
|
||||
if (! is_array($tokens) || ! array_key_exists($token, $tokens)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unset($tokens[$token]);
|
||||
session()->set($key, $tokens);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function printRequestTokenSessionKey(string $type): string
|
||||
{
|
||||
return 'print_request_' . $type . '_tokens';
|
||||
}
|
||||
|
||||
private function applyPrintRequestSchoolYearScope($query, string $schoolYear): void
|
||||
{
|
||||
if ($schoolYear === '') {
|
||||
@@ -620,7 +680,7 @@ class PrintRequests extends BaseController
|
||||
'action_url' => $isCopyRequest ? '' : $actionUrl,
|
||||
'scheduled_at' => utc_now(),
|
||||
'school_year' => $this->configModel->getConfig('school_year'),
|
||||
'semester' => $this->configModel->getConfig('semester'),
|
||||
'semester' => getSemester(),
|
||||
];
|
||||
|
||||
$notificationFields = $db->getFieldNames('notifications');
|
||||
|
||||
Reference in New Issue
Block a user