otf-api 0.8.2__py3-none-any.whl → 0.9.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.
Files changed (43) hide show
  1. otf_api/__init__.py +7 -4
  2. otf_api/api.py +699 -480
  3. otf_api/auth/__init__.py +4 -0
  4. otf_api/auth/auth.py +234 -0
  5. otf_api/auth/user.py +66 -0
  6. otf_api/auth/utils.py +129 -0
  7. otf_api/exceptions.py +38 -5
  8. otf_api/filters.py +97 -0
  9. otf_api/logging.py +19 -0
  10. otf_api/models/__init__.py +27 -38
  11. otf_api/models/body_composition_list.py +47 -50
  12. otf_api/models/bookings.py +63 -87
  13. otf_api/models/challenge_tracker_content.py +42 -21
  14. otf_api/models/challenge_tracker_detail.py +68 -48
  15. otf_api/models/classes.py +53 -62
  16. otf_api/models/enums.py +108 -30
  17. otf_api/models/lifetime_stats.py +59 -45
  18. otf_api/models/member_detail.py +95 -115
  19. otf_api/models/member_membership.py +18 -17
  20. otf_api/models/member_purchases.py +21 -127
  21. otf_api/models/mixins.py +37 -33
  22. otf_api/models/notifications.py +17 -0
  23. otf_api/models/out_of_studio_workout_history.py +22 -31
  24. otf_api/models/performance_summary_detail.py +47 -42
  25. otf_api/models/performance_summary_list.py +19 -37
  26. otf_api/models/studio_detail.py +51 -98
  27. otf_api/models/studio_services.py +27 -48
  28. otf_api/models/telemetry.py +14 -5
  29. otf_api/utils.py +134 -0
  30. {otf_api-0.8.2.dist-info → otf_api-0.9.1.dist-info}/METADATA +21 -10
  31. otf_api-0.9.1.dist-info/RECORD +35 -0
  32. {otf_api-0.8.2.dist-info → otf_api-0.9.1.dist-info}/WHEEL +1 -1
  33. otf_api/auth.py +0 -316
  34. otf_api/models/book_class.py +0 -89
  35. otf_api/models/cancel_booking.py +0 -49
  36. otf_api/models/favorite_studios.py +0 -106
  37. otf_api/models/latest_agreement.py +0 -21
  38. otf_api/models/telemetry_hr_history.py +0 -34
  39. otf_api/models/telemetry_max_hr.py +0 -13
  40. otf_api/models/total_classes.py +0 -8
  41. otf_api-0.8.2.dist-info/AUTHORS.md +0 -9
  42. otf_api-0.8.2.dist-info/RECORD +0 -36
  43. {otf_api-0.8.2.dist-info → otf_api-0.9.1.dist-info}/LICENSE +0 -0
@@ -1,135 +1,115 @@
1
1
  from datetime import date, datetime
2
- from typing import Any
3
2
 
4
3
  from pydantic import Field, field_validator
5
4
 
6
5
  from otf_api.models.base import OtfItemBase
6
+ from otf_api.models.mixins import AddressMixin
7
+ from otf_api.models.studio_detail import StudioDetail
7
8
 
8
9
 
9
- class Address(OtfItemBase):
10
- member_address_uuid: str | None = Field(None, alias="memberAddressUUId")
11
- type: str
12
- address1: str
13
- address2: str | None = None
14
- suburb: str | None = None
15
- territory: str
16
- postal_code: str = Field(..., alias="postalCode")
17
- country: str
18
-
19
-
20
- class MemberCreditCard(OtfItemBase):
21
- name_on_card: str = Field(..., alias="nameOnCard")
22
- cc_type: str = Field(..., alias="ccType")
23
- cc_last4: str = Field(..., alias="ccLast4")
24
-
25
-
26
- class PhysicalCountryDetails(OtfItemBase):
27
- country_code: str = Field(..., alias="countryCode")
28
- description: str
29
-
30
-
31
- class StudioLocation(OtfItemBase):
32
- physical_country_id: int = Field(..., alias="physicalCountryId")
33
- physical_country_details: PhysicalCountryDetails = Field(..., alias="physicalCountryDetails")
34
-
35
-
36
- class StudioPartner(OtfItemBase):
37
- studio_acs_id: str = Field(..., alias="studioAcsId")
38
-
39
-
40
- class HomeStudio(OtfItemBase):
41
- studio_id: int = Field(..., alias="studioId")
42
- studio_uuid: str = Field(..., alias="studioUUId")
43
- studio_name: str = Field(..., alias="studioName")
44
- studio_number: str = Field(..., alias="studioNumber")
45
- mbo_studio_id: int = Field(..., alias="mboStudioId")
46
- time_zone: str = Field(..., alias="timeZone")
47
- is_integrated: bool = Field(..., alias="isIntegrated")
48
- studio_status: str = Field(..., alias="studioStatus")
49
- studio_location: StudioLocation = Field(..., alias="studioLocation")
50
- studio_partner: StudioPartner = Field(..., alias="studioPartner")
10
+ class Address(AddressMixin):
11
+ member_address_uuid: str | None = Field(None, alias="memberAddressUUId", exclude=True, repr=False)
12
+ type: str | None = None
51
13
 
