brynq-sdk-bob 2.6.0__tar.gz → 2.6.2.dev0__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 (33) hide show
  1. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/PKG-INFO +1 -1
  2. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/__init__.py +4 -0
  3. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/bank.py +6 -1
  4. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/custom_tables.py +1 -1
  5. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/payments.py +56 -9
  6. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/people.py +45 -4
  7. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/salaries.py +9 -2
  8. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/bank.py +8 -7
  9. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/people.py +3 -3
  10. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/salary.py +1 -1
  11. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/timeoff.py +12 -12
  12. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob.egg-info/PKG-INFO +1 -1
  13. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/setup.py +1 -1
  14. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/company.py +0 -0
  15. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/documents.py +0 -0
  16. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/employment.py +0 -0
  17. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/named_lists.py +0 -0
  18. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/payroll_history.py +0 -0
  19. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/__init__.py +0 -0
  20. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/custom_tables.py +0 -0
  21. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/employment.py +0 -0
  22. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/named_lists.py +0 -0
  23. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/payments.py +0 -0
  24. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/payroll_history.py +0 -0
  25. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/schemas/work.py +0 -0
  26. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/timeoff.py +0 -0
  27. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob/work.py +0 -0
  28. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob.egg-info/SOURCES.txt +0 -0
  29. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob.egg-info/dependency_links.txt +0 -0
  30. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob.egg-info/not-zip-safe +0 -0
  31. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob.egg-info/requires.txt +0 -0
  32. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/brynq_sdk_bob.egg-info/top_level.txt +0 -0
  33. {brynq_sdk_bob-2.6.0 → brynq_sdk_bob-2.6.2.dev0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq_sdk_bob
3
- Version: 2.6.0
3
+ Version: 2.6.2.dev0
4
4
  Summary: Bob wrapper from BrynQ
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -45,6 +45,10 @@ class Bob(BrynQ):
45
45
 
46
46
  def _get_request_headers(self, system_type):
47
47
  credentials = self.interfaces.credentials.get(system='bob', system_type=system_type)
48
+ if type(credentials) is list:
49
+ credentials = credentials[0]
50
+
51
+ print(credentials)
48
52
  auth_token = base64.b64encode(f"{credentials.get('data').get('User ID')}:{credentials.get('data').get('API Token')}".encode()).decode('utf-8')
49
53
  headers = {
50
54
  "accept": "application/json",
@@ -2,6 +2,8 @@ import pandas as pd
2
2
  from brynq_sdk_functions import Functions
3
3
  from .schemas.bank import BankSchema
4
4
 
5
+ import time
6
+ from tqdm import tqdm
5
7
 
6
8
  class Bank:
7
9
  def __init__(self, bob):
@@ -10,7 +12,7 @@ class Bank:
10
12
 
11
13
  def get(self, person_ids: pd.Series, field_selection: list[str] = []) -> (pd.DataFrame, pd.DataFrame):
12
14
  data = []
13
- for person_id in person_ids:
15
+ for person_id in tqdm(person_ids, desc="Fetching bank accounts"):
14
16
  resp = self.bob.session.get(url=f"{self.bob.base_url}people/{person_id}/bank-accounts", timeout=self.bob.timeout)
15
17
  resp.raise_for_status()
16
18
  temp_data = resp.json()['values']
@@ -19,6 +21,9 @@ class Bank:
19
21
  account['employee_id'] = person_id
20
22
  data += temp_data
21
23
 
24
+ # rate limit is 50 per minute
25
+ time.sleep(1.3)
26
+
22
27
  df = pd.DataFrame(data)
23
28
 
24
29
  valid_banks, invalid_banks = Functions.validate_data(df=df, schema=BankSchema, debug=True)
@@ -29,7 +29,7 @@ class CustomTables:
29
29
  record_path=['values']
30
30
  )
31
31
 
32
- df['employeeId'] = employee_id
32
+ df['employee_id'] = employee_id
33
33
  valid_data, invalid_data = Functions.validate_data(df=df, schema=self.schema, debug=True)
34
34
 
35
35
  return valid_data, invalid_data
@@ -3,23 +3,67 @@ from typing import Optional, List
3
3
  from brynq_sdk_functions import Functions
4
4
  from .schemas.payments import VariablePaymentSchema, ActualPaymentsSchema
5
5
 
6
+ import time
7
+ from tqdm import tqdm
8
+
6
9
 
7
10
  class Payments:
8
11
  def __init__(self, bob):
9
12
  self.bob = bob
10
13
  self.schema = VariablePaymentSchema
11
14
 
12
- def get(self, person_id: str) -> (pd.DataFrame, pd.DataFrame):
13
- resp = self.bob.session.get(url=f"{self.bob.base_url}people/{person_id}/variable", timeout=self.bob.timeout)
14
- resp.raise_for_status()
15
- data = resp.json()
16
- df = pd.json_normalize(
17
- data,
18
- record_path='values'
15
+ def _apply_named_list_mappings(self, df: pd.DataFrame) -> pd.DataFrame:
16
+ """Apply named list ID-to-value mappings to dataframe columns."""
17
+ if df.empty:
18
+ return df
19
+
20
+ # Fetch named lists from Bob API
21
+ resp_named_lists = self.bob.session.get(
22
+ url=f"{self.bob.base_url}company/named-lists",
23
+ timeout=self.bob.timeout,
24
+ headers=self.bob.headers
19
25
  )
20
- df['employee_id'] = person_id
21
- valid_payments, invalid_payments = Functions.validate_data(df=df, schema=self.schema, debug=True)
26
+ named_lists = resp_named_lists.json()
22
27
 
28
+ # Transform named_lists to create id-to-value mappings for each field
29
+ named_lists = {
30
+ key.split('.')[-1]: {item['id']: item['value'] for item in value['values']}
31
+ for key, value in named_lists.items()
32
+ }
33
+
34
+ for field in df.columns:
35
+ # Fields in the response and in the named-list have different building blocks
36
+ # but they both end with the same last block
37
+ field_df = field.split('.')[-1].split('work_')[-1]
38
+ if field_df in named_lists.keys() and field_df not in ['site']:
39
+ mapping = named_lists[field_df]
40
+ df[field] = df[field].apply(
41
+ lambda v: [mapping.get(x, x) for x in v] if isinstance(v, list) else mapping.get(v, v)
42
+ )
43
+
44
+ return df
45
+
46
+ def get(self, person_ids: List[str]) -> (pd.DataFrame, pd.DataFrame):
47
+ df = pd.DataFrame()
48
+ for person_id in tqdm(person_ids, desc="Fetching variable payments"):
49
+ resp = self.bob.session.get(url=f"{self.bob.base_url}people/{person_id}/variable", timeout=self.bob.timeout)
50
+ resp.raise_for_status()
51
+ data = resp.json()
52
+ df = pd.concat([df, pd.json_normalize(
53
+ data,
54
+ record_path='values'
55
+ )])
56
+ df['employee_id'] = person_id
57
+
58
+ # Rate limit is 50 per minute
59
+ time.sleep(1.3)
60
+
61
+ df = df.reset_index(drop=True)
62
+
63
+ # Apply named list mappings
64
+ df = self._apply_named_list_mappings(df)
65
+
66
+ valid_payments, invalid_payments = Functions.validate_data(df=df, schema=self.schema, debug=True)
23
67
  return valid_payments, invalid_payments
24
68
 
25
69
  def get_actual_payments(
@@ -105,6 +149,9 @@ class Payments:
105
149
 
106
150
  df = pd.json_normalize(all_results)
107
151
 
152
+ # Apply named list mappings
153
+ df = self._apply_named_list_mappings(df)
154
+
108
155
  valid_payments, invalid_payments = Functions.validate_data(
109
156
  df=df,
110
157
  schema=ActualPaymentsSchema,
@@ -1,5 +1,5 @@
1
1
  import pandas as pd
2
- from typing import Optional
2
+ from typing import Optional, List
3
3
  from brynq_sdk_functions import Functions
4
4
  from brynq_sdk_functions import BrynQPanderaDataFrameModel
5
5
  from .bank import Bank
@@ -29,25 +29,66 @@ class People:
29
29
  for col_name, col in schema.columns.items()
30
30
  ]
31
31
 
32
- def get(self, schema_custom_fields: Optional[BrynQPanderaDataFrameModel] = None) -> pd.DataFrame:
33
-
32
+ def get(self, schema_custom_fields: Optional[BrynQPanderaDataFrameModel] = None, employee_ids: Optional[List[str]] = None) -> pd.DataFrame:
34
33
  core_fields = self.__build_api_fields(PeopleSchema)
35
34
  custom_fields = self.__build_api_fields(schema_custom_fields) if schema_custom_fields is not None else []
36
35
  fields = core_fields + custom_fields
37
36
 
37
+ # Build filters based on employee_ids if provided
38
+ filters = []
39
+ if employee_ids is not None:
40
+ filters = [
41
+ {
42
+ "fieldPath": "root.id",
43
+ "operator": "equals",
44
+ "values": employee_ids
45
+ }
46
+ ]
47
+
38
48
  resp = self.bob.session.post(url=f"{self.bob.base_url}people/search",
39
49
  json={
40
50
  "fields": fields,
41
- "filters": []
51
+ "filters": filters
42
52
  #"humanReadable": "REPLACE"
43
53
  },
44
54
  timeout=self.bob.timeout)
45
55
  resp.raise_for_status()
46
56
  df = pd.json_normalize(resp.json()['employees'])
47
57
  df = df.loc[:, ~df.columns.str.contains('value')]
58
+
48
59
  # Normalize separators in incoming data: convert '/' to '.' to match schema aliases
49
60
  df.columns = df.columns.str.replace('/', '.', regex=False)
50
61
 
62
+ # A lot of fields from Bob are returned with only ID's. Those fields should be mapped to names. Therefore, we need to get the mapping from the named-lists endpoint.
63
+ resp_named_lists = self.bob.session.get(url=f"{self.bob.base_url}company/named-lists", timeout=self.bob.timeout, headers=self.bob.headers)
64
+ named_lists = resp_named_lists.json()
65
+ # save json to file
66
+ # import json
67
+ # with open('named_lists.json', 'w') as f:
68
+ # json.dump(named_lists, f, indent=4)
69
+
70
+ # Transform named_lists to create id-to-value mappings for each field
71
+ named_lists = {key.split('.')[-1]: {item['id']: item['value'] for item in value['values']} for key, value in named_lists.items()}
72
+
73
+ deviating_named_list_cols_mapping = {
74
+ 'payroll.employment.type': 'payrollEmploymentType',
75
+ 'home.familyStatus': 'familystatus',
76
+ 'personal.nationality': 'nationalities',
77
+ }
78
+
79
+ for field in df.columns:
80
+ # Fields in the response and in the named-list does have different building blocks (e.g. people.payroll.entitlement. or people.entitlement.). But they both end with the same last block
81
+ field_df = field.split('.')[-1].split('work_')[-1]
82
+
83
+ # Check if this field has a deviating mapping
84
+ named_list_key = deviating_named_list_cols_mapping.get(field, field_df)
85
+
86
+ if named_list_key in named_lists.keys() and named_list_key not in ['site']:
87
+ mapping = named_lists[named_list_key]
88
+ df[field] = df[field].apply(
89
+ lambda v: [mapping.get(x, x) for x in v] if isinstance(v, list) else mapping.get(v, v)
90
+ )
91
+
51
92
  if schema_custom_fields is not None:
52
93
  valid_people, invalid_people_custom = Functions.validate_data(df=df, schema=schema_custom_fields, debug=True)
53
94
  else:
@@ -1,5 +1,6 @@
1
1
  import pandas as pd
2
2
  import requests
3
+ from typing import Optional, List
3
4
  from brynq_sdk_functions import Functions
4
5
  from .schemas.salary import SalarySchema, SalaryCreateSchema
5
6
 
@@ -9,10 +10,16 @@ class Salaries:
9
10
  self.bob = bob
10
11
  self.schema = SalarySchema
11
12
 
12
- def get(self) -> tuple[pd.DataFrame, pd.DataFrame]:
13
+ def get(self, employee_ids: Optional[List[str]] = None) -> tuple[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
+
13
20
  request = requests.Request(method='GET',
14
21
  url=f"{self.bob.base_url}bulk/people/salaries",
15
- params={"limit": 100})
22
+ params=params)
16
23
  data = self.bob.get_paginated_result(request)
17
24
  df = pd.json_normalize(
18
25
  data,
@@ -1,4 +1,5 @@
1
1
  import pandera as pa
2
+ from typing import Optional
2
3
  from pandera.typing import Series, String
3
4
  import pandas as pd
4
5
  from brynq_sdk_functions import BrynQPanderaDataFrameModel
@@ -6,19 +7,19 @@ from brynq_sdk_functions import BrynQPanderaDataFrameModel
6
7
 
7
8
  class BankSchema(BrynQPanderaDataFrameModel):
8
9
  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")
10
+ employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employee_id")
11
+ amount: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, description="Amount", alias="amount")
12
+ allocation: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Allocation", alias="allocation")
13
+ branch_address: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Branch Address", alias="branchAddress")
13
14
  bank_name: Series[String] = pa.Field(coerce=True, nullable=True, description="Bank Name", alias="bankName")
14
15
  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
+ routing_number: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Routing Number", alias="routingNumber")
16
17
  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
+ bic_or_swift: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="BIC or SWIFT", alias="bicOrSwift")
18
19
  changed_by: Series[String] = pa.Field(coerce=True, nullable=True, description="Changed By", alias="changedBy")
19
20
  iban: Series[String] = pa.Field(coerce=True, description="IBAN", alias="iban")
20
21
  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
+ use_for_bonus: Optional[Series[pd.BooleanDtype]] = pa.Field(coerce=True, nullable=True, description="Use for Bonus", alias="useForBonus")
22
23
 
23
24
  class Config:
24
25
  coerce = True
@@ -16,7 +16,7 @@ def check_list(x):
16
16
 
17
17
 
18
18
  class PeopleSchema(BrynQPanderaDataFrameModel):
19
- id: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, description="Person ID", alias="id", metadata={"api_field": "root.id"})
19
+ id: Optional[Series[String]] = pa.Field(coerce=True, description="Person ID", alias="id", metadata={"api_field": "root.id"})
20
20
  display_name: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Display Name", alias="displayName", metadata={"api_field": "root.displayName"})
21
21
  company_id: Optional[Series[String]] = pa.Field(coerce=True, description="Company ID", alias="companyId", metadata={"api_field": "root.companyId"})
22
22
  email: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Email", alias="email", metadata={"api_field": "root.email"})
@@ -50,7 +50,7 @@ class PeopleSchema(BrynQPanderaDataFrameModel):
50
50
  work_reports_to_display_name: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Reports to Display Name", alias="work.reportsTo.displayName")
51
51
  work_reports_to_surname: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Reports to Surname", alias="work.reportsTo.surname")
52
52
  work_reports_to_first_name: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Reports to First Name", alias="work.reportsTo.firstName")
53
- work_reports_to_id: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Reports to ID", alias="work.reportsTo.id")
53
+ work_reports_to_id: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Reports to ID", alias="work.reportsTo.id")
54
54
  work_work_mobile: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Work Mobile", alias="work.workMobile")
55
55
  work_indirect_reports: Optional[Series[pd.Int64Dtype]] = pa.Field(coerce=True, nullable=True, description="Work Indirect Reports", alias="work.indirectReports")
56
56
  work_site_id: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Work Site ID", alias="work.siteId")
@@ -106,7 +106,7 @@ class PeopleSchema(BrynQPanderaDataFrameModel):
106
106
  internal_termination_date: Optional[Series[DateTime]] = pa.Field(coerce=True, nullable=True, description="Internal Termination Date", alias="internal.terminationDate")
107
107
  internal_termination_type: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Internal Termination Type", alias="internal.terminationType")
108
108
  employee_last_day_of_work: Optional[Series[DateTime]] = pa.Field(coerce=True, nullable=True, description="Employee Last Day of Work", alias="employee.lastDayOfWork")
109
- financial_iban: Series[String] = pa.Field(coerce=True, nullable=True, alias='financial.iban')
109
+ financial_iban: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, alias='financial.iban')
110
110
  employee_band_effective_date_ote: Optional[Series[DateTime]] = pa.Field(coerce=True, nullable=True, description="Employee Band Effective Date OTE", alias="employee.band_effectiveDate_ote")
