mirror of
https://github.com/i701/sarlink-portal-api.git
synced 2025-07-12 03:05:51 +00:00
150 lines
5.0 KiB
Python
150 lines
5.0 KiB
Python
import logging
|
|
|
|
from django.db import transaction
|
|
from django.utils import timezone
|
|
from procrastinate.contrib.django import app
|
|
from api.notifications import send_sms
|
|
from billing.models import Topup, Payment
|
|
from django.utils.timezone import localtime
|
|
from datetime import datetime
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@app.periodic(
|
|
cron="*/1 * * * * *", periodic_id="notify_expired_topups", queue="heavy_tasks"
|
|
)
|
|
@app.task
|
|
def update_expired_topups(timestamp: int):
|
|
expired_topups_qs = Topup.objects.filter(
|
|
expires_at__lte=timezone.now(),
|
|
expiry_notification_sent=False,
|
|
paid=False,
|
|
).select_related("user")
|
|
if not expired_topups_qs.exists():
|
|
logger.info("No expired topups found.")
|
|
return {"total_expired_topups": 0}
|
|
|
|
with transaction.atomic():
|
|
count = expired_topups_qs.count()
|
|
logger.info(f"Found {count} topups to expire.")
|
|
|
|
for topup in expired_topups_qs:
|
|
if topup.user and topup.user.mobile and not topup.expiry_notification_sent:
|
|
send_sms_task.defer(
|
|
mobile=topup.user.mobile,
|
|
type="TOPUP",
|
|
amount=topup.amount,
|
|
model_id=str(topup.id),
|
|
created_at=localtime(topup.created_at).isoformat(),
|
|
user=f"{topup.user.first_name + ' ' + topup.user.last_name}"
|
|
if topup.user.last_name and topup.user.first_name
|
|
else "User",
|
|
)
|
|
topup.expiry_notification_sent = True
|
|
topup.save()
|
|
else:
|
|
topup.expiry_notification_sent = True
|
|
topup.save()
|
|
return
|
|
|
|
return {
|
|
"total_expired_topups": count,
|
|
}
|
|
|
|
|
|
@app.periodic(
|
|
cron="*/1 * * * * *", periodic_id="notify_expired_payments", queue="heavy_tasks"
|
|
)
|
|
@app.task
|
|
def update_expired_payments(timestamp: int):
|
|
expired_payments_qs = Payment.objects.filter(
|
|
expires_at__lte=timezone.now(),
|
|
expiry_notification_sent=False,
|
|
paid=False,
|
|
).select_related("user")
|
|
if not expired_payments_qs.exists():
|
|
logger.info("No expired payments found.")
|
|
return {"total_expired_payments": 0}
|
|
|
|
with transaction.atomic():
|
|
count = expired_payments_qs.count()
|
|
logger.info(f"Found {count} payments to expire.")
|
|
|
|
for payment in expired_payments_qs:
|
|
for device in payment.devices.all():
|
|
device.has_a_pending_payment = False
|
|
device.save()
|
|
if (
|
|
payment.user
|
|
and payment.user.mobile
|
|
and not payment.expiry_notification_sent
|
|
):
|
|
send_sms_task.defer(
|
|
mobile=payment.user.mobile,
|
|
type="PAYMENT",
|
|
amount=payment.amount,
|
|
model_id=str(payment.id),
|
|
created_at=localtime(payment.created_at).isoformat(),
|
|
user=f"{payment.user.first_name + ' ' + payment.user.last_name}"
|
|
if payment.user.last_name and payment.user.first_name
|
|
else "User",
|
|
)
|
|
payment.expiry_notification_sent = True
|
|
payment.save()
|
|
else:
|
|
payment.expiry_notification_sent = True
|
|
payment.save()
|
|
return
|
|
|
|
return {
|
|
"total_expired_payments": count,
|
|
}
|
|
|
|
|
|
@app.task
|
|
def send_sms_task(
|
|
user: str,
|
|
mobile: str,
|
|
amount: float,
|
|
model_id: str,
|
|
created_at: str,
|
|
type: str = "TOPUP", # Default to TOPUP if not provided,
|
|
):
|
|
try:
|
|
dt = datetime.fromisoformat(created_at)
|
|
formatted_date = dt.strftime("%d %b %Y, %I:%M %p")
|
|
except Exception:
|
|
formatted_date = created_at
|
|
message: str = ""
|
|
if type == "TOPUP":
|
|
message = (
|
|
f"Dear {user}, \n\nYour topup of {amount} MVR [created at {formatted_date}] has expired. "
|
|
"Please make a new topup to update your wallet. \n\n- SAR Link"
|
|
)
|
|
elif type == "PAYMENT":
|
|
message = f"Dear {user}, \n\nYour payment of {amount} MVR [created at {formatted_date}] has expired. \n\n- SAR Link"
|
|
send_sms(mobile, message)
|
|
logger.info(f"SMS sent to {mobile} for expired {type} of {amount} MVR.")
|
|
|
|
if type == "TOPUP":
|
|
try:
|
|
topup = Topup.objects.get(id=model_id)
|
|
topup.expiry_notification_sent = True
|
|
topup.save()
|
|
logger.info(f"Marked topup {model_id} as notified.")
|
|
except Topup.DoesNotExist:
|
|
logger.error(
|
|
f"Topup id: {model_id} not found when trying to mark as notified."
|
|
)
|
|
else:
|
|
try:
|
|
topup = Payment.objects.get(id=model_id)
|
|
topup.expiry_notification_sent = True
|
|
topup.save()
|
|
logger.info(f"Marked payment {model_id} as notified.")
|
|
except Payment.DoesNotExist:
|
|
logger.error(
|
|
f"Payment id: {model_id} not found when trying to mark as notified."
|
|
)
|