mbu-dev-shared-components 2.4.3__tar.gz → 2.4.5__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.
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/PKG-INFO +1 -1
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/document.py +4 -2
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components.egg-info/PKG-INFO +1 -1
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components.egg-info/SOURCES.txt +0 -3
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/pyproject.toml +1 -1
- mbu_dev_shared_components-2.4.3/mbu_dev_shared_components/tests/go_tests/go_integration_tests.py +0 -278
- mbu_dev_shared_components-2.4.3/mbu_dev_shared_components/tests/go_tests/objects_tests.py +0 -124
- mbu_dev_shared_components-2.4.3/mbu_dev_shared_components/tests/msoffice_tests/msoffice_integration_tests.py +0 -188
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/LICENSE +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/README.md +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/database/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/database/constants.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/database/logging.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/database/utility.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/auth.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/cases.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/contacts.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/documents.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/getorganized/objects.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/google/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/google/api/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/google/api/auth.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/google/workspace/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/google/workspace/alerts.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/msoffice365/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/msoffice365/excel/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/msoffice365/excel/excel_reader.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/msoffice365/sharepoint_api/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/msoffice365/sharepoint_api/files.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/os2forms/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/os2forms/documents.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/os2forms/forms.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/romexis/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/romexis/db_handler.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/romexis/helper_functions.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/sap/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/sap/create_invoice.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/app_handler.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/appointment.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/base_ui.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/clinic.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/edi_portal.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/event.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/exceptions.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/handler_base.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/journal_note.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/application/patient.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/database/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/solteqtand/database/db_handler.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/utils/__init__.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/utils/db_stored_procedure_executor.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/utils/fernet_encryptor.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/utils/file_handler.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components/utils/json_handler.py +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components.egg-info/dependency_links.txt +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components.egg-info/requires.txt +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/mbu_dev_shared_components.egg-info/top_level.txt +0 -0
- {mbu_dev_shared_components-2.4.3 → mbu_dev_shared_components-2.4.5}/setup.cfg +0 -0
|
@@ -171,7 +171,8 @@ class DocumentHandler(HandlerBase):
|
|
|
171
171
|
if new_value != metadata['templateName']:
|
|
172
172
|
raise ValueError(f"Failed to set the correct status. Expected '{metadata['templateName']}', but got '{new_value}'.")
|
|
173
173
|
|
|
174
|
-
|
|
174
|
+
if os.path.exists(folder_path):
|
|
175
|
+
shutil.rmtree(folder_path, ignore_errors=True)
|
|
175
176
|
|
|
176
177
|
form_mail_merge.PaneControl(AutomationId="ButtonMerge").GetLegacyIAccessiblePattern().DoDefaultAction()
|
|
177
178
|
|
|
@@ -230,7 +231,8 @@ class DocumentHandler(HandlerBase):
|
|
|
230
231
|
print(f"Error while creating document from template: {e}")
|
|
231
232
|
raise
|
|
232
233
|
finally:
|
|
233
|
-
|
|
234
|
+
if os.path.exists(folder_path):
|
|
235
|
+
shutil.rmtree(folder_path, ignore_errors=True)
|
|
234
236
|
|
|
235
237
|
def send_discharge_document_digitalpost(self, metadata: dict) -> None:
|
|
236
238
|
"""
|
|
@@ -49,9 +49,6 @@ mbu_dev_shared_components/solteqtand/application/journal_note.py
|
|
|
49
49
|
mbu_dev_shared_components/solteqtand/application/patient.py
|
|
50
50
|
mbu_dev_shared_components/solteqtand/database/__init__.py
|
|
51
51
|
mbu_dev_shared_components/solteqtand/database/db_handler.py
|
|
52
|
-
mbu_dev_shared_components/tests/go_tests/go_integration_tests.py
|
|
53
|
-
mbu_dev_shared_components/tests/go_tests/objects_tests.py
|
|
54
|
-
mbu_dev_shared_components/tests/msoffice_tests/msoffice_integration_tests.py
|
|
55
52
|
mbu_dev_shared_components/utils/__init__.py
|
|
56
53
|
mbu_dev_shared_components/utils/db_stored_procedure_executor.py
|
|
57
54
|
mbu_dev_shared_components/utils/fernet_encryptor.py
|
|
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "mbu_dev_shared_components"
|
|
11
|
-
version = "2.4.
|
|
11
|
+
version = "2.4.5" # Specify the version manually here
|
|
12
12
|
authors = [
|
|
13
13
|
{ name="MBU", email="rpa@mbu.aarhus.dk" },
|
|
14
14
|
]
|
mbu_dev_shared_components-2.4.3/mbu_dev_shared_components/tests/go_tests/go_integration_tests.py
DELETED
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Integration tests for the GetOrganized API.
|
|
3
|
-
|
|
4
|
-
These tests validate the following key functionalities:
|
|
5
|
-
1. Authentication success using CPR lookup
|
|
6
|
-
2. Contact lookup returns correct citizen profile
|
|
7
|
-
3. Retrieval of metadata for a specific case (Borgermappe)
|
|
8
|
-
4. Case lookup using case properties
|
|
9
|
-
5. Document metadata retrieval
|
|
10
|
-
6. Document search (legacy and modern search APIs)
|
|
11
|
-
|
|
12
|
-
Expected to run daily to ensure API stability and data consistency.
|
|
13
|
-
|
|
14
|
-
Required environment variables:
|
|
15
|
-
- GO_API_ENDPOINT: Base URL for GetOrganized API
|
|
16
|
-
- GO_API_USERNAME: API username for authentication
|
|
17
|
-
- GO_API_PASSWORD: API password
|
|
18
|
-
- DADJ_FULL_NAME: Full name of test citizen
|
|
19
|
-
- DADJ_SSN: CPR number of test citizen
|
|
20
|
-
- DADJ_GO_ID: Internal ID of test citizen in GO
|
|
21
|
-
- DADJ_BORGERMAPPE_SAGS_ID: Case ID of the test citizen's "Borgermappe"
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
import os
|
|
25
|
-
import xml.etree.ElementTree as ET
|
|
26
|
-
import requests
|
|
27
|
-
import pytest
|
|
28
|
-
|
|
29
|
-
from mbu_dev_shared_components.getorganized import contacts
|
|
30
|
-
from mbu_dev_shared_components.getorganized import cases
|
|
31
|
-
from mbu_dev_shared_components.getorganized import documents
|
|
32
|
-
from mbu_dev_shared_components.getorganized import objects
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# -------------------------------
|
|
36
|
-
# Helper to load environment vars safely
|
|
37
|
-
# -------------------------------
|
|
38
|
-
def _get_cfg(key: str) -> str:
|
|
39
|
-
val = os.getenv(key)
|
|
40
|
-
|
|
41
|
-
if not val:
|
|
42
|
-
pytest.skip(f"env var '{key}' not set → skipping integration test")
|
|
43
|
-
|
|
44
|
-
return val
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
@pytest.fixture(scope="module")
|
|
48
|
-
def go_env():
|
|
49
|
-
"""
|
|
50
|
-
Loads required environment variables for the GetOrganized API tests.
|
|
51
|
-
Skips tests if any required variable is missing.
|
|
52
|
-
"""
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
"endpoint": _get_cfg("GO_API_ENDPOINT"),
|
|
56
|
-
"username": _get_cfg("GO_API_USERNAME"),
|
|
57
|
-
"password": _get_cfg("GO_API_PASSWORD"),
|
|
58
|
-
"full_name": _get_cfg("DADJ_FULL_NAME"),
|
|
59
|
-
"ssn": _get_cfg("DADJ_SSN"),
|
|
60
|
-
"go_id": _get_cfg("DADJ_GO_ID"),
|
|
61
|
-
"case_id": _get_cfg("DADJ_BORGERMAPPE_SAGS_ID"),
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def test_authentication_success(go_env):
|
|
66
|
-
"""
|
|
67
|
-
Ensures valid credentials can access the API without 401/403.
|
|
68
|
-
"""
|
|
69
|
-
|
|
70
|
-
resp = contacts.contact_lookup(
|
|
71
|
-
person_ssn=go_env["ssn"],
|
|
72
|
-
api_endpoint=f"{go_env['endpoint']}/_goapi/contacts/readitem",
|
|
73
|
-
api_username=go_env["username"],
|
|
74
|
-
api_password=go_env["password"],
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
assert resp.status_code != 401
|
|
78
|
-
assert resp.status_code != 403
|
|
79
|
-
assert resp.ok
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def test_contact_lookup_returns_expected_name(go_env):
|
|
83
|
-
"""
|
|
84
|
-
Verifies that contact lookup returns correct full name, ID, and CPR.
|
|
85
|
-
"""
|
|
86
|
-
|
|
87
|
-
resp = contacts.contact_lookup(
|
|
88
|
-
person_ssn=go_env["ssn"],
|
|
89
|
-
api_endpoint=f"{go_env['endpoint']}/_goapi/contacts/readitem",
|
|
90
|
-
api_username=go_env["username"],
|
|
91
|
-
api_password=go_env["password"],
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
assert resp.ok
|
|
95
|
-
|
|
96
|
-
data = resp.json()
|
|
97
|
-
|
|
98
|
-
assert data["FullName"] == go_env["full_name"]
|
|
99
|
-
assert data["ID"] == go_env["go_id"]
|
|
100
|
-
assert data["CPR"] == go_env["ssn"]
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def test_case_metadata_structure(go_env):
|
|
104
|
-
"""
|
|
105
|
-
Validates the metadata structure of a known 'Borgermappe' case.
|
|
106
|
-
"""
|
|
107
|
-
|
|
108
|
-
resp = cases.get_case_metadata(
|
|
109
|
-
api_endpoint=f"{go_env['endpoint']}/_goapi/Cases/Metadata/{go_env['case_id']}",
|
|
110
|
-
api_username=go_env["username"],
|
|
111
|
-
api_password=go_env["password"],
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
assert resp.ok
|
|
115
|
-
|
|
116
|
-
# Extract XML metadata and parse attributes
|
|
117
|
-
resp_metadata_xml = resp.json().get("Metadata")
|
|
118
|
-
|
|
119
|
-
assert resp_metadata_xml
|
|
120
|
-
|
|
121
|
-
data = ET.fromstring(resp_metadata_xml).attrib
|
|
122
|
-
|
|
123
|
-
assert data["ows_CaseID"] == go_env["case_id"]
|
|
124
|
-
|
|
125
|
-
assert data["ows_CaseCategory"] == "Borgermappe"
|
|
126
|
-
|
|
127
|
-
assert data["ows_CCMContactData"] == f"{go_env['full_name']};#{go_env['go_id']};#{go_env['ssn']};#;#"
|
|
128
|
-
|
|
129
|
-
assert data["ows_CCMContactData_CPR"] == go_env["ssn"]
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def test_find_case_by_case_properties(go_env):
|
|
133
|
-
"""
|
|
134
|
-
Searches for a case using known properties of the test citizen.
|
|
135
|
-
"""
|
|
136
|
-
|
|
137
|
-
case_data_json = objects.CaseDataJson()
|
|
138
|
-
|
|
139
|
-
case_data = case_data_json.search_citizen_folder_data_json(
|
|
140
|
-
case_type_prefix="BOR",
|
|
141
|
-
person_full_name=go_env["full_name"],
|
|
142
|
-
person_id=go_env["go_id"],
|
|
143
|
-
person_ssn=go_env["ssn"]
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
resp = cases.find_case_by_case_properties(
|
|
147
|
-
case_data=case_data,
|
|
148
|
-
api_endpoint=f"{go_env['endpoint']}/_goapi/Cases/FindByCaseProperties",
|
|
149
|
-
api_username=go_env["username"],
|
|
150
|
-
api_password=go_env["password"],
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
assert resp.ok
|
|
154
|
-
|
|
155
|
-
data = resp.json().get("CasesInfo")
|
|
156
|
-
|
|
157
|
-
assert isinstance(data, list)
|
|
158
|
-
|
|
159
|
-
assert len(data) == 1
|
|
160
|
-
|
|
161
|
-
assert data[0].get("CaseID") == go_env["case_id"]
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
def test_get_document_metadata(go_env):
|
|
165
|
-
"""
|
|
166
|
-
Fetches metadata for a known document tied to the test citizen.
|
|
167
|
-
"""
|
|
168
|
-
document_id = 14583373 # ID must be valid for test profile
|
|
169
|
-
|
|
170
|
-
resp = documents.get_document_metadata(
|
|
171
|
-
api_endpoint=f"{go_env['endpoint']}/_goapi/Documents/Metadata/{document_id}",
|
|
172
|
-
api_username=go_env["username"],
|
|
173
|
-
api_password=go_env["password"],
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
assert resp.ok
|
|
177
|
-
|
|
178
|
-
data = ET.fromstring(resp.json().get("Metadata")).attrib
|
|
179
|
-
|
|
180
|
-
assert "ows_Title" in data
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def test_search_documents(go_env):
|
|
184
|
-
"""
|
|
185
|
-
Performs a legacy document search using full name + CPR.
|
|
186
|
-
"""
|
|
187
|
-
|
|
188
|
-
search_term = f"{go_env['full_name']} {go_env['ssn']}"
|
|
189
|
-
|
|
190
|
-
resp = documents.search_documents(
|
|
191
|
-
search_term=search_term,
|
|
192
|
-
api_endpoint=f"{go_env['endpoint']}/_goapi/Search/Results",
|
|
193
|
-
api_username=go_env["username"],
|
|
194
|
-
api_password=go_env["password"],
|
|
195
|
-
)
|
|
196
|
-
|
|
197
|
-
assert resp.ok
|
|
198
|
-
|
|
199
|
-
results = resp.json().get("Rows").get("Results")
|
|
200
|
-
total_rows = resp.json().get("TotalRows")
|
|
201
|
-
|
|
202
|
-
assert isinstance(results, list)
|
|
203
|
-
|
|
204
|
-
if total_rows == 0:
|
|
205
|
-
assert len(results) == 0
|
|
206
|
-
|
|
207
|
-
else:
|
|
208
|
-
assert len(results) == total_rows
|
|
209
|
-
|
|
210
|
-
for doc in results:
|
|
211
|
-
assert "title" in doc
|
|
212
|
-
assert "created" in doc
|
|
213
|
-
assert "caseid" in doc
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
def _validate_modern_search_response(resp: requests.Response):
|
|
217
|
-
"""
|
|
218
|
-
Helper: Validates structure of modern search response.
|
|
219
|
-
"""
|
|
220
|
-
|
|
221
|
-
assert resp.ok
|
|
222
|
-
|
|
223
|
-
json_data = resp.json()
|
|
224
|
-
|
|
225
|
-
results = json_data.get("results", {}).get("Results", [])
|
|
226
|
-
|
|
227
|
-
total_rows = json_data.get("totalRows")
|
|
228
|
-
|
|
229
|
-
assert isinstance(results, list)
|
|
230
|
-
|
|
231
|
-
if total_rows == 0:
|
|
232
|
-
assert len(results) == 0
|
|
233
|
-
|
|
234
|
-
else:
|
|
235
|
-
assert len(results) == total_rows
|
|
236
|
-
for doc in results:
|
|
237
|
-
|
|
238
|
-
assert "title" in doc
|
|
239
|
-
assert "created" in doc
|
|
240
|
-
assert "caseid" in doc
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
def test_modern_search(go_env):
|
|
244
|
-
"""
|
|
245
|
-
Runs two modern searches: one without date filter, one with date filter.
|
|
246
|
-
"""
|
|
247
|
-
|
|
248
|
-
search_term = f"{go_env['full_name']} {go_env['ssn']}"
|
|
249
|
-
|
|
250
|
-
# Search 1: All-time
|
|
251
|
-
resp_1 = documents.modern_search(
|
|
252
|
-
page_index=0,
|
|
253
|
-
search_term=search_term,
|
|
254
|
-
start_date=None,
|
|
255
|
-
end_date=None,
|
|
256
|
-
only_items=False,
|
|
257
|
-
case_type_prefix="BOR",
|
|
258
|
-
api_endpoint=f"{go_env['endpoint']}/_goapi/search/ExecuteModernSearch",
|
|
259
|
-
api_username=go_env["username"],
|
|
260
|
-
api_password=go_env["password"],
|
|
261
|
-
)
|
|
262
|
-
|
|
263
|
-
# Search 2: Specific March 2025 range
|
|
264
|
-
resp_2 = documents.modern_search(
|
|
265
|
-
page_index=0,
|
|
266
|
-
search_term=search_term,
|
|
267
|
-
start_date="2025-03-01",
|
|
268
|
-
end_date="2025-03-31",
|
|
269
|
-
only_items=False,
|
|
270
|
-
case_type_prefix="BOR",
|
|
271
|
-
api_endpoint=f"{go_env['endpoint']}/_goapi/search/ExecuteModernSearch",
|
|
272
|
-
api_username=go_env["username"],
|
|
273
|
-
api_password=go_env["password"],
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
_validate_modern_search_response(resp_1)
|
|
277
|
-
|
|
278
|
-
_validate_modern_search_response(resp_2)
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Unit tests for data structure creation methods in CaseDataJson.
|
|
3
|
-
These are pure functions that return formatted dictionaries, used in API requests.
|
|
4
|
-
|
|
5
|
-
Should run on pull requests to ensure the data structure is correct.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import pytest
|
|
9
|
-
from mbu_dev_shared_components.getorganized.objects import CaseDataJson
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@pytest.fixture
|
|
13
|
-
def case_data_handler():
|
|
14
|
-
"""
|
|
15
|
-
Fixture to provide an instance of CaseDataJson for testing.
|
|
16
|
-
"""
|
|
17
|
-
return CaseDataJson()
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def test_search_citizen_folder_data_json(case_data_handler: CaseDataJson):
|
|
21
|
-
"""
|
|
22
|
-
Ensure that the search_citizen_folder_data_json method correctly builds
|
|
23
|
-
a search structure for a citizen's full data and filters by 'Borgermappe' case category.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
result = case_data_handler.search_citizen_folder_data_json(
|
|
27
|
-
case_type_prefix="BOR",
|
|
28
|
-
person_full_name="Test Person",
|
|
29
|
-
person_id="12345",
|
|
30
|
-
person_ssn="0101011234"
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
assert result["LogicalOperator"] == "AND"
|
|
34
|
-
assert result["ExcludeDeletedCases"] == "True"
|
|
35
|
-
assert result["ReturnCasesNumber"] == "1"
|
|
36
|
-
|
|
37
|
-
assert {
|
|
38
|
-
"InternalName": "ows_CCMContactData",
|
|
39
|
-
"Value": "Test Person;#12345;#0101011234;#;#",
|
|
40
|
-
"DataType": "Text",
|
|
41
|
-
"ComparisonType": "Equal",
|
|
42
|
-
"IsMultiValue": "False"
|
|
43
|
-
} in result["FieldProperties"]
|
|
44
|
-
|
|
45
|
-
assert {
|
|
46
|
-
"InternalName": "ows_CaseCategory",
|
|
47
|
-
"Value": "Borgermappe",
|
|
48
|
-
"DataType": "Text",
|
|
49
|
-
"ComparisonType": "Equal",
|
|
50
|
-
"IsMultiValue": "False"
|
|
51
|
-
} in result["FieldProperties"]
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def test_generic_search_case_data_json_with_name_and_extra_field(case_data_handler: CaseDataJson):
|
|
55
|
-
"""
|
|
56
|
-
Ensure that generic_search_case_data_json assembles a correct structure when using:
|
|
57
|
-
- a custom case_type_prefix,
|
|
58
|
-
- a non-default number of return cases,
|
|
59
|
-
- full citizen data,
|
|
60
|
-
- and extra field properties.
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
field_properties = {
|
|
64
|
-
"ows_Title": "Lønbilag"
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
result = case_data_handler.generic_search_case_data_json(
|
|
68
|
-
case_type_prefix="PER",
|
|
69
|
-
person_full_name="Test Person",
|
|
70
|
-
person_id="12345",
|
|
71
|
-
person_ssn="0101011234",
|
|
72
|
-
include_name=True,
|
|
73
|
-
returned_cases_number="5",
|
|
74
|
-
field_properties=field_properties
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
assert result["CaseTypePrefixes"] == ["PER"]
|
|
78
|
-
|
|
79
|
-
assert {
|
|
80
|
-
"InternalName": "ows_CCMContactData",
|
|
81
|
-
"Value": "Test Person;#12345;#0101011234;#;#",
|
|
82
|
-
"DataType": "Text",
|
|
83
|
-
"ComparisonType": "Equal",
|
|
84
|
-
"IsMultiValue": "False"
|
|
85
|
-
} in result["FieldProperties"]
|
|
86
|
-
|
|
87
|
-
assert result["ReturnCasesNumber"] == "5"
|
|
88
|
-
|
|
89
|
-
assert {
|
|
90
|
-
"InternalName": "ows_Title",
|
|
91
|
-
"Value": "Lønbilag",
|
|
92
|
-
"DataType": "Text",
|
|
93
|
-
"ComparisonType": "Equal",
|
|
94
|
-
"IsMultiValue": "False"
|
|
95
|
-
} in result["FieldProperties"]
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def test_generic_search_case_data_json_without_name(case_data_handler: CaseDataJson):
|
|
99
|
-
"""
|
|
100
|
-
Ensure that generic_search_case_data_json builds correct contact data when include_name=False,
|
|
101
|
-
and only includes one field (ows_CCMContactData) by default when no additional fields are passed.
|
|
102
|
-
"""
|
|
103
|
-
|
|
104
|
-
result = case_data_handler.generic_search_case_data_json(
|
|
105
|
-
case_type_prefix="BOR",
|
|
106
|
-
person_full_name="Daniel Tester",
|
|
107
|
-
person_id="12345",
|
|
108
|
-
person_ssn="0101011234",
|
|
109
|
-
include_name=False
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
assert result["CaseTypePrefixes"] == ["BOR"]
|
|
113
|
-
|
|
114
|
-
assert {
|
|
115
|
-
"InternalName": "ows_CCMContactData",
|
|
116
|
-
"Value": ";#12345;#0101011234;#;#",
|
|
117
|
-
"DataType": "Text",
|
|
118
|
-
"ComparisonType": "Equal",
|
|
119
|
-
"IsMultiValue": "False"
|
|
120
|
-
} in result["FieldProperties"]
|
|
121
|
-
|
|
122
|
-
assert result["ReturnCasesNumber"] == "1"
|
|
123
|
-
|
|
124
|
-
assert len(result["FieldProperties"]) == 1
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Integration tests for verifying Microsoft Office Excel functionality through SharePoint.
|
|
3
|
-
|
|
4
|
-
Tests included:
|
|
5
|
-
1. `test_list_files_from_sharepoint_folder`:
|
|
6
|
-
- Verifies that a known test Excel file exists in the SharePoint folder.
|
|
7
|
-
|
|
8
|
-
2. `test_append_row_to_excel`:
|
|
9
|
-
- Appends a row to a specific sheet in the Excel file.
|
|
10
|
-
- Verifies the row was successfully added.
|
|
11
|
-
|
|
12
|
-
3. `test_format_and_sort_excel_file`:
|
|
13
|
-
- Sorts the Excel sheet by date/time (descending).
|
|
14
|
-
- Applies formatting (bold headers, auto column widths).
|
|
15
|
-
- Verifies that sorting has changed the order.
|
|
16
|
-
|
|
17
|
-
Important constants:
|
|
18
|
-
- FOLDER_NAME = "MSOffice tests"
|
|
19
|
-
- FILE_NAME = "Test_Append_Rows.xlsx"
|
|
20
|
-
- SHEET_NAME = "Upload logs"
|
|
21
|
-
- HEADERS = ["Upload date", "Upload time"]
|
|
22
|
-
|
|
23
|
-
Requires environment variables:
|
|
24
|
-
- MSOFFICE_USERNAME
|
|
25
|
-
- MSOFFICE_PASSWORD
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
import os
|
|
29
|
-
import datetime
|
|
30
|
-
|
|
31
|
-
from io import BytesIO
|
|
32
|
-
|
|
33
|
-
import pytest
|
|
34
|
-
import openpyxl
|
|
35
|
-
|
|
36
|
-
from mbu_dev_shared_components.msoffice365.sharepoint_api.files import Sharepoint
|
|
37
|
-
|
|
38
|
-
FOLDER_NAME = "MSOffice tests"
|
|
39
|
-
CURRENT_DATE = datetime.datetime.now().strftime("%d-%m-%Y")
|
|
40
|
-
CURRENT_TIME = datetime.datetime.now().strftime("%H:%M")
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@pytest.fixture(scope="module")
|
|
44
|
-
def sharepoint_api():
|
|
45
|
-
"""
|
|
46
|
-
Authenticates with SharePoint and returns a Sharepoint API instance.
|
|
47
|
-
Skips test if required environment variables are missing.
|
|
48
|
-
"""
|
|
49
|
-
|
|
50
|
-
def _get_cfg(key: str) -> str:
|
|
51
|
-
val = os.getenv(key)
|
|
52
|
-
|
|
53
|
-
if not val:
|
|
54
|
-
pytest.skip(f"env var '{key}' not set → skipping integration test")
|
|
55
|
-
|
|
56
|
-
return val
|
|
57
|
-
|
|
58
|
-
username = _get_cfg("MSOFFICE_USERNAME")
|
|
59
|
-
password = _get_cfg("MSOFFICE_PASSWORD")
|
|
60
|
-
|
|
61
|
-
site_url = "https://aarhuskommune.sharepoint.com"
|
|
62
|
-
site_name = "MBURPA"
|
|
63
|
-
document_library = "Delte dokumenter"
|
|
64
|
-
|
|
65
|
-
sp = Sharepoint(
|
|
66
|
-
username=username,
|
|
67
|
-
password=password,
|
|
68
|
-
site_url=site_url,
|
|
69
|
-
site_name=site_name,
|
|
70
|
-
document_library=document_library
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
assert sp.ctx is not None, "SharePoint authentication failed"
|
|
74
|
-
|
|
75
|
-
return sp
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
@pytest.mark.dependency(name="list_files")
|
|
79
|
-
def test_list_files_from_sharepoint_folder(sharepoint_api: Sharepoint):
|
|
80
|
-
"""
|
|
81
|
-
Test 1: Check that the expected Excel file exists in the SharePoint folder.
|
|
82
|
-
"""
|
|
83
|
-
|
|
84
|
-
files = sharepoint_api.fetch_files_list(FOLDER_NAME)
|
|
85
|
-
|
|
86
|
-
file_names = [f["Name"] for f in files]
|
|
87
|
-
|
|
88
|
-
assert "Test_Append_Rows.xlsx" in file_names
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
@pytest.mark.dependency(name="append_row", depends=["list_files"])
|
|
92
|
-
def test_append_row_to_excel(sharepoint_api: Sharepoint):
|
|
93
|
-
"""
|
|
94
|
-
Test 2: Append a row to the Excel file and verify it was added correctly.
|
|
95
|
-
"""
|
|
96
|
-
|
|
97
|
-
file_name = "Test_Append_Rows.xlsx"
|
|
98
|
-
|
|
99
|
-
sheet_name = "Upload logs"
|
|
100
|
-
|
|
101
|
-
headers = ["Upload date", "Upload time"]
|
|
102
|
-
|
|
103
|
-
data = {
|
|
104
|
-
"Upload date": CURRENT_DATE,
|
|
105
|
-
"Upload time": CURRENT_TIME
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
# Append the row to the SharePoint-hosted Excel file
|
|
109
|
-
sharepoint_api.append_row_to_sharepoint_excel(
|
|
110
|
-
required_headers=headers,
|
|
111
|
-
folder_name=FOLDER_NAME,
|
|
112
|
-
excel_file_name=file_name,
|
|
113
|
-
sheet_name=sheet_name,
|
|
114
|
-
new_row=data,
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
# Fetch the updated file and check that the last row matches the new data
|
|
118
|
-
binary_file = sharepoint_api.fetch_file_using_open_binary(file_name, FOLDER_NAME)
|
|
119
|
-
|
|
120
|
-
wb = openpyxl.load_workbook(BytesIO(binary_file))
|
|
121
|
-
|
|
122
|
-
ws = wb[sheet_name]
|
|
123
|
-
|
|
124
|
-
newest_row = list(ws.iter_rows(values_only=True))[-1]
|
|
125
|
-
|
|
126
|
-
assert newest_row[0] == CURRENT_DATE
|
|
127
|
-
assert newest_row[1] == CURRENT_TIME
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
@pytest.mark.dependency(depends=["append_row"])
|
|
131
|
-
def test_format_and_sort_excel_file(sharepoint_api: Sharepoint):
|
|
132
|
-
"""
|
|
133
|
-
Test 3: Format and sort the Excel file by date and time.
|
|
134
|
-
Ensures that sorting changes the order and formatting is applied.
|
|
135
|
-
"""
|
|
136
|
-
|
|
137
|
-
file_name = "Test_Append_Rows.xlsx"
|
|
138
|
-
|
|
139
|
-
sheet_name = "Upload logs"
|
|
140
|
-
|
|
141
|
-
# Download the file before sorting to capture original row order
|
|
142
|
-
test_file = sharepoint_api.fetch_file_using_open_binary(file_name, FOLDER_NAME)
|
|
143
|
-
|
|
144
|
-
wb = openpyxl.load_workbook(BytesIO(test_file))
|
|
145
|
-
|
|
146
|
-
ws = wb[sheet_name]
|
|
147
|
-
|
|
148
|
-
all_rows = list(ws.iter_rows(values_only=True))
|
|
149
|
-
|
|
150
|
-
top_before = all_rows[1] # First data row
|
|
151
|
-
|
|
152
|
-
bottom_before = all_rows[-1] # Last data row
|
|
153
|
-
|
|
154
|
-
# Sort by first two columns (date, time) in descending order
|
|
155
|
-
sorting_keys = [
|
|
156
|
-
{"key": "A", "ascending": False, "type": "str"},
|
|
157
|
-
{"key": "B", "ascending": False, "type": "str"},
|
|
158
|
-
]
|
|
159
|
-
|
|
160
|
-
# Apply sorting and formatting
|
|
161
|
-
sharepoint_api.format_and_sort_excel_file(
|
|
162
|
-
folder_name=FOLDER_NAME,
|
|
163
|
-
excel_file_name=file_name,
|
|
164
|
-
sheet_name=sheet_name,
|
|
165
|
-
sorting_keys=sorting_keys,
|
|
166
|
-
bold_rows=[1],
|
|
167
|
-
column_widths="auto",
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
# Re-fetch the file after sorting and verify order has changed
|
|
171
|
-
test_file = sharepoint_api.fetch_file_using_open_binary(file_name, FOLDER_NAME)
|
|
172
|
-
|
|
173
|
-
wb = openpyxl.load_workbook(BytesIO(test_file))
|
|
174
|
-
|
|
175
|
-
ws = wb[sheet_name]
|
|
176
|
-
|
|
177
|
-
all_rows = list(ws.iter_rows(values_only=True))
|
|
178
|
-
|
|
179
|
-
top_after = all_rows[1]
|
|
180
|
-
|
|
181
|
-
bottom_after = all_rows[-1]
|
|
182
|
-
|
|
183
|
-
# Check that sorting actually changed the row order
|
|
184
|
-
assert top_before != top_after
|
|
185
|
-
assert bottom_before != bottom_after
|
|
186
|
-
|
|
187
|
-
# Check that the top row after sorting is the one just added
|
|
188
|
-
assert top_after[0] == CURRENT_DATE
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|