mbu-dev-shared-components 4.0.3__tar.gz → 4.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 (60) hide show
  1. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/PKG-INFO +4 -1
  2. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/database/utility.py +30 -15
  3. mbu_dev_shared_components-4.2.0/mbu_dev_shared_components/solteqtand/application/aftalebog.py +209 -0
  4. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/app_handler.py +20 -20
  5. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components.egg-info/PKG-INFO +4 -1
  6. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components.egg-info/SOURCES.txt +1 -0
  7. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components.egg-info/requires.txt +3 -0
  8. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/pyproject.toml +4 -1
  9. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/LICENSE +0 -0
  10. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/README.md +0 -0
  11. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/database/__init__.py +0 -0
  12. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/database/connection.py +0 -0
  13. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/database/constants.py +0 -0
  14. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/database/logging.py +0 -0
  15. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/getorganized/__init__.py +0 -0
  16. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/getorganized/auth.py +0 -0
  17. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/getorganized/cases.py +0 -0
  18. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/getorganized/contacts.py +0 -0
  19. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/getorganized/documents.py +0 -0
  20. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/getorganized/objects.py +0 -0
  21. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/google/__init__.py +0 -0
  22. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/google/api/__init__.py +0 -0
  23. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/google/api/auth.py +0 -0
  24. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/google/workspace/__init__.py +0 -0
  25. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/google/workspace/alerts.py +0 -0
  26. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/msoffice365/__init__.py +0 -0
  27. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/msoffice365/excel/__init__.py +0 -0
  28. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/msoffice365/excel/excel_reader.py +0 -0
  29. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/msoffice365/sharepoint_api/__init__.py +0 -0
  30. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/msoffice365/sharepoint_api/files.py +0 -0
  31. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/os2forms/__init__.py +0 -0
  32. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/os2forms/documents.py +0 -0
  33. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/os2forms/forms.py +0 -0
  34. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/romexis/__init__.py +0 -0
  35. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/romexis/db_handler.py +0 -0
  36. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/romexis/helper_functions.py +0 -0
  37. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/sap/__init__.py +0 -0
  38. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/sap/create_invoice.py +0 -0
  39. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/__init__.py +0 -0
  40. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/__init__.py +0 -0
  41. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/appointment.py +0 -0
  42. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/base_ui.py +0 -0
  43. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/clinic.py +0 -0
  44. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/document.py +0 -0
  45. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/edi_portal.py +0 -0
  46. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/event.py +0 -0
  47. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/exceptions.py +0 -0
  48. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/handler_base.py +0 -0
  49. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/journal_note.py +0 -0
  50. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/application/patient.py +0 -0
  51. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/database/__init__.py +0 -0
  52. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/solteqtand/database/db_handler.py +0 -0
  53. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/utils/__init__.py +0 -0
  54. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/utils/db_stored_procedure_executor.py +0 -0
  55. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/utils/fernet_encryptor.py +0 -0
  56. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/utils/file_handler.py +0 -0
  57. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components/utils/json_handler.py +0 -0
  58. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components.egg-info/dependency_links.txt +0 -0
  59. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/mbu_dev_shared_components.egg-info/top_level.txt +0 -0
  60. {mbu_dev_shared_components-4.0.3 → mbu_dev_shared_components-4.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mbu_dev_shared_components
3
- Version: 4.0.3
3
+ Version: 4.2.0
4
4
  Summary: Shared components to use in RPA projects
5
5
  Author-email: MBU <rpa@mbu.aarhus.dk>
6
6
  License-Expression: MIT
@@ -12,6 +12,7 @@ License-File: LICENSE
12
12
  Requires-Dist: cryptography>=43.0.0
13
13
  Requires-Dist: pyodbc>=5.1.0
14
14
  Requires-Dist: python-dateutil==2.9.*
15
+ Requires-Dist: dotenv
15
16
  Provides-Extra: getorganized
16
17
  Requires-Dist: requests_ntlm>=1.2.0; extra == "getorganized"
17
18
  Provides-Extra: google
@@ -31,6 +32,8 @@ Provides-Extra: sap
31
32
  Provides-Extra: solteqtand
32
33
  Requires-Dist: uiautomation; extra == "solteqtand"
33
34
  Requires-Dist: pyodbc>=5.1.0; extra == "solteqtand"
35
+ Requires-Dist: psutil; extra == "solteqtand"
36
+ Requires-Dist: docx2pdf; extra == "solteqtand"
34
37
  Provides-Extra: utils
35
38
  Requires-Dist: python-dateutil==2.9.*; extra == "utils"
36
39
  Requires-Dist: cryptography>=43.0.0; extra == "utils"
@@ -1,15 +1,17 @@
1
1
  """This module handles general database connection and calls"""
2
2
 
3
- import os
4
3
  import json
5
- from typing import Dict, Union, Tuple, Any
6
- from dateutil import parser
4
+ import os
5
+ from typing import Any, Dict, Tuple, Union
6
+
7
7
  import pyodbc
8
- from dotenv import load_dotenv
8
+ from dateutil import parser
9
+ from dotenv import load_dotenv
9
10
 
10
11
 
11
12
  class Utility:
12
13
  """Base class handling general utilities"""
14
+
13
15
  def connect_to_db(self, autocommit=True, db_env="PROD") -> pyodbc.Connection:
14
16
  """Establish connection to sql database
15
17
 
@@ -22,17 +24,24 @@ class Utility:
22
24
  rpa_conn = pyodbc.connect(rpa_conn_string, autocommit=autocommit)
23
25
  return rpa_conn
24
26
 
25
- def execute_query(self, query: str, params: list = None) -> pyodbc.Cursor:
27
+ def execute_query(
28
+ self, query: str, params: list = None, return_dict: bool = False
29
+ ) -> list | None:
26
30
  """Execute SQL query with pyodbc"""
27
31
  params = [] if not params else params
28
- is_select = query.strip().upper().startswith('SELECT')
32
+ is_select = query.strip().upper().startswith("SELECT")
29
33
  try:
30
34
  res = self.cursor.execute(query, params)
31
35
  if is_select:
32
- res = self.cursor.fetchall()
33
- if len(res) == 0:
36
+ rows = self.cursor.fetchall()
37
+ if len(rows) == 0:
34
38
  print("No results from query")
35
39
  return None
40
+ if return_dict:
41
+ columns = [column[0] for column in self.cursor.description]
42
+ res = [dict(zip(columns, row)) for row in rows]
43
+ else:
44
+ res = rows
36
45
  return res
37
46
  else:
38
47
  return None
@@ -44,15 +53,19 @@ class Utility:
44
53
  def fetch_env(self, db_env):
45
54
  """Get env variable based on context, PROD or TEST"""
46
55
  if db_env.upper() == "PROD":
47
- connection_env = "DBCONNECTIONSTRINGPROD"
56
+ connection_env = "DBCONNECTIONSTRINGPROD"
48
57
  return connection_env
49
58
  if db_env.upper() == "TEST":
50
- connection_env = "DBCONNECTIONSTRINGDEV"
59
+ connection_env = "DBCONNECTIONSTRINGDEV"
51
60
  return connection_env
52
61
 
53
- raise ValueError(f"arg db_env is {db_env.upper()} but should be 'PROD' or 'TEST'")
62
+ raise ValueError(
63
+ f"arg db_env is {db_env.upper()} but should be 'PROD' or 'TEST'"
64
+ )
54
65
 
55
- def execute_stored_procedure(self, stored_procedure: str, params: Dict[str, Tuple[type, Any]] | None = None) -> Dict[str, Union[bool, str, Any]]:
66
+ def execute_stored_procedure(
67
+ self, stored_procedure: str, params: Dict[str, Tuple[type, Any]] | None = None
68
+ ) -> Dict[str, Union[bool, str, Any]]:
56
69
  """
57
70
  Executes a stored procedure with the given parameters.
58
71
 
@@ -76,12 +89,12 @@ class Utility:
76
89
  "int": int,
77
90
  "float": float,
78
91
  "datetime": parser.isoparse,
79
- "json": lambda x: json.dumps(x, ensure_ascii=False)
92
+ "json": lambda x: json.dumps(x, ensure_ascii=False),
80
93
  }
