recreate project
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Models\ClassProgressReportModel;
|
||||
use App\Models\ClassProgressAttachmentModel;
|
||||
use App\Models\ClassSectionModel;
|
||||
use App\Models\StudentClassModel;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
|
||||
class AdminProgressController extends BaseController
|
||||
{
|
||||
protected ClassProgressReportModel $reportModel;
|
||||
protected ClassProgressAttachmentModel $attachmentModel;
|
||||
protected ClassSectionModel $classSectionModel;
|
||||
protected StudentClassModel $studentClassModel;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
helper(['url', 'form']);
|
||||
$this->reportModel = new ClassProgressReportModel();
|
||||
$this->attachmentModel = new ClassProgressAttachmentModel();
|
||||
$this->classSectionModel = new ClassSectionModel();
|
||||
$this->studentClassModel = new StudentClassModel();
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$filters = [
|
||||
'from' => (string) $this->request->getGet('from'),
|
||||
'to' => (string) $this->request->getGet('to'),
|
||||
'class_section_id' => (string) $this->request->getGet('class_section_id'),
|
||||
'status' => (string) $this->request->getGet('status'),
|
||||
];
|
||||
|
||||
$builder = $this->reportModel
|
||||
->select('class_progress_reports.*, cs.class_section_name, CONCAT(IFNULL(u.firstname, ""), " ", IFNULL(u.lastname, "")) AS teacher_name')
|
||||
->join('classSection cs', 'cs.class_section_id = class_progress_reports.class_section_id', 'left')
|
||||
->join('users u', 'u.id = class_progress_reports.teacher_id', 'left');
|
||||
|
||||
if ($filters['from']) {
|
||||
$builder->where('week_start >=', $filters['from']);
|
||||
}
|
||||
if ($filters['to']) {
|
||||
$builder->where('week_end <=', $filters['to']);
|
||||
}
|
||||
if ($filters['class_section_id']) {
|
||||
$builder->where('class_progress_reports.class_section_id', (int) $filters['class_section_id']);
|
||||
}
|
||||
if ($filters['status']) {
|
||||
$builder->where('class_progress_reports.status', $filters['status']);
|
||||
}
|
||||
|
||||
$rows = $builder->orderBy('week_start', 'DESC')->get()->getResultArray();
|
||||
$reportGroups = [];
|
||||
foreach ($rows as $row) {
|
||||
$row['status_label'] = ClassProgressController::STATUS_OPTIONS[$row['status']] ?? 'Unknown';
|
||||
$key = ($row['week_start'] ?? '') . '_' . ($row['class_section_id'] ?? '');
|
||||
if ($key === '_') {
|
||||
continue;
|
||||
}
|
||||
if (! isset($reportGroups[$key])) {
|
||||
$reportGroups[$key] = [
|
||||
'week_start' => $row['week_start'],
|
||||
'week_end' => $row['week_end'],
|
||||
'class_section_name' => $row['class_section_name'] ?? '',
|
||||
'reports' => [],
|
||||
];
|
||||
}
|
||||
$reportGroups[$key]['reports'][$row['subject']] = $row;
|
||||
}
|
||||
|
||||
$classSections = $this->classSectionModel->getClassSections();
|
||||
$studentCounts = $this->studentClassModel->getStudentCountsBySection();
|
||||
$filteredSections = array_values(array_filter($classSections, function ($section) use ($studentCounts) {
|
||||
$sectionId = (int) ($section['class_section_id'] ?? 0);
|
||||
return isset($studentCounts[$sectionId]) && $studentCounts[$sectionId] > 0;
|
||||
}));
|
||||
|
||||
return view('admin/class_progress_list', [
|
||||
'reportGroups' => $reportGroups,
|
||||
'filters' => $filters,
|
||||
'classSections' => $filteredSections,
|
||||
'statusOptions' => ClassProgressController::STATUS_OPTIONS,
|
||||
'subjectSections' => ClassProgressController::SUBJECT_SECTIONS,
|
||||
]);
|
||||
}
|
||||
|
||||
public function view($id)
|
||||
{
|
||||
$row = $this->reportModel
|
||||
->select('class_progress_reports.*, cs.class_section_name, CONCAT(IFNULL(u.firstname, ""), " ", IFNULL(u.lastname, "")) AS teacher_name')
|
||||
->join('classSection cs', 'cs.class_section_id = class_progress_reports.class_section_id', 'left')
|
||||
->join('users u', 'u.id = class_progress_reports.teacher_id', 'left')
|
||||
->find((int) $id);
|
||||
|
||||
if (! $row) {
|
||||
throw new PageNotFoundException('Progress report not found.');
|
||||
}
|
||||
|
||||
$row['status_label'] = ClassProgressController::STATUS_OPTIONS[$row['status']] ?? 'Unknown';
|
||||
$row['flags'] = $this->decodeFlags($row['flags_json']);
|
||||
|
||||
$weeklyReports = $this->reportModel
|
||||
->select('class_progress_reports.*')
|
||||
->where('class_section_id', $row['class_section_id'])
|
||||
->where('week_start', $row['week_start'])
|
||||
->orderBy('subject', 'ASC')
|
||||
->findAll();
|
||||
|
||||
$attachmentMap = $this->loadAttachmentsForReports(array_column($weeklyReports, 'id'));
|
||||
foreach ($weeklyReports as &$report) {
|
||||
$report['attachments'] = $attachmentMap[$report['id']] ?? [];
|
||||
if (empty($report['attachments']) && ! empty($report['attachment_path'])) {
|
||||
$report['attachments'][] = [
|
||||
'id' => $report['id'],
|
||||
'name' => basename((string) $report['attachment_path']),
|
||||
'legacy' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return view('admin/class_progress_view', [
|
||||
'row' => $row,
|
||||
'weeklyReports' => $weeklyReports,
|
||||
'subjectSections' => ClassProgressController::SUBJECT_SECTIONS,
|
||||
]);
|
||||
}
|
||||
|
||||
public function attachment($id)
|
||||
{
|
||||
$row = $this->reportModel->find((int)$id);
|
||||
if (! $row || empty($row['attachment_path'])) {
|
||||
throw new PageNotFoundException('Attachment not found.');
|
||||
}
|
||||
|
||||
$file = $this->resolveAttachmentFile($row);
|
||||
if (! $file) {
|
||||
throw new PageNotFoundException('Attachment missing.');
|
||||
}
|
||||
|
||||
return $this->response->download($file, null)->setFileName(basename($file));
|
||||
}
|
||||
|
||||
public function attachmentFile($id)
|
||||
{
|
||||
$attachment = $this->attachmentModel->find((int) $id);
|
||||
if (! $attachment || empty($attachment['file_path'])) {
|
||||
throw new PageNotFoundException('Attachment not found.');
|
||||
}
|
||||
|
||||
$file = $this->resolveAttachmentPath($attachment['file_path']);
|
||||
if (! $file) {
|
||||
throw new PageNotFoundException('Attachment missing.');
|
||||
}
|
||||
|
||||
$downloadName = $attachment['original_name'] ?: basename($file);
|
||||
return $this->response->download($file, null)->setFileName($downloadName);
|
||||
}
|
||||
|
||||
protected function resolveAttachmentFile(array $row): ?string
|
||||
{
|
||||
$path = trim((string) ($row['attachment_path'] ?? ''));
|
||||
if ($path === '') {
|
||||
return null;
|
||||
}
|
||||
return $this->resolveAttachmentPath($path);
|
||||
}
|
||||
|
||||
protected function resolveAttachmentPath(string $path): ?string
|
||||
{
|
||||
$relative = preg_replace('#^writable/uploads/#', '', $path);
|
||||
$absolute = WRITEPATH . 'uploads/' . ltrim($relative, '/');
|
||||
return is_file($absolute) ? $absolute : null;
|
||||
}
|
||||
|
||||
protected function loadAttachmentsForReports(array $reportIds): array
|
||||
{
|
||||
$reportIds = array_values(array_filter(array_map('intval', $reportIds)));
|
||||
if (empty($reportIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$rows = $this->attachmentModel
|
||||
->whereIn('report_id', $reportIds)
|
||||
->orderBy('id', 'ASC')
|
||||
->findAll();
|
||||
|
||||
$map = [];
|
||||
foreach ($rows as $row) {
|
||||
$reportId = (int) ($row['report_id'] ?? 0);
|
||||
if ($reportId === 0) {
|
||||
continue;
|
||||
}
|
||||
$map[$reportId][] = [
|
||||
'id' => (int) $row['id'],
|
||||
'name' => $row['original_name'] ?: basename((string) $row['file_path']),
|
||||
];
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
protected function decodeFlags(?string $json): array
|
||||
{
|
||||
if (! $json) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$flags = json_decode($json, true);
|
||||
return is_array($flags) ? $flags : [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user