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.
- brynq_sdk_zenegy/__init__.py +23 -0
- brynq_sdk_zenegy/absence.py +100 -0
- brynq_sdk_zenegy/companies.py +43 -0
- brynq_sdk_zenegy/cost_center.py +80 -0
- brynq_sdk_zenegy/departments.py +77 -0
- brynq_sdk_zenegy/employee_documents.py +40 -0
- brynq_sdk_zenegy/employees.py +301 -0
- brynq_sdk_zenegy/global_value_sets.py +260 -0
- brynq_sdk_zenegy/global_values.py +265 -0
- brynq_sdk_zenegy/paychecks.py +119 -0
- brynq_sdk_zenegy/payroll.py +117 -0
- brynq_sdk_zenegy/payslips.py +43 -0
- brynq_sdk_zenegy/pensions.py +118 -0
- brynq_sdk_zenegy/schemas/__init__.py +30 -0
- brynq_sdk_zenegy/schemas/absences.py +393 -0
- brynq_sdk_zenegy/schemas/companies.py +42 -0
- brynq_sdk_zenegy/schemas/company_cost_centers.py +48 -0
- brynq_sdk_zenegy/schemas/company_departments.py +147 -0
- brynq_sdk_zenegy/schemas/employee_documents.py +30 -0
- brynq_sdk_zenegy/schemas/employee_pay_checks.py +169 -0
- brynq_sdk_zenegy/schemas/employee_pensions.py +140 -0
- brynq_sdk_zenegy/schemas/employees.py +2372 -0
- brynq_sdk_zenegy/schemas/global_value_sets.py +185 -0
- brynq_sdk_zenegy/schemas/global_values.py +433 -0
- brynq_sdk_zenegy/schemas/payrolls.py +134 -0
- brynq_sdk_zenegy/schemas/payslips.py +32 -0
- brynq_sdk_zenegy/schemas/supplements_and_deductions_rates.py +189 -0
- brynq_sdk_zenegy/supplements_and_deductions_rates.py +71 -0
- brynq_sdk_zenegy/zenegy.py +221 -0
- brynq_sdk_zenegy-1.3.3.dist-info/METADATA +16 -0
- brynq_sdk_zenegy-1.3.3.dist-info/RECORD +33 -0
- brynq_sdk_zenegy-1.3.3.dist-info/WHEEL +5 -0
- 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)}")
|