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.
Files changed (52) hide show
  1. tallyfy/__init__.py +27 -0
  2. tallyfy/__pycache__/__init__.cpython-310.pyc +0 -0
  3. tallyfy/__pycache__/core.cpython-310.pyc +0 -0
  4. tallyfy/__pycache__/form_fields_management.cpython-310.pyc +0 -0
  5. tallyfy/__pycache__/models.cpython-310.pyc +0 -0
  6. tallyfy/__pycache__/task_management.cpython-310.pyc +0 -0
  7. tallyfy/__pycache__/template_management.cpython-310.pyc +0 -0
  8. tallyfy/__pycache__/user_management.cpython-310.pyc +0 -0
  9. tallyfy/core.py +361 -0
  10. tallyfy/form_fields_management/__init__.py +70 -0
  11. tallyfy/form_fields_management/__pycache__/__init__.cpython-310.pyc +0 -0
  12. tallyfy/form_fields_management/__pycache__/base.cpython-310.pyc +0 -0
  13. tallyfy/form_fields_management/__pycache__/crud_operations.cpython-310.pyc +0 -0
  14. tallyfy/form_fields_management/__pycache__/options_management.cpython-310.pyc +0 -0
  15. tallyfy/form_fields_management/__pycache__/suggestions.cpython-310.pyc +0 -0
  16. tallyfy/form_fields_management/base.py +109 -0
  17. tallyfy/form_fields_management/crud_operations.py +234 -0
  18. tallyfy/form_fields_management/options_management.py +222 -0
  19. tallyfy/form_fields_management/suggestions.py +411 -0
  20. tallyfy/models.py +1464 -0
  21. tallyfy/organization_management/__init__.py +26 -0
  22. tallyfy/organization_management/base.py +76 -0
  23. tallyfy/organization_management/retrieval.py +39 -0
  24. tallyfy/task_management/__init__.py +81 -0
  25. tallyfy/task_management/__pycache__/__init__.cpython-310.pyc +0 -0
  26. tallyfy/task_management/__pycache__/base.cpython-310.pyc +0 -0
  27. tallyfy/task_management/__pycache__/creation.cpython-310.pyc +0 -0
  28. tallyfy/task_management/__pycache__/retrieval.cpython-310.pyc +0 -0
  29. tallyfy/task_management/__pycache__/search.cpython-310.pyc +0 -0
  30. tallyfy/task_management/base.py +125 -0
  31. tallyfy/task_management/creation.py +221 -0
  32. tallyfy/task_management/retrieval.py +252 -0
  33. tallyfy/task_management/search.py +198 -0
  34. tallyfy/template_management/__init__.py +85 -0
  35. tallyfy/template_management/analysis.py +1099 -0
  36. tallyfy/template_management/automation.py +469 -0
  37. tallyfy/template_management/base.py +56 -0
  38. tallyfy/template_management/basic_operations.py +479 -0
  39. tallyfy/template_management/health_assessment.py +793 -0
  40. tallyfy/user_management/__init__.py +70 -0
  41. tallyfy/user_management/__pycache__/__init__.cpython-310.pyc +0 -0
  42. tallyfy/user_management/__pycache__/base.cpython-310.pyc +0 -0
  43. tallyfy/user_management/__pycache__/invitation.cpython-310.pyc +0 -0
  44. tallyfy/user_management/__pycache__/retrieval.cpython-310.pyc +0 -0
  45. tallyfy/user_management/base.py +146 -0
  46. tallyfy/user_management/invitation.py +286 -0
  47. tallyfy/user_management/retrieval.py +381 -0
  48. tallyfy-1.0.16.dist-info/METADATA +742 -0
  49. tallyfy-1.0.16.dist-info/RECORD +52 -0
  50. tallyfy-1.0.16.dist-info/WHEEL +5 -0
  51. tallyfy-1.0.16.dist-info/licenses/LICENSE +21 -0
  52. tallyfy-1.0.16.dist-info/top_level.txt +1 -0
@@ -0,0 +1,234 @@
1
+ """
2
+ CRUD operations for form field management
3
+ """
4
+
5
+ from typing import Dict, Any, Optional
6
+ from .base import FormFieldManagerBase
7
+ from ..models import Capture, Step, TallyfyError
8
+
9
+
10
+ class FormFieldCRUD(FormFieldManagerBase):
11
+ """Handles basic CRUD operations for form fields"""
12
+
13
+ def add_form_field_to_step(self, org_id: str, template_id: str, step_id: str, field_data: Dict[str, Any]) -> Optional[Capture]:
14
+ """
15
+ Add form fields (text, dropdown, date, etc.) to a step.
16
+
17
+ Args:
18
+ org_id: Organization ID
19
+ template_id: Template ID
20
+ step_id: Step ID
21
+ field_data: Form field creation data including field_type, label, required, etc.
22
+
23
+ Returns:
24
+ Created Capture object or None if creation failed
25
+
26
+ Raises:
27
+ TallyfyError: If the request fails
28
+ """
29
+ self._validate_org_id(org_id)
30
+ self._validate_template_id(template_id)
31
+ self._validate_step_id(step_id)
32
+
33
+ try:
34
+ endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}/captures"
35
+
36
+ # Validate required fields
37
+ required_fields = ['field_type', 'label']
38
+ for field in required_fields:
39
+ if field not in field_data:
40
+ raise ValueError(f"Missing required field: {field}")
41
+
42
+ # Set defaults for optional fields
43
+ capture_data = {
44
+ 'field_type': field_data['field_type'],
45
+ 'label': field_data['label'],
46
+ 'required': field_data.get('required', True),
47
+ 'position': field_data.get('position', 1)
48
+ }
49
+
50
+ # Add optional fields if provided
51
+ optional_fields = ['guidance', 'options', 'default_value', 'default_value_enabled']
52
+ for field in optional_fields:
53
+ if field in field_data:
54
+ capture_data[field] = field_data[field]
55
+
56
+ response_data = self.sdk._make_request('POST', endpoint, data=capture_data)
57
+
58
+ extracted_data = self._extract_data(response_data)
59
+ if extracted_data:
60
+ return Capture.from_dict(extracted_data)
61
+ else:
62
+ self.sdk.logger.warning("Unexpected response format for form field creation")
63
+ return None
64
+
65
+ except TallyfyError:
66
+ raise
67
+ except Exception as e:
68
+ self._handle_api_error(e, "add form field to step", org_id=org_id, template_id=template_id, step_id=step_id)
69
+
70
+ def update_form_field(self, org_id: str, template_id: str, step_id: str, field_id: str, **kwargs) -> Optional[Capture]:
71
+ """
72
+ Update form field properties, validation, options.
73
+
74
+ Args:
75
+ org_id: Organization ID
76
+ template_id: Template ID
77
+ step_id: Step ID
78
+ field_id: Form field ID
79
+ **kwargs: Form field properties to update
80
+
81
+ Returns:
82
+ Updated Capture object or None if update failed
83
+
84
+ Raises:
85
+ TallyfyError: If the request fails
86
+ """
87
+ self._validate_org_id(org_id)
88
+ self._validate_template_id(template_id)
89
+ self._validate_step_id(step_id)
90
+ self._validate_field_id(field_id)
91
+
92
+ try:
93
+ endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}/captures/{field_id}"
94
+
95
+ # Build update data from kwargs
96
+ update_data = {}
97
+ allowed_fields = [
98
+ 'field_type', 'label', 'guidance', 'position', 'required',
99
+ 'options', 'default_value', 'default_value_enabled'
100
+ ]
101
+
102
+ for field, value in kwargs.items():
103
+ if field in allowed_fields:
104
+ update_data[field] = value
105
+ else:
106
+ self.sdk.logger.warning(f"Ignoring unknown form field: {field}")
107
+
108
+ if not update_data:
109
+ raise ValueError("No valid form field properties provided for update")
110
+
111
+ response_data = self.sdk._make_request('PUT', endpoint, data=update_data)
112
+
113
+ extracted_data = self._extract_data(response_data)
114
+ if extracted_data:
115
+ return Capture.from_dict(extracted_data)
116
+ else:
117
+ self.sdk.logger.warning("Unexpected response format for form field update")
118
+ return None
119
+
120
+ except TallyfyError:
121
+ raise
122
+ except Exception as e:
123
+ self._handle_api_error(e, "update form field", org_id=org_id, template_id=template_id, step_id=step_id, field_id=field_id)
124
+
125
+ def move_form_field(self, org_id: str, template_id: str, from_step: str, field_id: str, to_step: str, position: int = 1) -> bool:
126
+ """
127
+ Move form field between steps.
128
+
129
+ Args:
130
+ org_id: Organization ID
131
+ template_id: Template ID
132
+ from_step: Source step ID
133
+ field_id: Form field ID to move
134
+ to_step: Target step ID
135
+ position: Position in target step (default: 1)
136
+
137
+ Returns:
138
+ True if move was successful
139
+
140
+ Raises:
141
+ TallyfyError: If the request fails
142
+ """
143
+ self._validate_org_id(org_id)
144
+ self._validate_template_id(template_id)
145
+ self._validate_step_id(from_step)
146
+ self._validate_field_id(field_id)
147
+ self._validate_step_id(to_step)
148
+
149
+ try:
150
+ endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{from_step}/captures/{field_id}/move"
151
+
152
+ move_data = {
153
+ 'to_step_id': to_step,
154
+ 'position': position
155
+ }
156
+
157
+ response_data = self.sdk._make_request('POST', endpoint, data=move_data)
158
+
159
+ # Check if move was successful
160
+ return isinstance(response_data, dict) and response_data.get('success', False)
161
+
162
+ except TallyfyError:
163
+ raise
164
+ except Exception as e:
165
+ self._handle_api_error(e, "move form field", org_id=org_id, template_id=template_id, from_step=from_step, field_id=field_id, to_step=to_step)
166
+
167
+ def delete_form_field(self, org_id: str, template_id: str, step_id: str, field_id: str) -> bool:
168
+ """
169
+ Delete a form field from a step.
170
+
171
+ Args:
172
+ org_id: Organization ID
173
+ template_id: Template ID
174
+ step_id: Step ID
175
+ field_id: Form field ID
176
+
177
+ Returns:
178
+ True if deletion was successful
179
+
180
+ Raises:
181
+ TallyfyError: If the request fails
182
+ """
183
+ self._validate_org_id(org_id)
184
+ self._validate_template_id(template_id)
185
+ self._validate_step_id(step_id)
186
+ self._validate_field_id(field_id)
187
+
188
+ try:
189
+ endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}/captures/{field_id}"
190
+
191
+ response_data = self.sdk._make_request('DELETE', endpoint)
192
+
193
+ # Check if deletion was successful
194
+ return isinstance(response_data, dict) and response_data.get('success', False)
195
+
196
+ except TallyfyError:
197
+ raise
198
+ except Exception as e:
199
+ self._handle_api_error(e, "delete form field", org_id=org_id, template_id=template_id, step_id=step_id, field_id=field_id)
200
+
201
+ def get_step(self, org_id: str, template_id: str, step_id: str) -> Optional[Step]:
202
+ """
203
+ Get a specific step with its details.
204
+
205
+ Args:
206
+ org_id: Organization ID
207
+ template_id: Template ID
208
+ step_id: Step ID
209
+
210
+ Returns:
211
+ Step object or None if not found
212
+
213
+ Raises:
214
+ TallyfyError: If the request fails
215
+ """
216
+ self._validate_org_id(org_id)
217
+ self._validate_template_id(template_id)
218
+ self._validate_step_id(step_id)
219
+
220
+ try:
221
+ endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}"
222
+ response_data = self.sdk._make_request('GET', endpoint)
223
+
224
+ extracted_data = self._extract_data(response_data)
225
+ if extracted_data:
226
+ return Step.from_dict(extracted_data)
227
+ else:
228
+ self.sdk.logger.warning("Unexpected response format for step")
229
+ return None
230
+
231
+ except TallyfyError:
232
+ raise
233
+ except Exception as e:
234
+ self._handle_api_error(e, "get step", org_id=org_id, template_id=template_id, step_id=step_id)
@@ -0,0 +1,222 @@
1
+ """
2
+ Dropdown options management for form fields
3
+ """
4
+
5
+ from typing import List, Dict, Any, Optional
6
+ from .base import FormFieldManagerBase
7
+ from ..models import TallyfyError
8
+
9
+
10
+ class FormFieldOptions(FormFieldManagerBase):
11
+ """Handles dropdown options management for form fields"""
12
+
13
+ def get_dropdown_options(self, org_id: str, template_id: str, step_id: str, field_id: str) -> List[str]:
14
+ """
15
+ Get current dropdown options for analysis.
16
+
17
+ Args:
18
+ org_id: Organization ID
19
+ template_id: Template ID
20
+ step_id: Step ID
21
+ field_id: Form field ID
22
+
23
+ Returns:
24
+ List of dropdown option strings
25
+
26
+ Raises:
27
+ TallyfyError: If the request fails
28
+ """
29
+ self._validate_org_id(org_id)
30
+ self._validate_template_id(template_id)
31
+ self._validate_step_id(step_id)
32
+ self._validate_field_id(field_id)
33
+
34
+ try:
35
+ endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}/captures/{field_id}"
36
+
37
+ response_data = self.sdk._make_request('GET', endpoint)
38
+
39
+ extracted_data = self._extract_data(response_data)
40
+ if extracted_data:
41
+ options = extracted_data.get('options', [])
42
+
43
+ # Extract option values/labels
44
+ if isinstance(options, list):
45
+ return [
46
+ opt.get('label', opt.get('value', str(opt))) if isinstance(opt, dict) else str(opt)
47
+ for opt in options
48
+ ]
49
+ else:
50
+ return []
51
+ else:
52
+ self.sdk.logger.warning("Unexpected response format for form field options")
53
+ return []
54
+
55
+ except TallyfyError:
56
+ raise
57
+ except Exception as e:
58
+ self._handle_api_error(e, "get dropdown options", org_id=org_id, template_id=template_id, step_id=step_id, field_id=field_id)
59
+
60
+ def update_dropdown_options(self, org_id: str, template_id: str, step_id: str, field_id: str, options: List[str]) -> bool:
61
+ """
62
+ Update dropdown options (for external data integration).
63
+
64
+ Args:
65
+ org_id: Organization ID
66
+ template_id: Template ID
67
+ step_id: Step ID
68
+ field_id: Form field ID
69
+ options: List of new option strings
70
+
71
+ Returns:
72
+ True if update was successful
73
+
74
+ Raises:
75
+ TallyfyError: If the request fails
76
+ """
77
+ self._validate_org_id(org_id)
78
+ self._validate_template_id(template_id)
79
+ self._validate_step_id(step_id)
80
+ self._validate_field_id(field_id)
81
+
82
+ try:
83
+ # Format options for API
84
+ formatted_options = []
85
+ for i, option in enumerate(options):
86
+ if isinstance(option, str):
87
+ formatted_options.append({
88
+ 'value': option.lower().replace(' ', '_'),
89
+ 'label': option,
90
+ 'position': i + 1
91
+ })
92
+ elif isinstance(option, dict):
93
+ formatted_options.append(option)
94
+ else:
95
+ formatted_options.append({
96
+ 'value': str(option),
97
+ 'label': str(option),
98
+ 'position': i + 1
99
+ })
100
+
101
+ # Update the field with new options using CRUD operations
102
+ # We need to import FormFieldCRUD here to avoid circular imports
103
+ from .crud_operations import FormFieldCRUD
104
+ crud = FormFieldCRUD(self.sdk)
105
+
106
+ updated_capture = crud.update_form_field(
107
+ org_id, template_id, step_id, field_id,
108
+ options=formatted_options
109
+ )
110
+
111
+ return updated_capture is not None
112
+
113
+ except TallyfyError:
114
+ raise
115
+ except Exception as e:
116
+ self._handle_api_error(e, "update dropdown options", org_id=org_id, template_id=template_id, step_id=step_id, field_id=field_id)
117
+
118
+ def add_dropdown_option(self, org_id: str, template_id: str, step_id: str, field_id: str, new_option: str, position: Optional[int] = None) -> bool:
119
+ """
120
+ Add a single new option to an existing dropdown field.
121
+
122
+ Args:
123
+ org_id: Organization ID
124
+ template_id: Template ID
125
+ step_id: Step ID
126
+ field_id: Form field ID
127
+ new_option: New option to add
128
+ position: Position to insert the option (None = append to end)
129
+
130
+ Returns:
131
+ True if addition was successful
132
+
133
+ Raises:
134
+ TallyfyError: If the request fails
135
+ """
136
+ try:
137
+ # Get current options
138
+ current_options = self.get_dropdown_options(org_id, template_id, step_id, field_id)
139
+
140
+ # Add new option at specified position or end
141
+ if position is not None and 0 <= position <= len(current_options):
142
+ current_options.insert(position, new_option)
143
+ else:
144
+ current_options.append(new_option)
145
+
146
+ # Update with new options list
147
+ return self.update_dropdown_options(org_id, template_id, step_id, field_id, current_options)
148
+
149
+ except TallyfyError:
150
+ raise
151
+ except Exception as e:
152
+ self._handle_api_error(e, "add dropdown option", org_id=org_id, template_id=template_id, step_id=step_id, field_id=field_id)
153
+
154
+ def remove_dropdown_option(self, org_id: str, template_id: str, step_id: str, field_id: str, option_to_remove: str) -> bool:
155
+ """
156
+ Remove a specific option from a dropdown field.
157
+
158
+ Args:
159
+ org_id: Organization ID
160
+ template_id: Template ID
161
+ step_id: Step ID
162
+ field_id: Form field ID
163
+ option_to_remove: Option to remove
164
+
165
+ Returns:
166
+ True if removal was successful
167
+
168
+ Raises:
169
+ TallyfyError: If the request fails
170
+ """
171
+ try:
172
+ # Get current options
173
+ current_options = self.get_dropdown_options(org_id, template_id, step_id, field_id)
174
+
175
+ # Remove the specified option if it exists
176
+ if option_to_remove in current_options:
177
+ current_options.remove(option_to_remove)
178
+
179
+ # Update with modified options list
180
+ return self.update_dropdown_options(org_id, template_id, step_id, field_id, current_options)
181
+ else:
182
+ self.sdk.logger.warning(f"Option '{option_to_remove}' not found in dropdown field {field_id}")
183
+ return False
184
+
185
+ except TallyfyError:
186
+ raise
187
+ except Exception as e:
188
+ self._handle_api_error(e, "remove dropdown option", org_id=org_id, template_id=template_id, step_id=step_id, field_id=field_id)
189
+
190
+ def reorder_dropdown_options(self, org_id: str, template_id: str, step_id: str, field_id: str, ordered_options: List[str]) -> bool:
191
+ """
192
+ Reorder dropdown options to match the provided list.
193
+
194
+ Args:
195
+ org_id: Organization ID
196
+ template_id: Template ID
197
+ step_id: Step ID
198
+ field_id: Form field ID
199
+ ordered_options: List of options in desired order
200
+
201
+ Returns:
202
+ True if reordering was successful
203
+
204
+ Raises:
205
+ TallyfyError: If the request fails
206
+ """
207
+ try:
208
+ # Get current options to validate
209
+ current_options = self.get_dropdown_options(org_id, template_id, step_id, field_id)
210
+
211
+ # Validate that all provided options exist in current options
212
+ missing_options = set(ordered_options) - set(current_options)
213
+ if missing_options:
214
+ raise ValueError(f"Cannot reorder: options not found in field: {missing_options}")
215
+
216
+ # Update with reordered options
217
+ return self.update_dropdown_options(org_id, template_id, step_id, field_id, ordered_options)
218
+
219
+ except TallyfyError:
220
+ raise
221
+ except Exception as e:
222
+ self._handle_api_error(e, "reorder dropdown options", org_id=org_id, template_id=template_id, step_id=step_id, field_id=field_id)