update
This commit is contained in:
302
controllers/schoolController.js
Normal file
302
controllers/schoolController.js
Normal file
@@ -0,0 +1,302 @@
|
||||
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
|
||||
*/
|
||||
class SchoolController {
|
||||
/**
|
||||
* Get all schools with pagination and caching
|
||||
*/
|
||||
async getAllSchools(req, res, next) {
|
||||
try {
|
||||
const { page = 1, limit = 20, type, city, is_active } = req.query;
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
// Generate cache key
|
||||
const cacheKey = `schools:list:${page}:${limit}:${type || 'all'}:${city || 'all'}:${is_active || 'all'}`;
|
||||
|
||||
// Try to get from cache first
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: cached,
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Build query conditions
|
||||
const where = {};
|
||||
if (type) where.school_type = type;
|
||||
if (city) where.city = city;
|
||||
if (is_active !== undefined) {
|
||||
where.is_active = is_active === 'true' || is_active === true;
|
||||
}
|
||||
|
||||
// Query from database (through ProxySQL)
|
||||
const { count, rows } = await School.findAndCountAll({
|
||||
where,
|
||||
limit: parseInt(limit),
|
||||
offset: parseInt(offset),
|
||||
order: [['school_name', 'ASC']],
|
||||
attributes: { exclude: ['config'] }, // Exclude sensitive data
|
||||
});
|
||||
|
||||
const result = {
|
||||
schools: rows,
|
||||
pagination: {
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
limit: parseInt(limit),
|
||||
totalPages: Math.ceil(count / limit),
|
||||
},
|
||||
};
|
||||
|
||||
// Cache the result
|
||||
await cacheUtils.set(cacheKey, result, 3600); // Cache for 1 hour
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result,
|
||||
cached: false,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get school by ID with caching
|
||||
*/
|
||||
async getSchoolById(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const cacheKey = `school:${id}`;
|
||||
|
||||
// Try cache first
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: cached,
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Query from database
|
||||
const school = await School.findByPk(id);
|
||||
|
||||
if (!school) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'School not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Cache the result
|
||||
await cacheUtils.set(cacheKey, school, 7200); // Cache for 2 hours
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: school,
|
||||
cached: false,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new school - Push to BullMQ
|
||||
*/
|
||||
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) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Missing required fields',
|
||||
});
|
||||
}
|
||||
|
||||
// Add job to BullMQ queue
|
||||
const job = await addDatabaseWriteJob(
|
||||
'create',
|
||||
'School',
|
||||
schoolData,
|
||||
{ userId, priority: 3 }
|
||||
);
|
||||
|
||||
res.status(202).json({
|
||||
success: true,
|
||||
message: 'School creation queued',
|
||||
jobId: job.id,
|
||||
data: {
|
||||
school_code: schoolData.school_code,
|
||||
school_name: schoolData.school_name,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update school - Push to BullMQ
|
||||
*/
|
||||
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);
|
||||
|
||||
if (!school) {
|
||||
school = await School.findByPk(id);
|
||||
if (!school) {
|
||||
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 }
|
||||
);
|
||||
|
||||
// Invalidate cache
|
||||
await cacheUtils.delete(cacheKey);
|
||||
await cacheUtils.deletePattern('schools:list:*');
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'School update queued',
|
||||
jobId: job.id,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete school - Push to BullMQ
|
||||
*/
|
||||
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);
|
||||
if (!school) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'School not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Soft delete - just mark as inactive
|
||||
const job = await addDatabaseWriteJob(
|
||||
'update',
|
||||
'School',
|
||||
{ id, is_active: false },
|
||||
{ userId, priority: 3 }
|
||||
);
|
||||
|
||||
// Invalidate cache
|
||||
await cacheUtils.delete(`school:${id}`);
|
||||
await cacheUtils.deletePattern('schools:list:*');
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'School deletion queued',
|
||||
jobId: job.id,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get school statistics
|
||||
*/
|
||||
async getSchoolStats(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const cacheKey = `school:${id}:stats`;
|
||||
|
||||
// Try cache first
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: cached,
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Get school with related data
|
||||
const school = await School.findByPk(id, {
|
||||
include: [
|
||||
{ association: 'classes', attributes: ['id'] },
|
||||
{ association: 'rooms', attributes: ['id'] },
|
||||
],
|
||||
});
|
||||
|
||||
if (!school) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'School not found',
|
||||
});
|
||||
}
|
||||
|
||||
const stats = {
|
||||
school_id: id,
|
||||
school_name: school.school_name,
|
||||
total_classes: school.classes?.length || 0,
|
||||
total_rooms: school.rooms?.length || 0,
|
||||
capacity: school.capacity,
|
||||
};
|
||||
|
||||
// Cache for 30 minutes
|
||||
await cacheUtils.set(cacheKey, stats, 1800);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: stats,
|
||||
cached: false,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get school datatypes
|
||||
*/
|
||||
async getSchoolDatatypes(req, res, next) {
|
||||
try {
|
||||
const datatypes = School.rawAttributes;
|
||||
res.json({
|
||||
success: true,
|
||||
data: datatypes,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new SchoolController();
|
||||
Reference in New Issue
Block a user