brynq-sdk-nmbrs 2.2.2__tar.gz → 2.3.1__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.
Files changed (57) hide show
  1. brynq_sdk_nmbrs-2.3.1/PKG-INFO +21 -0
  2. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/__init__.py +22 -0
  3. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/employees.py +19 -1
  4. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/address.py +1 -0
  5. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/bank.py +2 -0
  6. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/contracts.py +2 -0
  7. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/costcenter.py +2 -0
  8. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/costunit.py +2 -0
  9. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/days.py +2 -0
  10. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/department.py +2 -0
  11. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/employees.py +12 -1
  12. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/employment.py +2 -0
  13. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/function.py +1 -0
  14. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/hours.py +4 -0
  15. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/leave.py +1 -0
  16. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/manager.py +3 -0
  17. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/salary.py +1 -0
  18. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/schedules.py +1 -0
  19. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/wage_tax.py +42 -1
  20. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/wagecomponents.py +4 -0
  21. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/wage_tax.py +48 -2
  22. brynq_sdk_nmbrs-2.3.1/brynq_sdk_nmbrs.egg-info/PKG-INFO +21 -0
  23. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/setup.py +1 -1
  24. brynq_sdk_nmbrs-2.2.2/PKG-INFO +0 -10
  25. brynq_sdk_nmbrs-2.2.2/brynq_sdk_nmbrs.egg-info/PKG-INFO +0 -10
  26. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/absence.py +0 -0
  27. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/address.py +0 -0
  28. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/bank.py +0 -0
  29. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/children.py +0 -0
  30. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/companies.py +0 -0
  31. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/contract.py +0 -0
  32. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/costcenter.py +0 -0
  33. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/costunit.py +0 -0
  34. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/days.py +0 -0
  35. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/debtors.py +0 -0
  36. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/department.py +0 -0
  37. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/document.py +0 -0
  38. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/employment.py +0 -0
  39. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/function.py +0 -0
  40. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/hours.py +0 -0
  41. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/leave.py +0 -0
  42. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/manager.py +0 -0
  43. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/salaries.py +0 -0
  44. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/salary_tables.py +0 -0
  45. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schedules.py +0 -0
  46. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/__init__.py +0 -0
  47. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/absence.py +0 -0
  48. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/debtor.py +0 -0
  49. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/schemas/social_insurance.py +0 -0
  50. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/social_insurance.py +0 -0
  51. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs/wagecomponents.py +0 -0
  52. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs.egg-info/SOURCES.txt +0 -0
  53. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs.egg-info/dependency_links.txt +0 -0
  54. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs.egg-info/not-zip-safe +0 -0
  55. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs.egg-info/requires.txt +0 -0
  56. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/brynq_sdk_nmbrs.egg-info/top_level.txt +0 -0
  57. {brynq_sdk_nmbrs-2.2.2 → brynq_sdk_nmbrs-2.3.1}/setup.cfg +0 -0
@@ -0,0 +1,21 @@
1
+ Metadata-Version: 2.4
2
+ Name: brynq_sdk_nmbrs
3
+ Version: 2.3.1
4
+ Summary: Nmbrs wrapper from BrynQ
5
+ Author: BrynQ
6
+ Author-email: support@brynq.com
7
+ License: BrynQ License
8
+ Requires-Dist: brynq-sdk-brynq<5,>=4
9
+ Requires-Dist: pandas<3.0.0,>=2.2.0
10
+ Requires-Dist: pydantic<3.0.0,>=2.5.0
11
+ Requires-Dist: pandera<1.0.0,>=0.16.0
12
+ Requires-Dist: zeep<5.0.0,>=4.0.0
13
+ Requires-Dist: brynq-sdk-functions>=2.0.5
14
+ Dynamic: author
15
+ Dynamic: author-email
16
+ Dynamic: description
17
+ Dynamic: license
18
+ Dynamic: requires-dist
19
+ Dynamic: summary
20
+
21
+ Nmbrs wrapper from BrynQ
@@ -139,6 +139,28 @@ class Nmbrs(BrynQ):
139
139
 
140
140
  return auth_header
141
141
 