52
14
 
53
15
  class MemberProfile(OtfItemBase):
54
- member_profile_uuid: str = Field(..., alias="memberProfileUUId")
55
- unit_of_measure: str = Field(..., alias="unitOfMeasure")
56
- max_hr_type: str = Field(..., alias="maxHrType")
57
- manual_max_hr: int = Field(..., alias="manualMaxHr")
58
- formula_max_hr: int = Field(..., alias="formulaMaxHr")
59
- automated_hr: int = Field(..., alias="automatedHr")
60
- member_optin_flow_type_id: int = Field(..., alias="memberOptinFlowTypeId")
16
+ unit_of_measure: str | None = Field(None, alias="unitOfMeasure")
17
+ max_hr_type: str | None = Field(None, alias="maxHrType")
18
+ manual_max_hr: int | None = Field(None, alias="manualMaxHr")
19
+ formula_max_hr: int | None = Field(None, alias="formulaMaxHr")
20
+ automated_hr: int | None = Field(None, alias="automatedHr")
61
21
 
22
+ member_profile_uuid: str | None = Field(None, alias="memberProfileUUId", exclude=True, repr=False)
23
+ member_optin_flow_type_id: int | None = Field(None, alias="memberOptinFlowTypeId", exclude=True, repr=False)
62
24
 
63
- class MemberClassSummary(OtfItemBase):
64
- total_classes_booked: int = Field(..., alias="totalClassesBooked")
65
- total_classes_attended: int = Field(..., alias="totalClassesAttended")
66
- total_intro: int = Field(..., alias="totalIntro")
67
- total_ot_live_classes_booked: int = Field(..., alias="totalOTLiveClassesBooked")
68
- total_ot_live_classes_attended: int = Field(..., alias="totalOTLiveClassesAttended")
69
- total_classes_used_hrm: int = Field(..., alias="totalClassesUsedHRM")
70
- total_studios_visited: int = Field(..., alias="totalStudiosVisited")
71
- first_visit_date: datetime = Field(..., alias="firstVisitDate")
72
- last_class_visited_date: datetime = Field(..., alias="lastClassVisitedDate")
73
- last_class_booked_date: datetime = Field(..., alias="lastClassBookedDate")
74
- last_class_studio_visited: int = Field(..., alias="lastClassStudioVisited")
75
25
 
26
+ class MemberClassSummary(OtfItemBase):
27
+ total_classes_booked: int | None = Field(None, alias="totalClassesBooked")
28
+ total_classes_attended: int | None = Field(None, alias="totalClassesAttended")
29
+ total_intro_classes: int | None = Field(None, alias="totalIntro")
30
+ total_ot_live_classes_booked: int | None = Field(None, alias="totalOTLiveClassesBooked")
31
+ total_ot_live_classes_attended: int | None = Field(None, alias="totalOTLiveClassesAttended")
32
+ total_classes_used_hrm: int | None = Field(None, alias="totalClassesUsedHRM")
33
+ total_studios_visited: int | None = Field(None, alias="totalStudiosVisited")
34
+ first_visit_date: date | None = Field(None, alias="firstVisitDate")
35
+ last_class_visited_date: date | None = Field(None, alias="lastClassVisitedDate")
36
+ last_class_booked_date: date | None = Field(None, alias="lastClassBookedDate")
76
37
 
77
- class MemberReferrer(OtfItemBase):
78
- member_referrer_uuid: str = Field(..., alias="memberReferrerUUId")
38
+ last_class_studio_visited: int | None = Field(None, alias="lastClassStudioVisited", exclude=True, repr=False)
79
39
 
80
40
 
81
41
  class MemberDetail(OtfItemBase):
82
- member_id: int = Field(..., alias="memberId")
83
42
  member_uuid: str = Field(..., alias="memberUUId")
