const { Op } = require("sequelize");
const { CourseDTO } = require("../dto/course.dto");
const db = require("../models");
/**
* Service to create, update, and retrieve course information.
* @module services/course
*/
const courseService = {
/**
* Search for courses based on the provided search terms.
* @memberof module:services/course
* @param {*} terms - The search terms to match against training name.
* @param {number} offset - The number of items to skip before starting to return results.
* @param {number} limit - The maximum number of items to return.
* @returns {Promise<CourseDTO[]>} A promise that resolves to an array of CourseDTO objects matching the search terms.
* @throws {Error} - If the operation fails or encounters an error.
*/
search: async (terms) => {
console.log("Search terms", terms);
const { rows, count } = await db.Course.findAndCountAll({
where: {
name: {
[Op.like]: `%${terms}%`,
},
},
distinct: true,
});
return {
courses: rows.map((course) => new CourseDTO(course)),
count,
};
},
/**
* Retrieve a paginated list of course.
* @memberof module:services/course
* @param {number} offset - The number of items to skip before starting to return results.
* @param {number} limit - The maximum number of items to return.
* @returns {Promise<{ students: Array<CourseDTO>, count: number }>} - A promise that resolves to an object containing an array of CourseDateDTO objects representing the course-date and the total count of teachers.
* @throws {Error} - If the operation fails or encounters an error.
*/
getAll: async (offset, limit) => {
const { rows, count } = await db.Course.findAndCountAll({
distinct: true,
offset,
limit,
include: [
db.Training,
{
model: db.Teacher,
// attributes: ["UserId"],
include: [
{
model: db.User,
attributes: ["firstName", "lastName"],
},
],
},
{
association: "dates",
include: [
{
model: db.Teacher,
// attributes: ["UserId"],
include: [
{ model: db.User, attributes: ["firstName", "lastName"] },
],
},
],
},
],
});
return {
courses: rows.map((course) => new CourseDTO(course)),
count,
};
},
/**
* Retrieve the course details with the provided ID.
* @memberof module:services/course
* @param {*} id - The ID of the course to retrieve.
* @returns {Promise<CourseDTO|null>} A promise that resolves to a CourseDTO instance representing the retrieved course, or null if the course is not found.
* @throws {Error} - If the operation fails or encounters an error.
*/
getById: async (id) => {
const course = await db.Course.findByPk(id, {
include: [
db.Training,
{
model: db.Teacher,
include: [
{
model: db.User,
attributes: ["firstName", "lastName"],
},
],
},
{
association: "dates",
include: [
{
model: db.Teacher,
// attributes: ["UserId"],
include: [
{ model: db.User, attributes: ["firstName", "lastName"] },
],
},
],
},
],
});
return course ? new CourseDTO(course) : null;
},
/**
* Create a course with the provided data.
* @memberof module:services/course
* @param {*} courseToAdd - The course data to be added.
* @returns {Promise<CourseDTO|null>} A promise that resolves to a new CourseDTO instance representing the created course, or null if creation fails.
* @throws {Error} - If the operation fails or encounters an error.
*/
create: async (courseToAdd) => {
console.log("Service Create course: ", courseToAdd);
const course = await db.Course.create(courseToAdd);
await course.setTraining(courseToAdd.Training.id);
await course.setTeacher(courseToAdd.Teacher.id);
console.log("Service course created", course);
// console.log(await course.countDates());
const newCourse = await db.Course.findByPk(course.id, {
include: [
db.Training,
{
model: db.Teacher,
include: [
{
model: db.User,
attributes: ["firstName", "lastName"],
},
],
},
{
association: "dates",
include: [
{
model: db.Teacher,
// attributes: ["UserId"],
include: [
{
model: db.User,
attributes: ["firstName", "lastName"],
},
],
},
],
},
],
});
console.log("create course find: ", newCourse);
return newCourse ? new CourseDTO(newCourse) : null;
},
/**
*
* @memberof module:services/course
* @param {*} id - The ID of the course to update
* @param {*} courseDTO - The detail of the course to update
* @returns {Promise<boolean>} - A promise that resolves to true if the course was successfully deleted, or false otherwise.
* @throws {Error} - If the operation fails or encounters an error.
*/
update: async (id, courseDTO) => {
const transaction = await db.sequelize.transaction();
console.log("ID: ", id);
console.log("DTO: ", courseDTO);
const course = await db.Course.findByPk(id, {
include: [
// {
// association: db.CourseDate,
// as: "dates",
// },
],
});
console.log("TO UPDATE: ", course);
try {
for (const date of courseDTO.dates) {
await course.createDate(
{
TeacherId: date.TeacherId,
CourseId: date.CourseId,
date: date.date,
},
{ transaction }
);
}
const updatedRow = await db.Course.update(
course,
{
where: { id },
},
{
include: [
{ association: "dates", model: db.CourseDate, as: "dates" },
],
}
);
await transaction.commit();
return updatedRow[0] === 1;
} catch (err) {
await transaction.rollback();
return null;
}
},
/**
* Delete course with the provided ID.
* @memberof module:services/course
* @param {*} courseId - The ID of the course to delete.
* @returns {Promise<boolean>} - A promise that resolves to true if the course was successfully deleted, or false otherwise.
* @throws {Error} - If the operation fails or encounters an error.
*/
delete: async (courseId) => {
const nbDeletedRow = await db.Course.destroy({
where: { id: courseId },
});
return nbDeletedRow === 1;
},
/**
* Returns an array of dates on which a course is scheduled.
* @memberof module:services/course
* @param {string} courseId - The ID of the course to retrieve the schedule for.
* @returns {Promise<any>}
* @throws {Error} - If the operation fails or encounters an error.
*/
getDates: async (courseId) => {
const course = await db.Course.findByPk(courseId, {
include: [{ association: "dates", as: "dates" }],
});
console.log(course);
return course.dates;
},
/**
* Retrieve a list of material for a course.
* @memberof module:services/course
* @param {*} courseId
* @returns {Promise<CourseDTO>}
* @throws {Error} - If the operation fails or encounters an error.
*/
getMaterials: async (courseId) => {
const course = await db.Course.findByPk(courseId, {
include: [db.CourseMaterial],
});
console.log(course);
return course.dates;
},
};
module.exports = courseService;