pyxecm 3.4.2__tar.gz → 3.4.4__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.
- {pyxecm-3.4.2 → pyxecm-3.4.4}/PKG-INFO +1 -1
- {pyxecm-3.4.2 → pyxecm-3.4.4}/pyproject.toml +1 -1
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/otcs.py +427 -46
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/payload.py +10 -6
- {pyxecm-3.4.2 → pyxecm-3.4.4}/.gitignore +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/README.md +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/avts.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/coreshare.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/helper/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/helper/assoc.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/helper/data.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/helper/logadapter.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/helper/web.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/helper/xml.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/otac.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/otawp.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/otca.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/otds.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/otiv.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/otkd.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/otmm.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/otpd.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm/py.typed +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/__main__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/app.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/auth/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/auth/functions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/auth/models.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/auth/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/common/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/common/functions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/common/metrics.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/common/models.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/common/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/settings.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/terminal/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/terminal/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_maintenance/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_maintenance/functions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_maintenance/models.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_maintenance/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_otcs/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_otcs/functions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_otcs/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_payload/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_payload/functions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_payload/models.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_api/v1_payload/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/__main__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/browser_automation.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/customizer.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/exceptions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/guidewire.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/k8s.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/log.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/m365.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/payload_list.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/salesforce.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/sap.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/servicenow.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/settings.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/successfactors.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_customizer/translate.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_maintenance_page/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_maintenance_page/__main__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_maintenance_page/app.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_maintenance_page/settings.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_maintenance_page/static/favicon.avif +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.4}/src/pyxecm_maintenance_page/templates/maintenance.html +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyxecm
|
|
3
|
-
Version: 3.4.
|
|
3
|
+
Version: 3.4.4
|
|
4
4
|
Summary: A Python library to interact with Opentext Content Management Rest API
|
|
5
5
|
Project-URL: Homepage, https://github.com/opentext/pyxecm
|
|
6
6
|
Author-email: Kai Gatzweiler <kgatzweiler@opentext.com>, "Dr. Marc Diefenbruch" <mdiefenb@opentext.com>
|
|
@@ -542,6 +542,8 @@ class OTCS:
|
|
|
542
542
|
otcs_config["businessObjectTypesUrl"] = otcs_rest_url + "/v2/businessobjecttypes"
|
|
543
543
|
otcs_config["businessObjectsSearchUrl"] = otcs_rest_url + "/v2/forms/businessobjects/search"
|
|
544
544
|
otcs_config["businessWorkspaceTypesUrl"] = otcs_rest_url + "/v1/businessworkspacetypes"
|
|
545
|
+
otcs_config["businessWorkspaceReportsUrl"] = otcs_rest_url + "/v2/businessworkspace"
|
|
546
|
+
otcs_config["businessWorkspaceMyTeamTodoUrl"] = otcs_rest_url + "/v2/businessworkspace/myteamtodo"
|
|
545
547
|
otcs_config["businessWorkspaceTypesUrlv2"] = otcs_rest_url + "/v2/businessworkspacetypes"
|
|
546
548
|
otcs_config["businessworkspacecreateform"] = otcs_rest_url + "/v2/forms/businessworkspaces/create"
|
|
547
549
|
otcs_config["businessWorkspacesUrl"] = otcs_rest_url + "/v2/businessworkspaces"
|
|
@@ -608,6 +610,12 @@ class OTCS:
|
|
|
608
610
|
self._soap_docman_client: Client | None = None
|
|
609
611
|
self._soap_transport: Transport | None = None
|
|
610
612
|
|
|
613
|
+
# Memoized full reminder client/type list (client_id=None). Reminder client
|
|
614
|
+
# and type configuration is effectively static for the lifetime of an OTCS
|
|
615
|
+
# object, so caching it avoids repeated 1+N REST round-trips when a single
|
|
616
|
+
# add/update operation resolves and validates a reminder type multiple times.
|
|
617
|
+
self._reminder_clients_cache: list[dict] | None = None
|
|
618
|
+
|
|
611
619
|
# Handle concurrent HTTP requests that may run into 401 errors and
|
|
612
620
|
# re-authentication at the same time:
|
|
613
621
|
self._authentication_lock = threading.Lock()
|
|
@@ -2692,6 +2700,55 @@ class OTCS:
|
|
|
2692
2700
|
|
|
2693
2701
|
# end method definition
|
|
2694
2702
|
|
|
2703
|
+
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_system_default_metadata_language")
|
|
2704
|
+
def get_system_default_metadata_language(self) -> str | None:
|
|
2705
|
+
"""Get the Content Server system default metadata language as a 2-letter ISO 639-1 code.
|
|
2706
|
+
|
|
2707
|
+
Derives the language from the server's ``metadata_languages`` list by finding
|
|
2708
|
+
the entry with ``'default': True`` (e.g. ``{'default': True, 'language_code': 'en'}`` → ``'en'``).
|
|
2709
|
+
|
|
2710
|
+
This is the language in which ``wksp_type_name`` and other default metadata fields are stored.
|
|
2711
|
+
|
|
2712
|
+
The result is cached because the system language does not change at runtime.
|
|
2713
|
+
|
|
2714
|
+
Returns:
|
|
2715
|
+
str | None:
|
|
2716
|
+
Two-letter language code (e.g. 'en', 'de', 'fr'),
|
|
2717
|
+
or None if the server info cannot be retrieved.
|
|
2718
|
+
|
|
2719
|
+
"""
|
|
2720
|
+
|
|
2721
|
+
language = self.__get_system_default_metadata_language_cached()
|
|
2722
|
+
if language is None:
|
|
2723
|
+
self.__get_system_default_metadata_language_cached.cache_clear()
|
|
2724
|
+
|
|
2725
|
+
return language
|
|
2726
|
+
|
|
2727
|
+
@cache
|
|
2728
|
+
def __get_system_default_metadata_language_cached(self) -> str | None:
|
|
2729
|
+
response = self.get_server_info()
|
|
2730
|
+
if not response:
|
|
2731
|
+
return None
|
|
2732
|
+
|
|
2733
|
+
server_info = response.get("server")
|
|
2734
|
+
if not server_info:
|
|
2735
|
+
return None
|
|
2736
|
+
|
|
2737
|
+
# metadata_languages is a list of dicts, e.g.:
|
|
2738
|
+
# [{'default': True, 'display_name': 'English', 'language_code': 'en'}, ...]
|
|
2739
|
+
# The entry with 'default': True defines the system's metadata language.
|
|
2740
|
+
metadata_languages = server_info.get("metadata_languages")
|
|
2741
|
+
if not metadata_languages:
|
|
2742
|
+
return None
|
|
2743
|
+
|
|
2744
|
+
for lang in metadata_languages:
|
|
2745
|
+
if lang.get("default"):
|
|
2746
|
+
return lang.get("language_code")
|
|
2747
|
+
|
|
2748
|
+
return None
|
|
2749
|
+
|
|
2750
|
+
# end method definition
|
|
2751
|
+
|
|
2695
2752
|
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="apply_config")
|
|
2696
2753
|
def apply_config(self, xml_file_path: str) -> dict | None:
|
|
2697
2754
|
"""Apply Content Server administration settings from XML file.
|
|
@@ -11167,11 +11224,24 @@ class OTCS:
|
|
|
11167
11224
|
# end method definition
|
|
11168
11225
|
|
|
11169
11226
|
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_business_object_types")
|
|
11170
|
-
def get_business_object_types(
|
|
11227
|
+
def get_business_object_types(
|
|
11228
|
+
self,
|
|
11229
|
+
where_is_default_search: bool | None = None,
|
|
11230
|
+
where_workspace_type_id: int | None = None,
|
|
11231
|
+
drop_empty: bool = True,
|
|
11232
|
+
) -> dict | None:
|
|
11171
11233
|
"""Get information for all configured business object types.
|
|
11172
11234
|
|
|
11173
11235
|
Args:
|
|
11174
|
-
None
|
|
11236
|
+
where_is_default_search (bool | None, optional):
|
|
11237
|
+
If True, only return business object types that are marked as default search.
|
|
11238
|
+
where_workspace_type_id (int | None, optional):
|
|
11239
|
+
If provided, only return business object types that are associated with the given workspace type ID.
|
|
11240
|
+
drop_empty (bool, optional):
|
|
11241
|
+
If True, drop any business object types that have empty properties. Default is True.
|
|
11242
|
+
It seems OTCM is returning some business object types with all properties empty
|
|
11243
|
+
except for the workspace type ID. These are likely the workspace types that
|
|
11244
|
+
don't have any business object types associated with them. We drop them by default.
|
|
11175
11245
|
|
|
11176
11246
|
Returns:
|
|
11177
11247
|
dict | None:
|
|
@@ -11210,15 +11280,28 @@ class OTCS:
|
|
|
11210
11280
|
|
|
11211
11281
|
"""
|
|
11212
11282
|
|
|
11213
|
-
|
|
11283
|
+
query = {}
|
|
11284
|
+
if where_is_default_search is not None:
|
|
11285
|
+
query["where_is_default_search"] = where_is_default_search
|
|
11286
|
+
|
|
11287
|
+
encoded_query = urllib.parse.urlencode(query=query, doseq=True)
|
|
11288
|
+
|
|
11289
|
+
request_url = self.config()["businessObjectTypesUrl"] + "?{}".format(encoded_query)
|
|
11214
11290
|
request_header = self.request_form_header()
|
|
11215
11291
|
|
|
11216
11292
|
self.logger.debug(
|
|
11217
|
-
"Get all business object types; calling -> %s",
|
|
11293
|
+
"Get all business object types%s%s%s; calling -> %s",
|
|
11294
|
+
" where is default search = {}".format(where_is_default_search)
|
|
11295
|
+
if where_is_default_search is not None
|
|
11296
|
+
else "",
|
|
11297
|
+
" and" if where_is_default_search is not None and where_workspace_type_id is not None else "",
|
|
11298
|
+
" where workspace type ID = {}".format(where_workspace_type_id)
|
|
11299
|
+
if where_workspace_type_id is not None
|
|
11300
|
+
else "",
|
|
11218
11301
|
request_url,
|
|
11219
11302
|
)
|
|
11220
11303
|
|
|
11221
|
-
|
|
11304
|
+
response = self.do_request(
|
|
11222
11305
|
url=request_url,
|
|
11223
11306
|
method="GET",
|
|
11224
11307
|
headers=request_header,
|
|
@@ -11226,6 +11309,26 @@ class OTCS:
|
|
|
11226
11309
|
failure_message="Failed to get business object types",
|
|
11227
11310
|
)
|
|
11228
11311
|
|
|
11312
|
+
# Filter for workspace type ID - the REST API above does not provide such option
|
|
11313
|
+
# so we need to do it manually:
|
|
11314
|
+
if where_workspace_type_id is not None and response and "results" in response:
|
|
11315
|
+
response["results"] = [
|
|
11316
|
+
item
|
|
11317
|
+
for item in response["results"]
|
|
11318
|
+
if "data" in item
|
|
11319
|
+
and "properties" in item["data"]
|
|
11320
|
+
and item["data"]["properties"]["workspace_type_id"] == where_workspace_type_id
|
|
11321
|
+
]
|
|
11322
|
+
# Drop empty business object types if requested:
|
|
11323
|
+
elif drop_empty and response and "results" in response:
|
|
11324
|
+
response["results"] = [
|
|
11325
|
+
item
|
|
11326
|
+
for item in response["results"]
|
|
11327
|
+
if "data" in item and "properties" in item["data"] and item["data"]["properties"]["bo_type"] is not None
|
|
11328
|
+
]
|
|
11329
|
+
|
|
11330
|
+
return response
|
|
11331
|
+
|
|
11229
11332
|
# end method definition
|
|
11230
11333
|
|
|
11231
11334
|
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_business_object_types_iterator")
|
|
@@ -11663,7 +11766,7 @@ class OTCS:
|
|
|
11663
11766
|
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_business_objects_search")
|
|
11664
11767
|
def get_business_objects_search(
|
|
11665
11768
|
self,
|
|
11666
|
-
external_system_id: str,
|
|
11769
|
+
external_system_id: str | None = None,
|
|
11667
11770
|
type_name: str | None = None,
|
|
11668
11771
|
type_id: int | None = None,
|
|
11669
11772
|
) -> dict | None:
|
|
@@ -11673,18 +11776,24 @@ class OTCS:
|
|
|
11673
11776
|
get_business_objects method.
|
|
11674
11777
|
|
|
11675
11778
|
Args:
|
|
11676
|
-
external_system_id (str):
|
|
11677
|
-
The External system ID (such as "TM6").
|
|
11779
|
+
external_system_id (str | None):
|
|
11780
|
+
The External system ID (such as "TM6"). Optional parameter but
|
|
11781
|
+
needed if type_id is NOT provided ot type_name. If type_id is provided,
|
|
11782
|
+
the external_system_id parameter will be ignored.
|
|
11678
11783
|
type_name (str | None):
|
|
11679
11784
|
Type name of the business object (such as "SAP Customer").
|
|
11680
11785
|
type_id (int | None):
|
|
11681
|
-
The business object type ID. This is an alternative to the
|
|
11682
|
-
|
|
11683
|
-
|
|
11786
|
+
The business object type ID. This is an alternative to the
|
|
11787
|
+
type_name + external_system_id parameters.
|
|
11788
|
+
Either external_system_id + type_name or type_id needs to be provided.
|
|
11789
|
+
If both are provided, type_id will be used and type_name and external_system_id
|
|
11790
|
+
will be ignored.
|
|
11684
11791
|
|
|
11685
11792
|
Returns:
|
|
11686
11793
|
dict | None:
|
|
11687
11794
|
Business Object Search Form or None if the request fails.
|
|
11795
|
+
The first element in results contains the business object type information
|
|
11796
|
+
and the second element contains the search form information.
|
|
11688
11797
|
|
|
11689
11798
|
Example:
|
|
11690
11799
|
{
|
|
@@ -11848,14 +11957,16 @@ class OTCS:
|
|
|
11848
11957
|
)
|
|
11849
11958
|
return None
|
|
11850
11959
|
|
|
11851
|
-
if not external_system_id:
|
|
11852
|
-
self.logger.error(
|
|
11960
|
+
if type_name and not external_system_id:
|
|
11961
|
+
self.logger.error(
|
|
11962
|
+
"External system ID needs to be provided when type name is used. Cannot get business object search form."
|
|
11963
|
+
)
|
|
11853
11964
|
return None
|
|
11854
11965
|
|
|
11855
|
-
query = {
|
|
11856
|
-
"ext_system_id": external_system_id,
|
|
11857
|
-
}
|
|
11966
|
+
query = {}
|
|
11858
11967
|
|
|
11968
|
+
if external_system_id:
|
|
11969
|
+
query["ext_system_id"] = external_system_id
|
|
11859
11970
|
if type_id:
|
|
11860
11971
|
query["bo_type_id"] = type_id
|
|
11861
11972
|
else:
|
|
@@ -11869,10 +11980,10 @@ class OTCS:
|
|
|
11869
11980
|
request_header = self.request_form_header()
|
|
11870
11981
|
|
|
11871
11982
|
self.logger.debug(
|
|
11872
|
-
"Get search form for business object type%s -> '%s'
|
|
11983
|
+
"Get search form for business object type%s -> '%s'%s; calling -> %s",
|
|
11873
11984
|
" ID" if type_id else "",
|
|
11874
11985
|
type_id or type_name,
|
|
11875
|
-
external_system_id,
|
|
11986
|
+
" and external system -> {}".format(external_system_id) if external_system_id else "",
|
|
11876
11987
|
request_url,
|
|
11877
11988
|
)
|
|
11878
11989
|
|
|
@@ -11881,10 +11992,10 @@ class OTCS:
|
|
|
11881
11992
|
method="GET",
|
|
11882
11993
|
headers=request_header,
|
|
11883
11994
|
timeout=None,
|
|
11884
|
-
failure_message="Failed to get search form for business object type{} -> '{}'
|
|
11995
|
+
failure_message="Failed to get search form for business object type{} -> '{}'{}".format(
|
|
11885
11996
|
" ID" if type_id else "",
|
|
11886
11997
|
type_id or type_name,
|
|
11887
|
-
external_system_id,
|
|
11998
|
+
" and external system -> {}".format(external_system_id) if external_system_id else "",
|
|
11888
11999
|
),
|
|
11889
12000
|
)
|
|
11890
12001
|
|
|
@@ -13150,6 +13261,8 @@ class OTCS:
|
|
|
13150
13261
|
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_workspace_types")
|
|
13151
13262
|
def get_workspace_types(
|
|
13152
13263
|
self,
|
|
13264
|
+
ext_system_id: int | None = None,
|
|
13265
|
+
bo_type: str | None = None,
|
|
13153
13266
|
expand_workspace_info: bool = True,
|
|
13154
13267
|
expand_templates: bool = True,
|
|
13155
13268
|
show_error: bool = True,
|
|
@@ -13162,6 +13275,16 @@ class OTCS:
|
|
|
13162
13275
|
This endpoint may throw an HTTP 500 error if no workspace types are in OTCS.
|
|
13163
13276
|
|
|
13164
13277
|
Args:
|
|
13278
|
+
ext_system_id (int | None, optional):
|
|
13279
|
+
External system ID to filter workspace types by. Needs to be provided
|
|
13280
|
+
together with bo_type. If ext_system_id is provided but bo_type is not,
|
|
13281
|
+
the REST API will fail.
|
|
13282
|
+
bo_type (str | None, optional):
|
|
13283
|
+
Business Object type name to filter workspace types by. The is the
|
|
13284
|
+
technical name of the business object type - NOT the ID! E.g. "KNA1"
|
|
13285
|
+
for customers in SAP S/4HANA. Needs to be provided together with ext_system_id.
|
|
13286
|
+
If bo_type is provided but ext_system_id is not, the REST API will fail.
|
|
13287
|
+
It is OK to omit both parameters to get all workspace types in OTCS.
|
|
13165
13288
|
expand_workspace_info (bool, optional):
|
|
13166
13289
|
Controls if the workspace info is returned as well
|
|
13167
13290
|
expand_templates (bool, optional):
|
|
@@ -13181,26 +13304,73 @@ class OTCS:
|
|
|
13181
13304
|
```json
|
|
13182
13305
|
{
|
|
13183
13306
|
'links': {
|
|
13184
|
-
'data': {
|
|
13307
|
+
'data': {
|
|
13308
|
+
'self': {
|
|
13309
|
+
'body': '',
|
|
13310
|
+
'content_type': '',
|
|
13311
|
+
'href': '/api/v2/businessworkspacetypes?bo_type=KNA1&expand_templates=true&expand_wksp_info=true&ext_system_id=TE1',
|
|
13312
|
+
'method': 'GET',
|
|
13313
|
+
'name': ''
|
|
13314
|
+
}
|
|
13315
|
+
}
|
|
13185
13316
|
},
|
|
13186
13317
|
'results': [
|
|
13187
13318
|
{
|
|
13188
13319
|
'data': {
|
|
13189
13320
|
'properties': {
|
|
13190
|
-
'
|
|
13191
|
-
'
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13321
|
+
'add_creator_to_lead_role': True,
|
|
13322
|
+
'aviator_enabled': True,
|
|
13323
|
+
'classification': {
|
|
13324
|
+
'location': 'StaticNodeId',
|
|
13325
|
+
'location_value': '30020'
|
|
13326
|
+
},
|
|
13327
|
+
'config_node_id': 39309,
|
|
13328
|
+
'external_document_storage': {
|
|
13329
|
+
'rm_classification': {...},
|
|
13330
|
+
'sub_location_path': {...}
|
|
13331
|
+
},
|
|
13332
|
+
'indexing': {
|
|
13333
|
+
'enabled': True,
|
|
13334
|
+
'sub_types': [...]
|
|
13335
|
+
},
|
|
13336
|
+
'relations': [{...}, {...}, {...}],
|
|
13337
|
+
'rm_enabled': True,
|
|
13338
|
+
'search': {
|
|
13339
|
+
'follow_related_wksp': 'AlwaysEnabled',
|
|
13340
|
+
'max_number_of_followed_wksp': 50
|
|
13341
|
+
},
|
|
13342
|
+
'simplify_business_workspace_creation': False,
|
|
13343
|
+
'templates': [{...}],
|
|
13344
|
+
'widget_icon': {
|
|
13345
|
+
'url': '/appimg/ot_bws/icons/39309.svg?v=162061_17502'
|
|
13346
|
+
},
|
|
13347
|
+
'wksp_copy_enabled': True,
|
|
13348
|
+
'wksp_creation': {
|
|
13349
|
+
'create_wksp_with_fast_bulk_method': False,
|
|
13350
|
+
'directly_open_created_wksp': True,
|
|
13351
|
+
'location': 'StaticNodeId',
|
|
13352
|
+
'location_value': '34962',
|
|
13353
|
+
'sub_location_path': {...},
|
|
13354
|
+
'use_also_for_manual_creation': True
|
|
13355
|
+
},
|
|
13356
|
+
'wksp_creation_enabled': True,
|
|
13357
|
+
'wksp_descriptions': {'ar': '', 'de': '', 'en': '', 'es': '', 'fr': '', 'it': '', 'iw': '', 'ja': '', 'nl': ''},
|
|
13358
|
+
'wksp_icon': 'otsapxecm/wksp_customer.png',
|
|
13359
|
+
'wksp_name_generation': {
|
|
13360
|
+
'use_also_for_wksp_without_bo': False,
|
|
13361
|
+
'wksp_names': {...}
|
|
13362
|
+
},
|
|
13363
|
+
'wksp_policies_enabled': False,
|
|
13364
|
+
'wksp_type_id': 16,
|
|
13365
|
+
'wksp_type_name': 'Customer',
|
|
13366
|
+
'wksp_type_names': {'ar': '', 'de': 'Kunde', 'en': 'Customer', 'es': '', 'fr': 'Client', 'it': 'Cliente', 'iw': '', 'ja': 'お客様', 'nl': ''}
|
|
13201
13367
|
},
|
|
13202
13368
|
'wksp_info': {
|
|
13203
|
-
'
|
|
13369
|
+
'in_use': True,
|
|
13370
|
+
'indexing_status': 'UpToDate',
|
|
13371
|
+
'modified': '2026-06-30T01:32:24',
|
|
13372
|
+
'perspective_folder_id': 39316,
|
|
13373
|
+
'wksp_type_icon': '/appimg/ot_bws/icons/39309.svg?v=162061_17502'
|
|
13204
13374
|
}
|
|
13205
13375
|
}
|
|
13206
13376
|
}
|
|
@@ -13212,6 +13382,15 @@ class OTCS:
|
|
|
13212
13382
|
|
|
13213
13383
|
query = {"expand_templates": expand_templates, "expand_wksp_info": expand_workspace_info}
|
|
13214
13384
|
|
|
13385
|
+
if (ext_system_id is not None and bo_type is None) or (ext_system_id is None and bo_type is not None):
|
|
13386
|
+
self.logger.error("Both ext_system_id and bo_type must be provided together.")
|
|
13387
|
+
return None
|
|
13388
|
+
|
|
13389
|
+
if ext_system_id is not None:
|
|
13390
|
+
query["ext_system_id"] = ext_system_id
|
|
13391
|
+
if bo_type is not None:
|
|
13392
|
+
query["bo_type"] = bo_type
|
|
13393
|
+
|
|
13215
13394
|
encoded_query = urllib.parse.urlencode(query=query, doseq=True)
|
|
13216
13395
|
|
|
13217
13396
|
request_url = self.config()["businessWorkspaceTypesUrlv2"] + "?{}".format(encoded_query)
|
|
@@ -14564,7 +14743,7 @@ class OTCS:
|
|
|
14564
14743
|
self,
|
|
14565
14744
|
node_id: int,
|
|
14566
14745
|
) -> list | None:
|
|
14567
|
-
"""Get
|
|
14746
|
+
"""Get the workspace references to business objects in external systems.
|
|
14568
14747
|
|
|
14569
14748
|
Args:
|
|
14570
14749
|
node_id (int):
|
|
@@ -14572,7 +14751,7 @@ class OTCS:
|
|
|
14572
14751
|
|
|
14573
14752
|
Returns:
|
|
14574
14753
|
list | None:
|
|
14575
|
-
A
|
|
14754
|
+
A list of references to business objects in external systems.
|
|
14576
14755
|
|
|
14577
14756
|
Example:
|
|
14578
14757
|
[
|
|
@@ -14760,7 +14939,7 @@ class OTCS:
|
|
|
14760
14939
|
def create_workspace(
|
|
14761
14940
|
self,
|
|
14762
14941
|
workspace_template_id: int,
|
|
14763
|
-
workspace_name: str,
|
|
14942
|
+
workspace_name: str | None,
|
|
14764
14943
|
workspace_description: str,
|
|
14765
14944
|
workspace_type: int,
|
|
14766
14945
|
category_data: dict | None = None,
|
|
@@ -14780,12 +14959,13 @@ class OTCS:
|
|
|
14780
14959
|
template and type, with optional category data and business object details.
|
|
14781
14960
|
It also supports linking to external systems and specifying metadata such as
|
|
14782
14961
|
creation and modification dates.
|
|
14962
|
+
If the name is not specified it will be derived from workspace metadata.
|
|
14783
14963
|
|
|
14784
14964
|
Args:
|
|
14785
14965
|
workspace_template_id (int):
|
|
14786
14966
|
The ID of the workspace template to be used.
|
|
14787
|
-
workspace_name (str):
|
|
14788
|
-
The name of the new workspace.
|
|
14967
|
+
workspace_name (str | None):
|
|
14968
|
+
The name of the new workspace. If not specified, it will be derived from workspace metadata.
|
|
14789
14969
|
workspace_description (str):
|
|
14790
14970
|
A description of the new workspace.
|
|
14791
14971
|
workspace_type (int):
|
|
@@ -14853,13 +15033,16 @@ class OTCS:
|
|
|
14853
15033
|
|
|
14854
15034
|
create_workspace_post_data = {
|
|
14855
15035
|
"template_id": str(workspace_template_id),
|
|
14856
|
-
"name": workspace_name,
|
|
14857
15036
|
"description": workspace_description,
|
|
14858
15037
|
"wksp_type_id": str(workspace_type),
|
|
14859
15038
|
"type": str(self.ITEM_TYPE_BUSINESS_WORKSPACE),
|
|
14860
15039
|
"roles": {}, # category_data,
|
|
14861
15040
|
}
|
|
14862
15041
|
|
|
15042
|
+
# Yes, workspace name is optional. If not specified, it will be derived from workspace metadata.
|
|
15043
|
+
if workspace_name:
|
|
15044
|
+
create_workspace_post_data["name"] = workspace_name
|
|
15045
|
+
|
|
14863
15046
|
if category_data:
|
|
14864
15047
|
create_workspace_post_data["roles"]["categories"] = category_data
|
|
14865
15048
|
if external_create_date:
|
|
@@ -14891,7 +15074,7 @@ class OTCS:
|
|
|
14891
15074
|
if parent_id is not None:
|
|
14892
15075
|
create_workspace_post_data["parent_id"] = parent_id
|
|
14893
15076
|
self.logger.debug(
|
|
14894
|
-
"Use specified location with node ID -> %d for workspace -> '%s'",
|
|
15077
|
+
"Use specified location with node ID -> %d for creation of workspace -> '%s'",
|
|
14895
15078
|
parent_id,
|
|
14896
15079
|
workspace_name,
|
|
14897
15080
|
)
|
|
@@ -15040,7 +15223,7 @@ class OTCS:
|
|
|
15040
15223
|
self,
|
|
15041
15224
|
workspace_id: int,
|
|
15042
15225
|
related_workspace_id: int,
|
|
15043
|
-
relationship_type: str = "child",
|
|
15226
|
+
relationship_type: str | None = "child",
|
|
15044
15227
|
show_error: bool = True,
|
|
15045
15228
|
) -> dict | None:
|
|
15046
15229
|
"""Create a relationship between two workspaces.
|
|
@@ -15060,7 +15243,7 @@ class OTCS:
|
|
|
15060
15243
|
and the other of type 'child', but this is a less common use case.
|
|
15061
15244
|
|
|
15062
15245
|
Adding a relationship R1: A --> Child --> B makes A to the parent of B _AND_ also
|
|
15063
|
-
B to the child of A. Requesting the childs of A will include
|
|
15246
|
+
B to the child of A. Requesting the childs of A will include relationship R1. Requesting the
|
|
15064
15247
|
parents of B will include R1 as well. But it is still possible to add a relationship
|
|
15065
15248
|
R2: A --> Parent --> B. This will be a separate relationship.
|
|
15066
15249
|
|
|
@@ -15069,8 +15252,10 @@ class OTCS:
|
|
|
15069
15252
|
The ID of the workspace.
|
|
15070
15253
|
related_workspace_id (int):
|
|
15071
15254
|
The ID of the related workspace.
|
|
15072
|
-
relationship_type (str, optional):
|
|
15073
|
-
Can be "parent" or "child" - "child" is default
|
|
15255
|
+
relationship_type (str | None, optional):
|
|
15256
|
+
Can be "parent" or "child" - "child" is the default. If None (or empty)
|
|
15257
|
+
is provided, it falls back to "child" instead of sending an invalid
|
|
15258
|
+
relationship type to the REST API.
|
|
15074
15259
|
show_error (bool, optional):
|
|
15075
15260
|
If True, log an error if relationship cration fails.
|
|
15076
15261
|
Otherwise log a warning.
|
|
@@ -15081,6 +15266,17 @@ class OTCS:
|
|
|
15081
15266
|
|
|
15082
15267
|
"""
|
|
15083
15268
|
|
|
15269
|
+
# Normalize the relationship type so that callers passing None explicitly
|
|
15270
|
+
# (which overrides the default) still get the intended "child" behavior:
|
|
15271
|
+
if not relationship_type:
|
|
15272
|
+
relationship_type = "child"
|
|
15273
|
+
elif relationship_type not in ("parent", "child"):
|
|
15274
|
+
self.logger.error(
|
|
15275
|
+
"Illegal relationship type -> '%s'! Must be either 'parent' or 'child'.",
|
|
15276
|
+
relationship_type,
|
|
15277
|
+
)
|
|
15278
|
+
return None
|
|
15279
|
+
|
|
15084
15280
|
create_workspace_relationship_post_data = {
|
|
15085
15281
|
"rel_bw_id": str(related_workspace_id),
|
|
15086
15282
|
"rel_type": relationship_type,
|
|
@@ -25942,6 +26138,14 @@ class OTCS:
|
|
|
25942
26138
|
|
|
25943
26139
|
# end method definition of _extract_field_mappings()
|
|
25944
26140
|
|
|
26141
|
+
# Serve the memoized full client/type list when no specific client filter
|
|
26142
|
+
# is requested (the common case for type resolution and validation). The
|
|
26143
|
+
# local `client_id` is reassigned inside the loop below, so capture the
|
|
26144
|
+
# original intent up front for both the cache read and the cache write:
|
|
26145
|
+
is_full_list = client_id is None
|
|
26146
|
+
if is_full_list and self._reminder_clients_cache is not None:
|
|
26147
|
+
return self._reminder_clients_cache
|
|
26148
|
+
|
|
25945
26149
|
response = self.get_reminder_types(client_id=client_id)
|
|
25946
26150
|
if not response:
|
|
25947
26151
|
return None
|
|
@@ -25983,6 +26187,10 @@ class OTCS:
|
|
|
25983
26187
|
str(clients),
|
|
25984
26188
|
)
|
|
25985
26189
|
|
|
26190
|
+
# Memoize the full client/type list for subsequent lookups in this session:
|
|
26191
|
+
if is_full_list:
|
|
26192
|
+
self._reminder_clients_cache = clients
|
|
26193
|
+
|
|
25986
26194
|
return clients
|
|
25987
26195
|
|
|
25988
26196
|
# end method definition
|
|
@@ -27330,7 +27538,13 @@ class OTCS:
|
|
|
27330
27538
|
dict | None:
|
|
27331
27539
|
Response from the server, or None if the request fails.
|
|
27332
27540
|
|
|
27333
|
-
|
|
27541
|
+
Note:
|
|
27542
|
+
On OTCM 26.2 and newer the `results` payload contains the ID of the
|
|
27543
|
+
newly created reminder (extractable via `get_result_value(response, key="id")`).
|
|
27544
|
+
On older releases `results` was empty even on success, so callers that
|
|
27545
|
+
need the reminder ID on those releases must fall back to `get_reminders()`.
|
|
27546
|
+
|
|
27547
|
+
Example (OTCM 26.2 and newer):
|
|
27334
27548
|
{
|
|
27335
27549
|
'links': {
|
|
27336
27550
|
'data': {
|
|
@@ -27343,7 +27557,7 @@ class OTCS:
|
|
|
27343
27557
|
}
|
|
27344
27558
|
}
|
|
27345
27559
|
},
|
|
27346
|
-
'results': {}
|
|
27560
|
+
'results': {'id': 66} # ID of the newly created reminder (empty {} on releases before 26.2)
|
|
27347
27561
|
}
|
|
27348
27562
|
|
|
27349
27563
|
"""
|
|
@@ -27719,3 +27933,170 @@ class OTCS:
|
|
|
27719
27933
|
)
|
|
27720
27934
|
|
|
27721
27935
|
# end method definition
|
|
27936
|
+
|
|
27937
|
+
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_workspace_report_detail")
|
|
27938
|
+
def get_workspace_report_detail(
|
|
27939
|
+
self,
|
|
27940
|
+
workspace_id: int,
|
|
27941
|
+
report_type: str,
|
|
27942
|
+
) -> dict | None:
|
|
27943
|
+
"""Get the full document list for a single workspace report type.
|
|
27944
|
+
|
|
27945
|
+
REST operation: GET /v2/businessworkspace/{workspace_id}/reports?type={report_type}
|
|
27946
|
+
|
|
27947
|
+
Args:
|
|
27948
|
+
workspace_id (int):
|
|
27949
|
+
Business workspace node ID.
|
|
27950
|
+
report_type (str):
|
|
27951
|
+
Report type key. One of ``"documentsAdded"``, ``"outdatedDocuments"``,
|
|
27952
|
+
or ``"recentDocuments"``.
|
|
27953
|
+
|
|
27954
|
+
Returns:
|
|
27955
|
+
dict | None:
|
|
27956
|
+
Report detail response containing a ``results.data`` list and
|
|
27957
|
+
``results.total_count``, or None on error.
|
|
27958
|
+
|
|
27959
|
+
"""
|
|
27960
|
+
|
|
27961
|
+
request_url = "{}/{}/reports?type={}".format(
|
|
27962
|
+
self.config()["businessWorkspaceReportsUrl"],
|
|
27963
|
+
workspace_id,
|
|
27964
|
+
report_type,
|
|
27965
|
+
)
|
|
27966
|
+
request_header = self.request_json_header()
|
|
27967
|
+
|
|
27968
|
+
self.logger.debug(
|
|
27969
|
+
"Get workspace report detail for workspace with ID -> %d, type -> %s; calling -> %s",
|
|
27970
|
+
workspace_id,
|
|
27971
|
+
report_type,
|
|
27972
|
+
request_url,
|
|
27973
|
+
)
|
|
27974
|
+
|
|
27975
|
+
return self.do_request(
|
|
27976
|
+
url=request_url,
|
|
27977
|
+
method="GET",
|
|
27978
|
+
headers=request_header,
|
|
27979
|
+
timeout=REQUEST_TIMEOUT,
|
|
27980
|
+
failure_message="Failed to get '{}' report detail for workspace with ID -> {}".format(
|
|
27981
|
+
report_type, workspace_id
|
|
27982
|
+
),
|
|
27983
|
+
)
|
|
27984
|
+
|
|
27985
|
+
# end method definition
|
|
27986
|
+
|
|
27987
|
+
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_workspace_documents")
|
|
27988
|
+
def get_workspace_documents(
|
|
27989
|
+
self,
|
|
27990
|
+
workspace_id: int,
|
|
27991
|
+
document_type: Literal["missing", "inprocess"] = "missing",
|
|
27992
|
+
) -> dict | None:
|
|
27993
|
+
"""Get the list of missing or in-process documents for a Business Workspace.
|
|
27994
|
+
|
|
27995
|
+
REST operation: GET /v2/businessworkspaces/{workspace_id}/missingdocuments
|
|
27996
|
+
REST operation: GET /v2/businessworkspaces/{workspace_id}/inprocessdocuments
|
|
27997
|
+
|
|
27998
|
+
Missing documents are required document types that are absent from the workspace.
|
|
27999
|
+
In-process documents are currently being processed within the workspace
|
|
28000
|
+
(e.g. pending classification, approval, or ingestion workflows).
|
|
28001
|
+
|
|
28002
|
+
Args:
|
|
28003
|
+
workspace_id (int):
|
|
28004
|
+
Business workspace node ID.
|
|
28005
|
+
document_type (Literal["missing", "inprocess"], optional):
|
|
28006
|
+
Which document category to retrieve:
|
|
28007
|
+
* ``"missing"`` — required documents absent from the workspace
|
|
28008
|
+
(``/missingdocuments``).
|
|
28009
|
+
* ``"inprocess"`` — documents currently being processed
|
|
28010
|
+
(``/inprocessdocuments``).
|
|
28011
|
+
Defaults to ``"missing"``.
|
|
28012
|
+
|
|
28013
|
+
Returns:
|
|
28014
|
+
dict | None:
|
|
28015
|
+
Response containing a ``results.data`` list and ``results.total_count``,
|
|
28016
|
+
or None on error.
|
|
28017
|
+
|
|
28018
|
+
"""
|
|
28019
|
+
|
|
28020
|
+
endpoint = "inprocessdocuments" if document_type == "inprocess" else "missingdocuments"
|
|
28021
|
+
request_url = "{}/{}/{}".format(
|
|
28022
|
+
self.config()["businessWorkspacesUrl"],
|
|
28023
|
+
workspace_id,
|
|
28024
|
+
endpoint,
|
|
28025
|
+
)
|
|
28026
|
+
request_header = self.request_json_header()
|
|
28027
|
+
|
|
28028
|
+
self.logger.debug(
|
|
28029
|
+
"Get %s for workspace with ID -> %d; calling -> %s",
|
|
28030
|
+
endpoint,
|
|
28031
|
+
workspace_id,
|
|
28032
|
+
request_url,
|
|
28033
|
+
)
|
|
28034
|
+
|
|
28035
|
+
return self.do_request(
|
|
28036
|
+
url=request_url,
|
|
28037
|
+
method="GET",
|
|
28038
|
+
headers=request_header,
|
|
28039
|
+
timeout=REQUEST_TIMEOUT,
|
|
28040
|
+
failure_message="Failed to get {} for workspace with ID -> {}".format(endpoint, workspace_id),
|
|
28041
|
+
)
|
|
28042
|
+
|
|
28043
|
+
# end method definition
|
|
28044
|
+
|
|
28045
|
+
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_workspace_myteamtodo")
|
|
28046
|
+
def get_workspace_myteamtodo(self) -> dict | None:
|
|
28047
|
+
"""Get the My Team Todo data for the currently authenticated user.
|
|
28048
|
+
|
|
28049
|
+
Returns the employee-file completeness status (missing and outdated document types)
|
|
28050
|
+
for all direct reports of the currently authenticated user.
|
|
28051
|
+
|
|
28052
|
+
REST operation: GET /v2/businessworkspace/myteamtodo
|
|
28053
|
+
|
|
28054
|
+
Returns:
|
|
28055
|
+
dict | None:
|
|
28056
|
+
Response containing a ``results`` list where each element holds a
|
|
28057
|
+
``data.members`` list of direct reportees with their completeness status,
|
|
28058
|
+
or None on error.
|
|
28059
|
+
|
|
28060
|
+
Example:
|
|
28061
|
+
{
|
|
28062
|
+
'results': [
|
|
28063
|
+
{
|
|
28064
|
+
'data': {
|
|
28065
|
+
'members': [
|
|
28066
|
+
{
|
|
28067
|
+
'id': 1234,
|
|
28068
|
+
'display_name': 'Ian Grant',
|
|
28069
|
+
'first_name': 'Ian',
|
|
28070
|
+
'last_name': 'Grant',
|
|
28071
|
+
'business_email': 'ian.grant@example.com',
|
|
28072
|
+
'employee_file_todos': {
|
|
28073
|
+
'missing': [{'doc_type_name': 'Contract'}],
|
|
28074
|
+
'outdated': [{'doc_type_name': 'Accident'}],
|
|
28075
|
+
},
|
|
28076
|
+
}
|
|
28077
|
+
]
|
|
28078
|
+
},
|
|
28079
|
+
'properties': None,
|
|
28080
|
+
}
|
|
28081
|
+
]
|
|
28082
|
+
}
|
|
28083
|
+
|
|
28084
|
+
"""
|
|
28085
|
+
|
|
28086
|
+
request_url = self.config()["businessWorkspaceMyTeamTodoUrl"]
|
|
28087
|
+
request_header = self.request_json_header()
|
|
28088
|
+
|
|
28089
|
+
self.logger.debug(
|
|
28090
|
+
"Get My Team Todo data for current user; calling -> %s",
|
|
28091
|
+
request_url,
|
|
28092
|
+
)
|
|
28093
|
+
|
|
28094
|
+
return self.do_request(
|
|
28095
|
+
url=request_url,
|
|
28096
|
+
method="GET",
|
|
28097
|
+
headers=request_header,
|
|
28098
|
+
timeout=REQUEST_TIMEOUT,
|
|
28099
|
+
failure_message="Failed to get My Team Todo data.",
|
|
28100
|
+
)
|
|
28101
|
+
|
|
28102
|
+
# end method definition
|
|
@@ -9010,11 +9010,12 @@ class Payload:
|
|
|
9010
9010
|
# that is used for display purposes in the SmartView if given.
|
|
9011
9011
|
# It can be either a string or a dict with language keys (e.g. "en", "de", ...)
|
|
9012
9012
|
# and text values for multilingual support.
|
|
9013
|
-
# If it is a string we convert it to the dict format with
|
|
9014
|
-
#
|
|
9013
|
+
# If it is a string we convert it to the dict format with the
|
|
9014
|
+
# system default metadata language key:
|
|
9015
9015
|
description = external_system.get("description")
|
|
9016
9016
|
if description and isinstance(description, str):
|
|
9017
|
-
|
|
9017
|
+
default_locale = self._otcs.get_system_default_metadata_language() or "en"
|
|
9018
|
+
description = {default_locale: description}
|
|
9018
9019
|
|
|
9019
9020
|
self._log_header_callback(
|
|
9020
9021
|
text="Process External System -> '{}' ({})".format(system_name, system_type),
|
|
@@ -13447,7 +13448,7 @@ class Payload:
|
|
|
13447
13448
|
|
|
13448
13449
|
"""
|
|
13449
13450
|
|
|
13450
|
-
if not self.
|
|
13451
|
+
if not self._ontologies:
|
|
13451
13452
|
self.logger.info(
|
|
13452
13453
|
"Payload section -> '%s' is empty. Skipping...",
|
|
13453
13454
|
section_name,
|
|
@@ -13505,6 +13506,8 @@ class Payload:
|
|
|
13505
13506
|
)
|
|
13506
13507
|
continue
|
|
13507
13508
|
|
|
13509
|
+
default_locale = ontology.get("locale", self._otcs.get_system_default_metadata_language() or "en")
|
|
13510
|
+
|
|
13508
13511
|
for entity in entities:
|
|
13509
13512
|
workspace_type_name = entity.get("name")
|
|
13510
13513
|
if not workspace_type_name:
|
|
@@ -13624,12 +13627,13 @@ class Payload:
|
|
|
13624
13627
|
for r in entity_relations
|
|
13625
13628
|
):
|
|
13626
13629
|
self.logger.debug(
|
|
13627
|
-
"Relationship from entity type -> '%s' (%s) to -> '%s' (%s) of relationship type -> '%s' already exists. Skipping duplicate...",
|
|
13630
|
+
"Relationship from entity type -> '%s' (%s) to -> '%s' (%s) of relationship type -> '%s' already exists (existing relationships -> %s). Skipping duplicate...",
|
|
13628
13631
|
workspace_type_name,
|
|
13629
13632
|
workspace_type_id,
|
|
13630
13633
|
target_wksp_type_name,
|
|
13631
13634
|
target_wksp_type_id,
|
|
13632
13635
|
rel_type,
|
|
13636
|
+
str(entity_relations),
|
|
13633
13637
|
)
|
|
13634
13638
|
continue
|
|
13635
13639
|
|
|
@@ -13638,7 +13642,7 @@ class Payload:
|
|
|
13638
13642
|
"target_wksp_type_id": int(target_wksp_type_id),
|
|
13639
13643
|
"rel_type": rel_type, # the REST API requires Child and Parent capitalized
|
|
13640
13644
|
"predicates": [
|
|
13641
|
-
predicate if isinstance(predicate, dict) else {
|
|
13645
|
+
predicate if isinstance(predicate, dict) else {default_locale: predicate}
|
|
13642
13646
|
for predicate in rel.get("predicates", [])
|
|
13643
13647
|
], # the REST API supports multi-lingual. If the payload has plain strings as elements we interpret this as english only
|
|
13644
13648
|
}
|
|
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
|
|
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
|