apps/recallassess/recallassess-api/src/api/admin/course/config/course-config.service.ts
ModuleConfigBase
Properties |
|
Methods |
|
| getConfiguration |
getConfiguration()
|
|
Returns :
ModuleConfig
|
| Private Async validateCourseDeletion | ||||||
validateCourseDeletion(courseId: number)
|
||||||
|
Validates that a course can be deleted Throws an error if the course has enrolled participants
Parameters :
Returns :
Promise<void>
|
| Private prisma |
Type : BNestPrismaService
|
Decorators :
@Inject()
|
import { ColumnConfig, ColumnType } from "@bish-nest/core/app-config/column-config.class";
import { MediaConfig } from "@bish-nest/core/app-config/media-config.class";
import { ModuleConfig } from "@bish-nest/core/app-config/module-config.class";
import { ModuleConfigBase } from "@bish-nest/core/app-config/module-config-base.class";
import { BNestPrismaService } from "@bish-nest/core/services/database/prisma/prisma.service";
import { BadRequestException, Inject, Injectable } from "@nestjs/common";
import { MediaName, MediaType } from "@prisma/client";
import { CourseAddDto } from "../dto/course-add.dto";
import { CourseDetailDto } from "../dto/course-detail.dto";
import { CourseListDto } from "../dto/course-list.dto";
import { CourseListSimpleDto } from "../dto/course-list-simple.dto";
import { CourseSaveDto } from "../dto/course-save.dto";
import { courseLinks } from "./course-links-config.service";
@Injectable()
export class CourseConfig extends ModuleConfigBase {
@Inject() private prisma!: BNestPrismaService;
getConfiguration(): ModuleConfig {
const columns: ColumnConfig[] = [
new ColumnConfig({ name: "id", type: ColumnType.Integer }),
new ColumnConfig({ name: "course_code" }),
new ColumnConfig({ name: "title" }),
new ColumnConfig({ name: "course_code_title" }),
new ColumnConfig({ name: "description" }),
new ColumnConfig({ name: "short_description" }),
new ColumnConfig({ name: "category" }),
new ColumnConfig({ name: "level" }),
new ColumnConfig({ name: "assessment_id", type: ColumnType.Integer }),
new ColumnConfig({ name: "knowledge_review_id", type: ColumnType.Integer }),
new ColumnConfig({ name: "is_published", type: ColumnType.Boolean }),
new ColumnConfig({ name: "is_featured", type: ColumnType.Boolean }),
new ColumnConfig({ name: "skip_hundred_dj", type: ColumnType.Boolean }),
new ColumnConfig({ name: "created_at", type: ColumnType.DateTime }),
new ColumnConfig({ name: "updated_at", type: ColumnType.DateTime }),
];
const mediaArr: MediaConfig[] = [
new MediaConfig({
name: MediaName.COURSE__IMAGE,
mediaRelationName: "mediaImages",
mediaRelationObj: {
mediaImages: {
where: { media_type: MediaType.IMAGE, media_name: MediaName.COURSE__IMAGE },
},
},
mediaRelationFromMediaTable: "courseMediaImages",
}),
new MediaConfig({
name: "COURSE__DETAIL_PDF" as MediaName,
mediaRelationName: "courseDetailPdfDocuments",
mediaRelationObj: {
courseDetailPdfDocuments: {
where: { media_type: MediaType.DOCUMENT, media_name: "COURSE__DETAIL_PDF" as MediaName },
},
},
mediaRelationFromMediaTable: "courseDetailPdfDocuments",
isPublic: true,
maxFiles: 1,
}),
new MediaConfig({
name: "COURSE__TESTIMONIALS_PDF" as MediaName,
mediaRelationName: "testimonialsPdfDocuments",
mediaRelationObj: {
testimonialsPdfDocuments: {
where: { media_type: MediaType.DOCUMENT, media_name: "COURSE__TESTIMONIALS_PDF" as MediaName },
},
},
mediaRelationFromMediaTable: "courseTestimonialsPdfDocuments",
isPublic: true,
maxFiles: 1,
}),
// Note: hundredDjEmail*Documents relations don't exist in Prisma Course model
// These are handled separately via direct Media queries, not as Prisma includes
// Keeping them in mediaArr for S3 URL prefix processing, but with empty relationObj
new MediaConfig({
name: "COURSE__HUNDRED_DJ_EMAIL1" as MediaName,
mediaRelationName: "hundredDjEmail1Documents",
mediaRelationObj: {
hundredDjEmail1Documents: {
where: { media_type: MediaType.DOCUMENT, media_name: MediaName.COURSE__HUNDRED_DJ_EMAIL1 },
},
},
mediaRelationFromMediaTable: "courseHundredDjEmail1Documents",
}),
new MediaConfig({
name: "COURSE__HUNDRED_DJ_EMAIL2" as MediaName,
mediaRelationName: "hundredDjEmail2Documents",
mediaRelationObj: {
hundredDjEmail2Documents: {
where: { media_type: MediaType.DOCUMENT, media_name: MediaName.COURSE__HUNDRED_DJ_EMAIL2 },
},
},
mediaRelationFromMediaTable: "courseHundredDjEmail2Documents",
}),
new MediaConfig({
name: "COURSE__HUNDRED_DJ_EMAIL3" as MediaName,
mediaRelationName: "hundredDjEmail3Documents",
mediaRelationObj: {
hundredDjEmail3Documents: {
where: { media_type: MediaType.DOCUMENT, media_name: MediaName.COURSE__HUNDRED_DJ_EMAIL3 },
},
},
mediaRelationFromMediaTable: "courseHundredDjEmail3Documents",
}),
new MediaConfig({
name: "COURSE__HUNDRED_DJ_EMAIL4" as MediaName,
mediaRelationName: "hundredDjEmail4Documents",
mediaRelationObj: {
hundredDjEmail4Documents: {
where: { media_type: MediaType.DOCUMENT, media_name: MediaName.COURSE__HUNDRED_DJ_EMAIL4 },
},
},
mediaRelationFromMediaTable: "courseHundredDjEmail4Documents",
}),
];
return new ModuleConfig({
name: "course",
columns,
// Allow searching by numeric id in the list keyword box (e.g. "11")
keywordSearchCols: ["id", "course_code", "title", "description", "short_description", "category"],
mediaArr,
relationObjToIncludeForDetail: {
assessment: true,
knowledgeReview: true,
// Note: hundredDjEmail*Documents are handled via mediaArr configuration and loaded separately
// in CourseService.getDetail() to avoid Prisma relation errors and reduce API calls
// Note: courseModules and learningGroupParticipants are not included here
// because counts are calculated efficiently using count queries in CourseService.getDetail()
userCreatedBy: true,
userUpdatedBy: true,
},
listDto: CourseListDto,
detailDto: CourseDetailDto,
addDto: CourseAddDto,
saveDto: CourseSaveDto,
simpleDto: CourseListSimpleDto,
deleteValidation: this.validateCourseDeletion.bind(this),
links: courseLinks,
});
}
/**
* Validates that a course can be deleted
* Throws an error if the course has enrolled participants
*/
private async validateCourseDeletion(courseId: number): Promise<void> {
// Check if there are any enrollments for this course
const enrollmentCount = await this.prisma.client.learningGroupParticipant.count({
where: {
course_id: courseId,
},
});
if (enrollmentCount > 0) {
throw new BadRequestException(
`Cannot delete course. This course has ${enrollmentCount} enrolled participant(s). Courses with enrollments cannot be deleted.`,
);
}
}
}