Snai3i-MarketPlace / backend / src / services / enrollment / enrollment.service.ts
enrollment.service.ts
Raw
import enrollmentLogs, {
  IEnrollmentLogs,
  enrollmentLogger,
} from './enrollment.logs';
import { formatString } from '../../utils/Strings';
import { HttpCodes } from '../../config/Errors';
import { ErrorResponseC, SuccessResponseC } from '../services.response';
import { db } from '../../settings';
import { ResultSetHeader, RowDataPacket } from 'mysql2';

export class EnrollmentServices {


  /**
   * @description Assign a teacher to a course
   * @param course_id - Number
   * @param teacher_id - Number
   * @param school_id - Number
   * @returns ResponseT
   */
  static assignTeacherToCourse = async (
    course_id: number,
    teacher_id: number,
    school_id: number
  ): Promise<ResponseT> => {
    try {
      // check if the teacher is already assinged to this course
      const sqlSelectQuery1 =
        'SELECT * FROM enrollments WHERE course_id = ? AND teacher_id = ?';
      const [enrollments]: any = await db.query<RowDataPacket[]>(
        sqlSelectQuery1,
        [course_id, teacher_id]
      );
      if (enrollments.length > 0) {
        const resp: ICode<IEnrollmentLogs> =
          enrollmentLogs.FAILED_TO_ASSIGN_TEACHER_TO_COURSE;
        const msg = formatString(resp.message, {
          error: 'The teacher is already assigned to the course',
        });
        enrollmentLogger.error(msg, { type: resp.type });
        return new ErrorResponseC(resp.type, HttpCodes.BadRequest.code, msg);
      }

      const sqlSelectQuery =
        'SELECT pack_id FROM orders WHERE course_id = ? AND school_id = ?';
      const [[pack]]: any = await db.query<RowDataPacket[]>(sqlSelectQuery, [
        course_id,
        school_id,
      ]);
      const pack_id = pack.pack_id;

      const sqlSelectQuery2 =
        'SELECT nb_teachers_accounts FROM packs WHERE pack_id = ?';
      const [[get_nb_teachers]]: any = await db.query<RowDataPacket[]>(
        sqlSelectQuery2,
        [pack_id]
      );
      const nb_teachers_accounts = get_nb_teachers.nb_teachers_accounts;

      const sqlSelectQuery3 =
        'SELECT COUNT(*) as count FROM enrollments WHERE course_id = ? AND school_id = ?';
      const [[get_count]]: any = await db.query<RowDataPacket[]>(
        sqlSelectQuery3,
        [course_id, school_id]
      );

      const count = get_count.count;

      if (count < nb_teachers_accounts) {
        return EnrollmentServices.createEnrollment(
          course_id,
          teacher_id,
          school_id
        );
      } else {
        const resp: ICode<IEnrollmentLogs> =
          enrollmentLogs.FAILED_TO_ASSIGN_TEACHER_TO_COURSE;
        const msg = formatString(resp.message, {
          error:
            'The number of teachers that are already assigned to the course is greater than or equal to the number of teachers that are allowed to be assigned to the course',
        });
        enrollmentLogger.error(msg, { type: resp.type });
        return new ErrorResponseC(resp.type, HttpCodes.BadRequest.code, msg);
      }
    } catch (err) {
      const msg = formatString(
        enrollmentLogs.ASSIGN_TEACHER_TO_COURSE_ERROR.message,
        {
          error: (err as Error)?.message || '',
        }
      );
      enrollmentLogger.error(msg, err as Error);
      return new ErrorResponseC(
        enrollmentLogs.ASSIGN_TEACHER_TO_COURSE_ERROR.type,
        HttpCodes.InternalServerError.code,
        msg
      );
    }
  };

