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,201 @@
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 };