477 lines
12 KiB
JavaScript
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);
|
|
}
|
|
};
|