brynq-sdk-nmbrs 1.3.2__tar.gz → 2.0.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 (42) hide show
  1. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/PKG-INFO +1 -1
  2. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/__init__.py +13 -12
  3. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/companies.py +1 -0
  4. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/costcenter.py +0 -47
  5. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/costunit.py +11 -35
  6. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/debtors.py +2 -1
  7. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/department.py +1 -24
  8. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/employees.py +16 -24
  9. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/employment.py +0 -24
  10. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/function.py +1 -24
  11. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/salaries.py +10 -34
  12. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schedules.py +18 -42
  13. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs.egg-info/PKG-INFO +1 -1
  14. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs.egg-info/requires.txt +1 -1
  15. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/setup.py +2 -2
  16. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/address.py +0 -0
  17. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/bank.py +0 -0
  18. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/children.py +0 -0
  19. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/contract.py +0 -0
  20. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/document.py +0 -0
  21. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/hours.py +0 -0
  22. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/salary_tables.py +0 -0
  23. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/__init__.py +0 -0
  24. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/address.py +0 -0
  25. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/bank.py +0 -0
  26. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/contracts.py +0 -0
  27. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/costcenter.py +0 -0
  28. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/costunit.py +0 -0
  29. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/department.py +0 -0
  30. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/employees.py +0 -0
  31. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/employment.py +0 -0
  32. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/function.py +0 -0
  33. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/hours.py +0 -0
  34. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/salary.py +0 -0
  35. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/schedules.py +0 -0
  36. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/schemas/wagecomponents.py +0 -0
  37. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs/wagecomponents.py +0 -0
  38. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs.egg-info/SOURCES.txt +0 -0
  39. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs.egg-info/dependency_links.txt +0 -0
  40. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs.egg-info/not-zip-safe +0 -0
  41. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/brynq_sdk_nmbrs.egg-info/top_level.txt +0 -0
  42. {brynq_sdk_nmbrs-1.3.2 → brynq_sdk_nmbrs-2.0.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq_sdk_nmbrs
3
- Version: 1.3.2
3
+ Version: 2.0.0
4
4
  Summary: Nmbrs wrapper from BrynQ
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -1,5 +1,5 @@
1
1
  import warnings
2
- from typing import Union, List
2
+ from typing import Union, List, Literal, Optional
3
3
  import re
4
4
  import pandas as pd
5
5
  import requests
@@ -23,10 +23,11 @@ from .hours import VariableHours, FixedHours
23
23
  from .salaries import Salaries
24
24
  from .schedules import Schedule
25
25
  from .wagecomponents import EmployeeFixedWageComponents, EmployeeVariableWageComponents
26
+ import os
26
27
 
27
28
 
28
29
  class Nmbrs(BrynQ):
29
- def __init__(self, label: Union[str, List], debug: bool = False, mock_mode: bool = True):
30
+ def __init__(self, system_type: Optional[Literal['source', 'target']] = None, debug: bool = False, mock_mode: bool = True):
30
31
  """
31
32
  Initialize the Nmbrs class.
32
33
 
@@ -38,10 +39,11 @@ class Nmbrs(BrynQ):
38
39
  self.mock_mode = mock_mode
39
40
  self.debug = debug
40
41
  self.timeout = 3600
42
+ self.system_type = system_type
41
43
  if mock_mode is False:
42
44
  super().__init__()
43
- self.label = label
44
- headers = self._get_request_headers(label=label)
45
+ self.data_interface_id = os.getenv("DATA_INTERFACE_ID")
46
+ headers = self._get_request_headers()
45
47
  self.base_url = "https://api.nmbrsapp.com/api/"
46
48
  self.session = requests.Session()
47
49
  self.session.headers.update(headers)
@@ -64,7 +66,7 @@ class Nmbrs(BrynQ):
64
66
  self.companies = Companies(self)
65
67
  self.contract = Contract(self)
66
68
  self.department = EmployeeDepartment(self)
67
- self.company_ids = self.companies.get()['company_id']
69
+ self.company_ids = self.companies.get()['companyId']
68
70
  self.soap_company_ids = self.companies.get_soap_ids()
69
71
  self.employees = Employees(self)
70
72
  self.employment = Employment(self)
@@ -80,14 +82,13 @@ class Nmbrs(BrynQ):
80
82
  self.salary_scales = SalaryScales(self)
81
83
  self.salary_steps = SalarySteps(self)
82
84
 
83
- def _get_request_headers(self, label):
84
- initial_credentials = self.get_system_credential(system='nmbrs', label=label)
85
- credentials = self.refresh_system_credential(system='nmbrs', system_id=initial_credentials['id'])
85
+ def _get_request_headers(self):
86
+ credentials = self.interfaces.credentials.get(system='nmbrs', system_type=self.system_type)
86
87
  headers = {
87
88
  "accept": "application/json",
88
- "Authorization": f"Bearer {credentials['access_token']}",
89
+ "Authorization": f"Bearer {credentials.get('data').get('access_token')}",
89
90
  # partner identifier
90
- "X-Subscription-Key": initial_credentials.get("config").get("subscription_key")
91
+ "X-Subscription-Key": credentials.get("custom_data").get("subscription_key")
91
92
  }
92
93
 
93
94
  return headers
@@ -99,7 +100,7 @@ class Nmbrs(BrynQ):
99
100
  Returns:
100
101
  AuthHeaderWithDomainType: The authentication header for SOAP requests
101
102
  """
102
- initial_credentials = self.get_system_credential(system='nmbrs', label=self.label)
103
+ initial_credentials = self.get_system_credential(system='nmbrs', label='bob')
103
104
  config = initial_credentials.get("config", {})
104
105
 
105
106
  # Get the AuthHeaderWithDomain type from the WSDL
@@ -120,7 +121,7 @@ class Nmbrs(BrynQ):
120
121
  while has_next_page:
121
122
  prepped = request.prepare()
122
123
  prepped.headers.update(self.session.headers)
123
- resp = self.session.send(prepped, timeout=self.nmbrs.timeout)
124
+ resp = self.session.send(prepped, timeout=self.timeout)
124
125
  resp.raise_for_status()
125
126
  response_data = resp.json()
126
127
  result_data += response_data['data']
@@ -25,6 +25,7 @@ class Companies:
25
25
  url=f"{self.nmbrs.base_url}companies")
