subscription alert

This commit is contained in:
rizwanisready
2024-05-07 22:26:13 +05:30
parent 4987862dfc
commit 34203e5fd5
8 changed files with 289 additions and 4 deletions

View File

@@ -5,6 +5,7 @@ from datetime import timedelta
from django.utils import timezone
from onesignal_sdk.client import Client as OneSignalClient
from accounts.models import IAmPrincipal, IAmPrincipalOtp, IAmPrincipalType
from manage_notifications.models import InAppNotification, NotificationCategoryChoices
from manage_referrals.models import (
GoodTimeCoins,
ReferralRecord,
@@ -40,6 +41,14 @@ class NotificationService:
response = self.client.send_notification(notification_payload)
return response
def save_notification(self, principal, title, message, notification_category):
InAppNotification.objects.create(
principal=principal,
title=title,
message=message,
notification_category=notification_category,
)
def payment_success_notification(
self, principal, subscription, principal_subscription, amount
):
@@ -48,18 +57,21 @@ class NotificationService:
end_date = principal_subscription.end_date
message = f"Your payment for {subscription} of ${amount} was successfully processed. Your subscription is valid till {end_date}"
self.send_notification(title, message, principal.player_id)
self.save_notification(principal, title, message, NotificationCategoryChoices.TRANSACTION)
def referral_received_notification(self, principal, amount, email):
print("referral_received_notification: ", principal.player_id)
title = "Congratulations! You got a referral G-Token."
message = f"Your referral {email} has subscribed to GoodTimesApp. You have received {amount} (£)"
self.send_notification(title, message, principal.player_id)
self.save_notification(principal, title, message, NotificationCategoryChoices.REFERRAL)
def payment_failed_notification(self, principal, subscription, amount):
print("payment_failed_notification: ", principal.player_id)
title = "Payment Failed!"
message = f"Your payment for {subscription} of ${amount} was failed."
self.send_notification(title, message, principal.player_id)
self.save_notification(principal, title, message, NotificationCategoryChoices.TRANSACTION)
class WebhookService:
@@ -257,7 +269,10 @@ class PaymentProcessingService:
referral_service.credit_referral_reward_if_applicable()
print("Third Part Done....!!!!!")
self.notification_service.payment_success_notification(
self.principal, self.subscription, self.principal_subscription, self.transaction.amount
self.principal,
self.subscription,
self.principal_subscription,
self.transaction.amount,
)
def handle_failure(self):

View File

@@ -0,0 +1,66 @@
from goodtimes.utils import ApiResponse
from rest_framework.views import APIView
from rest_framework import status
from django.utils import timezone
from django.conf import settings
from datetime import timedelta
from onesignal_sdk.client import Client as OneSignalClient
from manage_notifications.models import (
IAmPrincipalNotificationSettings,
InAppNotification,
NotificationCategoryChoices,
)
from manage_subscriptions.models import SubscriptionStatus
class OneWeekSubscriptionAlertView(APIView):
authentication_classes = []
permission_classes = []
def post(self, request, *args, **kwargs):
self.client = OneSignalClient(
app_id=settings.ONE_SIGNAL_APP_ID, rest_api_key=settings.ONE_SIGNAL_API_KEY
)
eligible_principals = self.eligible_principals()
for principal in eligible_principals:
notification_title = "Subscription Expiry Reminder"
notification_message = "Your subscription is going to expire in a week."
notification_category = NotificationCategoryChoices.SUBSCRIPTION
# Send notification to principal
notification_payload = {
"headings": {"en": notification_title},
"contents": {"en": notification_message},
"include_player_ids": [principal.player_id],
}
response = self.client.send_notification(notification_payload)
# Save notification to InAppNotification table
in_app_notification = InAppNotification(
principal=principal,
title=notification_title,
message=notification_message,
notification_category=notification_category,
)
in_app_notification.save()
return ApiResponse.success(
message="Notifications sent successfully",
data="Notifications sent successfully",
status=status.HTTP_200_OK,
)
def eligible_principals(self):
one_week_from_now = timezone.now().date() + timedelta(days=7)
eligible_principals = IAmPrincipalNotificationSettings.objects.filter(
principal__principalsubscription__end_date=one_week_from_now,
principal__principalsubscription__status=SubscriptionStatus.ACTIVE,
principal__principalsubscription__cancelled=False,
principal__principalsubscription__deleted=False,
notification_category=NotificationCategoryChoices.SUBSCRIPTION,
is_enabled=True,
).select_related("principal")
return eligible_principals

View File

@@ -1,5 +1,9 @@
from rest_framework import serializers
from manage_notifications.models import IAmPrincipalNotificationSettings, NotificationCategoryChoices
from manage_notifications.models import (
IAmPrincipalNotificationSettings,
InAppNotification,
NotificationCategoryChoices,
)
class IAmPrincipalNotificationSettingsSerializer(serializers.ModelSerializer):
@@ -10,4 +14,33 @@ class IAmPrincipalNotificationSettingsSerializer(serializers.ModelSerializer):
class Meta:
model = IAmPrincipalNotificationSettings
fields = ['id', 'notification_category', 'notification_category_display', 'is_enabled']
fields = [
"id",
"notification_category",
"notification_category_display",
"is_enabled",
]
class InAppNotificationSerializer(serializers.ModelSerializer):
notification_category = serializers.ChoiceField(
choices=NotificationCategoryChoices.choices
)
class Meta:
model = InAppNotification
fields = [
"id",
"title",
"message",
"notification_category",
"created_on",
"principal",
]
def to_representation(self, instance):
representation = super().to_representation(instance)
representation["notification_category"] = (
NotificationCategoryChoices.name_for_value(instance.notification_category)
)
return representation

View File

@@ -1,5 +1,5 @@
from django.urls import path
from . import views
from . import views, cron_views
app_name = "manage_notifications_api"
@@ -14,4 +14,14 @@ urlpatterns = [
views.UserNotificationsAPIView.as_view(),
name="user-notifications",
),
path(
"in-app-notifications/",
views.InAppNotificationListAPIView.as_view(),
name="in_app_notifications",
),
path(
"one-week-alert/",
cron_views.OneWeekSubscriptionAlertView.as_view(),
name="in_app_notifications",
),
]

