чистка PG

This commit is contained in:
2026-04-06 22:45:36 +05:00
parent 488cb5d1e2
commit 76ee4b7ac3
4 changed files with 0 additions and 424 deletions

View File

@@ -1,5 +1,4 @@
// notifications.js // notifications.js
const postgresLogger = require('./postgres');
const { getDb } = require('./database'); const { getDb } = require('./database');
const emailNotifications = require('./email-notifications'); const emailNotifications = require('./email-notifications');
@@ -86,24 +85,6 @@ async function sendTaskNotifications(type, taskId, taskTitle, taskDescription, a
} }
} }
// Логируем в PostgreSQL (если настроено)
let postgresLogIds = [];
if (postgresLogger.initialized) {
postgresLogIds = await logNotificationToPostgres({
type,
taskId,
taskTitle,
taskDescription,
authorId,
authorName,
authorLogin,
recipients,
comment,
status,
userName
});
}
// 5. Отправляем email уведомления выбранным получателям // 5. Отправляем email уведомления выбранным получателям
for (const recipient of recipients) { for (const recipient of recipients) {
const taskData = { const taskData = {
@@ -217,90 +198,6 @@ async function checkUpcomingDeadlines() {
}); });
} }
/**
* Логирует уведомление в PostgreSQL
*/
async function logNotificationToPostgres(data) {
try {
const {
type,
taskId,
taskTitle,
taskDescription,
authorId,
authorName,
authorLogin,
recipients = [],
comment = '',
status = '',
userName = '',
error = ''
} = data;
// Создаем сообщение
let messageContent = '';
switch (type) {
case 'created':
messageContent = `Создана новая задача: ${taskTitle}`;
break;
case 'updated':
messageContent = `Обновлена задача: ${taskTitle}`;
break;
case 'rework':
messageContent = `Задача возвращена на доработку: ${taskTitle}. Комментарий: ${comment}`;
break;
case 'closed':
messageContent = `Задача закрыта: ${taskTitle}`;
break;
case 'status_changed':
messageContent = `Изменен статус задачи: ${taskTitle}. Новый статус: ${getStatusText(status)}`;
break;
}
const logIds = [];
for (const recipient of recipients) {
const logId = await postgresLogger.logNotification({
taskId,
taskTitle,
taskDescription,
notificationType: type,
authorId,
authorName,
authorLogin,
recipientId: recipient.user_id,
recipientName: recipient.user_name,
recipientLogin: recipient.user_login,
messageContent: `${messageContent}\n\nЗадача: ${taskTitle}\nОписание: ${taskDescription || 'Без описания'}\nАвтор: ${authorName}`,
messageSubject: getNotificationSubject(type, taskTitle),
deliveryMethods: ['email', 'telegram', 'vk'],
comments: error ? `Ошибка: ${error}` : comment
});
if (logId) {
logIds.push(logId);
}
}
return logIds;
} catch (error) {
console.error('❌ Ошибка логирования в PostgreSQL:', error);
return [];
}
}
/**
* Обновляет статус доставки уведомления в PostgreSQL
*/
async function updatePostgresLogStatus(logIds, status, errorMessage = null, sentAt = null) {
if (!logIds || logIds.length === 0) return;
for (const logId of logIds) {
await postgresLogger.updateNotificationStatus(logId, status, errorMessage, sentAt);
}
}
/** /**
* Возвращает тему уведомления в зависимости от типа * Возвращает тему уведомления в зависимости от типа
*/ */

View File

