brynq-sdk-nmbrs 2.3.1.dev0__py3-none-any.whl → 2.3.2.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. brynq_sdk_nmbrs/__init__.py +86 -80
  2. brynq_sdk_nmbrs/address.py +82 -2
  3. brynq_sdk_nmbrs/children.py +96 -61
  4. brynq_sdk_nmbrs/companies.py +45 -1
  5. brynq_sdk_nmbrs/debtors.py +76 -2
  6. brynq_sdk_nmbrs/department.py +113 -1
  7. brynq_sdk_nmbrs/document.py +50 -0
  8. brynq_sdk_nmbrs/employee_wage_tax_settings.py +16 -9
  9. brynq_sdk_nmbrs/function.py +128 -2
  10. brynq_sdk_nmbrs/leave.py +105 -8
  11. brynq_sdk_nmbrs/salaries.py +75 -3
  12. brynq_sdk_nmbrs/schedules.py +77 -3
  13. brynq_sdk_nmbrs/schemas/address.py +26 -0
  14. brynq_sdk_nmbrs/schemas/children.py +67 -0
  15. brynq_sdk_nmbrs/schemas/company.py +16 -0
  16. brynq_sdk_nmbrs/schemas/debtor.py +23 -1
  17. brynq_sdk_nmbrs/schemas/department.py +33 -0
  18. brynq_sdk_nmbrs/schemas/document.py +13 -0
  19. brynq_sdk_nmbrs/schemas/employees.py +3 -1
  20. brynq_sdk_nmbrs/schemas/function.py +28 -0
  21. brynq_sdk_nmbrs/schemas/leave.py +12 -0
  22. brynq_sdk_nmbrs/schemas/salary.py +18 -0
  23. brynq_sdk_nmbrs/schemas/schedules.py +49 -0
  24. brynq_sdk_nmbrs/schemas/social_insurance.py +39 -6
  25. brynq_sdk_nmbrs/schemas/wage_tax.py +65 -5
  26. brynq_sdk_nmbrs/schemas/wage_tax_settings.py +42 -29
  27. brynq_sdk_nmbrs/social_insurance.py +81 -3
  28. brynq_sdk_nmbrs/wage_tax.py +104 -3
  29. {brynq_sdk_nmbrs-2.3.1.dev0.dist-info → brynq_sdk_nmbrs-2.3.2.dev0.dist-info}/METADATA +1 -1
  30. brynq_sdk_nmbrs-2.3.2.dev0.dist-info/RECORD +55 -0
  31. brynq_sdk_nmbrs-2.3.1.dev0.dist-info/RECORD +0 -52
  32. {brynq_sdk_nmbrs-2.3.1.dev0.dist-info → brynq_sdk_nmbrs-2.3.2.dev0.dist-info}/WHEEL +0 -0
  33. {brynq_sdk_nmbrs-2.3.1.dev0.dist-info → brynq_sdk_nmbrs-2.3.2.dev0.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,11 @@
1
1
  import pandas as pd
2
2
  import requests
3
- import math
4
3
  from brynq_sdk_functions import Functions
5
- from .schemas.schedules import ScheduleGet, ScheduleCreate
4
+ from .schemas.schedules import ScheduleGet, ScheduleCreate, ScheduleUpdate
6
5
  from datetime import datetime
7
- from typing import Dict, Any, Optional, Tuple
6
+ from typing import Dict, Any, Tuple, Union
7
+ from zeep.exceptions import Fault
8
+ from zeep.helpers import serialize_object
8
9
 
9
10
 
10
11
  class Schedule:
@@ -82,3 +83,76 @@ class Schedule:
82
83
 
83
84
  except Exception as e:
84
85
  raise ValueError(f"Schedule validation failed: {str(e)}")
86
+
87
+ def update(self, data: Dict[str, Any]):
88
+ """
89
+ Update a schedule for an employee using SOAP API.
90
+
91
+ Args:
92
+ data: Dictionary containing schedule data with fields matching ScheduleUpdate schema:
93
+ - employeeId: Employee ID
94
+ - startDate: Start date of the schedule
95
+ - parttimePercentage: Part-time percentage (0-100)
96
+ - hoursMonday, hoursTuesday, etc.: Hours for each day of week 1
97
+ - hoursMonday2, hoursTuesday2, etc.: Hours for each day of week 2
98
+
99
+ Returns:
100
+ Response from the API
101
+ """
102
+ try:
103
+ schedule_model = ScheduleUpdate(**data)
104
+
105
+ if self.nmbrs.mock_mode:
106
+ return schedule_model
107
+
108
+ # Convert to SOAP object
109
+ schedule_soap = schedule_model.to_soap_schedule(self.nmbrs.soap_client_employees)
110
+
111
+ # Make SOAP request - CompanyRoosterNr is separate parameter (0 = no template)
112
+ response = self.nmbrs.soap_client_employees.service.Schedule_UpdateCurrent(
113
+ EmployeeId=schedule_model.employee_id,
114
+ Schedule=schedule_soap,
115
+ CompanyRoosterNr=schedule_model.company_rooster_nr or 0,
116
+ _soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_employees}
117
+ )
118
+
119
+ return response
120
+
121
+ except Fault as e:
122
+ raise Exception(f"SOAP request failed: {str(e)}")
123
+ except Exception as e:
124
+ raise Exception(f"Failed to update Schedule: {str(e)}")
125
+
126
+ def get_current(self, employee_id: Union[int, str]) -> pd.DataFrame:
127
+ """
128
+ Get current schedule for an employee via SOAP.
129
+
130
+ Args:
131
+ employee_id: The ID of the employee
132
+
133
+ Returns:
134
+ DataFrame with current schedule
135
+ """
136
+ if self.nmbrs.mock_mode:
137
+ return pd.DataFrame()
138
+
139
+ try:
140
+ response = self.nmbrs.soap_client_employees.service.Schedule_GetCurrent(
141
+ EmployeeId=int(employee_id),
142
+ _soapheaders={'AuthHeaderWithDomain': self.nmbrs.soap_auth_header_employees}
143
+ )
144
+
145
+ if response:
146
+ serialized = serialize_object(response)
147
+ if not isinstance(serialized, list):
148
+ serialized = [serialized]
149
+ df = pd.DataFrame(serialized)
150
+ df['employee_id'] = str(employee_id)
151
+ return df
152
+ else:
153
+ return pd.DataFrame()
154
+
155
+ except Fault as e:
156
+ raise Exception(f"SOAP request failed: {str(e)}")
157
+ except Exception as e:
158
+ raise Exception(f"Failed to get Schedule: {str(e)}")
@@ -73,3 +73,29 @@ class AddressCreate(BaseModel):
73
73
  )
