обновление логики
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
const mongoose = require('../../../utils/mongoose');
|
const mongoose = require('mongoose');
|
||||||
|
|
||||||
const criterionItemSchema = new mongoose.Schema({
|
const criterionItemSchema = new mongoose.Schema({
|
||||||
name: {
|
name: {
|
||||||
@@ -14,6 +14,11 @@ const criterionItemSchema = new mongoose.Schema({
|
|||||||
}, { _id: false });
|
}, { _id: false });
|
||||||
|
|
||||||
const criteriaSchema = new mongoose.Schema({
|
const criteriaSchema = new mongoose.Schema({
|
||||||
|
eventId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: 'Event',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
blockName: {
|
blockName: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const mongoose = require('../../../utils/mongoose');
|
const mongoose = require('mongoose');
|
||||||
|
|
||||||
const eventSchema = new mongoose.Schema({
|
const eventSchema = new mongoose.Schema({
|
||||||
name: {
|
name: {
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
const mongoose = require('../../../utils/mongoose');
|
const mongoose = require('mongoose');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
|
||||||
const expertSchema = new mongoose.Schema({
|
const expertSchema = new mongoose.Schema({
|
||||||
|
eventId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: 'Event',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
fullName: {
|
fullName: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const mongoose = require('../../../utils/mongoose');
|
const mongoose = require('mongoose');
|
||||||
|
|
||||||
const ratingItemSchema = new mongoose.Schema({
|
const ratingItemSchema = new mongoose.Schema({
|
||||||
criteriaId: {
|
criteriaId: {
|
||||||
@@ -19,6 +19,11 @@ const ratingItemSchema = new mongoose.Schema({
|
|||||||
}, { _id: false });
|
}, { _id: false });
|
||||||
|
|
||||||
const ratingSchema = new mongoose.Schema({
|
const ratingSchema = new mongoose.Schema({
|
||||||
|
eventId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: 'Event',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
expertId: {
|
expertId: {
|
||||||
type: mongoose.Schema.Types.ObjectId,
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
ref: 'Expert',
|
ref: 'Expert',
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
const mongoose = require('../../../utils/mongoose');
|
const mongoose = require('mongoose');
|
||||||
|
|
||||||
const teamSchema = new mongoose.Schema({
|
const teamSchema = new mongoose.Schema({
|
||||||
|
eventId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: 'Event',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: ['team', 'participant'],
|
enum: ['team', 'participant'],
|
||||||
|
|||||||
@@ -23,7 +23,10 @@ const DEFAULT_CRITERIA = [
|
|||||||
// GET /api/criteria - получить все блоки критериев
|
// GET /api/criteria - получить все блоки критериев
|
||||||
router.get('/', async (req, res) => {
|
router.get('/', async (req, res) => {
|
||||||
try {
|
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);
|
res.json(criteria);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: error.message });
|
res.status(500).json({ error: error.message });
|
||||||
@@ -46,13 +49,14 @@ router.get('/:id', async (req, res) => {
|
|||||||
// POST /api/criteria - создать блок критериев
|
// POST /api/criteria - создать блок критериев
|
||||||
router.post('/', async (req, res) => {
|
router.post('/', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { blockName, criteria, order } = req.body;
|
const { eventId, blockName, criteria, order } = req.body;
|
||||||
|
|
||||||
if (!blockName || !criteria || !Array.isArray(criteria)) {
|
if (!eventId || !blockName || !criteria || !Array.isArray(criteria)) {
|
||||||
return res.status(400).json({ error: 'Block name and criteria array are required' });
|
return res.status(400).json({ error: 'EventId, block name and criteria array are required' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const criteriaBlock = await Criteria.create({
|
const criteriaBlock = await Criteria.create({
|
||||||
|
eventId,
|
||||||
blockName,
|
blockName,
|
||||||
criteria,
|
criteria,
|
||||||
order: order !== undefined ? order : 0
|
order: order !== undefined ? order : 0
|
||||||
@@ -67,11 +71,21 @@ router.post('/', async (req, res) => {
|
|||||||
// POST /api/criteria/default - загрузить критерии по умолчанию из hack.md
|
// POST /api/criteria/default - загрузить критерии по умолчанию из hack.md
|
||||||
router.post('/default', async (req, res) => {
|
router.post('/default', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
// Удаляем все существующие критерии
|
const { eventId } = req.body;
|
||||||
await Criteria.deleteMany({});
|
|
||||||
|
|
||||||
// Создаем критерии по умолчанию
|
if (!eventId) {
|
||||||
const createdCriteria = await Criteria.insertMany(DEFAULT_CRITERIA);
|
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);
|
res.status(201).json(createdCriteria);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ const { Expert } = require('../models');
|
|||||||
// GET /api/experts - список экспертов
|
// GET /api/experts - список экспертов
|
||||||
router.get('/', async (req, res) => {
|
router.get('/', async (req, res) => {
|
||||||
try {
|
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);
|
res.json(experts);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: error.message });
|
res.status(500).json({ error: error.message });
|
||||||
@@ -40,14 +43,15 @@ router.get('/:id', async (req, res) => {
|
|||||||
// POST /api/experts - создать эксперта (с генерацией уникальной ссылки)
|
// POST /api/experts - создать эксперта (с генерацией уникальной ссылки)
|
||||||
router.post('/', async (req, res) => {
|
router.post('/', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { fullName } = req.body;
|
const { eventId, fullName } = req.body;
|
||||||
|
|
||||||
if (!fullName) {
|
if (!eventId || !fullName) {
|
||||||
return res.status(400).json({ error: 'Full name is required' });
|
return res.status(400).json({ error: 'EventId and full name are required' });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Создаем нового эксперта
|
// Создаем нового эксперта
|
||||||
const expert = new Expert({
|
const expert = new Expert({
|
||||||
|
eventId,
|
||||||
fullName
|
fullName
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ const { Rating, Team, Expert, Criteria } = require('../models');
|
|||||||
// GET /api/ratings - получить все оценки (с фильтрами)
|
// GET /api/ratings - получить все оценки (с фильтрами)
|
||||||
router.get('/', async (req, res) => {
|
router.get('/', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { expertId, teamId } = req.query;
|
const { expertId, teamId, eventId } = req.query;
|
||||||
const filter = {};
|
const filter = {};
|
||||||
|
|
||||||
if (expertId) filter.expertId = expertId;
|
if (expertId) filter.expertId = expertId;
|
||||||
if (teamId) filter.teamId = teamId;
|
if (teamId) filter.teamId = teamId;
|
||||||
|
if (eventId) filter.eventId = eventId;
|
||||||
|
|
||||||
const ratings = await Rating.find(filter)
|
const ratings = await Rating.find(filter)
|
||||||
.populate('expertId', 'fullName')
|
.populate('expertId', 'fullName')
|
||||||
@@ -49,14 +50,18 @@ router.get('/expert/:expertId', async (req, res) => {
|
|||||||
// GET /api/ratings/statistics - статистика с группировкой по командам
|
// GET /api/ratings/statistics - статистика с группировкой по командам
|
||||||
router.get('/statistics', async (req, res) => {
|
router.get('/statistics', async (req, res) => {
|
||||||
try {
|
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 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('expertId', 'fullName')
|
||||||
.populate('teamId', 'name type projectName');
|
.populate('teamId', 'name type projectName');
|
||||||
|
|
||||||
@@ -117,13 +122,17 @@ router.get('/statistics', async (req, res) => {
|
|||||||
// GET /api/ratings/top3 - топ-3 команды/участники
|
// GET /api/ratings/top3 - топ-3 команды/участники
|
||||||
router.get('/top3', async (req, res) => {
|
router.get('/top3', async (req, res) => {
|
||||||
try {
|
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 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');
|
.populate('teamId', 'name type projectName');
|
||||||
|
|
||||||
// Группируем и считаем средние баллы
|
// Группируем и считаем средние баллы
|
||||||
@@ -161,10 +170,10 @@ router.get('/top3', async (req, res) => {
|
|||||||
// POST /api/ratings - создать/обновить оценку эксперта
|
// POST /api/ratings - создать/обновить оценку эксперта
|
||||||
router.post('/', async (req, res) => {
|
router.post('/', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { expertId, teamId, ratings } = req.body;
|
const { eventId, expertId, teamId, ratings } = req.body;
|
||||||
|
|
||||||
if (!expertId || !teamId || !ratings || !Array.isArray(ratings)) {
|
if (!eventId || !expertId || !teamId || !ratings || !Array.isArray(ratings)) {
|
||||||
return res.status(400).json({ error: 'Expert ID, team ID, and ratings array are required' });
|
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) {
|
if (rating) {
|
||||||
// Обновляем существующую оценку
|
// Обновляем существующую оценку
|
||||||
@@ -194,6 +203,7 @@ router.post('/', async (req, res) => {
|
|||||||
} else {
|
} else {
|
||||||
// Создаем новую оценку
|
// Создаем новую оценку
|
||||||
rating = await Rating.create({
|
rating = await Rating.create({
|
||||||
|
eventId,
|
||||||
expertId,
|
expertId,
|
||||||
teamId,
|
teamId,
|
||||||
ratings
|
ratings
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ const { Team } = require('../models');
|
|||||||
// GET /api/teams - список всех команд
|
// GET /api/teams - список всех команд
|
||||||
router.get('/', async (req, res) => {
|
router.get('/', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { type } = req.query;
|
const { type, eventId } = req.query;
|
||||||
const filter = type ? { type } : {};
|
const filter = {};
|
||||||
|
if (type) filter.type = type;
|
||||||
|
if (eventId) filter.eventId = eventId;
|
||||||
const teams = await Team.find(filter).sort({ createdAt: -1 });
|
const teams = await Team.find(filter).sort({ createdAt: -1 });
|
||||||
res.json(teams);
|
res.json(teams);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -16,7 +18,10 @@ router.get('/', async (req, res) => {
|
|||||||
// GET /api/teams/active/voting - получить активную для оценки команду (ДОЛЖЕН БЫТЬ ПЕРЕД /:id)
|
// GET /api/teams/active/voting - получить активную для оценки команду (ДОЛЖЕН БЫТЬ ПЕРЕД /:id)
|
||||||
router.get('/active/voting', async (req, res) => {
|
router.get('/active/voting', async (req, res) => {
|
||||||
try {
|
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);
|
res.json(team);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).json({ error: error.message });
|
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)
|
// PATCH /api/teams/stop-all-voting/global - остановить все оценивания (ДОЛЖЕН БЫТЬ ПЕРЕД /:id)
|
||||||
router.patch('/stop-all-voting/global', async (req, res) => {
|
router.patch('/stop-all-voting/global', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
const { eventId } = req.body;
|
||||||
// Находим все команды, которые сейчас оцениваются
|
// Находим все команды, которые сейчас оцениваются
|
||||||
|
const filter = { isActiveForVoting: true };
|
||||||
|
if (eventId) filter.eventId = eventId;
|
||||||
|
|
||||||
const result = await Team.updateMany(
|
const result = await Team.updateMany(
|
||||||
{ isActiveForVoting: true },
|
filter,
|
||||||
{
|
{
|
||||||
isActiveForVoting: false,
|
isActiveForVoting: false,
|
||||||
votingStatus: 'evaluated'
|
votingStatus: 'evaluated'
|
||||||
@@ -60,13 +69,14 @@ router.get('/:id', async (req, res) => {
|
|||||||
// POST /api/teams - создать команду/участника
|
// POST /api/teams - создать команду/участника
|
||||||
router.post('/', async (req, res) => {
|
router.post('/', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { type, name, projectName, caseDescription } = req.body;
|
const { eventId, type, name, projectName, caseDescription } = req.body;
|
||||||
|
|
||||||
if (!type || !name) {
|
if (!eventId || !type || !name) {
|
||||||
return res.status(400).json({ error: 'Type and name are required' });
|
return res.status(400).json({ error: 'EventId, type and name are required' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const team = await Team.create({
|
const team = await Team.create({
|
||||||
|
eventId,
|
||||||
type,
|
type,
|
||||||
name,
|
name,
|
||||||
projectName: projectName || '',
|
projectName: projectName || '',
|
||||||
@@ -118,8 +128,17 @@ router.delete('/:id', async (req, res) => {
|
|||||||
// PATCH /api/teams/:id/activate-for-voting - активировать команду для оценки
|
// PATCH /api/teams/:id/activate-for-voting - активировать команду для оценки
|
||||||
router.patch('/:id/activate-for-voting', async (req, res) => {
|
router.patch('/:id/activate-for-voting', async (req, res) => {
|
||||||
try {
|
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) {
|
if (previouslyActive) {
|
||||||
previouslyActive.isActiveForVoting = false;
|
previouslyActive.isActiveForVoting = false;
|
||||||
previouslyActive.votingStatus = 'evaluated';
|
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.isActiveForVoting = true;
|
||||||
team.votingStatus = 'evaluating';
|
team.votingStatus = 'evaluating';
|
||||||
await team.save();
|
await team.save();
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
// Импортировать mongoose из общего модуля (подключение происходит в server/utils/mongoose.ts)
|
// Импортировать mongoose из общего модуля (подключение происходит автоматически)
|
||||||
const mongoose = require('../../../utils/mongoose');
|
const mongoose = require('../../../utils/mongoose');
|
||||||
const { Event } = require('../models');
|
const Event = require('../models/Event');
|
||||||
|
|
||||||
async function recreateTestUser() {
|
async function recreateTestUser() {
|
||||||
try {
|
try {
|
||||||
// Ждем, пока подключение будет готово
|
// Проверяем подключение к MongoDB
|
||||||
if (mongoose.connection.readyState !== 1) {
|
if (mongoose.connection.readyState !== 1) {
|
||||||
await new Promise(resolve => {
|
console.log('Waiting for MongoDB connection...');
|
||||||
mongoose.connection.once('connected', resolve);
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Connected to MongoDB');
|
console.log('Connected to MongoDB');
|
||||||
@@ -22,12 +21,11 @@ async function recreateTestUser() {
|
|||||||
votingEnabled: false
|
votingEnabled: false
|
||||||
});
|
});
|
||||||
console.log('Test event created:', event.name);
|
console.log('Test event created:', event.name);
|
||||||
|
} else {
|
||||||
|
console.log('Event already exists:', event.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Database initialized successfully');
|
console.log('Database initialized successfully');
|
||||||
|
|
||||||
await mongoose.disconnect();
|
|
||||||
console.log('Disconnected from MongoDB');
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|||||||
Reference in New Issue
Block a user