brynq-sdk-bob 1.1.2__tar.gz → 2.2.0__tar.gz

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 (43) hide show
  1. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/PKG-INFO +1 -1
  2. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/__init__.py +10 -17
  3. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/bank.py +3 -3
  4. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/company.py +1 -1
  5. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/custom_tables.py +7 -7
  6. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/employment.py +3 -3
  7. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/named_lists.py +5 -5
  8. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/payments.py +2 -2
  9. brynq_sdk_bob-2.2.0/brynq_sdk_bob/people.py +82 -0
  10. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/salaries.py +2 -2
  11. brynq_sdk_bob-2.2.0/brynq_sdk_bob/schemas/bank.py +24 -0
  12. brynq_sdk_bob-2.2.0/brynq_sdk_bob/schemas/custom_tables.py +11 -0
  13. brynq_sdk_bob-2.2.0/brynq_sdk_bob/schemas/employment.py +31 -0
  14. brynq_sdk_bob-2.2.0/brynq_sdk_bob/schemas/named_lists.py +14 -0
  15. brynq_sdk_bob-2.2.0/brynq_sdk_bob/schemas/payments.py +31 -0
  16. brynq_sdk_bob-2.2.0/brynq_sdk_bob/schemas/people.py +99 -0
  17. brynq_sdk_bob-2.2.0/brynq_sdk_bob/schemas/salary.py +25 -0
  18. brynq_sdk_bob-2.2.0/brynq_sdk_bob/schemas/timeoff.py +29 -0
  19. brynq_sdk_bob-2.2.0/brynq_sdk_bob/schemas/work.py +33 -0
  20. brynq_sdk_bob-2.2.0/brynq_sdk_bob/timeoff.py +51 -0
  21. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/work.py +3 -4
  22. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob.egg-info/PKG-INFO +1 -1
  23. brynq_sdk_bob-2.2.0/brynq_sdk_bob.egg-info/requires.txt +2 -0
  24. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/setup.py +2 -2
  25. brynq_sdk_bob-1.1.2/brynq_sdk_bob/people.py +0 -62
  26. brynq_sdk_bob-1.1.2/brynq_sdk_bob/schemas/bank.py +0 -20
  27. brynq_sdk_bob-1.1.2/brynq_sdk_bob/schemas/custom_tables.py +0 -10
  28. brynq_sdk_bob-1.1.2/brynq_sdk_bob/schemas/employment.py +0 -28
  29. brynq_sdk_bob-1.1.2/brynq_sdk_bob/schemas/named_lists.py +0 -13
  30. brynq_sdk_bob-1.1.2/brynq_sdk_bob/schemas/payments.py +0 -30
  31. brynq_sdk_bob-1.1.2/brynq_sdk_bob/schemas/people.py +0 -87
  32. brynq_sdk_bob-1.1.2/brynq_sdk_bob/schemas/salary.py +0 -21
  33. brynq_sdk_bob-1.1.2/brynq_sdk_bob/schemas/timeoff.py +0 -28
  34. brynq_sdk_bob-1.1.2/brynq_sdk_bob/schemas/work.py +0 -29
  35. brynq_sdk_bob-1.1.2/brynq_sdk_bob/timeoff.py +0 -26
  36. brynq_sdk_bob-1.1.2/brynq_sdk_bob.egg-info/requires.txt +0 -2
  37. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/documents.py +0 -0
  38. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob/schemas/__init__.py +0 -0
  39. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob.egg-info/SOURCES.txt +0 -0
  40. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob.egg-info/dependency_links.txt +0 -0
  41. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob.egg-info/not-zip-safe +0 -0
  42. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/brynq_sdk_bob.egg-info/top_level.txt +0 -0
  43. {brynq_sdk_bob-1.1.2 → brynq_sdk_bob-2.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq_sdk_bob
3
- Version: 1.1.2
3
+ Version: 2.2.0
4
4
  Summary: Bob wrapper from BrynQ
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -1,9 +1,11 @@
1
1
  import base64
2
2
  import re
3
- from typing import Union, List
3
+ from typing import Union, List, Optional, Literal
4
4
  import pandas as pd
5
5
  import requests
6
+ import os
6
7
  from brynq_sdk_brynq import BrynQ
8
+ from brynq_sdk_functions import Functions
7
9
  from .bank import Bank
8
10
  from .company import Company
9
11
  from .documents import CustomDocuments
@@ -16,10 +18,10 @@ from .timeoff import TimeOff
16
18
  from .work import Work
17
19
 
18
20
  class Bob(BrynQ):
19
- def __init__(self, label: Union[str, List], test_environment: bool = True, debug: bool = False, target_system: str = None):
21
+ def __init__(self, system_type: Optional[Literal['source', 'target']] = None, test_environment: bool = True, debug: bool = False, target_system: str = None):
20
22
  super().__init__()
21
23
  self.timeout = 3600
22
- self.headers = self._get_request_headers(label=label)
24
+ self.headers = self._get_request_headers(system_type)
23
25
  if test_environment:
24
26
  self.base_url = "https://api.sandbox.hibob.com/v1/"
25
27
  else:
@@ -36,10 +38,12 @@ class Bob(BrynQ):
36
38
  self.documents = CustomDocuments(self)
37
39
  self.companies = Company(self)
38
40
  self.named_lists = NamedLists(self)
41
+ self.data_interface_id = os.getenv("DATA_INTERFACE_ID")
42
+ self.debug = debug
39
43
 
40
- def _get_request_headers(self, label):
41
- credentials = self.get_system_credential(system='bob', label=label)
42
- auth_token = base64.b64encode(f"{credentials['User ID']}:{credentials['API Token']}".encode()).decode('utf-8')
44
+ def _get_request_headers(self, system_type):
45
+ credentials = self.interfaces.credentials.get(system='bob', system_type=system_type)
46
+ auth_token = base64.b64encode(f"{credentials.get('data').get('User ID')}:{credentials.get('data').get('API Token')}".encode()).decode('utf-8')
43
47
  headers = {
44
48
  "accept": "application/json",
45
49
  "Authorization": f"Basic {auth_token}",
@@ -65,14 +69,3 @@ class Bob(BrynQ):
65
69
  request.params.update({"cursor": next_cursor})
66
70
 
67
71
  return result_data
68
-
69
- def rename_camel_columns_to_snake_case(self, df: pd.DataFrame) -> pd.DataFrame:
70
- def camel_to_snake_case(column):
71
- # Replace periods with underscores
72
- column = column.replace('.', '_')
73
- # Insert underscores before capital letters and convert to lowercase
74
- return re.sub(r'(?<!^)(?=[A-Z])', '_', column).lower()
75
-
76
- df.columns = map(camel_to_snake_case, df.columns)
77
-
78
- return df
@@ -6,8 +6,9 @@ from .schemas.bank import BankSchema
6
6
  class Bank:
7
7
  def __init__(self, bob):
8
8
  self.bob = bob
9
+ self.schema = BankSchema
9
10
 
10
- def get(self, person_ids: pd.Series) -> (pd.DataFrame, pd.DataFrame):
11
+ def get(self, person_ids: pd.Series, field_selection: list[str] = []) -> (pd.DataFrame, pd.DataFrame):
11
12
  data = []
12
13
  for person_id in person_ids:
13
14
  resp = self.bob.session.get(url=f"{self.bob.base_url}people/{person_id}/bank-accounts", timeout=self.bob.timeout)
@@ -19,8 +20,7 @@ class Bank:
19
20
  data += temp_data
20
21
 
21
22
  df = pd.DataFrame(data)
22
- df = self.bob.rename_camel_columns_to_snake_case(df)
23
23
 
24
24
  valid_banks, invalid_banks = Functions.validate_data(df=df, schema=BankSchema, debug=True)
25
25
 
26
- return valid_banks, invalid_banks
26
+ return valid_banks, invalid_banks
@@ -20,4 +20,4 @@ class Company:
20
20
  for list_key, list_data in data.items():
21
21
  values.update({list_key: [value['id'] for value in list_data['values']]})
22
22
 
23
- return values
23
+ return values
@@ -7,30 +7,30 @@ from .schemas.custom_tables import CustomTableSchema
7
7
  class CustomTables:
8
8
  def __init__(self, bob):
9
9
  self.bob = bob
10
+ self.schema = CustomTableSchema
10
11
 
11
12
  def get(self, employee_id: str, custom_table_id: str) -> (pd.DataFrame, pd.DataFrame):
12
13
  """
13
14
  Get custom table data for an employee
14
-
15
+
15
16
  Args:
16
17
  employee_id: The employee ID
17
18
  custom_table_id: The custom table ID
18
-
19
+
19
20
  Returns:
20
21
  A tuple of (valid_data, invalid_data) as pandas DataFrames
21
22
  """
22
23
  resp = self.bob.session.get(url=f"{self.bob.base_url}people/custom-tables/{employee_id}/{custom_table_id}")
23
24
  resp.raise_for_status()
24
25
  data = resp.json()
25
-
26
+
26
27
  # Normalize the nested JSON response
27
28
  df = pd.json_normalize(
28
29
  data,
29
30
  record_path=['values']
30
31
  )
31
-
32
+
32
33
  df['employee_id'] = employee_id
33
- df = self.bob.rename_camel_columns_to_snake_case(df)
34
- valid_data, invalid_data = Functions.validate_data(df=df, schema=CustomTableSchema, debug=True)
34
+ valid_data, invalid_data = Functions.validate_data(df=df, schema=self.schema, debug=True)
35
35
 
36
- return valid_data, invalid_data
36
+ return valid_data, invalid_data
@@ -7,6 +7,7 @@ from brynq_sdk_functions import Functions
7
7
  class Employment:
8
8
  def __init__(self, bob):
9
9
  self.bob = bob
10
+ self.schema = EmploymentSchema
10
11
 
11
12
  def get(self) -> (pd.DataFrame, pd.DataFrame):
12
13
  request = requests.Request(method='GET',
@@ -17,7 +18,6 @@ class Employment:
17
18
  record_path='values',
18
19
  meta=['employeeId']
19
20
  )
20
- df = self.bob.rename_camel_columns_to_snake_case(df)
21
- valid_contracts, invalid_contracts = Functions.validate_data(df=df, schema=EmploymentSchema, debug=True)
21
+ valid_contracts, invalid_contracts = Functions.validate_data(df=df, schema=self.schema, debug=True)
22
22
 
23
- return valid_contracts, invalid_contracts
23
+ return valid_contracts, invalid_contracts
@@ -7,14 +7,15 @@ from .schemas.named_lists import NamedListSchema
7
7
  class NamedLists:
8
8
  def __init__(self, bob):
9
9
  self.bob = bob
10
+ self.schema = NamedListSchema
10
11
 
11
12
  def get(self) -> (pd.DataFrame, pd.DataFrame):
12
13
  """
13
14
  Get custom table data for an employee
14
-
15
+
15
16
  Args:
16
17
  list_name: The list name
17
-
18
+
18
19
  Returns:
19
20
  A tuple of (valid_data, invalid_data) as pandas DataFrames
20
21
  """
@@ -28,10 +29,9 @@ class NamedLists:
28
29
  for key, group in data.items()
29
30
  for item in group["values"]
30
31
  ])
