hz
This commit is contained in:
@@ -2,6 +2,19 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
function getApproverUsers(groupId) {
|
||||
return new Promise((resolve) => {
|
||||
db.all(`
|
||||
SELECT u.id, u.login, u.name, u.email
|
||||
FROM users u
|
||||
JOIN user_group_memberships ugm ON u.id = ugm.user_id
|
||||
WHERE ugm.group_id = ?
|
||||
`, [groupId], (err, users) => {
|
||||
resolve(err ? [] : users);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setupTaskEndpoints(app, db, upload) {
|
||||
const { logActivity, createUserTaskFolder, saveTaskMetadata, updateTaskMetadata, checkTaskAccess } = require('./database');
|
||||
const { sendTaskNotifications } = require('./notifications');
|
||||
@@ -444,7 +457,180 @@ function setupTaskEndpoints(app, db, upload) {
|
||||
});
|
||||
});
|
||||
});
|
||||
// API для создания задачи согласования документов
|
||||
app.post('/api/document-approval-tasks', requireAuth, upload.array('files', 15), (req, res) => {
|
||||
const { title, description, approverGroupId, documentId, dueDate } = req.body;
|
||||
const createdBy = req.session.user.id;
|
||||
|
||||
if (!title) {
|
||||
return res.status(400).json({ error: 'Название задачи обязательно' });
|
||||
}
|
||||
|
||||
if (!approverGroupId) {
|
||||
return res.status(400).json({ error: 'Выберите группу для согласования' });
|
||||
}
|
||||
|
||||
if (!dueDate) {
|
||||
return res.status(400).json({ error: 'Дата и время выполнения обязательны' });
|
||||
}
|
||||
|
||||
// Проверяем, может ли группа согласовывать документы
|
||||
db.get("SELECT can_approve_documents FROM user_groups WHERE id = ?",
|
||||
[approverGroupId], (err, group) => {
|
||||
if (err || !group || !group.can_approve_documents) {
|
||||
return res.status(400).json({ error: 'Выбранная группа не может согласовывать документы' });
|
||||
}
|
||||
|
||||
db.serialize(async () => {
|
||||
const startDate = new Date().toISOString();
|
||||
|
||||
// Создаем задачу с типом "document_approval"
|
||||
db.run(
|
||||
`INSERT INTO tasks (title, description, created_by, task_type,
|
||||
approver_group_id, document_id, start_date, due_date)
|
||||
VALUES (?, ?, ?, 'document_approval', ?, ?, ?, ?)`,
|
||||
[title, description, createdBy, approverGroupId, documentId || null, startDate, dueDate || null],
|
||||
async function(err) {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
|
||||
const taskId = this.lastID;
|
||||
|
||||
// Сохраняем метаданные
|
||||
saveTaskMetadata(taskId, title, description, createdBy, null, startDate, dueDate);
|
||||
|
||||
// Получаем всех пользователей из группы согласующих
|
||||
const approvers = await getApproverUsers(approverGroupId);
|
||||
|
||||
// Назначаем задачу всем согласующим в группе
|
||||
if (approvers.length > 0) {
|
||||
approvers.forEach(approver => {
|
||||
db.run(
|
||||
"INSERT INTO task_assignments (task_id, user_id, status, start_date, due_date) VALUES (?, ?, 'assigned', ?, ?)",
|
||||
[taskId, approver.id, startDate, dueDate || null]
|
||||
);
|
||||
});
|
||||
|
||||
// Отправляем уведомления
|
||||
sendTaskNotifications('created', taskId, title, description, createdBy);
|
||||
}
|
||||
|
||||
logActivity(taskId, createdBy, 'DOCUMENT_APPROVAL_TASK_CREATED',
|
||||
`Создана задача согласования документа для группы ${approverGroupId}`);
|
||||
|
||||
// Загрузка файлов (если есть)
|
||||
if (req.files && req.files.length > 0) {
|
||||
const userFolder = createUserTaskFolder(taskId, req.session.user.login);
|
||||
|
||||
req.files.forEach(file => {
|
||||
const newPath = path.join(userFolder, path.basename(file.filename));
|
||||
fs.renameSync(file.path, newPath);
|
||||
|
||||
const originalName = file.originalname;
|
||||
|
||||
db.run(
|
||||
"INSERT INTO task_files (task_id, user_id, filename, original_name, file_path, file_size) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
[taskId, createdBy, path.basename(file.filename), originalName, newPath, file.size]
|
||||
);
|
||||
|
||||
logActivity(taskId, createdBy, 'FILE_UPLOADED', `Загружен файл: ${originalName}`);
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
taskId: taskId,
|
||||
message: 'Задача согласования документа создана',
|
||||
approversCount: approvers.length
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// API для получения задач согласования документов
|
||||
app.get('/api/document-approval-tasks', requireAuth, (req, res) => {
|
||||
const userId = req.session.user.id;
|
||||
|
||||
const query = `
|
||||
SELECT DISTINCT
|
||||
t.*,
|
||||
u.name as creator_name,
|
||||
u.login as creator_login,
|
||||
g.name as approver_group_name,
|
||||
g.color as approver_group_color,
|
||||
GROUP_CONCAT(DISTINCT ta.user_id) as assigned_user_ids,
|
||||
GROUP_CONCAT(DISTINCT u2.name) as assigned_user_names
|
||||
FROM tasks t
|
||||
LEFT JOIN users u ON t.created_by = u.id
|
||||
LEFT JOIN user_groups g ON t.approver_group_id = g.id
|
||||
LEFT JOIN task_assignments ta ON t.id = ta.task_id
|
||||
LEFT JOIN users u2 ON ta.user_id = u2.id
|
||||
WHERE t.task_type = 'document_approval'
|
||||
AND t.status = 'active'
|
||||
AND t.closed_at IS NULL
|
||||
`;
|
||||
|
||||
const params = [];
|
||||
|
||||
if (req.session.user.role !== 'admin') {
|
||||
query += ` AND (t.created_by = ? OR ta.user_id = ?)`;
|
||||
params.push(userId, userId);
|
||||
}
|
||||
|
||||
query += " GROUP BY t.id ORDER BY t.created_at DESC";
|
||||
|
||||
db.all(query, params, (err, tasks) => {
|
||||
if (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
return;
|
||||
}
|
||||
|
||||
const taskPromises = tasks.map(task => {
|
||||
return new Promise((resolve) => {
|
||||
// Получаем назначения
|
||||
db.all(`
|
||||
SELECT ta.*, u.name as user_name, u.login as user_login
|
||||
FROM task_assignments ta
|
||||
LEFT JOIN users u ON ta.user_id = u.id
|
||||
WHERE ta.task_id = ?
|
||||
`, [task.id], (err, assignments) => {
|
||||
if (err) {
|
||||
task.assignments = [];
|
||||
} else {
|
||||
assignments.forEach(assignment => {
|
||||
if (checkIfOverdue(assignment.due_date, assignment.status) && assignment.status !== 'completed') {
|
||||
assignment.status = 'overdue';
|
||||
}
|
||||
});
|
||||
task.assignments = assignments || [];
|
||||
}
|
||||
|
||||
// Получаем информацию о группе согласующих
|
||||
if (task.approver_group_id) {
|
||||
db.get(`
|
||||
SELECT name, color, can_approve_documents
|
||||
FROM user_groups
|
||||
WHERE id = ?
|
||||
`, [task.approver_group_id], (err, group) => {
|
||||
task.approver_group = group || null;
|
||||
resolve(task);
|
||||
});
|
||||
} else {
|
||||
resolve(task);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Promise.all(taskPromises).then(completedTasks => {
|
||||
res.json(completedTasks);
|
||||
});
|
||||
});
|
||||
});
|
||||
// API для обновления статуса в Канбане
|
||||
app.put('/api/kanban-tasks/:taskId/status', requireAuth, (req, res) => {
|
||||
const { taskId } = req.params;
|
||||
@@ -1163,4 +1349,4 @@ function setupTaskEndpoints(app, db, upload) {
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { setupTaskEndpoints };
|
||||
module.exports = { setupTaskEndpoints,getApproverUsers };
|
||||
Reference in New Issue
Block a user