diff --git a/orders/views.py b/orders/views.py index 3f3ccf0..7b2b2ac 100644 --- a/orders/views.py +++ b/orders/views.py @@ -1,6 +1,7 @@ import json import requests from django.conf import settings +from django.db.models import Q import logging audit_logger = logging.getLogger('audit') from rest_framework import status, permissions @@ -823,9 +824,32 @@ class OrderTrackView(APIView): except Order.DoesNotExist: pass - awb_number = (order.awb_number if order else awb_query) or None + seller_order = None + if order: + seller_order = SellerOrder.objects.filter(Q(order_id__startswith=f"{order.id}-") | Q(order_id=str(order.id))).first() + elif order_id: + seller_order = SellerOrder.objects.filter(order_id=str(order_id)).first() + + awb_number = (order.awb_number if order and order.awb_number else None) or (seller_order.tracking if seller_order and seller_order.tracking != 'Pending' else None) or awb_query or None raw_status = (order.status if order else 'pending').lower() + # Dynamic carrier identification + detected_carrier = None + if order and order.shipping_carrier and order.shipping_carrier not in ('Pending', ''): + detected_carrier = order.shipping_carrier + elif seller_order and seller_order.carrier and seller_order.carrier not in ('Pending', ''): + detected_carrier = seller_order.carrier + elif awb_number: + if str(awb_number).isdigit() or str(awb_number).startswith(('698', 'DELHI', '14', '12', '179', '139', '142')): + detected_carrier = 'Delhivery Logistics' + elif str(awb_number).startswith(('EKART', 'ELIT')): + detected_carrier = 'Ekart Logistics' + elif str(awb_number).startswith('SFX'): + detected_carrier = 'Shadowfax Express' + + if not detected_carrier: + detected_carrier = 'Delhivery Logistics' if (awb_number and str(awb_number).isdigit()) else ('Shadowfax Express' if awb_number else 'Awaiting Dispatch') + # Call shippingservice track API if AWB is present live_data = None if awb_number: @@ -844,6 +868,79 @@ class OrderTrackView(APIView): except Exception: pass + # Direct Delhivery live tracking check if shippingservice data is empty or upstream format + if (not live_data or 'data' not in live_data or not live_data.get('data', {}).get('tracking_history')) and (str(awb_number).isdigit() or str(awb_number).startswith(('698', 'DELHI', '14', '12'))): + try: + dlh_token = 'e70dfd63665335ee6e0a1094f6d34e17a126f5a6' + dlh_url = f"https://track.delhivery.com/api/v1/packages/json/?waybill={awb_number}" + dlh_resp = requests.get(dlh_url, headers={'Authorization': f'Token {dlh_token}'}, timeout=6) + if dlh_resp.status_code == 200: + dlh_data = dlh_resp.json() + shipments = dlh_data.get('ShipmentData', []) + if shipments: + ship = shipments[0].get('Shipment', {}) + st_info = ship.get('Status', {}) + curr_st = st_info.get('Status') or 'In Transit' + scans = ship.get('Scans', []) + formatted_history = [] + for sc in scans: + scan_detail = sc.get('ScanDetail', {}) + raw_scan = scan_detail.get('Scan', '') + instr = scan_detail.get('Instructions', '') + combined = (raw_scan + ' ' + instr).lower() + st_key = 'manifested' if 'manifest' in combined else ('picked_up' if 'picked up' in combined else ('in_transit' if 'transit' in combined or 'bag' in combined or 'center' in combined else raw_scan.lower().replace(' ', '_'))) + formatted_history.append({ + 'status': st_key, + 'status_display': instr or raw_scan, + 'remarks': instr, + 'location': scan_detail.get('ScannedLocation') or 'Hub', + 'timestamp': scan_detail.get('ScanDateTime') or scan_detail.get('StatusDateTime') + }) + norm_st = 'delivered' if 'delivered' in curr_st.lower() else ('out_for_delivery' if 'out for delivery' in curr_st.lower() else ('in_transit' if 'transit' in curr_st.lower() or any(h['status'] == 'picked_up' for h in formatted_history) else curr_st.lower().replace(' ', '_'))) + live_data = { + 'status': 'success', + 'carrier': 'Delhivery Logistics', + 'data': { + 'carrier': 'Delhivery Logistics', + 'awb_number': str(awb_number), + 'current_status': norm_st, + 'status_display': f"Delhivery: {curr_st} ({st_info.get('Instructions', '')})", + 'expected_delivery_date': ship.get('ExpectedDeliveryDate'), + 'picked_up_date': ship.get('PickedupDate') or ship.get('PickUpDate'), + 'tracking_history': formatted_history, + 'order_details': { + 'carrier': 'Delhivery Logistics', + 'awb_number': str(awb_number), + 'origin': ship.get('Origin'), + 'destination': ship.get('Destination'), + 'expected_delivery_date': ship.get('ExpectedDeliveryDate'), + 'picked_up_date': ship.get('PickedupDate') or ship.get('PickUpDate') + } + } + } + except Exception as e: + audit_logger.warning(f"Direct Delhivery track check notice: {e}") + + # Update database order status if carrier confirms picked up or in transit + is_picked_up_live = False + if live_data and isinstance(live_data.get('data'), dict): + cur = str(live_data['data'].get('current_status') or '').lower() + th = live_data['data'].get('tracking_history') or [] + if any(cur == s or s in cur for s in ['picked_up', 'in_transit', 'shipped', 'delivered', 'out_for_delivery']): + is_picked_up_live = True + elif any(h.get('status') in ['picked_up', 'in_transit'] for h in th): + is_picked_up_live = True + + if is_picked_up_live and order: + if order.status.lower() in ['pending', 'confirmed', 'ready to ship', 'ready_to_ship']: + order.status = 'shipped' + order.shipping_status = 'in_transit' + if detected_carrier: + order.shipping_carrier = detected_carrier + order.save() + if seller_order and seller_order.status in ['Pending Acceptance', 'Ready to Ship']: + SellerOrder.objects.filter(Q(order_id__startswith=f"{order.id}-") | Q(order_id=str(order.id))).update(status='Shipped') + if not live_data or 'data' not in live_data: placed_ts = order.placed_at.strftime('%Y-%m-%dT%H:%M:%SZ') if (order and getattr(order, 'placed_at', None)) else '2026-10-09T10:00:00Z' @@ -881,7 +978,7 @@ class OrderTrackView(APIView): 'data': { 'awb_number': awb_number or ('Cancelled' if raw_status in ['cancelled', 'canceled'] else 'Pending Dispatch'), 'current_status': display_status, - 'carrier': 'Shadowfax Express' if awb_number else 'Awaiting Dispatch', + 'carrier': detected_carrier, 'tracking_history': tracking_history } } @@ -898,14 +995,18 @@ class OrderTrackView(APIView): # Ensure executive rider details are stripped for customer privacy customer_live_tracking = dict(live_data.get('data', {})) if isinstance(live_data.get('data'), dict) else {} customer_live_tracking.pop('rider_details', None) + carrier_name = customer_live_tracking.get('carrier') or detected_carrier or 'Delhivery Logistics' + customer_live_tracking['carrier'] = carrier_name result = { 'order_id': order.id if order else order_id, 'awb_number': awb_number or (order.awb_number if order else None), - 'carrier': 'Shadowfax Express' if (order and order.awb_number) else 'Awaiting Dispatch', + 'carrier': carrier_name, 'order_status': order.status if order else raw_status, 'placed_at': order.placed_at if order else None, 'shipping_address': order.shipping_address if order else '', + 'expected_delivery_date': customer_live_tracking.get('expected_delivery_date'), + 'picked_up_date': customer_live_tracking.get('picked_up_date'), 'live_tracking': customer_live_tracking }