supersaas-api-client 2.1.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.
- SuperSaaS/API/Appointments.py +221 -0
- SuperSaaS/API/BaseApi.py +69 -0
- SuperSaaS/API/Forms.py +31 -0
- SuperSaaS/API/Groups.py +10 -0
- SuperSaaS/API/Hooks.py +23 -0
- SuperSaaS/API/Promotions.py +32 -0
- SuperSaaS/API/Schedules.py +29 -0
- SuperSaaS/API/Slots.py +63 -0
- SuperSaaS/API/Users.py +98 -0
- SuperSaaS/API/__init__.py +14 -0
- SuperSaaS/Client.py +229 -0
- SuperSaaS/Error.py +6 -0
- SuperSaaS/Models/Appointment.py +4 -0
- SuperSaaS/Models/BaseModel.py +5 -0
- SuperSaaS/Models/FieldList.py +5 -0
- SuperSaaS/Models/Form.py +5 -0
- SuperSaaS/Models/Group.py +5 -0
- SuperSaaS/Models/Promotion.py +5 -0
- SuperSaaS/Models/Resource.py +5 -0
- SuperSaaS/Models/Schedule.py +5 -0
- SuperSaaS/Models/Slot.py +5 -0
- SuperSaaS/Models/SuperForm.py +5 -0
- SuperSaaS/Models/User.py +5 -0
- SuperSaaS/Models/__init__.py +16 -0
- SuperSaaS/__init__.py +5 -0
- supersaas_api_client-2.1.0.dist-info/METADATA +477 -0
- supersaas_api_client-2.1.0.dist-info/RECORD +30 -0
- supersaas_api_client-2.1.0.dist-info/WHEEL +5 -0
- supersaas_api_client-2.1.0.dist-info/licenses/LICENSE +21 -0
- supersaas_api_client-2.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
from .BaseApi import BaseApi
|
|
2
|
+
from ..Models.Appointment import Appointment
|
|
3
|
+
from ..Models.Slot import Slot
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Appointments(BaseApi):
|
|
7
|
+
def agenda(self, schedule_id, user, from_time=None, slot=False):
|
|
8
|
+
path = f"/agenda/{self._validate_id(schedule_id)}"
|
|
9
|
+
query = {
|
|
10
|
+
'user': self._validate_present(user),
|
|
11
|
+
'from': self._validate_datetime(from_time) if from_time else None
|
|
12
|
+
}
|
|
13
|
+
if slot:
|
|
14
|
+
query['slot'] = True
|
|
15
|
+
res = self.client.get(path, query)
|
|
16
|
+
return self.__map_slots_or_bookings(res)
|
|
17
|
+
|
|
18
|
+
def agenda_slots(self, schedule_id, user_id, from_time=None):
|
|
19
|
+
"""Deprecated, will be removed in a future version. Use `agenda(..., slot=True)` instead."""
|
|
20
|
+
path = f"/agenda/{self._validate_id(schedule_id)}"
|
|
21
|
+
query = {
|
|
22
|
+
'user': self._validate_present(user_id),
|
|
23
|
+
'from': self._validate_datetime(from_time) if from_time else None,
|
|
24
|
+
'slot': 'true'
|
|
25
|
+
}
|
|
26
|
+
res = self.client.get(path, query)
|
|
27
|
+
return self.__map_slots_or_bookings(res)
|
|
28
|
+
|
|
29
|
+
def available(self,
|
|
30
|
+
schedule_id,
|
|
31
|
+
from_time=None,
|
|
32
|
+
length_minutes=None,
|
|
33
|
+
resource=None,
|
|
34
|
+
full=None,
|
|
35
|
+
limit=None):
|
|
36
|
+
path = f"/free/{self._validate_id(schedule_id)}"
|
|
37
|
+
query = {
|
|
38
|
+
'length':
|
|
39
|
+
self._validate_number(length_minutes) if length_minutes else None,
|
|
40
|
+
'from': self._validate_datetime(from_time) if from_time else None,
|
|
41
|
+
'resource': resource,
|
|
42
|
+
'full': 'true' if full else None,
|
|
43
|
+
'maxresults': self._validate_number(limit) if limit else None
|
|
44
|
+
}
|
|
45
|
+
res = self.client.get(path, query)
|
|
46
|
+
return self.__map_slots_or_bookings(res)
|
|
47
|
+
|
|
48
|
+
def list(self, schedule_id, form=None, start_time=None, limit=None, finish=None):
|
|
49
|
+
path = "/bookings"
|
|
50
|
+
query = {
|
|
51
|
+
'schedule_id': self._validate_id(schedule_id),
|
|
52
|
+
'form': 'true' if form else None,
|
|
53
|
+
'start':
|
|
54
|
+
self._validate_datetime(start_time) if start_time else None,
|
|
55
|
+
'limit': self._validate_number(limit) if limit else None,
|
|
56
|
+
'finish':
|
|
57
|
+
self._validate_datetime(finish) if finish else None
|
|
58
|
+
}
|
|
59
|
+
res = self.client.get(path, query)
|
|
60
|
+
return self.__map_slots_or_bookings(res)
|
|
61
|
+
|
|
62
|
+
def get(self, schedule_id, appointment_id=None):
|
|
63
|
+
query = {'schedule_id': self._validate_id(schedule_id)}
|
|
64
|
+
path = f"/bookings/{self._validate_id(appointment_id)}"
|
|
65
|
+
res = self.client.get(path, query)
|
|
66
|
+
return Appointment(res)
|
|
67
|
+
|
|
68
|
+
def create(self, schedule_id, user_id, attributes,
|
|
69
|
+
form=None,
|
|
70
|
+
webhook=None):
|
|
71
|
+
path = "/bookings"
|
|
72
|
+
params = self.__create_update_params(schedule_id, attributes, form, webhook)
|
|
73
|
+
if user_id:
|
|
74
|
+
params['user_id'] = self._validate_id(user_id)
|
|
75
|
+
params['booking'] = dict(
|
|
76
|
+
filter(lambda item: item[1] is not None,
|
|
77
|
+
params['booking'].items()))
|
|
78
|
+
res = self.client.post(path, params)
|
|
79
|
+
return {'location': res}
|
|
80
|
+
|
|
81
|
+
def update(self, schedule_id, appointment_id, attributes, form=None, webhook=None):
|
|
82
|
+
"""
|
|
83
|
+
Update an existing appointment/booking
|
|
84
|
+
"""
|
|
85
|
+
path = f"/bookings/{self._validate_id(appointment_id)}"
|
|
86
|
+
params = self.__create_update_params(schedule_id, attributes, form, webhook)
|
|
87
|
+
|
|
88
|
+
# Attributes passed as {'booking': None} are sent as an empty booking
|
|
89
|
+
if params.get('booking') is None:
|
|
90
|
+
params['booking'] = {}
|
|
91
|
+
|
|
92
|
+
# Filter out None values from booking attributes
|
|
93
|
+
params['booking'] = {k: v for k, v in params['booking'].items() if v is not None}
|
|
94
|
+
|
|
95
|
+
res = self.client.put(path, params)
|
|
96
|
+
return Appointment(res)
|
|
97
|
+
|
|
98
|
+
def delete(self, schedule_id, appointment_id, webhook=None):
|
|
99
|
+
path = f'/bookings/{self._validate_id(appointment_id)}'
|
|
100
|
+
query = {'schedule_id': schedule_id, 'webhook': 'true' if webhook else None}
|
|
101
|
+
return self.client.delete(path, None, query)
|
|
102
|
+
|
|
103
|
+
def changes(self,
|
|
104
|
+
schedule_id,
|
|
105
|
+
from_time=None,
|
|
106
|
+
to=None,
|
|
107
|
+
slot=False,
|
|
108
|
+
user=None,
|
|
109
|
+
limit=None,
|
|
110
|
+
offset=None):
|
|
111
|
+
path = f"/changes/{self._validate_id(schedule_id)}"
|
|
112
|
+
params = self.__build_param({}, from_time, to, slot, user, limit,
|
|
113
|
+
offset)
|
|
114
|
+
res = self.client.get(path, params)
|
|
115
|
+
return self.__map_slots_or_bookings(res)
|
|
116
|
+
|
|
117
|
+
def changes_slots(self, schedule_id, from_time=None):
|
|
118
|
+
"""Deprecated, will be removed in a future version. Use `changes(..., slot=True)` instead."""
|
|
119
|
+
path = f"/changes/{self._validate_id(schedule_id)}"
|
|
120
|
+
query = {
|
|
121
|
+
'from': self._validate_datetime(from_time) if from_time else None,
|
|
122
|
+
'slot': 'true'
|
|
123
|
+
}
|
|
124
|
+
res = self.client.get(path, query)
|
|
125
|
+
return self.__map_slots_or_bookings(res)
|
|
126
|
+
|
|
127
|
+
def range(self,
|
|
128
|
+
schedule_id,
|
|
129
|
+
today=False,
|
|
130
|
+
from_time=None,
|
|
131
|
+
to=None,
|
|
132
|
+
slot=False,
|
|
133
|
+
user=None,
|
|
134
|
+
resource_id=None,
|
|
135
|
+
service_id=None,
|
|
136
|
+
limit=None,
|
|
137
|
+
offset=None):
|
|
138
|
+
path = f"/range/{self._validate_id(schedule_id)}"
|
|
139
|
+
params = {}
|
|
140
|
+
params = self.__build_param(params, from_time, to, slot, user, limit,
|
|
141
|
+
offset, resource_id, service_id)
|
|
142
|
+
if today:
|
|
143
|
+
params['today'] = True
|
|
144
|
+
res = self.client.get(path, params)
|
|
145
|
+
return self.__map_slots_or_bookings(res)
|
|
146
|
+
|
|
147
|
+
def __create_update_params(self, schedule_id, attributes,
|
|
148
|
+
form=None,
|
|
149
|
+
webhook=None):
|
|
150
|
+
# Attributes may be passed already wrapped as {'booking': {...}}
|
|
151
|
+
if isinstance(attributes, dict) and 'booking' in attributes:
|
|
152
|
+
attributes = attributes['booking'] or {}
|
|
153
|
+
params = {
|
|
154
|
+
'schedule_id': self._validate_id(schedule_id),
|
|
155
|
+
'booking': {
|
|
156
|
+
'start': attributes.get('start', None),
|
|
157
|
+
'finish': attributes.get('finish', None),
|
|
158
|
+
'email': attributes.get('email', None),
|
|
159
|
+
'full_name': attributes.get('full_name', None),
|
|
160
|
+
'address': attributes.get('address', None),
|
|
161
|
+
'mobile': attributes.get('mobile', None),
|
|
162
|
+
'phone': attributes.get('phone', None),
|
|
163
|
+
'country': attributes.get('country', None),
|
|
164
|
+
'field_1': attributes.get('field_1', None),
|
|
165
|
+
'field_2': attributes.get('field_2', None),
|
|
166
|
+
'field_1_r': attributes.get('field_1_r', None),
|
|
167
|
+
'field_2_r': attributes.get('field_2_r', None),
|
|
168
|
+
'super_field': attributes.get('super_field', None),
|
|
169
|
+
'resource_id': attributes.get('resource_id', None),
|
|
170
|
+
'slot_id': attributes.get('slot_id', None),
|
|
171
|
+
# description is for resource schedules, quantity (number of places) for capacity schedules,
|
|
172
|
+
# form_id attaches an existing form
|
|
173
|
+
'description': attributes.get('description', None),
|
|
174
|
+
'quantity': attributes.get('quantity', None),
|
|
175
|
+
'form_id': attributes.get('form_id', None),
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if form:
|
|
179
|
+
params['form'] = form
|
|
180
|
+
if webhook:
|
|
181
|
+
params['webhook'] = webhook
|
|
182
|
+
return params
|
|
183
|
+
|
|
184
|
+
def __map_slots_or_bookings(self, obj):
|
|
185
|
+
if isinstance(obj, list):
|
|
186
|
+
return [Appointment(attributes) for attributes in obj]
|
|
187
|
+
if 'slots' in obj:
|
|
188
|
+
return [Slot(attributes) for attributes in obj.get('slots', [])]
|
|
189
|
+
return [
|
|
190
|
+
Appointment(attributes)
|
|
191
|
+
for attributes in obj.get('bookings', [])
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
def __build_param(self,
|
|
195
|
+
params,
|
|
196
|
+
from_time,
|
|
197
|
+
to,
|
|
198
|
+
slot,
|
|
199
|
+
user,
|
|
200
|
+
limit,
|
|
201
|
+
offset,
|
|
202
|
+
resource_id=None,
|
|
203
|
+
service_id=None):
|
|
204
|
+
if from_time:
|
|
205
|
+
params['from'] = self._validate_datetime(from_time)
|
|
206
|
+
if to:
|
|
207
|
+
params['to'] = self._validate_datetime(to)
|
|
208
|
+
if slot:
|
|
209
|
+
params['slot'] = True
|
|
210
|
+
if user or user == 0:
|
|
211
|
+
params['user'] = self._validate_user(user)
|
|
212
|
+
if limit:
|
|
213
|
+
params['limit'] = self._validate_number(limit)
|
|
214
|
+
if offset:
|
|
215
|
+
params['offset'] = self._validate_number(offset)
|
|
216
|
+
if resource_id is not None:
|
|
217
|
+
params['resource_id'] = self._validate_id(resource_id)
|
|
218
|
+
if service_id is not None:
|
|
219
|
+
params['service_id'] = self._validate_id(service_id)
|
|
220
|
+
|
|
221
|
+
return params
|
SuperSaaS/API/BaseApi.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from SuperSaaS.Error import Error
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseApi:
|
|
7
|
+
INTEGER_REGEX = re.compile(r'\A[0-9]+\Z')
|
|
8
|
+
DATETIME_REGEX = re.compile(
|
|
9
|
+
r'\A\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}\Z')
|
|
10
|
+
PROMOTION_REGEX = re.compile(r'\A[a-zA-Z0-9]+\Z')
|
|
11
|
+
|
|
12
|
+
def __init__(self, client):
|
|
13
|
+
self.client = client
|
|
14
|
+
|
|
15
|
+
def _validate_id(self, value):
|
|
16
|
+
return value
|
|
17
|
+
|
|
18
|
+
def _validate_number(self, value):
|
|
19
|
+
return self._validate_id(value)
|
|
20
|
+
|
|
21
|
+
def _validate_present(self, value):
|
|
22
|
+
if not value:
|
|
23
|
+
raise Error("Required parameter is missing.")
|
|
24
|
+
return value
|
|
25
|
+
|
|
26
|
+
def _validate_user(self, value):
|
|
27
|
+
if value is None:
|
|
28
|
+
return None
|
|
29
|
+
|
|
30
|
+
if not isinstance(value, (int, str)):
|
|
31
|
+
raise Error(f"Invalid user id parameter: {value}")
|
|
32
|
+
return value
|
|
33
|
+
|
|
34
|
+
def _validate_datetime(self, value):
|
|
35
|
+
if isinstance(value, datetime):
|
|
36
|
+
return value.strftime("%Y-%m-%d %H:%M:%S")
|
|
37
|
+
if isinstance(value, str) and self.DATETIME_REGEX.match(value):
|
|
38
|
+
return value
|
|
39
|
+
raise Error(
|
|
40
|
+
f"Invalid datetime parameter: {value}. Provide a Time object or formatted 'YYYY-DD-MM%HH:MM:SS' string."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def _validate_options(self, value, options):
|
|
44
|
+
if value in options:
|
|
45
|
+
return value
|
|
46
|
+
raise Error(
|
|
47
|
+
f"Invalid option parameter: {value}. Must be one of {', '.join(options)}."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def _validate_promotion(self, value):
|
|
51
|
+
if not isinstance(value, str) or not value or not re.match(
|
|
52
|
+
self.PROMOTION_REGEX, value):
|
|
53
|
+
raise Error(
|
|
54
|
+
'Required parameter promotional code not found or contains other than alphanumeric characters.'
|
|
55
|
+
)
|
|
56
|
+
return value
|
|
57
|
+
|
|
58
|
+
def _validate_duplicate(self, value):
|
|
59
|
+
if not isinstance(value, str) or value not in ['ignore', 'raise']:
|
|
60
|
+
raise Error(
|
|
61
|
+
"Required parameter duplicate can only be 'ignore' or 'raise'."
|
|
62
|
+
)
|
|
63
|
+
return value
|
|
64
|
+
|
|
65
|
+
def _validate_notfound(self, value):
|
|
66
|
+
if not isinstance(value, str) or value not in ['error', 'ignore']:
|
|
67
|
+
raise Error(
|
|
68
|
+
"Required parameter notfound can only be 'error' or 'ignore'.")
|
|
69
|
+
return value
|
SuperSaaS/API/Forms.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from .BaseApi import BaseApi
|
|
2
|
+
from ..Models.Form import Form
|
|
3
|
+
from ..Models.SuperForm import SuperForm
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Forms(BaseApi):
|
|
7
|
+
|
|
8
|
+
def get(self, form_id):
|
|
9
|
+
path = "/forms"
|
|
10
|
+
query = {'id': self._validate_id(form_id)}
|
|
11
|
+
res = self.client.get(path, query)
|
|
12
|
+
return Form(res)
|
|
13
|
+
|
|
14
|
+
def list(self, superform_id, from_time=None, user=None, limit=None, offset=None):
|
|
15
|
+
path = "/forms"
|
|
16
|
+
params = {'form_id': self._validate_id(superform_id)}
|
|
17
|
+
if from_time:
|
|
18
|
+
params['from'] = self._validate_datetime(from_time)
|
|
19
|
+
if user or user == 0:
|
|
20
|
+
params['user'] = self._validate_user(user)
|
|
21
|
+
if limit:
|
|
22
|
+
params['limit'] = self._validate_number(limit)
|
|
23
|
+
if offset:
|
|
24
|
+
params['offset'] = self._validate_number(offset)
|
|
25
|
+
res = self.client.get(path, params)
|
|
26
|
+
return [Form(attributes) for attributes in res]
|
|
27
|
+
|
|
28
|
+
def forms(self):
|
|
29
|
+
path = "/super_forms"
|
|
30
|
+
res = self.client.get(path)
|
|
31
|
+
return [SuperForm(attributes) for attributes in res]
|
SuperSaaS/API/Groups.py
ADDED
SuperSaaS/API/Hooks.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from .BaseApi import BaseApi
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Hooks(BaseApi):
|
|
5
|
+
"""Manage webhooks (`/api/hooks`)."""
|
|
6
|
+
|
|
7
|
+
def list(self):
|
|
8
|
+
return self.client.get('/hooks')
|
|
9
|
+
|
|
10
|
+
def create(self, target_url, event, parent_id):
|
|
11
|
+
params = {
|
|
12
|
+
'target_url': self._validate_present(target_url),
|
|
13
|
+
'event': self._validate_present(event),
|
|
14
|
+
'parent_id': self._validate_present(self._validate_id(parent_id))
|
|
15
|
+
}
|
|
16
|
+
return self.client.post('/hooks', params)
|
|
17
|
+
|
|
18
|
+
def delete(self, hook_id, parent_id):
|
|
19
|
+
query = {
|
|
20
|
+
'id': self._validate_present(self._validate_id(hook_id)),
|
|
21
|
+
'parent_id': self._validate_present(self._validate_id(parent_id))
|
|
22
|
+
}
|
|
23
|
+
return self.client.delete('/hooks', None, query)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from .BaseApi import BaseApi
|
|
2
|
+
from ..Models.Promotion import Promotion
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Promotions(BaseApi):
|
|
6
|
+
|
|
7
|
+
def list(self, limit=None, offset=None):
|
|
8
|
+
path = '/promotions'
|
|
9
|
+
params = {
|
|
10
|
+
'limit':
|
|
11
|
+
self._validate_number(limit) if limit is not None else None,
|
|
12
|
+
'offset':
|
|
13
|
+
self._validate_number(offset) if offset is not None else None
|
|
14
|
+
}
|
|
15
|
+
# Filter out None values, so Client.request does not append an empty "?" to the URL
|
|
16
|
+
params = {k: v for k, v in params.items() if v is not None}
|
|
17
|
+
res = self.client.get(path, params)
|
|
18
|
+
return [Promotion(attributes) for attributes in res]
|
|
19
|
+
|
|
20
|
+
def promotion(self, promotion_code):
|
|
21
|
+
path = '/promotions'
|
|
22
|
+
query = {'promotion_code': self._validate_promotion(promotion_code)}
|
|
23
|
+
res = self.client.get(path, query)
|
|
24
|
+
return [Promotion(attributes) for attributes in res]
|
|
25
|
+
|
|
26
|
+
def duplicate_promotion_code(self, promotion_code, template_code):
|
|
27
|
+
path = '/promotions'
|
|
28
|
+
query = {
|
|
29
|
+
'id': self._validate_promotion(promotion_code),
|
|
30
|
+
'template_code': self._validate_promotion(template_code)
|
|
31
|
+
}
|
|
32
|
+
self.client.post(path, query)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from .BaseApi import BaseApi
|
|
2
|
+
from ..Models.Schedule import Schedule
|
|
3
|
+
from ..Models.Resource import Resource
|
|
4
|
+
from ..Models.FieldList import FieldList
|
|
5
|
+
|
|
6
|
+
class Schedules(BaseApi):
|
|
7
|
+
|
|
8
|
+
def list(self):
|
|
9
|
+
path = "/schedules"
|
|
10
|
+
res = self.client.get(path)
|
|
11
|
+
return [Schedule(attributes) for attributes in res]
|
|
12
|
+
|
|
13
|
+
def resources(self, schedule_id):
|
|
14
|
+
query = {'schedule_id': self._validate_id(schedule_id)}
|
|
15
|
+
path = "/resources"
|
|
16
|
+
res = self.client.get(path, query)
|
|
17
|
+
return [Resource(attributes) for attributes in res]
|
|
18
|
+
|
|
19
|
+
def field_list(self, schedule_id):
|
|
20
|
+
path = '/field_list'
|
|
21
|
+
query = {'schedule_id': self._validate_id(schedule_id)}
|
|
22
|
+
res = self.client.get(path, query)
|
|
23
|
+
return [FieldList(attributes) for attributes in res]
|
|
24
|
+
|
|
25
|
+
def input_field_list(self, schedule_id):
|
|
26
|
+
path = '/input_field_list'
|
|
27
|
+
query = {'schedule_id': self._validate_id(schedule_id)}
|
|
28
|
+
res = self.client.get(path, query)
|
|
29
|
+
return [FieldList(attributes) for attributes in res]
|
SuperSaaS/API/Slots.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from .BaseApi import BaseApi
|
|
2
|
+
from ..Models.Slot import Slot
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Slots(BaseApi):
|
|
6
|
+
"""Manage slots of capacity type schedules (`/api/slots`)."""
|
|
7
|
+
|
|
8
|
+
ATTRIBUTES = ('start', 'finish', 'title', 'description', 'location',
|
|
9
|
+
'capacity', 'price', 'color')
|
|
10
|
+
|
|
11
|
+
def list(self, schedule_id, start_time=None, finish=None, limit=None, offset=None):
|
|
12
|
+
path = "/slots"
|
|
13
|
+
query = {
|
|
14
|
+
'schedule_id': self._validate_id(schedule_id),
|
|
15
|
+
'start':
|
|
16
|
+
self._validate_datetime(start_time) if start_time else None,
|
|
17
|
+
'finish': self._validate_datetime(finish) if finish else None,
|
|
18
|
+
'limit': self._validate_number(limit) if limit else None,
|
|
19
|
+
'offset': self._validate_number(offset) if offset else None
|
|
20
|
+
}
|
|
21
|
+
res = self.client.get(path, query)
|
|
22
|
+
return [Slot(attributes) for attributes in res]
|
|
23
|
+
|
|
24
|
+
def get(self, schedule_id, slot_id):
|
|
25
|
+
query = {'schedule_id': self._validate_id(schedule_id)}
|
|
26
|
+
path = self.__slot_path(slot_id)
|
|
27
|
+
res = self.client.get(path, query)
|
|
28
|
+
return Slot(res)
|
|
29
|
+
|
|
30
|
+
def create(self, schedule_id, attributes):
|
|
31
|
+
path = "/slots"
|
|
32
|
+
query = {'schedule_id': self._validate_id(schedule_id)}
|
|
33
|
+
res = self.client.post(path, self.__params(attributes), query)
|
|
34
|
+
return {'location': res}
|
|
35
|
+
|
|
36
|
+
def update(self, schedule_id, slot_id, attributes):
|
|
37
|
+
path = self.__slot_path(slot_id)
|
|
38
|
+
query = {'schedule_id': self._validate_id(schedule_id)}
|
|
39
|
+
return self.client.put(path, self.__params(attributes), query)
|
|
40
|
+
|
|
41
|
+
def delete(self, schedule_id, slot_id):
|
|
42
|
+
path = self.__slot_path(slot_id)
|
|
43
|
+
query = {'schedule_id': self._validate_id(schedule_id)}
|
|
44
|
+
return self.client.delete(path, None, query)
|
|
45
|
+
|
|
46
|
+
def __slot_path(self, slot_id):
|
|
47
|
+
return f"/slots/{self._validate_present(self._validate_id(slot_id))}"
|
|
48
|
+
|
|
49
|
+
def __params(self, attributes):
|
|
50
|
+
# Don't wrap attributes in 'slot' if they're already wrapped
|
|
51
|
+
if isinstance(attributes, dict) and 'slot' in attributes:
|
|
52
|
+
attributes = attributes['slot']
|
|
53
|
+
attributes = attributes or {}
|
|
54
|
+
slot = {}
|
|
55
|
+
for key in self.ATTRIBUTES:
|
|
56
|
+
value = attributes.get(key)
|
|
57
|
+
if key in ('start', 'finish') and value is not None:
|
|
58
|
+
value = self._validate_datetime(value)
|
|
59
|
+
# capacity: '-' means unlimited and 0 means no places. None values aren't sent, so
|
|
60
|
+
# capacity=None leaves the capacity unchanged instead of making it unlimited.
|
|
61
|
+
if value is not None:
|
|
62
|
+
slot[key] = value
|
|
63
|
+
return {'slot': slot}
|
SuperSaaS/API/Users.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from .BaseApi import BaseApi
|
|
2
|
+
from ..Models.User import User
|
|
3
|
+
from ..Models.FieldList import FieldList
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Users(BaseApi):
|
|
7
|
+
|
|
8
|
+
def get(self, user_id=None, form=None):
|
|
9
|
+
path = self.__user_path(user_id)
|
|
10
|
+
query = {
|
|
11
|
+
'form': 'true' if form else None
|
|
12
|
+
}
|
|
13
|
+
res = self.client.get(path, query)
|
|
14
|
+
return User(res)
|
|
15
|
+
|
|
16
|
+
def list(self, form=None, limit=None, offset=None):
|
|
17
|
+
path = self.__user_path()
|
|
18
|
+
query = {
|
|
19
|
+
'form': 'true' if form else None,
|
|
20
|
+
'limit': self._validate_number(limit) if limit else None,
|
|
21
|
+
'offset': self._validate_number(offset) if offset else None
|
|
22
|
+
}
|
|
23
|
+
res = self.client.get(path, query)
|
|
24
|
+
return [User(attributes) for attributes in res]
|
|
25
|
+
|
|
26
|
+
def create(self, attributes, user_id=None, webhook=None, duplicate=None):
|
|
27
|
+
path = self.__user_path(user_id)
|
|
28
|
+
query = {'webhook': 'true' if webhook else None}
|
|
29
|
+
if duplicate:
|
|
30
|
+
query['duplicate'] = self._validate_duplicate(duplicate)
|
|
31
|
+
params = self.__params_for_update_create(attributes)
|
|
32
|
+
params['user'] = dict(
|
|
33
|
+
filter(lambda item: item[1] is not None, params['user'].items()))
|
|
34
|
+
res = self.client.post(path, params, query)
|
|
35
|
+
return {'location': res}
|
|
36
|
+
|
|
37
|
+
def update(self, user_id, attributes, webhook=None, notfound=None):
|
|
38
|
+
path = self.__user_path(user_id)
|
|
39
|
+
query = {'webhook': 'true' if webhook else None}
|
|
40
|
+
if notfound:
|
|
41
|
+
query['notfound'] = self._validate_notfound(notfound)
|
|
42
|
+
params = self.__params_for_update_create(attributes)
|
|
43
|
+
params['user'] = dict(
|
|
44
|
+
filter(lambda item: item[1] is not None, params['user'].items()))
|
|
45
|
+
return self.client.put(path, params, query)
|
|
46
|
+
|
|
47
|
+
def delete(self, user_id, webhook=None):
|
|
48
|
+
path = self.__user_path(self._validate_id(user_id))
|
|
49
|
+
query = {'webhook': 'true'} if webhook else None
|
|
50
|
+
return self.client.delete(path, None, query)
|
|
51
|
+
|
|
52
|
+
def field_list(self):
|
|
53
|
+
path = '/field_list'
|
|
54
|
+
res = self.client.get(path)
|
|
55
|
+
return [FieldList(attributes) for attributes in res]
|
|
56
|
+
|
|
57
|
+
def input_field_list(self):
|
|
58
|
+
path = '/input_field_list'
|
|
59
|
+
res = self.client.get(path)
|
|
60
|
+
return [FieldList(attributes) for attributes in res]
|
|
61
|
+
|
|
62
|
+
def __user_path(self, user_id=None):
|
|
63
|
+
return f"/users/{user_id}" if user_id else "/users"
|
|
64
|
+
|
|
65
|
+
def __params_for_update_create(self, attributes):
|
|
66
|
+
return {
|
|
67
|
+
'user': {
|
|
68
|
+
'name':
|
|
69
|
+
self._validate_present(attributes.get('name', ''))
|
|
70
|
+
if attributes.get('name', '') else None,
|
|
71
|
+
'email':
|
|
72
|
+
attributes.get('email', None),
|
|
73
|
+
'password':
|
|
74
|
+
attributes.get('password', None),
|
|
75
|
+
'full_name':
|
|
76
|
+
attributes.get('full_name', None),
|
|
77
|
+
'address':
|
|
78
|
+
attributes.get('address', None),
|
|
79
|
+
'mobile':
|
|
80
|
+
attributes.get('mobile', None),
|
|
81
|
+
'phone':
|
|
82
|
+
attributes.get('phone', None),
|
|
83
|
+
'country':
|
|
84
|
+
attributes.get('country', None),
|
|
85
|
+
'field_1':
|
|
86
|
+
attributes.get('field_1', None),
|
|
87
|
+
'field_2':
|
|
88
|
+
attributes.get('field_2', None),
|
|
89
|
+
'super_field':
|
|
90
|
+
attributes.get('super_field', None),
|
|
91
|
+
'credit':
|
|
92
|
+
attributes.get('credit', None),
|
|
93
|
+
'role':
|
|
94
|
+
attributes.get('role', None),
|
|
95
|
+
'group':
|
|
96
|
+
attributes.get('group', None)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
__all__ = [
|
|
2
|
+
"BaseApi", "Appointments", "Slots", "Forms", "Users", "Schedules", "Promotions",
|
|
3
|
+
"Groups", "Hooks"
|
|
4
|
+
]
|
|
5
|
+
|
|
6
|
+
from .BaseApi import BaseApi
|
|
7
|
+
from .Appointments import Appointments
|
|
8
|
+
from .Slots import Slots
|
|
9
|
+
from .Forms import Forms
|
|
10
|
+
from .Users import Users
|
|
11
|
+
from .Schedules import Schedules
|
|
12
|
+
from .Promotions import Promotions
|
|
13
|
+
from .Groups import Groups
|
|
14
|
+
from .Hooks import Hooks
|