Reflex/backend/controllers/reportController.js

255 lines
8.2 KiB
JavaScript
Raw Permalink Normal View History

const Report = require('../models/Report');
const User = require('../models/User');
// @desc Подать жалобу на пользователя
// @route POST /api/reports
// @access Private
const createReport = async (req, res, next) => {
try {
const { reportedUserId, reason, description } = req.body;
const reporterId = req.user._id;
// Проверяем, что пользователь не подает жалобу на самого себя
if (reporterId.equals(reportedUserId)) {
const error = new Error('Вы не можете подать жалобу на самого себя');
error.statusCode = 400;
return next(error);
}
// Проверяем, существует ли пользователь, на которого подается жалоба
const reportedUser = await User.findById(reportedUserId);
if (!reportedUser) {
const error = new Error('Пользователь не найден');
error.statusCode = 404;
return next(error);
}
// Проверяем, нет ли уже жалобы от этого пользователя на этого же пользователя
const existingReport = await Report.findOne({
reporter: reporterId,
reportedUser: reportedUserId
});
if (existingReport) {
const error = new Error('Вы уже подавали жалобу на этого пользователя');
error.statusCode = 400;
return next(error);
}
// Создаем новую жалобу
const newReport = new Report({
reporter: reporterId,
reportedUser: reportedUserId,
reason,
description: description || ''
});
await newReport.save();
console.log(`[REPORT_CTRL] Создана жалоба ${newReport._id} от пользователя ${reporterId} на пользователя ${reportedUserId}`);
res.status(201).json({
message: 'Жалоба успешно подана. Мы рассмотрим её в ближайшее время.',
reportId: newReport._id
});
} catch (error) {
console.error('[REPORT_CTRL] Ошибка при создании жалобы:', error.message);
next(error);
}
};
// @desc Получить список всех жалоб (для админов)
// @route GET /api/admin/reports
// @access Admin
const getAllReports = async (req, res, next) => {
try {
const { page = 1, limit = 20, status = 'all' } = req.query;
const skip = (page - 1) * limit;
// Строим фильтр
let filter = {};
if (status !== 'all') {
filter.status = status;
}
// Получаем жалобы с информацией о пользователях
const reports = await Report.find(filter)
.populate('reporter', 'name email')
.populate('reportedUser', 'name email isActive')
.populate('reviewedBy', 'name email')
.skip(skip)
.limit(parseInt(limit))
.sort({ createdAt: -1 });
// Получаем общее количество жалоб
const total = await Report.countDocuments(filter);
res.json({
reports,
pagination: {
page: parseInt(page),
limit: parseInt(limit),
total,
pages: Math.ceil(total / limit)
}
});
} catch (error) {
console.error('[REPORT_CTRL] Ошибка при получении списка жалоб:', error.message);
next(error);
}
};
// @desc Получить детали жалобы
// @route GET /api/admin/reports/:id
// @access Admin
const getReportById = async (req, res, next) => {
try {
const { id } = req.params;
const report = await Report.findById(id)
.populate('reporter', 'name email photos')
.populate('reportedUser', 'name email photos isActive')
.populate('reviewedBy', 'name email');
if (!report) {
const error = new Error('Жалоба не найдена');
error.statusCode = 404;
return next(error);
}
2025-05-26 01:05:41 +07:00
// Преобразуем поля для совместимости с фронтендом
2025-05-26 00:57:20 +07:00
const reportResponse = report.toObject();
2025-05-26 01:05:41 +07:00
// Преобразуем adminComment в adminNotes
2025-05-26 00:57:20 +07:00
if (reportResponse.adminComment) {
reportResponse.adminNotes = reportResponse.adminComment;
}
2025-05-26 01:05:41 +07:00
// Преобразуем reviewedAt в resolvedAt
if (reportResponse.reviewedAt) {
reportResponse.resolvedAt = reportResponse.reviewedAt;
}
2025-05-26 00:57:20 +07:00
res.json(reportResponse);
} catch (error) {
console.error('[REPORT_CTRL] Ошибка при получении деталей жалобы:', error.message);
next(error);
}
};
// @desc Обновить статус жалобы
// @route PUT /api/admin/reports/:id
// @access Admin
const updateReportStatus = async (req, res, next) => {
try {
const { id } = req.params;
2025-05-26 00:57:20 +07:00
const { status, adminNotes } = req.body;
const adminId = req.user._id;
const report = await Report.findById(id);
if (!report) {
const error = new Error('Жалоба не найдена');
error.statusCode = 404;
return next(error);
}
// Обновляем жалобу
report.status = status;
report.reviewedBy = adminId;
2025-05-26 00:57:20 +07:00
if (status === 'resolved' || status === 'dismissed') {
report.reviewedAt = new Date();
}
2025-05-26 00:57:20 +07:00
if (adminNotes) {
report.adminComment = adminNotes; // В модели поле называется adminComment
}
await report.save();
2025-05-26 01:28:53 +07:00
console.log(`[REPORT_CTRL] Жалоба ${id} обновлена администратором ${adminId}, статус: ${status}`);
2025-05-26 00:57:20 +07:00
// Возвращаем обновленную жалобу с заполненными связями
const updatedReport = await Report.findById(id)
.populate('reporter', 'name email')
.populate('reportedUser', 'name email isActive')
.populate('reviewedBy', 'name email');
2025-05-26 01:05:41 +07:00
// Преобразуем поля для совместимости с фронтендом
2025-05-26 00:57:20 +07:00
const reportResponse = updatedReport.toObject();
2025-05-26 01:05:41 +07:00
// Преобразуем adminComment в adminNotes
2025-05-26 00:57:20 +07:00
if (reportResponse.adminComment) {
reportResponse.adminNotes = reportResponse.adminComment;
}
2025-05-26 01:05:41 +07:00
// Преобразуем reviewedAt в resolvedAt
if (reportResponse.reviewedAt) {
reportResponse.resolvedAt = reportResponse.reviewedAt;
}
2025-05-26 00:57:20 +07:00
res.json(reportResponse);
} catch (error) {
console.error('[REPORT_CTRL] Ошибка при обновлении жалобы:', error.message);
next(error);
}
};
// @desc Получить статистику жалоб
// @route GET /api/admin/reports/stats
// @access Admin
const getReportsStats = async (req, res, next) => {
try {
// Общее количество жалоб
const totalReports = await Report.countDocuments();
// Жалобы по статусам
const pendingReports = await Report.countDocuments({ status: 'pending' });
const reviewedReports = await Report.countDocuments({ status: 'reviewed' });
const resolvedReports = await Report.countDocuments({ status: 'resolved' });
const dismissedReports = await Report.countDocuments({ status: 'dismissed' });
// Жалобы за последние 30 дней
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
const recentReports = await Report.countDocuments({
createdAt: { $gte: thirtyDaysAgo }
});
// Топ причин жалоб
const topReasons = await Report.aggregate([
{ $group: { _id: '$reason', count: { $sum: 1 } } },
{ $sort: { count: -1 } },
{ $limit: 5 }
]);
const stats = {
total: totalReports,
byStatus: {
pending: pendingReports,
reviewed: reviewedReports,
resolved: resolvedReports,
dismissed: dismissedReports
},
recent: recentReports,
topReasons
};
res.json(stats);
} catch (error) {
console.error('[REPORT_CTRL] Ошибка при получении статистики жалоб:', error.message);
next(error);
}
};
module.exports = {
createReport,
getAllReports,
getReportById,
updateReportStatus,
getReportsStats
};