This commit is contained in:
Ken
2026-01-19 09:33:35 +07:00
parent 374dc12b2d
commit 70838a4bc1
103 changed files with 16929 additions and 2 deletions

View File

@@ -0,0 +1,193 @@
/**
* Script: Export Teacher Profiles to JSON
* Xuất chi tiết thông tin tất cả teachers ra file JSON
*
* Usage:
* node src/scripts/export-teachers-info.js
* node src/scripts/export-teachers-info.js --output=teachers.json
*/
require('dotenv').config();
const fs = require('fs');
const path = require('path');
const { sequelize, TeacherDetail, UserProfile, UsersAuth } = require('../models');
async function exportTeachersInfo() {
console.log('📤 Exporting All Teachers Information...\n');
try {
await sequelize.authenticate();
console.log('✅ Database connected\n');
// Get all teachers
const teachers = await TeacherDetail.findAll({
order: [['created_at', 'ASC']],
});
console.log(`📊 Found ${teachers.length} teachers\n`);
console.log('Processing...\n');
const exportData = [];
for (const teacher of teachers) {
// Get auth info
const userAuth = await UsersAuth.findByPk(teacher.user_id, {
attributes: ['id', 'username', 'email', 'is_active', 'last_login', 'login_count', 'qr_version'],
});
// Get profile info
const userProfile = await UserProfile.findOne({
where: { user_id: teacher.user_id },
});
const teacherData = {
// Teacher Details
teacher_id: teacher.id,
teacher_code: teacher.teacher_code,
teacher_type: teacher.teacher_type,
status: teacher.status,
qualification: teacher.qualification,
specialization: teacher.specialization,
hire_date: teacher.hire_date,
training_hours: teacher.training_hours,
last_training_date: teacher.last_training_date,
training_score_avg: teacher.training_score_avg,
skill_tags: teacher.skill_tags,
certifications: teacher.certifications,
created_at: teacher.created_at,
updated_at: teacher.updated_at,
// Auth Info
user_id: teacher.user_id,
username: userAuth?.username,
email: userAuth?.email,
is_active: userAuth?.is_active,
last_login: userAuth?.last_login,
login_count: userAuth?.login_count,
qr_version: userAuth?.qr_version,
// Profile Info
has_profile: !!userProfile,
profile: userProfile ? {
profile_id: userProfile.id,
full_name: userProfile.full_name,
first_name: userProfile.first_name,
last_name: userProfile.last_name,
phone: userProfile.phone,
date_of_birth: userProfile.date_of_birth,
gender: userProfile.gender,
address: userProfile.address,
school_id: userProfile.school_id,
city: userProfile.city,
district: userProfile.district,
avatar_url: userProfile.avatar_url,
etc: userProfile.etc,
created_at: userProfile.created_at,
updated_at: userProfile.updated_at,
} : null,
};
exportData.push(teacherData);
}
// Summary statistics
const stats = {
total_teachers: exportData.length,
with_profile: exportData.filter(t => t.has_profile).length,
without_profile: exportData.filter(t => !t.has_profile).length,
active: exportData.filter(t => t.is_active).length,
inactive: exportData.filter(t => !t.is_active).length,
by_type: {
foreign: exportData.filter(t => t.teacher_type === 'foreign').length,
homeroom: exportData.filter(t => t.teacher_type === 'homeroom').length,
subject: exportData.filter(t => t.teacher_type === 'subject').length,
assistant: exportData.filter(t => t.teacher_type === 'assistant').length,
},
by_status: {
active: exportData.filter(t => t.status === 'active').length,
on_leave: exportData.filter(t => t.status === 'on_leave').length,
resigned: exportData.filter(t => t.status === 'resigned').length,
},
};
// Parse output filename
const args = process.argv.slice(2);
const outputArg = args.find(arg => arg.startsWith('--output='));
const outputFileName = outputArg ? outputArg.split('=')[1] : 'teachers-export.json';
const outputPath = path.join(process.cwd(), '..', 'data', outputFileName);
// Prepare export object
const exportObject = {
exported_at: new Date().toISOString(),
statistics: stats,
teachers: exportData,
};
// Write to file
fs.writeFileSync(outputPath, JSON.stringify(exportObject, null, 2), 'utf8');
console.log('✅ Export completed!\n');
console.log('📊 Statistics:');
console.log('='.repeat(60));
console.log(`Total Teachers: ${stats.total_teachers}`);
console.log(` ✅ With Profile: ${stats.with_profile}`);
console.log(` ❌ Without Profile: ${stats.without_profile}`);
console.log(` 🟢 Active: ${stats.active}`);
console.log(` 🔴 Inactive: ${stats.inactive}`);
console.log('\nBy Teacher Type:');
console.log(` Foreign: ${stats.by_type.foreign}`);
console.log(` Homeroom: ${stats.by_type.homeroom}`);
console.log(` Subject: ${stats.by_type.subject}`);
console.log(` Assistant: ${stats.by_type.assistant}`);
console.log('\nBy Status:');
console.log(` Active: ${stats.by_status.active}`);
console.log(` On Leave: ${stats.by_status.on_leave}`);
console.log(` Resigned: ${stats.by_status.resigned}`);
console.log('='.repeat(60));
console.log(`\n📁 File saved: ${outputPath}`);
console.log(` Size: ${(fs.statSync(outputPath).size / 1024).toFixed(2)} KB\n`);
// Show sample data
console.log('📋 Sample Teacher Data (first 3):\n');
exportData.slice(0, 3).forEach((t, i) => {
console.log(`${i + 1}. ${t.teacher_code} (${t.teacher_type})`);
console.log(` Username: ${t.username}`);
console.log(` Email: ${t.email}`);
console.log(` Full Name: ${t.profile?.full_name || 'N/A'}`);
console.log(` Phone: ${t.profile?.phone || 'N/A'}`);
console.log(` Status: ${t.status} | Active: ${t.is_active}`);
console.log('');
});
return {
outputPath,
stats,
};
} catch (error) {
console.error('❌ Export failed:', error.message);
throw error;
}
}
async function main() {
console.log('\n🚀 Teacher Profile Export Tool\n');
try {
const result = await exportTeachersInfo();
console.log('🎉 Done! You can now view the exported file:\n');
console.log(` cat ${result.outputPath}`);
console.log(` or open it in a text editor/VS Code\n`);
process.exit(0);
} catch (error) {
console.error('\n❌ Error:', error.message);
console.error(error.stack);
process.exit(1);
}
}
// Run
main();