eduverse-backend / src /modules /schedule /controllers /exam-schedule.controller.ts
amirhamdi's picture
all works courses materials and structures fixed all done
3058aa3
Raw
History Blame Contribute Delete
7.2 kB
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';
@ApiTags('📝 Exam Schedules')
@ApiBearerAuth('JWT-auth')
@Controller('api/exams/schedule')
@UseGuards(JwtAuthGuard, RolesGuard)
export class ExamScheduleController {
constructor(private readonly examService: ExamScheduleService) {}
@Get()
@ApiOperation({
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
`,
})
@ApiResponse({ status: 200, description: 'Paginated list of exam schedules' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
async findAll(@Query() query: QueryExamScheduleDto, @Req() req: any) {
const userId = req.user.userId || req.user.id;
const roles = this.extractRoles(req.user);
return this.examService.findAll(query, userId, roles);
}
@Get('conflicts')
@Roles(RoleName.ADMIN, RoleName.IT_ADMIN)
@ApiOperation({
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
`,
})
@ApiResponse({ status: 200, description: 'List of conflicting exam schedules' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
@ApiResponse({ status: 403, description: 'Forbidden - Admin role required' })
async checkConflicts(
@Query('courseId') courseId?: number,
@Query('semesterId') semesterId?: number,
) {
return this.examService.checkExamConflicts(courseId, semesterId);
}
@Get(':id')
@ApiOperation({
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
`,
})
@ApiParam({ name: 'id', description: 'Exam schedule ID', type: Number, example: 1 })
@ApiResponse({ status: 200, description: 'Exam schedule details' })
@ApiResponse({ status: 404, description: 'Exam schedule not found' })
async findById(@Param('id', ParseIntPipe) id: number, @Req() req: any) {
const userId = req.user.userId || req.user.id;
const roles = this.extractRoles(req.user);
return this.examService.findById(id, userId, roles);
}
@Post()
@Roles(RoleName.INSTRUCTOR, RoleName.ADMIN, RoleName.IT_ADMIN)
@HttpCode(HttpStatus.CREATED)
@ApiOperation({
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
`,
})
@ApiBody({ type: CreateExamScheduleDto })
@ApiResponse({ status: 201, description: 'Exam schedule created successfully' })
@ApiResponse({ status: 400, description: 'Invalid input data' })
@ApiResponse({ status: 403, description: 'Forbidden - Instructor/Admin role required' })
@ApiResponse({ status: 409, description: 'Exam schedule conflict' })
async create(@Body() dto: CreateExamScheduleDto, @Req() req: any) {
const userId = req.user.userId || req.user.id;
const roles = this.extractRoles(req.user);
return this.examService.create(dto, userId, roles);
}
@Put(':id')
@Roles(RoleName.INSTRUCTOR, RoleName.ADMIN, RoleName.IT_ADMIN)
@ApiOperation({
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.
`,
})
@ApiParam({ name: 'id', description: 'Exam schedule ID', type: Number, example: 1 })
@ApiBody({ type: UpdateExamScheduleDto })
@ApiResponse({ status: 200, description: 'Exam schedule updated successfully' })
@ApiResponse({ status: 404, description: 'Exam schedule not found' })
@ApiResponse({ status: 403, description: 'Forbidden' })
@ApiResponse({ status: 409, description: 'Exam schedule conflict' })
async update(
@Param('id', ParseIntPipe) id: number,
@Body() dto: UpdateExamScheduleDto,
@Req() req: any,
) {
const userId = req.user.userId || req.user.id;
const roles = this.extractRoles(req.user);
return this.examService.update(id, dto, userId, roles);
}
@Delete(':id')
@Roles(RoleName.INSTRUCTOR, RoleName.ADMIN, RoleName.IT_ADMIN)
@HttpCode(HttpStatus.OK)
@ApiOperation({
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
`,
})
@ApiParam({ name: 'id', description: 'Exam schedule ID', type: Number, example: 1 })
@ApiResponse({ status: 200, description: 'Exam schedule deleted successfully' })
@ApiResponse({ status: 404, description: 'Exam schedule not found' })
@ApiResponse({ status: 403, description: 'Forbidden' })
async delete(@Param('id', ParseIntPipe) id: number, @Req() 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 [];
}
}