brynq-sdk-nmbrs 2.0.0__tar.gz → 2.1.0__tar.gz
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-2.0.0 → brynq_sdk_nmbrs-2.1.0}/PKG-INFO +1 -1
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/__init__.py +6 -5
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/companies.py +4 -2
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/debtors.py +8 -8
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/department.py +3 -2
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/employees.py +2 -2
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/function.py +6 -4
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/hours.py +1 -1
- brynq_sdk_nmbrs-2.1.0/brynq_sdk_nmbrs/manager.py +294 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/salary_tables.py +20 -15
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schedules.py +3 -3
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/__init__.py +5 -2
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/address.py +9 -9
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/bank.py +1 -1
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/contracts.py +6 -6
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/costcenter.py +10 -10
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/costunit.py +1 -1
- brynq_sdk_nmbrs-2.1.0/brynq_sdk_nmbrs/schemas/debtor.py +16 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/department.py +13 -3
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/employees.py +45 -45
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/function.py +9 -3
- brynq_sdk_nmbrs-2.1.0/brynq_sdk_nmbrs/schemas/manager.py +123 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/salary.py +24 -2
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/schedules.py +25 -16
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs.egg-info/PKG-INFO +1 -1
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs.egg-info/SOURCES.txt +3 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/setup.py +1 -1
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/address.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/bank.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/children.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/contract.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/costcenter.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/costunit.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/document.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/employment.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/salaries.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/employment.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/hours.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/schemas/wagecomponents.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs/wagecomponents.py +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs.egg-info/dependency_links.txt +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs.egg-info/not-zip-safe +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs.egg-info/requires.txt +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/brynq_sdk_nmbrs.egg-info/top_level.txt +0 -0
- {brynq_sdk_nmbrs-2.0.0 → brynq_sdk_nmbrs-2.1.0}/setup.cfg +0 -0
|
@@ -20,6 +20,7 @@ from .salary_tables import SalaryTables, SalaryScales, SalarySteps
|
|
|
20
20
|
from .employment import Employment
|
|
21
21
|
from .function import EmployeeFunction
|
|
22
22
|
from .hours import VariableHours, FixedHours
|
|
23
|
+
from .manager import EmployeeManager, Manager
|
|
23
24
|
from .salaries import Salaries
|
|
24
25
|
from .schedules import Schedule
|
|
25
26
|
from .wagecomponents import EmployeeFixedWageComponents, EmployeeVariableWageComponents
|
|
@@ -73,6 +74,8 @@ class Nmbrs(BrynQ):
|
|
|
73
74
|
self.function = EmployeeFunction(self)
|
|
74
75
|
self.fixed_hours = FixedHours(self)
|
|
75
76
|
self.variable_hours = VariableHours(self)
|
|
77
|
+
self.manager = Manager(self)
|
|
78
|
+
self.employee_manager = EmployeeManager(self)
|
|
76
79
|
self.salaries = Salaries(self)
|
|
77
80
|
self.schedule = Schedule(self)
|
|
78
81
|
self.fixed_wagecomponents = EmployeeFixedWageComponents(self)
|
|
@@ -96,23 +99,22 @@ class Nmbrs(BrynQ):
|
|
|
96
99
|
def _get_soap_auth_header(self):
|
|
97
100
|
"""
|
|
98
101
|
Creates the SOAP authentication header using credentials from initial_credentials.
|
|
99
|
-
|
|
100
102
|
Returns:
|
|
101
103
|
AuthHeaderWithDomainType: The authentication header for SOAP requests
|
|
102
104
|
"""
|
|
103
105
|
initial_credentials = self.get_system_credential(system='nmbrs', label='bob')
|
|
104
106
|
config = initial_credentials.get("config", {})
|
|
105
|
-
|
|
107
|
+
|
|
106
108
|
# Get the AuthHeaderWithDomain type from the WSDL
|
|
107
109
|
AuthHeaderWithDomainType = self.soap_client.get_element('ns0:AuthHeaderWithDomain')
|
|
108
|
-
|
|
110
|
+
|
|
109
111
|
# Create the auth header using credentials from config
|
|
110
112
|
auth_header = AuthHeaderWithDomainType(
|
|
111
113
|
Username=config.get("soap_api_username"),
|
|
112
114
|
Token=config.get("soap_api_token"),
|
|
113
115
|
Domain=config.get("soap_api_domain")
|
|
114
116
|
)
|
|
115
|
-
|
|
117
|
+
|
|
116
118
|
return auth_header
|
|
117
119
|
|
|
118
120
|
def get_paginated_result(self, request: requests.Request) -> List:
|
|
@@ -158,4 +160,3 @@ class Nmbrs(BrynQ):
|
|
|
158
160
|
df.columns = map(camel_to_snake_case, df.columns)
|
|
159
161
|
|
|
160
162
|
return df
|
|
161
|
-
|
|
@@ -49,10 +49,12 @@ class Companies:
|
|
|
49
49
|
if response:
|
|
50
50
|
# Convert Zeep objects to Python dictionaries
|
|
51
51
|
serialized_response = serialize_object(response)
|
|
52
|
-
|
|
52
|
+
|
|
53
|
+
# TODO: add validation here
|
|
53
54
|
# Convert to DataFrame
|
|
54
55
|
df = pd.DataFrame(serialized_response)
|
|
55
|
-
|
|
56
|
+
df = self.nmbrs._rename_camel_columns_to_snake_case(df)
|
|
57
|
+
|
|
56
58
|
return df
|
|
57
59
|
else:
|
|
58
60
|
return pd.DataFrame()
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
2
|
import requests
|
|
3
|
-
from
|
|
4
|
-
from .costunit import Costunit
|
|
3
|
+
from brynq_sdk_functions import Functions
|
|
5
4
|
from .department import Departments
|
|
6
|
-
from .
|
|
7
|
-
from .
|
|
8
|
-
from .function import Functions
|
|
5
|
+
from .function import Functions as NmbrsFunctions
|
|
6
|
+
from .schemas.debtor import DebtorsGet
|
|
9
7
|
|
|
10
8
|
|
|
11
9
|
class Debtors:
|
|
12
10
|
def __init__(self, nmbrs):
|
|
13
11
|
self.nmbrs = nmbrs
|
|
14
12
|
self.departments = Departments(nmbrs)
|
|
15
|
-
self.functions =
|
|
13
|
+
self.functions = NmbrsFunctions(nmbrs)
|
|
16
14
|
|
|
17
15
|
|
|
18
|
-
def get(self) -> pd.DataFrame:
|
|
16
|
+
def get(self) -> (pd.DataFrame, pd.DataFrame):
|
|
19
17
|
request = requests.Request(method='GET',
|
|
20
18
|
url=f"{self.nmbrs.base_url}debtors")
|
|
21
19
|
data = self.nmbrs.get_paginated_result(request)
|
|
22
20
|
|
|
23
21
|
df = pd.DataFrame(data)
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
valid_debtors, invalid_debtors = Functions.validate_data(df=df, schema=DebtorsGet, debug=True)
|
|
24
|
+
|
|
25
|
+
return valid_debtors, invalid_debtors
|
|
@@ -2,7 +2,7 @@ import math
|
|
|
2
2
|
import pandas as pd
|
|
3
3
|
import requests
|
|
4
4
|
from typing import Dict, Any
|
|
5
|
-
from .schemas.department import DepartmentCreate, DepartmentUpdate, DepartmentDelete, Period, DepartmentGet
|
|
5
|
+
from .schemas.department import DepartmentCreate, DepartmentUpdate, DepartmentDelete, Period, EmployeeDepartmentGet, DepartmentGet
|
|
6
6
|
from brynq_sdk_functions import Functions
|
|
7
7
|
|
|
8
8
|
|
|
@@ -17,7 +17,7 @@ class EmployeeDepartment:
|
|
|
17
17
|
for company in self.nmbrs.company_ids:
|
|
18
18
|
departments = pd.concat([departments, self._get(company, created_from, employee_id)])
|
|
19
19
|
|
|
20
|
-
valid_departments, invalid_departments = Functions.validate_data(df=departments, schema=
|
|
20
|
+
valid_departments, invalid_departments = Functions.validate_data(df=departments, schema=EmployeeDepartmentGet, debug=True)
|
|
21
21
|
|
|
22
22
|
return valid_departments, invalid_departments
|
|
23
23
|
|
|
@@ -114,5 +114,6 @@ class Departments:
|
|
|
114
114
|
|
|
115
115
|
data = self.nmbrs.get_paginated_result(request)
|
|
116
116
|
df = pd.DataFrame(data)
|
|
117
|
+
valid_departments, invalid_departments = Functions.validate_data(df=df, schema=DepartmentGet, debug=True)
|
|
117
118
|
|
|
118
119
|
return df
|
|
@@ -67,7 +67,7 @@ class Employees:
|
|
|
67
67
|
record_path='info',
|
|
68
68
|
meta=['employeeId']
|
|
69
69
|
)
|
|
70
|
-
df['
|
|
70
|
+
df['companyId'] = company_id
|
|
71
71
|
|
|
72
72
|
df['createdAt'] = pd.to_datetime(df['createdAt'])
|
|
73
73
|
df = df.loc[df.groupby('employeeId')['createdAt'].idxmax()]
|
|
@@ -108,7 +108,7 @@ class Employees:
|
|
|
108
108
|
return employee_model
|
|
109
109
|
|
|
110
110
|
# Convert validated model to dict for API payload
|
|
111
|
-
payload = employee_model.
|
|
111
|
+
payload = employee_model.model_dump(exclude_none=True, by_alias=True)
|
|
112
112
|
|
|
113
113
|
# Send request
|
|
114
114
|
resp = self.nmbrs.session.post(
|
|
@@ -3,7 +3,7 @@ import requests
|
|
|
3
3
|
from brynq_sdk_functions import Functions as BrynQFunctions
|
|
4
4
|
import math
|
|
5
5
|
from typing import Dict, Any
|
|
6
|
-
from .schemas.function import
|
|
6
|
+
from .schemas.function import EmployeeFunctionGet, FunctionCreate, FunctionUpdate, FunctionDelete, FunctionGet
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class EmployeeFunction:
|
|
@@ -16,7 +16,7 @@ class EmployeeFunction:
|
|
|
16
16
|
for company in self.nmbrs.company_ids:
|
|
17
17
|
functions = pd.concat([functions, self._get(company, created_from)])
|
|
18
18
|
|
|
19
|
-
valid_functions, invalid_functions = BrynQFunctions.validate_data(df=functions, schema=
|
|
19
|
+
valid_functions, invalid_functions = BrynQFunctions.validate_data(df=functions, schema=EmployeeFunctionGet, debug=True)
|
|
20
20
|
|
|
21
21
|
return valid_functions, invalid_functions
|
|
22
22
|
|
|
@@ -102,14 +102,16 @@ class Functions:
|
|
|
102
102
|
def __init__(self, nmbrs):
|
|
103
103
|
self.nmbrs = nmbrs
|
|
104
104
|
|
|
105
|
-
def get(self, debtor_id: str) -> pd.DataFrame:
|
|
105
|
+
def get(self, debtor_id: str) -> (pd.DataFrame, pd.DataFrame):
|
|
106
106
|
try:
|
|
107
107
|
request = requests.Request(method='GET',
|
|
108
108
|
url=f"{self.nmbrs.base_url}debtors/{debtor_id}/functions")
|
|
109
109
|
|
|
110
110
|
data = self.nmbrs.get_paginated_result(request)
|
|
111
111
|
df = pd.DataFrame(data)
|
|
112
|
+
valid_functions, invalid_functions = BrynQFunctions.validate_data(df=df, schema=FunctionGet, debug=True)
|
|
113
|
+
|
|
112
114
|
except requests.HTTPError as e:
|
|
113
115
|
df = pd.DataFrame()
|
|
114
116
|
|
|
115
|
-
return
|
|
117
|
+
return valid_functions, invalid_functions
|
|
@@ -46,7 +46,7 @@ class VariableHours:
|
|
|
46
46
|
|
|
47
47
|
df = pd.DataFrame(data)
|
|
48
48
|
|
|
49
|
-
df['
|
|
49
|
+
df['employeeId'] = employee_id # Add employee_id for tracking
|
|
50
50
|
|
|
51
51
|
# Validate data using the schema
|
|
52
52
|
valid_hours, invalid_hours = Functions.validate_data(df=df, schema=VariableHoursGet, debug=True)
|
|
@@ -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
|
|
@@ -5,7 +5,8 @@ from zeep.ns import WSDL, SOAP_ENV_11
|
|
|
5
5
|
from zeep.xsd import ComplexType, Element, String
|
|
6
6
|
from zeep.helpers import serialize_object
|
|
7
7
|
# import logging
|
|
8
|
-
|
|
8
|
+
from brynq_sdk_functions import Functions
|
|
9
|
+
from .schemas.salary import SalaryTableGet, SalaryScalesGet, SalaryStepsGet
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class SalaryTables:
|
|
@@ -13,7 +14,7 @@ class SalaryTables:
|
|
|
13
14
|
self.nmbrs = nmbrs
|
|
14
15
|
self.soap_client = nmbrs.soap_client
|
|
15
16
|
|
|
16
|
-
def get(self, period: int, year: int) -> pd.DataFrame:
|
|
17
|
+
def get(self, period: int, year: int) -> (pd.DataFrame, pd.DataFrame):
|
|
17
18
|
"""
|
|
18
19
|
Get salary tables for all companies for a specific period and year.
|
|
19
20
|
|
|
@@ -28,11 +29,13 @@ class SalaryTables:
|
|
|
28
29
|
for company in self.nmbrs.soap_company_ids.to_dict(orient='records'):
|
|
29
30
|
salary_table_temp = self._get(company['i_d'], period, year)
|
|
30
31
|
if not salary_table_temp.empty:
|
|
31
|
-
salary_table_temp['
|
|
32
|
+
salary_table_temp['companyId'] = company['number']
|
|
32
33
|
salary_tables = pd.concat([salary_tables, salary_table_temp])
|
|
33
|
-
|
|
34
|
+
|
|
35
|
+
valid_salary_tables, invalid_salary_tables = Functions.validate_data(df=salary_tables, schema=SalaryTableGet, debug=True)
|
|
36
|
+
|
|
34
37
|
# No validation schema for now, but could be added later
|
|
35
|
-
return
|
|
38
|
+
return valid_salary_tables, invalid_salary_tables
|
|
36
39
|
|
|
37
40
|
def _get(self, company_id: int, period: int, year: int) -> pd.DataFrame:
|
|
38
41
|
"""
|
|
@@ -85,7 +88,7 @@ class SalaryScales:
|
|
|
85
88
|
self.nmbrs = nmbrs
|
|
86
89
|
self.soap_client = nmbrs.soap_client
|
|
87
90
|
|
|
88
|
-
def get(self, period: int, year: int) -> pd.DataFrame:
|
|
91
|
+
def get(self, period: int, year: int) -> (pd.DataFrame, pd.DataFrame):
|
|
89
92
|
"""
|
|
90
93
|
Get salary scales for all companies for a specific period and year.
|
|
91
94
|
|
|
@@ -100,11 +103,12 @@ class SalaryScales:
|
|
|
100
103
|
for company in self.nmbrs.soap_company_ids.to_dict(orient='records'):
|
|
101
104
|
salary_scale_temp = self._get(company['i_d'], period, year)
|
|
102
105
|
if not salary_scale_temp.empty:
|
|
103
|
-
salary_scale_temp['
|
|
106
|
+
salary_scale_temp['companyId'] = company['number']
|
|
104
107
|
salary_scales = pd.concat([salary_scales, salary_scale_temp])
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
|
|
109
|
+
valid_salary_scales, invalid_salary_scales = Functions.validate_data(df=salary_scales, schema=SalaryScalesGet, debug=True)
|
|
110
|
+
|
|
111
|
+
return valid_salary_scales, invalid_salary_scales
|
|
108
112
|
|
|
109
113
|
def _get(self, company_id: int, period: int, year: int) -> pd.DataFrame:
|
|
110
114
|
"""
|
|
@@ -157,7 +161,7 @@ class SalarySteps:
|
|
|
157
161
|
self.nmbrs = nmbrs
|
|
158
162
|
self.soap_client = nmbrs.soap_client
|
|
159
163
|
|
|
160
|
-
def get(self, period: int, year: int, scale: dict) -> pd.DataFrame:
|
|
164
|
+
def get(self, period: int, year: int, scale: dict) -> (pd.DataFrame, pd.DataFrame):
|
|
161
165
|
"""
|
|
162
166
|
Get salary steps for all companies for a specific period, year and scale.
|
|
163
167
|
|
|
@@ -178,11 +182,12 @@ class SalarySteps:
|
|
|
178
182
|
for company in self.nmbrs.soap_company_ids.to_dict(orient='records'):
|
|
179
183
|
salary_steps_temp = self._get(company['i_d'], period, year, scale)
|
|
180
184
|
if not salary_steps_temp.empty:
|
|
181
|
-
salary_steps_temp['
|
|
185
|
+
salary_steps_temp['companyId'] = company['number']
|
|
182
186
|
salary_steps = pd.concat([salary_steps, salary_steps_temp])
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
187
|
+
|
|
188
|
+
valid_salary_steps, invalid_salary_steps = Functions.validate_data(df=salary_steps, schema=SalaryStepsGet, debug=True)
|
|
189
|
+
|
|
190
|
+
return valid_salary_steps, invalid_salary_steps
|
|
186
191
|
|
|
187
192
|
def _get(self, company_id: int, period: int, year: int, scale: dict) -> pd.DataFrame:
|
|
188
193
|
"""
|
|
@@ -68,10 +68,10 @@ class Schedule:
|
|
|
68
68
|
schedule_data["startDate"] = data["start_date_schedule"]
|
|
69
69
|
|
|
70
70
|
# Optional field
|
|
71
|
-
if "
|
|
71
|
+
if "hours_per_week" in data:
|
|
72
72
|
# Handle NaN values
|
|
73
|
-
if not isinstance(data["
|
|
74
|
-
schedule_data["hoursPerWeek"] = data["
|
|
73
|
+
if not isinstance(data["hours_per_week"], float) or not math.isnan(data["hours_per_week"]):
|
|
74
|
+
schedule_data["hoursPerWeek"] = data["hours_per_week"]
|
|
75
75
|
|
|
76
76
|
# Create week1 and week2 data
|
|
77
77
|
week1_data = {}
|
|
@@ -5,11 +5,12 @@ DATEFORMAT = '%Y%m%d'
|
|
|
5
5
|
from .address import AddressGet, AddressCreate, AddressUpdate, AddressDelete
|
|
6
6
|
from .bank import BankGet, BankCreate, BankUpdate, BankDelete
|
|
7
7
|
from .contracts import ContractGet, ContractCreate, ContractUpdate, ContractDelete
|
|
8
|
-
from .department import
|
|
8
|
+
from .department import EmployeeDepartmentGet, DepartmentCreate, DepartmentUpdate, DepartmentDelete, DepartmentGet
|
|
9
9
|
from .employees import EmployeeGet, EmployeeCreate, EmployeeUpdate, EmployeeDelete
|
|
10
10
|
from .employment import EmploymentGet, EmploymentCreate, EmploymentUpdate, EmploymentDelete
|
|
11
11
|
from .function import FunctionGet, FunctionCreate, FunctionUpdate, FunctionDelete
|
|
12
12
|
from .hours import FixedHoursGet, FixedHoursCreate, FixedHoursUpdate, HoursDelete, VariableHoursGet, VariableHoursCreate, VariableHoursUpdate
|
|
13
|
+
from .manager import ManagerGet, ManagerBasicGet, EmployeeManagerGet, ManagerHistoricBasicGet, ManagerCreate, ManagerUpdate, ManagerDelete, UpdateEmployeeManager
|
|
13
14
|
from .salary import SalaryGet, SalaryCreate, SalaryUpdate, SalaryDelete
|
|
14
15
|
from .wagecomponents import FixedWageComponentGet, FixedWageComponentCreate, FixedWageComponentUpdate, WageComponentDelete, VariableWageComponentGet, VariableWageComponentCreate, VariableWageComponentUpdate
|
|
15
16
|
|
|
@@ -19,12 +20,14 @@ __all__ = [
|
|
|
19
20
|
'AddressGet', 'AddressCreate', 'AddressUpdate', 'AddressDelete',
|
|
20
21
|
'BankGet', 'BankCreate', 'BankUpdate', 'BankDelete',
|
|
21
22
|
'ContractGet', 'ContractCreate', 'ContractUpdate', 'ContractDelete',
|
|
22
|
-
'
|
|
23
|
+
'EmployeeDepartmentGet', 'DepartmentCreate', 'DepartmentUpdate', 'DepartmentDelete', 'DepartmentGet',
|
|
23
24
|
'EmployeeGet', 'EmployeeCreate', 'EmployeeUpdate', 'EmployeeDelete',
|
|
24
25
|
'EmploymentGet', 'EmploymentCreate', 'EmploymentUpdate', 'EmploymentDelete',
|
|
25
26
|
'FunctionGet', 'FunctionCreate', 'FunctionUpdate', 'FunctionDelete',
|
|
26
27
|
'FixedHoursGet', 'FixedHoursCreate', 'FixedHoursUpdate', 'HoursDelete',
|
|
27
28
|
'VariableHoursGet', 'VariableHoursCreate', 'VariableHoursUpdate',
|
|
29
|
+
'ManagerGet', 'ManagerBasicGet', 'EmployeeManagerGet', 'ManagerHistoricBasicGet',
|
|
30
|
+
'ManagerCreate', 'ManagerUpdate', 'ManagerDelete', 'UpdateEmployeeManager',
|
|
28
31
|
'SalaryGet', 'SalaryCreate', 'SalaryUpdate', 'SalaryDelete',
|
|
29
32
|
'FixedWageComponentGet', 'FixedWageComponentCreate', 'FixedWageComponentUpdate', 'WageComponentDelete',
|
|
30
33
|
'VariableWageComponentGet', 'VariableWageComponentCreate', 'VariableWageComponentUpdate'
|
|
@@ -27,8 +27,8 @@ class AddressGet(BrynQPanderaDataFrameModel):
|
|
|
27
27
|
city: Series[String] = pa.Field(coerce=True, description="City", alias="city")
|
|
28
28
|
state_province: Series[String] = pa.Field(coerce=True, nullable=True, description="State or Province", alias="stateProvince")
|
|
29
29
|
country_i_s_o_code: Series[String] = pa.Field(coerce=True, nullable=True, description="Country ISO code", alias="countryISOCode")
|
|
30
|
-
period_year: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Year", alias="
|
|
31
|
-
period_period: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Period", alias="
|
|
30
|
+
period_year: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Year", alias="period.year")
|
|
31
|
+
period_period: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Period", alias="period.period")
|
|
32
32
|
|
|
33
33
|
class _Annotation:
|
|
34
34
|
primary_key = "address_id"
|
|
@@ -64,11 +64,11 @@ class AddressCreate(BaseModel):
|
|
|
64
64
|
city: str = Field(..., min_length=1, max_length=100, example="Amsterdam", description="City", alias="city")
|
|
65
65
|
state_province: Optional[str] = Field(None, max_length=100, example="Noord-Holland", description="State or Province", alias="stateProvince")
|
|
66
66
|
country_iso_code: Annotated[
|
|
67
|
-
str,
|
|
67
|
+
str,
|
|
68
68
|
StringConstraints(
|
|
69
|
-
pattern=r'^[A-Za-z]+$',
|
|
69
|
+
pattern=r'^[A-Za-z]+$',
|
|
70
70
|
strip_whitespace=True,
|
|
71
|
-
min_length=2,
|
|
71
|
+
min_length=2,
|
|
72
72
|
max_length=3
|
|
73
73
|
)
|
|
74
74
|
] = Field(..., example="NL", description="Country ISO Code", alias="countryISOCode")
|
|
@@ -91,15 +91,15 @@ class AddressUpdate(BaseModel):
|
|
|
91
91
|
city: str = Field(..., min_length=1, max_length=100, example="Amsterdam", description="City", alias="city")
|
|
92
92
|
state_province: Optional[str] = Field(None, max_length=100, example="Noord-Holland", description="State or Province", alias="stateProvince")
|
|
93
93
|
country_iso_code: Annotated[
|
|
94
|
-
str,
|
|
94
|
+
str,
|
|
95
95
|
StringConstraints(
|
|
96
|
-
pattern=r'^[A-Za-z]+$',
|
|
96
|
+
pattern=r'^[A-Za-z]+$',
|
|
97
97
|
strip_whitespace=True,
|
|
98
|
-
min_length=2,
|
|
98
|
+
min_length=2,
|
|
99
99
|
max_length=3
|
|
100
100
|
)
|
|
101
101
|
] = Field(..., example="NL")
|
|
102
102
|
period_details: Period
|
|
103
103
|
|
|
104
104
|
class AddressDelete(BaseModel):
|
|
105
|
-
address_id: str = Field(..., description="Address ID", example="cc3449f5-9941-4209-be36-187a16267394", alias="addressId")
|
|
105
|
+
address_id: str = Field(..., description="Address ID", example="cc3449f5-9941-4209-be36-187a16267394", alias="addressId")
|