update
This commit is contained in:
193
scripts/export-teachers-info.js
Normal file
193
scripts/export-teachers-info.js
Normal 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();
|
||||
Reference in New Issue
Block a user