View File

@@ -1,14 +1,18 @@
from rest_framework import status
from rest_framework.views import APIView
from django.conf import settings
from rest_framework import generics
from manage_notifications.api.serializers import (
IAmPrincipalNotificationSettingsSerializer,
InAppNotificationSerializer,
)
from manage_notifications.models import (
IAmPrincipalNotificationSettings,
InAppNotification,
NotificationCategoryChoices,
)
from goodtimes import constants
from rest_framework.pagination import LimitOffsetPagination
from goodtimes.utils import ApiResponse
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication
@@ -73,3 +77,32 @@ class UserNotificationsAPIView(APIView):
message=constants.SUCCESS,
status=status.HTTP_200_OK,
)
class InAppNotificationListAPIView(generics.ListAPIView):
serializer_class = InAppNotificationSerializer
pagination_class = LimitOffsetPagination # Add this line
permission_classes = [IsAuthenticated]
authentication_classes = [JWTAuthentication]
def get_queryset(self):
queryset = InAppNotification.objects.filter(
principal=self.request.user, deleted=False, active=True
)
return queryset
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return ApiResponse.success(
message="InAppNotifications retrieved successfully",
data=serializer.data,
status=status.HTTP_200_OK,
)

View File

@@ -0,0 +1,86 @@
# Generated by Django 5.0.2 on 2024-05-07 12:34
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
(
"manage_notifications",
"0002_alter_pushnotification_notification_category_and_more",
),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="InAppNotification",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("active", models.BooleanField(default=True)),
("deleted", models.BooleanField(default=False)),
("created_on", models.DateTimeField(auto_now_add=True)),
("modified_on", models.DateTimeField(auto_now=True)),
("title", models.CharField(max_length=255)),
("message", models.TextField()),
(
"notification_category",
models.CharField(
choices=[
("general", "General"),
("transaction", "Transaction"),
("referral", "Referral"),
("subscription", "Subscription"),
("event", "Event"),
("promotions", "Promotions"),
],
max_length=50,
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("read_at", models.DateTimeField(blank=True, null=True)),
(
"created_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="%(class)s_created",
to=settings.AUTH_USER_MODEL,
),
),
(
"modified_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="%(class)s_modified",
to=settings.AUTH_USER_MODEL,
),
),
(
"principal",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="in_app_notifications",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"db_table": "in_app_notifications",
},
),
]

View File

@@ -0,0 +1,21 @@
# Generated by Django 5.0.2 on 2024-05-07 13:41
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("manage_notifications", "0003_inappnotification"),
]
operations = [
migrations.RemoveField(
model_name="inappnotification",
name="created_at",
),
migrations.RemoveField(
model_name="inappnotification",
name="read_at",
),
]

View File

@@ -55,3 +55,24 @@ class IAmPrincipalNotificationSettings(BaseModel):
def __str__(self):
return f"{self.principal.first_name} - {self.notification_category}"
class InAppNotification(BaseModel):
"""
Model for in-app notifications
"""
principal = models.ForeignKey(
IAmPrincipal, on_delete=models.CASCADE, related_name="in_app_notifications"
)
title = models.CharField(max_length=255)
message = models.TextField()
notification_category = models.CharField(
max_length=50,
choices=NotificationCategoryChoices.choices,
)
def __str__(self):
return f"{self.title} - {self.notification_category}"
class Meta:
db_table = "in_app_notifications"