74
74
  ] = Field(..., example="NL", description="Country ISO Code", alias="countryISOCode")
75
75
  period: Period
76
+
77
+
78
+ class AddressDelete(BaseModel):
79
+ """Schema for deleting an address via SOAP API."""
80
+ employee_id: int = Field(..., example=12345, description="Employee ID", alias="employeeId")
81
+ address_id: int = Field(..., example=67890, description="Address ID to delete", alias="addressId")
82
+
83
+ class Config:
84
+ populate_by_name = True
85
+
86
+
87
+ class AddressUpdate(BaseModel):
88
+ """Schema for updating an address via SOAP API."""
89
+ id: int = Field(..., example=67890, description="Address ID to update", alias="id")
90
+ default: bool = Field(False, example=False, description="Is default address", alias="default")
91
+ street: str = Field(..., min_length=1, max_length=200, example="Naritaweg", description="Street", alias="street")
92
+ house_number: Optional[str] = Field(None, max_length=20, example="70", description="House Number", alias="houseNumber")
93
+ house_number_addition: Optional[str] = Field(None, max_length=20, example="A", description="House Number Addition", alias="houseNumberAddition")
94
+ postal_code: Optional[str] = Field(None, max_length=15, example="1043BZ", description="Postal Code", alias="postalCode")
95
+ city: str = Field(..., min_length=1, max_length=100, example="Amsterdam", description="City", alias="city")
96
+ state_province: Optional[str] = Field(None, max_length=100, example="Noord-Holland", description="State or Province", alias="stateProvince")
97
+ country_iso_code: str = Field(..., min_length=2, max_length=3, example="NL", description="Country ISO Code", alias="countryISOCode")
98
+ address_type: str = Field("HomeAddress", example="HomeAddress", description="Address type", alias="type")
99
+
100
+ class Config:
101
+ populate_by_name = True
@@ -0,0 +1,67 @@
1
+ import pandas as pd
2
+ import pandera as pa
3
+ from pandera import Bool
4
+ from pandera.typing import Series, String, DateTime
5
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
6
+ from typing import Optional, Literal
7
+ from pydantic import BaseModel, Field
8
+ from datetime import datetime
9
+
10
+ # ---------------------------
11
+ # Get Schemas
12
+ # ---------------------------
13
+ class ChildrenGet(BrynQPanderaDataFrameModel):
14
+ employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
15
+ child_id: Series[String] = pa.Field(coerce=True, description="Child ID", alias="childId")
16
+ name: Series[String] = pa.Field(coerce=True, description="Last Name", alias="name")
17
+ first_name: Series[String] = pa.Field(coerce=True, description="First Name", alias="firstName")
18
+ initials: Series[String] = pa.Field(coerce=True, nullable=True, description="Initials", alias="initials")
19
+ gender: Series[String] = pa.Field(coerce=True, description="Gender", alias="gender")
20
+ birthday: Series[DateTime] = pa.Field(coerce=True, description="Birthday", alias="birthday")
21
+
22
+ class _Annotation:
23
+ primary_key = "child_id"
24
+ foreign_keys = {
25
+ "employee_id": {
26
+ "parent_schema": "EmployeeSchema",
27
+ "parent_column": "employee_id",
28
+ "cardinality": "N:1"
29
+ }
30
+ }
31
+
32
+ # ---------------------------
33
+ # Upload Schemas
34
+ # ---------------------------
35
+ class ChildCreate(BaseModel):
36
+ """Schema for creating a child via SOAP API."""
37
+ name: str = Field(..., min_length=1, max_length=100, example="Doe", description="Last Name", alias="name")
38
+ first_name: str = Field(..., min_length=1, max_length=100, example="John", description="First Name", alias="firstName")
39
+ initials: Optional[str] = Field(None, max_length=20, example="J.D.", description="Initials", alias="initials")
40
+ gender: Literal["male", "female", "unknown", "undefined"] = Field(..., example="male", description="Gender", alias="gender")
41
+ birthday: datetime = Field(..., example="2020-01-01T00:00:00", description="Birthday", alias="birthday")
42
+
43
+ class Config:
44
+ populate_by_name = True
45
+
46
+
47
+ class ChildDelete(BaseModel):
48
+ """Schema for deleting a child via SOAP API."""
49
+ employee_id: int = Field(..., example=12345, description="Employee ID", alias="employeeId")
50
+ child_id: int = Field(..., example=67890, description="Child ID to delete", alias="childId")
51
+
52
+ class Config:
53
+ populate_by_name = True
54
+
55
+
56
+ class ChildUpdate(BaseModel):
57
+ """Schema for updating a child via SOAP API."""
58
+ id: int = Field(..., example=67890, description="Child ID to update", alias="id")
59
+ name: str = Field(..., min_length=1, max_length=100, example="Doe", description="Last Name", alias="name")
60
+ first_name: str = Field(..., min_length=1, max_length=100, example="John", description="First Name", alias="firstName")
61
+ initials: Optional[str] = Field(None, max_length=20, example="J.D.", description="Initials", alias="initials")
62
+ gender: Literal["male", "female", "unknown", "undefined"] = Field(..., example="male", description="Gender", alias="gender")
63
+ birthday: datetime = Field(..., example="2020-01-01T00:00:00", description="Birthday", alias="birthday")
64
+
65
+ class Config:
66
+ populate_by_name = True
67
+
@@ -0,0 +1,16 @@
1
+ from pydantic import BaseModel, Field
2
+ from typing import Optional
3
+
4
+
5
+ class CompanyCreate(BaseModel):
6
+ """Schema for creating a company via SOAP API."""
7
+ debtor_id: int = Field(..., description="Debtor ID", alias="debtorId", example=34548)
8
+ company_name: str = Field(..., min_length=1, max_length=200, description="Company name", alias="companyName", example="New Company BV")
9
+ period_type: int = Field(1, ge=1, le=4, description="Period type (1=Monthly, 2=4-Weekly, 3=Weekly, 4=Quarterly)", alias="periodType", example=1)
10
+ default_company_id: int = Field(0, description="Default company ID to copy settings from (0 for none)", alias="defaultCompanyId", example=0)
11
+ labour_agreement_settings_group_guid: Optional[str] = Field(None, description="Labour agreement settings group GUID", alias="labourAgreementSettingsGroupGuid", example="00000000-0000-0000-0000-000000000000")
12
+ pay_in_advance: bool = Field(False, description="Pay in advance", alias="payInAdvance", example=False)
13
+
14
+ class Config:
15
+ populate_by_name = True
16
+
@@ -13,4 +13,26 @@ from pydantic import BaseModel, Field, StringConstraints
13
13
  class DebtorsGet(BrynQPanderaDataFrameModel):
