brynq-sdk-nmbrs 2.3.4.dev0__py3-none-any.whl → 2.4.5__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 (51) hide show
  1. brynq_sdk_nmbrs/__init__.py +95 -91
  2. brynq_sdk_nmbrs/absence.py +1 -4
  3. brynq_sdk_nmbrs/address.py +5 -81
  4. brynq_sdk_nmbrs/bank.py +1 -2
  5. brynq_sdk_nmbrs/companies.py +130 -39
  6. brynq_sdk_nmbrs/contract.py +0 -1
  7. brynq_sdk_nmbrs/days.py +1 -1
  8. brynq_sdk_nmbrs/debtors.py +53 -65
  9. brynq_sdk_nmbrs/department.py +23 -111
  10. brynq_sdk_nmbrs/document.py +195 -4
  11. brynq_sdk_nmbrs/employee_wage_tax_settings.py +13 -5
  12. brynq_sdk_nmbrs/employees.py +55 -21
  13. brynq_sdk_nmbrs/employment.py +0 -2
  14. brynq_sdk_nmbrs/extra_fields.py +126 -0
  15. brynq_sdk_nmbrs/function.py +35 -97
  16. brynq_sdk_nmbrs/leave.py +53 -58
  17. brynq_sdk_nmbrs/manager.py +51 -35
  18. brynq_sdk_nmbrs/salaries.py +48 -65
  19. brynq_sdk_nmbrs/salary_tables.py +1 -4
  20. brynq_sdk_nmbrs/schedules.py +5 -78
  21. brynq_sdk_nmbrs/schemas/absence.py +26 -16
  22. brynq_sdk_nmbrs/schemas/address.py +2 -29
  23. brynq_sdk_nmbrs/schemas/children.py +0 -2
  24. brynq_sdk_nmbrs/schemas/contracts.py +7 -6
  25. brynq_sdk_nmbrs/schemas/costcenter.py +2 -2
  26. brynq_sdk_nmbrs/schemas/costunit.py +2 -0
  27. brynq_sdk_nmbrs/schemas/days.py +13 -11
  28. brynq_sdk_nmbrs/schemas/debtor.py +6 -28
  29. brynq_sdk_nmbrs/schemas/department.py +5 -39
  30. brynq_sdk_nmbrs/schemas/document.py +0 -2
  31. brynq_sdk_nmbrs/schemas/employee_wage_tax_settings.py +75 -0
  32. brynq_sdk_nmbrs/schemas/employees.py +2 -0
  33. brynq_sdk_nmbrs/schemas/extra_fields.py +56 -0
  34. brynq_sdk_nmbrs/schemas/function.py +5 -32
  35. brynq_sdk_nmbrs/schemas/hours.py +5 -1
  36. brynq_sdk_nmbrs/schemas/leave.py +17 -6
  37. brynq_sdk_nmbrs/schemas/manager.py +11 -20
  38. brynq_sdk_nmbrs/schemas/salary.py +11 -1
  39. brynq_sdk_nmbrs/schemas/schedules.py +2 -54
  40. brynq_sdk_nmbrs/schemas/svw_settings.py +116 -0
  41. brynq_sdk_nmbrs/schemas/wage_tax.py +53 -21
  42. brynq_sdk_nmbrs/schemas/wagecomponents.py +6 -9
  43. brynq_sdk_nmbrs/svw_settings.py +213 -0
  44. brynq_sdk_nmbrs/wage_tax.py +120 -11
  45. {brynq_sdk_nmbrs-2.3.4.dev0.dist-info → brynq_sdk_nmbrs-2.4.5.dist-info}/METADATA +1 -1
  46. brynq_sdk_nmbrs-2.4.5.dist-info/RECORD +58 -0
  47. brynq_sdk_nmbrs/schemas/social_insurance.py +0 -73
  48. brynq_sdk_nmbrs/social_insurance.py +0 -130
  49. brynq_sdk_nmbrs-2.3.4.dev0.dist-info/RECORD +0 -55
  50. {brynq_sdk_nmbrs-2.3.4.dev0.dist-info → brynq_sdk_nmbrs-2.4.5.dist-info}/WHEEL +0 -0
  51. {brynq_sdk_nmbrs-2.3.4.dev0.dist-info → brynq_sdk_nmbrs-2.4.5.dist-info}/top_level.txt +0 -0
