This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
const { AcademicYear } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
|
||||
|
||||
/**
|
||||
* Academic Year Controller - Quản lý năm học
|
||||
@@ -146,24 +146,23 @@ class AcademicYearController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new academic year (async via BullMQ)
|
||||
* Create new academic year
|
||||
*/
|
||||
async createAcademicYear(req, res, next) {
|
||||
try {
|
||||
const academicYearData = req.body;
|
||||
|
||||
// Add to job queue for async processing
|
||||
const job = await addDatabaseWriteJob('create', 'AcademicYear', academicYearData);
|
||||
// Create academic year directly
|
||||
const academicYear = await AcademicYear.create(academicYearData);
|
||||
|
||||
// Invalidate related caches
|
||||
await cacheUtils.deletePattern('academic_years:list:*');
|
||||
await cacheUtils.delete('academic_year:current');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Academic year creation job queued',
|
||||
jobId: job.id,
|
||||
data: academicYearData,
|
||||
message: 'Academic year created successfully',
|
||||
data: academicYear,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -171,28 +170,34 @@ class AcademicYearController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update academic year (async via BullMQ)
|
||||
* Update academic year
|
||||
*/
|
||||
async updateAcademicYear(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
// Add to job queue for async processing
|
||||
const job = await addDatabaseWriteJob('update', 'AcademicYear', {
|
||||
id,
|
||||
updates,
|
||||
});
|
||||
const academicYear = await AcademicYear.findByPk(id);
|
||||
|
||||
if (!academicYear) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Academic year not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Update academic year directly
|
||||
await academicYear.update(updates);
|
||||
|
||||
// Invalidate related caches
|
||||
await cacheUtils.delete(`academic_year:${id}`);
|
||||
await cacheUtils.deletePattern('academic_years:list:*');
|
||||
await cacheUtils.delete('academic_year:current');
|
||||
|
||||
res.status(202).json({
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Academic year update job queued',
|
||||
jobId: job.id,
|
||||
message: 'Academic year updated successfully',
|
||||
data: academicYear,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -200,24 +205,32 @@ class AcademicYearController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete academic year (async via BullMQ)
|
||||
* Delete academic year
|
||||
*/
|
||||
async deleteAcademicYear(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
// Add to job queue for async processing
|
||||
const job = await addDatabaseWriteJob('delete', 'AcademicYear', { id });
|
||||
const academicYear = await AcademicYear.findByPk(id);
|
||||
|
||||
if (!academicYear) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Academic year not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Delete academic year directly
|
||||
await academicYear.destroy();
|
||||
|
||||
// Invalidate related caches
|
||||
await cacheUtils.delete(`academic_year:${id}`);
|
||||
await cacheUtils.deletePattern('academic_years:list:*');
|
||||
await cacheUtils.delete('academic_year:current');
|
||||
|
||||
res.status(202).json({
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Academic year deletion job queued',
|
||||
jobId: job.id,
|
||||
message: 'Academic year deleted successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -231,20 +244,31 @@ class AcademicYearController {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
// Add to job queue to update current year
|
||||
const job = await addDatabaseWriteJob('update', 'AcademicYear', {
|
||||
id,
|
||||
updates: { is_current: true },
|
||||
// Will also set all other years to is_current: false
|
||||
});
|
||||
const academicYear = await AcademicYear.findByPk(id);
|
||||
|
||||
if (!academicYear) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Academic year not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Set all other years to not current
|
||||
await AcademicYear.update(
|
||||
{ is_current: false },
|
||||
{ where: {} }
|
||||
);
|
||||
|
||||
// Set this year as current
|
||||
await academicYear.update({ is_current: true });
|
||||
|
||||
// Invalidate all academic year caches
|
||||
await cacheUtils.deletePattern('academic_year*');
|
||||
|
||||
res.status(202).json({
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Set current academic year job queued',
|
||||
jobId: job.id,
|
||||
message: 'Academic year set as current successfully',
|
||||
data: academicYear,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const { AttendanceLog, AttendanceDaily, UsersAuth, School } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob, addAttendanceProcessJob } = require('../config/bullmq');
|
||||
const { addAttendanceProcessJob } = require('../config/bullmq');
|
||||
|
||||
/**
|
||||
* Attendance Controller - Quản lý điểm danh
|
||||
@@ -82,15 +82,15 @@ class AttendanceController {
|
||||
try {
|
||||
const logData = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('create', 'AttendanceLog', logData);
|
||||
const newLog = await AttendanceLog.create(logData);
|
||||
|
||||
await cacheUtils.deletePattern('attendance:logs:*');
|
||||
await cacheUtils.deletePattern('attendance:daily:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Attendance log created',
|
||||
jobId: job.id,
|
||||
message: 'Attendance log created successfully',
|
||||
data: newLog,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const { Class } = require('../models');
|
||||
const { StudentDetail, UserProfile, UsersAuth, School } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
|
||||
/**
|
||||
* Class Controller - Quản lý thông tin lớp học
|
||||
@@ -107,22 +106,55 @@ class ClassController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new class (async via BullMQ)
|
||||
* Create new class
|
||||
*/
|
||||
async createClass(req, res, next) {
|
||||
try {
|
||||
const classData = req.body;
|
||||
|
||||
// Add to job queue for async processing
|
||||
const job = await addDatabaseWriteJob('create', 'Class', classData);
|
||||
// Create class directly
|
||||
const newClass = await Class.create(classData);
|
||||
|
||||
// Invalidate related caches
|
||||
await cacheUtils.deletePattern('classes:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Class creation job queued',
|
||||
jobId: job.id,
|
||||
message: 'Class created successfully',
|
||||
data: newClass,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update class
|
||||
*/
|
||||
async updateClass(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
const classData = await Class.findByPk(id);
|
||||
|
||||
if (!classData) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Class not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Update class directly
|
||||
await classData.update(updates);
|
||||
|
||||
// Invalidate related caches
|
||||
await cacheUtils.delete(`class:${id}`);
|
||||
await cacheUtils.deletePattern('classes:list:*');
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Class updated successfully',
|
||||
data: classData,
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -131,51 +163,31 @@ class ClassController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update class (async via BullMQ)
|
||||
*/
|
||||
async updateClass(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
// Add to job queue for async processing
|
||||
const job = await addDatabaseWriteJob('update', 'Class', {
|
||||
id,
|
||||
updates,
|
||||
});
|
||||
|
||||
// Invalidate related caches
|
||||
await cacheUtils.delete(`class:${id}`);
|
||||
await cacheUtils.deletePattern('classes:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
success: true,
|
||||
message: 'Class update job queued',
|
||||
jobId: job.id,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete class (async via BullMQ)
|
||||
* Delete class
|
||||
*/
|
||||
async deleteClass(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
// Add to job queue for async processing
|
||||
const job = await addDatabaseWriteJob('delete', 'Class', { id });
|
||||
const classData = await Class.findByPk(id);
|
||||
|
||||
if (!classData) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Class not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Delete class directly
|
||||
await classData.destroy();
|
||||
|
||||
// Invalidate related caches
|
||||
await cacheUtils.delete(`class:${id}`);
|
||||
await cacheUtils.deletePattern('classes:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Class deletion job queued',
|
||||
jobId: job.id,
|
||||
message: 'Class deleted successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
343
controllers/gameTypeController.js
Normal file
343
controllers/gameTypeController.js
Normal file
@@ -0,0 +1,343 @@
|
||||
const { GameType } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
|
||||
/**
|
||||
* GameType Controller - Quản lý loại trò chơi giáo dục
|
||||
*/
|
||||
class GameTypeController {
|
||||
/**
|
||||
* Get all game types with pagination
|
||||
*/
|
||||
async getAllGameTypes(req, res, next) {
|
||||
try {
|
||||
const { page = 1, limit = 20, is_active, is_premium, difficulty_level } = req.query;
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
const cacheKey = `game_types:list:${page}:${limit}:${is_active || 'all'}:${is_premium || 'all'}:${difficulty_level || 'all'}`;
|
||||
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: cached,
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
|
||||
const where = {};
|
||||
if (is_active !== undefined) where.is_active = is_active === 'true';
|
||||
if (is_premium !== undefined) where.is_premium = is_premium === 'true';
|
||||
if (difficulty_level) where.difficulty_level = difficulty_level;
|
||||
|
||||
const { count, rows } = await GameType.findAndCountAll({
|
||||
where,
|
||||
limit: parseInt(limit),
|
||||
offset: parseInt(offset),
|
||||
order: [['display_order', 'ASC'], ['rating', 'DESC']],
|
||||
});
|
||||
|
||||
const result = {
|
||||
gameTypes: rows,
|
||||
pagination: {
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
limit: parseInt(limit),
|
||||
totalPages: Math.ceil(count / limit),
|
||||
},
|
||||
};
|
||||
|
||||
await cacheUtils.set(cacheKey, result, 1800);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result,
|
||||
cached: false,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get game type by ID
|
||||
*/
|
||||
async getGameTypeById(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const cacheKey = `game_type:${id}`;
|
||||
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: cached,
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
|
||||
const gameType = await GameType.findByPk(id);
|
||||
|
||||
if (!gameType) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Game type not found',
|
||||
});
|
||||
}
|
||||
|
||||
await cacheUtils.set(cacheKey, gameType, 3600);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: gameType,
|
||||
cached: false,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get game type by type code
|
||||
*/
|
||||
async getGameTypeByType(req, res, next) {
|
||||
try {
|
||||
const { type } = req.params;
|
||||
const cacheKey = `game_type:type:${type}`;
|
||||
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: cached,
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
|
||||
const gameType = await GameType.findOne({
|
||||
where: { type },
|
||||
});
|
||||
|
||||
if (!gameType) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Game type not found',
|
||||
});
|
||||
}
|
||||
|
||||
await cacheUtils.set(cacheKey, gameType, 3600);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: gameType,
|
||||
cached: false,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new game type
|
||||
*/
|
||||
async createGameType(req, res, next) {
|
||||
try {
|
||||
const gameTypeData = req.body;
|
||||
|
||||
// Check if type already exists
|
||||
const existingType = await GameType.findOne({
|
||||
where: { type: gameTypeData.type },
|
||||
});
|
||||
|
||||
if (existingType) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Game type with this type code already exists',
|
||||
});
|
||||
}
|
||||
|
||||
const gameType = await GameType.create(gameTypeData);
|
||||
|
||||
// Invalidate cache
|
||||
await cacheUtils.deletePattern('game_types:*');
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
data: gameType,
|
||||
message: 'Game type created successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update game type
|
||||
*/
|
||||
async updateGameType(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updateData = req.body;
|
||||
|
||||
const gameType = await GameType.findByPk(id);
|
||||
|
||||
if (!gameType) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Game type not found',
|
||||
});
|
||||
}
|
||||
|
||||
// If updating type code, check uniqueness
|
||||
if (updateData.type && updateData.type !== gameType.type) {
|
||||
const existingType = await GameType.findOne({
|
||||
where: { type: updateData.type },
|
||||
});
|
||||
|
||||
if (existingType) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'Game type with this type code already exists',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await gameType.update(updateData);
|
||||
|
||||
// Invalidate cache
|
||||
await cacheUtils.del(`game_type:${id}`);
|
||||
await cacheUtils.del(`game_type:type:${gameType.type}`);
|
||||
await cacheUtils.deletePattern('game_types:*');
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: gameType,
|
||||
message: 'Game type updated successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete game type
|
||||
*/
|
||||
async deleteGameType(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const gameType = await GameType.findByPk(id);
|
||||
|
||||
if (!gameType) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Game type not found',
|
||||
});
|
||||
}
|
||||
|
||||
const typeCode = gameType.type;
|
||||
|
||||
await gameType.destroy();
|
||||
|
||||
// Invalidate cache
|
||||
await cacheUtils.del(`game_type:${id}`);
|
||||
await cacheUtils.del(`game_type:type:${typeCode}`);
|
||||
await cacheUtils.deletePattern('game_types:*');
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Game type deleted successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active game types only
|
||||
*/
|
||||
async getActiveGameTypes(req, res, next) {
|
||||
try {
|
||||
const cacheKey = 'game_types:active';
|
||||
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: cached,
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
|
||||
const gameTypes = await GameType.findAll({
|
||||
where: { is_active: true },
|
||||
order: [['display_order', 'ASC'], ['rating', 'DESC']],
|
||||
});
|
||||
|
||||
await cacheUtils.set(cacheKey, gameTypes, 3600);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: gameTypes,
|
||||
cached: false,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get game types statistics
|
||||
*/
|
||||
async getGameTypeStats(req, res, next) {
|
||||
try {
|
||||
const cacheKey = 'game_types:stats';
|
||||
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: cached,
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
|
||||
const [total, active, premium, byDifficulty] = await Promise.all([
|
||||
GameType.count(),
|
||||
GameType.count({ where: { is_active: true } }),
|
||||
GameType.count({ where: { is_premium: true } }),
|
||||
GameType.findAll({
|
||||
attributes: [
|
||||
'difficulty_level',
|
||||
[GameType.sequelize.fn('COUNT', GameType.sequelize.col('id')), 'count'],
|
||||
],
|
||||
group: ['difficulty_level'],
|
||||
}),
|
||||
]);
|
||||
|
||||
const stats = {
|
||||
total,
|
||||
active,
|
||||
premium,
|
||||
inactive: total - active,
|
||||
byDifficulty: byDifficulty.reduce((acc, item) => {
|
||||
if (item.difficulty_level) {
|
||||
acc[item.difficulty_level] = parseInt(item.dataValues.count);
|
||||
}
|
||||
return acc;
|
||||
}, {}),
|
||||
};
|
||||
|
||||
await cacheUtils.set(cacheKey, stats, 1800);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: stats,
|
||||
cached: false,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new GameTypeController();
|
||||
@@ -1,6 +1,6 @@
|
||||
const { Grade, GradeItem, GradeSummary, StudentDetail, Subject, AcademicYear } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob, addGradeCalculationJob } = require('../config/bullmq');
|
||||
const { addGradeCalculationJob } = require('../config/bullmq');
|
||||
|
||||
/**
|
||||
* Grade Controller - Quản lý điểm số
|
||||
@@ -121,22 +121,21 @@ class GradeController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new grade (async via BullMQ)
|
||||
* Create new grade
|
||||
*/
|
||||
async createGrade(req, res, next) {
|
||||
try {
|
||||
const gradeData = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('create', 'Grade', gradeData);
|
||||
const grade = await Grade.create(gradeData);
|
||||
|
||||
await cacheUtils.deletePattern('grades:list:*');
|
||||
await cacheUtils.deletePattern(`grade:student:${gradeData.student_id}:*`);
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Grade creation job queued',
|
||||
jobId: job.id,
|
||||
data: gradeData,
|
||||
message: 'Grade created successfully',
|
||||
data: grade,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -144,25 +143,31 @@ class GradeController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update grade (async via BullMQ)
|
||||
* Update grade
|
||||
*/
|
||||
async updateGrade(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('update', 'Grade', {
|
||||
id,
|
||||
updates,
|
||||
});
|
||||
const grade = await Grade.findByPk(id);
|
||||
|
||||
if (!grade) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Grade not found',
|
||||
});
|
||||
}
|
||||
|
||||
await grade.update(updates);
|
||||
|
||||
await cacheUtils.delete(`grade:${id}`);
|
||||
await cacheUtils.deletePattern('grades:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Grade update job queued',
|
||||
jobId: job.id,
|
||||
message: 'Grade updated successfully',
|
||||
data: grade,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -170,21 +175,29 @@ class GradeController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete grade (async via BullMQ)
|
||||
* Delete grade
|
||||
*/
|
||||
async deleteGrade(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const job = await addDatabaseWriteJob('delete', 'Grade', { id });
|
||||
const grade = await Grade.findByPk(id);
|
||||
|
||||
if (!grade) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Grade not found',
|
||||
});
|
||||
}
|
||||
|
||||
await grade.destroy();
|
||||
|
||||
await cacheUtils.delete(`grade:${id}`);
|
||||
await cacheUtils.deletePattern('grades:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Grade deletion job queued',
|
||||
jobId: job.id,
|
||||
message: 'Grade deleted successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const { ParentAssignedTask, GradeItem, StudentDetail, UsersAuth, ParentStudentMap } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob, addNotificationJob } = require('../config/bullmq');
|
||||
const { addNotificationJob } = require('../config/bullmq');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
|
||||
/**
|
||||
@@ -64,8 +64,8 @@ class ParentTaskController {
|
||||
priority: priority || 'normal',
|
||||
};
|
||||
|
||||
// Async write to DB via BullMQ
|
||||
await addDatabaseWriteJob('create', 'ParentAssignedTask', taskData);
|
||||
// Create task directly in database
|
||||
const task = await ParentAssignedTask.create(taskData);
|
||||
|
||||
// Gửi notification cho học sinh
|
||||
await addNotificationJob({
|
||||
@@ -80,10 +80,10 @@ class ParentTaskController {
|
||||
await cacheUtils.del(`parent:tasks:${parent_id}`);
|
||||
await cacheUtils.del(`student:tasks:${student_id}`);
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Task assignment request queued',
|
||||
data: taskData,
|
||||
message: 'Task assigned successfully',
|
||||
data: task,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -138,11 +138,7 @@ class ParentTaskController {
|
||||
for (const task of tasks) {
|
||||
if (task.status !== 'completed' && new Date(task.due_date) < now) {
|
||||
if (task.status !== 'overdue') {
|
||||
await addDatabaseWriteJob('update', 'ParentAssignedTask', {
|
||||
id: task.id,
|
||||
status: 'overdue',
|
||||
});
|
||||
task.status = 'overdue';
|
||||
await task.update({ status: 'overdue' });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,8 +231,7 @@ class ParentTaskController {
|
||||
});
|
||||
}
|
||||
|
||||
await addDatabaseWriteJob('update', 'ParentAssignedTask', {
|
||||
id,
|
||||
await task.update({
|
||||
status: 'completed',
|
||||
completion_date: new Date(),
|
||||
student_notes: student_notes || null,
|
||||
@@ -255,9 +250,10 @@ class ParentTaskController {
|
||||
await cacheUtils.del(`parent:tasks:${task.parent_id}:*`);
|
||||
await cacheUtils.del(`student:tasks:${task.student_id}:*`);
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Task completion request queued',
|
||||
message: 'Task completed successfully',
|
||||
data: task,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -288,18 +284,16 @@ class ParentTaskController {
|
||||
});
|
||||
}
|
||||
|
||||
await addDatabaseWriteJob('update', 'ParentAssignedTask', {
|
||||
id,
|
||||
status,
|
||||
});
|
||||
await task.update({ status });
|
||||
|
||||
// Clear cache
|
||||
await cacheUtils.del(`parent:tasks:${task.parent_id}:*`);
|
||||
await cacheUtils.del(`student:tasks:${task.student_id}:*`);
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Task status update queued',
|
||||
message: 'Task status updated successfully',
|
||||
data: task,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -330,15 +324,15 @@ class ParentTaskController {
|
||||
});
|
||||
}
|
||||
|
||||
await addDatabaseWriteJob('delete', 'ParentAssignedTask', { id });
|
||||
await task.destroy();
|
||||
|
||||
// Clear cache
|
||||
await cacheUtils.del(`parent:tasks:${task.parent_id}:*`);
|
||||
await cacheUtils.del(`student:tasks:${task.student_id}:*`);
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Task deletion request queued',
|
||||
message: 'Task deleted successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const { Room, School } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
|
||||
/**
|
||||
* Room Controller - Quản lý phòng học
|
||||
@@ -97,21 +96,20 @@ class RoomController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new room (async via BullMQ)
|
||||
* Create new room
|
||||
*/
|
||||
async createRoom(req, res, next) {
|
||||
try {
|
||||
const roomData = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('create', 'Room', roomData);
|
||||
const room = await Room.create(roomData);
|
||||
|
||||
await cacheUtils.deletePattern('rooms:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Room creation job queued',
|
||||
jobId: job.id,
|
||||
data: roomData,
|
||||
message: 'Room created successfully',
|
||||
data: room,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -119,25 +117,31 @@ class RoomController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update room (async via BullMQ)
|
||||
* Update room
|
||||
*/
|
||||
async updateRoom(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('update', 'Room', {
|
||||
id,
|
||||
updates,
|
||||
});
|
||||
const room = await Room.findByPk(id);
|
||||
|
||||
if (!room) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Room not found',
|
||||
});
|
||||
}
|
||||
|
||||
await room.update(updates);
|
||||
|
||||
await cacheUtils.delete(`room:${id}`);
|
||||
await cacheUtils.deletePattern('rooms:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Room update job queued',
|
||||
jobId: job.id,
|
||||
message: 'Room updated successfully',
|
||||
data: room,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -145,21 +149,29 @@ class RoomController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete room (async via BullMQ)
|
||||
* Delete room
|
||||
*/
|
||||
async deleteRoom(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const job = await addDatabaseWriteJob('delete', 'Room', { id });
|
||||
const room = await Room.findByPk(id);
|
||||
|
||||
if (!room) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Room not found',
|
||||
});
|
||||
}
|
||||
|
||||
await room.destroy();
|
||||
|
||||
await cacheUtils.delete(`room:${id}`);
|
||||
await cacheUtils.deletePattern('rooms:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Room deletion job queued',
|
||||
jobId: job.id,
|
||||
message: 'Room deleted successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const { School } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
|
||||
/**
|
||||
* School Controller - Quản lý thông tin trường học
|
||||
@@ -108,12 +107,11 @@ class SchoolController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new school - Push to BullMQ
|
||||
* Create new school
|
||||
*/
|
||||
async createSchool(req, res, next) {
|
||||
try {
|
||||
const schoolData = req.body;
|
||||
const userId = req.user?.id; // From auth middleware
|
||||
|
||||
// Validate required fields (you can use Joi for this)
|
||||
if (!schoolData.school_code || !schoolData.school_name || !schoolData.school_type) {
|
||||
@@ -123,22 +121,14 @@ class SchoolController {
|
||||
});
|
||||
}
|
||||
|
||||
// Add job to BullMQ queue
|
||||
const job = await addDatabaseWriteJob(
|
||||
'create',
|
||||
'School',
|
||||
schoolData,
|
||||
{ userId, priority: 3 }
|
||||
);
|
||||
const newSchool = await School.create(schoolData);
|
||||
|
||||
res.status(202).json({
|
||||
await cacheUtils.deletePattern('schools:list:*');
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'School creation queued',
|
||||
jobId: job.id,
|
||||
data: {
|
||||
school_code: schoolData.school_code,
|
||||
school_name: schoolData.school_name,
|
||||
},
|
||||
message: 'School created successfully',
|
||||
data: newSchool,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -146,44 +136,31 @@ class SchoolController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update school - Push to BullMQ
|
||||
* Update school
|
||||
*/
|
||||
async updateSchool(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updateData = req.body;
|
||||
const userId = req.user?.id;
|
||||
|
||||
// Check if school exists (from cache or DB)
|
||||
const cacheKey = `school:${id}`;
|
||||
let school = await cacheUtils.get(cacheKey);
|
||||
|
||||
const school = await School.findByPk(id);
|
||||
if (!school) {
|
||||
school = await School.findByPk(id);
|
||||
if (!school) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'School not found',
|
||||
});
|
||||
}
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'School not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Add update job to BullMQ
|
||||
const job = await addDatabaseWriteJob(
|
||||
'update',
|
||||
'School',
|
||||
{ id, ...updateData },
|
||||
{ userId, priority: 3 }
|
||||
);
|
||||
await school.update(updateData);
|
||||
|
||||
// Invalidate cache
|
||||
await cacheUtils.delete(cacheKey);
|
||||
await cacheUtils.delete(`school:${id}`);
|
||||
await cacheUtils.deletePattern('schools:list:*');
|
||||
|
||||
res.json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'School update queued',
|
||||
jobId: job.id,
|
||||
message: 'School updated successfully',
|
||||
data: school,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -191,12 +168,11 @@ class SchoolController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete school - Push to BullMQ
|
||||
* Delete school (soft delete)
|
||||
*/
|
||||
async deleteSchool(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const userId = req.user?.id;
|
||||
|
||||
// Check if school exists
|
||||
const school = await School.findByPk(id);
|
||||
@@ -208,21 +184,16 @@ class SchoolController {
|
||||
}
|
||||
|
||||
// Soft delete - just mark as inactive
|
||||
const job = await addDatabaseWriteJob(
|
||||
'update',
|
||||
'School',
|
||||
{ id, is_active: false },
|
||||
{ userId, priority: 3 }
|
||||
);
|
||||
await school.update({ is_active: false });
|
||||
|
||||
// Invalidate cache
|
||||
await cacheUtils.delete(`school:${id}`);
|
||||
await cacheUtils.deletePattern('schools:list:*');
|
||||
|
||||
res.json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'School deletion queued',
|
||||
jobId: job.id,
|
||||
message: 'School deactivated successfully',
|
||||
data: school,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const { StudentDetail, UserProfile, UsersAuth, Class } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
|
||||
/**
|
||||
* Student Controller - Quản lý học sinh
|
||||
@@ -120,21 +119,20 @@ class StudentController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new student (async via BullMQ)
|
||||
* Create new student
|
||||
*/
|
||||
async createStudent(req, res, next) {
|
||||
try {
|
||||
const studentData = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('create', 'StudentDetail', studentData);
|
||||
const newStudent = await StudentDetail.create(studentData);
|
||||
|
||||
await cacheUtils.deletePattern('students:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Student creation job queued',
|
||||
jobId: job.id,
|
||||
data: studentData,
|
||||
message: 'Student created successfully',
|
||||
data: newStudent,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -142,25 +140,30 @@ class StudentController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update student (async via BullMQ)
|
||||
* Update student
|
||||
*/
|
||||
async updateStudent(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('update', 'StudentDetail', {
|
||||
id,
|
||||
updates,
|
||||
});
|
||||
const student = await StudentDetail.findByPk(id);
|
||||
if (!student) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Student not found',
|
||||
});
|
||||
}
|
||||
|
||||
await student.update(updates);
|
||||
|
||||
await cacheUtils.delete(`student:${id}`);
|
||||
await cacheUtils.deletePattern('students:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Student update job queued',
|
||||
jobId: job.id,
|
||||
message: 'Student updated successfully',
|
||||
data: student,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -174,18 +177,23 @@ class StudentController {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const job = await addDatabaseWriteJob('update', 'StudentDetail', {
|
||||
id,
|
||||
updates: { status: 'dropped' },
|
||||
});
|
||||
const student = await StudentDetail.findByPk(id);
|
||||
if (!student) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Student not found',
|
||||
});
|
||||
}
|
||||
|
||||
await student.update({ status: 'dropped' });
|
||||
|
||||
await cacheUtils.delete(`student:${id}`);
|
||||
await cacheUtils.deletePattern('students:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Student deletion job queued',
|
||||
jobId: job.id,
|
||||
message: 'Student status updated to dropped',
|
||||
data: student,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const { Subject, Chapter } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
|
||||
/**
|
||||
* Subject Controller - Quản lý môn học
|
||||
@@ -147,22 +146,20 @@ class SubjectController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new subject (async via BullMQ)
|
||||
* Create new subject
|
||||
*/
|
||||
async createSubject(req, res, next) {
|
||||
try {
|
||||
const subjectData = req.body;
|
||||
|
||||
// Add to job queue for async processing
|
||||
const job = await addDatabaseWriteJob('create', 'Subject', subjectData);
|
||||
const subject = await Subject.create(subjectData);
|
||||
|
||||
// Note: Cache will be invalidated by worker after successful creation
|
||||
await cacheUtils.deletePattern('subjects:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Subject creation job queued',
|
||||
jobId: job.id,
|
||||
data: subjectData,
|
||||
message: 'Subject created successfully',
|
||||
data: subject,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -170,25 +167,31 @@ class SubjectController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update subject (async via BullMQ)
|
||||
* Update subject
|
||||
*/
|
||||
async updateSubject(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
// Add to job queue for async processing
|
||||
const job = await addDatabaseWriteJob('update', 'Subject', {
|
||||
id,
|
||||
updates,
|
||||
});
|
||||
const subject = await Subject.findByPk(id);
|
||||
|
||||
// Note: Cache will be invalidated by worker after successful update
|
||||
if (!subject) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Subject not found',
|
||||
});
|
||||
}
|
||||
|
||||
res.status(202).json({
|
||||
await subject.update(updates);
|
||||
|
||||
await cacheUtils.delete(`subject:${id}`);
|
||||
await cacheUtils.deletePattern('subjects:list:*');
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Subject update job queued',
|
||||
jobId: job.id,
|
||||
message: 'Subject updated successfully',
|
||||
data: subject,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -196,21 +199,29 @@ class SubjectController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete subject (async via BullMQ)
|
||||
* Delete subject
|
||||
*/
|
||||
async deleteSubject(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
// Add to job queue for async processing
|
||||
const job = await addDatabaseWriteJob('delete', 'Subject', { id });
|
||||
const subject = await Subject.findByPk(id);
|
||||
|
||||
// Note: Cache will be invalidated by worker after successful deletion
|
||||
if (!subject) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Subject not found',
|
||||
});
|
||||
}
|
||||
|
||||
res.status(202).json({
|
||||
await subject.destroy();
|
||||
|
||||
await cacheUtils.delete(`subject:${id}`);
|
||||
await cacheUtils.deletePattern('subjects:list:*');
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Subject deletion job queued',
|
||||
jobId: job.id,
|
||||
message: 'Subject deleted successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const { SubscriptionPlan, UserSubscription, UsersAuth } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
|
||||
/**
|
||||
@@ -98,16 +97,15 @@ class SubscriptionController {
|
||||
auto_renew: req.body.auto_renew || false,
|
||||
};
|
||||
|
||||
// Async write to DB via BullMQ
|
||||
await addDatabaseWriteJob('create', 'UserSubscription', subscriptionData);
|
||||
const newSubscription = await UserSubscription.create(subscriptionData);
|
||||
|
||||
// Clear cache
|
||||
await cacheUtils.del(`subscription:user:${user_id}`);
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Subscription purchase request queued',
|
||||
data: subscriptionData,
|
||||
message: 'Subscription purchased successfully',
|
||||
data: newSubscription,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -153,11 +151,7 @@ class SubscriptionController {
|
||||
// Check nếu subscription đã hết hạn
|
||||
const now = new Date();
|
||||
if (subscription.status === 'active' && new Date(subscription.end_date) < now) {
|
||||
subscription.status = 'expired';
|
||||
await addDatabaseWriteJob('update', 'UserSubscription', {
|
||||
id: subscription.id,
|
||||
status: 'expired',
|
||||
});
|
||||
await subscription.update({ status: 'expired' });
|
||||
}
|
||||
|
||||
await cacheUtils.set(cacheKey, subscription, 900); // Cache 15 min
|
||||
@@ -195,9 +189,8 @@ class SubscriptionController {
|
||||
});
|
||||
}
|
||||
|
||||
// Async update via BullMQ
|
||||
await addDatabaseWriteJob('update', 'UserSubscription', {
|
||||
id,
|
||||
// Update subscription
|
||||
await subscription.update({
|
||||
status: 'cancelled',
|
||||
auto_renew: false,
|
||||
});
|
||||
@@ -205,9 +198,10 @@ class SubscriptionController {
|
||||
// Clear cache
|
||||
await cacheUtils.del(`subscription:user:${subscription.user_id}`);
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Subscription cancellation request queued',
|
||||
message: 'Subscription cancelled successfully',
|
||||
data: subscription,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const { TeacherDetail, UserProfile, UsersAuth } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
const teacherProfileService = require('../services/teacherProfileService');
|
||||
|
||||
/**
|
||||
@@ -205,25 +204,30 @@ class TeacherController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update teacher (async via BullMQ)
|
||||
* Update teacher
|
||||
*/
|
||||
async updateTeacher(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('update', 'TeacherDetail', {
|
||||
id,
|
||||
updates,
|
||||
});
|
||||
const teacher = await TeacherDetail.findByPk(id);
|
||||
if (!teacher) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Teacher not found',
|
||||
});
|
||||
}
|
||||
|
||||
await teacher.update(updates);
|
||||
|
||||
await cacheUtils.delete(`teacher:${id}`);
|
||||
await cacheUtils.deletePattern('teachers:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Teacher update job queued',
|
||||
jobId: job.id,
|
||||
message: 'Teacher updated successfully',
|
||||
data: teacher,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -237,17 +241,28 @@ class TeacherController {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const job = await addDatabaseWriteJob('update', 'TeacherDetail', {
|
||||
id,
|
||||
updates: { status: 'resigned' },
|
||||
});
|
||||
const teacher = await TeacherDetail.findByPk(id);
|
||||
if (!teacher) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Teacher not found',
|
||||
});
|
||||
}
|
||||
|
||||
await teacher.update({ status: 'resigned' });
|
||||
|
||||
await cacheUtils.delete(`teacher:${id}`);
|
||||
await cacheUtils.deletePattern('teachers:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Teacher deletion job queued',
|
||||
message: 'Teacher status updated to resigned',
|
||||
data: teacher,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
jobId: job.id,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const { StaffTrainingAssignment, StaffAchievement, UsersAuth, Subject } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
|
||||
/**
|
||||
@@ -55,11 +54,7 @@ class TrainingController {
|
||||
for (const assignment of assignments) {
|
||||
if (assignment.status !== 'completed' && new Date(assignment.deadline) < now) {
|
||||
if (assignment.status !== 'overdue') {
|
||||
await addDatabaseWriteJob('update', 'StaffTrainingAssignment', {
|
||||
id: assignment.id,
|
||||
status: 'overdue',
|
||||
});
|
||||
assignment.status = 'overdue';
|
||||
await assignment.update({ status: 'overdue' });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,16 +97,15 @@ class TrainingController {
|
||||
notes: notes || null,
|
||||
};
|
||||
|
||||
// Async write to DB via BullMQ
|
||||
await addDatabaseWriteJob('create', 'StaffTrainingAssignment', assignmentData);
|
||||
const newAssignment = await StaffTrainingAssignment.create(assignmentData);
|
||||
|
||||
// Clear cache
|
||||
await cacheUtils.del(`training:assignments:${staff_id}:*`);
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Training assignment request queued',
|
||||
data: assignmentData,
|
||||
message: 'Training assignment created successfully',
|
||||
data: newAssignment,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -142,17 +136,15 @@ class TrainingController {
|
||||
});
|
||||
}
|
||||
|
||||
await addDatabaseWriteJob('update', 'StaffTrainingAssignment', {
|
||||
id,
|
||||
status,
|
||||
});
|
||||
await assignment.update({ status });
|
||||
|
||||
// Clear cache
|
||||
await cacheUtils.del(`training:assignments:${assignment.staff_id}:*`);
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'Assignment status update queued',
|
||||
message: 'Assignment status updated successfully',
|
||||
data: assignment,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -199,16 +191,15 @@ class TrainingController {
|
||||
verified_at: verified_by ? new Date() : null,
|
||||
};
|
||||
|
||||
// Async write to DB via BullMQ
|
||||
await addDatabaseWriteJob('create', 'StaffAchievement', achievementData);
|
||||
const newAchievement = await StaffAchievement.create(achievementData);
|
||||
|
||||
// Clear cache
|
||||
await cacheUtils.del(`training:achievements:${staff_id}`);
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Achievement creation request queued',
|
||||
data: achievementData,
|
||||
message: 'Achievement created successfully',
|
||||
data: newAchievement,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const { UsersAuth, UserProfile } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
const bcrypt = require('bcrypt');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const crypto = require('crypto');
|
||||
@@ -404,21 +403,20 @@ class UserController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new user (async via BullMQ)
|
||||
* Create new user
|
||||
*/
|
||||
async createUser(req, res, next) {
|
||||
try {
|
||||
const userData = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('create', 'UsersAuth', userData);
|
||||
const newUser = await UsersAuth.create(userData);
|
||||
|
||||
await cacheUtils.deletePattern('users:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'User creation job queued',
|
||||
jobId: job.id,
|
||||
data: userData,
|
||||
message: 'User created successfully',
|
||||
data: newUser,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -426,25 +424,30 @@ class UserController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user (async via BullMQ)
|
||||
* Update user
|
||||
*/
|
||||
async updateUser(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('update', 'UsersAuth', {
|
||||
id,
|
||||
updates,
|
||||
});
|
||||
const user = await UsersAuth.findByPk(id);
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'User not found',
|
||||
});
|
||||
}
|
||||
|
||||
await user.update(updates);
|
||||
|
||||
await cacheUtils.delete(`user:${id}`);
|
||||
await cacheUtils.deletePattern('users:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'User update job queued',
|
||||
jobId: job.id,
|
||||
message: 'User updated successfully',
|
||||
data: user,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
@@ -458,18 +461,23 @@ class UserController {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const job = await addDatabaseWriteJob('update', 'UsersAuth', {
|
||||
id,
|
||||
updates: { is_active: false },
|
||||
});
|
||||
const user = await UsersAuth.findByPk(id);
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'User not found',
|
||||
});
|
||||
}
|
||||
|
||||
await user.update({ is_active: false });
|
||||
|
||||
await cacheUtils.delete(`user:${id}`);
|
||||
await cacheUtils.deletePattern('users:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'User deletion job queued',
|
||||
jobId: job.id,
|
||||
message: 'User deactivated successfully',
|
||||
data: user,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
|
||||
Reference in New Issue
Block a user