14
14
  debtor_id: Series[String] = pa.Field(coerce=True, description="Debtor ID", alias="debtorId")
15
15
  number: Series[String] = pa.Field(coerce=True, description="Debtor number", alias="number")
16
- name: Series[Bool] = pa.Field(coerce=True, description="Debtor name", alias="name")
16
+ name: Series[Bool] = pa.Field(coerce=True, description="Debtor name", alias="name")
17
+
18
+
19
+ # ---------------------------
20
+ # SOAP Schemas
21
+ # ---------------------------
22
+ class DebtorCreate(BaseModel):
23
+ """Schema for creating a debtor via SOAP API."""
24
+ number: int = Field(..., ge=1, description="Debtor number", alias="number", example=1001)
25
+ name: str = Field(..., min_length=1, max_length=200, description="Debtor name", alias="name", example="New Debtor Company")
26
+
27
+ class Config:
28
+ populate_by_name = True
29
+
30
+
31
+ class DebtorUpdate(BaseModel):
32
+ """Schema for updating a debtor via SOAP API."""
33
+ debtor_id: int = Field(..., description="Debtor ID", alias="debtorId", example=34548)
34
+ number: int = Field(..., ge=1, description="Debtor number", alias="number", example=1001)
35
+ name: str = Field(..., min_length=1, max_length=200, description="Debtor name", alias="name", example="Updated Debtor Company")
36
+
37
+ class Config:
38
+ populate_by_name = True
@@ -56,3 +56,36 @@ class EmployeeDepartmentUpdate(BaseModel):
56
56
 