142
+ def _get_soap_auth_header_employees(self):
143
+ """
144
+ Creates the SOAP authentication header using credentials from initial_credentials.
145
+
146
+ Returns:
147
+ AuthHeaderWithDomainType: The authentication header for SOAP requests
148
+ """
149
+ initial_credentials = self.get_system_credential(system='nmbrs', label='bob')
150
+ config = initial_credentials.get("config", {})
151
+
152
+ # Get the AuthHeaderWithDomain type from the WSDL
153
+ AuthHeaderWithDomainType = self.soap_client_employees.get_element('ns0:AuthHeaderWithDomain')
154
+
155
+ # Create the auth header using credentials from config
156
+ auth_header = AuthHeaderWithDomainType(
157
+ Username=config.get("soap_api_username"),
158
+ Token=config.get("soap_api_token"),
159
+ Domain=config.get("soap_api_domain")
160
+ )
161
+
162
+ return auth_header
163
+
142
164
  def get_paginated_result(self, request: requests.Request) -> List:
143
165
  has_next_page = True
144
166
  result_data = []
@@ -22,7 +22,7 @@ from .days import VariableDays
22
22
  from .wagecomponents import EmployeeVariableWageComponents, EmployeeFixedWageComponents
23
23
  from .leave import Leave, LeaveBalance
24
24
  from .schemas.employees import (
25
- EmployeeGet, EmployeeCreate, EmployeeUpdate, EmployeeDelete,
25
+ BsnGet, EmployeeGet, EmployeeCreate, EmployeeUpdate, EmployeeDelete,
26
26
  BasicInfo, BirthInfo, ContactInfo, PartnerInfo, Period, AdditionalEmployeeInfo,
27
27
  CreateEmployeePersonalInfo
28
28
  )
@@ -83,6 +83,24 @@ class Employees:
83
83
 
84
84
  return df
85
85
 
86
+ def get_private_info(self) -> str:
87
+ combined = []
88
+ for company_id in self.nmbrs.company_ids:
89
+ request = requests.Request(method='GET',
90
+ url=f"{self.nmbrs.base_url}companies/{company_id}/employees/privateInfos")
91
+ data = self.nmbrs.get_paginated_result(request)
92
+ df = pd.json_normalize(
93
+ data,
94
+ record_path='privateInfos',
95
+ meta=['employeeId']
96
+ )
97
+ df['companyId'] = company_id
98
+ combined.append(df)
99
+ df = pd.concat(combined, ignore_index=True)
100
+ valid_bsn, invalid_bsn = Functions.validate_data(df, BsnGet)
101
+
102
+ return valid_bsn, invalid_bsn
103
+
86
104
  def get_default_templates(self) -> pd.DataFrame:
87
105
  default_templates = pd.DataFrame()
88
106
  for company in self.nmbrs.company_ids:
@@ -49,6 +49,7 @@ class Period(BaseModel):
49
49
  period: int = Field(..., ge=1, le=53, example=4, description="Period", alias="period")
50
50
 
51
51
  class AddressCreate(BaseModel):
52
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
52
53
  is_default: Optional[bool] = Field(None, description="Default Address", alias="isDefault")