84
- cognito_id: str = Field(..., alias="cognitoId")
85
- home_studio_id: int = Field(..., alias="homeStudioId")
86
- mbo_studio_id: int = Field(..., alias="mboStudioId")
87
- mbo_id: str = Field(..., alias="mboId")
88
- mbo_unique_id: int = Field(..., alias="mboUniqueId")
89
- mbo_status: str = Field(..., alias="mboStatus")
90
- user_name: str = Field(..., alias="userName")
91
- first_name: str = Field(..., alias="firstName")
92
- last_name: str = Field(..., alias="lastName")
93
- email: str
94
- profile_picture_url: str | None = Field(None, alias="profilePictureUrl")
95
- alternate_emails: None = Field(..., alias="alternateEmails")
96
- address_line1: str | None = Field(None, alias="addressLine1")
97
- address_line2: str | None = Field(None, alias="addressLine2")
98
- city: str | None
99
- state: str | None
100
- postal_code: str | None = Field(None, alias="postalCode")
101
- phone_number: str = Field(..., alias="phoneNumber")
102
- home_phone: str | None = Field(None, alias="homePhone")
103
- work_phone: str | None = Field(None, alias="workPhone")
104
- phone_type: None = Field(..., alias="phoneType")
105
- birth_day: date = Field(..., alias="birthDay")
106
- cc_last4: str = Field(..., alias="ccLast4")
107
- cc_type: str = Field(..., alias="ccType")
108
- gender: str
109
- liability: Any
110
- locale: str
111
- weight: int
112
- weight_measure: str = Field(..., alias="weightMeasure")
113
- height: int
114
- height_measure: str = Field(..., alias="heightMeasure")
115
- max_hr: int = Field(..., alias="maxHr")
116
- intro_neccessary: bool = Field(..., alias="introNeccessary")
117
- online_signup: None = Field(..., alias="onlineSignup")
118
- year_imported: int = Field(..., alias="yearImported")
119
- is_member_verified: bool = Field(..., alias="isMemberVerified")
120
- lead_prospect: bool = Field(..., alias="leadProspect")
121
- created_by: str | None = Field(None, alias="createdBy")
122
- created_date: datetime = Field(..., alias="createdDate")
123
- updated_by: str = Field(..., alias="updatedBy")
124
- updated_date: datetime = Field(..., alias="updatedDate")
125
- is_deleted: bool = Field(..., alias="isDeleted")
126
- addresses: list[Address] | None = None
127
- member_credit_card: MemberCreditCard | None = Field(None, alias="memberCreditCard")
128
- home_studio: HomeStudio = Field(..., alias="homeStudio")
129
- member_profile: MemberProfile = Field(..., alias="memberProfile")
130
- member_referrer: None | MemberReferrer = Field(None, alias="memberReferrer")
131
- otf_acs_id: str = Field(..., alias="otfAcsId")
132
- member_class_summary: MemberClassSummary | None = Field(None, alias="memberClassSummary")
43
+ cognito_id: str = Field(
44
+ ...,
45
+ alias="cognitoId",
46
+ exclude=True,
47
+ repr=False,
48
+ description="Cognito user ID, not necessary for end users. Also on OtfUser object.",
49
+ )
50
+
51
+ home_studio: StudioDetail
52
+ profile: MemberProfile = Field(..., alias="memberProfile")
53
+ class_summary: MemberClassSummary | None = Field(None, alias="memberClassSummary")
54
+ addresses: list[Address] | None = Field(default_factory=list)
55
+
56
+ studio_display_name: str | None = Field(
57
+ None, alias="userName", description="The value that is displayed on tread/rower tablets and OTBeat screens"
58
+ )
59
+ first_name: str | None = Field(None, alias="firstName")
60
+ last_name: str | None = Field(None, alias="lastName")
61
+ email: str | None = Field(None, alias="email")
62
+ phone_number: str | None = Field(None, alias="phoneNumber")
63
+ birth_day: date | None = Field(None, alias="birthDay")
64
+ gender: str | None = Field(None, alias="gender")
65
+ locale: str | None = Field(None, alias="locale")
66
+ weight: int | None = Field(None, alias="weight")
67
+ weight_units: str | None = Field(None, alias="weightMeasure")
68
+ height: int | None = Field(None, alias="height")
69
+ height_units: str | None = Field(None, alias="heightMeasure")
70
+
71
+ # unused fields - leaving these in for now in case someone finds a purpose for them
72
+ # but they will potentially (likely?) be removed in the future
73
+
74
+ # mbo fields
75
+ mbo_id: str | None = Field(None, alias="mboId", exclude=True, repr=False, description="MindBody attr")
76
+ mbo_status: str | None = Field(None, alias="mboStatus", exclude=True, repr=False, description="MindBody attr")
77
+ mbo_studio_id: int | None = Field(None, alias="mboStudioId", exclude=True, repr=False, description="MindBody attr")
78
+ mbo_unique_id: int | None = Field(None, alias="mboUniqueId", exclude=True, repr=False, description="MindBody attr")
79
+
80
+ # ids
81
+ created_by: str | None = Field(None, alias="createdBy", exclude=True, repr=False)
82
+ home_studio_id: int | None = Field(
83
+ None, alias="homeStudioId", exclude=True, repr=False, description="Not used by API"
84
+ )
85
+ member_id: int | None = Field(None, alias="memberId", exclude=True, repr=False, description="Not used by API")
86
+ otf_acs_id: str | None = Field(None, alias="otfAcsId", exclude=True, repr=False)
87
+ updated_by: str | None = Field(None, alias="updatedBy", exclude=True, repr=False)
88
+
89
+ # unused address/member detail fields
90
+ created_date: datetime | None = Field(None, alias="createdDate", exclude=True, repr=False)
91
+ updated_date: datetime | None = Field(None, alias="updatedDate", exclude=True, repr=False)
92
+
93
+ address_line1: str | None = Field(None, alias="addressLine1", exclude=True, repr=False)
94
+ address_line2: str | None = Field(None, alias="addressLine2", exclude=True, repr=False)
95
+ alternate_emails: None = Field(None, alias="alternateEmails", exclude=True, repr=False)
96
+ cc_last4: str | None = Field(None, alias="ccLast4", exclude=True, repr=False)
97
+ cc_type: str | None = Field(None, alias="ccType", exclude=True, repr=False)
98
+ city: str | None = Field(None, exclude=True, repr=False)
99
+ home_phone: str | None = Field(None, alias="homePhone", exclude=True, repr=False)
100
+ intro_neccessary: bool | None = Field(None, alias="introNeccessary", exclude=True, repr=False)
101
+ is_deleted: bool | None = Field(None, alias="isDeleted", exclude=True, repr=False)
102
+ is_member_verified: bool | None = Field(None, alias="isMemberVerified", exclude=True, repr=False)
103
+ lead_prospect: bool | None = Field(None, alias="leadProspect", exclude=True, repr=False)
104
+ max_hr: int | None = Field(
105
+ None, alias="maxHr", exclude=True, repr=False, description="Also found in member_profile"
106
+ )
107
+ online_signup: None = Field(None, alias="onlineSignup", exclude=True, repr=False)
108
+ phone_type: None = Field(None, alias="phoneType", exclude=True, repr=False)
109
+ postal_code: str | None = Field(None, alias="postalCode", exclude=True, repr=False)
110
+ state: str | None = Field(None, exclude=True, repr=False)
111
+ work_phone: str | None = Field(None, alias="workPhone", exclude=True, repr=False)
112
+ year_imported: int | None = Field(None, alias="yearImported", exclude=True, repr=False)
133
113
 
