brynq-sdk-nmbrs 2.3.1__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_nmbrs/__init__.py +226 -0
- brynq_sdk_nmbrs/absence.py +124 -0
- brynq_sdk_nmbrs/address.py +66 -0
- brynq_sdk_nmbrs/bank.py +125 -0
- brynq_sdk_nmbrs/children.py +100 -0
- brynq_sdk_nmbrs/companies.py +93 -0
- brynq_sdk_nmbrs/contract.py +132 -0
- brynq_sdk_nmbrs/costcenter.py +166 -0
- brynq_sdk_nmbrs/costunit.py +90 -0
- brynq_sdk_nmbrs/days.py +137 -0
- brynq_sdk_nmbrs/debtors.py +25 -0
- brynq_sdk_nmbrs/department.py +122 -0
- brynq_sdk_nmbrs/document.py +30 -0
- brynq_sdk_nmbrs/employees.py +196 -0
- brynq_sdk_nmbrs/employment.py +107 -0
- brynq_sdk_nmbrs/function.py +89 -0
- brynq_sdk_nmbrs/hours.py +252 -0
- brynq_sdk_nmbrs/leave.py +139 -0
- brynq_sdk_nmbrs/manager.py +294 -0
- brynq_sdk_nmbrs/salaries.py +85 -0
- brynq_sdk_nmbrs/salary_tables.py +242 -0
- brynq_sdk_nmbrs/schedules.py +84 -0
- brynq_sdk_nmbrs/schemas/__init__.py +37 -0
- brynq_sdk_nmbrs/schemas/absence.py +61 -0
- brynq_sdk_nmbrs/schemas/address.py +76 -0
- brynq_sdk_nmbrs/schemas/bank.py +83 -0
- brynq_sdk_nmbrs/schemas/contracts.py +60 -0
- brynq_sdk_nmbrs/schemas/costcenter.py +91 -0
- brynq_sdk_nmbrs/schemas/costunit.py +40 -0
- brynq_sdk_nmbrs/schemas/days.py +98 -0
- brynq_sdk_nmbrs/schemas/debtor.py +16 -0
- brynq_sdk_nmbrs/schemas/department.py +57 -0
- brynq_sdk_nmbrs/schemas/employees.py +153 -0
- brynq_sdk_nmbrs/schemas/employment.py +48 -0
- brynq_sdk_nmbrs/schemas/function.py +50 -0
- brynq_sdk_nmbrs/schemas/hours.py +121 -0
- brynq_sdk_nmbrs/schemas/leave.py +53 -0
- brynq_sdk_nmbrs/schemas/manager.py +126 -0
- brynq_sdk_nmbrs/schemas/salary.py +92 -0
- brynq_sdk_nmbrs/schemas/schedules.py +96 -0
- brynq_sdk_nmbrs/schemas/social_insurance.py +40 -0
- brynq_sdk_nmbrs/schemas/wage_tax.py +98 -0
- brynq_sdk_nmbrs/schemas/wagecomponents.py +114 -0
- brynq_sdk_nmbrs/social_insurance.py +52 -0
- brynq_sdk_nmbrs/wage_tax.py +164 -0
- brynq_sdk_nmbrs/wagecomponents.py +268 -0
- brynq_sdk_nmbrs-2.3.1.dist-info/METADATA +21 -0
- brynq_sdk_nmbrs-2.3.1.dist-info/RECORD +50 -0
- brynq_sdk_nmbrs-2.3.1.dist-info/WHEEL +5 -0
- brynq_sdk_nmbrs-2.3.1.dist-info/top_level.txt +1 -0
brynq_sdk_nmbrs/hours.py
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import requests
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
from .schemas.hours import (
|
|
5
|
+
VariableHoursCreate, VariableHoursUpdate, HoursDelete,
|
|
6
|
+
FixedHoursCreate, FixedHoursUpdate, VariableHoursGet, FixedHoursGet
|
|
7
|
+
)
|
|
8
|
+
from brynq_sdk_functions import Functions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Hours:
|
|
12
|
+
def __init__(self, nmbrs):
|
|
13
|
+
self.nmbrs = nmbrs
|
|
14
|
+
|
|
15
|
+
def get_types(self,
|
|
16
|
+
company_id: str) -> pd.DataFrame:
|
|
17
|
+
request = requests.Request(method='GET',
|
|
18
|
+
url=f"{self.nmbrs.base_url}companies/{company_id}/hourcodes")
|
|
19
|
+
|
|
20
|
+
df = self.nmbrs.get_paginated_result(request)
|
|
21
|
+
|
|
22
|
+
return df
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class VariableHours:
|
|
26
|
+
def __init__(self, nmbrs):
|
|
27
|
+
self.nmbrs = nmbrs
|
|
28
|
+
|
|
29
|
+
def get(self,
|
|
30
|
+
employee_id: str,
|
|
31
|
+
created_from: str = None,
|
|
32
|
+
period: int = None,
|
|
33
|
+
year: int = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
34
|
+
params = {}
|
|
35
|
+
if created_from:
|
|
36
|
+
params['createdFrom'] = created_from
|
|
37
|
+
if period:
|
|
38
|
+
params['period'] = period
|
|
39
|
+
if year:
|
|
40
|
+
params['year'] = year
|
|
41
|
+
request = requests.Request(method='GET',
|
|
42
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/variablehours",
|
|
43
|
+
params=params)
|
|
44
|
+
|
|
45
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
46
|
+
|
|
47
|
+
df = pd.DataFrame(data)
|
|
48
|
+
|
|
49
|
+
df['employeeId'] = employee_id # Add employee_id for tracking
|
|
50
|
+
df['period'] = period
|
|
51
|
+
df['year'] = year
|
|
52
|
+
|
|
53
|
+
# Validate data using the schema
|
|
54
|
+
valid_hours, invalid_hours = Functions.validate_data(df=df, schema=VariableHoursGet, debug=True)
|
|
55
|
+
|
|
56
|
+
return valid_hours, invalid_hours
|
|
57
|
+
|
|
58
|
+
def create(self, employee_id: str, data: Dict[str, Any]):
|
|
59
|
+
"""
|
|
60
|
+
Create variable hours for an employee using Pydantic validation.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
employee_id: The ID of the employee
|
|
64
|
+
data: Dictionary containing hours data with fields matching
|
|
65
|
+
the VariableHoursCreate schema (using camelCase field names)
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Response from the API
|
|
69
|
+
"""
|
|
70
|
+
# Validate with Pydantic model
|
|
71
|
+
nested_data = self.nmbrs.flat_dict_to_nested_dict(data, VariableHoursCreate)
|
|
72
|
+
hours_model = VariableHoursCreate(**nested_data)
|
|
73
|
+
|
|
74
|
+
if self.nmbrs.mock_mode:
|
|
75
|
+
return hours_model
|
|
76
|
+
|
|
77
|
+
# Convert validated model to dict for API payload
|
|
78
|
+
payload = hours_model.model_dump(exclude_none=True, by_alias=True)
|
|
79
|
+
|
|
80
|
+
# Send request
|
|
81
|
+
resp = self.nmbrs.session.post(
|
|
82
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/variablehours",
|
|
83
|
+
json=payload,
|
|
84
|
+
timeout=self.nmbrs.timeout
|
|
85
|
+
)
|
|
86
|
+
return resp
|
|
87
|
+
|
|
88
|
+
def update(self, employee_id: str, data: Dict[str, Any]):
|
|
89
|
+
"""
|
|
90
|
+
Update variable hours for an employee using Pydantic validation.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
employee_id: The ID of the employee
|
|
94
|
+
data: Dictionary containing hours data with fields matching
|
|
95
|
+
the VariableHoursUpdate schema (using camelCase field names)
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Response from the API
|
|
99
|
+
"""
|
|
100
|
+
# Validate with Pydantic model
|
|
101
|
+
nested_data = self.nmbrs.flat_dict_to_nested_dict(data, VariableHoursUpdate)
|
|
102
|
+
hours_model = VariableHoursUpdate(**nested_data)
|
|
103
|
+
|
|
104
|
+
if self.nmbrs.mock_mode:
|
|
105
|
+
return hours_model
|
|
106
|
+
|
|
107
|
+
# Convert validated model to dict for API payload
|
|
108
|
+
payload = hours_model.model_dump(exclude_none=True, by_alias=True)
|
|
109
|
+
|
|
110
|
+
# Send request
|
|
111
|
+
resp = self.nmbrs.session.put(
|
|
112
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/variablehours",
|
|
113
|
+
json=payload,
|
|
114
|
+
timeout=self.nmbrs.timeout
|
|
115
|
+
)
|
|
116
|
+
return resp
|
|
117
|
+
|
|
118
|
+
def delete(self, employee_id: str, hourcomponent_id: str):
|
|
119
|
+
"""
|
|
120
|
+
Delete hours for an employee.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
employee_id: The ID of the employee
|
|
124
|
+
hourcomponent_id: The ID of the hour component to delete
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
Response from the API
|
|
128
|
+
"""
|
|
129
|
+
# Create and validate a HoursDelete model
|
|
130
|
+
hours_model = HoursDelete(hourComponentId=hourcomponent_id)
|
|
131
|
+
|
|
132
|
+
if self.nmbrs.mock_mode:
|
|
133
|
+
return hours_model
|
|
134
|
+
|
|
135
|
+
# Send request
|
|
136
|
+
resp = self.nmbrs.session.delete(
|
|
137
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/hours/{hourcomponent_id}",
|
|
138
|
+
timeout=self.nmbrs.timeout
|
|
139
|
+
)
|
|
140
|
+
return resp
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class FixedHours:
|
|
144
|
+
def __init__(self, nmbrs):
|
|
145
|
+
self.nmbrs = nmbrs
|
|
146
|
+
|
|
147
|
+
def get(self,
|
|
148
|
+
company_id: str,
|
|
149
|
+
created_from: str = None,
|
|
150
|
+
employee_id: str = None,
|
|
151
|
+
period: int = None,
|
|
152
|
+
year: int = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
153
|
+
params = {}
|
|
154
|
+
if created_from:
|
|
155
|
+
params['createdFrom'] = created_from
|
|
156
|
+
if employee_id:
|
|
157
|
+
params['employeeId'] = employee_id
|
|
158
|
+
if period:
|
|
159
|
+
params['period'] = period
|
|
160
|
+
if year:
|
|
161
|
+
params['year'] = year
|
|
162
|
+
request = requests.Request(method='GET',
|
|
163
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/fixedhours",
|
|
164
|
+
params=params)
|
|
165
|
+
|
|
166
|
+
df = self.nmbrs.get_paginated_result(request)
|
|
167
|
+
|
|
168
|
+
return df
|
|
169
|
+
|
|
170
|
+
def create(self, employee_id: str, data: Dict[str, Any]):
|
|
171
|
+
"""
|
|
172
|
+
Create fixed hours for an employee using Pydantic validation.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
employee_id: The ID of the employee
|
|
176
|
+
data: Dictionary containing hours data with fields matching
|
|
177
|
+
the FixedHoursCreate schema (using camelCase field names)
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
Response from the API
|
|
181
|
+
"""
|
|
182
|
+
# Validate with Pydantic model
|
|
183
|
+
nested_data = self.nmbrs.flat_dict_to_nested_dict(data, FixedHoursCreate)
|
|
184
|
+
hours_model = FixedHoursCreate(**nested_data)
|
|
185
|
+
|
|
186
|
+
if self.nmbrs.mock_mode:
|
|
187
|
+
return hours_model
|
|
188
|
+
|
|
189
|
+
# Convert validated model to dict for API payload
|
|
190
|
+
payload = hours_model.model_dump(exclude_none=True, by_alias=True)
|
|
191
|
+
|
|
192
|
+
# Send request
|
|
193
|
+
resp = self.nmbrs.session.post(
|
|
194
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/fixedhours",
|
|
195
|
+
json=payload,
|
|
196
|
+
timeout=self.nmbrs.timeout
|
|
197
|
+
)
|
|
198
|
+
return resp
|
|
199
|
+
|
|
200
|
+
def update(self, employee_id: str, data: Dict[str, Any]):
|
|
201
|
+
"""
|
|
202
|
+
Update fixed hours for an employee using Pydantic validation.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
employee_id: The ID of the employee
|
|
206
|
+
data: Dictionary containing hours data with fields matching
|
|
207
|
+
the FixedHoursUpdate schema (using camelCase field names)
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
Response from the API
|
|
211
|
+
"""
|
|
212
|
+
# Validate with Pydantic model
|
|
213
|
+
nested_data = self.nmbrs.flat_dict_to_nested_dict(data, FixedHoursUpdate)
|
|
214
|
+
hours_model = FixedHoursUpdate(**nested_data)
|
|
215
|
+
|
|
216
|
+
if self.nmbrs.mock_mode:
|
|
217
|
+
return hours_model
|
|
218
|
+
|
|
219
|
+
# Convert validated model to dict for API payload
|
|
220
|
+
payload = hours_model.model_dump(exclude_none=True, by_alias=True)
|
|
221
|
+
|
|
222
|
+
# Send request
|
|
223
|
+
resp = self.nmbrs.session.put(
|
|
224
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/fixedhours",
|
|
225
|
+
json=payload,
|
|
226
|
+
timeout=self.nmbrs.timeout
|
|
227
|
+
)
|
|
228
|
+
return resp
|
|
229
|
+
|
|
230
|
+
def delete(self, employee_id: str, hourcomponent_id: str):
|
|
231
|
+
"""
|
|
232
|
+
Delete hours for an employee.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
employee_id: The ID of the employee
|
|
236
|
+
hourcomponent_id: The ID of the hour component to delete
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Response from the API
|
|
240
|
+
"""
|
|
241
|
+
# Create and validate a HoursDelete model
|
|
242
|
+
hours_model = HoursDelete(hourComponentId=hourcomponent_id)
|
|
243
|
+
|
|
244
|
+
if self.nmbrs.mock_mode:
|
|
245
|
+
return hours_model
|
|
246
|
+
|
|
247
|
+
# Send request
|
|
248
|
+
resp = self.nmbrs.session.delete(
|
|
249
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/hours/{hourcomponent_id}",
|
|
250
|
+
timeout=self.nmbrs.timeout
|
|
251
|
+
)
|
|
252
|
+
return resp
|
brynq_sdk_nmbrs/leave.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import requests
|
|
4
|
+
from brynq_sdk_functions import Functions
|
|
5
|
+
from typing import Dict, Any
|
|
6
|
+
from .schemas.leave import LeaveBalanceGet, LeaveGet, LeaveCreate
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Leave:
|
|
10
|
+
def __init__(self, nmbrs):
|
|
11
|
+
self.nmbrs = nmbrs
|
|
12
|
+
|
|
13
|
+
def get(self,
|
|
14
|
+
changed_from: str = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
15
|
+
leave = pd.DataFrame()
|
|
16
|
+
for company in self.nmbrs.company_ids:
|
|
17
|
+
leave = pd.concat([leave, self._get(company, changed_from)])
|
|
18
|
+
|
|
19
|
+
valid_leave, invalid_leave = Functions.validate_data(df=leave, schema=LeaveGet, debug=True)
|
|
20
|
+
|
|
21
|
+
return valid_leave, invalid_leave
|
|
22
|
+
|
|
23
|
+
def _get(self,
|
|
24
|
+
company_id: str,
|
|
25
|
+
changed_from: str = None) -> pd.DataFrame:
|
|
26
|
+
params = {}
|
|
27
|
+
if changed_from:
|
|
28
|
+
params['changed_from'] = changed_from
|
|
29
|
+
try:
|
|
30
|
+
request = requests.Request(method='GET',
|
|
31
|
+
url=f"{self.nmbrs.base_url}companies/{company_id}/employees/leaverequests",
|
|
32
|
+
params=params)
|
|
33
|
+
|
|
34
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
35
|
+
df = pd.json_normalize(
|
|
36
|
+
data,
|
|
37
|
+
record_path='EmployeeLeaveRequests',
|
|
38
|
+
meta=['employeeId']
|
|
39
|
+
)
|
|
40
|
+
except requests.HTTPError as e:
|
|
41
|
+
df = pd.DataFrame()
|
|
42
|
+
|
|
43
|
+
return df
|
|
44
|
+
|
|
45
|
+
def create(self, employee_id: str, data: Dict[str, Any]):
|
|
46
|
+
"""
|
|
47
|
+
Create a new leave request for an employee using Pydantic validation.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
employee_id: The ID of the employee
|
|
51
|
+
data: Dictionary containing leave request data in the format matching LeaveCreate schema
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Response from the API
|
|
55
|
+
"""
|
|
56
|
+
# Validate with Pydantic model - this will raise an error if required fields are missing
|
|
57
|
+
nested_data = self.nmbrs.flat_dict_to_nested_dict(data, LeaveCreate)
|
|
58
|
+
leave_model = LeaveCreate(**nested_data)
|
|
59
|
+
|
|
60
|
+
if self.nmbrs.mock_mode:
|
|
61
|
+
return leave_model
|
|
62
|
+
|
|
63
|
+
# Convert validated model to dict for API payload
|
|
64
|
+
payload = leave_model.model_dump(exclude_none=True, by_alias=True)
|
|
65
|
+
|
|
66
|
+
# Send request
|
|
67
|
+
resp = self.nmbrs.session.post(
|
|
68
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/leaverequest",
|
|
69
|
+
json=payload,
|
|
70
|
+
timeout=self.nmbrs.timeout
|
|
71
|
+
)
|
|
72
|
+
return resp
|
|
73
|
+
|
|
74
|
+
def delete(self, employee_id: str, leave_request_id: str):
|
|
75
|
+
"""
|
|
76
|
+
Delete a leave request for an employee.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
employee_id: The ID of the employee
|
|
80
|
+
leave_request_id: The ID of the leave request to delete
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Response from the API
|
|
84
|
+
"""
|
|
85
|
+
# Create and validate a BankDelete model
|
|
86
|
+
leave_model = LeaveDelete(leave_request_id=leave_request_id)
|
|
87
|
+
|
|
88
|
+
if self.nmbrs.mock_mode:
|
|
89
|
+
return leave_model
|
|
90
|
+
|
|
91
|
+
# Send request
|
|
92
|
+
resp = self.nmbrs.session.delete(
|
|
93
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/leave/{leave_request_id}",
|
|
94
|
+
timeout=self.nmbrs.timeout
|
|
95
|
+
)
|
|
96
|
+
return resp
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class LeaveBalance:
|
|
100
|
+
def __init__(self, nmbrs):
|
|
101
|
+
self.nmbrs = nmbrs
|
|
102
|
+
|
|
103
|
+
def get(self,
|
|
104
|
+
changed_from: str = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
105
|
+
leave = pd.DataFrame()
|
|
106
|
+
for company in self.nmbrs.company_ids:
|
|
107
|
+
leave = pd.concat([leave, self._get(company, changed_from)])
|
|
108
|
+
|
|
109
|
+
valid_leave, invalid_leave = Functions.validate_data(df=leave, schema=LeaveBalanceGet, debug=True)
|
|
110
|
+
|
|
111
|
+
return valid_leave, invalid_leave
|
|
112
|
+
|
|
113
|
+
def _get(self,
|
|
114
|
+
company_id: str) -> pd.DataFrame:
|
|
115
|
+
try:
|
|
116
|
+
request = requests.Request(method='GET',
|
|
117
|
+
url=f"{self.nmbrs.base_url}companies/{company_id}/employees/leaveBalances")
|
|
118
|
+
|
|
119
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
120
|
+
df = pd.json_normalize(
|
|
121
|
+
data,
|
|
122
|
+
record_path='leaveBalances',
|
|
123
|
+
meta=['employeeId']
|
|
124
|
+
)
|
|
125
|
+
except requests.HTTPError as e:
|
|
126
|
+
df = pd.DataFrame()
|
|
127
|
+
|
|
128
|
+
return df
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class LeaveGroup:
|
|
132
|
+
def __init__(self, nmbrs):
|
|
133
|
+
self.nmbrs = nmbrs
|
|
134
|
+
|
|
135
|
+
def get(self,
|
|
136
|
+
changed_from: str = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
137
|
+
leave = pd.DataFrame()
|
|
138
|
+
for company in self.nmbrs.company_ids:
|
|
139
|
+
leave = pd.concat([leave, self._get(company, changed_from)])
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import requests
|
|
3
|
+
from brynq_sdk_functions import Functions as BrynQFunctions
|
|
4
|
+
import math
|
|
5
|
+
from typing import Dict, Any
|
|
6
|
+
from .schemas.manager import (
|
|
7
|
+
ManagerGet, ManagerBasicGet, EmployeeManagerGet, ManagerHistoricBasicGet,
|
|
8
|
+
ManagerCreate, ManagerUpdate, ManagerDelete, UpdateEmployeeManager
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class EmployeeManager:
|
|
13
|
+
def __init__(self, nmbrs):
|
|
14
|
+
self.nmbrs = nmbrs
|
|
15
|
+
|
|
16
|
+
def get(self, created_from: str = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
17
|
+
"""
|
|
18
|
+
Get employee manager history for all companies.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
created_from: Optional filter to get managers created from a specific date
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Tuple of (valid_managers, invalid_managers) DataFrames
|
|
25
|
+
"""
|
|
26
|
+
managers = pd.DataFrame()
|
|
27
|
+
for company in self.nmbrs.company_ids:
|
|
28
|
+
managers = pd.concat([managers, self._get(company, created_from)])
|
|
29
|
+
|
|
30
|
+
valid_managers, invalid_managers = BrynQFunctions.validate_data(df=managers, schema=EmployeeManagerGet, debug=True)
|
|
31
|
+
|
|
32
|
+
return valid_managers, invalid_managers
|
|
33
|
+
|
|
34
|
+
def _get(self, company_id: str, created_from: str = None) -> pd.DataFrame:
|
|
35
|
+
"""
|
|
36
|
+
Get employee manager history for a specific company.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
company_id: The ID of the company
|
|
40
|
+
created_from: Optional filter to get managers created from a specific date
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
DataFrame containing employee manager data
|
|
44
|
+
"""
|
|
45
|
+
params = {}
|
|
46
|
+
if created_from:
|
|
47
|
+
params['createdFrom'] = created_from
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
request = requests.Request(
|
|
51
|
+
method='GET',
|
|
52
|
+
url=f"{self.nmbrs.base_url}companies/{company_id}/employees/managers",
|
|
53
|
+
params=params
|
|
54
|
+
)
|
|
55
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
56
|
+
df = pd.json_normalize(
|
|
57
|
+
data,
|
|
58
|
+
record_path='managers',
|
|
59
|
+
meta=['employeeId']
|
|
60
|
+
)
|
|
61
|
+
df['companyId'] = company_id
|
|
62
|
+
except requests.HTTPError as e:
|
|
63
|
+
df = pd.DataFrame()
|
|
64
|
+
|
|
65
|
+
return df
|
|
66
|
+
|
|
67
|
+
def get_historic_basic(self, created_from: str = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
68
|
+
"""
|
|
69
|
+
Get historic basic manager information for employees.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
created_from: Optional filter to get managers created from a specific date
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Tuple of (valid_managers, invalid_managers) DataFrames
|
|
76
|
+
"""
|
|
77
|
+
managers = pd.DataFrame()
|
|
78
|
+
for company in self.nmbrs.company_ids:
|
|
79
|
+
managers = pd.concat([managers, self._get_historic_basic(company, created_from)])
|
|
80
|
+
|
|
81
|
+
valid_managers, invalid_managers = BrynQFunctions.validate_data(df=managers, schema=ManagerHistoricBasicGet, debug=True)
|
|
82
|
+
|
|
83
|
+
return valid_managers, invalid_managers
|
|
84
|
+
|
|
85
|
+
def _get_historic_basic(self, company_id: str, created_from: str = None) -> pd.DataFrame:
|
|
86
|
+
"""
|
|
87
|
+
Get historic basic manager information for a specific company.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
company_id: The ID of the company
|
|
91
|
+
created_from: Optional filter to get managers created from a specific date
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
DataFrame containing historic basic manager data
|
|
95
|
+
"""
|
|
96
|
+
params = {}
|
|
97
|
+
if created_from:
|
|
98
|
+
params['createdFrom'] = created_from
|
|
99
|
+
|
|
100
|
+
try:
|
|
101
|
+
request = requests.Request(
|
|
102
|
+
method='GET',
|
|
103
|
+
url=f"{self.nmbrs.base_url}companies/{company_id}/employees/managers",
|
|
104
|
+
params=params
|
|
105
|
+
)
|
|
106
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
107
|
+
df = pd.json_normalize(
|
|
108
|
+
data,
|
|
109
|
+
record_path='managers',
|
|
110
|
+
meta=['employeeId']
|
|
111
|
+
)
|
|
112
|
+
df['companyId'] = company_id
|
|
113
|
+
except requests.HTTPError as e:
|
|
114
|
+
df = pd.DataFrame()
|
|
115
|
+
|
|
116
|
+
return df
|
|
117
|
+
|
|
118
|
+
def update(self, employee_id: str, data: Dict[str, Any]):
|
|
119
|
+
"""
|
|
120
|
+
Update the manager of a specific employee using Pydantic validation.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
employee_id: The ID of the employee
|
|
124
|
+
data: Dictionary containing manager data with fields matching
|
|
125
|
+
the UpdateEmployeeManager schema (using camelCase field names)
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Response from the API
|
|
129
|
+
"""
|
|
130
|
+
# Validate with Pydantic model
|
|
131
|
+
manager_model = UpdateEmployeeManager(**data)
|
|
132
|
+
|
|
133
|
+
if self.nmbrs.mock_mode:
|
|
134
|
+
return manager_model
|
|
135
|
+
|
|
136
|
+
# Convert validated model to dict for API payload
|
|
137
|
+
payload = manager_model.dict(exclude_none=True)
|
|
138
|
+
|
|
139
|
+
# Send request
|
|
140
|
+
resp = self.nmbrs.session.put(
|
|
141
|
+
url=f"{self.nmbrs.base_url}employees/{employee_id}/manager",
|
|
142
|
+
json=payload,
|
|
143
|
+
timeout=self.nmbrs.timeout
|
|
144
|
+
)
|
|
145
|
+
return resp
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class Manager:
|
|
149
|
+
def __init__(self, nmbrs):
|
|
150
|
+
self.nmbrs = nmbrs
|
|
151
|
+
|
|
152
|
+
def get(self, debtor_id: str) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
153
|
+
"""
|
|
154
|
+
Get all managers for a specific debtor.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
debtor_id: The ID of the debtor
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
Tuple of (valid_managers, invalid_managers) DataFrames
|
|
161
|
+
"""
|
|
162
|
+
try:
|
|
163
|
+
request = requests.Request(
|
|
164
|
+
method='GET',
|
|
165
|
+
url=f"{self.nmbrs.base_url}debtors/{debtor_id}/managers"
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
169
|
+
df = pd.DataFrame(data)
|
|
170
|
+
df['debtorId'] = debtor_id
|
|
171
|
+
|
|
172
|
+
valid_managers, invalid_managers = BrynQFunctions.validate_data(df=df, schema=ManagerGet, debug=True)
|
|
173
|
+
|
|
174
|
+
except requests.HTTPError as e:
|
|
175
|
+
df = pd.DataFrame()
|
|
176
|
+
valid_managers = df
|
|
177
|
+
invalid_managers = df
|
|
178
|
+
|
|
179
|
+
return valid_managers, invalid_managers
|
|
180
|
+
|
|
181
|
+
def get_basic(self, debtor_id: str) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
182
|
+
"""
|
|
183
|
+
Get basic manager information for a specific debtor.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
debtor_id: The ID of the debtor
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
Tuple of (valid_managers, invalid_managers) DataFrames
|
|
190
|
+
"""
|
|
191
|
+
try:
|
|
192
|
+
request = requests.Request(
|
|
193
|
+
method='GET',
|
|
194
|
+
url=f"{self.nmbrs.base_url}debtors/{debtor_id}/managers"
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
198
|
+
df = pd.DataFrame(data)
|
|
199
|
+
df['debtorId'] = debtor_id
|
|
200
|
+
|
|
201
|
+
valid_managers, invalid_managers = BrynQFunctions.validate_data(df=df, schema=ManagerBasicGet, debug=True)
|
|
202
|
+
|
|
203
|
+
except requests.HTTPError as e:
|
|
204
|
+
df = pd.DataFrame()
|
|
205
|
+
valid_managers = df
|
|
206
|
+
invalid_managers = df
|
|
207
|
+
|
|
208
|
+
return valid_managers, invalid_managers
|
|
209
|
+
|
|
210
|
+
def create(self, debtor_id: str, data: Dict[str, Any]):
|
|
211
|
+
"""
|
|
212
|
+
Create a new manager using Pydantic validation.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
debtor_id: The ID of the debtor
|
|
216
|
+
data: Dictionary containing manager data with fields matching
|
|
217
|
+
the ManagerCreate schema (using camelCase field names)
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
Response from the API
|
|
221
|
+
"""
|
|
222
|
+
# Validate with Pydantic model
|
|
223
|
+
manager_model = ManagerCreate(**data)
|
|
224
|
+
|
|
225
|
+
if self.nmbrs.mock_mode:
|
|
226
|
+
return manager_model
|
|
227
|
+
|
|
228
|
+
# Convert validated model to dict for API payload
|
|
229
|
+
payload = manager_model.dict(exclude_none=True)
|
|
230
|
+
|
|
231
|
+
# Send request
|
|
232
|
+
resp = self.nmbrs.session.post(
|
|
233
|
+
url=f"{self.nmbrs.base_url}debtors/{debtor_id}/managers",
|
|
234
|
+
json=payload,
|
|
235
|
+
timeout=self.nmbrs.timeout
|
|
236
|
+
)
|
|
237
|
+
return resp
|
|
238
|
+
|
|
239
|
+
def update(self, debtor_id: str, data: Dict[str, Any]):
|
|
240
|
+
"""
|
|
241
|
+
Update a manager using Pydantic validation.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
debtor_id: The ID of the debtor
|
|
245
|
+
data: Dictionary containing manager data with fields matching
|
|
246
|
+
the ManagerUpdate schema (using camelCase field names)
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
Response from the API
|
|
250
|
+
"""
|
|
251
|
+
# Validate with Pydantic model
|
|
252
|
+
manager_model = ManagerUpdate(**data)
|
|
253
|
+
|
|
254
|
+
if self.nmbrs.mock_mode:
|
|
255
|
+
return manager_model
|
|
256
|
+
|
|
257
|
+
# Convert validated model to dict for API payload
|
|
258
|
+
payload = manager_model.dict(exclude_none=True)
|
|
259
|
+
|
|
260
|
+
# Send request
|
|
261
|
+
resp = self.nmbrs.session.put(
|
|
262
|
+
url=f"{self.nmbrs.base_url}debtors/{debtor_id}/managers/{payload['managerId']}",
|
|
263
|
+
json=payload,
|
|
264
|
+
timeout=self.nmbrs.timeout
|
|
265
|
+
)
|
|
266
|
+
return resp
|
|
267
|
+
|
|
268
|
+
def delete(self, debtor_id: str, data: Dict[str, Any]):
|
|
269
|
+
"""
|
|
270
|
+
Delete a manager using Pydantic validation.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
debtor_id: The ID of the debtor
|
|
274
|
+
data: Dictionary containing manager data with fields matching
|
|
275
|
+
the ManagerDelete schema (using camelCase field names)
|
|
276
|
+
|
|
277
|
+
Returns:
|
|
278
|
+
Response from the API
|
|
279
|
+
"""
|
|
280
|
+
# Validate with Pydantic model
|
|
281
|
+
manager_model = ManagerDelete(**data)
|
|
282
|
+
|
|
283
|
+
if self.nmbrs.mock_mode:
|
|
284
|
+
return manager_model
|
|
285
|
+
|
|
286
|
+
# Convert validated model to dict for API payload
|
|
287
|
+
payload = manager_model.dict(exclude_none=True)
|
|
288
|
+
|
|
289
|
+
# Send request
|
|
290
|
+
resp = self.nmbrs.session.delete(
|
|
291
|
+
url=f"{self.nmbrs.base_url}debtors/{debtor_id}/managers/{payload['managerId']}",
|
|
292
|
+
timeout=self.nmbrs.timeout
|
|
293
|
+
)
|
|
294
|
+
return resp
|