import { HttpCodes } from '../../config/Errors'; import { db } from '../../settings'; import { ResultSetHeader } from 'mysql2'; import { ErrorResponseC, SuccessResponseC } from '../services.response'; import courseLogs, { ICourseLogs, courseLogger } from './course.logs'; import { formatString } from '../../utils/Strings'; import { VideoServices } from './video.service'; import { DocumentServices } from './document.service'; export class ChapterServices { static createChapter = async ( course_id: number, chapter: ChapterI ): Promise => { try { const sqlInsertQuery = 'INSERT INTO chapters (course_id, title, position) VALUES (?, ?, ?)'; const [result]: any = await db.query(sqlInsertQuery, [ course_id, chapter.title, chapter.position, ]); const chapterId = result.insertId; const resp: ICode = courseLogs.CREATE_CHAPTER_SUCCESS; const msg = formatString(resp.message, { chapterId, }); courseLogger.info(msg, { type: resp.type }); return new SuccessResponseC(resp.type, {}, msg, HttpCodes.Created.code); } catch (err) { const msg = formatString(courseLogs.CHAPTER_ERROR_GENERIC.message, { error: (err as Error)?.message || '', }); courseLogger.error(msg, err as Error); return new ErrorResponseC( courseLogs.CHAPTER_ERROR_GENERIC.type, HttpCodes.InternalServerError.code, msg ); } }; static createChapters = async ( course_id: number, chapters: ChapterI[] ): Promise => { try { const sqlInsertQuery = 'INSERT INTO chapters (course_id, title, position) VALUES (?, ?, ?)'; for (const chapter of chapters) { const { title, position, data } = chapter; // if data item has video_id then it is a video const videos = data?.filter( (item) => (item as VideoI).videoLength ) as VideoI[]; // documents = rest of the data items const documents = data?.filter( (item) => !(item as VideoI).videoLength ) as DocumentI[]; const [result]: any = await db.query( sqlInsertQuery, [course_id, title, position] ); const chapterId = result.insertId; chapter.chapter_id = chapterId; if (videos.length > 0) { videos.forEach((video) => (video.chapter_id = chapterId)); const videosResponse = await VideoServices.insertVideos(videos); if (videosResponse instanceof ErrorResponseC) { return videosResponse; } } if (documents.length > 0) { documents.forEach((document) => (document.chapter_id = chapterId)); const documentsResponse = await DocumentServices.insertDocuments( documents ); if (documentsResponse instanceof ErrorResponseC) { return documentsResponse; } } } const resp: ICode = courseLogs.CREATE_CHAPTERS_SUCCESS; const msg = formatString(resp.message, { chapterIds: chapters.map((chapter) => chapter.chapter_id).join(', '), }); courseLogger.info(msg, { type: resp.type }); return new SuccessResponseC( resp.type, chapters, msg, HttpCodes.Created.code ); } catch (err) { const msg = formatString(courseLogs.CHAPTER_ERROR_GENERIC.message, { error: (err as Error)?.message || '', }); courseLogger.error(msg, err as Error); return new ErrorResponseC( courseLogs.CHAPTER_ERROR_GENERIC.type, HttpCodes.InternalServerError.code, msg ); } }; static updateChapters = async (chapters: ChapterI[]): Promise => { try { const sqlUpdateQuery = 'UPDATE chapters SET title = ?, position = ? WHERE chapter_id = ?'; const values: any = chapters.map((chapter) => [ chapter.title, chapter.position, chapter.chapter_id, ]); for (const value of values) { // const [result]: any = await db.query(sqlUpdateQuery, [ value.title, value.position, value.chapter_id, ]); // if (result.affectedRows === 0) { // const msg = formatString(courseLogs.CHAPTER_ERROR_NOT_FOUND.message, { // chapterId: chapters.map((chapter) => chapter.chapter_id).join(', '), // }); // courseLogger.error(msg); // return new ErrorResponseC( // courseLogs.CHAPTER_ERROR_NOT_FOUND.type, // HttpCodes.NotFound.code, // msg // ); // } } const resp: ICode = courseLogs.UPDATE_CHAPTER_SUCCESS; const msg = formatString(resp.message, { chapterIds: chapters.map((chapter) => chapter.chapter_id).join(', '), }); courseLogger.info(msg, { type: resp.type }); return new SuccessResponseC(resp.type, {}, msg, HttpCodes.Accepted.code); } catch (err) { const msg = formatString(courseLogs.CHAPTER_ERROR_GENERIC.message, { error: (err as Error)?.message || '', }); courseLogger.error(msg, err as Error); return new ErrorResponseC( courseLogs.CHAPTER_ERROR_GENERIC.type, HttpCodes.InternalServerError.code, msg ); } }; static deleteChapters = async (chapter_ids: number[]): Promise => { try { const sqlDeleteQuery = 'DELETE FROM chapters WHERE chapter_id IN (?)'; const [result]: any = await db.query(sqlDeleteQuery, [ chapter_ids, ]); if (result.affectedRows === 0) { const msg = formatString(courseLogs.CHAPTER_ERROR_NOT_FOUND.message, { chapterId: chapter_ids.join(', '), }); courseLogger.error(msg); return new ErrorResponseC( courseLogs.CHAPTER_ERROR_NOT_FOUND.type, HttpCodes.NotFound.code, msg ); } const resp: ICode = courseLogs.DELETE_CHAPTERS_SUCCESS; const msg = formatString(resp.message, { chapterIds: chapter_ids.join(', '), }); courseLogger.info(msg, { type: resp.type }); return new SuccessResponseC(resp.type, {}, msg, HttpCodes.Accepted.code); } catch (err) { const msg = formatString(courseLogs.CHAPTER_ERROR_GENERIC.message, { error: (err as Error)?.message || '', }); courseLogger.error(msg, err as Error); return new ErrorResponseC( courseLogs.CHAPTER_ERROR_GENERIC.type, HttpCodes.InternalServerError.code, msg ); } }; static identifyAddedChapters = ( oldChapters: ChapterI[], newChapters: ChapterI[] ) => { const addedChapters = newChapters.filter( (newChapter) => !oldChapters.some( (oldChapter) => oldChapter.chapter_id === newChapter.chapter_id ) ); return addedChapters; }; static identifyDeletedChapters = ( oldChapters: ChapterI[], newChapters: ChapterI[] ) => { const deletedChapters = oldChapters.filter( (oldChapter) => !newChapters.some( (newChapter) => newChapter.chapter_id === oldChapter.chapter_id ) ); return deletedChapters; }; static identifyUpdatedChapters = ( oldChapters: ChapterI[], newChapters: ChapterI[] ) => { const updatedChapters = newChapters.filter((newChapter) => oldChapters.some( (oldChapter) => oldChapter.chapter_id === newChapter.chapter_id && (oldChapter.title !== newChapter.title || oldChapter.position !== newChapter.position) ) ); return updatedChapters; }; static filterChapters = ( chapters: ChapterI[], deletedChapters: ChapterI[] ) => { const filteredChapters = chapters.filter( (chapter) => !deletedChapters.some( (deletedChapter) => deletedChapter.chapter_id === chapter.chapter_id ) ); return filteredChapters; }; }