diff --git a/shipping/__pycache__/carrier_allocator.cpython-314.pyc b/shipping/__pycache__/carrier_allocator.cpython-314.pyc
index c3868fc..0551ffa 100644
Binary files a/shipping/__pycache__/carrier_allocator.cpython-314.pyc and b/shipping/__pycache__/carrier_allocator.cpython-314.pyc differ
diff --git a/shipping/__pycache__/sfx_client.cpython-314.pyc b/shipping/__pycache__/sfx_client.cpython-314.pyc
index 5a09724..f33b251 100644
Binary files a/shipping/__pycache__/sfx_client.cpython-314.pyc and b/shipping/__pycache__/sfx_client.cpython-314.pyc differ
diff --git a/shipping/__pycache__/tests.cpython-314.pyc b/shipping/__pycache__/tests.cpython-314.pyc
index 1367802..dc7f942 100644
Binary files a/shipping/__pycache__/tests.cpython-314.pyc and b/shipping/__pycache__/tests.cpython-314.pyc differ
diff --git a/shipping/__pycache__/urls.cpython-314.pyc b/shipping/__pycache__/urls.cpython-314.pyc
index d682b10..a60c066 100644
Binary files a/shipping/__pycache__/urls.cpython-314.pyc and b/shipping/__pycache__/urls.cpython-314.pyc differ
diff --git a/shipping/__pycache__/views.cpython-314.pyc b/shipping/__pycache__/views.cpython-314.pyc
index bc8576f..fec5d26 100644
Binary files a/shipping/__pycache__/views.cpython-314.pyc and b/shipping/__pycache__/views.cpython-314.pyc differ
diff --git a/shipping/carrier_allocator.py b/shipping/carrier_allocator.py
index 04dbbbd..3c60c31 100644
--- a/shipping/carrier_allocator.py
+++ b/shipping/carrier_allocator.py
@@ -203,16 +203,47 @@ def resolve_city_state_by_pincode(pincode, default_city=None, default_state=None
return ('Bengaluru', 'Karnataka')
-def check_shadowfax_availability(pickup_pincode, drop_pincode, service='express', weight=500, env='production'):
+def check_shadowfax_availability(pickup_pincode, drop_pincode, service='express', weight=500, env='production', token=None, use_mock=False):
"""
Checks Shadowfax pincode serviceability and logistics rate estimation directly from live Shadowfax API.
+ Provides detailed first-mile (pickup hub) and last-mile (doorstep delivery) status.
"""
weight_slabs = max(1, int(weight) // 500)
estimated_rate = round(45.0 + (weight_slabs * 15.0), 2)
+ p_city, p_state = resolve_city_state_by_pincode(pickup_pincode)
+ d_city, d_state = resolve_city_state_by_pincode(drop_pincode)
+
+ if use_mock:
+ return {
+ "carrier": "SHADOWFAX",
+ "serviceable": True,
+ "cod_available": True,
+ "estimated_cost": estimated_rate,
+ "currency": "INR",
+ "first_mile": {
+ "serviceable": True,
+ "pincode": str(pickup_pincode),
+ "city": p_city,
+ "state": p_state,
+ "hub_active": True,
+ "pickup_type": "Seller Store / Warehouse Sweep",
+ "message": f"First-mile pickup serviceable in {p_city}, {p_state} (Simulation)"
+ },
+ "last_mile": {
+ "serviceable": True,
+ "pincode": str(drop_pincode),
+ "city": d_city,
+ "state": d_state,
+ "cod_available": True,
+ "delivery_type": "Doorstep Delivery (Express)",
+ "message": f"Last-mile delivery serviceable in {d_city}, {d_state} (Simulation)"
+ },
+ "details": {"mock": True, "pincodes": [str(pickup_pincode), str(drop_pincode)]}
+ }
base_url = get_base_url(env)
- token = get_default_token(env)
- headers = {"Authorization": f"Token {token}", "Content-Type": "application/json"}
+ auth_token = str(token).strip() if token else get_default_token(env)
+ headers = {"Authorization": f"Token {auth_token}", "Content-Type": "application/json"}
pincodes_str = f"{pickup_pincode},{drop_pincode}"
sfx_service = "express" if service == "express" else "customer_delivery"
url = f"{base_url}/v1/clients/serviceability/?service={sfx_service}&page=1&count=100&pincodes={pincodes_str}"
@@ -223,49 +254,149 @@ def check_shadowfax_availability(pickup_pincode, drop_pincode, service='express'
parsed = json.loads(res.get('response', '{}')) if isinstance(res.get('response'), str) else res.get('response', {})
data = parsed.get('data', {})
p_list = data.get('pincodes', []) if isinstance(data, dict) else []
+
+ pickup_info = next((p for p in p_list if str(p.get('pincode')) == str(pickup_pincode)), None)
drop_info = next((p for p in p_list if str(p.get('pincode')) == str(drop_pincode)), None)
-
- if drop_info:
- return {
- "carrier": "SHADOWFAX",
- "serviceable": drop_info.get('serviceable', True),
- "cod_available": drop_info.get('cod_available', True),
- "estimated_cost": estimated_rate,
- "currency": "INR",
- "details": drop_info
- }
+
+ if str(pickup_pincode) == str(drop_pincode) and p_list:
+ pickup_info = drop_info = p_list[0]
+
+ fm_ok = pickup_info.get('serviceable', True) if pickup_info else True
+ lm_ok = drop_info.get('serviceable', True) if drop_info else True
+ cod_ok = drop_info.get('cod_available', True) if drop_info else True
+
+ fm_city = (pickup_info.get('city') if pickup_info else None) or p_city
+ fm_state = (pickup_info.get('state') if pickup_info else None) or p_state
+ lm_city = (drop_info.get('city') if drop_info else None) or d_city
+ lm_state = (drop_info.get('state') if drop_info else None) or d_state
+
+ overall_serviceable = bool(fm_ok and lm_ok)
+
+ first_mile = {
+ "serviceable": bool(fm_ok),
+ "pincode": str(pickup_pincode),
+ "city": fm_city,
+ "state": fm_state,
+ "hub_active": bool(fm_ok),
+ "pickup_type": "Seller Store / Warehouse Sweep",
+ "message": f"First-mile pickup serviceable in {fm_city}, {fm_state}" if fm_ok else f"Pickup pincode {pickup_pincode} not serviceable by Shadowfax"
+ }
+
+ last_mile = {
+ "serviceable": bool(lm_ok),
+ "pincode": str(drop_pincode),
+ "city": lm_city,
+ "state": lm_state,
+ "cod_available": bool(cod_ok),
+ "delivery_type": "Doorstep Delivery (Express)",
+ "message": f"Last-mile delivery serviceable in {lm_city}, {lm_state}" if lm_ok else f"Destination pincode {drop_pincode} not serviceable by Shadowfax"
+ }
+
return {
"carrier": "SHADOWFAX",
- "serviceable": True,
- "cod_available": True,
- "estimated_cost": estimated_rate,
+ "serviceable": overall_serviceable,
+ "cod_available": bool(cod_ok),
+ "estimated_cost": estimated_rate if overall_serviceable else None,
"currency": "INR",
- "details": parsed
+ "first_mile": first_mile,
+ "last_mile": last_mile,
+ "details": drop_info or parsed
}
else:
+ first_mile = {
+ "serviceable": False,
+ "pincode": str(pickup_pincode),
+ "city": p_city,
+ "state": p_state,
+ "hub_active": False,
+ "pickup_type": "Seller Store / Warehouse Sweep",
+ "message": f"SFX API returned status {res.get('status_code')}"
+ }
+ last_mile = {
+ "serviceable": False,
+ "pincode": str(drop_pincode),
+ "city": d_city,
+ "state": d_state,
+ "cod_available": False,
+ "delivery_type": "Doorstep Delivery (Express)",
+ "message": f"SFX API returned status {res.get('status_code')}"
+ }
return {
"carrier": "SHADOWFAX",
"serviceable": False,
"cod_available": False,
"estimated_cost": None,
+ "first_mile": first_mile,
+ "last_mile": last_mile,
"error": f"SFX API returned status {res.get('status_code')}"
}
except Exception as e:
+ first_mile = {
+ "serviceable": False,
+ "pincode": str(pickup_pincode),
+ "city": p_city,
+ "state": p_state,
+ "hub_active": False,
+ "pickup_type": "Seller Store / Warehouse Sweep",
+ "message": str(e)
+ }
+ last_mile = {
+ "serviceable": False,
+ "pincode": str(drop_pincode),
+ "city": d_city,
+ "state": d_state,
+ "cod_available": False,
+ "delivery_type": "Doorstep Delivery (Express)",
+ "message": str(e)
+ }
return {
"carrier": "SHADOWFAX",
"serviceable": False,
"cod_available": False,
"estimated_cost": None,
+ "first_mile": first_mile,
+ "last_mile": last_mile,
"error": str(e)
}
-def check_ekart_availability(pickup_pincode, drop_pincode, weight=500, payment_type='Prepaid', invoice_amount=1000):
+def check_ekart_availability(pickup_pincode, drop_pincode, weight=500, payment_type='Prepaid', invoice_amount=1000, use_mock=False):
"""
Checks Ekart pincode serviceability and logistics rate estimation directly from live Ekart API.
+ Provides detailed first-mile and last-mile breakdown.
"""
weight_slabs = max(1, int(weight) // 500)
estimated_rate = round(38.0 + (weight_slabs * 12.0), 2)
+ p_city, p_state = resolve_city_state_by_pincode(pickup_pincode)
+ d_city, d_state = resolve_city_state_by_pincode(drop_pincode)
+
+ if use_mock:
+ return {
+ "carrier": "EKART",
+ "serviceable": True,
+ "cod_available": True,
+ "estimated_cost": estimated_rate,
+ "currency": "INR",
+ "first_mile": {
+ "serviceable": True,
+ "pincode": str(pickup_pincode),
+ "city": p_city,
+ "state": p_state,
+ "hub_active": True,
+ "pickup_type": "Ekart Hub Sweep",
+ "message": f"First-mile pickup serviceable in {p_city}, {p_state} (Simulation)"
+ },
+ "last_mile": {
+ "serviceable": True,
+ "pincode": str(drop_pincode),
+ "city": d_city,
+ "state": d_state,
+ "cod_available": True,
+ "delivery_type": "Doorstep Surface/Air Delivery",
+ "message": f"Last-mile delivery serviceable in {d_city}, {d_state} (Simulation)"
+ },
+ "details": {"mock": True}
+ }
client = EkartAPIClient()
try:
@@ -303,49 +434,133 @@ def check_ekart_availability(pickup_pincode, drop_pincode, weight=500, payment_t
except Exception:
pass
+ first_mile = {
+ "serviceable": bool(serviceable),
+ "pincode": str(pickup_pincode),
+ "city": p_city,
+ "state": p_state,
+ "hub_active": bool(serviceable),
+ "pickup_type": "Ekart Hub Sweep",
+ "message": f"First-mile pickup serviceable in {p_city}, {p_state}" if serviceable else f"Pickup pincode {pickup_pincode} not serviceable"
+ }
+
+ last_mile = {
+ "serviceable": bool(serviceable),
+ "pincode": str(drop_pincode),
+ "city": d_city,
+ "state": d_state,
+ "cod_available": bool(cod_available),
+ "delivery_type": "Doorstep Surface/Air Delivery",
+ "message": f"Last-mile delivery serviceable in {d_city}, {d_state}" if serviceable else f"Destination pincode {drop_pincode} not serviceable"
+ }
+
return {
"carrier": "EKART",
"serviceable": bool(serviceable),
"cod_available": bool(cod_available),
- "estimated_cost": live_cost,
+ "estimated_cost": live_cost if serviceable else None,
"currency": "INR",
+ "first_mile": first_mile,
+ "last_mile": last_mile,
"details": res
}
except Exception as e:
+ first_mile = {
+ "serviceable": False,
+ "pincode": str(pickup_pincode),
+ "city": p_city,
+ "state": p_state,
+ "hub_active": False,
+ "pickup_type": "Ekart Hub Sweep",
+ "message": str(e)
+ }
+ last_mile = {
+ "serviceable": False,
+ "pincode": str(drop_pincode),
+ "city": d_city,
+ "state": d_state,
+ "cod_available": False,
+ "delivery_type": "Doorstep Surface/Air Delivery",
+ "message": str(e)
+ }
return {
"carrier": "EKART",
"serviceable": False,
"cod_available": False,
"estimated_cost": None,
+ "first_mile": first_mile,
+ "last_mile": last_mile,
"error": str(e)
}
-def check_delhivery_availability(pickup_pincode, drop_pincode, weight=500, payment_type='Prepaid'):
+def check_delhivery_availability(pickup_pincode, drop_pincode, weight=500, payment_type='Prepaid', api_token=None, use_mock=False):
"""
Checks Delhivery pincode serviceability and logistics rate estimation directly
against official Delhivery serviceability matrix (18,699 pincodes) and live Delhivery API.
+ Provides detailed first-mile (pickup hub) and last-mile (doorstep delivery) status.
"""
weight_slabs = max(1, int(weight) // 500)
estimated_rate = round(35.0 + (weight_slabs * 11.0), 2)
is_cod = (str(payment_type).upper() == 'COD')
- # Step 1: Validate against official Delhivery serviceability matrix
- route_ok, route_msg, drop_info, pickup_info = check_delhivery_route_serviceability(
- pickup_pincode=pickup_pincode,
- drop_pincode=drop_pincode,
- is_cod=is_cod
- )
+ # Step 1: Validate individual first-mile and last-mile against Delhivery 18,699 database
+ p_ok, p_msg, pickup_info = is_delhivery_serviceable(pickup_pincode, is_cod=False)
+ d_ok, d_msg, drop_info = is_delhivery_serviceable(drop_pincode, is_cod=is_cod)
- if not route_ok:
+ p_city = (pickup_info.get('city') if pickup_info else None) or resolve_city_state_by_pincode(pickup_pincode)[0]
+ p_state = (pickup_info.get('state') if pickup_info else None) or resolve_city_state_by_pincode(pickup_pincode)[1]
+ p_st_code = pickup_info.get('state_code', '') if pickup_info else ''
+
+ d_city = (drop_info.get('city') if drop_info else None) or resolve_city_state_by_pincode(drop_pincode)[0]
+ d_state = (drop_info.get('state') if drop_info else None) or resolve_city_state_by_pincode(drop_pincode)[1]
+ d_st_code = drop_info.get('state_code', '') if drop_info else ''
+ cod_avail = bool(drop_info.get('cod', True)) if drop_info else False
+
+ first_mile = {
+ "serviceable": bool(p_ok),
+ "pincode": str(pickup_pincode),
+ "city": p_city,
+ "state": p_state,
+ "state_code": p_st_code,
+ "reverse_pickup": bool(pickup_info.get('reverse_pickup', True)) if pickup_info else False,
+ "pickup_type": "B2C Surface / Express Hub Sweep",
+ "message": f"First-mile pickup serviceable in {p_city}, {p_state}" if p_ok else f"Pickup: {p_msg}"
+ }
+
+ last_mile = {
+ "serviceable": bool(d_ok),
+ "pincode": str(drop_pincode),
+ "city": d_city,
+ "state": d_state,
+ "state_code": d_st_code,
+ "cod_available": cod_avail,
+ "cash_support": bool(drop_info.get('cash', True)) if drop_info else False,
+ "delivery_type": "Doorstep Express / Surface Delivery",
+ "message": f"Last-mile delivery serviceable in {d_city}, {d_state}" if d_ok else f"Destination: {d_msg}"
+ }
+
+ route_serviceable = bool(p_ok and d_ok)
+
+ if not route_serviceable:
+ err_parts = []
+ if not p_ok:
+ err_parts.append(f"Pickup: {p_msg}")
+ if not d_ok:
+ err_parts.append(f"Destination: {d_msg}")
return {
"carrier": "DELHIVERY",
"serviceable": False,
- "cod_available": False,
+ "cod_available": cod_avail,
"estimated_cost": None,
- "error": route_msg,
+ "error": " | ".join(err_parts),
+ "city": d_city,
+ "state": d_state,
+ "state_code": d_st_code,
+ "first_mile": first_mile,
+ "last_mile": last_mile,
"details": {
- "route_message": route_msg,
+ "route_message": " | ".join(err_parts),
"drop_info": drop_info,
"pickup_info": pickup_info
}
@@ -358,60 +573,68 @@ def check_delhivery_availability(pickup_pincode, drop_pincode, weight=500, payme
"pickup_info": pickup_info
}
- try:
- client = DelhiveryAPIClient()
- rate_res = client.get_rate_estimate(
- origin_pin=pickup_pincode,
- dest_pin=drop_pincode,
- weight=weight,
- mode="S",
- payment_type=payment_type
- )
- if isinstance(rate_res, dict) and rate_res.get('total_amount'):
- live_cost = float(rate_res['total_amount'])
- api_details['rate_estimate'] = rate_res
- except Exception as e:
- api_details['rate_api_warning'] = str(e)
+ if not use_mock:
+ try:
+ client = DelhiveryAPIClient(api_token=api_token)
+ rate_res = client.get_rate_estimate(
+ origin_pin=pickup_pincode,
+ dest_pin=drop_pincode,
+ weight=weight,
+ mode="S",
+ payment_type=payment_type
+ )
+ if isinstance(rate_res, dict) and rate_res.get('total_amount'):
+ live_cost = float(rate_res['total_amount'])
+ api_details['rate_estimate'] = rate_res
+ except Exception as e:
+ api_details['rate_api_warning'] = str(e)
return {
"carrier": "DELHIVERY",
"serviceable": True,
- "cod_available": bool(drop_info.get('cod', True)),
+ "cod_available": cod_avail,
"estimated_cost": live_cost,
"currency": "INR",
- "city": drop_info.get('city'),
- "state": drop_info.get('state'),
- "state_code": drop_info.get('state_code'),
+ "city": d_city,
+ "state": d_state,
+ "state_code": d_st_code,
+ "first_mile": first_mile,
+ "last_mile": last_mile,
"details": api_details
}
-def check_all_carriers_availability(pickup_pincode, drop_pincode, payment_type='Prepaid', weight=500, env='production'):
+def check_all_carriers_availability(pickup_pincode, drop_pincode, payment_type='Prepaid', weight=500, env='production', sfx_token=None, delhivery_token=None, use_mock=False):
"""
- Evaluates serviceability and rate estimates across all registered carriers (Shadowfax, Ekart, Delhivery) via live APIs.
+ Evaluates serviceability, first-mile, and last-mile delivery across all registered carriers (Shadowfax, Delhivery, Ekart).
"""
sfx_res = check_shadowfax_availability(
pickup_pincode=pickup_pincode,
drop_pincode=drop_pincode,
weight=weight,
- env=env
- )
-
- ekart_res = check_ekart_availability(
- pickup_pincode=pickup_pincode,
- drop_pincode=drop_pincode,
- weight=weight,
- payment_type=payment_type
+ env=env,
+ token=sfx_token,
+ use_mock=use_mock
)
delhivery_res = check_delhivery_availability(
pickup_pincode=pickup_pincode,
drop_pincode=drop_pincode,
weight=weight,
- payment_type=payment_type
+ payment_type=payment_type,
+ api_token=delhivery_token,
+ use_mock=use_mock
)
- return {
+ ekart_res = check_ekart_availability(
+ pickup_pincode=pickup_pincode,
+ drop_pincode=drop_pincode,
+ weight=weight,
+ payment_type=payment_type,
+ use_mock=use_mock
+ )
+
+ availability_dict = {
"status": "success",
"pickup_pincode": str(pickup_pincode),
"drop_pincode": str(drop_pincode),
@@ -419,11 +642,21 @@ def check_all_carriers_availability(pickup_pincode, drop_pincode, payment_type='
"weight": weight,
"carriers": {
"SHADOWFAX": sfx_res,
- "EKART": ekart_res,
- "DELHIVERY": delhivery_res
+ "DELHIVERY": delhivery_res,
+ "EKART": ekart_res
}
}
+ best_carrier = select_best_carrier(
+ availability_dict,
+ selection_strategy='CHEAPEST',
+ preferred_carrier='SHADOWFAX',
+ is_cod=(str(payment_type).upper() == 'COD')
+ )
+ availability_dict["best_carrier"] = best_carrier
+
+ return availability_dict
+
CARRIER_PRIORITY = {
'SHADOWFAX': 0,
diff --git a/shipping/sfx_client.py b/shipping/sfx_client.py
index c3449e9..4ff4e3e 100644
--- a/shipping/sfx_client.py
+++ b/shipping/sfx_client.py
@@ -4,11 +4,10 @@ import requests
from django.conf import settings
from .models import ActivityLog
-STAGING_BASE_URL = getattr(settings, 'SFX_STAGING_BASE_URL', 'https://dale.shadowfax.in/api')
PRODUCTION_BASE_URL = getattr(settings, 'SFX_PRODUCTION_BASE_URL', 'https://dale.shadowfax.in/api')
def get_base_url(env="production"):
- return getattr(settings, 'SFX_PRODUCTION_BASE_URL', 'https://dale.shadowfax.in/api').rstrip('/')
+ return PRODUCTION_BASE_URL.rstrip('/')
def get_default_token(env="production"):
@@ -56,7 +55,7 @@ def execute_sfx_call(service_type, action_name, method, full_url, headers, paylo
response_body_str = json.dumps({
"error": "Upstream Connection Failed",
"details": str(e),
- "note": "Shadowfax Staging API host may be unreachable directly from your machine or blocked by Akamai WAF. Simulation mode fallback can be enabled."
+ "note": "Shadowfax Production API host may be unreachable directly from your machine or blocked by Akamai WAF. Simulation mode fallback can be enabled."
}, indent=2)
status_label = "ERROR"
diff --git a/shipping/templates/shipping/base.html b/shipping/templates/shipping/base.html
index 7209922..658e48f 100644
--- a/shipping/templates/shipping/base.html
+++ b/shipping/templates/shipping/base.html
@@ -19,6 +19,9 @@
Multi-Carrier Shipping Platform
+
+ ⚖️ Route & Carrier Checker
+
📦 Shadowfax Forward
diff --git a/shipping/templates/shipping/carrier_checker.html b/shipping/templates/shipping/carrier_checker.html
new file mode 100644
index 0000000..3ee3df8
--- /dev/null
+++ b/shipping/templates/shipping/carrier_checker.html
@@ -0,0 +1,675 @@
+{% extends 'shipping/base.html' %}
+
+{% block title %}Multi-Carrier Route Checker — Shadowfax vs Delhivery{% endblock %}
+
+{% block extra_head %}
+
+{% endblock %}
+
+{% block content %}
+
+
+
+
+
+ 📍 Route & Shipment Parameters
+ Real-time Multi-Carrier API Evaluation
+
+
+
+
+
+
+
+
+
+
+
+ Route Evaluation Verdict
+
+
+ Checking carriers...
+
+
+ Multi-carrier serviceability determined.
+
+
+
+
+
+
+
+
+
+
+
+
+ 📦 Shadowfax Logistics
+
+
API Integrated / Express & Hyperlocal
+
+
+
+
+
+
+
+
+ Origin Pincode: -
+
+
+ Hub Location: -
+
+
-
+
+
+
+
+
+
+ Destination Pincode: -
+
+
+ Delivery Area: -
+
+
+ -
+ -
+
+
+
+
+
+
+
+
+
+ 🚚 Delhivery Logistics
+
+
18,699 Pincodes / Surface & Express
+
+
+
+
+
+
+
+
+ Origin Pincode: -
+
+
+ Hub Location: -
+
+
-
+
+
+
+
+
+
+ Destination Pincode: -
+
+
+ Delivery Area: -
+
+
+ -
+ -
+
+
+
+
+
+
+
+
+
+ ⚡ Ekart Logistics
+
+
Elite API v3.8.10 / Pan-India Network
+
+
+
+
+
+
+
+
+ Origin Pincode: -
+
+
+ Hub Location: -
+
+
-
+
+
+
+
+
+
+ Destination Pincode: -
+
+
+ Delivery Area: -
+
+
+ -
+ -
+
+
+
+
+
+
+
+
+ 📊 Side-by-Side Capability Comparison Table
+
+
+
+
+
+ Carrier Partner
+ First-Mile (Origin Pickup)
+ Last-Mile (Destination Drop)
+ COD Support
+ Estimated Freight
+ Route Status
+
+
+
+
+
+
+
+
+
+
+ 🔍 Raw Multi-Carrier JSON Response (`/api/v1/carrier/check-availability/`)
+
+ 📋 Copy JSON
+
+
+
// Response will appear here
+
+
+{% endblock %}
+
+{% block extra_scripts %}
+
+{% endblock %}
diff --git a/shipping/templates/shipping/forward.html b/shipping/templates/shipping/forward.html
index 1c1144a..b16445d 100644
--- a/shipping/templates/shipping/forward.html
+++ b/shipping/templates/shipping/forward.html
@@ -17,10 +17,10 @@
Shadowfax Authorization API Token
@@ -295,18 +295,7 @@
{% block extra_scripts %}