57
57
  class Config:
58
58
  primary_key = "departmentId"
59
+
60
+
61
+ # ---------------------------
62
+ # SOAP Schemas (DebtorService)
63
+ # ---------------------------
64
+ class DepartmentMasterCreate(BaseModel):
65
+ """Schema for creating a master department via SOAP API."""
66
+ debtor_id: int = Field(..., description="Debtor ID", alias="debtorId", example=34548)
67
+ code: int = Field(..., ge=1, description="Department Code", alias="code", example=101)
68
+ description: str = Field(..., min_length=1, max_length=200, description="Department Description", alias="description", example="Engineering")
69
+
70
+ class Config:
71
+ populate_by_name = True
72
+
73
+
74
+ class DepartmentMasterUpdate(BaseModel):
75
+ """Schema for updating a master department via SOAP API."""
76
+ debtor_id: int = Field(..., description="Debtor ID", alias="debtorId", example=34548)
77
+ department_id: int = Field(..., description="Department ID", alias="departmentId", example=12345)
78
+ code: int = Field(..., ge=1, description="Department Code", alias="code", example=101)
79
+ description: str = Field(..., min_length=1, max_length=200, description="Department Description", alias="description", example="Engineering Updated")
80
+
81
+ class Config:
82
+ populate_by_name = True
83
+
84
+
85
+ class DepartmentMasterDelete(BaseModel):
86
+ """Schema for deleting a master department via SOAP API."""
87
+ debtor_id: int = Field(..., description="Debtor ID", alias="debtorId", example=34548)
88
+ department_id: int = Field(..., description="Department ID to delete", alias="departmentId", example=12345)
89
+
90
+ class Config:
91
+ populate_by_name = True
@@ -0,0 +1,13 @@
1
+ from pydantic import BaseModel, Field
2
+ from typing import Optional
3
+
4
+
5
+ class DocumentUpload(BaseModel):
6
+ """Schema for uploading a document to an employee via SOAP API."""
7
+ employee_id: int = Field(..., description="Employee ID", alias="employeeId", example=276967)
8
+ document_name: str = Field(..., description="Document name (with extension)", alias="documentName", example="contract.pdf")
9
+ document_type_guid: str = Field(..., description="Document type GUID", alias="documentTypeGuid", example="00000000-0000-0000-0000-000000000000")
10
+
11
+ class Config:
12
+ populate_by_name = True
13
+
@@ -25,7 +25,9 @@ class EmployeeGet(BrynQPanderaDataFrameModel):
25
25
  last_name: Series[String] = pa.Field(coerce=True, description="Last Name", alias="basicInfo.lastName")
26
26
  employee_type: Series[String] = pa.Field(coerce=True, description="Employee Type", alias="basicInfo.employeeType")
27
27
  birth_date: Series[DateTime] = pa.Field(coerce=True, description="Birth Date", alias="birthInfo.birthDate")
28
- birth_country_code_iso: Series[String] = pa.Field(coerce=True, nullable=True, description="Birth Country Code ISO", alias="birthInfo.birthCountry")
28
+ birth_country_code_iso: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Birth Country Code ISO", alias="birthInfo.birthCountry")
29
+ birth_country: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Birth Country Code ISO", alias="birthInfo.birthCountry.codeISO")
30
+ birth_country_description: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Birth Country Code ISO", alias="birthInfo.birthCountry.description")
29
31
  nationality_code_iso: Series[String] = pa.Field(coerce=True, nullable=True, description="Nationality Code ISO", alias="birthInfo.nationality.codeISO")
