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