otf-api 0.2.1__py3-none-any.whl → 0.3.0__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 +12 -67
- otf_api/api.py +794 -36
- otf_api/cli/__init__.py +4 -0
- otf_api/cli/_utilities.py +60 -0
- otf_api/cli/app.py +177 -0
- otf_api/cli/bookings.py +231 -0
- otf_api/cli/prompts.py +162 -0
- otf_api/models/__init__.py +4 -8
- otf_api/models/auth.py +18 -12
- otf_api/models/base.py +205 -2
- otf_api/models/responses/__init__.py +6 -14
- otf_api/models/responses/body_composition_list.py +304 -0
- otf_api/models/responses/book_class.py +405 -0
- otf_api/models/responses/bookings.py +211 -37
- otf_api/models/responses/cancel_booking.py +93 -0
- otf_api/models/responses/challenge_tracker_content.py +6 -6
- otf_api/models/responses/challenge_tracker_detail.py +6 -6
- otf_api/models/responses/classes.py +205 -7
- otf_api/models/responses/enums.py +0 -35
- otf_api/models/responses/favorite_studios.py +5 -5
- otf_api/models/responses/latest_agreement.py +2 -2
- otf_api/models/responses/lifetime_stats.py +92 -0
- otf_api/models/responses/member_detail.py +17 -12
- otf_api/models/responses/member_membership.py +2 -2
- otf_api/models/responses/member_purchases.py +9 -9
- otf_api/models/responses/out_of_studio_workout_history.py +4 -4
- otf_api/models/responses/performance_summary_detail.py +1 -1
- otf_api/models/responses/performance_summary_list.py +13 -13
- otf_api/models/responses/studio_detail.py +10 -10
- otf_api/models/responses/studio_services.py +8 -8
- otf_api/models/responses/telemetry.py +6 -6
- otf_api/models/responses/telemetry_hr_history.py +6 -6
- otf_api/models/responses/telemetry_max_hr.py +3 -3
- otf_api/models/responses/total_classes.py +2 -2
- otf_api/models/responses/workouts.py +4 -4
- otf_api-0.3.0.dist-info/METADATA +55 -0
- otf_api-0.3.0.dist-info/RECORD +42 -0
- otf_api-0.3.0.dist-info/entry_points.txt +3 -0
- otf_api/__version__.py +0 -1
- otf_api/classes_api.py +0 -44
- otf_api/member_api.py +0 -380
- otf_api/performance_api.py +0 -54
- otf_api/studios_api.py +0 -96
- otf_api/telemetry_api.py +0 -95
- otf_api-0.2.1.dist-info/METADATA +0 -284
- otf_api-0.2.1.dist-info/RECORD +0 -38
- {otf_api-0.2.1.dist-info → otf_api-0.3.0.dist-info}/AUTHORS.md +0 -0
- {otf_api-0.2.1.dist-info → otf_api-0.3.0.dist-info}/LICENSE +0 -0
- {otf_api-0.2.1.dist-info → otf_api-0.3.0.dist-info}/WHEEL +0 -0
@@ -1,9 +1,76 @@
|
|
1
1
|
from datetime import datetime
|
2
|
+
from enum import Enum
|
3
|
+
from typing import ClassVar
|
2
4
|
|
3
|
-
from
|
5
|
+
from humanize import precisedelta
|
6
|
+
from inflection import humanize
|
7
|
+
from pydantic import Field
|
8
|
+
from rich.style import Style
|
9
|
+
from rich.styled import Styled
|
10
|
+
from rich.table import Table
|
4
11
|
|
12
|
+
from otf_api.models.base import OtfItemBase, OtfListBase
|
5
13
|
|
6
|
-
|
14
|
+
|
15
|
+
class DoW(str, Enum):
|
16
|
+
monday = "monday"
|
17
|
+
tuesday = "tuesday"
|
18
|
+
wednesday = "wednesday"
|
19
|
+
thursday = "thursday"
|
20
|
+
friday = "friday"
|
21
|
+
saturday = "saturday"
|
22
|
+
sunday = "sunday"
|
23
|
+
|
24
|
+
@classmethod
|
25
|
+
def get_case_insensitive(cls, value: str) -> str:
|
26
|
+
lcase_to_actual = {item.value.lower(): item.value for item in cls}
|
27
|
+
return lcase_to_actual[value.lower()]
|
28
|
+
|
29
|
+
|
30
|
+
class ClassType(str, Enum):
|
31
|
+
ORANGE_60_MIN_2G = "Orange 60 Min 2G"
|
32
|
+
TREAD_50 = "Tread 50"
|
33
|
+
STRENGTH_50 = "Strength 50"
|
34
|
+
ORANGE_3G = "Orange 3G"
|
35
|
+
ORANGE_60_TORNADO = "Orange 60 - Tornado"
|
36
|
+
ORANGE_TORNADO = "Orange Tornado"
|
37
|
+
ORANGE_90_MIN_3G = "Orange 90 Min 3G"
|
38
|
+
VIP_CLASS = "VIP Class"
|
39
|
+
OTHER = "Other"
|
40
|
+
|
41
|
+
@classmethod
|
42
|
+
def all_statuses(cls) -> list[str]:
|
43
|
+
return list(cls.__members__.values())
|
44
|
+
|
45
|
+
@classmethod
|
46
|
+
def get_from_key_insensitive(cls, key: str) -> "ClassType":
|
47
|
+
lcase_to_actual = {item.lower(): item for item in cls._member_map_}
|
48
|
+
val = cls.__members__.get(lcase_to_actual[key.lower()])
|
49
|
+
if not val:
|
50
|
+
raise ValueError(f"Invalid ClassType: {key}")
|
51
|
+
return val
|
52
|
+
|
53
|
+
@classmethod
|
54
|
+
def get_case_insensitive(cls, value: str) -> str:
|
55
|
+
lcase_to_actual = {item.value.lower(): item.value for item in cls}
|
56
|
+
return lcase_to_actual[value.lower()]
|
57
|
+
|
58
|
+
|
59
|
+
class ClassTypeCli(str, Enum):
|
60
|
+
"""Flipped enum so that the CLI does not have values with spaces"""
|
61
|
+
|
62
|
+
ORANGE_60_MIN_2G = "Orange_60_Min_2G"
|
63
|
+
TREAD_50 = "Tread_50"
|
64
|
+
STRENGTH_50 = "Strength_50"
|
65
|
+
ORANGE_3G = "Orange_3G"
|
66
|
+
ORANGE_60_TORNADO = "Orange_60_Tornado"
|
67
|
+
ORANGE_TORNADO = "Orange_Tornado"
|
68
|
+
ORANGE_90_MIN_3G = "Orange_90_Min_3G"
|
69
|
+
VIP_CLASS = "VIP_Class"
|
70
|
+
OTHER = "Other"
|
71
|
+
|
72
|
+
|
73
|
+
class Address(OtfItemBase):
|
7
74
|
line1: str
|
8
75
|
city: str
|
9
76
|
state: str
|
@@ -11,7 +78,7 @@ class Address(OtfBaseModel):
|
|
11
78
|
postal_code: str
|
12
79
|
|
13
80
|
|
14
|
-
class Studio(
|
81
|
+
class Studio(OtfItemBase):
|
15
82
|
id: str
|
16
83
|
name: str
|
17
84
|
mbo_studio_id: str
|
@@ -23,15 +90,57 @@ class Studio(OtfBaseModel):
|
|
23
90
|
longitude: float
|
24
91
|
|
25
92
|
|
26
|
-
class Coach(
|
93
|
+
class Coach(OtfItemBase):
|
27
94
|
mbo_staff_id: str
|
28
95
|
first_name: str
|
29
96
|
image_url: str | None = None
|
30
97
|
|
31
98
|
|
32
|
-
class
|
99
|
+
class OtfClassTimeMixin:
|
100
|
+
starts_at_local: datetime
|
101
|
+
ends_at_local: datetime
|
102
|
+
name: str
|
103
|
+
|
104
|
+
@property
|
105
|
+
def day_of_week(self) -> str:
|
106
|
+
return self.starts_at_local.strftime("%A")
|
107
|
+
|
108
|
+
@property
|
109
|
+
def date(self) -> str:
|
110
|
+
return self.starts_at_local.strftime("%Y-%m-%d")
|
111
|
+
|
112
|
+
@property
|
113
|
+
def time(self) -> str:
|
114
|
+
"""Returns time in 12 hour clock format, with no leading 0"""
|
115
|
+
val = self.starts_at_local.strftime("%I:%M %p")
|
116
|
+
if val[0] == "0":
|
117
|
+
val = " " + val[1:]
|
118
|
+
|
119
|
+
return val
|
120
|
+
|
121
|
+
@property
|
122
|
+
def duration(self) -> str:
|
123
|
+
duration = self.ends_at_local - self.starts_at_local
|
124
|
+
human_val: str = precisedelta(duration, minimum_unit="minutes")
|
125
|
+
if human_val == "1 hour and 30 minutes":
|
126
|
+
return "90 minutes"
|
127
|
+
return human_val
|
128
|
+
|
129
|
+
@property
|
130
|
+
def class_type(self) -> ClassType:
|
131
|
+
for class_type in ClassType:
|
132
|
+
if class_type.value in self.name:
|
133
|
+
return class_type
|
134
|
+
|
135
|
+
return ClassType.OTHER
|
136
|
+
|
137
|
+
|
138
|
+
class OtfClass(OtfItemBase, OtfClassTimeMixin):
|
33
139
|
id: str
|
34
|
-
|
140
|
+
ot_class_uuid: str = Field(
|
141
|
+
alias="ot_base_class_uuid",
|
142
|
+
description="The OTF class UUID, this is what shows in a booking response and how you can book a class.",
|
143
|
+
)
|
35
144
|
starts_at: datetime
|
36
145
|
starts_at_local: datetime
|
37
146
|
ends_at: datetime
|
@@ -51,7 +160,96 @@ class OtfClass(OtfBaseModel):
|
|
51
160
|
mbo_class_description_id: str
|
52
161
|
created_at: datetime
|
53
162
|
updated_at: datetime
|
163
|
+
is_home_studio: bool | None = Field(None, description="Custom helper field to determine if at home studio")
|
164
|
+
is_booked: bool | None = Field(None, description="Custom helper field to determine if class is already booked")
|
165
|
+
|
166
|
+
@property
|
167
|
+
def has_availability(self) -> bool:
|
168
|
+
return not self.full
|
169
|
+
|
170
|
+
@property
|
171
|
+
def id_val(self) -> str:
|
172
|
+
return self.ot_class_uuid
|
173
|
+
|
174
|
+
@property
|
175
|
+
def day_of_week_enum(self) -> DoW:
|
176
|
+
dow = self.starts_at_local.strftime("%A")
|
177
|
+
return DoW.get_case_insensitive(dow)
|
178
|
+
|
179
|
+
@property
|
180
|
+
def sidebar_data(self) -> Table:
|
181
|
+
data = {
|
182
|
+
"class_date": self.date,
|
183
|
+
"class_time": self.time.strip(),
|
184
|
+
"class_name": self.name,
|
185
|
+
"class_id": self.id_val,
|
186
|
+
"available": self.has_availability,
|
187
|
+
"waitlist_available": self.waitlist_available,
|
188
|
+
"studio_address": self.studio.address.line1,
|
189
|
+
"coach_name": self.coach.first_name,
|
190
|
+
"waitlist_size": self.waitlist_size,
|
191
|
+
"max_capacity": self.max_capacity,
|
192
|
+
}
|
193
|
+
|
194
|
+
if not self.full:
|
195
|
+
del data["waitlist_available"]
|
196
|
+
del data["waitlist_size"]
|
197
|
+
|
198
|
+
table = Table(expand=True, show_header=False, show_footer=False)
|
199
|
+
table.add_column("Key", style="cyan", ratio=1)
|
200
|
+
table.add_column("Value", style="magenta", ratio=2)
|
54
201
|
|
202
|
+
for key, value in data.items():
|
203
|
+
if value is False:
|
204
|
+
table.add_row(key, Styled(str(value), style="red"))
|
205
|
+
else:
|
206
|
+
table.add_row(key, str(value))
|
55
207
|
|
56
|
-
|
208
|
+
return table
|
209
|
+
|
210
|
+
def get_style(self, is_selected: bool = False) -> Style:
|
211
|
+
style = super().get_style(is_selected)
|
212
|
+
if self.is_booked:
|
213
|
+
style = Style(color="grey58")
|
214
|
+
return style
|
215
|
+
|
216
|
+
@classmethod
|
217
|
+
def attr_to_column_header(cls, attr: str) -> str:
|
218
|
+
attr_map = {k: humanize(k) for k in cls.model_fields}
|
219
|
+
overrides = {
|
220
|
+
"day_of_week": "Class DoW",
|
221
|
+
"date": "Class Date",
|
222
|
+
"time": "Class Time",
|
223
|
+
"duration": "Class Duration",
|
224
|
+
"name": "Class Name",
|
225
|
+
"is_home_studio": "Home Studio",
|
226
|
+
"is_booked": "Booked",
|
227
|
+
}
|
228
|
+
|
229
|
+
attr_map.update(overrides)
|
230
|
+
|
231
|
+
return attr_map.get(attr, attr)
|
232
|
+
|
233
|
+
|
234
|
+
class OtfClassList(OtfListBase):
|
235
|
+
collection_field: ClassVar[str] = "classes"
|
57
236
|
classes: list[OtfClass]
|
237
|
+
|
238
|
+
@staticmethod
|
239
|
+
def book_class_columns() -> list[str]:
|
240
|
+
return [
|
241
|
+
"day_of_week",
|
242
|
+
"date",
|
243
|
+
"time",
|
244
|
+
"duration",
|
245
|
+
"name",
|
246
|
+
"studio.name",
|
247
|
+
"is_home_studio",
|
248
|
+
"is_booked",
|
249
|
+
]
|
250
|
+
|
251
|
+
def to_table(self, columns: list[str] | None = None) -> Table:
|
252
|
+
if not columns:
|
253
|
+
columns = self.book_class_columns()
|
254
|
+
|
255
|
+
return super().to_table(columns)
|
@@ -1,19 +1,6 @@
|
|
1
1
|
from enum import Enum
|
2
2
|
|
3
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
|
-
@classmethod
|
13
|
-
def all_statuses(cls) -> list[str]:
|
14
|
-
return list(cls.__members__.values())
|
15
|
-
|
16
|
-
|
17
4
|
class EquipmentType(int, Enum):
|
18
5
|
Treadmill = 2
|
19
6
|
Strider = 3
|
@@ -36,23 +23,6 @@ class ChallengeType(int, Enum):
|
|
36
23
|
BackAtIt = 84
|
37
24
|
|
38
25
|
|
39
|
-
class BookingStatus(str, Enum):
|
40
|
-
CheckedIn = "Checked In"
|
41
|
-
CancelCheckinPending = "Cancel Checkin Pending"
|
42
|
-
CancelCheckinRequested = "Cancel Checkin Requested"
|
43
|
-
Cancelled = "Cancelled"
|
44
|
-
LateCancelled = "Late Cancelled"
|
45
|
-
Booked = "Booked"
|
46
|
-
Waitlisted = "Waitlisted"
|
47
|
-
CheckinPending = "Checkin Pending"
|
48
|
-
CheckinRequested = "Checkin Requested"
|
49
|
-
CheckinCancelled = "Checkin Cancelled"
|
50
|
-
|
51
|
-
@classmethod
|
52
|
-
def all_statuses(cls) -> list[str]:
|
53
|
-
return list(cls.__members__.values())
|
54
|
-
|
55
|
-
|
56
26
|
class HistoryBookingStatus(str, Enum):
|
57
27
|
Attended = "Attended"
|
58
28
|
Cancelled = "Cancelled"
|
@@ -80,8 +50,3 @@ class HistoryClassStatus(str, Enum):
|
|
80
50
|
@classmethod
|
81
51
|
def all_statuses(cls) -> list[str]:
|
82
52
|
return list(cls.__members__.values())
|
83
|
-
|
84
|
-
|
85
|
-
ALL_CLASS_STATUS = BookingStatus.all_statuses()
|
86
|
-
ALL_HISTORY_CLASS_STATUS = HistoryClassStatus.all_statuses()
|
87
|
-
ALL_STUDIO_STATUS = StudioStatus.all_statuses()
|
@@ -2,10 +2,10 @@ from datetime import datetime
|
|
2
2
|
|
3
3
|
from pydantic import Field
|
4
4
|
|
5
|
-
from otf_api.models.base import
|
5
|
+
from otf_api.models.base import OtfItemBase
|
6
6
|
|
7
7
|
|
8
|
-
class Location(
|
8
|
+
class Location(OtfItemBase):
|
9
9
|
location_id: int = Field(..., alias="locationId")
|
10
10
|
location_uuid: str = Field(..., alias="locationUUId")
|
11
11
|
studio_id: int = Field(..., alias="studioId")
|
@@ -21,7 +21,7 @@ class Location(OtfBaseModel):
|
|
21
21
|
postal_code: str = Field(..., alias="postalCode")
|
22
22
|
|
23
23
|
|
24
|
-
class StudioLocation(
|
24
|
+
class StudioLocation(OtfItemBase):
|
25
25
|
bill_to_address: str = Field(..., alias="billToAddress")
|
26
26
|
bill_to_address2: str = Field(..., alias="billToAddress2")
|
27
27
|
bill_to_city: str = Field(..., alias="billToCity")
|
@@ -51,7 +51,7 @@ class StudioLocation(OtfBaseModel):
|
|
51
51
|
longitude: str
|
52
52
|
|
53
53
|
|
54
|
-
class FavoriteStudio(
|
54
|
+
class FavoriteStudio(OtfItemBase):
|
55
55
|
studio_id: int = Field(..., alias="studioId")
|
56
56
|
studio_uuid: str = Field(..., alias="studioUUId")
|
57
57
|
mbo_studio_id: int = Field(..., alias="mboStudioId")
|
@@ -94,7 +94,7 @@ class FavoriteStudio(OtfBaseModel):
|
|
94
94
|
studio_location: StudioLocation = Field(..., alias="studioLocation")
|
95
95
|
|
96
96
|
|
97
|
-
class FavoriteStudioList(
|
97
|
+
class FavoriteStudioList(OtfItemBase):
|
98
98
|
studios: list[FavoriteStudio]
|
99
99
|
|
100
100
|
@property
|
@@ -2,10 +2,10 @@ from datetime import datetime
|
|
2
2
|
|
3
3
|
from pydantic import Field
|
4
4
|
|
5
|
-
from otf_api.models.base import
|
5
|
+
from otf_api.models.base import OtfItemBase
|
6
6
|
|
7
7
|
|
8
|
-
class LatestAgreement(
|
8
|
+
class LatestAgreement(OtfItemBase):
|
9
9
|
file_url: str = Field(..., alias="fileUrl")
|
10
10
|
agreement_id: int = Field(..., alias="agreementId")
|
11
11
|
agreement_uuid: str = Field(..., alias="agreementUUId")
|
@@ -0,0 +1,92 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
|
3
|
+
from pydantic import BaseModel, Field
|
4
|
+
|
5
|
+
|
6
|
+
class StatsTime(str, Enum):
|
7
|
+
LastYear = "lastYear"
|
8
|
+
ThisYear = "thisYear"
|
9
|
+
LastMonth = "lastMonth"
|
10
|
+
ThisMonth = "thisMonth"
|
11
|
+
LastWeek = "lastWeek"
|
12
|
+
ThisWeek = "thisWeek"
|
13
|
+
AllTime = "allTime"
|
14
|
+
|
15
|
+
|
16
|
+
class StatsType(str, Enum):
|
17
|
+
Home = "outStudio"
|
18
|
+
Studio = "inStudio"
|
19
|
+
All = "allStats"
|
20
|
+
|
21
|
+
|
22
|
+
class OutStudioMixin(BaseModel):
|
23
|
+
walking_distance: float = Field(..., alias="walkingDistance")
|
24
|
+
running_distance: float = Field(..., alias="runningDistance")
|
25
|
+
cycling_distance: float = Field(..., alias="cyclingDistance")
|
26
|
+
|
27
|
+
|
28
|
+
class InStudioMixin(BaseModel):
|
29
|
+
treadmill_distance: float = Field(..., alias="treadmillDistance")
|
30
|
+
treadmill_elevation_gained: float = Field(..., alias="treadmillElevationGained")
|
31
|
+
rower_distance: float = Field(..., alias="rowerDistance")
|
32
|
+
rower_watt: float = Field(..., alias="rowerWatt")
|
33
|
+
|
34
|
+
|
35
|
+
class BaseStatsData(BaseModel):
|
36
|
+
calories: float
|
37
|
+
splat_point: float = Field(..., alias="splatPoint")
|
38
|
+
total_black_zone: float = Field(..., alias="totalBlackZone")
|
39
|
+
total_blue_zone: float = Field(..., alias="totalBlueZone")
|
40
|
+
total_green_zone: float = Field(..., alias="totalGreenZone")
|
41
|
+
total_orange_zone: float = Field(..., alias="totalOrangeZone")
|
42
|
+
total_red_zone: float = Field(..., alias="totalRedZone")
|
43
|
+
workout_duration: float = Field(..., alias="workoutDuration")
|
44
|
+
step_count: float = Field(..., alias="stepCount")
|
45
|
+
|
46
|
+
|
47
|
+
class InStudioStatsData(InStudioMixin, BaseStatsData):
|
48
|
+
pass
|
49
|
+
|
50
|
+
|
51
|
+
class OutStudioStatsData(OutStudioMixin, BaseStatsData):
|
52
|
+
pass
|
53
|
+
|
54
|
+
|
55
|
+
class AllStatsData(OutStudioMixin, InStudioMixin, BaseStatsData):
|
56
|
+
pass
|
57
|
+
|
58
|
+
|
59
|
+
class OutStudioTimeStats(BaseModel):
|
60
|
+
last_year: OutStudioStatsData = Field(..., alias="lastYear")
|
61
|
+
this_year: OutStudioStatsData = Field(..., alias="thisYear")
|
62
|
+
last_month: OutStudioStatsData = Field(..., alias="lastMonth")
|
63
|
+
this_month: OutStudioStatsData = Field(..., alias="thisMonth")
|
64
|
+
last_week: OutStudioStatsData = Field(..., alias="lastWeek")
|
65
|
+
this_week: OutStudioStatsData = Field(..., alias="thisWeek")
|
66
|
+
all_time: OutStudioStatsData = Field(..., alias="allTime")
|
67
|
+
|
68
|
+
|
69
|
+
class InStudioTimeStats(BaseModel):
|
70
|
+
last_year: InStudioStatsData = Field(..., alias="lastYear")
|
71
|
+
this_year: InStudioStatsData = Field(..., alias="thisYear")
|
72
|
+
last_month: InStudioStatsData = Field(..., alias="lastMonth")
|
73
|
+
this_month: InStudioStatsData = Field(..., alias="thisMonth")
|
74
|
+
last_week: InStudioStatsData = Field(..., alias="lastWeek")
|
75
|
+
this_week: InStudioStatsData = Field(..., alias="thisWeek")
|
76
|
+
all_time: InStudioStatsData = Field(..., alias="allTime")
|
77
|
+
|
78
|
+
|
79
|
+
class AllStatsTimeStats(BaseModel):
|
80
|
+
last_year: AllStatsData = Field(..., alias="lastYear")
|
81
|
+
this_year: AllStatsData = Field(..., alias="thisYear")
|
82
|
+
last_month: AllStatsData = Field(..., alias="lastMonth")
|
83
|
+
this_month: AllStatsData = Field(..., alias="thisMonth")
|
84
|
+
last_week: AllStatsData = Field(..., alias="lastWeek")
|
85
|
+
this_week: AllStatsData = Field(..., alias="thisWeek")
|
86
|
+
all_time: AllStatsData = Field(..., alias="allTime")
|
87
|
+
|
88
|
+
|
89
|
+
class StatsResponse(BaseModel):
|
90
|
+
all_stats: AllStatsTimeStats = Field(..., alias="allStats")
|
91
|
+
in_studio: InStudioTimeStats = Field(..., alias="inStudio")
|
92
|
+
out_studio: OutStudioTimeStats = Field(..., alias="outStudio")
|
@@ -3,12 +3,11 @@ from typing import Any
|
|
3
3
|
|
4
4
|
from pydantic import Field
|
5
5
|
|
6
|
-
from otf_api.models.base import
|
6
|
+
from otf_api.models.base import OtfItemBase
|
7
7
|
|
8
8
|
|
9
|
-
class Address(
|
10
|
-
member_address_uuid: str = Field(
|
11
|
-
memberaddress_uuid: str = Field(..., alias="memberaddressUUId")
|
9
|
+
class Address(OtfItemBase):
|
10
|
+
member_address_uuid: str | None = Field(None, alias="memberAddressUUId")
|
12
11
|
type: str
|
13
12
|
address1: str
|
14
13
|
address2: str | None = None
|
@@ -17,28 +16,34 @@ class Address(OtfBaseModel):
|
|
17
16
|
postal_code: str = Field(..., alias="postalCode")
|
18
17
|
country: str
|
19
18
|
|
19
|
+
def __init__(self, **data):
|
20
|
+
if "memberaddressUUId" in data:
|
21
|
+
data["memberAddressUUId"] = data.pop("memberaddressUUId")
|
20
22
|
|
21
|
-
|
23
|
+
super().__init__(**data)
|
24
|
+
|
25
|
+
|
26
|
+
class MemberCreditCard(OtfItemBase):
|
22
27
|
name_on_card: str = Field(..., alias="nameOnCard")
|
23
28
|
cc_type: str = Field(..., alias="ccType")
|
24
29
|
cc_last4: str = Field(..., alias="ccLast4")
|
25
30
|
|
26
31
|
|
27
|
-
class PhysicalCountryDetails(
|
32
|
+
class PhysicalCountryDetails(OtfItemBase):
|
28
33
|
country_code: str = Field(..., alias="countryCode")
|
29
34
|
description: str
|
30
35
|
|
31
36
|
|
32
|
-
class StudioLocation(
|
37
|
+
class StudioLocation(OtfItemBase):
|
33
38
|
physical_country_id: int = Field(..., alias="physicalCountryId")
|
34
39
|
physical_country_details: PhysicalCountryDetails = Field(..., alias="physicalCountryDetails")
|
35
40
|
|
36
41
|
|
37
|
-
class StudioPartner(
|
42
|
+
class StudioPartner(OtfItemBase):
|
38
43
|
studio_acs_id: str = Field(..., alias="studioAcsId")
|
39
44
|
|
40
45
|
|
41
|
-
class HomeStudio(
|
46
|
+
class HomeStudio(OtfItemBase):
|
42
47
|
studio_id: int = Field(..., alias="studioId")
|
43
48
|
studio_uuid: str = Field(..., alias="studioUUId")
|
44
49
|
studio_name: str = Field(..., alias="studioName")
|
@@ -51,7 +56,7 @@ class HomeStudio(OtfBaseModel):
|
|
51
56
|
studio_partner: StudioPartner = Field(..., alias="studioPartner")
|
52
57
|
|
53
58
|
|
54
|
-
class MemberProfile(
|
59
|
+
class MemberProfile(OtfItemBase):
|
55
60
|
member_profile_uuid: str = Field(..., alias="memberProfileUUId")
|
56
61
|
unit_of_measure: str = Field(..., alias="unitOfMeasure")
|
57
62
|
max_hr_type: str = Field(..., alias="maxHrType")
|
@@ -61,7 +66,7 @@ class MemberProfile(OtfBaseModel):
|
|
61
66
|
member_optin_flow_type_id: int = Field(..., alias="memberOptinFlowTypeId")
|
62
67
|
|
63
68
|
|
64
|
-
class MemberClassSummary(
|
69
|
+
class MemberClassSummary(OtfItemBase):
|
65
70
|
total_classes_booked: int = Field(..., alias="totalClassesBooked")
|
66
71
|
total_classes_attended: int = Field(..., alias="totalClassesAttended")
|
67
72
|
total_intro: int = Field(..., alias="totalIntro")
|
@@ -75,7 +80,7 @@ class MemberClassSummary(OtfBaseModel):
|
|
75
80
|
last_class_studio_visited: int = Field(..., alias="lastClassStudioVisited")
|
76
81
|
|
77
82
|
|
78
|
-
class MemberDetail(
|
83
|
+
class MemberDetail(OtfItemBase):
|
79
84
|
member_id: int = Field(..., alias="memberId")
|
80
85
|
member_uuid: str = Field(..., alias="memberUUId")
|
81
86
|
cognito_id: str = Field(..., alias="cognitoId")
|
@@ -2,10 +2,10 @@ from datetime import datetime
|
|
2
2
|
|
3
3
|
from pydantic import Field
|
4
4
|
|
5
|
-
from otf_api.models.base import
|
5
|
+
from otf_api.models.base import OtfItemBase
|
6
6
|
|
7
7
|
|
8
|
-
class MemberMembership(
|
8
|
+
class MemberMembership(OtfItemBase):
|
9
9
|
member_membership_id: int = Field(..., alias="memberMembershipId")
|
10
10
|
member_membership_uuid: str = Field(..., alias="memberMembershipUUId")
|
11
11
|
membership_id: int = Field(..., alias="membershipId")
|
@@ -2,10 +2,10 @@ from datetime import datetime
|
|
2
2
|
|
3
3
|
from pydantic import Field
|
4
4
|
|
5
|
-
from otf_api.models.base import
|
5
|
+
from otf_api.models.base import OtfItemBase
|
6
6
|
|
7
7
|
|
8
|
-
class Location(
|
8
|
+
class Location(OtfItemBase):
|
9
9
|
phone: str
|
10
10
|
latitude: str
|
11
11
|
longitude: str
|
@@ -16,16 +16,16 @@ class Location(OtfBaseModel):
|
|
16
16
|
postal_code: str = Field(..., alias="postalCode")
|
17
17
|
|
18
18
|
|
19
|
-
class Currency(
|
19
|
+
class Currency(OtfItemBase):
|
20
20
|
currency_alphabetic_code: str = Field(..., alias="currencyAlphabeticCode")
|
21
21
|
|
22
22
|
|
23
|
-
class DefaultCurrency(
|
23
|
+
class DefaultCurrency(OtfItemBase):
|
24
24
|
currency_id: int = Field(..., alias="currencyId")
|
25
25
|
currency: Currency
|
26
26
|
|
27
27
|
|
28
|
-
class Country(
|
28
|
+
class Country(OtfItemBase):
|
29
29
|
country_id: int = Field(..., alias="countryId")
|
30
30
|
country_code: str = Field(..., alias="countryCode")
|
31
31
|
description: str
|
@@ -33,7 +33,7 @@ class Country(OtfBaseModel):
|
|
33
33
|
default_currency: DefaultCurrency = Field(..., alias="defaultCurrency")
|
34
34
|
|
35
35
|
|
36
|
-
class StudioLocation(
|
36
|
+
class StudioLocation(OtfItemBase):
|
37
37
|
studio_location_id: int = Field(..., alias="studioLocationId")
|
38
38
|
bill_to_address: str = Field(..., alias="billToAddress")
|
39
39
|
bill_to_address2: str = Field(..., alias="billToAddress2")
|
@@ -65,7 +65,7 @@ class StudioLocation(OtfBaseModel):
|
|
65
65
|
country: Country
|
66
66
|
|
67
67
|
|
68
|
-
class Studio(
|
68
|
+
class Studio(OtfItemBase):
|
69
69
|
studio_id: int = Field(..., alias="studioId")
|
70
70
|
studio_uuid: str = Field(..., alias="studioUUId")
|
71
71
|
mbo_studio_id: int = Field(..., alias="mboStudioId")
|
@@ -109,7 +109,7 @@ class Studio(OtfBaseModel):
|
|
109
109
|
studio_location: StudioLocation = Field(..., alias="studioLocation")
|
110
110
|
|
111
111
|
|
112
|
-
class MemberPurchase(
|
112
|
+
class MemberPurchase(OtfItemBase):
|
113
113
|
member_purchase_id: int = Field(..., alias="memberPurchaseId")
|
114
114
|
member_purchase_uuid: str = Field(..., alias="memberPurchaseUUId")
|
115
115
|
studio_id: int = Field(..., alias="studioId")
|
@@ -131,5 +131,5 @@ class MemberPurchase(OtfBaseModel):
|
|
131
131
|
studio: Studio
|
132
132
|
|
133
133
|
|
134
|
-
class MemberPurchaseList(
|
134
|
+
class MemberPurchaseList(OtfItemBase):
|
135
135
|
data: list[MemberPurchase]
|
@@ -2,16 +2,16 @@ from datetime import datetime
|
|
2
2
|
|
3
3
|
from pydantic import Field
|
4
4
|
|
5
|
-
from otf_api.models.base import
|
5
|
+
from otf_api.models.base import OtfItemBase
|
6
6
|
|
7
7
|
|
8
|
-
class WorkoutType(
|
8
|
+
class WorkoutType(OtfItemBase):
|
9
9
|
id: int
|
10
10
|
display_name: str = Field(..., alias="displayName")
|
11
11
|
icon: str
|
12
12
|
|
13
13
|
|
14
|
-
class OutOfStudioWorkoutHistory(
|
14
|
+
class OutOfStudioWorkoutHistory(OtfItemBase):
|
15
15
|
workout_date: datetime = Field(..., alias="workoutDate")
|
16
16
|
start_time: datetime = Field(..., alias="startTime")
|
17
17
|
end_time: datetime = Field(..., alias="endTime")
|
@@ -37,5 +37,5 @@ class OutOfStudioWorkoutHistory(OtfBaseModel):
|
|
37
37
|
max_heartrate: int = Field(..., alias="maxHeartrate")
|
38
38
|
|
39
39
|
|
40
|
-
class OutOfStudioWorkoutHistoryList(
|
40
|
+
class OutOfStudioWorkoutHistoryList(OtfItemBase):
|
41
41
|
data: list[OutOfStudioWorkoutHistory]
|