fix teacher page

This commit is contained in:
root
2026-06-04 19:26:24 -04:00
parent 6408906f07
commit 6fa656bb6c
9 changed files with 1370 additions and 4 deletions
@@ -44,6 +44,7 @@ class ScoreController extends BaseApiController
'semester' => $data['semester'] ?? null, 'semester' => $data['semester'] ?? null,
'school_year' => $data['school_year'] ?? null, 'school_year' => $data['school_year'] ?? null,
'scores_locked' => $data['scoresLocked'] ?? false, 'scores_locked' => $data['scoresLocked'] ?? false,
'missing_ok_map' => $data['missing_ok_map'] ?? [],
]); ]);
} }
+2
View File
@@ -14,6 +14,7 @@ class TeacherClass extends BaseModel
protected $fillable = [ protected $fillable = [
'teacher_id', 'teacher_id',
'class_section_id', 'class_section_id',
'semester',
'school_year', 'school_year',
'position', 'position',
'updated_by', 'updated_by',
@@ -404,6 +405,7 @@ class TeacherClass extends BaseModel
return [ return [
'teacher_id' => [$req, 'integer', 'min:1', 'exists:users,id'], 'teacher_id' => [$req, 'integer', 'min:1', 'exists:users,id'],
'class_section_id' => [$req, 'integer', 'min:1'], 'class_section_id' => [$req, 'integer', 'min:1'],
'semester' => [$req, 'string', 'max:25'],
'school_year' => [$req, 'string', 'max:9'], 'school_year' => [$req, 'string', 'max:9'],
'position' => [$req, 'string', 'in:' . implode(',', self::allowedPositions())], 'position' => [$req, 'string', 'in:' . implode(',', self::allowedPositions())],
'updated_by' => ['nullable', 'integer'], 'updated_by' => ['nullable', 'integer'],
@@ -114,6 +114,7 @@ class ScoreDashboardService
'homework' => $this->normalizeScore($scoreRow->homework_avg), 'homework' => $this->normalizeScore($scoreRow->homework_avg),
'quiz' => $this->normalizeScore($scoreRow->quiz_avg), 'quiz' => $this->normalizeScore($scoreRow->quiz_avg),
'project' => $this->normalizeScore($scoreRow->project_avg), 'project' => $this->normalizeScore($scoreRow->project_avg),
'participation' => $this->normalizeScore($scoreRow->participation_score),
'midterm_exam' => $this->normalizeScore($scoreRow->midterm_exam_score), 'midterm_exam' => $this->normalizeScore($scoreRow->midterm_exam_score),
'final_exam' => $this->normalizeScore($scoreRow->final_exam_score), 'final_exam' => $this->normalizeScore($scoreRow->final_exam_score),
'attendance' => $this->normalizeScore($scoreRow->attendance_score), 'attendance' => $this->normalizeScore($scoreRow->attendance_score),
@@ -125,6 +126,24 @@ class ScoreDashboardService
unset($student); unset($student);
$classSection = ClassSection::query()->where('class_section_id', $classSectionId)->first(); $classSection = ClassSection::query()->where('class_section_id', $classSectionId)->first();
$missingOkMap = [
'ptap_comment' => MissingScoreOverride::getOverridesMap($classSectionId, $semesterLabel, $schoolYear, 'ptap_comment'),
];
if (strtolower($semesterLabel) === 'fall') {
$missingOkMap['midterm_comment'] = MissingScoreOverride::getOverridesMap(
$classSectionId,
$semesterLabel,
$schoolYear,
'midterm_comment'
);
} elseif (strtolower($semesterLabel) === 'spring') {
$missingOkMap['final_comment'] = MissingScoreOverride::getOverridesMap(
$classSectionId,
$semesterLabel,
$schoolYear,
'final_comment'
);
}
return [ return [
'students' => $students, 'students' => $students,
@@ -133,6 +152,7 @@ class ScoreDashboardService
'semester' => $semesterLabel, 'semester' => $semesterLabel,
'school_year' => $schoolYear, 'school_year' => $schoolYear,
'scoresLocked' => GradingLock::isLocked($classSectionId, $semesterLabel, $schoolYear), 'scoresLocked' => GradingLock::isLocked($classSectionId, $semesterLabel, $schoolYear),
'missing_ok_map' => $missingOkMap,
]; ];
} }
@@ -16,6 +16,7 @@ class TeacherAssignmentService
{ {
$context = $this->configService->context(); $context = $this->configService->context();
$schoolYear = $schoolYear ?: (string) ($context['school_year'] ?? ''); $schoolYear = $schoolYear ?: (string) ($context['school_year'] ?? '');
$semester = trim((string) ($context['semester'] ?? ''));
$teachers = User::getTeachersAndTAs(); $teachers = User::getTeachersAndTAs();
$classSections = ClassSection::query() $classSections = ClassSection::query()
@@ -39,6 +40,7 @@ class TeacherAssignmentService
$assignments = TeacherClass::query() $assignments = TeacherClass::query()
->when($schoolYear !== '', fn ($q) => $q->where('school_year', $schoolYear)) ->when($schoolYear !== '', fn ($q) => $q->where('school_year', $schoolYear))
->when($semester !== '', fn ($q) => $q->where('semester', $semester))
->get() ->get()
->toArray(); ->toArray();
@@ -113,12 +115,13 @@ class TeacherAssignmentService
{ {
$context = $this->configService->context(); $context = $this->configService->context();
$schoolYear = (string) ($input['school_year'] ?? $context['school_year'] ?? ''); $schoolYear = (string) ($input['school_year'] ?? $context['school_year'] ?? '');
$semester = trim((string) ($input['semester'] ?? $context['semester'] ?? ''));
$teacherId = (int) ($input['teacher_id'] ?? 0); $teacherId = (int) ($input['teacher_id'] ?? 0);
$classSectionId = (int) ($input['class_section_id'] ?? 0); $classSectionId = (int) ($input['class_section_id'] ?? 0);
$teacherRole = (string) ($input['teacher_role'] ?? ''); $teacherRole = (string) ($input['teacher_role'] ?? '');
$loggedInUserId = (int) ($input['updated_by'] ?? 0); $loggedInUserId = (int) ($input['updated_by'] ?? 0);
if ($teacherId <= 0 || $classSectionId <= 0 || $schoolYear === '') { if ($teacherId <= 0 || $classSectionId <= 0 || $schoolYear === '' || $semester === '') {
return ['ok' => false, 'message' => 'Missing required parameters for assignment.']; return ['ok' => false, 'message' => 'Missing required parameters for assignment.'];
} }
@@ -132,6 +135,7 @@ class TeacherAssignmentService
->where('teacher_id', $teacherId) ->where('teacher_id', $teacherId)
->where('class_section_id', $classSectionId) ->where('class_section_id', $classSectionId)
->where('position', $position) ->where('position', $position)
->where('semester', $semester)
->where('school_year', $schoolYear) ->where('school_year', $schoolYear)
->first(); ->first();
@@ -143,6 +147,7 @@ class TeacherAssignmentService
'teacher_id' => $teacherId, 'teacher_id' => $teacherId,
'class_section_id' => $classSectionId, 'class_section_id' => $classSectionId,
'position' => $position, 'position' => $position,
'semester' => $semester,
'school_year' => $schoolYear, 'school_year' => $schoolYear,
'created_at' => now(), 'created_at' => now(),
'updated_at' => now(), 'updated_at' => now(),
@@ -162,15 +167,17 @@ class TeacherAssignmentService
$teacherId = (int) ($input['teacher_id'] ?? 0); $teacherId = (int) ($input['teacher_id'] ?? 0);
$classSectionId = (int) ($input['class_section_id'] ?? 0); $classSectionId = (int) ($input['class_section_id'] ?? 0);
$position = strtolower((string) ($input['position'] ?? '')); $position = strtolower((string) ($input['position'] ?? ''));
$semester = trim((string) ($input['semester'] ?? $context['semester'] ?? ''));
$schoolYear = trim((string) ($input['school_year'] ?? $context['school_year'] ?? '')); $schoolYear = trim((string) ($input['school_year'] ?? $context['school_year'] ?? ''));
if ($teacherId <= 0 || $classSectionId <= 0 || !in_array($position, ['main', 'ta'], true) || $schoolYear === '') { if ($teacherId <= 0 || $classSectionId <= 0 || !in_array($position, ['main', 'ta'], true) || $schoolYear === '' || $semester === '') {
return ['ok' => false, 'message' => 'Missing or invalid data for deletion.']; return ['ok' => false, 'message' => 'Missing or invalid data for deletion.'];
} }
$assignment = TeacherClass::query() $assignment = TeacherClass::query()
->where('teacher_id', $teacherId) ->where('teacher_id', $teacherId)
->where('class_section_id', $classSectionId) ->where('class_section_id', $classSectionId)
->where('semester', $semester)
->where('school_year', $schoolYear) ->where('school_year', $schoolYear)
->where('position', $position) ->where('position', $position)
->first(); ->first();
File diff suppressed because it is too large Load Diff
+6
View File
@@ -80,4 +80,10 @@ Route::middleware('web')->group(function () {
->name('teacher.calendar'); ->name('teacher.calendar');
Route::middleware('auth')->get('app/teacher/calendar', [TeacherCalendarPageController::class, 'show']) Route::middleware('auth')->get('app/teacher/calendar', [TeacherCalendarPageController::class, 'show'])
->name('app.teacher.calendar'); ->name('app.teacher.calendar');
Route::middleware('auth')->get('teacher/absence-vacation', function () {
return redirect('/app/teacher/absence-vacation');
})->name('teacher.absence-vacation');
Route::middleware('auth')->get('teacher/absence_vacation', function () {
return redirect('/app/teacher/absence-vacation');
})->name('teacher.absence_vacation');
}); });
@@ -19,7 +19,7 @@ class TeacherClassAssignmentControllerTest extends TestCase
$this->seedTeacherUser(); $this->seedTeacherUser();
$this->seedClassSection(); $this->seedClassSection();
Sanctum::actingAs($admin); Sanctum::actingAs($admin, [], 'api');
$response = $this->getJson('/api/v1/administrator/teacher-class/assignments?school_year=2025-2026'); $response = $this->getJson('/api/v1/administrator/teacher-class/assignments?school_year=2025-2026');
$response->assertOk(); $response->assertOk();
@@ -35,7 +35,7 @@ class TeacherClassAssignmentControllerTest extends TestCase
$teacher = $this->seedTeacherUser(); $teacher = $this->seedTeacherUser();
$classSectionId = $this->seedClassSection(); $classSectionId = $this->seedClassSection();
Sanctum::actingAs($admin); Sanctum::actingAs($admin, [], 'api');
$storeResponse = $this->postJson('/api/v1/administrator/teacher-class/assign', [ $storeResponse = $this->postJson('/api/v1/administrator/teacher-class/assign', [
'teacher_id' => $teacher->id, 'teacher_id' => $teacher->id,
'class_section_id' => $classSectionId, 'class_section_id' => $classSectionId,
@@ -48,6 +48,8 @@ class TeacherClassAssignmentControllerTest extends TestCase
'teacher_id' => $teacher->id, 'teacher_id' => $teacher->id,
'class_section_id' => $classSectionId, 'class_section_id' => $classSectionId,
'position' => 'main', 'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
]); ]);
$deleteResponse = $this->postJson('/api/v1/administrator/teacher-class/delete', [ $deleteResponse = $this->postJson('/api/v1/administrator/teacher-class/delete', [
@@ -62,6 +64,8 @@ class TeacherClassAssignmentControllerTest extends TestCase
'teacher_id' => $teacher->id, 'teacher_id' => $teacher->id,
'class_section_id' => $classSectionId, 'class_section_id' => $classSectionId,
'position' => 'main', 'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
]); ]);
} }
@@ -75,6 +79,12 @@ class TeacherClassAssignmentControllerTest extends TestCase
private function seedAdminUser(): User private function seedAdminUser(): User
{ {
$roleId = DB::table('roles')->insertGetId([
'name' => 'administrator',
'slug' => 'administrator',
'is_active' => 1,
]);
$userId = DB::table('users')->insertGetId([ $userId = DB::table('users')->insertGetId([
'firstname' => 'Admin', 'firstname' => 'Admin',
'lastname' => 'User', 'lastname' => 'User',
@@ -92,6 +102,11 @@ class TeacherClassAssignmentControllerTest extends TestCase
'status' => 'Active', 'status' => 'Active',
]); ]);
DB::table('user_roles')->insert([
'user_id' => $userId,
'role_id' => $roleId,
]);
return User::query()->findOrFail($userId); return User::query()->findOrFail($userId);
} }
@@ -0,0 +1,45 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Encryption\Encrypter;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class TeacherAbsenceVacationRouteTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
$key = 'base64:'.base64_encode(random_bytes(32));
config([
'app.key' => $key,
'app.cipher' => 'aes-256-cbc',
]);
$rawKey = base64_decode(substr($key, 7), true);
$this->app->instance('encrypter', new Encrypter($rawKey, 'aes-256-cbc'));
}
public function test_authenticated_teacher_absence_vacation_route_redirects_to_spa_page(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->get('/teacher/absence-vacation');
$response->assertRedirect('/app/teacher/absence-vacation');
}
public function test_authenticated_legacy_teacher_absence_vacation_route_redirects_to_spa_page(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->get('/teacher/absence_vacation');
$response->assertRedirect('/app/teacher/absence-vacation');
}
}
@@ -30,6 +30,8 @@ class TeacherAssignmentServiceTest extends TestCase
'teacher_id' => $teacherId, 'teacher_id' => $teacherId,
'class_section_id' => $classSectionId, 'class_section_id' => $classSectionId,
'position' => 'main', 'position' => 'main',
'semester' => 'Fall',
'school_year' => '2025-2026',
]); ]);
} }
@@ -43,6 +45,7 @@ class TeacherAssignmentServiceTest extends TestCase
'teacher_id' => $teacherId, 'teacher_id' => $teacherId,
'class_section_id' => $classSectionId, 'class_section_id' => $classSectionId,
'position' => 'ta', 'position' => 'ta',
'semester' => 'Fall',
'school_year' => '2025-2026', 'school_year' => '2025-2026',
'created_at' => now(), 'created_at' => now(),
'updated_at' => now(), 'updated_at' => now(),
@@ -60,6 +63,8 @@ class TeacherAssignmentServiceTest extends TestCase
'teacher_id' => $teacherId, 'teacher_id' => $teacherId,
'class_section_id' => $classSectionId, 'class_section_id' => $classSectionId,
'position' => 'ta', 'position' => 'ta',
'semester' => 'Fall',
'school_year' => '2025-2026',
]); ]);
} }