import response from "../../response.js"; import models from "../../models/index.js"; import { createMonitoring } from "../monitoringControllers/monitoring.js"; export const getStdLearnings = async (req, res) => { try { const stdLearning = await models.StdLearning.findAll(); response(200, stdLearning, "Success", res); } catch (error) { console.log(error); response(500, null, "Error retrieving student learning data!", res); } }; export const getStdLearningById = async (req, res) => { try { const { id } = req.params; const stdLearning = await models.StdLearning.findByPk(id); if (!stdLearning) { return response(404, null, "Student learning data not found", res); } response(200, stdLearning, "Success", res); } catch (error) { response(500, null, "Internal Server Error", res); } }; export const createStdLearning = async (req, res) => { const { ID_LEVEL } = req.body; if (!req.user) { return response(401, null, "User not authenticated", res); } const ID = req.user.ID; try { if (req.stdLearning) { return response( 200, req.stdLearning, "Student Learning data found and reused", res ); } const level = await models.Level.findByPk(ID_LEVEL); if (!level) { return response(404, null, "Level not found", res); } const newStdLearning = await models.StdLearning.create({ ID, ID_LEVEL, }); response( 201, newStdLearning, "Student Learning data created successfully", res ); } catch (error) { console.log(error); response(500, null, "Internal Server Error", res); } }; export const updateStdLearningById = async (req, res) => { const { id } = req.params; const { FEEDBACK_STUDENT } = req.body; try { const stdLearning = await models.StdLearning.findByPk(id, { include: [ { model: models.Level, as: "level", }, ], }); if (!stdLearning) { return response(404, null, "Student Learning record not found", res); } if (req.user.ID !== stdLearning.ID) { return response(403, null, "Unauthorized to update this record", res); } stdLearning.STUDENT_FINISH = new Date(); stdLearning.SCORE = req.body.SCORE || stdLearning.SCORE; stdLearning.NEXT_LEARNING = req.body.NEXT_LEARNING || stdLearning.NEXT_LEARNING; stdLearning.IS_PASS = req.body.IS_PASS || stdLearning.IS_PASS; if (FEEDBACK_STUDENT) { stdLearning.FEEDBACK_STUDENT = FEEDBACK_STUDENT; } await stdLearning.save(); const level6 = await models.Level.findOne({ where: { NAME_LEVEL: "Level 6", ID_TOPIC: stdLearning.level.ID_TOPIC, }, }); if (!level6) { return response(404, null, "Level 6 not found", res); } if ( stdLearning.level.ID_LEVEL === level6.ID_LEVEL && stdLearning.IS_PASS === 1 ) { req.body.ID_STUDENT_LEARNING = id; const existingMonitoring = await models.Monitoring.findOne({ where: { ID_STUDENT_LEARNING: id }, }); if (!existingMonitoring) { const newMonitoring = await createMonitoring(req); const { level, ...responseData } = stdLearning.toJSON(); const combinedPayload = { ...responseData, MONITORING: newMonitoring, }; return response( 200, combinedPayload, "Student Learning record updated and monitoring created successfully", res ); } } else { const monitoringToDelete = await models.Monitoring.findOne({ where: { ID_STUDENT_LEARNING: id }, }); if (monitoringToDelete) { await monitoringToDelete.destroy(); } } const { level, ...responseData } = stdLearning.toJSON(); response( 200, responseData, "Student Learning record updated successfully", res ); } catch (error) { console.log(error); response(500, null, "Internal Server Error", res); } }; export const learningScoreByStdLearningId = async (req, res) => { try { if (!req.user) { return response(401, null, "User not authenticated", res); } const { ID } = req.user; const { stdLearningId } = req.params; const stdLearning = await models.StdLearning.findOne({ where: { ID_STUDENT_LEARNING: stdLearningId, ID: ID, }, include: [ { model: models.Level, as: "level", attributes: ["ID_LEVEL", "NAME_LEVEL"], }, { model: models.Level, as: "nextLevel", attributes: ["NAME_LEVEL"], }, { model: models.User, as: "learningUser", attributes: ["NAME_USERS"], include: [ { model: models.Student, as: "students", attributes: ["NISN"], }, ], }, ], }); if (!stdLearning) { return response( 404, null, "No matching learning data found for this user", res ); } if (!stdLearning.NEXT_LEARNING || !stdLearning.nextLevel) { return response(200, null, "No next learning level found", res); } const nextLearningData = { ID_STUDENT_LEARNING: stdLearning.ID_STUDENT_LEARNING, NAME_USERS: stdLearning.learningUser.NAME_USERS, NISN: stdLearning.learningUser.students ? stdLearning.learningUser.students.NISN : null, ID_LEVEL: stdLearning.level ? stdLearning.level.ID_LEVEL : null, CURRENT_LEVEL_NAME: stdLearning.level ? stdLearning.level.NAME_LEVEL : null, SCORE: stdLearning.SCORE, NEXT_LEARNING: stdLearning.NEXT_LEARNING, NEXT_LEARNING_NAME: stdLearning.nextLevel.NAME_LEVEL, IS_PASS: stdLearning.IS_PASS, }; return response(200, nextLearningData, "Success", res); } catch (error) { console.log(error); return response(500, null, "Internal Server Error", res); } }; export const learningHistory = async (req, res) => { const { page = 1, limit = 10 } = req.query; try { if (!req.user) { return response(401, null, "User not authenticated", res); } const { ID } = req.user; const stdLearnings = await models.StdLearning.findAll({ where: { ID }, STUDENT_FINISH: { [models.Sequelize.Op.ne]: null, }, include: [ { model: models.Level, as: "level", include: [ { model: models.Topic, as: "levelTopic", required: true, include: [ { model: models.Section, as: "topicSection", required: true, }, ], }, ], required: true, }, ], order: [["STUDENT_FINISH", "DESC"]], }); if (!stdLearnings.length) { return response( 404, null, "No learning history found for this user", res ); } const formattedLearnings = await Promise.all( stdLearnings.map(async (learning) => { let nextLevelName = null; if (learning.NEXT_LEARNING) { const nextLevel = await models.Level.findOne({ where: { ID_LEVEL: learning.NEXT_LEARNING }, }); if (nextLevel) { nextLevelName = nextLevel.NAME_LEVEL; } } return { SCORE: learning.SCORE, CURRENT_LEVEL: learning.level?.NAME_LEVEL || "No level", NEXT_LEVEL: nextLevelName, STUDENT_FINISH: learning.STUDENT_FINISH, TOPIC_NAME: learning.level?.levelTopic?.NAME_TOPIC || "No topic", SECTION_NAME: learning.level?.levelTopic?.topicSection?.NAME_SECTION || "No section", IS_PASS: learning.IS_PASS, }; }) ); const paginatedLearnings = formattedLearnings.slice( (page - 1) * limit, page * limit ); const totalPages = Math.ceil(formattedLearnings.length / limit); const currentPage = parseInt(page); response( 200, { history: paginatedLearnings, currentPage, totalPages, totalItems: formattedLearnings.length, }, "Learning history retrieved successfully", res ); } catch (error) { console.error(error); response(500, null, "Internal Server Error", res); } }; export const learningHistoryBySectionId = async (req, res) => { const { page = 1, limit = 10 } = req.query; try { if (!req.user) { return response(401, null, "User not authenticated", res); } const { ID } = req.user; const { sectionId } = req.params; const stdLearnings = await models.StdLearning.findAll({ where: { ID }, STUDENT_FINISH: { [models.Sequelize.Op.ne]: null, }, include: [ { model: models.Level, as: "level", include: [ { model: models.Topic, as: "levelTopic", include: [ { model: models.Section, as: "topicSection", where: { ID_SECTION: sectionId }, required: true, }, ], required: true, }, ], required: true, }, ], order: [["STUDENT_FINISH", "DESC"]], }); if (!stdLearnings.length) { return response( 404, null, "No learning history found for the specified section", res ); } const formattedLearnings = await Promise.all( stdLearnings.map(async (learning) => { let nextLevelName = null; if (learning.NEXT_LEARNING) { const nextLevel = await models.Level.findOne({ where: { ID_LEVEL: learning.NEXT_LEARNING }, }); if (nextLevel) { nextLevelName = nextLevel.NAME_LEVEL; } } return { SCORE: learning.SCORE, CURRENT_LEVEL: learning.level?.NAME_LEVEL || "No level", NEXT_LEVEL: nextLevelName, STUDENT_FINISH: learning.STUDENT_FINISH, TOPIC_NAME: learning.level?.levelTopic?.NAME_TOPIC || "No topic", SECTION_NAME: learning.level?.levelTopic?.topicSection?.NAME_SECTION || "No section", IS_PASS: learning.IS_PASS, }; }) ); const paginatedLearnings = formattedLearnings.slice( (page - 1) * limit, page * limit ); const totalPages = Math.ceil(formattedLearnings.length / limit); const currentPage = parseInt(page); response( 200, { history: paginatedLearnings, currentPage, totalPages, totalItems: formattedLearnings.length, }, "Learning history retrieved successfully", res ); } catch (error) { console.log(error); response(500, null, "Internal Server Error", res); } }; export const learningHistoryByTopicId = async (req, res) => { const { page = 1, limit = 10 } = req.query; try { if (!req.user) { return response(401, null, "User not authenticated", res); } const { ID } = req.user; const { topicId } = req.params; if (!topicId) { return response(400, null, "Topic ID is required", res); } const stdLearnings = await models.StdLearning.findAll({ where: { ID }, STUDENT_FINISH: { [models.Sequelize.Op.ne]: null, }, include: [ { model: models.Level, as: "level", include: [ { model: models.Topic, as: "levelTopic", where: { ID_TOPIC: topicId }, required: true, include: [ { model: models.Section, as: "topicSection", required: true, }, ], }, ], required: true, }, ], order: [["STUDENT_FINISH", "DESC"]], }); if (!stdLearnings.length) { return response( 404, null, "No learning history found for the specified topic", res ); } const formattedLearnings = await Promise.all( stdLearnings.map(async (learning) => { let nextLevelName = null; if (learning.NEXT_LEARNING) { const nextLevel = await models.Level.findOne({ where: { ID_LEVEL: learning.NEXT_LEARNING }, }); if (nextLevel) { nextLevelName = nextLevel.NAME_LEVEL; } } return { SCORE: learning.SCORE, CURRENT_LEVEL: learning.level?.NAME_LEVEL || "No level", NEXT_LEVEL: nextLevelName, STUDENT_FINISH: learning.STUDENT_FINISH, TOPIC_NAME: learning.level?.levelTopic?.NAME_TOPIC || "No topic", SECTION_NAME: learning.level?.levelTopic?.topicSection?.NAME_SECTION || "No section", IS_PASS: learning.IS_PASS, }; }) ); const paginatedLearnings = formattedLearnings.slice( (page - 1) * limit, page * limit ); const totalPages = Math.ceil(formattedLearnings.length / limit); const currentPage = parseInt(page); response( 200, { history: paginatedLearnings, currentPage, totalPages, totalItems: formattedLearnings.length, }, "Learning history retrieved successfully", res ); } catch (error) { console.error(error); response(500, null, "Internal Server Error", res); } }; export const recentStudentActivities = async (req, res) => { try { const stdLearnings = await models.StdLearning.findAll({ include: [ { model: models.User, as: "learningUser", attributes: ["ID", "NAME_USERS"], include: [ { model: models.Student, as: "students", attributes: ["NISN"], }, ], }, { model: models.Level, as: "level", attributes: ["NAME_LEVEL"], include: [ { model: models.Topic, as: "levelTopic", attributes: ["NAME_TOPIC"], include: [ { model: models.Section, as: "topicSection", attributes: ["NAME_SECTION"], }, ], }, ], }, ], order: [["STUDENT_FINISH", "DESC"]], limit: 5, }); const recentActivities = stdLearnings.map((learning) => ({ NISN: learning.learningUser?.students?.NISN || "N/A", NAME_USERS: learning.learningUser?.NAME_USERS || "N/A", NAME_SECTION: learning.level?.levelTopic?.topicSection?.NAME_SECTION || "N/A", NAME_TOPIC: learning.level?.levelTopic?.NAME_TOPIC || "N/A", NAME_LEVEL: learning.level?.NAME_LEVEL || "N/A", SCORE: learning.SCORE || "N/A", })); if (!recentActivities.length) { return res.status(404).json({ message: "No recent activities found" }); } res.status(200).json({ recentActivities }); } catch (error) { console.error(error); res.status(500).json({ message: "Internal Server Error" }); } }; export const getLastCreatedStdLearningByLevelId = async (req, res) => { try { if (!req.user) { return response(401, null, "User not authenticated", res); } const { ID } = req.user; const { levelId } = req.params; if (!levelId) { return response(400, null, "Level ID is required", res); } const latestStdLearning = await models.StdLearning.findOne({ where: { ID: ID, ID_LEVEL: levelId, }, order: [["STUDENT_START", "DESC"]], }); if (!latestStdLearning) { return response(404, null, "No StdLearning data found", res); } response(200, latestStdLearning, "Success", res); } catch (error) { console.error(error); response(500, null, "Internal Server Error", res); } };