brynq-sdk-bob 2.6.2.dev10__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_bob/__init__.py +77 -0
- brynq_sdk_bob/bank.py +38 -0
- brynq_sdk_bob/company.py +23 -0
- brynq_sdk_bob/custom_tables.py +75 -0
- brynq_sdk_bob/documents.py +47 -0
- brynq_sdk_bob/employment.py +25 -0
- brynq_sdk_bob/named_lists.py +37 -0
- brynq_sdk_bob/payments.py +166 -0
- brynq_sdk_bob/payroll_history.py +71 -0
- brynq_sdk_bob/people.py +108 -0
- brynq_sdk_bob/salaries.py +45 -0
- brynq_sdk_bob/schemas/__init__.py +0 -0
- brynq_sdk_bob/schemas/bank.py +25 -0
- brynq_sdk_bob/schemas/custom_tables.py +27 -0
- brynq_sdk_bob/schemas/employment.py +31 -0
- brynq_sdk_bob/schemas/named_lists.py +14 -0
- brynq_sdk_bob/schemas/payments.py +46 -0
- brynq_sdk_bob/schemas/payroll_history.py +24 -0
- brynq_sdk_bob/schemas/people.py +286 -0
- brynq_sdk_bob/schemas/salary.py +49 -0
- brynq_sdk_bob/schemas/timeoff.py +48 -0
- brynq_sdk_bob/schemas/work.py +32 -0
- brynq_sdk_bob/timeoff.py +79 -0
- brynq_sdk_bob/work.py +31 -0
- brynq_sdk_bob-2.6.2.dev10.dist-info/METADATA +18 -0
- brynq_sdk_bob-2.6.2.dev10.dist-info/RECORD +28 -0
- brynq_sdk_bob-2.6.2.dev10.dist-info/WHEEL +5 -0
- brynq_sdk_bob-2.6.2.dev10.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import pandera as pa
|
|
2
|
+
from pandera.typing import Series, String, Float
|
|
3
|
+
from typing import Optional
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from brynq_sdk_functions import BrynQPanderaDataFrameModel
|
|
6
|
+
|
|
7
|
+
class TimeOffSchema(BrynQPanderaDataFrameModel):
|
|
8
|
+
change_type: Series[String] = pa.Field(coerce=True, description="Change Type", alias="changeType")
|
|
9
|
+
employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
|
|
10
|
+
employee_display_name: Series[String] = pa.Field(coerce=True, description="Employee Display Name", alias="employeeDisplayName")
|
|
11
|
+
employee_email: Series[String] = pa.Field(coerce=True, description="Employee Email", alias="employeeEmail")
|
|
12
|
+
request_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Request ID", alias="requestId")
|
|
13
|
+
policy_type_display_name: Series[String] = pa.Field(coerce=True, description="Policy Type Display Name", alias="policyTypeDisplayName")
|
|
14
|
+
type: Series[String] = pa.Field(coerce=True, description="Type", alias="type")
|
|
15
|
+
start_date: Series[String] = pa.Field(coerce=True, nullable=True, description="Start Date", alias="startDate")
|
|
16
|
+
start_portion: Series[String] = pa.Field(coerce=True, nullable=True, description="Start Portion", alias="startPortion")
|
|
17
|
+
end_date: Series[String] = pa.Field(coerce=True, nullable=True, description="End Date", alias="endDate")
|
|
18
|
+
end_portion: Series[String] = pa.Field(coerce=True, nullable=True, description="End Portion", alias="endPortion")
|
|
19
|
+
day_portion: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Day Portion", alias="dayPortion")
|
|
20
|
+
date: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Date", alias="date")
|
|
21
|
+
hours_on_date: Optional[Series[Float]] = pa.Field(coerce=True, nullable=True, description="Hours on Date", alias="hoursOnDate")
|
|
22
|
+
daily_hours: Optional[Series[Float]] = pa.Field(coerce=True, nullable=True, description="Daily Hours", alias="dailyHours")
|
|
23
|
+
duration_unit: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Duration Unit", alias="durationUnit")
|
|
24
|
+
total_duration: Optional[Series[Float]] = pa.Field(coerce=True, nullable=True, description="Total Duration", alias="totalDuration")
|
|
25
|
+
total_cost: Optional[Series[Float]] = pa.Field(coerce=True, nullable=True, description="Total Cost", alias="totalCost")
|
|
26
|
+
change_reason: Optional[Series[String]] = pa.Field(nullable=True, coerce=True, description="Change Reason", alias="changeReason")
|
|
27
|
+
visibility: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Visibility", alias="visibility")
|
|
28
|
+
|
|
29
|
+
class Config:
|
|
30
|
+
coerce = True
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TimeOffBalanceSchema(BrynQPanderaDataFrameModel):
|
|
34
|
+
employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
|
|
35
|
+
policy_type_name: Series[String] = pa.Field(coerce=True, description="Policy Type Name", alias="policyTypeName")
|
|
36
|
+
policy_type_display_name: Series[String] = pa.Field(coerce=True, description="Policy Type Display Name", alias="policyTypeDisplayName")
|
|
37
|
+
balance: Series[Float] = pa.Field(coerce=True, description="Current Balance", alias="balance")
|
|
38
|
+
used: Series[Float] = pa.Field(coerce=True, description="Used Balance", alias="used")
|
|
39
|
+
available: Series[Float] = pa.Field(coerce=True, description="Available Balance", alias="available")
|
|
40
|
+
approved_requests: Series[Float] = pa.Field(coerce=True, description="Approved Requests", alias="approvedRequests")
|
|
41
|
+
pending_requests: Series[Float] = pa.Field(coerce=True, description="Pending Requests", alias="pendingRequests")
|
|
42
|
+
as_of_date: Series[String] = pa.Field(coerce=True, description="As of Date", alias="asOfDate")
|
|
43
|
+
accrual_start_date: Series[String] = pa.Field(nullable=True, coerce=True, description="Accrual Start Date", alias="accrualStartDate")
|
|
44
|
+
expiry_date: Series[String] = pa.Field(nullable=True, coerce=True, description="Expiry Date", alias="expiryDate")
|
|
45
|
+
duration_unit: Series[String] = pa.Field(coerce=True, description="Duration Unit", alias="durationUnit")
|
|
46
|
+
|
|
47
|
+
class Config:
|
|
48
|
+
coerce = True
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import pandera as pa
|
|
2
|
+
from pandera.typing import Series
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from brynq_sdk_functions import BrynQPanderaDataFrameModel
|
|
6
|
+
|
|
7
|
+
class WorkSchema(BrynQPanderaDataFrameModel):
|
|
8
|
+
can_be_deleted: Series[pa.Bool] = pa.Field(coerce=True, description="Can Be Deleted", alias="canBeDeleted")
|
|
9
|
+
work_change_type: Series[str] = pa.Field(coerce=True, description="Work Change Type", alias="workChangeType")
|
|
10
|
+
creation_date: Series[datetime] = pa.Field(coerce=True, nullable=True, description="Creation Date", alias="creationDate")
|
|
11
|
+
title: Series[str] = pa.Field(coerce=True, nullable=True, description="Title", alias="title")
|
|
12
|
+
is_current: Series[pa.Bool] = pa.Field(coerce=True, description="Is Current", alias="isCurrent")
|
|
13
|
+
modification_date: Series[datetime] = pa.Field(coerce=True, nullable=True, description="Modification Date", alias="modificationDate")
|
|
14
|
+
site: Series[str] = pa.Field(coerce=True, nullable=True, description="Site", alias="site")
|
|
15
|
+
site_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Site ID", alias="siteId")
|
|
16
|
+
id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="ID", alias="id")
|
|
17
|
+
end_effective_date: Series[datetime] = pa.Field(coerce=True, nullable=True, description="End Effective Date", alias="endEffectiveDate")
|
|
18
|
+
active_effective_date: Series[datetime] = pa.Field(coerce=True, nullable=True, description="Active Effective Date", alias="activeEffectiveDate")
|
|
19
|
+
department: Series[str] = pa.Field(coerce=True, nullable=True, description="Department", alias="department")
|
|
20
|
+
effective_date: Series[datetime] = pa.Field(coerce=True, nullable=True, description="Effective Date", alias="effectiveDate")
|
|
21
|
+
change_reason: Series[str] = pa.Field(coerce=True, nullable=True, description="Change Reason", alias="change.reason")
|
|
22
|
+
change_changed_by: Series[str] = pa.Field(coerce=True, nullable=True, description="Change Changed By", alias="change.changedBy")
|
|
23
|
+
change_changed_by_id: Series[str] = pa.Field(coerce=True, nullable=True, description="Change Changed By ID", alias="change.changedById")
|
|
24
|
+
reports_to_id: Series[str] = pa.Field(coerce=True, nullable=True, description="Reports To ID", alias="reportsTo.id")
|
|
25
|
+
reports_to_first_name: Series[str] = pa.Field(coerce=True, nullable=True, description="Reports To First Name", alias="reportsTo.firstName")
|
|
26
|
+
reports_to_surname: Series[str] = pa.Field(coerce=True, nullable=True, description="Reports To Surname", alias="reportsTo.surname")
|
|
27
|
+
reports_to_email: Series[str] = pa.Field(coerce=True, nullable=True, description="Reports To Email", alias="reportsTo.email")
|
|
28
|
+
reports_to_display_name: Series[str] = pa.Field(coerce=True, nullable=True, description="Reports To Display Name", alias="reportsTo.displayName")
|
|
29
|
+
employee_id: Series[str] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
|
|
30
|
+
|
|
31
|
+
class Config:
|
|
32
|
+
coerce = True
|
brynq_sdk_bob/timeoff.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from datetime import datetime, timezone, timedelta
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from brynq_sdk_functions import Functions
|
|
4
|
+
from .schemas.timeoff import TimeOffSchema, TimeOffBalanceSchema
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TimeOff:
|
|
9
|
+
def __init__(self, bob):
|
|
10
|
+
self.bob = bob
|
|
11
|
+
self.schema = TimeOffSchema
|
|
12
|
+
self.balance_schema = TimeOffBalanceSchema
|
|
13
|
+
|
|
14
|
+
def get(self, since: datetime = None, include_pending: bool = False) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
15
|
+
"""
|
|
16
|
+
Get time off requests
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
since (datetime, optional): The start date of the time off requests max 6 months ago. Defaults to 6 months ago if not provided.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
tuple[pd.DataFrame, pd.DataFrame]: A tuple of (valid_timeoff, invalid_timeoff) as pandas DataFrames
|
|
23
|
+
"""
|
|
24
|
+
max_lookback = timedelta(days=int((365 / 2) - 1))
|
|
25
|
+
now_utc = datetime.now(timezone.utc)
|
|
26
|
+
six_months_ago = now_utc - max_lookback
|
|
27
|
+
#if since is provided, use it and cap to 6 months max
|
|
28
|
+
if since is not None:
|
|
29
|
+
if since.tzinfo is None:
|
|
30
|
+
since = since.replace(tzinfo=timezone.utc)
|
|
31
|
+
if since < six_months_ago:
|
|
32
|
+
warnings.warn("The 'since' date is more than 6 months ago. Limiting to 6 months ago due to API restrictions.")
|
|
33
|
+
since = six_months_ago
|
|
34
|
+
#if no since is provided, use 6 months ago
|
|
35
|
+
else:
|
|
36
|
+
since = six_months_ago
|
|
37
|
+
|
|
38
|
+
since = since.replace(tzinfo=timezone.utc).isoformat(timespec='milliseconds').replace('+00:00', 'Z')
|
|
39
|
+
resp = self.bob.session.get(url=f"{self.bob.base_url}timeoff/requests/changes",
|
|
40
|
+
params={'since': since, 'includePending': 'true' if include_pending else 'false'},
|
|
41
|
+
timeout=self.bob.timeout)
|
|
42
|
+
resp.raise_for_status()
|
|
43
|
+
data = resp.json()['changes']
|
|
44
|
+
# data = self.bob.get_paginated_result(request)
|
|
45
|
+
df = pd.DataFrame(data)
|
|
46
|
+
valid_timeoff, invalid_timeoff = Functions.validate_data(df=df, schema=self.schema, debug=True)
|
|
47
|
+
|
|
48
|
+
return valid_timeoff, invalid_timeoff
|
|
49
|
+
|
|
50
|
+
def get_balance(self, employee_id: str, policy_type: str = None, as_of_date: str = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
51
|
+
"""
|
|
52
|
+
Get time off balance for a specific employee
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
employee_id (str): The ID of the employee
|
|
56
|
+
policy_type (str, optional): The policy type to filter by. Defaults to None.
|
|
57
|
+
as_of_date (str, optional): The date to get balance as of (YYYY-MM-DD format). Defaults to None.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
tuple[pd.DataFrame, pd.DataFrame]: A tuple of (valid_balance, invalid_balance) as pandas DataFrames
|
|
61
|
+
"""
|
|
62
|
+
params = {}
|
|
63
|
+
if policy_type:
|
|
64
|
+
params['policyType'] = policy_type
|
|
65
|
+
if as_of_date:
|
|
66
|
+
params['asOfDate'] = as_of_date
|
|
67
|
+
|
|
68
|
+
resp = self.bob.session.get(
|
|
69
|
+
url=f"{self.bob.base_url}timeoff/employees/{employee_id}/balance",
|
|
70
|
+
params=params,
|
|
71
|
+
timeout=self.bob.timeout
|
|
72
|
+
)
|
|
73
|
+
resp.raise_for_status()
|
|
74
|
+
data = resp.json()
|
|
75
|
+
df = pd.DataFrame(data)
|
|
76
|
+
|
|
77
|
+
valid_balance, invalid_balance = Functions.validate_data(df=df, schema=self.balance_schema, debug=True)
|
|
78
|
+
|
|
79
|
+
return valid_balance, invalid_balance
|
brynq_sdk_bob/work.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import requests
|
|
3
|
+
from typing import Optional, List
|
|
4
|
+
from brynq_sdk_functions import Functions
|
|
5
|
+
from .schemas.work import WorkSchema
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Work:
|
|
9
|
+
def __init__(self, bob):
|
|
10
|
+
self.bob = bob
|
|
11
|
+
self.schema = WorkSchema
|
|
12
|
+
|
|
13
|
+
def get(self, employee_ids: Optional[List[str]] = None) ->(pd.DataFrame, pd.DataFrame):
|
|
14
|
+
params = {"limit": 100}
|
|
15
|
+
|
|
16
|
+
# Add employeeIds filter if provided
|
|
17
|
+
if employee_ids is not None:
|
|
18
|
+
params["employeeIds"] = ",".join(employee_ids)
|
|
19
|
+
|
|
20
|
+
request = requests.Request(method='GET',
|
|
21
|
+
url=f"{self.bob.base_url}bulk/people/work",
|
|
22
|
+
params=params)
|
|
23
|
+
data = self.bob.get_paginated_result(request)
|
|
24
|
+
df = pd.json_normalize(
|
|
25
|
+
data,
|
|
26
|
+
record_path='values',
|
|
27
|
+
meta=['employeeId']
|
|
28
|
+
)
|
|
29
|
+
valid_work, invalid_work = Functions.validate_data(df=df, schema=self.schema, debug=True)
|
|
30
|
+
|
|
31
|
+
return valid_work, invalid_work
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: brynq_sdk_bob
|
|
3
|
+
Version: 2.6.2.dev10
|
|
4
|
+
Summary: Bob wrapper from BrynQ
|
|
5
|
+
Author: BrynQ
|
|
6
|
+
Author-email: support@brynq.com
|
|
7
|
+
License: BrynQ License
|
|
8
|
+
Requires-Dist: brynq-sdk-brynq<5,>=4
|
|
9
|
+
Requires-Dist: pandas<3.0.0,>=2.2.0
|
|
10
|
+
Requires-Dist: tenacity==8.2.3
|
|
11
|
+
Dynamic: author
|
|
12
|
+
Dynamic: author-email
|
|
13
|
+
Dynamic: description
|
|
14
|
+
Dynamic: license
|
|
15
|
+
Dynamic: requires-dist
|
|
16
|
+
Dynamic: summary
|
|
17
|
+
|
|
18
|
+
Bob wrapper from BrynQ
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
brynq_sdk_bob/__init__.py,sha256=bw2Www_wgVxqZczJpz9K_94k7OdgqwWKF0aQaKG5TQE,3052
|
|
2
|
+
brynq_sdk_bob/bank.py,sha256=5ncWsmeAvNoiLnVvIvPgFDRQ5DB5_VY2ipMC439GVHU,1460
|
|
3
|
+
brynq_sdk_bob/company.py,sha256=rjOpkm0CZ1EeJ-jddBl36GrGKUQviC1ca1aUL2tl1_M,848
|
|
4
|
+
brynq_sdk_bob/custom_tables.py,sha256=MvnR2mIcyK0rpwd0P7xV3BPIvCYQVEClBvo901GttPs,2642
|
|
5
|
+
brynq_sdk_bob/documents.py,sha256=ww101owiBGARCxOANdDtmWrNedSBe9V-BEed6QspQPg,1756
|
|
6
|
+
brynq_sdk_bob/employment.py,sha256=kBEKfUmKEw-A_FjC9fOuJqcsT7NxUKwXJs_V_-x9LbI,765
|
|
7
|
+
brynq_sdk_bob/named_lists.py,sha256=ksLXV2ysBFegq4gZiiaC56gjkgdnPzL7WajZTGvjYIM,1069
|
|
8
|
+
brynq_sdk_bob/payments.py,sha256=e1TnJcXlbotOfULukVUiaYZ1N-bDGynAtmPgpux7It0,5670
|
|
9
|
+
brynq_sdk_bob/payroll_history.py,sha256=wHo6da7kLDe1ViL4egyMdyJBMZnWVhwjNjmh4cTCTeY,3972
|
|
10
|
+
brynq_sdk_bob/people.py,sha256=6b7uCucl_xqtAq_4YJZU457fUY0qssMwfCCStzbNG0M,5036
|
|
11
|
+
brynq_sdk_bob/salaries.py,sha256=8xq9XDTK473Az2MpuAPofz9CvZstjufSoWtF0bi1wC4,1766
|
|
12
|
+
brynq_sdk_bob/timeoff.py,sha256=NbBZ39qy9D7jbS_z9bpmB-BKNuUGmNrkYTbEw034tZ0,3339
|
|
13
|
+
brynq_sdk_bob/work.py,sha256=IADipEuI_ofhhLZZV9oI8PV10VN07yluPPkLZT19Ze8,1013
|
|
14
|
+
brynq_sdk_bob/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
brynq_sdk_bob/schemas/bank.py,sha256=Yfq-ouzcAyaqcZj5_lWLcaQgtLikI9zlcsHhsuPUQzY,1935
|
|
16
|
+
brynq_sdk_bob/schemas/custom_tables.py,sha256=638NH2n50vHzw1LFlbKVCBKBhfSsfGqtEGuor0Z-QS4,1567
|
|
17
|
+
brynq_sdk_bob/schemas/employment.py,sha256=uErbSyl8xYaYo5Hu0FZ7_tl1WCOaytcU9pjkIWJbmOo,3226
|
|
18
|
+
brynq_sdk_bob/schemas/named_lists.py,sha256=HJBRKrAI2vhrkq-5MVXqQcmpGNzFtoOnaZI2Ii_6_vs,725
|
|
19
|
+
brynq_sdk_bob/schemas/payments.py,sha256=N4Ylommed-hsw0aX7rjuZuVZQc4XU0iDBdSIxz8eAxc,4292
|
|
20
|
+
brynq_sdk_bob/schemas/payroll_history.py,sha256=JdAq0XaArHHEw8EsXo3GD0EhSAyBhPtYQMmdvjCiY8g,806
|
|
21
|
+
brynq_sdk_bob/schemas/people.py,sha256=cy0mLKRdUhjOv52WB53AWd1XHn6mwrACGZAvK2ufsz4,38780
|
|
22
|
+
brynq_sdk_bob/schemas/salary.py,sha256=TSaM1g92y3oiDcUrfJW7ushgKZenI9xB6XW3kKuU0dE,4540
|
|
23
|
+
brynq_sdk_bob/schemas/timeoff.py,sha256=BHImTTT4n8j7bF7T5Ue_B0WHmmj1_QTPV9TKAlHeBZM,4124
|
|
24
|
+
brynq_sdk_bob/schemas/work.py,sha256=klzJtQf-avwhOkRHuPTM-jMhTIsroDPE56da1H5xaYs,2926
|
|
25
|
+
brynq_sdk_bob-2.6.2.dev10.dist-info/METADATA,sha256=hlLk5XIWFqHhiKBwQb8E-EPiyr34wWndRQvBxcSP5_M,408
|
|
26
|
+
brynq_sdk_bob-2.6.2.dev10.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
27
|
+
brynq_sdk_bob-2.6.2.dev10.dist-info/top_level.txt,sha256=oGiWqOuAAiVoLIzGe6F-Lo4IJBYz5ftOwBft7HtPuoY,14
|
|
28
|
+
brynq_sdk_bob-2.6.2.dev10.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
brynq_sdk_bob
|