26
26
  data = self.nmbrs.get_paginated_result(request)
27
27
  df = pd.DataFrame(data)
28
+ # TODO: add validation for rename
28
29
 
29
30
  return df
30
31
 
@@ -104,29 +104,6 @@ class EmployeeCostcenter:
104
104
  )
105
105
  return resp
106
106
 
107
- def delete(self, employee_id: str, employee_cost_center_id: str):
108
- """
109
- Delete a costcenter for an employee.
110
-
111
- Args:
112
- employee_id: The ID of the employee
113
- employee_cost_center_id: The ID of the costcenter to delete
114
-
115
- Returns:
116
- Response from the API
117
- """
118
- # Create and validate a EmployeeCostcenterDelete model
119
- costcenter_model = EmployeeCostcenterDelete(employeeCostCenterId=employee_cost_center_id)
120
-
121
- if self.nmbrs.mock_mode:
122
- return costcenter_model
123
-
124
- # Send request
125
- resp = self.nmbrs.session.delete(
126
- url=f"{self.nmbrs.base_url}employees/{employee_id}/costcenters/{employee_cost_center_id}",
127
- timeout=self.nmbrs.timeout
128
- )
129
- return resp
130
107
 
131
108
 
132
109
  class Costcenter:
@@ -208,27 +185,3 @@ class Costcenter:
208
185
  timeout=self.nmbrs.timeout
209
186
  )
210
187
  return resp
211
-
212
- def delete(self, company_id: str, cost_center_id: str):
213
- """
214
- Delete a costcenter.
215
-
216
- Args:
217
- company_id: The ID of the company
218
- cost_center_id: The ID of the costcenter to delete
219
-
220
- Returns:
221
- Response from the API
222
- """
223
- # Create and validate a CostcenterDelete model
224
- costcenter_model = CostcenterDelete(costCenterId=cost_center_id)
225
-
226
- if self.nmbrs.mock_mode:
227
- return costcenter_model
228
-
229
- # Send request
230
- resp = self.nmbrs.session.delete(
231
- url=f"{self.nmbrs.base_url}companies/{company_id}/costcenters/{cost_center_id}",
232
- timeout=self.nmbrs.timeout
233
- )
234
- return resp
@@ -28,28 +28,28 @@ class Costunit:
28
28
  df = pd.DataFrame(data)
29
29
 
30
30
  return df
31
-
31
+
32
32
  def create(self, company_id: str, data: Dict[str, Any]):
