add projet

This commit is contained in:
root
2026-03-05 12:29:37 -05:00
parent 8d1eef8ba8
commit 23b7db1107
9109 changed files with 1106501 additions and 73 deletions
+399
View File
@@ -0,0 +1,399 @@
<?php
namespace App\Http\Controllers\Api;
use App\Models\ClassSection;
use App\Models\Configuration;
use App\Models\CurrentFlag;
use App\Models\Flag;
use App\Models\StudentClass;
use App\Models\Student;
use Symfony\Component\HttpFoundation\Response;
class FlagController extends BaseApiController
{
protected CurrentFlag $currentFlag;
protected Flag $flag;
protected Student $student;
protected ClassSection $classSection;
protected StudentClass $studentClass;
protected Configuration $config;
public function __construct()
{
parent::__construct();
$this->currentFlag = model(CurrentFlag::class);
$this->flag = model(Flag::class);
$this->student = model(Student::class);
$this->classSection = model(ClassSection::class);
$this->studentClass = model(StudentClass::class);
$this->config = model(Configuration::class);
}
public function index()
{
$page = max(1, (int) ($this->request->getGet('page') ?? 1));
$perPage = min(100, max(1, (int) ($this->request->getGet('per_page') ?? 20)));
$studentId = $this->request->getGet('student_id');
$flagType = $this->request->getGet('flag_type') ?? $this->request->getGet('flag');
$state = $this->request->getGet('state') ?? $this->request->getGet('flag_state');
$query = $this->currentFlag->newQuery()->orderBy('created_at', 'DESC');
if ($studentId) {
$query->where('student_id', $studentId);
}
if ($flagType) {
$query->where('flag', $flagType);
}
if ($state) {
$query->where('flag_state', $state);
}
$result = $this->paginate($query, $page, $perPage);
// Also return class sections (grades) for UI
$classSections = $this->classSection->findAll();
$grades = [];
foreach ($classSections as $section) {
$grades[] = [
'id' => $section['class_section_id'] ?? $section['id'] ?? null,
'name' => $section['class_section_name'] ?? $section['name'] ?? '',
];
}
$result['grades'] = $grades;
return $this->success($result, 'Flags retrieved successfully');
}
public function show($id = null)
{
$flag = $this->currentFlag->find($id);
if (!$flag) {
return $this->respondError('Flag not found', Response::HTTP_NOT_FOUND);
}
return $this->success($flag, 'Flag retrieved successfully');
}
public function create()
{
return $this->addFlag();
}
/**
* Add or update a flag for a student
* If a flag of the same type exists, it updates it; otherwise creates a new one
*/
public function addFlag()
{
$user = $this->getCurrentUser();
$data = $this->payloadData();
if (empty($data)) {
return $this->respondError('Invalid request data', Response::HTTP_BAD_REQUEST);
}
$studentId = $data['student_id'] ?? $data['student'] ?? null;
$flagType = $data['flag'] ?? $data['flag_type'] ?? null;
$description = $data['description'] ?? $data['open_description'] ?? null;
$flagState = $data['flag_state'] ?? 'Open';
$stateDescription = $data['state_description'] ?? null;
$grade = $data['grade'] ?? null;
if (!$studentId || !$flagType || !$description) {
return $this->respondError('Missing required fields: student_id, flag, description', Response::HTTP_BAD_REQUEST);
}
try {
// Retrieve student information
$student = $this->student->find($studentId);
if (!$student) {
return $this->respondError('Student not found', Response::HTTP_NOT_FOUND);
}
$userId = $user->id ?? null;
$semester = $this->config->getConfig('semester');
$schoolYear = $this->config->getConfig('school_year');
$currentDateTime = date('Y-m-d H:i:s');
// Check if a flag of the same type already exists for this student
$existingFlag = $this->currentFlag
->where('student_id', $studentId)
->where('flag', $flagType)
->first();
if ($existingFlag) {
// Update existing flag
$updateData = [
'flag_datetime' => $currentDateTime,
'updated_by_open' => $userId,
];
// Append description based on flag state
if ($flagState === 'Closed') {
$updateData['flag_state'] = 'Closed';
$existingCloseDesc = $existingFlag['close_description'] ?? '';
$updateData['close_description'] = $existingCloseDesc
? $existingCloseDesc . PHP_EOL . $stateDescription
: $stateDescription;
} elseif ($flagState === 'Canceled') {
$updateData['flag_state'] = 'Canceled';
$existingCancelDesc = $existingFlag['cancel_description'] ?? '';
$updateData['cancel_description'] = $existingCancelDesc
? $existingCancelDesc . PHP_EOL . $stateDescription
: $stateDescription;
} else {
$existingOpenDesc = $existingFlag['open_description'] ?? '';
$updateData['open_description'] = $existingOpenDesc
? $existingOpenDesc . PHP_EOL . $description
: $description;
}
$this->currentFlag->update($existingFlag['id'], $updateData);
$flag = $this->currentFlag->find($existingFlag['id']);
return $this->success($flag, 'Flag updated successfully');
} else {
// Create new flag
$flagData = [
'student_id' => $student['id'],
'student_name' => trim(($student['firstname'] ?? '') . ' ' . ($student['lastname'] ?? '')),
'grade' => $grade,
'flag' => $flagType,
'flag_datetime' => $currentDateTime,
'flag_state' => 'Open',
'updated_by_open' => $userId,
'open_description' => $description,
'semester' => $semester,
'school_year' => $schoolYear,
];
$flag = $this->currentFlag->create($flagData);
return $this->success($flag, 'New flag added successfully', Response::HTTP_CREATED);
}
} catch (\Throwable $e) {
log_message('error', 'Add flag error: ' . $e->getMessage());
return $this->respondError('Failed to add flag', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function updateState($id = null)
{
$flag = $this->currentFlag->find($id);
if (!$flag) {
return $this->respondError('Flag not found', Response::HTTP_NOT_FOUND);
}
$data = $this->payloadData();
if (empty($data)) {
return $this->respondError('Invalid request data', Response::HTTP_BAD_REQUEST);
}
$newState = $data['flag_state'] ?? null;
if (!$newState) {
return $this->respondError('Flag state is required', Response::HTTP_BAD_REQUEST);
}
try {
$updateData = ['flag_state' => $newState];
// Update appropriate description field based on state
if (isset($data['state_description'])) {
if ($newState === 'Closed') {
$updateData['close_description'] = $data['state_description'];
} elseif ($newState === 'Canceled') {
$updateData['cancel_description'] = $data['state_description'];
} else {
$updateData['open_description'] = $data['state_description'];
}
}
$this->currentFlag->update($id, $updateData);
$flag = $this->currentFlag->find($id);
return $this->success($flag, 'Flag state updated successfully');
} catch (\Throwable $e) {
log_message('error', 'Update flag state error: ' . $e->getMessage());
return $this->respondError('Failed to update flag state', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function close($id = null)
{
return $this->closeFlag($id);
}
public function cancel($id = null)
{
return $this->cancelFlag($id);
}
/**
* Close a flag and move it to history
*/
public function closeFlag($flagId = null)
{
$flagId = $flagId ?? $this->request->getPost('id') ?? $this->request->getGet('id');
if (!$flagId) {
return $this->respondError('Flag ID is required', Response::HTTP_BAD_REQUEST);
}
try {
$user = $this->getCurrentUser();
$userId = $user->id ?? null;
// Get the current flag data
$flagData = $this->currentFlag->find($flagId);
if (!$flagData) {
return $this->respondError('Flag not found', Response::HTTP_NOT_FOUND);
}
// Check if flag is already closed
if ($flagData['flag_state'] === 'Closed') {
return $this->respondError('Flag is already closed', Response::HTTP_BAD_REQUEST);
}
// Get close description from request
$data = $this->payloadData();
$closeDescription = $data['state_description'] ?? $data['close_description'] ?? null;
if (empty($closeDescription)) {
return $this->respondError('Close description is required', Response::HTTP_BAD_REQUEST);
}
// Update the flag state to Closed
$this->currentFlag->update($flagId, [
'flag_state' => 'Closed',
'updated_by_closed' => $userId,
'close_description' => $closeDescription,
]);
// Retrieve updated flag data
$flagData = $this->currentFlag->find($flagId);
// Move to history
return $this->moveToHistory($flagData);
} catch (\Throwable $e) {
log_message('error', 'Close flag error: ' . $e->getMessage());
return $this->respondError('Failed to close flag', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Cancel a flag and move it to history
*/
public function cancelFlag($flagId = null)
{
$flagId = $flagId ?? $this->request->getPost('id') ?? $this->request->getGet('id');
if (!$flagId) {
return $this->respondError('Flag ID is required', Response::HTTP_BAD_REQUEST);
}
try {
$user = $this->getCurrentUser();
$userId = $user->id ?? null;
// Get the current flag data
$flagData = $this->currentFlag->find($flagId);
if (!$flagData) {
return $this->respondError('Flag not found', Response::HTTP_NOT_FOUND);
}
// Check if flag is already canceled
if ($flagData['flag_state'] === 'Canceled') {
return $this->respondError('Flag is already canceled', Response::HTTP_BAD_REQUEST);
}
// Get cancel description from request
$data = $this->payloadData();
$cancelDescription = $data['state_description'] ?? $data['cancel_description'] ?? null;
if (empty($cancelDescription)) {
return $this->respondError('Cancel description is required', Response::HTTP_BAD_REQUEST);
}
// Update the flag state to Canceled
$this->currentFlag->update($flagId, [
'flag_state' => 'Canceled',
'updated_by_canceled' => $userId,
'cancel_description' => $cancelDescription,
]);
// Retrieve updated flag data
$flagData = $this->currentFlag->find($flagId);
// Move to history
return $this->moveToHistory($flagData);
} catch (\Throwable $e) {
log_message('error', 'Cancel flag error: ' . $e->getMessage());
return $this->respondError('Failed to cancel flag', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
/**
* Move flag to history table and delete from current_flag table
*/
protected function moveToHistory($flagData)
{
try {
// Prepare data for the flag table
$dataToInsert = [
'student_id' => $flagData['student_id'] ?? null,
'student_name' => $flagData['student_name'] ?? null,
'grade' => $flagData['grade'] ?? null,
'flag' => $flagData['flag'] ?? null,
'flag_datetime' => $flagData['flag_datetime'] ?? null,
'flag_state' => $flagData['flag_state'] ?? null,
'updated_by_open' => $flagData['updated_by_open'] ?? null,
'open_description' => $flagData['open_description'] ?? null,
'updated_by_closed' => $flagData['updated_by_closed'] ?? null,
'close_description' => $flagData['close_description'] ?? null,
'updated_by_canceled' => $flagData['updated_by_canceled'] ?? null,
'cancel_description' => $flagData['cancel_description'] ?? null,
'semester' => $flagData['semester'] ?? null,
'school_year' => $flagData['school_year'] ?? null,
'created_at' => $flagData['created_at'] ?? date('Y-m-d H:i:s'),
'updated_at' => $flagData['updated_at'] ?? date('Y-m-d H:i:s'),
];
// Insert data into the flag table
$this->flag->insert($dataToInsert);
// Delete the entry from the current_flag table
$this->currentFlag->delete($flagData['id']);
return $this->success(['moved_to_history' => true], 'Flag has been moved to history');
} catch (\Throwable $e) {
log_message('error', 'Move to history error: ' . $e->getMessage());
return $this->respondError('Failed to move flag to history', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
public function getStudentsByGrade($gradeId = null)
{
try {
$studentIds = $this->studentClass->newQuery()
->where('class_section_id', $gradeId)
->pluck('student_id')
->toArray();
if (empty($studentIds)) {
return $this->success([], 'No students found for this grade');
}
$students = $this->student->newQuery()
->whereIn('id', $studentIds)
->get()
->map(fn($student) => [
'id' => $student->id,
'name' => trim(($student->firstname ?? '') . ' ' . ($student->lastname ?? '')),
])
->values()
->toArray();
return $this->success($students, 'Students retrieved successfully');
} catch (\Throwable $e) {
log_message('error', 'Get students by grade error: ' . $e->getMessage());
return $this->respondError('Failed to retrieve students', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}
}