Initial commit
This commit is contained in:
+246
@@ -0,0 +1,246 @@
|
||||
const sqlite3 = require('sqlite3').verbose();
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const dbPath = process.env.DATABASE_PATH || path.join(__dirname, 'database.db');
|
||||
|
||||
// Ensure database directory exists
|
||||
const dbDir = path.dirname(dbPath);
|
||||
if (!fs.existsSync(dbDir)) {
|
||||
fs.mkdirSync(dbDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Database schema is initialized safely using CREATE TABLE IF NOT EXISTS below.
|
||||
|
||||
const db = new sqlite3.Database(dbPath, (err) => {
|
||||
if (err) {
|
||||
console.error('Error opening database:', err.message);
|
||||
} else {
|
||||
console.log('Connected to SQLite database at:', dbPath);
|
||||
initializeTables();
|
||||
}
|
||||
});
|
||||
|
||||
function run(sql, params = []) {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.run(sql, params, function (err) {
|
||||
if (err) reject(err);
|
||||
else resolve({ id: this.lastID, changes: this.changes });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function get(sql, params = []) {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.get(sql, params, (err, row) => {
|
||||
if (err) reject(err);
|
||||
else resolve(row);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function all(sql, params = []) {
|
||||
return new Promise((resolve, reject) => {
|
||||
db.all(sql, params, (err, rows) => {
|
||||
if (err) reject(err);
|
||||
else resolve(rows);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function initializeTables() {
|
||||
try {
|
||||
// 1. Create Departments Table
|
||||
await run(`
|
||||
CREATE TABLE IF NOT EXISTS departments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT UNIQUE NOT NULL
|
||||
)
|
||||
`);
|
||||
|
||||
// 2. Create Companies Table (New dictionary table)
|
||||
await run(`
|
||||
CREATE TABLE IF NOT EXISTS companies (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT UNIQUE NOT NULL
|
||||
)
|
||||
`);
|
||||
|
||||
// 3. Create Employees Table (Updated Schema with foreign keys)
|
||||
await run(`
|
||||
CREATE TABLE IF NOT EXISTS employees (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
company_id INTEGER,
|
||||
job_title TEXT NOT NULL,
|
||||
department_id INTEGER,
|
||||
phone TEXT,
|
||||
email TEXT,
|
||||
building TEXT,
|
||||
floor TEXT,
|
||||
FOREIGN KEY (department_id) REFERENCES departments(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE SET NULL
|
||||
)
|
||||
`);
|
||||
|
||||
// Seed data if database is fresh
|
||||
const deptCount = await get('SELECT COUNT(*) as count FROM departments');
|
||||
if (deptCount.count === 0) {
|
||||
console.log('Seeding initial departments, companies, and employees...');
|
||||
await seedData();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error initializing tables:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function seedData() {
|
||||
// Seed Departments
|
||||
const depts = [
|
||||
'Руководство',
|
||||
'Производственно-технический отдел',
|
||||
'Бухгалтерия',
|
||||
'Отдел кадров',
|
||||
'Информационные технологии',
|
||||
'Монтажный участок',
|
||||
'Цех металлоконструкций',
|
||||
'Служба безопасности'
|
||||
];
|
||||
|
||||
const deptIds = {};
|
||||
for (const dept of depts) {
|
||||
const res = await run('INSERT INTO departments (name) VALUES (?)', [dept]);
|
||||
deptIds[dept] = res.id;
|
||||
}
|
||||
|
||||
// Seed Companies (Melto Raboty)
|
||||
const companiesList = [
|
||||
'АО КМУ Гидромонтаж',
|
||||
'ООО Гидромонтаж-Услуги',
|
||||
'ООО Спецтранс'
|
||||
];
|
||||
|
||||
const companyIds = {};
|
||||
for (const comp of companiesList) {
|
||||
const res = await run('INSERT INTO companies (name) VALUES (?)', [comp]);
|
||||
companyIds[comp] = res.id;
|
||||
}
|
||||
|
||||
// Seed Employees
|
||||
const employees = [
|
||||
{
|
||||
name: 'Иванов Александр Сергеевич',
|
||||
company: 'АО КМУ Гидромонтаж',
|
||||
job_title: 'Генеральный директор',
|
||||
department: 'Руководство',
|
||||
phone: '+7 (391) 234-56-78',
|
||||
email: 'a.ivanov@gidrom24.ru',
|
||||
building: 'Административный корпус',
|
||||
floor: '3'
|
||||
},
|
||||
{
|
||||
name: 'Петров Дмитрий Васильевич',
|
||||
company: 'АО КМУ Гидромонтаж',
|
||||
job_title: 'Руководитель IT-отдела',
|
||||
department: 'Информационные технологии',
|
||||
phone: '+7 (391) 234-56-79',
|
||||
email: 'd.petrov@gidrom24.ru',
|
||||
building: 'Административный корпус',
|
||||
floor: '2'
|
||||
},
|
||||
{
|
||||
name: 'Сидоров Алексей Михайлович',
|
||||
company: 'АО КМУ Гидромонтаж',
|
||||
job_title: 'Системный администратор',
|
||||
department: 'Информационные технологии',
|
||||
phone: '+7 (923) 456-78-90',
|
||||
email: 'sysadmin@gidrom24.ru',
|
||||
building: 'Административный корпус',
|
||||
floor: '2'
|
||||
},
|
||||
{
|
||||
name: 'Смирнова Елена Николаевна',
|
||||
company: 'ООО Гидромонтаж-Услуги',
|
||||
job_title: 'Главный бухгалтер',
|
||||
department: 'Бухгалтерия',
|
||||
phone: '+7 (391) 234-56-80',
|
||||
email: 'e.smirnova@gidrom24.ru',
|
||||
building: 'Административный корпус',
|
||||
floor: '3'
|
||||
},
|
||||
{
|
||||
name: 'Кузнецов Сергей Петрович',
|
||||
company: 'АО КМУ Гидромонтаж',
|
||||
job_title: 'Начальник ПТО',
|
||||
department: 'Производственно-технический отдел',
|
||||
phone: '+7 (391) 234-56-81',
|
||||
email: 's.kuznetsov@gidrom24.ru',
|
||||
building: 'Производственный корпус №1',
|
||||
floor: '2'
|
||||
},
|
||||
{
|
||||
name: 'Козлова Мария Игоревна',
|
||||
company: 'АО КМУ Гидромонтаж',
|
||||
job_title: 'Начальник отдела кадров',
|
||||
department: 'Отдел кадров',
|
||||
phone: '+7 (391) 234-56-82',
|
||||
email: 'm.kozlova@gidrom24.ru',
|
||||
building: 'Административный корпус',
|
||||
floor: '3'
|
||||
},
|
||||
{
|
||||
name: 'Морозов Артем Александрович',
|
||||
company: 'ООО Спецтранс',
|
||||
job_title: 'Начальник цеха металлоконструкций',
|
||||
department: 'Цех металлоконструкций',
|
||||
phone: '+7 (913) 765-43-21',
|
||||
email: 'a.morozov@gidrom24.ru',
|
||||
building: 'Производственный корпус №1',
|
||||
floor: '1'
|
||||
},
|
||||
{
|
||||
name: 'Васильев Игорь Олегович',
|
||||
company: 'ООО Гидромонтаж-Услуги',
|
||||
job_title: 'Бригадир монтажников',
|
||||
department: 'Монтажный участок',
|
||||
phone: '+7 (902) 123-45-67',
|
||||
email: 'i.vasiliev@gidrom24.ru',
|
||||
building: 'Складской терминал',
|
||||
floor: '1'
|
||||
},
|
||||
{
|
||||
name: 'Федоров Роман Геннадьевич',
|
||||
company: 'ООО Спецтранс',
|
||||
job_title: 'Начальник службы безопасности',
|
||||
department: 'Служба безопасности',
|
||||
phone: '+7 (391) 234-56-99',
|
||||
email: 'security@gidrom24.ru',
|
||||
building: 'Административный корпус',
|
||||
floor: '1'
|
||||
}
|
||||
];
|
||||
|
||||
for (const emp of employees) {
|
||||
await run(`
|
||||
INSERT INTO employees (name, company_id, job_title, department_id, phone, email, building, floor)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, [
|
||||
emp.name,
|
||||
companyIds[emp.company],
|
||||
emp.job_title,
|
||||
deptIds[emp.department],
|
||||
emp.phone,
|
||||
emp.email,
|
||||
emp.building,
|
||||
emp.floor
|
||||
]);
|
||||
}
|
||||
console.log('Database initialized and seeded successfully.');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
db,
|
||||
run,
|
||||
get,
|
||||
all
|
||||
};
|
||||
Generated
+3011
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "corporate-address-book-backend",
|
||||
"version": "1.0.0",
|
||||
"description": "Intranet Corporate Address Book Backend Server",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"dev": "nodemon server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.19.2",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"sqlite3": "^5.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
require('dotenv').config();
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const db = require('./db');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 8180;
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'super_secret_corporate_token_key_123!';
|
||||
|
||||
// Setup default admin credentials
|
||||
const ADMIN_USER = process.env.ADMIN_USERNAME || 'admin';
|
||||
let ADMIN_PASS = process.env.ADMIN_PASSWORD || 'adminpass';
|
||||
const ADMIN_PASS_HASH = bcrypt.hashSync(ADMIN_PASS, 10);
|
||||
|
||||
console.log(`=========================================`);
|
||||
console.log(`Intranet Address Book Server starting...`);
|
||||
console.log(`Admin Username: ${ADMIN_USER}`);
|
||||
console.log(`Admin Password: ${process.env.ADMIN_PASSWORD ? '****** (From Env)' : 'adminpass (Default)'}`);
|
||||
console.log(`Default Port: ${PORT}`);
|
||||
console.log(`=========================================`);
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
|
||||
// Serve React static build files
|
||||
const publicDir = path.join(__dirname, 'public');
|
||||
if (fs.existsSync(publicDir)) {
|
||||
app.use(express.static(publicDir));
|
||||
}
|
||||
|
||||
// Authentication Middleware
|
||||
function authenticateToken(req, res, next) {
|
||||
const authHeader = req.headers['authorization'];
|
||||
const token = authHeader && authHeader.split(' ')[1];
|
||||
|
||||
if (!token) return res.status(401).json({ error: 'Access denied. No token provided.' });
|
||||
|
||||
jwt.verify(token, JWT_SECRET, (err, user) => {
|
||||
if (err) return res.status(403).json({ error: 'Invalid or expired token.' });
|
||||
req.user = user;
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// API ROUTES
|
||||
// ==========================================
|
||||
|
||||
// 1. Auth Endpoint
|
||||
app.post('/api/auth/login', (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
|
||||
if (!username || !password) {
|
||||
return res.status(400).json({ error: 'Username and password are required' });
|
||||
}
|
||||
|
||||
if (username === ADMIN_USER && bcrypt.compareSync(password, ADMIN_PASS_HASH)) {
|
||||
const token = jwt.sign({ username }, JWT_SECRET, { expiresIn: '24h' });
|
||||
return res.json({ token, username });
|
||||
}
|
||||
|
||||
return res.status(401).json({ error: 'Incorrect username or password' });
|
||||
});
|
||||
|
||||
// 2. Departments Endpoints
|
||||
app.get('/api/departments', async (req, res) => {
|
||||
try {
|
||||
const rows = await db.all('SELECT * FROM departments ORDER BY name ASC');
|
||||
res.json(rows);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/departments', authenticateToken, async (req, res) => {
|
||||
const { name } = req.body;
|
||||
if (!name || name.trim() === '') {
|
||||
return res.status(400).json({ error: 'Department name is required' });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await db.run('INSERT INTO departments (name) VALUES (?)', [name.trim()]);
|
||||
res.status(201).json({ id: result.id, name: name.trim() });
|
||||
} catch (error) {
|
||||
if (error.message.includes('UNIQUE')) {
|
||||
return res.status(400).json({ error: 'Department already exists' });
|
||||
}
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.delete('/api/departments/:id', authenticateToken, async (req, res) => {
|
||||
const { id } = req.params;
|
||||
try {
|
||||
await db.run('UPDATE employees SET department_id = NULL WHERE department_id = ?', [id]);
|
||||
const result = await db.run('DELETE FROM departments WHERE id = ?', [id]);
|
||||
res.json({ success: true, changes: result.changes });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Companies Endpoints (New dictionary CRUD)
|
||||
app.get('/api/companies', async (req, res) => {
|
||||
try {
|
||||
const rows = await db.all('SELECT * FROM companies ORDER BY name ASC');
|
||||
res.json(rows);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/companies', authenticateToken, async (req, res) => {
|
||||
const { name } = req.body;
|
||||
if (!name || name.trim() === '') {
|
||||
return res.status(400).json({ error: 'Company name is required' });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await db.run('INSERT INTO companies (name) VALUES (?)', [name.trim()]);
|
||||
res.status(201).json({ id: result.id, name: name.trim() });
|
||||
} catch (error) {
|
||||
if (error.message.includes('UNIQUE')) {
|
||||
return res.status(400).json({ error: 'Company already exists' });
|
||||
}
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.delete('/api/companies/:id', authenticateToken, async (req, res) => {
|
||||
const { id } = req.params;
|
||||
try {
|
||||
await db.run('UPDATE employees SET company_id = NULL WHERE company_id = ?', [id]);
|
||||
const result = await db.run('DELETE FROM companies WHERE id = ?', [id]);
|
||||
res.json({ success: true, changes: result.changes });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// 4. Employees Endpoints (Search & List)
|
||||
app.get('/api/employees', async (req, res) => {
|
||||
const { search, departmentId } = req.query;
|
||||
|
||||
let sql = `
|
||||
SELECT e.*, d.name as department_name, c.name as company_name
|
||||
FROM employees e
|
||||
LEFT JOIN departments d ON e.department_id = d.id
|
||||
LEFT JOIN companies c ON e.company_id = c.id
|
||||
`;
|
||||
const params = [];
|
||||
const conditions = [];
|
||||
|
||||
if (departmentId) {
|
||||
conditions.push('e.department_id = ?');
|
||||
params.push(departmentId);
|
||||
}
|
||||
|
||||
if (conditions.length > 0) {
|
||||
sql += ' WHERE ' + conditions.join(' AND ');
|
||||
}
|
||||
|
||||
sql += ' ORDER BY e.name ASC';
|
||||
|
||||
try {
|
||||
let rows = await db.all(sql, params);
|
||||
|
||||
if (search && search.trim() !== '') {
|
||||
const cleanSearch = search.trim().toLowerCase();
|
||||
|
||||
const normalizePhone = (p) => {
|
||||
if (!p) return '';
|
||||
const digits = p.replace(/\D/g, '');
|
||||
if (digits.length === 11 && (digits.startsWith('7') || digits.startsWith('8'))) {
|
||||
return digits.slice(1);
|
||||
}
|
||||
return digits;
|
||||
};
|
||||
|
||||
const searchDigits = normalizePhone(cleanSearch);
|
||||
|
||||
rows = rows.filter(e => {
|
||||
const nameMatch = e.name && e.name.toLowerCase().includes(cleanSearch);
|
||||
const jobMatch = e.job_title && e.job_title.toLowerCase().includes(cleanSearch);
|
||||
const emailMatch = e.email && e.email.toLowerCase().includes(cleanSearch);
|
||||
const deptMatch = e.department_name && e.department_name.toLowerCase().includes(cleanSearch);
|
||||
const compMatch = e.company_name && e.company_name.toLowerCase().includes(cleanSearch);
|
||||
const buildMatch = e.building && e.building.toLowerCase().includes(cleanSearch);
|
||||
const floorMatch = e.floor && e.floor.toLowerCase().includes(cleanSearch);
|
||||
|
||||
let phoneMatch = false;
|
||||
if (searchDigits.length > 0 && e.phone) {
|
||||
const empPhoneDigits = normalizePhone(e.phone);
|
||||
if (empPhoneDigits.includes(searchDigits)) {
|
||||
phoneMatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
return nameMatch || jobMatch || emailMatch || deptMatch || compMatch || buildMatch || floorMatch || phoneMatch;
|
||||
});
|
||||
}
|
||||
|
||||
res.json(rows);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Create Employee
|
||||
app.post('/api/employees', authenticateToken, async (req, res) => {
|
||||
const { name, company_id, job_title, department_id, phone, email, building, floor } = req.body;
|
||||
|
||||
if (!name || !job_title) {
|
||||
return res.status(400).json({ error: 'Name and Job Title are required fields.' });
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await db.run(`
|
||||
INSERT INTO employees (name, company_id, job_title, department_id, phone, email, building, floor)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, [
|
||||
name.trim(),
|
||||
company_id || null,
|
||||
job_title.trim(),
|
||||
department_id || null,
|
||||
phone ? phone.trim() : '',
|
||||
email ? email.trim() : '',
|
||||
building ? building.trim() : '',
|
||||
floor ? floor.trim() : ''
|
||||
]);
|
||||
|
||||
const newEmp = await db.get(`
|
||||
SELECT e.*, d.name as department_name, c.name as company_name
|
||||
FROM employees e
|
||||
LEFT JOIN departments d ON e.department_id = d.id
|
||||
LEFT JOIN companies c ON e.company_id = c.id
|
||||
WHERE e.id = ?
|
||||
`, [result.id]);
|
||||
|
||||
res.status(201).json(newEmp);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Update Employee
|
||||
app.put('/api/employees/:id', authenticateToken, async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { name, company_id, job_title, department_id, phone, email, building, floor } = req.body;
|
||||
|
||||
if (!name || !job_title) {
|
||||
return res.status(400).json({ error: 'Name and Job Title are required fields.' });
|
||||
}
|
||||
|
||||
try {
|
||||
await db.run(`
|
||||
UPDATE employees
|
||||
SET name = ?, company_id = ?, job_title = ?, department_id = ?, phone = ?, email = ?, building = ?, floor = ?
|
||||
WHERE id = ?
|
||||
`, [
|
||||
name.trim(),
|
||||
company_id || null,
|
||||
job_title.trim(),
|
||||
department_id || null,
|
||||
phone ? phone.trim() : '',
|
||||
email ? email.trim() : '',
|
||||
building ? building.trim() : '',
|
||||
floor ? floor.trim() : '',
|
||||
id
|
||||
]);
|
||||
|
||||
const updatedEmp = await db.get(`
|
||||
SELECT e.*, d.name as department_name, c.name as company_name
|
||||
FROM employees e
|
||||
LEFT JOIN departments d ON e.department_id = d.id
|
||||
LEFT JOIN companies c ON e.company_id = c.id
|
||||
WHERE e.id = ?
|
||||
`, [id]);
|
||||
|
||||
res.json(updatedEmp);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Delete Employee
|
||||
app.delete('/api/employees/:id', authenticateToken, async (req, res) => {
|
||||
const { id } = req.params;
|
||||
try {
|
||||
const result = await db.run('DELETE FROM employees WHERE id = ?', [id]);
|
||||
res.json({ success: true, changes: result.changes });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Bulk Export (JSON dump of departments, companies, and employees)
|
||||
app.get('/api/admin/export', authenticateToken, async (req, res) => {
|
||||
try {
|
||||
const employees = await db.all('SELECT * FROM employees');
|
||||
const departments = await db.all('SELECT * FROM departments');
|
||||
const companies = await db.all('SELECT * FROM companies');
|
||||
res.json({ employees, departments, companies });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Bulk Import
|
||||
app.post('/api/admin/import', authenticateToken, async (req, res) => {
|
||||
const { employees, departments, companies } = req.body;
|
||||
|
||||
if (!Array.isArray(employees) || !Array.isArray(departments) || !Array.isArray(companies)) {
|
||||
return res.status(400).json({ error: 'Invalid data format. Expected arrays for employees, departments, and companies.' });
|
||||
}
|
||||
|
||||
try {
|
||||
// Truncate existing data
|
||||
await db.run('DELETE FROM employees');
|
||||
await db.run('DELETE FROM departments');
|
||||
await db.run('DELETE FROM companies');
|
||||
// Reset autoincrement sequence
|
||||
await db.run("UPDATE sqlite_sequence SET seq = 0 WHERE name = 'employees'");
|
||||
await db.run("UPDATE sqlite_sequence SET seq = 0 WHERE name = 'departments'");
|
||||
await db.run("UPDATE sqlite_sequence SET seq = 0 WHERE name = 'companies'");
|
||||
|
||||
// Insert departments
|
||||
const deptIdMapping = {};
|
||||
for (const d of departments) {
|
||||
const result = await db.run('INSERT INTO departments (name) VALUES (?)', [d.name]);
|
||||
deptIdMapping[d.id] = result.id;
|
||||
}
|
||||
|
||||
// Insert companies
|
||||
const compIdMapping = {};
|
||||
for (const c of companies) {
|
||||
const result = await db.run('INSERT INTO companies (name) VALUES (?)', [c.name]);
|
||||
compIdMapping[c.id] = result.id;
|
||||
}
|
||||
|
||||
// Insert employees
|
||||
for (const e of employees) {
|
||||
const newDeptId = e.department_id ? (deptIdMapping[e.department_id] || null) : null;
|
||||
const newCompId = e.company_id ? (compIdMapping[e.company_id] || null) : null;
|
||||
await db.run(`
|
||||
INSERT INTO employees (name, company_id, job_title, department_id, phone, email, building, floor)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`, [
|
||||
e.name,
|
||||
newCompId,
|
||||
e.job_title,
|
||||
newDeptId,
|
||||
e.phone || '',
|
||||
e.email || '',
|
||||
e.building || '',
|
||||
e.floor || ''
|
||||
]);
|
||||
}
|
||||
|
||||
res.json({ success: true, message: `Imported ${departments.length} departments, ${companies.length} companies and ${employees.length} employees.` });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Catch-all route to serve Index.html
|
||||
if (fs.existsSync(publicDir)) {
|
||||
app.get('*', (req, res) => {
|
||||
res.sendFile(path.join(publicDir, 'index.html'));
|
||||
});
|
||||
}
|
||||
|
||||
// Start Server
|
||||
app.listen(PORT, '0.0.0.0', () => {
|
||||
console.log(`Server is running on http://localhost:${PORT}`);
|
||||
console.log(`Ready for Intranet users!`);
|
||||
});
|
||||
Reference in New Issue
Block a user