brynq-sdk-acerta 1.1.1__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 (34) hide show
  1. brynq_sdk_acerta/__init__.py +14 -0
  2. brynq_sdk_acerta/acerta.py +118 -0
  3. brynq_sdk_acerta/addresses.py +99 -0
  4. brynq_sdk_acerta/agreements.py +426 -0
  5. brynq_sdk_acerta/bank_accounts.py +90 -0
  6. brynq_sdk_acerta/code_lists.py +264 -0
  7. brynq_sdk_acerta/company_cars.py +135 -0
  8. brynq_sdk_acerta/contact_information.py +79 -0
  9. brynq_sdk_acerta/cost_centers.py +94 -0
  10. brynq_sdk_acerta/employees.py +121 -0
  11. brynq_sdk_acerta/employees_additional_information.py +87 -0
  12. brynq_sdk_acerta/employer.py +179 -0
  13. brynq_sdk_acerta/family_members.py +99 -0
  14. brynq_sdk_acerta/family_situation.py +99 -0
  15. brynq_sdk_acerta/inservice.py +99 -0
  16. brynq_sdk_acerta/salaries.py +74 -0
  17. brynq_sdk_acerta/schemas/__init__.py +135 -0
  18. brynq_sdk_acerta/schemas/address.py +80 -0
  19. brynq_sdk_acerta/schemas/agreement.py +982 -0
  20. brynq_sdk_acerta/schemas/bank_account.py +87 -0
  21. brynq_sdk_acerta/schemas/company_car.py +124 -0
  22. brynq_sdk_acerta/schemas/contact_information.py +83 -0
  23. brynq_sdk_acerta/schemas/cost_center.py +82 -0
  24. brynq_sdk_acerta/schemas/employee.py +406 -0
  25. brynq_sdk_acerta/schemas/employer.py +71 -0
  26. brynq_sdk_acerta/schemas/family.py +220 -0
  27. brynq_sdk_acerta/schemas/in_service.py +243 -0
  28. brynq_sdk_acerta/schemas/in_service_config.py +28 -0
  29. brynq_sdk_acerta/schemas/planning.py +37 -0
  30. brynq_sdk_acerta/schemas/salaries.py +84 -0
  31. brynq_sdk_acerta-1.1.1.dist-info/METADATA +21 -0
  32. brynq_sdk_acerta-1.1.1.dist-info/RECORD +34 -0
  33. brynq_sdk_acerta-1.1.1.dist-info/WHEEL +5 -0
  34. brynq_sdk_acerta-1.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,74 @@
