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.
Files changed (46) hide show
  1. brynq_sdk_nmbrs/__init__.py +104 -84
  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/costcenter.py +53 -8
  6. brynq_sdk_nmbrs/costunit.py +16 -4
  7. brynq_sdk_nmbrs/debtors.py +76 -2
  8. brynq_sdk_nmbrs/department.py +149 -28
  9. brynq_sdk_nmbrs/document.py +50 -0
  10. brynq_sdk_nmbrs/employee_wage_tax_settings.py +113 -0
  11. brynq_sdk_nmbrs/employees.py +119 -24
  12. brynq_sdk_nmbrs/employment.py +12 -4
  13. brynq_sdk_nmbrs/function.py +128 -2
  14. brynq_sdk_nmbrs/leave.py +105 -8
  15. brynq_sdk_nmbrs/salaries.py +78 -3
  16. brynq_sdk_nmbrs/schedules.py +77 -3
  17. brynq_sdk_nmbrs/schemas/address.py +30 -5
  18. brynq_sdk_nmbrs/schemas/bank.py +0 -2
  19. brynq_sdk_nmbrs/schemas/children.py +67 -0
  20. brynq_sdk_nmbrs/schemas/company.py +16 -0
  21. brynq_sdk_nmbrs/schemas/contracts.py +25 -11
  22. brynq_sdk_nmbrs/schemas/costcenter.py +57 -18
  23. brynq_sdk_nmbrs/schemas/costunit.py +0 -2
  24. brynq_sdk_nmbrs/schemas/days.py +0 -2
  25. brynq_sdk_nmbrs/schemas/debtor.py +23 -1
  26. brynq_sdk_nmbrs/schemas/department.py +41 -7
  27. brynq_sdk_nmbrs/schemas/document.py +13 -0
  28. brynq_sdk_nmbrs/schemas/employees.py +44 -38
  29. brynq_sdk_nmbrs/schemas/employment.py +10 -10
  30. brynq_sdk_nmbrs/schemas/function.py +34 -7
  31. brynq_sdk_nmbrs/schemas/hours.py +0 -4
  32. brynq_sdk_nmbrs/schemas/leave.py +12 -1
  33. brynq_sdk_nmbrs/schemas/manager.py +0 -3
  34. brynq_sdk_nmbrs/schemas/salary.py +37 -12
  35. brynq_sdk_nmbrs/schemas/schedules.py +49 -1
  36. brynq_sdk_nmbrs/schemas/social_insurance.py +39 -6
  37. brynq_sdk_nmbrs/schemas/wage_tax.py +68 -8
  38. brynq_sdk_nmbrs/schemas/wage_tax_settings.py +76 -0
  39. brynq_sdk_nmbrs/schemas/wagecomponents.py +0 -4
  40. brynq_sdk_nmbrs/social_insurance.py +81 -3
  41. brynq_sdk_nmbrs/wage_tax.py +105 -4
  42. {brynq_sdk_nmbrs-2.3.1.dist-info → brynq_sdk_nmbrs-2.3.2.dev0.dist-info}/METADATA +1 -1
  43. brynq_sdk_nmbrs-2.3.2.dev0.dist-info/RECORD +55 -0
  44. {brynq_sdk_nmbrs-2.3.1.dist-info → brynq_sdk_nmbrs-2.3.2.dev0.dist-info}/WHEEL +1 -1
  45. brynq_sdk_nmbrs-2.3.1.dist-info/RECORD +0 -50
  46. {brynq_sdk_nmbrs-2.3.1.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)}")
@@ -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
- country_i_s_o_code: Series[String] = pa.Field(coerce=True, nullable=True, description="Country ISO code", alias="countryISOCode")
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
- year: int = Field(..., ge=1900, le=2100, example=2021, description="Year", alias="year")
49
- period: int = Field(..., ge=1, le=53, example=4, description="Period", alias="period")
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
- country_code: Annotated[
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
@@ -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
- weekly_hours: Series[Float] = pa.Field(coerce=True, nullable=True, description="Contract Hours per Week", alias="hoursPerWeek")
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
- employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
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
- end_date_contract: Optional[datetime] = Field(None, example="2021-08-24T14:15:22Z", description="End Date Contract", alias="endDate")
43
- indefinite_contract: bool = Field(..., example=True, description="Indefinite Contract", alias="indefinite")
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
- weekly_hours: Optional[float] = Field(None, ge=0, le=168, example=40, description="Contract Hours per Week", alias="hoursPerWeek")
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
- end_date_contract: Optional[datetime] = Field(None, example="2021-12-31T00:00:00Z", description="End Date Contract", alias="endDate")
52
- indefinite_contract: bool = Field(..., example=True, description="Indefinite Contract", alias="indefinite")
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
- weekly_hours: Optional[float] = Field(None, ge=0, le=168, example=20, description="Contract Hours per Week", alias="hoursPerWeek")
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 Series, String, Float, DateTime
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
- from datetime import datetime
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
- cost_centers_cost_center_id: Series[String] = pa.Field(coerce=True, description="Cost Center ID", alias="costCenters.costCenterId")
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
- cost_units_cost_unit_id: Series[String] = pa.Field(coerce=True, description="Cost Unit ID", alias="costUnits.costUnitId")
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 = "employee_cost_center_id"
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
- costcenter_id: str = Field(..., example="a405f980-1c4c-42c1-8ddb-2d90c58da0b1", description="Cost Center ID", alias="costCenterId")
52
- costunit_id: Optional[str] = Field(None, example="b505f980-1c4c-42c1-8ddb-2d90c58da0b2", description="Cost Unit ID", alias="costUnitId")
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
- employee_cost_center_id: str = Field(..., example="c605f980-1c4c-42c1-8ddb-2d90c58da0b3", description="Employee Cost Center ID", alias="employeeCostCenterId")
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")
@@ -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 brynq_sdk_functions import BrynQPanderaDataFrameModel
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
- year: int = Field(..., ge=1900, le=2100, example=2021, description="Year", alias="year")
37
- period: int = Field(..., ge=1, le=53, example=4, description="Period", alias="period")
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
+