@@ -1,100 +0,0 @@
const { Client } = require('pg');
require('dotenv').config();
async function initializeDatabase() {
console.log('🔄 Инициализация PostgreSQL...');
// Сначала подключаемся без конкретной БД
const adminClient = new Client({
host: process.env.DB_HOST,
port: process.env.DB_PORT || 5432,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: 'postgres' // Подключаемся к системной БД
});
try {
await adminClient.connect();
console.log('✅ Подключение к PostgreSQL установлено');
// Проверяем существование базы данных
const dbCheck = await adminClient.query(`
SELECT 1 FROM pg_database WHERE datname = '${process.env.DB_NAME}'
`);
if (dbCheck.rows.length === 0) {
console.log(`📦 База данных ${process.env.DB_NAME} не существует, создаем...`);
await adminClient.query(`CREATE DATABASE ${process.env.DB_NAME}`);
console.log(`✅ База данных ${process.env.DB_NAME} создана`);
} else {
console.log(`✅ База данных ${process.env.DB_NAME} уже существует`);
}
await adminClient.end();
// Теперь подключаемся к созданной БД
const dbClient = new Client({
host: process.env.DB_HOST,
port: process.env.DB_PORT || 5432,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
});
await dbClient.connect();
// Создаем таблицы
await dbClient.query(`
CREATE TABLE IF NOT EXISTS sms_logs (
id SERIAL PRIMARY KEY,
task_id INTEGER NOT NULL,
task_title VARCHAR(500) NOT NULL,
task_description TEXT,
notification_type VARCHAR(50) NOT NULL,
creator_id INTEGER,
creator_name VARCHAR(255),
creator_login VARCHAR(100),
assignee_id INTEGER,
assignee_name VARCHAR(255),
assignee_login VARCHAR(100),
message_content TEXT NOT NULL,
message_subject VARCHAR(500),
delivery_methods JSONB DEFAULT '[]',
status VARCHAR(50) DEFAULT 'pending',
error_message TEXT,
retry_count INTEGER DEFAULT 0,
sent_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
comments TEXT
)
`);
// Создаем индексы
const indexes = [
'CREATE INDEX IF NOT EXISTS idx_sms_logs_task_id ON sms_logs(task_id)',
'CREATE INDEX IF NOT EXISTS idx_sms_logs_creator_id ON sms_logs(creator_id)',
'CREATE INDEX IF NOT EXISTS idx_sms_logs_assignee_id ON sms_logs(assignee_id)',
'CREATE INDEX IF NOT EXISTS idx_sms_logs_status ON sms_logs(status)',
'CREATE INDEX IF NOT EXISTS idx_sms_logs_created_at ON sms_logs(created_at)'
];
for (const indexQuery of indexes) {
try {
await dbClient.query(indexQuery);
} catch (err) {
console.warn(`⚠️ Индекс не создан: ${err.message}`);
}
}
await dbClient.end();
console.log('✅ PostgreSQL полностью инициализирован');
return true;
} catch (error) {
console.error('❌ Ошибка инициализации PostgreSQL:', error.message);
return false;
}
}
module.exports = { initializeDatabase };

View File

