Files
minicrm/api-doc.js
2026-02-02 16:16:14 +05:00

925 lines
45 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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();
}
};
//