- Add MercadoLibre OAuth, listings, orders, webhooks and category search - New marketplace_external_bp.py, meli_service.py, marketplace_external_service.py - New marketplace_external.html/js with ML management UI - Inventory: bulk publish to ML with category autocomplete, listing type and shipping selectors - Inventory: new .btn--meli styles, select/label CSS fixes - WhatsApp bridge: rate limiting, 440/515/408 error handling, stale watchdog - DB migration v3.4_meli_integration.sql for marketplace_listings, orders, sync_queue - Add Celery tasks for ML sync and webhook processing - Sidebar: MercadoLibre navigation link
57 lines
1.7 KiB
Python
57 lines
1.7 KiB
Python
import math
|
|
|
|
def haversine(lat1, lon1, lat2, lon2):
|
|
"""Calculate the great-circle distance between two points on Earth in km."""
|
|
R = 6371.0 # Earth radius in km
|
|
phi1 = math.radians(lat1)
|
|
phi2 = math.radians(lat2)
|
|
dphi = math.radians(lat2 - lat1)
|
|
dlambda = math.radians(lon2 - lon1)
|
|
|
|
a = math.sin(dphi / 2) ** 2 + math.cos(phi1) * math.cos(phi2) * math.sin(dlambda / 2) ** 2
|
|
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
|
|
|
return R * c
|
|
|
|
|
|
def find_nearest_branch(tenant_conn, latitude, longitude):
|
|
"""
|
|
Find the nearest active branch with coordinates.
|
|
Returns a dict with branch info + distance_km, or None.
|
|
"""
|
|
if not tenant_conn or latitude is None or longitude is None:
|
|
return None
|
|
|
|
cur = tenant_conn.cursor()
|
|
cur.execute(
|
|
"""
|
|
SELECT id, name, address, phone, latitude, longitude
|
|
FROM branches
|
|
WHERE is_active = TRUE AND latitude IS NOT NULL AND longitude IS NOT NULL
|
|
"""
|
|
)
|
|
branches = cur.fetchall()
|
|
cur.close()
|
|
|
|
nearest = None
|
|
min_dist = float('inf')
|
|
|
|
for row in branches:
|
|
bid, name, address, phone, b_lat, b_lon = row
|
|
if b_lat is None or b_lon is None:
|
|
continue
|
|
dist = haversine(float(latitude), float(longitude), float(b_lat), float(b_lon))
|
|
if dist < min_dist:
|
|
min_dist = dist
|
|
nearest = {
|
|
'id': bid,
|
|
'name': name,
|
|
'address': address or '',
|
|
'phone': phone or '',
|
|
'latitude': float(b_lat),
|
|
'longitude': float(b_lon),
|
|
'distance_km': round(dist, 1),
|
|
}
|
|
|
|
return nearest
|