30
32
  gender: Series[String] = pa.Field(coerce=True, nullable=True, description="Gender", alias="birthInfo.gender")
31
33
  private_email: Series[String] = pa.Field(coerce=True, nullable=True, description="Private Email", alias="contactInfo.privateEmail")
@@ -47,3 +47,31 @@ class FunctionGet(BrynQPanderaDataFrameModel):
47
47
  class FunctionUpdate(BaseModel):
48
48
  function_id: str = Field(..., example="5981", description="Function ID", alias="functionId")
49
49
  period_details: Period = Field(..., alias="periodDetails")
50
+
51
+
52
+ # SOAP Schemas for DebtorService Functions
53
+ class FunctionCreate(BaseModel):
54
+ """Schema for creating a master function via SOAP API."""
55
+ code: int = Field(..., example=101, description="Function Code", alias="code")
56
+ description: str = Field(..., example="Software Developer", description="Function Description", alias="description")
57
+
58
+ class Config:
59
+ populate_by_name = True
60
+
61
+
62
+ class FunctionDelete(BaseModel):
63
+ """Schema for deleting a master function via SOAP API."""
64
+ function_id: int = Field(..., example=12345, description="Function ID to delete", alias="functionId")
65
+
66
+ class Config:
67
+ populate_by_name = True
68
+
69
+
70
+ class FunctionMasterUpdate(BaseModel):
71
+ """Schema for updating a master function via SOAP API."""
72
+ function_id: int = Field(..., example=12345, description="Function ID", alias="functionId")
73
+ code: int = Field(..., example=101, description="Function Code", alias="code")
74
+ description: str = Field(..., example="Senior Software Developer", description="Function Description", alias="description")
75
+
76
+ class Config:
77
+ populate_by_name = True
@@ -46,6 +46,18 @@ class LeaveDelete(BaseModel):
46
46
  leave_request_id: str = Field(..., example="49a69eda-252e-4ccb-a220-38ea90511d4f", description="Leave Request ID", alias="leaveRequestId")
47
47
 
48
48
 
49
+ class LeaveUpdate(BaseModel):
50
+ """Schema for updating leave via SOAP API."""
51
+ employee_id: int = Field(..., example=12345, description="Employee ID", alias="employeeId")
52
+ leave_id: int = Field(..., example=67890, description="Leave ID", alias="leaveId")
53
+ start_date: datetime = Field(..., example="2025-01-01T00:00:00", description="Leave Start Date", alias="startDate")
54
+ end_date: datetime = Field(..., example="2025-01-02T00:00:00", description="Leave End Date", alias="endDate")
55
+ description: Optional[str] = Field(None, example="Vacation leave", description="Description", alias="description")
56
+
57
+ class Config:
58
+ populate_by_name = True
59
+
60
+
49
61
  class LeaveBalanceGet(BrynQPanderaDataFrameModel):
50
62
  employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
51
63
  leave_group_id: Series[String] = pa.Field(coerce=True, nullable=True, description="Leave Group ID", alias="leaveGroupId")
@@ -76,6 +76,24 @@ class SalaryCreate(BaseModel):
76
76
  data.pop('salaryTable')
77
77
  return data
78
78
 
79
+ class Config:
80
+ populate_by_name = True
81
+
82
+
83
+ class SalaryUpdate(BaseModel):
84
+ """Schema for updating salary via SOAP API (Salary_UpdateCurrent)."""
85
+ employee_id: int = Field(..., example=12345, description="Employee ID", alias="employeeId")
86
+ salary_value: float = Field(..., ge=0, example=5000.00, description="Salary value (gross amount)", alias="salaryValue")
87
+ salary_type: str = Field(
88
+ "Bruto_Salaris_Fulltime",
89
+ example="Bruto_Salaris_Fulltime",
90
+ description="Salary type enum: Bruto_Salaris_Fulltime, Bruto_Salaris_Parttime, Bruto_Uurloon, etc.",
91
+ alias="salaryType"
92
+ )
93
+
94
+ class Config:
95
+ populate_by_name = True
96
+
79
97
  class SalaryTableGet(BrynQPanderaDataFrameModel):
80
98
  code: Series[String] = pa.Field(coerce=True, description="Salary Code", alias="Code")
81
99
  description: Series[String] = pa.Field(coerce=True, description="Salary Description", alias="Description")
@@ -93,3 +93,52 @@ class ScheduleCreate(BaseModel):
93
93
  }
94
94
  }
95
95
  }
