Files
sena_db_api_layer/controllers/trainingController.js
silverpro89 3791b7cae1
All checks were successful
Deploy to Production / deploy (push) Successful in 21s
update
2026-01-28 11:21:21 +07:00

310 lines
8.3 KiB
JavaScript

const { StaffTrainingAssignment, StaffAchievement, UsersAuth, Subject } = require('../models');
const { cacheUtils } = require('../config/redis');
const { v4: uuidv4 } = require('uuid');
/**
* Training Controller - Quản lý đào tạo nhân sự
*/
class TrainingController {
/**
* GET /api/training/assignments/:staff_id - Danh sách khóa học bắt buộc của nhân viên
*/
async getStaffAssignments(req, res, next) {
try {
const { staff_id } = req.params;
const { status, priority } = req.query;
const cacheKey = `training:assignments:${staff_id}:${status || 'all'}:${priority || 'all'}`;
const cached = await cacheUtils.get(cacheKey);
if (cached) {
return res.json({
success: true,
data: cached,
cached: true,
});
}
const where = { staff_id };
if (status) where.status = status;
if (priority) where.priority = priority;
const assignments = await StaffTrainingAssignment.findAll({
where,
include: [
{
model: Subject,
as: 'subject',
attributes: ['subject_name', 'subject_code', 'description'],
},
{
model: UsersAuth,
as: 'assignedBy',
attributes: ['username', 'full_name'],
},
],
order: [
['priority', 'DESC'],
['deadline', 'ASC'],
],
});
// Check for overdue assignments
const now = new Date();
for (const assignment of assignments) {
if (assignment.status !== 'completed' && new Date(assignment.deadline) < now) {
if (assignment.status !== 'overdue') {
await assignment.update({ status: 'overdue' });
}
}
}
await cacheUtils.set(cacheKey, assignments, 900); // Cache 15 min
res.json({
success: true,
data: assignments,
});
} catch (error) {
next(error);
}
}
/**
* POST /api/training/assignments - Phân công đào tạo mới
*/
async assignTraining(req, res, next) {
try {
const { staff_id, course_name, subject_id, deadline, priority, notes, assigned_by } = req.body;
if (!staff_id || !course_name || !deadline || !assigned_by) {
return res.status(400).json({
success: false,
message: 'Missing required fields: staff_id, course_name, deadline, assigned_by',
});
}
const assignmentData = {
id: uuidv4(),
staff_id,
course_name,
subject_id: subject_id || null,
assigned_by,
assigned_date: new Date(),
deadline: new Date(deadline),
status: 'pending',
priority: priority || 'normal',
notes: notes || null,
};
const newAssignment = await StaffTrainingAssignment.create(assignmentData);
// Clear cache
await cacheUtils.del(`training:assignments:${staff_id}:*`);
res.status(201).json({
success: true,
message: 'Training assignment created successfully',
data: newAssignment,
});
} catch (error) {
next(error);
}
}
/**
* PUT /api/training/assignments/:id/status - Cập nhật trạng thái assignment
*/
async updateAssignmentStatus(req, res, next) {
try {
const { id } = req.params;
const { status } = req.body;
const validStatuses = ['pending', 'in_progress', 'completed', 'overdue'];
if (!validStatuses.includes(status)) {
return res.status(400).json({
success: false,
message: `Invalid status. Must be one of: ${validStatuses.join(', ')}`,
});
}
const assignment = await StaffTrainingAssignment.findByPk(id);
if (!assignment) {
return res.status(404).json({
success: false,
message: 'Assignment not found',
});
}
await assignment.update({ status });
// Clear cache
await cacheUtils.del(`training:assignments:${assignment.staff_id}:*`);
res.status(200).json({
success: true,
message: 'Assignment status updated successfully',
data: assignment,
});
} catch (error) {
next(error);
}
}
/**
* POST /api/training/achievements - Ghi nhận hoàn thành khóa đào tạo
*/
async createAchievement(req, res, next) {
try {
const {
staff_id,
course_name,
course_id,
completion_date,
certificate_url,
certificate_code,
type,
score,
total_hours,
verified_by,
} = req.body;
if (!staff_id || !course_name || !completion_date) {
return res.status(400).json({
success: false,
message: 'Missing required fields: staff_id, course_name, completion_date',
});
}
const achievementData = {
id: uuidv4(),
staff_id,
course_name,
course_id: course_id || null,
completion_date: new Date(completion_date),
certificate_url: certificate_url || null,
certificate_code: certificate_code || null,
type: type || 'mandatory',
score: score || null,
total_hours: total_hours || null,
verified_by: verified_by || null,
verified_at: verified_by ? new Date() : null,
};
const newAchievement = await StaffAchievement.create(achievementData);
// Clear cache
await cacheUtils.del(`training:achievements:${staff_id}`);
res.status(201).json({
success: true,
message: 'Achievement created successfully',
data: newAchievement,
});
} catch (error) {
next(error);
}
}
/**
* GET /api/training/achievements/:staff_id - Danh sách chứng chỉ của nhân viên
*/
async getStaffAchievements(req, res, next) {
try {
const { staff_id } = req.params;
const { type } = req.query;
const cacheKey = `training:achievements:${staff_id}:${type || 'all'}`;
const cached = await cacheUtils.get(cacheKey);
if (cached) {
return res.json({
success: true,
data: cached,
cached: true,
});
}
const where = { staff_id };
if (type) where.type = type;
const achievements = await StaffAchievement.findAll({
where,
include: [
{
model: Subject,
as: 'course',
attributes: ['subject_name', 'subject_code'],
},
{
model: UsersAuth,
as: 'verifiedBy',
attributes: ['username', 'full_name'],
},
],
order: [['completion_date', 'DESC']],
});
await cacheUtils.set(cacheKey, achievements, 1800); // Cache 30 min
res.json({
success: true,
data: achievements,
});
} catch (error) {
next(error);
}
}
/**
* GET /api/training/stats - Thống kê đào tạo
*/
async getTrainingStats(req, res, next) {
try {
const cacheKey = 'training:stats';
const cached = await cacheUtils.get(cacheKey);
if (cached) {
return res.json({
success: true,
data: cached,
cached: true,
});
}
const assignmentStats = await StaffTrainingAssignment.findAll({
attributes: [
'status',
[require('sequelize').fn('COUNT', require('sequelize').col('id')), 'count'],
],
group: ['status'],
});
const achievementStats = await StaffAchievement.findAll({
attributes: [
'type',
[require('sequelize').fn('COUNT', require('sequelize').col('id')), 'count'],
[require('sequelize').fn('SUM', require('sequelize').col('total_hours')), 'total_hours'],
],
group: ['type'],
});
const stats = {
assignments: assignmentStats,
achievements: achievementStats,
};
await cacheUtils.set(cacheKey, stats, 300); // Cache 5 min
res.json({
success: true,
data: stats,
});
} catch (error) {
next(error);
}
}
}
module.exports = new TrainingController();