53
54
  type: Annotated[
54
55
  str,
@@ -53,6 +53,7 @@ class BankGet(BrynQPanderaDataFrameModel):
53
53
  # Upload Schemas
54
54
  # ---------------------------
55
55
  class BankCreate(BaseModel):
56
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
56
57
  number: Optional[str] = Field(None, max_length=34, example="123456789", description="Bank Account Number", alias="number")
57
58
  description: Optional[str] = Field(None, max_length=100, example="Salary Bank", description="Bank Account Description", alias="description")
58
59
  iban: str = Field(..., min_length=5, max_length=34, example="NL20INGB0001234567", description="IBAN", alias="IBAN")
@@ -61,6 +62,7 @@ class BankCreate(BaseModel):
61
62
  bank_account_type: Optional[BankAccountType] = Field(None, example=BankAccountType.BANK_ACCOUNT_1.value, description="Bank Account Type", alias="bankAccountType")
62
63
 
63
64
  class BankUpdate(BaseModel):
65
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
64
66
  bank_account_id: str = Field(..., example="49a69eda-252e-4ccb-a220-38ea90511d4f", description="Bank Account ID", alias="bankAccountId")
65
67
  number: Optional[str] = Field(None, max_length=34, example="123456789", description="Bank Account Number", alias="number")
66
68
  description: Optional[str] = Field(None, max_length=100, example="Main Checking Account", description="Bank Account Description", alias="description")
@@ -36,6 +36,7 @@ class ContractGet(BrynQPanderaDataFrameModel):
36
36
  # Upload Schemas
37
37
  # ---------------------------
38
38
  class ContractCreate(BaseModel):
39
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
39
40
  start_date_contract: datetime = Field(..., example="2021-01-01T09:29:18Z", description="Start Date Contract", alias="startDate")
40
41
  trial_period: Optional[datetime] = Field(None, example="2021-02-01T00:00:00Z", description="Trial Period Contract", alias="trialPeriod")
41
42
  end_date_contract: Optional[datetime] = Field(None, example="2021-08-24T14:15:22Z", description="End Date Contract", alias="endDate")
@@ -44,6 +45,7 @@ class ContractCreate(BaseModel):
44
45
  weekly_hours: Optional[float] = Field(None, ge=0, le=168, example=40, description="Contract Hours per Week", alias="hoursPerWeek")
45
46
 
46
47
  class ContractUpdate(BaseModel):
48
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
47
49
  contract_id: str = Field(..., example="e35e343b-55a3-4e44-bc4b-f41c3b93bcf5", description="Contract ID", alias="contractId")
48
50
  trial_period: Optional[datetime] = Field(None, example="2021-07-31T00:00:00Z", description="Trial Period Contract", alias="trialPeriod")
49
51
  end_date_contract: Optional[datetime] = Field(None, example="2021-12-31T00:00:00Z", description="End Date Contract", alias="endDate")
@@ -74,10 +74,12 @@ class EmployeeCostcenterDelete(BaseModel):
74
74
  # CostCenter CRUD schemas - These are hypothetical since the API doesn't have create/update/delete endpoints
75
75
  # but we add them for consistency with other schema files
76
76
  class CostcenterCreate(BaseModel):
77
+ company_id: str = Field(..., description="Company identifier", alias="companyId")
77
78
  code: str = Field(..., example="CC001", description="Code", alias="code")
78
79
  description: str = Field(..., example="Sales Department", description="Description", alias="description")
79
80
 
80
81
  class CostcenterUpdate(BaseModel):
82
+ company_id: str = Field(..., description="Company identifier", alias="companyId")
81
83
  cost_center_id: str = Field(..., example="a405f980-1c4c-42c1-8ddb-2d90c58da0b1", description="Cost Center ID", alias="costCenterId")
82
84
  code: str = Field(..., example="CC001", description="Code", alias="code")
83
85
  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")
@@ -86,11 +86,13 @@ class HoursDelete(BaseModel):
86
86
 
87
87
 
88
88
  class FixedDaysCreate(BaseModel):
89
+ employee_id: str = Field(..., 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
92
  period_details: Optional[PeriodPost] = Field(None, example="Period details", description="Period details", alias="periodDetails")
92
93
 
93
94
  class VariableDaysCreate(BaseModel):
95
+ employee_id: str = Field(..., 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
98
  period_details: Optional[PeriodPost] = Field(None, example="Period details", description="Period details", alias="periodDetails")
@@ -44,10 +44,12 @@ class DepartmentGet(BrynQPanderaDataFrameModel):
44
44
  managers: Series[String] = pa.Field(coerce=True, description="List of managers", alias="managers")
45
45
 
46
46
  class DepartmentCreate(BaseModel):
47
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
47
48
  code: int = Field(..., ge=1, example=2, description="Department Code", alias="code")
48
49
  description: str = Field(..., min_length=1, max_length=200, example="Sales", description="Department Description", alias="description")
49
50
 
50
51
  class EmployeeDepartmentUpdate(BaseModel):
52
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
51
53
  department_id: str = Field(..., example="3214", description="Department ID", alias="departmentId")
52
54
  period_details: Period = Field(..., example=Period(year=2021, period=4), description="Period details", alias="periodDetails")
53
55
 
@@ -84,7 +84,7 @@ class BirthInfo(BaseModel):
84
84
  StringConstraints(
85
85
  pattern=r'^[A-Za-z]+$',
86
86
  strip_whitespace=True,
87
- min_length=2,
87
+ min_length=2,
88
88
  max_length=3
89
89
  )
90
90
  ]] = Field(None, example="PT", description="Nationality Code ISO", alias="nationalityCodeISO")
@@ -128,10 +128,12 @@ class CreateEmployeePersonalInfo(BaseModel):
128
128
  created_at: Optional[str] = Field(None, example="2021-07-01T10:15:08Z", description="Created At", alias="createdAt")
129
129
 
130
130
  class EmployeeCreate(BaseModel):
131
+ company_id: str = Field(..., description="Company identifier", alias="companyId")
131
132
  personal_info: CreateEmployeePersonalInfo = Field(..., alias="personalInfo")
132
133
  additional_employee_info: AdditionalEmployeeInfo = Field(..., alias="additionalEmployeeInfo")
133
134
 
134
135
  class EmployeeUpdate(BaseModel):
136
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
135
137
  basic_info: Optional[BasicInfoUpdate] = Field(None, alias="basicInfo")
136
138
  birth_info: Optional[BirthInfo] = Field(None, alias="birthInfo")
137
139
  contact_info: Optional[ContactInfo] = Field(None, alias="contactInfo")
@@ -140,3 +142,12 @@ class EmployeeUpdate(BaseModel):
140
142
 
141
143
  class EmployeeDelete(BaseModel):
142
144
  employee_id: str = Field(..., example="3054d4cf-b449-489d-8d2e-5dd30e5ab994", description="Employee ID", alias="employeeId")
145
+
146
+ class BsnGet(BrynQPanderaDataFrameModel):
147
+ employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
148
+ social_security_number: Series[String] = pa.Field(coerce=True, description="Social Security Number", alias="BSN")
149
+ company_id: Series[String] = pa.Field(coerce=True, description="Company ID", alias="companyId")
150
+ created_at: Series[DateTime] = pa.Field(coerce=True, description="Created At", alias="createdAt")
151
+
152
+ class _Annotation:
153
+ primary_key = "employee_id"
@@ -33,10 +33,12 @@ class EmploymentGet(BrynQPanderaDataFrameModel):
33
33
  # Upload Schemas
34
34
  # ---------------------------
35
35
  class EmploymentCreate(BaseModel):
36
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
36
37
  start_date: datetime = Field(..., example="2021-06-07T07:59:11Z", description="Start Date Employment", alias="startDate")
37
38
  seniority_date: Optional[datetime] = Field(None, example="2021-06-09T07:59:11Z", description="Seniority Date Employment", alias="seniorityDate")
38
39
 
39
40
  class EmploymentUpdate(BaseModel):
41
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
40
42
  employment_id: str = Field(..., example="a405f980-1c4c-42c1-8ddb-2d90c58da0b1", description="Employment ID", alias="employmentId")
41
43
  seniority_date: Optional[datetime] = Field(None, example="2021-06-07T07:59:11Z", description="Seniority Date Employment", alias="seniorityDate")
42
44
  end_of_service_date: Optional[datetime] = Field(None, example="2021-10-01T00:00:00Z", description="End of Service Date Employment", alias="endOfServiceDate")
@@ -45,5 +45,6 @@ class FunctionGet(BrynQPanderaDataFrameModel):
45
45
  created_at: Series[datetime] = pa.Field(coerce=True, description="Function Created At", alias="createdAt")
46
46
 
47
47
  class FunctionUpdate(BaseModel):
48
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
48
49
  function_id: str = Field(..., example="5981", description="Function ID", alias="functionId")
49
50
  period_details: Period = Field(..., alias="periodDetails")
@@ -76,6 +76,7 @@ class PeriodPost(BaseModel):
76
76
  unprotected_mode: Optional[bool] = Field(None, example=False, description="Unprotected Mode", alias="unprotectedMode")
77
77
 
78
78
  class FixedHoursCreate(BaseModel):
79
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
79
80
  hour_code: int = Field(..., ge=1, example=2100, description="Hour Code", alias="hourCode")
80
81
  number_of_hours: float = Field(..., ge=0, le=1000, example=40, description="Hours", alias="hours")
81
82
  cost_center_id: Optional[str] = Field(None, example="aa506564-d1db-4fa8-83dc-d68db4cfcd82", description="Cost Center ID", alias="costCenterId")
@@ -86,6 +87,7 @@ class FixedHoursCreate(BaseModel):
86
87
  period_details: Optional[PeriodPost] = None
87
88
 
88
89
  class FixedHoursUpdate(BaseModel):
90
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
89
91
  hour_component_id: str = Field(..., example="ddaae291-47fa-4c67-bb2f-de0e5da9e8a1", description="Hour Component ID", alias="hourComponentId")
90
92
  hour_code: Optional[int] = Field(None, ge=1, example=2100, description="Hour Code", alias="hourCode")
91
93
  number_of_hours: Optional[float] = Field(None, ge=0, le=1000, example=40, description="Hours", alias="hours")
@@ -97,6 +99,7 @@ class FixedHoursUpdate(BaseModel):
97
99
  period_details: Optional[PeriodPost] = None
98
100
 
99
101
  class VariableHoursCreate(BaseModel):
102
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
100
103
  hour_code: int = Field(..., ge=1, example=2100, description="Hour Code", alias="hourCode")
101
104
  number_of_hours: float = Field(..., ge=0, le=1000, example=3.5, description="Hours", alias="hours")
102
105
  cost_center_id: Optional[str] = Field(None, example="aa506564-d1db-4fa8-83dc-d68db4cfcd82", description="Cost Center ID", alias="costCenterId")
@@ -105,6 +108,7 @@ class VariableHoursCreate(BaseModel):
105
108
  period_details: Optional[PeriodPost] = Field(None, example="Period details", description="Period details", alias="periodDetails")
106
109
 
107
110
  class VariableHoursUpdate(BaseModel):
111
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
108
112
  hour_component_id: str = Field(..., example="49a69eda-252e-4ccb-a220-38ea90511d4f", description="Hour Component ID", alias="hourComponentId")
109
113
  hour_code: Optional[int] = Field(None, ge=1, example=2100, description="Hour Code", alias="hourCode")
110
114
  number_of_hours: Optional[float] = Field(None, ge=0, le=1000, example=45.5, description="Hours", alias="hours")
@@ -33,6 +33,7 @@ class LeaveGet(BrynQPanderaDataFrameModel):
33
33
 
34
34
 
35
35
  class LeaveCreate(BaseModel):
36
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
36
37
  leave_group_id: str = Field(..., example="49a69eda-252e-4ccb-a220-38ea90511d4f", description="Leave Group ID", alias="leaveGroupId")
37
38
  start_date: datetime = Field(..., example="2025-01-01", description="Leave Start Date", alias="startDate")
38
39
  end_date: datetime = Field(..., example="2025-01-02", description="Leave End Date", alias="endDate")
@@ -102,6 +102,7 @@ class Period(BaseModel):
102
102
  period: int = Field(..., ge=1, le=53, example=4, description="Period", alias="period")
103
103
 
104
104
  class ManagerCreate(BaseModel):
105
+ debtor_id: str = Field(..., description="Debtor identifier", alias="debtorId")
105
106
  number: int = Field(..., ge=1, example=1, description="Manager number", alias="number")
106
107
  first_name: str = Field(..., max_length=100, example="John", description="Manager first name", alias="firstName")
107
108
  last_name: str = Field(..., max_length=100, example="Doe", description="Manager last name", alias="lastName")
@@ -112,6 +113,7 @@ class ManagerCreate(BaseModel):
112
113
  email: Optional[str] = Field(None, max_length=100, example="john.doe@company.com", description="Manager email", alias="email")
113
114
 
114
115
  class ManagerUpdate(BaseModel):
116
+ debtor_id: str = Field(..., description="Debtor identifier", alias="debtorId")
115
117
  manager_id: str = Field(..., example="2f6aa11c-504a-49a1-903b-e15e79965702", description="Manager ID", alias="managerId")
116
118
  period_details: Period = Field(..., alias="periodDetails")
117
119
 
@@ -119,5 +121,6 @@ class ManagerDelete(BaseModel):
119
121
  manager_id: str = Field(..., example="2f6aa11c-504a-49a1-903b-e15e79965702", description="Manager ID", alias="managerId")
120
122
 
121
123
  class UpdateEmployeeManager(BaseModel):
124
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
122
125
  manager_id: str = Field(..., example="2f6aa11c-504a-49a1-903b-e15e79965702", description="Manager ID", alias="managerId")
123
126
  period_details: Period = Field(..., alias="periodDetails")
@@ -54,6 +54,7 @@ class SalaryTableUpdate(BaseModel):
54
54
  step_id: Optional[str] = Field(None, example="c9c6feef-cd69-4773-8602-f70fa3b561e4", description="Step ID", alias="stepId")
55
55
 
56
56
  class SalaryCreate(BaseModel):
57
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
57
58
  start_date_salary: datetime = Field(..., example="2021-08-01T00:00:00Z", description="Start Date", alias="startDate")
58
59
  salary_type: Optional[Annotated[
59
60
  str,
@@ -60,6 +60,7 @@ class ScheduleCreate(BaseModel):
60
60
  """
61
61
  Pydantic model for creating a new schedule
62
62
  """
63
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
63
64
  start_date_schedule: datetime = Field(..., description="Start date of the schedule", example="2021-01-01T09:29:18Z", alias="startDate")
64
65
  hours_per_week: Optional[float] = Field(None, description="Hours per week", example=40, alias="hoursPerWeek")
65
66
  week1: Optional[ScheduleHours] = Field(None, description="Week 1 schedule hours", alias="week1")
@@ -10,7 +10,7 @@ from pydantic import BaseModel, Field, StringConstraints
10
10
  from datetime import datetime
11
11
 
12
12
 
13
- class WageTaxGet(BrynQPanderaDataFrameModel):
13
+ class WageTaxSettingsGet(BrynQPanderaDataFrameModel):
14
14
  wagetax_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Loonaangifte ID", alias="LoonaangifteID")
15
15
  serial_number: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Serial Number", alias="SerialNumber")
16
16
  payment_reference: Series[String] = pa.Field(coerce=True, description="Payment Reference", alias="PaymentReference")
@@ -24,6 +24,47 @@ class WageTaxGet(BrynQPanderaDataFrameModel):
24
24
  correction_period_start: Series[DateTime] = pa.Field(nullable=True, coerce=True, description="Correction Tijdvak Start", alias="CorrectionTijdvakStart")
25
25
  correction_period_end: Series[DateTime] = pa.Field(nullable=True, coerce=True, description="Correction Tijdvak End", alias="CorrectionTijdvakEnd")
26
26
 
27
+ # <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
28
+ # <soap:Body>
29
+ # <WageTax_GetListResponse xmlns="https://api.nmbrs.nl/soap/v3/EmployeeService">
30
+ # <WageTax_GetListResult>
31
+ # <WageTaxSettings>
32
+ # <Id>2998190</Id>
33
+ # <JaarloonBT>12144.00</JaarloonBT>
34
+ # <AfwBijzTariefLH>0</AfwBijzTariefLH>
35
+ # <AutoKleineBanenRegeling>true</AutoKleineBanenRegeling>
36
+ # <Loonheffingkorting>true</Loonheffingkorting>
37
+ # <Voordeelreg>true</Voordeelreg>
38
+ # <Loonheffing>true</Loonheffing>
39
+ # <CodeAfdrachtvermindering>0</CodeAfdrachtvermindering>
40
+ # <KleurTabel>1</KleurTabel>
41
+ # <SoortInkomen>15</SoortInkomen>
42
+ # <SpecialeTabel>0</SpecialeTabel>
43
+ # <TijdvakTabel>2</TijdvakTabel>
44
+ # <VakantieBonnen>0</VakantieBonnen>
45
+ # <CodeCalc30PercRule>0</CodeCalc30PercRule>
46
+ # </WageTaxSettings>
47
+ # </WageTax_GetListResult>
48
+ # </WageTax_GetListResponse>
49
+ # </soap:Body>
50
+ # </soap:Envelope>
51
+
52
+ class WageTaxGet(BrynQPanderaDataFrameModel):
53
+ wage_tax_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Wage Tax ID", alias="Id")
54
+ employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Employee ID", alias="EmployeeId")
55
+ yearly_salary: Series[pd.Float64Dtype] = pa.Field(coerce=True, description="Yearly Salary", alias="JaarloonBT")
56
+ deviation_special_rate_payroll_tax_deduction: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Afw Bijz Tarief LH", alias="AfwBijzTariefLH")
57
+ auto_small_jobs: Series[Bool] = pa.Field(coerce=True, description="Auto Kleine Banen Regeling", alias="AutoKleineBanenRegeling")
58
+ payroll_tax_deduction: Series[Bool] = pa.Field(coerce=True, description="Loonheffingkorting", alias="Loonheffingkorting")
59
+ benefit_scheme: Series[Bool] = pa.Field(coerce=True, description="Voordeelreg", alias="Voordeelreg")
60
+ payroll_tax: Series[Bool] = pa.Field(coerce=True, description="Loonheffing", alias="Loonheffing")
61
+ code_tax_reduction: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Code Afdrachtvermindering", alias="CodeAfdrachtvermindering")
62
+ color_table: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Kleur Tabel", alias="KleurTabel")
63
+ type_of_income: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Soort Inkomen", alias="SoortInkomen")
64
+ special_table: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Speciale Tabel", alias="SpecialeTabel")
65
+ period_table: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Tijdvak Tabel", alias="TijdvakTabel")
66
+ holiday_vouchers: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Vakantie Bonnen", alias="VakantieBonnen")
67
+ code_calculate_30_percent_rule: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Code Calc 30% Rule", alias="CodeCalc30PercRule")
27
68
 
28
69
  class WageTaxUpdate(BaseModel):
29
70
  employee_id: Optional[int] = Field(None, example="1234567890", description="Employee ID", alias="EmployeeId")
@@ -65,6 +65,7 @@ class PeriodPost(BaseModel):
65
65
  period: int = Field(..., ge=1, le=53, example=4, description="Period", alias="period")
66
66
 
67
67
  class FixedWageComponentCreate(BaseModel):
68
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
68
69
  code: int = Field(..., ge=1, example=1100, description="Wage Component Code", alias="code")
69
70
  value: float = Field(..., ge=0, example=500, description="Wage Component Value", alias="value")
70
71
  end_year: Optional[int] = Field(None, ge=1900, le=2100, example=2023, description="End Year", alias="endYear")
@@ -76,6 +77,7 @@ class FixedWageComponentCreate(BaseModel):
76
77
  unprotected_mode: Optional[bool] = Field(None, example=True, description="Unprotected Mode", alias="unprotectedMode")
77
78
 
78
79
  class FixedWageComponentUpdate(BaseModel):
80
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
79
81
  fixed_wage_component_id: str = Field(..., example="643c6b90-57c6-4199-9e4e-ded553572d78", description="Fixed Wage Component ID", alias="fixedWageComponentId")
80
82
  code: Optional[int] = Field(None, ge=1, example=1100, description="Wage Component Code", alias="code")
81
83
  value: Optional[float] = Field(None, ge=0, example=500, description="Wage Component Value", alias="value")
@@ -88,6 +90,7 @@ class FixedWageComponentUpdate(BaseModel):
88
90
  unprotected_mode: Optional[bool] = Field(None, example=True, description="Unprotected Mode", alias="unprotectedMode")
89
91
 
90
92
  class VariableWageComponentCreate(BaseModel):
93
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
91
94
  code: int = Field(..., ge=1, example=3045, description="Wage Component Code", alias="code")
92
95
  value: float = Field(..., ge=0, example=200, description="Wage Component Value", alias="value")
93
96
  comment: Optional[str] = Field(None, example="comment", description="Comment", alias="comment")
@@ -97,6 +100,7 @@ class VariableWageComponentCreate(BaseModel):
97
100
  unprotected_mode: Optional[bool] = Field(None, example=True, description="Unprotected Mode", alias="unprotectedMode")
98
101
 
99
102
  class VariableWageComponentUpdate(BaseModel):
103
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
100
104
  variable_wage_component_id: str = Field(..., example="7fc59095-daed-4746-a7f8-a454e38e3683", description="Variable Wage Component ID", alias="variableWageComponentId")
101
105
  code: Optional[int] = Field(None, ge=1, example=3045, description="Wage Component Code", alias="code")
102
106
  value: Optional[float] = Field(None, ge=0, example=2200, description="Wage Component Value", alias="value")
@@ -1,6 +1,6 @@
1
1
  from typing import Any, Dict, List, Union, Tuple
2
2
  import pandas as pd
3
- from .schemas.wage_tax import WageTaxGet, WageTaxUpdate
3
+ from .schemas.wage_tax import WageTaxGet, WageTaxUpdate, WageTaxSettingsGet
4
4
  from zeep.exceptions import Fault
5
5
  from zeep.ns import WSDL, SOAP_ENV_11
6
6
  from zeep.xsd import ComplexType, Element, String
@@ -33,7 +33,7 @@ class WageTax:
33
33
  wagetax_settings_temp['companyId'] = company['number']
34
34
  wagetax_settings = pd.concat([wagetax_settings, wagetax_settings_temp])
35
35
 
36
- valid_wagetax_settings, invalid_wagetax_settings = Functions.validate_data(df=wagetax_settings, schema=WageTaxGet, debug=True)
36
+ valid_wagetax_settings, invalid_wagetax_settings = Functions.validate_data(df=wagetax_settings, schema=WageTaxSettingsGet, debug=True)
37
37
 
38
38
  # No validation schema for now, but could be added later
39
39
  return valid_wagetax_settings, invalid_wagetax_settings
@@ -79,6 +79,49 @@ class WageTax:
79
79
  except Exception as e:
80
80
  raise Exception(f"Failed to get salary tables: {str(e)}")
81
81
 
82
+ def get(self, employee_id: int) -> Tuple[pd.DataFrame, pd.DataFrame]:
83
+ """
84
+ Get wage tax settings for a specific employee.
85
+
86
+ Args:
87
+ employee_id (int): The ID of the employee
88
+
89
+ Returns:
90
+ pd.DataFrame: DataFrame containing the wage tax settings
91
+ """
92
+ try:
93
+ # Get the auth header using the centralized method
94
+ auth_header = self.nmbrs._get_soap_auth_header_employees()
95
+
96
+ # Make SOAP request with the proper header structure
97
+ response = self.soap_client_employees.service.WageTax_GetCurrent(
98
+ EmployeeId=employee_id,
99
+ _soapheaders=[auth_header]
100
+ )
101
+
102
+ # Convert response to DataFrame
103
+ if response:
104
+ # Convert Zeep objects to Python dictionaries
105
+ serialized_response = serialize_object(response)
106
+
107
+ # Convert to list if it's not already
108
+ if not isinstance(serialized_response, list):
109
+ serialized_response = [serialized_response]
110
+
111
+ # Convert to DataFrame
112
+ df = pd.DataFrame(serialized_response)
113
+ df['EmployeeId'] = employee_id
114
+ valid_wage_tax, invalid_wage_tax = Functions.validate_data(df=df, schema=WageTaxGet, debug=True)
115
+
116
+ return valid_wage_tax, invalid_wage_tax
117
+ else:
118
+ return pd.DataFrame(), 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 wage tax settings: {str(e)}")
124
+
82
125
  def update(self, data: Dict[str, Any]) -> pd.DataFrame:
83
126
  try:
84
127
  wage_tax_model = WageTaxUpdate(**data)
@@ -86,6 +129,9 @@ class WageTax:
86
129
  if self.nmbrs.mock_mode:
87
130
  return wage_tax_model
88
131
 
132
+ # Get the auth header using the centralized method
133
+ auth_header = self.nmbrs._get_soap_auth_header_employees()
134
+
89
135
  # Use the model's built-in SOAP conversion method
90
136
  wage_tax_settings = wage_tax_model.to_soap_settings(self.nmbrs.soap_client_employees)
91
137
 
@@ -0,0 +1,21 @@
1
+ Metadata-Version: 2.4
2
+ Name: brynq_sdk_nmbrs
3
+ Version: 2.3.1
4
+ Summary: Nmbrs wrapper from BrynQ
5
+ Author: BrynQ
6
+ Author-email: support@brynq.com
7
+ License: BrynQ License
8
+ Requires-Dist: brynq-sdk-brynq<5,>=4
9
+ Requires-Dist: pandas<3.0.0,>=2.2.0
10
+ Requires-Dist: pydantic<3.0.0,>=2.5.0
11
+ Requires-Dist: pandera<1.0.0,>=0.16.0
12
+ Requires-Dist: zeep<5.0.0,>=4.0.0
13
+ Requires-Dist: brynq-sdk-functions>=2.0.5
14
+ Dynamic: author
15
+ Dynamic: author-email
16
+ Dynamic: description
17
+ Dynamic: license
18
+ Dynamic: requires-dist
19
+ Dynamic: summary
20
+
21
+ Nmbrs wrapper from BrynQ
@@ -2,7 +2,7 @@ from setuptools import setup, find_namespace_packages
2
2
 
3
3
  setup(
4
4
  name='brynq_sdk_nmbrs',
5
- version='2.2.2',
5
+ version='2.3.1',
6
6
  description='Nmbrs wrapper from BrynQ',
7
7
  long_description='Nmbrs wrapper from BrynQ',
8
8
  author='BrynQ',
@@ -1,10 +0,0 @@
1
- Metadata-Version: 1.0
2
- Name: brynq_sdk_nmbrs
3
- Version: 2.2.2
4
- Summary: Nmbrs wrapper from BrynQ
5
- Home-page: UNKNOWN
6
- Author: BrynQ
7
- Author-email: support@brynq.com
8
- License: BrynQ License
9
- Description: Nmbrs wrapper from BrynQ
10
- Platform: UNKNOWN
@@ -1,10 +0,0 @@
1
- Metadata-Version: 1.0
2
- Name: brynq-sdk-nmbrs
3
- Version: 2.2.2
4
- Summary: Nmbrs wrapper from BrynQ
5
- Home-page: UNKNOWN
6
- Author: BrynQ
7
- Author-email: support@brynq.com
8
- License: BrynQ License
9
- Description: Nmbrs wrapper from BrynQ
10
- Platform: UNKNOWN