@@ -1,206 +0,0 @@
const { Pool } = require('pg');
require('dotenv').config();
const { initializeDatabase } = require('./postgres-init');
class PostgresLogger {
constructor() {
this.pool = null;
this.initialized = false;
this.init();
}
async init() {
try {
console.log('🔌 Инициализация PostgreSQL логгера...');
// Проверяем наличие переменных окружения
if (!process.env.DB_HOST || !process.env.DB_USER || !process.env.DB_PASSWORD) {
console.log('⚠️ Переменные окружения для PostgreSQL не заданы');
console.log(' DB_HOST:', process.env.DB_HOST || 'не задано');
console.log(' DB_USER:', process.env.DB_USER || 'не задано');
console.log(' DB_NAME:', process.env.DB_NAME || 'minicrm');
this.initialized = false;
return;
}
// Создаем базу данных если нужно
const dbInitialized = await initializeDatabase();
if (!dbInitialized) {
console.error('❌ Не удалось инициализировать базу данных');
this.initialized = false;
return;
}
// Подключаемся к созданной БД
this.pool = 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: 5000,
});
// Тестируем подключение
const client = await this.pool.connect();
await client.query('SELECT 1');
client.release();
this.initialized = true;
console.log('✅ PostgreSQL логгер готов к работе');
} catch (error) {
console.error('❌ Ошибка инициализации PostgreSQL логгера:', error.message);
console.error(' Убедитесь, что:');
console.error(' 1. PostgreSQL сервер запущен на', process.env.DB_HOST);
console.error(' 2. Пользователь', process.env.DB_USER, 'имеет права на создание БД');
console.error(' 3. Пароль указан верно в .env файле');
this.initialized = false;
}
}
async logNotification(notificationData) {
if (!this.initialized) {
console.log('⚠️ PostgreSQL не инициализирован, логирование пропущено');
return null;
}
const {
taskId,
taskTitle,
taskDescription = '',
notificationType,
authorId,
authorName,
authorLogin,
recipientId,
recipientName,
recipientLogin,
messageContent,
messageSubject = '',
deliveryMethods = ['email', 'telegram', 'vk'],
comments = ''
} = notificationData;
let client;
try {
client = await this.pool.connect();
const query = `
INSERT INTO sms_logs (
task_id, task_title, task_description, notification_type,
creator_id, creator_name, creator_login,
assignee_id, assignee_name, assignee_login,
message_content, message_subject, delivery_methods,
status, comments, created_at
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, CURRENT_TIMESTAMP)
RETURNING id;
`;
const values = [
taskId,
taskTitle?.substring(0, 500) || 'Без названия',
taskDescription?.substring(0, 5000) || '',
notificationType,
authorId,
authorName || 'Неизвестно',
authorLogin || 'unknown',
recipientId,
recipientName || 'Неизвестно',
recipientLogin || 'unknown',
messageContent?.substring(0, 5000) || '',
messageSubject?.substring(0, 500) || '',
JSON.stringify(deliveryMethods),
'pending',
comments
];
const result = await client.query(query, values);
const logId = result.rows[0]?.id;
if (logId) {
console.log(`📝 Уведомление записано в PostgreSQL, ID: ${logId}`);
}
return logId || null;
} catch (error) {
console.error('❌ Ошибка записи уведомления в PostgreSQL:', error.message);
return null;
} finally {
if (client) client.release();
}
}
async updateNotificationStatus(logId, status, errorMessage = null, sentAt = null) {
if (!this.initialized || !logId) return;
let client;
try {
client = await this.pool.connect();
const query = `
UPDATE sms_logs
SET status = $1,
error_message = $2,
sent_at = $3,
updated_at = CURRENT_TIMESTAMP
WHERE id = $4;
`;
await client.query(query, [
status,
errorMessage,
sentAt ? new Date(sentAt) : (status === 'sent' ? new Date() : null),
logId
]);
console.log(`📝 Статус уведомления ${logId} обновлен на: ${status}`);
} catch (error) {
console.error('❌ Ошибка обновления статуса уведомления:', error.message);
} finally {
if (client) client.release();
}
}
async healthCheck() {
if (!this.initialized) {
return {
connected: false,
error: 'PostgreSQL не инициализирован',
timestamp: new Date().toISOString()
};
}
let client;
try {
client = await this.pool.connect();
await client.query('SELECT 1');
return {
connected: true,
timestamp: new Date().toISOString(),
database: process.env.DB_NAME || 'minicrm',
host: process.env.DB_HOST
};
} catch (error) {
return {
connected: false,
error: error.message,
timestamp: new Date().toISOString()
};
} finally {
if (client) client.release();
}
}
// Другие методы остаются без изменений...
}
// Экспортируем singleton
const postgresLogger = new PostgresLogger();
module.exports = postgresLogger;

View File

@@ -12,7 +12,6 @@ const userListsAPI = require('./api-user-lists');
// Импортируем модули // Импортируем модули
const { initializeDatabase, getDb, isInitialized } = require('./database'); const { initializeDatabase, getDb, isInitialized } = require('./database');
const authService = require('./auth'); const authService = require('./auth');
const postgresLogger = require('./postgres');
const { sendTaskNotifications, checkUpcomingDeadlines, getStatusText } = require('./notifications'); const { sendTaskNotifications, checkUpcomingDeadlines, getStatusText } = require('./notifications');
const { setupUploadMiddleware } = require('./upload-middleware'); const { setupUploadMiddleware } = require('./upload-middleware');
const { setupTaskEndpoints } = require('./task-endpoints'); const { setupTaskEndpoints } = require('./task-endpoints');
@@ -735,20 +734,6 @@ app.get('/api/notification-stats', requireAuth, async (req, res) => {
} }
}); });
// API для проверки состояния PostgreSQL
app.get('/api/postgres-health', requireAuth, async (req, res) => {
try {
if (req.session.user.role !== 'admin') {
return res.status(403).json({ error: 'Недостаточно прав' });
}
const health = await postgresLogger.healthCheck();
res.json(health);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Админ панель // Админ панель
app.get('/admin', (req, res) => { app.get('/admin', (req, res) => {
if (!req.session.user) { if (!req.session.user) {