Why is my Django signal file not working after setting it up?

64 Views Asked by At

I'm trying to send an email to a seller after a buyer completes their payment but I'm facing some issues and the email was not sent. I added a print statement and a try-except block so that I can use that to debug but the print statement did not bring any information in the console and the try block did not return any success or error message in the console too. Please help. Here's my signals.py file

# Stdlib Imports
import uuid

# Django Imports
from django.db.models.signals import pre_save, post_save
from django.dispatch import receiver
from django.core.mail import send_mail
from django.conf import settings

# Own Imports
from payment.models import PaymentHistory


@receiver(pre_save, sender=PaymentHistory)
def create_ref_code_if_does_not_exist(sender, instance, **kwargs):
    """
    Creates a reference code that will be used by paysack;
    if one does not exist.
    """

    if not instance.ref_code:
        instance.ref_code = uuid.uuid4()


@receiver(post_save, sender=PaymentHistory)
def send_payment_notification_email(sender, instance, created, **kwargs):
    if created and instance.status == 'completed':
        print("PaymentNotificationEmail signal triggered.") # For debugging 
        # PaymentHistory model has a ForeignKey to the BuyerOrderHistory model
        buyer_order = instance.order

        # BuyerOrderHistory has a ForeignKey to the Product model
        product = buyer_order.product

        # Get the seller's email address and name
        seller_email = product.user.email
        seller_name = product.user.full_name  

        # Compose the email subject and message
        subject = 'Product Payment Notification'
        message = f'Hello {seller_name},\n\n'
        message += f'The product "{product.title}" has been paid for.\n'
        message += f'Amount Paid: {instance.amount}\n\n'
        message += 'Log in to your account to manage the order.'

        # Send the email
        try:
            send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, [seller_email])
            print("Email sent successfully.")
        except Exception as e:
            print(f"Error sending email: {e}")

My apps.py file looks like this

from django.apps import AppConfig


class PaymentConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "payment"

    def ready(self):
        """Import payment signals when app load."""
        import payment.signals


This is my payment/models.py file:

class PaymentHistory(ObjectTracker):
    user_email = models.EmailField(
        max_length=255, help_text="THe user email address.", editable=False
    )
    order = models.ForeignKey(
        BuyerOrderHistory,
        on_delete=models.DO_NOTHING,
        help_text="The order on-which the payment action was initiated for.",
    )
    amount = models.FloatField(
        help_text="The naira amount of the payment.", null=True, blank=True
    )
    status = models.CharField(
        choices=PaymentStatus.choices, default="pending", max_length=100
    )
    remark = models.CharField(
        max_length=300, help_text="What is this payment transaction for?"
    )

The status field has a defualt value which is pending but when the buyer completes the transaction and it is verified, the value will be updated to 'completed'.

My settings.py has the app installed

INSTALLED_APPS = [
    ...
    "payment",
    ...
]

Here is the code that updates the status:

def post(self, request: Request, ref_code: str) -> Response:
        payment_history = get_payment_history_by_its_status_and_ref_code(
            status="pending", ref_code=ref_code
        )

        if payment_history:

            """verify reference code from paystack"""
            status, data = asyncio.run(paystack().verify_transaction(ref=ref_code))

            if data["message"] is None and data["paid_at"] is None:
                """
                Inform the user that the transaction hasn't been completed.
                """

                payload = error_response(status=False, message=data["gateway_response"])
                return Response(data=payload, status=res_status.HTTP_202_ACCEPTED)

            elif status is True and data["status"] == "success":
                """
                Complete payment transaction and update payment history.
                """
                payment_history.status = "completed"
                payment_history.save(update_fields=["status"])
                
                """Get buyer order"""
                order = BuyerOrderHistory.objects.filter(
                    id=payment_history.order.id
                ).first()

                """Update order status"""
                order.status = "confirmed"
                order.save(update_fields=["status"])

                payload = success_response(
                    status=True,
                    message="Payment transaction has been completed.",
                    data=data,
                )
                return Response(data=payload, status=res_status.HTTP_200_OK)

        else:
            payload = error_response(
                status=False, message="No transaction found for this reference code."
            )
            return Response(data=payload, status=res_status.HTTP_400_BAD_REQUEST)

I've tried running the code and the operation was successful but the email in the signal file was not sent. It was as if my signal file is not being triggered at all.

0

There are 0 best solutions below