  /**
   * @description Create an enrollment
   * @param course_id - Number
   * @param teacher_id - Number
   * @returns ResponseT
   */
  static createEnrollment = async (
    course_id: number,
    teacher_id: number,
    school_id: number | null = null
  ): Promise<ResponseT> => {
    try {
      const sqlInsertQuery =
        'INSERT INTO enrollments (course_id, teacher_id, school_id) VALUES (?, ?, ?)';

      const result: any = await db.query<ResultSetHeader[]>(sqlInsertQuery, [
        course_id,
        teacher_id,
        school_id,
      ]);

      const enrollmentId = result[0].insertId;

      const enrollment: EnrollmentI = {
        enrollment_id: enrollmentId,
        course_id,
        teacher_id,
        school_id: school_id ?? null,
      };

      const resp: ICode<IEnrollmentLogs> =
        enrollmentLogs.CREATE_ENROLLMENT_SUCCESS;
      const msg = formatString(resp.message, {
        enrollmentId,
      });
      enrollmentLogger.info(msg, { type: resp.type });

      return new SuccessResponseC(
        resp.type,
        enrollment,
        'Teacher has been assigned to the course',
        HttpCodes.Created.code
      );
    } catch (err) {
      const msg = formatString(enrollmentLogs.CREATE_ENROLLMENT_ERROR.message, {
        error: (err as Error)?.message || '',
      });
      enrollmentLogger.error(msg, err as Error);
      return new ErrorResponseC(
        enrollmentLogs.CREATE_ENROLLMENT_ERROR.type,
        HttpCodes.InternalServerError.code,
        msg
      );
    }
  };

  /**
   * @description Update an enrollment
   * @param enrollment_id - Number
   * @param course_id - Number
   * @param teacher_id - Number
   * @returns ResponseT
   */
  static deleteEnrollment = async (
    teacher_id: number,
    course_id: number
  ): Promise<ResponseT> => {
    try {
      const sqlDeleteQuery =
        'DELETE FROM enrollments WHERE teacher_id = ? AND course_id = ?';

      const [result]: any = await db.query<RowDataPacket[]>(sqlDeleteQuery, [
        teacher_id,
        course_id,
      ]);

      if (result.affectedRows === 0) {
        const resp: ICode<IEnrollmentLogs> =
          enrollmentLogs.DELETE_ENROLLMENT_ERROR;
        const msg = formatString(resp.message, {
          error: 'Enrollment not found',
        });
        enrollmentLogger.error(msg, { type: resp.type });
        return new ErrorResponseC(resp.type, HttpCodes.NotFound.code, msg);
      }

      const resp: ICode<IEnrollmentLogs> =
        enrollmentLogs.DELETE_ENROLLMENT_SUCCESS;
      const msg = formatString(resp.message, {
        teacher_id,
        course_id,
      });
      enrollmentLogger.info(msg, { type: resp.type });

      return new SuccessResponseC(
        resp.type,
        null,
        msg,
        HttpCodes.Accepted.code
      );
    } catch (err) {
      const msg = formatString(enrollmentLogs.DELETE_ENROLLMENT_ERROR.message, {
        error: (err as Error)?.message || '',
      });
      enrollmentLogger.error(msg, err as Error);
      return new ErrorResponseC(
        enrollmentLogs.DELETE_ENROLLMENT_ERROR.type,
        HttpCodes.InternalServerError.code,
        msg
      );
    }
  };