31
-
32
+
32
33
  # Normalize the nested JSON response
33
34
  # df = pd.DataFrame(data.get('values'))
34
- df = self.bob.rename_camel_columns_to_snake_case(df)
35
35
  valid_data, invalid_data = Functions.validate_data(df=df, schema=NamedListSchema, debug=True)
36
36
 
37
- return valid_data, invalid_data
37
+ return valid_data, invalid_data
@@ -7,6 +7,7 @@ from .schemas.payments import VariablePaymentSchema
7
7
  class Payments:
8
8
  def __init__(self, bob):
9
9
  self.bob = bob
10
+ self.schema = VariablePaymentSchema
10
11
 
11
12
  def get(self, person_id: str) -> (pd.DataFrame, pd.DataFrame):
12
13
  resp = self.bob.session.get(url=f"{self.bob.base_url}people/{person_id}/variable", timeout=self.bob.timeout)
@@ -17,7 +18,6 @@ class Payments:
17
18
  record_path='values'
18
19
  )
19
20
  df['employee_id'] = person_id
20
- df = self.bob.rename_camel_columns_to_snake_case(df)
21
- valid_payments, invalid_payments = Functions.validate_data(df=df, schema=VariablePaymentSchema, debug=True)
21
+ valid_payments, invalid_payments = Functions.validate_data(df=df, schema=self.schema, debug=True)
22
22
 
23
23
  return valid_payments, invalid_payments
@@ -0,0 +1,82 @@
1
+ import pandas as pd
2
+ from brynq_sdk_functions import Functions
3
+ from .bank import Bank
4
+ from .employment import Employment
5
+ from .salaries import Salaries
6
+ from .schemas.people import PeopleSchema
7
+ from .work import Work
8
+ from .custom_tables import CustomTables
9
+
10
+
11
+ class People:
12
+ def __init__(self, bob):
13
+ self.bob = bob
14
+ self.salaries = Salaries(bob)
15
+ self.employment = Employment(bob)
16
+ self.bank = Bank(bob)
17
+ self.work = Work(bob)
18
+ self.custom_tables = CustomTables(bob)
19
+ self.schema = PeopleSchema
20
+ self.field_name_in_body, self.field_name_in_response, self.endpoint_to_response = self._init_fields()
21
+
22
+ def get(self, additional_fields: list[str] = [], field_selection: list[str] = []) -> tuple[pd.DataFrame, pd.DataFrame]:
23
+ """
24
+ Get people from Bob
25
+
26
+ Args:
27
+ additional_fields (list[str]): Additional fields to get (not defined in the schema)
28
+ field_selection (list[str]): Fields to get (defined in the schema), if not provided, all fields are returned
29
+ """
30
+ #resp = self.bob.session.get(url=f"{self.bob.base_url}profiles", timeout=self.bob.timeout)
31
+ body_fields = list(set(self.field_name_in_body + additional_fields))
32
+ response_fields = list(set(self.field_name_in_response + additional_fields))
33
+
34
+ if field_selection:
35
+ body_fields = [field for field in body_fields if field in field_selection]
36
+ response_fields = [self.endpoint_to_response.get(field) for field in field_selection if field in self.endpoint_to_response]
37
+
38
+ # Bob sucks with default fields so you need to do a search call to retrieve additional fields.
39
+ resp_additional_fields = self.bob.session.post(url=f"{self.bob.base_url}people/search",
40
+ json={
41
+ "fields": body_fields,
42
+ "filters": []
43
+ },
44
+ timeout=self.bob.timeout)
45
+ json_response = resp_additional_fields.json()
46
+ df = pd.json_normalize(resp_additional_fields.json()['employees'])
47
+ df = df[[col for col in response_fields if col in df.columns]]
48
+ # Get the valid column names from PeopleSchema
49
+ valid_people, invalid_people = Functions.validate_data(df=df, schema=PeopleSchema, debug=True)
50
+ return valid_people, invalid_people
51
+
52
+
53
+ def _init_fields(self) -> tuple[list[str], list[str], dict[str, str]]:
54
+ resp_fields = self.bob.session.get(
55
+ url=f"{self.bob.base_url}company/people/fields",
56
+ timeout=self.bob.timeout,
57
+ headers=self.bob.headers
58
+ )
59
+ fields = resp_fields.json()
60
+ field_name_in_body = [field.get('id') for field in fields]
61
+ field_name_in_response = [field['jsonPath'] for field in fields]
62
+ endpoint_to_response = {field['id']: field['jsonPath'] for field in fields}
63
+ return field_name_in_body, field_name_in_response, endpoint_to_response
64
+
65
+ def _get_employee_id_to_person_id_mapping(self) -> tuple[pd.DataFrame, pd.DataFrame]:
66
+ employee_id_in_company = "work.employeeIdInCompany"
67
+ person_id = "root.id"
68
+
69
+ body_fields = [employee_id_in_company, person_id]
70
+ response_fields = [self.endpoint_to_response.get(field) for field in body_fields if field in self.endpoint_to_response]
71
+
72
+ resp_additional_fields = self.bob.session.post(url=f"{self.bob.base_url}people/search",
73
+ json={
74
+ "fields": body_fields,
75
+ "filters": []
76
+ },
77
+ timeout=self.bob.timeout)
78
+ df = pd.json_normalize(resp_additional_fields.json()['employees'])
79
+ df = df[[col for col in response_fields if col in df.columns]]
80
+ # Get the valid column names from PeopleSchema
81
+ valid_people, invalid_people = Functions.validate_data(df=df, schema=PeopleSchema, debug=True)
82
+ return valid_people, invalid_people
@@ -7,6 +7,7 @@ from .schemas.salary import SalarySchema
7
7
  class Salaries:
8
8
  def __init__(self, bob):
9
9
  self.bob = bob
10
+ self.schema = SalarySchema
10
11
 
11
12
  def get(self) -> (pd.DataFrame, pd.DataFrame):
12
13
  request = requests.Request(method='GET',
@@ -18,7 +19,6 @@ class Salaries:
18
19
  record_path='values',
19
20
  meta=['employeeId']
20
21
  )
21
- df = self.bob.rename_camel_columns_to_snake_case(df)
22
22
  valid_salaries, invalid_salaries = Functions.validate_data(df=df, schema=SalarySchema, debug=True)
23
23
 
24
- return valid_salaries, invalid_salaries
24
+ return valid_salaries, invalid_salaries
@@ -0,0 +1,24 @@
1
+ import pandera as pa
2
+ from pandera.typing import Series, String
3
+ import pandas as pd
4
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
5
+
6
+
7
+ class BankSchema(BrynQPanderaDataFrameModel):
8
+ id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Bank ID", alias="id")
9
+ employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
10
+ amount: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Amount", alias="amount")
11
+ allocation: Series[String] = pa.Field(coerce=True, nullable=True, description="Allocation", alias="allocation")
12
+ branch_address: Series[String] = pa.Field(coerce=True, nullable=True, description="Branch Address", alias="branchAddress")
13
+ bank_name: Series[String] = pa.Field(coerce=True, nullable=True, description="Bank Name", alias="bankName")
14
+ account_number: Series[String] = pa.Field(coerce=True, nullable=True, description="Account Number", alias="accountNumber")
15
+ routing_number: Series[String] = pa.Field(coerce=True, nullable=True, description="Routing Number", alias="routingNumber")
16
+ bank_account_type: Series[String] = pa.Field(coerce=True, nullable=True, description="Bank Account Type", alias="bankAccountType")
17
+ bic_or_swift: Series[String] = pa.Field(coerce=True, nullable=True, description="BIC or SWIFT", alias="bicOrSwift")
18
+ changed_by: Series[String] = pa.Field(coerce=True, nullable=True, description="Changed By", alias="changedBy")
19
+ iban: Series[String] = pa.Field(coerce=True, description="IBAN", alias="iban")
20
+ account_nickname: Series[String] = pa.Field(coerce=True, nullable=True, description="Account Nickname", alias="accountNickname")
21
+ use_for_bonus: Series[pd.BooleanDtype] = pa.Field(coerce=True, nullable=True, description="Use for Bonus", alias="useForBonus")
22
+
23
+ class Config:
24
+ coerce = True
@@ -0,0 +1,11 @@
1
+ import pandera as pa
2
+ from pandera.typing import Series
3
+ import pandas as pd
4
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
5
+
6
+ class CustomTableSchema(BrynQPanderaDataFrameModel):
7
+ id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Custom Table ID", alias="id")
8
+ employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
9
+
10
+ class Config:
11
+ coerce = True
@@ -0,0 +1,31 @@
1
+ import pandas as pd
2
+ import pandera as pa
3
+ from pandera import Bool
4
+ from pandera.typing import Series, String, Float, DateTime
5
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
6
+
7
+ class EmploymentSchema(BrynQPanderaDataFrameModel):
8
+ id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Employment ID", alias="id")
9
+ employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
10
+ active_effective_date: Series[DateTime] = pa.Field(coerce=True, description="Active Effective Date", alias="activeEffectiveDate")
11
+ contract: Series[String] = pa.Field(coerce=True, nullable=True, description="Contract", alias="contract") # has a list of possible values
12
+ creation_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="Creation Date", alias="creationDate")
13
+ effective_date: Series[DateTime] = pa.Field(coerce=True, description="Effective Date", alias="effectiveDate")
14
+ end_effective_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="End Effective Date", alias="endEffectiveDate")
15
+ fte: Series[Float] = pa.Field(coerce=True, description="FTE", alias="fte")
16
+ is_current: Series[Bool] = pa.Field(coerce=True, description="Is Current", alias="isCurrent")
17
+ modification_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="Modification Date", alias="modificationDate")
18
+ salary_pay_type: Series[String] = pa.Field(coerce=True, nullable=True, description="Salary Pay Type", alias="salaryPayType")
19
+ weekly_hours: Series[Float] = pa.Field(coerce=True, nullable=True, description="Weekly Hours", alias="weeklyHours")
20
+ # weekly_hours_sort_factor: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=False)
21
+ actual_working_pattern_working_pattern_type: Series[pa.String] = pa.Field(nullable=True, description="Actual Working Pattern Working Pattern Type", alias="actualWorkingPattern.workingPatternType")
22
+ actual_working_pattern_days_sunday: Series[Float] = pa.Field(nullable=True, description="Actual Working Pattern Days Sunday", alias="actualWorkingPattern.days.sunday")
23
+ actual_working_pattern_days_tuesday: Series[Float] = pa.Field(nullable=True, description="Actual Working Pattern Days Tuesday", alias="actualWorkingPattern.days.tuesday")
24
+ actual_working_pattern_days_wednesday: Series[Float] = pa.Field(nullable=True, description="Actual Working Pattern Days Wednesday", alias="actualWorkingPattern.days.wednesday")
25
+ actual_working_pattern_days_monday: Series[Float] = pa.Field(nullable=True, description="Actual Working Pattern Days Monday", alias="actualWorkingPattern.days.monday")
26
+ actual_working_pattern_days_friday: Series[Float] = pa.Field(nullable=True, description="Actual Working Pattern Days Friday", alias="actualWorkingPattern.days.friday")
27
+ actual_working_pattern_days_thursday: Series[Float] = pa.Field(nullable=True, description="Actual Working Pattern Days Thursday", alias="actualWorkingPattern.days.thursday")
28
+ actual_working_pattern_days_saturday: Series[Float] = pa.Field(nullable=True, description="Actual Working Pattern Days Saturday", alias="actualWorkingPattern.days.saturday")
29
+
30
+ class Config:
31
+ coerce = True
@@ -0,0 +1,14 @@
1
+ import pandera as pa
2
+ from pandera.typing import Series
3
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
4
+
5
+ class NamedListSchema(BrynQPanderaDataFrameModel):
6
+ id: Series[str] = pa.Field(coerce=True, description="Named List ID", alias="id")
7
+ value: Series[str] = pa.Field(coerce=True, description="Named List Value", alias="value")
8
+ name: Series[str] = pa.Field(coerce=True, description="Named List Name", alias="name")
9
+ archived: Series[bool] = pa.Field(coerce=True, description="Named List Archived", alias="archived")
10
+ # children: Series[list] = pa.Field(coerce=True)
11
+ type: Series[str] = pa.Field(coerce=True, description="Named List Type", alias="type")
12
+
13
+ class Config:
14
+ coerce = True
@@ -0,0 +1,31 @@
1
+ import pandera as pa
2
+ from pandera.typing import Series, String, Float, DateTime
3
+ from typing import Optional
4
+ import pandas as pd
5
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
6
+
7
+ class VariablePaymentSchema(BrynQPanderaDataFrameModel):
8
+ can_be_deleted: Series[bool] = pa.Field(nullable=True, coerce=True, description="Can Be Deleted", alias="canBeDeleted")
9
+ department_percent: Series[Float] = pa.Field(nullable=True, coerce=True, description="Department Percent", alias="departmentPercent")
10
+ payout_type: Series[String] = pa.Field(coerce=True, description="Payout Type", alias="payoutType")
11
+ num_of_salaries: Optional[Series[pd.Int64Dtype]] = pa.Field(nullable=True, coerce=True, description="Number of Salaries", alias="numOfSalaries")
12
+ end_date: Series[DateTime] = pa.Field(nullable=True, coerce=True, description="End Date", alias="endDate")
13
+ creation_date: Series[DateTime] = pa.Field(coerce=True, description="Creation Date", alias="creationDate")
14
+ percentage_of_annual_salary: Series[Float] = pa.Field(nullable=True, coerce=True, description="Percentage of Annual Salary", alias="percentageOfAnnualSalary")
15
+ individual_percent: Series[Float] = pa.Field(nullable=True, coerce=True, description="Individual Percent", alias="individualPercent")
16
+ variable_type: Series[String] = pa.Field(nullable=True, coerce=True, description="Variable Type", alias="variableType")
17
+ is_current: Series[bool] = pa.Field(nullable=True, coerce=True, description="Is Current", alias="isCurrent")
18
+ modification_date: Series[DateTime] = pa.Field(nullable=True, coerce=True, description="Modification Date", alias="modificationDate")
19
+ company_percent: Series[Float] = pa.Field(nullable=True, coerce=True, description="Company Percent", alias="companyPercent")
20
+ id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="ID", alias="id")
21
+ end_effective_date: Series[DateTime] = pa.Field(nullable=True, coerce=True, description="End Effective Date", alias="endEffectiveDate")
22
+ payment_period: Series[String] = pa.Field(coerce=True, description="Payment Period", alias="paymentPeriod")
23
+ effective_date: Series[DateTime] = pa.Field(coerce=True, description="Effective Date", alias="effectiveDate")
24
+ amount_value: Series[Float] = pa.Field(coerce=True, description="Amount Value", alias="amount.value")
25
+ amount_currency: Series[String] = pa.Field(coerce=True, description="Amount Currency", alias="amount.currency")
26
+ change_reason: Series[String] = pa.Field(nullable=True, coerce=True, description="Change Reason", alias="change.reason")
27
+ change_changed_by: Series[String] = pa.Field(nullable=True, coerce=True, description="Change Changed By", alias="change.changedBy")
28
+ change_changed_by_id: Series[pd.Int64Dtype] = pa.Field(nullable=True, coerce=True, description="Change Changed By ID", alias="change.changedById")
29
+ employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Employee ID", alias="employeeId") #set manually
30
+ class Config:
31
+ coerce = True
@@ -0,0 +1,99 @@
1
+ from datetime import datetime
2
+ from typing import Optional
3
+
4
+ import pandas as pd
5
+ import pandera as pa
6
+ from pandera import Bool
7
+ from pandera.typing import Series, String, Float, DateTime
8
+ import pandera.extensions as extensions
9
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
10
+
11
+
12
+
13
+ @extensions.register_check_method()
14
+ def check_list(x):
15
+ return isinstance(x, list)
16
+
17
+
18
+ class PeopleSchema(BrynQPanderaDataFrameModel):
19
+ id: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, description="Person ID", alias="id")
20
+ display_name: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Display Name", alias="displayName")
21
+ company_id: Optional[Series[String]] = pa.Field(coerce=True, description="Company ID", alias="companyId")
22
+ email: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Email", alias="email")
23
+ home_mobile_phone: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Personal Mobile Phone", alias="home.mobilePhone")
24
+ surname: Optional[Series[String]] = pa.Field(coerce=True, description="Surname", alias="surname")
25
+ first_name: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="First Name", alias="firstName")
26
+ full_name: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Full Name", alias="fullName")
27
+ personal_birth_date: Optional[Series[DateTime]] = pa.Field(coerce=True, nullable=True, description="Personal Birth Date", alias="personal.birthDate")
28
+ personal_pronouns: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Personal Pronouns", alias="personal.pronouns")
29
+ personal_honorific: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Personal Honorific", alias="personal.honorific")
30
+ personal_nationality: Optional[Series[object]] = pa.Field(coerce=True, check_name=check_list, description="Personal Nationality", alias="personal.nationality")
31
+ # employee_payroll_manager: Series[String] = pa.Field(coerce=True, nullable=True)
32
+ # employee_hrbp: Series[String] = pa.Field(coerce=True, nullable=True)
33
+ # employee_it_admin: Series[String] = pa.Field(coerce=True, nullable=True)
34
+ # employee_buddy: Series[String] = pa.Field(coerce=True, nullable=True)
35
+ employee_veteran_status: Optional[Series[object]] = pa.Field(coerce=True, check_name=check_list, description="Employee Veteran Status", alias="employee.veteranStatus")
36
+ employee_disability_status: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Employee Disability Status", alias="employee.disabilityStatus")
37
+ work_start_date: Optional[Series[DateTime]] = pa.Field(coerce=True, nullable=True, description="Work Start Date", alias="work.startDate")
38
+ work_manager: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Manager", alias="work.manager")
39
+ work_work_phone: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Work Phone", alias="work.workPhone")
40
+ work_tenure_duration_period_i_s_o: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Tenure Duration Period ISO", alias="work.tenureDurationPeriodIso")
41
+ work_tenure_duration_sort_factor: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=False, description="Work Tenure Duration Sort Factor", alias="work.tenureDurationSortFactor")
42
+ work_tenure_duration_humanize: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Tenure Duration Humanize", alias="work.tenureDurationHumanize")
43
+ work_duration_of_employment_period_i_s_o: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Duration of Employment Period ISO", alias="work.durationOfEmploymentPeriodIso")
44
+ work_duration_of_employment_sort_factor: Optional[Series[String]] = pa.Field(coerce=True, nullable=False, description="Work Duration of Employment Sort Factor", alias="work.durationOfEmploymentSortFactor")
45
+ work_duration_of_employment_humanize: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Duration of Employment Humanize", alias="work.durationOfEmploymentHumanize")
46
+ work_reports_to_id_in_company: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Reports to ID in Company", alias="work.reportsToIdInCompany")
47
+ work_employee_id_in_company: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Employee ID in Company", alias="work.employeeIdInCompany")
48
+ work_reports_to_display_name: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Reports to Display Name", alias="work.reportsToDisplayName")
49
+ work_reports_to_email: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Reports to Email", alias="work.reportsToEmail")
50
+ work_reports_to_surname: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Reports to Surname", alias="work.reportsToSurname")
51
+ work_reports_to_first_name: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Reports to First Name", alias="work.reportsToFirstName")
52
+ work_reports_to_id: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Reports to ID", alias="work.reportsToId")
53
+ work_work_mobile: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Work Mobile", alias="work.workMobile")
54
+ work_indirect_reports: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Indirect Reports", alias="work.indirectReports")
55
+ work_site_id: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Site ID", alias="work.siteId")
56
+ work_department: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Department", alias="work.department")
57
+ work_tenure_duration_years: Optional[Series[Float]] = pa.Field(coerce=True, nullable=True, description="Work Tenure Duration Years", alias="work.tenureDurationYears")
58
+ work_tenure_years: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Tenure Years", alias="work.tenureYears")
59
+ work_is_manager: Optional[Series[Bool]] = pa.Field(coerce=True, nullable=True, description="Work Is Manager", alias="work.isManager")
60
+ work_title: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Title", alias="work.title")
61
+ work_site: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Site", alias="work.site")
62
+ work_original_start_date: Optional[Series[DateTime]] = pa.Field(coerce=True, nullable=True, description="Work Original Start Date", alias="work.originalStartDate")
63
+ work_active_effective_date: Optional[Series[DateTime]] = pa.Field(coerce=True, nullable=True, description="Work Active Effective Date", alias="work.activeEffectiveDate")
64
+ work_direct_reports: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Direct Reports", alias="work.directReports")
65
+ # work_work_change_type: Series[String] = pa.Field(coerce=True, nullable=True)
66
+ work_second_level_manager: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Second Level Manager", alias="work.secondLevelManager")
67
+ work_days_of_previous_service: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Days of Previous Service", alias="work.daysOfPreviousService")
68
+ work_years_of_service: Optional[Series[Float]] = pa.Field(coerce=True, nullable=True, description="Work Years of Service", alias="work.yearsOfService")
69
+ payroll_employment_contract: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Contract Type", alias="payroll.employment.contract")
70
+ payroll_employment_type: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Employment Type", alias="payroll.employment.type")
71
+
72
+ about_food_preferences: Optional[Series[object]] = pa.Field(coerce=True, check_name=check_list, description="About Food Preferences", alias="about.foodPreferences")
73
+ # about_social_data_linkedin: Series[String] = pa.Field(coerce=True, nullable=True)
74
+ about_social_data_twitter: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="About Social Data Twitter", alias="about.socialDataTwitter")
75
+ about_social_data_facebook: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="About Social Data Facebook", alias="about.socialDataFacebook")
76
+ about_superpowers: Optional[Series[object]] = pa.Field(coerce=True, check_name=check_list, description="About Superpowers", alias="about.superpowers")
77
+ about_hobbies: Optional[Series[object]] = pa.Field(coerce=True, check_name=check_list, description="About Hobbies", alias="about.hobbies")
78
+ about_about: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="About About", alias="about.about")
79
+ about_avatar: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="About Avatar", alias="about.avatar")
80
+ address_city: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Address City", alias="address.city")
81
+ address_post_code: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Address Post Code", alias="address.postCode")
82
+ address_line1: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Address Line 1", alias="address.line1")
83
+ address_line2: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Address Line 2", alias="address.line2")
84
+ address_country: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Address Country", alias="address.country")
85
+ address_active_effective_date: Optional[Series[DateTime]] = pa.Field(coerce=True, nullable=True, description="Address Active Effective Date", alias="address.activeEffectiveDate")
86
+ home_legal_gender: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Legal Gender", alias="home.legalGender")
87
+ home_family_status: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Family / Marital Status", alias="home.familyStatus")
88
+ home_spouse_first_name: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Spouse First Name", alias="home.SpouseFirstName")
89
+ home_spouse_surname: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Spouse Surname", alias="home.SpouseSurname")
90
+ # home_spouse_birth_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
91
+ home_spouse_gender: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Spouse Gender", alias="home.SpouseGender")
92
+ identification_ssn_serial_number: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="SSN Serial Number", alias="identification.ssnSerialNumber")
93
+ internal_termination_reason: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Internal Termination Reason", alias="internal.terminationReason")
94
+ internal_termination_date: Optional[Series[DateTime]] = pa.Field(coerce=True, nullable=True, description="Internal Termination Date", alias="internal.terminationDate")
95
+ internal_termination_type: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Internal Termination Type", alias="internal.terminationType")
96
+ employee_last_day_of_work: Optional[Series[DateTime]] = pa.Field(coerce=True, nullable=True, description="Employee Last Day of Work", alias="employee.lastDayOfWork")
97
+
98
+ class Config:
99
+ coerce = True
@@ -0,0 +1,25 @@
1
+ import pandas as pd
2
+ import pandera as pa
3
+ 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
+
8
+
9
+ class SalarySchema(BrynQPanderaDataFrameModel):
10
+ id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Salary ID", alias="id")
11
+ employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
12
+ pay_frequency: Series[String] = pa.Field(coerce=True, nullable=True, description="Pay Frequency", alias="payFrequency") # has a list of possible values , isin=['Monthly']
13
+ creation_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="Creation Date", alias="creationDate")
14
+ is_current: Series[Bool] = pa.Field(coerce=True, description="Is Current", alias="isCurrent")
15
+ modification_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="Modification Date", alias="modificationDate")
16
+ effective_date: Series[DateTime] = pa.Field(coerce=True, description="Effective Date", alias="effectiveDate")
17
+ end_effective_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="End Effective Date", alias="endEffectiveDate")
18
+ change_reason: Series[str] = pa.Field(coerce=True, nullable=True, description="Change Reason", alias="change.reason")
19
+ pay_period: Series[String] = pa.Field(coerce=True, nullable=True, description="Pay Period", alias="payPeriod")
20
+ base_value: Series[Float] = pa.Field(coerce=True, nullable=True, description="Base Value", alias="base.value") #needs to become base.value?
21
+ base_currency: Series[String] = pa.Field(coerce=True, nullable=True, description="Base Currency", alias="base.currency")
22
+ active_effective_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="Active Effective Date", alias="activeEffectiveDate")
23
+
24
+ class Config:
25
+ coerce = True
@@ -0,0 +1,29 @@
1
+ import pandera as pa
2
+ from pandera.typing import Series, String, Float
3
+ import pandas as pd
4
+ from brynq_sdk_functions import BrynQPanderaDataFrameModel
5
+
6
+ class TimeOffSchema(BrynQPanderaDataFrameModel):
7
+ change_type: Series[String] = pa.Field(coerce=True, description="Change Type", alias="changeType")
8
+ employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
9
+ employee_display_name: Series[String] = pa.Field(coerce=True, description="Employee Display Name", alias="employeeDisplayName")
10
+ employee_email: Series[String] = pa.Field(coerce=True, description="Employee Email", alias="employeeEmail")
11
+ request_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Request ID", alias="requestId")
12
+ policy_type_display_name: Series[String] = pa.Field(coerce=True, description="Policy Type Display Name", alias="policyTypeDisplayName")
13
+ type: Series[String] = pa.Field(coerce=True, description="Type", alias="type")
14
+ start_date: Series[String] = pa.Field(coerce=True, description="Start Date", alias="startDate")
15
+ start_portion: Series[String] = pa.Field(coerce=True, description="Start Portion", alias="startPortion")
16
+ end_date: Series[String] = pa.Field(coerce=True, description="End Date", alias="endDate")
17
+ end_portion: Series[String] = pa.Field(coerce=True, description="End Portion", alias="endPortion")
18
+ day_portion: Series[String] = pa.Field(coerce=True, description="Day Portion", alias="dayPortion")
19
+ date: Series[String] = pa.Field(coerce=True, description="Date", alias="date")
20
+ hours_on_date: Series[Float] = pa.Field(coerce=True, description="Hours on Date", alias="hoursOnDate")
21
+ daily_hours: Series[Float] = pa.Field(coerce=True, description="Daily Hours", alias="dailyHours")
22
+ duration_unit: Series[String] = pa.Field(coerce=True, description="Duration Unit", alias="durationUnit")
23
+ total_duration: Series[Float] = pa.Field(coerce=True, description="Total Duration", alias="totalDuration")
24
+ total_cost: Series[Float] = pa.Field(coerce=True, description="Total Cost", alias="totalCost")
25
+ change_reason: Series[String] = pa.Field(nullable=True, coerce=True, description="Change Reason", alias="changeReason")
26
+ visibility: Series[String] = pa.Field(coerce=True, description="Visibility", alias="visibility")
27
+
28
+ class Config:
29
+ coerce = True
@@ -0,0 +1,33 @@
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="changeReason")
22
+ change_changed_by: Series[str] = pa.Field(coerce=True, nullable=True, description="Change Changed By", alias="changeChangedBy")
23
+ change_changed_by_id: Series[str] = pa.Field(coerce=True, nullable=True, description="Change Changed By ID", alias="changeChangedById")
24
+ reports_to_id: Series[str] = pa.Field(coerce=True, nullable=True, description="Reports To ID", alias="reportsToId")
25
+ reports_to_first_name: Series[str] = pa.Field(coerce=True, nullable=True, description="Reports To First Name", alias="reportsToFirstName")
26
+ reports_to_surname: Series[str] = pa.Field(coerce=True, nullable=True, description="Reports To Surname", alias="reportsToSurname")
27
+ reports_to_email: Series[str] = pa.Field(coerce=True, nullable=True, description="Reports To Email", alias="reportsToEmail")
28
+ reports_to_display_name: Series[str] = pa.Field(coerce=True, nullable=True, description="Reports To Display Name", alias="reportsToDisplayName")
29
+ reports_to: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True, description="Reports To", alias="reportsTo")
30
+ employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
31
+
32
+ class Config:
33
+ coerce = True
@@ -0,0 +1,51 @@
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
5
+ import warnings
6
+
7
+
8
+ class TimeOff:
9
+ def __init__(self, bob):
10
+ self.bob = bob
11
+ self.schema = TimeOffSchema
12
+
13
+ def get(self, since: datetime = None) -> tuple[pd.DataFrame, pd.DataFrame]:
14
+ """
15
+ Get time off requests
16
+
17
+ Args:
18
+ since (datetime, optional): The start date of the time off requests max 6 months ago. Defaults to 6 months ago if not provided.
19
+
20
+ Returns:
21
+ tuple[pd.DataFrame, pd.DataFrame]: A tuple of (valid_timeoff, invalid_timeoff) as pandas DataFrames
22
+ """
23
+ max_lookback = timedelta(days=int((365 / 2) - 1))
24
+ now_utc = datetime.now(timezone.utc)
25
+ six_months_ago = now_utc - max_lookback
26
+ #if since is provided, use it and cap to 6 months max
27
+ if since is not None:
28
+ if since.tzinfo is None:
29
+ since = since.replace(tzinfo=timezone.utc)
30
+ if since < six_months_ago:
31
+ warnings.warn("The 'since' date is more than 6 months ago. Limiting to 6 months ago due to API restrictions.")
32
+ since = six_months_ago
33
+ #if no since is provided, use 6 months ago
34
+ else:
35
+ since = six_months_ago
36
+
37
+ since = since.replace(tzinfo=timezone.utc).isoformat(timespec='milliseconds').replace('+00:00', 'Z')
38
+ resp = self.bob.session.get(url=f"{self.bob.base_url}timeoff/requests/changes",
39
+ params={'since': since},
40
+ timeout=self.bob.timeout)
41
+ resp.raise_for_status()
42
+ data = resp.json()['changes']
43
+ # data = self.bob.get_paginated_result(request)
44
+ df = pd.json_normalize(
45
+ data,
46
+ record_path='changes',
47
+ meta=['employeeId']
48
+ )
49
+ valid_timeoff, invalid_timeoff = Functions.validate_data(df=df, schema=self.schema, debug=True)
50
+
51
+ return valid_timeoff, invalid_timeoff
@@ -7,6 +7,7 @@ from .schemas.work import WorkSchema
7
7
  class Work:
8
8
  def __init__(self, bob):
9
9
  self.bob = bob
10
+ self.schema = WorkSchema
10
11
 
11
12
  def get(self) ->(pd.DataFrame, pd.DataFrame):
12
13
  request = requests.Request(method='GET',
@@ -17,8 +18,6 @@ class Work:
17
18
  record_path='values',
18
19
  meta=['employeeId']
19
20
  )
20
- df = self.bob.rename_camel_columns_to_snake_case(df)
21
+ valid_work, invalid_work = Functions.validate_data(df=df, schema=self.schema, debug=True)
21
22
 
22
- valid_work, invalid_work = Functions.validate_data(df=df, schema=WorkSchema, debug=True)
23
-
24
- return valid_work, invalid_work
23
+ return valid_work, invalid_work
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq-sdk-bob
3
- Version: 1.1.2
3
+ Version: 2.2.0
4
4
  Summary: Bob wrapper from BrynQ
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -0,0 +1,2 @@
1
+ brynq-sdk-brynq<5,>=4
2
+ pandas<3.0.0,>=2.2.0
@@ -2,7 +2,7 @@ from setuptools import setup, find_namespace_packages
2
2
 
3
3
  setup(
4
4
  name='brynq_sdk_bob',
5
- version='1.1.2',
5
+ version='2.2.0',
6
6
  description='Bob wrapper from BrynQ',
7
7
  long_description='Bob wrapper from BrynQ',
8
8
  author='BrynQ',
@@ -10,7 +10,7 @@ setup(
10
10
  packages=find_namespace_packages(include=['brynq_sdk*']),
11
11
  license='BrynQ License',
12
12
  install_requires=[
13
- 'brynq-sdk-brynq>=2',
13
+ 'brynq-sdk-brynq>=4,<5',
14
14
  'pandas>=2.2.0,<3.0.0',
15
15
  ],
16
16
  zip_safe=False,
@@ -1,62 +0,0 @@
1
- import pandas as pd
2
- from brynq_sdk_functions import Functions
3
- from .bank import Bank
4
- from .employment import Employment
5
- from .salaries import Salaries
6
- from .schemas.people import PeopleSchema
7
- from .work import Work
8
- from .custom_tables import CustomTables
9
-
10
-
11
- class People:
12
- def __init__(self, bob):
13
- self.bob = bob
14
- self.salaries = Salaries(bob)
15
- self.employment = Employment(bob)
16
- self.bank = Bank(bob)
17
- self.work = Work(bob)
18
- self.custom_tables = CustomTables(bob)
19
-
20
- def get(self) -> pd.DataFrame:
21
- resp = self.bob.session.get(url=f"{self.bob.base_url}profiles", timeout=self.bob.timeout)
22
- # Bob sucks with default fields so you need to do a search call to retrieve additional fields.
23
- additional_fields = [
24
- "personal.birthDate",
25
- "address.city",
26
- "address.postCode",
27
- "address.line1",
28
- "address.line2",
29
- "address.activeEffectiveDate",
30
- "address.country",
31
- # "home.legalGender",
32
- "home.spouse.firstName",
33
- "home.spouse.surname",
34
- # "home.spouse.birthDate",
35
- "home.spouse.gender",
36
- "internal.terminationReason",
37
- "internal.terminationDate",
38
- "internal.terminationType",
39
- "employee.lastDayOfWork",
40
- # housenumber addition
41
- "address.customColumns.column_1740046184782",
42
- # contract end date (bob only fills this when you get a new contract normally)
43
- "payroll.employment.customColumns.column_1680013460318",
44
- # iban
45
- "financial.iban"
46
- # ploegentoeslag
47
- ]
48
- resp_additional_fields = self.bob.session.post(url=f"{self.bob.base_url}people/search",
49
- json={
50
- "fields": ["root.id"] + additional_fields,
51
- "filters": []
52
- },
53
- timeout=self.bob.timeout)
54
- df_extra_fields = pd.json_normalize(resp_additional_fields.json()['employees'])
55
- resp.raise_for_status()
56
- data = resp.json()
57
- df = pd.json_normalize(data['employees'])
58
- df = pd.merge(df, df_extra_fields[["id"] + additional_fields], left_on='id', right_on='id')
59
- df = self.bob.rename_camel_columns_to_snake_case(df)
60
- valid_people, invalid_people = Functions.validate_data(df=df, schema=PeopleSchema, debug=True)
61
-
62
- return valid_people, invalid_people
@@ -1,20 +0,0 @@
1
- import pandera as pa
2
- from pandera.typing import Series, String
3
- import pandas as pd
4
-
5
-
6
- class BankSchema(pa.DataFrameModel):
7
- id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
8
- employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
9
- amount: Series[pd.Int64Dtype] = pa.Field(coerce=True)
10
- allocation: Series[String] = pa.Field(coerce=True, nullable=True)
11
- branch_address: Series[String] = pa.Field(coerce=True, nullable=True)
12
- bank_name: Series[String] = pa.Field(coerce=True, nullable=True)
13
- account_number: Series[String] = pa.Field(coerce=True, nullable=True)
14
- routing_number: Series[String] = pa.Field(coerce=True, nullable=True)
15
- bank_account_type: Series[String] = pa.Field(coerce=True, nullable=True)
16
- bic_or_swift: Series[String] = pa.Field(coerce=True, nullable=True)
17
- changed_by: Series[String] = pa.Field(coerce=True, nullable=True)
18
- iban: Series[String] = pa.Field(coerce=True)
19
- account_nickname: Series[String] = pa.Field(coerce=True, nullable=True)
20
- use_for_bonus: Series[pd.BooleanDtype] = pa.Field(coerce=True, nullable=True)
@@ -1,10 +0,0 @@
1
- import pandera as pa
2
- from pandera.typing import Series
3
- import pandas as pd
4
-
5
- class CustomTableSchema(pa.DataFrameModel):
6
- id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
7
- employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
8
-
9
- class Config:
10
- coerce = True
@@ -1,28 +0,0 @@
1
- import pandas as pd
2
- import pandera as pa
3
- from pandera import Bool
4
- from pandera.typing import Series, String, Float, DateTime
5
-
6
-
7
- class EmploymentSchema(pa.DataFrameModel):
8
- id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
9
- employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
10
- active_effective_date: Series[DateTime] = pa.Field(coerce=True)
11
- contract: Series[String] = pa.Field(coerce=True, nullable=True) # has a list of possible values
12
- creation_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
13
- effective_date: Series[DateTime] = pa.Field(coerce=True)
14
- end_effective_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
15
- fte: Series[Float] = pa.Field(coerce=True)
16
- is_current: Series[Bool] = pa.Field(coerce=True)
17
- modification_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
18
- salary_pay_type: Series[String] = pa.Field(coerce=True, nullable=True)
19
- weekly_hours: Series[Float] = pa.Field(coerce=True, nullable=True)
20
- # weekly_hours_sort_factor: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=False)
21
- actual_working_pattern_working_pattern_type: Series[pa.String] = pa.Field(nullable=True)
22
- actual_working_pattern_days_sunday: Series[Float] = pa.Field(nullable=True)
23
- actual_working_pattern_days_tuesday: Series[Float] = pa.Field(nullable=True)
24
- actual_working_pattern_days_wednesday: Series[Float] = pa.Field(nullable=True)
25
- actual_working_pattern_days_monday: Series[Float] = pa.Field(nullable=True)
26
- actual_working_pattern_days_friday: Series[Float] = pa.Field(nullable=True)
27
- actual_working_pattern_days_thursday: Series[Float] = pa.Field(nullable=True)
28
- actual_working_pattern_days_saturday: Series[Float] = pa.Field(nullable=True)
@@ -1,13 +0,0 @@
1
- import pandera as pa
2
- from pandera.typing import Series
3
-
4
- class NamedListSchema(pa.DataFrameModel):
5
- id: Series[str] = pa.Field(coerce=True)
6
- value: Series[str] = pa.Field(coerce=True)
7
- name: Series[str] = pa.Field(coerce=True)
8
- archived: Series[bool] = pa.Field(coerce=True)
9
- # children: Series[list] = pa.Field(coerce=True)
10
- type: Series[str] = pa.Field(coerce=True)
11
-
12
- class Config:
13
- coerce = True
@@ -1,30 +0,0 @@
1
- import pandera as pa
2
- from pandera.typing import Series, String, Float, DateTime
3
- import pandas as pd
4
-
5
- class VariablePaymentSchema(pa.DataFrameModel):
6
- can_be_deleted: Series[bool] = pa.Field(nullable=True, coerce=True)
7
- department_percent: Series[Float] = pa.Field(nullable=True, coerce=True)
8
- payout_type: Series[String] = pa.Field(coerce=True)
9
- num_of_salaries: Series[pd.Int64Dtype] = pa.Field(nullable=True, coerce=True)
10
- end_date: Series[DateTime] = pa.Field(nullable=True, coerce=True)
11
- creation_date: Series[DateTime] = pa.Field(coerce=True)
12
- percentage_of_annual_salary: Series[Float] = pa.Field(nullable=True, coerce=True)
13
- individual_percent: Series[Float] = pa.Field(nullable=True, coerce=True)
14
- variable_type: Series[String] = pa.Field(nullable=True, coerce=True)
15
- is_current: Series[bool] = pa.Field(nullable=True, coerce=True)
16
- modification_date: Series[DateTime] = pa.Field(nullable=True, coerce=True)
17
- company_percent: Series[Float] = pa.Field(nullable=True, coerce=True)
18
- id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
19
- end_effective_date: Series[DateTime] = pa.Field(nullable=True, coerce=True)
20
- payment_period: Series[String] = pa.Field(coerce=True)
21
- effective_date: Series[DateTime] = pa.Field(coerce=True)
22
- amount_value: Series[Float] = pa.Field(coerce=True)
23
- amount_currency: Series[String] = pa.Field(coerce=True)
24
- change_reason: Series[String] = pa.Field(nullable=True, coerce=True)
25
- change_changed_by: Series[String] = pa.Field(nullable=True, coerce=True)
26
- change_changed_by_id: Series[pd.Int64Dtype] = pa.Field(nullable=True, coerce=True)
27
- employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
28
-
29
- class Config:
30
- coerce = True
@@ -1,87 +0,0 @@
1
- from datetime import datetime
2
-
3
- import pandas as pd
4
- import pandera as pa
5
- from pandera import Bool
6
- from pandera.typing import Series, String, Float, DateTime
7
- import pandera.extensions as extensions
8
-
9
-
10
-
11
- @extensions.register_check_method()
12
- def check_list(x):
13
- return isinstance(x, list)
14
-
15
-
16
- class PeopleSchema(pa.DataFrameModel):
17
- id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
18
- display_name: Series[String] = pa.Field(coerce=True, nullable=True)
19
- company_id: Series[String] = pa.Field(coerce=True)
20
- email: Series[String] = pa.Field(coerce=True, nullable=True)
21
- surname: Series[String] = pa.Field(coerce=True)
22
- first_name: Series[String] = pa.Field(coerce=True, nullable=True)
23
- personal_birth_date: Series[DateTime] = pa.Field(coerce=True)
24
- personal_pronouns: Series[String] = pa.Field(coerce=True, nullable=True)
25
- personal_honorific: Series[String] = pa.Field(coerce=True, nullable=True)
26
- personal_nationality: Series[object] = pa.Field(coerce=True, check_name=check_list)
27
- # employee_payroll_manager: Series[String] = pa.Field(coerce=True, nullable=True)
28
- # employee_hrbp: Series[String] = pa.Field(coerce=True, nullable=True)
29
- # employee_it_admin: Series[String] = pa.Field(coerce=True, nullable=True)
30
- # employee_buddy: Series[String] = pa.Field(coerce=True, nullable=True)
31
- employee_veteran_status: Series[object] = pa.Field(coerce=True, check_name=check_list)
32
- employee_disability_status: Series[String] = pa.Field(coerce=True, nullable=True)
33
- work_start_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
34
- work_manager: Series[String] = pa.Field(coerce=True, nullable=True)
35
- work_work_phone: Series[String] = pa.Field(coerce=True, nullable=True)
36
- work_tenure_duration_period_i_s_o: Series[String] = pa.Field(coerce=True, nullable=True)
37
- work_tenure_duration_sort_factor: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=False)
38
- work_tenure_duration_humanize: Series[String] = pa.Field(coerce=True, nullable=True)
39
- work_duration_of_employment_period_i_s_o: Series[String] = pa.Field(coerce=True, nullable=True)
40
- work_duration_of_employment_sort_factor: Series[String] = pa.Field(coerce=True, nullable=False)
41
- work_duration_of_employment_humanize: Series[String] = pa.Field(coerce=True, nullable=True)
42
- work_reports_to_id_in_company: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True)
43
- work_employee_id_in_company: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True)
44
- work_reports_to_display_name: Series[String] = pa.Field(coerce=True, nullable=True)
45
- work_reports_to_email: Series[String] = pa.Field(coerce=True, nullable=True)
46
- work_reports_to_surname: Series[String] = pa.Field(coerce=True, nullable=True)
47
- work_reports_to_first_name: Series[String] = pa.Field(coerce=True, nullable=True)
48
- work_reports_to_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True)
49
- work_work_mobile: Series[String] = pa.Field(coerce=True, nullable=True)
50
- work_indirect_reports: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True)
51
- work_site_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True)
52
- work_department: Series[String] = pa.Field(coerce=True, nullable=True)
53
- work_tenure_duration_years: Series[Float] = pa.Field(coerce=True, nullable=True)
54
- work_tenure_years: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True)
55
- work_is_manager: Series[Bool] = pa.Field(coerce=True)
56
- work_title: Series[String] = pa.Field(coerce=True, nullable=True)
57
- work_site: Series[String] = pa.Field(coerce=True, nullable=True)
58
- work_original_start_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
59
- work_active_effective_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
60
- work_direct_reports: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True)
61
- # work_work_change_type: Series[String] = pa.Field(coerce=True, nullable=True)
62
- work_second_level_manager: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True)
63
- work_days_of_previous_service: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True)
64
- work_years_of_service: Series[Float] = pa.Field(coerce=True, nullable=True)
65
- about_food_preferences: Series[object] = pa.Field(coerce=True, check_name=check_list)
66
- # about_social_data_linkedin: Series[String] = pa.Field(coerce=True, nullable=True)
67
- about_social_data_twitter: Series[String] = pa.Field(coerce=True, nullable=True)
68
- about_social_data_facebook: Series[String] = pa.Field(coerce=True, nullable=True)
69
- about_superpowers: Series[object] = pa.Field(coerce=True, check_name=check_list)
70
- about_hobbies: Series[object] = pa.Field(coerce=True, check_name=check_list)
71
- about_about: Series[String] = pa.Field(coerce=True, nullable=True)
72
- about_avatar: Series[String] = pa.Field(coerce=True, nullable=True)
73
- address_city: Series[String] = pa.Field(coerce=True, nullable=True)
74
- address_post_code: Series[String] = pa.Field(coerce=True, nullable=True)
75
- address_line1: Series[String] = pa.Field(coerce=True, nullable=True)
76
- address_line2: Series[String] = pa.Field(coerce=True, nullable=True)
77
- # address_country: Series[String] = pa.Field(coerce=True, nullable=True)
78
- address_active_effective_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
79
- # home_legal_gender: Series[String] = pa.Field(coerce=True, nullable=True)
80
- home_spouse_first_name: Series[String] = pa.Field(coerce=True, nullable=True)
81
- home_spouse_surname: Series[String] = pa.Field(coerce=True, nullable=True)
82
- # home_spouse_birth_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
83
- home_spouse_gender: Series[String] = pa.Field(coerce=True, nullable=True)
84
- internal_termination_reason: Series[String] = pa.Field(coerce=True, nullable=True)
85
- internal_termination_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
86
- internal_termination_type: Series[String] = pa.Field(coerce=True, nullable=True)
87
- employee_last_day_of_work: Series[DateTime] = pa.Field(coerce=True, nullable=True)
@@ -1,21 +0,0 @@
1
- import pandas as pd
2
- import pandera as pa
3
- from pandera import Bool
4
- from pandera.typing import Series, String, Float, DateTime
5
- import pandera.extensions as extensions
6
-
7
-
8
- class SalarySchema(pa.DataFrameModel):
9
- id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
10
- employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
11
- pay_frequency: Series[String] = pa.Field(coerce=True, nullable=True) # has a list of possible values , isin=['Monthly']
12
- creation_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
13
- is_current: Series[Bool] = pa.Field(coerce=True)
14
- modification_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
15
- effective_date: Series[DateTime] = pa.Field(coerce=True)
16
- end_effective_date: Series[DateTime] = pa.Field(coerce=True, nullable=True)
17
- change_reason: Series[str] = pa.Field(coerce=True, nullable=True)
18
- pay_period: Series[String] = pa.Field(coerce=True, nullable=True)
19
- base_value: Series[Float] = pa.Field(coerce=True, nullable=True)
20
- base_currency: Series[String] = pa.Field(coerce=True, isin=['EUR', 'USD'])
21
- active_effective_date: Series[DateTime] = pa.Field(coerce=True)
@@ -1,28 +0,0 @@
1
- import pandera as pa
2
- from pandera.typing import Series, String, Float
3
- import pandas as pd
4
-
5
- class TimeOffSchema(pa.DataFrameModel):
6
- change_type: Series[String] = pa.Field(coerce=True)
7
- employee_id: Series[String] = pa.Field(coerce=True)
8
- employee_display_name: Series[String] = pa.Field(coerce=True)
9
- employee_email: Series[String] = pa.Field(coerce=True)
10
- request_id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
11
- policy_type_display_name: Series[String] = pa.Field(coerce=True)
12
- type: Series[String] = pa.Field(coerce=True)
13
- start_date: Series[String] = pa.Field(coerce=True)
14
- start_portion: Series[String] = pa.Field(coerce=True)
15
- end_date: Series[String] = pa.Field(coerce=True)
16
- end_portion: Series[String] = pa.Field(coerce=True)
17
- day_portion: Series[String] = pa.Field(coerce=True)
18
- date: Series[String] = pa.Field(coerce=True)
19
- hours_on_date: Series[Float] = pa.Field(coerce=True)
20
- daily_hours: Series[Float] = pa.Field(coerce=True)
21
- duration_unit: Series[String] = pa.Field(coerce=True)
22
- total_duration: Series[Float] = pa.Field(coerce=True)
23
- total_cost: Series[Float] = pa.Field(coerce=True)
24
- change_reason: Series[String] = pa.Field(nullable=True, coerce=True)
25
- visibility: Series[String] = pa.Field(coerce=True)
26
-
27
- class Config:
28
- coerce = True
@@ -1,29 +0,0 @@
1
- import pandera as pa
2
- from pandera.typing import Series
3
- import pandas as pd
4
- from datetime import datetime
5
-
6
- class WorkSchema(pa.DataFrameModel):
7
- can_be_deleted: Series[pa.Bool] = pa.Field(coerce=True)
8
- work_change_type: Series[str] = pa.Field(coerce=True)
9
- creation_date: Series[datetime] = pa.Field(coerce=True, nullable=True)
10
- title: Series[str] = pa.Field(coerce=True, nullable=True)
11
- is_current: Series[pa.Bool] = pa.Field(coerce=True)
12
- modification_date: Series[datetime] = pa.Field(coerce=True, nullable=True)
13
- site: Series[str] = pa.Field(coerce=True, nullable=True)
14
- site_id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
15
- id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
16
- end_effective_date: Series[datetime] = pa.Field(coerce=True, nullable=True)
17
- active_effective_date: Series[datetime] = pa.Field(coerce=True, nullable=True)
18
- department: Series[str] = pa.Field(coerce=True, nullable=True)
19
- effective_date: Series[datetime] = pa.Field(coerce=True, nullable=True)
20
- change_reason: Series[str] = pa.Field(coerce=True, nullable=True)
21
- change_changed_by: Series[str] = pa.Field(coerce=True, nullable=True)
22
- change_changed_by_id: Series[str] = pa.Field(coerce=True, nullable=True)
23
- reports_to_id: Series[str] = pa.Field(coerce=True, nullable=True)
24
- reports_to_first_name: Series[str] = pa.Field(coerce=True, nullable=True)
25
- reports_to_surname: Series[str] = pa.Field(coerce=True, nullable=True)
26
- reports_to_email: Series[str] = pa.Field(coerce=True, nullable=True)
27
- reports_to_display_name: Series[str] = pa.Field(coerce=True, nullable=True)
28
- reports_to: Series[pd.Int64Dtype] = pa.Field(coerce=True, nullable=True)
29
- employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True)
@@ -1,26 +0,0 @@
1
- from datetime import datetime, timezone
2
- import pandas as pd
3
- from brynq_sdk_functions import Functions
4
- from .schemas.timeoff import TimeOffSchema
5
-
6
-
7
- class TimeOff:
8
- def __init__(self, bob):
9
- self.bob = bob
10
-
11
- def get(self, since: datetime) -> (pd.DataFrame, pd.DataFrame):
12
- resp = self.bob.session.get(url=f"{self.bob.base_url}timeoff/requests/changes",
13
- params={'since': since.replace(tzinfo=timezone.utc).isoformat(timespec='milliseconds')},
14
- timeout=self.bob.timeout)
15
- resp.raise_for_status()
16
- data = resp.json()['changes']
17
- # data = self.bob.get_paginated_result(request)
18
- df = pd.json_normalize(
19
- data,
20
- record_path='changes',
21
- meta=['employeeId']
22
- )
23
- df = self.bob.rename_camel_columns_to_snake_case(df)
24
- valid_timeoff, invalid_timeoff = Functions.validate_data(df=df, schema=TimeOffSchema, debug=True)
25
-
26
- return valid_timeoff, invalid_timeoff
@@ -1,2 +0,0 @@
1
- brynq-sdk-brynq>=2
2
- pandas<3.0.0,>=2.2.0
File without changes