96
+
97
+
98
+ class ScheduleUpdate(BaseModel):
99
+ """
100
+ Pydantic model for updating a schedule via SOAP API
101
+ """
102
+ employee_id: int = Field(..., example=12345, description="Employee ID", alias="employeeId")
103
+ start_date: datetime = Field(..., example="2025-01-01T00:00:00", description="Start date of the schedule", alias="startDate")
104
+ parttime_percentage: float = Field(..., ge=0, le=100, example=100.0, description="Part-time percentage", alias="parttimePercentage")
105
+ company_rooster_nr: Optional[int] = Field(0, example=0, description="Company Rooster Number (schedule template)", alias="companyRoosterNr")
106
+ hours_monday: Optional[float] = Field(0, ge=0, le=24, example=8.0, description="Hours Monday", alias="hoursMonday")
107
+ hours_tuesday: Optional[float] = Field(0, ge=0, le=24, example=8.0, description="Hours Tuesday", alias="hoursTuesday")
108
+ hours_wednesday: Optional[float] = Field(0, ge=0, le=24, example=8.0, description="Hours Wednesday", alias="hoursWednesday")
109
+ hours_thursday: Optional[float] = Field(0, ge=0, le=24, example=8.0, description="Hours Thursday", alias="hoursThursday")
110
+ hours_friday: Optional[float] = Field(0, ge=0, le=24, example=8.0, description="Hours Friday", alias="hoursFriday")
111
+ hours_saturday: Optional[float] = Field(0, ge=0, le=24, example=0.0, description="Hours Saturday", alias="hoursSaturday")
112
+ hours_sunday: Optional[float] = Field(0, ge=0, le=24, example=0.0, description="Hours Sunday", alias="hoursSunday")
113
+ hours_monday2: Optional[float] = Field(0, ge=0, le=24, example=8.0, description="Hours Monday Week 2", alias="hoursMonday2")
114
+ hours_tuesday2: Optional[float] = Field(0, ge=0, le=24, example=8.0, description="Hours Tuesday Week 2", alias="hoursTuesday2")
115
+ hours_wednesday2: Optional[float] = Field(0, ge=0, le=24, example=8.0, description="Hours Wednesday Week 2", alias="hoursWednesday2")
116
+ hours_thursday2: Optional[float] = Field(0, ge=0, le=24, example=8.0, description="Hours Thursday Week 2", alias="hoursThursday2")
117
+ hours_friday2: Optional[float] = Field(0, ge=0, le=24, example=8.0, description="Hours Friday Week 2", alias="hoursFriday2")
118
+ hours_saturday2: Optional[float] = Field(0, ge=0, le=24, example=0.0, description="Hours Saturday Week 2", alias="hoursSaturday2")
119
+ hours_sunday2: Optional[float] = Field(0, ge=0, le=24, example=0.0, description="Hours Sunday Week 2", alias="hoursSunday2")
120
+
121
+ def to_soap_schedule(self, soap_client):
122
+ """Convert to SOAP Schedule object"""
123
+ ScheduleType = soap_client.get_type('ns0:Schedule')
124
+ return ScheduleType(
125
+ StartDate=self.start_date,
126
+ ParttimePercentage=self.parttime_percentage,
127
+ HoursMonday=self.hours_monday or 0,
128
+ HoursTuesday=self.hours_tuesday or 0,
129
+ HoursWednesday=self.hours_wednesday or 0,
130
+ HoursThursday=self.hours_thursday or 0,
131
+ HoursFriday=self.hours_friday or 0,
132
+ HoursSaturday=self.hours_saturday or 0,
133
+ HoursSunday=self.hours_sunday or 0,
134
+ HoursMonday2=self.hours_monday2 or 0,
135
+ HoursTuesday2=self.hours_tuesday2 or 0,
136
+ HoursWednesday2=self.hours_wednesday2 or 0,
137
+ HoursThursday2=self.hours_thursday2 or 0,
138
+ HoursFriday2=self.hours_friday2 or 0,
139
+ HoursSaturday2=self.hours_saturday2 or 0,
140
+ HoursSunday2=self.hours_sunday2 or 0
141
+ )
142
+
143
+ class Config:
144
+ populate_by_name = True
@@ -1,14 +1,47 @@
1
- import math
2
1
  import pandas as pd
3
2
  import pandera as pa
4
3
  from pandera import Bool
5
- from pandera.typing import Series, String, Float, DateTime
6
- import pandera.extensions as extensions
4
+ from pandera.typing import Series, String, DateTime
7
5
  from brynq_sdk_functions import BrynQPanderaDataFrameModel
8
- from typing import Optional, Annotated
9
- from pydantic import BaseModel, Field, StringConstraints
10
- from datetime import datetime
6
+ from typing import Optional
7
+ from pydantic import BaseModel, Field
11
8
 