@@ -1,20 +1,36 @@
1
+
1
2
  import pandas as pd
2
3
  import requests
3
- from typing import Dict, Any
4
- from zeep.exceptions import Fault
4
+
5
5
  from brynq_sdk_functions import Functions
6
+
6
7
  from .department import Departments
7
8
  from .function import Functions as NmbrsFunctions
8
- from .schemas.debtor import DebtorsGet, DebtorCreate, DebtorUpdate
9
+ from .schemas.debtor import DebtorsGet
9
10
 
10
11
 
11
12
  class Debtors:
13
+ """
14
+ Class for handling debtor information.
15
+
16
+ Endpoints:
17
+ - GET /api/debtors
18
+ - GET /api/debtors/info
19
+ - GET /api/debtors/endcontractreasons/{Year}
20
+ """
21
+
12
22
  def __init__(self, nmbrs):
13
23
  self.nmbrs = nmbrs
14
24
  self.departments = Departments(nmbrs)
15
25
  self.functions = NmbrsFunctions(nmbrs)
16
26
 
17
- def get(self) -> (pd.DataFrame, pd.DataFrame):
27
+ def get(self) -> tuple:
28
+ """
29
+ Get a list of all debtors for the authenticated user.
30
+
31
+ Returns:
32
+ Tuple of (valid_data, invalid_data) DataFrames
33
+ """
18
34
  request = requests.Request(method='GET',
19
35
  url=f"{self.nmbrs.base_url}debtors")
20
36
  data = self.nmbrs.get_paginated_result(request)
@@ -25,75 +41,47 @@ class Debtors:
25
41
 
26
42
  return valid_debtors, invalid_debtors
27
43
 
28
- def create(self, data: Dict[str, Any]) -> int:
44
+ def get_info(self) -> pd.DataFrame:
29
45
  """
30
- Create a new debtor using SOAP API.
46
+ Get information about the authenticated debtor.
31
47
 
32
- Args:
33
- data: Dictionary containing debtor data with fields matching DebtorCreate schema:
34
- - number: Debtor number
35
- - name: Debtor name
48
+ Returns info about the debtor that the API keys belong to,
49
+ including current settings and subscription details.
36
50
 
37
51
  Returns:
38
- The ID of the newly created debtor.
52
+ DataFrame containing debtor info
39
53
  """
40
- debtor_model = DebtorCreate(**data)
41
-
42
- if self.nmbrs.mock_mode:
43
- return 12345 # Mock ID
44
-
45
- try:
46
- DebtorType = self.nmbrs.soap_client_debtors.get_type('ns0:Debtor')
47
- soap_debtor = DebtorType(
48
- Id=0, # 0 for new debtor
49
- Number=debtor_model.number,
50
- Name=debtor_model.name
51
- )
52
-
53
- response = self.nmbrs.soap_client_debtors.service.Debtor_Insert(
54
- Debtor=soap_debtor,
55
- _soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_debtors}
56
- )
57
- return response
58
-
59
- except Fault as e:
60
- raise Exception(f"SOAP request failed: {str(e)}")
61
- except Exception as e:
62
- raise Exception(f"Failed to create Debtor: {str(e)}")
63
-
64
- def update(self, data: Dict[str, Any]):
54
+ resp = self.nmbrs.session.get(
55
+ url=f"{self.nmbrs.base_url}debtors/info",
56
+ timeout=self.nmbrs.timeout
57
+ )
58
+ resp.raise_for_status()
59
+ data = resp.json()
60
+
61
+ # Normalize the response if it's a dict
62
+ if isinstance(data, dict):
63
+ df = pd.json_normalize(data)
64
+ else:
65
+ df = pd.DataFrame(data)
66
+
67
+ return df
68
+
69
+ def get_end_contract_reasons(self, year: int) -> pd.DataFrame:
65
70
  """
66
- Update a debtor using SOAP API.
71
+ Get the available end contract reasons for a specific year.
67
72
 
68
73
  Args:
69
- data: Dictionary containing debtor data with fields matching DebtorUpdate schema:
70
- - debtor_id: Debtor ID to update
71
- - number: Debtor number
72
- - name: Debtor name
74
+ year: The year to get end contract reasons for
73
75
 
74
76
  Returns:
75
- Response from the API
77
+ DataFrame containing end contract reasons
76
78
  """
