diff --git a/backend/communications/models.py b/backend/communications/models.py index 3e0849b9..f64965f1 100644 --- a/backend/communications/models.py +++ b/backend/communications/models.py @@ -266,6 +266,19 @@ class Chat(models.Model): ).distinct() if self.type == "global": return Employee.objects.filter(is_active=True) + if self.type in ["announcement", "channel"]: + # Если include_all_employees - все активные сотрудники + if self.include_all_employees: + return Employee.objects.filter(is_active=True) + # Иначе только явно добавленные через participants или ChatMembership + from .models import ChatMembership + membership_ids = ChatMembership.objects.filter( + chat=self + ).values_list("user_id", flat=True) + return Employee.objects.filter( + Q(id__in=self.participants.values_list('id', flat=True)) | + Q(id__in=membership_ids) + ).distinct() return Employee.objects.none() def __str__(self): diff --git a/backend/communications/notification_signals.py b/backend/communications/notification_signals.py index b303e8f4..e5496101 100644 --- a/backend/communications/notification_signals.py +++ b/backend/communications/notification_signals.py @@ -37,7 +37,11 @@ def create_message_notifications(sender, instance, created, **kwargs): content = instance.content # Получаем всех участников чата кроме автора - participants = chat.participants.exclude(id=author.id) + # Для announcement/channel/department используем get_participants + if chat.type in ['announcement', 'channel', 'department', 'global']: + participants = chat.get_participants.exclude(id=author.id) + else: + participants = chat.participants.exclude(id=author.id) # 1. Обработка упоминаний (@username) mentioned_users = extract_mentions(content) diff --git a/backend/test_announcement_notifications.py b/backend/test_announcement_notifications.py new file mode 100644 index 00000000..1404bb5f --- /dev/null +++ b/backend/test_announcement_notifications.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +""" +Тестирование уведомлений для объявлений +""" +import os +import django + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'eusrr_backend.settings') +django.setup() + +from communications.models import Chat, Message +from employees.models import Employee + +def test_announcement_notifications(): + """Проверяет, что уведомления для объявлений отправляются всем""" + + # Находим чат-объявление + announcement = Chat.objects.filter(type='announcement').first() + + if not announcement: + print("❌ Нет объявлений в системе") + return + + print(f"✓ Найдено объявление: {announcement.name}") + print(f" Created by: {announcement.created_by}") + print(f" include_all_employees: {announcement.include_all_employees}") + + # Получаем участников + participants = announcement.get_participants + print(f" Участников (get_participants): {participants.count()}") + + # Список участников + for p in participants[:5]: + print(f" - {p.get_full_name() or p.username} ({p.email})") + + if participants.count() > 5: + print(f" ... и ещё {participants.count() - 5}") + + # Проверяем последнее сообщение + last_message = announcement.messages.order_by('-created_at').first() + + if last_message: + print(f"\n✓ Последнее сообщение:") + print(f" ID: {last_message.id}") + print(f" Автор: {last_message.author}") + print(f" Текст: {last_message.content[:50]}...") + print(f" Создано: {last_message.created_at}") + + # Проверяем уведомления + from notifications.models import Notification + notifications = Notification.objects.filter( + content_type__model='message', + object_id=last_message.id + ) + + print(f"\n✓ Уведомлений создано: {notifications.count()}") + + # Проверяем тип уведомлений + announcement_notifs = notifications.filter( + notification_type__code='announcement_new_message' + ) + print(f" Типа 'announcement_new_message': {announcement_notifs.count()}") + + # Показываем первые 5 + for n in notifications[:5]: + print(f" - Для: {n.recipient.get_full_name()}") + print(f" Тип: {n.notification_type.code}") + print(f" Прочитано: {n.is_read}") + else: + print("\n❌ Нет сообщений в объявлении") + + # Итоги + print("\n" + "="*60) + all_employees = Employee.objects.filter(is_active=True).count() + print(f"Всего активных сотрудников: {all_employees}") + print(f"Участников объявления: {participants.count()}") + + if participants.count() == all_employees: + print("✅ ПРАВИЛЬНО: Все сотрудники получат уведомления") + else: + print(f"⚠️ ВНИМАНИЕ: Уведомления получат только {participants.count()} из {all_employees}") + +if __name__ == '__main__': + test_announcement_notifications() diff --git a/backend/test_create_announcement_message.py b/backend/test_create_announcement_message.py new file mode 100644 index 00000000..979bf3ae --- /dev/null +++ b/backend/test_create_announcement_message.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +""" +Создаём тестовое сообщение в объявлении и проверяем уведомления +""" +import os +import django + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'eusrr_backend.settings') +django.setup() + +from communications.models import Chat, Message +from employees.models import Employee +from notifications.models import Notification + +def create_test_message(): + """Создаёт тестовое сообщение в объявлении""" + + # Находим чат-объявление + announcement = Chat.objects.filter(type='announcement').first() + + if not announcement: + print("❌ Нет объявлений в системе") + return + + print(f"✓ Найдено объявление: {announcement.name}") + print(f" Created by: {announcement.created_by}") + + # Подсчитываем уведомления ДО + notif_count_before = Notification.objects.count() + print(f"\nУведомлений ДО создания сообщения: {notif_count_before}") + + # Создаём сообщение + message = Message.objects.create( + chat=announcement, + author=announcement.created_by, + content="ТЕСТОВОЕ ОБЪЯВЛЕНИЕ для проверки уведомлений" + ) + + print(f"\n✓ Создано сообщение ID={message.id}") + + # Подсчитываем уведомления ПОСЛЕ + notif_count_after = Notification.objects.count() + print(f"Уведомлений ПОСЛЕ создания сообщения: {notif_count_after}") + print(f"Создано новых уведомлений: {notif_count_after - notif_count_before}") + + # Проверяем уведомления для этого сообщения + message_notifs = Notification.objects.filter( + content_type__model='message', + object_id=message.id + ) + + print(f"\nУведомлений для сообщения ID={message.id}: {message_notifs.count()}") + + if message_notifs.exists(): + print("\n📧 Список уведомлений:") + for n in message_notifs: + print(f" - Получатель: {n.recipient.get_full_name()}") + print(f" Тип: {n.notification_type.code}") + print(f" Заголовок: {n.title}") + print() + else: + print("\n❌ Уведомления НЕ созданы!") + print("\nПроверяем настройки:") + print(f" - message.is_system: {message.is_system}") + print(f" - message.is_deleted: {message.is_deleted}") + print(f" - chat.type: {announcement.type}") + + # Проверяем участников + participants = announcement.get_participants + print(f" - Участников: {participants.count()}") + for p in participants: + print(f" * {p.get_full_name()} (ID={p.id})") + + print(f" - Автор: {message.author.get_full_name()} (ID={message.author.id})") + + # Участники без автора + participants_no_author = participants.exclude(id=message.author.id) + print(f" - Участников без автора: {participants_no_author.count()}") + +if __name__ == '__main__': + create_test_message()