1119 lines
44 KiB
Python
1119 lines
44 KiB
Python
|
|
from django.http import JsonResponse
|
||
|
|
from django.utils.decorators import method_decorator
|
||
|
|
from django.views.decorators.csrf import csrf_exempt
|
||
|
|
from django.forms.models import model_to_dict
|
||
|
|
from django.contrib.auth import get_user_model
|
||
|
|
from django.db import models as django_models
|
||
|
|
from django.utils import timezone
|
||
|
|
from datetime import timedelta
|
||
|
|
|
||
|
|
from rest_framework.views import APIView
|
||
|
|
|
||
|
|
from partner.models import Partner
|
||
|
|
from mobile_api.utils import validate_token_and_get_user
|
||
|
|
from eventify_logger.services import log
|
||
|
|
|
||
|
|
User = get_user_model()
|
||
|
|
|
||
|
|
|
||
|
|
def _partner_to_dict(partner, request=None):
|
||
|
|
"""Serialize Partner for JSON."""
|
||
|
|
data = model_to_dict(
|
||
|
|
partner,
|
||
|
|
fields=[
|
||
|
|
"id",
|
||
|
|
"name",
|
||
|
|
"partner_type",
|
||
|
|
"primary_contact_person_name",
|
||
|
|
"primary_contact_person_email",
|
||
|
|
"primary_contact_person_phone",
|
||
|
|
"status",
|
||
|
|
"address",
|
||
|
|
"city",
|
||
|
|
"state",
|
||
|
|
"country",
|
||
|
|
"website_url",
|
||
|
|
"pincode",
|
||
|
|
"latitude",
|
||
|
|
"longitude",
|
||
|
|
"is_kyc_compliant",
|
||
|
|
"kyc_compliance_status",
|
||
|
|
"kyc_compliance_reason",
|
||
|
|
"kyc_compliance_document_type",
|
||
|
|
"kyc_compliance_document_other_type",
|
||
|
|
"kyc_compliance_document_number",
|
||
|
|
],
|
||
|
|
)
|
||
|
|
# Add document file URL if exists
|
||
|
|
if partner.kyc_compliance_document_file:
|
||
|
|
if request:
|
||
|
|
data["kyc_compliance_document_file"] = request.build_absolute_uri(partner.kyc_compliance_document_file.url)
|
||
|
|
else:
|
||
|
|
data["kyc_compliance_document_file"] = partner.kyc_compliance_document_file.url
|
||
|
|
else:
|
||
|
|
data["kyc_compliance_document_file"] = None
|
||
|
|
return data
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerCreateAPI(APIView):
|
||
|
|
"""
|
||
|
|
Create a new Partner.
|
||
|
|
Body: token, username, name, partner_type, primary_contact_person_name,
|
||
|
|
primary_contact_person_email, primary_contact_person_phone (required);
|
||
|
|
address, city, state, country, website_url, pincode, latitude, longitude,
|
||
|
|
is_kyc_compliant, kyc_compliance_status, kyc_compliance_reason,
|
||
|
|
kyc_compliance_document_type, kyc_compliance_document_other_type,
|
||
|
|
kyc_compliance_document_number (optional).
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
name = data.get("name")
|
||
|
|
partner_type = data.get("partner_type")
|
||
|
|
primary_contact_person_name = data.get("primary_contact_person_name")
|
||
|
|
primary_contact_person_email = data.get("primary_contact_person_email")
|
||
|
|
primary_contact_person_phone = data.get("primary_contact_person_phone")
|
||
|
|
|
||
|
|
if not all([name, partner_type, primary_contact_person_name, primary_contact_person_email, primary_contact_person_phone]):
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": "name, partner_type, primary_contact_person_name, primary_contact_person_email, and primary_contact_person_phone are required.",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Validate partner_type
|
||
|
|
valid_partner_types = [choice[1] for choice in Partner._meta.get_field("partner_type").choices]
|
||
|
|
print(valid_partner_types)
|
||
|
|
if partner_type not in valid_partner_types:
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": f"Invalid partner_type. Must be one of: {', '.join(valid_partner_types)}",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
partner = Partner.objects.create(
|
||
|
|
name=name,
|
||
|
|
partner_type=partner_type,
|
||
|
|
primary_contact_person_name=primary_contact_person_name,
|
||
|
|
primary_contact_person_email=primary_contact_person_email,
|
||
|
|
primary_contact_person_phone=primary_contact_person_phone,
|
||
|
|
address=data.get("address"),
|
||
|
|
city=data.get("city"),
|
||
|
|
state=data.get("state"),
|
||
|
|
country=data.get("country"),
|
||
|
|
website_url=data.get("website_url"),
|
||
|
|
pincode=data.get("pincode"),
|
||
|
|
latitude=data.get("latitude"),
|
||
|
|
longitude=data.get("longitude"),
|
||
|
|
is_kyc_compliant=data.get("is_kyc_compliant", False),
|
||
|
|
kyc_compliance_status=data.get("kyc_compliance_status", "pending"),
|
||
|
|
kyc_compliance_reason=data.get("kyc_compliance_reason"),
|
||
|
|
kyc_compliance_document_type=data.get("kyc_compliance_document_type"),
|
||
|
|
kyc_compliance_document_other_type=data.get("kyc_compliance_document_other_type"),
|
||
|
|
kyc_compliance_document_number=data.get("kyc_compliance_document_number"),
|
||
|
|
)
|
||
|
|
|
||
|
|
# Handle file upload if provided
|
||
|
|
if "kyc_compliance_document_file" in request.FILES:
|
||
|
|
partner.kyc_compliance_document_file = request.FILES["kyc_compliance_document_file"]
|
||
|
|
partner.save()
|
||
|
|
|
||
|
|
log("info", "Partner created", request=request, user=user, logger_data={"partner_id": partner.id, "partner_name": name})
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "success", "partner": _partner_to_dict(partner, request)},
|
||
|
|
status=201,
|
||
|
|
)
|
||
|
|
except Exception as e:
|
||
|
|
log("error", "Partner create exception", request=request, logger_data={"error": str(e)})
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerListAPI(APIView):
|
||
|
|
"""
|
||
|
|
List Partners, optionally filtered by partner_type or kyc_compliance_status.
|
||
|
|
Body: token, username, partner_type (optional), kyc_compliance_status (optional).
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
qs = Partner.objects.all().order_by("-id")
|
||
|
|
|
||
|
|
partner_type = data.get("partner_type")
|
||
|
|
if partner_type:
|
||
|
|
qs = qs.filter(partner_type=partner_type)
|
||
|
|
|
||
|
|
kyc_compliance_status = data.get("kyc_compliance_status")
|
||
|
|
if kyc_compliance_status:
|
||
|
|
qs = qs.filter(kyc_compliance_status=kyc_compliance_status)
|
||
|
|
|
||
|
|
partners = [_partner_to_dict(p, request) for p in qs]
|
||
|
|
return JsonResponse({"status": "success", "partners": partners}, status=200)
|
||
|
|
except Exception as e:
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerUpdateAPI(APIView):
|
||
|
|
"""
|
||
|
|
Update an existing Partner.
|
||
|
|
Body: token, username, partner_id (required);
|
||
|
|
name, partner_type, primary_contact_person_name, primary_contact_person_email,
|
||
|
|
primary_contact_person_phone, address, city, state, country, website_url,
|
||
|
|
pincode, latitude, longitude, is_kyc_compliant, kyc_compliance_status,
|
||
|
|
kyc_compliance_reason, kyc_compliance_document_type,
|
||
|
|
kyc_compliance_document_other_type, kyc_compliance_document_number (optional).
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
partner_id = data.get("partner_id")
|
||
|
|
if not partner_id:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "partner_id is required."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
try:
|
||
|
|
partner = Partner.objects.get(id=partner_id)
|
||
|
|
except Partner.DoesNotExist:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "Partner not found."},
|
||
|
|
status=404,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Update fields if provided
|
||
|
|
if data.get("name") is not None:
|
||
|
|
partner.name = data["name"]
|
||
|
|
if data.get("partner_type") is not None:
|
||
|
|
valid_partner_types = [choice[0] for choice in Partner._meta.get_field("partner_type").choices]
|
||
|
|
if data["partner_type"] not in valid_partner_types:
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": f"Invalid partner_type. Must be one of: {', '.join(valid_partner_types)}",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
partner.partner_type = data["partner_type"]
|
||
|
|
if data.get("primary_contact_person_name") is not None:
|
||
|
|
partner.primary_contact_person_name = data["primary_contact_person_name"]
|
||
|
|
if data.get("primary_contact_person_email") is not None:
|
||
|
|
partner.primary_contact_person_email = data["primary_contact_person_email"]
|
||
|
|
if data.get("primary_contact_person_phone") is not None:
|
||
|
|
partner.primary_contact_person_phone = data["primary_contact_person_phone"]
|
||
|
|
if "address" in data:
|
||
|
|
partner.address = data["address"]
|
||
|
|
if "city" in data:
|
||
|
|
partner.city = data["city"]
|
||
|
|
if "state" in data:
|
||
|
|
partner.state = data["state"]
|
||
|
|
if "country" in data:
|
||
|
|
partner.country = data["country"]
|
||
|
|
if "website_url" in data:
|
||
|
|
partner.website_url = data["website_url"]
|
||
|
|
if "pincode" in data:
|
||
|
|
partner.pincode = data["pincode"]
|
||
|
|
if data.get("latitude") is not None:
|
||
|
|
try:
|
||
|
|
partner.latitude = float(data["latitude"])
|
||
|
|
except (TypeError, ValueError):
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "latitude must be numeric."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
if data.get("longitude") is not None:
|
||
|
|
try:
|
||
|
|
partner.longitude = float(data["longitude"])
|
||
|
|
except (TypeError, ValueError):
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "longitude must be numeric."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
if data.get("is_kyc_compliant") is not None:
|
||
|
|
partner.is_kyc_compliant = bool(data["is_kyc_compliant"])
|
||
|
|
if data.get("kyc_compliance_status") is not None:
|
||
|
|
valid_statuses = [choice[0] for choice in Partner._meta.get_field("kyc_compliance_status").choices]
|
||
|
|
if data["kyc_compliance_status"] not in valid_statuses:
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": f"Invalid kyc_compliance_status. Must be one of: {', '.join(valid_statuses)}",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
partner.kyc_compliance_status = data["kyc_compliance_status"]
|
||
|
|
if "kyc_compliance_reason" in data:
|
||
|
|
partner.kyc_compliance_reason = data["kyc_compliance_reason"]
|
||
|
|
if "kyc_compliance_document_type" in data:
|
||
|
|
partner.kyc_compliance_document_type = data["kyc_compliance_document_type"]
|
||
|
|
if "kyc_compliance_document_other_type" in data:
|
||
|
|
partner.kyc_compliance_document_other_type = data["kyc_compliance_document_other_type"]
|
||
|
|
if "kyc_compliance_document_number" in data:
|
||
|
|
partner.kyc_compliance_document_number = data["kyc_compliance_document_number"]
|
||
|
|
|
||
|
|
# Handle file upload if provided
|
||
|
|
if "kyc_compliance_document_file" in request.FILES:
|
||
|
|
partner.kyc_compliance_document_file = request.FILES["kyc_compliance_document_file"]
|
||
|
|
|
||
|
|
partner.save()
|
||
|
|
log("info", "Partner updated", request=request, user=user, logger_data={"partner_id": partner_id})
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "success", "partner": _partner_to_dict(partner, request)},
|
||
|
|
status=200,
|
||
|
|
)
|
||
|
|
except Exception as e:
|
||
|
|
log("error", "Partner update exception", request=request, logger_data={"error": str(e)})
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerDeleteAPI(APIView):
|
||
|
|
"""
|
||
|
|
Delete an existing Partner.
|
||
|
|
Body: token, username, partner_id.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
partner_id = data.get("partner_id")
|
||
|
|
if not partner_id:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "partner_id is required."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
try:
|
||
|
|
partner = Partner.objects.get(id=partner_id)
|
||
|
|
except Partner.DoesNotExist:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "Partner not found."},
|
||
|
|
status=404,
|
||
|
|
)
|
||
|
|
|
||
|
|
partner_name = partner.name
|
||
|
|
partner.delete()
|
||
|
|
log("info", "Partner deleted", request=request, user=user, logger_data={"partner_id": partner_id, "partner_name": partner_name})
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "success", "message": "Partner deleted successfully."},
|
||
|
|
status=200,
|
||
|
|
)
|
||
|
|
except Exception as e:
|
||
|
|
log("error", "Partner delete exception", request=request, logger_data={"error": str(e)})
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerUpdateKYCDocumentsAPI(APIView):
|
||
|
|
"""
|
||
|
|
Update KYC documents for an existing Partner.
|
||
|
|
Body: token, username, partner_id (required);
|
||
|
|
kyc_compliance_document_type, kyc_compliance_document_other_type,
|
||
|
|
kyc_compliance_document_number (optional);
|
||
|
|
kyc_compliance_document_file (file upload, optional);
|
||
|
|
is_kyc_compliant, kyc_compliance_status, kyc_compliance_reason (optional).
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
partner_id = data.get("partner_id")
|
||
|
|
if not partner_id:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "partner_id is required."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
try:
|
||
|
|
partner = Partner.objects.get(id=partner_id)
|
||
|
|
except Partner.DoesNotExist:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "Partner not found."},
|
||
|
|
status=404,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Update KYC document fields
|
||
|
|
if "kyc_compliance_document_type" in data:
|
||
|
|
document_type = data["kyc_compliance_document_type"]
|
||
|
|
if document_type: # Allow empty string to clear
|
||
|
|
valid_types = [choice[0] for choice in Partner._meta.get_field("kyc_compliance_document_type").choices]
|
||
|
|
if document_type not in valid_types:
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": f"Invalid kyc_compliance_document_type. Must be one of: {', '.join(valid_types)}",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
partner.kyc_compliance_document_type = document_type if document_type else None
|
||
|
|
|
||
|
|
if "kyc_compliance_document_other_type" in data:
|
||
|
|
partner.kyc_compliance_document_other_type = data["kyc_compliance_document_other_type"] or None
|
||
|
|
|
||
|
|
if "kyc_compliance_document_number" in data:
|
||
|
|
partner.kyc_compliance_document_number = data["kyc_compliance_document_number"] or None
|
||
|
|
|
||
|
|
# Handle file upload
|
||
|
|
if "kyc_compliance_document_file" in request.FILES:
|
||
|
|
partner.kyc_compliance_document_file = request.FILES["kyc_compliance_document_file"]
|
||
|
|
|
||
|
|
# Optionally update compliance status fields
|
||
|
|
if data.get("is_kyc_compliant") is not None:
|
||
|
|
partner.is_kyc_compliant = bool(data["is_kyc_compliant"])
|
||
|
|
|
||
|
|
if data.get("kyc_compliance_status") is not None:
|
||
|
|
valid_statuses = [choice[0] for choice in Partner._meta.get_field("kyc_compliance_status").choices]
|
||
|
|
if data["kyc_compliance_status"] not in valid_statuses:
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": f"Invalid kyc_compliance_status. Must be one of: {', '.join(valid_statuses)}",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
partner.kyc_compliance_status = data["kyc_compliance_status"]
|
||
|
|
|
||
|
|
if "kyc_compliance_reason" in data:
|
||
|
|
partner.kyc_compliance_reason = data["kyc_compliance_reason"] or None
|
||
|
|
|
||
|
|
partner.save()
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "success",
|
||
|
|
"message": "KYC documents updated successfully.",
|
||
|
|
"partner": _partner_to_dict(partner, request),
|
||
|
|
},
|
||
|
|
status=200,
|
||
|
|
)
|
||
|
|
except Exception as e:
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerUpdateAddressLocationAPI(APIView):
|
||
|
|
"""
|
||
|
|
Update address and location fields for an existing Partner.
|
||
|
|
Body: token, username, partner_id (required);
|
||
|
|
address, city, state, country, website_url, pincode, latitude, longitude (optional).
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
partner_id = data.get("partner_id")
|
||
|
|
if not partner_id:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "partner_id is required."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
try:
|
||
|
|
partner = Partner.objects.get(id=partner_id)
|
||
|
|
except Partner.DoesNotExist:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "Partner not found."},
|
||
|
|
status=404,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Update address fields
|
||
|
|
if "address" in data:
|
||
|
|
partner.address = data["address"] or None
|
||
|
|
if "city" in data:
|
||
|
|
partner.city = data["city"] or None
|
||
|
|
if "state" in data:
|
||
|
|
partner.state = data["state"] or None
|
||
|
|
if "country" in data:
|
||
|
|
partner.country = data["country"] or None
|
||
|
|
if "website_url" in data:
|
||
|
|
partner.website_url = data["website_url"] or None
|
||
|
|
if "pincode" in data:
|
||
|
|
partner.pincode = data["pincode"] or None
|
||
|
|
|
||
|
|
# Update location coordinates with validation
|
||
|
|
if data.get("latitude") is not None:
|
||
|
|
try:
|
||
|
|
latitude = float(data["latitude"])
|
||
|
|
# Validate latitude range (-90 to 90)
|
||
|
|
if latitude < -90 or latitude > 90:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "latitude must be between -90 and 90."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
partner.latitude = latitude
|
||
|
|
except (TypeError, ValueError):
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "latitude must be numeric."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
if data.get("longitude") is not None:
|
||
|
|
try:
|
||
|
|
longitude = float(data["longitude"])
|
||
|
|
# Validate longitude range (-180 to 180)
|
||
|
|
if longitude < -180 or longitude > 180:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "longitude must be between -180 and 180."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
partner.longitude = longitude
|
||
|
|
except (TypeError, ValueError):
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "longitude must be numeric."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
partner.save()
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "success",
|
||
|
|
"message": "Address and location updated successfully.",
|
||
|
|
"partner": _partner_to_dict(partner, request),
|
||
|
|
},
|
||
|
|
status=200,
|
||
|
|
)
|
||
|
|
except Exception as e:
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
def _user_to_dict(user, request=None):
|
||
|
|
"""Serialize User for JSON."""
|
||
|
|
data = model_to_dict(
|
||
|
|
user,
|
||
|
|
fields=[
|
||
|
|
"id",
|
||
|
|
"username",
|
||
|
|
"email",
|
||
|
|
"phone_number",
|
||
|
|
"role",
|
||
|
|
"is_staff",
|
||
|
|
"is_customer",
|
||
|
|
"is_user",
|
||
|
|
"pincode",
|
||
|
|
"district",
|
||
|
|
"state",
|
||
|
|
"country",
|
||
|
|
"place",
|
||
|
|
"latitude",
|
||
|
|
"longitude",
|
||
|
|
],
|
||
|
|
)
|
||
|
|
# Add profile picture URL if exists
|
||
|
|
if user.profile_picture:
|
||
|
|
if request:
|
||
|
|
data["profile_picture"] = request.build_absolute_uri(user.profile_picture.url)
|
||
|
|
else:
|
||
|
|
data["profile_picture"] = user.profile_picture.url
|
||
|
|
else:
|
||
|
|
data["profile_picture"] = None
|
||
|
|
return data
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerCreateUserAPI(APIView):
|
||
|
|
"""
|
||
|
|
Create a user with partner-related role (partner, partner_manager, partner_staff, partner_customer).
|
||
|
|
Body: token, username, email, password, role (required);
|
||
|
|
phone_number, partner_id, pincode, district, state, country, place, latitude, longitude (optional).
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
username = data.get("username")
|
||
|
|
email = data.get("email")
|
||
|
|
password = data.get("password")
|
||
|
|
role = data.get("role")
|
||
|
|
partner_id = data.get("partner_id")
|
||
|
|
|
||
|
|
if not all([username, email, password, role]):
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": "username, email, password, and role are required.",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Validate role - must be one of the partner-related roles
|
||
|
|
valid_partner_roles = ["partner", "partner_manager", "partner_staff", "partner_customer"]
|
||
|
|
if role not in valid_partner_roles:
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": f"Invalid role. Must be one of: {', '.join(valid_partner_roles)}",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Check if username already exists
|
||
|
|
if User.objects.filter(username=username).exists():
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "Username already exists."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Check if email already exists
|
||
|
|
if User.objects.filter(email=email).exists():
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "Email already exists."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Validate partner_id if provided
|
||
|
|
partner = None
|
||
|
|
if partner_id:
|
||
|
|
try:
|
||
|
|
partner = Partner.objects.get(id=partner_id)
|
||
|
|
except Partner.DoesNotExist:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "Partner not found."},
|
||
|
|
status=404,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Create user
|
||
|
|
new_user = User.objects.create_user(
|
||
|
|
username=username,
|
||
|
|
email=email,
|
||
|
|
password=password,
|
||
|
|
role=role,
|
||
|
|
phone_number=data.get("phone_number"),
|
||
|
|
pincode=data.get("pincode"),
|
||
|
|
district=data.get("district"),
|
||
|
|
state=data.get("state"),
|
||
|
|
country=data.get("country"),
|
||
|
|
place=data.get("place"),
|
||
|
|
)
|
||
|
|
|
||
|
|
# Set location coordinates if provided
|
||
|
|
if data.get("latitude") is not None:
|
||
|
|
try:
|
||
|
|
latitude = float(data["latitude"])
|
||
|
|
if latitude < -90 or latitude > 90:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "latitude must be between -90 and 90."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
new_user.latitude = latitude
|
||
|
|
except (TypeError, ValueError):
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "latitude must be numeric."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
if data.get("longitude") is not None:
|
||
|
|
try:
|
||
|
|
longitude = float(data["longitude"])
|
||
|
|
if longitude < -180 or longitude > 180:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "longitude must be between -180 and 180."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
new_user.longitude = longitude
|
||
|
|
except (TypeError, ValueError):
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "longitude must be numeric."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Handle profile picture upload if provided
|
||
|
|
if "profile_picture" in request.FILES:
|
||
|
|
new_user.profile_picture = request.FILES["profile_picture"]
|
||
|
|
|
||
|
|
new_user.save()
|
||
|
|
|
||
|
|
response_data = {
|
||
|
|
"status": "success",
|
||
|
|
"message": f"User created successfully with role: {role}.",
|
||
|
|
"user": _user_to_dict(new_user, request),
|
||
|
|
}
|
||
|
|
|
||
|
|
# Include partner info if linked
|
||
|
|
if partner:
|
||
|
|
response_data["partner"] = {
|
||
|
|
"id": partner.id,
|
||
|
|
"name": partner.name,
|
||
|
|
"partner_type": partner.partner_type,
|
||
|
|
}
|
||
|
|
|
||
|
|
log("info", "Partner user created", request=request, user=user, logger_data={"new_user_id": new_user.id, "username": new_user.username, "role": role})
|
||
|
|
return JsonResponse(response_data, status=201)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
log("error", "Partner create user exception", request=request, logger_data={"error": str(e)})
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerListUsersAPI(APIView):
|
||
|
|
"""
|
||
|
|
List users associated with a partner (users with partner-related roles).
|
||
|
|
Body: token, username, partner_id (required);
|
||
|
|
role (optional filter: partner, partner_manager, partner_staff, partner_customer).
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
partner_id = data.get("partner_id")
|
||
|
|
if not partner_id:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "partner_id is required."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Validate partner exists
|
||
|
|
try:
|
||
|
|
partner = Partner.objects.get(id=partner_id)
|
||
|
|
except Partner.DoesNotExist:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "Partner not found."},
|
||
|
|
status=404,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Filter users by partner-related roles
|
||
|
|
partner_roles = ["partner", "partner_manager", "partner_staff", "partner_customer"]
|
||
|
|
qs = User.objects.filter(role__in=partner_roles).order_by("-id")
|
||
|
|
|
||
|
|
# Optional role filter
|
||
|
|
role_filter = data.get("role")
|
||
|
|
if role_filter:
|
||
|
|
if role_filter not in partner_roles:
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": f"Invalid role filter. Must be one of: {', '.join(partner_roles)}",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
qs = qs.filter(role=role_filter)
|
||
|
|
|
||
|
|
# Optionally filter by matching contact email or phone (if partner contact info matches user)
|
||
|
|
# This is a heuristic approach since there's no direct FK relationship
|
||
|
|
# You can enhance this logic based on your business requirements
|
||
|
|
match_by_contact = data.get("match_by_contact", False)
|
||
|
|
if match_by_contact:
|
||
|
|
qs = qs.filter(
|
||
|
|
django_models.Q(email=partner.primary_contact_person_email)
|
||
|
|
| django_models.Q(phone_number=partner.primary_contact_person_phone)
|
||
|
|
)
|
||
|
|
|
||
|
|
users = [_user_to_dict(u, request) for u in qs]
|
||
|
|
|
||
|
|
response_data = {
|
||
|
|
"status": "success",
|
||
|
|
"partner": {
|
||
|
|
"id": partner.id,
|
||
|
|
"name": partner.name,
|
||
|
|
"partner_type": partner.partner_type,
|
||
|
|
},
|
||
|
|
"users": users,
|
||
|
|
"total_count": len(users),
|
||
|
|
}
|
||
|
|
|
||
|
|
return JsonResponse(response_data, status=200)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerUpdateUserAPI(APIView):
|
||
|
|
"""
|
||
|
|
Update a partner user (user with partner-related role).
|
||
|
|
Body: token, username, user_id (required);
|
||
|
|
email, phone_number, role (must be partner-related), pincode, district, state,
|
||
|
|
country, place, latitude, longitude, profile_picture (optional).
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
user_id = data.get("user_id")
|
||
|
|
if not user_id:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "user_id is required."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
try:
|
||
|
|
target_user = User.objects.get(id=user_id)
|
||
|
|
except User.DoesNotExist:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "User not found."},
|
||
|
|
status=404,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Validate that the user has a partner-related role
|
||
|
|
partner_roles = ["partner", "partner_manager", "partner_staff", "partner_customer"]
|
||
|
|
if target_user.role not in partner_roles:
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": "User is not a partner-related user. Only users with partner roles can be updated.",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Update fields if provided
|
||
|
|
if data.get("email") is not None:
|
||
|
|
new_email = data["email"]
|
||
|
|
# Check if email already exists for another user
|
||
|
|
if User.objects.filter(email=new_email).exclude(id=user_id).exists():
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "Email already exists for another user."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
target_user.email = new_email
|
||
|
|
|
||
|
|
if data.get("phone_number") is not None:
|
||
|
|
target_user.phone_number = data["phone_number"] or None
|
||
|
|
|
||
|
|
if data.get("role") is not None:
|
||
|
|
new_role = data["role"]
|
||
|
|
if new_role not in partner_roles:
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": f"Invalid role. Must be one of: {', '.join(partner_roles)}",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
target_user.role = new_role
|
||
|
|
|
||
|
|
if "pincode" in data:
|
||
|
|
target_user.pincode = data["pincode"] or None
|
||
|
|
if "district" in data:
|
||
|
|
target_user.district = data["district"] or None
|
||
|
|
if "state" in data:
|
||
|
|
target_user.state = data["state"] or None
|
||
|
|
if "country" in data:
|
||
|
|
target_user.country = data["country"] or None
|
||
|
|
if "place" in data:
|
||
|
|
target_user.place = data["place"] or None
|
||
|
|
|
||
|
|
if data.get("latitude") is not None:
|
||
|
|
try:
|
||
|
|
latitude = float(data["latitude"])
|
||
|
|
if latitude < -90 or latitude > 90:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "latitude must be between -90 and 90."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
target_user.latitude = latitude
|
||
|
|
except (TypeError, ValueError):
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "latitude must be numeric."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
if data.get("longitude") is not None:
|
||
|
|
try:
|
||
|
|
longitude = float(data["longitude"])
|
||
|
|
if longitude < -180 or longitude > 180:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "longitude must be between -180 and 180."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
target_user.longitude = longitude
|
||
|
|
except (TypeError, ValueError):
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "longitude must be numeric."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Handle profile picture upload if provided
|
||
|
|
if "profile_picture" in request.FILES:
|
||
|
|
target_user.profile_picture = request.FILES["profile_picture"]
|
||
|
|
|
||
|
|
# Handle password update if provided
|
||
|
|
if data.get("password"):
|
||
|
|
target_user.set_password(data["password"])
|
||
|
|
|
||
|
|
target_user.save()
|
||
|
|
|
||
|
|
log("info", "Partner user updated", request=request, user=user, logger_data={"user_id": user_id})
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "success",
|
||
|
|
"message": "Partner user updated successfully.",
|
||
|
|
"user": _user_to_dict(target_user, request),
|
||
|
|
},
|
||
|
|
status=200,
|
||
|
|
)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
log("error", "Partner update user exception", request=request, logger_data={"error": str(e)})
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerDeleteUserAPI(APIView):
|
||
|
|
"""
|
||
|
|
Delete a partner user (user with partner-related role).
|
||
|
|
Body: token, username, user_id (required).
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
user_id = data.get("user_id")
|
||
|
|
if not user_id:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "user_id is required."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
try:
|
||
|
|
target_user = User.objects.get(id=user_id)
|
||
|
|
except User.DoesNotExist:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "User not found."},
|
||
|
|
status=404,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Validate that the user has a partner-related role
|
||
|
|
partner_roles = ["partner", "partner_manager", "partner_staff", "partner_customer"]
|
||
|
|
if target_user.role not in partner_roles:
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "error",
|
||
|
|
"message": "User is not a partner-related user. Only users with partner roles can be deleted.",
|
||
|
|
},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
# Prevent deleting yourself
|
||
|
|
if target_user.id == user.id:
|
||
|
|
return JsonResponse(
|
||
|
|
{"status": "error", "message": "You cannot delete your own account."},
|
||
|
|
status=400,
|
||
|
|
)
|
||
|
|
|
||
|
|
username = target_user.username
|
||
|
|
target_user.delete()
|
||
|
|
|
||
|
|
log("info", "Partner user deleted", request=request, user=user, logger_data={"user_id": user_id, "username": username})
|
||
|
|
return JsonResponse(
|
||
|
|
{
|
||
|
|
"status": "success",
|
||
|
|
"message": f"Partner user '{username}' deleted successfully.",
|
||
|
|
},
|
||
|
|
status=200,
|
||
|
|
)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
log("error", "Partner delete user exception", request=request, logger_data={"error": str(e)})
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
# ============================================================================
|
||
|
|
# Partner List APIs (Filtered by Criteria)
|
||
|
|
# ============================================================================
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerListAllAPI(APIView):
|
||
|
|
"""
|
||
|
|
List All Partners API.
|
||
|
|
Body: token, username (required).
|
||
|
|
Returns: list of all partners.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request, error_status_code=True)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
partners = Partner.objects.all().order_by("-id")
|
||
|
|
partners_list = [_partner_to_dict(p, request) for p in partners]
|
||
|
|
|
||
|
|
return JsonResponse({
|
||
|
|
"status": "success",
|
||
|
|
"partners": partners_list,
|
||
|
|
"total_count": len(partners_list)
|
||
|
|
}, status=200)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerListKYCCompliantAPI(APIView):
|
||
|
|
"""
|
||
|
|
List KYC Compliant Partners API.
|
||
|
|
Body: token, username (required).
|
||
|
|
Returns: list of partners where is_kyc_compliant=True and kyc_compliance_status='approved'.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request, error_status_code=True)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
partners = Partner.objects.filter(
|
||
|
|
is_kyc_compliant=True,
|
||
|
|
kyc_compliance_status='approved'
|
||
|
|
).order_by("-id")
|
||
|
|
partners_list = [_partner_to_dict(p, request) for p in partners]
|
||
|
|
|
||
|
|
return JsonResponse({
|
||
|
|
"status": "success",
|
||
|
|
"partners": partners_list,
|
||
|
|
"total_count": len(partners_list)
|
||
|
|
}, status=200)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerListKYCPendingAPI(APIView):
|
||
|
|
"""
|
||
|
|
List KYC Pending Partners API.
|
||
|
|
Body: token, username (required).
|
||
|
|
Returns: list of partners where kyc_compliance_status='pending'.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request, error_status_code=True)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
partners = Partner.objects.filter(
|
||
|
|
kyc_compliance_status='pending'
|
||
|
|
).order_by("-id")
|
||
|
|
partners_list = [_partner_to_dict(p, request) for p in partners]
|
||
|
|
|
||
|
|
return JsonResponse({
|
||
|
|
"status": "success",
|
||
|
|
"partners": partners_list,
|
||
|
|
"total_count": len(partners_list)
|
||
|
|
}, status=200)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerListHighRiskAPI(APIView):
|
||
|
|
"""
|
||
|
|
List High Risk Partners API.
|
||
|
|
Body: token, username (required).
|
||
|
|
Returns: list of partners where kyc_compliance_status='high_risk'.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request, error_status_code=True)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
partners = Partner.objects.filter(
|
||
|
|
kyc_compliance_status='high_risk'
|
||
|
|
).order_by("-id")
|
||
|
|
partners_list = [_partner_to_dict(p, request) for p in partners]
|
||
|
|
|
||
|
|
return JsonResponse({
|
||
|
|
"status": "success",
|
||
|
|
"partners": partners_list,
|
||
|
|
"total_count": len(partners_list)
|
||
|
|
}, status=200)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|
||
|
|
|
||
|
|
|
||
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
||
|
|
class PartnerListJoinedThisWeekAPI(APIView):
|
||
|
|
"""
|
||
|
|
List Partners Joined This Week API.
|
||
|
|
Body: token, username (required).
|
||
|
|
Returns: list of partners created in the last 7 days.
|
||
|
|
|
||
|
|
Note: This API uses id-based filtering as a proxy for creation date.
|
||
|
|
For accurate results, consider adding a created_date field to the Partner model.
|
||
|
|
"""
|
||
|
|
|
||
|
|
def post(self, request):
|
||
|
|
try:
|
||
|
|
user, token, data, error_response = validate_token_and_get_user(request, error_status_code=True)
|
||
|
|
if error_response:
|
||
|
|
return error_response
|
||
|
|
|
||
|
|
# Calculate date range for this week
|
||
|
|
today = timezone.now().date()
|
||
|
|
week_start = today - timedelta(days=7)
|
||
|
|
|
||
|
|
# Since Partner model doesn't have created_date, we'll use id as a proxy
|
||
|
|
# Get the highest id to approximate recent partners
|
||
|
|
# This is a workaround - ideally Partner model should have created_date field
|
||
|
|
latest_partner = Partner.objects.order_by('-id').first()
|
||
|
|
|
||
|
|
if latest_partner:
|
||
|
|
# Get partners created in the last week based on id approximation
|
||
|
|
# This assumes sequential id assignment
|
||
|
|
# For accurate results, add created_date field to Partner model
|
||
|
|
partners = Partner.objects.filter(
|
||
|
|
id__gte=latest_partner.id - 1000 # Approximate filter
|
||
|
|
).order_by("-id")
|
||
|
|
|
||
|
|
# Alternative: If you want to add created_date field, use:
|
||
|
|
# partners = Partner.objects.filter(
|
||
|
|
# created_date__gte=week_start
|
||
|
|
# ).order_by("-created_date")
|
||
|
|
else:
|
||
|
|
partners = Partner.objects.none()
|
||
|
|
|
||
|
|
partners_list = [_partner_to_dict(p, request) for p in partners]
|
||
|
|
|
||
|
|
return JsonResponse({
|
||
|
|
"status": "success",
|
||
|
|
"partners": partners_list,
|
||
|
|
"total_count": len(partners_list),
|
||
|
|
"note": "This uses id-based approximation. Consider adding created_date field for accurate results."
|
||
|
|
}, status=200)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
return JsonResponse({"status": "error", "message": str(e)}, status=500)
|