apps/recallassess/recallassess-api/src/api/admin/knowledge-review/services/knowledge-review.service.ts
BNestBaseModuleService
Methods |
|
constructor(prisma: BNestPrismaService, systemLogService: SystemLogService)
|
|||||||||
|
Parameters :
|
| Async add | ||||||
add(data: any)
|
||||||
|
Override add method to prevent creation when course has enrollments
Parameters :
Returns :
unknown
|
| Private Async checkCourseEnrollments | |||||||||
checkCourseEnrollments(courseId: number | null, knowledgeReviewId?: number)
|
|||||||||
|
Check if the associated course has enrollments Also checks if knowledge review is used in course module pages for courses with enrollments
Parameters :
Returns :
Promise<void>
|
| Async delete | ||||||
delete(id: number)
|
||||||
|
Override delete method to prevent deletion when course has enrollments
Parameters :
Returns :
Promise<void>
|
| Async save |
save(id: number, data: any)
|
|
Override save method to prevent modifications when course has enrollments
Returns :
Promise<SaveResponseDataInterface<any>>
|
import { BNestBaseModuleService } from "@bish-nest/core/data/module-service/base-module.service";
import { BNestPrismaService } from "@bish-nest/core/services";
import { SystemLogService } from "@api/shared/services";
import { SaveResponseDataInterface } from "@bish-nest/core/interfaces/save-response-data.interface";
import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common";
import { SystemLogEntityType } from "@prisma/client";
import { plainToInstance } from "class-transformer";
@Injectable()
export class KnowledgeReviewService extends BNestBaseModuleService {
constructor(
protected prisma: BNestPrismaService,
private readonly systemLogService: SystemLogService,
) {
super();
}
/**
* Check if the associated course has enrollments
* Also checks if knowledge review is used in course module pages for courses with enrollments
*/
private async checkCourseEnrollments(courseId: number | null, knowledgeReviewId?: number): Promise<void> {
// If course_id is provided, check that course
if (courseId) {
const enrollmentCount = await this.prisma.client.learningGroupParticipant.count({
where: {
course_id: courseId,
},
});
if (enrollmentCount > 0) {
throw new BadRequestException(
`Cannot modify knowledge review. The associated course has ${enrollmentCount} enrolled participant(s). Knowledge reviews for courses with enrollments cannot be modified or deleted.`,
);
}
}
// Also check if this knowledge review is used in any course module pages
if (knowledgeReviewId) {
const courseModulePages = await this.prisma.client.courseModulePage.findMany({
where: {
knowledge_review_id: knowledgeReviewId,
},
select: {
course_id: true,
},
});
for (const page of courseModulePages) {
const pageEnrollmentCount = await this.prisma.client.learningGroupParticipant.count({
where: {
course_id: page.course_id,
},
});
if (pageEnrollmentCount > 0) {
throw new BadRequestException(
`Cannot modify knowledge review. This knowledge review is used in course module pages for a course with ${pageEnrollmentCount} enrolled participant(s). Knowledge reviews for courses with enrollments cannot be modified or deleted.`,
);
}
}
}
}
/**
* Override add method to prevent creation when course has enrollments
*/
async add(data: any) {
// Check if course_id is provided in the data
const courseId = data.course_id || data.course?.id || null;
if (courseId) {
await this.checkCourseEnrollments(courseId);
}
const repo = this.commonMethods.getRepo(this.gVars.moduleCurrentCfg.repoName);
let dataAdd = plainToInstance(this.gVars.moduleCurrentCfg.addDto, data);
// Use scalar audit columns to avoid relation create errors
dataAdd = await this.dbUtilService.addCreatedById(dataAdd);
const newRow = await repo.create({ data: dataAdd });
const addResponse = this.moduleMethods.getReturnDataForAdd(newRow);
// Log the creation
await this.systemLogService.logInsert(
SystemLogEntityType.KNOWLEDGE_REVIEW,
newRow.id,
newRow as Record<string, unknown>,
);
return addResponse;
}
/**
* Override save method to prevent modifications when course has enrollments
*/
async save(id: number, data: any): Promise<SaveResponseDataInterface<any>> {
// Get old data before update
const oldKnowledgeReview = await this.prisma.client.knowledgeReview.findUnique({
where: { id },
});
if (!oldKnowledgeReview) {
throw new NotFoundException(`Knowledge review with ID ${id} not found`);
}
// Check if the associated course has enrollments and if used in pages
await this.checkCourseEnrollments(oldKnowledgeReview.course_id, id);
// Also check if the course_id is being changed in the update data
const courseId = data.course_id !== undefined ? (data.course_id || data.course?.id || null) : null;
if (courseId !== null && courseId !== oldKnowledgeReview.course_id) {
await this.checkCourseEnrollments(courseId, id);
}
const repo = this.commonMethods.getRepo(this.gVars.moduleCurrentCfg.repoName);
let dataSave = plainToInstance(this.gVars.moduleCurrentCfg.saveDto, data);
// Use scalar audit columns to avoid relation update errors
dataSave = await this.dbUtilService.addUpdatedById(dataSave);
await repo.update({ where: { id }, data: dataSave });
// Get updated data directly from database for logging
const updatedKnowledgeReview = await this.prisma.client.knowledgeReview.findUnique({
where: { id },
});
if (!updatedKnowledgeReview) {
throw new NotFoundException(`Knowledge review with ID ${id} not found after update`);
}
// Calculate changed fields and log the update
const changedFields = SystemLogService.calculateChangedFields(
oldKnowledgeReview as Record<string, unknown>,
updatedKnowledgeReview as Record<string, unknown>,
);
await this.systemLogService.logUpdate(
SystemLogEntityType.KNOWLEDGE_REVIEW,
id,
oldKnowledgeReview as Record<string, unknown>,
updatedKnowledgeReview as Record<string, unknown>,
changedFields,
);
return await this.getDetail(id);
}
/**
* Override delete method to prevent deletion when course has enrollments
*/
async delete(id: number): Promise<void> {
// Get knowledge review data before deletion
const knowledgeReview = await this.prisma.client.knowledgeReview.findUnique({
where: { id },
});
if (!knowledgeReview) {
throw new NotFoundException(`Knowledge review with ID ${id} not found`);
}
// Check if the associated course has enrollments and if used in pages
await this.checkCourseEnrollments(knowledgeReview.course_id, id);
// Call parent delete method
await super.delete(id);
// Log the deletion
await this.systemLogService.logDelete(
SystemLogEntityType.KNOWLEDGE_REVIEW,
id,
knowledgeReview as Record<string, unknown>,
);
}
}