Files
sena_db_api_layer/scripts/import-foreign-teachers.js
2026-01-19 09:33:35 +07:00

202 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const { sequelize } = require('../config/database');
const UsersAuth = require('../models/UsersAuth');
const UserProfile = require('../models/UserProfile');
const TeacherDetail = require('../models/TeacherDetail');
const School = require('../models/School');
const bcrypt = require('bcrypt');
const fs = require('fs');
const path = require('path');
/**
* Script import giáo viên nước ngoài từ fteacher.txt
* Chạy: node src/scripts/import-foreign-teachers.js
*/
// Hàm hash password
async function hashPassword(password) {
const salt = await bcrypt.genSalt(10);
const hash = await bcrypt.hash(password, salt);
return { hash, salt };
}
// Hàm parse tên từ username
function parseNameFromUsername(username) {
// tdv_altaf -> Altaf
const name = username.replace('tdv_', '').replace(/_/g, ' ');
return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
}
// Hàm tạo email từ username
function generateEmail(username) {
// tdv_altaf -> altaf@senaai.edu.vn
const name = username.replace('tdv_', '');
return `${name}@senaai.edu.vn`;
}
async function importForeignTeachers() {
try {
console.log('🚀 Bắt đầu import giáo viên nước ngoài...\n');
// Đọc file fteacher.txt
const filePath = path.join(__dirname, '../../data/fteacher.txt');
const fileContent = fs.readFileSync(filePath, 'utf8');
const lines = fileContent.split('\n').filter(line => line.trim());
console.log(`📚 Tìm thấy ${lines.length} giáo viên trong file\n`);
// Kết nối database
await sequelize.authenticate();
console.log('✅ Kết nối database thành công\n');
// Lấy thông tin trung tâm SenaAI
const senaAI = await School.findOne({
where: { school_code: 'SENAAI' }
});
if (!senaAI) {
throw new Error('❌ Không tìm thấy trung tâm SenaAI trong database. Vui lòng chạy add-senaai-center.js trước!');
}
let importedCount = 0;
let skippedCount = 0;
const errors = [];
// Parse từng dòng
for (const line of lines) {
try {
// Parse: Created user: tdv_altaf with password: 13082025
const match = line.match(/Created user: (\S+) with password: (\S+)/);
if (!match) {
console.log(`⚠️ Bỏ qua dòng không hợp lệ: ${line}`);
continue;
}
const [, username, password] = match;
const fullName = parseNameFromUsername(username);
const email = generateEmail(username);
const teacherCode = username.toUpperCase();
console.log(`📖 Đang xử lý: ${fullName} (${username})`);
// Kiểm tra user đã tồn tại
const existingAuth = await UsersAuth.findOne({
where: { username }
});
if (existingAuth) {
console.log(` ⚠️ User đã tồn tại, bỏ qua\n`);
skippedCount++;
continue;
}
// Hash password
const { hash, salt } = await hashPassword(password);
// Transaction để đảm bảo tính toàn vẹn dữ liệu
await sequelize.transaction(async (t) => {
// 1. Tạo UsersAuth
const userAuth = await UsersAuth.create({
username,
email,
password_hash: hash,
salt,
role: 'teacher',
is_active: true,
is_verified: true,
}, { transaction: t });
// 2. Tạo UserProfile
const userProfile = await UserProfile.create({
user_id: userAuth.id,
full_name: fullName,
first_name: fullName.split(' ')[0],
last_name: fullName.split(' ').slice(1).join(' ') || fullName,
phone: '',
school_id: senaAI.id,
address: 'SenaAI Education Center',
city: 'Thành phố Hồ Chí Minh',
district: 'Đang cập nhật',
}, { transaction: t });
// 3. Tạo TeacherDetail
await TeacherDetail.create({
user_id: userAuth.id,
teacher_code: teacherCode,
teacher_type: 'foreign',
qualification: 'Native Speaker',
specialization: 'English Language Teaching',
hire_date: new Date(),
status: 'active',
skill_tags: [
{ name: 'English Teaching', level: 'expert' },
{ name: 'Communication', level: 'expert' }
],
certifications: [],
training_hours: 0,
}, { transaction: t });
});
console.log(` ✅ Tạo thành công (Email: ${email})\n`);
importedCount++;
} catch (error) {
console.error(` ❌ Lỗi: ${error.message}\n`);
errors.push({
line,
error: error.message
});
}
}
// Tổng kết
console.log('\n' + '='.repeat(60));
console.log('📊 KẾT QUẢ IMPORT');
console.log('='.repeat(60));
console.log(`✅ Giáo viên mới: ${importedCount}`);
console.log(`⚠️ Đã tồn tại: ${skippedCount}`);
console.log(`❌ Lỗi: ${errors.length}`);
console.log('='.repeat(60));
if (errors.length > 0) {
console.log('\n⚠ CHI TIẾT LỖI:');
errors.forEach((err, index) => {
console.log(`\n${index + 1}. ${err.line}`);
console.log(` Lỗi: ${err.error}`);
});
}
// Thống kê giáo viên nước ngoài
const foreignTeachersCount = await TeacherDetail.count({
where: { teacher_type: 'foreign' }
});
console.log('\n📊 THỐNG KÊ:');
console.log(` Tổng số giáo viên nước ngoài: ${foreignTeachersCount}`);
console.log('\n✅ Hoàn thành import dữ liệu!\n');
} catch (error) {
console.error('❌ Lỗi nghiêm trọng:', error);
throw error;
} finally {
await sequelize.close();
console.log('🔌 Đã đóng kết nối database');
}
}
// Chạy script
if (require.main === module) {
importForeignTeachers()
.then(() => {
console.log('\n🎉 Script hoàn thành thành công!');
process.exit(0);
})
.catch((error) => {
console.error('\n💥 Script thất bại:', error);
process.exit(1);
});
}
module.exports = { importForeignTeachers };