33
33
  """
34
34
  Create a new costunit using Pydantic validation.
35
-
35
+
36
36
  Args:
37
37
  company_id: The ID of the company
38
38
  data: Dictionary containing costunit data with fields matching
39
39
  the CostunitCreate schema (using camelCase field names)
40
-
40
+
41
41
  Returns:
42
42
  Response from the API
43
43
  """
44
44
  # Validate with Pydantic model - this will raise an error if required fields are missing
45
45
  costunit_model = CostunitCreate(**data)
46
-
46
+
47
47
  if self.nmbrs.mock_mode:
48
48
  return costunit_model
49
-
49
+
50
50
  # Convert validated model to dict for API payload
51
51
  payload = costunit_model.dict(exclude_none=True)
52
-
52
+
53
53
  # Send request
54
54
  resp = self.nmbrs.session.post(
55
55
  url=f"{self.nmbrs.base_url}companies/{company_id}/costunit",
@@ -61,24 +61,24 @@ class Costunit:
61
61
  def update(self, company_id: str, data: Dict[str, Any]):
62
62
  """
63
63
  Update a costunit using Pydantic validation.
64
-
64
+
65
65
  Args:
66
66
  company_id: The ID of the company
67
67
  data: Dictionary containing costunit data with fields matching
68
68
  the CostunitUpdate schema (using camelCase field names)
69
-
69
+
70
70
  Returns:
71
71
  Response from the API
72
72
  """
73
73
  # Validate with Pydantic model - this will raise an error if required fields are missing
74
74
  costunit_model = CostunitUpdate(**data)
75
-
75
+
76
76
  if self.nmbrs.mock_mode:
77
77
  return costunit_model
78
-
78
+
79
79
  # Convert validated model to dict for API payload
80
80
  payload = costunit_model.dict(exclude_none=True)
81
-
81
+
82
82
  # Send request
83
83
  resp = self.nmbrs.session.put(
84
84
  url=f"{self.nmbrs.base_url}companies/{company_id}/costunit",
@@ -86,27 +86,3 @@ class Costunit:
86
86
  timeout=self.nmbrs.timeout
87
87
  )
88
88
  return resp
89
-
90
- def delete(self, company_id: str, cost_unit_id: str):
91
- """
92
- Delete a costunit.
93
-
94
- Args:
95
- company_id: The ID of the company
96
- cost_unit_id: The ID of the costunit to delete
97
-
98
- Returns:
99
- Response from the API
100
- """
101
- # Create and validate a CostunitDelete model
102
- costunit_model = CostunitDelete(costUnitId=cost_unit_id)
103
-
104
- if self.nmbrs.mock_mode:
105
- return costunit_model
106
-
107
- # Send request
108
- resp = self.nmbrs.session.delete(
109
- url=f"{self.nmbrs.base_url}companies/{company_id}/costunits/{cost_unit_id}",
110
- timeout=self.nmbrs.timeout
111
- )
112
- return resp
@@ -1,6 +1,7 @@
1
1
  import pandas as pd
2
2
  import requests
3
- from .costcenter import Costcenter, Costunit
3
+ from .costcenter import Costcenter
4
+ from .costunit import Costunit
4
5
  from .department import Departments
5
6
  from .hours import Hours
6
7
  from .bank import Bank
@@ -101,29 +101,6 @@ class EmployeeDepartment:
101
101
  )
102
102
  return resp
103
103
 
104
- def delete(self, employee_id: str, department_id: str):
105
- """
106
- Delete a department assignment for an employee.
107
-
108
- Args:
109
- employee_id: The ID of the employee
110
- department_id: The ID of the department to delete
111
-
112
- Returns:
113
- Response from the API
114
- """
115
- # Create and validate a DepartmentDelete model
116
- department_model = DepartmentDelete(departmentId=department_id)
117
-
118
- if self.nmbrs.mock_mode:
119
- return department_model
120
-
121
- # Send request
122
- resp = self.nmbrs.session.delete(
123
- url=f"{self.nmbrs.base_url}employees/{employee_id}/departments/{department_id}",
124
- timeout=self.nmbrs.timeout
125
- )
126
-
127
104
 
128
105
 
129
106
  class Departments:
@@ -138,4 +115,4 @@ class Departments:
138
115
  data = self.nmbrs.get_paginated_result(request)
139
116
  df = pd.DataFrame(data)