9
+ # ---------------------------
10
+ # Get Schemas
11
+ # ---------------------------
12
+ class SocialInsuranceGet(BrynQPanderaDataFrameModel):
13
+ employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employee_id")
14
+ id: Series[String] = pa.Field(coerce=True, description="SVW Settings ID", alias="Id")
15
+ creation_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="Creation Date", alias="CreationDate")
16
+ start_period: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Start Period", alias="StartPeriod")
17
+ start_year: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Start Year", alias="StartYear")
18
+ influence_obliged_insurance: Series[Bool] = pa.Field(coerce=True, nullable=True, description="Whether employee influences obligatory insurance status", alias="InfluenceObligedInsurance")
19
+ wage_cost_benefit: Series[Bool] = pa.Field(coerce=True, nullable=True, description="Eligible for wage cost subsidy (LKV - Loonkostenvoordeel)", alias="WageCostBenefit")
20
+ cao: Series[String] = pa.Field(coerce=True, nullable=True, description="Collectieve Arbeidsovereenkomst (Collective Labor Agreement)", alias="CAO")
21
+ wao_wia: Series[Bool] = pa.Field(coerce=True, nullable=True, description="Disability Insurance (WAO/WIA - Wet Arbeidsongeschiktheid)", alias="Wao_Wia")
22
+ ww: Series[Bool] = pa.Field(coerce=True, nullable=True, description="Unemployment Insurance (WW - Werkloosheidswet)", alias="Ww")
23
+ zw: Series[Bool] = pa.Field(coerce=True, nullable=True, description="Sickness Benefits (ZW - Ziektewet)", alias="Zw")
24
+ income_related_contribution_zvw: Series[Bool] = pa.Field(coerce=True, nullable=True, description="Income Related Health Insurance Contribution (ZVW - Zorgverzekeringswet)", alias="IncomeRelatedContributionZvw")
25
+ code_zvw: Series[String] = pa.Field(coerce=True, nullable=True, description="Health Insurance Code (ZVW)", alias="CodeZvw")
26
+ risk_group: Series[String] = pa.Field(coerce=True, nullable=True, description="Risk Group for premium calculation", alias="RiskGroup")
27
+ sector: Series[String] = pa.Field(coerce=True, nullable=True, description="Industry Sector code", alias="Sector")
28
+ employment_type: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Employment Type", alias="EmploymentType")
29
+ phase_classification: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Phase Classification", alias="PhaseClassification")
30
+ employment_sequence_tax_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Employment Sequence Tax ID", alias="EmploymentSequenceTaxId")
31
+
32
+ class _Annotation:
33
+ primary_key = "id"
34
+ foreign_keys = {
35
+ "employee_id": {
36
+ "parent_schema": "EmployeeSchema",
37
+ "parent_column": "employee_id",
38
+ "cardinality": "N:1"
39
+ }
40
+ }
41
+
42
+ # ---------------------------
43
+ # Upload Schemas
44
+ # ---------------------------
12
45
  class SocialInsuranceUpdate(BaseModel):
13
46
  employee_id: int = Field(None, example="1234567890", description="Employee ID", alias="EmployeeId")
14
47
  influence_obliged_insurance: Optional[bool] = Field(None, example="1234567890", description="Influence Obliged Insurance", alias="InfluenceObligedInsurance")
@@ -1,16 +1,76 @@
1
1
  import math
2
+ from datetime import datetime
3
+ from typing import Annotated, Optional, Union
4
+
2
5
  import pandas as pd
3
6
  import pandera as pa
4
- from pandera import Bool
5
- from pandera.typing import Series, String, Float, DateTime
6
7
  import pandera.extensions as extensions
7
- from brynq_sdk_functions import BrynQPanderaDataFrameModel
8
- from typing import Optional, Annotated, Union
8
+ from pandera import Bool
9
+ from pandera.typing import DateTime, Float, Series, String
9
10
  from pydantic import BaseModel, Field, StringConstraints
10
- from datetime import datetime
11
+
12
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
11
13
 
12
14
 
15
+ # ---------------------------
16
+ # REST API Get Schema (Wage Tax Settings History)
17
+ # ---------------------------
13
18
  class WageTaxSettingsGet(BrynQPanderaDataFrameModel):
