Hide compliance status on none-Schengen trips.
This commit is contained in:
parent
7e3f9a9b1e
commit
5d5ce61da4
|
|
@ -7,26 +7,37 @@ from datetime import date, timedelta
|
|||
import flask
|
||||
|
||||
from . import get_country, trip
|
||||
from .schengen import calculate_schengen_time, extract_schengen_stays_from_travel
|
||||
from .schengen import (
|
||||
SCHENGEN_COUNTRIES,
|
||||
calculate_schengen_time,
|
||||
extract_schengen_stays_from_travel,
|
||||
)
|
||||
from .types import SchengenCalculation, SchengenStay, StrDict, Trip
|
||||
|
||||
|
||||
def add_schengen_compliance_to_trip(trip_obj: Trip) -> Trip:
|
||||
def trip_includes_schengen(trip: Trip) -> bool:
|
||||
return bool({c.alpha_2.lower() for c in trip.countries} & SCHENGEN_COUNTRIES)
|
||||
|
||||
|
||||
def add_schengen_compliance_to_trip(trip: Trip) -> Trip:
|
||||
"""Add Schengen compliance information to a trip object."""
|
||||
if not trip_includes_schengen(trip):
|
||||
return trip
|
||||
|
||||
try:
|
||||
# Calculate Schengen compliance for the trip
|
||||
calculation = calculate_schengen_time(trip_obj.travel)
|
||||
calculation = calculate_schengen_time(trip.travel)
|
||||
|
||||
# Add the calculation to the trip object
|
||||
trip_obj.schengen_compliance = calculation
|
||||
trip.schengen_compliance = calculation
|
||||
except Exception as e:
|
||||
# Log the error but don't fail the trip loading
|
||||
logging.warning(
|
||||
f"Failed to calculate Schengen compliance for trip {trip_obj.start}: {e}"
|
||||
f"Failed to calculate Schengen compliance for trip {trip.start}: {e}"
|
||||
)
|
||||
trip_obj.schengen_compliance = None
|
||||
trip.schengen_compliance = None
|
||||
|
||||
return trip_obj
|
||||
return trip
|
||||
|
||||
|
||||
def get_schengen_compliance_for_all_trips(
|
||||
|
|
@ -127,7 +138,9 @@ def schengen_dashboard_data(data_dir: str | None = None) -> dict[str, typing.Any
|
|||
data_dir = flask.current_app.config["PERSONAL_DATA"]
|
||||
|
||||
# Load all trips
|
||||
trip_list = trip.build_trip_list(data_dir)
|
||||
trip_list = [
|
||||
trip for trip in trip.build_trip_list(data_dir) if trip_includes_schengen(trip)
|
||||
]
|
||||
|
||||
# Calculate current compliance with trip information
|
||||
all_travel_items = []
|
||||
|
|
|
|||
|
|
@ -55,6 +55,43 @@ def airport_label(airport: StrDict) -> str:
|
|||
return f"{name} ({airport['iata']})"
|
||||
|
||||
|
||||
@dataclass
|
||||
class SchengenStay:
|
||||
"""Represents a stay in the Schengen area."""
|
||||
|
||||
entry_date: date
|
||||
exit_date: date | None # None if currently in Schengen
|
||||
country: str
|
||||
days: int
|
||||
trip_date: date | None = None # Trip start date for linking
|
||||
trip_name: str | None = None # Trip name for display
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""Post init."""
|
||||
if self.exit_date is None:
|
||||
# Currently in Schengen, calculate days up to today
|
||||
self.days = (date.today() - self.entry_date).days + 1
|
||||
else:
|
||||
self.days = (self.exit_date - self.entry_date).days + 1
|
||||
|
||||
|
||||
@dataclass
|
||||
class SchengenCalculation:
|
||||
"""Result of Schengen time calculation."""
|
||||
|
||||
total_days_used: int
|
||||
days_remaining: int
|
||||
is_compliant: bool
|
||||
current_180_day_period: tuple[date, date] # (start, end)
|
||||
stays_in_period: SchengenStay
|
||||
next_reset_date: typing.Optional[date] # When the 180-day window resets
|
||||
|
||||
@property
|
||||
def days_over_limit(self) -> int:
|
||||
"""Days over the 90-day limit."""
|
||||
return max(0, self.total_days_used - 90)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Trip:
|
||||
"""Trip."""
|
||||
|
|
@ -67,7 +104,7 @@ class Trip:
|
|||
flight_bookings: list[StrDict] = field(default_factory=list)
|
||||
name: str | None = None
|
||||
private: bool = False
|
||||
schengen_compliance: typing.Optional["SchengenCalculation"] = None
|
||||
schengen_compliance: SchengenCalculation | None = None
|
||||
|
||||
@property
|
||||
def title(self) -> str:
|
||||
|
|
@ -409,39 +446,3 @@ class Holiday:
|
|||
if self.local_name and self.local_name != self.name
|
||||
else self.name
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SchengenStay:
|
||||
"""Represents a stay in the Schengen area."""
|
||||
|
||||
entry_date: date
|
||||
exit_date: typing.Optional[date] # None if currently in Schengen
|
||||
country: str
|
||||
days: int
|
||||
trip_date: typing.Optional[date] = None # Trip start date for linking
|
||||
trip_name: typing.Optional[str] = None # Trip name for display
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if self.exit_date is None:
|
||||
# Currently in Schengen, calculate days up to today
|
||||
self.days = (date.today() - self.entry_date).days + 1
|
||||
else:
|
||||
self.days = (self.exit_date - self.entry_date).days + 1
|
||||
|
||||
|
||||
@dataclass
|
||||
class SchengenCalculation:
|
||||
"""Result of Schengen time calculation."""
|
||||
|
||||
total_days_used: int
|
||||
days_remaining: int
|
||||
is_compliant: bool
|
||||
current_180_day_period: tuple[date, date] # (start, end)
|
||||
stays_in_period: list["SchengenStay"]
|
||||
next_reset_date: typing.Optional[date] # When the 180-day window resets
|
||||
|
||||
@property
|
||||
def days_over_limit(self) -> int:
|
||||
"""Days over the 90-day limit."""
|
||||
return max(0, self.total_days_used - 90)
|
||||
|
|
|
|||
Loading…
Reference in a new issue