134
114
  @field_validator("birth_day")
135
115
  @classmethod
@@ -137,5 +117,5 @@ class MemberDetail(OtfItemBase):
137
117
  if value is None:
138
118
  return value
139
119
  if not isinstance(value, date):
140
- return datetime.strptime(value, "%Y-%m-%d").date() # noqa
120
+ return datetime.strptime(value, "%Y-%m-%d").date()
141
121
  return value
@@ -6,20 +6,21 @@ from otf_api.models.base import OtfItemBase
6
6
 
7
7
 
8
8
  class MemberMembership(OtfItemBase):
9
- member_membership_id: int = Field(..., alias="memberMembershipId")
10
- member_membership_uuid: str = Field(..., alias="memberMembershipUUId")
11
- membership_id: int = Field(..., alias="membershipId")
12
- member_id: int = Field(..., alias="memberId")
13
- payment_date: datetime = Field(..., alias="paymentDate")
14
- active_date: datetime = Field(..., alias="activeDate")
15
- expiration_date: datetime = Field(..., alias="expirationDate")
16
- mbo_description_id: str = Field(..., alias="mboDescriptionId")
17
- current: bool
18
- count: int
19
- remaining: int
20
- name: str
21
- created_by: str = Field(..., alias="createdBy")
22
- created_date: datetime = Field(..., alias="createdDate")
23
- updated_by: str = Field(..., alias="updatedBy")
24
- updated_date: datetime = Field(..., alias="updatedDate")
25
- is_deleted: bool = Field(..., alias="isDeleted")
9
+ payment_date: datetime | None = Field(None, alias="paymentDate")
10
+ active_date: datetime | None = Field(None, alias="activeDate")
11
+ expiration_date: datetime | None = Field(None, alias="expirationDate")
12
+ current: bool | None = None
13
+ count: int | None = None
14
+ remaining: int | None = None
15
+ name: str | None = None
16
+ updated_date: datetime | None = Field(None, alias="updatedDate")
17
+ created_date: datetime | None = Field(None, alias="createdDate")
18
+ is_deleted: bool | None = Field(None, alias="isDeleted")
19
+
20
+ member_membership_id: int | None = Field(None, alias="memberMembershipId", exclude=True, repr=False)
21
+ member_membership_uuid: str | None = Field(None, alias="memberMembershipUUId", exclude=True, repr=False)
22
+ membership_id: int | None = Field(None, alias="membershipId", exclude=True, repr=False)
23
+ member_id: int | None = Field(None, alias="memberId", exclude=True, repr=False)
24
+ mbo_description_id: str | None = Field(None, alias="mboDescriptionId", exclude=True, repr=False)
25
+ created_by: str | None = Field(None, alias="createdBy", exclude=True, repr=False)
26
+ updated_by: str | None = Field(None, alias="updatedBy", exclude=True, repr=False)
@@ -3,133 +3,27 @@ from datetime import datetime
3
3
  from pydantic import Field