77
- debtor_model = DebtorUpdate(**data)
78
-
79
- if self.nmbrs.mock_mode:
80
- return debtor_model
81
-
82
- try:
83
- DebtorType = self.nmbrs.soap_client_debtors.get_type('ns0:Debtor')
84
- soap_debtor = DebtorType(
85
- Id=debtor_model.debtor_id,
86
- Number=debtor_model.number,
87
- Name=debtor_model.name
88
- )
89
-
90
- response = self.nmbrs.soap_client_debtors.service.Debtor_Update(
91
- Debtor=soap_debtor,
92
- _soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_debtors}
93
- )
94
- return response
95
-
96
- except Fault as e:
97
- raise Exception(f"SOAP request failed: {str(e)}")
98
- except Exception as e:
99
- raise Exception(f"Failed to update Debtor: {str(e)}")
79
+ request = requests.Request(
80
+ method='GET',
81
+ url=f"{self.nmbrs.base_url}debtors/endcontractreasons/{year}"
82
+ )
83
+
84
+ data = self.nmbrs.get_paginated_result(request)
85
+ df = pd.DataFrame(data)
86
+
87
+ return df
@@ -2,19 +2,13 @@ from typing import Any, Dict
2
2
 
3
3
  import pandas as pd
4
4
  import requests
5
- from zeep.exceptions import Fault
6
5
 
7
6
  from brynq_sdk_functions import Functions
8
7
 
9
8
  from .schemas.department import (
10
- DepartmentCreate,
11
9
  DepartmentGet,
12
- DepartmentMasterCreate,
13
- DepartmentMasterDelete,
14
- DepartmentMasterUpdate,
15
10
  EmployeeDepartmentGet,
16
11
  EmployeeDepartmentUpdate,
17
- Period,
18
12
  )
19
13
 
20
14
 
@@ -119,125 +113,43 @@ class EmployeeDepartment:
119
113
 
120
114
  class Departments:
121
115
  """Master department operations (Debtor level) - uses SOAP for create/update/delete."""
122
-
116
+
123
117
  def __init__(self, nmbrs):
124
118
  self.nmbrs = nmbrs
125
119
 
126
- def get(self,
127
- debtor_id: str) -> pd.DataFrame:
128
- request = requests.Request(method='GET',
129
- url=f"{self.nmbrs.base_url}debtors/{debtor_id}/departments")
130
-
131
- data = self.nmbrs.get_paginated_result(request)
132
-
133
- df = pd.DataFrame(data)
134
- valid_departments, invalid_departments = Functions.validate_data(df=df, schema=DepartmentGet, debug=True)
135
-
136
- return valid_departments, invalid_departments
137
-
138
- def create(self, data: Dict[str, Any]) -> int:
120
+ def get(self, debtor_id: str = None) -> tuple[pd.DataFrame, pd.DataFrame]:
139
121
  """
140
- Create a new master department for a debtor using SOAP API.
122
+ Get all departments for debtor(s).
141
123
 
142
124
  Args:
143
- data: Dictionary containing department data with fields matching DepartmentMasterCreate schema:
144
- - debtor_id: Debtor ID
145
- - code: Department code
146
- - description: Department description
125
+ debtor_id: Optional debtor ID. If not provided, fetches for all debtors.
147
126
 
148
127
  Returns:
149
- The ID of the newly created department.
128
+ Tuple of (valid_departments, invalid_departments) DataFrames
150
129
  """
151
- dept_model = DepartmentMasterCreate(**data)
130
+ if debtor_id:
131
+ df = self._get(debtor_id)
132
+ else:
133
+ df = pd.DataFrame()
134
+ for debtor in self.nmbrs.debtor_ids:
135
+ df = pd.concat([df, self._get(debtor)])
152
136
 
