еще - лишнее в проекте
This commit is contained in:
parent
a784212ea1
commit
a196a2b941
@ -1,201 +0,0 @@
|
||||
# Celery Integration - Следующие шаги
|
||||
|
||||
## ✅ Что уже сделано
|
||||
|
||||
1. ✅ Добавлены зависимости в `requirements.txt`:
|
||||
- `celery==5.5.3`
|
||||
- `redis==5.2.1`
|
||||
- `django-celery-beat==2.7.0`
|
||||
- `django-celery-results==2.5.1`
|
||||
- `flower==2.0.1`
|
||||
|
||||
2. ✅ Создан файл конфигурации `eusrr_backend/celery.py`
|
||||
- Настроена автоматическая регистрация задач
|
||||
- Добавлен debug task для тестирования
|
||||
|
||||
3. ✅ Обновлен `eusrr_backend/__init__.py`
|
||||
- Автоматический импорт celery_app при запуске Django
|
||||
|
||||
4. ✅ Добавлены настройки Celery в `settings.py`:
|
||||
- `CELERY_BROKER_URL` - Redis как брокер сообщений
|
||||
- `CELERY_RESULT_BACKEND` - Redis для хранения результатов
|
||||
- Настройка роутинга задач по очередям
|
||||
- Таймауты и лимиты для workers
|
||||
|
||||
5. ✅ Добавлены приложения в `INSTALLED_APPS`:
|
||||
- `django_celery_beat` - для периодических задач
|
||||
- `django_celery_results` - для хранения результатов
|
||||
|
||||
6. ✅ Созданы Celery задачи в `notifications/tasks.py`:
|
||||
- `send_notification_task` - отправка одного уведомления
|
||||
- `send_bulk_notifications_task` - массовая отправка
|
||||
- `cleanup_old_notifications_task` - очистка старых уведомлений
|
||||
- `send_digest_email_task` - email-дайджесты
|
||||
|
||||
## 🔄 Следующие шаги (выполнить вручную)
|
||||
|
||||
### Шаг 1: Установка зависимостей
|
||||
|
||||
Запустите задачу в VS Code:
|
||||
- **Pip: install requirements**
|
||||
|
||||
Или вручную:
|
||||
```bash
|
||||
cd backend
|
||||
..\.venv\Scripts\pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### Шаг 2: Установка и запуск Redis
|
||||
|
||||
#### Вариант 1: Windows (рекомендуется Memurai)
|
||||
1. Скачайте Memurai (Redis для Windows): https://www.memurai.com/
|
||||
2. Установите и запустите как службу Windows
|
||||
3. Redis будет доступен на `localhost:6379`
|
||||
|
||||
#### Вариант 2: Docker
|
||||
```bash
|
||||
docker run -d -p 6379:6379 --name redis redis:7-alpine
|
||||
```
|
||||
|
||||
#### Проверка Redis:
|
||||
```bash
|
||||
redis-cli ping
|
||||
# Должно вернуть: PONG
|
||||
```
|
||||
|
||||
### Шаг 3: Применение миграций
|
||||
|
||||
Запустите:
|
||||
```bash
|
||||
cd backend
|
||||
migrate_celery.bat
|
||||
```
|
||||
|
||||
Или вручную:
|
||||
```bash
|
||||
..\.venv\Scripts\python manage.py migrate django_celery_beat
|
||||
..\.venv\Scripts\python manage.py migrate django_celery_results
|
||||
```
|
||||
|
||||
### Шаг 4: Тестирование Celery Worker
|
||||
|
||||
В отдельном терминале запустите worker:
|
||||
```bash
|
||||
cd backend
|
||||
..\.venv\Scripts\celery -A eusrr_backend worker -l info --pool=solo
|
||||
```
|
||||
|
||||
**Примечание**: На Windows используйте `--pool=solo` или `--pool=gevent`
|
||||
|
||||
### Шаг 5: Тестирование отправки задачи
|
||||
|
||||
В Django shell:
|
||||
```python
|
||||
..\.venv\Scripts\python manage.py shell
|
||||
|
||||
from celery import current_app
|
||||
current_app.send_task('eusrr_backend.debug_task')
|
||||
```
|
||||
|
||||
Вы должны увидеть выполнение задачи в логах worker.
|
||||
|
||||
### Шаг 6: Интеграция с NotificationService
|
||||
|
||||
Обновите `notifications/services.py`:
|
||||
```python
|
||||
from notifications.tasks import send_notification_task, send_bulk_notifications_task
|
||||
|
||||
class NotificationService:
|
||||
@staticmethod
|
||||
def create_notification(...):
|
||||
# Вместо синхронного создания
|
||||
send_notification_task.delay(
|
||||
notification_type=notification_type,
|
||||
user_id=user.id,
|
||||
title=title,
|
||||
message=message,
|
||||
link=link,
|
||||
sender_id=sender.id if sender else None,
|
||||
metadata=metadata,
|
||||
)
|
||||
```
|
||||
|
||||
### Шаг 7: Запуск Flower (мониторинг)
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
..\.venv\Scripts\celery -A eusrr_backend flower
|
||||
```
|
||||
|
||||
Откройте http://localhost:5555 для просмотра статистики задач.
|
||||
|
||||
### Шаг 8: Настройка периодических задач
|
||||
|
||||
В Django Admin:
|
||||
1. Перейдите в "Periodic Tasks"
|
||||
2. Добавьте задачу для `notifications.cleanup_old_notifications`
|
||||
3. Настройте интервал (например, раз в день)
|
||||
|
||||
Или программно в `eusrr_backend/celery.py`:
|
||||
```python
|
||||
from celery.schedules import crontab
|
||||
|
||||
app.conf.beat_schedule = {
|
||||
'cleanup-old-notifications': {
|
||||
'task': 'notifications.cleanup_old_notifications',
|
||||
'schedule': crontab(hour=3, minute=0), # Каждый день в 3:00
|
||||
'args': (90,) # Удалять уведомления старше 90 дней
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Запустите beat scheduler:
|
||||
```bash
|
||||
..\.venv\Scripts\celery -A eusrr_backend beat -l info
|
||||
```
|
||||
|
||||
## 📊 Ожидаемый результат
|
||||
|
||||
**До внедрения Celery:**
|
||||
- Отправка сообщения в группу с 8 участниками: ~500ms
|
||||
- Блокировка API response до отправки всех уведомлений
|
||||
|
||||
**После внедрения Celery:**
|
||||
- Отправка сообщения: <50ms (только создание задачи)
|
||||
- Уведомления обрабатываются асинхронно
|
||||
- API мгновенно отвечает пользователю
|
||||
|
||||
## 🔍 Отладка
|
||||
|
||||
### Проверка статуса Celery
|
||||
```bash
|
||||
..\.venv\Scripts\celery -A eusrr_backend inspect active
|
||||
..\.venv\Scripts\celery -A eusrr_backend inspect stats
|
||||
```
|
||||
|
||||
### Проверка задач в очереди
|
||||
```bash
|
||||
..\.venv\Scripts\celery -A eusrr_backend inspect reserved
|
||||
```
|
||||
|
||||
### Логи
|
||||
- Worker логи: консоль где запущен worker
|
||||
- Flower: http://localhost:5555
|
||||
- Django логи: стандартные логи приложения
|
||||
|
||||
## 📚 Документация
|
||||
|
||||
- Подробная документация: `docs/guides/CELERY_SETUP.md`
|
||||
- План внедрения (5 дней): `docs/in-progress/CELERY_INTEGRATION_PLAN.md`
|
||||
- Celery docs: https://docs.celeryq.dev/
|
||||
|
||||
## ⚠️ Production Deployment
|
||||
|
||||
Для production:
|
||||
1. Используйте Redis Cluster или Redis Sentinel
|
||||
2. Запускайте несколько workers с supervisord/systemd
|
||||
3. Настройте мониторинг (Flower + Prometheus)
|
||||
4. Добавьте retry policies и dead letter queue
|
||||
5. Настройте автоматический перезапуск workers
|
||||
|
||||
См. `docs/in-progress/CELERY_INTEGRATION_PLAN.md` для деталей.
|
||||
@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""Проверка параметров события в базе данных."""
|
||||
import os
|
||||
import sys
|
||||
import django
|
||||
|
||||
# Setup Django
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "eusrr_backend.settings")
|
||||
django.setup()
|
||||
|
||||
# ЯВНЫЙ импорт патча
|
||||
import schedule_patch # noqa
|
||||
|
||||
from schedule.models import Event, Rule
|
||||
|
||||
# Найдём событие по названию
|
||||
event = Event.objects.filter(title__icontains='ыфвыфыф').first()
|
||||
|
||||
if event:
|
||||
print(f"=" * 80)
|
||||
print(f"Event ID: {event.id}")
|
||||
print(f"Title: {event.title}")
|
||||
print(f"Start: {event.start} (weekday: {event.start.weekday()})")
|
||||
print(f"End recurring: {event.end_recurring_period}")
|
||||
print(f"=" * 80)
|
||||
|
||||
if event.rule:
|
||||
print(f"\nRule ID: {event.rule.id}")
|
||||
print(f"Frequency: {event.rule.frequency}")
|
||||
print(f"Params: {event.rule.params}")
|
||||
print(f"=" * 80)
|
||||
|
||||
# Проверим occurrences
|
||||
from datetime import datetime
|
||||
from django.utils import timezone
|
||||
start = timezone.make_aware(datetime(2026, 2, 1, 0, 0, 0))
|
||||
end = timezone.make_aware(datetime(2026, 2, 28, 23, 59, 59))
|
||||
occurrences = event.get_occurrences(start, end)
|
||||
|
||||
print(f"\nOccurrences в феврале 2026:")
|
||||
for occ in occurrences:
|
||||
print(f" - {occ.start.strftime('%Y-%m-%d %A')} {occ.start.strftime('%H:%M')}")
|
||||
print(f"=" * 80)
|
||||
else:
|
||||
print("НЕТ ПРАВИЛА!")
|
||||
else:
|
||||
print("Событие не найдено!")
|
||||
@ -1,57 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
# OpenLDAP сервер для тестирования
|
||||
test-ldap:
|
||||
image: osixia/openldap:1.5.0
|
||||
container_name: eusrr-test-ldap
|
||||
hostname: ldap.test.local
|
||||
environment:
|
||||
# Базовая конфигурация
|
||||
LDAP_ORGANISATION: "EUSRR Test"
|
||||
LDAP_DOMAIN: "test.local"
|
||||
LDAP_BASE_DN: "dc=test,dc=local"
|
||||
LDAP_ADMIN_PASSWORD: "test_change-me-redacted-secret"
|
||||
LDAP_CONFIG_PASSWORD: "test_config_password"
|
||||
LDAP_READONLY_USER: "false"
|
||||
|
||||
# Настройки для совместимости с вашим кодом
|
||||
LDAP_RFC2307BIS_SCHEMA: "true"
|
||||
LDAP_BACKEND: "mdb"
|
||||
LDAP_TLS: "false"
|
||||
LDAP_TLS_VERIFY_CLIENT: "never"
|
||||
|
||||
# Логирование для отладки
|
||||
LDAP_LOG_LEVEL: "256"
|
||||
ports:
|
||||
- "10389:389" # Используем порт 10389 чтобы не конфликтовать с prod
|
||||
- "10636:636" # SSL порт (если понадобится)
|
||||
volumes:
|
||||
- ./ldap_test_data:/var/lib/ldap
|
||||
- ./ldap_test_config:/etc/ldap/slapd.d
|
||||
- ./tests/ldap_fixtures:/container/service/slapd/assets/config/bootstrap/ldif/custom
|
||||
networks:
|
||||
- test-network
|
||||
command: --copy-service --loglevel debug
|
||||
|
||||
# phpLDAPadmin - веб-интерфейс для управления (опционально)
|
||||
ldap-admin:
|
||||
image: osixia/phpldapadmin:0.9.0
|
||||
container_name: eusrr-ldap-admin
|
||||
environment:
|
||||
PHPLDAPADMIN_LDAP_HOSTS: "test-ldap"
|
||||
PHPLDAPADMIN_HTTPS: "false"
|
||||
ports:
|
||||
- "8090:80"
|
||||
depends_on:
|
||||
- test-ldap
|
||||
networks:
|
||||
- test-network
|
||||
|
||||
networks:
|
||||
test-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
ldap_test_data:
|
||||
ldap_test_config:
|
||||
@ -1,146 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Тест полного цикла уведомлений
|
||||
|
||||
Проверяет:
|
||||
1. Создание уведомления через notify.send()
|
||||
2. Срабатывание post_save сигнала
|
||||
3. Отправку задач в Celery
|
||||
4. Наличие уведомления в БД
|
||||
5. Выполнение задач Celery
|
||||
"""
|
||||
|
||||
import django
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
# Setup Django
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'eusrr_backend.settings')
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
django.setup()
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from notifications.signals import notify
|
||||
from notifications.models import Notification
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
def test_notification_creation():
|
||||
"""Тест создания уведомления"""
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("ТЕСТ СИСТЕМЫ УВЕДОМЛЕНИЙ")
|
||||
print("="*60)
|
||||
|
||||
# 1. Находим двух пользователей
|
||||
print("\n1. Поиск пользователей...")
|
||||
users = User.objects.filter(is_active=True)[:2]
|
||||
|
||||
if users.count() < 2:
|
||||
print("❌ Нужно минимум 2 активных пользователя")
|
||||
return
|
||||
|
||||
sender = users[0]
|
||||
recipient = users[1]
|
||||
|
||||
print(f" ✅ Отправитель: {sender.username} (ID: {sender.id})")
|
||||
print(f" ✅ Получатель: {recipient.username} (ID: {recipient.id})")
|
||||
|
||||
# 2. Проверяем настройки получателя
|
||||
print("\n2. Проверка настроек получателя...")
|
||||
try:
|
||||
prefs = recipient.channel_preferences
|
||||
print(f" ✅ web_enabled: {prefs.web_enabled}")
|
||||
print(f" ✅ email_enabled: {prefs.email_enabled}")
|
||||
print(f" ✅ push_enabled: {prefs.push_enabled}")
|
||||
print(f" ✅ email_frequency: {prefs.email_frequency}")
|
||||
print(f" ✅ DND период: {prefs.is_in_dnd_period()}")
|
||||
except Exception as e:
|
||||
print(f" ⚠️ Нет настроек (будут созданы): {e}")
|
||||
|
||||
# 3. Подсчет уведомлений до создания
|
||||
print("\n3. Подсчет уведомлений перед тестом...")
|
||||
count_before = Notification.objects.count()
|
||||
print(f" Всего уведомлений в БД: {count_before}")
|
||||
|
||||
# 4. Создаем уведомление
|
||||
print("\n4. Создание уведомления через notify.send()...")
|
||||
|
||||
try:
|
||||
result = notify.send(
|
||||
sender=sender,
|
||||
recipient=recipient,
|
||||
verb='test_notification',
|
||||
description=f'🧪 Тестовое уведомление от {sender.username}',
|
||||
action_url='/test/',
|
||||
data={
|
||||
'test': True,
|
||||
'timestamp': time.time(),
|
||||
}
|
||||
)
|
||||
|
||||
print(f" ✅ notify.send() выполнен")
|
||||
print(f" Результат: {result}")
|
||||
|
||||
except Exception as e:
|
||||
print(f" ❌ Ошибка при создании: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return
|
||||
|
||||
# 5. Проверяем что уведомление создано в БД
|
||||
print("\n5. Проверка создания в БД...")
|
||||
time.sleep(0.1) # Небольшая задержка для сохранения
|
||||
|
||||
count_after = Notification.objects.count()
|
||||
new_notifications = count_after - count_before
|
||||
|
||||
print(f" Всего уведомлений в БД: {count_after}")
|
||||
print(f" Создано новых: {new_notifications}")
|
||||
|
||||
if new_notifications == 0:
|
||||
print(" ❌ Уведомление не создано в БД!")
|
||||
return
|
||||
|
||||
# 6. Получаем созданное уведомление
|
||||
print("\n6. Детали созданного уведомления...")
|
||||
notification = Notification.objects.filter(recipient=recipient).order_by('-id').first()
|
||||
|
||||
if notification:
|
||||
print(f" ✅ ID: {notification.id}")
|
||||
print(f" ✅ verb: {notification.verb}")
|
||||
print(f" ✅ description: {notification.description}")
|
||||
print(f" ✅ recipient: {notification.recipient.username}")
|
||||
print(f" ✅ actor: {notification.actor}")
|
||||
print(f" ✅ unread: {notification.unread}")
|
||||
print(f" ✅ timestamp: {notification.timestamp}")
|
||||
else:
|
||||
print(" ❌ Уведомление не найдено!")
|
||||
return
|
||||
|
||||
# 7. Ждем выполнения Celery задач
|
||||
print("\n7. Ожидание выполнения Celery задач...")
|
||||
print(" ⏳ Ждем 2 секунды...")
|
||||
time.sleep(2)
|
||||
|
||||
# 8. Проверяем логи Celery
|
||||
print("\n8. Результаты:")
|
||||
print(" 📋 Проверьте логи Celery worker на наличие:")
|
||||
print(f" - Task notifications.send_websocket_notification[...] received")
|
||||
print(f" - Notification {notification.id} not found (если есть race condition)")
|
||||
print(f" - Task ... succeeded (если всё ОК)")
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("ТЕСТ ЗАВЕРШЕН")
|
||||
print("="*60)
|
||||
print("\nПроверьте:")
|
||||
print("1. Логи Celery worker")
|
||||
print("2. WebSocket соединение в браузере")
|
||||
print("3. Появилось ли уведомление в UI")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_notification_creation()
|
||||
@ -1,237 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Тестовый скрипт для проверки системы уведомлений v2.0
|
||||
|
||||
Использование:
|
||||
python test_notifications.py
|
||||
|
||||
Что тестируется:
|
||||
- Создание уведомления через notify.send()
|
||||
- Сохранение в БД
|
||||
- Отправка через Celery задачи (WebSocket, Email, Push)
|
||||
- Channel preferences
|
||||
- API endpoints
|
||||
"""
|
||||
import os
|
||||
import django
|
||||
|
||||
# Настройка Django
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'eusrr_backend.settings')
|
||||
django.setup()
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from notifications.signals import notify
|
||||
from notifications.models import Notification, UserChannelPreferences
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
def test_notify_send():
|
||||
"""Тест создания уведомления через notify.send()"""
|
||||
print("\n" + "="*80)
|
||||
print("ТЕСТ 1: Создание уведомления через notify.send()")
|
||||
print("="*80)
|
||||
|
||||
try:
|
||||
# Получаем первых двух пользователей
|
||||
users = User.objects.all()[:2]
|
||||
if len(users) < 2:
|
||||
print("❌ Нужно минимум 2 пользователя в БД")
|
||||
return False
|
||||
|
||||
sender_user = users[0]
|
||||
recipient_user = users[1]
|
||||
|
||||
print(f"📤 Отправитель: {sender_user.username}")
|
||||
print(f"📥 Получатель: {recipient_user.username}")
|
||||
|
||||
# Создаем уведомление
|
||||
notification = notify.send(
|
||||
sender=sender_user,
|
||||
recipient=recipient_user,
|
||||
verb='liked',
|
||||
description=f'{sender_user.get_full_name() or sender_user.username} liked your post',
|
||||
action_url='/posts/123/',
|
||||
)
|
||||
|
||||
if isinstance(notification, list):
|
||||
notification = notification[0]
|
||||
|
||||
print(f"✅ Уведомление создано: ID={notification.id}")
|
||||
print(f" Verb: {notification.verb}")
|
||||
print(f" Description: {notification.description}")
|
||||
print(f" Actor: {notification.actor}")
|
||||
print(f" Unread: {notification.unread}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def test_channel_preferences():
|
||||
"""Тест настроек каналов"""
|
||||
print("\n" + "="*80)
|
||||
print("ТЕСТ 2: UserChannelPreferences")
|
||||
print("="*80)
|
||||
|
||||
try:
|
||||
user = User.objects.first()
|
||||
if not user:
|
||||
print("❌ Нет пользователей в БД")
|
||||
return False
|
||||
|
||||
print(f"👤 Пользователь: {user.username}")
|
||||
|
||||
# Получаем или создаем настройки
|
||||
prefs, created = UserChannelPreferences.objects.get_or_create(user=user)
|
||||
|
||||
if created:
|
||||
print("✅ Созданы новые настройки с дефолтными значениями")
|
||||
else:
|
||||
print("✅ Настройки уже существуют")
|
||||
|
||||
print(f" Web: {prefs.web_enabled}")
|
||||
print(f" Email: {prefs.email_enabled} (frequency: {prefs.email_frequency})")
|
||||
print(f" Push: {prefs.push_enabled}")
|
||||
print(f" DND: {prefs.dnd_enabled} ({prefs.dnd_start_time} - {prefs.dnd_end_time})")
|
||||
|
||||
# Проверяем is_in_dnd_period()
|
||||
is_dnd = prefs.is_in_dnd_period()
|
||||
print(f" Сейчас в DND: {is_dnd}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def test_queryset_methods():
|
||||
"""Тест методов QuerySet"""
|
||||
print("\n" + "="*80)
|
||||
print("ТЕСТ 3: QuerySet методы")
|
||||
print("="*80)
|
||||
|
||||
try:
|
||||
user = User.objects.first()
|
||||
if not user:
|
||||
print("❌ Нет пользователей в БД")
|
||||
return False
|
||||
|
||||
print(f"👤 Пользователь: {user.username}")
|
||||
|
||||
# Получаем статистику
|
||||
total = Notification.objects.filter(recipient=user).count()
|
||||
unread = Notification.objects.filter(recipient=user).unread().count()
|
||||
read_count = Notification.objects.filter(recipient=user).read().count()
|
||||
|
||||
print(f"📊 Статистика:")
|
||||
print(f" Всего: {total}")
|
||||
print(f" Непрочитанных: {unread}")
|
||||
print(f" Прочитанных: {read_count}")
|
||||
|
||||
# Последние 5 уведомлений
|
||||
recent = Notification.objects.filter(
|
||||
recipient=user
|
||||
).order_by('-timestamp')[:5]
|
||||
|
||||
if recent:
|
||||
print(f"\n📬 Последние {recent.count()} уведомлений:")
|
||||
for n in recent:
|
||||
status = "🔵" if n.unread else "⚪"
|
||||
print(f" {status} [{n.verb}] {n.description[:50]}... ({n.timesince()} ago)")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def test_mark_as_read():
|
||||
"""Тест отметки как прочитанного"""
|
||||
print("\n" + "="*80)
|
||||
print("ТЕСТ 4: Отметка как прочитанного")
|
||||
print("="*80)
|
||||
|
||||
try:
|
||||
user = User.objects.first()
|
||||
if not user:
|
||||
print("❌ Нет пользователей в БД")
|
||||
return False
|
||||
|
||||
# Находим непрочитанное уведомление
|
||||
notification = Notification.objects.filter(
|
||||
recipient=user,
|
||||
unread=True
|
||||
).first()
|
||||
|
||||
if not notification:
|
||||
print("⚠️ Нет непрочитанных уведомлений")
|
||||
return True
|
||||
|
||||
print(f"📬 Уведомление ID={notification.id}: unread={notification.unread}")
|
||||
|
||||
# Отмечаем как прочитанное
|
||||
notification.mark_as_read()
|
||||
|
||||
# Перезагружаем из БД
|
||||
notification.refresh_from_db()
|
||||
|
||||
print(f"✅ После mark_as_read(): unread={notification.unread}")
|
||||
print(f" timestamp_read: {notification.timestamp_read}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
"""Запуск всех тестов"""
|
||||
print("\n" * 2)
|
||||
print("╔" + "="*78 + "╗")
|
||||
print("║" + " "*20 + "ТЕСТИРОВАНИЕ NOTIFICATIONS V2.0" + " "*25 + "║")
|
||||
print("╚" + "="*78 + "╝")
|
||||
|
||||
results = []
|
||||
|
||||
# Запускаем тесты
|
||||
results.append(("notify.send()", test_notify_send()))
|
||||
results.append(("UserChannelPreferences", test_channel_preferences()))
|
||||
results.append(("QuerySet методы", test_queryset_methods()))
|
||||
results.append(("mark_as_read()", test_mark_as_read()))
|
||||
|
||||
# Итоги
|
||||
print("\n" + "="*80)
|
||||
print("ИТОГИ")
|
||||
print("="*80)
|
||||
|
||||
for test_name, result in results:
|
||||
status = "✅ PASSED" if result else "❌ FAILED"
|
||||
print(f"{status}: {test_name}")
|
||||
|
||||
passed = sum(1 for _, r in results if r)
|
||||
total = len(results)
|
||||
|
||||
print(f"\n{'='*80}")
|
||||
print(f"Пройдено: {passed}/{total} тестов")
|
||||
print(f"{'='*80}\n")
|
||||
|
||||
return all(r for _, r in results)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
exit(0 if success else 1)
|
||||
Loading…
x
Reference in New Issue
Block a user