1
+ from typing import Dict, Any, Tuple
2
+ import pandas as pd
3
+ import requests
4
+ from brynq_sdk_functions import Functions
5
+ from .schemas.salaries import BasicSalaryGet, PatchBasicSalariesRequest
6
+ from typing import TYPE_CHECKING
7
+ if TYPE_CHECKING:
8
+ from .acerta import Acerta
9
+
10
+
11
+ class Salaries:
12
+ """Resource class for Agreement Basic Salaries endpoints"""
13
+
14
+ def __init__(self, acerta):
15
+ self.acerta: Acerta = acerta
16
+ self.base_uri = "agreement-data-management/v1/agreements"
17
+
18
+ def get(self) -> Tuple[pd.DataFrame, pd.DataFrame]:
19
+ """
20
+ GET /agreement-data-management/v1/agreements/{agreementId}/basic-salaries - Basic Salaries
21
+
22
+ Retrieves basic salary history segments and their salary elements for all cached agreements.
23
+
24
+ Args:
25
+
26
+ Returns:
27
+ Tuple[pd.DataFrame, pd.DataFrame]: (valid_df, invalid_df) after normalizing and validating
28
+ """
29
+ if not self.acerta._agreement_ids:
30
+ self.acerta.agreements.get()
31
+
32
+ frames = []
33
+ for agreement_id in self.acerta._agreement_ids:
34
+ response = self.acerta.session.get(
35
+ url=f"{self.acerta.base_url}/{self.base_uri}/{agreement_id}/basic-salaries",
36
+ timeout=self.acerta.TIMEOUT,
37
+ )
38
+ response.raise_for_status()
39
+ raw = response.json()
40
+ df = pd.json_normalize(
41
+ raw,
42
+ record_path=["basicSalaries", "basicSalaryElements"],
43
+ meta=["agreementId", ["basicSalaries", "period", "startDate"], ["basicSalaries", "period", "endDate"]],
44
+ errors="ignore",
45
+ sep=".",
46
+ )
47
+ frames.append(df)
48
+
49
+ combined = pd.concat(frames, ignore_index=True) if frames else pd.DataFrame()
50
+
51
+ valid_df, invalid_df = Functions.validate_data(combined, BasicSalaryGet)
52
+
53
+ return valid_df, invalid_df
54
+
55
+ def update(self, agreement_id: str, data: Dict[str, Any]) -> requests.Response:
56
+ """
57
+ PATCH /agreement-data-management/v1/agreements/{agreementId}/basic-salaries - Basic Salaries
58
+
59
+ Update basic salary elements for a given agreement in a time window.
60
+ """
61
+ nested_data = Functions.flat_to_nested_with_prefix(data, PatchBasicSalariesRequest)
62
+
63
+ # Validate the nested data
64
+ validated_data = PatchBasicSalariesRequest(**nested_data)
65
+
66
+ # Make API request
67
+ response = self.acerta.session.patch(
68
+ url=f"{self.acerta.base_url}/{self.base_uri}/{agreement_id}/basic-salaries",
69
+ json=validated_data.model_dump(by_alias=True, exclude_none=True),
70
+ timeout=self.acerta.TIMEOUT,
71
+ )
72
+ response.raise_for_status()
73
+
74
+ return response
@@ -0,0 +1,135 @@
1
+ """
2
+ Schemas module for Acerta SDK
3
+ """
4
+
5
+ from .agreement import AgreementGet, AgreementRemunerationBankAccountCreate, AgreementRemunerationBankAccountUpdate
6
+ from .family import (
7
+ FamilyMemberGet,
8
+ FamilySituationGet,
9
+ FamilySituationUpdate,
10
+ FamilyMemberCreate,
11
+ FamilyMemberPersonalia,
12
+ FamilyMemberName,
13
+ FamilyMemberOther,
14
+ CivilStatus,
15
+ Partner,
16
+ DependantsChildren,
17
+ DependantsOver65,
18
+ DependantsOthers,
19
+ Dependants,
20
+ FiscalDetails
21
+ )
22
+ from .bank_account import BankAccountUpdate, BankOwner, OwnerName, BankDetails
23
+ from .employee import (
24
+ AdditionalInformationGet,
25
+ AdditionalInformationUpdate,
26
+ PersonalDetailsGet,
27
+ PersonalDetailsUpdate,
28
+ EmployeeName,
29
+ EmployeeBirth,
30
+ AddressBase,
31
+ ContactBase,
32
+ EmergencyContactBase,
33
+ EmployeePersonalDetails,
34
+ EmployeeAddressDetails,
35
+ EmployeeAdditionalInformation,
36
+ EmployeeContactInformation,
37
+ EmployeeCivilStatus,
38
+ EmployeePartner,
39
+ EmployeeDependants,
40
+ EmployeeDependantsChildren,
41
+ EmployeeDependantsOver65,
42
+ EmployeeDependantsOthers,
43
+ EmployeeFiscalDetails,
44
+ EmployeeFamilySituation,
45
+ EmployeeBankDetails,
46
+ EmployeeForeignBankAccount,
47
+ EmployeeBankAccountOwner,
48
+ EmployeeBankAccount,
49
+ EmployeeCreate
50
+ )
51
+ from .contact_information import ContactInformationGet, ContactInformationUpdate, Contact, EmergencyContact
52
+ from .address import AddressGet, AddressUpdate, Address, OfficialAddressUpdate, CorrespondenceAddressUpdate
53
+ from .planning import CountryGet, BelgianCityGet
54
+ from .employer import JointCommitteeGet, FunctionGet, SalaryCodeGet
55
+ from .in_service import EmploymentCreate, EmploymentRehire
56
+ from .cost_center import CostCenterGet, CostCenterCreate, CostCenterDescription, CostCenterPeriod
57
+ from .salaries import BasicSalaryGet, PatchBasicSalariesRequest
58
+ from .company_car import CompanyCarGet, CompanyCarCreate, CompanyCarUpdate
59
+
60
+ __all__ = [
61
+ 'AgreementGet',
62
+ 'AgreementRemunerationBankAccountCreate',
63
+ 'AgreementRemunerationBankAccountUpdate',
64
+ 'FamilyMemberGet',
65
+ 'FamilySituationGet',
66
+ 'FamilySituationUpdate',
67
+ 'FamilyMemberCreate',
68
+ 'FamilyMemberPersonalia',
69
+ 'FamilyMemberName',
70
+ 'FamilyMemberOther',
71
+ 'CivilStatus',
72
+ 'Partner',
73
+ 'DependantsChildren',
74
+ 'DependantsOver65',
75
+ 'DependantsOthers',
76
+ 'Dependants',
77
+ 'FiscalDetails',
78
+ 'BankAccountLinkGet',
79
+ 'BankAccountUpdate',
80
+ 'BankOwner',
81
+ 'OwnerName',
82
+ 'BankDetails',
83
+ 'EmployeeGet',
84
+ 'ContactInformationGet',
85
+ 'ContactInformationUpdate',
86
+ 'Contact',
87
+ 'EmergencyContact',
88
+ 'AddressGet',
89
+ 'AddressUpdate',
90
+ 'Address',
91
+ 'OfficialAddressUpdate',
92
+ 'CorrespondenceAddressUpdate',
93
+ 'AdditionalInformationGet',
94
+ 'AdditionalInformationUpdate',
95
+ 'PersonalDetailsGet',
96
+ 'PersonalDetailsUpdate',
97
+ 'EmployeeName',
98
+ 'EmployeeBirth',
99
+ 'AddressBase',
100
+ 'ContactBase',
101
+ 'EmergencyContactBase',
102
+ 'EmployeePersonalDetails',
103
+ 'EmployeeAddressDetails',
104
+ 'EmployeeAdditionalInformation',
105
+ 'EmployeeContactInformation',
106
+ 'EmployeeCivilStatus',
107
+ 'EmployeePartner',
108
+ 'EmployeeDependants',
109
+ 'EmployeeDependantsChildren',
110
+ 'EmployeeDependantsOver65',
111
+ 'EmployeeDependantsOthers',
112
+ 'EmployeeFiscalDetails',
113
+ 'EmployeeFamilySituation',
114
+ 'EmployeeBankDetails',
115
+ 'EmployeeForeignBankAccount',
116
+ 'EmployeeBankAccountOwner',
117
+ 'EmployeeBankAccount',
118
+ 'EmployeeCreate',
119
+ 'CountryGet',
120
+ 'BelgianCityGet',
121
+ 'JointCommitteeGet',
122
+ 'FunctionGet',
123
+ 'SalaryCodeGet',
124
+ 'EmploymentCreate',
125
+ 'EmploymentRehire',
126
+ 'CostCenterGet',
127
+ 'CostCenterCreate',
128
+ 'CostCenterDescription',
129
+ 'CostCenterPeriod',
130
+ 'BasicSalaryGet',
131
+ 'PatchBasicSalariesRequest',
132
+ 'CompanyCarGet',
133
+ 'CompanyCarCreate',
134
+ 'CompanyCarUpdate'
135
+ ]
@@ -0,0 +1,80 @@
1
+ """
2
+ Schema for GET /employee-data-management/v3/employees/{employeeId}/addresses
3
+ """
4
+
5
+ import pandas as pd
6
+ import pandera as pa
7
+ from pandera.typing import Series
8
+ from typing import Optional
9
+ from pydantic import BaseModel, Field
10
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
11
+
12
+
13
+ class AddressGet(BrynQPanderaDataFrameModel):
14
+ """Schema for GET /employee-data-management/v3/employees/{employeeId}/addresses endpoint."""
15
+
16
+ # Employee identification
17
+ employee_id: Series[pd.StringDtype] = pa.Field(coerce=True, description="Employee identifier", alias="employeeId")
18
+
19
+ # Period information
20
+ period_start_date: Series[pd.StringDtype] = pa.Field(coerce=True, description="Address period start date", alias="period.startDate")
21
+ period_end_date: Optional[Series[pd.StringDtype]] = pa.Field(coerce=True, nullable=True, description="Address period end date", alias="period.endDate")
22
+
23
+ # Official address
24
+ official_street: Series[pd.StringDtype] = pa.Field(coerce=True, description="Official address street", alias="officialAddress.street")
25
+ official_house_number: Series[pd.StringDtype] = pa.Field(coerce=True, description="Official address house number", alias="officialAddress.houseNumber")
26
+ official_post_box: Optional[Series[pd.StringDtype]] = pa.Field(coerce=True, nullable=True, description="Official address post box", alias="officialAddress.postBox")
27
+ official_postal_code: Series[pd.StringDtype] = pa.Field(coerce=True, description="Official address postal code", alias="officialAddress.postalCode")
28
+ official_community: Series[pd.StringDtype] = pa.Field(coerce=True, description="Official address community", alias="officialAddress.community")
29
+ official_country_name: Series[pd.StringDtype] = pa.Field(coerce=True, description="Official address country name", alias="officialAddress.country.name")
30
+ official_country_nis_code: Series[pd.StringDtype] = pa.Field(coerce=True, description="Official address country NIS code", alias="officialAddress.country.NISCode")
31
+
32
+ # Correspondence address (nullable)
33
+ correspondence_street: Optional[Series[pd.StringDtype]] = pa.Field(coerce=True, nullable=True, description="Correspondence address street", alias="correspondenceAddress.street")
34
+ correspondence_house_number: Optional[Series[pd.StringDtype]] = pa.Field(coerce=True, nullable=True, description="Correspondence address house number", alias="correspondenceAddress.houseNumber")
35
+ correspondence_post_box: Optional[Series[pd.StringDtype]] = pa.Field(coerce=True, nullable=True, description="Correspondence address post box", alias="correspondenceAddress.postBox")
36
+ correspondence_postal_code: Optional[Series[pd.StringDtype]] = pa.Field(coerce=True, nullable=True, description="Correspondence address postal code", alias="correspondenceAddress.postalCode")
37
+ correspondence_community: Optional[Series[pd.StringDtype]] = pa.Field(coerce=True, nullable=True, description="Correspondence address community", alias="correspondenceAddress.community")
38
+ correspondence_country_name: Optional[Series[pd.StringDtype]] = pa.Field(coerce=True, nullable=True, description="Correspondence address country name", alias="correspondenceAddress.country.name")
39
+ correspondence_country_nis_code: Optional[Series[pd.StringDtype]] = pa.Field(coerce=True, nullable=True, description="Correspondence address country NIS code", alias="correspondenceAddress.country.NISCode")
40
+
41
+ class _Annotation:
42
+ primary_key = "employee_id"
43
+ foreign_keys = {}
44
+
45
+ class Config:
46
+ metadata = {"class": "Address", "dependencies": []}
47
+
48
+
49
+ # Pydantic schemas for PATCH address
50
+ # Uses json_schema_extra for prefix-based field mapping
51
+
52
+ class Address(BaseModel):
53
+ """Reusable address schema (no prefix in field names)"""
54
+ street: str = Field(..., min_length=1, max_length=40, example="Bondgenotenlaan", description="Street name", alias="street")
55
+ house_number: str = Field(..., min_length=1, max_length=9, example="2", description="House number", alias="houseNumber")
56
+ post_box: Optional[str] = Field(None, min_length=1, max_length=4, example="A", description="Box number", alias="postBox")
57
+ postal_code: str = Field(..., min_length=1, max_length=14, example="3000", description="Postal code", alias="postalCode")
58
+ community: str = Field(..., min_length=1, max_length=35, example="Leuven", description="City name", alias="community")
59
+ country: str = Field(..., min_length=3, max_length=3, example="150", description="NIS Code of the country", alias="country")
60
+
61
+ class Config:
62
+ populate_by_name = True
63
+
64
+
65
+ # Backward compatibility aliases
66
+ OfficialAddressUpdate = Address
67
+ CorrespondenceAddressUpdate = Address
68
+
69
+
70
+ class AddressUpdate(BaseModel):
71
+ """Schema for PATCH /employee-data-management/v3/employees/{employeeId}/addresses endpoint"""
72
+ # Function parameters
73
+ employee_id: str = Field(..., description="Employee identifier", alias="employeeId")
74
+
75
+ from_date: Optional[str] = Field(None, example="2022-01-01", description="Date from which this information is valid", alias="fromDate")
76
+ official_address: Optional[Address] = Field(None, description="Official address of the employee", alias="officialAddress", json_schema_extra={"prefix": "official_address_"})
77
+ correspondence_address: Optional[Address] = Field(None, description="Correspondence address of the employee", alias="correspondenceAddress", json_schema_extra={"prefix": "correspondence_address_"})
78
+
79
+ class Config:
80
+ populate_by_name = True