update
This commit is contained in:
274
controllers/teacherController.js
Normal file
274
controllers/teacherController.js
Normal file
@@ -0,0 +1,274 @@
|
||||
const { TeacherDetail, UserProfile, UsersAuth } = require('../models');
|
||||
const { cacheUtils } = require('../config/redis');
|
||||
const { addDatabaseWriteJob } = require('../config/bullmq');
|
||||
const teacherProfileService = require('../services/teacherProfileService');
|
||||
|
||||
/**
|
||||
* Teacher Controller - Quản lý giáo viên
|
||||
*/
|
||||
class TeacherController {
|
||||
/**
|
||||
* Get all teachers with pagination and caching
|
||||
*/
|
||||
async getAllTeachers(req, res, next) {
|
||||
try {
|
||||
const { page = 1, limit = 20, status, teacher_type, school_id } = req.query;
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
const cacheKey = `teachers:list:${page}:${limit}:${status || 'all'}:${teacher_type || 'all'}:${school_id || 'all'}`;
|
||||
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: cached,
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
|
||||
const where = {};
|
||||
if (status) where.status = status;
|
||||
if (teacher_type) where.teacher_type = teacher_type;
|
||||
|
||||
// Query teachers
|
||||
const { count, rows } = await TeacherDetail.findAndCountAll({
|
||||
where,
|
||||
limit: parseInt(limit),
|
||||
offset: parseInt(offset),
|
||||
order: [['created_at', 'DESC']],
|
||||
});
|
||||
|
||||
// Manually fetch profiles for each teacher
|
||||
const teachersWithProfiles = await Promise.all(
|
||||
rows.map(async (teacher) => {
|
||||
const profile = await UserProfile.findOne({
|
||||
where: { user_id: teacher.user_id },
|
||||
attributes: ['id', 'full_name', 'phone', 'date_of_birth', 'gender', 'address', 'school_id', 'city', 'district', 'avatar_url'],
|
||||
});
|
||||
|
||||
// Filter by school_id if provided
|
||||
if (school_id && (!profile || profile.school_id !== school_id)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
...teacher.toJSON(),
|
||||
profile: profile ? profile.toJSON() : null,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
// Filter out nulls (teachers not matching school_id)
|
||||
const filteredTeachers = teachersWithProfiles.filter(t => t !== null);
|
||||
|
||||
const result = {
|
||||
teachers: filteredTeachers,
|
||||
pagination: {
|
||||
total: school_id ? filteredTeachers.length : count,
|
||||
page: parseInt(page),
|
||||
limit: parseInt(limit),
|
||||
totalPages: Math.ceil((school_id ? filteredTeachers.length : count) / limit),
|
||||
},
|
||||
};
|
||||
|
||||
await cacheUtils.set(cacheKey, result, 1800);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result,
|
||||
cached: false,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get teacher by ID with manual profile fetch
|
||||
*/
|
||||
async getTeacherById(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const cacheKey = `teacher:${id}`;
|
||||
|
||||
const cached = await cacheUtils.get(cacheKey);
|
||||
if (cached) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: cached,
|
||||
cached: true,
|
||||
});
|
||||
}
|
||||
|
||||
const teacher = await TeacherDetail.findByPk(id);
|
||||
|
||||
if (!teacher) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Teacher not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Manually fetch profile
|
||||
const profile = await UserProfile.findOne({
|
||||
where: { user_id: teacher.user_id },
|
||||
});
|
||||
|
||||
const teacherData = {
|
||||
...teacher.toJSON(),
|
||||
profile: profile ? profile.toJSON() : null,
|
||||
};
|
||||
|
||||
await cacheUtils.set(cacheKey, teacherData, 3600);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: teacherData,
|
||||
cached: false,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new teacher with full profile (users_auth + user_profile + teacher_detail)
|
||||
*/
|
||||
async createTeacher(req, res, next) {
|
||||
try {
|
||||
const teacherData = req.body;
|
||||
|
||||
// Use service to create full teacher profile
|
||||
const result = await teacherProfileService.createTeacherWithProfile(teacherData);
|
||||
|
||||
// Clear cache
|
||||
await cacheUtils.deletePattern('teachers:list:*');
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: 'Teacher created successfully',
|
||||
data: {
|
||||
user_id: result.user_id,
|
||||
username: result.username,
|
||||
email: result.email,
|
||||
temporary_password: result.temporary_password, // null if user provided password
|
||||
teacher_code: result.teacher_detail.teacher_code,
|
||||
teacher_type: result.teacher_detail.teacher_type,
|
||||
profile: {
|
||||
full_name: result.profile.full_name,
|
||||
needs_update: result.profile.etc?.needs_profile_update || false,
|
||||
}
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update teacher profile (cho phép user tự cập nhật)
|
||||
*/
|
||||
async updateTeacherProfile(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params; // user_id or teacher_id
|
||||
const profileData = req.body;
|
||||
|
||||
// Nếu id là teacher_id, tìm user_id
|
||||
let userId = id;
|
||||
if (profileData.teacher_id) {
|
||||
const teacher = await TeacherDetail.findByPk(profileData.teacher_id);
|
||||
if (!teacher) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Teacher not found',
|
||||
});
|
||||
}
|
||||
userId = teacher.user_id;
|
||||
}
|
||||
|
||||
// Update profile
|
||||
const updatedProfile = await teacherProfileService.updateTeacherProfile(userId, profileData);
|
||||
|
||||
// Clear cache
|
||||
await cacheUtils.delete(`teacher:${id}`);
|
||||
await cacheUtils.delete(`user:profile:${userId}`);
|
||||
await cacheUtils.deletePattern('teachers:list:*');
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Teacher profile updated successfully',
|
||||
data: updatedProfile,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update teacher (async via BullMQ)
|
||||
*/
|
||||
async updateTeacher(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const updates = req.body;
|
||||
|
||||
const job = await addDatabaseWriteJob('update', 'TeacherDetail', {
|
||||
id,
|
||||
updates,
|
||||
});
|
||||
|
||||
await cacheUtils.delete(`teacher:${id}`);
|
||||
await cacheUtils.deletePattern('teachers:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
success: true,
|
||||
message: 'Teacher update job queued',
|
||||
jobId: job.id,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete teacher (update status to resigned)
|
||||
*/
|
||||
async deleteTeacher(req, res, next) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const job = await addDatabaseWriteJob('update', 'TeacherDetail', {
|
||||
id,
|
||||
updates: { status: 'resigned' },
|
||||
});
|
||||
|
||||
await cacheUtils.delete(`teacher:${id}`);
|
||||
await cacheUtils.deletePattern('teachers:list:*');
|
||||
|
||||
res.status(202).json({
|
||||
success: true,
|
||||
message: 'Teacher deletion job queued',
|
||||
jobId: job.id,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get teacher datatypes
|
||||
*/
|
||||
async getTeacherDatatypes(req, res, next) {
|
||||
try {
|
||||
const datatypes = TeacherDetail.rawAttributes;
|
||||
res.json({
|
||||
success: true,
|
||||
data: datatypes,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new TeacherController();
|
||||
Reference in New Issue
Block a user