Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 44 additions & 14 deletions notifications/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,63 @@ def notify_new_borrowing(borrowing_id):
id=borrowing_id
)
message = (
f"New borrowing created!\n"
f"{borrowing.user}\n"
f"Book: {borrowing.book.title}\n"
f"Borrowed: {borrowing.borrow_date}\n"
f"Expected return: {borrowing.expected_return_date}"
f"📚 New Borrowing Created!\n"
f"👤 User: {borrowing.user.get_full_name()}\n"
f"📖 Book: {borrowing.book.title}\n"
f"📅 Borrowed: {borrowing.borrow_date}\n"
f"📅 Expected Return: {borrowing.expected_return_date}\n"
f"💰 Daily Fee: ${borrowing.book.daily_fee}"
)
send_telegram_message(message)
except Borrowing.DoesNotExist:
pass


@shared_task
def notify_successful_payment(payment_id):
try:
from payments.models import Payment

payment = Payment.objects.select_related(
"borrowing__book", "borrowing__user"
).get(id=payment_id)

borrowing = payment.borrowing
message = (
f"💰 Payment Completed!\n"
f"👤 User: {borrowing.user.get_full_name()}\n"
f"📚 Book: {borrowing.book.title}\n"
f"💵 Amount: ${payment.money_to_pay}\n"
f"💳 Payment Type: {payment.payment_type}\n"
f"✅ Status: {payment.status}\n"
f"📅 Borrowed: {borrowing.borrow_date}\n"
f"📅 Expected Return: {borrowing.expected_return_date}"
)
send_telegram_message(message)
except Exception:
pass


@shared_task
def check_overdue_borrowings():
today = timezone.now().date()
overdues = Borrowing.objects.filter(
expected_return_date__lte=today, actual_return_date__isnull=True
).select_related("book", "user")

if overdues.exists():
for b in overdues:
msg = (
f"Overdue borrowing!\n"
f"{b.user}\n"
f"Book: {b.book.title}\n"
f"Borrowed: {b.borrow_date}\n"
f"Expected return: {b.expected_return_date}\n"
f"Status: Not returned!"
for borrowing in overdues:
days_overdue = (today - borrowing.expected_return_date).days
message = (
f"⚠️ Overdue Borrowing Alert!\n"
f"👤 User: {borrowing.user.get_full_name()}\n"
f"📚 Book: {borrowing.book.title}\n"
f"📅 Borrowed: {borrowing.borrow_date}\n"
f"📅 Expected Return: {borrowing.expected_return_date}\n"
f"⏰ Days Overdue: {days_overdue}\n"
f"❌ Status: Not returned!\n"
f"💸 Daily Fee: ${borrowing.book.daily_fee}"
)
send_telegram_message(msg)
send_telegram_message(message)
else:
send_telegram_message("✅ No borrowings overdue today!")
51 changes: 31 additions & 20 deletions payments/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import stripe
from django.conf import settings
from django.db import transaction
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
Expand All @@ -15,6 +16,7 @@
PaymentListSerializer,
PaymentDetailSerializer,
)
from notifications.tasks import notify_successful_payment


@extend_schema_view(
Expand Down Expand Up @@ -67,23 +69,28 @@ class PaymentSuccessView(APIView):
def _update_payment_status(self, session_id, is_test=False):
"""Common logic for updating payment status"""
try:
payment = Payment.objects.get(session_id=session_id)
payment.status = "PAID"
payment.save()

message = (
"Payment status updated to PAID (TEST MODE)"
if is_test
else "Payment successful!"
)
with transaction.atomic():
payment = Payment.objects.select_for_update().get(
session_id=session_id
)
payment.status = "PAID"
payment.save()

return Response(
{
"message": message,
"payment_id": payment.id,
"status": payment.status,
}
)
notify_successful_payment.delay(payment.id)

message = (
"Payment status updated to PAID (TEST MODE)"
if is_test
else "Payment successful!"
)

return Response(
{
"message": message,
"payment_id": payment.id,
"status": payment.status,
}
)
except Payment.DoesNotExist:
return Response(
{"error": "Payment not found"},
Expand Down Expand Up @@ -186,10 +193,14 @@ def post(self, request):
session_id = session["id"]

try:
payment = Payment.objects.get(session_id=session_id)
if session["payment_status"] == "paid":
payment.status = "PAID"
payment.save()
with transaction.atomic():
payment = Payment.objects.select_for_update().get(
session_id=session_id
)
if session["payment_status"] == "paid":
payment.status = "PAID"
payment.save()
notify_successful_payment.delay(payment.id)
except Payment.DoesNotExist:
pass

Expand Down
Loading