brynq-sdk-nmbrs 2.3.3.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 +16 -24
- 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.3.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-2.3.3.dev0.dist-info → brynq_sdk_nmbrs-2.4.5.dist-info}/WHEEL +1 -1
- brynq_sdk_nmbrs/schemas/social_insurance.py +0 -73
- brynq_sdk_nmbrs/social_insurance.py +0 -130
- brynq_sdk_nmbrs-2.3.3.dev0.dist-info/RECORD +0 -55
- {brynq_sdk_nmbrs-2.3.3.dev0.dist-info → brynq_sdk_nmbrs-2.4.5.dist-info}/top_level.txt +0 -0
brynq_sdk_nmbrs/__init__.py
CHANGED
|
@@ -17,14 +17,14 @@ from .children import Children
|
|
|
17
17
|
from .companies import Companies
|
|
18
18
|
from .contract import Contract
|
|
19
19
|
from .costcenter import Costcenter, EmployeeCostcenter
|
|
20
|
-
from .costunit import Costunit
|
|
21
20
|
from .days import FixedDays, VariableDays
|
|
22
21
|
from .debtors import Debtors
|
|
23
22
|
from .department import Departments, EmployeeDepartment
|
|
24
|
-
from .document import
|
|
23
|
+
from .document import Document
|
|
25
24
|
from .employee_wage_tax_settings import EmployeeWageTaxSettings
|
|
26
25
|
from .employees import Employees
|
|
27
26
|
from .employment import Employment
|
|
27
|
+
from .extra_fields import EmployeeExtraFields, ExtraFieldSettings
|
|
28
28
|
from .function import EmployeeFunction, Functions
|
|
29
29
|
from .hours import FixedHours, VariableHours
|
|
30
30
|
from .leave import Leave, LeaveBalance, LeaveGroup
|
|
@@ -32,115 +32,119 @@ from .manager import EmployeeManager, Manager
|
|
|
32
32
|
from .salaries import Salaries
|
|
33
33
|
from .salary_tables import SalaryScales, SalarySteps, SalaryTables
|
|
34
34
|
from .schedules import Schedule
|
|
35
|
-
from .
|
|
35
|
+
from .svw_settings import CompanySVWSettings, EmployeeSVWSettings
|
|
36
|
+
from .wage_tax import CompanyWageTax, WageTax
|
|
36
37
|
from .wagecomponents import EmployeeFixedWageComponents, EmployeeVariableWageComponents
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
class Nmbrs(BrynQ):
|
|
40
|
-
def __init__(self, system_type: Optional[Literal['source', 'target']] = None, debug: bool = False
|
|
41
|
+
def __init__(self, system_type: Optional[Literal['source', 'target']] = None, debug: bool = False):
|
|
41
42
|
"""
|
|
42
43
|
Initialize the Nmbrs class.
|
|
43
44
|
|
|
44
45
|
Args:
|
|
45
|
-
|
|
46
|
+
system_type: The type of system ('source' or 'target')
|
|
46
47
|
debug: Whether to print debug information
|
|
47
|
-
mock_mode: If true, data will NOT be sent to Nmbrs but only be tested for validity against Pydantic schemas
|
|
48
48
|
"""
|
|
49
|
-
|
|
49
|
+
super().__init__()
|
|
50
|
+
self.mock_mode = False # Always disabled, kept for backwards compatibility with existing code
|
|
50
51
|
self.debug = debug
|
|
51
52
|
self.timeout = 3600
|
|
52
53
|
self.system_type = system_type
|
|
54
|
+
self.data_interface_id = os.getenv("DATA_INTERFACE_ID")
|
|
55
|
+
|
|
56
|
+
# Fetch and store credentials
|
|
57
|
+
credentials = self.interfaces.credentials.get(system="nmbrs", system_type=system_type)
|
|
58
|
+
if isinstance(credentials, list):
|
|
59
|
+
credentials = credentials[0] if credentials else {}
|
|
60
|
+
if not isinstance(credentials, dict):
|
|
61
|
+
credentials = {}
|
|
62
|
+
self._credentials = credentials.get("data", credentials) or {}
|
|
63
|
+
self._custom_config = (
|
|
64
|
+
credentials.get("custom_config")
|
|
65
|
+
or credentials.get("custom_data")
|
|
66
|
+
or {}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
headers = self._get_request_headers()
|
|
70
|
+
self.base_url = "https://api.nmbrsapp.com/api/"
|
|
71
|
+
self.session = requests.Session()
|
|
72
|
+
self.session.headers.update(headers)
|
|
53
73
|
|
|
54
|
-
# Initialize
|
|
74
|
+
# Initialize SOAP client
|
|
75
|
+
self.soap_settings = Settings(
|
|
76
|
+
strict=False,
|
|
77
|
+
xml_huge_tree=True,
|
|
78
|
+
force_https=True
|
|
79
|
+
)
|
|
80
|
+
self.soap_client_companies = Client(
|
|
81
|
+
'https://api.nmbrs.nl/soap/v3/CompanyService.asmx?wsdl',
|
|
82
|
+
settings=self.soap_settings
|
|
83
|
+
)
|
|
84
|
+
self.soap_client_employees = Client(
|
|
85
|
+
'https://api.nmbrs.nl/soap/v3/EmployeeService.asmx?wsdl',
|
|
86
|
+
settings=self.soap_settings
|
|
87
|
+
)
|
|
88
|
+
self.soap_auth_header = self._get_soap_auth_header()
|
|
89
|
+
self.companies = Companies(self)
|
|
90
|
+
# Following methods can only be used if the SOAP authentication header is set (optional, this is not always in scope for all integrations)
|
|
91
|
+
if self.soap_auth_header is not None:
|
|
92
|
+
self.soap_company_ids = self.companies.get_soap_ids()
|
|
93
|
+
self.salary_tables = SalaryTables(self)
|
|
94
|
+
self.salary_scales = SalaryScales(self)
|
|
95
|
+
self.salary_steps = SalarySteps(self)
|
|
96
|
+
self.wage_tax = WageTax(self)
|
|
97
|
+
self.absence = Absence(self)
|
|
98
|
+
self.children = Children(self)
|
|
55
99
|
self.address = Address(self)
|
|
56
100
|
self.bank = Bank(self)
|
|
57
|
-
self.
|
|
101
|
+
self.cost_center = Costcenter(self)
|
|
102
|
+
self.employee_cost_center = EmployeeCostcenter(self)
|
|
103
|
+
if self.soap_auth_header is None:
|
|
104
|
+
self.children = Children(self)
|
|
105
|
+
self.debtor = Debtors(self)
|
|
58
106
|
self.contract = Contract(self)
|
|
107
|
+
self.employee_department = EmployeeDepartment(self)
|
|
108
|
+
self.department = Departments(self)
|
|
109
|
+
debtors, _ = self.debtor.get()
|
|
110
|
+
self.debtor_ids = debtors['debtor_id'].to_list()
|
|
111
|
+
self.company_ids = self.companies.get()['companyId'].to_list()
|
|
112
|
+
self.employees = Employees(self)
|
|
113
|
+
self.employment = Employment(self)
|
|
114
|
+
self.employee_function = EmployeeFunction(self)
|
|
115
|
+
self.function = Functions(self)
|
|
116
|
+
self.fixed_hours = FixedHours(self)
|
|
117
|
+
self.fixed_days = FixedDays(self)
|
|
118
|
+
self.variable_hours = VariableHours(self)
|
|
119
|
+
self.variable_days = VariableDays(self)
|
|
120
|
+
self.manager = Manager(self)
|
|
121
|
+
self.employee_manager = EmployeeManager(self)
|
|
122
|
+
self.salaries = Salaries(self)
|
|
123
|
+
self.schedule = Schedule(self)
|
|
124
|
+
self.fixed_wagecomponents = EmployeeFixedWageComponents(self)
|
|
125
|
+
self.variable_wagecomponents = EmployeeVariableWageComponents(self)
|
|
126
|
+
self.current_period = self.companies.get_current_period()
|
|
127
|
+
|
|
128
|
+
self.company_wage_tax = CompanyWageTax(self)
|
|
129
|
+
self.documents = Document(self)
|
|
130
|
+
self.company_svw_settings = CompanySVWSettings(self)
|
|
131
|
+
self.employee_svw_settings = EmployeeSVWSettings(self)
|
|
132
|
+
self.employee_wage_tax_settings = EmployeeWageTaxSettings(self)
|
|
133
|
+
self.extra_field_settings = ExtraFieldSettings(self)
|
|
134
|
+
self.employee_extra_fields = EmployeeExtraFields(self)
|
|
59
135
|
self.leave = Leave(self)
|
|
60
|
-
self.
|
|
61
|
-
self.
|
|
62
|
-
|
|
63
|
-
self.employee_document = EmployeeDocument(self)
|
|
64
|
-
self.departments = Departments(self)
|
|
65
|
-
self.debtor = Debtors(self)
|
|
66
|
-
self.companies = Companies(self)
|
|
136
|
+
self.leave_balance = LeaveBalance(self)
|
|
137
|
+
self.leave_groups = LeaveGroup(self)
|
|
138
|
+
|
|
67
139
|
|
|
68
|
-
if mock_mode is False:
|
|
69
|
-
# Initialize BrynQ parent class for REST API credentials
|
|
70
|
-
super().__init__()
|
|
71
|
-
self.data_interface_id = os.getenv("DATA_INTERFACE_ID")
|
|
72
|
-
|
|
73
|
-
# Get credentials once and store
|
|
74
|
-
self._credentials = self.interfaces.credentials.get(system='nmbrs', system_type=self.system_type)
|
|
75
|
-
self._custom_config = self._credentials.get("custom_data", {})
|
|
76
|
-
|
|
77
|
-
headers = self._get_request_headers()
|
|
78
|
-
self.base_url = "https://api.nmbrsapp.com/api/"
|
|
79
|
-
self.session = requests.Session()
|
|
80
|
-
self.session.headers.update(headers)
|
|
81
|
-
|
|
82
|
-
# Initialize SOAP clients
|
|
83
|
-
self.soap_settings = Settings(
|
|
84
|
-
strict=False,
|
|
85
|
-
xml_huge_tree=True,
|
|
86
|
-
force_https=True
|
|
87
|
-
)
|
|
88
|
-
self.soap_client_companies = Client(
|
|
89
|
-
'https://api.nmbrs.nl/soap/v3/CompanyService.asmx?wsdl',
|
|
90
|
-
settings=self.soap_settings
|
|
91
|
-
)
|
|
92
|
-
self.soap_client_employees = Client(
|
|
93
|
-
'https://api.nmbrs.nl/soap/v3/EmployeeService.asmx?wsdl',
|
|
94
|
-
settings=self.soap_settings
|
|
95
|
-
)
|
|
96
|
-
self.soap_client_debtors = Client(
|
|
97
|
-
'https://api.nmbrs.nl/soap/v3/DebtorService.asmx?wsdl',
|
|
98
|
-
settings=self.soap_settings
|
|
99
|
-
)
|
|
100
|
-
# Create auth headers for each service (namespace must match)
|
|
101
|
-
self.soap_auth_header = self._create_soap_auth_header(self.soap_client_companies)
|
|
102
|
-
self.soap_auth_header_employees = self._create_soap_auth_header(self.soap_client_employees)
|
|
103
|
-
self.soap_auth_header_debtors = self._create_soap_auth_header(self.soap_client_debtors)
|
|
104
|
-
|
|
105
|
-
# REST API dependent classes
|
|
106
|
-
self.employee_department = EmployeeDepartment(self)
|
|
107
|
-
|
|
108
|
-
debtors, _ = self.debtor.get()
|
|
109
|
-
self.debtor_ids = debtors['debtor_id'].to_list()
|
|
110
|
-
self.company_ids = self.companies.get()['companyId'].to_list()
|
|
111
|
-
|
|
112
|
-
# SOAP dependent on REST - companies must be defined first
|
|
113
|
-
if self.soap_auth_header is not None:
|
|
114
|
-
self.employees = Employees(self)
|
|
115
|
-
self.soap_company_ids = self.companies.get_soap_ids()
|
|
116
|
-
self.soap_employee_ids = self.employees.get_soap_ids()
|
|
117
|
-
self.salary_tables = SalaryTables(self)
|
|
118
|
-
self.salary_scales = SalaryScales(self)
|
|
119
|
-
self.salary_steps = SalarySteps(self)
|
|
120
|
-
self.wage_tax = WageTax(self)
|
|
121
|
-
self.absence = Absence(self)
|
|
122
|
-
|
|
123
|
-
self.employees = Employees(self)
|
|
124
|
-
self.employment = Employment(self)
|
|
125
|
-
self.wage_tax_settings = WageTaxSettings(self)
|
|
126
|
-
self.fixed_hours = FixedHours(self)
|
|
127
|
-
self.fixed_days = FixedDays(self)
|
|
128
|
-
self.variable_hours = VariableHours(self)
|
|
129
|
-
self.variable_days = VariableDays(self)
|
|
130
|
-
self.manager = Manager(self)
|
|
131
|
-
self.employee_manager = EmployeeManager(self)
|
|
132
|
-
self.salaries = Salaries(self)
|
|
133
|
-
self.schedule = Schedule(self)
|
|
134
|
-
self.fixed_wagecomponents = EmployeeFixedWageComponents(self)
|
|
135
|
-
self.variable_wagecomponents = EmployeeVariableWageComponents(self)
|
|
136
|
-
self.current_period = self.companies.get_current_period()
|
|
137
|
-
self.cost_center = Costcenter(self)
|
|
138
|
-
self.employee_cost_center = EmployeeCostcenter(self)
|
|
139
|
-
self.cost_unit = Costunit(self)
|
|
140
|
-
self.employee_wage_tax_settings = EmployeeWageTaxSettings(self)
|
|
141
140
|
def _get_request_headers(self):
|
|
142
|
-
access_token = self._credentials.get('
|
|
143
|
-
subscription_key =
|
|
141
|
+
access_token = self._credentials.get('access_token')
|
|
142
|
+
subscription_key = (
|
|
143
|
+
self._custom_config.get("subscription_key")
|
|
144
|
+
or self._custom_config.get("subscriptionKey")
|
|
145
|
+
or self._credentials.get("subscription_key")
|
|
146
|
+
or self._credentials.get("subscriptionKey")
|
|
147
|
+
)
|
|
144
148
|
headers = {
|
|
145
149
|
"accept": "application/json",
|
|
146
150
|
"Authorization": f"Bearer {access_token.strip() if access_token else ''}",
|
brynq_sdk_nmbrs/absence.py
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
from typing import Any, Dict,
|
|
1
|
+
from typing import Any, Dict, Tuple
|
|
2
2
|
import pandas as pd
|
|
3
3
|
from .schemas.absence import AbsenceCreate, AbsenceGet
|
|
4
4
|
from zeep.exceptions import Fault
|
|
5
|
-
from zeep.ns import WSDL, SOAP_ENV_11
|
|
6
|
-
from zeep.xsd import ComplexType, Element, String
|
|
7
5
|
from zeep.helpers import serialize_object
|
|
8
|
-
# import logging
|
|
9
6
|
from brynq_sdk_functions import Functions
|
|
10
7
|
|
|
11
8
|
|
brynq_sdk_nmbrs/address.py
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
1
3
|
import pandas as pd
|
|
2
4
|
import requests
|
|
3
|
-
|
|
4
|
-
from .schemas.address import AddressCreate, AddressGet, AddressDelete, AddressUpdate, Period
|
|
5
|
+
|
|
5
6
|
from brynq_sdk_functions import Functions
|
|
6
7
|
|
|
8
|
+
from .schemas.address import AddressCreate, AddressGet
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
class Address:
|
|
9
12
|
def __init__(self, nmbrs):
|
|
@@ -65,82 +68,3 @@ class Address:
|
|
|
65
68
|
timeout=self.nmbrs.timeout
|
|
66
69
|
)
|
|
67
70
|
return resp
|
|
68
|
-
|
|
69
|
-
def delete(self, employee_id: Union[int, str], address_id: Union[int, str]) -> bool:
|
|
70
|
-
"""
|
|
71
|
-
Delete an address for an employee using SOAP API.
|
|
72
|
-
|
|
73
|
-
REST API does not support address deletion, so we use SOAP as interim solution.
|
|
74
|
-
|
|
75
|
-
Args:
|
|
76
|
-
employee_id: The ID of the employee
|
|
77
|
-
address_id: The ID of the address to delete
|
|
78
|
-
|
|
79
|
-
Returns:
|
|
80
|
-
bool: True if deletion was successful
|
|
81
|
-
|
|
82
|
-
Raises:
|
|
83
|
-
Exception: If SOAP client is not available or deletion fails
|
|
84
|
-
"""
|
|
85
|
-
# Validate input using Pydantic schema
|
|
86
|
-
delete_model = AddressDelete(employeeId=int(employee_id), addressId=int(address_id))
|
|
87
|
-
|
|
88
|
-
if self.nmbrs.mock_mode:
|
|
89
|
-
return delete_model
|
|
90
|
-
|
|
91
|
-
# Call SOAP Address_Delete using EmployeeService auth header
|
|
92
|
-
resp = self.nmbrs.soap_client_employees.service.Address_Delete(
|
|
93
|
-
EmployeeId=delete_model.employee_id,
|
|
94
|
-
AddressID=delete_model.address_id,
|
|
95
|
-
_soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_employees}
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
return resp
|
|
99
|
-
|
|
100
|
-
def update(self, employee_id: Union[int, str], data: Dict[str, Any]):
|
|
101
|
-
"""
|
|
102
|
-
Update an address for an employee using SOAP API.
|
|
103
|
-
|
|
104
|
-
Args:
|
|
105
|
-
employee_id: The ID of the employee
|
|
106
|
-
data: Dictionary containing address data with fields matching AddressUpdate schema:
|
|
107
|
-
- id: Address ID to update
|
|
108
|
-
- street: Street name
|
|
109
|
-
- house_number: House number (optional)
|
|
110
|
-
- house_number_addition: House number addition (optional)
|
|
111
|
-
- postal_code: Postal code (optional)
|
|
112
|
-
- city: City name
|
|
113
|
-
- state_province: State or province (optional)
|
|
114
|
-
- country_iso_code: Country ISO code (e.g., "NL")
|
|
115
|
-
|
|
116
|
-
Returns:
|
|
117
|
-
Response from the API
|
|
118
|
-
"""
|
|
119
|
-
# Validate with Pydantic model
|
|
120
|
-
address_model = AddressUpdate(**data)
|
|
121
|
-
|
|
122
|
-
if self.nmbrs.mock_mode:
|
|
123
|
-
return address_model
|
|
124
|
-
|
|
125
|
-
# Create EmployeeAddress type
|
|
126
|
-
AddressType = self.nmbrs.soap_client_employees.get_type('ns0:EmployeeAddress')
|
|
127
|
-
soap_address = AddressType(
|
|
128
|
-
Id=address_model.id,
|
|
129
|
-
Default=address_model.default,
|
|
130
|
-
Street=address_model.street,
|
|
131
|
-
HouseNumber=address_model.house_number or '',
|
|
132
|
-
HouseNumberAddition=address_model.house_number_addition or '',
|
|
133
|
-
PostalCode=address_model.postal_code or '',
|
|
134
|
-
City=address_model.city,
|
|
135
|
-
StateProvince=address_model.state_province or '',
|
|
136
|
-
CountryISOCode=address_model.country_iso_code,
|
|
137
|
-
Type=address_model.address_type
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
# Call SOAP Address_Update
|
|
141
|
-
result = self.nmbrs.soap_client_employees.service.Address_Update(
|
|
142
|
-
EmployeeId=int(employee_id),
|
|
143
|
-
Address=soap_address,
|
|
144
|
-
_soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_employees}
|
|
145
|
-
)
|
|
146
|
-
return result
|
brynq_sdk_nmbrs/bank.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import math
|
|
2
1
|
from typing import Any, Dict
|
|
3
2
|
|
|
4
3
|
import pandas as pd
|
|
@@ -40,7 +39,7 @@ class Bank:
|
|
|
40
39
|
record_path='bankAccounts',
|
|
41
40
|
meta=['employeeId']
|
|
42
41
|
)
|
|
43
|
-
except requests.HTTPError
|
|
42
|
+
except requests.HTTPError:
|
|
44
43
|
df = pd.DataFrame()
|
|
45
44
|
|
|
46
45
|
return df
|
brynq_sdk_nmbrs/companies.py
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Optional
|
|
3
|
+
|
|
1
4
|
import pandas as pd
|
|
2
5
|
import requests
|
|
3
|
-
import
|
|
4
|
-
from
|
|
6
|
+
from zeep.exceptions import Fault
|
|
7
|
+
from zeep.helpers import serialize_object
|
|
5
8
|
|
|
6
|
-
from .
|
|
9
|
+
from .bank import Bank
|
|
7
10
|
from .costcenter import Costcenter
|
|
8
11
|
from .costunit import Costunit
|
|
9
12
|
from .hours import Hours
|
|
10
|
-
from .
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
from
|
|
14
|
-
from zeep.helpers import serialize_object
|
|
13
|
+
from .leave import LeaveGroup
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from brynq_sdk_nmbrs import Nmbrs
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
class Companies:
|
|
18
20
|
def __init__(self, nmbrs):
|
|
19
|
-
self.nmbrs = nmbrs
|
|
21
|
+
self.nmbrs: Nmbrs = nmbrs
|
|
20
22
|
self.costcenters = Costcenter(nmbrs)
|
|
21
23
|
self.costunits = Costunit(nmbrs)
|
|
22
24
|
self.hours = Hours(nmbrs)
|
|
@@ -57,7 +59,7 @@ class Companies:
|
|
|
57
59
|
"""
|
|
58
60
|
try:
|
|
59
61
|
# Make SOAP request with the proper header structure
|
|
60
|
-
response = self.soap_client_companies.service.List_GetAll(
|
|
62
|
+
response = self.nmbrs.soap_client_companies.service.List_GetAll(
|
|
61
63
|
_soapheaders=[self.nmbrs.soap_auth_header]
|
|
62
64
|
)
|
|
63
65
|
|
|
@@ -97,41 +99,130 @@ class Companies:
|
|
|
97
99
|
self.logger.exception("Exception occurred:")
|
|
98
100
|
raise Exception(f"Failed to get current period: {str(e)}")
|
|
99
101
|
|
|
100
|
-
def
|
|
102
|
+
def get_wage_models(self,
|
|
103
|
+
company_id: Optional[str] = None,
|
|
104
|
+
period: Optional[int] = None,
|
|
105
|
+
year: Optional[int] = None) -> pd.DataFrame:
|
|
101
106
|
"""
|
|
102
|
-
|
|
107
|
+
Get company wage models per period.
|
|
108
|
+
|
|
109
|
+
Returns the available wage codes for employees of this company in the
|
|
110
|
+
period consulted. If no period is used it returns the current period information.
|
|
103
111
|
|
|
104
112
|
Args:
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
- period_type: Period type (1=Monthly, 2=4-Weekly, 3=Weekly, 4=Quarterly)
|
|
109
|
-
- default_company_id: Default company ID to copy settings from (0 for none)
|
|
110
|
-
- labour_agreement_settings_group_guid: Labour agreement settings group GUID
|
|
111
|
-
- pay_in_advance: Pay in advance
|
|
113
|
+
company_id: Optional company ID. If not provided, fetches for all companies.
|
|
114
|
+
period: Optional period filter
|
|
115
|
+
year: Optional year filter
|
|
112
116
|
|
|
113
117
|
Returns:
|
|
114
|
-
|
|
118
|
+
DataFrame containing wage models
|
|
115
119
|
"""
|
|
116
|
-
|
|
120
|
+
if company_id:
|
|
121
|
+
return self._get_wage_models(company_id, period, year)
|
|
117
122
|
|
|
118
|
-
|
|
119
|
-
|
|
123
|
+
df = pd.DataFrame()
|
|
124
|
+
for company in self.nmbrs.company_ids:
|
|
125
|
+
df = pd.concat([df, self._get_wage_models(company, period, year)])
|
|
120
126
|
|
|
121
|
-
|
|
122
|
-
response = self.soap_client_companies.service.Company_Insert(
|
|
123
|
-
DebtorId=company_model.debtor_id,
|
|
124
|
-
CompanyName=company_model.company_name,
|
|
125
|
-
PeriodType=company_model.period_type,
|
|
126
|
-
DefaultCompanyId=company_model.default_company_id,
|
|
127
|
-
LabourAgreementSettingsGroupGuid=company_model.labour_agreement_settings_group_guid or "00000000-0000-0000-0000-000000000000",
|
|
128
|
-
PayInAdvance=company_model.pay_in_advance,
|
|
129
|
-
_soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header}
|
|
130
|
-
)
|
|
131
|
-
return response
|
|
127
|
+
return df
|
|
132
128
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
129
|
+
def _get_wage_models(self,
|
|
130
|
+
company_id: str,
|
|
131
|
+
period: Optional[int] = None,
|
|
132
|
+
year: Optional[int] = None) -> pd.DataFrame:
|
|
133
|
+
"""
|
|
134
|
+
Internal method to get wage models for a single company.
|
|
135
|
+
"""
|
|
136
|
+
params = {}
|
|
137
|
+
if period is not None:
|
|
138
|
+
params['period'] = period
|
|
139
|
+
if year is not None:
|
|
140
|
+
params['year'] = year
|
|
141
|
+
|
|
142
|
+
request = requests.Request(
|
|
143
|
+
method='GET',
|
|
144
|
+
url=f"{self.nmbrs.base_url}companies/{company_id}/wagemodels",
|
|
145
|
+
params=params
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
149
|
+
df = pd.DataFrame(data)
|
|
150
|
+
|
|
151
|
+
if not df.empty:
|
|
152
|
+
df['companyId'] = company_id
|
|
153
|
+
|
|
154
|
+
return df
|
|
155
|
+
|
|
156
|
+
def get_addresses(self, company_id: Optional[str] = None) -> pd.DataFrame:
|
|
157
|
+
"""
|
|
158
|
+
Get addresses history for a company.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
company_id: Optional company ID. If not provided, fetches for all companies.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
DataFrame containing company addresses
|
|
165
|
+
"""
|
|
166
|
+
if company_id:
|
|
167
|
+
return self._get_addresses(company_id)
|
|
168
|
+
|
|
169
|
+
df = pd.DataFrame()
|
|
170
|
+
for company in self.nmbrs.company_ids:
|
|
171
|
+
df = pd.concat([df, self._get_addresses(company)])
|
|
172
|
+
|
|
173
|
+
return df
|
|
174
|
+
|
|
175
|
+
def _get_addresses(self, company_id: str) -> pd.DataFrame:
|
|
176
|
+
"""
|
|
177
|
+
Internal method to get addresses for a single company.
|
|
178
|
+
"""
|
|
179
|
+
request = requests.Request(
|
|
180
|
+
method='GET',
|
|
181
|
+
url=f"{self.nmbrs.base_url}companies/{company_id}/addresses"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
185
|
+
df = pd.DataFrame(data)
|
|
186
|
+
|
|
187
|
+
if not df.empty:
|
|
188
|
+
df['companyId'] = company_id
|
|
189
|
+
|
|
190
|
+
return df
|
|
191
|
+
|
|
192
|
+
def get_contact_persons(self, company_id: Optional[str] = None) -> pd.DataFrame:
|
|
193
|
+
"""
|
|
194
|
+
Get contact persons for a company.
|
|
195
|
+
|
|
196
|
+
There's no history on these values.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
company_id: Optional company ID. If not provided, fetches for all companies.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
DataFrame containing contact persons
|
|
203
|
+
"""
|
|
204
|
+
if company_id:
|
|
205
|
+
return self._get_contact_persons(company_id)
|
|
206
|
+
|
|
207
|
+
df = pd.DataFrame()
|
|
208
|
+
for company in self.nmbrs.company_ids:
|
|
209
|
+
df = pd.concat([df, self._get_contact_persons(company)])
|
|
210
|
+
|
|
211
|
+
return df
|
|
212
|
+
|
|
213
|
+
def _get_contact_persons(self, company_id: str) -> pd.DataFrame:
|
|
214
|
+
"""
|
|
215
|
+
Internal method to get contact persons for a single company.
|
|
216
|
+
"""
|
|
217
|
+
request = requests.Request(
|
|
218
|
+
method='GET',
|
|
219
|
+
url=f"{self.nmbrs.base_url}companies/{company_id}/contactpersons"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
data = self.nmbrs.get_paginated_result(request)
|
|
223
|
+
df = pd.DataFrame(data)
|
|
224
|
+
|
|
225
|
+
if not df.empty:
|
|
226
|
+
df['companyId'] = company_id
|
|
227
|
+
|
|
228
|
+
return df
|
brynq_sdk_nmbrs/contract.py
CHANGED
brynq_sdk_nmbrs/days.py
CHANGED
|
@@ -2,7 +2,7 @@ import pandas as pd
|
|
|
2
2
|
import requests
|
|
3
3
|
from typing import Dict, Any
|
|
4
4
|
from .schemas.days import (
|
|
5
|
-
VariableDaysGet, VariableDaysCreate, FixedDaysCreate
|
|
5
|
+
VariableDaysGet, VariableDaysCreate, FixedDaysCreate
|
|
6
6
|
)
|
|
7
7
|
from brynq_sdk_functions import Functions
|
|
8
8
|
|