153
- if self.nmbrs.mock_mode:
154
- return 12345 # Mock ID
155
-
156
- try:
157
- DepartmentType = self.nmbrs.soap_client_debtors.get_type('ns0:Department')
158
- soap_department = DepartmentType(
159
- Id=0, # 0 for new department
160
- Code=dept_model.code,
161
- Description=dept_model.description
162
- )
163
-
164
- response = self.nmbrs.soap_client_debtors.service.Department_Insert(
165
- DebtorId=dept_model.debtor_id,
166
- department=soap_department,
167
- _soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_debtors}
168
- )
169
- return response
170
-
171
- except Fault as e:
172
- raise Exception(f"SOAP request failed: {str(e)}")
173
- except Exception as e:
174
- raise Exception(f"Failed to create Department: {str(e)}")
175
-
176
- def update(self, data: Dict[str, Any]):
177
- """
178
- Update a master department for a debtor using SOAP API.
137
+ if df.empty:
138
+ return df, pd.DataFrame()
179
139
 
180
- Args:
181
- data: Dictionary containing department data with fields matching DepartmentMasterUpdate schema:
182
- - debtor_id: Debtor ID
183
- - department_id: Department ID to update
184
- - code: Department code
185
- - description: Department description
140
+ valid_departments, invalid_departments = Functions.validate_data(df=df, schema=DepartmentGet, debug=self.nmbrs.debug)
141
+ return valid_departments, invalid_departments
186
142
 
187
- Returns:
188
- Response from the API
143
+ def _get(self, debtor_id: str) -> pd.DataFrame:
189
144
  """
190
- dept_model = DepartmentMasterUpdate(**data)
191
-
192
- if self.nmbrs.mock_mode:
193
- return dept_model
194
-
195
- try:
196
- DepartmentType = self.nmbrs.soap_client_debtors.get_type('ns0:Department')
197
- soap_department = DepartmentType(
198
- Id=dept_model.department_id,
199
- Code=dept_model.code,
200
- Description=dept_model.description
201
- )
202
-
203
- response = self.nmbrs.soap_client_debtors.service.Department_Update(
204
- DebtorId=dept_model.debtor_id,
205
- department=soap_department,
206
- _soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_debtors}
207
- )
208
- return response
209
-
210
- except Fault as e:
211
- raise Exception(f"SOAP request failed: {str(e)}")
212
- except Exception as e:
213
- raise Exception(f"Failed to update Department: {str(e)}")
214
-
215
- def delete(self, data: Dict[str, Any]):
145
+ Internal method to get departments for a single debtor.
216
146
  """
217
- Delete a master department for a debtor using SOAP API.
147
+ request = requests.Request(method='GET',
148
+ url=f"{self.nmbrs.base_url}debtors/{debtor_id}/departments")
218
149
 
219
- Args:
220
- data: Dictionary containing department data with fields matching DepartmentMasterDelete schema:
221
- - debtor_id: Debtor ID
222
- - department_id: Department ID to delete
150
+ data = self.nmbrs.get_paginated_result(request)
223
151
 
224
- Returns:
225
- Response from the API
226
- """
227
- dept_model = DepartmentMasterDelete(**data)
152
+ df = pd.DataFrame(data)
153
+ df['debtorId'] = debtor_id
228
154
 
229
- if self.nmbrs.mock_mode:
230
- return True
231
-
232
- try:
233
- response = self.nmbrs.soap_client_debtors.service.Department_Delete(
234
- DebtorId=dept_model.debtor_id,
235
- id=dept_model.department_id,
236
- _soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_debtors}
237
- )
238
- return response
239
-
240
- except Fault as e:
241
- raise Exception(f"SOAP request failed: {str(e)}")
242
- except Exception as e:
243
- raise Exception(f"Failed to delete Department: {str(e)}")
155
+ return df
@@ -1,6 +1,6 @@
1
- from io import BytesIO
2
1
  import base64
3
- from typing import Dict, Any, Union
2
+ from io import BytesIO
3
+ from typing import Any, BinaryIO, Dict, Optional
4
4
 
5
5
  import pandas as pd
6
6
  import requests
@@ -11,7 +11,7 @@ from .schemas.document import DocumentUpload
11
11
 
12
12
  class EmployeeDocument:
13
13
  """Handle employee document operations via SOAP API."""
14
-
14
+
15
15
  def __init__(self, nmbrs):
16
16
  self.nmbrs = nmbrs
17
17
 
@@ -55,13 +55,31 @@ class EmployeeDocument:
55
55
 
56
56
 
57
57
  class Payslip:
58
+ """
59
+ Class for handling employee payslips.
60
+
61
+ Endpoints:
62
+ - GET /api/employees/{employeeId}/payslipperperiod
63
+ """
64
+
58
65
  def __init__(self, nmbrs):
59
66
  self.nmbrs = nmbrs
60
67
 