4
4
 
5
5
  from otf_api.models.base import OtfItemBase
6
-
7
-
8
- class Location(OtfItemBase):
9
- phone: str
10
- latitude: str
11
- longitude: str
12
- address1: str
13
- address2: str | None = None
14
- city: str
15
- state: str
16
- postal_code: str = Field(..., alias="postalCode")
17
-
18
-
19
- class Currency(OtfItemBase):
20
- currency_alphabetic_code: str = Field(..., alias="currencyAlphabeticCode")
21
-
22
-
23
- class DefaultCurrency(OtfItemBase):
24
- currency_id: int = Field(..., alias="currencyId")
25
- currency: Currency
26
-
27
-
28
- class Country(OtfItemBase):
29
- country_id: int = Field(..., alias="countryId")
30
- country_code: str = Field(..., alias="countryCode")
31
- description: str
32
- country_currency_code: str = Field(..., alias="countryCurrencyCode")
33
- default_currency: DefaultCurrency = Field(..., alias="defaultCurrency")
34
-
35
-
36
- class StudioLocation(OtfItemBase):
37
- studio_location_id: int = Field(..., alias="studioLocationId")
38
- bill_to_address: str = Field(..., alias="billToAddress")
39
- bill_to_address2: str = Field(..., alias="billToAddress2")
40
- bill_to_city: str = Field(..., alias="billToCity")
41
- bill_to_state: str = Field(..., alias="billToState")
42
- bill_to_postal_code: str = Field(..., alias="billToPostalCode")
43
- bill_to_region: str = Field(..., alias="billToRegion")
44
- bill_to_country_id: int = Field(..., alias="billToCountryId")
45
- bill_to_country: str = Field(..., alias="billToCountry")
46
- ship_to_address: str = Field(..., alias="shipToAddress")
47
- ship_to_address2: str | None = Field(None, alias="shipToAddress2")
48
- ship_to_city: str = Field(..., alias="shipToCity")
49
- ship_to_state: str = Field(..., alias="shipToState")
50
- ship_to_postal_code: str = Field(..., alias="shipToPostalCode")
51
- ship_to_region: str = Field(..., alias="shipToRegion")
52
- ship_to_country_id: int = Field(..., alias="shipToCountryId")
53
- ship_to_country: str = Field(..., alias="shipToCountry")
54
- physical_address: str = Field(..., alias="physicalAddress")
55
- physical_address2: str | None = Field(None, alias="physicalAddress2")
56
- physical_city: str = Field(..., alias="physicalCity")
57
- physical_state: str = Field(..., alias="physicalState")
58
- physical_postal_code: str = Field(..., alias="physicalPostalCode")
59
- physical_region: str = Field(..., alias="physicalRegion")
60
- physical_country_id: int = Field(..., alias="physicalCountryId")
61
- physical_country: str = Field(..., alias="physicalCountry")
62
- phone_number: str = Field(..., alias="phoneNumber")
63
- latitude: str
64
- longitude: str
65
- country: Country
66
-
67
-
68
- class Studio(OtfItemBase):
69
- studio_id: int = Field(..., alias="studioId")
70
- studio_uuid: str = Field(..., alias="studioUUId")
71
- mbo_studio_id: int = Field(..., alias="mboStudioId")
72
- studio_name: str = Field(..., alias="studioName")
73
- area_id: int = Field(..., alias="areaId")
74
- market_id: int = Field(..., alias="marketId")
75
- state_id: int = Field(..., alias="stateId")
76
- studio_physical_location_id: int = Field(..., alias="studioPhysicalLocationId")
77
- studio_number: str = Field(..., alias="studioNumber")
78
- description: str
79
- studio_version: str = Field(..., alias="studioVersion")
80
- studio_token: str = Field(..., alias="studioToken")
81
- studio_status: str = Field(..., alias="studioStatus")
82
- open_date: datetime = Field(..., alias="openDate")
83
- studio_type_id: int = Field(..., alias="studioTypeId")
84
- pos_type_id: int = Field(..., alias="posTypeId")
85
- tax_inclusive_pricing: bool = Field(..., alias="taxInclusivePricing")
86
- tax_rate: str = Field(..., alias="taxRate")
87
- logo_url: str = Field(..., alias="logoUrl")
88
- page_color1: str = Field(..., alias="pageColor1")
89
- page_color2: str = Field(..., alias="pageColor2")
90
- page_color3: str = Field(..., alias="pageColor3")
91
- page_color4: str = Field(..., alias="pageColor4")
92
- accepts_visa_master_card: bool = Field(..., alias="acceptsVisaMasterCard")
93
- accepts_american_express: bool = Field(..., alias="acceptsAmericanExpress")
94
- accepts_discover: bool = Field(..., alias="acceptsDiscover")
95
- accepts_ach: bool = Field(..., alias="acceptsACH")
96
- sms_package_enabled: bool = Field(..., alias="smsPackageEnabled")
97
- allows_dashboard_access: bool = Field(..., alias="allowsDashboardAccess")
98
- pricing_level: str = Field(..., alias="pricingLevel")
99
- contact_email: str = Field(..., alias="contactEmail")
100
- royalty_rate: str = Field(..., alias="royaltyRate")
101
- commission_percent: str = Field(..., alias="commissionPercent")
102
- marketing_fund_rate: str = Field(..., alias="marketingFundRate")
103
- time_zone: str = Field(..., alias="timeZone")
104
- environment: str
105
- allows_cr_waitlist: bool = Field(..., alias="allowsCRWaitlist")
106
- cr_waitlist_flag_last_updated: datetime = Field(..., alias="crWaitlistFlagLastUpdated")
107
- is_integrated: bool = Field(..., alias="isIntegrated")
108
- locations: list[Location]
109
- studio_location: StudioLocation = Field(..., alias="studioLocation")
6
+ from otf_api.models.studio_detail import StudioDetail
110
7
 
