This commit is contained in:
2026-02-02 10:24:37 +05:00
parent be9a2a0da0
commit f1bb8cec80
8 changed files with 2499 additions and 749 deletions

921
api-doc.js Normal file
View File

@@ -0,0 +1,921 @@
// api-doc.js - API endpoints для согласования документов
const path = require('path');
const fs = require('fs');
const archiver = require('archiver');
module.exports = function(app, db, upload) {
// API для типов документов
app.get('/api/document-types', requireAuth, (req, res) => {
db.all("SELECT * FROM document_types ORDER BY name", [], (err, rows) => {
if (err) {
res.status(500).json({ error: err.message });
return;
}
res.json(rows);
});
});
// API для создания документа
app.post('/api/documents', requireAuth, upload.array('files', 15), async (req, res) => {
try {
const userId = req.session.user.id;
const {
title,
description,
dueDate,
documentTypeId,
documentNumber,
documentDate,
pagesCount,
urgencyLevel,
comment
} = req.body;
// Валидация
if (!title || title.trim() === '') {
return res.status(400).json({ error: 'Название документа обязательно' });
}
// Получаем пользователей для согласования из .env
const doc1User = process.env.DOC1_USER;
const doc2Users = process.env.DOC2_USERS ? process.env.DOC2_USERS.split(',') : [];
if (!doc1User) {
return res.status(400).json({ error: 'Не настроен DOC1_USER в системе' });
}
// Находим пользователя DOC1
db.get("SELECT id FROM users WHERE login = ?", [doc1User], async (err, doc1) => {
if (err || !doc1) {
return res.status(400).json({ error: `Пользователь DOC1 (${doc1User}) не найден` });
}
// Создаем задачу для документа
db.run(`
INSERT INTO tasks (title, description, due_date, created_by, status, created_at)
VALUES (?, ?, ?, ?, 'active', datetime('now'))
`, [
`Документ: ${title}`,
description || '',
dueDate || null,
userId
], function(err) {
if (err) {
return res.status(500).json({ error: err.message });
}
const taskId = this.lastID;
// Создаем запись документа
db.run(`
INSERT INTO documents (
task_id, document_type_id, document_number,
document_date, pages_count, urgency_level, comment,
created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))
`, [
taskId,
documentTypeId || null,
documentNumber || null,
documentDate || null,
pagesCount || null,
urgencyLevel || 'normal',
comment || null
], function(err) {
if (err) {
console.error('❌ Ошибка создания документа:', err);
db.run("DELETE FROM tasks WHERE id = ?", [taskId]);
return res.status(500).json({ error: 'Ошибка создания записи документа' });
}
const documentId = this.lastID;
// Назначаем DOC1 для предварительного согласования
db.run(`
INSERT INTO task_assignments (task_id, user_id, status, created_at)
VALUES (?, ?, 'assigned', datetime('now'))
`, [taskId, doc1.id], function(err) {
if (err) {
console.error('❌ Ошибка назначения DOC1:', err);
db.run("DELETE FROM documents WHERE id = ?", [documentId]);
db.run("DELETE FROM tasks WHERE id = ?", [taskId]);
return res.status(500).json({ error: 'Ошибка назначения документа на согласование' });
}
const doc1AssignmentId = this.lastID;
// Загружаем файлы если есть
if (req.files && req.files.length > 0) {
const uploadPromises = req.files.map(file => {
return new Promise((resolve, reject) => {
const filePath = file.path;
const originalName = Buffer.from(file.originalname, 'latin1').toString('utf8');
db.run(`
INSERT INTO task_files (task_id, user_id, file_path, original_name, file_size, uploaded_at)
VALUES (?, ?, ?, ?, ?, datetime('now'))
`, [taskId, userId, filePath, originalName, file.size], function(err) {
if (err) {
console.error('❌ Ошибка сохранения файла:', err);
reject(err);
} else {
resolve();
}
});
});
});
Promise.all(uploadPromises)
.then(() => {
// Логируем создание документа
const { logActivity } = require('./database');
logActivity(taskId, userId, 'DOCUMENT_CREATED', `Создан документ: ${title}`);
// Отправляем уведомление DOC1
sendDocumentNotification(doc1.id, taskId, 'new_document', title);
res.json({
success: true,
message: 'Документ успешно создан и отправлен на предварительное согласование'
});
})
.catch(error => {
// Все равно возвращаем успех, так как документ создан
const { logActivity } = require('./database');
logActivity(taskId, userId, 'DOCUMENT_CREATED', `Создан документ: ${title}`);
// Отправляем уведомление DOC1
sendDocumentNotification(doc1.id, taskId, 'new_document', title);
res.json({
success: true,
message: 'Документ создан, но были проблемы с загрузкой файлов'
});
});
} else {
// Логируем создание документа
const { logActivity } = require('./database');
logActivity(taskId, userId, 'DOCUMENT_CREATED', `Создан документ: ${title}`);
// Отправляем уведомление DOC1
sendDocumentNotification(doc1.id, taskId, 'new_document', title);
res.json({
success: true,
message: 'Документ успешно создан и отправлен на предварительное согласование'
});
}
});
});
});
});
} catch (error) {
console.error('❌ Общая ошибка создания документа:', error);
res.status(500).json({
error: 'Ошибка создания документа',
details: error.message
});
}
});
// Получение моих документов
app.get('/api/documents/my', requireAuth, (req, res) => {
const userId = req.session.user.id;
db.all(`
SELECT
t.id,
t.title,
t.description,
t.due_date,
t.created_at,
t.status,
t.closed_at,
d.id as document_id,
d.document_type_id,
dt.name as document_type_name,
d.document_number,
d.document_date,
d.pages_count,
d.urgency_level,
d.comment,
d.refusal_reason,
ta.status as assignment_status
FROM tasks t
LEFT JOIN documents d ON t.id = d.task_id
LEFT JOIN document_types dt ON d.document_type_id = dt.id
LEFT JOIN task_assignments ta ON t.id = ta.task_id
WHERE t.created_by = ?
AND t.title LIKE 'Документ:%'
ORDER BY t.created_at DESC
`, [userId], async (err, tasks) => {
if (err) {
return res.status(500).json({ error: err.message });
}
// Загружаем файлы для каждой задачи
const tasksWithFiles = await Promise.all(tasks.map(async (task) => {
try {
const files = await new Promise((resolve, reject) => {
db.all(`
SELECT tf.*, u.name as user_name
FROM task_files tf
LEFT JOIN users u ON tf.user_id = u.id
WHERE tf.task_id = ?
ORDER BY tf.uploaded_at DESC
`, [task.id], (err, rows) => {
if (err) reject(err);
else resolve(rows || []);
});
});
task.files = files || [];
} catch (error) {
task.files = [];
}
return task;
}));
res.json(tasksWithFiles);
});
});
// Получение документов для согласования (DOC1 и DOC2)
app.get('/api/documents/approval', requireAuth, (req, res) => {
const userId = req.session.user.id;
// Проверяем, является ли пользователь DOC1 или DOC2
db.get("SELECT login FROM users WHERE id = ?", [userId], (err, user) => {
if (err || !user) {
return res.status(403).json({ error: 'Пользователь не найден' });
}
const userLogin = user.login;
const doc1User = process.env.DOC1_USER;
const doc2Users = process.env.DOC2_USERS ? process.env.DOC2_USERS.split(',') : [];
const isDoc1 = userLogin === doc1User;
const isDoc2 = doc2Users.includes(userLogin);
if (!isDoc1 && !isDoc2) {
return res.status(403).json({ error: 'Недостаточно прав для согласования документов' });
}
// Определяем статус для фильтрации
let statusFilter = '';
if (isDoc1) {
// DOC1 видит документы на предварительном согласовании
statusFilter = "AND ta.status IN ('assigned', 'pre_approved')";
} else if (isDoc2) {
// DOC2 видит предварительно согласованные документы
statusFilter = "AND ta.status = 'pre_approved'";
}
db.all(`
SELECT
t.id,
t.title,
t.description,
t.due_date,
t.created_at,
d.id as document_id,
d.document_type_id,
dt.name as document_type_name,
d.document_number,
d.document_date,
d.pages_count,
d.urgency_level,
d.comment,
d.refusal_reason,
ta.status as assignment_status,
u.name as creator_name,
u.login as creator_login
FROM tasks t
JOIN documents d ON t.id = d.task_id
LEFT JOIN document_types dt ON d.document_type_id = dt.id
JOIN task_assignments ta ON t.id = ta.task_id
JOIN users u ON t.created_by = u.id
WHERE ta.user_id = ?
AND t.title LIKE 'Документ:%'
AND t.status = 'active'
AND t.closed_at IS NULL
${statusFilter}
ORDER BY
CASE d.urgency_level
WHEN 'very_urgent' THEN 1
WHEN 'urgent' THEN 2
ELSE 3
END,
t.due_date ASC,
t.created_at DESC
`, [userId], async (err, tasks) => {
if (err) {
return res.status(500).json({ error: err.message });
}
// Загружаем файлы для каждой задачи
const tasksWithFiles = await Promise.all(tasks.map(async (task) => {
try {
const files = await new Promise((resolve, reject) => {
db.all(`
SELECT tf.*, u.name as user_name
FROM task_files tf
LEFT JOIN users u ON tf.user_id = u.id
WHERE tf.task_id = ?
ORDER BY tf.uploaded_at DESC
`, [task.id], (err, rows) => {
if (err) reject(err);
else resolve(rows || []);
});
});
task.files = files || [];
} catch (error) {
task.files = [];
}
return task;
}));
res.json(tasksWithFiles);
});
});
});
// Обновление статуса документа
app.put('/api/documents/:id/status', requireAuth, (req, res) => {
const documentId = req.params.id;
const { status, comment, refusalReason } = req.body;
const userId = req.session.user.id;
// Проверяем права пользователя
db.get("SELECT login FROM users WHERE id = ?", [userId], (err, user) => {
if (err || !user) {
return res.status(403).json({ error: 'Пользователь не найден' });
}
const userLogin = user.login;
const doc1User = process.env.DOC1_USER;
const doc2Users = process.env.DOC2_USERS ? process.env.DOC2_USERS.split(',') : [];
const isDoc1 = userLogin === doc1User;
const isDoc2 = doc2Users.includes(userLogin);
if (!isDoc1 && !isDoc2) {
return res.status(403).json({ error: 'Недостаточно прав' });
}
// Проверяем текущий статус документа
db.get(`
SELECT d.*, ta.status as assignment_status, ta.user_id as assignee_id,
t.title, t.created_by
FROM documents d
JOIN tasks t ON d.task_id = t.id
JOIN task_assignments ta ON t.id = ta.task_id
WHERE d.id = ? AND ta.user_id = ?
`, [documentId, userId], (err, document) => {
if (err || !document) {
return res.status(404).json({ error: 'Документ не найден или у вас нет прав' });
}
// Валидация переходов статусов
if (isDoc1) {
// DOC1 может только предварительно согласовать или отказать
if (status !== 'pre_approved' && status !== 'refused') {
return res.status(400).json({ error: 'DOC1 может только предварительно согласовать или отказать' });
}
if (status === 'pre_approved') {
// Если DOC1 предварительно согласовал, назначаем DOC2
updateDoc1Status();
} else {
// Если отказал, просто обновляем статус
updateStatus();
}
} else if (isDoc2) {
// DOC2 может согласовать или отказать только предварительно согласованные документы
if (document.assignment_status !== 'pre_approved') {
return res.status(400).json({ error: 'DOC2 может работать только с предварительно согласованными документами' });
}
if (status === 'approved' || status === 'refused') {
updateStatus();
} else {
return res.status(400).json({ error: 'DOC2 может только согласовать или отказать' });
}
}
function updateDoc1Status() {
// Обновляем статус DOC1
db.run("UPDATE task_assignments SET status = ? WHERE task_id = ? AND user_id = ?",
[status, document.task_id, userId], function(err) {
if (err) {
return res.status(500).json({ error: err.message });
}
// Назначаем DOC2 пользователям
const doc2Logins = doc2Users;
// Находим ID пользователей DOC2
const placeholders = doc2Logins.map(() => '?').join(',');
db.all(`SELECT id FROM users WHERE login IN (${placeholders})`, doc2Logins, (err, doc2UsersList) => {
if (err || doc2UsersList.length === 0) {
console.error('DOC2 пользователи не найдены');
// Все равно считаем успехом
return afterAssignments();
}
// Создаем задания для каждого DOC2
const assignmentPromises = doc2UsersList.map(doc2User => {
return new Promise((resolve, reject) => {
db.run(`
INSERT INTO task_assignments (task_id, user_id, status, created_at)
VALUES (?, ?, 'assigned', datetime('now'))
`, [document.task_id, doc2User.id], function(err) {
if (err) reject(err);
else resolve();
});
});
});
Promise.all(assignmentPromises)
.then(() => {
afterAssignments();
})
.catch(error => {
console.error('Ошибка назначения DOC2:', error);
afterAssignments(); // Все равно продолжаем
});
});
function afterAssignments() {
// Логируем действие
const { logActivity } = require('./database');
logActivity(document.task_id, userId, 'STATUS_CHANGED',
`Документ предварительно согласован. Назначен DOC2: ${doc2Logins.join(', ')}`);
// Сохраняем комментарий
if (comment) {
db.run("UPDATE documents SET comment = COALESCE(comment, '') || '\n' || ? WHERE id = ?",
[`DOC1 (${new Date().toLocaleString('ru-RU')}): ${comment}`, documentId]);
}
// Отправляем уведомление создателю
sendDocumentNotification(document.created_by, document.task_id, 'pre_approved', document.title);
// Отправляем уведомления всем DOC2
doc2Users.forEach(login => {
db.get("SELECT id FROM users WHERE login = ?", [login], (err, doc2User) => {
if (!err && doc2User) {
sendDocumentNotification(doc2User.id, document.task_id, 'new_document_for_doc2', document.title);
}
});
});
res.json({ success: true });
}
}
);
}
function updateStatus() {
// Обновляем статус
db.run("UPDATE task_assignments SET status = ? WHERE task_id = ? AND user_id = ?",
[status, document.task_id, userId], function(err) {
if (err) {
return res.status(500).json({ error: err.message });
}
// Сохраняем комментарий и причину отказа
if (comment) {
const role = isDoc1 ? 'DOC1' : 'DOC2';
const timestamp = new Date().toLocaleString('ru-RU');
db.run("UPDATE documents SET comment = COALESCE(comment, '') || '\n' || ? WHERE id = ?",
[`${role} (${timestamp}): ${comment}`, documentId]);
}
if (status === 'refused' && refusalReason) {
db.run("UPDATE documents SET refusal_reason = ? WHERE id = ?",
[refusalReason, documentId]);
}
// Логируем действие
const { logActivity } = require('./database');
const actionText = isDoc1 ?
`DOC1: ${status === 'refused' ? 'Отказано' : 'Предварительно согласовано'}` :
`DOC2: ${status === 'refused' ? 'Отказано' : 'Согласовано'}`;
logActivity(document.task_id, userId, 'STATUS_CHANGED', actionText);
// Отправляем уведомление создателю
if (status === 'approved') {
sendDocumentNotification(document.created_by, document.task_id, 'approved', document.title);
} else if (status === 'refused') {
sendDocumentNotification(document.created_by, document.task_id, 'refused', document.title);
}
res.json({ success: true });
}
);
}
});
});
});
// Отзыв документа
app.post('/api/documents/:id/cancel', requireAuth, (req, res) => {
const documentId = req.params.id;
const userId = req.session.user.id;
db.get("SELECT task_id FROM documents WHERE id = ?", [documentId], (err, document) => {
if (err || !document) {
return res.status(404).json({ error: 'Документ не найден' });
}
const taskId = document.task_id;
// Проверяем, что пользователь создатель задачи
db.get("SELECT created_by FROM tasks WHERE id = ?", [taskId], (err, task) => {
if (err || !task) {
return res.status(404).json({ error: 'Задача не найдена' });
}
if (parseInt(task.created_by) !== parseInt(userId)) {
return res.status(403).json({ error: 'Вы не являетесь создателем этого документа' });
}
// Получаем всех согласующих для уведомлений
db.all("SELECT user_id FROM task_assignments WHERE task_id = ?", [taskId], (err, assignees) => {
if (err) {
console.error('Ошибка получения согласующих:', err);
}
// Обновляем статус задачи
db.run("UPDATE tasks SET status = 'cancelled', closed_at = datetime('now') WHERE id = ?", [taskId], function(err) {
if (err) {
return res.status(500).json({ error: err.message });
}
// Логируем действие
const { logActivity } = require('./database');
logActivity(taskId, userId, 'STATUS_CHANGED', 'Документ отозван создателем');
// Отправляем уведомления согласующим
if (assignees) {
assignees.forEach(assignee => {
if (assignee.user_id !== userId) {
sendDocumentNotification(assignee.user_id, taskId, 'cancelled', 'Документ отозван');
}
});
}
res.json({ success: true });
});
});
});
});
});
// Получение пакета документов (ZIP архив)
app.get('/api/documents/:id/package', requireAuth, async (req, res) => {
const documentId = req.params.id;
const userId = req.session.user.id;
// Проверяем доступ к документу
db.get(`
SELECT t.id, t.created_by, t.title, d.document_number
FROM documents d
JOIN tasks t ON d.task_id = t.id
WHERE d.id = ?
`, [documentId], async (err, result) => {
if (err || !result) {
return res.status(404).json({ error: 'Документ не найден' });
}
// Проверяем, что пользователь имеет доступ
const isCreator = parseInt(result.created_by) === parseInt(userId);
const isDoc1orDoc2 = await checkIfDoc1orDoc2(userId);
if (!isCreator && !isDoc1orDoc2) {
return res.status(403).json({ error: 'Недостаточно прав' });
}
try {
// Получаем все файлы документа
db.all(`
SELECT tf.*
FROM task_files tf
JOIN tasks t ON tf.task_id = t.id
JOIN documents d ON t.id = d.task_id
WHERE d.id = ?
`, [documentId], async (err, files) => {
if (err) {
return res.status(500).json({ error: err.message });
}
if (files.length === 0) {
return res.json({
success: true,
message: 'Нет файлов для скачивания'
});
}
// Создаем временный файл для архива
const tempDir = path.join(__dirname, 'temp');
if (!fs.existsSync(tempDir)) {
fs.mkdirSync(tempDir, { recursive: true });
}
const zipFileName = `document_${documentId}_${Date.now()}.zip`;
const zipFilePath = path.join(tempDir, zipFileName);
const output = fs.createWriteStream(zipFilePath);
const archive = archiver('zip', {
zlib: { level: 9 }
});
output.on('close', () => {
// Отправляем файл
res.download(zipFilePath, `Документ_${result.document_number || result.id}.zip`, (err) => {
// Удаляем временный файл после отправки
if (fs.existsSync(zipFilePath)) {
fs.unlinkSync(zipFilePath);
}
});
});
archive.on('error', (err) => {
console.error('Ошибка создания архива:', err);
res.status(500).json({ error: 'Ошибка создания архива' });
});
archive.pipe(output);
// Добавляем файлы в архив
for (const file of files) {
if (fs.existsSync(file.file_path)) {
const fileName = path.basename(file.original_name);
archive.file(file.file_path, { name: fileName });
}
}
// Добавляем информацию о документе как текстовый файл
const docInfo = `
Документ: ${result.title}
Номер документа: ${result.document_number || 'Не указан'}
Дата создания: ${new Date().toLocaleString('ru-RU')}
Файлы в архиве:
${files.map((f, i) => `${i + 1}. ${f.original_name} (${formatFileSize(f.file_size)})`).join('\n')}
`;
archive.append(docInfo, { name: 'Информация_оокументе.txt' });
await archive.finalize();
});
} catch (error) {
console.error('Ошибка создания пакета:', error);
res.status(500).json({
success: false,
message: 'Ошибка создания пакета документов'
});
}
});
});
// Статистика по документам
app.get('/api/documents/stats', requireAuth, (req, res) => {
const userId = req.session.user.id;
// Проверяем права
db.get("SELECT login FROM users WHERE id = ?", [userId], (err, user) => {
if (err || !user) {
return res.status(403).json({ error: 'Пользователь не найден' });
}
const userLogin = user.login;
const doc1User = process.env.DOC1_USER;
const doc2Users = process.env.DOC2_USERS ? process.env.DOC2_USERS.split(',') : [];
const isDoc1 = userLogin === doc1User;
const isDoc2 = doc2Users.includes(userLogin);
const isAdmin = req.session.user.role === 'admin';
if (!isDoc1 && !isDoc2 && !isAdmin) {
return res.status(403).json({ error: 'Недостаточно прав' });
}
let statsQuery = '';
let params = [];
if (isAdmin) {
// Админ видит все документы
statsQuery = `
SELECT
COUNT(*) as total,
COUNT(CASE WHEN t.status = 'active' AND t.closed_at IS NULL THEN 1 END) as active,
COUNT(CASE WHEN ta.status = 'pre_approved' THEN 1 END) as pre_approved,
COUNT(CASE WHEN ta.status = 'approved' THEN 1 END) as approved,
COUNT(CASE WHEN ta.status = 'refused' THEN 1 END) as refused,
COUNT(CASE WHEN t.status = 'cancelled' THEN 1 END) as cancelled
FROM tasks t
LEFT JOIN documents d ON t.id = d.task_id
LEFT JOIN task_assignments ta ON t.id = ta.task_id
WHERE t.title LIKE 'Документ:%'
`;
} else {
// DOC1 и DOC2 видят только свои документы
statsQuery = `
SELECT
COUNT(*) as total,
COUNT(CASE WHEN ta.status = 'assigned' THEN 1 END) as assigned,
COUNT(CASE WHEN ta.status = 'pre_approved' THEN 1 END) as pre_approved,
COUNT(CASE WHEN ta.status = 'approved' THEN 1 END) as approved,
COUNT(CASE WHEN ta.status = 'refused' THEN 1 END) as refused
FROM tasks t
JOIN documents d ON t.id = d.task_id
JOIN task_assignments ta ON t.id = ta.task_id
WHERE t.title LIKE 'Документ:%'
AND t.status = 'active'
AND t.closed_at IS NULL
AND ta.user_id = ?
`;
params = [userId];
}
db.get(statsQuery, params, (err, stats) => {
if (err) {
return res.status(500).json({ error: err.message });
}
res.json(stats || {
total: 0,
active: 0,
pre_approved: 0,
approved: 0,
refused: 0,
cancelled: 0
});
});
});
});
// Получение истории документа
app.get('/api/documents/:id/history', requireAuth, (req, res) => {
const documentId = req.params.id;
const userId = req.session.user.id;
// Проверяем доступ к документу
db.get(`
SELECT t.created_by
FROM documents d
JOIN tasks t ON d.task_id = t.id
WHERE d.id = ?
`, [documentId], (err, document) => {
if (err || !document) {
return res.status(404).json({ error: 'Документ не найден' });
}
// Проверяем права
const isCreator = parseInt(document.created_by) === parseInt(userId);
const isDoc1orDoc2 = checkIfDoc1orDoc2Sync(userId);
if (!isCreator && !isDoc1orDoc2) {
return res.status(403).json({ error: 'Недостаточно прав' });
}
const taskIdQuery = "SELECT task_id FROM documents WHERE id = ?";
db.get(taskIdQuery, [documentId], (err, result) => {
if (err || !result) {
return res.status(500).json({ error: 'Ошибка получения истории' });
}
const taskId = result.task_id;
// Получаем историю активности
db.all(`
SELECT al.*, u.name as user_name
FROM activity_logs al
LEFT JOIN users u ON al.user_id = u.id
WHERE al.task_id = ?
ORDER BY al.created_at DESC
`, [taskId], (err, history) => {
if (err) {
return res.status(500).json({ error: err.message });
}
// Получаем комментарии из документа
db.get("SELECT comment FROM documents WHERE id = ?", [documentId], (err, doc) => {
if (err) {
doc = { comment: '' };
}
const comments = doc.comment ? doc.comment.split('\n').filter(c => c.trim()).map(c => {
return {
text: c,
type: 'comment'
};
}) : [];
res.json({
activity: history || [],
comments: comments
});
});
});
});
});
});
// Вспомогательные функции
// Функция для проверки DOC1/DOC2 (асинхронная)
function checkIfDoc1orDoc2(userId) {
return new Promise((resolve, reject) => {
db.get("SELECT login FROM users WHERE id = ?", [userId], (err, user) => {
if (err || !user) {
resolve(false);
return;
}
const userLogin = user.login;
const doc1User = process.env.DOC1_USER;
const doc2Users = process.env.DOC2_USERS ? process.env.DOC2_USERS.split(',') : [];
const isDoc1 = userLogin === doc1User;
const isDoc2 = doc2Users.includes(userLogin);
resolve(isDoc1 || isDoc2);
});
});
}
// Функция для проверки DOC1/DOC2 (синхронная версия)
function checkIfDoc1orDoc2Sync(userId) {
// Эта функция используется в синхронных контекстах
// В реальном приложении нужно быть осторожным с синхронными вызовами
try {
const user = db.getSync("SELECT login FROM users WHERE id = ?", [userId]);
if (!user) return false;
const userLogin = user.login;
const doc1User = process.env.DOC1_USER;
const doc2Users = process.env.DOC2_USERS ? process.env.DOC2_USERS.split(',') : [];
const isDoc1 = userLogin === doc1User;
const isDoc2 = doc2Users.includes(userLogin);
return isDoc1 || isDoc2;
} catch (error) {
return false;
}
}
// Функция для отправки уведомлений о документах
function sendDocumentNotification(userId, taskId, type, documentTitle) {
try {
const { sendTaskNotifications } = require('./notifications');
let message = '';
switch(type) {
case 'new_document':
message = `Новый документ на согласование: ${documentTitle}`;
break;
case 'new_document_for_doc2':
message = `Новый документ для согласования (DOC2): ${documentTitle}`;
break;
case 'pre_approved':
message = `Документ предварительно согласован: ${documentTitle}`;
break;
case 'approved':
message = `Документ согласован: ${documentTitle}`;
break;
case 'refused':
message = `В согласовании документа отказано: ${documentTitle}`;
break;
case 'cancelled':
message = `Документ отозван создателем: ${documentTitle}`;
break;
default:
message = `Обновление документа: ${documentTitle}`;
}
sendTaskNotifications(taskId, userId, message);
} catch (error) {
console.error('Ошибка отправки уведомления:', error);
}
}
// Вспомогательная функция для форматирования размера файла
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
// Middleware для аутентификации (можно импортировать из server.js)
function requireAuth(req, res, next) {
if (!req.session.user) {
return res.status(401).json({ error: 'Требуется аутентификация' });
}
next();
}
};