otf-api 0.6.4__py3-none-any.whl → 0.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- otf_api/__init__.py +1 -9
- otf_api/api.py +76 -111
- otf_api/auth.py +11 -10
- otf_api/exceptions.py +18 -0
- otf_api/models/__init__.py +25 -32
- otf_api/models/base.py +1 -16
- otf_api/models/{responses/body_composition_list.py → body_composition_list.py} +3 -14
- otf_api/models/book_class.py +89 -0
- otf_api/models/bookings.py +119 -0
- otf_api/models/cancel_booking.py +49 -0
- otf_api/models/{responses/challenge_tracker_detail.py → challenge_tracker_detail.py} +12 -13
- otf_api/models/classes.py +80 -0
- otf_api/models/enums.py +87 -0
- otf_api/models/{responses/favorite_studios.py → favorite_studios.py} +17 -19
- otf_api/models/{responses/lifetime_stats.py → lifetime_stats.py} +0 -18
- otf_api/models/{responses/member_detail.py → member_detail.py} +16 -19
- otf_api/models/{responses/member_purchases.py → member_purchases.py} +10 -10
- otf_api/models/mixins.py +44 -0
- otf_api/models/{responses/out_of_studio_workout_history.py → out_of_studio_workout_history.py} +3 -3
- otf_api/models/{responses/performance_summary_list.py → performance_summary_list.py} +2 -5
- otf_api/models/studio_detail.py +109 -0
- otf_api/models/{responses/studio_services.py → studio_services.py} +2 -2
- otf_api/models/{responses/telemetry.py → telemetry.py} +1 -1
- {otf_api-0.6.4.dist-info → otf_api-0.7.1.dist-info}/METADATA +3 -3
- otf_api-0.7.1.dist-info/RECORD +36 -0
- otf_api/models/responses/__init__.py +0 -57
- otf_api/models/responses/book_class.py +0 -407
- otf_api/models/responses/bookings.py +0 -160
- otf_api/models/responses/cancel_booking.py +0 -95
- otf_api/models/responses/classes.py +0 -148
- otf_api/models/responses/enums.py +0 -23
- otf_api/models/responses/studio_detail.py +0 -113
- otf_api-0.6.4.dist-info/RECORD +0 -35
- /otf_api/models/{responses/challenge_tracker_content.py → challenge_tracker_content.py} +0 -0
- /otf_api/models/{responses/latest_agreement.py → latest_agreement.py} +0 -0
- /otf_api/models/{responses/member_membership.py → member_membership.py} +0 -0
- /otf_api/models/{responses/performance_summary_detail.py → performance_summary_detail.py} +0 -0
- /otf_api/models/{responses/telemetry_hr_history.py → telemetry_hr_history.py} +0 -0
- /otf_api/models/{responses/telemetry_max_hr.py → telemetry_max_hr.py} +0 -0
- /otf_api/models/{responses/total_classes.py → total_classes.py} +0 -0
- {otf_api-0.6.4.dist-info → otf_api-0.7.1.dist-info}/AUTHORS.md +0 -0
- {otf_api-0.6.4.dist-info → otf_api-0.7.1.dist-info}/LICENSE +0 -0
- {otf_api-0.6.4.dist-info → otf_api-0.7.1.dist-info}/WHEEL +0 -0
otf_api/models/base.py
CHANGED
@@ -4,19 +4,4 @@ from pydantic import BaseModel, ConfigDict
|
|
4
4
|
|
5
5
|
|
6
6
|
class OtfItemBase(BaseModel):
|
7
|
-
model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True, extra="
|
8
|
-
|
9
|
-
|
10
|
-
class OtfListBase(BaseModel):
|
11
|
-
model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True, extra="allow")
|
12
|
-
collection_field: ClassVar[str] = "data"
|
13
|
-
|
14
|
-
@property
|
15
|
-
def collection(self) -> list[OtfItemBase]:
|
16
|
-
return getattr(self, self.collection_field)
|
17
|
-
|
18
|
-
def to_json(self, **kwargs) -> str:
|
19
|
-
kwargs.setdefault("indent", 4)
|
20
|
-
kwargs.setdefault("exclude_none", True)
|
21
|
-
|
22
|
-
return self.model_dump_json(**kwargs)
|
7
|
+
model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True, extra="ignore")
|
@@ -3,9 +3,9 @@ from datetime import datetime
|
|
3
3
|
from enum import Enum
|
4
4
|
|
5
5
|
import pint
|
6
|
-
from pydantic import BaseModel,
|
6
|
+
from pydantic import BaseModel, Field, field_validator
|
7
7
|
|
8
|
-
from otf_api.models.base import OtfItemBase
|
8
|
+
from otf_api.models.base import OtfItemBase
|
9
9
|
|
10
10
|
ureg = pint.UnitRegistry()
|
11
11
|
|
@@ -101,7 +101,6 @@ def get_body_fat_percent_dividers_female(age: int) -> list[float]:
|
|
101
101
|
|
102
102
|
|
103
103
|
class LeanBodyMass(OtfItemBase):
|
104
|
-
model_config: ConfigDict = ConfigDict(extra="ignore")
|
105
104
|
left_arm: float = Field(..., alias="lbmOfLeftArm")
|
106
105
|
left_leg: float = Field(..., alias="lbmOfLeftLeg")
|
107
106
|
right_arm: float = Field(..., alias="lbmOfRightArm")
|
@@ -110,7 +109,6 @@ class LeanBodyMass(OtfItemBase):
|
|
110
109
|
|
111
110
|
|
112
111
|
class LeanBodyMassPercent(OtfItemBase):
|
113
|
-
model_config: ConfigDict = ConfigDict(extra="ignore")
|
114
112
|
left_arm: float = Field(..., alias="lbmPercentOfLeftArm")
|
115
113
|
left_leg: float = Field(..., alias="lbmPercentOfLeftLeg")
|
116
114
|
right_arm: float = Field(..., alias="lbmPercentOfRightArm")
|
@@ -119,7 +117,6 @@ class LeanBodyMassPercent(OtfItemBase):
|
|
119
117
|
|
120
118
|
|
121
119
|
class BodyFatMass(OtfItemBase):
|
122
|
-
model_config: ConfigDict = ConfigDict(extra="ignore")
|
123
120
|
control: float = Field(..., alias="bfmControl")
|
124
121
|
left_arm: float = Field(..., alias="bfmOfLeftArm")
|
125
122
|
left_leg: float = Field(..., alias="bfmOfLeftLeg")
|
@@ -129,7 +126,6 @@ class BodyFatMass(OtfItemBase):
|
|
129
126
|
|
130
127
|
|
131
128
|
class BodyFatMassPercent(OtfItemBase):
|
132
|
-
model_config: ConfigDict = ConfigDict(extra="ignore")
|
133
129
|
left_arm: float = Field(..., alias="bfmPercentOfLeftArm")
|
134
130
|
left_leg: float = Field(..., alias="bfmPercentOfLeftLeg")
|
135
131
|
right_arm: float = Field(..., alias="bfmPercentOfRightArm")
|
@@ -138,7 +134,6 @@ class BodyFatMassPercent(OtfItemBase):
|
|
138
134
|
|
139
135
|
|
140
136
|
class TotalBodyWeight(OtfItemBase):
|
141
|
-
model_config: ConfigDict = ConfigDict(extra="ignore")
|
142
137
|
right_arm: float = Field(..., alias="tbwOfRightArm")
|
143
138
|
left_arm: float = Field(..., alias="tbwOfLeftArm")
|
144
139
|
trunk: float = Field(..., alias="tbwOfTrunk")
|
@@ -147,7 +142,6 @@ class TotalBodyWeight(OtfItemBase):
|
|
147
142
|
|
148
143
|
|
149
144
|
class IntraCellularWater(OtfItemBase):
|
150
|
-
model_config: ConfigDict = ConfigDict(extra="ignore")
|
151
145
|
right_arm: float = Field(..., alias="icwOfRightArm")
|
152
146
|
left_arm: float = Field(..., alias="icwOfLeftArm")
|
153
147
|
trunk: float = Field(..., alias="icwOfTrunk")
|
@@ -156,7 +150,6 @@ class IntraCellularWater(OtfItemBase):
|
|
156
150
|
|
157
151
|
|
158
152
|
class ExtraCellularWater(OtfItemBase):
|
159
|
-
model_config: ConfigDict = ConfigDict(extra="ignore")
|
160
153
|
right_arm: float = Field(..., alias="ecwOfRightArm")
|
161
154
|
left_arm: float = Field(..., alias="ecwOfLeftArm")
|
162
155
|
trunk: float = Field(..., alias="ecwOfTrunk")
|
@@ -165,7 +158,6 @@ class ExtraCellularWater(OtfItemBase):
|
|
165
158
|
|
166
159
|
|
167
160
|
class ExtraCellularWaterOverTotalBodyWater(OtfItemBase):
|
168
|
-
model_config: ConfigDict = ConfigDict(extra="ignore")
|
169
161
|
right_arm: float = Field(..., alias="ecwOverTBWOfRightArm")
|
170
162
|
left_arm: float = Field(..., alias="ecwOverTBWOfLeftArm")
|
171
163
|
trunk: float = Field(..., alias="ecwOverTBWOfTrunk")
|
@@ -200,9 +192,6 @@ class BodyCompositionData(OtfItemBase):
|
|
200
192
|
basal_metabolic_rate: float = Field(..., alias="bmr")
|
201
193
|
in_body_type: str = Field(..., alias="inBodyType")
|
202
194
|
|
203
|
-
body_fat_mass: float = Field(..., alias="bfm")
|
204
|
-
skeletal_muscle_mass: float = Field(..., alias="smm")
|
205
|
-
|
206
195
|
# excluded because they are only useful for end result of calculations
|
207
196
|
body_fat_mass_dividers: list[float] = Field(..., alias="bfmGraphScale", exclude=True)
|
208
197
|
body_fat_mass_plot_point: float = Field(..., alias="pfatnew", exclude=True)
|
@@ -302,5 +291,5 @@ class BodyCompositionData(OtfItemBase):
|
|
302
291
|
)
|
303
292
|
|
304
293
|
|
305
|
-
class BodyCompositionList(
|
294
|
+
class BodyCompositionList(OtfItemBase):
|
306
295
|
data: list[BodyCompositionData]
|
@@ -0,0 +1,89 @@
|
|
1
|
+
from collections.abc import Hashable
|
2
|
+
from datetime import datetime
|
3
|
+
from typing import Any
|
4
|
+
|
5
|
+
from pydantic import Field
|
6
|
+
|
7
|
+
from otf_api.models.base import OtfItemBase
|
8
|
+
|
9
|
+
|
10
|
+
class Class(OtfItemBase):
|
11
|
+
class_id: int = Field(None, alias="classId")
|
12
|
+
class_uuid: str = Field(None, alias="classUUId")
|
13
|
+
mbo_studio_id: int | None = Field(None, alias="mboStudioId")
|
14
|
+
mbo_class_id: int | None = Field(None, alias="mboClassId")
|
15
|
+
mbo_class_schedule_id: int | None = Field(None, alias="mboClassScheduleId")
|
16
|
+
mbo_program_id: int | None = Field(None, alias="mboProgramId")
|
17
|
+
studio_id: int | None = Field(None, alias="studioId")
|
18
|
+
coach_id: int | None = Field(None, alias="coachId")
|
19
|
+
location_id: int | None = Field(None, alias="locationId")
|
20
|
+
name: str | None = None
|
21
|
+
description: str | None = None
|
22
|
+
program_name: str | None = Field(None, alias="programName")
|
23
|
+
program_schedule_type: str | None = Field(None, alias="programScheduleType")
|
24
|
+
program_cancel_offset: int | None = Field(None, alias="programCancelOffset")
|
25
|
+
max_capacity: int | None = Field(None, alias="maxCapacity")
|
26
|
+
total_booked: int | None = Field(None, alias="totalBooked")
|
27
|
+
web_capacity: int | None = Field(None, alias="webCapacity")
|
28
|
+
web_booked: int | None = Field(None, alias="webBooked")
|
29
|
+
total_booked_waitlist: int | None = Field(None, alias="totalBookedWaitlist")
|
30
|
+
start_date_time: datetime | None = Field(None, alias="startDateTime")
|
31
|
+
end_date_time: datetime | None = Field(None, alias="endDateTime")
|
32
|
+
is_cancelled: bool | None = Field(None, alias="isCancelled")
|
33
|
+
substitute: bool | None = None
|
34
|
+
is_active: bool | None = Field(None, alias="isActive")
|
35
|
+
is_waitlist_available: bool | None = Field(None, alias="isWaitlistAvailable")
|
36
|
+
is_enrolled: bool | None = Field(None, alias="isEnrolled")
|
37
|
+
is_hide_cancel: bool | None = Field(None, alias="isHideCancel")
|
38
|
+
is_available: bool | None = Field(None, alias="isAvailable")
|
39
|
+
room_number: int | None = Field(None, alias="roomNumber")
|
40
|
+
created_by: str | None = Field(None, alias="createdBy")
|
41
|
+
created_date: datetime | None = Field(None, alias="createdDate")
|
42
|
+
updated_by: str | None = Field(None, alias="updatedBy")
|
43
|
+
updated_date: datetime | None = Field(None, alias="updatedDate")
|
44
|
+
is_deleted: bool | None = Field(None, alias="isDeleted")
|
45
|
+
studio: dict[Hashable, Any] | None = Field(None, exclude=True)
|
46
|
+
location: dict[Hashable, Any] | None = Field(None, exclude=True)
|
47
|
+
coach: dict[Hashable, Any] | None = Field(None, exclude=True)
|
48
|
+
attributes: dict[str, Any] | None = Field(None, exclude=True)
|
49
|
+
|
50
|
+
|
51
|
+
class SavedBooking(OtfItemBase):
|
52
|
+
class_booking_id: int = Field(..., alias="classBookingId")
|
53
|
+
class_booking_uuid: str = Field(..., alias="classBookingUUId")
|
54
|
+
studio_id: int | None = Field(None, alias="studioId")
|
55
|
+
class_id: int | None = Field(None, alias="classId")
|
56
|
+
is_intro: bool | None = Field(None, alias="isIntro")
|
57
|
+
member_id: int | None = Field(None, alias="memberId")
|
58
|
+
mbo_member_id: str | None = Field(None, alias="mboMemberId")
|
59
|
+
mbo_class_id: int | None = Field(None, alias="mboClassId")
|
60
|
+
mbo_visit_id: int | None = Field(None, alias="mboVisitId")
|
61
|
+
mbo_waitlist_entry_id: int | None = Field(None, alias="mboWaitlistEntryId")
|
62
|
+
mbo_sync_message: str | None = Field(None, alias="mboSyncMessage")
|
63
|
+
status: str | None = None
|
64
|
+
booked_date: datetime | None = Field(None, alias="bookedDate")
|
65
|
+
checked_in_date: datetime | None = Field(None, alias="checkedInDate")
|
66
|
+
cancelled_date: datetime | None = Field(None, alias="cancelledDate")
|
67
|
+
created_by: str | None = Field(None, alias="createdBy")
|
68
|
+
created_date: datetime | None = Field(None, alias="createdDate")
|
69
|
+
updated_by: str | None = Field(None, alias="updatedBy")
|
70
|
+
updated_date: datetime | None = Field(None, alias="updatedDate")
|
71
|
+
is_deleted: bool | None = Field(None, alias="isDeleted")
|
72
|
+
member: dict[Hashable, Any] | None = Field(None, exclude=True)
|
73
|
+
otf_class: Class = Field(..., alias="class")
|
74
|
+
custom_data: Any | None = Field(None, alias="customData", exclude=True)
|
75
|
+
attributes: dict[str, Any] | None = Field(None, exclude=True)
|
76
|
+
|
77
|
+
|
78
|
+
class BookClass(OtfItemBase):
|
79
|
+
saved_bookings: list[SavedBooking] = Field(None, alias="savedBookings")
|
80
|
+
mbo_response: list[dict[Hashable, Any]] | Any | None = Field(None, alias="mboResponse", exclude=True)
|
81
|
+
|
82
|
+
@property
|
83
|
+
def booking(self) -> SavedBooking:
|
84
|
+
return self.saved_bookings[0]
|
85
|
+
|
86
|
+
@property
|
87
|
+
def booking_uuid(self) -> str:
|
88
|
+
"""Returns the booking UUID for the class. This can be used to cancel the class."""
|
89
|
+
return self.booking.class_booking_uuid
|
@@ -0,0 +1,119 @@
|
|
1
|
+
from collections.abc import Hashable
|
2
|
+
from datetime import datetime
|
3
|
+
from typing import Any
|
4
|
+
|
5
|
+
from pydantic import Field
|
6
|
+
|
7
|
+
from otf_api.models.base import OtfItemBase
|
8
|
+
from otf_api.models.enums import BookingStatus, StudioStatus
|
9
|
+
from otf_api.models.mixins import OtfClassTimeMixin
|
10
|
+
|
11
|
+
|
12
|
+
class Location(OtfItemBase):
|
13
|
+
address_one: str | None = Field(None, alias="address1")
|
14
|
+
address_two: str | None = Field(alias="address2")
|
15
|
+
city: str | None = None
|
16
|
+
country: str | None = None
|
17
|
+
distance: float | None = None
|
18
|
+
location_name: str | None = Field(None, alias="locationName")
|
19
|
+
latitude: float | None = Field(None, alias="latitude")
|
20
|
+
longitude: float | None = Field(None, alias="longitude")
|
21
|
+
phone_number: str | None = Field(None, alias="phone")
|
22
|
+
postal_code: str | None = Field(None, alias="postalCode")
|
23
|
+
state: str | None = None
|
24
|
+
|
25
|
+
|
26
|
+
class Coach(OtfItemBase):
|
27
|
+
coach_uuid: str = Field(alias="coachUUId")
|
28
|
+
name: str
|
29
|
+
first_name: str | None = Field(None, alias="firstName")
|
30
|
+
last_name: str | None = Field(None, alias="lastName")
|
31
|
+
image_url: str | None = Field(None, alias="imageUrl", exclude=True)
|
32
|
+
profile_picture_url: str | None = Field(None, alias="profilePictureUrl", exclude=True)
|
33
|
+
|
34
|
+
|
35
|
+
class StudioLocation(OtfItemBase):
|
36
|
+
latitude: float | None = Field(None, alias="latitude")
|
37
|
+
longitude: float | None = Field(None, alias="longitude")
|
38
|
+
phone_number: str | None = Field(None, alias="phoneNumber")
|
39
|
+
physical_city: str | None = Field(None, alias="physicalCity")
|
40
|
+
physical_address: str | None = Field(None, alias="physicalAddress")
|
41
|
+
physical_address2: str | None = Field(None, alias="physicalAddress2")
|
42
|
+
physical_state: str | None = Field(None, alias="physicalState")
|
43
|
+
physical_postal_code: str | None = Field(None, alias="physicalPostalCode")
|
44
|
+
physical_region: str | None = Field(None, alias="physicalRegion", exclude=True)
|
45
|
+
physical_country_id: int | None = Field(None, alias="physicalCountryId", exclude=True)
|
46
|
+
physical_country: str | None = Field(None, alias="physicalCountry")
|
47
|
+
country: dict[Hashable, Any] | None = Field(None, alias="country", exclude=True)
|
48
|
+
|
49
|
+
|
50
|
+
class Studio(OtfItemBase):
|
51
|
+
studio_uuid: str = Field(alias="studioUUId")
|
52
|
+
studio_name: str = Field(alias="studioName")
|
53
|
+
studio_id: int = Field(alias="studioId")
|
54
|
+
description: str | None = None
|
55
|
+
contact_email: str | None = Field(None, alias="contactEmail", exclude=True)
|
56
|
+
status: StudioStatus | None = None
|
57
|
+
logo_url: str | None = Field(None, alias="logoUrl", exclude=True)
|
58
|
+
time_zone: str = Field(alias="timeZone")
|
59
|
+
mbo_studio_id: int | None = Field(None, alias="mboStudioId", exclude=True)
|
60
|
+
allows_cr_waitlist: bool | None = Field(None, alias="allowsCRWaitlist")
|
61
|
+
cr_waitlist_flag_last_updated: datetime | None = Field(None, alias="crWaitlistFlagLastUpdated", exclude=True)
|
62
|
+
studio_location: StudioLocation | None = Field(None, alias="studioLocation", exclude=True)
|
63
|
+
|
64
|
+
|
65
|
+
class OtfClass(OtfItemBase, OtfClassTimeMixin):
|
66
|
+
class_uuid: str = Field(alias="classUUId")
|
67
|
+
name: str
|
68
|
+
description: str | None = Field(None, exclude=True)
|
69
|
+
starts_at_local: datetime = Field(alias="startDateTime")
|
70
|
+
ends_at_local: datetime = Field(alias="endDateTime")
|
71
|
+
is_available: bool = Field(alias="isAvailable")
|
72
|
+
is_cancelled: bool = Field(alias="isCancelled")
|
73
|
+
program_name: str | None = Field(None, alias="programName")
|
74
|
+
coach_id: int | None = Field(None, alias="coachId")
|
75
|
+
studio: Studio | None = None
|
76
|
+
coach: Coach | None = None
|
77
|
+
location: Location | None = None
|
78
|
+
virtual_class: bool | None = Field(None, alias="virtualClass")
|
79
|
+
|
80
|
+
|
81
|
+
class Member(OtfItemBase):
|
82
|
+
member_uuid: str = Field(alias="memberUUId")
|
83
|
+
first_name: str = Field(alias="firstName")
|
84
|
+
last_name: str = Field(alias="lastName")
|
85
|
+
email: str | None = None
|
86
|
+
phone_number: str | None = Field(None, alias="phoneNumber")
|
87
|
+
gender: str | None = None
|
88
|
+
cc_last_4: str | None = Field(None, alias="ccLast4", exclude=True)
|
89
|
+
|
90
|
+
|
91
|
+
class Booking(OtfItemBase):
|
92
|
+
class_booking_id: int = Field(alias="classBookingId")
|
93
|
+
class_booking_uuid: str = Field(alias="classBookingUUId", description="ID used to cancel the booking")
|
94
|
+
studio_id: int = Field(alias="studioId")
|
95
|
+
class_id: int = Field(alias="classId")
|
96
|
+
is_intro: bool = Field(alias="isIntro")
|
97
|
+
member_id: int = Field(alias="memberId")
|
98
|
+
mbo_member_id: str | None = Field(None, alias="mboMemberId", exclude=True)
|
99
|
+
mbo_class_id: int | None = Field(None, alias="mboClassId", exclude=True)
|
100
|
+
mbo_visit_id: int | None = Field(None, alias="mboVisitId", exclude=True)
|
101
|
+
mbo_waitlist_entry_id: int | None = Field(None, alias="mboWaitlistEntryId", exclude=True)
|
102
|
+
mbo_sync_message: str | None = Field(None, alias="mboSyncMessage", exclude=True)
|
103
|
+
status: BookingStatus
|
104
|
+
booked_date: datetime | None = Field(None, alias="bookedDate")
|
105
|
+
checked_in_date: datetime | None = Field(None, alias="checkedInDate")
|
106
|
+
cancelled_date: datetime | None = Field(None, alias="cancelledDate")
|
107
|
+
created_by: str = Field(alias="createdBy", exclude=True)
|
108
|
+
created_date: datetime = Field(alias="createdDate")
|
109
|
+
updated_by: str = Field(alias="updatedBy", exclude=True)
|
110
|
+
updated_date: datetime = Field(alias="updatedDate")
|
111
|
+
is_deleted: bool = Field(alias="isDeleted")
|
112
|
+
member: Member | None = Field(None, exclude=True)
|
113
|
+
waitlist_position: int | None = Field(None, alias="waitlistPosition")
|
114
|
+
otf_class: OtfClass = Field(alias="class")
|
115
|
+
is_home_studio: bool | None = Field(None, description="Custom helper field to determine if at home studio")
|
116
|
+
|
117
|
+
|
118
|
+
class BookingList(OtfItemBase):
|
119
|
+
bookings: list[Booking]
|
@@ -0,0 +1,49 @@
|
|
1
|
+
from collections.abc import Hashable
|
2
|
+
from datetime import datetime
|
3
|
+
from typing import Any
|
4
|
+
|
5
|
+
from pydantic import Field
|
6
|
+
|
7
|
+
from otf_api.models.base import OtfItemBase
|
8
|
+
|
9
|
+
|
10
|
+
class Class(OtfItemBase):
|
11
|
+
class_uuid: str = Field(..., alias="classUUId")
|
12
|
+
name: str | None = None
|
13
|
+
description: str | None = None
|
14
|
+
start_date_time: datetime | None = Field(None, alias="startDateTime")
|
15
|
+
end_date_time: datetime | None = Field(None, alias="endDateTime")
|
16
|
+
is_available: bool | None = Field(None, alias="isAvailable")
|
17
|
+
is_cancelled: bool | None = Field(None, alias="isCancelled")
|
18
|
+
total_booked: int | None = Field(None, alias="totalBooked")
|
19
|
+
mbo_class_id: int | None = Field(None, alias="mboClassId")
|
20
|
+
mbo_studio_id: int | None = Field(None, alias="mboStudioId")
|
21
|
+
studio: dict[Hashable, Any] | None = None
|
22
|
+
coach: dict[Hashable, Any] | None = None
|
23
|
+
|
24
|
+
|
25
|
+
class CancelBooking(OtfItemBase):
|
26
|
+
class_booking_id: int = Field(..., alias="classBookingId")
|
27
|
+
class_booking_uuid: str = Field(..., alias="classBookingUUId")
|
28
|
+
otf_class: Class = Field(..., alias="class")
|
29
|
+
|
30
|
+
studio_id: int | None = Field(None, alias="studioId")
|
31
|
+
class_id: int | None = Field(None, alias="classId")
|
32
|
+
is_intro: bool | None = Field(None, alias="isIntro")
|
33
|
+
member_id: int | None = Field(None, alias="memberId")
|
34
|
+
mbo_member_id: str | None = Field(None, alias="mboMemberId")
|
35
|
+
mbo_class_id: int | None = Field(None, alias="mboClassId")
|
36
|
+
mbo_visit_id: int | None = Field(None, alias="mboVisitId")
|
37
|
+
mbo_waitlist_entry_id: int | None = Field(None, alias="mboWaitlistEntryId")
|
38
|
+
mbo_sync_message: str | None = Field(None, alias="mboSyncMessage")
|
39
|
+
status: str | None = None
|
40
|
+
booked_date: datetime | None = Field(None, alias="bookedDate")
|
41
|
+
checked_in_date: datetime | None = Field(None, alias="checkedInDate")
|
42
|
+
cancelled_date: datetime | None = Field(None, alias="cancelledDate")
|
43
|
+
created_by: str | None = Field(None, alias="createdBy")
|
44
|
+
created_date: datetime | None = Field(None, alias="createdDate")
|
45
|
+
updated_by: str | None = Field(None, alias="updatedBy")
|
46
|
+
updated_date: datetime | None = Field(None, alias="updatedDate")
|
47
|
+
is_deleted: bool | None = Field(None, alias="isDeleted")
|
48
|
+
member: dict[Hashable, Any] | None = None
|
49
|
+
continue_retry: bool | None = Field(None, alias="continueRetry")
|
@@ -1,9 +1,9 @@
|
|
1
1
|
from datetime import datetime
|
2
|
-
from typing import Any
|
2
|
+
from typing import Any
|
3
3
|
|
4
4
|
from pydantic import Field
|
5
5
|
|
6
|
-
from otf_api.models.base import OtfItemBase
|
6
|
+
from otf_api.models.base import OtfItemBase
|
7
7
|
|
8
8
|
|
9
9
|
class MetricEntry(OtfItemBase):
|
@@ -22,17 +22,17 @@ class BenchmarkHistory(OtfItemBase):
|
|
22
22
|
date_created: datetime = Field(..., alias="DateCreated")
|
23
23
|
date_updated: datetime = Field(..., alias="DateUpdated")
|
24
24
|
class_time: datetime = Field(..., alias="ClassTime")
|
25
|
-
challenge_sub_category_id: int | None = Field(
|
25
|
+
challenge_sub_category_id: int | None = Field(None, alias="ChallengeSubCategoryId")
|
26
26
|
class_id: int = Field(..., alias="ClassId")
|
27
|
-
substitute_id: int | None = Field(
|
27
|
+
substitute_id: int | None = Field(None, alias="SubstituteId")
|
28
28
|
weight_lbs: int = Field(..., alias="WeightLBS")
|
29
29
|
class_name: str = Field(..., alias="ClassName")
|
30
30
|
coach_name: str = Field(..., alias="CoachName")
|
31
|
-
coach_image_url: str = Field(
|
32
|
-
workout_type_id: int | None = Field(
|
33
|
-
workout_id: int | None = Field(
|
34
|
-
linked_challenges: list[Any] = Field(
|
35
|
-
|
31
|
+
coach_image_url: str | None = Field(None, alias="CoachImageUrl", exclude=True)
|
32
|
+
workout_type_id: int | None = Field(None, alias="WorkoutTypeId")
|
33
|
+
workout_id: int | None = Field(None, alias="WorkoutId")
|
34
|
+
linked_challenges: list[Any] | None = Field(
|
35
|
+
None, alias="LinkedChallenges", exclude=True
|
36
36
|
) # not sure what this will be, never seen it before
|
37
37
|
|
38
38
|
|
@@ -50,7 +50,7 @@ class ChallengeHistory(OtfItemBase):
|
|
50
50
|
|
51
51
|
class ChallengeTrackerDetail(OtfItemBase):
|
52
52
|
challenge_category_id: int = Field(..., alias="ChallengeCategoryId")
|
53
|
-
challenge_sub_category_id: int | None = Field(
|
53
|
+
challenge_sub_category_id: int | None = Field(None, alias="ChallengeSubCategoryId")
|
54
54
|
equipment_id: int = Field(..., alias="EquipmentId")
|
55
55
|
equipment_name: str = Field(..., alias="EquipmentName")
|
56
56
|
metric_entry: MetricEntry = Field(..., alias="MetricEntry")
|
@@ -59,11 +59,10 @@ class ChallengeTrackerDetail(OtfItemBase):
|
|
59
59
|
best_record: float | str = Field(..., alias="BestRecord")
|
60
60
|
last_record: float | str = Field(..., alias="LastRecord")
|
61
61
|
previous_record: float | str = Field(..., alias="PreviousRecord")
|
62
|
-
unit: str | None = Field(
|
62
|
+
unit: str | None = Field(None, alias="Unit")
|
63
63
|
goals: None = Field(..., alias="Goals")
|
64
64
|
challenge_histories: list[ChallengeHistory] = Field(..., alias="ChallengeHistories")
|
65
65
|
|
66
66
|
|
67
|
-
class ChallengeTrackerDetailList(
|
68
|
-
collection_field: ClassVar[str] = "details"
|
67
|
+
class ChallengeTrackerDetailList(OtfItemBase):
|
69
68
|
details: list[ChallengeTrackerDetail]
|
@@ -0,0 +1,80 @@
|
|
1
|
+
from datetime import datetime
|
2
|
+
|
3
|
+
from pydantic import Field
|
4
|
+
|
5
|
+
from otf_api.models.base import OtfItemBase
|
6
|
+
from otf_api.models.enums import DoW
|
7
|
+
from otf_api.models.mixins import OtfClassTimeMixin
|
8
|
+
|
9
|
+
|
10
|
+
class Address(OtfItemBase):
|
11
|
+
line1: str
|
12
|
+
city: str
|
13
|
+
state: str
|
14
|
+
country: str
|
15
|
+
postal_code: str
|
16
|
+
|
17
|
+
|
18
|
+
class Studio(OtfItemBase):
|
19
|
+
id: str
|
20
|
+
name: str
|
21
|
+
mbo_studio_id: str
|
22
|
+
time_zone: str
|
23
|
+
currency_code: str
|
24
|
+
address: Address
|
25
|
+
phone_number: str
|
26
|
+
latitude: float
|
27
|
+
longitude: float
|
28
|
+
|
29
|
+
|
30
|
+
class Coach(OtfItemBase):
|
31
|
+
mbo_staff_id: str
|
32
|
+
first_name: str
|
33
|
+
image_url: str | None = None
|
34
|
+
|
35
|
+
|
36
|
+
class OtfClass(OtfItemBase, OtfClassTimeMixin):
|
37
|
+
id: str
|
38
|
+
ot_class_uuid: str = Field(
|
39
|
+
alias="ot_base_class_uuid",
|
40
|
+
description="The OTF class UUID, this is what shows in a booking response and how you can book a class.",
|
41
|
+
)
|
42
|
+
starts_at: datetime
|
43
|
+
starts_at_local: datetime
|
44
|
+
ends_at: datetime
|
45
|
+
ends_at_local: datetime
|
46
|
+
name: str
|
47
|
+
type: str
|
48
|
+
studio: Studio
|
49
|
+
coach: Coach
|
50
|
+
max_capacity: int
|
51
|
+
booking_capacity: int
|
52
|
+
waitlist_size: int
|
53
|
+
full: bool
|
54
|
+
waitlist_available: bool
|
55
|
+
canceled: bool
|
56
|
+
mbo_class_id: str
|
57
|
+
mbo_class_schedule_id: str
|
58
|
+
mbo_class_description_id: str
|
59
|
+
created_at: datetime
|
60
|
+
updated_at: datetime
|
61
|
+
is_home_studio: bool | None = Field(None, description="Custom helper field to determine if at home studio")
|
62
|
+
is_booked: bool | None = Field(None, description="Custom helper field to determine if class is already booked")
|
63
|
+
|
64
|
+
@property
|
65
|
+
def has_availability(self) -> bool:
|
66
|
+
return not self.full
|
67
|
+
|
68
|
+
@property
|
69
|
+
def day_of_week_enum(self) -> DoW:
|
70
|
+
dow = self.starts_at_local.strftime("%A")
|
71
|
+
return DoW.get_case_insensitive(dow)
|
72
|
+
|
73
|
+
@property
|
74
|
+
def actual_class_uuid(self) -> str:
|
75
|
+
"""The UUID used to book the class"""
|
76
|
+
return self.ot_class_uuid
|
77
|
+
|
78
|
+
|
79
|
+
class OtfClassList(OtfItemBase):
|
80
|
+
classes: list[OtfClass]
|
otf_api/models/enums.py
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
|
3
|
+
|
4
|
+
class StudioStatus(str, Enum):
|
5
|
+
OTHER = "OTHER"
|
6
|
+
ACTIVE = "Active"
|
7
|
+
INACTIVE = "Inactive"
|
8
|
+
COMING_SOON = "Coming Soon"
|
9
|
+
TEMP_CLOSED = "Temporarily Closed"
|
10
|
+
PERM_CLOSED = "Permanently Closed"
|
11
|
+
|
12
|
+
|
13
|
+
class BookingStatus(str, Enum):
|
14
|
+
CheckedIn = "Checked In"
|
15
|
+
CancelCheckinPending = "Cancel Checkin Pending"
|
16
|
+
CancelCheckinRequested = "Cancel Checkin Requested"
|
17
|
+
Cancelled = "Cancelled"
|
18
|
+
LateCancelled = "Late Cancelled"
|
19
|
+
Booked = "Booked"
|
20
|
+
Waitlisted = "Waitlisted"
|
21
|
+
CheckinPending = "Checkin Pending"
|
22
|
+
CheckinRequested = "Checkin Requested"
|
23
|
+
CheckinCancelled = "Checkin Cancelled"
|
24
|
+
|
25
|
+
|
26
|
+
class DoW(str, Enum):
|
27
|
+
MONDAY = "monday"
|
28
|
+
TUESDAY = "tuesday"
|
29
|
+
WEDNESDAY = "wednesday"
|
30
|
+
THURSDAY = "thursday"
|
31
|
+
FRIDAY = "friday"
|
32
|
+
SATURDAY = "saturday"
|
33
|
+
SUNDAY = "sunday"
|
34
|
+
|
35
|
+
@classmethod
|
36
|
+
def get_case_insensitive(cls, value: str) -> "DoW":
|
37
|
+
lcase_to_actual = {item.value.lower(): item for item in cls}
|
38
|
+
return lcase_to_actual[value.lower()]
|
39
|
+
|
40
|
+
|
41
|
+
class ClassType(str, Enum):
|
42
|
+
ORANGE_60_MIN_2G = "Orange 60 Min 2G"
|
43
|
+
TREAD_50 = "Tread 50"
|
44
|
+
STRENGTH_50 = "Strength 50"
|
45
|
+
ORANGE_3G = "Orange 3G"
|
46
|
+
ORANGE_60_TORNADO = "Orange 60 - Tornado"
|
47
|
+
ORANGE_TORNADO = "Orange Tornado"
|
48
|
+
ORANGE_90_MIN_3G = "Orange 90 Min 3G"
|
49
|
+
VIP_CLASS = "VIP Class"
|
50
|
+
OTHER = "Other"
|
51
|
+
|
52
|
+
@classmethod
|
53
|
+
def get_case_insensitive(cls, value: str) -> str:
|
54
|
+
lcase_to_actual = {item.value.lower(): item.value for item in cls}
|
55
|
+
return lcase_to_actual[value.lower()]
|
56
|
+
|
57
|
+
|
58
|
+
class StatsTime(str, Enum):
|
59
|
+
LastYear = "lastYear"
|
60
|
+
ThisYear = "thisYear"
|
61
|
+
LastMonth = "lastMonth"
|
62
|
+
ThisMonth = "thisMonth"
|
63
|
+
LastWeek = "lastWeek"
|
64
|
+
ThisWeek = "thisWeek"
|
65
|
+
AllTime = "allTime"
|
66
|
+
|
67
|
+
|
68
|
+
class EquipmentType(int, Enum):
|
69
|
+
Treadmill = 2
|
70
|
+
Strider = 3
|
71
|
+
Rower = 4
|
72
|
+
Bike = 5
|
73
|
+
WeightFloor = 6
|
74
|
+
PowerWalker = 7
|
75
|
+
|
76
|
+
|
77
|
+
class ChallengeType(int, Enum):
|
78
|
+
Other = 0
|
79
|
+
DriTri = 2
|
80
|
+
MarathonMonth = 5
|
81
|
+
HellWeek = 52
|
82
|
+
Mayhem = 58
|
83
|
+
TwelveDaysOfFitness = 63
|
84
|
+
Transformation = 64
|
85
|
+
RemixInSix = 65
|
86
|
+
Push = 66
|
87
|
+
BackAtIt = 84
|