clear
This commit is contained in:
@@ -1,82 +0,0 @@
|
|||||||
// init-document-types.js - Инициализация типов документов
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
function initializeDocumentTypes(db) {
|
|
||||||
const documentTypes = [
|
|
||||||
{ name: 'Приказ', description: 'Распорядительный документ' },
|
|
||||||
{ name: 'Распоряжение', description: 'Распорядительный документ' },
|
|
||||||
{ name: 'Инструкция', description: 'Нормативный документ' },
|
|
||||||
{ name: 'Положение', description: 'Нормативный документ' },
|
|
||||||
{ name: 'Договор', description: 'Юридический документ' },
|
|
||||||
{ name: 'Соглашение', description: 'Юридический документ' },
|
|
||||||
{ name: 'Акт', description: 'Документ подтверждения факта' },
|
|
||||||
{ name: 'Служебная записка', description: 'Внутренний документ' },
|
|
||||||
{ name: 'Заявление', description: 'Обращение' },
|
|
||||||
{ name: 'Отчет', description: 'Отчетный документ' },
|
|
||||||
{ name: 'План', description: 'Плановый документ' },
|
|
||||||
{ name: 'Программа', description: 'Плановый документ' },
|
|
||||||
{ name: 'Протокол', description: 'Документ собрания' },
|
|
||||||
{ name: 'Решение', description: 'Документ коллегиального органа' },
|
|
||||||
{ name: 'Письмо', description: 'Корреспонденция' },
|
|
||||||
{ name: 'Справка', description: 'Информационный документ' },
|
|
||||||
{ name: 'Выписка', description: 'Копия части документа' },
|
|
||||||
{ name: 'Копия', description: 'Копия документа' },
|
|
||||||
{ name: 'Проект', description: 'Проект документа' },
|
|
||||||
{ name: 'Шаблон', description: 'Шаблон документа' }
|
|
||||||
];
|
|
||||||
|
|
||||||
// Создаем таблицу если её нет
|
|
||||||
db.run(`
|
|
||||||
CREATE TABLE IF NOT EXISTS document_types (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
description TEXT,
|
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`, (err) => {
|
|
||||||
if (err) {
|
|
||||||
console.error('❌ Ошибка создания таблицы типов документов:', err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('✅ Таблица типов документов создана/проверена');
|
|
||||||
|
|
||||||
// Проверяем, есть ли уже типы документов
|
|
||||||
db.get("SELECT COUNT(*) as count FROM document_types", [], (err, result) => {
|
|
||||||
if (err) {
|
|
||||||
console.error('❌ Ошибка проверки типов документов:', err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.count === 0) {
|
|
||||||
console.log('📄 Добавление типов документов...');
|
|
||||||
|
|
||||||
const insertPromises = documentTypes.map(type => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
db.run(
|
|
||||||
"INSERT INTO document_types (name, description) VALUES (?, ?)",
|
|
||||||
[type.name, type.description],
|
|
||||||
(err) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
else resolve();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
Promise.all(insertPromises)
|
|
||||||
.then(() => {
|
|
||||||
console.log(`✅ Добавлено ${documentTypes.length} типов документов`);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('❌ Ошибка добавления типов документов:', error);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.log(`✅ В базе уже есть ${result.count} типов документов`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { initializeDocumentTypes };
|
|
||||||
483
migrate.js
483
migrate.js
@@ -1,483 +0,0 @@
|
|||||||
|
|
||||||
const sqlite3 = require('sqlite3').verbose();
|
|
||||||
const { Pool } = require('pg');
|
|
||||||
const path = require('path');
|
|
||||||
const fs = require('fs');
|
|
||||||
require('dotenv').config();
|
|
||||||
|
|
||||||
async function migrateToPostgres() {
|
|
||||||
console.log('🚀 Начинаем миграцию данных из SQLite в PostgreSQL...');
|
|
||||||
|
|
||||||
// Проверяем существование SQLite базы
|
|
||||||
const sqlitePath = path.join(__dirname, 'data', 'school_crm.db');
|
|
||||||
if (!fs.existsSync(sqlitePath)) {
|
|
||||||
console.error('❌ Файл SQLite базы не найден:', sqlitePath);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Подключаемся к SQLite
|
|
||||||
const sqliteDb = new sqlite3.Database(sqlitePath, (err) => {
|
|
||||||
if (err) {
|
|
||||||
console.error('❌ Ошибка подключения к SQLite:', err.message);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('✅ SQLite база найдена и подключена');
|
|
||||||
|
|
||||||
// Проверяем настройки PostgreSQL
|
|
||||||
if (!process.env.DB_HOST || !process.env.DB_USER || !process.env.DB_PASSWORD) {
|
|
||||||
console.error('❌ Настройки PostgreSQL не указаны в .env файле');
|
|
||||||
console.error(' Укажите DB_HOST, DB_USER, DB_PASSWORD');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Подключаемся к PostgreSQL
|
|
||||||
const pgPool = new Pool({
|
|
||||||
host: process.env.DB_HOST,
|
|
||||||
port: process.env.DB_PORT || 5432,
|
|
||||||
database: process.env.DB_NAME || 'minicrm',
|
|
||||||
user: process.env.DB_USER,
|
|
||||||
password: process.env.DB_PASSWORD,
|
|
||||||
max: 5,
|
|
||||||
idleTimeoutMillis: 30000,
|
|
||||||
connectionTimeoutMillis: 10000,
|
|
||||||
});
|
|
||||||
|
|
||||||
let client;
|
|
||||||
try {
|
|
||||||
console.log('🔌 Подключаемся к PostgreSQL...');
|
|
||||||
client = await pgPool.connect();
|
|
||||||
console.log('✅ Подключение к PostgreSQL установлено');
|
|
||||||
|
|
||||||
// Создаем таблицы в PostgreSQL если их нет
|
|
||||||
console.log('🔧 Создаем/проверяем таблицы в PostgreSQL...');
|
|
||||||
await createPostgresTables(client);
|
|
||||||
|
|
||||||
// Отключаем foreign key constraints для упрощения миграции
|
|
||||||
await client.query('SET session_replication_role = replica;');
|
|
||||||
|
|
||||||
// Мигрируем таблицу users
|
|
||||||
console.log('📦 Мигрируем таблицу users...');
|
|
||||||
const users = await new Promise((resolve, reject) => {
|
|
||||||
sqliteDb.all('SELECT * FROM users ORDER BY id', [], (err, rows) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
else resolve(rows);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (users.length > 0) {
|
|
||||||
let migratedUsers = 0;
|
|
||||||
for (const user of users) {
|
|
||||||
try {
|
|
||||||
await client.query(`
|
|
||||||
INSERT INTO users (id, login, password, name, email, role, auth_type,
|
|
||||||
groups, description, created_at, last_login, updated_at)
|
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
|
||||||
ON CONFLICT (id) DO UPDATE SET
|
|
||||||
login = EXCLUDED.login,
|
|
||||||
name = EXCLUDED.name,
|
|
||||||
email = EXCLUDED.email,
|
|
||||||
role = EXCLUDED.role,
|
|
||||||
auth_type = EXCLUDED.auth_type,
|
|
||||||
groups = EXCLUDED.groups,
|
|
||||||
description = EXCLUDED.description,
|
|
||||||
last_login = EXCLUDED.last_login,
|
|
||||||
updated_at = EXCLUDED.updated_at
|
|
||||||
`, [
|
|
||||||
user.id,
|
|
||||||
user.login,
|
|
||||||
user.password || null,
|
|
||||||
user.name,
|
|
||||||
user.email,
|
|
||||||
user.role || 'teacher',
|
|
||||||
user.auth_type || 'local',
|
|
||||||
user.groups || '[]',
|
|
||||||
user.description || '',
|
|
||||||
user.created_at,
|
|
||||||
user.last_login,
|
|
||||||
user.updated_at || user.created_at
|
|
||||||
]);
|
|
||||||
migratedUsers++;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(` Ошибка при миграции пользователя ${user.id}:`, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`✅ Мигрировано ${migratedUsers} из ${users.length} пользователей`);
|
|
||||||
} else {
|
|
||||||
console.log('ℹ️ В таблице users нет данных для миграции');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Мигрируем таблицу tasks
|
|
||||||
console.log('📦 Мигрируем таблицу tasks...');
|
|
||||||
const tasks = await new Promise((resolve, reject) => {
|
|
||||||
sqliteDb.all('SELECT * FROM tasks ORDER BY id', [], (err, rows) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
else resolve(rows);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (tasks.length > 0) {
|
|
||||||
let migratedTasks = 0;
|
|
||||||
for (const task of tasks) {
|
|
||||||
try {
|
|
||||||
await client.query(`
|
|
||||||
INSERT INTO tasks (id, title, description, status, created_by, created_at,
|
|
||||||
updated_at, deleted_at, deleted_by, original_task_id,
|
|
||||||
start_date, due_date, rework_comment, closed_at, closed_by)
|
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
|
||||||
ON CONFLICT (id) DO UPDATE SET
|
|
||||||
title = EXCLUDED.title,
|
|
||||||
description = EXCLUDED.description,
|
|
||||||
status = EXCLUDED.status,
|
|
||||||
created_by = EXCLUDED.created_by,
|
|
||||||
updated_at = EXCLUDED.updated_at,
|
|
||||||
deleted_at = EXCLUDED.deleted_at,
|
|
||||||
deleted_by = EXCLUDED.deleted_by,
|
|
||||||
original_task_id = EXCLUDED.original_task_id,
|
|
||||||
start_date = EXCLUDED.start_date,
|
|
||||||
due_date = EXCLUDED.due_date,
|
|
||||||
rework_comment = EXCLUDED.rework_comment,
|
|
||||||
closed_at = EXCLUDED.closed_at,
|
|
||||||
closed_by = EXCLUDED.closed_by
|
|
||||||
`, [
|
|
||||||
task.id,
|
|
||||||
task.title,
|
|
||||||
task.description || '',
|
|
||||||
task.status || 'active',
|
|
||||||
task.created_by,
|
|
||||||
task.created_at,
|
|
||||||
task.updated_at || task.created_at,
|
|
||||||
task.deleted_at,
|
|
||||||
task.deleted_by,
|
|
||||||
task.original_task_id,
|
|
||||||
task.start_date,
|
|
||||||
task.due_date,
|
|
||||||
task.rework_comment,
|
|
||||||
task.closed_at,
|
|
||||||
task.closed_by
|
|
||||||
]);
|
|
||||||
migratedTasks++;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(` Ошибка при миграции задачи ${task.id}:`, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`✅ Мигрировано ${migratedTasks} из ${tasks.length} задач`);
|
|
||||||
} else {
|
|
||||||
console.log('ℹ️ В таблице tasks нет данных для миграции');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Мигрируем таблицу task_assignments
|
|
||||||
console.log('📦 Мигрируем таблицу task_assignments...');
|
|
||||||
const assignments = await new Promise((resolve, reject) => {
|
|
||||||
sqliteDb.all('SELECT * FROM task_assignments ORDER BY id', [], (err, rows) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
else resolve(rows);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (assignments.length > 0) {
|
|
||||||
let migratedAssignments = 0;
|
|
||||||
for (const assignment of assignments) {
|
|
||||||
try {
|
|
||||||
await client.query(`
|
|
||||||
INSERT INTO task_assignments (id, task_id, user_id, status, start_date,
|
|
||||||
due_date, rework_comment, created_at, updated_at)
|
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
||||||
ON CONFLICT (id) DO UPDATE SET
|
|
||||||
task_id = EXCLUDED.task_id,
|
|
||||||
user_id = EXCLUDED.user_id,
|
|
||||||
status = EXCLUDED.status,
|
|
||||||
start_date = EXCLUDED.start_date,
|
|
||||||
due_date = EXCLUDED.due_date,
|
|
||||||
rework_comment = EXCLUDED.rework_comment,
|
|
||||||
updated_at = EXCLUDED.updated_at
|
|
||||||
`, [
|
|
||||||
assignment.id,
|
|
||||||
assignment.task_id,
|
|
||||||
assignment.user_id,
|
|
||||||
assignment.status || 'assigned',
|
|
||||||
assignment.start_date,
|
|
||||||
assignment.due_date,
|
|
||||||
assignment.rework_comment,
|
|
||||||
assignment.created_at,
|
|
||||||
assignment.updated_at || assignment.created_at
|
|
||||||
]);
|
|
||||||
migratedAssignments++;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(` Ошибка при миграции назначения ${assignment.id}:`, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`✅ Мигрировано ${migratedAssignments} из ${assignments.length} назначений`);
|
|
||||||
} else {
|
|
||||||
console.log('ℹ️ В таблице task_assignments нет данных для миграции');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Мигрируем таблицу task_files
|
|
||||||
console.log('📦 Мигрируем таблицу task_files...');
|
|
||||||
const files = await new Promise((resolve, reject) => {
|
|
||||||
sqliteDb.all('SELECT * FROM task_files ORDER BY id', [], (err, rows) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
else resolve(rows);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (files.length > 0) {
|
|
||||||
let migratedFiles = 0;
|
|
||||||
for (const file of files) {
|
|
||||||
try {
|
|
||||||
await client.query(`
|
|
||||||
INSERT INTO task_files (id, task_id, user_id, filename, original_name,
|
|
||||||
file_path, file_size, uploaded_at)
|
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
||||||
ON CONFLICT (id) DO UPDATE SET
|
|
||||||
task_id = EXCLUDED.task_id,
|
|
||||||
user_id = EXCLUDED.user_id,
|
|
||||||
filename = EXCLUDED.filename,
|
|
||||||
original_name = EXCLUDED.original_name,
|
|
||||||
file_path = EXCLUDED.file_path,
|
|
||||||
file_size = EXCLUDED.file_size
|
|
||||||
`, [
|
|
||||||
file.id,
|
|
||||||
file.task_id,
|
|
||||||
file.user_id,
|
|
||||||
file.filename,
|
|
||||||
file.original_name,
|
|
||||||
file.file_path,
|
|
||||||
file.file_size,
|
|
||||||
file.uploaded_at
|
|
||||||
]);
|
|
||||||
migratedFiles++;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(` Ошибка при миграции файла ${file.id}:`, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`✅ Мигрировано ${migratedFiles} из ${files.length} файлов`);
|
|
||||||
} else {
|
|
||||||
console.log('ℹ️ В таблице task_files нет данных для миграции');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Мигрируем таблицу activity_logs
|
|
||||||
console.log('📦 Мигрируем таблицу activity_logs...');
|
|
||||||
const logs = await new Promise((resolve, reject) => {
|
|
||||||
sqliteDb.all('SELECT * FROM activity_logs ORDER BY id', [], (err, rows) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
else resolve(rows);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (logs.length > 0) {
|
|
||||||
let migratedLogs = 0;
|
|
||||||
for (const log of logs) {
|
|
||||||
try {
|
|
||||||
await client.query(`
|
|
||||||
INSERT INTO activity_logs (id, task_id, user_id, action, details, created_at)
|
|
||||||
VALUES ($1, $2, $3, $4, $5, $6)
|
|
||||||
ON CONFLICT (id) DO UPDATE SET
|
|
||||||
task_id = EXCLUDED.task_id,
|
|
||||||
user_id = EXCLUDED.user_id,
|
|
||||||
action = EXCLUDED.action,
|
|
||||||
details = EXCLUDED.details
|
|
||||||
`, [
|
|
||||||
log.id,
|
|
||||||
log.task_id,
|
|
||||||
log.user_id,
|
|
||||||
log.action,
|
|
||||||
log.details || '',
|
|
||||||
log.created_at
|
|
||||||
]);
|
|
||||||
migratedLogs++;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(` Ошибка при миграции лога ${log.id}:`, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`✅ Мигрировано ${migratedLogs} из ${logs.length} логов активности`);
|
|
||||||
} else {
|
|
||||||
console.log('ℹ️ В таблице activity_logs нет данных для миграции');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Мигрируем таблицу notification_logs
|
|
||||||
console.log('📦 Мигрируем таблицу notification_logs...');
|
|
||||||
const notifications = await new Promise((resolve, reject) => {
|
|
||||||
sqliteDb.all('SELECT * FROM notification_logs ORDER BY id', [], (err, rows) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
else resolve(rows);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (notifications.length > 0) {
|
|
||||||
let migratedNotifications = 0;
|
|
||||||
for (const notification of notifications) {
|
|
||||||
try {
|
|
||||||
await client.query(`
|
|
||||||
INSERT INTO notification_logs (id, notification_key, created_at)
|
|
||||||
VALUES ($1, $2, $3)
|
|
||||||
ON CONFLICT (id) DO UPDATE SET
|
|
||||||
notification_key = EXCLUDED.notification_key
|
|
||||||
`, [
|
|
||||||
notification.id,
|
|
||||||
notification.notification_key,
|
|
||||||
notification.created_at
|
|
||||||
]);
|
|
||||||
migratedNotifications++;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(` Ошибка при миграции уведомления ${notification.id}:`, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log(`✅ Мигрировано ${migratedNotifications} из ${notifications.length} логов уведомлений`);
|
|
||||||
} else {
|
|
||||||
console.log('ℹ️ В таблице notification_logs нет данных для миграции');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Включаем foreign key constraints обратно
|
|
||||||
await client.query('SET session_replication_role = DEFAULT;');
|
|
||||||
|
|
||||||
// Обновляем последовательности
|
|
||||||
await updateSequences(client);
|
|
||||||
|
|
||||||
client.release();
|
|
||||||
sqliteDb.close();
|
|
||||||
|
|
||||||
console.log('\n🎉 Миграция успешно завершена!');
|
|
||||||
console.log('📊 Сводка:');
|
|
||||||
console.log(` 👥 Пользователи: ${users.length}`);
|
|
||||||
console.log(` 📋 Задачи: ${tasks.length}`);
|
|
||||||
console.log(` 👤 Назначения: ${assignments.length}`);
|
|
||||||
console.log(` 📁 Файлы: ${files.length}`);
|
|
||||||
console.log(` 📝 Логи активности: ${logs.length}`);
|
|
||||||
console.log(` 🔔 Логи уведомлений: ${notifications.length}`);
|
|
||||||
console.log('\n⚠️ Для переключения на PostgreSQL выполните следующие действия:');
|
|
||||||
console.log(' 1. Откройте файл .env');
|
|
||||||
console.log(' 2. Измените POSTGRESQL=no на POSTGRESQL=yes');
|
|
||||||
console.log(' 3. Перезапустите сервер командой: npm start');
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Ошибка миграции:', error.message);
|
|
||||||
if (client) client.release();
|
|
||||||
sqliteDb.close();
|
|
||||||
process.exit(1);
|
|
||||||
} finally {
|
|
||||||
await pgPool.end();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createPostgresTables(client) {
|
|
||||||
// Создаем таблицы PostgreSQL
|
|
||||||
await client.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
login VARCHAR(100) UNIQUE NOT NULL,
|
|
||||||
password TEXT,
|
|
||||||
name VARCHAR(255) NOT NULL,
|
|
||||||
email VARCHAR(255) UNIQUE NOT NULL,
|
|
||||||
role VARCHAR(50) DEFAULT 'teacher',
|
|
||||||
auth_type VARCHAR(50) DEFAULT 'local',
|
|
||||||
groups TEXT DEFAULT '[]',
|
|
||||||
description TEXT,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
last_login TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
|
|
||||||
await client.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS tasks (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
title VARCHAR(500) NOT NULL,
|
|
||||||
description TEXT,
|
|
||||||
status VARCHAR(50) DEFAULT 'active',
|
|
||||||
created_by INTEGER NOT NULL REFERENCES users(id),
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
deleted_at TIMESTAMP,
|
|
||||||
deleted_by INTEGER REFERENCES users(id),
|
|
||||||
original_task_id INTEGER REFERENCES tasks(id),
|
|
||||||
start_date TIMESTAMP,
|
|
||||||
due_date TIMESTAMP,
|
|
||||||
rework_comment TEXT,
|
|
||||||
closed_at TIMESTAMP,
|
|
||||||
closed_by INTEGER REFERENCES users(id)
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
|
|
||||||
await client.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS task_assignments (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
task_id INTEGER NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
||||||
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
||||||
status VARCHAR(50) DEFAULT 'assigned',
|
|
||||||
start_date TIMESTAMP,
|
|
||||||
due_date TIMESTAMP,
|
|
||||||
rework_comment TEXT,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
|
|
||||||
await client.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS task_files (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
task_id INTEGER NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
||||||
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
||||||
filename VARCHAR(255) NOT NULL,
|
|
||||||
original_name VARCHAR(500) NOT NULL,
|
|
||||||
file_path TEXT NOT NULL,
|
|
||||||
file_size BIGINT NOT NULL,
|
|
||||||
uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
|
|
||||||
await client.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS activity_logs (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
task_id INTEGER NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
||||||
user_id INTEGER NOT NULL REFERENCES users(id),
|
|
||||||
action VARCHAR(100) NOT NULL,
|
|
||||||
details TEXT,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
|
|
||||||
await client.query(`
|
|
||||||
CREATE TABLE IF NOT EXISTS notification_logs (
|
|
||||||
id SERIAL PRIMARY KEY,
|
|
||||||
notification_key VARCHAR(500) NOT NULL,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)
|
|
||||||
`);
|
|
||||||
|
|
||||||
console.log('✅ Таблицы PostgreSQL созданы/проверены');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateSequences(client) {
|
|
||||||
// Обновляем последовательности для автоинкремента
|
|
||||||
const tables = [
|
|
||||||
{ name: 'users', id: 'id' },
|
|
||||||
{ name: 'tasks', id: 'id' },
|
|
||||||
{ name: 'task_assignments', id: 'id' },
|
|
||||||
{ name: 'task_files', id: 'id' },
|
|
||||||
{ name: 'activity_logs', id: 'id' },
|
|
||||||
{ name: 'notification_logs', id: 'id' }
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const table of tables) {
|
|
||||||
try {
|
|
||||||
const result = await client.query(`
|
|
||||||
SELECT MAX(${table.id}) as max_id FROM ${table.name}
|
|
||||||
`);
|
|
||||||
|
|
||||||
const maxId = result.rows[0].max_id || 0;
|
|
||||||
if (maxId > 0) {
|
|
||||||
await client.query(`
|
|
||||||
SELECT setval(pg_get_serial_sequence('${table.name}', '${table.id}'), ${maxId}, true)
|
|
||||||
`);
|
|
||||||
console.log(`🔢 Последовательность для ${table.name} обновлена до ${maxId}`);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(`⚠️ Не удалось обновить последовательность для ${table.name}: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Запускаем миграцию
|
|
||||||
migrateToPostgres().catch(console.error);
|
|
||||||
@@ -1187,10 +1187,6 @@ async function initializeServer() {
|
|||||||
// 2. Получаем объект БД
|
// 2. Получаем объект БД
|
||||||
db = getDb();
|
db = getDb();
|
||||||
console.log('✅ База данных готова');
|
console.log('✅ База данных готова');
|
||||||
|
|
||||||
const { initializeDocumentTypes } = require('./init-document-types');
|
|
||||||
initializeDocumentTypes(db);
|
|
||||||
console.log('✅ Сервис document готов');
|
|
||||||
|
|
||||||
// 3. Настраиваем authService с БД
|
// 3. Настраиваем authService с БД
|
||||||
authService.setDatabase(db);
|
authService.setDatabase(db);
|
||||||
|
|||||||
Reference in New Issue
Block a user