brynq-sdk-nmbrs 2.3.1__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.
- brynq_sdk_nmbrs/__init__.py +104 -84
- brynq_sdk_nmbrs/address.py +82 -2
- brynq_sdk_nmbrs/children.py +96 -61
- brynq_sdk_nmbrs/companies.py +45 -1
- brynq_sdk_nmbrs/costcenter.py +53 -8
- brynq_sdk_nmbrs/costunit.py +16 -4
- brynq_sdk_nmbrs/debtors.py +76 -2
- brynq_sdk_nmbrs/department.py +149 -28
- brynq_sdk_nmbrs/document.py +50 -0
- brynq_sdk_nmbrs/employee_wage_tax_settings.py +113 -0
- brynq_sdk_nmbrs/employees.py +119 -24
- brynq_sdk_nmbrs/employment.py +12 -4
- brynq_sdk_nmbrs/function.py +128 -2
- brynq_sdk_nmbrs/leave.py +105 -8
- brynq_sdk_nmbrs/salaries.py +78 -3
- brynq_sdk_nmbrs/schedules.py +77 -3
- brynq_sdk_nmbrs/schemas/address.py +30 -5
- brynq_sdk_nmbrs/schemas/bank.py +0 -2
- brynq_sdk_nmbrs/schemas/children.py +67 -0
- brynq_sdk_nmbrs/schemas/company.py +16 -0
- brynq_sdk_nmbrs/schemas/contracts.py +25 -11
- brynq_sdk_nmbrs/schemas/costcenter.py +57 -18
- brynq_sdk_nmbrs/schemas/costunit.py +0 -2
- brynq_sdk_nmbrs/schemas/days.py +0 -2
- brynq_sdk_nmbrs/schemas/debtor.py +23 -1
- brynq_sdk_nmbrs/schemas/department.py +41 -7
- brynq_sdk_nmbrs/schemas/document.py +13 -0
- brynq_sdk_nmbrs/schemas/employees.py +44 -38
- brynq_sdk_nmbrs/schemas/employment.py +10 -10
- brynq_sdk_nmbrs/schemas/function.py +34 -7
- brynq_sdk_nmbrs/schemas/hours.py +0 -4
- brynq_sdk_nmbrs/schemas/leave.py +12 -1
- brynq_sdk_nmbrs/schemas/manager.py +0 -3
- brynq_sdk_nmbrs/schemas/salary.py +37 -12
- brynq_sdk_nmbrs/schemas/schedules.py +49 -1
- brynq_sdk_nmbrs/schemas/social_insurance.py +39 -6
- brynq_sdk_nmbrs/schemas/wage_tax.py +68 -8
- brynq_sdk_nmbrs/schemas/wage_tax_settings.py +76 -0
- brynq_sdk_nmbrs/schemas/wagecomponents.py +0 -4
- brynq_sdk_nmbrs/social_insurance.py +81 -3
- brynq_sdk_nmbrs/wage_tax.py +105 -4
- {brynq_sdk_nmbrs-2.3.1.dist-info → brynq_sdk_nmbrs-2.3.2.dev0.dist-info}/METADATA +1 -1
- brynq_sdk_nmbrs-2.3.2.dev0.dist-info/RECORD +55 -0
- {brynq_sdk_nmbrs-2.3.1.dist-info → brynq_sdk_nmbrs-2.3.2.dev0.dist-info}/WHEEL +1 -1
- brynq_sdk_nmbrs-2.3.1.dist-info/RECORD +0 -50
- {brynq_sdk_nmbrs-2.3.1.dist-info → brynq_sdk_nmbrs-2.3.2.dev0.dist-info}/top_level.txt +0 -0
brynq_sdk_nmbrs/schedules.py
CHANGED
|
@@ -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,
|
|
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)}")
|
|
@@ -26,7 +26,7 @@ class AddressGet(BrynQPanderaDataFrameModel):
|
|
|
26
26
|
postal_code: Series[String] = pa.Field(coerce=True, description="Postal Code", alias="postalCode")
|
|
27
27
|
city: Series[String] = pa.Field(coerce=True, description="City", alias="city")
|
|
28
28
|
state_province: Series[String] = pa.Field(coerce=True, nullable=True, description="State or Province", alias="stateProvince")
|
|
29
|
-
|
|
29
|
+
country_iso_code: Series[String] = pa.Field(coerce=True, nullable=True, description="Country ISO code", alias="countryISOCode")
|
|
30
30
|
period_year: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Year", alias="period.year")
|
|
31
31
|
period_period: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Period", alias="period.period")
|
|
32
32
|
|
|
@@ -45,11 +45,10 @@ class AddressGet(BrynQPanderaDataFrameModel):
|
|
|
45
45
|
# ---------------------------
|
|
46
46
|
|
|
47
47
|
class Period(BaseModel):
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
period_year: int = Field(..., ge=1900, le=2100, example=2021, description="Year", alias="year")
|
|
49
|
+
period_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")
|
|
53
52
|
is_default: Optional[bool] = Field(None, description="Default Address", alias="isDefault")
|
|
54
53
|
type: Annotated[
|
|
55
54
|
str,
|
|
@@ -64,7 +63,7 @@ class AddressCreate(BaseModel):
|
|
|
64
63
|
postal_code: Optional[str] = Field(None, max_length=15, example="1043BZ", description="Postal Code", alias="postalCode")
|
|
65
64
|
city: str = Field(..., min_length=1, max_length=100, example="Amsterdam", description="City", alias="city")
|
|
66
65
|
state_province: Optional[str] = Field(None, max_length=100, example="Noord-Holland", description="State or Province", alias="stateProvince")
|
|
67
|
-
|
|
66
|
+
country_iso_code: Annotated[
|
|
68
67
|
str,
|
|
69
68
|
StringConstraints(
|
|
70
69
|
pattern=r'^[A-Za-z]+$',
|
|
@@ -74,3 +73,29 @@ class AddressCreate(BaseModel):
|
|
|
74
73
|
)
|
|
75
74
|
] = Field(..., example="NL", description="Country ISO Code", alias="countryISOCode")
|
|
76
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
|
brynq_sdk_nmbrs/schemas/bank.py
CHANGED
|
@@ -53,7 +53,6 @@ class BankGet(BrynQPanderaDataFrameModel):
|
|
|
53
53
|
# Upload Schemas
|
|
54
54
|
# ---------------------------
|
|
55
55
|
class BankCreate(BaseModel):
|
|
56
|
-
employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
|
|
57
56
|
number: Optional[str] = Field(None, max_length=34, example="123456789", description="Bank Account Number", alias="number")
|
|
58
57
|
description: Optional[str] = Field(None, max_length=100, example="Salary Bank", description="Bank Account Description", alias="description")
|
|
59
58
|
iban: str = Field(..., min_length=5, max_length=34, example="NL20INGB0001234567", description="IBAN", alias="IBAN")
|
|
@@ -62,7 +61,6 @@ class BankCreate(BaseModel):
|
|
|
62
61
|
bank_account_type: Optional[BankAccountType] = Field(None, example=BankAccountType.BANK_ACCOUNT_1.value, description="Bank Account Type", alias="bankAccountType")
|
|
63
62
|
|
|
64
63
|
class BankUpdate(BaseModel):
|
|
65
|
-
employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
|
|
66
64
|
bank_account_id: str = Field(..., example="49a69eda-252e-4ccb-a220-38ea90511d4f", description="Bank Account ID", alias="bankAccountId")
|
|
67
65
|
number: Optional[str] = Field(None, max_length=34, example="123456789", description="Bank Account Number", alias="number")
|
|
68
66
|
description: Optional[str] = Field(None, max_length=100, example="Main Checking Account", description="Bank Account Description", alias="description")
|
|
@@ -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
|
+
|
|
@@ -5,7 +5,7 @@ from pandera.typing import Series, String, Float, DateTime
|
|
|
5
5
|
import pandera.extensions as extensions
|
|
6
6
|
from brynq_sdk_functions import BrynQPanderaDataFrameModel
|
|
7
7
|
from typing import Optional
|
|
8
|
-
from pydantic import BaseModel, Field
|
|
8
|
+
from pydantic import BaseModel, Field, field_validator
|
|
9
9
|
from datetime import datetime
|
|
10
10
|
|
|
11
11
|
# ---------------------------
|
|
@@ -19,7 +19,7 @@ class ContractGet(BrynQPanderaDataFrameModel):
|
|
|
19
19
|
end_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="End Date Contract", alias="endDate")
|
|
20
20
|
indefinite: Series[Bool] = pa.Field(coerce=True, description="Indefinite Contract", alias="indefinite")
|
|
21
21
|
written_contract: Series[Bool] = pa.Field(coerce=True, description="Written Contract", alias="writtenContract")
|
|
22
|
-
|
|
22
|
+
hours_per_week: Series[Float] = pa.Field(coerce=True, nullable=True, description="Contract Hours per Week", alias="hoursPerWeek")
|
|
23
23
|
created_at: Series[DateTime] = pa.Field(coerce=True, description="Contract Created At", alias="createdAt")
|
|
24
24
|
|
|
25
25
|
class _Annotation:
|
|
@@ -36,22 +36,36 @@ class ContractGet(BrynQPanderaDataFrameModel):
|
|
|
36
36
|
# Upload Schemas
|
|
37
37
|
# ---------------------------
|
|
38
38
|
class ContractCreate(BaseModel):
|
|
39
|
-
|
|
40
|
-
start_date_contract: datetime = Field(..., example="2021-01-01T09:29:18Z", description="Start Date Contract", alias="startDate")
|
|
39
|
+
start_date: datetime = Field(..., example="2021-01-01T09:29:18Z", description="Start Date Contract", alias="startDate")
|
|
41
40
|
trial_period: Optional[datetime] = Field(None, example="2021-02-01T00:00:00Z", description="Trial Period Contract", alias="trialPeriod")
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
end_date: Optional[datetime] = Field(None, example="2021-08-24T14:15:22Z", description="End Date Contract", alias="endDate")
|
|
42
|
+
indefinite: bool = Field(..., example=True, description="Indefinite Contract", alias="indefinite")
|
|
44
43
|
written_contract: Optional[bool] = Field(None, example=True, description="Written Contract", alias="writtenContract")
|
|
45
|
-
|
|
44
|
+
hours_per_week: Optional[float] = Field(None, ge=0, le=168, example=40, description="Contract Hours per Week", alias="hoursPerWeek")
|
|
45
|
+
|
|
46
|
+
@field_validator("start_date", "trial_period", "end_date", mode="before")
|
|
47
|
+
@classmethod
|
|
48
|
+
def empty_str_to_none(cls, v):
|
|
49
|
+
"""Convert empty strings to None for date fields"""
|
|
50
|
+
if v == "":
|
|
51
|
+
return None
|
|
52
|
+
return v
|
|
46
53
|
|
|
47
54
|
class ContractUpdate(BaseModel):
|
|
48
|
-
employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
|
|
49
55
|
contract_id: str = Field(..., example="e35e343b-55a3-4e44-bc4b-f41c3b93bcf5", description="Contract ID", alias="contractId")
|
|
50
56
|
trial_period: Optional[datetime] = Field(None, example="2021-07-31T00:00:00Z", description="Trial Period Contract", alias="trialPeriod")
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
end_date: Optional[datetime] = Field(None, example="2021-12-31T00:00:00Z", description="End Date Contract", alias="endDate")
|
|
58
|
+
indefinite: bool = Field(..., example=True, description="Indefinite Contract", alias="indefinite")
|
|
53
59
|
written_contract: Optional[bool] = Field(None, example=True, description="Written Contract", alias="writtenContract")
|
|
54
|
-
|
|
60
|
+
hours_per_week: Optional[float] = Field(None, ge=0, le=168, example=20, description="Contract Hours per Week", alias="hoursPerWeek")
|
|
61
|
+
|
|
62
|
+
@field_validator("trial_period", "end_date", mode="before")
|
|
63
|
+
@classmethod
|
|
64
|
+
def empty_str_to_none(cls, v):
|
|
65
|
+
"""Convert empty strings to None for date fields"""
|
|
66
|
+
if v == "":
|
|
67
|
+
return None
|
|
68
|
+
return v
|
|
55
69
|
|
|
56
70
|
class Config:
|
|
57
71
|
primary_key = "contractId"
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
|
|
1
3
|
import pandas as pd
|
|
2
4
|
import pandera as pa
|
|
3
5
|
from pandera import Bool
|
|
4
|
-
from pandera.typing import
|
|
5
|
-
import pandera.extensions as extensions
|
|
6
|
-
from brynq_sdk_functions import BrynQPanderaDataFrameModel
|
|
7
|
-
from typing import Optional, List
|
|
6
|
+
from pandera.typing import DateTime, Float, Series, String
|
|
8
7
|
from pydantic import BaseModel, Field
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
from brynq_sdk_functions import BrynQPanderaDataFrameModel
|
|
10
|
+
|
|
10
11
|
|
|
11
12
|
# ---------------------------
|
|
12
13
|
# Get Schemas
|
|
@@ -14,12 +15,12 @@ from datetime import datetime
|
|
|
14
15
|
class EmployeeCostcenterGet(BrynQPanderaDataFrameModel):
|
|
15
16
|
employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
|
|
16
17
|
employee_cost_center_id: Series[String] = pa.Field(coerce=True, description="Employee Cost Center ID", alias="employeeCostCenterId")
|
|
17
|
-
|
|
18
|
+
cost_center_id: Series[String] = pa.Field(coerce=True, description="Cost Center ID", alias="costCenters.costCenterId")
|
|
18
19
|
cost_centers_code: Series[String] = pa.Field(coerce=True, description="Cost Centers Code", alias="costCenters.code")
|
|
19
20
|
cost_centers_description: Series[String] = pa.Field(coerce=True, description="Cost Centers Description", alias="costCenters.description")
|
|
20
|
-
|
|
21
|
-
cost_units_code: Series[String] = pa.Field(coerce=True, description="Cost Unit Code", alias="costUnits.code")
|
|
22
|
-
cost_units_description: Series[String] = pa.Field(coerce=True, description="Cost Unit Description", alias="costUnits.description")
|
|
21
|
+
cost_unit_id: Series[String] = pa.Field(coerce=True, nullable=True, description="Cost Unit ID", alias="costUnits.costUnitId")
|
|
22
|
+
cost_units_code: Series[String] = pa.Field(coerce=True, nullable=True, description="Cost Unit Code", alias="costUnits.code")
|
|
23
|
+
cost_units_description: Series[String] = pa.Field(coerce=True, nullable=True, description="Cost Unit Description", alias="costUnits.description")
|
|
23
24
|
percentage: Series[Float] = pa.Field(coerce=True, description="Percentage", alias="percentage")
|
|
24
25
|
default: Series[Bool] = pa.Field(coerce=True, description="Default", alias="default")
|
|
25
26
|
period_year: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Year", alias="period.year")
|
|
@@ -27,7 +28,7 @@ class EmployeeCostcenterGet(BrynQPanderaDataFrameModel):
|
|
|
27
28
|
created_at: Series[DateTime] = pa.Field(coerce=True, description="Created At", alias="createdAt")
|
|
28
29
|
|
|
29
30
|
class _Annotation:
|
|
30
|
-
primary_key = "
|
|
31
|
+
primary_key = "cost_center_id"
|
|
31
32
|
foreign_keys = {
|
|
32
33
|
"employee_id": {
|
|
33
34
|
"parent_schema": "EmployeeSchema",
|
|
@@ -44,19 +45,59 @@ class CostcenterGet(BrynQPanderaDataFrameModel):
|
|
|
44
45
|
class _Annotation:
|
|
45
46
|
primary_key = "cost_center_id"
|
|
46
47
|
|
|
48
|
+
# ---------------------------
|
|
49
|
+
# API Response Models (Pydantic)
|
|
50
|
+
# ---------------------------
|
|
51
|
+
class CostCenter(BaseModel):
|
|
52
|
+
cost_center_id: str = Field(..., description="Cost Center ID", alias="costCenterId")
|
|
53
|
+
code: str = Field(..., description="Cost Center Code", alias="code")
|
|
54
|
+
description: str = Field(..., description="Cost Center Description", alias="description")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class CostUnit(BaseModel):
|
|
58
|
+
cost_unit_id: Optional[str] = Field(None, description="Cost Unit ID", alias="costUnitId")
|
|
59
|
+
code: Optional[str] = Field(None, description="Cost Unit Code", alias="code")
|
|
60
|
+
description: Optional[str] = Field(None, description="Cost Unit Description", alias="description")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class Period(BaseModel):
|
|
64
|
+
period_year: int = Field(..., ge=1900, le=2100, example=2021, description="Year", alias="year")
|
|
65
|
+
period_period: int = Field(..., ge=1, le=53, example=4, description="Period", alias="period")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class EmployeeCostCenterItem(BaseModel):
|
|
69
|
+
employee_cost_center_id: str = Field(..., description="Employee Cost Center ID", alias="employeeCostCenterId")
|
|
70
|
+
cost_centers: CostCenter = Field(..., description="Cost Center", alias="costCenters")
|
|
71
|
+
cost_units: Optional[CostUnit] = Field(None, description="Cost Unit", alias="costUnits")
|
|
72
|
+
percentage: float = Field(..., description="Percentage", alias="percentage")
|
|
73
|
+
default: bool = Field(..., description="Default", alias="default")
|
|
74
|
+
period: Period = Field(..., description="Period", alias="period")
|
|
75
|
+
created_at: str = Field(..., description="Created At", alias="createdAt")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class EmployeeCostCentersList(BaseModel):
|
|
79
|
+
employee_id: str = Field(..., description="Employee ID", alias="employeeId")
|
|
80
|
+
employee_cost_centers: List[EmployeeCostCenterItem] = Field(..., description="Employee Cost Centers", alias="employeeCostCenters")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class EmployeeCostCentersResponse(BaseModel):
|
|
84
|
+
data: List[EmployeeCostCentersList] = Field(..., description="List of employee cost centers")
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class CostCentersResponse(BaseModel):
|
|
88
|
+
data: List[CostCenter] = Field(..., description="List of cost centers")
|
|
89
|
+
|
|
90
|
+
|
|
47
91
|
# ---------------------------
|
|
48
92
|
# Upload Schemas
|
|
49
93
|
# ---------------------------
|
|
50
94
|
class CostcenterTable(BaseModel):
|
|
51
|
-
|
|
52
|
-
|
|
95
|
+
cost_center_id: str = Field(..., example="a405f980-1c4c-42c1-8ddb-2d90c58da0b1", description="Cost Center ID", alias="costCenterId")
|
|
96
|
+
cost_unit_id: Optional[str] = Field(None, example="b505f980-1c4c-42c1-8ddb-2d90c58da0b2", description="Cost Unit ID", alias="costUnitId")
|
|
53
97
|
percentage: Optional[float] = Field(100, example=100, description="Percentage", alias="percentage")
|
|
54
98
|
default: Optional[bool] = Field(True, example=True, description="Default", alias="default")
|
|
55
99
|
|
|
56
100
|
|
|
57
|
-
class Period(BaseModel):
|
|
58
|
-
year: int = Field(..., ge=1900, le=2100, example=2021, description="Year", alias="year")
|
|
59
|
-
period: int = Field(..., ge=1, le=53, example=4, description="Period", alias="period")
|
|
60
101
|
|
|
61
102
|
|
|
62
103
|
class EmployeeCostcenterUpdate(BaseModel):
|
|
@@ -69,17 +110,15 @@ class EmployeeCostcenterUpdate(BaseModel):
|
|
|
69
110
|
|
|
70
111
|
|
|
71
112
|
class EmployeeCostcenterDelete(BaseModel):
|
|
72
|
-
|
|
113
|
+
cost_center_id: str = Field(..., example="c605f980-1c4c-42c1-8ddb-2d90c58da0b3", description="Employee Cost Center ID", alias="employeeCostCenterId")
|
|
73
114
|
|
|
74
115
|
# CostCenter CRUD schemas - These are hypothetical since the API doesn't have create/update/delete endpoints
|
|
75
116
|
# but we add them for consistency with other schema files
|
|
76
117
|
class CostcenterCreate(BaseModel):
|
|
77
|
-
company_id: str = Field(..., description="Company identifier", alias="companyId")
|
|
78
118
|
code: str = Field(..., example="CC001", description="Code", alias="code")
|
|
79
119
|
description: str = Field(..., example="Sales Department", description="Description", alias="description")
|
|
80
120
|
|
|
81
121
|
class CostcenterUpdate(BaseModel):
|
|
82
|
-
company_id: str = Field(..., description="Company identifier", alias="companyId")
|
|
83
122
|
cost_center_id: str = Field(..., example="a405f980-1c4c-42c1-8ddb-2d90c58da0b1", description="Cost Center ID", alias="costCenterId")
|
|
84
123
|
code: str = Field(..., example="CC001", description="Code", alias="code")
|
|
85
124
|
description: str = Field(..., example="Sales Department", description="Description", alias="description")
|
|
@@ -23,12 +23,10 @@ class CostunitGet(BrynQPanderaDataFrameModel):
|
|
|
23
23
|
# Upload Schemas
|
|
24
24
|
# ---------------------------
|
|
25
25
|
class CostunitCreate(BaseModel):
|
|
26
|
-
company_id: str = Field(..., description="Company identifier", alias="companyId")
|
|
27
26
|
code: str = Field(..., example="CU001", description="Code", alias="code")
|
|
28
27
|
description: str = Field(..., example="Marketing Unit", description="Description", alias="description")
|
|
29
28
|
|
|
30
29
|
class CostunitUpdate(BaseModel):
|
|
31
|
-
company_id: str = Field(..., description="Company identifier", alias="companyId")
|
|
32
30
|
cost_unit_id: str = Field(..., example="b505f980-1c4c-42c1-8ddb-2d90c58da0b2", description="Cost Unit ID", alias="costUnitId")
|
|
33
31
|
code: str = Field(..., example="CU001", description="Code", alias="code")
|
|
34
32
|
description: str = Field(..., example="Marketing Unit", description="Description", alias="description")
|
brynq_sdk_nmbrs/schemas/days.py
CHANGED
|
@@ -86,13 +86,11 @@ class HoursDelete(BaseModel):
|
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
class FixedDaysCreate(BaseModel):
|
|
89
|
-
employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
|
|
90
89
|
number_of_days: int = Field(..., ge=0, le=1000, example=40, description="Days", alias="days")
|
|
91
90
|
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")
|
|
92
91
|
period_details: Optional[PeriodPost] = Field(None, example="Period details", description="Period details", alias="periodDetails")
|
|
93
92
|
|
|
94
93
|
class VariableDaysCreate(BaseModel):
|
|
95
|
-
employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
|
|
96
94
|
number_of_days: int = Field(..., ge=0, le=1000, example=40, description="Days", alias="days")
|
|
97
95
|
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")
|
|
98
96
|
period_details: Optional[PeriodPost] = Field(None, example="Period details", description="Period details", alias="periodDetails")
|
|
@@ -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
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
2
4
|
import pandas as pd
|
|
3
5
|
import pandera as pa
|
|
4
|
-
from pandera.typing import Series, String, Float, DateTime
|
|
5
6
|
import pandera.extensions as extensions
|
|
6
|
-
from
|
|
7
|
-
from typing import Optional
|
|
7
|
+
from pandera.typing import DateTime, Float, Series, String
|
|
8
8
|
from pydantic import BaseModel, Field
|
|
9
9
|
|
|
10
|
+
from brynq_sdk_functions import BrynQPanderaDataFrameModel
|
|
11
|
+
|
|
12
|
+
|
|
10
13
|
# ---------------------------
|
|
11
14
|
# Get Schemas
|
|
12
15
|
# ---------------------------
|
|
@@ -33,8 +36,8 @@ class EmployeeDepartmentGet(BrynQPanderaDataFrameModel):
|
|
|
33
36
|
# Upload Schemas
|
|
34
37
|
# ---------------------------
|
|
35
38
|
class Period(BaseModel):
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
period_year: int = Field(..., ge=1900, le=2100, example=2021, description="Year", alias="year")
|
|
40
|
+
period_period: int = Field(..., ge=1, le=53, example=4, description="Period", alias="period")
|
|
38
41
|
|
|
39
42
|
class DepartmentGet(BrynQPanderaDataFrameModel):
|
|
40
43
|
department_id: Series[String] = pa.Field(coerce=True, description="Department ID", alias="departmentId")
|
|
@@ -44,14 +47,45 @@ class DepartmentGet(BrynQPanderaDataFrameModel):
|
|
|
44
47
|
managers: Series[String] = pa.Field(coerce=True, description="List of managers", alias="managers")
|
|
45
48
|
|
|
46
49
|
class DepartmentCreate(BaseModel):
|
|
47
|
-
employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
|
|
48
50
|
code: int = Field(..., ge=1, example=2, description="Department Code", alias="code")
|
|
49
51
|
description: str = Field(..., min_length=1, max_length=200, example="Sales", description="Department Description", alias="description")
|
|
50
52
|
|
|
51
53
|
class EmployeeDepartmentUpdate(BaseModel):
|
|
52
|
-
employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
|
|
53
54
|
department_id: str = Field(..., example="3214", description="Department ID", alias="departmentId")
|
|
54
55
|
period_details: Period = Field(..., example=Period(year=2021, period=4), description="Period details", alias="periodDetails")
|
|
55
56
|
|
|
56
57
|
class Config:
|
|
57
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
|
+
|