111
8
 
112
9
  class MemberPurchase(OtfItemBase):
113
- member_purchase_id: int = Field(..., alias="memberPurchaseId")
114
- member_purchase_uuid: str = Field(..., alias="memberPurchaseUUId")
115
- studio_id: int = Field(..., alias="studioId")
116
- name: str
117
- price: str
118
- member_purchase_date_time: datetime = Field(..., alias="memberPurchaseDateTime")
119
- member_purchase_type: str = Field(..., alias="memberPurchaseType")
120
- status: str
121
- member_service_id: int | None = Field(None, alias="memberServiceId")
122
- member_membership_id: int | None = Field(None, alias="memberMembershipId")
123
- member_fee_id: int | None = Field(None, alias="memberFeeId")
124
- pos_contract_id: int | None = Field(None, alias="posContractId")
125
- pos_product_id: int = Field(..., alias="posProductId")
126
- pos_description_id: int | None = Field(None, alias="posDescriptionId")
127
- pos_pmt_ref_no: int | None = Field(None, alias="posPmtRefNo")
128
- pos_sale_id: int = Field(..., alias="posSaleId")
129
- quantity: int
130
- member_id: int = Field(..., alias="memberId")
131
- studio: Studio
132
-
133
-
134
- class MemberPurchaseList(OtfItemBase):
135
- data: list[MemberPurchase]
10
+ purchase_uuid: str = Field(..., alias="memberPurchaseUUId")
11
+ name: str | None = None
12
+ price: str | None = None
13
+ purchase_date_time: datetime | None = Field(None, alias="memberPurchaseDateTime")
14
+ purchase_type: str | None = Field(None, alias="memberPurchaseType")
15
+ status: str | None = None
16
+ quantity: int | None = None
17
+ studio: StudioDetail = Field(..., exclude=True, repr=False)
18
+
19
+ member_fee_id: int | None = Field(None, alias="memberFeeId", exclude=True, repr=False)
20
+ member_id: int | None = Field(..., alias="memberId", exclude=True, repr=False)
21
+ member_membership_id: int | None = Field(None, alias="memberMembershipId", exclude=True, repr=False)
22
+ member_purchase_id: int | None = Field(..., alias="memberPurchaseId", exclude=True, repr=False)
23
+ member_service_id: int | None = Field(None, alias="memberServiceId", exclude=True, repr=False)
24
+ pos_contract_id: int | None = Field(None, alias="posContractId", exclude=True, repr=False)
25
+ pos_description_id: int | None = Field(None, alias="posDescriptionId", exclude=True, repr=False)
26
+ pos_pmt_ref_no: int | None = Field(None, alias="posPmtRefNo", exclude=True, repr=False)
27
+ pos_product_id: int | None = Field(..., alias="posProductId", exclude=True, repr=False)
28
+ pos_sale_id: int | None = Field(..., alias="posSaleId", exclude=True, repr=False)
29
+ studio_id: int | None = Field(..., alias="studioId", exclude=True, repr=False)
otf_api/models/mixins.py CHANGED
@@ -1,44 +1,48 @@
1
- from datetime import datetime
1
+ from pydantic import AliasChoices, Field, field_validator, model_validator
2
2
 