111
111
  employee_band_site_ote: Optional[Series[object]] = pa.Field(coerce=True, nullable=True, check_name=check_list, description="Employee Band Site OTE", alias="employee.band_site_ote")
112
112
  employee_band_min_ote: Optional[Series[Float]] = pa.Field(coerce=True, nullable=True, description="Employee Band Min OTE", alias="employee.band_min_ote")
@@ -11,7 +11,7 @@ from typing import Optional, Dict, Any
11
11
 
12
12
  class SalarySchema(BrynQPanderaDataFrameModel):
13
13
  id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Salary ID", alias="id")
14
- employee_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
14
+ employee_id: Series[String] = pa.Field(coerce=True, description="Employee ID", alias="employeeId")
15
15
  pay_frequency: Series[String] = pa.Field(coerce=True, nullable=True, description="Pay Frequency", alias="payFrequency") # has a list of possible values , isin=['Monthly']
16
16
  creation_date: Series[DateTime] = pa.Field(coerce=True, nullable=True, description="Creation Date", alias="creationDate")
17
17
  is_current: Series[Bool] = pa.Field(coerce=True, description="Is Current", alias="isCurrent")
@@ -12,19 +12,19 @@ class TimeOffSchema(BrynQPanderaDataFrameModel):
12
12
  request_id: Series[pd.Int64Dtype] = pa.Field(coerce=True, description="Request ID", alias="requestId")