19
+ """Schema for REST API: GET /companies/{companyId}/employees/wagetaxsettings"""
20
+ employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
21
+ wage_tax_setting_id: Series[String] = pa.Field(coerce=True, description="Wage Tax Setting ID", alias="wageTaxSettingId")
22
+ start_date: Series[DateTime] = pa.Field(coerce=True, description="Start Date", alias="startDate")
23
+ created_at: Series[DateTime] = pa.Field(coerce=True, description="Created At", alias="createdAt")
24
+ payroll_tax_reduction: Series[Bool] = pa.Field(coerce=True, nullable=True, description="Payroll Tax Reduction", alias="payrollTaxReduction")
25
+ type_of_income: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Type of Income", alias="typeOfIncome")
26
+ color_table: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Color Table", alias="colorTable")
27
+ period_table: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Period Table", alias="periodTable")
28
+ special_table: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Special Table", alias="specialTable")
29
+ payroll_tax: Series[Bool] = pa.Field(coerce=True, nullable=True, description="Payroll Tax", alias="payrollTax")
30
+ benefit_scheme: Series[Bool] = pa.Field(coerce=True, nullable=True, description="Benefit Scheme", alias="benefitScheme")
31
+ auto_small_jobs: Series[Bool] = pa.Field(coerce=True, nullable=True, description="Auto Small Jobs Regulation", alias="autoSmallJobs")
32
+ yearly_salary: Series[pd.Float64Dtype] = pa.Field(coerce=True, nullable=True, description="Yearly Salary", alias="yearlySalary")
33
+ deviation_special_rate: Series[pd.Float64Dtype] = pa.Field(coerce=True, nullable=True, description="Deviation Special Rate Payroll Tax Deduction", alias="deviationSpecialRatePayrollTaxDeduction")
34
+ code_tax_reduction: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Code Tax Reduction", alias="codeTaxReduction")
35
+ holiday_vouchers: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Holiday Vouchers", alias="holidayVouchers")
36
+ code_30_percent_rule: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Code Calculate 30 Percent Rule", alias="codeCalculate30PercentRule")
37
+
38
+ class _Annotation:
39
+ primary_key = "wage_tax_setting_id"
40
+ foreign_keys = {
41
+ "employee_id": {
42
+ "parent_schema": "EmployeeSchema",
43
+ "parent_column": "employee_id",
44
+ "cardinality": "N:1"
45
+ }
46
+ }
47
+
48
+
49
+ class WageTaxSettingsCreate(BaseModel):
50
+ """Schema for REST API: POST /employees/{employeeId}/wagetaxsetting"""
51
+ start_date: datetime = Field(..., example="2024-01-01T00:00:00Z", description="Start Date", alias="startDate")
52
+ payroll_tax_reduction: Optional[bool] = Field(None, example=True, description="Payroll Tax Reduction", alias="payrollTaxReduction")
53
+ type_of_income: Optional[int] = Field(None, example=15, description="Type of Income", alias="typeOfIncome")
54
+ color_table: Optional[int] = Field(None, example=1, description="Color Table", alias="colorTable")
55
+ period_table: Optional[int] = Field(None, example=2, description="Period Table", alias="periodTable")
56
+ special_table: Optional[int] = Field(None, example=0, description="Special Table", alias="specialTable")
57
+ payroll_tax: Optional[bool] = Field(None, example=True, description="Payroll Tax", alias="payrollTax")
58
+ benefit_scheme: Optional[bool] = Field(None, example=True, description="Benefit Scheme", alias="benefitScheme")
59
+ auto_small_jobs: Optional[bool] = Field(None, example=False, description="Auto Small Jobs Regulation", alias="autoSmallJobs")
60
+ yearly_salary: Optional[float] = Field(None, example=45000.00, description="Yearly Salary", alias="yearlySalary")
61
+ deviation_special_rate: Optional[float] = Field(None, example=0.0, description="Deviation Special Rate Payroll Tax Deduction", alias="deviationSpecialRatePayrollTaxDeduction")
62
+ code_tax_reduction: Optional[int] = Field(None, example=0, description="Code Tax Reduction", alias="codeTaxReduction")
63
+ holiday_vouchers: Optional[int] = Field(None, example=0, description="Holiday Vouchers", alias="holidayVouchers")
64
+ code_30_percent_rule: Optional[int] = Field(None, example=0, description="Code Calculate 30 Percent Rule", alias="codeCalculate30PercentRule")
65
+
66
+ class Config:
67
+ populate_by_name = True
68
+
69
+
70
+ # ---------------------------
71
+ # SOAP API Get Schema (Company Wage Tax List)
72
+ # ---------------------------
73
+ class CompanyWageTaxGet(BrynQPanderaDataFrameModel):
14
74
  wagetax_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Loonaangifte ID", alias="LoonaangifteID")
15
75
  serial_number: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Serial Number", alias="SerialNumber")
16
76
  payment_reference: Series[String] = pa.Field(coerce=True, description="Payment Reference", alias="PaymentReference")