140
117
 
141
- return df
118
+ return df
@@ -1,5 +1,7 @@
1
1
  import pandas as pd
2
2
  import requests
3
+ from pydantic import BaseModel
4
+
3
5
  from brynq_sdk_functions import Functions
4
6
  from typing import Dict, Any, Optional
5
7
 
@@ -87,7 +89,20 @@ class Employees:
87
89
  Response from the API
88
90
  """
89
91
  # Validate with Pydantic model
90
- employee_model = EmployeeCreate(**data)
92
+ def nest_dict(flat_dict, model):
93
+ nested = {}
94
+ for name, field in model.model_fields.items():
95
+ key_in_input = name # Original model field name as key in flat_dict
96
+ alias = field.alias or name
97
+ if isinstance(field.annotation, type) and issubclass(field.annotation, BaseModel):
98
+ nested[alias] = nest_dict(flat_dict, field.annotation)
99
+ else:
100
+ if key_in_input in flat_dict:
101
+ nested[alias] = flat_dict[key_in_input]
102
+ return nested
103
+
104
+ nested_data = nest_dict(data, EmployeeCreate)
105
+ employee_model = EmployeeCreate(**nested_data)
91
106
 
92
107
  if self.nmbrs.mock_mode:
93
108
  return employee_model
@@ -144,26 +159,3 @@ class Employees:
144
159
  )
145
160
 
146
161
  return resp
147
-
148
- def delete(self, employee_id: str):
149
- """
150
- Delete an employee.
151
-
152
- Args:
153
- employee_id: The ID of the employee to delete
154
-
155
- Returns:
156
- Response from the API
157
- """
158
- # Create and validate an EmployeeDelete model
159
- employee_model = EmployeeDelete(employeeId=employee_id)
160
-
161
- if self.nmbrs.mock_mode:
162
- return employee_model
163
-
164
- # Send request
165
- resp = self.nmbrs.session.delete(
166
- url=f"{self.nmbrs.base_url}employees/{employee_id}",
167
- timeout=self.nmbrs.timeout
168
- )
169
- return resp
@@ -103,27 +103,3 @@ class Employment:
103
103
  timeout=self.nmbrs.timeout
104
104
  )
105
105
  return resp
106
-
107
- def delete(self, employee_id: str, employment_id: str):
108
- """
109
- Delete an employment record for an employee.
110
-
111
- Args:
112
- employee_id: The ID of the employee
113
- employment_id: The ID of the employment record to delete
114
-
115
- Returns:
116
- Response from the API
117
- """
118
- # Create and validate an EmploymentDelete model
119
- employment_model = EmploymentDelete(employmentId=employment_id)
120
-
121
- if self.nmbrs.mock_mode:
122
- return employment_model
123
-
124
- # Send request
125
- resp = self.nmbrs.session.delete(
126
- url=f"{self.nmbrs.base_url}employees/{employee_id}/employments/{employment_id}",
127
- timeout=self.nmbrs.timeout
128
- )
129
- return resp
@@ -96,29 +96,6 @@ class EmployeeFunction:
96
96
  )
97
97
  return resp
98
98
 
99
- def delete(self, employee_id: str, function_id: str):
100
- """
101
- Delete a function for an employee.
102
-
103
- Args:
104
- employee_id: The ID of the employee
105
- function_id: The ID of the function to delete
106
-
107
- Returns:
108
- Response from the API
109
- """
110
- # Create and validate a FunctionDelete model
111
- function_model = FunctionDelete(functionId=function_id)
112
-
113
- if self.nmbrs.mock_mode:
114
- return function_model
115
-
116
- # Send request
117
- resp = self.nmbrs.session.delete(
118
- url=f"{self.nmbrs.base_url}employees/{employee_id}/functions/{function_id}",
119
- timeout=self.nmbrs.timeout
120
- )
121
- return resp
122
99
 
123
100
 
124
101
  class Functions:
@@ -135,4 +112,4 @@ class Functions:
135
112
  except requests.HTTPError as e:
136
113
  df = pd.DataFrame()
137
114
 
138
- return df
115
+ return df
@@ -56,24 +56,24 @@ class Salaries:
56
56
  def create(self, employee_id: str, data: Dict[str, Any]):
57
57
  """
58
58
  Create a new salary for an employee using Pydantic validation.
59
-
59
+
60
60
  Args:
61
61
  employee_id: The ID of the employee