13
13
  policy_type_display_name: Series[String] = pa.Field(coerce=True, description="Policy Type Display Name", alias="policyTypeDisplayName")
14
14
  type: Series[String] = pa.Field(coerce=True, description="Type", alias="type")
15
- start_date: Series[String] = pa.Field(coerce=True, description="Start Date", alias="startDate")
16
- start_portion: Series[String] = pa.Field(coerce=True, description="Start Portion", alias="startPortion")
17
- end_date: Series[String] = pa.Field(coerce=True, description="End Date", alias="endDate")
18
- end_portion: Series[String] = pa.Field(coerce=True, description="End Portion", alias="endPortion")
19
- day_portion: Optional[Series[String]] = pa.Field(coerce=True, description="Day Portion", alias="dayPortion")
20
- date: Optional[Series[String]] = pa.Field(coerce=True, description="Date", alias="date")
21
- hours_on_date: Optional[Series[Float]] = pa.Field(coerce=True, description="Hours on Date", alias="hoursOnDate")
22
- daily_hours: Optional[Series[Float]] = pa.Field(coerce=True, description="Daily Hours", alias="dailyHours")
23
- duration_unit: Optional[Series[String]] = pa.Field(coerce=True, description="Duration Unit", alias="durationUnit")
24
- total_duration: Optional[Series[Float]] = pa.Field(coerce=True, description="Total Duration", alias="totalDuration")
25
- total_cost: Optional[Series[Float]] = pa.Field(coerce=True, description="Total Cost", alias="totalCost")
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
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, description="Visibility", alias="visibility")
27
+ visibility: Optional[Series[String]] = pa.Field(coerce=True, nullable=True, description="Visibility", alias="visibility")
28
28
 
29
29
  class Config:
30
30
  coerce = True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq-sdk-bob
3
- Version: 2.6.0
3
+ Version: 2.6.2.dev0
4
4
  Summary: Bob wrapper from BrynQ
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -2,7 +2,7 @@ from setuptools import setup, find_namespace_packages
2
2
 
3
3
  setup(
4
4
  name='brynq_sdk_bob',
5
- version='2.6.0',
5
+ version='2.6.2.dev0',
6
6
  description='Bob wrapper from BrynQ',
7
7
  long_description='Bob wrapper from BrynQ',
8
8
  author='BrynQ',