81
94
 
82
95
  try:
83
96
  if params:
84
- param_placeholders = ', '.join([f"@{key} = ?" for key in params.keys()])
97
+ param_placeholders = ", ".join([f"@{key} = ?" for key in params.keys()])
85
98
  param_values = []
86
99
 
87
100
  for key, value in params.items():
@@ -92,7 +105,9 @@ class Utility:
92
105
  else:
93
106
  param_values.append(actual_value)
94
107
  else:
95
- raise ValueError("Each parameter value must be a tuple of (type, actual_value).")
108
+ raise ValueError(
109
+ "Each parameter value must be a tuple of (type, actual_value)."
110
+ )
96
111
 
97
112
  sql = f"EXEC {stored_procedure} {param_placeholders}"
98
113
  rows_updated = self.cursor.execute(sql, tuple(param_values))
@@ -0,0 +1,209 @@
1
+ from datetime import datetime
2
+
3
+ import uiautomation as auto
4
+
5
+ from .handler_base import HandlerBase
6
+
7
+
8
+ class AftalebogHandler(HandlerBase):
9
+ """Functions within aftalebog"""
10
+
11
+ def get_appointments_aftalebog(
12
+ self, close_after: bool = False, headers_to_keep: list | None = None
13
+ ) -> dict:
14
+ """Function to retrive data on appointments in view in aftalebog"""
15
+
16
+ # Get list control
17
+ list_box = self.wait_for_control(
18
+ control_type=auto.GroupControl,
19
+ search_params={"AutomationId": "GroupBoxView"},
20
+ search_depth=5,
21
+ )
22
+
23
+ appointment_list = self.find_element_by_property(
24
+ control=list_box, control_type=50008
25
+ )
26
+
27
+ # Extract headers
28
+ appointment_headers = [
29
+ header.Name
30
+ for header in appointment_list.GetFirstChildControl().GetChildren()
31
+ ]
32
+
33
+ # Extract ListItem controls
34
+ appointment_ctrls = [
35
+ ctrl for ctrl in appointment_list.GetChildren() if ctrl.ControlType == 50007
36
+ ]
37
+
38
+ # Package data in dictionary
39
+ # Keep only selected headers if any selected.
40
+ if not headers_to_keep:
41
+ headers_to_keep = appointment_headers
42
+
43
+ appointment_data = {
44
+ j: {
45
+ k: v.Name
46
+ for k, v in zip(appointment_headers, ctrl.GetChildren())
47
+ if k in headers_to_keep
48
+ }
49
+ for j, ctrl in enumerate(appointment_ctrls)
50
+ }
51
+
52
+ if close_after:
53
+ # Should maybe be in a method of its own?
54
+ list_box.SendKeys("{Control}{F4}")
55
+ self.wait_for_control_to_disappear(
56
+ control_type=auto.WindowControl,
57
+ search_params={"AutomationId": "FormBooking"},
58
+ )
59
+
60
+ return appointment_data
61
+
62
+ def set_date_in_aftalebog(self, from_date: datetime, to_date: datetime) -> None:
63
+ """Set to and from dates in aftalebog oversigt"""
64
+ import locale
65
+
66
+ dt_picker_from = self.wait_for_control(
67
+ control_type=auto.PaneControl,
68
+ search_params={"AutomationId": "DateTimePickerFromDate"},
69
+ search_depth=7,
70
+ )
71
+
72
+ from_keys = (
73
+ f"{from_date.day}"
74
+ + "{right}"
75
+ + f"{from_date.month}"
76
+ + "{right}"
77
+ + f"{from_date.year}"
78
+ )
79
+
80
+ dt_picker_from.SendKeys(from_keys)
81
+
82
+ try:
83
+ from_date.strftime(format="%d. %B %Y") == dt_picker_from.Name
84
+ except Exception:
85
+ # Should maybe try a number of times until it hits right or ends in systemerror
86
+ # End with raise error where resulting dates are printed
87
+ print("Dates after insert not matching input")
88
+ print(
89
+ (
90
+ f"'From' input: {from_date.strftime(format='%d. %B %Y')} "
91
+ + f"Current value: {dt_picker_from.Name}"
92
+ )
93
+ )
94
+
95
+ dt_picker_to = self.wait_for_control(
96
+ control_type=auto.PaneControl,
97
+ search_params={"AutomationId": "DateTimePickerToDate"},
98
+ search_depth=7,
99
+ )
100
+
101
+ to_keys = (
102
+ f"{to_date.day}"
103
+ + "{right}"
104
+ + f"{to_date.month}"
105
+ + "{right}"
106
+ + f"{to_date.year}"
107
+ )
108
+
109
+ dt_picker_to.SendKeys(to_keys)
110
+
111
+ locale.setlocale(locale.LC_TIME, "da_dk.utf-8")
112
+
113
+ try:
114
+ to_date.strftime(format="%d. %B %Y") == dt_picker_to.Name
115
+ except Exception:
116
+ print("Dates after insert not matching input")
117
+ print(
118
+ (
119
+ f"'To' input: {to_date.strftime(format='%d. %B %Y')} "
120
+ + f"Current value: {dt_picker_to.Name}"
121
+ )
122
+ )
123
+
124
+ def pick_appointment_types_aftalebog(self, appointment_types: str | list):
125
+ """Set one or more appointment types in aftalebog oversigt"""
126
+
127
+ if isinstance(appointment_types, str):
128
+ appointment_types = [appointment_types]
129
+
130
+ # deselect all
131
+ slct_none = self.wait_for_control(
132
+ control_type=auto.PaneControl,
133
+ search_params={"AutomationId": "ButtonToggleStatusList"},
134
+ search_depth=7,
135
+ )
136
+ slct_none.SetFocus()
137
+ # If possible to select none click once, otherwise click twice
138
+ try:
139
+ assert slct_none.Name == "Vælge ingen"
140
+ slct_none.SendKeys("{Enter}")
141
+ except AssertionError:
142
+ slct_none.SendKeys("{Enter}{Enter}")
143
+
144
+ # Getting status controls
145
+ status_list = self.wait_for_control(
146
+ control_type=auto.ListControl,
147
+ search_params={"AutomationId": "CheckedListBoxStatus"},
148
+ search_depth=7,
149
+ )
150
+ status_ctrls = [
151
+ _child
152
+ for _child in status_list.GetChildren()
153
+ if _child.ControlType == 50002
154
+ ]
155
+ status_names = [
156
+ _child.Name
157
+ for _child in status_list.GetChildren()
158
+ if _child.ControlType == 50002
159
+ ]
160
+
161
+ # Toggle all selected appointment types
162
+ for a_type in appointment_types:
163
+ slct_idx = status_names.index(a_type)
164
+ status_ctrls[slct_idx].GetTogglePattern().Toggle()
165
+
166
+ def pick_clinic_aftalebog(self, clinic: str):
167
+ """Set clinic in aftalebog oversigt"""
168
+
169
+ ## UNFINISHED
170
+ # Press clinic button
171
+ clinic_button = self.wait_for_control(
172
+ control_type=auto.PaneControl,
173
+ search_params={"AutomationId": "ButtonClinic"},
174
+ search_depth=8,
175
+ )
176
+ clinic_button.SetFocus()
177
+ clinic_button.SendKeys("{Enter}")
178
+
179
+ # Wait for popup window
180
+ find_clinic = self.wait_for_control(
181
+ control_type=auto.WindowControl,
182
+ search_params={"AutomationId": "FormFindClinics"},
183
+ search_depth=2,
184
+ )
185
+ # Get list and select clinic
186
+ clinic_list = self.find_element_by_property(
187
+ control=find_clinic, automation_id="ListClinics"
188
+ )
189
+ clinic_ctrls = [
190
+ _child
191
+ for _child in clinic_list.GetChildren()
192
+ if _child.ControlType == 50007
193
+ ]
194
+ clinic_names = [
195
+ _child.Name
196
+ for _child in clinic_list.GetChildren()
197
+ if _child.ControlType == 50007
198
+ ]
199
+ try:
200
+ slct_idx = clinic_names.index(clinic)
201
+ except Exception as e:
202
+ print(e)
203
+ print(f"Chosen clinic: {clinic}")
204
+ print("Possibilities: ")
205
+ print(" \n".join(clinic_names[::-1]))
206
+ # Search for the clinic if it is in the list (to get in focus)
207
+ find_clinic.SendKeys(clinic)
208
+ clinic_ctrls[slct_idx].SetFocus()
209
+ clinic_ctrls[slct_idx].SendKeys("{Enter}")
@@ -1,15 +1,18 @@
1
1
  """This module provides the main application handler for Solteq Tand, integrating various components."""
