arbret/backend/date_validation.py
counterweight db7a0dbe28
refactor(backend): extract date range validation utilities
Issue #5: Date validation logic was duplicated across availability
and booking routes.

Changes:
- Add date_validation.py with shared utilities:
  - get_bookable_date_range: returns (min_date, max_date) tuple
  - validate_date_in_range: validates date with contextual errors
- Update routes/availability.py to use shared utilities
- Update routes/booking.py to use shared utilities
- Remove redundant _get_date_range_bounds and _get_bookable_date_range
- Error messages now include context (book, set availability, etc.)
2025-12-22 00:02:41 +01:00

52 lines
1.4 KiB
Python

"""Date range validation utilities for booking and availability."""
from datetime import date, timedelta
from fastapi import HTTPException
from shared_constants import MAX_ADVANCE_DAYS, MIN_ADVANCE_DAYS
def get_bookable_date_range() -> tuple[date, date]:
"""
Get the valid date range for booking/availability.
Returns:
Tuple of (min_date, max_date) where:
- min_date is MIN_ADVANCE_DAYS from today
- max_date is MAX_ADVANCE_DAYS from today
"""
today = date.today()
min_date = today + timedelta(days=MIN_ADVANCE_DAYS)
max_date = today + timedelta(days=MAX_ADVANCE_DAYS)
return min_date, max_date
def validate_date_in_range(
d: date,
*,
context: str = "action",
) -> None:
"""
Validate a date is within the bookable range.
Args:
d: The date to validate
context: Description for error messages (e.g., "book", "set availability")
Raises:
HTTPException: If the date is outside the valid range
"""
min_date, max_date = get_bookable_date_range()
if d < min_date:
raise HTTPException(
status_code=400,
detail=f"Cannot {context} for past dates. Earliest allowed: {min_date}",
)
if d > max_date:
raise HTTPException(
status_code=400,
detail=f"Cannot {context} more than {MAX_ADVANCE_DAYS} days ahead. "
f"Latest allowed: {max_date}",
)