Corp/backend/notifications/management/commands/notification_stats.py
Игорь Надеин e5503a1490 fix: исправление модуля уведомлений и добавление тестов
- Исправлена маршрутизация API: обновлены JS файлы для использования /api/v1/notifications/
- Исправлена ошибка в api_views.py: last_error='' вместо None (TextField не может быть NULL)
- Исправлена ошибка в services.py: использование метода reset_errors()
- Добавлено 36 комплексных тестов (модели, API, сервисы) - все проходят
- Создана документация аудита модуля (NOTIFICATIONS_AUDIT.md)
- Создано руководство по тестированию (NOTIFICATIONS_TESTING.md)
- Добавлены management команды: cleanup_push_subscriptions, notification_stats
- Тесты перемещены в backend/tests/notifications/ для правильной организации

Вся функциональность уведомлений проверена и работает корректно.
2026-01-05 15:38:36 +03:00

121 lines
5.0 KiB
Python
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.

"""
Management команда для показа статистики уведомлений
"""
from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model
from django.db.models import Count, Q
from notifications.models import (
Notification,
NotificationCategory,
NotificationType,
WebPushSubscription,
)
User = get_user_model()
class Command(BaseCommand):
help = 'Показать статистику уведомлений'
def handle(self, *args, **options):
self.stdout.write(self.style.SUCCESS('\n📊 СТАТИСТИКА УВЕДОМЛЕНИЙ\n'))
# Общая статистика уведомлений
total_notifications = Notification.objects.count()
unread_notifications = Notification.objects.filter(is_read=False).count()
archived_notifications = Notification.objects.filter(is_archived=True).count()
self.stdout.write('📧 Уведомления:')
self.stdout.write(f' Всего: {total_notifications}')
self.stdout.write(f' Непрочитанных: {unread_notifications}')
self.stdout.write(f' Архивных: {archived_notifications}')
# Статистика по категориям
self.stdout.write('\n📁 По категориям:')
category_stats = Notification.objects.values(
'notification_type__category__name'
).annotate(
count=Count('id'),
unread=Count('id', filter=Q(is_read=False))
).order_by('-count')
for stat in category_stats[:10]:
category_name = stat['notification_type__category__name'] or 'Unknown'
self.stdout.write(
f' {category_name}: {stat["count"]} '
f'(непрочитанных: {stat["unread"]})'
)
# Статистика по типам (топ 10)
self.stdout.write('\n🔔 Топ-10 типов уведомлений:')
type_stats = Notification.objects.values(
'notification_type__name'
).annotate(
count=Count('id')
).order_by('-count')[:10]
for stat in type_stats:
type_name = stat['notification_type__name']
self.stdout.write(f' {type_name}: {stat["count"]}')
# Статистика по пользователям (топ 10)
self.stdout.write('\n👥 Топ-10 пользователей по уведомлениям:')
user_stats = Notification.objects.values(
'recipient__email'
).annotate(
count=Count('id'),
unread=Count('id', filter=Q(is_read=False))
).order_by('-count')[:10]
for stat in user_stats:
email = stat['recipient__email']
self.stdout.write(
f' {email}: {stat["count"]} '
f'(непрочитанных: {stat["unread"]})'
)
# Web Push подписки
self.stdout.write('\n📱 Web Push подписки:')
total_subs = WebPushSubscription.objects.count()
active_subs = WebPushSubscription.objects.filter(is_active=True).count()
error_subs = WebPushSubscription.objects.filter(
error_count__gt=0
).count()
self.stdout.write(f' Всего: {total_subs}')
self.stdout.write(f' Активных: {active_subs}')
self.stdout.write(f' С ошибками: {error_subs}')
# Подписки по устройствам
if active_subs > 0:
self.stdout.write('\n По устройствам:')
device_stats = WebPushSubscription.objects.filter(
is_active=True
).values('device_name').annotate(
count=Count('id')
).order_by('-count')
for stat in device_stats[:10]:
device = stat['device_name'] or 'Unknown'
self.stdout.write(f' {device}: {stat["count"]}')
# Каналы доставки
self.stdout.write('\n📤 Статистика доставки:')
sent_web = Notification.objects.filter(sent_web=True).count()
sent_email = Notification.objects.filter(sent_email=True).count()
sent_telegram = Notification.objects.filter(sent_telegram=True).count()
self.stdout.write(f' Web: {sent_web}')
self.stdout.write(f' Email: {sent_email}')
self.stdout.write(f' Telegram: {sent_telegram}')
# Типы уведомлений
self.stdout.write('\n⚙️ Типы уведомлений:')
total_types = NotificationType.objects.count()
active_types = NotificationType.objects.filter(is_active=True).count()
self.stdout.write(f' Всего: {total_types}')
self.stdout.write(f' Активных: {active_types}')
self.stdout.write('')