diff --git a/server/routers/assessment-tools/models/Criteria.js b/server/routers/assessment-tools/models/Criteria.js index 3aa2ba4..35961e2 100644 --- a/server/routers/assessment-tools/models/Criteria.js +++ b/server/routers/assessment-tools/models/Criteria.js @@ -1,4 +1,4 @@ -const mongoose = require('../../../utils/mongoose'); +const mongoose = require('mongoose'); const criterionItemSchema = new mongoose.Schema({ name: { @@ -14,6 +14,11 @@ const criterionItemSchema = new mongoose.Schema({ }, { _id: false }); const criteriaSchema = new mongoose.Schema({ + eventId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Event', + required: true + }, blockName: { type: String, required: true diff --git a/server/routers/assessment-tools/models/Event.js b/server/routers/assessment-tools/models/Event.js index bb17b50..6d504a8 100644 --- a/server/routers/assessment-tools/models/Event.js +++ b/server/routers/assessment-tools/models/Event.js @@ -1,4 +1,4 @@ -const mongoose = require('../../../utils/mongoose'); +const mongoose = require('mongoose'); const eventSchema = new mongoose.Schema({ name: { diff --git a/server/routers/assessment-tools/models/Expert.js b/server/routers/assessment-tools/models/Expert.js index 5a4ce67..a774160 100644 --- a/server/routers/assessment-tools/models/Expert.js +++ b/server/routers/assessment-tools/models/Expert.js @@ -1,7 +1,12 @@ -const mongoose = require('../../../utils/mongoose'); +const mongoose = require('mongoose'); const crypto = require('crypto'); const expertSchema = new mongoose.Schema({ + eventId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Event', + required: true + }, fullName: { type: String, required: true diff --git a/server/routers/assessment-tools/models/Rating.js b/server/routers/assessment-tools/models/Rating.js index 13ed07f..b5a2539 100644 --- a/server/routers/assessment-tools/models/Rating.js +++ b/server/routers/assessment-tools/models/Rating.js @@ -1,4 +1,4 @@ -const mongoose = require('../../../utils/mongoose'); +const mongoose = require('mongoose'); const ratingItemSchema = new mongoose.Schema({ criteriaId: { @@ -19,6 +19,11 @@ const ratingItemSchema = new mongoose.Schema({ }, { _id: false }); const ratingSchema = new mongoose.Schema({ + eventId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Event', + required: true + }, expertId: { type: mongoose.Schema.Types.ObjectId, ref: 'Expert', diff --git a/server/routers/assessment-tools/models/Team.js b/server/routers/assessment-tools/models/Team.js index 27aabc0..abb2a6c 100644 --- a/server/routers/assessment-tools/models/Team.js +++ b/server/routers/assessment-tools/models/Team.js @@ -1,6 +1,11 @@ -const mongoose = require('../../../utils/mongoose'); +const mongoose = require('mongoose'); const teamSchema = new mongoose.Schema({ + eventId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Event', + required: true + }, type: { type: String, enum: ['team', 'participant'], diff --git a/server/routers/assessment-tools/routes/criteria.js b/server/routers/assessment-tools/routes/criteria.js index 6c7b405..41c6dbf 100644 --- a/server/routers/assessment-tools/routes/criteria.js +++ b/server/routers/assessment-tools/routes/criteria.js @@ -23,7 +23,10 @@ const DEFAULT_CRITERIA = [ // GET /api/criteria - получить все блоки критериев router.get('/', async (req, res) => { try { - const criteria = await Criteria.find().sort({ order: 1 }); + const { eventId } = req.query; + const filter = {}; + if (eventId) filter.eventId = eventId; + const criteria = await Criteria.find(filter).sort({ order: 1 }); res.json(criteria); } catch (error) { res.status(500).json({ error: error.message }); @@ -46,13 +49,14 @@ router.get('/:id', async (req, res) => { // POST /api/criteria - создать блок критериев router.post('/', async (req, res) => { try { - const { blockName, criteria, order } = req.body; + const { eventId, blockName, criteria, order } = req.body; - if (!blockName || !criteria || !Array.isArray(criteria)) { - return res.status(400).json({ error: 'Block name and criteria array are required' }); + if (!eventId || !blockName || !criteria || !Array.isArray(criteria)) { + return res.status(400).json({ error: 'EventId, block name and criteria array are required' }); } const criteriaBlock = await Criteria.create({ + eventId, blockName, criteria, order: order !== undefined ? order : 0 @@ -67,11 +71,21 @@ router.post('/', async (req, res) => { // POST /api/criteria/default - загрузить критерии по умолчанию из hack.md router.post('/default', async (req, res) => { try { - // Удаляем все существующие критерии - await Criteria.deleteMany({}); + const { eventId } = req.body; - // Создаем критерии по умолчанию - const createdCriteria = await Criteria.insertMany(DEFAULT_CRITERIA); + if (!eventId) { + return res.status(400).json({ error: 'EventId is required' }); + } + + // Удаляем все существующие критерии для этого мероприятия + await Criteria.deleteMany({ eventId }); + + // Создаем критерии по умолчанию с eventId + const criteriaWithEventId = DEFAULT_CRITERIA.map(c => ({ + ...c, + eventId + })); + const createdCriteria = await Criteria.insertMany(criteriaWithEventId); res.status(201).json(createdCriteria); } catch (error) { diff --git a/server/routers/assessment-tools/routes/experts.js b/server/routers/assessment-tools/routes/experts.js index dbbf43f..189c438 100644 --- a/server/routers/assessment-tools/routes/experts.js +++ b/server/routers/assessment-tools/routes/experts.js @@ -4,7 +4,10 @@ const { Expert } = require('../models'); // GET /api/experts - список экспертов router.get('/', async (req, res) => { try { - const experts = await Expert.find().sort({ createdAt: -1 }); + const { eventId } = req.query; + const filter = {}; + if (eventId) filter.eventId = eventId; + const experts = await Expert.find(filter).sort({ createdAt: -1 }); res.json(experts); } catch (error) { res.status(500).json({ error: error.message }); @@ -40,14 +43,15 @@ router.get('/:id', async (req, res) => { // POST /api/experts - создать эксперта (с генерацией уникальной ссылки) router.post('/', async (req, res) => { try { - const { fullName } = req.body; + const { eventId, fullName } = req.body; - if (!fullName) { - return res.status(400).json({ error: 'Full name is required' }); + if (!eventId || !fullName) { + return res.status(400).json({ error: 'EventId and full name are required' }); } // Создаем нового эксперта const expert = new Expert({ + eventId, fullName }); diff --git a/server/routers/assessment-tools/routes/ratings.js b/server/routers/assessment-tools/routes/ratings.js index de1cc10..2bbb5b0 100644 --- a/server/routers/assessment-tools/routes/ratings.js +++ b/server/routers/assessment-tools/routes/ratings.js @@ -4,11 +4,12 @@ const { Rating, Team, Expert, Criteria } = require('../models'); // GET /api/ratings - получить все оценки (с фильтрами) router.get('/', async (req, res) => { try { - const { expertId, teamId } = req.query; + const { expertId, teamId, eventId } = req.query; const filter = {}; if (expertId) filter.expertId = expertId; if (teamId) filter.teamId = teamId; + if (eventId) filter.eventId = eventId; const ratings = await Rating.find(filter) .populate('expertId', 'fullName') @@ -49,14 +50,18 @@ router.get('/expert/:expertId', async (req, res) => { // GET /api/ratings/statistics - статистика с группировкой по командам router.get('/statistics', async (req, res) => { try { - const { type } = req.query; + const { type, eventId } = req.query; // Получаем все команды - const teamFilter = type ? { type, isActive: true } : { isActive: true }; + const teamFilter = { isActive: true }; + if (type) teamFilter.type = type; + if (eventId) teamFilter.eventId = eventId; const teams = await Team.find(teamFilter); // Получаем все оценки - const ratings = await Rating.find() + const ratingFilter = {}; + if (eventId) ratingFilter.eventId = eventId; + const ratings = await Rating.find(ratingFilter) .populate('expertId', 'fullName') .populate('teamId', 'name type projectName'); @@ -117,13 +122,17 @@ router.get('/statistics', async (req, res) => { // GET /api/ratings/top3 - топ-3 команды/участники router.get('/top3', async (req, res) => { try { - const { type } = req.query; + const { type, eventId } = req.query; // Получаем статистику - const teamFilter = type ? { type, isActive: true } : { isActive: true }; + const teamFilter = { isActive: true }; + if (type) teamFilter.type = type; + if (eventId) teamFilter.eventId = eventId; const teams = await Team.find(teamFilter); - const ratings = await Rating.find() + const ratingFilter = {}; + if (eventId) ratingFilter.eventId = eventId; + const ratings = await Rating.find(ratingFilter) .populate('teamId', 'name type projectName'); // Группируем и считаем средние баллы @@ -161,10 +170,10 @@ router.get('/top3', async (req, res) => { // POST /api/ratings - создать/обновить оценку эксперта router.post('/', async (req, res) => { try { - const { expertId, teamId, ratings } = req.body; + const { eventId, expertId, teamId, ratings } = req.body; - if (!expertId || !teamId || !ratings || !Array.isArray(ratings)) { - return res.status(400).json({ error: 'Expert ID, team ID, and ratings array are required' }); + if (!eventId || !expertId || !teamId || !ratings || !Array.isArray(ratings)) { + return res.status(400).json({ error: 'EventId, expert ID, team ID, and ratings array are required' }); } // Проверяем существование эксперта и команды @@ -185,7 +194,7 @@ router.post('/', async (req, res) => { } // Ищем существующую оценку - let rating = await Rating.findOne({ expertId, teamId }); + let rating = await Rating.findOne({ eventId, expertId, teamId }); if (rating) { // Обновляем существующую оценку @@ -194,6 +203,7 @@ router.post('/', async (req, res) => { } else { // Создаем новую оценку rating = await Rating.create({ + eventId, expertId, teamId, ratings diff --git a/server/routers/assessment-tools/routes/teams.js b/server/routers/assessment-tools/routes/teams.js index 746925a..284db0e 100644 --- a/server/routers/assessment-tools/routes/teams.js +++ b/server/routers/assessment-tools/routes/teams.js @@ -4,8 +4,10 @@ const { Team } = require('../models'); // GET /api/teams - список всех команд router.get('/', async (req, res) => { try { - const { type } = req.query; - const filter = type ? { type } : {}; + const { type, eventId } = req.query; + const filter = {}; + if (type) filter.type = type; + if (eventId) filter.eventId = eventId; const teams = await Team.find(filter).sort({ createdAt: -1 }); res.json(teams); } catch (error) { @@ -16,7 +18,10 @@ router.get('/', async (req, res) => { // GET /api/teams/active/voting - получить активную для оценки команду (ДОЛЖЕН БЫТЬ ПЕРЕД /:id) router.get('/active/voting', async (req, res) => { try { - const team = await Team.findOne({ isActiveForVoting: true }); + const { eventId } = req.query; + const filter = { isActiveForVoting: true }; + if (eventId) filter.eventId = eventId; + const team = await Team.findOne(filter); res.json(team); } catch (error) { res.status(500).json({ error: error.message }); @@ -26,9 +31,13 @@ router.get('/active/voting', async (req, res) => { // PATCH /api/teams/stop-all-voting/global - остановить все оценивания (ДОЛЖЕН БЫТЬ ПЕРЕД /:id) router.patch('/stop-all-voting/global', async (req, res) => { try { + const { eventId } = req.body; // Находим все команды, которые сейчас оцениваются + const filter = { isActiveForVoting: true }; + if (eventId) filter.eventId = eventId; + const result = await Team.updateMany( - { isActiveForVoting: true }, + filter, { isActiveForVoting: false, votingStatus: 'evaluated' @@ -60,13 +69,14 @@ router.get('/:id', async (req, res) => { // POST /api/teams - создать команду/участника router.post('/', async (req, res) => { try { - const { type, name, projectName, caseDescription } = req.body; + const { eventId, type, name, projectName, caseDescription } = req.body; - if (!type || !name) { - return res.status(400).json({ error: 'Type and name are required' }); + if (!eventId || !type || !name) { + return res.status(400).json({ error: 'EventId, type and name are required' }); } const team = await Team.create({ + eventId, type, name, projectName: projectName || '', @@ -118,8 +128,17 @@ router.delete('/:id', async (req, res) => { // PATCH /api/teams/:id/activate-for-voting - активировать команду для оценки router.patch('/:id/activate-for-voting', async (req, res) => { try { - // Деактивируем все команды и сохраняем их статус - const previouslyActive = await Team.findOne({ isActiveForVoting: true }); + // Получаем команду для активации + const team = await Team.findById(req.params.id); + if (!team) { + return res.status(404).json({ error: 'Team not found' }); + } + + // Деактивируем все команды этого мероприятия + const previouslyActive = await Team.findOne({ + isActiveForVoting: true, + eventId: team.eventId + }); if (previouslyActive) { previouslyActive.isActiveForVoting = false; previouslyActive.votingStatus = 'evaluated'; @@ -127,11 +146,6 @@ router.patch('/:id/activate-for-voting', async (req, res) => { } // Активируем выбранную команду - const team = await Team.findById(req.params.id); - if (!team) { - return res.status(404).json({ error: 'Team not found' }); - } - team.isActiveForVoting = true; team.votingStatus = 'evaluating'; await team.save(); diff --git a/server/routers/assessment-tools/scripts/recreate-test-user.js b/server/routers/assessment-tools/scripts/recreate-test-user.js index b1362de..6002d66 100644 --- a/server/routers/assessment-tools/scripts/recreate-test-user.js +++ b/server/routers/assessment-tools/scripts/recreate-test-user.js @@ -1,14 +1,13 @@ -// Импортировать mongoose из общего модуля (подключение происходит в server/utils/mongoose.ts) +// Импортировать mongoose из общего модуля (подключение происходит автоматически) const mongoose = require('../../../utils/mongoose'); -const { Event } = require('../models'); +const Event = require('../models/Event'); async function recreateTestUser() { try { - // Ждем, пока подключение будет готово + // Проверяем подключение к MongoDB if (mongoose.connection.readyState !== 1) { - await new Promise(resolve => { - mongoose.connection.once('connected', resolve); - }); + console.log('Waiting for MongoDB connection...'); + await new Promise(resolve => setTimeout(resolve, 1000)); } console.log('Connected to MongoDB'); @@ -22,12 +21,11 @@ async function recreateTestUser() { votingEnabled: false }); console.log('Test event created:', event.name); + } else { + console.log('Event already exists:', event.name); } console.log('Database initialized successfully'); - - await mongoose.disconnect(); - console.log('Disconnected from MongoDB'); } catch (error) { console.error('Error:', error); process.exit(1);