241 lines
7.7 KiB
JavaScript
241 lines
7.7 KiB
JavaScript
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);
|
||
}
|
||
|
||
// Преобразуем adminComment в adminNotes для фронтенда
|
||
const reportResponse = report.toObject();
|
||
if (reportResponse.adminComment) {
|
||
reportResponse.adminNotes = reportResponse.adminComment;
|
||
}
|
||
|
||
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;
|
||
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;
|
||
|
||
if (status === 'resolved' || status === 'dismissed') {
|
||
report.reviewedAt = new Date();
|
||
}
|
||
|
||
if (adminNotes) {
|
||
report.adminComment = adminNotes; // В модели поле называется adminComment
|
||
}
|
||
|
||
await report.save();
|
||
|
||
console.log(`[REPORT_CTRL] Жалоба ${id} обновлена администратором ${adminId}, статус: ${status}`);
|
||
|
||
// Возвращаем обновленную жалобу с заполненными связями
|
||
const updatedReport = await Report.findById(id)
|
||
.populate('reporter', 'name email')
|
||
.populate('reportedUser', 'name email isActive')
|
||
.populate('reviewedBy', 'name email');
|
||
|
||
// Преобразуем adminComment в adminNotes для фронтенда
|
||
const reportResponse = updatedReport.toObject();
|
||
if (reportResponse.adminComment) {
|
||
reportResponse.adminNotes = reportResponse.adminComment;
|
||
}
|
||
|
||
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
|
||
}; |