3
- from humanize import precisedelta
3
+ from otf_api.models.base import OtfItemBase
4
4
 
5
- from otf_api.models.enums import ClassType
6
5
 
6
+ class PhoneLongitudeLatitudeMixin(OtfItemBase):
7
+ phone_number: str | None = Field(None, alias=AliasChoices("phone", "phoneNumber"))
8
+ latitude: float | None = Field(None, alias=AliasChoices("latitude"))
9
+ longitude: float | None = Field(None, alias=AliasChoices("longitude"))
7
10
 
8
- class OtfClassTimeMixin:
9
- starts_at_local: datetime
10
- ends_at_local: datetime
11
- name: str
12
11
 
13
- @property
14
- def day_of_week(self) -> str:
15
- return self.starts_at_local.strftime("%A")
12
+ class AddressMixin(OtfItemBase):
13
+ address_line1: str | None = Field(None, alias=AliasChoices("line1", "address1", "address", "physicalAddress"))
14
+ address_line2: str | None = Field(None, alias=AliasChoices("line2", "address2", "physicalAddress2"))
15
+ city: str | None = Field(None, alias=AliasChoices("city", "physicalCity", "suburb"))
16
+ postal_code: str | None = Field(None, alias=AliasChoices("postal_code", "postalCode", "physicalPostalCode"))
17
+ state: str | None = Field(None, alias=AliasChoices("state", "physicalState", "territory"))
18
+ country: str | None = Field(None, alias=AliasChoices("country", "physicalCountry"))
19
+ region: str | None = Field(None, exclude=True, repr=False, alias=AliasChoices("physicalRegion", "region"))
20
+ country_id: int | None = Field(None, exclude=True, repr=False, alias=AliasChoices("physicalCountryId", "countryId"))
16
21
 
17
- @property
18
- def date(self) -> str:
19
- return self.starts_at_local.strftime("%Y-%m-%d")
22
+ @model_validator(mode="before")
23
+ @classmethod
24
+ def check_country(cls, values):
25
+ if set(values.keys()) == set(
26
+ ["phone", "latitude", "longitude", "address1", "address2", "city", "state", "postalCode"]
27
+ ):
28
+ values = {k: v for k, v in values.items() if v and str(v) != "0.00000000"}
20
29
 
21
- @property
22
- def time(self) -> str:
23
- """Returns time in 12 hour clock format, with no leading 0"""
24
- val = self.starts_at_local.strftime("%I:%M %p")
25
- if val[0] == "0":
26
- val = " " + val[1:]
30
+ if "country" in values and isinstance(values["country"], dict):
31
+ values["country_currency"] = values.pop("country")
27
32
 
28
- return val
33
+ if "physicalCountry" in values and isinstance(values["physicalCountry"], dict):
34
+ values["country_currency"] = values.pop("physicalCountry")
29
35
 
30
- @property
31
- def duration(self) -> str:
32
- duration = self.ends_at_local - self.starts_at_local
33
- human_val: str = precisedelta(duration, minimum_unit="minutes")
34
- if human_val == "1 hour and 30 minutes":
35
- return "90 minutes"
36
- return human_val
36
+ return values
37
37
 
38
- @property
39
- def class_type(self) -> ClassType:
40
- for class_type in ClassType:
41
- if class_type.value in self.name:
42
- return class_type
38
+ @field_validator("address_line1", "address_line2", "city", "postal_code", "state", "country")
39
+ @classmethod
40
+ def clean_strings(cls, value: str | None, **_kwargs) -> str | None:
41
+ if value is None:
42
+ return value
43
+ value = value.strip()
43
44
 
