All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 55s
317 lines
12 KiB
Python
317 lines
12 KiB
Python
import logging
|
|
from rest_framework import status
|
|
from rest_framework.views import APIView
|
|
from rest_framework.response import Response
|
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
|
from .shipping_client import ShippingServiceClient
|
|
from .models import Order, ReturnRequest, SupplierProfile
|
|
|
|
logger = logging.getLogger('api')
|
|
|
|
class ShippingHealthView(APIView):
|
|
permission_classes = [AllowAny]
|
|
|
|
def get(self, request):
|
|
client = ShippingServiceClient()
|
|
res = client.check_health()
|
|
is_ok = res.get('status', '').lower() in ('healthy', 'success')
|
|
return Response(res, status=status.HTTP_200_OK if is_ok else status.HTTP_503_SERVICE_UNAVAILABLE)
|
|
|
|
|
|
class ForwardServiceabilityView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
pincodes = request.data.get('pincodes')
|
|
service = request.data.get('service', 'express')
|
|
if not pincodes:
|
|
return Response({'error': 'pincodes is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
client = ShippingServiceClient()
|
|
res = client.check_forward_serviceability(pincodes, service=service)
|
|
return Response(res)
|
|
|
|
|
|
class ForwardCreatePickupView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
order_id = request.data.get('order_id')
|
|
if not order_id:
|
|
return Response({'error': 'order_id is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
order = Order.objects.filter(supplier=request.user, order_id=order_id).first()
|
|
if not order:
|
|
order = Order.objects.filter(supplier=request.user, id=order_id).first()
|
|
if not order:
|
|
return Response({'error': f'Order {order_id} not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
profile = getattr(request.user, 'profile', None)
|
|
pickup_details = request.data.get('pickup_details')
|
|
customer_details = request.data.get('customer_details')
|
|
product_details = request.data.get('product_details')
|
|
pkg_weight = request.data.get('weight') or request.data.get('package_weight')
|
|
|
|
client = ShippingServiceClient()
|
|
shipping_res = client.create_delivery_pickup(
|
|
order,
|
|
supplier_profile=profile,
|
|
pickup_details=pickup_details,
|
|
customer_details=customer_details,
|
|
product_details=product_details,
|
|
weight=pkg_weight
|
|
)
|
|
|
|
is_ok = shipping_res.get('status', '').lower() in ('success', 'healthy') or shipping_res.get('status_code') in (200, 201)
|
|
data = shipping_res.get('data', {}) if isinstance(shipping_res.get('data'), dict) else {}
|
|
awb = data.get('awb_number')
|
|
|
|
if not is_ok or not awb or shipping_res.get('status') == 'error':
|
|
return Response(
|
|
{'error': shipping_res.get('message') or 'Shipping service unavailable for location'},
|
|
status=status.HTTP_400_BAD_REQUEST
|
|
)
|
|
assigned_carrier = data.get('carrier')
|
|
if not assigned_carrier:
|
|
assigned_carrier = 'Delhivery Logistics' if str(awb).startswith(('DELHI', '179', '139', '142', '12', '14', '698')) else ('Ekart Logistics' if str(awb).startswith(('EKART', 'ELIT')) else 'Shadowfax Logistics')
|
|
|
|
order.carrier = assigned_carrier
|
|
order.tracking = awb
|
|
order.status = 'Ready to Ship'
|
|
order.save()
|
|
|
|
return Response(shipping_res)
|
|
|
|
|
|
class ForwardTrackView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request):
|
|
awb = request.query_params.get('awb') or request.query_params.get('tracking')
|
|
order_id = request.query_params.get('order_id')
|
|
|
|
if not awb and order_id:
|
|
order = Order.objects.filter(supplier=request.user, order_id=order_id).first()
|
|
if not order:
|
|
order = Order.objects.filter(supplier=request.user, id=order_id).first()
|
|
if order and order.tracking and order.tracking not in ('Pending', 'N/A'):
|
|
awb = order.tracking
|
|
|
|
if not awb:
|
|
return Response({'error': 'awb query parameter or valid order_id is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
client = ShippingServiceClient()
|
|
res = client.track_delivery_order(awb)
|
|
|
|
# Store logistics ETA internally in DB
|
|
try:
|
|
r_data = res.get('data', {}) if isinstance(res.get('data'), dict) else {}
|
|
eta_val = r_data.get('expected_delivery_date') or (r_data.get('order_details') or {}).get('expected_delivery_date') or r_data.get('eta')
|
|
if eta_val:
|
|
Order.objects.filter(tracking=str(awb).strip()).update(eta=str(eta_val), expected_delivery_date=str(eta_val))
|
|
if order_id:
|
|
Order.objects.filter(order_id=str(order_id).strip()).update(eta=str(eta_val), expected_delivery_date=str(eta_val))
|
|
except Exception as e:
|
|
logger.warning(f"Failed to persist ETA in ForwardTrackView: {e}")
|
|
|
|
return Response(res)
|
|
|
|
|
|
class ForwardCancelView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
order_id = request.data.get('order_id')
|
|
awb = request.data.get('awb_number')
|
|
reason = request.data.get('reason', 'Seller requested cancellation')
|
|
|
|
if not order_id and not awb:
|
|
return Response({'error': 'order_id or awb_number is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
order = None
|
|
if order_id:
|
|
order = Order.objects.filter(supplier=request.user, order_id=order_id).first()
|
|
if not order:
|
|
order = Order.objects.filter(supplier=request.user, id=order_id).first()
|
|
if order and not awb:
|
|
awb = order.tracking
|
|
|
|
client = ShippingServiceClient()
|
|
res = client.cancel_delivery_order(client_order_id=order_id or "ORD-CANCEL", awb_number=awb, reason=reason)
|
|
|
|
is_ok = res.get('status', '').lower() in ('success', 'healthy') or res.get('status_code') in (200, 201)
|
|
if is_ok and order:
|
|
order.status = 'Cancelled'
|
|
order.save()
|
|
|
|
return Response(res)
|
|
|
|
|
|
class ReverseServiceabilityView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
pincodes = request.data.get('pincodes')
|
|
if not pincodes:
|
|
return Response({'error': 'pincodes is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
client = ShippingServiceClient()
|
|
res = client.check_reverse_serviceability(pincodes)
|
|
return Response(res)
|
|
|
|
|
|
class ReverseCreatePickupView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
return_id = request.data.get('return_id')
|
|
if not return_id:
|
|
return Response({'error': 'return_id is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
ret = ReturnRequest.objects.filter(supplier=request.user, return_id=return_id).first()
|
|
if not ret:
|
|
ret = ReturnRequest.objects.filter(supplier=request.user, id=return_id).first()
|
|
if not ret:
|
|
return Response({'error': f'Return request {return_id} not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
profile = getattr(request.user, 'profile', None)
|
|
pickup_details = request.data.get('pickup_details')
|
|
return_details = request.data.get('return_details')
|
|
qc_details = request.data.get('qc_details')
|
|
|
|
client = ShippingServiceClient()
|
|
res = client.create_customer_return_pickup(
|
|
ret,
|
|
supplier_profile=profile,
|
|
pickup_details=pickup_details,
|
|
return_details=return_details,
|
|
qc_details=qc_details
|
|
)
|
|
|
|
is_ok = res.get('status', '').lower() in ('success', 'healthy') or res.get('status_code') in (200, 201)
|
|
if is_ok:
|
|
data = res.get('data', {}) if isinstance(res.get('data'), dict) else {}
|
|
awb = data.get('awb_number') or f"SFX-REV-{ret.id}"
|
|
ret.returning_tracking = awb
|
|
ret.status = 'In Transit'
|
|
ret.save()
|
|
|
|
return Response(res)
|
|
|
|
|
|
class ReverseTrackView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request):
|
|
client_request_id = request.query_params.get('client_request_id') or request.query_params.get('return_id')
|
|
if not client_request_id:
|
|
return Response({'error': 'client_request_id query parameter is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
client = ShippingServiceClient()
|
|
res = client.track_customer_return_pickup(client_request_id)
|
|
return Response(res)
|
|
|
|
|
|
class ReverseUpdateQCView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def put(self, request):
|
|
client_request_id = request.data.get('client_request_id') or request.data.get('return_id')
|
|
if not client_request_id:
|
|
return Response({'error': 'client_request_id is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
qc_check = request.data.get('qc_check', True)
|
|
serial_number = request.data.get('serial_number')
|
|
brand_name = request.data.get('brand_name')
|
|
item_name = request.data.get('item_name')
|
|
|
|
client = ShippingServiceClient()
|
|
res = client.update_return_qc(
|
|
client_request_id,
|
|
qc_check=qc_check,
|
|
serial_number=serial_number,
|
|
brand_name=brand_name,
|
|
item_name=item_name
|
|
)
|
|
return Response(res)
|
|
|
|
|
|
class ForwardLabelView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request):
|
|
order_id = request.query_params.get('order_id')
|
|
if not order_id:
|
|
return Response({'error': 'order_id is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
order = Order.objects.filter(supplier=request.user, order_id=order_id).first()
|
|
if not order:
|
|
order = Order.objects.filter(supplier=request.user, id=order_id).first()
|
|
if not order:
|
|
return Response({'error': f'Order {order_id} not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
profile = getattr(request.user, 'profile', None)
|
|
client = ShippingServiceClient()
|
|
res = client.generate_shipping_label(order, supplier_profile=profile)
|
|
if res.get('status') == 'error':
|
|
return Response(res, status=status.HTTP_400_BAD_REQUEST)
|
|
return Response(res)
|
|
|
|
|
|
class ReverseLabelView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request):
|
|
return_id = request.query_params.get('return_id')
|
|
if not return_id:
|
|
return Response({'error': 'return_id is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
ret = ReturnRequest.objects.filter(supplier=request.user, return_id=return_id).first()
|
|
if not ret:
|
|
ret = ReturnRequest.objects.filter(supplier=request.user, id=return_id).first()
|
|
if not ret:
|
|
return Response({'error': f'Return request {return_id} not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
profile = getattr(request.user, 'profile', None)
|
|
client = ShippingServiceClient()
|
|
res = client.generate_return_label(ret, supplier_profile=profile)
|
|
return Response(res)
|
|
|
|
|
|
class ForwardSchedulePickupView(APIView):
|
|
permission_classes = [IsAuthenticated]
|
|
|
|
def get(self, request):
|
|
carrier = request.query_params.get('carrier')
|
|
client = ShippingServiceClient()
|
|
res = client.get_pickup_capabilities(carrier)
|
|
return Response(res)
|
|
|
|
def post(self, request):
|
|
order_id = request.data.get('order_id')
|
|
if not order_id:
|
|
return Response({'error': 'order_id is required'}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
order = Order.objects.filter(supplier=request.user, order_id=order_id).first()
|
|
if not order:
|
|
order = Order.objects.filter(supplier=request.user, id=order_id).first()
|
|
if not order:
|
|
return Response({'error': f'Order {order_id} not found'}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
pickup_date = request.data.get('pickup_date') or request.data.get('date')
|
|
pickup_time = request.data.get('pickup_time') or request.data.get('time') or request.data.get('slot')
|
|
package_count = request.data.get('package_count') or 1
|
|
notes = request.data.get('notes')
|
|
profile = getattr(request.user, 'profile', None)
|
|
|
|
client = ShippingServiceClient()
|
|
res = client.schedule_pickup(
|
|
order,
|
|
pickup_date=pickup_date,
|
|
pickup_time=pickup_time,
|
|
package_count=package_count,
|
|
notes=notes,
|
|
supplier_profile=profile
|
|
)
|
|
return Response(res)
|
|
|