61
68
  def get(self,
62
69
  employee_id: str,
63
70
  period: int = None,
64
- year: int = None) -> pd.DataFrame:
71
+ year: int = None) -> BytesIO:
72
+ """
73
+ Get an employee payslip per period.
74
+
75
+ Args:
76
+ employee_id: The ID of the employee
77
+ period: Optional period number
78
+ year: Optional year
79
+
80
+ Returns:
81
+ BytesIO containing the payslip PDF
82
+ """
65
83
  params = {}
66
84
  if period:
67
85
  params['period'] = period
@@ -78,3 +96,176 @@ class Payslip:
78
96
  return BytesIO(resp.content)
79
97
 
80
98
 
99
+ class Document:
100
+ """
101
+ Class for handling employee documents.
102
+
103
+ Endpoints:
104
+ - GET /api/employees/{employeeId}/annualstatement
105
+ - GET /api/employees/{employeeId}/documents/types
106
+ - GET /api/employees/{employeeId}/documents/folders
107
+ - POST /api/employees/{employeeId}/documents
108
+ - GET /api/documents/{taskId}
109
+ """
110
+
111
+ def __init__(self, nmbrs):
112
+ self.nmbrs = nmbrs
113
+
114
+ def get_annual_statement(self, employee_id: str, year: Optional[int] = None) -> BytesIO:
115
+ """
116
+ Get an employee annual statement for the given year.
117
+
118
+ Args:
119
+ employee_id: The ID of the employee
120
+ year: Optional year filter
121
+
122
+ Returns:
123
+ BytesIO containing the annual statement PDF
124
+ """
125
+ params = {}
126
+ if year is not None:
127
+ params['year'] = year
128
+
129
+ resp = self.nmbrs.session.get(
130
+ f"{self.nmbrs.base_url}employees/{employee_id}/annualstatement",
131
+ params=params,
132
+ timeout=self.nmbrs.timeout
133
+ )
134
+ resp.raise_for_status()
135
+ task_id = resp.json()['taskId']
136
+
137
+ # Retrieve the actual document content
138
+ resp = self.nmbrs.session.get(
139
+ f"{self.nmbrs.base_url}documents/{task_id}",
140
+ timeout=self.nmbrs.timeout
141
+ )
142
+
143
+ return BytesIO(resp.content)
144
+
145
+ def get_types(self, employee_id: str) -> pd.DataFrame:
146
+ """
147
+ Get the document types available for a specific employee.
148
+
149
+ Args:
150
+ employee_id: The ID of the employee
151
+
152
+ Returns:
153
+ DataFrame containing document types
154
+ """
155
+ request = requests.Request(
156
+ method='GET',
157
+ url=f"{self.nmbrs.base_url}employees/{employee_id}/documents/types"
158
+ )
159
+
160
+ data = self.nmbrs.get_paginated_result(request)
161
+ return pd.DataFrame(data)
162
+
163
+ def get_folders(self, employee_id: str) -> pd.DataFrame:
164
+ """
165
+ Get document folders for a specific employee.
166
+
167
+ Args:
168
+ employee_id: The ID of the employee
169
+
170
+ Returns:
171
+ DataFrame containing document folders
172
+ """
173
+ request = requests.Request(
174
+ method='GET',
175
+ url=f"{self.nmbrs.base_url}employees/{employee_id}/documents/folders"
176
+ )
177
+
178
+ data = self.nmbrs.get_paginated_result(request)
179
+ return pd.DataFrame(data)
180
+
181
+ def upload(self,
182
+ employee_id: str,
183
+ file: BinaryIO,
184
+ file_name: str,
185
+ file_extension: str,
186
+ document_type: str,
187
+ description: Optional[str] = None,
188
+ number: Optional[str] = None,
189
+ is_visible_for_employee: Optional[bool] = None,
190
+ folder: Optional[str] = None,
191
+ valid_from: Optional[str] = None,
192
+ valid_to: Optional[str] = None):
193
+ """
194
+ Upload a document for a specific employee.
195
+
196
+ Args:
197
+ employee_id: The ID of the employee
198
+ file: Binary file content to upload
199
+ file_name: Name of the file
200
+ file_extension: Extension of the file (e.g., "pdf", "docx")
201
+ document_type: Type of the document
202
+ description: Optional description of the document
203
+ number: Optional document number
204
+ is_visible_for_employee: Optional flag if document is visible for employee
205
+ folder: Optional folder UUID to place document in
206
+ valid_from: Optional valid from date (ISO format)
207
+ valid_to: Optional valid to date (ISO format)
208
+
209
+ Returns:
210
+ Response from the API
211
+ """
212
+ if self.nmbrs.mock_mode:
213
+ return {
214
+ 'employee_id': employee_id,
215
+ 'file_name': file_name,
216
+ 'file_extension': file_extension,
217
+ 'document_type': document_type,
218
+ 'description': description
219
+ }
220
+
221
+ # Prepare multipart form data
222
+ files = {
223
+ 'file': (file_name, file)
224
+ }
225
+
226
+ data = {
227
+ 'fileName': file_name,
228
+ 'fileExtension': file_extension,
229
+ 'type': document_type
230
+ }
231
+
232
+ if description is not None:
233
+ data['description'] = description
234
+ if number is not None:
235
+ data['number'] = number
236
+ if is_visible_for_employee is not None:
237
+ data['isVisibleForEmployee'] = str(is_visible_for_employee).lower()
238
+ if folder is not None:
239
+ data['folder'] = folder
240
+ if valid_from is not None:
241
+ data['validFrom'] = valid_from
242
+ if valid_to is not None:
243
+ data['validTo'] = valid_to
244
+
245
+ resp = self.nmbrs.session.post(
246
+ url=f"{self.nmbrs.base_url}employees/{employee_id}/documents",
247
+ data=data,
248
+ files=files,
249
+ timeout=self.nmbrs.timeout
250
+ )
251
+ resp.raise_for_status()
252
+ return resp.json()
253
+
254
+ def get_content(self, task_id: str) -> BytesIO:
255
+ """
256
+ Get document content by task ID.
257
+
258
+ Use this to retrieve documents after getting a task ID from other endpoints.
259
+
260
+ Args:
261
+ task_id: The task ID from a previous document request
262
+
263
+ Returns:
264
+ BytesIO containing the document content
265
+ """
266
+ resp = self.nmbrs.session.get(
267
+ f"{self.nmbrs.base_url}documents/{task_id}",
268
+ timeout=self.nmbrs.timeout
269
+ )
270
+
271
+ return BytesIO(resp.content)
@@ -1,4 +1,4 @@
1
- from typing import Any, Dict
1
+ from typing import Any, Dict, Optional
2
2
 