2
+
2
3
  import os
4
+
3
5
  import uiautomation as auto
4
6
 
7
+ from .aftalebog import AftalebogHandler
8
+ from .appointment import AppointmentHandler
5
9
  from .base_ui import BaseUI
6
- from .patient import PatientHandler
10
+ from .clinic import ClinicHandler
7
11
  from .document import DocumentHandler
8
- from .appointment import AppointmentHandler
9
12
  from .edi_portal import EDIHandler
10
- from .clinic import ClinicHandler
11
13
  from .event import EventHandler
12
14
  from .journal_note import JournalNoteHandler
15
+ from .patient import PatientHandler
13
16
 
14
17
 
15
18
  class SolteqTandApp(
@@ -20,7 +23,8 @@ class SolteqTandApp(
20
23
  EDIHandler,
21
24
  ClinicHandler,
22
25
  EventHandler,
23
- JournalNoteHandler
26
+ JournalNoteHandler,
27
+ AftalebogHandler,
24
28
  ):
25
29
  """
26
30
  Main application handler for Solteq Tand, integrating various components.
@@ -62,9 +66,9 @@ class SolteqTandApp(
62
66
  """
63
67
  self.app_window = self.wait_for_control(
64
68
  auto.WindowControl,
65
- {'AutomationId': 'FormLogin'},
69
+ {"AutomationId": "FormLogin"},
66
70
  search_depth=3,
67
- timeout=60
71
+ timeout=60,
68
72
  )
69
73
  self.app_window.SetFocus()
70
74
 
@@ -76,13 +80,13 @@ class SolteqTandApp(
76
80
 
77
81
  login_button = self.app_window.PaneControl(AutomationId="ButtonLogin")
78
82
  login_button.SetFocus()
79
- login_button.SendKeys('{ENTER}')
83
+ login_button.SendKeys("{ENTER}")
80
84
 
81
85
  self.app_window = self.wait_for_control(
82
86
  auto.WindowControl,
83
- {'AutomationId': 'FormFront'},
87
+ {"AutomationId": "FormFront"},
84
88
  search_depth=2,
85
- timeout=60
89
+ timeout=60,
86
90
  )
87
91
 
88
92
  def open_sub_tab(self, sub_tab_name: str):
@@ -97,7 +101,7 @@ class SolteqTandApp(
97
101
 
98
102
  if not is_sub_tab_selected:
99
103
  sub_tab_button.SetFocus()
100
- sub_tab_button.SendKeys('{ENTER}')
104
+ sub_tab_button.SendKeys("{ENTER}")
101
105
 
102
106
  def open_tab(self, tab_name: str):
103
107
  """
@@ -122,13 +126,13 @@ class SolteqTandApp(
122
126
  tab_button = self.find_element_by_property(
123
127
  control=self.app_window,
124
128
  control_type=auto.ControlType.TabItemControl,
125
- name=tab_name_modified
129
+ name=tab_name_modified,
126
130
  )
127
131
  is_tab_selected = tab_button.GetPattern(10010).IsSelected
128
132
 
129
133
  if not is_tab_selected:
130
134
  tab_button.SetFocus()
131
- tab_button.SendKeys('{ENTER}')
135
+ tab_button.SendKeys("{ENTER}")
132
136
 
133
137
  def open_from_main_menu(self, menu_item: str) -> None:
134
138
  """
@@ -137,20 +141,16 @@ class SolteqTandApp(
137
141
  # Find hyperlink
138
142
  menu_link = self.wait_for_control(
139
143
  control_type=auto.HyperlinkControl,
140
- search_params={
141
- 'Name': menu_item
142
- },
143
- search_depth=5
144
+ search_params={"Name": menu_item},
145
+ search_depth=5,
144
146
  )
145
147
 
146
148
  menu_link.GetInvokePattern().Invoke()
147
149
 
148
150
  self.app_window = self.wait_for_control(
149
151
  control_type=auto.WindowControl,
150
- search_params={
151
- "AutomationId": "FormBooking"
152
- },
153
- search_depth=2
152
+ search_params={"AutomationId": "FormBooking"},
153
+ search_depth=2,
154
154
  )
155
155
 
156
156
  def close_solteq_tand(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mbu_dev_shared_components
3
- Version: 4.0.3
3
+ Version: 4.2.0
4
4
  Summary: Shared components to use in RPA projects
5
5
  Author-email: MBU <rpa@mbu.aarhus.dk>
6
6
  License-Expression: MIT
@@ -12,6 +12,7 @@ License-File: LICENSE
12
12
  Requires-Dist: cryptography>=43.0.0
13
13
  Requires-Dist: pyodbc>=5.1.0
14
14
  Requires-Dist: python-dateutil==2.9.*
15
+ Requires-Dist: dotenv
15
16
  Provides-Extra: getorganized
16
17
  Requires-Dist: requests_ntlm>=1.2.0; extra == "getorganized"
17
18
  Provides-Extra: google
@@ -31,6 +32,8 @@ Provides-Extra: sap
31
32
  Provides-Extra: solteqtand
32
33
  Requires-Dist: uiautomation; extra == "solteqtand"
33
34
  Requires-Dist: pyodbc>=5.1.0; extra == "solteqtand"
35
+ Requires-Dist: psutil; extra == "solteqtand"
36
+ Requires-Dist: docx2pdf; extra == "solteqtand"
34
37
  Provides-Extra: utils
35
38
  Requires-Dist: python-dateutil==2.9.*; extra == "utils"
36
39
  Requires-Dist: cryptography>=43.0.0; extra == "utils"
@@ -37,6 +37,7 @@ mbu_dev_shared_components/sap/__init__.py
37
37
  mbu_dev_shared_components/sap/create_invoice.py
38
38
  mbu_dev_shared_components/solteqtand/__init__.py
39
39
  mbu_dev_shared_components/solteqtand/application/__init__.py
40
+ mbu_dev_shared_components/solteqtand/application/aftalebog.py
40
41
  mbu_dev_shared_components/solteqtand/application/app_handler.py
41
42
  mbu_dev_shared_components/solteqtand/application/appointment.py
42
43
  mbu_dev_shared_components/solteqtand/application/base_ui.py
@@ -1,6 +1,7 @@
1
1
  cryptography>=43.0.0
2
2
  pyodbc>=5.1.0
3
3
  python-dateutil==2.9.*
4
+ dotenv
4
5
 
5
6
  [dev]
6
7
  pylint
@@ -34,6 +35,8 @@ numpy
34
35
  [solteqtand]
35
36
  uiautomation
36
37
  pyodbc>=5.1.0
38
+ psutil
39
+ docx2pdf
37
40
 
38
41
  [utils]
39
42
  python-dateutil==2.9.*
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mbu_dev_shared_components"
7
- version = "4.0.3"
7
+ version = "4.2.0"
8
8
  authors = [
9
9
  { name="MBU", email="rpa@mbu.aarhus.dk" },
10
10
  ]
@@ -20,6 +20,7 @@ dependencies = [
20
20
  "cryptography >= 43.0.0",
21
21
  "pyodbc >= 5.1.0",
22
22
  "python-dateutil == 2.9.*",
23
+ "dotenv",
23
24
  ]
24
25
 
25
26
  [project.optional-dependencies]
@@ -49,6 +50,8 @@ sap = [
49
50
  solteqtand = [
50
51
  "uiautomation",
51
52
  "pyodbc >= 5.1.0",
53
+ "psutil",
54
+ "docx2pdf",
52
55
  ]
53
56
  utils = [
54
57
  "python-dateutil == 2.9.*",