apps/recallassess/recallassess-api/src/api/admin/knowledge-review/services/knowledge-review-question.service.ts
Methods |
|
constructor(prisma: BNestPrismaService)
|
||||||
|
Parameters :
|
| Async addQuestion | |||||||||
addQuestion(addQuestionDto: KnowledgeReviewQuestionAddDto, knowledgeReviewId: number)
|
|||||||||
|
Parameters :
Returns :
Promise<KnowledgeReviewQuestionDto>
|
| Private Async checkCourseEnrollments | ||||||
checkCourseEnrollments(courseId: number)
|
||||||
|
Check if the associated course has enrollments
Parameters :
Returns :
Promise<void>
|
| Async deleteQuestion | ||||||
deleteQuestion(knowledge_review_question_id: number)
|
||||||
|
Parameters :
Returns :
Promise<void>
|
| Async getQuestionsByKnowledgeReview | ||||||
getQuestionsByKnowledgeReview(knowledgeReviewId: number)
|
||||||
|
Parameters :
|
| Async reorderQuestions | ||||||
reorderQuestions(questions: literal type[])
|
||||||
|
Parameters :
Returns :
Promise<void>
|
| Async saveQuestion | |||||||||
saveQuestion(knowledgeReviewQuestionId: number, updateQuestionDto: KnowledgeReviewQuestionSaveDto)
|
|||||||||
|
Parameters :
Returns :
Promise<KnowledgeReviewQuestionDto>
|
import { BNestPrismaService } from "@bish-nest/core/services/database/prisma/prisma.service";
import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common";
import { plainToInstance } from "class-transformer";
import { KnowledgeReviewQuestionDto } from "../dto/quiz/knowledge-review-question.dto";
import { KnowledgeReviewQuestionAddDto } from "../dto/quiz/knowledge-review-question-add.dto";
import { KnowledgeReviewQuestionListDto } from "../dto/quiz/knowledge-review-question-list.dto";
import { KnowledgeReviewQuestionSaveDto } from "../dto/quiz/knowledge-review-question-save.dto";
@Injectable()
export class KnowledgeReviewQuestionService {
constructor(private readonly prisma: BNestPrismaService) {}
/**
* Check if the associated course has enrollments
*/
private async checkCourseEnrollments(courseId: number): Promise<void> {
const enrollmentCount = await this.prisma.client.learningGroupParticipant.count({
where: {
course_id: courseId,
},
});
if (enrollmentCount > 0) {
throw new BadRequestException(
`Cannot modify knowledge review question. The associated course has ${enrollmentCount} enrolled participant(s). Knowledge review questions for courses with enrollments cannot be modified or deleted.`,
);
}
}
async getQuestionsByKnowledgeReview(knowledgeReviewId: number): Promise<KnowledgeReviewQuestionListDto[]> {
const questions = await this.prisma.client.knowledgeReviewQuestion.findMany({
where: { knowledge_review_id: knowledgeReviewId },
include: {
knowledgeReviewAnswers: {
orderBy: { sort_order: "asc" },
},
},
orderBy: { sort_order: "asc" },
});
// Map knowledgeReviewAnswers to answers for the DTO
const questionsWithAnswers = questions.map((question) => ({
...question,
answers: question.knowledgeReviewAnswers,
}));
return plainToInstance(KnowledgeReviewQuestionListDto, questionsWithAnswers, { excludeExtraneousValues: true });
}
async addQuestion(
addQuestionDto: KnowledgeReviewQuestionAddDto,
knowledgeReviewId: number,
): Promise<KnowledgeReviewQuestionDto> {
// Check if course has enrollments before adding question
if (addQuestionDto.course_id) {
await this.checkCourseEnrollments(addQuestionDto.course_id);
}
// Compute next sort_order = (max sort_order for this knowledge review) + 1
let nextSortOrder = 0;
if (knowledgeReviewId !== undefined) {
const agg = await this.prisma.client.knowledgeReviewQuestion.aggregate({
where: { knowledge_review_id: knowledgeReviewId },
_max: { sort_order: true },
});
nextSortOrder = ((agg._max?.sort_order as number | null) ?? -1) + 1;
}
addQuestionDto.sort_order = addQuestionDto.sort_order ?? nextSortOrder;
const question = await this.prisma.client.knowledgeReviewQuestion.create({
data: {
course_id: addQuestionDto.course_id,
knowledge_review_id: knowledgeReviewId,
question_text: addQuestionDto.question_text,
question_type: (addQuestionDto.question_type as any) || "MULTIPLE_CHOICE",
sort_order: addQuestionDto.sort_order,
},
});
return plainToInstance(KnowledgeReviewQuestionDto, question, { excludeExtraneousValues: true });
}
async saveQuestion(
knowledgeReviewQuestionId: number,
updateQuestionDto: KnowledgeReviewQuestionSaveDto,
): Promise<KnowledgeReviewQuestionDto> {
const existingQuestion = await this.prisma.client.knowledgeReviewQuestion.findUnique({
where: { id: knowledgeReviewQuestionId },
});
if (!existingQuestion) {
throw new NotFoundException(`Knowledge review question with ID ${knowledgeReviewQuestionId} not found`);
}
// Check if course has enrollments before saving
await this.checkCourseEnrollments(existingQuestion.course_id);
const question = await this.prisma.client.knowledgeReviewQuestion.update({
where: { id: knowledgeReviewQuestionId },
data: {
question_text: updateQuestionDto.question_text,
question_type: updateQuestionDto.question_type as any,
sort_order: updateQuestionDto.sort_order,
},
include: {
knowledgeReviewAnswers: true,
},
});
return plainToInstance(KnowledgeReviewQuestionDto, question, { excludeExtraneousValues: true });
}
async deleteQuestion(knowledge_review_question_id: number): Promise<void> {
const existingQuestion = await this.prisma.client.knowledgeReviewQuestion.findUnique({
where: { id: knowledge_review_question_id },
});
if (!existingQuestion) {
throw new NotFoundException(`Knowledge review question with ID ${knowledge_review_question_id} not found`);
}
// Check if course has enrollments before deleting
await this.checkCourseEnrollments(existingQuestion.course_id);
// Delete associated knowledge review results first
await this.prisma.client.knowledgeReviewResult.deleteMany({
where: { knowledge_review_question_id: knowledge_review_question_id },
});
// Delete associated answers
await this.prisma.client.knowledgeReviewAnswer.deleteMany({
where: { knowledge_review_question_id: knowledge_review_question_id },
});
// Delete the question
await this.prisma.client.knowledgeReviewQuestion.delete({
where: { id: knowledge_review_question_id },
});
}
async reorderQuestions(questions: { id: number; sort_order: number }[]): Promise<void> {
// Check enrollments for all questions being reordered
if (questions.length > 0) {
const firstQuestion = await this.prisma.client.knowledgeReviewQuestion.findUnique({
where: { id: questions[0].id },
});
if (firstQuestion) {
await this.checkCourseEnrollments(firstQuestion.course_id);
}
}
const updatePromises = questions.map((question) =>
this.prisma.client.knowledgeReviewQuestion.update({
where: { id: question.id },
data: { sort_order: question.sort_order },
}),
);
await Promise.all(updatePromises);
}
}