feat: Implement MFA authentication, add ride statistics model, and update various services, APIs, and tests across the application.

This commit is contained in:
pacnpal
2025-12-28 17:32:53 -05:00
parent aa56c46c27
commit c95f99ca10
452 changed files with 7948 additions and 6073 deletions

View File

@@ -9,18 +9,19 @@ This service provides functionality for:
- Proper rate limiting and caching
"""
import time
import math
import logging
import requests
from typing import Dict, List, Optional, Any
import math
import time
from dataclasses import dataclass
from itertools import permutations
from typing import Any
import requests
from django.conf import settings
from django.core.cache import cache
from django.contrib.gis.geos import Point
from django.contrib.gis.measure import Distance
from django.core.cache import cache
from apps.parks.models import Park
logger = logging.getLogger(__name__)
@@ -33,7 +34,7 @@ class Coordinates:
latitude: float
longitude: float
def to_list(self) -> List[float]:
def to_list(self) -> list[float]:
"""Return as [lat, lon] list."""
return [self.latitude, self.longitude]
@@ -48,7 +49,7 @@ class RouteInfo:
distance_km: float
duration_minutes: int
geometry: Optional[str] = None # Encoded polyline
geometry: str | None = None # Encoded polyline
@property
def formatted_distance(self) -> str:
@@ -79,7 +80,7 @@ class TripLeg:
route: RouteInfo
@property
def parks_along_route(self) -> List["Park"]:
def parks_along_route(self) -> list["Park"]:
"""Get parks along this route segment."""
# This would be populated by find_parks_along_route
return []
@@ -89,8 +90,8 @@ class TripLeg:
class RoadTrip:
"""Complete road trip with multiple parks."""
parks: List["Park"]
legs: List[TripLeg]
parks: list["Park"]
legs: list[TripLeg]
total_distance_km: float
total_duration_minutes: int
@@ -170,7 +171,7 @@ class RoadTripService:
}
)
def _make_request(self, url: str, params: Dict[str, Any]) -> Dict[str, Any]:
def _make_request(self, url: str, params: dict[str, Any]) -> dict[str, Any]:
"""
Make HTTP request with rate limiting, retries, and error handling.
"""
@@ -195,7 +196,7 @@ class RoadTripService:
f"Failed to make request after {self.max_retries} attempts: {e}"
)
def geocode_address(self, address: str) -> Optional[Coordinates]:
def geocode_address(self, address: str) -> Coordinates | None:
"""
Convert address to coordinates using Nominatim geocoding service.
@@ -256,7 +257,7 @@ class RoadTripService:
def calculate_route(
self, start_coords: Coordinates, end_coords: Coordinates
) -> Optional[RouteInfo]:
) -> RouteInfo | None:
"""
Calculate route between two coordinate points using OSRM.
@@ -377,7 +378,7 @@ class RoadTripService:
def find_parks_along_route(
self, start_park: "Park", end_park: "Park", max_detour_km: float = 50
) -> List["Park"]:
) -> list["Park"]:
"""
Find parks along a route within specified detour distance.
@@ -444,7 +445,7 @@ class RoadTripService:
def _calculate_detour_distance(
self, start: Coordinates, end: Coordinates, waypoint: Coordinates
) -> Optional[float]:
) -> float | None:
"""
Calculate the detour distance when visiting a waypoint.
"""
@@ -470,7 +471,7 @@ class RoadTripService:
logger.error(f"Failed to calculate detour distance: {e}")
return None
def create_multi_park_trip(self, park_list: List["Park"]) -> Optional[RoadTrip]:
def create_multi_park_trip(self, park_list: list["Park"]) -> RoadTrip | None:
"""
Create optimized multi-park road trip using simple nearest neighbor heuristic.
@@ -489,7 +490,7 @@ class RoadTripService:
else:
return self._optimize_trip_nearest_neighbor(park_list)
def _optimize_trip_exhaustive(self, park_list: List["Park"]) -> Optional[RoadTrip]:
def _optimize_trip_exhaustive(self, park_list: list["Park"]) -> RoadTrip | None:
"""
Find optimal route by testing all permutations (for small lists).
"""
@@ -508,8 +509,8 @@ class RoadTripService:
return best_trip
def _optimize_trip_nearest_neighbor(
self, park_list: List["Park"]
) -> Optional[RoadTrip]:
self, park_list: list["Park"]
) -> RoadTrip | None:
"""
Optimize trip using nearest neighbor heuristic (for larger lists).
"""
@@ -553,8 +554,8 @@ class RoadTripService:
return self._create_trip_from_order(ordered_parks)
def _create_trip_from_order(
self, ordered_parks: List["Park"]
) -> Optional[RoadTrip]:
self, ordered_parks: list["Park"]
) -> RoadTrip | None:
"""
Create a RoadTrip object from an ordered list of parks.
"""
@@ -596,7 +597,7 @@ class RoadTripService:
def get_park_distances(
self, center_park: "Park", radius_km: float = 100
) -> List[Dict[str, Any]]:
) -> list[dict[str, Any]]:
"""
Get all parks within radius of a center park with distances.