pyxecm 3.4.2__tar.gz → 3.4.3__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.3}/PKG-INFO +1 -1
- {pyxecm-3.4.2 → pyxecm-3.4.3}/pyproject.toml +1 -1
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/otcs.py +206 -35
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/payload.py +10 -6
- {pyxecm-3.4.2 → pyxecm-3.4.3}/.gitignore +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/README.md +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/avts.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/coreshare.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/helper/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/helper/assoc.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/helper/data.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/helper/logadapter.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/helper/web.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/helper/xml.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/otac.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/otawp.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/otca.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/otds.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/otiv.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/otkd.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/otmm.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/otpd.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm/py.typed +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/__main__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/app.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/auth/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/auth/functions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/auth/models.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/auth/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/common/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/common/functions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/common/metrics.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/common/models.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/common/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/settings.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/terminal/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/terminal/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_maintenance/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_maintenance/functions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_maintenance/models.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_maintenance/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_otcs/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_otcs/functions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_otcs/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_payload/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_payload/functions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_payload/models.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_api/v1_payload/router.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/__main__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/browser_automation.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/customizer.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/exceptions.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/guidewire.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/k8s.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/log.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/m365.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/payload_list.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/salesforce.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/sap.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/servicenow.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/settings.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/successfactors.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_customizer/translate.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_maintenance_page/__init__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_maintenance_page/__main__.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_maintenance_page/app.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_maintenance_page/settings.py +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/src/pyxecm_maintenance_page/static/favicon.avif +0 -0
- {pyxecm-3.4.2 → pyxecm-3.4.3}/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.3
|
|
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>
|
|
@@ -2692,6 +2692,55 @@ class OTCS:
|
|
|
2692
2692
|
|
|
2693
2693
|
# end method definition
|
|
2694
2694
|
|
|
2695
|
+
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_system_default_metadata_language")
|
|
2696
|
+
def get_system_default_metadata_language(self) -> str | None:
|
|
2697
|
+
"""Get the Content Server system default metadata language as a 2-letter ISO 639-1 code.
|
|
2698
|
+
|
|
2699
|
+
Derives the language from the server's ``metadata_languages`` list by finding
|
|
2700
|
+
the entry with ``'default': True`` (e.g. ``{'default': True, 'language_code': 'en'}`` → ``'en'``).
|
|
2701
|
+
|
|
2702
|
+
This is the language in which ``wksp_type_name`` and other default metadata fields are stored.
|
|
2703
|
+
|
|
2704
|
+
The result is cached because the system language does not change at runtime.
|
|
2705
|
+
|
|
2706
|
+
Returns:
|
|
2707
|
+
str | None:
|
|
2708
|
+
Two-letter language code (e.g. 'en', 'de', 'fr'),
|
|
2709
|
+
or None if the server info cannot be retrieved.
|
|
2710
|
+
|
|
2711
|
+
"""
|
|
2712
|
+
|
|
2713
|
+
language = self.__get_system_default_metadata_language_cached()
|
|
2714
|
+
if language is None:
|
|
2715
|
+
self.__get_system_default_metadata_language_cached.cache_clear()
|
|
2716
|
+
|
|
2717
|
+
return language
|
|
2718
|
+
|
|
2719
|
+
@cache
|
|
2720
|
+
def __get_system_default_metadata_language_cached(self) -> str | None:
|
|
2721
|
+
response = self.get_server_info()
|
|
2722
|
+
if not response:
|
|
2723
|
+
return None
|
|
2724
|
+
|
|
2725
|
+
server_info = response.get("server")
|
|
2726
|
+
if not server_info:
|
|
2727
|
+
return None
|
|
2728
|
+
|
|
2729
|
+
# metadata_languages is a list of dicts, e.g.:
|
|
2730
|
+
# [{'default': True, 'display_name': 'English', 'language_code': 'en'}, ...]
|
|
2731
|
+
# The entry with 'default': True defines the system's metadata language.
|
|
2732
|
+
metadata_languages = server_info.get("metadata_languages")
|
|
2733
|
+
if not metadata_languages:
|
|
2734
|
+
return None
|
|
2735
|
+
|
|
2736
|
+
for lang in metadata_languages:
|
|
2737
|
+
if lang.get("default"):
|
|
2738
|
+
return lang.get("language_code")
|
|
2739
|
+
|
|
2740
|
+
return None
|
|
2741
|
+
|
|
2742
|
+
# end method definition
|
|
2743
|
+
|
|
2695
2744
|
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="apply_config")
|
|
2696
2745
|
def apply_config(self, xml_file_path: str) -> dict | None:
|
|
2697
2746
|
"""Apply Content Server administration settings from XML file.
|
|
@@ -11167,11 +11216,24 @@ class OTCS:
|
|
|
11167
11216
|
# end method definition
|
|
11168
11217
|
|
|
11169
11218
|
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_business_object_types")
|
|
11170
|
-
def get_business_object_types(
|
|
11219
|
+
def get_business_object_types(
|
|
11220
|
+
self,
|
|
11221
|
+
where_is_default_search: bool | None = None,
|
|
11222
|
+
where_workspace_type_id: int | None = None,
|
|
11223
|
+
drop_empty: bool = True,
|
|
11224
|
+
) -> dict | None:
|
|
11171
11225
|
"""Get information for all configured business object types.
|
|
11172
11226
|
|
|
11173
11227
|
Args:
|
|
11174
|
-
None
|
|
11228
|
+
where_is_default_search (bool | None, optional):
|
|
11229
|
+
If True, only return business object types that are marked as default search.
|
|
11230
|
+
where_workspace_type_id (int | None, optional):
|
|
11231
|
+
If provided, only return business object types that are associated with the given workspace type ID.
|
|
11232
|
+
drop_empty (bool, optional):
|
|
11233
|
+
If True, drop any business object types that have empty properties. Default is True.
|
|
11234
|
+
It seems OTCM is returning some business object types with all properties empty
|
|
11235
|
+
except for the workspace type ID. These are likely the workspace types that
|
|
11236
|
+
don't have any business object types associated with them. We drop them by default.
|
|
11175
11237
|
|
|
11176
11238
|
Returns:
|
|
11177
11239
|
dict | None:
|
|
@@ -11210,15 +11272,28 @@ class OTCS:
|
|
|
11210
11272
|
|
|
11211
11273
|
"""
|
|
11212
11274
|
|
|
11213
|
-
|
|
11275
|
+
query = {}
|
|
11276
|
+
if where_is_default_search is not None:
|
|
11277
|
+
query["where_is_default_search"] = where_is_default_search
|
|
11278
|
+
|
|
11279
|
+
encoded_query = urllib.parse.urlencode(query=query, doseq=True)
|
|
11280
|
+
|
|
11281
|
+
request_url = self.config()["businessObjectTypesUrl"] + "?{}".format(encoded_query)
|
|
11214
11282
|
request_header = self.request_form_header()
|
|
11215
11283
|
|
|
11216
11284
|
self.logger.debug(
|
|
11217
|
-
"Get all business object types; calling -> %s",
|
|
11285
|
+
"Get all business object types%s%s%s; calling -> %s",
|
|
11286
|
+
" where is default search = {}".format(where_is_default_search)
|
|
11287
|
+
if where_is_default_search is not None
|
|
11288
|
+
else "",
|
|
11289
|
+
" and" if where_is_default_search is not None and where_workspace_type_id is not None else "",
|
|
11290
|
+
" where workspace type ID = {}".format(where_workspace_type_id)
|
|
11291
|
+
if where_workspace_type_id is not None
|
|
11292
|
+
else "",
|
|
11218
11293
|
request_url,
|
|
11219
11294
|
)
|
|
11220
11295
|
|
|
11221
|
-
|
|
11296
|
+
response = self.do_request(
|
|
11222
11297
|
url=request_url,
|
|
11223
11298
|
method="GET",
|
|
11224
11299
|
headers=request_header,
|
|
@@ -11226,6 +11301,26 @@ class OTCS:
|
|
|
11226
11301
|
failure_message="Failed to get business object types",
|
|
11227
11302
|
)
|
|
11228
11303
|
|
|
11304
|
+
# Filter for workspace type ID - the REST API above does not provide such option
|
|
11305
|
+
# so we need to do it manually:
|
|
11306
|
+
if where_workspace_type_id is not None and response and "results" in response:
|
|
11307
|
+
response["results"] = [
|
|
11308
|
+
item
|
|
11309
|
+
for item in response["results"]
|
|
11310
|
+
if "data" in item
|
|
11311
|
+
and "properties" in item["data"]
|
|
11312
|
+
and item["data"]["properties"]["workspace_type_id"] == where_workspace_type_id
|
|
11313
|
+
]
|
|
11314
|
+
# Drop empty business object types if requested:
|
|
11315
|
+
elif drop_empty and response and "results" in response:
|
|
11316
|
+
response["results"] = [
|
|
11317
|
+
item
|
|
11318
|
+
for item in response["results"]
|
|
11319
|
+
if "data" in item and "properties" in item["data"] and item["data"]["properties"]["bo_type"] is not None
|
|
11320
|
+
]
|
|
11321
|
+
|
|
11322
|
+
return response
|
|
11323
|
+
|
|
11229
11324
|
# end method definition
|
|
11230
11325
|
|
|
11231
11326
|
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_business_object_types_iterator")
|
|
@@ -11663,7 +11758,7 @@ class OTCS:
|
|
|
11663
11758
|
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_business_objects_search")
|
|
11664
11759
|
def get_business_objects_search(
|
|
11665
11760
|
self,
|
|
11666
|
-
external_system_id: str,
|
|
11761
|
+
external_system_id: str | None = None,
|
|
11667
11762
|
type_name: str | None = None,
|
|
11668
11763
|
type_id: int | None = None,
|
|
11669
11764
|
) -> dict | None:
|
|
@@ -11673,18 +11768,24 @@ class OTCS:
|
|
|
11673
11768
|
get_business_objects method.
|
|
11674
11769
|
|
|
11675
11770
|
Args:
|
|
11676
|
-
external_system_id (str):
|
|
11677
|
-
The External system ID (such as "TM6").
|
|
11771
|
+
external_system_id (str | None):
|
|
11772
|
+
The External system ID (such as "TM6"). Optional parameter but
|
|
11773
|
+
needed if type_id is NOT provided ot type_name. If type_id is provided,
|
|
11774
|
+
the external_system_id parameter will be ignored.
|
|
11678
11775
|
type_name (str | None):
|
|
11679
11776
|
Type name of the business object (such as "SAP Customer").
|
|
11680
11777
|
type_id (int | None):
|
|
11681
|
-
The business object type ID. This is an alternative to the
|
|
11682
|
-
|
|
11683
|
-
|
|
11778
|
+
The business object type ID. This is an alternative to the
|
|
11779
|
+
type_name + external_system_id parameters.
|
|
11780
|
+
Either external_system_id + type_name or type_id needs to be provided.
|
|
11781
|
+
If both are provided, type_id will be used and type_name and external_system_id
|
|
11782
|
+
will be ignored.
|
|
11684
11783
|
|
|
11685
11784
|
Returns:
|
|
11686
11785
|
dict | None:
|
|
11687
11786
|
Business Object Search Form or None if the request fails.
|
|
11787
|
+
The first element in results contains the business object type information
|
|
11788
|
+
and the second element contains the search form information.
|
|
11688
11789
|
|
|
11689
11790
|
Example:
|
|
11690
11791
|
{
|
|
@@ -11848,14 +11949,16 @@ class OTCS:
|
|
|
11848
11949
|
)
|
|
11849
11950
|
return None
|
|
11850
11951
|
|
|
11851
|
-
if not external_system_id:
|
|
11852
|
-
self.logger.error(
|
|
11952
|
+
if type_name and not external_system_id:
|
|
11953
|
+
self.logger.error(
|
|
11954
|
+
"External system ID needs to be provided when type name is used. Cannot get business object search form."
|
|
11955
|
+
)
|
|
11853
11956
|
return None
|
|
11854
11957
|
|
|
11855
|
-
query = {
|
|
11856
|
-
"ext_system_id": external_system_id,
|
|
11857
|
-
}
|
|
11958
|
+
query = {}
|
|
11858
11959
|
|
|
11960
|
+
if external_system_id:
|
|
11961
|
+
query["ext_system_id"] = external_system_id
|
|
11859
11962
|
if type_id:
|
|
11860
11963
|
query["bo_type_id"] = type_id
|
|
11861
11964
|
else:
|
|
@@ -11869,10 +11972,10 @@ class OTCS:
|
|
|
11869
11972
|
request_header = self.request_form_header()
|
|
11870
11973
|
|
|
11871
11974
|
self.logger.debug(
|
|
11872
|
-
"Get search form for business object type%s -> '%s'
|
|
11975
|
+
"Get search form for business object type%s -> '%s'%s; calling -> %s",
|
|
11873
11976
|
" ID" if type_id else "",
|
|
11874
11977
|
type_id or type_name,
|
|
11875
|
-
external_system_id,
|
|
11978
|
+
" and external system -> {}".format(external_system_id) if external_system_id else "",
|
|
11876
11979
|
request_url,
|
|
11877
11980
|
)
|
|
11878
11981
|
|
|
@@ -11881,10 +11984,10 @@ class OTCS:
|
|
|
11881
11984
|
method="GET",
|
|
11882
11985
|
headers=request_header,
|
|
11883
11986
|
timeout=None,
|
|
11884
|
-
failure_message="Failed to get search form for business object type{} -> '{}'
|
|
11987
|
+
failure_message="Failed to get search form for business object type{} -> '{}'{}".format(
|
|
11885
11988
|
" ID" if type_id else "",
|
|
11886
11989
|
type_id or type_name,
|
|
11887
|
-
external_system_id,
|
|
11990
|
+
" and external system -> {}".format(external_system_id) if external_system_id else "",
|
|
11888
11991
|
),
|
|
11889
11992
|
)
|
|
11890
11993
|
|
|
@@ -13150,6 +13253,8 @@ class OTCS:
|
|
|
13150
13253
|
@tracer.start_as_current_span(attributes=OTEL_TRACING_ATTRIBUTES, name="get_workspace_types")
|
|
13151
13254
|
def get_workspace_types(
|
|
13152
13255
|
self,
|
|
13256
|
+
ext_system_id: int | None = None,
|
|
13257
|
+
bo_type: str | None = None,
|
|
13153
13258
|
expand_workspace_info: bool = True,
|
|
13154
13259
|
expand_templates: bool = True,
|
|
13155
13260
|
show_error: bool = True,
|
|
@@ -13162,6 +13267,16 @@ class OTCS:
|
|
|
13162
13267
|
This endpoint may throw an HTTP 500 error if no workspace types are in OTCS.
|
|
13163
13268
|
|
|
13164
13269
|
Args:
|
|
13270
|
+
ext_system_id (int | None, optional):
|
|
13271
|
+
External system ID to filter workspace types by. Needs to be provided
|
|
13272
|
+
together with bo_type. If ext_system_id is provided but bo_type is not,
|
|
13273
|
+
the REST API will fail.
|
|
13274
|
+
bo_type (str | None, optional):
|
|
13275
|
+
Business Object type name to filter workspace types by. The is the
|
|
13276
|
+
technical name of the business object type - NOT the ID! E.g. "KNA1"
|
|
13277
|
+
for customers in SAP S/4HANA. Needs to be provided together with ext_system_id.
|
|
13278
|
+
If bo_type is provided but ext_system_id is not, the REST API will fail.
|
|
13279
|
+
It is OK to omit both parameters to get all workspace types in OTCS.
|
|
13165
13280
|
expand_workspace_info (bool, optional):
|
|
13166
13281
|
Controls if the workspace info is returned as well
|
|
13167
13282
|
expand_templates (bool, optional):
|
|
@@ -13181,26 +13296,73 @@ class OTCS:
|
|
|
13181
13296
|
```json
|
|
13182
13297
|
{
|
|
13183
13298
|
'links': {
|
|
13184
|
-
'data': {
|
|
13299
|
+
'data': {
|
|
13300
|
+
'self': {
|
|
13301
|
+
'body': '',
|
|
13302
|
+
'content_type': '',
|
|
13303
|
+
'href': '/api/v2/businessworkspacetypes?bo_type=KNA1&expand_templates=true&expand_wksp_info=true&ext_system_id=TE1',
|
|
13304
|
+
'method': 'GET',
|
|
13305
|
+
'name': ''
|
|
13306
|
+
}
|
|
13307
|
+
}
|
|
13185
13308
|
},
|
|
13186
13309
|
'results': [
|
|
13187
13310
|
{
|
|
13188
13311
|
'data': {
|
|
13189
13312
|
'properties': {
|
|
13190
|
-
'
|
|
13191
|
-
'
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13313
|
+
'add_creator_to_lead_role': True,
|
|
13314
|
+
'aviator_enabled': True,
|
|
13315
|
+
'classification': {
|
|
13316
|
+
'location': 'StaticNodeId',
|
|
13317
|
+
'location_value': '30020'
|
|
13318
|
+
},
|
|
13319
|
+
'config_node_id': 39309,
|
|
13320
|
+
'external_document_storage': {
|
|
13321
|
+
'rm_classification': {...},
|
|
13322
|
+
'sub_location_path': {...}
|
|
13323
|
+
},
|
|
13324
|
+
'indexing': {
|
|
13325
|
+
'enabled': True,
|
|
13326
|
+
'sub_types': [...]
|
|
13327
|
+
},
|
|
13328
|
+
'relations': [{...}, {...}, {...}],
|
|
13329
|
+
'rm_enabled': True,
|
|
13330
|
+
'search': {
|
|
13331
|
+
'follow_related_wksp': 'AlwaysEnabled',
|
|
13332
|
+
'max_number_of_followed_wksp': 50
|
|
13333
|
+
},
|
|
13334
|
+
'simplify_business_workspace_creation': False,
|
|
13335
|
+
'templates': [{...}],
|
|
13336
|
+
'widget_icon': {
|
|
13337
|
+
'url': '/appimg/ot_bws/icons/39309.svg?v=162061_17502'
|
|
13338
|
+
},
|
|
13339
|
+
'wksp_copy_enabled': True,
|
|
13340
|
+
'wksp_creation': {
|
|
13341
|
+
'create_wksp_with_fast_bulk_method': False,
|
|
13342
|
+
'directly_open_created_wksp': True,
|
|
13343
|
+
'location': 'StaticNodeId',
|
|
13344
|
+
'location_value': '34962',
|
|
13345
|
+
'sub_location_path': {...},
|
|
13346
|
+
'use_also_for_manual_creation': True
|
|
13347
|
+
},
|
|
13348
|
+
'wksp_creation_enabled': True,
|
|
13349
|
+
'wksp_descriptions': {'ar': '', 'de': '', 'en': '', 'es': '', 'fr': '', 'it': '', 'iw': '', 'ja': '', 'nl': ''},
|
|
13350
|
+
'wksp_icon': 'otsapxecm/wksp_customer.png',
|
|
13351
|
+
'wksp_name_generation': {
|
|
13352
|
+
'use_also_for_wksp_without_bo': False,
|
|
13353
|
+
'wksp_names': {...}
|
|
13354
|
+
},
|
|
13355
|
+
'wksp_policies_enabled': False,
|
|
13356
|
+
'wksp_type_id': 16,
|
|
13357
|
+
'wksp_type_name': 'Customer',
|
|
13358
|
+
'wksp_type_names': {'ar': '', 'de': 'Kunde', 'en': 'Customer', 'es': '', 'fr': 'Client', 'it': 'Cliente', 'iw': '', 'ja': 'お客様', 'nl': ''}
|
|
13201
13359
|
},
|
|
13202
13360
|
'wksp_info': {
|
|
13203
|
-
'
|
|
13361
|
+
'in_use': True,
|
|
13362
|
+
'indexing_status': 'UpToDate',
|
|
13363
|
+
'modified': '2026-06-30T01:32:24',
|
|
13364
|
+
'perspective_folder_id': 39316,
|
|
13365
|
+
'wksp_type_icon': '/appimg/ot_bws/icons/39309.svg?v=162061_17502'
|
|
13204
13366
|
}
|
|
13205
13367
|
}
|
|
13206
13368
|
}
|
|
@@ -13212,6 +13374,15 @@ class OTCS:
|
|
|
13212
13374
|
|
|
13213
13375
|
query = {"expand_templates": expand_templates, "expand_wksp_info": expand_workspace_info}
|
|
13214
13376
|
|
|
13377
|
+
if (ext_system_id is not None and bo_type is None) or (ext_system_id is None and bo_type is not None):
|
|
13378
|
+
self.logger.error("Both ext_system_id and bo_type must be provided together.")
|
|
13379
|
+
return None
|
|
13380
|
+
|
|
13381
|
+
if ext_system_id is not None:
|
|
13382
|
+
query["ext_system_id"] = ext_system_id
|
|
13383
|
+
if bo_type is not None:
|
|
13384
|
+
query["bo_type"] = bo_type
|
|
13385
|
+
|
|
13215
13386
|
encoded_query = urllib.parse.urlencode(query=query, doseq=True)
|
|
13216
13387
|
|
|
13217
13388
|
request_url = self.config()["businessWorkspaceTypesUrlv2"] + "?{}".format(encoded_query)
|
|
@@ -14564,7 +14735,7 @@ class OTCS:
|
|
|
14564
14735
|
self,
|
|
14565
14736
|
node_id: int,
|
|
14566
14737
|
) -> list | None:
|
|
14567
|
-
"""Get
|
|
14738
|
+
"""Get the workspace references to business objects in external systems.
|
|
14568
14739
|
|
|
14569
14740
|
Args:
|
|
14570
14741
|
node_id (int):
|
|
@@ -14572,7 +14743,7 @@ class OTCS:
|
|
|
14572
14743
|
|
|
14573
14744
|
Returns:
|
|
14574
14745
|
list | None:
|
|
14575
|
-
A
|
|
14746
|
+
A list of references to business objects in external systems.
|
|
14576
14747
|
|
|
14577
14748
|
Example:
|
|
14578
14749
|
[
|
|
@@ -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
|