62
62
  data: Dictionary containing salary data with fields matching
63
63
  the SalaryCreate schema (using camelCase field names)
64
-
64
+
65
65
  Returns:
66
66
  Response from the API
67
67
  """
68
68
  # Validate with Pydantic model
69
69
  salary_model = SalaryCreate(**data)
70
-
70
+
71
71
  if self.nmbrs.mock_mode:
72
72
  return salary_model
73
-
73
+
74
74
  # Convert validated model to dict for API payload
75
75
  payload = salary_model.dict(exclude_none=True)
76
-
76
+
77
77
  # Send request
78
78
  resp = self.nmbrs.session.post(
79
79
  url=f"{self.nmbrs.base_url}employees/{employee_id}/salary",
@@ -85,24 +85,24 @@ class Salaries:
85
85
  def update(self, employee_id: str, data: Dict[str, Any]):
86
86
  """
87
87
  Update a salary for an employee using Pydantic validation.
88
-
88
+
89
89
  Args:
90
90
  employee_id: The ID of the employee
91
91
  data: Dictionary containing salary data with fields matching
92
92
  the SalaryUpdate schema (using camelCase field names)
93
-
93
+
94
94
  Returns:
95
95
  Response from the API
96
96
  """
97
97
  # Validate with Pydantic model
98
98
  salary_model = SalaryUpdate(**data)
99
-
99
+
100
100
  if self.nmbrs.mock_mode:
101
101
  return salary_model
102
-
102
+
103
103
  # Convert validated model to dict for API payload
104
104
  payload = salary_model.dict(exclude_none=True)
105
-
105
+
106
106
  # Send request
107
107
  resp = self.nmbrs.session.put(
108
108
  url=f"{self.nmbrs.base_url}employees/{employee_id}/salary",
@@ -110,27 +110,3 @@ class Salaries:
110
110
  timeout=self.nmbrs.timeout
111
111
  )
112
112
  return resp
113
-
114
- def delete(self, employee_id: str, salary_id: str):
115
- """
116
- Delete a salary for an employee.
117
-
118
- Args:
119
- employee_id: The ID of the employee
120
- salary_id: The ID of the salary to delete
121
-
122
- Returns:
123
- Response from the API
124
- """
125
- # Create and validate a SalaryDelete model
126
- salary_model = SalaryDelete(salaryId=salary_id)
127
-
128
- if self.nmbrs.mock_mode:
129
- return salary_model
130
-
131
- # Send request
132
- resp = self.nmbrs.session.delete(
133
- url=f"{self.nmbrs.base_url}employees/{employee_id}/salaries/{salary_id}",
134
- timeout=self.nmbrs.timeout
135
- )
136
- return resp
@@ -49,34 +49,34 @@ class Schedule:
49
49
  data: Dict[str, Any]):
50
50
  """
51
51
  Create a new schedule for an employee using Pydantic validation
52
-
52
+
53
53
  Args:
54
54
  employee_id: The employee ID
55
55
  data: Schedule data dictionary with the following keys:
56
56
  - start_date_schedule: Start date of the schedule
57
57
  - weekly_hours: Hours per week (optional)
58
58
  - hours_monday, hours_tuesday, etc.: Hours for each day
59
-
59
+
60
60
  Returns:
61
61
  Response from the API
