11 changed files with 247 additions and 165 deletions
-
138apps/account/management/commands/seed_notification_templates.py
-
41apps/account/migrations/0008_remove_notificationtemplate_body_fa_and_more.py
-
8apps/account/models/notification.py
-
25apps/account/notification_service.py
-
4apps/account/tasks.py
-
22apps/account/tests/notifications/test_communication_notifications.py
-
24apps/account/tests/notifications/test_live_notifications.py
-
78apps/account/tests/notifications/test_notifications.py
-
24apps/account/tests/notifications/test_quiz_notifications.py
-
20apps/account/tests/notifications/test_retention_notifications.py
-
28apps/account/tests/notifications/test_transaction_notifications.py
@ -0,0 +1,41 @@ |
|||||
|
# Generated by Django 4.2.30 on 2026-07-11 13:51 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('account', '0007_notificationtemplate_schedulednotification'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.RemoveField( |
||||
|
model_name='notificationtemplate', |
||||
|
name='body_fa', |
||||
|
), |
||||
|
migrations.RemoveField( |
||||
|
model_name='notificationtemplate', |
||||
|
name='title_fa', |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='notificationtemplate', |
||||
|
name='body_ru', |
||||
|
field=models.TextField(default='', max_length=1024, verbose_name='body (RU)'), |
||||
|
), |
||||
|
migrations.AddField( |
||||
|
model_name='notificationtemplate', |
||||
|
name='title_ru', |
||||
|
field=models.CharField(default='', max_length=255, verbose_name='title (RU)'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='notificationtemplate', |
||||
|
name='body_en', |
||||
|
field=models.TextField(default='', max_length=1024, verbose_name='body (EN)'), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='notificationtemplate', |
||||
|
name='title_en', |
||||
|
field=models.CharField(default='', max_length=255, verbose_name='title (EN)'), |
||||
|
), |
||||
|
] |
||||
@ -13,9 +13,9 @@ from apps.chat.models import RoomMessage, ChatMessage |
|||||
class CommunicationNotificationsFlowTests(TestCase): |
class CommunicationNotificationsFlowTests(TestCase): |
||||
def setUp(self): |
def setUp(self): |
||||
# Create languages |
# Create languages |
||||
self.lang_fa, _ = Language.objects.update_or_create( |
|
||||
code='fa', |
|
||||
defaults={'name': 'Persian', 'status': True, 'countries': []} |
|
||||
|
self.lang_ru, _ = Language.objects.update_or_create( |
||||
|
code='ru', |
||||
|
defaults={'name': 'Russian', 'status': True, 'countries': []} |
||||
) |
) |
||||
self.lang_en, _ = Language.objects.update_or_create( |
self.lang_en, _ = Language.objects.update_or_create( |
||||
code='en', |
code='en', |
||||
@ -33,7 +33,7 @@ class CommunicationNotificationsFlowTests(TestCase): |
|||||
email='[email protected]', |
email='[email protected]', |
||||
username='student_comm', |
username='student_comm', |
||||
fullname='Comm Student', |
fullname='Comm Student', |
||||
language=self.lang_fa, |
|
||||
|
language=self.lang_ru, |
||||
fcm='token_comm_student' |
fcm='token_comm_student' |
||||
) |
) |
||||
|
|
||||
@ -44,7 +44,7 @@ class CommunicationNotificationsFlowTests(TestCase): |
|||||
fullname='Teacher Comm', |
fullname='Teacher Comm', |
||||
user_type='professor', |
user_type='professor', |
||||
is_active=True, |
is_active=True, |
||||
language=self.lang_fa |
|
||||
|
language=self.lang_ru |
||||
) |
) |
||||
|
|
||||
# Create support user (admin) |
# Create support user (admin) |
||||
@ -54,7 +54,7 @@ class CommunicationNotificationsFlowTests(TestCase): |
|||||
fullname='Support Comm', |
fullname='Support Comm', |
||||
user_type='admin', |
user_type='admin', |
||||
is_active=True, |
is_active=True, |
||||
language=self.lang_fa |
|
||||
|
language=self.lang_ru |
||||
) |
) |
||||
|
|
||||
# Create Course |
# Create Course |
||||
@ -62,7 +62,7 @@ class CommunicationNotificationsFlowTests(TestCase): |
|||||
self.course = Course.objects.create( |
self.course = Course.objects.create( |
||||
title=[ |
title=[ |
||||
{"title": "Course 1", "language_code": "en"}, |
{"title": "Course 1", "language_code": "en"}, |
||||
{"title": "دوره ۱", "language_code": "fa"} |
|
||||
|
{"title": "Курс 1", "language_code": "ru"} |
||||
], |
], |
||||
slug=[{"title": "course-1", "language_code": "en"}], |
slug=[{"title": "course-1", "language_code": "en"}], |
||||
category=self.category, |
category=self.category, |
||||
@ -105,7 +105,7 @@ class CommunicationNotificationsFlowTests(TestCase): |
|||||
) |
) |
||||
|
|
||||
# Verify notification sent to the student |
# Verify notification sent to the student |
||||
notif = Notification.objects.filter(user=self.student, title="پیام جدید از طرف استاد").first() |
|
||||
|
notif = Notification.objects.filter(user=self.student, title="Новое сообщение от преподавателя").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("Hello from teacher", notif.message) |
self.assertIn("Hello from teacher", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
@ -129,7 +129,7 @@ class CommunicationNotificationsFlowTests(TestCase): |
|||||
) |
) |
||||
|
|
||||
# Verify notification sent to the student |
# Verify notification sent to the student |
||||
notif = Notification.objects.filter(user=self.student, title="پاسخ پشتیبانی").first() |
|
||||
|
notif = Notification.objects.filter(user=self.student, title="Новое сообщение от поддержки").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("How can I help you?", notif.message) |
self.assertIn("How can I help you?", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
@ -153,10 +153,10 @@ class CommunicationNotificationsFlowTests(TestCase): |
|||||
) |
) |
||||
|
|
||||
# Verify notification sent to the student enrolled |
# Verify notification sent to the student enrolled |
||||
notif = Notification.objects.filter(user=self.student, title="پیام استاد در گفتگوی دوره").first() |
|
||||
|
notif = Notification.objects.filter(user=self.student, title="Сообщение от преподавателя в чате курса").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("homework", notif.message) |
self.assertIn("homework", notif.message) |
||||
self.assertIn("دوره ۱", notif.message) |
|
||||
|
self.assertIn("Курс 1", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
|
|||||
@ -13,9 +13,9 @@ from apps.course.models.live_session import CourseLiveSession, LiveSessionRecord |
|||||
class LiveNotificationsFlowTests(TestCase): |
class LiveNotificationsFlowTests(TestCase): |
||||
def setUp(self): |
def setUp(self): |
||||
# Create languages |
# Create languages |
||||
self.lang_fa, _ = Language.objects.update_or_create( |
|
||||
code='fa', |
|
||||
defaults={'name': 'Persian', 'status': True, 'countries': []} |
|
||||
|
self.lang_ru, _ = Language.objects.update_or_create( |
||||
|
code='ru', |
||||
|
defaults={'name': 'Russian', 'status': True, 'countries': []} |
||||
) |
) |
||||
self.lang_en, _ = Language.objects.update_or_create( |
self.lang_en, _ = Language.objects.update_or_create( |
||||
code='en', |
code='en', |
||||
@ -33,7 +33,7 @@ class LiveNotificationsFlowTests(TestCase): |
|||||
email='[email protected]', |
email='[email protected]', |
||||
username='student_live', |
username='student_live', |
||||
fullname='Live Student', |
fullname='Live Student', |
||||
language=self.lang_fa, |
|
||||
|
language=self.lang_ru, |
||||
fcm='token_live_student' |
fcm='token_live_student' |
||||
) |
) |
||||
|
|
||||
@ -42,7 +42,7 @@ class LiveNotificationsFlowTests(TestCase): |
|||||
self.course = Course.objects.create( |
self.course = Course.objects.create( |
||||
title=[ |
title=[ |
||||
{"title": "Course 1", "language_code": "en"}, |
{"title": "Course 1", "language_code": "en"}, |
||||
{"title": "دوره ۱", "language_code": "fa"} |
|
||||
|
{"title": "Курс 1", "language_code": "ru"} |
||||
], |
], |
||||
slug=[{"title": "course-1", "language_code": "en"}], |
slug=[{"title": "course-1", "language_code": "en"}], |
||||
category=self.category, |
category=self.category, |
||||
@ -81,11 +81,11 @@ class LiveNotificationsFlowTests(TestCase): |
|||||
self.session.is_cancelled = True |
self.session.is_cancelled = True |
||||
self.session.save() |
self.session.save() |
||||
|
|
||||
# Check DB notification for Persian student |
|
||||
notif = Notification.objects.filter(user=self.student, title="کلاس زنده لغو شد").first() |
|
||||
|
# Check DB notification for Russian student |
||||
|
notif = Notification.objects.filter(user=self.student, title="Живой урок отменен").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("Lesson One Live", notif.message) |
self.assertIn("Lesson One Live", notif.message) |
||||
self.assertIn("دوره ۱", notif.message) |
|
||||
|
self.assertIn("Курс 1", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
@ -98,10 +98,10 @@ class LiveNotificationsFlowTests(TestCase): |
|||||
self.session.save() |
self.session.save() |
||||
|
|
||||
# Check DB notification |
# Check DB notification |
||||
notif = Notification.objects.filter(user=self.student, title="کلاس زنده تغییر زمان یافت").first() |
|
||||
|
notif = Notification.objects.filter(user=self.student, title="Время живого урока изменено").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("Lesson One Live", notif.message) |
self.assertIn("Lesson One Live", notif.message) |
||||
self.assertIn("دوره ۱", notif.message) |
|
||||
|
self.assertIn("Курс 1", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
@ -115,8 +115,8 @@ class LiveNotificationsFlowTests(TestCase): |
|||||
) |
) |
||||
|
|
||||
# Check DB notification |
# Check DB notification |
||||
notif = Notification.objects.filter(user=self.student, title="ضبط کلاس زنده در دسترس است").first() |
|
||||
|
notif = Notification.objects.filter(user=self.student, title="Доступна запись урока").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("Lesson One Live", notif.message) |
self.assertIn("Lesson One Live", notif.message) |
||||
self.assertIn("دوره ۱", notif.message) |
|
||||
|
self.assertIn("Курс 1", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
@ -16,9 +16,9 @@ from apps.account.tasks import check_live_class_reminders_task, check_new_course |
|||||
class NotificationFlowTests(TestCase): |
class NotificationFlowTests(TestCase): |
||||
def setUp(self): |
def setUp(self): |
||||
# Create languages |
# Create languages |
||||
self.lang_fa, _ = Language.objects.update_or_create( |
|
||||
code='fa', |
|
||||
defaults={'name': 'Persian', 'status': True, 'countries': []} |
|
||||
|
self.lang_ru, _ = Language.objects.update_or_create( |
||||
|
code='ru', |
||||
|
defaults={'name': 'Russian', 'status': True, 'countries': []} |
||||
) |
) |
||||
self.lang_en, _ = Language.objects.update_or_create( |
self.lang_en, _ = Language.objects.update_or_create( |
||||
code='en', |
code='en', |
||||
@ -36,7 +36,7 @@ class NotificationFlowTests(TestCase): |
|||||
email='[email protected]', |
email='[email protected]', |
||||
username='student_test', |
username='student_test', |
||||
fullname='Test Student', |
fullname='Test Student', |
||||
language=self.lang_fa, # Persian template check |
|
||||
|
language=self.lang_ru, # Russian template check |
||||
fcm='token_student' |
fcm='token_student' |
||||
) |
) |
||||
|
|
||||
@ -49,12 +49,12 @@ class NotificationFlowTests(TestCase): |
|||||
fcm='token_student_en' |
fcm='token_student_en' |
||||
) |
) |
||||
|
|
||||
def _create_course(self, slug, title_en, title_fa, status='ongoing'): |
|
||||
|
def _create_course(self, slug, title_en, title_ru, status='ongoing'): |
||||
thumbnail = SimpleUploadedFile('thumb.jpg', b'filecontent', content_type='image/jpeg') |
thumbnail = SimpleUploadedFile('thumb.jpg', b'filecontent', content_type='image/jpeg') |
||||
return Course.objects.create( |
return Course.objects.create( |
||||
title=[ |
title=[ |
||||
{"title": title_en, "language_code": "en"}, |
{"title": title_en, "language_code": "en"}, |
||||
{"title": title_fa, "language_code": "fa"} |
|
||||
|
{"title": title_ru, "language_code": "ru"} |
||||
], |
], |
||||
slug=[{"title": slug, "language_code": "en"}], |
slug=[{"title": slug, "language_code": "en"}], |
||||
category=self.category, |
category=self.category, |
||||
@ -77,19 +77,19 @@ class NotificationFlowTests(TestCase): |
|||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
def test_course_access_granted_notification(self, mock_send): |
def test_course_access_granted_notification(self, mock_send): |
||||
# Event 1: Course Access Granted |
# Event 1: Course Access Granted |
||||
course = self._create_course('course-access', 'Course 1', 'دوره ۱') |
|
||||
|
course = self._create_course('course-access', 'Course 1', 'Курс 1') |
||||
|
|
||||
# Create participant (active=True by default) |
# Create participant (active=True by default) |
||||
Participant.objects.create(student=self.student, course=course) |
Participant.objects.create(student=self.student, course=course) |
||||
|
|
||||
# Verify notification created in DB (in Persian) |
|
||||
notif_fa = Notification.objects.filter(user=self.student).first() |
|
||||
self.assertIsNotNone(notif_fa) |
|
||||
self.assertEqual(notif_fa.title, "دسترسی به دوره فعال شد") |
|
||||
self.assertIn("دوره ۱", notif_fa.message) |
|
||||
self.assertEqual(notif_fa.notification_type, "course_access_granted") |
|
||||
self.assertEqual(notif_fa.action, "navigate") |
|
||||
self.assertEqual(notif_fa.navigate_to, "/course_info?slug=course-access") |
|
||||
|
# Verify notification created in DB (in Russian) |
||||
|
notif_ru = Notification.objects.filter(user=self.student).first() |
||||
|
self.assertIsNotNone(notif_ru) |
||||
|
self.assertEqual(notif_ru.title, "Доступ к курсу активирован") |
||||
|
self.assertIn("Курс 1", notif_ru.message) |
||||
|
self.assertEqual(notif_ru.notification_type, "course_access_granted") |
||||
|
self.assertEqual(notif_ru.action, "navigate") |
||||
|
self.assertEqual(notif_ru.navigate_to, "/course_info?slug=course-access") |
||||
|
|
||||
# Create participant for English student |
# Create participant for English student |
||||
Participant.objects.create(student=self.student_en, course=course) |
Participant.objects.create(student=self.student_en, course=course) |
||||
@ -113,7 +113,7 @@ class NotificationFlowTests(TestCase): |
|||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
def test_live_class_reminder_notification(self, mock_send): |
def test_live_class_reminder_notification(self, mock_send): |
||||
# Event 2: LIVE Class Reminder |
# Event 2: LIVE Class Reminder |
||||
course = self._create_course('course-live', 'Course 2', 'دوره ۲') |
|
||||
|
course = self._create_course('course-live', 'Course 2', 'Курс 2') |
||||
Participant.objects.create(student=self.student, course=course) |
Participant.objects.create(student=self.student, course=course) |
||||
|
|
||||
# Create a live session starting in 2 hours |
# Create a live session starting in 2 hours |
||||
@ -132,9 +132,9 @@ class NotificationFlowTests(TestCase): |
|||||
session.refresh_from_db() |
session.refresh_from_db() |
||||
self.assertTrue(session.reminder_sent) |
self.assertTrue(session.reminder_sent) |
||||
|
|
||||
notif = Notification.objects.filter(user=self.student, title="یادآوری کلاس زنده").first() |
|
||||
|
notif = Notification.objects.filter(user=self.student, title="Напоминание о живом уроке").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("دوره ۲", notif.message) |
|
||||
|
self.assertIn("Live Lesson 1", notif.message) |
||||
|
|
||||
# Test rescheduling resets reminder_sent |
# Test rescheduling resets reminder_sent |
||||
session.started_at = timezone.now() + datetime.timedelta(hours=5) |
session.started_at = timezone.now() + datetime.timedelta(hours=5) |
||||
@ -146,7 +146,7 @@ class NotificationFlowTests(TestCase): |
|||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
def test_course_completed_notification(self, mock_send): |
def test_course_completed_notification(self, mock_send): |
||||
# Event 3: Course Completed |
# Event 3: Course Completed |
||||
course = self._create_course('course-complete', 'Course 3', 'دوره ۳') |
|
||||
|
course = self._create_course('course-complete', 'Course 3', 'Курс 3') |
||||
Participant.objects.create(student=self.student, course=course) |
Participant.objects.create(student=self.student, course=course) |
||||
|
|
||||
chapter = CourseChapter.objects.create( |
chapter = CourseChapter.objects.create( |
||||
@ -165,18 +165,18 @@ class NotificationFlowTests(TestCase): |
|||||
|
|
||||
# Complete first lesson |
# Complete first lesson |
||||
LessonCompletion.objects.create(student=self.student, course_lesson=cl1) |
LessonCompletion.objects.create(student=self.student, course_lesson=cl1) |
||||
self.assertFalse(Notification.objects.filter(user=self.student, title="دوره به پایان رسید").exists()) |
|
||||
|
self.assertFalse(Notification.objects.filter(user=self.student, title="Курс завершен").exists()) |
||||
|
|
||||
# Complete second (last) lesson |
# Complete second (last) lesson |
||||
LessonCompletion.objects.create(student=self.student, course_lesson=cl2) |
LessonCompletion.objects.create(student=self.student, course_lesson=cl2) |
||||
|
|
||||
# Verify notification triggered |
# Verify notification triggered |
||||
self.assertTrue(Notification.objects.filter(user=self.student, title="دوره به پایان رسید").exists()) |
|
||||
|
self.assertTrue(Notification.objects.filter(user=self.student, title="Курс завершен").exists()) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
def test_certificate_issued_notification(self, mock_send): |
def test_certificate_issued_notification(self, mock_send): |
||||
# Event 4: Certificate Issued |
# Event 4: Certificate Issued |
||||
course = self._create_course('course-cert', 'Course 4', 'دوره ۴') |
|
||||
|
course = self._create_course('course-cert', 'Course 4', 'Курс 4') |
||||
|
|
||||
cert = Certificate.objects.create( |
cert = Certificate.objects.create( |
||||
student=self.student, |
student=self.student, |
||||
@ -185,14 +185,14 @@ class NotificationFlowTests(TestCase): |
|||||
) |
) |
||||
|
|
||||
# Verify no notification yet |
# Verify no notification yet |
||||
self.assertFalse(Notification.objects.filter(user=self.student, title="گواهی صادر شد").exists()) |
|
||||
|
self.assertFalse(Notification.objects.filter(user=self.student, title="Сертификат выдан").exists()) |
||||
|
|
||||
# Approve certificate |
# Approve certificate |
||||
cert.status = 'approved' |
cert.status = 'approved' |
||||
cert.save() |
cert.save() |
||||
|
|
||||
# Verify notification triggered |
# Verify notification triggered |
||||
self.assertTrue(Notification.objects.filter(user=self.student, title="گواهی صادر شد").exists()) |
|
||||
|
self.assertTrue(Notification.objects.filter(user=self.student, title="Сертификат выдан").exists()) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
def test_new_course_registration_notification(self, mock_send): |
def test_new_course_registration_notification(self, mock_send): |
||||
@ -203,20 +203,20 @@ class NotificationFlowTests(TestCase): |
|||||
fullname='Recipient Student', |
fullname='Recipient Student', |
||||
user_type='student', |
user_type='student', |
||||
is_active=True, |
is_active=True, |
||||
language=self.lang_fa, |
|
||||
|
language=self.lang_ru, |
||||
fcm='token_recipient' |
fcm='token_recipient' |
||||
) |
) |
||||
|
|
||||
course = self._create_course('course-new', 'New Course A', 'دوره جدید الف', status='registering') |
|
||||
|
course = self._create_course('course-new', 'New Course A', 'Новый курс А', status='registering') |
||||
|
|
||||
check_new_course_registration_task() |
check_new_course_registration_task() |
||||
|
|
||||
course.refresh_from_db() |
course.refresh_from_db() |
||||
self.assertTrue(course.notified_new_registration) |
self.assertTrue(course.notified_new_registration) |
||||
|
|
||||
notif = Notification.objects.filter(user=student_recipient, title="ثبتنام دوره جدید").first() |
|
||||
|
notif = Notification.objects.filter(user=student_recipient, title="Добавлен новый курс").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("دوره جدید الف", notif.message) |
|
||||
|
self.assertIn("Новый курс А", notif.message) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
def test_notification_template_customization_and_deactivation(self, mock_send): |
def test_notification_template_customization_and_deactivation(self, mock_send): |
||||
@ -225,14 +225,14 @@ class NotificationFlowTests(TestCase): |
|||||
template = NotificationTemplate.objects.create( |
template = NotificationTemplate.objects.create( |
||||
notification_type="custom_test_type", |
notification_type="custom_test_type", |
||||
name="Test Template", |
name="Test Template", |
||||
title_fa="سلام {student_name} به دوره {course_title}", |
|
||||
|
title_ru="Привет {student_name} к курсу {course_title}", |
||||
title_en="Hello {student_name} to course {course_title}", |
title_en="Hello {student_name} to course {course_title}", |
||||
body_fa="توضیحات فارسی {student_name}", |
|
||||
|
body_ru="Русское описание {student_name}", |
||||
body_en="English description {student_name}", |
body_en="English description {student_name}", |
||||
is_active=True |
is_active=True |
||||
) |
) |
||||
|
|
||||
course = self._create_course('test-tpl-course', 'Tpl Course', 'دوره تیپیال') |
|
||||
|
course = self._create_course('test-tpl-course', 'Tpl Course', 'Курс Шаблон') |
||||
|
|
||||
# 2. Trigger notification and verify custom text formatting |
# 2. Trigger notification and verify custom text formatting |
||||
from apps.account.notification_service import create_and_send_notification |
from apps.account.notification_service import create_and_send_notification |
||||
@ -240,8 +240,8 @@ class NotificationFlowTests(TestCase): |
|||||
user=self.student, |
user=self.student, |
||||
title_en="Default Title EN", |
title_en="Default Title EN", |
||||
body_en="Default Body EN", |
body_en="Default Body EN", |
||||
title_fa="Default Title FA", |
|
||||
body_fa="Default Body FA", |
|
||||
|
title_ru="Default Title RU", |
||||
|
body_ru="Default Body RU", |
||||
service='imam-javad', |
service='imam-javad', |
||||
data={'type': 'custom_test_type', 'course_id': course.id} |
data={'type': 'custom_test_type', 'course_id': course.id} |
||||
) |
) |
||||
@ -249,8 +249,8 @@ class NotificationFlowTests(TestCase): |
|||||
notif = Notification.objects.filter(user=self.student).order_by('-id').first() |
notif = Notification.objects.filter(user=self.student).order_by('-id').first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
# Verify it loaded from template and formatted using course name & student name |
# Verify it loaded from template and formatted using course name & student name |
||||
self.assertEqual(notif.title, f"سلام {self.student.fullname} به دوره دوره تیپیال") |
|
||||
self.assertEqual(notif.message, f"توضیحات فارسی {self.student.fullname}") |
|
||||
|
self.assertEqual(notif.title, f"Привет {self.student.fullname} к курсу Курс Шаблон") |
||||
|
self.assertEqual(notif.message, f"Русское описание {self.student.fullname}") |
||||
|
|
||||
# 3. Disable template and verify notification is discarded |
# 3. Disable template and verify notification is discarded |
||||
template.is_active = False |
template.is_active = False |
||||
@ -261,8 +261,8 @@ class NotificationFlowTests(TestCase): |
|||||
user=self.student, |
user=self.student, |
||||
title_en="Default Title EN", |
title_en="Default Title EN", |
||||
body_en="Default Body EN", |
body_en="Default Body EN", |
||||
title_fa="Default Title FA", |
|
||||
body_fa="Default Body FA", |
|
||||
|
title_ru="Default Title RU", |
||||
|
body_ru="Default Body RU", |
||||
service='imam-javad', |
service='imam-javad', |
||||
data={'type': 'custom_test_type', 'course_id': course.id} |
data={'type': 'custom_test_type', 'course_id': course.id} |
||||
) |
) |
||||
@ -277,9 +277,9 @@ class NotificationFlowTests(TestCase): |
|||||
template = NotificationTemplate.objects.create( |
template = NotificationTemplate.objects.create( |
||||
notification_type="sched_test", |
notification_type="sched_test", |
||||
name="Scheduled Test", |
name="Scheduled Test", |
||||
title_fa="تست زمانبندی", |
|
||||
|
title_ru="Тест планирования", |
||||
title_en="Scheduled Test", |
title_en="Scheduled Test", |
||||
body_fa="تست", |
|
||||
|
body_ru="Тест", |
||||
body_en="Test" |
body_en="Test" |
||||
) |
) |
||||
|
|
||||
|
|||||
@ -13,9 +13,9 @@ from apps.account.tasks import check_low_quiz_results_task |
|||||
class QuizNotificationFlowTests(TestCase): |
class QuizNotificationFlowTests(TestCase): |
||||
def setUp(self): |
def setUp(self): |
||||
# Create languages |
# Create languages |
||||
self.lang_fa, _ = Language.objects.update_or_create( |
|
||||
code='fa', |
|
||||
defaults={'name': 'Persian', 'status': True, 'countries': []} |
|
||||
|
self.lang_ru, _ = Language.objects.update_or_create( |
||||
|
code='ru', |
||||
|
defaults={'name': 'Russian', 'status': True, 'countries': []} |
||||
) |
) |
||||
self.lang_en, _ = Language.objects.update_or_create( |
self.lang_en, _ = Language.objects.update_or_create( |
||||
code='en', |
code='en', |
||||
@ -33,7 +33,7 @@ class QuizNotificationFlowTests(TestCase): |
|||||
email='[email protected]', |
email='[email protected]', |
||||
username='student_quiz', |
username='student_quiz', |
||||
fullname='Quiz Student', |
fullname='Quiz Student', |
||||
language=self.lang_fa, |
|
||||
|
language=self.lang_ru, |
||||
fcm='token_quiz_student' |
fcm='token_quiz_student' |
||||
) |
) |
||||
|
|
||||
@ -42,7 +42,7 @@ class QuizNotificationFlowTests(TestCase): |
|||||
self.course = Course.objects.create( |
self.course = Course.objects.create( |
||||
title=[ |
title=[ |
||||
{"title": "Course 1", "language_code": "en"}, |
{"title": "Course 1", "language_code": "en"}, |
||||
{"title": "دوره ۱", "language_code": "fa"} |
|
||||
|
{"title": "Курс 1", "language_code": "ru"} |
||||
], |
], |
||||
slug=[{"title": "course-1", "language_code": "en"}], |
slug=[{"title": "course-1", "language_code": "en"}], |
||||
category=self.category, |
category=self.category, |
||||
@ -64,7 +64,7 @@ class QuizNotificationFlowTests(TestCase): |
|||||
course=self.course, |
course=self.course, |
||||
title=[ |
title=[ |
||||
{"title": "Quiz A", "language_code": "en"}, |
{"title": "Quiz A", "language_code": "en"}, |
||||
{"title": "آزمون الف", "language_code": "fa"} |
|
||||
|
{"title": "Тест А", "language_code": "ru"} |
||||
], |
], |
||||
each_question_timing=60, |
each_question_timing=60, |
||||
status=True |
status=True |
||||
@ -88,10 +88,10 @@ class QuizNotificationFlowTests(TestCase): |
|||||
# Run periodic task |
# Run periodic task |
||||
check_low_quiz_results_task() |
check_low_quiz_results_task() |
||||
|
|
||||
# Verify reminder sent to the student (Persian template check) |
|
||||
notif = Notification.objects.filter(user=self.student, title="پیشنهاد شرکت مجدد در آزمون").first() |
|
||||
|
# Verify reminder sent to the student (Russian template check) |
||||
|
notif = Notification.objects.filter(user=self.student, title="Предложение пересдать тест").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("آزمون الف", notif.message) |
|
||||
|
self.assertIn("Тест А", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
@ -110,7 +110,7 @@ class QuizNotificationFlowTests(TestCase): |
|||||
|
|
||||
check_low_quiz_results_task() |
check_low_quiz_results_task() |
||||
|
|
||||
self.assertFalse(Notification.objects.filter(user=self.student, title="پیشنهاد شرکت مجدد در آزمون").exists()) |
|
||||
|
self.assertFalse(Notification.objects.filter(user=self.student, title="Предложение пересдать тест").exists()) |
||||
self.assertFalse(mock_send.called) |
self.assertFalse(mock_send.called) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
@ -142,7 +142,7 @@ class QuizNotificationFlowTests(TestCase): |
|||||
check_low_quiz_results_task() |
check_low_quiz_results_task() |
||||
|
|
||||
# Should not suggest retake since they passed subsequently |
# Should not suggest retake since they passed subsequently |
||||
self.assertFalse(Notification.objects.filter(user=self.student, title="پیشنهاد شرکت مجدد در آزمون").exists()) |
|
||||
|
self.assertFalse(Notification.objects.filter(user=self.student, title="Предложение пересдать тест").exists()) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
def test_no_reminder_if_already_retaken_even_if_failed(self, mock_send): |
def test_no_reminder_if_already_retaken_even_if_failed(self, mock_send): |
||||
@ -173,4 +173,4 @@ class QuizNotificationFlowTests(TestCase): |
|||||
|
|
||||
check_low_quiz_results_task() |
check_low_quiz_results_task() |
||||
|
|
||||
self.assertFalse(Notification.objects.filter(user=self.student, title="پیشنهاد شرکت مجدد در آزمون").exists()) |
|
||||
|
self.assertFalse(Notification.objects.filter(user=self.student, title="Предложение пересдать тест").exists()) |
||||
@ -15,9 +15,9 @@ from apps.account.tasks import check_inactive_students_task |
|||||
class RetentionNotificationsFlowTests(TestCase): |
class RetentionNotificationsFlowTests(TestCase): |
||||
def setUp(self): |
def setUp(self): |
||||
# Create languages |
# Create languages |
||||
self.lang_fa, _ = Language.objects.update_or_create( |
|
||||
code='fa', |
|
||||
defaults={'name': 'Persian', 'status': True, 'countries': []} |
|
||||
|
self.lang_ru, _ = Language.objects.update_or_create( |
||||
|
code='ru', |
||||
|
defaults={'name': 'Russian', 'status': True, 'countries': []} |
||||
) |
) |
||||
self.lang_en, _ = Language.objects.update_or_create( |
self.lang_en, _ = Language.objects.update_or_create( |
||||
code='en', |
code='en', |
||||
@ -35,7 +35,7 @@ class RetentionNotificationsFlowTests(TestCase): |
|||||
email='[email protected]', |
email='[email protected]', |
||||
username='student_ret', |
username='student_ret', |
||||
fullname='Ret Student', |
fullname='Ret Student', |
||||
language=self.lang_fa, |
|
||||
|
language=self.lang_ru, |
||||
fcm='token_ret_student' |
fcm='token_ret_student' |
||||
) |
) |
||||
|
|
||||
@ -44,7 +44,7 @@ class RetentionNotificationsFlowTests(TestCase): |
|||||
self.course = Course.objects.create( |
self.course = Course.objects.create( |
||||
title=[ |
title=[ |
||||
{"title": "Course 1", "language_code": "en"}, |
{"title": "Course 1", "language_code": "en"}, |
||||
{"title": "دوره ۱", "language_code": "fa"} |
|
||||
|
{"title": "Курс 1", "language_code": "ru"} |
||||
], |
], |
||||
slug=[{"title": "course-1", "language_code": "en"}], |
slug=[{"title": "course-1", "language_code": "en"}], |
||||
category=self.category, |
category=self.category, |
||||
@ -80,7 +80,7 @@ class RetentionNotificationsFlowTests(TestCase): |
|||||
check_inactive_students_task() |
check_inactive_students_task() |
||||
|
|
||||
# Check DB notification |
# Check DB notification |
||||
notif = Notification.objects.filter(user=self.student, title="دلمان برایتان تنگ شده!").first() |
|
||||
|
notif = Notification.objects.filter(user=self.student, title="Мы скучаем по вам!").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
|
|
||||
@ -93,7 +93,7 @@ class RetentionNotificationsFlowTests(TestCase): |
|||||
|
|
||||
check_inactive_students_task() |
check_inactive_students_task() |
||||
|
|
||||
self.assertFalse(Notification.objects.filter(user=self.student, title="دلمان برایتان تنگ شده!").exists()) |
|
||||
|
self.assertFalse(Notification.objects.filter(user=self.student, title="Мы скучаем по вам!").exists()) |
||||
self.assertFalse(mock_send.called) |
self.assertFalse(mock_send.called) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
@ -117,7 +117,7 @@ class RetentionNotificationsFlowTests(TestCase): |
|||||
|
|
||||
check_inactive_students_task() |
check_inactive_students_task() |
||||
|
|
||||
self.assertFalse(Notification.objects.filter(user=self.student, title="دلمان برایتان تنگ شده!").exists()) |
|
||||
|
self.assertFalse(Notification.objects.filter(user=self.student, title="Мы скучаем по вам!").exists()) |
||||
self.assertFalse(mock_send.called) |
self.assertFalse(mock_send.called) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
@ -148,7 +148,7 @@ class RetentionNotificationsFlowTests(TestCase): |
|||||
s2.save() |
s2.save() |
||||
|
|
||||
# Check DB notification |
# Check DB notification |
||||
notif = Notification.objects.filter(user=self.student, title="جای شما در کلاس زنده خالی بود!").first() |
|
||||
|
notif = Notification.objects.filter(user=self.student, title="Пропуск живых уроков").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("دوره ۱", notif.message) |
|
||||
|
self.assertIn("Курс 1", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
@ -12,9 +12,9 @@ from apps.transaction.models import TransactionParticipant |
|||||
class TransactionNotificationsFlowTests(TestCase): |
class TransactionNotificationsFlowTests(TestCase): |
||||
def setUp(self): |
def setUp(self): |
||||
# Create languages |
# Create languages |
||||
self.lang_fa, _ = Language.objects.update_or_create( |
|
||||
code='fa', |
|
||||
defaults={'name': 'Persian', 'status': True, 'countries': []} |
|
||||
|
self.lang_ru, _ = Language.objects.update_or_create( |
||||
|
code='ru', |
||||
|
defaults={'name': 'Russian', 'status': True, 'countries': []} |
||||
) |
) |
||||
self.lang_en, _ = Language.objects.update_or_create( |
self.lang_en, _ = Language.objects.update_or_create( |
||||
code='en', |
code='en', |
||||
@ -32,7 +32,7 @@ class TransactionNotificationsFlowTests(TestCase): |
|||||
email='[email protected]', |
email='[email protected]', |
||||
username='student_tx', |
username='student_tx', |
||||
fullname='Tx Student', |
fullname='Tx Student', |
||||
language=self.lang_fa, |
|
||||
|
language=self.lang_ru, |
||||
fcm='token_tx_student' |
fcm='token_tx_student' |
||||
) |
) |
||||
|
|
||||
@ -41,7 +41,7 @@ class TransactionNotificationsFlowTests(TestCase): |
|||||
self.course = Course.objects.create( |
self.course = Course.objects.create( |
||||
title=[ |
title=[ |
||||
{"title": "Course 1", "language_code": "en"}, |
{"title": "Course 1", "language_code": "en"}, |
||||
{"title": "دوره ۱", "language_code": "fa"} |
|
||||
|
{"title": "Курс 1", "language_code": "ru"} |
||||
], |
], |
||||
slug=[{"title": "course-1", "language_code": "en"}], |
slug=[{"title": "course-1", "language_code": "en"}], |
||||
category=self.category, |
category=self.category, |
||||
@ -72,10 +72,10 @@ class TransactionNotificationsFlowTests(TestCase): |
|||||
self.tx.status = TransactionParticipant.TransactionStatus.SUCCESS |
self.tx.status = TransactionParticipant.TransactionStatus.SUCCESS |
||||
self.tx.save() |
self.tx.save() |
||||
|
|
||||
# Check DB notification (in Persian) |
|
||||
notif = Notification.objects.filter(user=self.student, title="پرداخت موفقیتآمیز").first() |
|
||||
|
# Check DB notification (in Russian) |
||||
|
notif = Notification.objects.filter(user=self.student, title="Оплата успешна").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("دوره ۱", notif.message) |
|
||||
|
self.assertIn("Курс 1", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
@ -84,10 +84,10 @@ class TransactionNotificationsFlowTests(TestCase): |
|||||
self.tx.status = TransactionParticipant.TransactionStatus.FAILED |
self.tx.status = TransactionParticipant.TransactionStatus.FAILED |
||||
self.tx.save() |
self.tx.save() |
||||
|
|
||||
# Check DB notification (in Persian) |
|
||||
notif = Notification.objects.filter(user=self.student, title="خطا در پرداخت").first() |
|
||||
|
# Check DB notification (in Russian) |
||||
|
notif = Notification.objects.filter(user=self.student, title="Ошибка оплаты").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("دوره ۱", notif.message) |
|
||||
|
self.assertIn("Курс 1", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
|
|
||||
@patch('apps.account.notification_service.send_notification') |
@patch('apps.account.notification_service.send_notification') |
||||
@ -96,8 +96,8 @@ class TransactionNotificationsFlowTests(TestCase): |
|||||
self.tx.status = TransactionParticipant.TransactionStatus.REFUNDED |
self.tx.status = TransactionParticipant.TransactionStatus.REFUNDED |
||||
self.tx.save() |
self.tx.save() |
||||
|
|
||||
# Check DB notification (in Persian) |
|
||||
notif = Notification.objects.filter(user=self.student, title="بازگشت وجه انجام شد").first() |
|
||||
|
# Check DB notification (in Russian) |
||||
|
notif = Notification.objects.filter(user=self.student, title="Возврат средств выполнен").first() |
||||
self.assertIsNotNone(notif) |
self.assertIsNotNone(notif) |
||||
self.assertIn("دوره ۱", notif.message) |
|
||||
|
self.assertIn("Курс 1", notif.message) |
||||
self.assertTrue(mock_send.called) |
self.assertTrue(mock_send.called) |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue