brynq-sdk-zenegy 1.3.3__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 (33) hide show
  1. brynq_sdk_zenegy/__init__.py +23 -0
  2. brynq_sdk_zenegy/absence.py +100 -0
  3. brynq_sdk_zenegy/companies.py +43 -0
  4. brynq_sdk_zenegy/cost_center.py +80 -0
  5. brynq_sdk_zenegy/departments.py +77 -0
  6. brynq_sdk_zenegy/employee_documents.py +40 -0
  7. brynq_sdk_zenegy/employees.py +301 -0
  8. brynq_sdk_zenegy/global_value_sets.py +260 -0
  9. brynq_sdk_zenegy/global_values.py +265 -0
  10. brynq_sdk_zenegy/paychecks.py +119 -0
  11. brynq_sdk_zenegy/payroll.py +117 -0
  12. brynq_sdk_zenegy/payslips.py +43 -0
  13. brynq_sdk_zenegy/pensions.py +118 -0
  14. brynq_sdk_zenegy/schemas/__init__.py +30 -0
  15. brynq_sdk_zenegy/schemas/absences.py +393 -0
  16. brynq_sdk_zenegy/schemas/companies.py +42 -0
  17. brynq_sdk_zenegy/schemas/company_cost_centers.py +48 -0
  18. brynq_sdk_zenegy/schemas/company_departments.py +147 -0
  19. brynq_sdk_zenegy/schemas/employee_documents.py +30 -0
  20. brynq_sdk_zenegy/schemas/employee_pay_checks.py +169 -0
  21. brynq_sdk_zenegy/schemas/employee_pensions.py +140 -0
  22. brynq_sdk_zenegy/schemas/employees.py +2372 -0
  23. brynq_sdk_zenegy/schemas/global_value_sets.py +185 -0
  24. brynq_sdk_zenegy/schemas/global_values.py +433 -0
  25. brynq_sdk_zenegy/schemas/payrolls.py +134 -0
  26. brynq_sdk_zenegy/schemas/payslips.py +32 -0
  27. brynq_sdk_zenegy/schemas/supplements_and_deductions_rates.py +189 -0
  28. brynq_sdk_zenegy/supplements_and_deductions_rates.py +71 -0
  29. brynq_sdk_zenegy/zenegy.py +221 -0
  30. brynq_sdk_zenegy-1.3.3.dist-info/METADATA +16 -0
  31. brynq_sdk_zenegy-1.3.3.dist-info/RECORD +33 -0
  32. brynq_sdk_zenegy-1.3.3.dist-info/WHEEL +5 -0
  33. brynq_sdk_zenegy-1.3.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,260 @@
1
+ from .schemas.global_value_sets import GlobalValueSetsGet, GlobalValueSetCreate, GlobalValueSetUpdate, GlobalValueSetEmployeeAssignment, GlobalValueSetEmployeeAssignmentResponse, RemoveGlobalValuesFromSetRequest, GetAssignedEmployeesRequest, AssignedEmployeesGet, AddCompanyGlobalValueRequest, CompanyGlobalValuesGet
2
+ from typing import Tuple, Dict, Any, List
3
+ import pandas as pd
4
+ from brynq_sdk_functions import Functions
5
+ import requests
6
+ from uuid import UUID
7
+
8
+ class GlobalValueSets:
9
+ """
10
+ Handles all global value sets-related operations in Zenegy API
11
+ """
12
+ def __init__(self, zenegy):
13
+ """
14
+ Initialize the GlobalValueSets class.
15
+
16
+ Args:
17
+ zenegy: The Zenegy instance to use for API calls
18
+ """
19
+ self.zenegy = zenegy
20
+ self.endpoint = f"api/companies/{self.zenegy.company_uid}/global-value-sets"
21
+
22
+ def get(self) -> Tuple[pd.DataFrame, pd.DataFrame]:
23
+ """
24
+ GetGlobalValueSetsPerCompanyAsync
25
+ Returns:
26
+ Tuple of (valid_data, invalid_data) DataFrames with global value sets information
27
+ """
28
+ try:
29
+ content = self.zenegy.get(endpoint=self.endpoint)
30
+
31
+ df = pd.json_normalize(
32
+ content,
33
+ sep='__'
34
+ )
35
+ if df.empty:
36
+ return pd.DataFrame(), pd.DataFrame()
37
+
38
+ # Validate against schema
39
+ valid_data, invalid_data = Functions.validate_data(df, GlobalValueSetsGet)
40
+
41
+ return valid_data, invalid_data
42
+ except Exception as e:
43
+ raise Exception(f"Failed to retrieve global value sets: {str(e)}") from e
44
+
45
+ def get_by_id(self, global_value_set_uid: UUID) -> Tuple[pd.DataFrame, pd.DataFrame]:
46
+ """
47
+ GetGlobalValueSetByIdAsync
48
+ Args:
49
+ global_value_set_uid (UUID): The global value set UID to retrieve
50
+ Returns:
51
+ Tuple of (valid_data, invalid_data) DataFrames with global value set information
52
+ """
53
+ try:
54
+ endpoint = f"{self.endpoint}/{global_value_set_uid}"
55
+ content = self.zenegy.get(endpoint=endpoint)
56
+
57
+ # Normalize the data
58
+ df = pd.json_normalize(
59
+ [content], # Wrap in list since it's a single object
60
+ sep='__'
61
+ )
62
+
63
+ if df.empty:
64
+ return pd.DataFrame(), pd.DataFrame()
65
+
66
+ # Validate data using schema
67
+ valid_data, invalid_data = Functions.validate_data(df, GlobalValueSetsGet)
68
+ return valid_data, invalid_data
69
+ except Exception as e:
70
+ raise Exception(f"Failed to retrieve global value set by ID: {str(e)}") from e
71
+
72
+ def get_assigned_employees(self, global_value_set_uid: UUID, filters: Dict[str, Any] = None) -> Tuple[pd.DataFrame, pd.DataFrame]:
73
+ """
74
+ Get employees assigned to a global value set with optional filters.
75
+
76
+ Args:
77
+ global_value_set_uid (UUID): The global value set UID to get assigned employees for
78
+ filters (Dict[str, Any], optional): Filter criteria for employees
79
+
80
+ Returns:
81
+ Tuple of (valid_data, invalid_data) DataFrames with assigned employee information
82
+ """
83
+ try:
84
+ # Default filter if none provided
85
+ if filters is None:
86
+ filters = {"skip": 0, "take": 50}
87
+
88
+ # Validate the filter data using Pydantic
89
+ valid_filter = GetAssignedEmployeesRequest(**filters)
90
+ req_body = valid_filter.model_dump(by_alias=True, mode='json', exclude_none=True)
91
+
92
+ endpoint = f"{self.endpoint}/{global_value_set_uid}/assigned"
93
+ response = self.zenegy.post(endpoint=endpoint, json=req_body)
94
+ self.zenegy.raise_for_status_with_details(response)
95
+
96
+ content = response.json()
97
+
98
+ # Get data from response
99
+ data = content.get("data", [])
100
+
101
+ if not data:
102
+ return pd.DataFrame(), pd.DataFrame()
103
+
104
+ # Normalize the data with expanded department fields
105
+ df = pd.json_normalize(
106
+ data,
107
+ sep='__'
108
+ )
109
+
110
+ if df.empty:
111
+ return pd.DataFrame(), pd.DataFrame()
112
+
113
+ # Validate data using schema
114
+ valid_data, invalid_data = Functions.validate_data(df, AssignedEmployeesGet)
115
+ return valid_data, invalid_data
116
+
117
+ except Exception as e:
118
+ raise Exception(f"Failed to get assigned employees for global value set: {str(e)}") from e
119
+
120
+ def create(self, data: Dict[str, Any]) -> requests.Response:
121
+ """
122
+ Create a new global value set.
123
+
124
+ Args:
125
+ data (Dict[str, Any]): The global value set data to create
126
+
127
+ Returns:
128
+ requests.Response: The API response
129
+ """
130
+ try:
131
+ # Convert flat dictionary to nested structure based on Pydantic model
132
+ nested_data = Functions.flat_dict_to_nested_dict(data, GlobalValueSetCreate)
133
+
134
+ valid_data = GlobalValueSetCreate(**nested_data)
135
+ req_body = valid_data.model_dump(by_alias=True, mode='json', exclude_none=True)
136
+
137
+ response = self.zenegy.post(endpoint=self.endpoint, json=req_body)
138
+ self.zenegy.raise_for_status_with_details(response)
139
+ return response
140
+
141
+ except Exception as e:
142
+ raise Exception(f"Failed to create global value set: {str(e)}") from e
143
+
144
+ def delete(self, global_value_set_uid: UUID) -> requests.Response:
145
+ """
146
+ Delete a global value set by UID.
147
+
148
+ Args:
149
+ global_value_set_uid (UUID): The global value set UID to delete
150
+
151
+ Returns:
152
+ requests.Response: The API response
153
+ """
154
+ try:
155
+ endpoint = f"{self.endpoint}/{global_value_set_uid}"
156
+
157
+ response = self.zenegy.delete(endpoint=endpoint)
158
+ self.zenegy.raise_for_status_with_details(response)
159
+ return response
160
+
161
+ except Exception as e:
162
+ raise Exception(f"Failed to delete global value set: {str(e)}") from e
163
+
164
+ def update(self, global_value_set_uid: UUID, data: Dict[str, Any]) -> requests.Response:
165
+ """
166
+ Update a global value set by UID.
167
+
168
+ Args:
169
+ global_value_set_uid (UUID): The global value set UID to update
170
+ data (Dict[str, Any]): The global value set data to update
171
+
172
+ Returns:
173
+ requests.Response: The API response
174
+ """
175
+ try:
176
+ # Convert flat dictionary to nested structure based on Pydantic model
177
+ nested_data = Functions.flat_dict_to_nested_dict(data, GlobalValueSetUpdate)
178
+
179
+ valid_data = GlobalValueSetUpdate(**nested_data)
180
+ req_body = valid_data.model_dump(by_alias=True, mode='json', exclude_none=True)
181
+ endpoint = f"{self.endpoint}/{global_value_set_uid}"
182
+
183
+ response = self.zenegy.patch(endpoint=endpoint, json=req_body)
184
+ self.zenegy.raise_for_status_with_details(response)
185
+ return response
186
+
187
+ except Exception as e:
188
+ raise Exception(f"Failed to update global value set: {str(e)}") from e
189
+
190
+ def manage_employees(self, global_value_set_uid: UUID, data: Dict[str, Any]) -> requests.Response:
191
+ """
192
+ Manage employee assignments for a global value set (add and/or remove employees).
193
+
194
+ Args:
195
+ global_value_set_uid (UUID): The global value set UID to manage employees for
196
+ data (Dict[str, Any]): The employee assignment data (add_employees and/or remove_employees)
197
+
198
+ Returns:
199
+ requests.Response: The API response with assignment results
200
+ """
201
+ try:
202
+ # Convert flat dictionary to nested structure based on Pydantic model
203
+ nested_data = Functions.flat_dict_to_nested_dict(data, GlobalValueSetEmployeeAssignment)
204
+
205
+ valid_data = GlobalValueSetEmployeeAssignment(**nested_data)
206
+ req_body = valid_data.model_dump(by_alias=True, mode='json', exclude_none=True)
207
+ endpoint = f"{self.endpoint}/{global_value_set_uid}/employees"
208
+
209
+ response = self.zenegy.put(endpoint=endpoint, json=req_body)
210
+ self.zenegy.raise_for_status_with_details(response)
211
+ return response
212
+
213
+ except Exception as e:
214
+ raise Exception(f"Failed to manage employees for global value set: {str(e)}") from e
215
+
216
+ def assign_to_employees(self, global_value_set_uid: UUID, employee_uids: List[str]) -> requests.Response:
217
+ """
218
+ Assign a global value set to specified employees.
219
+
220
+ Args:
221
+ global_value_set_uid (UUID): The global value set UID to assign
222
+ employee_uids (List[str]): List of employee UIDs to assign the global value set to
223
+
224
+ Returns:
225
+ requests.Response: The API response (204 No Content on success)
226
+ """
227
+ try:
228
+ # API expects a simple Array[string] as body
229
+ endpoint = f"{self.endpoint}/{global_value_set_uid}/assign"
230
+ req_body = employee_uids
231
+
232
+ response = self.zenegy.post(endpoint=endpoint, json=employee_uids)
233
+ self.zenegy.raise_for_status_with_details(response)
234
+ return response
235
+
236
+ except Exception as e:
237
+ raise Exception(f"Failed to assign global value set to employees: {str(e)}") from e
238
+
239
+ def unassign_from_employees(self, global_value_set_uid: UUID, employee_uids: List[str]) -> requests.Response:
240
+ """
241
+ Unassign employees from a global value set.
242
+
243
+ Args:
244
+ global_value_set_uid (UUID): The global value set UID to unassign employees from
245
+ employee_uids (List[str]): List of employee UIDs to unassign
246
+
247
+ Returns:
248
+ requests.Response: The API response
249
+ """
250
+ try:
251
+ # API expects a simple Array[string] as body
252
+ endpoint = f"{self.endpoint}/{global_value_set_uid}/employees/delete"
253
+ req_body = employee_uids
254
+
255
+ response = self.zenegy.post(endpoint=endpoint, json=employee_uids)
256
+ self.zenegy.raise_for_status_with_details(response)
257
+ return response
258
+
259
+ except Exception as e:
260
+ raise Exception(f"Failed to unassign employees from global value set: {str(e)}") from e
@@ -0,0 +1,265 @@
1
+ from .schemas.global_values import (GlobalValuesGet, CompanyGlobalValueCreate, CompanyGlobalValueUpdate, GlobalValueAssign, AssignedGlobalValuesGet, GetAssignedEmployeesToGlobalValueAsyncRequest, AssignedEmployeesToGlobalValueGet)
2
+ from typing import Tuple, Dict, Any, List
3
+ import pandas as pd
4
+ from brynq_sdk_functions import Functions
5
+ import requests
6
+ from uuid import UUID
7
+
8
+ class GlobalValues:
9
+ """
10
+ Handles all globalvalues-related operations in Zenegy API
11
+ """
12
+ def __init__(self, zenegy):
13
+ """
14
+ Initialize the GlobalValues class.
15
+
16
+ Args:
17
+ zenegy: The Zenegy instance to use for API calls
18
+ """
19
+ self.zenegy = zenegy
20
+ self.endpoint = f"api/companies/{self.zenegy.company_uid}/global-values"
21
+
22
+ def get(self) -> Tuple[pd.DataFrame, pd.DataFrame]:
23
+ """
24
+ GetGlobalValuesPerCompanyAsync
25
+ Returns:
26
+ Tuple of (valid_data, invalid_data) DataFrames with global values information
27
+ """
28
+ try:
29
+ # Make the API request and get raw response
30
+ content = self.zenegy.get(endpoint=self.endpoint)
31
+
32
+ # Normalize the data with expanded effectiveFrom and effectiveTo
33
+ df = pd.json_normalize(
34
+ content,
35
+ sep='__'
36
+ )
37
+
38
+ if df.empty:
39
+ return pd.DataFrame(), pd.DataFrame()
40
+
41
+ # Validate data using schema
42
+ valid_data, invalid_data = Functions.validate_data(df, GlobalValuesGet)
43
+ return valid_data, invalid_data
44
+
45
+ except Exception as e:
46
+ raise Exception(f"Failed to retrieve global values: {str(e)}") from e
47
+
48
+ def create(self, data: Dict[str, Any]) -> requests.Response:
49
+ """
50
+ CreateGlobalValueAsync
51
+ Args:
52
+ data (Dict[str, Any]): The global value data to create
53
+ Returns:
54
+ requests.Response: The API response
55
+ """
56
+ try:
57
+ # Convert flat dictionary to nested structure based on Pydantic model
58
+ nested_data = Functions.flat_dict_to_nested_dict(data, CompanyGlobalValueCreate)
59
+
60
+ # Validate the data using Pydantic
61
+ valid_data = CompanyGlobalValueCreate(**nested_data)
62
+ req_body = valid_data.model_dump(by_alias=True, mode='json', exclude_none=True)
63
+
64
+ response = self.zenegy.post(endpoint=self.endpoint, json=req_body)
65
+ self.zenegy.raise_for_status_with_details(response)
66
+ return response
67
+
68
+ except Exception as e:
69
+ raise Exception(f"Failed to create global value: {str(e)}") from e
70
+
71
+ def get_by_id(self, global_value_uid: UUID) -> Tuple[pd.DataFrame, pd.DataFrame]:
72
+ """
73
+ GetGlobalValueByIdAsync
74
+ Args:
75
+ global_value_uid (UUID): The global value UID to retrieve
76
+ Returns:
77
+ Tuple of (valid_data, invalid_data) DataFrames with global value information
78
+ """
79
+ try:
80
+ endpoint = f"{self.endpoint}/{global_value_uid}"
81
+ content = self.zenegy.get(endpoint=endpoint)
82
+
83
+ # Normalize the data with expanded effectiveFrom and effectiveTo
84
+ df = pd.json_normalize(
85
+ [content], # Wrap in list since it's a single object
86
+ sep='__'
87
+ )
88
+
89
+ if df.empty:
90
+ return pd.DataFrame(), pd.DataFrame()
91
+
92
+ # Validate data using schema
93
+ valid_data, invalid_data = Functions.validate_data(df, GlobalValuesGet)
94
+ return valid_data, invalid_data
95
+ except Exception as e:
96
+ raise Exception(f"Failed to retrieve global value by ID: {str(e)}") from e
97
+
98
+ def get_assigned_global_values(self, employee_uid: UUID) -> Tuple[pd.DataFrame, pd.DataFrame]:
99
+ """
100
+ GetAssignedGlobalValuesAsync
101
+ Args:
102
+ employee_uid (UUID): The employee UID to get assigned global values for
103
+ Returns:
104
+ Tuple of (valid_data, invalid_data) DataFrames with assigned global values information
105
+ """
106
+ try:
107
+ endpoint = f"{self.endpoint}/assignedGlobalValues/{employee_uid}"
108
+ content = self.zenegy.get(endpoint=endpoint)
109
+
110
+ # Normalize the data with expanded companyGlobalValueReferenceUidsPairs
111
+ df = pd.json_normalize(
112
+ content,
113
+ record_path='companyGlobalValueReferenceUidsPairs',
114
+ meta=['type', 'isAvailableInCompany', 'isEmployeeAssigned'],
115
+ record_prefix='companyGlobalValueReferenceUidsPairs__',
116
+ sep='__'
117
+ )
118
+
119
+ if df.empty:
120
+ return pd.DataFrame(), pd.DataFrame()
121
+
122
+ # Validate data using schema
123
+ valid_data, invalid_data = Functions.validate_data(df, AssignedGlobalValuesGet)
124
+ return valid_data, invalid_data
125
+ except Exception as e:
126
+ raise Exception(f"Failed to retrieve assigned global values for employee: {str(e)}") from e
127
+
128
+ def get_assigned_employees(self, global_value_uid: UUID, filters: Dict[str, Any] = None) -> Tuple[pd.DataFrame, pd.DataFrame]:
129
+ """
130
+ Get employees assigned to a global value with optional filters.
131
+
132
+ Args:
133
+ global_value_uid (UUID): The global value UID to get assigned employees for
134
+ filters (Dict[str, Any], optional): Filter criteria for employees
135
+
136
+ Returns:
137
+ Tuple of (valid_data, invalid_data) DataFrames with assigned employee information
138
+ """
139
+ try:
140
+ if filters is None:
141
+ filters = {"skip": 0, "take": 50}
142
+
143
+ # Validate the filter data using Pydantic
144
+ valid_filter = GetAssignedEmployeesToGlobalValueAsyncRequest(**filters)
145
+ req_body = valid_filter.model_dump(by_alias=True, mode='json', exclude_none=True)
146
+
147
+ endpoint = f"{self.endpoint}/{global_value_uid}/assigned"
148
+ response = self.zenegy.post(endpoint=endpoint, json=req_body)
149
+ self.zenegy.raise_for_status_with_details(response)
150
+
151
+ content = response.json()
152
+ data = content.get("data", [])
153
+
154
+ if not data:
155
+ return pd.DataFrame(), pd.DataFrame()
156
+
157
+ # Normalize the data with expanded department and user fields
158
+ df = pd.json_normalize(data, sep='__')
159
+
160
+ if df.empty:
161
+ return pd.DataFrame(), pd.DataFrame()
162
+
163
+ # Validate data using schema
164
+ valid_data, invalid_data = Functions.validate_data(df, AssignedEmployeesToGlobalValueGet)
165
+ return valid_data, invalid_data
166
+
167
+ except Exception as e:
168
+ raise Exception(f"Failed to get assigned employees for global value: {str(e)}") from e
169
+
170
+ def update(self, global_value_uid: UUID, data: Dict[str, Any]) -> requests.Response:
171
+ """
172
+ Update a global value by UID.
173
+
174
+ Args:
175
+ global_value_uid (UUID): The global value UID to update
176
+ data (Dict[str, Any]): The global value data to update
177
+
178
+ Returns:
179
+ requests.Response: The API response
180
+ """
181
+ try:
182
+ # Convert flat dictionary to nested structure based on Pydantic model
183
+ nested_data = Functions.flat_dict_to_nested_dict(data, CompanyGlobalValueUpdate)
184
+
185
+ # Validate the data using Pydantic
186
+ valid_data = CompanyGlobalValueUpdate(**nested_data)
187
+ req_body = valid_data.model_dump(by_alias=True, mode='json', exclude_none=True)
188
+ endpoint = f"{self.endpoint}/{global_value_uid}"
189
+
190
+ response = self.zenegy.patch(endpoint=endpoint, json=req_body)
191
+ self.zenegy.raise_for_status_with_details(response)
192
+ return response
193
+
194
+ except Exception as e:
195
+ raise Exception(f"Failed to update global value: {str(e)}") from e
196
+
197
+ def assign_to_employees(self, global_value_uid: UUID, data: Dict[str, Any]) -> requests.Response:
198
+ """
199
+ Assign a global value to multiple employees with optional settings.
200
+
201
+ Args:
202
+ global_value_uid (UUID): The global value UID to assign
203
+ data (Dict[str, Any]): The assignment data with employee UIDs and optional settings
204
+
205
+ Returns:
206
+ requests.Response: The API response (204 No Content on success)
207
+ """
208
+ try:
209
+ # Convert flat dictionary to nested structure based on Pydantic model
210
+ nested_data = Functions.flat_dict_to_nested_dict(data, GlobalValueAssign)
211
+
212
+ # Validate the data using Pydantic
213
+ valid_data = GlobalValueAssign(**nested_data)
214
+ req_body = valid_data.model_dump(by_alias=True, mode='json', exclude_none=True)
215
+ endpoint = f"{self.endpoint}/{global_value_uid}/assign"
216
+
217
+ response = self.zenegy.post(endpoint=endpoint, json=req_body)
218
+ self.zenegy.raise_for_status_with_details(response)
219
+ return response
220
+
221
+ except Exception as e:
222
+ raise Exception(f"Failed to assign global value to employees: {str(e)}") from e
223
+
224
+ def unassign_from_employees(self, global_value_uid: UUID, employee_uids: List[str]) -> requests.Response:
225
+ """
226
+ Unassign a global value from multiple employees.
227
+
228
+ Args:
229
+ global_value_uid (UUID): The global value UID to unassign
230
+ employee_uids (List[str]): List of employee UIDs to unassign from
231
+
232
+ Returns:
233
+ requests.Response: The API response (204 No Content on success)
234
+ """
235
+ try:
236
+ # API expects a simple Array[string] as body
237
+ endpoint = f"{self.endpoint}/{global_value_uid}/unassign"
238
+ req_body = employee_uids
239
+
240
+ response = self.zenegy.post(endpoint=endpoint, json=employee_uids)
241
+ self.zenegy.raise_for_status_with_details(response)
242
+ return response
243
+
244
+ except Exception as e:
245
+ raise Exception(f"Failed to unassign global value from employees: {str(e)}") from e
246
+
247
+ def delete(self, global_value_uid: UUID) -> requests.Response:
248
+ """
249
+ Delete a global value.
250
+
251
+ Args:
252
+ global_value_uid (UUID): The global value UID to delete
253
+
254
+ Returns:
255
+ requests.Response: The API response (204 No Content on success)
256
+ """
257
+ try:
258
+ endpoint = f"{self.endpoint}/{global_value_uid}"
259
+
260
+ response = self.zenegy.delete(endpoint=endpoint)
261
+ self.zenegy.raise_for_status_with_details(response)
262
+ return response
263
+
264
+ except Exception as e:
265
+ raise Exception(f"Failed to delete global value: {str(e)}") from e
@@ -0,0 +1,119 @@
1
+ import requests
2
+ from uuid import UUID
3
+ from brynq_sdk_functions import Functions
4
+ from .schemas.employee_pay_checks import (PaycheckUpdate,
5
+ PaycheckCreate,
6
+ PayChecksGet)
7
+ from typing import Dict, Any, Tuple
8
+ import pandas as pd
9
+ from pydantic import ValidationError
10
+
11
+
12
+ class PayChecks:
13
+ """
14
+ Handles all Employee Pay Check related operations in Zenegy API
15
+ """
16
+ def __init__(self, zenegy):
17
+ """
18
+ Initialize the Employeepaychecks class.
19
+
20
+ Args:
21
+ zenegy: The Zenegy instance to use for API calls
22
+ """
23
+ self.zenegy = zenegy
24
+ self.endpoint = f"api/companies/{self.zenegy.company_uid}/paychecks/bulk"
25
+
26
+ def get(self, employee_uid: UUID) -> Tuple[pd.DataFrame, pd.DataFrame]:
27
+ """
28
+ GetPayCheckBasesAsync
29
+ Args:
30
+ employee_uid (UUID): The employee uid
31
+ Returns:
32
+ Tuple of (valid_data, invalid_data) DataFrames
33
+ """
34
+ try:
35
+ endpoint = f"api/companies/{self.zenegy.company_uid}/employees/{employee_uid}/paychecks"
36
+ content = self.zenegy.get(endpoint=endpoint)
37
+
38
+ # Normalize the response (direct list of dicts with nested objects)
39
+ df = pd.json_normalize(content, sep='__')
40
+ if df.empty:
41
+ return pd.DataFrame(), pd.DataFrame()
42
+ # Validate against schema
43
+ valid_data, invalid_data = Functions.validate_data(df, PayChecksGet)
44
+
45
+ return valid_data, invalid_data
46
+ except Exception as e:
47
+ raise Exception(f"Failed to retrieve pay checks: {str(e)}") from e
48
+
49
+ def create(self, employee_uid: UUID, data: Dict[str, Any]) -> requests.Response:
50
+ """
51
+ PostPayChecksAsync
52
+ Args:
53
+ employee_uid (UUID): The employee uid
54
+ data (Dict[str, Any]): The data to create the pay check
55
+ Returns:
56
+ requests.Response: The response from the API
57
+ Raises:
58
+ ValidationError: If the data is invalid
59
+ Exception: If there is an error in the API call
60
+ """
61
+ url = f"{self.zenegy.base_url}/api/companies/{self.zenegy.company_uid}/employees/{employee_uid}/paychecks"
62
+
63
+ try:
64
+ # Validate data using Pydantic schema
65
+ validated_data = PaycheckCreate(**data)
66
+ req_body = validated_data.model_dump(by_alias=True,mode='json')
67
+
68
+ endpoint = f"api/companies/{self.zenegy.company_uid}/employees/{employee_uid}/paychecks"
69
+ response = self.zenegy.post(endpoint=endpoint, json=req_body)
70
+ self.zenegy.raise_for_status_with_details(response)
71
+ return response
72
+ except ValidationError as e:
73
+ raise ValidationError(f"Invalid data: {e.errors()}")
74
+ except Exception as e:
75
+ raise Exception(f"Error creating pay check: {str(e)}")
76
+
77
+ def update(self, employee_uid: UUID, paycheck_uid: UUID, data: Dict[str, Any]) -> requests.Response:
78
+ """
79
+ UpdatePayCheckPerEmployeeAsync
80
+ Args:
81
+ employee_uid (UUID): The employee uid
82
+ paycheck_uid (UUID): The pay check uid
83
+ data (Dict[str, Any]): The data to update the pay check
84
+ Returns:
85
+ requests.Response: The response from the API
86
+ Raises:
87
+ ValidationError: If the data is invalid
88
+ Exception: If there is an error in the API call
89
+ """
90
+ try:
91
+ # Validate data using Pydantic schema
92
+ validated_data = PaycheckUpdate(**data)
93
+ req_body = validated_data.model_dump(by_alias=True,mode="json")
94
+ endpoint = f"api/companies/{self.zenegy.company_uid}/employees/{employee_uid}/paychecks"
95
+ response = self.zenegy.post(endpoint=endpoint, json=req_body)
96
+ self.zenegy.raise_for_status_with_details(response)
97
+ return response
98
+ except ValidationError as e:
99
+ raise ValidationError(f"Invalid data: {e.errors()}")
100
+ except Exception as e:
101
+ raise Exception(f"Error updating pay check: {str(e)}")
102
+
103
+ def delete(self, employee_uid: UUID, pay_check_uid: UUID) -> requests.Response:
104
+ """
105
+ DeletePayCheckPerEmployee
106
+ Args:
107
+ employee_uid (UUID): The employee uid
108
+ Args:
109
+ pay_check_uid (UUID): The pay check uid
110
+ Returns:
111
+ requests.Response: The API response
112
+ """
113
+ endpoint = f"api/companies/{self.zenegy.company_uid}/employees/{employee_uid}/paychecks/{pay_check_uid}"
114
+ try:
115
+ response = self.zenegy.delete(endpoint=endpoint)
116
+ self.zenegy.raise_for_status_with_details(response)
117
+ return response
118
+ except Exception as e:
119
+ raise Exception(f"Failed to delete pay check: {str(e)}")