backend_adaptive_learning/controllers/monitoringControllers/class.js
2024-12-18 09:00:15 +07:00

477 lines
12 KiB
JavaScript

import response from "../../response.js";
import models from "../../models/index.js";
import { updateMonitoringClass } from "./monitoring.js";
export const getClasses = async (req, res) => {
try {
const classes = await models.Class.findAll({
attributes: {
include: [
[
models.Sequelize.fn(
"COUNT",
models.Sequelize.col("ClassStudents.ID_SISWA")
),
"TOTAL_STUDENT",
],
],
},
include: [
{
model: models.Student,
as: "ClassStudents",
attributes: [],
},
],
group: ["class.ID_CLASS"],
});
response(200, classes, "Success", res);
} catch (error) {
console.error(error);
response(500, null, "Error retrieving classes data!", res);
}
};
export const getClassById = async (req, res) => {
try {
const { id } = req.params;
const classes = await models.Class.findByPk(id);
if (!classes) {
return response(404, null, "Class not found", res);
}
response(200, classes, "Success", res);
} catch (error) {
console.log(error);
response(500, null, "Internal Server Error", res);
}
};
export const getClassForAdmin = async (req, res) => {
const { page = 1, limit = 10, search = "", sort = "time" } = req.query;
try {
const { count, rows: classes } = await models.Class.findAndCountAll({
where: {
...(search && {
[models.Op.or]: [
{
NAME_CLASS: {
[models.Op.like]: `%${search}%`,
},
},
models.Sequelize.where(
models.Sequelize.literal(
`(SELECT COUNT(*) FROM student WHERE student.ID_CLASS = class.ID_CLASS)`
),
{
[models.Op.like]: `%${search}%`,
}
),
{
TOTAL_STUDENT: {
[models.Op.like]: `%${search}%`,
},
},
],
}),
},
attributes: [
"ID_CLASS",
"NAME_CLASS",
"TOTAL_STUDENT",
"TIME_CLASS",
[
models.Sequelize.literal(
`(SELECT COUNT(*) FROM student WHERE student.ID_CLASS = class.ID_CLASS)`
),
"STUDENTS",
],
],
distinct: true,
});
const formattedClasses = classes.map((classItem) => ({
ID_CLASS: classItem.ID_CLASS,
NAME_CLASS: classItem.NAME_CLASS,
STUDENTS: classItem.get("STUDENTS"),
TOTAL_STUDENT: classItem.TOTAL_STUDENT,
TIME_CLASS: classItem.TIME_CLASS,
}));
if (sort === "class") {
formattedClasses.sort((a, b) => a.NAME_CLASS.localeCompare(b.NAME_CLASS));
} else if (sort === "total") {
formattedClasses.sort((a, b) => a.TOTAL_STUDENT - b.TOTAL_STUDENT);
} else if (sort === "students") {
formattedClasses.sort((a, b) => a.STUDENTS - b.STUDENTS);
} else {
formattedClasses.sort(
(a, b) => new Date(b.TIME_CLASS) - new Date(a.TIME_CLASS)
);
}
const paginatedClasses = formattedClasses.slice(
(page - 1) * limit,
page * limit
);
const totalPages = Math.ceil(count / limit);
const currentPage = parseInt(page);
response(
200,
{
classes: paginatedClasses,
currentPage,
totalPages,
totalItems: count,
},
"Classes retrieved successfully",
res
);
} catch (error) {
console.log(error);
response(500, null, "Error retrieving classes data!", res);
}
};
export const createClass = async (req, res) => {
const { NAME_CLASS, TOTAL_STUDENT } = req.body;
if (!NAME_CLASS) {
return response(400, null, "Class name is required", res);
}
if (!TOTAL_STUDENT) {
return response(400, null, "Total student is required", res);
}
try {
const existingClass = await models.Class.findOne({
where: { NAME_CLASS },
});
if (existingClass) {
return response(400, null, "Class with this name already exists", res);
}
const newClass = await models.Class.create({
NAME_CLASS,
TOTAL_STUDENT,
});
response(201, newClass, "Class created successfully", res);
} catch (error) {
console.log(error);
response(500, null, "Internal Server Error", res);
}
};
export const updateClassById = async (req, res) => {
const { id } = req.params;
const { NAME_CLASS, TOTAL_STUDENT } = req.body;
try {
const classes = await models.Class.findByPk(id);
if (!classes) {
return response(404, null, "Class not found", res);
}
if (NAME_CLASS && NAME_CLASS !== classes.NAME_CLASS) {
const existingClass = await models.Class.findOne({
where: { NAME_CLASS },
});
if (existingClass) {
return response(400, null, "Class with this name already exists", res);
}
classes.NAME_CLASS = NAME_CLASS;
}
if (TOTAL_STUDENT) {
classes.TOTAL_STUDENT = TOTAL_STUDENT;
}
await classes.save();
response(200, classes, "Class updated successfully", res);
} catch (error) {
console.log(error);
response(500, null, "Internal Server Error", res);
}
};
export const deleteClassById = async (req, res) => {
const { id } = req.params;
try {
const classes = await models.Class.findByPk(id);
if (!classes) {
return response(404, null, "Class not found", res);
}
await models.Student.update(
{ ID_CLASS: null },
{
where: { ID_CLASS: id },
}
);
await models.Monitoring.update(
{ ID_CLASS: null },
{
where: { ID_CLASS: id },
}
);
await classes.destroy();
response(
200,
null,
"Class deleted successfully and related models updated",
res
);
} catch (error) {
console.log(error);
response(500, null, "Internal Server Error", res);
}
};
export const updateStudentClassByName = async (req, res) => {
const { NAME_CLASS, STUDENTS } = req.body;
if (!NAME_CLASS || !Array.isArray(STUDENTS) || STUDENTS.length === 0) {
return response(
400,
null,
"Class name and students data are required",
res
);
}
try {
const classRecord = await models.Class.findOne({
where: { NAME_CLASS },
});
if (!classRecord) {
return response(404, null, "Class not found", res);
}
const updateResults = [];
let hasError = false;
let successCount = 0;
let failureCount = 0;
for (const { NAME_USERS, NISN } of STUDENTS) {
if (!NAME_USERS || !NISN) {
updateResults.push({
NAME_USERS,
NISN,
error: "User name and NISN are required for each student",
});
hasError = true;
failureCount++;
continue;
}
try {
const student = await models.Student.findOne({
include: [
{
model: models.User,
as: "studentUser",
where: { NAME_USERS },
},
],
where: { NISN },
});
if (!student) {
updateResults.push({
NAME_USERS,
NISN,
error: "Student with the given name and NISN not found",
});
hasError = true;
failureCount++;
continue;
}
if (student.ID_CLASS === classRecord.ID_CLASS) {
updateResults.push({
NAME_USERS,
NISN,
error: "Student is already in the selected class",
});
hasError = true;
failureCount++;
continue;
}
student.ID_CLASS = classRecord.ID_CLASS;
await student.save();
const stdLearningRecords = await models.StdLearning.findAll({
where: { ID: student.ID },
include: [
{
model: models.Level,
as: "level",
where: { NAME_LEVEL: "Level 6" },
},
],
});
const studentUpdateResults = [];
for (const stdLearning of stdLearningRecords) {
try {
const result = await updateMonitoringClass({
ID_STUDENT_LEARNING: stdLearning.ID_STUDENT_LEARNING,
ID_CLASS: classRecord.ID_CLASS,
});
studentUpdateResults.push(result);
} catch (error) {
console.error("Error updating monitoring class:", error.message);
studentUpdateResults.push({ error: error.message });
}
}
updateResults.push({
NAME_USERS,
NISN,
message:
"Student's class and related monitoring updated successfully",
studentUpdateResults,
});
successCount++;
} catch (error) {
console.error("Error processing student:", error.message);
updateResults.push({
NAME_USERS,
NISN,
error: "Error processing student",
details: error.message,
});
hasError = true;
failureCount++;
}
}
let responseMessage = "";
if (failureCount === STUDENTS.length) {
responseMessage = "Failed to update all students.";
} else if (successCount > 0 && failureCount > 0) {
responseMessage =
"Some students updated successfully, but there were errors with others.";
} else if (successCount === STUDENTS.length) {
responseMessage = "All students updated successfully.";
}
return response(200, { updateResults }, responseMessage, res);
} catch (error) {
console.error(error);
response(500, null, "Internal Server Error", res);
}
};
export const getStudentsByClassId = async (req, res) => {
try {
const { classId } = req.params;
const studentsInClass = await models.User.findAll({
where: {
ROLE: "student",
},
attributes: ["ID", "NAME_USERS", "EMAIL", "ROLE"],
include: [
{
model: models.Student,
as: "students",
attributes: ["NISN", "ID_CLASS"],
include: [
{
model: models.Class,
as: "studentClass",
attributes: ["NAME_CLASS"],
},
],
where: {
ID_CLASS: classId,
},
},
],
raw: true,
nest: true,
});
const formattedStudents = studentsInClass.map((student) => ({
ID: student.ID,
NAME_USERS: student.NAME_USERS,
EMAIL: student.EMAIL,
NISN: student.students.NISN,
NAME_CLASS: student.students.studentClass.NAME_CLASS,
ROLE: student.ROLE,
}));
response(200, formattedStudents, "Success", res);
} catch (error) {
console.log(error);
response(500, null, "Error retrieving students by class ID", res);
}
};
export const getStudentsWithNoClass = async (req, res) => {
try {
const studentsWithoutClass = await models.User.findAll({
where: {
ROLE: "student",
},
attributes: ["ID", "NAME_USERS", "EMAIL", "ROLE"],
include: [
{
model: models.Student,
as: "students",
attributes: ["NISN", "ID_CLASS"],
include: [
{
model: models.Class,
as: "studentClass",
attributes: ["NAME_CLASS"],
},
],
where: {
ID_CLASS: null,
},
},
],
raw: true,
nest: true,
});
const formattedStudents = studentsWithoutClass.map((student) => ({
ID: student.ID,
NAME_USERS: student.NAME_USERS,
EMAIL: student.EMAIL,
NISN: student.students.NISN,
NAME_CLASS: student.students.studentClass.NAME_CLASS,
ROLE: student.ROLE,
}));
response(200, formattedStudents, "Success", res);
} catch (error) {
console.log(error);
response(500, null, "Error retrieving students with no class", res);
}
};