brynq-sdk-zenegy 1.3.7__py3-none-any.whl → 1.3.10__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_zenegy/employees.py +117 -32
- brynq_sdk_zenegy/payslips.py +1 -1
- brynq_sdk_zenegy/schemas/employee_pay_checks.py +7 -0
- brynq_sdk_zenegy/schemas/employee_pensions.py +3 -0
- {brynq_sdk_zenegy-1.3.7.dist-info → brynq_sdk_zenegy-1.3.10.dist-info}/METADATA +1 -1
- {brynq_sdk_zenegy-1.3.7.dist-info → brynq_sdk_zenegy-1.3.10.dist-info}/RECORD +8 -8
- {brynq_sdk_zenegy-1.3.7.dist-info → brynq_sdk_zenegy-1.3.10.dist-info}/WHEEL +1 -1
- {brynq_sdk_zenegy-1.3.7.dist-info → brynq_sdk_zenegy-1.3.10.dist-info}/top_level.txt +0 -0
brynq_sdk_zenegy/employees.py
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
# Generated endpoint class for tag: Employees
|
|
2
|
+
from typing import Any, Dict, List, Tuple
|
|
3
|
+
from uuid import UUID
|
|
4
|
+
|
|
2
5
|
import pandas as pd
|
|
3
6
|
import requests
|
|
4
|
-
|
|
7
|
+
|
|
5
8
|
from brynq_sdk_functions import Functions
|
|
6
9
|
|
|
7
|
-
from .schemas.employees import (EmployeeCreate,
|
|
8
|
-
EmployeeUpdate,
|
|
9
|
-
EmployeesGet,
|
|
10
|
-
EmployeesGetById,
|
|
11
|
-
EmployeeEmploymentDataUpdate,
|
|
12
|
-
EmployeeEmploymentUpdate,
|
|
13
|
-
EmployeeAdditionalUpdate,
|
|
14
|
-
StartSaldo,
|
|
15
|
-
EmployeePatch)
|
|
16
10
|
from .paychecks import PayChecks
|
|
17
11
|
from .pensions import Pensions
|
|
18
|
-
from
|
|
12
|
+
from .schemas.employees import (
|
|
13
|
+
EmployeeAdditionalUpdate,
|
|
14
|
+
EmployeeCreate,
|
|
15
|
+
EmployeeEmploymentDataUpdate,
|
|
16
|
+
EmployeeEmploymentUpdate,
|
|
17
|
+
EmployeePatch,
|
|
18
|
+
EmployeesGet,
|
|
19
|
+
EmployeesGetById,
|
|
20
|
+
EmployeeUpdate,
|
|
21
|
+
StartSaldo,
|
|
22
|
+
)
|
|
19
23
|
|
|
20
24
|
|
|
21
25
|
class Employees:
|
|
@@ -282,7 +286,7 @@ class Employees:
|
|
|
282
286
|
Single entry point for patching employees using a flat data dictionary.
|
|
283
287
|
Flat keys may include prefixes for nested fields using a single underscore '_',
|
|
284
288
|
e.g., 'start_saldo_start_g_days', 'language_name'. All generated operations
|
|
285
|
-
are
|
|
289
|
+
are grouped into one or more PATCH requests to avoid all-or-none failures.
|
|
286
290
|
|
|
287
291
|
Args:
|
|
288
292
|
employee_uid (UUID): The employee uid
|
|
@@ -296,41 +300,122 @@ class Employees:
|
|
|
296
300
|
if not op:
|
|
297
301
|
raise ValueError("Patch operation 'op' must be provided")
|
|
298
302
|
|
|
299
|
-
|
|
303
|
+
operation_batches = self.build_patch_operation_batches(data=data, op=op)
|
|
304
|
+
if not operation_batches:
|
|
305
|
+
raise ValueError("No valid fields to patch")
|
|
306
|
+
|
|
300
307
|
endpoint = f"{self.endpoint}/{employee_uid}".lstrip('/')
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
308
|
+
last_response = None
|
|
309
|
+
for operations in operation_batches:
|
|
310
|
+
response = self.zenegy.patch(endpoint=endpoint, json=operations)
|
|
311
|
+
self.zenegy.raise_for_status_with_details(response)
|
|
312
|
+
last_response = response
|
|
313
|
+
return last_response
|
|
304
314
|
except Exception as e:
|
|
305
315
|
raise Exception(f"Failed to patch employee: {str(e)}")
|
|
306
316
|
|
|
307
317
|
|
|
308
|
-
def
|
|
318
|
+
def build_patch_operation_batches(self, data: Dict[str, Any], op: str = "replace") -> List[List[Dict[str, Any]]]:
|
|
309
319
|
"""
|
|
310
|
-
Build JSON Patch operations from a flat employee data dictionary
|
|
311
|
-
|
|
320
|
+
Build grouped JSON Patch operations from a flat employee data dictionary.
|
|
321
|
+
Grouping reduces validation failures when certain fields must be updated together.
|
|
312
322
|
|
|
313
323
|
Args:
|
|
314
324
|
data (Dict[str, Any]): Flat data with pythonic keys (e.g., name, email, start_g_days)
|
|
315
325
|
op (str): JSON Patch op. Defaults to "replace".
|
|
316
326
|
|
|
317
327
|
Returns:
|
|
318
|
-
List[Dict[str, Any]]: JSON Patch operations
|
|
328
|
+
List[List[Dict[str, Any]]]: Batches of JSON Patch operations
|
|
319
329
|
"""
|
|
320
330
|
if not isinstance(data, dict):
|
|
321
331
|
raise ValueError("data must be a dictionary")
|
|
322
332
|
if not op:
|
|
323
333
|
raise ValueError("Patch operation 'op' must be provided")
|
|
324
334
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
335
|
+
def is_blank_value(value: Any) -> bool:
|
|
336
|
+
if value is None:
|
|
337
|
+
return True
|
|
338
|
+
if isinstance(value, str) and value.strip() == "":
|
|
339
|
+
return True
|
|
340
|
+
if isinstance(value, str) and value in ("nan", "NaN"):
|
|
341
|
+
return True
|
|
342
|
+
try:
|
|
343
|
+
if pd.isna(value):
|
|
344
|
+
return True
|
|
345
|
+
except Exception:
|
|
346
|
+
pass
|
|
347
|
+
return False
|
|
348
|
+
|
|
349
|
+
payloads: List[Dict[str, Any]] = []
|
|
350
|
+
processed_fields: set[str] = set()
|
|
351
|
+
|
|
352
|
+
# Address fields must be patched together and cannot be blank
|
|
353
|
+
address_fields = ["address", "postal_number", "city"]
|
|
354
|
+
if any(field in data for field in address_fields):
|
|
355
|
+
address_payload: Dict[str, Any] = {}
|
|
356
|
+
for field in address_fields:
|
|
357
|
+
if field in data:
|
|
358
|
+
value = data.get(field)
|
|
359
|
+
if not is_blank_value(value):
|
|
360
|
+
address_payload[field] = value
|
|
361
|
+
processed_fields.add(field)
|
|
362
|
+
if address_payload:
|
|
363
|
+
payloads.append(address_payload)
|
|
364
|
+
|
|
365
|
+
# reg_number and konto_number should be patched together
|
|
366
|
+
bank_fields = ["reg_number", "konto_number"]
|
|
367
|
+
if any(field in data for field in bank_fields):
|
|
368
|
+
bank_payload: Dict[str, Any] = {}
|
|
369
|
+
for field in bank_fields:
|
|
370
|
+
if field in data:
|
|
371
|
+
bank_payload[field] = data[field]
|
|
372
|
+
processed_fields.add(field)
|
|
373
|
+
if bank_payload:
|
|
374
|
+
payloads.append(bank_payload)
|
|
375
|
+
|
|
376
|
+
# swift should be patched together with iban if provided
|
|
377
|
+
if "swift" in data:
|
|
378
|
+
swift_payload: Dict[str, Any] = {"swift": data.get("swift")}
|
|
379
|
+
processed_fields.add("swift")
|
|
380
|
+
if "iban" in data:
|
|
381
|
+
swift_payload["iban"] = data.get("iban")
|
|
382
|
+
processed_fields.add("iban")
|
|
383
|
+
payloads.append(swift_payload)
|
|
384
|
+
|
|
385
|
+
# department_id and department_uid should be patched together when available
|
|
386
|
+
if "department_id" in data:
|
|
387
|
+
dept_payload: Dict[str, Any] = {"department_id": data.get("department_id")}
|
|
388
|
+
processed_fields.add("department_id")
|
|
389
|
+
if "department_uid" in data:
|
|
390
|
+
dept_payload["department_uid"] = data.get("department_uid")
|
|
391
|
+
processed_fields.add("department_uid")
|
|
392
|
+
payloads.append(dept_payload)
|
|
393
|
+
|
|
394
|
+
# Every other field is sent separately to avoid all-or-none failures
|
|
395
|
+
for field, value in data.items():
|
|
396
|
+
if field not in processed_fields:
|
|
397
|
+
payloads.append({field: value})
|
|
398
|
+
processed_fields.add(field)
|
|
399
|
+
|
|
400
|
+
operation_batches: List[List[Dict[str, Any]]] = []
|
|
401
|
+
for payload in payloads:
|
|
402
|
+
validated = EmployeePatch(**payload)
|
|
403
|
+
alias_dump: Dict[str, Any] = validated.model_dump(
|
|
404
|
+
by_alias=True,
|
|
405
|
+
mode='json',
|
|
406
|
+
exclude_none=True,
|
|
407
|
+
exclude_unset=True,
|
|
408
|
+
)
|
|
409
|
+
if not alias_dump:
|
|
410
|
+
continue
|
|
411
|
+
operations: List[Dict[str, Any]] = []
|
|
412
|
+
for alias_key, value in alias_dump.items():
|
|
413
|
+
operations.append({
|
|
414
|
+
"op": op,
|
|
415
|
+
"path": f"/{alias_key}",
|
|
416
|
+
"value": value,
|
|
417
|
+
})
|
|
418
|
+
if operations:
|
|
419
|
+
operation_batches.append(operations)
|
|
420
|
+
|
|
421
|
+
return operation_batches
|
brynq_sdk_zenegy/payslips.py
CHANGED
|
@@ -27,7 +27,7 @@ class Payslips:
|
|
|
27
27
|
Tuple of (valid_data, invalid_data) DataFrames
|
|
28
28
|
"""
|
|
29
29
|
try:
|
|
30
|
-
endpoint = f"api/companies/{self.zenegy.company_uid}/employees/{employee_uid}/payslips"
|
|
30
|
+
endpoint = f"api/companies/{self.zenegy.company_uid}/employees/{employee_uid}/payslips/report"
|
|
31
31
|
content = self.zenegy.get(endpoint=endpoint)
|
|
32
32
|
|
|
33
33
|
# Normalize the response (data field contains the list)
|
|
@@ -9,7 +9,10 @@ from brynq_sdk_zenegy.schemas.company_departments import CompanyDepartmentData
|
|
|
9
9
|
|
|
10
10
|
class PaycheckCreate(BaseModel):
|
|
11
11
|
"""Schema for creating pay checks."""
|
|
12
|
+
# Function Parameters
|
|
13
|
+
employee_uid: UUID = Field(..., description="Employee identifier", alias="employeeUid")
|
|
12
14
|
paycheck_for: Optional[int] = Field(alias="payCheckFor", default=None, description="Target paycheck type/code", example=1)
|
|
15
|
+
|
|
13
16
|
name: str = Field(..., min_length=0, max_length=128, description="Paycheck item name", example="Bonus")
|
|
14
17
|
unit: Optional[float] = Field(default=None, description="Units for the item", example=10.0)
|
|
15
18
|
payment_per_unit: Optional[float] = Field(alias="paymentPerUnit", default=None, description="Payment per unit", example=150.0)
|
|
@@ -30,7 +33,11 @@ class PaycheckCreate(BaseModel):
|
|
|
30
33
|
|
|
31
34
|
class PaycheckUpdate(BaseModel):
|
|
32
35
|
"""Schema for updating pay checks."""
|
|
36
|
+
# Function Parameters
|
|
37
|
+
employee_uid: UUID = Field(..., description="Employee identifier", alias="employeeUid")
|
|
38
|
+
paycheck_uid: UUID = Field(..., description="Paycheck identifier", alias="paycheckUid")
|
|
33
39
|
paycheck_for: Optional[int] = Field(alias="payCheckFor", default=None, description="Target paycheck type/code", example=1)
|
|
40
|
+
|
|
34
41
|
name: str = Field(..., min_length=0, max_length=128, description="Paycheck item name", example="Bonus")
|
|
35
42
|
unit: Optional[float] = Field(default=None, description="Units for the item", example=10.0)
|
|
36
43
|
payment_per_unit: Optional[float] = Field(alias="paymentPerUnit", default=None, description="Payment per unit", example=150.0)
|
|
@@ -22,10 +22,13 @@ class Pension(BaseModel):
|
|
|
22
22
|
populate_by_name = True
|
|
23
23
|
|
|
24
24
|
class EmployeePensionCreate(BaseModel):
|
|
25
|
+
# Function Parameters
|
|
26
|
+
employee_uid: UUID = Field(..., description="Employee identifier", alias="employeeUid")
|
|
25
27
|
pension_uid: Optional[UUID] = Field(
|
|
26
28
|
example="00000000-0000-0000-0000-000000000000", alias="pensionUid", default=None,
|
|
27
29
|
description="Target pension UID (if updating an existing pension)"
|
|
28
30
|
)
|
|
31
|
+
|
|
29
32
|
pension: Pension = Field(
|
|
30
33
|
default=None,
|
|
31
34
|
description="Pension master data (name, type, PBS codes)",
|
|
@@ -4,12 +4,12 @@ brynq_sdk_zenegy/companies.py,sha256=DbNx4E-tjqdohbqpPeVrKTWCNCyOa9m7ZIXwuPx4ctU
|
|
|
4
4
|
brynq_sdk_zenegy/cost_center.py,sha256=zdBSe8KZ683LIeHIXCt5Y9sCY4HcXI_eEcooq3P9jSU,2763
|
|
5
5
|
brynq_sdk_zenegy/departments.py,sha256=o2G59BkLioyo9_FhwppA_1nurzNf30k6XkkTYDLdsa4,2451
|
|
6
6
|
brynq_sdk_zenegy/employee_documents.py,sha256=xYXukrSd6gqI5UbiupGb5_zrKzOsNeh4FbVippdIpw8,1396
|
|
7
|
-
brynq_sdk_zenegy/employees.py,sha256=
|
|
7
|
+
brynq_sdk_zenegy/employees.py,sha256=7dKAIe431EwGTP2H9aJJBSMm5EU19yLJjlLE9d9j6n0,16740
|
|
8
8
|
brynq_sdk_zenegy/global_value_sets.py,sha256=2T63dLUvD4mY7L1coXYQD8UttE4m0gKGolH55r_2mmI,10289
|
|
9
9
|
brynq_sdk_zenegy/global_values.py,sha256=RBv33piYctIu95Z022noDFsMhPjSzsaBbyeaU84V2bw,10598
|
|
10
10
|
brynq_sdk_zenegy/paychecks.py,sha256=9kUuFY3jc8vfyYVxqBXDWSVXD_X-FlW693an-CirlTw,4844
|
|
11
11
|
brynq_sdk_zenegy/payroll.py,sha256=gVLBEaMe2Rq3Vt06Gf2KllnGmwt5glNJFFiSylQ4AMs,4921
|
|
12
|
-
brynq_sdk_zenegy/payslips.py,sha256=
|
|
12
|
+
brynq_sdk_zenegy/payslips.py,sha256=yqYhREtpO41fO-7C4eGC9a8UO4BqoFTq4cHASUnWPGI,2217
|
|
13
13
|
brynq_sdk_zenegy/pensions.py,sha256=1-IBvs8CzABTCDh_FYjx9nSk4qWQ0e6gXijncWXxgzg,4581
|
|
14
14
|
brynq_sdk_zenegy/supplements_and_deductions_rates.py,sha256=cGVs73SYDFxeIifzvHfKGqzd_SrtxqeG-KFGJdDu2pA,2723
|
|
15
15
|
brynq_sdk_zenegy/zenegy.py,sha256=XbRm-Wj8jC4fVNmZfbOj-Rk0d6cFoPDeQYGz_MSXFsU,7745
|
|
@@ -19,15 +19,15 @@ brynq_sdk_zenegy/schemas/companies.py,sha256=8HAs1Y6E1lj54P8bN_HgEt_WDrABm7F1_pe
|
|
|
19
19
|
brynq_sdk_zenegy/schemas/company_cost_centers.py,sha256=PG1POeqMDVSUg_NE_ICNOiBy7hTlO1f4SGPhvUiNTlc,1896
|
|
20
20
|
brynq_sdk_zenegy/schemas/company_departments.py,sha256=supGcTOp5cKq10OFzt82zdo5ZJjzd2h_A6W33qMNiOg,11449
|
|
21
21
|
brynq_sdk_zenegy/schemas/employee_documents.py,sha256=eGVDkx48GFTQ31C1uKZ9rC2fXD-_-KqFu8azNU2rskY,1871
|
|
22
|
-
brynq_sdk_zenegy/schemas/employee_pay_checks.py,sha256=
|
|
23
|
-
brynq_sdk_zenegy/schemas/employee_pensions.py,sha256=
|
|
22
|
+
brynq_sdk_zenegy/schemas/employee_pay_checks.py,sha256=gXZ7A9t35Pp3rkcG5dykkmv3VLPx5Bb70vTovW0h_Rg,21315
|
|
23
|
+
brynq_sdk_zenegy/schemas/employee_pensions.py,sha256=rbVezcnD4vSJPDna7EZgiBVfb0ha272dS9iOXnRUHe8,9350
|
|
24
24
|
brynq_sdk_zenegy/schemas/employees.py,sha256=Fb5S7LOZiZJ6FzMHPdR_yh-Qn1yWSn_rIc173EShXLQ,225480
|
|
25
25
|
brynq_sdk_zenegy/schemas/global_value_sets.py,sha256=YEZm-im-22VbTcDpiBwNLcJgT7UAqkBUN3I961ffd8Y,12912
|
|
26
26
|
brynq_sdk_zenegy/schemas/global_values.py,sha256=cdfOewCPiMIJynWaxml-GAmY44qR5SQwGYgijD-f7fg,34270
|
|
27
27
|
brynq_sdk_zenegy/schemas/payrolls.py,sha256=DLCDpm5jSBeC4KhdRHVVbne8x3zdbAKwRM3MOChWHBM,16514
|
|
28
28
|
brynq_sdk_zenegy/schemas/payslips.py,sha256=kgRuEky2B2huVtag7OZzaXOX_hc2_cZMOS84DyZCZvo,2466
|
|
29
29
|
brynq_sdk_zenegy/schemas/supplements_and_deductions_rates.py,sha256=Ig4V27KhJrt_HqF1mOrr0yb0KgYxiYqs1A3k3AcQ-Ng,16928
|
|
30
|
-
brynq_sdk_zenegy-1.3.
|
|
31
|
-
brynq_sdk_zenegy-1.3.
|
|
32
|
-
brynq_sdk_zenegy-1.3.
|
|
33
|
-
brynq_sdk_zenegy-1.3.
|
|
30
|
+
brynq_sdk_zenegy-1.3.10.dist-info/METADATA,sha256=LNd-kTiWkxod-_znMdHe1aVFvBUw6wmwVuHocClFKZo,342
|
|
31
|
+
brynq_sdk_zenegy-1.3.10.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
32
|
+
brynq_sdk_zenegy-1.3.10.dist-info/top_level.txt,sha256=quyHxFQMtqHujnE15mGvieYNp-0MR1aLx0ns5VYYWOo,17
|
|
33
|
+
brynq_sdk_zenegy-1.3.10.dist-info/RECORD,,
|
|
File without changes
|