mirror of
https://github.com/i701/sarlink-portal-api.git
synced 2025-04-30 13:55:41 +00:00
Enhance environment variable handling, add Celery configuration, and implement device expiration notification tasks
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 13m45s
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 13m45s
This commit is contained in:
parent
ee8145f07f
commit
99982d13d5
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -9,5 +9,6 @@
|
|||||||
],
|
],
|
||||||
"python.testing.pytestEnabled": false,
|
"python.testing.pytestEnabled": false,
|
||||||
"python.testing.unittestEnabled": true,
|
"python.testing.unittestEnabled": true,
|
||||||
"postman.settings.dotenv-detection-notification-visibility": false
|
"postman.settings.dotenv-detection-notification-visibility": false,
|
||||||
|
"python.analysis.autoImportCompletions": true
|
||||||
}
|
}
|
@ -4,8 +4,13 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
api_url = config("SMS_API_URL", default="")
|
api_url = str(config("SMS_API_URL", cast=str, default=""))
|
||||||
api_key = config("SMS_API_KEY", default="")
|
api_key = str(config("SMS_API_KEY", cast=str, default=""))
|
||||||
|
|
||||||
|
if not api_url or not api_key:
|
||||||
|
raise ValueError(
|
||||||
|
"SMS_API_URL and SMS_API_KEY must be set in the environment variables."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def send_otp(mobile: str, otp: int, message: str):
|
def send_otp(mobile: str, otp: int, message: str):
|
||||||
|
59
api/tasks.py
59
api/tasks.py
@ -1,16 +1,57 @@
|
|||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from api.models import User
|
from api.models import User
|
||||||
|
from devices.models import Device
|
||||||
from api.sms import send_sms
|
from api.sms import send_sms
|
||||||
import requests
|
import requests
|
||||||
from apibase.env import env, BASE_DIR
|
from apibase.env import env, BASE_DIR
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
from celery import shared_task
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
env.read_env(os.path.join(BASE_DIR, ".env"))
|
env.read_env(os.path.join(BASE_DIR, ".env"))
|
||||||
PEOPLE_API_URL = env.str("PEOPLE_API_URL", "")
|
PERSON_VERIFY_BASE_URL = env.str("PERSON_VERIFY_BASE_URL")
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def add(x, y):
|
||||||
|
print(f"Adding {x} and {y}")
|
||||||
|
return x + y
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def deactivate_expired_devices():
|
||||||
|
expired_devices = Device.objects.filter(
|
||||||
|
expiry_date__lte=timezone.localtime(timezone.now()), is_active=True
|
||||||
|
).select_related("user")
|
||||||
|
print("Expired Devices: ", expired_devices)
|
||||||
|
count = expired_devices.count()
|
||||||
|
user_devices_map = {}
|
||||||
|
for device in expired_devices:
|
||||||
|
if device.user and device.user.mobile:
|
||||||
|
if device.user.mobile not in user_devices_map:
|
||||||
|
user_devices_map[device.user.mobile] = []
|
||||||
|
user_devices_map[device.user.mobile].append(device.name)
|
||||||
|
|
||||||
|
for mobile, device_names in user_devices_map.items():
|
||||||
|
if not mobile:
|
||||||
|
continue
|
||||||
|
device_list = "\n".join(
|
||||||
|
[f"{i + 1}. {name}" for i, name in enumerate(device_names)]
|
||||||
|
)
|
||||||
|
print("device list: ", device_list)
|
||||||
|
send_sms(
|
||||||
|
mobile,
|
||||||
|
f"Dear {mobile}, \n\nThe following devices have expired: \n{device_list}. \n\nPlease make a payment to keep your devices active. \n\n- SAR Link",
|
||||||
|
)
|
||||||
|
# expired_devices.update(is_active=False)
|
||||||
|
print(f"Total {count} expired devices.")
|
||||||
|
return {
|
||||||
|
"total_expired_devices": count,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def verify_user_with_person_api_task(user_id: int):
|
def verify_user_with_person_api_task(user_id: int):
|
||||||
@ -21,9 +62,11 @@ def verify_user_with_person_api_task(user_id: int):
|
|||||||
|
|
||||||
user = get_object_or_404(User, id=user_id)
|
user = get_object_or_404(User, id=user_id)
|
||||||
# Call the Person API to verify the user
|
# Call the Person API to verify the user
|
||||||
if not PEOPLE_API_URL:
|
if not PERSON_VERIFY_BASE_URL:
|
||||||
raise ValueError("PEOPLE_API_URL is not set in the environment variables.")
|
raise ValueError(
|
||||||
response = requests.get(f"{PEOPLE_API_URL}/api/person/{user.id_card}")
|
"PERSON_VERIFY_BASE_URL is not set in the environment variables."
|
||||||
|
)
|
||||||
|
response = requests.get(f"{PERSON_VERIFY_BASE_URL}/api/person/{user.id_card}")
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
data = response.json()
|
data = response.json()
|
||||||
api_nic = data.get("nic")
|
api_nic = data.get("nic")
|
||||||
@ -33,6 +76,13 @@ def verify_user_with_person_api_task(user_id: int):
|
|||||||
api_atoll = data.get("atoll_en")
|
api_atoll = data.get("atoll_en")
|
||||||
api_island_name = data.get("island_name_en")
|
api_island_name = data.get("island_name_en")
|
||||||
|
|
||||||
|
if not user.mobile or user.dob is None:
|
||||||
|
logger.error("User mobile or date of birth is not set.")
|
||||||
|
return None
|
||||||
|
if not user.island or user.atoll is None:
|
||||||
|
logger.error("User island or atoll is not set.")
|
||||||
|
return None
|
||||||
|
|
||||||
logger.info(f"API nic: {api_nic}")
|
logger.info(f"API nic: {api_nic}")
|
||||||
logger.info(f"API name: {api_name}")
|
logger.info(f"API name: {api_name}")
|
||||||
logger.info(f"API house name: {api_house_name}")
|
logger.info(f"API house name: {api_house_name}")
|
||||||
@ -77,6 +127,7 @@ def verify_user_with_person_api_task(user_id: int):
|
|||||||
else:
|
else:
|
||||||
user.verified = False
|
user.verified = False
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
send_sms(
|
send_sms(
|
||||||
user.mobile,
|
user.mobile,
|
||||||
f"Dear {user.first_name} {user.last_name}, \n\nYour account registration is being processed. \n\nWe will notify you once verification is complete. \n\n - SAR Link",
|
f"Dear {user.first_name} {user.last_name}, \n\nYour account registration is being processed. \n\nWe will notify you once verification is complete. \n\n - SAR Link",
|
||||||
|
14
api/views.py
14
api/views.py
@ -31,7 +31,7 @@ from typing import cast, Dict, Any
|
|||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from api.sms import send_otp
|
from api.sms import send_otp
|
||||||
|
from .tasks import add, deactivate_expired_devices
|
||||||
|
|
||||||
# local apps import
|
# local apps import
|
||||||
from .serializers import (
|
from .serializers import (
|
||||||
@ -57,6 +57,13 @@ class ErrorMessages:
|
|||||||
UNDERAGE_ERROR = "You must be 18 and above to signup."
|
UNDERAGE_ERROR = "You must be 18 and above to signup."
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(["GET"])
|
||||||
|
def healthcheck(request):
|
||||||
|
add.delay(1, 2)
|
||||||
|
deactivate_expired_devices.delay()
|
||||||
|
return Response({"status": "Good"}, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
|
|
||||||
class UpdateUserWalletView(generics.UpdateAPIView):
|
class UpdateUserWalletView(generics.UpdateAPIView):
|
||||||
# Create user API view
|
# Create user API view
|
||||||
serializer_class = CustomUserByWalletBalanceSerializer
|
serializer_class = CustomUserByWalletBalanceSerializer
|
||||||
@ -416,11 +423,6 @@ class UserDetailAPIView(StaffEditorPermissionMixin, generics.RetrieveAPIView):
|
|||||||
return Response(data)
|
return Response(data)
|
||||||
|
|
||||||
|
|
||||||
@api_view(["GET"])
|
|
||||||
def healthcheck(request):
|
|
||||||
return Response({"status": "Good"}, status=status.HTTP_200_OK)
|
|
||||||
|
|
||||||
|
|
||||||
@api_view(["POST"])
|
@api_view(["POST"])
|
||||||
@permission_classes((permissions.AllowAny,))
|
@permission_classes((permissions.AllowAny,))
|
||||||
def test_email(request):
|
def test_email(request):
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
# myproject/__init__.py
|
||||||
|
from .celery import app as celery_app
|
||||||
|
|
||||||
|
__all__ = ("celery_app",)
|
22
apibase/celery.py
Normal file
22
apibase/celery.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from celery import Celery
|
||||||
|
|
||||||
|
# Set the default Django settings module for the 'celery' program.
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "apibase.settings")
|
||||||
|
|
||||||
|
app = Celery("apibase")
|
||||||
|
|
||||||
|
# Using a string here means the worker doesn't have to serialize
|
||||||
|
# the configuration object to child processes.
|
||||||
|
# - namespace='CELERY' means all celery-related configuration keys
|
||||||
|
# should have a `CELERY_` prefix.
|
||||||
|
app.config_from_object("django.conf:settings", namespace="CELERY")
|
||||||
|
|
||||||
|
# Load task modules from all registered Django apps.
|
||||||
|
app.autodiscover_tasks(["api", "devices"])
|
||||||
|
|
||||||
|
|
||||||
|
@app.task(bind=True, ignore_result=True)
|
||||||
|
def debug_task(self):
|
||||||
|
print(f"Request: {self.request!r}")
|
@ -363,3 +363,10 @@ PASSWORDLESS_AUTH = {
|
|||||||
"PASSWORDLESS_REGISTER_NEW_USERS": True,
|
"PASSWORDLESS_REGISTER_NEW_USERS": True,
|
||||||
"PASSWORDLESS_EMAIL_NOREPLY_ADDRESS": "noreply@sarlink.net",
|
"PASSWORDLESS_EMAIL_NOREPLY_ADDRESS": "noreply@sarlink.net",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# CELERY CONFIGURATION
|
||||||
|
CELERY_BROKER_URL = "redis://localhost:6379/0" # or your Redis URL
|
||||||
|
CELERY_ACCEPT_CONTENT = ["json"]
|
||||||
|
CELERY_TASK_SERIALIZER = "json"
|
||||||
|
CELERY_RESULT_BACKEND = "redis://localhost:6379/0"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"venv": ".venv",
|
"venv": ".venv",
|
||||||
"reportMissingImports": "error",
|
"reportMissingImports": "error",
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
"typeCheckingMode": "off",
|
"typeCheckingMode": "standard",
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"council-api/**/migrations",
|
"council-api/**/migrations",
|
||||||
"**/__pycache__",
|
"**/__pycache__",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user