Spaces:
Sleeping
Sleeping
| import { | |
| Controller, | |
| Get, | |
| Post, | |
| Put, | |
| Delete, | |
| Body, | |
| Param, | |
| Query, | |
| Req, | |
| UseGuards, | |
| ParseIntPipe, | |
| HttpCode, | |
| HttpStatus, | |
| } from '@nestjs/common'; | |
| import { | |
| ApiTags, | |
| ApiOperation, | |
| ApiParam, | |
| ApiBody, | |
| ApiResponse, | |
| ApiBearerAuth, | |
| } from '@nestjs/swagger'; | |
| import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard'; | |
| import { RolesGuard } from '../../auth/guards/roles.guard'; | |
| import { Roles } from '../../auth/roles.decorator'; | |
| import { RoleName } from '../../auth/entities/role.entity'; | |
| import { ExamScheduleService } from '../services'; | |
| import { | |
| CreateExamScheduleDto, | |
| UpdateExamScheduleDto, | |
| QueryExamScheduleDto, | |
| } from '../dto'; | |
| ('📝 Exam Schedules') | |
| ('JWT-auth') | |
| ('api/exams/schedule') | |
| (JwtAuthGuard, RolesGuard) | |
| export class ExamScheduleController { | |
| constructor(private readonly examService: ExamScheduleService) {} | |
| () | |
| ({ | |
| summary: 'List exam schedules', | |
| description: ` | |
| ## List Exam Schedules | |
| Returns paginated list of exam schedules with optional filtering. | |
| ### Access Control | |
| - **Authentication Required**: ✅ Yes (Bearer Token) | |
| - **Roles**: ALL (filtered by role) | |
| ### Role-Based Filtering | |
| - **Students**: See exams for enrolled courses only | |
| - **Instructors**: See exams for courses they teach | |
| - **TAs**: See exams for courses they assist | |
| - **Admins**: See all exam schedules | |
| ### Query Parameters | |
| - \`courseId\`: Filter by course | |
| - \`semesterId\`: Filter by semester | |
| - \`examType\`: Filter by type (midterm, final, quiz, makeup) | |
| - \`fromDate\`: Filter from date | |
| - \`toDate\`: Filter until date | |
| `, | |
| }) | |
| ({ status: 200, description: 'Paginated list of exam schedules' }) | |
| ({ status: 401, description: 'Unauthorized' }) | |
| async findAll(() query: QueryExamScheduleDto, () req: any) { | |
| const userId = req.user.userId || req.user.id; | |
| const roles = this.extractRoles(req.user); | |
| return this.examService.findAll(query, userId, roles); | |
| } | |
| ('conflicts') | |
| (RoleName.ADMIN, RoleName.IT_ADMIN) | |
| ({ | |
| summary: 'Check exam conflicts', | |
| description: ` | |
| ## Check Exam Conflicts | |
| Identifies overlapping exam schedules that could affect students enrolled in multiple courses. | |
| ### Access Control | |
| - **Authentication Required**: ✅ Yes (Bearer Token) | |
| - **Roles**: ADMIN, IT_ADMIN only | |
| ### Use Cases | |
| - Identify scheduling conflicts before finalizing exam dates | |
| - Generate conflict reports for academic planning | |
| `, | |
| }) | |
| ({ status: 200, description: 'List of conflicting exam schedules' }) | |
| ({ status: 401, description: 'Unauthorized' }) | |
| ({ status: 403, description: 'Forbidden - Admin role required' }) | |
| async checkConflicts( | |
| ('courseId') courseId?: number, | |
| ('semesterId') semesterId?: number, | |
| ) { | |
| return this.examService.checkExamConflicts(courseId, semesterId); | |
| } | |
| (':id') | |
| ({ | |
| summary: 'Get exam schedule by ID', | |
| description: ` | |
| ## Get Exam Details | |
| Returns detailed information about a specific exam schedule. | |
| ### Access Control | |
| - **Authentication Required**: ✅ Yes (Bearer Token) | |
| - **Roles**: ALL | |
| `, | |
| }) | |
| ({ name: 'id', description: 'Exam schedule ID', type: Number, example: 1 }) | |
| ({ status: 200, description: 'Exam schedule details' }) | |
| ({ status: 404, description: 'Exam schedule not found' }) | |
| async findById(('id', ParseIntPipe) id: number, () req: any) { | |
| const userId = req.user.userId || req.user.id; | |
| const roles = this.extractRoles(req.user); | |
| return this.examService.findById(id, userId, roles); | |
| } | |
| () | |
| (RoleName.INSTRUCTOR, RoleName.ADMIN, RoleName.IT_ADMIN) | |
| (HttpStatus.CREATED) | |
| ({ | |
| summary: 'Create exam schedule', | |
| description: ` | |
| ## Create New Exam Schedule | |
| Creates a new exam schedule for a course. | |
| ### Access Control | |
| - **Authentication Required**: ✅ Yes (Bearer Token) | |
| - **Roles**: INSTRUCTOR, ADMIN only | |
| ### Conflict Detection | |
| The system automatically checks for: | |
| - Same location/time conflicts | |
| - Overlapping exam times | |
| ### Required Fields | |
| - \`courseId\`: Course ID | |
| - \`semesterId\`: Semester ID | |
| - \`examType\`: Type of exam | |
| - \`examDate\`: Date of exam | |
| - \`startTime\`: Start time | |
| - \`durationMinutes\`: Duration in minutes | |
| `, | |
| }) | |
| ({ type: CreateExamScheduleDto }) | |
| ({ status: 201, description: 'Exam schedule created successfully' }) | |
| ({ status: 400, description: 'Invalid input data' }) | |
| ({ status: 403, description: 'Forbidden - Instructor/Admin role required' }) | |
| ({ status: 409, description: 'Exam schedule conflict' }) | |
| async create(() dto: CreateExamScheduleDto, () req: any) { | |
| const userId = req.user.userId || req.user.id; | |
| const roles = this.extractRoles(req.user); | |
| return this.examService.create(dto, userId, roles); | |
| } | |
| (':id') | |
| (RoleName.INSTRUCTOR, RoleName.ADMIN, RoleName.IT_ADMIN) | |
| ({ | |
| summary: 'Update exam schedule', | |
| description: ` | |
| ## Update Exam Schedule | |
| Updates an existing exam schedule. | |
| ### Access Control | |
| - **Authentication Required**: ✅ Yes (Bearer Token) | |
| - **Roles**: INSTRUCTOR (own courses), ADMIN | |
| ### Conflict Detection | |
| If date/time changes, conflict detection is re-run. | |
| `, | |
| }) | |
| ({ name: 'id', description: 'Exam schedule ID', type: Number, example: 1 }) | |
| ({ type: UpdateExamScheduleDto }) | |
| ({ status: 200, description: 'Exam schedule updated successfully' }) | |
| ({ status: 404, description: 'Exam schedule not found' }) | |
| ({ status: 403, description: 'Forbidden' }) | |
| ({ status: 409, description: 'Exam schedule conflict' }) | |
| async update( | |
| ('id', ParseIntPipe) id: number, | |
| () dto: UpdateExamScheduleDto, | |
| () req: any, | |
| ) { | |
| const userId = req.user.userId || req.user.id; | |
| const roles = this.extractRoles(req.user); | |
| return this.examService.update(id, dto, userId, roles); | |
| } | |
| (':id') | |
| (RoleName.INSTRUCTOR, RoleName.ADMIN, RoleName.IT_ADMIN) | |
| (HttpStatus.OK) | |
| ({ | |
| summary: 'Delete exam schedule', | |
| description: ` | |
| ## Delete Exam Schedule | |
| Removes an exam schedule from the system. | |
| ### Access Control | |
| - **Authentication Required**: ✅ Yes (Bearer Token) | |
| - **Roles**: INSTRUCTOR (own courses), ADMIN | |
| `, | |
| }) | |
| ({ name: 'id', description: 'Exam schedule ID', type: Number, example: 1 }) | |
| ({ status: 200, description: 'Exam schedule deleted successfully' }) | |
| ({ status: 404, description: 'Exam schedule not found' }) | |
| ({ status: 403, description: 'Forbidden' }) | |
| async delete(('id', ParseIntPipe) id: number, () req: any) { | |
| const userId = req.user.userId || req.user.id; | |
| const roles = this.extractRoles(req.user); | |
| return this.examService.delete(id, userId, roles); | |
| } | |
| private extractRoles(user: any): string[] { | |
| if (Array.isArray(user.roles)) { | |
| return user.roles.map((r: any) => (typeof r === 'string' ? r : r.name || r.roleName)); | |
| } | |
| return []; | |
| } | |
| } | |