44
- return ClassType.OTHER
45
+ if not value:
46
+ return None
47
+
48
+ return value
@@ -0,0 +1,17 @@
1
+ from pydantic import Field
2
+
3
+ from otf_api.models.base import OtfItemBase
4
+
5
+
6
+ class SmsNotificationSettings(OtfItemBase):
7
+ is_promotional_sms_opt_in: bool | None = Field(None, alias="isPromotionalSmsOptIn")
8
+ is_transactional_sms_opt_in: bool | None = Field(None, alias="isTransactionalSmsOptIn")
9
+ is_promotional_phone_opt_in: bool | None = Field(None, alias="isPromotionalPhoneOptIn")
10
+ is_transactional_phone_opt_in: bool | None = Field(None, alias="isTransactionalPhoneOptIn")
11
+
12
+
13
+ class EmailNotificationSettings(OtfItemBase):
14
+ is_system_email_opt_in: bool | None = Field(None, alias="isSystemEmailOptIn")
15
+ is_promotional_email_opt_in: bool | None = Field(None, alias="isPromotionalEmailOptIn")
16
+ is_transactional_email_opt_in: bool | None = Field(None, alias="isTransactionalEmailOptIn")
17
+ email: str | None = None
@@ -1,41 +1,32 @@
1
1
  from datetime import datetime
2
2
 
3
- from pydantic import Field
3
+ from pydantic import AliasPath, Field
4
4
 
5
5
  from otf_api.models.base import OtfItemBase
6
6
 
7
7
 
8
- class WorkoutType(OtfItemBase):
9
- id: int
10
- display_name: str = Field(..., alias="displayName")
11
- icon: str
12
-
13
-
14
8
  class OutOfStudioWorkoutHistory(OtfItemBase):
15
- workout_date: datetime = Field(..., alias="workoutDate")
16
- start_time: datetime = Field(..., alias="startTime")
17
- end_time: datetime = Field(..., alias="endTime")
18
- duration_unit: str = Field(..., alias="durationUnit")
19
- duration: float
20
- total_calories: int = Field(..., alias="totalCalories")
21
- hr_percent_max: int = Field(..., alias="hrPercentMax")
22
- distance_unit: str = Field(..., alias="distanceUnit")
23
- total_distance: float = Field(..., alias="totalDistance")
24
- splat_points: int = Field(..., alias="splatPoints")
25
- target_heart_rate: int = Field(..., alias="targetHeartRate")
26
- red_zone_seconds: int = Field(..., alias="redZoneSeconds")
27
- orange_zone_seconds: int = Field(..., alias="orangeZoneSeconds")
28
- green_zone_seconds: int = Field(..., alias="greenZoneSeconds")
29
- blue_zone_seconds: int = Field(..., alias="blueZoneSeconds")
30
- grey_zone_seconds: int = Field(..., alias="greyZoneSeconds")
31
- total_steps: int = Field(..., alias="totalSteps")
32
- has_detailed_data: bool = Field(..., alias="hasDetailedData")
33
- workout_type: WorkoutType = Field(..., alias="workoutType")
34
9
  member_uuid: str = Field(..., alias="memberUUId")
35
10
  workout_uuid: str = Field(..., alias="workoutUUId")
36
- avg_heartrate: int = Field(..., alias="avgHeartrate")
37
- max_heartrate: int = Field(..., alias="maxHeartrate")
38
-
39
11
 
40
- class OutOfStudioWorkoutHistoryList(OtfItemBase):
41
- workouts: list[OutOfStudioWorkoutHistory]
12
+ workout_date: datetime | None = Field(None, alias="workoutDate")
13
+ start_time: datetime | None = Field(None, alias="startTime")
14
+ end_time: datetime | None = Field(None, alias="endTime")
15
+ duration: float | None = None
16
+ duration_unit: str | None = Field(None, alias="durationUnit")
17
+ total_calories: int | None = Field(None, alias="totalCalories")
18
+ hr_percent_max: int | None = Field(None, alias="hrPercentMax")
19
+ distance_unit: str | None = Field(None, alias="distanceUnit")
20
+ total_distance: float | None = Field(None, alias="totalDistance")
21
+ splat_points: int | None = Field(None, alias="splatPoints")
22
+ target_heart_rate: int | None = Field(None, alias="targetHeartRate")
23
+ total_steps: int | None = Field(None, alias="totalSteps")
24
+ has_detailed_data: bool | None = Field(None, alias="hasDetailedData")
25
+ avg_heartrate: int | None = Field(None, alias="avgHeartrate")
26
+ max_heartrate: int | None = Field(None, alias="maxHeartrate")
27
+ workout_type: str | None = Field(None, alias=AliasPath("workoutType", "displayName"))
28
+ red_zone_seconds: int | None = Field(None, alias="redZoneSeconds")
29
+ orange_zone_seconds: int | None = Field(None, alias="orangeZoneSeconds")
30
+ green_zone_seconds: int | None = Field(None, alias="greenZoneSeconds")
31
+ blue_zone_seconds: int | None = Field(None, alias="blueZoneSeconds")
32
+ grey_zone_seconds: int | None = Field(None, alias="greyZoneSeconds")