62
62
  """
63
63
  # Transform data to match schema
64
64
  schedule_data = {}
65
-
65
+
66
66
  # Required field
67
67
  if "start_date_schedule" in data:
68
68
  schedule_data["startDate"] = data["start_date_schedule"]
69
-
69
+
70
70
  # Optional field
71
71
  if "weekly_hours" in data:
72
72
  # Handle NaN values
73
73
  if not isinstance(data["weekly_hours"], float) or not math.isnan(data["weekly_hours"]):
74
74
  schedule_data["hoursPerWeek"] = data["weekly_hours"]
75
-
75
+
76
76
  # Create week1 and week2 data
77
77
  week1_data = {}
78
78
  week2_data = {}
79
-
79
+
80
80
  day_mapping = {
81
81
  "hours_monday": "hoursMonday",
82
82
  "hours_tuesday": "hoursTuesday",
@@ -86,7 +86,7 @@ class Schedule:
86
86
  "hours_saturday": "hoursSaturday",
87
87
  "hours_sunday": "hoursSunday"
88
88
  }
89
-
89
+
90
90
  # Populate week1 data
91
91
  for day, api_day in day_mapping.items():
92
92
  if day in data and (not isinstance(data[day], float) or not math.isnan(data[day])):
@@ -94,20 +94,20 @@ class Schedule:
94
94
  else:
95
95
  # Default to 0 hours if not specified
96
96
  week1_data[api_day] = 0.0
97
-
97
+
98
98
  # For now, set week2 same as week1 (can be adjusted if needed)
99
99
  week2_data = week1_data.copy()
100
-
100
+
101
101
  schedule_data["week1"] = week1_data
102
102
  schedule_data["week2"] = week2_data
103
-
103
+
104
104
  # Validate with Pydantic schema
105
105
  try:
106
106
  validated_data = ScheduleCreate(**schedule_data)
107
-
107
+
108
108
  if self.nmbrs.mock_mode:
109
109
  return validated_data
110
-
110
+
111
111
  # Use the validated data for the API call
112
112
  resp = self.nmbrs.session.post(
113
113
  url=f"{self.nmbrs.base_url}employees/{employee_id}/schedule",
@@ -115,31 +115,31 @@ class Schedule:
115
115
  timeout=self.nmbrs.timeout
116
116
  )
117
117
  return resp
118
-
118
+
119
119
  except Exception as e:
120
120
  raise ValueError(f"Schedule validation failed: {str(e)}")
121
121
 
122
122
  def update(self, employee_id: str, data: Dict[str, Any]):
123
123
  """
124
124
  Update a schedule for an employee using Pydantic validation.
125
-
125
+
126
126
  Args:
127
127
  employee_id: The ID of the employee
128
128
  data: Dictionary containing schedule data with fields matching
129
129
  the ScheduleUpdate schema (using camelCase field names)
130
-
130
+
131
131
  Returns:
132
132
  Response from the API
133
133
  """
134
134
  # Validate with Pydantic model - this will raise an error if required fields are missing
135
135
  schedule_model = ScheduleUpdate(**data)
136
-
136
+
137
137
  if self.nmbrs.mock_mode:
138
138
  return schedule_model
139
-
139
+
140
140
  # Convert validated model to dict for API payload
141
141
  payload = schedule_model.dict(exclude_none=True)
142
-
142
+
143
143
  # Send request
144
144
  resp = self.nmbrs.session.put(
145
145
  url=f"{self.nmbrs.base_url}employees/{employee_id}/schedule",
@@ -147,27 +147,3 @@ class Schedule:
147
147
  timeout=self.nmbrs.timeout
148
148
  )
149
149
  return resp
150
-
151
- def delete(self, employee_id: str, schedule_id: str):
152
- """
153
- Delete a schedule for an employee.
154
-
155
- Args:
156
- employee_id: The ID of the employee
157
- schedule_id: The ID of the schedule to delete
158
-
159
- Returns:
160
- Response from the API
161
- """
162
- # Create and validate a ScheduleDelete model
163
- schedule_model = ScheduleDelete(scheduleId=schedule_id)
164
-
165
- if self.nmbrs.mock_mode:
166
- return schedule_model
167
-
168
- # Send request
169
- resp = self.nmbrs.session.delete(
170
- url=f"{self.nmbrs.base_url}employees/{employee_id}/schedules/{schedule_id}",
171
- timeout=self.nmbrs.timeout
172
- )
173
- return resp
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: brynq-sdk-nmbrs
3
- Version: 1.3.2
3
+ Version: 2.0.0
4
4
  Summary: Nmbrs wrapper from BrynQ
5
5
  Home-page: UNKNOWN
6
6
  Author: BrynQ
@@ -1,4 +1,4 @@
1
- brynq-sdk-brynq>=2
1
+ brynq-sdk-brynq<5,>=4
2
2
  pandas<3.0.0,>=2.2.0
3
3
  pydantic<3.0.0,>=2.5.0
4
4
  pandera<1.0.0,>=0.16.0
@@ -2,7 +2,7 @@ from setuptools import setup, find_namespace_packages
2
2
 
3
3
  setup(
4
4
  name='brynq_sdk_nmbrs',
5
- version='1.3.2',
5
+ version='2.0.0',
6
6
  description='Nmbrs wrapper from BrynQ',
7
7
  long_description='Nmbrs 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
  'pydantic>=2.5.0,<3.0.0',
16
16
  'pandera>=0.16.0,<1.0.0',