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.
- brynq_sdk_nmbrs/__init__.py +95 -91
- brynq_sdk_nmbrs/absence.py +1 -4
- brynq_sdk_nmbrs/address.py +5 -81
- brynq_sdk_nmbrs/bank.py +1 -2
- brynq_sdk_nmbrs/companies.py +130 -39
- brynq_sdk_nmbrs/contract.py +0 -1
- brynq_sdk_nmbrs/days.py +1 -1
- brynq_sdk_nmbrs/debtors.py +53 -65
- brynq_sdk_nmbrs/department.py +23 -111
- brynq_sdk_nmbrs/document.py +195 -4
- brynq_sdk_nmbrs/employee_wage_tax_settings.py +13 -5
- brynq_sdk_nmbrs/employees.py +55 -21
- brynq_sdk_nmbrs/employment.py +0 -2
- brynq_sdk_nmbrs/extra_fields.py +126 -0
- brynq_sdk_nmbrs/function.py +35 -97
- brynq_sdk_nmbrs/leave.py +53 -58
- brynq_sdk_nmbrs/manager.py +51 -35
- brynq_sdk_nmbrs/salaries.py +48 -65
- brynq_sdk_nmbrs/salary_tables.py +1 -4
- brynq_sdk_nmbrs/schedules.py +5 -78
- brynq_sdk_nmbrs/schemas/absence.py +26 -16
- brynq_sdk_nmbrs/schemas/address.py +2 -29
- brynq_sdk_nmbrs/schemas/children.py +0 -2
- brynq_sdk_nmbrs/schemas/contracts.py +7 -6
- brynq_sdk_nmbrs/schemas/costcenter.py +2 -2
- brynq_sdk_nmbrs/schemas/costunit.py +2 -0
- brynq_sdk_nmbrs/schemas/days.py +13 -11
- brynq_sdk_nmbrs/schemas/debtor.py +6 -28
- brynq_sdk_nmbrs/schemas/department.py +5 -39
- brynq_sdk_nmbrs/schemas/document.py +0 -2
- brynq_sdk_nmbrs/schemas/employee_wage_tax_settings.py +75 -0
- brynq_sdk_nmbrs/schemas/employees.py +2 -0
- brynq_sdk_nmbrs/schemas/extra_fields.py +56 -0
- brynq_sdk_nmbrs/schemas/function.py +5 -32
- brynq_sdk_nmbrs/schemas/hours.py +5 -1
- brynq_sdk_nmbrs/schemas/leave.py +17 -6
- brynq_sdk_nmbrs/schemas/manager.py +11 -20
- brynq_sdk_nmbrs/schemas/salary.py +11 -1
- brynq_sdk_nmbrs/schemas/schedules.py +2 -54
- brynq_sdk_nmbrs/schemas/svw_settings.py +116 -0
- brynq_sdk_nmbrs/schemas/wage_tax.py +53 -21
- brynq_sdk_nmbrs/schemas/wagecomponents.py +6 -9
- brynq_sdk_nmbrs/svw_settings.py +213 -0
- brynq_sdk_nmbrs/wage_tax.py +120 -11
- {brynq_sdk_nmbrs-2.3.4.dev0.dist-info → brynq_sdk_nmbrs-2.4.5.dist-info}/METADATA +1 -1
- brynq_sdk_nmbrs-2.4.5.dist-info/RECORD +58 -0
- brynq_sdk_nmbrs/schemas/social_insurance.py +0 -73
- brynq_sdk_nmbrs/social_insurance.py +0 -130
- brynq_sdk_nmbrs-2.3.4.dev0.dist-info/RECORD +0 -55
- {brynq_sdk_nmbrs-2.3.4.dev0.dist-info → brynq_sdk_nmbrs-2.4.5.dist-info}/WHEEL +0 -0
- {brynq_sdk_nmbrs-2.3.4.dev0.dist-info → brynq_sdk_nmbrs-2.4.5.dist-info}/top_level.txt +0 -0
brynq_sdk_nmbrs/manager.py
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
1
3
|
import pandas as pd
|
|
2
4
|
import requests
|
|
5
|
+
|
|
3
6
|
from brynq_sdk_functions import Functions as BrynQFunctions
|
|
4
|
-
|
|
5
|
-
from typing import Dict, Any
|
|
7
|
+
|
|
6
8
|
from .schemas.manager import (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
EmployeeManagerGet,
|
|
10
|
+
ManagerBasicGet,
|
|
11
|
+
ManagerCreate,
|
|
12
|
+
ManagerDelete,
|
|
13
|
+
ManagerGet,
|
|
14
|
+
ManagerHistoricBasicGet,
|
|
15
|
+
ManagerUpdate,
|
|
16
|
+
UpdateEmployeeManager,
|
|
9
17
|
)
|
|
10
18
|
|
|
11
19
|
|
|
@@ -127,16 +135,17 @@ class EmployeeManager:
|
|
|
127
135
|
Returns:
|
|
128
136
|
Response from the API
|
|
129
137
|
"""
|
|
130
|
-
# Validate with Pydantic model
|
|
131
138
|
manager_model = UpdateEmployeeManager(**data)
|
|
132
139
|
|
|
133
140
|
if self.nmbrs.mock_mode:
|
|
134
141
|
return manager_model
|
|
135
142
|
|
|
136
|
-
|
|
137
|
-
|
|
143
|
+
payload = manager_model.model_dump(by_alias=True, exclude_none=True)
|
|
144
|
+
|
|
145
|
+
# because of nmbrs bug, it needs to be passed (without year and period) as empty dict if not in the data.
|
|
146
|
+
if 'periodDetails' not in payload or payload.get('periodDetails') is None:
|
|
147
|
+
payload['periodDetails'] = {}
|
|
138
148
|
|
|
139
|
-
# Send request
|
|
140
149
|
resp = self.nmbrs.session.put(
|
|
141
150
|
url=f"{self.nmbrs.base_url}employees/{employee_id}/manager",
|
|
142
151
|
json=payload,
|
|
@@ -149,16 +158,33 @@ class Manager:
|
|
|
149
158
|
def __init__(self, nmbrs):
|
|
150
159
|
self.nmbrs = nmbrs
|
|
151
160
|
|
|
152
|
-
def get(self, debtor_id: str) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
161
|
+
def get(self, debtor_id: str = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
153
162
|
"""
|
|
154
|
-
Get all managers for
|
|
163
|
+
Get all managers for debtor(s).
|
|
155
164
|
|
|
156
165
|
Args:
|
|
157
|
-
debtor_id:
|
|
166
|
+
debtor_id: Optional debtor ID. If not provided, fetches for all debtors.
|
|
158
167
|
|
|
159
168
|
Returns:
|
|
160
169
|
Tuple of (valid_managers, invalid_managers) DataFrames
|
|
161
170
|
"""
|
|
171
|
+
if debtor_id:
|
|
172
|
+
df = self._get(debtor_id)
|
|
173
|
+
else:
|
|
174
|
+
df = pd.DataFrame()
|
|
175
|
+
for debtor in self.nmbrs.debtor_ids:
|
|
176
|
+
df = pd.concat([df, self._get(debtor)])
|
|
177
|
+
|
|
178
|
+
if df.empty:
|
|
179
|
+
return df, pd.DataFrame()
|
|
180
|
+
|
|
181
|
+
valid_managers, invalid_managers = BrynQFunctions.validate_data(df=df, schema=ManagerGet, debug=self.nmbrs.debug)
|
|
182
|
+
return valid_managers, invalid_managers
|
|
183
|
+
|
|
184
|
+
def _get(self, debtor_id: str) -> pd.DataFrame:
|
|
185
|
+
"""
|
|
186
|
+
Internal method to get managers for a single debtor.
|
|
187
|
+
"""
|
|
162
188
|
try:
|
|
163
189
|
request = requests.Request(
|
|
164
190
|
method='GET',
|
|
@@ -169,42 +195,32 @@ class Manager:
|
|
|
169
195
|
df = pd.DataFrame(data)
|
|
170
196
|
df['debtorId'] = debtor_id
|
|
171
197
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
except requests.HTTPError as e:
|
|
198
|
+
except requests.HTTPError:
|
|
175
199
|
df = pd.DataFrame()
|
|
176
|
-
valid_managers = df
|
|
177
|
-
invalid_managers = df
|
|
178
200
|
|
|
179
|
-
return
|
|
201
|
+
return df
|
|
180
202
|
|
|
181
|
-
def get_basic(self, debtor_id: str) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
203
|
+
def get_basic(self, debtor_id: str = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
182
204
|
"""
|
|
183
|
-
Get basic manager information for
|
|
205
|
+
Get basic manager information for debtor(s).
|
|
184
206
|
|
|
185
207
|
Args:
|
|
186
|
-
debtor_id:
|
|
208
|
+
debtor_id: Optional debtor ID. If not provided, fetches for all debtors.
|
|
187
209
|
|
|
188
210
|
Returns:
|
|
189
211
|
Tuple of (valid_managers, invalid_managers) DataFrames
|
|
190
212
|
"""
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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:
|
|
213
|
+
if debtor_id:
|
|
214
|
+
df = self._get(debtor_id)
|
|
215
|
+
else:
|
|
204
216
|
df = pd.DataFrame()
|
|
205
|
-
|
|
206
|
-
|
|
217
|
+
for debtor in self.nmbrs.debtor_ids:
|
|
218
|
+
df = pd.concat([df, self._get(debtor)])
|
|
219
|
+
|
|
220
|
+
if df.empty:
|
|
221
|
+
return df, pd.DataFrame()
|
|
207
222
|
|
|
223
|
+
valid_managers, invalid_managers = BrynQFunctions.validate_data(df=df, schema=ManagerBasicGet, debug=self.nmbrs.debug)
|
|
208
224
|
return valid_managers, invalid_managers
|
|
209
225
|
|
|
210
226
|
def create(self, debtor_id: str, data: Dict[str, Any]):
|
brynq_sdk_nmbrs/salaries.py
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
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
|
|
5
|
-
from zeep.exceptions import Fault
|
|
6
|
-
from zeep.helpers import serialize_object
|
|
7
5
|
|
|
8
6
|
from brynq_sdk_functions import Functions
|
|
9
7
|
|
|
10
|
-
from .schemas.salary import SalaryCreate, SalaryGet
|
|
8
|
+
from .schemas.salary import SalaryCreate, SalaryGet
|
|
11
9
|
|
|
12
10
|
|
|
13
11
|
class Salaries:
|
|
@@ -88,73 +86,58 @@ class Salaries:
|
|
|
88
86
|
)
|
|
89
87
|
return resp
|
|
90
88
|
|
|
91
|
-
def
|
|
89
|
+
def get_cost_per_hour(self,
|
|
90
|
+
company_id: Optional[str] = None,
|
|
91
|
+
employee_id: Optional[str] = None,
|
|
92
|
+
year: Optional[int] = None,
|
|
93
|
+
period: Optional[int] = None) -> pd.DataFrame:
|
|
92
94
|
"""
|
|
93
|
-
Get
|
|
95
|
+
Get the estimated cost per hour of employees.
|
|
94
96
|
|
|
95
97
|
Args:
|
|
96
|
-
|
|
98
|
+
company_id: Optional company ID. If not provided, fetches for all companies.
|
|
99
|
+
employee_id: Optional employee ID filter
|
|
100
|
+
year: Optional year filter
|
|
101
|
+
period: Optional period filter
|
|
97
102
|
|
|
98
103
|
Returns:
|
|
99
|
-
DataFrame
|
|
100
|
-
"""
|
|
101
|
-
if self.nmbrs.mock_mode:
|
|
102
|
-
return pd.DataFrame()
|
|
103
|
-
|
|
104
|
-
try:
|
|
105
|
-
response = self.nmbrs.soap_client_employees.service.Salary_GetCurrent(
|
|
106
|
-
EmployeeId=int(employee_id),
|
|
107
|
-
_soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_employees}
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
if response:
|
|
111
|
-
serialized = serialize_object(response)
|
|
112
|
-
if not isinstance(serialized, list):
|
|
113
|
-
serialized = [serialized]
|
|
114
|
-
df = pd.DataFrame(serialized)
|
|
115
|
-
df['employee_id'] = str(employee_id)
|
|
116
|
-
return df
|
|
117
|
-
else:
|
|
118
|
-
return pd.DataFrame()
|
|
119
|
-
|
|
120
|
-
except Fault as e:
|
|
121
|
-
raise Exception(f"SOAP request failed: {str(e)}")
|
|
122
|
-
except Exception as e:
|
|
123
|
-
raise Exception(f"Failed to get Salary: {str(e)}")
|
|
124
|
-
|
|
125
|
-
def update(self, data: Dict[str, Any]):
|
|
104
|
+
DataFrame containing cost per hour data
|
|
126
105
|
"""
|
|
127
|
-
|
|
106
|
+
if company_id:
|
|
107
|
+
return self._get_cost_per_hour(company_id, employee_id, year, period)
|
|
128
108
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
- salary_value: Salary value (gross amount)
|
|
133
|
-
- salary_type: Salary type (1=FulltimeSalary, 2=ParttimeSalary, etc.)
|
|
134
|
-
- start_date: Start date (optional)
|
|
109
|
+
df = pd.DataFrame()
|
|
110
|
+
for company in self.nmbrs.company_ids:
|
|
111
|
+
df = pd.concat([df, self._get_cost_per_hour(company, employee_id, year, period)])
|
|
135
112
|
|
|
136
|
-
|
|
137
|
-
|
|
113
|
+
return df
|
|
114
|
+
|
|
115
|
+
def _get_cost_per_hour(self,
|
|
116
|
+
company_id: str,
|
|
117
|
+
employee_id: Optional[str] = None,
|
|
118
|
+
year: Optional[int] = None,
|
|
119
|
+
period: Optional[int] = None) -> pd.DataFrame:
|
|
120
|
+
"""
|
|
121
|
+
Internal method to get cost per hour for a single company.
|
|
138
122
|
"""
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
raise Exception(f"Failed to update Salary: {str(e)}")
|
|
123
|
+
params = {}
|
|
124
|
+
if employee_id is not None:
|
|
125
|
+
params['employeeId'] = employee_id
|
|
126
|
+
if year is not None:
|
|
127
|
+
params['year'] = year
|
|
128
|
+
if period is not None:
|
|
129
|
+
params['period'] = period
|
|
130
|
+
|
|
131
|
+
request = requests.Request(
|
|
132
|
+
method='GET',
|
|
133
|
+
url=f"{self.nmbrs.base_url}companies/{company_id}/employees/costperhour",
|
|
134
|
+
params=params
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
138
|
+
df = pd.DataFrame(data)
|
|
139
|
+
|
|
140
|
+
if not df.empty:
|
|
141
|
+
df['companyId'] = company_id
|
|
142
|
+
|
|
143
|
+
return df
|
brynq_sdk_nmbrs/salary_tables.py
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
from typing import Dict,
|
|
1
|
+
from typing import Dict, Tuple
|
|
2
2
|
import pandas as pd
|
|
3
3
|
from zeep.exceptions import Fault
|
|
4
|
-
from zeep.ns import WSDL, SOAP_ENV_11
|
|
5
|
-
from zeep.xsd import ComplexType, Element, String
|
|
6
4
|
from zeep.helpers import serialize_object
|
|
7
|
-
# import logging
|
|
8
5
|
from brynq_sdk_functions import Functions
|
|
9
6
|
from .schemas.salary import SalaryTableGet, SalaryScalesGet, SalaryStepsGet
|
|
10
7
|
|
brynq_sdk_nmbrs/schedules.py
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
from typing import Any, Dict, Tuple
|
|
2
|
+
|
|
1
3
|
import pandas as pd
|
|
2
4
|
import requests
|
|
5
|
+
|
|
3
6
|
from brynq_sdk_functions import Functions
|
|
4
|
-
|
|
5
|
-
from
|
|
6
|
-
from typing import Dict, Any, Tuple, Union
|
|
7
|
-
from zeep.exceptions import Fault
|
|
8
|
-
from zeep.helpers import serialize_object
|
|
7
|
+
|
|
8
|
+
from .schemas.schedules import ScheduleCreate, ScheduleGet
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class Schedule:
|
|
@@ -83,76 +83,3 @@ class Schedule:
|
|
|
83
83
|
|
|
84
84
|
except Exception as e:
|
|
85
85
|
raise ValueError(f"Schedule validation failed: {str(e)}")
|
|
86
|
-
|
|
87
|
-
def update(self, data: Dict[str, Any]):
|
|
88
|
-
"""
|
|
89
|
-
Update a schedule for an employee using SOAP API.
|
|
90
|
-
|
|
91
|
-
Args:
|
|
92
|
-
data: Dictionary containing schedule data with fields matching ScheduleUpdate schema:
|
|
93
|
-
- employeeId: Employee ID
|
|
94
|
-
- startDate: Start date of the schedule
|
|
95
|
-
- parttimePercentage: Part-time percentage (0-100)
|
|
96
|
-
- hoursMonday, hoursTuesday, etc.: Hours for each day of week 1
|
|
97
|
-
- hoursMonday2, hoursTuesday2, etc.: Hours for each day of week 2
|
|
98
|
-
|
|
99
|
-
Returns:
|
|
100
|
-
Response from the API
|
|
101
|
-
"""
|
|
102
|
-
try:
|
|
103
|
-
schedule_model = ScheduleUpdate(**data)
|
|
104
|
-
|
|
105
|
-
if self.nmbrs.mock_mode:
|
|
106
|
-
return schedule_model
|
|
107
|
-
|
|
108
|
-
# Convert to SOAP object
|
|
109
|
-
schedule_soap = schedule_model.to_soap_schedule(self.nmbrs.soap_client_employees)
|
|
110
|
-
|
|
111
|
-
# Make SOAP request - CompanyRoosterNr is separate parameter (0 = no template)
|
|
112
|
-
response = self.nmbrs.soap_client_employees.service.Schedule_UpdateCurrent(
|
|
113
|
-
EmployeeId=schedule_model.employee_id,
|
|
114
|
-
Schedule=schedule_soap,
|
|
115
|
-
CompanyRoosterNr=schedule_model.company_rooster_nr or 0,
|
|
116
|
-
_soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_employees}
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
return response
|
|
120
|
-
|
|
121
|
-
except Fault as e:
|
|
122
|
-
raise Exception(f"SOAP request failed: {str(e)}")
|
|
123
|
-
except Exception as e:
|
|
124
|
-
raise Exception(f"Failed to update Schedule: {str(e)}")
|
|
125
|
-
|
|
126
|
-
def get_current(self, employee_id: Union[int, str]) -> pd.DataFrame:
|
|
127
|
-
"""
|
|
128
|
-
Get current schedule for an employee via SOAP.
|
|
129
|
-
|
|
130
|
-
Args:
|
|
131
|
-
employee_id: The ID of the employee
|
|
132
|
-
|
|
133
|
-
Returns:
|
|
134
|
-
DataFrame with current schedule
|
|
135
|
-
"""
|
|
136
|
-
if self.nmbrs.mock_mode:
|
|
137
|
-
return pd.DataFrame()
|
|
138
|
-
|
|
139
|
-
try:
|
|
140
|
-
response = self.nmbrs.soap_client_employees.service.Schedule_GetCurrent(
|
|
141
|
-
EmployeeId=int(employee_id),
|
|
142
|
-
_soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_employees}
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
if response:
|
|
146
|
-
serialized = serialize_object(response)
|
|
147
|
-
if not isinstance(serialized, list):
|
|
148
|
-
serialized = [serialized]
|
|
149
|
-
df = pd.DataFrame(serialized)
|
|
150
|
-
df['employee_id'] = str(employee_id)
|
|
151
|
-
return df
|
|
152
|
-
else:
|
|
153
|
-
return pd.DataFrame()
|
|
154
|
-
|
|
155
|
-
except Fault as e:
|
|
156
|
-
raise Exception(f"SOAP request failed: {str(e)}")
|
|
157
|
-
except Exception as e:
|
|
158
|
-
raise Exception(f"Failed to get Schedule: {str(e)}")
|
|
@@ -22,28 +22,38 @@ from datetime import datetime
|
|
|
22
22
|
class AbsenceGet(BrynQPanderaDataFrameModel):
|
|
23
23
|
employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Employee ID", alias="EmployeeId")
|
|
24
24
|
absence_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Absence ID", alias="AbsenceId")
|
|
25
|
-
comment: Series[String] = pa.Field(coerce=True, description="Comment", alias="Comment")
|
|
25
|
+
comment: Series[String] = pa.Field(coerce=True, nullable=True, description="Comment", alias="Comment")
|
|
26
26
|
percentage: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Percentage", alias="Percentage")
|
|
27
27
|
start: Series[DateTime] = pa.Field(coerce=True, description="Start", alias="Start")
|
|
28
28
|
registration_start_date: Series[DateTime] = pa.Field(coerce=True, description="Registration Start Date", alias="RegistrationStartDate")
|
|
29
|
-
end: Series[DateTime] = pa.Field(coerce=True, description="End", alias="End")
|
|
30
|
-
registration_end_date: Series[DateTime] = pa.Field(coerce=True, description="Registration End Date", alias="RegistrationEndDate")
|
|
31
|
-
dossier: Series[String] = pa.Field(coerce=True, description="Dossier", alias="Dossier")
|
|
32
|
-
dossiernr: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Dossier Number", alias="Dossiernr")
|
|
29
|
+
end: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="End", alias="End")
|
|
30
|
+
registration_end_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="Registration End Date", alias="RegistrationEndDate")
|
|
31
|
+
dossier: Series[String] = pa.Field(coerce=True, nullable=True, description="Dossier", alias="Dossier")
|
|
32
|
+
dossiernr: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Dossier Number", alias="Dossiernr")
|
|
33
|
+
|
|
34
|
+
class _Annotation:
|
|
35
|
+
primary_key = "absence_id"
|
|
36
|
+
foreign_keys = {
|
|
37
|
+
"employee_id": {
|
|
38
|
+
"parent_schema": "EmployeeSchema",
|
|
39
|
+
"parent_column": "employee_id",
|
|
40
|
+
"cardinality": "N:1"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
33
43
|
|
|
34
44
|
|
|
35
45
|
class AbsenceCreate(BaseModel):
|
|
36
|
-
employee_id: Optional[int] = Field(None, example=
|
|
37
|
-
absence_id: int = Field(
|
|
38
|
-
comment: str = Field(
|
|
39
|
-
percentage: int = Field(
|
|
40
|
-
start: datetime = Field(
|
|
41
|
-
registration_start_date: datetime = Field(
|
|
42
|
-
end: datetime = Field(
|
|
43
|
-
registration_end_date: datetime = Field(
|
|
44
|
-
dossier: str = Field(
|
|
45
|
-
dossiernr: int = Field(
|
|
46
|
-
new_dossier: bool =
|
|
46
|
+
employee_id: Optional[int] = Field(None, example=1234567890, description="Employee ID", alias="EmployeeId")
|
|
47
|
+
absence_id: int = Field(..., example=1, description="Absence ID", alias="AbsenceId")
|
|
48
|
+
comment: Optional[str] = Field(None, example="Sick leave", description="Comment", alias="Comment")
|
|
49
|
+
percentage: int = Field(..., ge=0, le=100, example=100, description="Percentage", alias="Percentage")
|
|
50
|
+
start: datetime = Field(..., example="2021-01-01T00:00:00Z", description="Start", alias="Start")
|
|
51
|
+
registration_start_date: datetime = Field(..., example="2021-01-01T00:00:00Z", description="Registration Start Date", alias="RegistrationStartDate")
|
|
52
|
+
end: Optional[datetime] = Field(None, example="2021-01-10T00:00:00Z", description="End", alias="End")
|
|
53
|
+
registration_end_date: Optional[datetime] = Field(None, example="2021-01-10T00:00:00Z", description="Registration End Date", alias="RegistrationEndDate")
|
|
54
|
+
dossier: Optional[str] = Field(None, example="Sick leave dossier", description="Dossier", alias="Dossier")
|
|
55
|
+
dossiernr: Optional[int] = Field(None, example=1, description="Dossier Number", alias="Dossiernr")
|
|
56
|
+
new_dossier: bool = Field(..., example=True, description="New Dossier", alias="NewDossier")
|
|
47
57
|
|
|
48
58
|
|
|
49
59
|
def to_soap_settings(self, soap_client):
|
|
@@ -2,9 +2,8 @@ from typing import Annotated, Optional
|
|
|
2
2
|
|
|
3
3
|
import pandas as pd
|
|
4
4
|
import pandera as pa
|
|
5
|
-
import pandera.extensions as extensions
|
|
6
5
|
from pandera import Bool
|
|
7
|
-
from pandera.typing import
|
|
6
|
+
from pandera.typing import Series, String
|
|
8
7
|
from pydantic import BaseModel, Field, StringConstraints
|
|
9
8
|
|
|
10
9
|
from brynq_sdk_functions import BrynQPanderaDataFrameModel
|
|
@@ -75,30 +74,4 @@ class AddressCreate(BaseModel):
|
|
|
75
74
|
max_length=3
|
|
76
75
|
)
|
|
77
76
|
] = Field(..., example="NL", description="Country ISO Code", alias="countryISOCode")
|
|
78
|
-
period: Period
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
class AddressDelete(BaseModel):
|
|
82
|
-
"""Schema for deleting an address via SOAP API."""
|
|
83
|
-
employee_id: int = Field(..., example=12345, description="Employee ID", alias="employeeId")
|
|
84
|
-
address_id: int = Field(..., example=67890, description="Address ID to delete", alias="addressId")
|
|
85
|
-
|
|
86
|
-
class Config:
|
|
87
|
-
populate_by_name = True
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
class AddressUpdate(BaseModel):
|
|
91
|
-
"""Schema for updating an address via SOAP API."""
|
|
92
|
-
id: int = Field(..., example=67890, description="Address ID to update", alias="id")
|
|
93
|
-
default: bool = Field(False, example=False, description="Is default address", alias="default")
|
|
94
|
-
street: str = Field(..., min_length=1, max_length=200, example="Naritaweg", description="Street", alias="street")
|
|
95
|
-
house_number: Optional[str] = Field(None, max_length=20, example="70", description="House Number", alias="houseNumber")
|
|
96
|
-
house_number_addition: Optional[str] = Field(None, max_length=20, example="A", description="House Number Addition", alias="houseNumberAddition")
|
|
97
|
-
postal_code: Optional[str] = Field(None, max_length=15, example="1043BZ", description="Postal Code", alias="postalCode")
|
|
98
|
-
city: str = Field(..., min_length=1, max_length=100, example="Amsterdam", description="City", alias="city")
|
|
99
|
-
state_province: Optional[str] = Field(None, max_length=100, example="Noord-Holland", description="State or Province", alias="stateProvince")
|
|
100
|
-
country_iso_code: str = Field(..., min_length=2, max_length=3, example="NL", description="Country ISO Code", alias="countryISOCode")
|
|
101
|
-
address_type: str = Field("HomeAddress", example="HomeAddress", description="Address type", alias="type")
|
|
102
|
-
|
|
103
|
-
class Config:
|
|
104
|
-
populate_by_name = True
|
|
77
|
+
period: Period = Field(..., example={"year": 2021, "period": 4}, description="Period details")
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
2
4
|
import pandera as pa
|
|
3
5
|
from pandera import Bool
|
|
4
|
-
from pandera.typing import
|
|
5
|
-
import pandera.extensions as extensions
|
|
6
|
-
from brynq_sdk_functions import BrynQPanderaDataFrameModel
|
|
7
|
-
from typing import Optional
|
|
6
|
+
from pandera.typing import DateTime, Float, Series, String
|
|
8
7
|
from pydantic import BaseModel, Field, field_validator
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
from brynq_sdk_functions import BrynQPanderaDataFrameModel
|
|
10
|
+
|
|
10
11
|
|
|
11
12
|
# ---------------------------
|
|
12
13
|
# Get Schemas
|
|
@@ -98,8 +98,6 @@ class CostcenterTable(BaseModel):
|
|
|
98
98
|
default: Optional[bool] = Field(True, example=True, description="Default", alias="default")
|
|
99
99
|
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
101
|
class EmployeeCostcenterUpdate(BaseModel):
|
|
104
102
|
employee_id: str = Field(..., example="c605f980-1c4c-42c1-8ddb-2d90c58da0b3", description="Employee Cost Center ID", alias="employeeId")
|
|
105
103
|
employee_cost_centers: List[CostcenterTable] = Field(..., description="Employee Cost Centers", alias="employeeCostCenters")
|
|
@@ -115,10 +113,12 @@ class EmployeeCostcenterDelete(BaseModel):
|
|
|
115
113
|
# CostCenter CRUD schemas - These are hypothetical since the API doesn't have create/update/delete endpoints
|
|
116
114
|
# but we add them for consistency with other schema files
|
|
117
115
|
class CostcenterCreate(BaseModel):
|
|
116
|
+
company_id: str = Field(..., description="Company identifier", alias="companyId")
|
|
118
117
|
code: str = Field(..., example="CC001", description="Code", alias="code")
|
|
119
118
|
description: str = Field(..., example="Sales Department", description="Description", alias="description")
|
|
120
119
|
|
|
121
120
|
class CostcenterUpdate(BaseModel):
|
|
121
|
+
company_id: str = Field(..., description="Company identifier", alias="companyId")
|
|
122
122
|
cost_center_id: str = Field(..., example="a405f980-1c4c-42c1-8ddb-2d90c58da0b1", description="Cost Center ID", alias="costCenterId")
|
|
123
123
|
code: str = Field(..., example="CC001", description="Code", alias="code")
|
|
124
124
|
description: str = Field(..., example="Sales Department", description="Description", alias="description")
|
|
@@ -23,10 +23,12 @@ class CostunitGet(BrynQPanderaDataFrameModel):
|
|
|
23
23
|
# Upload Schemas
|
|
24
24
|
# ---------------------------
|
|
25
25
|
class CostunitCreate(BaseModel):
|
|
26
|
+
company_id: str = Field(..., description="Company identifier", alias="companyId")
|
|
26
27
|
code: str = Field(..., example="CU001", description="Code", alias="code")
|
|
27
28
|
description: str = Field(..., example="Marketing Unit", description="Description", alias="description")
|
|
28
29
|
|
|
29
30
|
class CostunitUpdate(BaseModel):
|
|
31
|
+
company_id: str = Field(..., description="Company identifier", alias="companyId")
|
|
30
32
|
cost_unit_id: str = Field(..., example="b505f980-1c4c-42c1-8ddb-2d90c58da0b2", description="Cost Unit ID", alias="costUnitId")
|
|
31
33
|
code: str = Field(..., example="CU001", description="Code", alias="code")
|
|
32
34
|
description: str = Field(..., example="Marketing Unit", description="Description", alias="description")
|
brynq_sdk_nmbrs/schemas/days.py
CHANGED
|
@@ -15,22 +15,22 @@ from pydantic import BaseModel, Field
|
|
|
15
15
|
# ---------------------------
|
|
16
16
|
# PANDERA SCHEMA
|
|
17
17
|
class VariableDaysGet(BrynQPanderaDataFrameModel):
|
|
18
|
-
days: Series[String] = pa.Field(coerce=True, description="
|
|
19
|
-
days_for_wage_components_per_day: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="
|
|
18
|
+
days: Series[String] = pa.Field(coerce=True, description="Days", alias="days")
|
|
19
|
+
days_for_wage_components_per_day: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Days for Wage Components per Day", alias="daysForWageComponentsPerDay")
|
|
20
20
|
employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
|
|
21
21
|
|
|
22
|
-
class
|
|
23
|
-
|
|
22
|
+
class _Annotation:
|
|
23
|
+
primary_key = "employee_id"
|
|
24
24
|
|
|
25
25
|
class FixedDaysGet(BrynQPanderaDataFrameModel):
|
|
26
|
-
days: Series[String] = pa.Field(coerce=True, description="
|
|
27
|
-
days_for_wage_components_per_day: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="
|
|
26
|
+
days: Series[String] = pa.Field(coerce=True, description="Days", alias="days")
|
|
27
|
+
days_for_wage_components_per_day: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Days for Wage Components per Day", alias="daysForWageComponentsPerDay")
|
|
28
28
|
end_year: Series[pd.Int64Dtype] = pa.Field(nullable=True, coerce=True, description="End Year", alias="endYear")
|
|
29
29
|
end_period: Series[pd.Int64Dtype] = pa.Field(nullable=True, coerce=True, description="End Period", alias="endPeriod")
|
|
30
30
|
employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
|
|
31
31
|
|
|
32
|
-
class
|
|
33
|
-
|
|
32
|
+
class _Annotation:
|
|
33
|
+
primary_key = "employee_id"
|
|
34
34
|
|
|
35
35
|
# ---------------------------
|
|
36
36
|
# Upload Schemas
|
|
@@ -70,7 +70,7 @@ class VariableHoursCreate(BaseModel):
|
|
|
70
70
|
cost_center_id: Optional[str] = Field(None, example="aa506564-d1db-4fa8-83dc-d68db4cfcd82", description="Cost Center ID", alias="costCenterId")
|
|
71
71
|
cost_unit_id: Optional[str] = Field(None, example="d8ac6afb-2ac6-43bf-9880-2d382cdace43", description="Cost Unit ID", alias="costUnitId")
|
|
72
72
|
comment: Optional[str] = Field(None, example="Shift hours", description="Comment", alias="comment")
|
|
73
|
-
period_details: Optional[PeriodPost] = Field(None, example="
|
|
73
|
+
period_details: Optional[PeriodPost] = Field(None, example={"period": {"year": 2025, "period": 1}, "unprotectedMode": False}, description="Period details", alias="periodDetails")
|
|
74
74
|
|
|
75
75
|
class VariableHoursUpdate(BaseModel):
|
|
76
76
|
hour_component_id: str = Field(..., example="49a69eda-252e-4ccb-a220-38ea90511d4f", description="Hour Component ID", alias="hourComponentId")
|
|
@@ -86,11 +86,13 @@ class HoursDelete(BaseModel):
|
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
class FixedDaysCreate(BaseModel):
|
|
89
|
+
employee_id: str = Field(..., example="3054d4cf-b449-489d-8d2e-5dd30e5ab994", description="Employee identifier", alias="employeeId")
|
|
89
90
|
number_of_days: int = Field(..., ge=0, le=1000, example=40, description="Days", alias="days")
|
|
90
91
|
days_for_wage_components_per_day: Optional[int] = Field(None, ge=0, le=1000, example=40, description="Days for Wage Components per Day", alias="daysForWageComponentsPerDay")
|
|
91
|
-
period_details: Optional[PeriodPost] = Field(None, example="
|
|
92
|
+
period_details: Optional[PeriodPost] = Field(None, example={"period": {"year": 2025, "period": 1}, "unprotectedMode": False}, description="Period details", alias="periodDetails")
|
|
92
93
|
|
|
93
94
|
class VariableDaysCreate(BaseModel):
|
|
95
|
+
employee_id: str = Field(..., example="3054d4cf-b449-489d-8d2e-5dd30e5ab994", description="Employee identifier", alias="employeeId")
|
|
94
96
|
number_of_days: int = Field(..., ge=0, le=1000, example=40, description="Days", alias="days")
|
|
95
97
|
days_for_wage_components_per_day: Optional[int] = Field(None, ge=0, le=1000, example=40, description="Days for Wage Components per Day", alias="daysForWageComponentsPerDay")
|
|
96
|
-
period_details: Optional[PeriodPost] = Field(None, example="
|
|
98
|
+
period_details: Optional[PeriodPost] = Field(None, example={"period": {"year": 2025, "period": 1}, "unprotectedMode": False}, description="Period details", alias="periodDetails")
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import pandas as pd
|
|
2
1
|
import pandera as pa
|
|
3
|
-
from pandera import
|
|
4
|
-
|
|
5
|
-
import pandera.extensions as extensions
|
|
2
|
+
from pandera.typing import Series, String
|
|
3
|
+
|
|
6
4
|
from brynq_sdk_functions import BrynQPanderaDataFrameModel
|
|
7
|
-
|
|
8
|
-
from pydantic import BaseModel, Field, StringConstraints
|
|
5
|
+
|
|
9
6
|
|
|
10
7
|
# ---------------------------
|
|
11
8
|
# Get Schemas
|
|
@@ -13,26 +10,7 @@ from pydantic import BaseModel, Field, StringConstraints
|
|
|
13
10
|
class DebtorsGet(BrynQPanderaDataFrameModel):
|
|
14
11
|
debtor_id: Series[String] = pa.Field(coerce=True, description="Debtor ID", alias="debtorId")
|
|
15
12
|
number: Series[String] = pa.Field(coerce=True, description="Debtor number", alias="number")
|
|
16
|
-
name: Series[
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
# ---------------------------
|
|
20
|
-
# SOAP Schemas
|
|
21
|
-
# ---------------------------
|
|
22
|
-
class DebtorCreate(BaseModel):
|
|
23
|
-
"""Schema for creating a debtor via SOAP API."""
|
|
24
|
-
number: int = Field(..., ge=1, description="Debtor number", alias="number", example=1001)
|
|
25
|
-
name: str = Field(..., min_length=1, max_length=200, description="Debtor name", alias="name", example="New Debtor Company")
|
|
26
|
-
|
|
27
|
-
class Config:
|
|
28
|
-
populate_by_name = True
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class DebtorUpdate(BaseModel):
|
|
32
|
-
"""Schema for updating a debtor via SOAP API."""
|
|
33
|
-
debtor_id: int = Field(..., description="Debtor ID", alias="debtorId", example=34548)
|
|
34
|
-
number: int = Field(..., ge=1, description="Debtor number", alias="number", example=1001)
|
|
35
|
-
name: str = Field(..., min_length=1, max_length=200, description="Debtor name", alias="name", example="Updated Debtor Company")
|
|
13
|
+
name: Series[String] = pa.Field(coerce=True, description="Debtor name", alias="name")
|
|
36
14
|
|
|
37
|
-
class
|
|
38
|
-
|
|
15
|
+
class _Annotation:
|
|
16
|
+
primary_key = "debtor_id"
|