subscription alert
This commit is contained in:
@@ -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):
|
||||
|
||||
66
manage_notifications/api/cron_views.py
Normal file
66
manage_notifications/api/cron_views.py
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
),
|
||||
]
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
86
manage_notifications/migrations/0003_inappnotification.py
Normal file
86
manage_notifications/migrations/0003_inappnotification.py
Normal 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",
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -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",
|
||||
),
|
||||
]
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user