feat: add shipping client api, views, and pickup scheduling architecture docs
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 39s
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 39s
This commit is contained in:
parent
c3cb4b3637
commit
d2b1a29fa3
3 changed files with 137 additions and 0 deletions
|
|
@ -1004,6 +1004,67 @@ class ShippingServiceClient:
|
|||
'time_slot_label': 'Standard Daily Hub Sweep (Morning & Evening)' if is_ekart else ('Automated Cutoff Sweep' if not is_delhivery else '')
|
||||
}
|
||||
|
||||
def get_pickup_schedule(self, awb_number):
|
||||
"""
|
||||
Check courier pickup schedule (date, time, slot, pickup_id, location, carrier, status)
|
||||
for a given tracking / AWB number via shipping microservice.
|
||||
"""
|
||||
trk = str(awb_number or '').strip()
|
||||
if not trk or trk in ('Pending', 'N/A'):
|
||||
return {'status': 'error', 'message': 'Valid tracking ID / AWB number is required'}
|
||||
|
||||
target_urls = [
|
||||
f"{self.base_url}/api/v1/carrier/pickup-schedule/?tracking_id={trk}",
|
||||
f"http://127.0.0.1:8086/api/v1/carrier/pickup-schedule/?tracking_id={trk}",
|
||||
f"http://localhost:8086/api/v1/carrier/pickup-schedule/?tracking_id={trk}",
|
||||
f"https://beta-shipping.tradhox.com/api/v1/carrier/pickup-schedule/?tracking_id={trk}"
|
||||
]
|
||||
for u in target_urls:
|
||||
try:
|
||||
res = requests.get(u, headers=self._get_headers(), timeout=5, verify=False)
|
||||
if res.status_code == 200:
|
||||
return res.json()
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# Direct database / local order fallback
|
||||
try:
|
||||
from .models import Order
|
||||
ord_obj = Order.objects.filter(tracking=trk).first()
|
||||
if not ord_obj and trk.startswith('TRDX-ORD-'):
|
||||
ord_obj = Order.objects.filter(order_id=trk).first()
|
||||
if ord_obj:
|
||||
p_date = None
|
||||
p_time = None
|
||||
if ord_obj.eta and 'Pickup:' in str(ord_obj.eta):
|
||||
import re
|
||||
m_d = re.search(r'Pickup:\s*([\d-]+)', str(ord_obj.eta))
|
||||
m_t = re.search(r'\(([\d:]+)\)', str(ord_obj.eta))
|
||||
if m_d: p_date = m_d.group(1)
|
||||
if m_t: p_time = m_t.group(1)
|
||||
|
||||
p_slot = ord_obj.eta.replace('Pickup:', '').strip() if ord_obj.eta else 'Afternoon Slot'
|
||||
return {
|
||||
'status': 'success',
|
||||
'tracking_id': trk,
|
||||
'order_id': ord_obj.order_id,
|
||||
'carrier': ord_obj.carrier,
|
||||
'carrier_display': ord_obj.carrier,
|
||||
'pickup_scheduled': bool(ord_obj.pickup_id),
|
||||
'pickup_id': ord_obj.pickup_id,
|
||||
'pickup_date': p_date or time.strftime('%Y-%m-%d'),
|
||||
'pickup_time': p_time or '14:00:00',
|
||||
'pickup_slot': p_slot,
|
||||
'status_display': f"Pickup Scheduled with {ord_obj.carrier} (ID: #{ord_obj.pickup_id})" if ord_obj.pickup_id else f"Ready for Pickup with {ord_obj.carrier}"
|
||||
}
|
||||
except Exception as e:
|
||||
logger.warning(f"Order fallback in get_pickup_schedule: {e}")
|
||||
|
||||
return {
|
||||
'status': 'error',
|
||||
'message': f"No pickup schedule found for tracking {trk}"
|
||||
}
|
||||
|
||||
def schedule_pickup(self, order, pickup_date=None, pickup_time=None, package_count=1, notes=None, supplier_profile=None):
|
||||
"""
|
||||
Schedule / reschedule courier pickup for an order with assigned carrier.
|
||||
|
|
|
|||
|
|
@ -1750,6 +1750,12 @@ class OrderViewSet(viewsets.ModelViewSet):
|
|||
'order': OrderSerializer(order).data
|
||||
})
|
||||
|
||||
@drf_action(detail=True, methods=['get'])
|
||||
def pickup_schedule(self, request, pk=None):
|
||||
order = self.get_object()
|
||||
awb = request.query_params.get('awb') or request.query_params.get('tracking_id') or order.tracking
|
||||
res = shipping_client.get_pickup_schedule(awb)
|
||||
return Response(res)
|
||||
|
||||
@drf_action(detail=True, methods=['get'])
|
||||
def print_label(self, request, pk=None):
|
||||
|
|
|
|||
|
|
@ -153,3 +153,73 @@ class Order(models.Model):
|
|||
- **Tradhox User Experience**:
|
||||
- In Tradhox Supplier Central, once an order is manifested and scheduled, Tradhox surfaces the active **Pickup Request ID (`PR #328095871`)** and **`PICKUP SCHEDULED`** badge.
|
||||
- Merchants do not need to manually click "Add to Pickup" inside the Delhivery One portal; the courier executive will collect all ready packages for warehouse `SAM`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Check Pickup Schedule by Tracking ID (AWB) Specification
|
||||
|
||||
### 7.1. REST Endpoints
|
||||
Clients can query the pickup schedule using either endpoint:
|
||||
|
||||
- **Primary Route**:
|
||||
`GET /api/v1/carrier/pickup-schedule/?tracking_id=<AWB>`
|
||||
- **Unified Alias**:
|
||||
`GET /api/v1/carrier/schedule-pickup/?tracking_id=<AWB>`
|
||||
- **POST Route**:
|
||||
`POST /api/v1/carrier/pickup-schedule/` with JSON `{"tracking_id": "<AWB>"}`
|
||||
|
||||
#### Supported Query Parameters
|
||||
- `tracking_id` / `awb` / `tracking` / `waybill`: The carrier waybill or client order ID (e.g. `69873010000232`).
|
||||
|
||||
### 7.2. Response Schema
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"tracking_id": "69873010000232",
|
||||
"order_id": "32-18",
|
||||
"carrier": "DELHIVERY",
|
||||
"carrier_display": "Delhivery Logistics",
|
||||
"pickup_scheduled": true,
|
||||
"pickup_id": "328095871",
|
||||
"pickup_date": "2026-10-14",
|
||||
"pickup_time": "10:00:00",
|
||||
"pickup_slot": "Morning Slot (10:00 AM – 1:00 PM)",
|
||||
"pickup_location": "SAM",
|
||||
"shipment_status": "Manifested",
|
||||
"pickup_status": "CONFIRMED",
|
||||
"status_display": "Pickup Confirmed with Delhivery Logistics (PR #328095871) for 2026-10-14 (Morning Slot (10:00 AM – 1:00 PM))",
|
||||
"destination": {
|
||||
"city": "Kanchipuram",
|
||||
"pincode": 600059
|
||||
},
|
||||
"consignee": {
|
||||
"name": "Vignesh Krishnasamy",
|
||||
"city": "Kanchipuram",
|
||||
"state": "Tamil Nadu",
|
||||
"pincode": 600059
|
||||
},
|
||||
"scans": [
|
||||
{
|
||||
"scan": "Manifested",
|
||||
"instructions": "Manifest uploaded",
|
||||
"location": "Mettupalayam_IshwaryNgr_D (Tamil Nadu)",
|
||||
"timestamp": "2026-10-12T19:04:35.275"
|
||||
}
|
||||
],
|
||||
"details": {
|
||||
"expected_package_count": 1,
|
||||
"manifest_date": "2026-10-12T19:04:35.245",
|
||||
"picked_up_date": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.3. Resolution Hierarchy
|
||||
1. **`shipping_pickupschedule` Table**: Checks if a local record exists.
|
||||
2. **Live Carrier Tracking API**:
|
||||
- For **Delhivery**, calls `/api/v1/packages/json/?waybill={trk}`, extracting origin warehouse, consignee address, and shipment status.
|
||||
- Cross-checks with active warehouse pickup requests.
|
||||
3. **Cross-Database Order Lookup**:
|
||||
- Queries `api_order` in `customerprofile_beta` to correlate `pickup_id` and ETA slot.
|
||||
4. **Auto-Caching**: Updates the `PickupSchedule` model so subsequent lookups are instant.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue