From 425c5b141862dd7e1e475ee33d8712fb43ad9dc8 Mon Sep 17 00:00:00 2001 From: KlemenSpruk Date: Tue, 24 Oct 2023 15:33:16 +0200 Subject: [PATCH] saving --- .../notifications/base/channels/channel.py | 23 +++++++++++++++--- .../notifications/base/notification.py | 2 +- .../base/send_notification_mixin.py | 24 +++++++++---------- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/django_project_base/notifications/base/channels/channel.py b/django_project_base/notifications/base/channels/channel.py index 6dc232d8..0db1de8d 100644 --- a/django_project_base/notifications/base/channels/channel.py +++ b/django_project_base/notifications/base/channels/channel.py @@ -6,6 +6,7 @@ from django.conf import settings from django.contrib.auth import get_user_model from django.utils.module_loading import import_string +from django.utils.translation import gettext from django_project_base.notifications.base.channels.integrations.provider_integration import ProviderIntegration from django_project_base.notifications.base.phone_number_parser import PhoneNumberParser @@ -90,13 +91,14 @@ def clean_recipients(self, recipients: List[Recipient]) -> List[Recipient]: def create_delivery_report( self, notification: DjangoProjectBaseNotification, recipient: Recipient, pk: str ) -> DeliveryReport: - return DeliveryReport.objects.create( + dlr, created = DeliveryReport.objects.get_or_create( notification=notification, user_id=recipient.identifier, channel=f"{self.__module__}.{self.__class__.__name__}", provider=f"{self.provider.__module__}.{self.provider.__class__.__name__}", pk=pk, ) + return dlr @abstractmethod def get_recipients(self, notification: DjangoProjectBaseNotification, unique_identifier="email") -> List[Recipient]: @@ -136,8 +138,23 @@ def send(self, notification: DjangoProjectBaseNotification, extra_data, **kwargs def make_send(notification_obj, rec_obj, message_str, dlr_pk) -> Optional[DeliveryReport]: try: + do_send = True if not getattr(settings, "TESTING", False): - self.provider.client_send(self.sender(notification_obj), rec_obj, message_str, dlr_pk) + dlr_exists = DeliveryReport.objects.filter( + notification=notification_obj, + user_id=rec_obj.identifier, + channel=f"{self.__module__}.{self.__class__.__name__}", + provider=f"{self.provider.__module__}.{self.provider.__class__.__name__}", + ) + if dlr_exists.count() > 1: + raise Exception(f"{gettext('To many DLR exist.')} {notification} {recipient}") + if dlr_notification := dlr_exists.first(): + dlr_pk = str(dlr_notification.pk) + if dlr_notification.status == DeliveryReport.Status.DELIVERED: + do_send = False + self.provider.client_send( + self.sender(notification_obj), rec_obj, message_str, dlr_pk + ) if do_send else None sent = True except Exception as te: logger.exception(te) @@ -151,7 +168,7 @@ def make_send(notification_obj, rec_obj, message_str, dlr_pk) -> Optional[Delive logger.exception(de) return dlr_obj - for recipient in recipients: # noqa: E203 + for recipient in recipients: dlr__uuid = str(uuid.uuid4()) try: while dlr := not make_send( diff --git a/django_project_base/notifications/base/notification.py b/django_project_base/notifications/base/notification.py index 842f25d2..45c68b26 100644 --- a/django_project_base/notifications/base/notification.py +++ b/django_project_base/notifications/base/notification.py @@ -95,7 +95,7 @@ def resend(notification: DjangoProjectBaseNotification, user_pk: str): notification.recipients_original_payload_search = None notification.sender = Notification._get_sender_config(notification.project_slug) notification.save(update_fields=["recipients", "recipients_original_payload_search"]) - SendNotificationMixin().make_send(notification, {}) + SendNotificationMixin().make_send(notification, {}, resend=True) def __set_via_channels(self, val): self._via_channels = val diff --git a/django_project_base/notifications/base/send_notification_mixin.py b/django_project_base/notifications/base/send_notification_mixin.py index c769ca7d..aaac5f0f 100644 --- a/django_project_base/notifications/base/send_notification_mixin.py +++ b/django_project_base/notifications/base/send_notification_mixin.py @@ -10,7 +10,9 @@ class SendNotificationMixin(object): - def make_send(self, notification: DjangoProjectBaseNotification, extra_data) -> DjangoProjectBaseNotification: + def make_send( + self, notification: DjangoProjectBaseNotification, extra_data, resend=False + ) -> DjangoProjectBaseNotification: sent_channels: list = [] failed_channels: list = [] @@ -35,15 +37,12 @@ def make_send(self, notification: DjangoProjectBaseNotification, extra_data) -> notification.sent_channels.split(",") if notification.sent_channels else [], ) ) - required_channels = ( - set( - filter( - lambda i: i not in (None, "") and i, - notification.required_channels.split(",") if notification.required_channels else [], - ) + required_channels = set( + filter( + lambda i: i not in (None, "") and i, + notification.required_channels.split(",") if notification.required_channels else [], ) - - already_sent_channels - ) + ) - (already_sent_channels if not resend else set()) already_failed_channels = set( filter( lambda i: i not in (None, "") and i, @@ -51,13 +50,12 @@ def make_send(self, notification: DjangoProjectBaseNotification, extra_data) -> ) ) - sent_to_channels = required_channels - already_sent_channels from django_project_base.notifications.base.channels.sms_channel import SmsChannel if notification.send_notification_sms: - sent_to_channels.add(SmsChannel.name) + required_channels.add(SmsChannel.name) - for channel_identifier in sent_to_channels: + for channel_identifier in required_channels: channel = ChannelIdentifier.channel( channel_identifier, extra_data=extra_data, project_slug=notification.project_slug, ensure_dlr_user=False ) @@ -82,7 +80,7 @@ def make_send(self, notification: DjangoProjectBaseNotification, extra_data) -> exceptions += f"{str(e)}\n\n" if notification.created_at: - if sent_to_channels: + if required_channels: notification.sent_channels = ( ",".join( set(