  static deleteEnrollmentById = async (
    enrollment_id: number
  ): Promise<ResponseT> => {
    try {
      const sqlDeleteQuery = 'DELETE FROM enrollments WHERE enrollment_id = ?';

      const [result]: any = await db.query<RowDataPacket[]>(sqlDeleteQuery, [
        enrollment_id,
      ]);

      if (result.affectedRows === 0) {
        const resp: ICode<IEnrollmentLogs> =
          enrollmentLogs.DELETE_ENROLLMENT_ERROR;
        const msg = formatString(resp.message, {
          error: 'Enrollment not found',
        });
        enrollmentLogger.error(msg, { type: resp.type });
        return new ErrorResponseC(resp.type, HttpCodes.NotFound.code, msg);
      }

      const resp: ICode<IEnrollmentLogs> =
        enrollmentLogs.DELETE_ENROLLMENT_SUCCESS;
      const msg = formatString(resp.message, {
        enrollment_id,
      });
      enrollmentLogger.info(msg, { type: resp.type });

      return new SuccessResponseC(
        resp.type,
        null,
        'Teacher has been unassigned from the course',
        HttpCodes.Accepted.code
      );
    } catch (err) {
      const msg = formatString(enrollmentLogs.DELETE_ENROLLMENT_ERROR.message, {
        error: (err as Error)?.message || '',
      });
      enrollmentLogger.error(msg, err as Error);
      return new ErrorResponseC(
        enrollmentLogs.DELETE_ENROLLMENT_ERROR.type,
        HttpCodes.InternalServerError.code,
        msg
      );
    }
  };
  /**
   * @description Get all enrollments
   * @returns ResponseT
   */
  static getEnrollments = async (): Promise<ResponseT> => {
    try {
      const sqlSelectQuery = 'SELECT * FROM enrollments';
      const [enrollments]: any = await db.query<RowDataPacket[]>(
        sqlSelectQuery
      );

      const resp: ICode<IEnrollmentLogs> =
        enrollmentLogs.GET_ENROLLMENTS_SUCCESS;
      const msg = formatString(resp.message, { count: enrollments.length });
      enrollmentLogger.info(msg, { type: resp.type });

      return new SuccessResponseC(
        resp.type,
        enrollments,
        msg,
        HttpCodes.OK.code
      );
    } catch (err) {
      const msg = formatString(enrollmentLogs.GET_ENROLLMENTS_ERROR.message, {
        error: (err as Error)?.message || '',
      });
      enrollmentLogger.error(msg, err as Error);
      return new ErrorResponseC(
        enrollmentLogs.GET_ENROLLMENTS_ERROR.type,
        HttpCodes.InternalServerError.code,
        msg
      );
    }
  };

  static getAssignedTeachersByCourseAndSchool = async (
    course_id: number,
    school_id: number
  ): Promise<ResponseT> => {
    try {
      const sqlSelectQuery =
        'SELECT * FROM enrollments WHERE course_id = ? AND school_id = ?';

      const [enrollments]: any = await db.query<RowDataPacket[]>(
        sqlSelectQuery,
        [course_id, school_id]
      );

      await Promise.all(
        enrollments.map(async (enrollment: any) => {
          const sqlSelectQuery2 =
            'SELECT t.*, u.firstName, u.lastName, u.user_id, u.email FROM teachers t INNER JOIN users u ON t.user_id = u.user_id WHERE teacher_id = ?';
          // 'SELECT * FROM Teachers WHERE teacher_id = ?';
          const [teacher]: any = await db.query<RowDataPacket[]>(
            sqlSelectQuery2,
            [enrollment.teacher_id]
          );
          enrollment.teacher = teacher[0];
        })
      );


      const resp: ICode<IEnrollmentLogs> =
        enrollmentLogs.GET_TEACHERS_BY_COURSE_AND_SCHOOL_SUCCESS;
      const msg = formatString(resp.message, {
        course_id,
        school_id,
      });
      enrollmentLogger.info(msg, { type: resp.type });

      return new SuccessResponseC(
        resp.type,
        enrollments,
        msg,
        HttpCodes.OK.code
      );
    } catch (err) {
      const msg = formatString(
        enrollmentLogs.GET_TEACHERS_BY_COURSE_AND_SCHOOL_ERROR.message,
        {
          course_id,
          school_id,
          error: (err as Error)?.message || '',
        }
      );
      enrollmentLogger.error(msg, err as Error);
      return new ErrorResponseC(
        enrollmentLogs.GET_TEACHERS_BY_COURSE_AND_SCHOOL_ERROR.type,
        HttpCodes.InternalServerError.code,
        msg
      );
    }
  };
}