tallyfy 1.0.16__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.
- tallyfy/__init__.py +27 -0
- tallyfy/__pycache__/__init__.cpython-310.pyc +0 -0
- tallyfy/__pycache__/core.cpython-310.pyc +0 -0
- tallyfy/__pycache__/form_fields_management.cpython-310.pyc +0 -0
- tallyfy/__pycache__/models.cpython-310.pyc +0 -0
- tallyfy/__pycache__/task_management.cpython-310.pyc +0 -0
- tallyfy/__pycache__/template_management.cpython-310.pyc +0 -0
- tallyfy/__pycache__/user_management.cpython-310.pyc +0 -0
- tallyfy/core.py +361 -0
- tallyfy/form_fields_management/__init__.py +70 -0
- tallyfy/form_fields_management/__pycache__/__init__.cpython-310.pyc +0 -0
- tallyfy/form_fields_management/__pycache__/base.cpython-310.pyc +0 -0
- tallyfy/form_fields_management/__pycache__/crud_operations.cpython-310.pyc +0 -0
- tallyfy/form_fields_management/__pycache__/options_management.cpython-310.pyc +0 -0
- tallyfy/form_fields_management/__pycache__/suggestions.cpython-310.pyc +0 -0
- tallyfy/form_fields_management/base.py +109 -0
- tallyfy/form_fields_management/crud_operations.py +234 -0
- tallyfy/form_fields_management/options_management.py +222 -0
- tallyfy/form_fields_management/suggestions.py +411 -0
- tallyfy/models.py +1464 -0
- tallyfy/organization_management/__init__.py +26 -0
- tallyfy/organization_management/base.py +76 -0
- tallyfy/organization_management/retrieval.py +39 -0
- tallyfy/task_management/__init__.py +81 -0
- tallyfy/task_management/__pycache__/__init__.cpython-310.pyc +0 -0
- tallyfy/task_management/__pycache__/base.cpython-310.pyc +0 -0
- tallyfy/task_management/__pycache__/creation.cpython-310.pyc +0 -0
- tallyfy/task_management/__pycache__/retrieval.cpython-310.pyc +0 -0
- tallyfy/task_management/__pycache__/search.cpython-310.pyc +0 -0
- tallyfy/task_management/base.py +125 -0
- tallyfy/task_management/creation.py +221 -0
- tallyfy/task_management/retrieval.py +252 -0
- tallyfy/task_management/search.py +198 -0
- tallyfy/template_management/__init__.py +85 -0
- tallyfy/template_management/analysis.py +1099 -0
- tallyfy/template_management/automation.py +469 -0
- tallyfy/template_management/base.py +56 -0
- tallyfy/template_management/basic_operations.py +479 -0
- tallyfy/template_management/health_assessment.py +793 -0
- tallyfy/user_management/__init__.py +70 -0
- tallyfy/user_management/__pycache__/__init__.cpython-310.pyc +0 -0
- tallyfy/user_management/__pycache__/base.cpython-310.pyc +0 -0
- tallyfy/user_management/__pycache__/invitation.cpython-310.pyc +0 -0
- tallyfy/user_management/__pycache__/retrieval.cpython-310.pyc +0 -0
- tallyfy/user_management/base.py +146 -0
- tallyfy/user_management/invitation.py +286 -0
- tallyfy/user_management/retrieval.py +381 -0
- tallyfy-1.0.16.dist-info/METADATA +742 -0
- tallyfy-1.0.16.dist-info/RECORD +52 -0
- tallyfy-1.0.16.dist-info/WHEEL +5 -0
- tallyfy-1.0.16.dist-info/licenses/LICENSE +21 -0
- tallyfy-1.0.16.dist-info/top_level.txt +1 -0
tallyfy/models.py
ADDED
|
@@ -0,0 +1,1464 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Data models for Tallyfy API responses
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Dict, Any, Optional, List
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TallyfyError(Exception):
|
|
10
|
+
"""Custom exception for Tallyfy API errors"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, message: str, status_code: Optional[int] = None, response_data: Optional[Any] = None):
|
|
13
|
+
super().__init__(message)
|
|
14
|
+
self.status_code = status_code
|
|
15
|
+
self.response_data = response_data
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class Country:
|
|
20
|
+
"""Country data model"""
|
|
21
|
+
id: int
|
|
22
|
+
name: str
|
|
23
|
+
phone_code: str
|
|
24
|
+
iso2: str
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Country':
|
|
28
|
+
"""Create Country instance from dictionary"""
|
|
29
|
+
return cls(
|
|
30
|
+
id=data.get('id', 0),
|
|
31
|
+
name=data.get('name', ''),
|
|
32
|
+
phone_code=data.get('phone_code', ''),
|
|
33
|
+
iso2=data.get('iso2', '')
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class User:
|
|
39
|
+
"""User data model"""
|
|
40
|
+
id: int
|
|
41
|
+
email: str
|
|
42
|
+
username: str
|
|
43
|
+
first_name: str
|
|
44
|
+
last_name: str
|
|
45
|
+
full_name: str
|
|
46
|
+
profile_pic: Optional[str] = None
|
|
47
|
+
locale: Optional[str] = None
|
|
48
|
+
active: bool = True
|
|
49
|
+
is_suspended: bool = False
|
|
50
|
+
created_at: Optional[str] = None
|
|
51
|
+
last_updated: Optional[str] = None
|
|
52
|
+
last_login_at: Optional[str] = None
|
|
53
|
+
activated_at: Optional[str] = None
|
|
54
|
+
support_user: bool = False
|
|
55
|
+
country: Optional[Country] = None
|
|
56
|
+
phone: Optional[str] = None
|
|
57
|
+
job_title: Optional[str] = None
|
|
58
|
+
job_description: Optional[str] = None
|
|
59
|
+
team: Optional[str] = None
|
|
60
|
+
timezone: Optional[str] = None
|
|
61
|
+
UTC_offset: Optional[str] = None
|
|
62
|
+
last_accessed_at: Optional[str] = None
|
|
63
|
+
approved_at: Optional[str] = None
|
|
64
|
+
invited_by: Optional[int] = None
|
|
65
|
+
disabled_at: Optional[str] = None
|
|
66
|
+
disabled_by: Optional[int] = None
|
|
67
|
+
reactivated_at: Optional[str] = None
|
|
68
|
+
reactivated_by: Optional[int] = None
|
|
69
|
+
status: Optional[str] = None
|
|
70
|
+
date_format: Optional[str] = None
|
|
71
|
+
last_known_ip: Optional[str] = None
|
|
72
|
+
last_known_country: Optional[str] = None
|
|
73
|
+
role: Optional[str] = None
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'User':
|
|
77
|
+
"""Create User instance from dictionary"""
|
|
78
|
+
country_data = data.get('country')
|
|
79
|
+
country = Country.from_dict(country_data) if country_data else None
|
|
80
|
+
|
|
81
|
+
return cls(
|
|
82
|
+
id=data.get('id', 0),
|
|
83
|
+
email=data.get('email', ''),
|
|
84
|
+
username=data.get('username', ''),
|
|
85
|
+
first_name=data.get('first_name', ''),
|
|
86
|
+
last_name=data.get('last_name', ''),
|
|
87
|
+
full_name=data.get('full_name', ''),
|
|
88
|
+
profile_pic=data.get('profile_pic'),
|
|
89
|
+
locale=data.get('locale'),
|
|
90
|
+
active=data.get('active', True),
|
|
91
|
+
is_suspended=data.get('is_suspended', False),
|
|
92
|
+
created_at=data.get('created_at'),
|
|
93
|
+
last_updated=data.get('last_updated'),
|
|
94
|
+
last_login_at=data.get('last_login_at'),
|
|
95
|
+
activated_at=data.get('activated_at'),
|
|
96
|
+
support_user=data.get('support_user', False),
|
|
97
|
+
country=country,
|
|
98
|
+
phone=data.get('phone'),
|
|
99
|
+
job_title=data.get('job_title'),
|
|
100
|
+
job_description=data.get('job_description'),
|
|
101
|
+
team=data.get('team'),
|
|
102
|
+
timezone=data.get('timezone'),
|
|
103
|
+
UTC_offset=data.get('UTC_offset'),
|
|
104
|
+
last_accessed_at=data.get('last_accessed_at'),
|
|
105
|
+
approved_at=data.get('approved_at'),
|
|
106
|
+
invited_by=data.get('invited_by'),
|
|
107
|
+
disabled_at=data.get('disabled_at'),
|
|
108
|
+
disabled_by=data.get('disabled_by'),
|
|
109
|
+
reactivated_at=data.get('reactivated_at'),
|
|
110
|
+
reactivated_by=data.get('reactivated_by'),
|
|
111
|
+
status=data.get('status'),
|
|
112
|
+
date_format=data.get('date_format'),
|
|
113
|
+
last_known_ip=data.get('last_known_ip'),
|
|
114
|
+
last_known_country=data.get('last_known_country'),
|
|
115
|
+
role=data.get('role')
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dataclass
|
|
120
|
+
class GuestDetails:
|
|
121
|
+
"""Guest details data model"""
|
|
122
|
+
first_name: Optional[str] = None
|
|
123
|
+
last_name: Optional[str] = None
|
|
124
|
+
status: Optional[str] = None
|
|
125
|
+
phone_1: Optional[str] = None
|
|
126
|
+
phone_2: Optional[str] = None
|
|
127
|
+
image_url: Optional[str] = None
|
|
128
|
+
contact_url: Optional[str] = None
|
|
129
|
+
company_url: Optional[str] = None
|
|
130
|
+
opportunity_url: Optional[str] = None
|
|
131
|
+
company_name: Optional[str] = None
|
|
132
|
+
opportunity_name: Optional[str] = None
|
|
133
|
+
external_sync_source: Optional[str] = None
|
|
134
|
+
external_date_creation: Optional[str] = None
|
|
135
|
+
timezone: Optional[str] = None
|
|
136
|
+
reactivated_at: Optional[str] = None
|
|
137
|
+
reactivated_by: Optional[int] = None
|
|
138
|
+
disabled_on: Optional[str] = None
|
|
139
|
+
disabled_by: Optional[int] = None
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'GuestDetails':
|
|
143
|
+
"""Create GuestDetails instance from dictionary"""
|
|
144
|
+
return cls(
|
|
145
|
+
first_name=data.get('first_name'),
|
|
146
|
+
last_name=data.get('last_name'),
|
|
147
|
+
status=data.get('status'),
|
|
148
|
+
phone_1=data.get('phone_1'),
|
|
149
|
+
phone_2=data.get('phone_2'),
|
|
150
|
+
image_url=data.get('image_url'),
|
|
151
|
+
contact_url=data.get('contact_url'),
|
|
152
|
+
company_url=data.get('company_url'),
|
|
153
|
+
opportunity_url=data.get('opportunity_url'),
|
|
154
|
+
company_name=data.get('company_name'),
|
|
155
|
+
opportunity_name=data.get('opportunity_name'),
|
|
156
|
+
external_sync_source=data.get('external_sync_source'),
|
|
157
|
+
external_date_creation=data.get('external_date_creation'),
|
|
158
|
+
timezone=data.get('timezone'),
|
|
159
|
+
reactivated_at=data.get('reactivated_at'),
|
|
160
|
+
reactivated_by=data.get('reactivated_by'),
|
|
161
|
+
disabled_on=data.get('disabled_on'),
|
|
162
|
+
disabled_by=data.get('disabled_by')
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@dataclass
|
|
167
|
+
class Guest:
|
|
168
|
+
"""Guest data model"""
|
|
169
|
+
email: str
|
|
170
|
+
last_accessed_at: Optional[str] = None
|
|
171
|
+
last_known_ip: Optional[str] = None
|
|
172
|
+
last_known_country: Optional[str] = None
|
|
173
|
+
details: Optional[GuestDetails] = None
|
|
174
|
+
|
|
175
|
+
@classmethod
|
|
176
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Guest':
|
|
177
|
+
"""Create Guest instance from dictionary"""
|
|
178
|
+
details_data = data.get('details')
|
|
179
|
+
details = GuestDetails.from_dict(details_data) if details_data else None
|
|
180
|
+
|
|
181
|
+
return cls(
|
|
182
|
+
email=data.get('email', ''),
|
|
183
|
+
last_accessed_at=data.get('last_accessed_at'),
|
|
184
|
+
last_known_ip=data.get('last_known_ip'),
|
|
185
|
+
last_known_country=data.get('last_known_country'),
|
|
186
|
+
details=details
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
@dataclass
|
|
191
|
+
class TaskOwners:
|
|
192
|
+
"""Task owners data model"""
|
|
193
|
+
users: List[int] = None
|
|
194
|
+
guests: List[str] = None
|
|
195
|
+
groups: List[int] = None
|
|
196
|
+
task_urls: List[str] = None
|
|
197
|
+
|
|
198
|
+
def __post_init__(self):
|
|
199
|
+
"""Initialize empty lists if None"""
|
|
200
|
+
if self.users is None:
|
|
201
|
+
self.users = []
|
|
202
|
+
if self.guests is None:
|
|
203
|
+
self.guests = []
|
|
204
|
+
if self.groups is None:
|
|
205
|
+
self.groups = []
|
|
206
|
+
if self.task_urls is None:
|
|
207
|
+
self.task_urls = []
|
|
208
|
+
|
|
209
|
+
@classmethod
|
|
210
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'TaskOwners':
|
|
211
|
+
"""Create TaskOwners instance from dictionary"""
|
|
212
|
+
return cls(
|
|
213
|
+
users=data.get('users', []),
|
|
214
|
+
guests=data.get('guests', []),
|
|
215
|
+
groups=data.get('groups', []),
|
|
216
|
+
task_urls=data.get('taskUrls', [])
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
@dataclass
|
|
224
|
+
class RunProgress:
|
|
225
|
+
"""Run progress data model"""
|
|
226
|
+
complete: int = 0
|
|
227
|
+
total: int = 0
|
|
228
|
+
percent: float = 0.0
|
|
229
|
+
|
|
230
|
+
@classmethod
|
|
231
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'RunProgress':
|
|
232
|
+
"""Create RunProgress instance from dictionary"""
|
|
233
|
+
return cls(
|
|
234
|
+
complete=data.get('complete', 0),
|
|
235
|
+
total=data.get('total', 0),
|
|
236
|
+
percent=data.get('percent', 0.0)
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@dataclass
|
|
241
|
+
class Run:
|
|
242
|
+
"""Run (Process) data model"""
|
|
243
|
+
id: str
|
|
244
|
+
increment_id: int
|
|
245
|
+
checklist_id: str
|
|
246
|
+
checklist_title: str
|
|
247
|
+
assign_someone_else: bool
|
|
248
|
+
name: str
|
|
249
|
+
summary: Optional[str] = None
|
|
250
|
+
status: str = "active"
|
|
251
|
+
progress: Optional[RunProgress] = None
|
|
252
|
+
whole_progress: Optional[RunProgress] = None
|
|
253
|
+
started_by: Optional[int] = None
|
|
254
|
+
prerun: Optional[Dict[str, Any]] = None
|
|
255
|
+
prerun_completed_at: Optional[str] = None
|
|
256
|
+
prerun_completed_by: Optional[int] = None
|
|
257
|
+
prerun_length: Optional[int] = None
|
|
258
|
+
starred: bool = False
|
|
259
|
+
created_at: Optional[str] = None
|
|
260
|
+
due_date: Optional[str] = None
|
|
261
|
+
owner_id: Optional[int] = None
|
|
262
|
+
started_at: Optional[str] = None
|
|
263
|
+
last_updated: Optional[str] = None
|
|
264
|
+
completed_at: Optional[str] = None
|
|
265
|
+
late_tasks: Optional[int] = None
|
|
266
|
+
archived_at: Optional[str] = None
|
|
267
|
+
due_date_passed: bool = False
|
|
268
|
+
collaborators: List[int] = None
|
|
269
|
+
due_soon: bool = False
|
|
270
|
+
max_task_deadline: Optional[str] = None
|
|
271
|
+
|
|
272
|
+
def __post_init__(self):
|
|
273
|
+
"""Initialize empty lists if None"""
|
|
274
|
+
if self.collaborators is None:
|
|
275
|
+
self.collaborators = []
|
|
276
|
+
|
|
277
|
+
@classmethod
|
|
278
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Run':
|
|
279
|
+
"""Create Run instance from dictionary"""
|
|
280
|
+
progress_data = data.get('progress')
|
|
281
|
+
progress = RunProgress.from_dict(progress_data) if progress_data else None
|
|
282
|
+
|
|
283
|
+
whole_progress_data = data.get('whole_progress')
|
|
284
|
+
whole_progress = RunProgress.from_dict(whole_progress_data) if whole_progress_data else None
|
|
285
|
+
|
|
286
|
+
return cls(
|
|
287
|
+
id=data.get('id', ''),
|
|
288
|
+
increment_id=data.get('increment_id', 0),
|
|
289
|
+
checklist_id=data.get('checklist_id', ''),
|
|
290
|
+
checklist_title=data.get('checklist_title', ''),
|
|
291
|
+
assign_someone_else=data.get('assign_someone_else', False),
|
|
292
|
+
name=data.get('name', ''),
|
|
293
|
+
summary=data.get('summary'),
|
|
294
|
+
status=data.get('status', 'active'),
|
|
295
|
+
progress=progress,
|
|
296
|
+
whole_progress=whole_progress,
|
|
297
|
+
started_by=data.get('started_by'),
|
|
298
|
+
prerun=data.get('prerun'),
|
|
299
|
+
prerun_completed_at=data.get('prerun_completed_at'),
|
|
300
|
+
prerun_completed_by=data.get('prerun_completed_by'),
|
|
301
|
+
prerun_length=data.get('prerun_length'),
|
|
302
|
+
starred=data.get('starred', False),
|
|
303
|
+
created_at=data.get('created_at'),
|
|
304
|
+
due_date=data.get('due_date'),
|
|
305
|
+
owner_id=data.get('owner_id'),
|
|
306
|
+
started_at=data.get('started_at'),
|
|
307
|
+
last_updated=data.get('last_updated'),
|
|
308
|
+
completed_at=data.get('completed_at'),
|
|
309
|
+
late_tasks=data.get('late_tasks'),
|
|
310
|
+
archived_at=data.get('archived_at'),
|
|
311
|
+
due_date_passed=data.get('due_date_passed', False),
|
|
312
|
+
collaborators=data.get('collaborators', []),
|
|
313
|
+
due_soon=data.get('due_soon', False),
|
|
314
|
+
max_task_deadline=data.get('max_task_deadline')
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
@dataclass
|
|
319
|
+
class Folder:
|
|
320
|
+
"""Folder data model for search results"""
|
|
321
|
+
id: str
|
|
322
|
+
parent: Optional[str]
|
|
323
|
+
name: str
|
|
324
|
+
|
|
325
|
+
@classmethod
|
|
326
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Folder':
|
|
327
|
+
"""Create Folder instance from dictionary"""
|
|
328
|
+
return cls(
|
|
329
|
+
id=data.get('id', ''),
|
|
330
|
+
parent=data.get('parent'),
|
|
331
|
+
name=data.get('name', '')
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
@dataclass
|
|
336
|
+
class Tag:
|
|
337
|
+
"""Tag data model for industry and topic tags"""
|
|
338
|
+
id: str
|
|
339
|
+
title: str
|
|
340
|
+
type: str
|
|
341
|
+
color: str
|
|
342
|
+
created_at: Optional[str] = None
|
|
343
|
+
deleted_at: Optional[str] = None
|
|
344
|
+
|
|
345
|
+
@classmethod
|
|
346
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Tag':
|
|
347
|
+
"""Create Tag instance from dictionary"""
|
|
348
|
+
return cls(
|
|
349
|
+
id=data.get('id', ''),
|
|
350
|
+
title=data.get('title', ''),
|
|
351
|
+
type=data.get('type', ''),
|
|
352
|
+
color=data.get('color', ''),
|
|
353
|
+
created_at=data.get('created_at'),
|
|
354
|
+
deleted_at=data.get('deleted_at')
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
@dataclass
|
|
359
|
+
class PrerunField:
|
|
360
|
+
"""Prerun field data model"""
|
|
361
|
+
id: str
|
|
362
|
+
checklist_id: str
|
|
363
|
+
alias: str
|
|
364
|
+
field_type: str
|
|
365
|
+
guidance: Optional[str] = None
|
|
366
|
+
position: int = 1
|
|
367
|
+
required: bool = True
|
|
368
|
+
use_wysiwyg_editor: bool = True
|
|
369
|
+
collect_time: bool = True
|
|
370
|
+
options: List[Dict[str, Any]] = None
|
|
371
|
+
field_validation: List[str] = None
|
|
372
|
+
created_at: Optional[str] = None
|
|
373
|
+
last_updated: Optional[str] = None
|
|
374
|
+
|
|
375
|
+
def __post_init__(self):
|
|
376
|
+
"""Initialize empty lists if None"""
|
|
377
|
+
if self.options is None:
|
|
378
|
+
self.options = []
|
|
379
|
+
if self.field_validation is None:
|
|
380
|
+
self.field_validation = []
|
|
381
|
+
|
|
382
|
+
@classmethod
|
|
383
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'PrerunField':
|
|
384
|
+
"""Create PrerunField instance from dictionary"""
|
|
385
|
+
return cls(
|
|
386
|
+
id=data.get('id', ''),
|
|
387
|
+
checklist_id=data.get('checklist_id', ''),
|
|
388
|
+
alias=data.get('alias', ''),
|
|
389
|
+
field_type=data.get('field_type', 'text'),
|
|
390
|
+
guidance=data.get('guidance'),
|
|
391
|
+
position=data.get('position', 1),
|
|
392
|
+
required=data.get('required', True),
|
|
393
|
+
use_wysiwyg_editor=data.get('use_wysiwyg_editor', True),
|
|
394
|
+
collect_time=data.get('collect_time', True),
|
|
395
|
+
options=data.get('options', []),
|
|
396
|
+
field_validation=data.get('field_validation', []),
|
|
397
|
+
created_at=data.get('created_at'),
|
|
398
|
+
last_updated=data.get('last_updated')
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
@dataclass
|
|
403
|
+
class AutomationCondition:
|
|
404
|
+
"""Automation condition data model"""
|
|
405
|
+
id: str
|
|
406
|
+
conditionable_id: str
|
|
407
|
+
conditionable_type: str
|
|
408
|
+
operation: str
|
|
409
|
+
statement: str
|
|
410
|
+
logic: str
|
|
411
|
+
position: int
|
|
412
|
+
column_contains_name: Optional[str] = None
|
|
413
|
+
|
|
414
|
+
@classmethod
|
|
415
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'AutomationCondition':
|
|
416
|
+
"""Create AutomationCondition instance from dictionary"""
|
|
417
|
+
return cls(
|
|
418
|
+
id=data.get('id', ''),
|
|
419
|
+
conditionable_id=data.get('conditionable_id', ''),
|
|
420
|
+
conditionable_type=data.get('conditionable_type', ''),
|
|
421
|
+
operation=data.get('operation', ''),
|
|
422
|
+
statement=data.get('statement', ''),
|
|
423
|
+
logic=data.get('logic', ''),
|
|
424
|
+
position=data.get('position', 0),
|
|
425
|
+
column_contains_name=data.get('column_contains_name')
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
@dataclass
|
|
430
|
+
class AutomationDeadline:
|
|
431
|
+
"""Automation deadline data model"""
|
|
432
|
+
value: int
|
|
433
|
+
unit: str
|
|
434
|
+
|
|
435
|
+
@classmethod
|
|
436
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'AutomationDeadline':
|
|
437
|
+
"""Create AutomationDeadline instance from dictionary"""
|
|
438
|
+
return cls(
|
|
439
|
+
value=data.get('value', 0),
|
|
440
|
+
unit=data.get('unit', 'days')
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
@dataclass
|
|
445
|
+
class AutomationAssignees:
|
|
446
|
+
"""Automation assignees data model"""
|
|
447
|
+
users: List[int] = None
|
|
448
|
+
guests: List[str] = None
|
|
449
|
+
groups: List[str] = None
|
|
450
|
+
|
|
451
|
+
def __post_init__(self):
|
|
452
|
+
"""Initialize empty lists if None"""
|
|
453
|
+
if self.users is None:
|
|
454
|
+
self.users = []
|
|
455
|
+
if self.guests is None:
|
|
456
|
+
self.guests = []
|
|
457
|
+
if self.groups is None:
|
|
458
|
+
self.groups = []
|
|
459
|
+
|
|
460
|
+
@classmethod
|
|
461
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'AutomationAssignees':
|
|
462
|
+
"""Create AutomationAssignees instance from dictionary"""
|
|
463
|
+
return cls(
|
|
464
|
+
users=data.get('users', []),
|
|
465
|
+
guests=data.get('guests', []),
|
|
466
|
+
groups=data.get('groups', [])
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
@dataclass
|
|
471
|
+
class AutomationAction:
|
|
472
|
+
"""Automation action data model"""
|
|
473
|
+
id: str
|
|
474
|
+
action_type: str
|
|
475
|
+
action_verb: str
|
|
476
|
+
target_step_id: Optional[str] = None
|
|
477
|
+
position: int = 0
|
|
478
|
+
actionable_id: Optional[str] = None
|
|
479
|
+
actionable_type: Optional[str] = None
|
|
480
|
+
deadline: Optional[AutomationDeadline] = None
|
|
481
|
+
assignees: Optional[AutomationAssignees] = None
|
|
482
|
+
|
|
483
|
+
@classmethod
|
|
484
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'AutomationAction':
|
|
485
|
+
"""Create AutomationAction instance from dictionary"""
|
|
486
|
+
deadline_data = data.get('deadline')
|
|
487
|
+
deadline = AutomationDeadline.from_dict(deadline_data) if deadline_data else None
|
|
488
|
+
|
|
489
|
+
assignees_data = data.get('assignees')
|
|
490
|
+
assignees = AutomationAssignees.from_dict(assignees_data) if assignees_data else None
|
|
491
|
+
|
|
492
|
+
return cls(
|
|
493
|
+
id=data.get('id', ''),
|
|
494
|
+
action_type=data.get('action_type', ''),
|
|
495
|
+
action_verb=data.get('action_verb', ''),
|
|
496
|
+
target_step_id=data.get('target_step_id'),
|
|
497
|
+
position=data.get('position', 0),
|
|
498
|
+
actionable_id=data.get('actionable_id'),
|
|
499
|
+
actionable_type=data.get('actionable_type'),
|
|
500
|
+
deadline=deadline,
|
|
501
|
+
assignees=assignees
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
@dataclass
|
|
506
|
+
class AutomatedAction:
|
|
507
|
+
"""Automated action data model"""
|
|
508
|
+
id: str
|
|
509
|
+
automated_alias: str
|
|
510
|
+
conditions: List[AutomationCondition] = None
|
|
511
|
+
then_actions: List[AutomationAction] = None
|
|
512
|
+
created_at: Optional[str] = None
|
|
513
|
+
last_updated: Optional[str] = None
|
|
514
|
+
archived_at: Optional[str] = None
|
|
515
|
+
|
|
516
|
+
def __post_init__(self):
|
|
517
|
+
"""Initialize empty lists if None"""
|
|
518
|
+
if self.conditions is None:
|
|
519
|
+
self.conditions = []
|
|
520
|
+
if self.then_actions is None:
|
|
521
|
+
self.then_actions = []
|
|
522
|
+
|
|
523
|
+
@classmethod
|
|
524
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'AutomatedAction':
|
|
525
|
+
"""Create AutomatedAction instance from dictionary"""
|
|
526
|
+
conditions_data = data.get('conditions', [])
|
|
527
|
+
conditions = [AutomationCondition.from_dict(cond_data) for cond_data in conditions_data] if conditions_data else []
|
|
528
|
+
|
|
529
|
+
actions_data = data.get('then_actions', [])
|
|
530
|
+
then_actions = [AutomationAction.from_dict(action_data) for action_data in actions_data] if actions_data else []
|
|
531
|
+
|
|
532
|
+
return cls(
|
|
533
|
+
id=data.get('id', ''),
|
|
534
|
+
automated_alias=data.get('automated_alias', ''),
|
|
535
|
+
conditions=conditions,
|
|
536
|
+
then_actions=then_actions,
|
|
537
|
+
created_at=data.get('created_at'),
|
|
538
|
+
last_updated=data.get('last_updated'),
|
|
539
|
+
archived_at=data.get('archived_at')
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
@dataclass
|
|
544
|
+
class StepStartDate:
|
|
545
|
+
"""Step start date data model"""
|
|
546
|
+
value: int = 0
|
|
547
|
+
unit: str = "days"
|
|
548
|
+
|
|
549
|
+
@classmethod
|
|
550
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'StepStartDate':
|
|
551
|
+
"""Create StepStartDate instance from dictionary"""
|
|
552
|
+
return cls(
|
|
553
|
+
value=data.get('value', 0),
|
|
554
|
+
unit=data.get('unit', 'days')
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
@dataclass
|
|
559
|
+
class StepDeadline:
|
|
560
|
+
"""Step deadline data model"""
|
|
561
|
+
value: int = 0
|
|
562
|
+
unit: str = "days"
|
|
563
|
+
option: str = "from"
|
|
564
|
+
step: str = "start_run"
|
|
565
|
+
|
|
566
|
+
@classmethod
|
|
567
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'StepDeadline':
|
|
568
|
+
"""Create StepDeadline instance from dictionary"""
|
|
569
|
+
return cls(
|
|
570
|
+
value=data.get('value', 0),
|
|
571
|
+
unit=data.get('unit', 'days'),
|
|
572
|
+
option=data.get('option', 'from'),
|
|
573
|
+
step=data.get('step', 'start_run')
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
@dataclass
|
|
578
|
+
class StepBpToLaunch:
|
|
579
|
+
"""Step blueprint to launch data model"""
|
|
580
|
+
id: Optional[str] = None
|
|
581
|
+
default_name_format: Optional[str] = None
|
|
582
|
+
tasks_within_process: bool = True
|
|
583
|
+
|
|
584
|
+
@classmethod
|
|
585
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'StepBpToLaunch':
|
|
586
|
+
"""Create StepBpToLaunch instance from dictionary"""
|
|
587
|
+
return cls(
|
|
588
|
+
id=data.get('id'),
|
|
589
|
+
default_name_format=data.get('default_name_format'),
|
|
590
|
+
tasks_within_process=data.get('tasks_within_process', True)
|
|
591
|
+
)
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
@dataclass
|
|
595
|
+
class Capture:
|
|
596
|
+
"""Capture (form field) data model"""
|
|
597
|
+
id: str
|
|
598
|
+
step_id: str
|
|
599
|
+
field_type: str
|
|
600
|
+
label: str
|
|
601
|
+
guidance: Optional[str] = None
|
|
602
|
+
position: int = 1
|
|
603
|
+
required: bool = True
|
|
604
|
+
options: List[Dict[str, Any]] = None
|
|
605
|
+
columns: List[Dict[str, Any]] = None
|
|
606
|
+
default_value_enabled: bool = False
|
|
607
|
+
default_value: Optional[str] = None
|
|
608
|
+
created_at: Optional[str] = None
|
|
609
|
+
last_updated: Optional[str] = None
|
|
610
|
+
|
|
611
|
+
def __post_init__(self):
|
|
612
|
+
"""Initialize empty lists if None"""
|
|
613
|
+
if self.options is None:
|
|
614
|
+
self.options = []
|
|
615
|
+
if self.columns is None:
|
|
616
|
+
self.columns = []
|
|
617
|
+
|
|
618
|
+
@classmethod
|
|
619
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Capture':
|
|
620
|
+
"""Create Capture instance from dictionary"""
|
|
621
|
+
return cls(
|
|
622
|
+
id=data.get('id', ''),
|
|
623
|
+
step_id=data.get('step_id', ''),
|
|
624
|
+
field_type=data.get('field_type', 'text'),
|
|
625
|
+
label=data.get('label', ''),
|
|
626
|
+
guidance=data.get('guidance'),
|
|
627
|
+
position=data.get('position', 1),
|
|
628
|
+
required=data.get('required', True),
|
|
629
|
+
options=data.get('options', []),
|
|
630
|
+
columns=data.get('columns', []),
|
|
631
|
+
default_value_enabled=data.get('default_value_enabled', False),
|
|
632
|
+
default_value=data.get('default_value'),
|
|
633
|
+
created_at=data.get('created_at'),
|
|
634
|
+
last_updated=data.get('last_updated')
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
@dataclass
|
|
639
|
+
class Step:
|
|
640
|
+
"""Step data model"""
|
|
641
|
+
id: str
|
|
642
|
+
checklist_id: str
|
|
643
|
+
title: str
|
|
644
|
+
alias: Optional[str] = None
|
|
645
|
+
summary: Optional[str] = None
|
|
646
|
+
step_type: Optional[str] = None
|
|
647
|
+
position: int = 1
|
|
648
|
+
allow_guest_owners: bool = False
|
|
649
|
+
max_assignable: int = 1
|
|
650
|
+
skip_start_process: bool = False
|
|
651
|
+
can_complete_only_assignees: bool = False
|
|
652
|
+
everyone_must_complete: bool = False
|
|
653
|
+
webhook: Optional[str] = None
|
|
654
|
+
start_date: Optional[StepStartDate] = None
|
|
655
|
+
is_soft_start_date: bool = False
|
|
656
|
+
deadline: Optional[StepDeadline] = None
|
|
657
|
+
bp_to_launch: Optional[StepBpToLaunch] = None
|
|
658
|
+
assignees: List[int] = None
|
|
659
|
+
guests: List[str] = None
|
|
660
|
+
groups: List[str] = None
|
|
661
|
+
captures: List[Capture] = None
|
|
662
|
+
prevent_guest_comment: bool = False
|
|
663
|
+
roles: List[str] = None
|
|
664
|
+
role_changes_every_time: bool = False
|
|
665
|
+
created_at: Optional[str] = None
|
|
666
|
+
last_updated: Optional[str] = None
|
|
667
|
+
archived_at: Optional[str] = None
|
|
668
|
+
|
|
669
|
+
def __post_init__(self):
|
|
670
|
+
"""Initialize empty lists if None"""
|
|
671
|
+
if self.assignees is None:
|
|
672
|
+
self.assignees = []
|
|
673
|
+
if self.guests is None:
|
|
674
|
+
self.guests = []
|
|
675
|
+
if self.groups is None:
|
|
676
|
+
self.groups = []
|
|
677
|
+
if self.captures is None:
|
|
678
|
+
self.captures = []
|
|
679
|
+
if self.roles is None:
|
|
680
|
+
self.roles = []
|
|
681
|
+
|
|
682
|
+
@classmethod
|
|
683
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Step':
|
|
684
|
+
"""Create Step instance from dictionary"""
|
|
685
|
+
start_date_data = data.get('start_date')
|
|
686
|
+
start_date = StepStartDate.from_dict(start_date_data) if start_date_data else None
|
|
687
|
+
|
|
688
|
+
deadline_data = data.get('deadline')
|
|
689
|
+
deadline = StepDeadline.from_dict(deadline_data) if deadline_data else None
|
|
690
|
+
|
|
691
|
+
bp_to_launch_data = data.get('bp_to_launch')
|
|
692
|
+
bp_to_launch = StepBpToLaunch.from_dict(bp_to_launch_data) if bp_to_launch_data else None
|
|
693
|
+
|
|
694
|
+
captures_data = data.get('captures', [])
|
|
695
|
+
captures = [Capture.from_dict(capture_data) for capture_data in captures_data] if captures_data else []
|
|
696
|
+
|
|
697
|
+
return cls(
|
|
698
|
+
id=data.get('id', ''),
|
|
699
|
+
checklist_id=data.get('checklist_id', ''),
|
|
700
|
+
title=data.get('title', ''),
|
|
701
|
+
alias=data.get('alias'),
|
|
702
|
+
summary=data.get('summary'),
|
|
703
|
+
step_type=data.get('step_type'),
|
|
704
|
+
position=data.get('position', 1),
|
|
705
|
+
allow_guest_owners=data.get('allow_guest_owners', False),
|
|
706
|
+
max_assignable=data.get('max_assignable', 1),
|
|
707
|
+
skip_start_process=data.get('skip_start_process', False),
|
|
708
|
+
can_complete_only_assignees=data.get('can_complete_only_assignees', False),
|
|
709
|
+
everyone_must_complete=data.get('everyone_must_complete', False),
|
|
710
|
+
webhook=data.get('webhook'),
|
|
711
|
+
start_date=start_date,
|
|
712
|
+
is_soft_start_date=data.get('is_soft_start_date', False),
|
|
713
|
+
deadline=deadline,
|
|
714
|
+
bp_to_launch=bp_to_launch,
|
|
715
|
+
assignees=data.get('assignees', []),
|
|
716
|
+
guests=data.get('guests', []),
|
|
717
|
+
groups=data.get('groups', []),
|
|
718
|
+
captures=captures,
|
|
719
|
+
prevent_guest_comment=data.get('prevent_guest_comment', False),
|
|
720
|
+
roles=data.get('roles', []),
|
|
721
|
+
role_changes_every_time=data.get('role_changes_every_time', False),
|
|
722
|
+
created_at=data.get('created_at'),
|
|
723
|
+
last_updated=data.get('last_updated'),
|
|
724
|
+
archived_at=data.get('archived_at')
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
@dataclass
|
|
729
|
+
class Task:
|
|
730
|
+
"""Task data model"""
|
|
731
|
+
id: str
|
|
732
|
+
increment_id: int
|
|
733
|
+
title: str
|
|
734
|
+
original_title: str
|
|
735
|
+
allow_guest_owners: bool
|
|
736
|
+
run_id: Optional[str] = None
|
|
737
|
+
checklist_id: Optional[str] = None
|
|
738
|
+
linked_step_id: Optional[str] = None
|
|
739
|
+
step_id: Optional[str] = None
|
|
740
|
+
alias: Optional[str] = None
|
|
741
|
+
taskdata: Optional[Dict[str, Any]] = None
|
|
742
|
+
owners: Optional[TaskOwners] = None
|
|
743
|
+
step: Optional[Step] = None
|
|
744
|
+
run: Optional[Run] = None
|
|
745
|
+
is_completable: bool = True
|
|
746
|
+
status: str = "not-started"
|
|
747
|
+
status_label: str = "not-started"
|
|
748
|
+
task_type: str = "task"
|
|
749
|
+
is_approved: Optional[bool] = None
|
|
750
|
+
position: int = 0
|
|
751
|
+
started_at: Optional[str] = None
|
|
752
|
+
deadline: Optional[str] = None
|
|
753
|
+
created_at: Optional[str] = None
|
|
754
|
+
last_updated: Optional[str] = None
|
|
755
|
+
archived_at: Optional[str] = None
|
|
756
|
+
completed_at: Optional[str] = None
|
|
757
|
+
starter_id: Optional[int] = None
|
|
758
|
+
completer_id: Optional[int] = None
|
|
759
|
+
is_oneoff_task: bool = False
|
|
760
|
+
everyone_must_complete: bool = False
|
|
761
|
+
completion_progress: Optional[float] = None
|
|
762
|
+
has_deadline_dependent_child_tasks: bool = False
|
|
763
|
+
can_complete_only_assignees: bool = False
|
|
764
|
+
max_assignable: int = 0
|
|
765
|
+
webhook: Optional[str] = None
|
|
766
|
+
prevent_guest_comment: bool = False
|
|
767
|
+
stage_id: Optional[str] = None
|
|
768
|
+
problem: bool = False
|
|
769
|
+
blueprint_position: Optional[int] = None
|
|
770
|
+
is_soft_start_date: bool = False
|
|
771
|
+
send_chromeless: Optional[bool] = None
|
|
772
|
+
run_status: Optional[str] = None
|
|
773
|
+
completer_guest: Optional[str] = None
|
|
774
|
+
|
|
775
|
+
@classmethod
|
|
776
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Task':
|
|
777
|
+
"""Create Task instance from dictionary"""
|
|
778
|
+
owners_data = data.get('owners')
|
|
779
|
+
owners = TaskOwners.from_dict(owners_data) if owners_data else None
|
|
780
|
+
|
|
781
|
+
try:
|
|
782
|
+
step_data = data.get('step')['data']
|
|
783
|
+
step = Step.from_dict(step_data) if step_data else None
|
|
784
|
+
except:
|
|
785
|
+
step = None
|
|
786
|
+
|
|
787
|
+
try:
|
|
788
|
+
run_data = data.get('run')['data']
|
|
789
|
+
run = Run.from_dict(run_data) if run_data else None
|
|
790
|
+
except:
|
|
791
|
+
run = None
|
|
792
|
+
|
|
793
|
+
return cls(
|
|
794
|
+
id=data.get('id', ''),
|
|
795
|
+
increment_id=data.get('increment_id', 0),
|
|
796
|
+
title=data.get('title', ''),
|
|
797
|
+
original_title=data.get('original_title', ''),
|
|
798
|
+
allow_guest_owners=data.get('allow_guest_owners', False),
|
|
799
|
+
run_id=data.get('run_id'),
|
|
800
|
+
checklist_id=data.get('checklist_id'),
|
|
801
|
+
linked_step_id=data.get('linked_step_id'),
|
|
802
|
+
step_id=data.get('step_id'),
|
|
803
|
+
alias=data.get('alias'),
|
|
804
|
+
taskdata=data.get('taskdata', {}),
|
|
805
|
+
owners=owners,
|
|
806
|
+
step=step,
|
|
807
|
+
run=run,
|
|
808
|
+
is_completable=data.get('is_completable', True),
|
|
809
|
+
status=data.get('status', 'not-started'),
|
|
810
|
+
status_label=data.get('status_label', 'not-started'),
|
|
811
|
+
task_type=data.get('task_type', 'task'),
|
|
812
|
+
is_approved=data.get('is_approved'),
|
|
813
|
+
position=data.get('position', 0),
|
|
814
|
+
started_at=data.get('started_at'),
|
|
815
|
+
deadline=data.get('deadline'),
|
|
816
|
+
created_at=data.get('created_at'),
|
|
817
|
+
last_updated=data.get('last_updated'),
|
|
818
|
+
archived_at=data.get('archived_at'),
|
|
819
|
+
completed_at=data.get('completed_at'),
|
|
820
|
+
starter_id=data.get('starter_id'),
|
|
821
|
+
completer_id=data.get('completer_id'),
|
|
822
|
+
is_oneoff_task=data.get('is_oneoff_task', False),
|
|
823
|
+
everyone_must_complete=data.get('everyone_must_complete', False),
|
|
824
|
+
completion_progress=data.get('completion_progress'),
|
|
825
|
+
has_deadline_dependent_child_tasks=data.get('has_deadline_dependent_child_tasks', False),
|
|
826
|
+
can_complete_only_assignees=data.get('can_complete_only_assignees', False),
|
|
827
|
+
max_assignable=data.get('max_assignable', 0),
|
|
828
|
+
webhook=data.get('webhook'),
|
|
829
|
+
prevent_guest_comment=data.get('prevent_guest_comment', False),
|
|
830
|
+
stage_id=data.get('stage_id'),
|
|
831
|
+
problem=data.get('problem', False),
|
|
832
|
+
blueprint_position=data.get('blueprint_position'),
|
|
833
|
+
is_soft_start_date=data.get('is_soft_start_date', False),
|
|
834
|
+
send_chromeless=data.get('send_chromeless'),
|
|
835
|
+
run_status=data.get('run_status'),
|
|
836
|
+
completer_guest=data.get('completer_guest')
|
|
837
|
+
)
|
|
838
|
+
|
|
839
|
+
@dataclass
|
|
840
|
+
class Template:
|
|
841
|
+
"""Template data model"""
|
|
842
|
+
id: str
|
|
843
|
+
title: str
|
|
844
|
+
summary: Optional[str] = None
|
|
845
|
+
starred: bool = True
|
|
846
|
+
webhook: Optional[str] = None
|
|
847
|
+
explanation_video: Optional[str] = None
|
|
848
|
+
guidance: Optional[str] = None
|
|
849
|
+
icon: Optional[str] = None
|
|
850
|
+
alias: Optional[str] = None
|
|
851
|
+
prerun: List[PrerunField] = None
|
|
852
|
+
automated_actions: List[AutomatedAction] = None
|
|
853
|
+
steps: List[Step] = None
|
|
854
|
+
created_by: Optional[int] = None
|
|
855
|
+
owner_id: Optional[int] = None
|
|
856
|
+
started_processes: int = 0
|
|
857
|
+
kickoff_title: Optional[str] = None
|
|
858
|
+
kickoff_description: Optional[str] = None
|
|
859
|
+
created_at: Optional[str] = None
|
|
860
|
+
last_updated: Optional[str] = None
|
|
861
|
+
archived_at: Optional[str] = None
|
|
862
|
+
is_public: bool = True
|
|
863
|
+
is_featured: bool = True
|
|
864
|
+
users: List[int] = None
|
|
865
|
+
groups: List[str] = None
|
|
866
|
+
public_cover: Optional[str] = None
|
|
867
|
+
industry_tags: List[Tag] = None
|
|
868
|
+
topic_tags: List[Tag] = None
|
|
869
|
+
type: Optional[str] = None
|
|
870
|
+
default_process_name_format: Optional[str] = None
|
|
871
|
+
is_public_kickoff: bool = True
|
|
872
|
+
dual_version_enabled: bool = True
|
|
873
|
+
is_published_state: bool = True
|
|
874
|
+
auto_naming: bool = True
|
|
875
|
+
last_updated_by: Optional[str] = None
|
|
876
|
+
linked_tasks: List[Task] = None
|
|
877
|
+
folderize_process: bool = True
|
|
878
|
+
tag_process: bool = True
|
|
879
|
+
allow_launcher_change_name: bool = True
|
|
880
|
+
is_pinned: bool = True
|
|
881
|
+
ko_form_blueprint_id: Optional[str] = None
|
|
882
|
+
default_folder: Optional[str] = None
|
|
883
|
+
folder_changeable_by_launcher: bool = True
|
|
884
|
+
kickoff_sharing_user_id: Optional[int] = None
|
|
885
|
+
|
|
886
|
+
def __post_init__(self):
|
|
887
|
+
"""Initialize empty lists if None"""
|
|
888
|
+
if self.prerun is None:
|
|
889
|
+
self.prerun = []
|
|
890
|
+
if self.automated_actions is None:
|
|
891
|
+
self.automated_actions = []
|
|
892
|
+
if self.users is None:
|
|
893
|
+
self.users = []
|
|
894
|
+
if self.groups is None:
|
|
895
|
+
self.groups = []
|
|
896
|
+
if self.industry_tags is None:
|
|
897
|
+
self.industry_tags = []
|
|
898
|
+
if self.topic_tags is None:
|
|
899
|
+
self.topic_tags = []
|
|
900
|
+
if self.linked_tasks is None:
|
|
901
|
+
self.linked_tasks = []
|
|
902
|
+
if self.steps is None:
|
|
903
|
+
self.steps = []
|
|
904
|
+
|
|
905
|
+
@classmethod
|
|
906
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Template':
|
|
907
|
+
"""Create Template instance from dictionary"""
|
|
908
|
+
prerun_data = data.get('prerun', [])
|
|
909
|
+
prerun = [PrerunField.from_dict(field_data) for field_data in prerun_data] if prerun_data else []
|
|
910
|
+
|
|
911
|
+
automated_actions_data = data.get('automated_actions', [])
|
|
912
|
+
automated_actions = [AutomatedAction.from_dict(action_data) for action_data in automated_actions_data] if automated_actions_data else []
|
|
913
|
+
|
|
914
|
+
steps_data = data.get('steps', [])
|
|
915
|
+
steps = [Step.from_dict(step_data) for step_data in
|
|
916
|
+
steps_data['data']] if steps_data else []
|
|
917
|
+
|
|
918
|
+
industry_tags_data = data.get('industry_tags', [])
|
|
919
|
+
industry_tags = [Tag.from_dict(tag_data) for tag_data in industry_tags_data] if industry_tags_data else []
|
|
920
|
+
|
|
921
|
+
topic_tags_data = data.get('topic_tags', [])
|
|
922
|
+
topic_tags = [Tag.from_dict(tag_data) for tag_data in topic_tags_data] if topic_tags_data else []
|
|
923
|
+
|
|
924
|
+
linked_tasks_data = data.get('linked_tasks', [])
|
|
925
|
+
linked_tasks = [Task.from_dict(task_data) for task_data in linked_tasks_data] if linked_tasks_data else []
|
|
926
|
+
|
|
927
|
+
return cls(
|
|
928
|
+
id=data.get('id', ''),
|
|
929
|
+
title=data.get('title', ''),
|
|
930
|
+
summary=data.get('summary'),
|
|
931
|
+
starred=data.get('starred', True),
|
|
932
|
+
webhook=data.get('webhook'),
|
|
933
|
+
explanation_video=data.get('explanation_video'),
|
|
934
|
+
guidance=data.get('guidance'),
|
|
935
|
+
icon=data.get('icon'),
|
|
936
|
+
alias=data.get('alias'),
|
|
937
|
+
prerun=prerun,
|
|
938
|
+
automated_actions=automated_actions,
|
|
939
|
+
steps=steps,
|
|
940
|
+
created_by=data.get('created_by'),
|
|
941
|
+
owner_id=data.get('owner_id'),
|
|
942
|
+
started_processes=data.get('started_processes', 0),
|
|
943
|
+
kickoff_title=data.get('kickoff_title'),
|
|
944
|
+
kickoff_description=data.get('kickoff_description'),
|
|
945
|
+
created_at=data.get('created_at'),
|
|
946
|
+
last_updated=data.get('last_updated'),
|
|
947
|
+
archived_at=data.get('archived_at'),
|
|
948
|
+
is_public=data.get('is_public', True),
|
|
949
|
+
is_featured=data.get('is_featured', True),
|
|
950
|
+
users=data.get('users', []),
|
|
951
|
+
groups=data.get('groups', []),
|
|
952
|
+
public_cover=data.get('public_cover'),
|
|
953
|
+
industry_tags=industry_tags,
|
|
954
|
+
topic_tags=topic_tags,
|
|
955
|
+
type=data.get('type'),
|
|
956
|
+
default_process_name_format=data.get('default_process_name_format'),
|
|
957
|
+
is_public_kickoff=data.get('is_public_kickoff', True),
|
|
958
|
+
dual_version_enabled=data.get('dual_version_enabled', True),
|
|
959
|
+
is_published_state=data.get('is_published_state', True),
|
|
960
|
+
auto_naming=data.get('auto_naming', True),
|
|
961
|
+
last_updated_by=data.get('last_updated_by'),
|
|
962
|
+
linked_tasks=linked_tasks,
|
|
963
|
+
folderize_process=data.get('folderize_process', True),
|
|
964
|
+
tag_process=data.get('tag_process', True),
|
|
965
|
+
allow_launcher_change_name=data.get('allow_launcher_change_name', True),
|
|
966
|
+
is_pinned=data.get('is_pinned', True),
|
|
967
|
+
ko_form_blueprint_id=data.get('ko_form_blueprint_id'),
|
|
968
|
+
default_folder=data.get('default_folder'),
|
|
969
|
+
folder_changeable_by_launcher=data.get('folder_changeable_by_launcher', True),
|
|
970
|
+
kickoff_sharing_user_id=data.get('kickoff_sharing_user_id')
|
|
971
|
+
)
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
|
|
975
|
+
@dataclass
|
|
976
|
+
class SearchResult:
|
|
977
|
+
"""Search result data model for templates, processes, and tasks"""
|
|
978
|
+
id: str
|
|
979
|
+
increment_id: int
|
|
980
|
+
search_type: str
|
|
981
|
+
|
|
982
|
+
# Common fields
|
|
983
|
+
name: Optional[str] = None
|
|
984
|
+
title: Optional[str] = None
|
|
985
|
+
status: Optional[str] = None
|
|
986
|
+
type: Optional[str] = None
|
|
987
|
+
|
|
988
|
+
# Template-specific fields
|
|
989
|
+
steps_count: Optional[int] = None
|
|
990
|
+
icon: Optional[str] = None
|
|
991
|
+
is_public: Optional[bool] = None
|
|
992
|
+
is_featured: Optional[bool] = None
|
|
993
|
+
organization_id: Optional[str] = None
|
|
994
|
+
folders: Optional[List[Folder]] = None
|
|
995
|
+
|
|
996
|
+
# Process-specific fields
|
|
997
|
+
due_date_passed: Optional[bool] = None
|
|
998
|
+
due_soon: Optional[bool] = None
|
|
999
|
+
|
|
1000
|
+
# Task-specific fields
|
|
1001
|
+
status_label: Optional[str] = None
|
|
1002
|
+
position: Optional[int] = None
|
|
1003
|
+
deadline: Optional[str] = None
|
|
1004
|
+
created_at: Optional[str] = None
|
|
1005
|
+
starter_id: Optional[int] = None
|
|
1006
|
+
is_oneoff_task: Optional[bool] = None
|
|
1007
|
+
owners: Optional[TaskOwners] = None
|
|
1008
|
+
|
|
1009
|
+
def __post_init__(self):
|
|
1010
|
+
"""Initialize empty lists if None"""
|
|
1011
|
+
if self.folders is None:
|
|
1012
|
+
self.folders = []
|
|
1013
|
+
|
|
1014
|
+
@classmethod
|
|
1015
|
+
def from_dict(cls, data: Dict[str, Any], search_type: str) -> 'SearchResult':
|
|
1016
|
+
"""Create SearchResult instance from dictionary"""
|
|
1017
|
+
folders_data = data.get('folders', [])
|
|
1018
|
+
folders = [Folder.from_dict(folder_data) for folder_data in folders_data] if folders_data else []
|
|
1019
|
+
|
|
1020
|
+
owners_data = data.get('owners')
|
|
1021
|
+
owners = TaskOwners.from_dict(owners_data) if owners_data else None
|
|
1022
|
+
|
|
1023
|
+
return cls(
|
|
1024
|
+
id=data.get('id', ''),
|
|
1025
|
+
increment_id=data.get('increment_id', 0),
|
|
1026
|
+
search_type=search_type,
|
|
1027
|
+
name=data.get('name'),
|
|
1028
|
+
title=data.get('title'),
|
|
1029
|
+
status=data.get('status'),
|
|
1030
|
+
type=data.get('type'),
|
|
1031
|
+
steps_count=data.get('steps_count'),
|
|
1032
|
+
icon=data.get('icon'),
|
|
1033
|
+
is_public=data.get('is_public'),
|
|
1034
|
+
is_featured=data.get('is_featured'),
|
|
1035
|
+
organization_id=data.get('organization_id'),
|
|
1036
|
+
folders=folders,
|
|
1037
|
+
due_date_passed=data.get('due_date_passed'),
|
|
1038
|
+
due_soon=data.get('due_soon'),
|
|
1039
|
+
status_label=data.get('status_label'),
|
|
1040
|
+
position=data.get('position'),
|
|
1041
|
+
deadline=data.get('deadline'),
|
|
1042
|
+
created_at=data.get('created_at'),
|
|
1043
|
+
starter_id=data.get('starter_id'),
|
|
1044
|
+
is_oneoff_task=data.get('is_oneoff_task'),
|
|
1045
|
+
owners=owners
|
|
1046
|
+
)
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
@dataclass
|
|
1050
|
+
class PaginationLinks:
|
|
1051
|
+
"""Pagination links data model"""
|
|
1052
|
+
next: Optional[str] = None
|
|
1053
|
+
prev: Optional[str] = None
|
|
1054
|
+
|
|
1055
|
+
@classmethod
|
|
1056
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'PaginationLinks':
|
|
1057
|
+
"""Create PaginationLinks instance from dictionary"""
|
|
1058
|
+
return cls(
|
|
1059
|
+
next=data.get('next'),
|
|
1060
|
+
prev=data.get('prev')
|
|
1061
|
+
)
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
@dataclass
|
|
1065
|
+
class PaginationMeta:
|
|
1066
|
+
"""Pagination metadata model"""
|
|
1067
|
+
total: int
|
|
1068
|
+
count: int
|
|
1069
|
+
per_page: int
|
|
1070
|
+
current_page: int
|
|
1071
|
+
total_pages: int
|
|
1072
|
+
links: Optional[PaginationLinks] = None
|
|
1073
|
+
|
|
1074
|
+
@classmethod
|
|
1075
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'PaginationMeta':
|
|
1076
|
+
"""Create PaginationMeta instance from dictionary"""
|
|
1077
|
+
links_data = data.get('links', {})
|
|
1078
|
+
links = PaginationLinks.from_dict(links_data) if links_data else None
|
|
1079
|
+
|
|
1080
|
+
return cls(
|
|
1081
|
+
total=data.get('total', 0),
|
|
1082
|
+
count=data.get('count', 0),
|
|
1083
|
+
per_page=data.get('per_page', 0),
|
|
1084
|
+
current_page=data.get('current_page', 1),
|
|
1085
|
+
total_pages=data.get('total_pages', 0),
|
|
1086
|
+
links=links
|
|
1087
|
+
)
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
@dataclass
|
|
1091
|
+
class OrganizationWorkingDays:
|
|
1092
|
+
"""Organization working days configuration"""
|
|
1093
|
+
Monday: Optional[Dict[str, Any]] = None
|
|
1094
|
+
Tuesday: Optional[Dict[str, Any]] = None
|
|
1095
|
+
Wednesday: Optional[Dict[str, Any]] = None
|
|
1096
|
+
Thursday: Optional[Dict[str, Any]] = None
|
|
1097
|
+
Friday: Optional[Dict[str, Any]] = None
|
|
1098
|
+
Saturday: Optional[Dict[str, Any]] = None
|
|
1099
|
+
Sunday: Optional[Dict[str, Any]] = None
|
|
1100
|
+
|
|
1101
|
+
@classmethod
|
|
1102
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'OrganizationWorkingDays':
|
|
1103
|
+
"""Create OrganizationWorkingDays instance from dictionary"""
|
|
1104
|
+
return cls(
|
|
1105
|
+
Monday=data.get('Monday'),
|
|
1106
|
+
Tuesday=data.get('Tuesday'),
|
|
1107
|
+
Wednesday=data.get('Wednesday'),
|
|
1108
|
+
Thursday=data.get('Thursday'),
|
|
1109
|
+
Friday=data.get('Friday'),
|
|
1110
|
+
Saturday=data.get('Saturday'),
|
|
1111
|
+
Sunday=data.get('Sunday')
|
|
1112
|
+
)
|
|
1113
|
+
|
|
1114
|
+
|
|
1115
|
+
@dataclass
|
|
1116
|
+
class OrganizationDefaultDeadline:
|
|
1117
|
+
"""Organization default deadline configuration"""
|
|
1118
|
+
type: str = "days"
|
|
1119
|
+
value: int = 5
|
|
1120
|
+
|
|
1121
|
+
@classmethod
|
|
1122
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'OrganizationDefaultDeadline':
|
|
1123
|
+
"""Create OrganizationDefaultDeadline instance from dictionary"""
|
|
1124
|
+
return cls(
|
|
1125
|
+
type=data.get('type', 'days'),
|
|
1126
|
+
value=data.get('value', 5)
|
|
1127
|
+
)
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
@dataclass
|
|
1131
|
+
class OrganizationAutoArchive:
|
|
1132
|
+
"""Organization auto archive configuration"""
|
|
1133
|
+
unit: str = "weeks"
|
|
1134
|
+
value: int = 52
|
|
1135
|
+
|
|
1136
|
+
@classmethod
|
|
1137
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'OrganizationAutoArchive':
|
|
1138
|
+
"""Create OrganizationAutoArchive instance from dictionary"""
|
|
1139
|
+
return cls(
|
|
1140
|
+
unit=data.get('unit', 'weeks'),
|
|
1141
|
+
value=data.get('value', 52)
|
|
1142
|
+
)
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
@dataclass
|
|
1146
|
+
class Organization:
|
|
1147
|
+
"""Organization data model"""
|
|
1148
|
+
id: str
|
|
1149
|
+
name: str
|
|
1150
|
+
industry: Optional[str] = None
|
|
1151
|
+
description: Optional[str] = None
|
|
1152
|
+
address1: Optional[str] = None
|
|
1153
|
+
address2: Optional[str] = None
|
|
1154
|
+
created_on: Optional[str] = None
|
|
1155
|
+
last_updated: Optional[str] = None
|
|
1156
|
+
live_support_enabled: int = 0
|
|
1157
|
+
org_logo: Optional[str] = None
|
|
1158
|
+
settings: Optional[str] = None
|
|
1159
|
+
country: Optional[str] = None
|
|
1160
|
+
state: Optional[str] = None
|
|
1161
|
+
city: Optional[str] = None
|
|
1162
|
+
zipcode: Optional[str] = None
|
|
1163
|
+
users_count: int = 0
|
|
1164
|
+
payment_state: Optional[str] = None
|
|
1165
|
+
team_size: Optional[List[int]] = None
|
|
1166
|
+
signup_survey: Optional[str] = None
|
|
1167
|
+
in_trial: bool = False
|
|
1168
|
+
analytics_enabled: bool = True
|
|
1169
|
+
limit_trial_features: bool = False
|
|
1170
|
+
real_time_billing: bool = True
|
|
1171
|
+
saml_enabled: bool = False
|
|
1172
|
+
saml_login_url: Optional[str] = None
|
|
1173
|
+
sso_default_role: Optional[str] = None
|
|
1174
|
+
preferred_trial_plan: Optional[str] = None
|
|
1175
|
+
google_analytics_id: Optional[str] = None
|
|
1176
|
+
mixpanel_token: Optional[str] = None
|
|
1177
|
+
plan_code: Optional[str] = None
|
|
1178
|
+
auto_join_signups: bool = False
|
|
1179
|
+
home_bg: Optional[str] = None
|
|
1180
|
+
guest_onboarding_snippet: Optional[str] = None
|
|
1181
|
+
maximum_group_assignment_limit: int = 0
|
|
1182
|
+
allow_user_invite: bool = True
|
|
1183
|
+
allow_manage_groups: bool = True
|
|
1184
|
+
working_days: Optional[OrganizationWorkingDays] = None
|
|
1185
|
+
deadline_setting: Optional[str] = None
|
|
1186
|
+
wyiwyg: bool = True
|
|
1187
|
+
cadence_days: Optional[List[str]] = None
|
|
1188
|
+
guest_cadence_days: Optional[List[str]] = None
|
|
1189
|
+
timezone: Optional[str] = None
|
|
1190
|
+
default_deadline: Optional[OrganizationDefaultDeadline] = None
|
|
1191
|
+
auto_archive: bool = False
|
|
1192
|
+
auto_complete_tasks: bool = True
|
|
1193
|
+
auto_complete_task_months: int = 18
|
|
1194
|
+
light_role_error_snippet: Optional[str] = None
|
|
1195
|
+
azure_cognitive_service: Optional[str] = None
|
|
1196
|
+
global_css: Optional[str] = None
|
|
1197
|
+
error_404_template: Optional[str] = None
|
|
1198
|
+
enable_custom_404_error: bool = False
|
|
1199
|
+
enable_custom_smtp: bool = False
|
|
1200
|
+
onboarding_template_id: Optional[str] = None
|
|
1201
|
+
enable_onboarding_template: bool = True
|
|
1202
|
+
disable_min_members_billing: bool = False
|
|
1203
|
+
enable_light_users_billing: bool = False
|
|
1204
|
+
webhook_date_field_format: str = "yyyy-MM-ddTHH:mm:ssZ"
|
|
1205
|
+
purpose: Optional[str] = None
|
|
1206
|
+
process_today: Optional[str] = None
|
|
1207
|
+
restrict_blueprint_permissions: bool = False
|
|
1208
|
+
auto_archive_processes_after: Optional[OrganizationAutoArchive] = None
|
|
1209
|
+
use_generative_ai: bool = True
|
|
1210
|
+
homepage_snippet: Optional[str] = None
|
|
1211
|
+
onboarding_snippet: Optional[str] = None
|
|
1212
|
+
disabled_on: Optional[str] = None
|
|
1213
|
+
last_accessed: Optional[str] = None
|
|
1214
|
+
user_role: Optional[str] = None
|
|
1215
|
+
|
|
1216
|
+
def __post_init__(self):
|
|
1217
|
+
"""Initialize empty lists if None"""
|
|
1218
|
+
if self.team_size is None:
|
|
1219
|
+
self.team_size = []
|
|
1220
|
+
if self.cadence_days is None:
|
|
1221
|
+
self.cadence_days = []
|
|
1222
|
+
if self.guest_cadence_days is None:
|
|
1223
|
+
self.guest_cadence_days = []
|
|
1224
|
+
|
|
1225
|
+
@classmethod
|
|
1226
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'Organization':
|
|
1227
|
+
"""Create Organization instance from dictionary"""
|
|
1228
|
+
working_days_data = data.get('working_days')
|
|
1229
|
+
working_days = OrganizationWorkingDays.from_dict(working_days_data) if working_days_data else None
|
|
1230
|
+
|
|
1231
|
+
default_deadline_data = data.get('default_deadline')
|
|
1232
|
+
default_deadline = OrganizationDefaultDeadline.from_dict(default_deadline_data) if default_deadline_data else None
|
|
1233
|
+
|
|
1234
|
+
auto_archive_processes_after_data = data.get('auto_archive_processes_after')
|
|
1235
|
+
auto_archive_processes_after = OrganizationAutoArchive.from_dict(auto_archive_processes_after_data) if auto_archive_processes_after_data else None
|
|
1236
|
+
|
|
1237
|
+
return cls(
|
|
1238
|
+
id=data.get('id', ''),
|
|
1239
|
+
name=data.get('name', ''),
|
|
1240
|
+
industry=data.get('industry'),
|
|
1241
|
+
description=data.get('description'),
|
|
1242
|
+
address1=data.get('address1'),
|
|
1243
|
+
address2=data.get('address2'),
|
|
1244
|
+
created_on=data.get('created_on'),
|
|
1245
|
+
last_updated=data.get('last_updated'),
|
|
1246
|
+
live_support_enabled=data.get('live_support_enabled', 0),
|
|
1247
|
+
org_logo=data.get('org_logo'),
|
|
1248
|
+
settings=data.get('settings'),
|
|
1249
|
+
country=data.get('country'),
|
|
1250
|
+
state=data.get('state'),
|
|
1251
|
+
city=data.get('city'),
|
|
1252
|
+
zipcode=data.get('zipcode'),
|
|
1253
|
+
users_count=data.get('users_count', 0),
|
|
1254
|
+
payment_state=data.get('payment_state'),
|
|
1255
|
+
team_size=data.get('team_size', []),
|
|
1256
|
+
signup_survey=data.get('signup_survey'),
|
|
1257
|
+
in_trial=data.get('in_trial', False),
|
|
1258
|
+
analytics_enabled=data.get('analytics_enabled', True),
|
|
1259
|
+
limit_trial_features=data.get('limit_trial_features', False),
|
|
1260
|
+
real_time_billing=data.get('real_time_billing', True),
|
|
1261
|
+
saml_enabled=data.get('saml_enabled', False),
|
|
1262
|
+
saml_login_url=data.get('saml_login_url'),
|
|
1263
|
+
sso_default_role=data.get('sso_default_role'),
|
|
1264
|
+
preferred_trial_plan=data.get('preferred_trial_plan'),
|
|
1265
|
+
google_analytics_id=data.get('google_analytics_id'),
|
|
1266
|
+
mixpanel_token=data.get('mixpanel_token'),
|
|
1267
|
+
plan_code=data.get('plan_code'),
|
|
1268
|
+
auto_join_signups=data.get('auto_join_signups', False),
|
|
1269
|
+
home_bg=data.get('home_bg'),
|
|
1270
|
+
guest_onboarding_snippet=data.get('guest_onboarding_snippet'),
|
|
1271
|
+
maximum_group_assignment_limit=data.get('maximum_group_assignment_limit', 0),
|
|
1272
|
+
allow_user_invite=data.get('allow_user_invite', True),
|
|
1273
|
+
allow_manage_groups=data.get('allow_manage_groups', True),
|
|
1274
|
+
working_days=working_days,
|
|
1275
|
+
deadline_setting=data.get('deadline_setting'),
|
|
1276
|
+
wyiwyg=data.get('wyiwyg', True),
|
|
1277
|
+
cadence_days=data.get('cadence_days', []),
|
|
1278
|
+
guest_cadence_days=data.get('guest_cadence_days', []),
|
|
1279
|
+
timezone=data.get('timezone'),
|
|
1280
|
+
default_deadline=default_deadline,
|
|
1281
|
+
auto_archive=data.get('auto_archive', False),
|
|
1282
|
+
auto_complete_tasks=data.get('auto_complete_tasks', True),
|
|
1283
|
+
auto_complete_task_months=data.get('auto_complete_task_months', 18),
|
|
1284
|
+
light_role_error_snippet=data.get('light_role_error_snippet'),
|
|
1285
|
+
azure_cognitive_service=data.get('azure_cognitive_service'),
|
|
1286
|
+
global_css=data.get('global_css'),
|
|
1287
|
+
error_404_template=data.get('error_404_template'),
|
|
1288
|
+
enable_custom_404_error=data.get('enable_custom_404_error', False),
|
|
1289
|
+
enable_custom_smtp=data.get('enable_custom_smtp', False),
|
|
1290
|
+
onboarding_template_id=data.get('onboarding_template_id'),
|
|
1291
|
+
enable_onboarding_template=data.get('enable_onboarding_template', True),
|
|
1292
|
+
disable_min_members_billing=data.get('disable_min_members_billing', False),
|
|
1293
|
+
enable_light_users_billing=data.get('enable_light_users_billing', False),
|
|
1294
|
+
webhook_date_field_format=data.get('webhook_date_field_format', 'yyyy-MM-ddTHH:mm:ssZ'),
|
|
1295
|
+
purpose=data.get('purpose'),
|
|
1296
|
+
process_today=data.get('process_today'),
|
|
1297
|
+
restrict_blueprint_permissions=data.get('restrict_blueprint_permissions', False),
|
|
1298
|
+
auto_archive_processes_after=auto_archive_processes_after,
|
|
1299
|
+
use_generative_ai=data.get('use_generative_ai', True),
|
|
1300
|
+
homepage_snippet=data.get('homepage_snippet'),
|
|
1301
|
+
onboarding_snippet=data.get('onboarding_snippet'),
|
|
1302
|
+
disabled_on=data.get('disabled_on'),
|
|
1303
|
+
last_accessed=data.get('last_accessed'),
|
|
1304
|
+
user_role=data.get('user_role')
|
|
1305
|
+
)
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
@dataclass
|
|
1309
|
+
class OrganizationsList:
|
|
1310
|
+
"""Organizations list response with pagination"""
|
|
1311
|
+
data: List[Organization]
|
|
1312
|
+
meta: PaginationMeta
|
|
1313
|
+
|
|
1314
|
+
@classmethod
|
|
1315
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'OrganizationsList':
|
|
1316
|
+
"""Create OrganizationsList instance from dictionary"""
|
|
1317
|
+
organizations_data = data.get('data', [])
|
|
1318
|
+
organizations = [Organization.from_dict(org_data) for org_data in organizations_data]
|
|
1319
|
+
|
|
1320
|
+
meta_data = data.get('meta', {})
|
|
1321
|
+
pagination_meta = meta_data.get('pagination', {})
|
|
1322
|
+
meta = PaginationMeta.from_dict(pagination_meta)
|
|
1323
|
+
|
|
1324
|
+
return cls(
|
|
1325
|
+
data=organizations,
|
|
1326
|
+
meta=meta
|
|
1327
|
+
)
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
@dataclass
|
|
1331
|
+
class TemplatesList:
|
|
1332
|
+
"""Templates list response with pagination"""
|
|
1333
|
+
data: List[Template]
|
|
1334
|
+
meta: PaginationMeta
|
|
1335
|
+
|
|
1336
|
+
@classmethod
|
|
1337
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'TemplatesList':
|
|
1338
|
+
"""Create TemplatesList instance from dictionary"""
|
|
1339
|
+
templates_data = data.get('data', [])
|
|
1340
|
+
templates = [Template.from_dict(template_data) for template_data in templates_data]
|
|
1341
|
+
|
|
1342
|
+
meta_data = data.get('meta', {})
|
|
1343
|
+
pagination_meta = meta_data.get('pagination', {})
|
|
1344
|
+
meta = PaginationMeta.from_dict(pagination_meta)
|
|
1345
|
+
|
|
1346
|
+
return cls(
|
|
1347
|
+
data=templates,
|
|
1348
|
+
meta=meta
|
|
1349
|
+
)
|
|
1350
|
+
|
|
1351
|
+
|
|
1352
|
+
@dataclass
|
|
1353
|
+
class UsersList:
|
|
1354
|
+
"""Users list response with pagination"""
|
|
1355
|
+
data: List[User]
|
|
1356
|
+
meta: PaginationMeta
|
|
1357
|
+
|
|
1358
|
+
@classmethod
|
|
1359
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'UsersList':
|
|
1360
|
+
"""Create UsersList instance from dictionary"""
|
|
1361
|
+
users_data = data.get('data', [])
|
|
1362
|
+
users = [User.from_dict(user_data) for user_data in users_data]
|
|
1363
|
+
|
|
1364
|
+
meta_data = data.get('meta', {})
|
|
1365
|
+
pagination_meta = meta_data.get('pagination', {})
|
|
1366
|
+
meta = PaginationMeta.from_dict(pagination_meta)
|
|
1367
|
+
|
|
1368
|
+
return cls(
|
|
1369
|
+
data=users,
|
|
1370
|
+
meta=meta
|
|
1371
|
+
)
|
|
1372
|
+
|
|
1373
|
+
|
|
1374
|
+
@dataclass
|
|
1375
|
+
class GuestsList:
|
|
1376
|
+
"""Guests list response with pagination"""
|
|
1377
|
+
data: List[Guest]
|
|
1378
|
+
meta: PaginationMeta
|
|
1379
|
+
|
|
1380
|
+
@classmethod
|
|
1381
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'GuestsList':
|
|
1382
|
+
"""Create GuestsList instance from dictionary"""
|
|
1383
|
+
guests_data = data.get('data', [])
|
|
1384
|
+
guests = [Guest.from_dict(guest_data) for guest_data in guests_data]
|
|
1385
|
+
|
|
1386
|
+
meta_data = data.get('meta', {})
|
|
1387
|
+
pagination_meta = meta_data.get('pagination', {})
|
|
1388
|
+
meta = PaginationMeta.from_dict(pagination_meta)
|
|
1389
|
+
|
|
1390
|
+
return cls(
|
|
1391
|
+
data=guests,
|
|
1392
|
+
meta=meta
|
|
1393
|
+
)
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
@dataclass
|
|
1397
|
+
class TasksList:
|
|
1398
|
+
"""Tasks list response with pagination"""
|
|
1399
|
+
data: List[Task]
|
|
1400
|
+
meta: PaginationMeta
|
|
1401
|
+
|
|
1402
|
+
@classmethod
|
|
1403
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'TasksList':
|
|
1404
|
+
"""Create TasksList instance from dictionary"""
|
|
1405
|
+
tasks_data = data.get('data', [])
|
|
1406
|
+
tasks = [Task.from_dict(task_data) for task_data in tasks_data]
|
|
1407
|
+
|
|
1408
|
+
meta_data = data.get('meta', {})
|
|
1409
|
+
pagination_meta = meta_data.get('pagination', {})
|
|
1410
|
+
meta = PaginationMeta.from_dict(pagination_meta)
|
|
1411
|
+
|
|
1412
|
+
return cls(
|
|
1413
|
+
data=tasks,
|
|
1414
|
+
meta=meta
|
|
1415
|
+
)
|
|
1416
|
+
|
|
1417
|
+
|
|
1418
|
+
@dataclass
|
|
1419
|
+
class RunsList:
|
|
1420
|
+
"""Runs (Processes) list response with pagination"""
|
|
1421
|
+
data: List[Run]
|
|
1422
|
+
meta: PaginationMeta
|
|
1423
|
+
|
|
1424
|
+
@classmethod
|
|
1425
|
+
def from_dict(cls, data: Dict[str, Any]) -> 'RunsList':
|
|
1426
|
+
"""Create RunsList instance from dictionary"""
|
|
1427
|
+
runs_data = data.get('data', [])
|
|
1428
|
+
runs = [Run.from_dict(run_data) for run_data in runs_data]
|
|
1429
|
+
|
|
1430
|
+
meta_data = data.get('meta', {})
|
|
1431
|
+
pagination_meta = meta_data.get('pagination', {})
|
|
1432
|
+
meta = PaginationMeta.from_dict(pagination_meta)
|
|
1433
|
+
|
|
1434
|
+
return cls(
|
|
1435
|
+
data=runs,
|
|
1436
|
+
meta=meta
|
|
1437
|
+
)
|
|
1438
|
+
|
|
1439
|
+
|
|
1440
|
+
@dataclass
|
|
1441
|
+
class SearchResultsList:
|
|
1442
|
+
"""Search results list response with pagination"""
|
|
1443
|
+
data: List[SearchResult]
|
|
1444
|
+
meta: PaginationMeta
|
|
1445
|
+
search_type: str
|
|
1446
|
+
|
|
1447
|
+
@classmethod
|
|
1448
|
+
def from_dict(cls, data: Dict[str, Any], search_type: str) -> 'SearchResultsList':
|
|
1449
|
+
"""Create SearchResultsList instance from dictionary"""
|
|
1450
|
+
# Search response has results nested under the search type key
|
|
1451
|
+
type_data = data.get(search_type, {})
|
|
1452
|
+
results_data = type_data.get('data', [])
|
|
1453
|
+
results = [SearchResult.from_dict(result_data, search_type) for result_data in results_data]
|
|
1454
|
+
|
|
1455
|
+
# Get pagination from the nested type data
|
|
1456
|
+
meta_data = type_data.get('meta', {})
|
|
1457
|
+
pagination_meta = meta_data.get('pagination', {})
|
|
1458
|
+
meta = PaginationMeta.from_dict(pagination_meta)
|
|
1459
|
+
|
|
1460
|
+
return cls(
|
|
1461
|
+
data=results,
|
|
1462
|
+
meta=meta,
|
|
1463
|
+
search_type=search_type
|
|
1464
|
+
)
|