212 lines
6.5 KiB
Python
212 lines
6.5 KiB
Python
from enum import Enum
|
|
from typing import Optional
|
|
|
|
import pendulum
|
|
from pendulum import Date, Time
|
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
from pydantic_extra_types.pendulum_dt import DateTime
|
|
|
|
|
|
class User(BaseModel):
|
|
login: str
|
|
password: str = Field(repr=False)
|
|
club_id: Optional[str] = Field(default=None)
|
|
|
|
|
|
class BookingOpening(BaseModel):
|
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
|
|
days_before: Optional[int] = Field(default=7, alias="daysBefore")
|
|
opening_time: Optional[str] = Field(alias="time", default=None, repr=False)
|
|
time_after_booking: Optional[str] = Field(
|
|
alias="timeAfterBookingTime", default=None, repr=False
|
|
)
|
|
|
|
def __repr__(self):
|
|
base = super().__repr__()
|
|
time = f", time: {self.time})" if self.time else ""
|
|
time_after_booking = (
|
|
f", time_after_booking_time: {self.time_after_booking_time})"
|
|
if self.time_after_booking_time
|
|
else ""
|
|
)
|
|
|
|
return base.removesuffix(")") + time + time_after_booking
|
|
|
|
@property
|
|
def time(self):
|
|
return pendulum.parse(self.opening_time).time()
|
|
|
|
@property
|
|
def time_after_booking_time(self):
|
|
return (
|
|
pendulum.parse(self.time_after_booking).time()
|
|
if self.time_after_booking
|
|
else None
|
|
)
|
|
|
|
|
|
class TotalBookings(BaseModel):
|
|
peak_hours: int | str = Field(alias="peakHours")
|
|
off_peak_hours: int | str = Field(alias="offPeakHours")
|
|
|
|
|
|
class Court(BaseModel):
|
|
id: int
|
|
name: str
|
|
number: int
|
|
is_indoor: Optional[bool] = Field(alias="isIndoor")
|
|
|
|
|
|
class Sport(BaseModel):
|
|
name: str
|
|
id: int
|
|
duration: int
|
|
price: int
|
|
players: int
|
|
courts: list[Court]
|
|
|
|
|
|
class Url(BaseModel):
|
|
name: str
|
|
path: str
|
|
payload_template: Optional[str] = Field(default=None, alias="payloadTemplate")
|
|
|
|
|
|
class BookingPlatform(BaseModel):
|
|
id: str
|
|
club_id: int = Field(alias="clubId")
|
|
url: str
|
|
hours_before_cancellation: int = Field(alias="hoursBeforeCancellation")
|
|
booking_opening: BookingOpening = Field(alias="bookingOpening")
|
|
total_bookings: TotalBookings = Field(alias="totalBookings")
|
|
sports: list[Sport]
|
|
urls: dict[str, Url]
|
|
|
|
|
|
class Club(BaseModel):
|
|
id: str
|
|
name: str
|
|
url: str
|
|
booking_platform: BookingPlatform = Field(alias="bookingPlatform")
|
|
|
|
|
|
class PlatformDefinition(BaseModel):
|
|
id: str
|
|
name: str
|
|
url: str
|
|
urls: list[Url]
|
|
|
|
|
|
class BookingFilter(BaseModel):
|
|
date: DateTime
|
|
sport_name: str
|
|
|
|
@field_validator("sport_name", mode="before")
|
|
@classmethod
|
|
def to_lower_case(cls, d: str) -> str:
|
|
return d.lower()
|
|
|
|
|
|
class Booking(BaseModel):
|
|
id: int
|
|
booking_date: DateTime = Field(alias="dateResa")
|
|
start_time: DateTime = Field(alias="startTime")
|
|
sport: str
|
|
court: str
|
|
game_creation: Optional[int] = Field(default=None, alias="creaPartie")
|
|
game_creation_limit: Optional[DateTime] = Field(
|
|
default=None, alias="limitCreaPartie"
|
|
)
|
|
cancel: Optional[bool] = Field(default=True)
|
|
block_player_replacement: Optional[int] = Field(
|
|
default=None, alias="bloquerRemplacementJoueur"
|
|
)
|
|
can_remove_parteners: bool = Field(default=True, alias="canRemovePartners")
|
|
end_time: Optional[DateTime] = Field(default=None, alias="endTime")
|
|
day_fr: Optional[str] = Field(default=None, alias="dayFr")
|
|
live_xperience_code: Optional[str] = Field(default=None, alias="codeLiveXperience")
|
|
spartime_qr_code: Optional[str] = Field(default=None, alias="qrCodeSpartime")
|
|
remaining_places: int = Field(default=3, alias="remainingPlaces")
|
|
is_captain: bool = Field(default=True, alias="isCaptain")
|
|
dt_start: Optional[DateTime] = Field(default=None, alias="dtStart")
|
|
credit_card_guaranty: Optional[str] = Field(default=None, alias="garantieCb")
|
|
certificate_validity_duration: Optional[int] = Field(
|
|
alias="dureeValidCertif", default=None
|
|
)
|
|
charge_id: Optional[str] = Field(default=None, alias="chargeId")
|
|
partners: Optional[list] = Field(default=[])
|
|
player_status: Optional[int] = Field(default=None, alias="playerStatus")
|
|
products: Optional[list] = Field(default=[])
|
|
|
|
@field_validator("booking_date", mode="before")
|
|
@classmethod
|
|
def validate_date(cls, d: str) -> DateTime:
|
|
return pendulum.from_format(
|
|
d, "DD/MM/YYYY", tz=pendulum.timezone("Europe/Paris")
|
|
)
|
|
|
|
@field_validator("start_time", "end_time", mode="before")
|
|
@classmethod
|
|
def validate_time(cls, t: str) -> DateTime:
|
|
return pendulum.from_format(t, "HH:mm", tz=pendulum.timezone("Europe/Paris"))
|
|
|
|
@field_validator("game_creation_limit", mode="before")
|
|
@classmethod
|
|
def validate_datetime_add_tz(cls, dt: str) -> DateTime:
|
|
return pendulum.parse(dt, tz=pendulum.timezone("Europe/Paris"))
|
|
|
|
@field_validator("dt_start", mode="before")
|
|
@classmethod
|
|
def validate_datetime(cls, dt: str) -> DateTime:
|
|
return pendulum.parse(dt)
|
|
|
|
@field_validator("sport", mode="before")
|
|
@classmethod
|
|
def to_lower_case(cls, d: str) -> str:
|
|
return d.lower()
|
|
|
|
def matches(self, booking_filter: BookingFilter) -> bool:
|
|
"""
|
|
Check if the booking matches the booking filter
|
|
|
|
:param booking_filter: the conditions the booking should meet
|
|
:return: true if the booking matches the conditions, false otherwise
|
|
"""
|
|
return (
|
|
self.is_same_sport(booking_filter.sport_name)
|
|
and self.is_same_date(booking_filter.date.date())
|
|
and self.is_same_time(booking_filter.date.time())
|
|
)
|
|
|
|
def is_same_sport(self, sport: str) -> bool:
|
|
"""
|
|
Check if the booking and the booking filter are about the same sport
|
|
|
|
:param sport: the sport to test
|
|
:return: true if the sport matches booking sport, false otherwise
|
|
"""
|
|
return self.sport == sport
|
|
|
|
def is_same_date(self, date: Date) -> bool:
|
|
"""
|
|
Check if the booking filter has the same date as the booking
|
|
|
|
:param date: the date to test
|
|
:return: true if the date matches the booking date, false otherwise
|
|
"""
|
|
return self.booking_date.date() == date
|
|
|
|
def is_same_time(self, time: Time) -> bool:
|
|
"""
|
|
Check if the booking filter has the same time as the booking
|
|
|
|
:param time: the time to test
|
|
:return: true if the time matches the booking time, false otherwise
|
|
"""
|
|
return self.start_time.time() == time
|
|
|
|
|
|
class Action(Enum):
|
|
BOOK = "book"
|
|
CANCEL = "cancel"
|