3
3
  import pandas as pd
4
4
  import requests
@@ -16,7 +16,9 @@ class EmployeeWageTaxSettings:
16
16
  self.nmbrs = nmbrs
17
17
 
18
18
  def get(self,
19
- employee_id: str = None) -> tuple[pd.DataFrame, pd.DataFrame]:
19
+ company_id: Optional[str] = None,
20
+ employee_id: str = None,
21
+ created_from: Optional[str] = None) -> tuple[pd.DataFrame, pd.DataFrame]:
20
22
  """
21
23
  Get wage tax settings history for employees in companies.
22
24
 
@@ -27,8 +29,11 @@ class EmployeeWageTaxSettings:
27
29
  Tuple of (valid_data, invalid_data) DataFrames
28
30
  """
29
31
  wage_tax_settings = pd.DataFrame()
30
- for company in self.nmbrs.company_ids:
31
- wage_tax_settings = pd.concat([wage_tax_settings, self._get(company, employee_id)])
32
+ if company_id:
33
+ wage_tax_settings = self._get(company_id, employee_id, created_from)
34
+ else:
35
+ for company in self.nmbrs.company_ids:
36
+ wage_tax_settings = pd.concat([wage_tax_settings, self._get(company, employee_id, created_from)])
32
37
 
33
38
  valid_settings, invalid_settings = Functions.validate_data(
34
39
  df=wage_tax_settings, schema=EmployeeWageTaxSettingsGet, debug=True
@@ -38,7 +43,8 @@ class EmployeeWageTaxSettings:
38
43
 
39
44
  def _get(self,
40
45
  company_id: str,
41
- employee_id: str = None) -> pd.DataFrame:
46
+ employee_id: str = None,
47
+ created_from: Optional[str] = None) -> pd.DataFrame:
42
48
  """
43
49
  Get wage tax settings history for a specific company.
44
50
 
@@ -52,6 +58,8 @@ class EmployeeWageTaxSettings:
52
58
  params = {}
53
59
  if employee_id:
54
60
  params['employeeId'] = employee_id
61
+ if created_from is not None:
62
+ params['createdFrom'] = created_from
55
63
 
56
64
  request = requests.Request(
57
65
  method='GET',