Files
minicrm/group-management.js
2026-01-27 00:32:06 +05:00

383 lines
16 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.
// group-management.js
const express = require('express');
const router = express.Router();
function setupGroupManagement(app, db) {
// Middleware для проверки администратора
function requireAdmin(req, res, next) {
if (!req.session.user || req.session.user.role !== 'admin') {
return res.status(403).json({ error: 'Недостаточно прав' });
}
next();
}
// API для получения всех групп
router.get('/api/groups', requireAdmin, (req, res) => {
db.all(`
SELECT g.*,
COUNT(DISTINCT ugm.user_id) as member_count
FROM user_groups g
LEFT JOIN user_group_memberships ugm ON g.id = ugm.group_id
GROUP BY g.id
ORDER BY g.name
`, [], (err, groups) => {
if (err) {
console.error('❌ Ошибка получения групп:', err);
return res.status(500).json({ error: 'Ошибка получения групп' });
}
res.json(groups || []);
});
});
// API для получения одной группы с участниками
router.get('/api/groups/:groupId', requireAdmin, (req, res) => {
const { groupId } = req.params;
db.get(`
SELECT g.*,
COUNT(DISTINCT ugm.user_id) as member_count
FROM user_groups g
LEFT JOIN user_group_memberships ugm ON g.id = ugm.group_id
WHERE g.id = ?
GROUP BY g.id
`, [groupId], (err, group) => {
if (err || !group) {
return res.status(404).json({ error: 'Группа не найдена' });
}
// Получаем участников группы
db.all(`
SELECT u.id, u.login, u.name, u.email, u.role
FROM users u
JOIN user_group_memberships ugm ON u.id = ugm.user_id
WHERE ugm.group_id = ?
ORDER BY u.name
`, [groupId], (err, members) => {
if (err) {
console.error('❌ Ошибка получения участников:', err);
return res.status(500).json({ error: 'Ошибка получения участников' });
}
res.json({
...group,
members: members || []
});
});
});
});
// API для создания новой группы
router.post('/api/groups', requireAdmin, (req, res) => {
const { name, description, color, can_approve_documents } = req.body;
if (!name) {
return res.status(400).json({ error: 'Название группы обязательно' });
}
db.run(`
INSERT INTO user_groups (name, description, color, can_approve_documents)
VALUES (?, ?, ?, ?)
`, [
name.trim(),
description || '',
color || '#3498db',
can_approve_documents ? 1 : 0
], function(err) {
if (err) {
console.error('❌ Ошибка создания группы:', err);
return res.status(500).json({
error: 'Ошибка создания группы',
details: err.message.includes('UNIQUE') ? 'Группа с таким названием уже существует' : err.message
});
}
res.json({
success: true,
groupId: this.lastID,
message: 'Группа создана успешно'
});
});
});
// API для обновления группы
router.put('/api/groups/:groupId', requireAdmin, (req, res) => {
const { groupId } = req.params;
const { name, description, color, can_approve_documents } = req.body;
if (!name) {
return res.status(400).json({ error: 'Название группы обязательно' });
}
db.run(`
UPDATE user_groups
SET name = ?, description = ?, color = ?, can_approve_documents = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?
`, [
name.trim(),
description || '',
color || '#3498db',
can_approve_documents ? 1 : 0,
groupId
], function(err) {
if (err) {
console.error('❌ Ошибка обновления группы:', err);
return res.status(500).json({
error: 'Ошибка обновления группы',
details: err.message.includes('UNIQUE') ? 'Группа с таким названием уже существует' : err.message
});
}
if (this.changes === 0) {
return res.status(404).json({ error: 'Группа не найдена' });
}
res.json({
success: true,
message: 'Группа обновлена успешно'
});
});
});
// API для удаления группы
router.delete('/api/groups/:groupId', requireAdmin, (req, res) => {
const { groupId } = req.params;
db.run(`DELETE FROM user_groups WHERE id = ?`, [groupId], function(err) {
if (err) {
console.error('❌ Ошибка удаления группы:', err);
return res.status(500).json({ error: 'Ошибка удаления группы' });
}
if (this.changes === 0) {
return res.status(404).json({ error: 'Группа не найдена' });
}
res.json({
success: true,
message: 'Группа удалена успешно'
});
});
});
// API для добавления пользователя в группу
router.post('/api/groups/:groupId/members', requireAdmin, (req, res) => {
const { groupId } = req.params;
const { userId } = req.body;
if (!userId) {
return res.status(400).json({ error: 'ID пользователя обязательно' });
}
// Проверяем существование группы и пользователя
db.get(`SELECT id FROM user_groups WHERE id = ?`, [groupId], (err, group) => {
if (err || !group) {
return res.status(404).json({ error: 'Группа не найдена' });
}
db.get(`SELECT id FROM users WHERE id = ?`, [userId], (err, user) => {
if (err || !user) {
return res.status(404).json({ error: 'Пользователь не найден' });
}
db.run(`
INSERT OR IGNORE INTO user_group_memberships (user_id, group_id)
VALUES (?, ?)
`, [userId, groupId], function(err) {
if (err) {
console.error('❌ Ошибка добавления пользователя в группу:', err);
return res.status(500).json({ error: 'Ошибка добавления пользователя в группу' });
}
res.json({
success: true,
message: 'Пользователь добавлен в группу'
});
});
});
});
});
// API для удаления пользователя из группы
router.delete('/api/groups/:groupId/members/:userId', requireAdmin, (req, res) => {
const { groupId, userId } = req.params;
db.run(`
DELETE FROM user_group_memberships
WHERE user_id = ? AND group_id = ?
`, [userId, groupId], function(err) {
if (err) {
console.error('❌ Ошибка удаления пользователя из группы:', err);
return res.status(500).json({ error: 'Ошибка удаления пользователя из группы' });
}
if (this.changes === 0) {
return res.status(404).json({ error: 'Пользователь не найден в группе' });
}
res.json({
success: true,
message: 'Пользователь удален из группы'
});
});
});
// API для получения всех пользователей с их группами
router.get('/api/users-with-groups', requireAdmin, (req, res) => {
db.all(`
SELECT u.id, u.login, u.name, u.email, u.role,
GROUP_CONCAT(DISTINCT g.name) as group_names,
GROUP_CONCAT(DISTINCT g.id) as group_ids
FROM users u
LEFT JOIN user_group_memberships ugm ON u.id = ugm.user_id
LEFT JOIN user_groups g ON ugm.group_id = g.id
WHERE u.role IN ('admin', 'teacher')
GROUP BY u.id
ORDER BY u.name
`, [], (err, users) => {
if (err) {
console.error('❌ Ошибка получения пользователей с группами:', err);
return res.status(500).json({ error: 'Ошибка получения данных' });
}
// Преобразуем строки в массивы
const formattedUsers = users.map(user => ({
...user,
group_names: user.group_names ? user.group_names.split(',') : [],
group_ids: user.group_ids ? user.group_ids.split(',').map(id => parseInt(id)) : []
}));
res.json(formattedUsers);
});
});
// API для получения доступных групп для пользователя
router.get('/api/users/:userId/available-groups', requireAdmin, (req, res) => {
const { userId } = req.params;
db.all(`
SELECT g.*,
CASE WHEN ugm.user_id IS NOT NULL THEN 1 ELSE 0 END as is_member
FROM user_groups g
LEFT JOIN user_group_memberships ugm ON g.id = ugm.group_id AND ugm.user_id = ?
ORDER BY g.name
`, [userId], (err, groups) => {
if (err) {
console.error('❌ Ошибка получения групп:', err);
return res.status(500).json({ error: 'Ошибка получения данных' });
}
res.json(groups || []);
});
});
// API для массового обновления групп пользователя
router.put('/api/users/:userId/groups', requireAdmin, (req, res) => {
const { userId } = req.params;
const { groupIds } = req.body; // массив ID групп
if (!Array.isArray(groupIds)) {
return res.status(400).json({ error: 'groupIds должен быть массивом' });
}
// Проверяем существование пользователя
db.get(`SELECT id FROM users WHERE id = ?`, [userId], (err, user) => {
if (err || !user) {
return res.status(404).json({ error: 'Пользователь не найден' });
}
db.serialize(() => {
// Удаляем все текущие группы пользователя
db.run(`DELETE FROM user_group_memberships WHERE user_id = ?`, [userId], (err) => {
if (err) {
console.error('❌ Ошибка удаления старых групп:', err);
return res.status(500).json({ error: 'Ошибка обновления групп' });
}
// Добавляем новые группы
if (groupIds.length > 0) {
const placeholders = groupIds.map(() => '(?, ?)').join(',');
const values = groupIds.reduce((acc, groupId) => {
acc.push(userId, groupId);
return acc;
}, []);
db.run(`
INSERT INTO user_group_memberships (user_id, group_id)
VALUES ${placeholders}
`, values, (err) => {
if (err) {
console.error('❌ Ошибка добавления новых групп:', err);
return res.status(500).json({ error: 'Ошибка обновления групп' });
}
res.json({
success: true,
message: 'Группы пользователя обновлены'
});
});
} else {
res.json({
success: true,
message: 'Группы пользователя обновлены'
});
}
});
});
});
});
// API для получения пользователей, которые могут согласовывать документы
router.get('/api/approvers', requireAdmin, (req, res) => {
db.all(`
SELECT DISTINCT u.id, u.login, u.name, u.email, u.role,
g.name as group_name, g.color as group_color
FROM users u
JOIN user_group_memberships ugm ON u.id = ugm.user_id
JOIN user_groups g ON ugm.group_id = g.id
WHERE g.can_approve_documents = 1
ORDER BY u.name
`, [], (err, approvers) => {
if (err) {
console.error('❌ Ошибка получения согласующих:', err);
return res.status(500).json({ error: 'Ошибка получения данных' });
}
res.json(approvers || []);
});
});
// API для получения групп, которые могут согласовывать документы
router.get('/api/approver-groups', (req, res) => {
const isAdmin = req.session.user && req.session.user.role === 'admin';
db.all(`
SELECT g.*,
COUNT(DISTINCT ugm.user_id) as member_count
FROM user_groups g
LEFT JOIN user_group_memberships ugm ON g.id = ugm.group_id
WHERE g.can_approve_documents = 1
GROUP BY g.id
ORDER BY g.name
`, [], (err, groups) => {
if (err) {
console.error('❌ Ошибка получения групп согласующих:', err);
return res.status(500).json({ error: 'Ошибка получения данных' });
}
// Для обычных пользователей скрываем ID пользователей в группах
if (!isAdmin) {
groups = groups.map(group => ({
...group,
members: undefined
}));
}
res.json(groups || []);
});
});
return router;
}
module.exports = { setupGroupManagement };