Browse Source

test endpoint added for better testing

master
Mohsen Taba 1 week ago
parent
commit
e794c4bc0e
  1. 21
      apps/account/notification_service.py
  2. 1
      apps/account/urls.py
  3. 138
      apps/account/views/notification.py

21
apps/account/notification_service.py

@ -1,12 +1,17 @@
import asyncio
import logging
import string
from apps.account.models import Notification, NotificationTemplate
logger = logging.getLogger(__name__)
class SafeDict(dict):
def __missing__(self, key):
return f"{{{key}}}"
class SafeFormatter(string.Formatter):
def get_value(self, key, args, kwargs):
if isinstance(key, str):
if key not in kwargs:
return f"{{{key}}}"
return kwargs[key]
return super().get_value(key, args, kwargs)
def get_template_context(user, notification_type, data):
"""
@ -198,13 +203,13 @@ def create_and_send_notification(user, title_en, body_en, title_fa=None, body_fa
# 2. Render templates safely with dynamic context
context = get_template_context(user, notification_type, data)
safe_ctx = SafeDict(context)
formatter = SafeFormatter()
try:
title_ru = title_ru.format(**safe_ctx) if title_ru else ""
title_en = title_en.format(**safe_ctx) if title_en else ""
body_ru = body_ru.format(**safe_ctx) if body_ru else ""
body_en = body_en.format(**safe_ctx) if body_en else ""
title_ru = formatter.format(title_ru, **context) if title_ru else ""
title_en = formatter.format(title_en, **context) if title_en else ""
body_ru = formatter.format(body_ru, **context) if body_ru else ""
body_en = formatter.format(body_en, **context) if body_en else ""
except Exception as e:
logger.error(f"Error formatting templates: {e}")

1
apps/account/urls.py

@ -46,6 +46,7 @@ urlpatterns = [
path('notif/', views.NotificationListView.as_view(), name='user-notif'),
path('notif/read', views.NotificationReadAllView.as_view(), name='user-notif-read-all'),
path('notif/send/', views.SendNotificationView.as_view(), name='user-send-notif'),
path('notifications/test/', views.TestNotificationAPIView.as_view(), name='test-notifications'),
# # URL to update user details, supports PUT to update user fields like phone or email given a token.
path('profile/update/', views.UserUpdateView.as_view(), name='user-update'),

138
apps/account/views/notification.py

@ -242,3 +242,141 @@ class AdminNotificationViewSet(ModelViewSet):
serializer = self.get_serializer(notif)
return Response(serializer.data, status=status.HTTP_201_CREATED)
class TestNotificationAPIView(generics.GenericAPIView):
permission_classes = []
authentication_classes = []
@swagger_auto_schema(
operation_description="Send all test notifications to a user by their email.",
tags=['Notifications'],
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
required=['email'],
properties={
'email': openapi.Schema(type=openapi.TYPE_STRING, description='Email of the user to send test notifications to'),
},
),
responses={
200: openapi.Response('All test notifications processed successfully.'),
400: openapi.Response('Email parameter missing.'),
404: openapi.Response('User not found.'),
}
)
def post(self, request, *args, **kwargs):
email = request.data.get('email')
if not email:
return Response({'error': 'Email parameter is required.'}, status=status.HTTP_400_BAD_REQUEST)
from apps.account.models import User
user = User.objects.filter(email=email).first()
if not user:
return Response({'error': f"User with email '{email}' not found."}, status=status.HTTP_404_NOT_FOUND)
from apps.account.notification_service import create_and_send_notification
notifications_to_send = [
{
"name": "1. Course Registered",
"title_en": "Course Registration Successful",
"body_en": "You have successfully registered for the course 'Quranic Studies'.",
"title_ru": "Успешная регистрация на курс",
"body_ru": "Вы успешно зарегистрировались на курс «مطالعات قرآنی».",
"data": {"type": "course_registered", "course_id": "1"}
},
{
"name": "2. Course Access Granted",
"title_en": "Course Access Granted",
"body_en": "Your access to the course 'Quranic Studies' has been activated.",
"title_ru": "Доступ к курсу активирован",
"body_ru": "Ваш доступ к курсу «مطالعات قرآنی» успешно активирован.",
"data": {"type": "course_access_granted", "course_id": "1"}
},
{
"name": "3. Lesson Completed",
"title_en": "Lesson Completed",
"body_en": "Congratulations! You completed the lesson 'Introduction to Surah Al-Fatiha'.",
"title_ru": "Урок завершен",
"body_ru": "Поздравляем! Вы завершили изучение урока «آشنایی با سوره فاتحه».",
"data": {"type": "lesson_completed", "course_id": "1", "lesson_id": "1"}
},
{
"name": "4. Course Completed",
"title_en": "Course Completed",
"body_en": "Well done! You have completed the course 'Quranic Studies'.",
"title_ru": "Курс завершен",
"body_ru": "Отличная работа! Вы успешно завершили курс «مطالعات قرآنی».",
"data": {"type": "course_completed", "course_id": "1"}
},
{
"name": "5. Low Quiz Score Suggestion",
"title_en": "Quiz Retake Suggestion",
"body_en": "You scored below the passing threshold on quiz 'Final Exam'. We suggest taking it again.",
"title_ru": "Предложение пересдать тест",
"body_ru": "Вы набрали балл ниже проходного в тесте «امتحان نهایی». Рекомендуем пройти его повторно.",
"data": {"type": "low_quiz_result", "quiz_id": "1"}
},
{
"name": "6. Payment Successful",
"title_en": "Payment Successful",
"body_en": "Your payment for course 'Quranic Studies' was successful.",
"title_ru": "Оплата успешна",
"body_ru": "Ваша оплата за курс «مطالعات قرآنی» успешно проведена.",
"data": {"type": "payment_successful", "course_id": "1"}
},
{
"name": "7. Payment Failed",
"title_en": "Payment Failed",
"body_en": "We encountered an issue processing your payment for 'Quranic Studies'.",
"title_ru": "Ошибка оплаты",
"body_ru": "Произошла ошибка при обработке вашей оплаты за курс «مطالعات قرآنی».",
"data": {"type": "payment_failed", "course_id": "1"}
},
{
"name": "8. Refund Completed",
"title_en": "Refund Completed",
"body_en": "A refund has been successfully completed for the course 'Quranic Studies'.",
"title_ru": "Возврат средств выполнен",
"body_ru": "Возврат средств за курс «مطالعات قرآنی» успешно завершен.",
"data": {"type": "refund_completed", "course_id": "1"}
},
{
"name": "9. Student Inactivity",
"title_en": "We Miss You!",
"body_en": "You haven't taken any lessons in the last week. Come back and continue your learning journey!",
"title_ru": "Мы скучаем по вам!",
"body_ru": "Вы не изучали уроки за последнюю неделю. Ждем вас для продолжения обучения!",
"data": {"type": "student_inactivity"}
}
]
results = []
for item in notifications_to_send:
try:
notif = create_and_send_notification(
user=user,
title_en=item['title_en'],
body_en=item['body_en'],
title_ru=item['title_ru'],
body_ru=item['body_ru'],
service='imam-javad',
data=item['data']
)
results.append({
'name': item['name'],
'status': 'sent' if notif else 'disabled',
'notification_id': notif.id if notif else None
})
except Exception as e:
results.append({
'name': item['name'],
'status': 'failed',
'error': str(e)
})
return Response({
'message': 'All test notifications processed successfully.',
'results': results,
'fcm_token_registered': bool(user.fcm)
}, status=status.HTTP_200_OK)
Loading…
Cancel
Save