pyxecm 1.6__py3-none-any.whl → 2.0.0__py3-none-any.whl

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.

Potentially problematic release.


This version of pyxecm might be problematic. Click here for more details.

Files changed (56) hide show
  1. pyxecm/__init__.py +6 -4
  2. pyxecm/avts.py +673 -246
  3. pyxecm/coreshare.py +686 -467
  4. pyxecm/customizer/__init__.py +16 -4
  5. pyxecm/customizer/__main__.py +58 -0
  6. pyxecm/customizer/api/__init__.py +5 -0
  7. pyxecm/customizer/api/__main__.py +6 -0
  8. pyxecm/customizer/api/app.py +914 -0
  9. pyxecm/customizer/api/auth.py +154 -0
  10. pyxecm/customizer/api/metrics.py +92 -0
  11. pyxecm/customizer/api/models.py +13 -0
  12. pyxecm/customizer/api/payload_list.py +865 -0
  13. pyxecm/customizer/api/settings.py +103 -0
  14. pyxecm/customizer/browser_automation.py +332 -139
  15. pyxecm/customizer/customizer.py +1007 -1130
  16. pyxecm/customizer/exceptions.py +35 -0
  17. pyxecm/customizer/guidewire.py +322 -0
  18. pyxecm/customizer/k8s.py +713 -378
  19. pyxecm/customizer/log.py +107 -0
  20. pyxecm/customizer/m365.py +2867 -909
  21. pyxecm/customizer/nhc.py +1169 -0
  22. pyxecm/customizer/openapi.py +258 -0
  23. pyxecm/customizer/payload.py +16817 -7467
  24. pyxecm/customizer/pht.py +699 -285
  25. pyxecm/customizer/salesforce.py +516 -342
  26. pyxecm/customizer/sap.py +58 -41
  27. pyxecm/customizer/servicenow.py +593 -371
  28. pyxecm/customizer/settings.py +442 -0
  29. pyxecm/customizer/successfactors.py +408 -346
  30. pyxecm/customizer/translate.py +83 -48
  31. pyxecm/helper/__init__.py +5 -2
  32. pyxecm/helper/assoc.py +83 -43
  33. pyxecm/helper/data.py +2406 -870
  34. pyxecm/helper/logadapter.py +27 -0
  35. pyxecm/helper/web.py +229 -101
  36. pyxecm/helper/xml.py +527 -171
  37. pyxecm/maintenance_page/__init__.py +5 -0
  38. pyxecm/maintenance_page/__main__.py +6 -0
  39. pyxecm/maintenance_page/app.py +51 -0
  40. pyxecm/maintenance_page/settings.py +28 -0
  41. pyxecm/maintenance_page/static/favicon.avif +0 -0
  42. pyxecm/maintenance_page/templates/maintenance.html +165 -0
  43. pyxecm/otac.py +234 -140
  44. pyxecm/otawp.py +1436 -557
  45. pyxecm/otcs.py +7716 -3161
  46. pyxecm/otds.py +2150 -919
  47. pyxecm/otiv.py +36 -21
  48. pyxecm/otmm.py +1272 -325
  49. pyxecm/otpd.py +231 -127
  50. pyxecm-2.0.0.dist-info/METADATA +145 -0
  51. pyxecm-2.0.0.dist-info/RECORD +54 -0
  52. {pyxecm-1.6.dist-info → pyxecm-2.0.0.dist-info}/WHEEL +1 -1
  53. pyxecm-1.6.dist-info/METADATA +0 -53
  54. pyxecm-1.6.dist-info/RECORD +0 -32
  55. {pyxecm-1.6.dist-info → pyxecm-2.0.0.dist-info/licenses}/LICENSE +0 -0
  56. {pyxecm-1.6.dist-info → pyxecm-2.0.0.dist-info}/top_level.txt +0 -0
pyxecm/otawp.py CHANGED
@@ -1,22 +1,27 @@
1
- """
2
- Otawp module for synchorinizing the pojects , publsh and create run time instances for that.
3
- loanmanagement is such application.
4
- """
1
+ """Synchronize AppWorks projects, publsh and create run time instances for that."""
2
+
3
+ __author__ = "Dr. Marc Diefenbruch"
4
+ __copyright__ = "Copyright (C) 2024-2025, OpenText"
5
+ __credits__ = ["Kai-Philip Gatzweiler"]
6
+ __maintainer__ = "Dr. Marc Diefenbruch"
7
+ __email__ = "mdiefenb@opentext.com"
5
8
 
6
- import logging
7
- import xml.etree.ElementTree as ET
8
- import uuid
9
9
  import json
10
+ import logging
10
11
  import re
11
12
  import time
13
+ import uuid
14
+ import xml.etree.ElementTree as ET
15
+
12
16
  import requests
13
- from .otds import OTDS
14
17
 
15
- logger = logging.getLogger("pyxecm.otawp")
18
+ from pyxecm.otds import OTDS
19
+
20
+ default_logger = logging.getLogger("pyxecm.otawp")
16
21
 
17
22
  REQUEST_HEADERS = {
18
23
  "Content-Type": "text/xml; charset=utf-8",
19
- "accept": "application/xml"
24
+ "accept": "application/xml",
20
25
  }
21
26
 
22
27
  REQUEST_FORM_HEADERS = {
@@ -26,12 +31,17 @@ REQUEST_FORM_HEADERS = {
26
31
 
27
32
  REQUEST_HEADERS_JSON = {
28
33
  "Content-Type": "application/json; charset=utf-8",
29
- "accept": "application/json"
34
+ "accept": "application/json",
30
35
  }
31
- REQUEST_TIMEOUT = 60
36
+ REQUEST_TIMEOUT = 120
37
+ SYNC_PUBLISH_REQUEST_TIMEOUT = 300
38
+
32
39
 
33
40
  class OTAWP:
34
- """Used to automate settings in OpenText AppWorks Platform (OTAWP)."""
41
+ """Class OTRAWP is used to automate settings in OpenText AppWorks Platform (OTAWP)."""
42
+
43
+ logger: logging.Logger = default_logger
44
+
35
45
  _config: dict
36
46
  _config = None
37
47
  _cookie = None
@@ -45,7 +55,46 @@ class OTAWP:
45
55
  username: str | None = None,
46
56
  password: str | None = None,
47
57
  otawp_ticket: str | None = None,
48
- ):
58
+ otcs_partition_name: str | None = None,
59
+ otds_admin_partition_mame: str | None = None,
60
+ config_map_name: str | None = None,
61
+ otcs_resource_id: str | None = None,
62
+ otds_url: str | None = None,
63
+ otcs_url: str | None = None,
64
+ otcs_base_path: str | None = None,
65
+ license_file: str | None = None,
66
+ product_name: str | None = None,
67
+ product_description: str | None = None,
68
+ logger: logging.Logger = default_logger,
69
+ ) -> None:
70
+ """Initialize OTAWP (AppWorks Platform) object.
71
+
72
+ Args:
73
+ protocol (str): #TODO _description_
74
+ hostname (str): #TODO _description_
75
+ port (int): #TODO _description_
76
+ username (str | None, optional): #TODO _description_. Defaults to None.
77
+ password (str | None, optional): #TODO _description_. Defaults to None.
78
+ otawp_ticket (str | None, optional): #TODO _description_. Defaults to None.
79
+ otcs_partition_name (str | None, optional): #TODO _description_. Defaults to None.
80
+ otds_admin_partition_mame (str | None, optional): #TODO _description_. Defaults to None.
81
+ config_map_name (str | None, optional): #TODO _description_. Defaults to None.
82
+ otcs_resource_id (str | None, optional): #TODO _description_. Defaults to None.
83
+ otds_url (str | None, optional): #TODO _description_. Defaults to None.
84
+ otcs_url (str | None, optional): #TODO _description_. Defaults to None.
85
+ otcs_base_path (str | None, optional): #TODO _description_. Defaults to None.
86
+ license_file (str | None, optional): #TODO _description_. Defaults to None.
87
+ product_name (str | None, optional): #TODO _description_. Defaults to None.
88
+ product_description (str | None, optional): #TODO _description_. Defaults to None.
89
+ logger (logging.Logger, optional): #TODO: _description_. Defaults to default_logger.
90
+
91
+ """
92
+
93
+ if logger != default_logger:
94
+ self.logger = logger.getChild("otawp")
95
+ for logfilter in logger.filters:
96
+ self.logger.addFilter(logfilter)
97
+
49
98
  otawp_config = {}
50
99
 
51
100
  otawp_config["hostname"] = hostname if hostname else "appworks"
@@ -53,125 +102,332 @@ class OTAWP:
53
102
  otawp_config["port"] = port if port else 8080
54
103
  otawp_config["username"] = username if username else "sysadmin"
55
104
  otawp_config["password"] = password if password else ""
105
+ otawp_config["otcs_partition_name"] = otcs_partition_name if otcs_partition_name else ""
106
+ otawp_config["otds_admin_partition_mame"] = otds_admin_partition_mame if otds_admin_partition_mame else ""
107
+ otawp_config["config_map_name"] = config_map_name if config_map_name else ""
108
+ otawp_config["otcs_resource_id"] = otcs_resource_id if otcs_resource_id else ""
109
+ otawp_config["otds_url"] = otds_url if otds_url else ""
110
+ otawp_config["otcs_url"] = otcs_url if otcs_url else ""
111
+ otawp_config["otcs_base_path"] = otcs_base_path if otcs_base_path else ""
112
+ otawp_config["license_file"] = license_file if license_file else ""
113
+ otawp_config["product_name"] = product_name if product_name else "APPWORKS_PLATFORM"
114
+ otawp_config["product_description"] = (
115
+ product_description if product_description else "OpenText Appworks Platform"
116
+ )
56
117
 
57
118
  if otawp_ticket:
58
119
  self._cookie = {"defaultinst_SAMLart": otawp_ticket}
59
120
 
60
- otds_base_url = "{}://{}".format(protocol, otawp_config["hostname"])
121
+ server = "{}://{}".format(protocol, otawp_config["hostname"])
61
122
  if str(port) not in ["80", "443"]:
62
- otds_base_url += f":{port}"
63
- otds_base_url += "/home/system"
123
+ server += f":{port}"
124
+
125
+ otawp_base_url = server + "/home/system"
126
+
127
+ otawp_config["server"] = server if server else "http://appworks"
64
128
 
65
129
  otawp_config["gatewayAuthenticationUrl"] = (
66
- otds_base_url
130
+ otawp_base_url
67
131
  + "/com.eibus.web.soap.Gateway.wcp?organization=o=system,cn=cordys,cn=defaultInst,o=opentext.net"
68
132
  )
69
133
 
70
134
  otawp_config["soapGatewayUrl"] = (
71
- otds_base_url
135
+ otawp_base_url
72
136
  + "/com.eibus.web.soap.Gateway.wcp?organization=o=system,cn=cordys,cn=defaultInst,o=opentext.net&defaultinst_ct=abcd"
73
137
  )
74
138
 
75
139
  otawp_config["createPriority"] = (
76
- otds_base_url
77
- + "/app/entityRestService/api/OpentextCaseManagement/entities/Priority?defaultinst_ct=abcd"
140
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/Priority?defaultinst_ct=abcd"
78
141
  )
79
142
  otawp_config["getAllPriorities"] = (
80
- otds_base_url
81
- + "/app/entityRestService/api/OpentextCaseManagement/entities/Priority/lists/PriorityList"
143
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/Priority/lists/PriorityList"
82
144
  )
83
145
 
84
146
  otawp_config["createCustomer"] = (
85
- otds_base_url
86
- + "/app/entityRestService/api/OpentextCaseManagement/entities/Customer?defaultinst_ct=abcd"
147
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/Customer?defaultinst_ct=abcd"
87
148
  )
88
- otawp_config["getAllCustomeres"] = (
89
- otds_base_url
90
- + "/app/entityRestService/api/OpentextCaseManagement/entities/Customer/lists/CustomerList"
149
+ otawp_config["getAllCustomers"] = (
150
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/Customer/lists/CustomerList"
91
151
  )
92
152
 
93
153
  otawp_config["createCaseType"] = (
94
- otds_base_url
95
- + "/app/entityRestService/api/OpentextCaseManagement/entities/CaseType?defaultinst_ct=abcd"
154
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/CaseType?defaultinst_ct=abcd"
96
155
  )
97
156
  otawp_config["getAllCaseTypes"] = (
98
- otds_base_url
99
- + "/app/entityRestService/api/OpentextCaseManagement/entities/CaseType/lists/AllCaseTypes"
157
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/CaseType/lists/AllCaseTypes"
100
158
  )
101
159
 
102
160
  otawp_config["createCategory"] = (
103
- otds_base_url
104
- + "/app/entityRestService/api/OpentextCaseManagement/entities/Category?defaultinst_ct=abcd"
161
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/Category?defaultinst_ct=abcd"
105
162
  )
106
163
  otawp_config["getAllCategories"] = (
107
- otds_base_url
108
- + "/app/entityRestService/api/OpentextCaseManagement/entities/Category/lists/CategoryList"
164
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/Category/lists/CategoryList"
109
165
  )
110
166
 
111
167
  otawp_config["createSource"] = (
112
- otds_base_url
113
- + "/app/entityRestService/api/OpentextCaseManagement/entities/Source"
168
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/Source"
114
169
  )
115
170
 
116
171
  otawp_config["getAllSources"] = (
117
- otds_base_url
118
- + "/app/entityRestService/api/OpentextCaseManagement/entities/Source/lists/AllSources"
172
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/Source/lists/AllSources"
119
173
  )
120
174
 
121
175
  otawp_config["getAllSubCategories"] = (
122
- otds_base_url
176
+ otawp_base_url
123
177
  + "/app/entityRestService/api/OpentextCaseManagement/entities/Category/childEntities/SubCategory/lists/AllSubcategories"
124
178
  )
125
179
 
126
- otawp_config["baseurl"] = (
127
- otds_base_url
128
- + ""
129
- )
180
+ otawp_config["baseurl"] = otawp_base_url + ""
130
181
  otawp_config["createLoan"] = (
131
- otds_base_url
132
- + "/app/entityRestService/api/OpentextCaseManagement/entities/Case?defaultinst_ct=abcd"
182
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/Case?defaultinst_ct=abcd"
133
183
  )
134
184
  otawp_config["getAllLoans"] = (
135
- otds_base_url
136
- + "/app/entityRestService/api/OpentextCaseManagement/entities/Case/lists/AllCasesList"
185
+ otawp_base_url + "/app/entityRestService/api/OpentextCaseManagement/entities/Case/lists/AllCasesList"
137
186
  )
138
187
  self._config = otawp_config
139
188
 
140
189
  # end method definition
141
190
 
142
- def baseurl(self) -> dict:
143
- """Returns the configuration dictionary
191
+ def server(self) -> str:
192
+ """Return server information.
193
+
144
194
  Returns:
145
- dict: Configuration dictionary
195
+ str:
196
+ Server configuration.
197
+
146
198
  """
199
+
200
+ return self.config()["server"]
201
+
202
+ # end method definition
203
+
204
+ def set_organization(self, organization: str) -> None:
205
+ """Set the organization context.
206
+
207
+ Args:
208
+ organization (str):
209
+ Organization name.
210
+
211
+ """
212
+
213
+ otawp_base_url = f"/home/{organization}"
214
+ otawp_url = self.server() + otawp_base_url
215
+ ldap_root = (
216
+ f"com.eibus.web.soap.Gateway.wcp?organization=o={organization},cn=cordys,cn=defaultInst,o=opentext.net"
217
+ )
218
+
219
+ # Assign to self._config if that's where you store configuration data
220
+ self._config["gatewayAuthenticationUrl"] = otawp_url + f"/com.eibus.web.soap.Gateway.wcp?{ldap_root}"
221
+
222
+ self._config["soapGatewayUrl"] = otawp_url + f"/com.eibus.web.soap.Gateway.wcp?{ldap_root}&defaultinst_ct=abcd"
223
+
224
+ self.logger.info("Organization set to '%s'.", organization)
225
+
226
+ # end method definition
227
+
228
+ def baseurl(self) -> str:
229
+ """Return the configuration dictionary.
230
+
231
+ Returns:
232
+ str:
233
+ Base URL of AppWorks Platform.
234
+
235
+ """
236
+
147
237
  return self.config()["baseurl"]
148
238
 
149
239
  # end method definition
150
240
 
241
+ def license_file(self) -> str:
242
+ """Return the license_file.
243
+
244
+ Returns:
245
+ str:
246
+ Returns license_file
247
+
248
+ """
249
+
250
+ return self.config()["license_file"]
251
+
252
+ # end method definition
253
+
254
+ def product_name(self) -> str:
255
+ """Return the product_name.
256
+
257
+ Returns:
258
+ str:
259
+ Returns product_name
260
+
261
+ """
262
+
263
+ return self.config()["product_name"]
264
+
265
+ # end method definition
266
+
267
+ def product_description(self) -> str:
268
+ """Return the product_description.
269
+
270
+ Returns:
271
+ str:
272
+ Returns product_description
273
+
274
+ """
275
+
276
+ return self.config()["product_description"]
277
+
278
+ # end method definition
279
+
280
+ def hostname(self) -> str:
281
+ """Return hostname.
282
+
283
+ Returns:
284
+ str: Returns hostname
285
+
286
+ """
287
+
288
+ return self.config()["hostname"]
289
+
290
+ def username(self) -> str:
291
+ """Return username.
292
+
293
+ Returns:
294
+ str: Returns username
295
+
296
+ """
297
+ return self.config()["username"]
298
+
299
+ # end method definition
300
+
301
+ def password(self) -> str:
302
+ """Return password.
303
+
304
+ Returns:
305
+ str: Returns password
306
+
307
+ """
308
+ return self.config()["password"]
309
+
310
+ # end method definition
311
+
312
+ def otcs_partition_name(self) -> str:
313
+ """Return OTCS partition name.
314
+
315
+ Returns:
316
+ str: Returns OTCS partition name
317
+
318
+ """
319
+ return self.config()["otcs_partition_name"]
320
+
321
+ # end method definition
322
+
323
+ def otds_admin_partition_mame(self) -> str:
324
+ """Return OTDS admin partition name.
325
+
326
+ Returns:
327
+ str:
328
+ Returns OTDS admin partition mame.
329
+
330
+ """
331
+
332
+ return self.config()["otds_admin_partition_mame"]
333
+
334
+ # end method definition
335
+
336
+ def config_map_name(self) -> str:
337
+ """Return config map name.
338
+
339
+ Returns:
340
+ str:
341
+ Returns config map name
342
+
343
+ """
344
+ return self.config()["config_map_name"]
345
+
346
+ # end method definition
347
+
348
+ def otcs_resource_id(self) -> str:
349
+ """Return OTCS resource ID.
350
+
351
+ Returns:
352
+ str:
353
+ Returns otcs resource id
354
+
355
+ """
356
+ return self.config()["otcs_resource_id"]
357
+
358
+ # end method definition
359
+
360
+ def otcs_url(self) -> str:
361
+ """Return OTCS URL.
362
+
363
+ Returns:
364
+ str:
365
+ Returns the OTCS URL.
366
+
367
+ """
368
+ return self.config()["otcs_url"]
369
+
370
+ # end method definition
371
+
372
+ def otds_url(self) -> str:
373
+ """Return the OTDS URL.
374
+
375
+ Returns:
376
+ str:
377
+ Returns otds url
378
+
379
+ """
380
+ return self.config()["otds_url"]
381
+
382
+ # end method definition
383
+
384
+ def otcs_base_path(self) -> str:
385
+ """Return the OTCS base path.
386
+
387
+ Returns:
388
+ str: Returns otcs base path
389
+
390
+ """
391
+ return self.config()["otcs_base_path"]
392
+
393
+ # end method definition
394
+
151
395
  def config(self) -> dict:
152
- """Returns the configuration dictionary
396
+ """Return the configuration dictionary.
397
+
153
398
  Returns:
154
399
  dict: Configuration dictionary
400
+
155
401
  """
402
+
156
403
  return self._config
157
404
 
158
405
  # end method definition
159
406
 
160
407
  def cookie(self) -> dict:
161
- """Returns the login cookie of OTAWP.
162
- This is set by the authenticate() method
408
+ """Return the login cookie of OTAWP.
409
+
410
+ This is set by the authenticate() method
411
+
163
412
  Returns:
164
- dict: OTAWP cookie
413
+ dict:
414
+ OTAWP cookie
415
+
165
416
  """
417
+
166
418
  return self._cookie
167
419
 
168
420
  # end method definition
169
421
 
170
422
  def credentials(self) -> str:
171
- """Returns the SOAP payload with credentials (username and password)
423
+ """Return the SOAP payload with credentials (username and password).
424
+
172
425
  Returns:
173
- str: SOAP payload with username and password
426
+ str:
427
+ SOAP payload with username and password.
428
+
174
429
  """
430
+
175
431
  username = self.config()["username"]
176
432
  password = self.config()["password"]
177
433
 
@@ -199,146 +455,196 @@ class OTAWP:
199
455
  </SOAP:Body>
200
456
  </SOAP:Envelope>
201
457
  """
458
+
202
459
  return soap_payload
203
460
 
204
461
  # end method definition
205
462
 
206
463
  def credential_url(self) -> str:
207
- """Returns the Credentials URL of OTAWP
464
+ """Return the Credentials URL of OTAWP.
208
465
 
209
466
  Returns:
210
467
  str: Credentials URL
468
+
211
469
  """
470
+
212
471
  return self.config()["gatewayAuthenticationUrl"]
213
472
 
214
473
  # end method definition
215
474
 
216
475
  def gateway_url(self) -> str:
217
- """Returns soapGatewayUrl URL of OTAWP
476
+ """Return SOAP gateway URL of OTAWP.
218
477
 
219
478
  Returns:
220
- str: soapGatewayUrl URL
479
+ str:
480
+ The SOAP gateway URL.
481
+
221
482
  """
483
+
222
484
  return self.config()["soapGatewayUrl"]
223
485
 
224
486
  # end method definition
225
487
 
226
488
  def create_priority_url(self) -> str:
227
- """Returns createPriority URL of OTAWP
489
+ """Return create priority URL of OTAWP.
228
490
 
229
491
  Returns:
230
492
  str: createPriority URL
493
+
231
494
  """
495
+
232
496
  return self.config()["createPriority"]
233
497
 
234
498
  # end method definition
235
499
 
236
500
  def get_all_priorities_url(self) -> str:
237
- """Returns getAllPriorities URL of OTAWP
501
+ """Return get all priorities URL of OTAWP.
238
502
 
239
503
  Returns:
240
- str: getAllPriorities URL
504
+ str:
505
+ The getAllPriorities URL of OTAWP.
506
+
241
507
  """
508
+
242
509
  return self.config()["getAllPriorities"]
243
510
 
244
511
  # end method definition
245
512
 
246
513
  def create_customer_url(self) -> str:
247
- """Returns createCustomer URL of OTAWP
514
+ """Return create customer URL of OTAWP.
248
515
 
249
516
  Returns:
250
- str: createCustomer url
517
+ str:
518
+ The create customer URL.
519
+
251
520
  """
521
+
252
522
  return self.config()["createCustomer"]
253
523
 
254
524
  # end method definition
255
525
 
256
526
  def get_all_customeres_url(self) -> str:
257
- """Returns getAllCustomeres url of OTAWP
527
+ """Return get all customers URL of OTAWP.
258
528
 
259
529
  Returns:
260
- str: getAllCustomeres url
530
+ str:
531
+ The get all customers URL.
532
+
261
533
  """
262
- return self.config()["getAllCustomeres"]
534
+
535
+ return self.config()["getAllCustomers"]
263
536
 
264
537
  # end method definition
265
538
 
266
539
  def create_casetype_url(self) -> str:
267
- """Returns createCaseType url of OTAWP
540
+ """Return create case type URL of OTAWP.
268
541
 
269
542
  Returns:
270
- str: createCaseType url
543
+ str:
544
+ The create case type URL.
545
+
271
546
  """
547
+
272
548
  return self.config()["createCaseType"]
273
549
 
274
550
  # end method definition
275
551
 
276
552
  def get_all_case_types_url(self) -> str:
277
- """Returns getAllCaseTypes URL of OTAWP
553
+ """Return get all case types URL of OTAWP.
278
554
 
279
555
  Returns:
280
- str: getAllCaseTypes URL
556
+ str:
557
+ The get all case types URL.
558
+
281
559
  """
560
+
282
561
  return self.config()["getAllCaseTypes"]
283
562
 
284
563
  # end method definition
285
564
 
286
565
  def create_category_url(self) -> str:
287
- """Returns createCategory URL of OTAWP
566
+ """Return create category URL of OTAWP.
288
567
 
289
568
  Returns:
290
- str: createCategory URL
569
+ str:
570
+ The create category URL.
571
+
291
572
  """
573
+
292
574
  return self.config()["createCategory"]
293
575
 
294
576
  # end method definition
295
577
 
296
578
  def get_all_categories_url(self) -> str:
297
- """Returns the getAllCategories URL of OTAWP
579
+ """Return the get all categories URL of OTAWP.
298
580
 
299
581
  Returns:
300
- str: getAllCategories URL
582
+ str:
583
+ The get all categories URL.
584
+
301
585
  """
586
+
302
587
  return self.config()["getAllCategories"]
303
588
 
304
589
  # end method definition
305
590
 
306
591
  def get_all_loans_url(self) -> str:
307
- """Returns getAllLoans URL of OTAWP
592
+ """Return get all loans URL of OTAWP.
308
593
 
309
594
  Returns:
310
- str: getAllLoans URL
595
+ str:
596
+ The get all loans URL.
597
+
311
598
  """
599
+
312
600
  return self.config()["getAllLoans"]
313
601
 
314
602
  # end method definition
315
603
 
316
- def remove_namespace(self, tag):
604
+ def remove_namespace(self, tag: str) -> str:
317
605
  """Remove namespace from XML tag."""
318
- return tag.split('}', 1)[-1]
606
+
607
+ return tag.split("}", 1)[-1]
319
608
 
320
609
  # end method definition
321
610
 
322
- def parse_xml(self, xml_string):
611
+ def parse_xml(self, xml_string: str) -> dict:
323
612
  """Parse XML string and return a dictionary without namespaces."""
324
- def element_to_dict(element):
613
+
614
+ def element_to_dict(element) -> dict: # noqa: ANN001
325
615
  """Convert XML element to dictionary."""
326
616
  tag = self.remove_namespace(element.tag)
327
617
  children = list(element)
328
618
  if children:
329
- return {tag: {self.remove_namespace(child.tag): element_to_dict(child) for child in children}}
619
+ return {
620
+ tag: {self.remove_namespace(child.tag): element_to_dict(child) for child in children},
621
+ }
330
622
  return {tag: element.text.strip() if element.text else None}
623
+
331
624
  root = ET.fromstring(xml_string)
625
+
332
626
  return element_to_dict(root)
333
627
 
334
628
  # end method definition
335
629
 
336
- def find_key(self, data, target_key):
337
- """Recursively search for a key in a nested dictionary and return its value."""
630
+ def find_key(self, data: dict | list, target_key: str) -> str:
631
+ """Recursively search for a key in a nested dictionary and return its value.
632
+
633
+ Args:
634
+ data (dict | list):
635
+ TODO: _description_
636
+ target_key (str):
637
+ TODO: _description_
638
+
639
+ Returns:
640
+ _type_: _description_
641
+
642
+ """
643
+
338
644
  if isinstance(data, dict):
339
645
  if target_key in data:
340
646
  return data[target_key]
341
- for _, value in data.items():
647
+ for value in data.values():
342
648
  result = self.find_key(value, target_key)
343
649
  if result is not None:
344
650
  return result
@@ -347,6 +653,7 @@ class OTAWP:
347
653
  result = self.find_key(item, target_key)
348
654
  if result is not None:
349
655
  return result
656
+
350
657
  return None
351
658
 
352
659
  # end method definition
@@ -357,20 +664,26 @@ class OTAWP:
357
664
  additional_error_message: str = "",
358
665
  show_error: bool = True,
359
666
  ) -> dict | None:
360
- """Converts the text property of a request response object to a Python dict in a safe way
361
- that also handles exceptions.
667
+ """Convert the text property of a request response object to a Python dict in a safe way.
668
+
669
+ Properly handle exceptions.
362
670
 
363
- Content Server may produce corrupt response when it gets restarted
364
- or hitting resource limits. So we try to avoid a fatal error and bail
365
- out more gracefully.
671
+ AppWorks may produce corrupt response when it gets restarted
672
+ or hitting resource limits. So we try to avoid a fatal error and bail
673
+ out more gracefully.
366
674
 
367
675
  Args:
368
- response_object (object): this is reponse object delivered by the request call
369
- additional_error_message (str): print a custom error message
370
- show_error (bool): if True log an error, if False log a warning
676
+ response_object (object):
677
+ This is reponse object delivered by the request call.
678
+ additional_error_message (str):
679
+ Print a custom error message.
680
+ show_error (bool):
681
+ If True log an error, if False log a warning.
371
682
 
372
683
  Returns:
373
- dict: response or None in case of an error
684
+ dict:
685
+ Response or None in case of an error.
686
+
374
687
  """
375
688
 
376
689
  if not response_object:
@@ -381,34 +694,39 @@ class OTAWP:
381
694
  except json.JSONDecodeError as exception:
382
695
  if additional_error_message:
383
696
  message = "Cannot decode response as JSon. {}; error -> {}".format(
384
- additional_error_message, exception
697
+ additional_error_message,
698
+ exception,
385
699
  )
386
700
  else:
387
701
  message = "Cannot decode response as JSon; error -> {}".format(
388
- exception
702
+ exception,
389
703
  )
390
704
  if show_error:
391
- logger.error(message)
705
+ self.logger.error(message)
392
706
  else:
393
- logger.warning(message)
707
+ self.logger.warning(message)
394
708
  return None
395
709
  return dict_object
396
710
 
397
711
  # end method definition
398
712
 
399
713
  def authenticate(self, revalidate: bool = False) -> dict | None:
400
- """Authenticate at appworks.
714
+ """Authenticate at AppWorks.
401
715
 
402
716
  Args:
403
- revalidate (bool, optional): determine if a re-authentication is enforced
404
- (e.g. if session has timed out with 401 error)
717
+ revalidate (bool, optional):
718
+ Determine if a re-authentication is enforced
719
+ (e.g. if session has timed out with 401 error).
720
+
405
721
  Returns:
406
- dict: Cookie information. Also stores cookie information in self._cookie
722
+ dict:
723
+ Cookie information. Also stores cookie information in self._cookie
724
+
407
725
  """
408
726
 
409
- logger.info("SAMLart generation started")
727
+ self.logger.info("SAMLart generation started")
410
728
  if self._cookie and not revalidate:
411
- logger.info(
729
+ self.logger.debug(
412
730
  "Session still valid - return existing cookie -> %s",
413
731
  str(self._cookie),
414
732
  )
@@ -423,30 +741,34 @@ class OTAWP:
423
741
  url=self.credential_url(),
424
742
  data=self.credentials(),
425
743
  headers=REQUEST_HEADERS,
426
- timeout=REQUEST_TIMEOUT
744
+ timeout=REQUEST_TIMEOUT,
427
745
  )
428
746
  except requests.exceptions.RequestException as exception:
429
- logger.warning(
430
- "Unable to connect to -> %s; error -> %s",
747
+ self.logger.warning(
748
+ "Unable to connect to OTAWP authentication endpoint -> %s; error -> %s",
431
749
  self.credential_url(),
432
- exception.strerror,
750
+ str(exception),
433
751
  )
434
- logger.warning("OTAWP service may not be ready yet.")
752
+ self.logger.warning("OTAWP service may not be ready yet.")
435
753
  return None
436
754
 
437
755
  if response.ok:
438
- logger.info("SAMLart generated successfully")
756
+ self.logger.info("SAMLart generated successfully")
439
757
  authenticate_dict = self.parse_xml(response.text)
440
758
  if not authenticate_dict:
441
759
  return None
442
760
  assertion_artifact_dict = self.find_key(
443
- authenticate_dict, "AssertionArtifact"
761
+ authenticate_dict,
762
+ "AssertionArtifact",
444
763
  )
445
764
  if isinstance(assertion_artifact_dict, dict):
446
765
  otawp_ticket = assertion_artifact_dict.get("AssertionArtifact")
447
- logger.info("SAML token -> %s", otawp_ticket)
766
+ self.logger.debug("SAML token -> %s", otawp_ticket)
448
767
  else:
449
- logger.error("Failed to request an OTAWP ticket; error -> %s", response.text)
768
+ self.logger.error(
769
+ "Failed to request an OTAWP ticket; error -> %s",
770
+ response.text,
771
+ )
450
772
  return None
451
773
 
452
774
  self._cookie = {"defaultinst_SAMLart": otawp_ticket, "defaultinst_ct": "abcd"}
@@ -456,21 +778,23 @@ class OTAWP:
456
778
 
457
779
  # end method definition
458
780
 
459
- def create_workspace(
460
- self,
461
- workspace_name: str,
462
- workspace_id: str
463
- ) -> dict | None:
464
- """Creates a workspace in cws
781
+ def create_workspace(self, workspace_name: str, workspace_id: str) -> dict | None:
782
+ """Create a workspace in cws.
783
+
465
784
  Args:
466
- workspace_name (str): workspace_name
467
- workspace_id (str): workspace_id
785
+ workspace_name (str):
786
+ The name of the workspace.
787
+ workspace_id (str):
788
+ The ID of the workspace.
789
+
468
790
  Returns:
469
- response test or error text
791
+ dict | None:
792
+ Response dictionary or error text
793
+
470
794
  """
471
795
 
472
- logger.info(
473
- "Create workspace with name -> '%s' and ID -> %s...",
796
+ self.logger.info(
797
+ "Create workspace -> '%s' (%s)...",
474
798
  workspace_name,
475
799
  workspace_id,
476
800
  )
@@ -567,10 +891,10 @@ class OTAWP:
567
891
  data=license_post_body_json,
568
892
  headers=REQUEST_HEADERS,
569
893
  cookies=self.cookie(),
570
- timeout=None,
894
+ timeout=REQUEST_TIMEOUT,
571
895
  )
572
896
  if response.ok:
573
- logger.info(
897
+ self.logger.info(
574
898
  "Successfully created workspace -> '%s' with ID -> %s",
575
899
  workspace_name,
576
900
  workspace_id,
@@ -578,69 +902,105 @@ class OTAWP:
578
902
  return response.text
579
903
  # Check if Session has expired - then re-authenticate and try once more
580
904
  if response.status_code == 401 and retries == 0:
581
- logger.warning("Session has expired - try to re-authenticate...")
905
+ self.logger.warning("Session has expired - try to re-authenticate...")
582
906
  self.authenticate(revalidate=True)
583
907
  retries += 1
584
- logger.error(response.text)
908
+ self.logger.error(response.text)
585
909
  return response.text
586
910
 
587
911
  # end method definition
588
912
 
589
- def sync_workspace(
590
- self,
591
- workspace_name: str,
592
- workspace_id: str
593
- ) -> dict | None:
594
- """ sync workspaces
913
+ def sync_workspace(self, workspace_name: str, workspace_id: str) -> dict | None:
914
+ """Synchronize workspace.
915
+
595
916
  Args:
596
- workspace_name (str): workspace_name
597
- workspace_id (str): workspace_id
917
+ workspace_name (str):
918
+ The name of the workspace.
919
+ workspace_id (str):
920
+ The ID of the workspace.
921
+
598
922
  Returns:
599
- Request response (dictionary) or None if the REST call fails
923
+ dict | None:
924
+ Parsed response as a dictionary if successful, None otherwise.
925
+
600
926
  """
601
927
 
602
- logger.info("Start synchronization of workspace -> '%s'...", workspace_name)
928
+ self.logger.info(
929
+ "Starting synchronization of workspace -> '%s'...",
930
+ workspace_name,
931
+ )
603
932
 
604
- license_post_body_json = f"""<SOAP:Envelope xmlns:SOAP=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n" +
605
- " <SOAP:Body>\r\n" +
606
- " <Synchronize workspaceID=\"{workspace_id}\" xmlns=\"http://schemas.cordys.com/cws/synchronize/1.0\" >\r\n" +
607
- " <DocumentID/>\r\n" +
608
- " <Asynchronous>false</Asynchronous>\r\n" +
609
- " </Synchronize>\r\n" +
610
- " </SOAP:Body>\r\n" +
611
- "</SOAP:Envelope>"""
612
- # self.authenticate(revalidate=True)
933
+ # SOAP request body
934
+ license_post_body_json = f"""
935
+ <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
936
+ <SOAP:Body>
937
+ <Synchronize workspaceID="{workspace_id}" xmlns="http://schemas.cordys.com/cws/synchronize/1.0">
938
+ <DocumentID/>
939
+ <Asynchronous>false</Asynchronous>
940
+ </Synchronize>
941
+ </SOAP:Body>
942
+ </SOAP:Envelope>
943
+ """
613
944
 
614
945
  retries = 0
615
- while True:
616
- response = requests.post(
617
- url=self.gateway_url(),
618
- data=license_post_body_json,
619
- headers=REQUEST_HEADERS,
620
- cookies=self.cookie(),
621
- timeout=None,
622
- )
623
- if response.ok:
624
- logger.info("Workspace -> '%s' synced successfully", workspace_name)
625
- return self.parse_xml(response.text)
626
- if response.status_code == 401 and retries == 0:
627
- logger.warning("Session has expired - try to re-authenticate...")
628
- self.authenticate(revalidate=True)
946
+ max_retries = 6
947
+ retry_delay = 60
948
+
949
+ while retries < max_retries:
950
+ try:
951
+ response = requests.post(
952
+ url=self.gateway_url(),
953
+ data=license_post_body_json,
954
+ headers=REQUEST_HEADERS,
955
+ cookies=self.cookie(),
956
+ timeout=SYNC_PUBLISH_REQUEST_TIMEOUT,
957
+ )
958
+
959
+ if response.ok:
960
+ self.logger.info(
961
+ "Workspace -> '%s' synchronized successfully.",
962
+ workspace_name,
963
+ )
964
+ return self.parse_xml(response.text)
965
+
966
+ if response.status_code == 401:
967
+ self.logger.warning("Session expired. Re-authenticating...")
968
+ self.authenticate(revalidate=True)
969
+ retries += 1
970
+ continue
971
+
972
+ if "faultcode" in response.text or "FaultDetails" in response.text:
973
+ self.logger.warning("SOAP fault occurred: %s", response.text)
974
+ retries += 1
975
+ time.sleep(retry_delay)
976
+ continue
977
+
978
+ self.logger.error("Unexpected error during sync: %s", response.text)
979
+ time.sleep(retry_delay)
629
980
  retries += 1
630
- logger.error(response.text)
631
- return None
981
+
982
+ except requests.RequestException:
983
+ self.logger.error("Sync failed with error. Proceeding with retry...")
984
+ time.sleep(retry_delay)
985
+ retries += 1
986
+
987
+ self.logger.error(
988
+ "Synchronization failed for workspace -> '%s' after %d retries.",
989
+ workspace_name,
990
+ retries,
991
+ )
992
+ return None
632
993
 
633
994
  # end method definition
634
995
 
635
996
  def publish_project(
636
- self,
637
- workspace_name: str,
638
- project_name: str,
639
- workspace_id: str,
640
- project_id: str
641
- ) -> dict | bool:
642
- """
643
- Publish the workspace project.
997
+ self,
998
+ workspace_name: str,
999
+ project_name: str,
1000
+ workspace_id: str,
1001
+ project_id: str,
1002
+ ) -> dict | bool:
1003
+ """Publish the workspace project.
644
1004
 
645
1005
  Args:
646
1006
  workspace_name (str): The name of the workspace.
@@ -650,9 +1010,10 @@ class OTAWP:
650
1010
 
651
1011
  Returns:
652
1012
  dict | bool: Request response (dictionary) if successful, False if it fails after retries.
1013
+
653
1014
  """
654
1015
 
655
- logger.info(
1016
+ self.logger.info(
656
1017
  "Publish project -> '%s' in workspace -> '%s'...",
657
1018
  project_name,
658
1019
  workspace_name,
@@ -674,54 +1035,57 @@ class OTAWP:
674
1035
  success_indicator = "deployObjectResponse"
675
1036
 
676
1037
  while retries < max_retries:
677
- response = requests.post(
678
- url=self.gateway_url(),
679
- data=project_publish,
680
- headers=REQUEST_HEADERS,
681
- cookies=self.cookie(),
682
- timeout=None,
683
- )
1038
+ try:
1039
+ response = requests.post(
1040
+ url=self.gateway_url(),
1041
+ data=project_publish,
1042
+ headers=REQUEST_HEADERS,
1043
+ cookies=self.cookie(),
1044
+ timeout=SYNC_PUBLISH_REQUEST_TIMEOUT,
1045
+ )
684
1046
 
685
- # Check if the response is successful
686
- if response.ok:
687
- # Check if the response contains the success indicator
688
- if success_indicator in response.text:
689
- logger.info(
690
- "Successfully published project -> '%s' in workspace -> '%s'",
691
- project_name,
692
- workspace_name,
1047
+ # Check if the response is successful
1048
+ if response.ok:
1049
+ if success_indicator in response.text:
1050
+ self.logger.info(
1051
+ "Successfully published project -> '%s' in workspace -> '%s'",
1052
+ project_name,
1053
+ workspace_name,
1054
+ )
1055
+ return True
1056
+ else:
1057
+ self.logger.warning(
1058
+ "Expected success indicator -> '%s' but it was not found in response. Retrying in 30 seconds... (Attempt %d of %d)",
1059
+ success_indicator,
1060
+ retries + 1,
1061
+ max_retries,
1062
+ )
1063
+ elif response.status_code == 401:
1064
+ # Check for session expiry and retry authentication
1065
+ self.logger.warning("Session has expired - re-authenticating...")
1066
+ self.authenticate(revalidate=True)
1067
+ else:
1068
+ self.logger.error(
1069
+ "Unexpected error (status code %d). Retrying in 30 seconds... (Attempt %d of %d)",
1070
+ response.status_code,
1071
+ retries + 1,
1072
+ max_retries,
693
1073
  )
694
- return True
695
-
696
- # If success indicator is not found, retry
697
- logger.warning(
698
- "Expected success indicator -> '%s' but it was not found in response. Retrying in 30 seconds... (Attempt %d of %d)",
699
- success_indicator,
700
- retries + 1,
701
- max_retries,
702
- )
703
- time.sleep(30)
1074
+ self.logger.error(
1075
+ "Error details: %s",
1076
+ response.text,
1077
+ )
1078
+ self.sync_workspace(workspace_name, workspace_id)
704
1079
  retries += 1
705
- continue
1080
+ time.sleep(30)
706
1081
 
707
- # Check for session expiry and retry authentication (only once)
708
- if response.status_code == 401 and retries == 0:
709
- logger.warning("Session has expired - re-authenticating...")
710
- self.authenticate(revalidate=True)
1082
+ except requests.RequestException:
1083
+ self.logger.error("Sync failed with error. Proceeding with retry...")
711
1084
  retries += 1
712
- continue
713
-
714
- # Log any other error and break the loop
715
- logger.error(
716
- "Error publishing project -> '%s' in workspace -> '%s'; response -> %s",
717
- project_name,
718
- workspace_name,
719
- response.text,
720
- )
721
- break
1085
+ time.sleep(30)
722
1086
 
723
1087
  # After reaching the maximum number of retries, log failure and return False
724
- logger.error(
1088
+ self.logger.error(
725
1089
  "Max retries reached. Failed to publish project -> '%s' in workspace -> '%s'.",
726
1090
  project_name,
727
1091
  workspace_name,
@@ -730,27 +1094,21 @@ class OTAWP:
730
1094
 
731
1095
  # end method definition
732
1096
 
733
- def create_priority(
734
- self,
735
- name: str,
736
- description: str,
737
- status: int
738
- ) -> dict | None:
739
- """ Create Priority entity instances.
1097
+ def create_priority(self, name: str, description: str, status: int) -> dict | None:
1098
+ """Create Priority entity instances.
740
1099
 
741
1100
  Args:
742
1101
  name (str): name
743
1102
  description (str): description
744
1103
  status (int): status
1104
+
745
1105
  Returns:
746
- dict: Request response (dictionary) or None if the REST call fails
1106
+ dict:
1107
+ Request response (dictionary) or None if the REST call fails
1108
+
747
1109
  """
748
1110
  create_priority = {
749
- "Properties": {
750
- "Name": name,
751
- "Description": description,
752
- "Status": status
753
- }
1111
+ "Properties": {"Name": name, "Description": description, "Status": status},
754
1112
  }
755
1113
  retries = 0
756
1114
  while True:
@@ -759,51 +1117,58 @@ class OTAWP:
759
1117
  json=create_priority,
760
1118
  headers=REQUEST_HEADERS_JSON,
761
1119
  cookies=self.cookie(),
762
- timeout=None,
1120
+ timeout=REQUEST_TIMEOUT,
763
1121
  )
764
1122
  if response.ok:
765
- logger.info("Priority created successfully")
1123
+ self.logger.info("Priority created successfully")
766
1124
  return self.parse_request_response(
767
- response, "This can be normal during restart", False
1125
+ response_object=response,
1126
+ additional_error_message="This can be normal during restart",
1127
+ show_error=False,
768
1128
  )
769
1129
  if response.status_code == 401 and retries == 0:
770
- logger.warning("Session has expired - try to re-authenticate...")
1130
+ self.logger.warning("Session has expired - try to re-authenticate...")
771
1131
  self.authenticate(revalidate=True)
772
1132
  retries += 1
773
- logger.error(response.text)
1133
+ self.logger.error(response.text)
774
1134
  return None
775
1135
 
776
1136
  # end method definition
777
1137
 
778
- def get_all_priorities(
779
- self
780
- ) -> dict | None:
781
- """ Get all priorities from entity
1138
+ def get_all_priorities(self) -> dict | None:
1139
+ """Get all priorities from entity.
1140
+
782
1141
  Args:
783
1142
  None
1143
+
784
1144
  Returns:
785
- dict: Request response (dictionary) or None if the REST call fails
1145
+ dict:
1146
+ Request response (dictionary) or None if the REST call fails.
1147
+
786
1148
  """
1149
+
787
1150
  retries = 0
788
1151
  while True:
789
1152
  response = requests.get(
790
1153
  url=self.get_all_priorities_url(),
791
1154
  headers=REQUEST_HEADERS_JSON,
792
1155
  cookies=self.cookie(),
793
- timeout=None,
1156
+ timeout=REQUEST_TIMEOUT,
794
1157
  )
795
1158
  if response.ok:
796
1159
  authenticate_dict = self.parse_request_response(
797
- response, "This can be normal during restart", False
1160
+ response_object=response,
1161
+ additional_error_message="This can be normal during restart",
1162
+ show_error=False,
798
1163
  )
799
1164
  if not authenticate_dict:
800
1165
  return None
801
1166
  return authenticate_dict
802
1167
  if response.status_code == 401 and retries == 0:
803
- logger.warning("Session has expired - try to re-authenticate...")
1168
+ self.logger.warning("Session has expired - try to re-authenticate...")
804
1169
  self.authenticate(revalidate=True)
805
1170
  retries += 1
806
- logger.error(response.text)
1171
+ self.logger.error(response.text)
807
1172
  return None
808
1173
 
809
1174
  # end method definition
@@ -812,23 +1177,30 @@ class OTAWP:
812
1177
  self,
813
1178
  customer_name: str,
814
1179
  legal_business_name: str,
815
- trading_name: str
1180
+ trading_name: str,
816
1181
  ) -> dict | None:
817
- """ Create customer entity instance
1182
+ """Create customer entity instance.
818
1183
 
819
1184
  Args:
820
- customer_name (str): customer_name
821
- legal_business_name (str): legal_business_name
822
- trading_name (str): trading_name
1185
+ customer_name (str):
1186
+ The name of the customer.
1187
+ legal_business_name (str):
1188
+ The legal business name.
1189
+ trading_name (str):
1190
+ The trading name.
1191
+
823
1192
  Returns:
824
- dict: Request response (dictionary) or None if the REST call fails
1193
+ dict:
1194
+ Request response (dictionary) or None if the REST call fails.
1195
+
825
1196
  """
1197
+
826
1198
  create_customer = {
827
1199
  "Properties": {
828
- "CustomerName": customer_name,
829
- "LegalBusinessName": legal_business_name,
830
- "TradingName": trading_name
831
- }
1200
+ "CustomerName": customer_name,
1201
+ "LegalBusinessName": legal_business_name,
1202
+ "TradingName": trading_name,
1203
+ },
832
1204
  }
833
1205
  retries = 0
834
1206
  while True:
@@ -837,29 +1209,34 @@ class OTAWP:
837
1209
  json=create_customer,
838
1210
  headers=REQUEST_HEADERS_JSON,
839
1211
  cookies=self.cookie(),
840
- timeout=None,
1212
+ timeout=REQUEST_TIMEOUT,
841
1213
  )
842
1214
  if response.ok:
843
- logger.info("Customer record created successfully")
844
- return self.parse_request_response(response, "This can be normal during restart", False)
1215
+ self.logger.info("Customer record created successfully")
1216
+ return self.parse_request_response(
1217
+ response_object=response,
1218
+ additional_error_message="This can be normal during restart",
1219
+ show_error=False,
1220
+ )
845
1221
  if response.status_code == 401 and retries == 0:
846
- logger.warning("Session has expired - try to re-authenticate...")
1222
+ self.logger.warning("Session has expired - try to re-authenticate...")
847
1223
  self.authenticate(revalidate=True)
848
1224
  retries += 1
849
- logger.error(response.text)
1225
+ self.logger.error(response.text)
850
1226
  return None
851
1227
 
852
1228
  # end method definition
853
1229
 
854
- def get_all_customers(
855
- self
856
- ) -> dict | None:
857
- """get all customer entity imstances
1230
+ def get_all_customers(self) -> dict | None:
1231
+ """Get all customer entity imstances.
858
1232
 
859
1233
  Args:
860
1234
  None
1235
+
861
1236
  Returns:
862
- dict: Request response (dictionary) or None if the REST call fails
1237
+ dict:
1238
+ Request response (dictionary) or None if the REST call fails
1239
+
863
1240
  """
864
1241
 
865
1242
  retries = 0
@@ -868,45 +1245,44 @@ class OTAWP:
868
1245
  url=self.get_all_customeres_url(),
869
1246
  headers=REQUEST_HEADERS_JSON,
870
1247
  cookies=self.cookie(),
871
- timeout=None,
1248
+ timeout=REQUEST_TIMEOUT,
872
1249
  )
873
1250
  if response.ok:
874
1251
  authenticate_dict = self.parse_request_response(
875
- response, "This can be normal during restart", False
1252
+ response_object=response,
1253
+ additional_error_message="This can be normal during restart",
1254
+ show_error=False,
876
1255
  )
877
1256
  if not authenticate_dict:
878
1257
  return None
879
- return authenticate_dict
1258
+ return authenticate_dict
880
1259
  if response.status_code == 401 and retries == 0:
881
- logger.warning("Session has expired - try to re-authenticate...")
1260
+ self.logger.warning("Session has expired - try to re-authenticate...")
882
1261
  self.authenticate(revalidate=True)
883
1262
  retries += 1
884
- logger.error(response.text)
1263
+ self.logger.error(response.text)
885
1264
  return None
886
1265
 
887
1266
  # end method definition
888
1267
 
889
- def create_case_type(
890
- self,
891
- name: str,
892
- description: str,
893
- status: int
894
- ) -> dict | None:
895
- """create case_type entity instances
1268
+ def create_case_type(self, name: str, description: str, status: int) -> dict | None:
1269
+ """Create case type entity instances.
896
1270
 
897
1271
  Args:
898
- name (str): name
899
- description (str): description
1272
+ name (str):
1273
+ The name of the case type.
1274
+ description (str):
1275
+ The description of the case type.
900
1276
  status (str): status
1277
+
901
1278
  Returns:
902
- dict: Request response (dictionary) or None if the REST call fails
1279
+ dict:
1280
+ Request response (dictionary) or None if the REST call fails.
1281
+
903
1282
  """
1283
+
904
1284
  create_case_type = {
905
- "Properties": {
906
- "Name": name,
907
- "Description": description,
908
- "Status": status
909
- }
1285
+ "Properties": {"Name": name, "Description": description, "Status": status},
910
1286
  }
911
1287
  retries = 0
912
1288
  while True:
@@ -915,52 +1291,58 @@ class OTAWP:
915
1291
  json=create_case_type,
916
1292
  headers=REQUEST_HEADERS_JSON,
917
1293
  cookies=self.cookie(),
918
- timeout=None,
1294
+ timeout=REQUEST_TIMEOUT,
919
1295
  )
920
1296
  if response.ok:
921
- logger.info("Case type created successfully")
1297
+ self.logger.info("Case type created successfully")
922
1298
  return self.parse_request_response(
923
- response, "This can be normal during restart", False
1299
+ response_object=response,
1300
+ additional_error_message="This can be normal during restart",
1301
+ show_error=False,
924
1302
  )
925
1303
  if response.status_code == 401 and retries == 0:
926
- logger.warning("Session has expired - try to re-authenticate...")
1304
+ self.logger.warning("Session has expired - try to re-authenticate...")
927
1305
  self.authenticate(revalidate=True)
928
1306
  retries += 1
929
- logger.error(response.text)
1307
+ self.logger.error(response.text)
930
1308
  return None
931
1309
 
932
1310
  # end method definition
933
1311
 
934
- def get_all_case_type(
935
- self
936
- ) -> dict | None:
937
- """get all case type entty instances
1312
+ def get_all_case_type(self) -> dict | None:
1313
+ """Get all case type entty instances.
938
1314
 
939
1315
  Args:
940
1316
  None
1317
+
941
1318
  Returns:
942
- dict: Request response (dictionary) or None if the REST call fails
1319
+ dict:
1320
+ Request response (dictionary) or None if the REST call fails.
1321
+
943
1322
  """
1323
+
944
1324
  retries = 0
945
1325
  while True:
946
1326
  response = requests.get(
947
1327
  url=self.get_all_case_types_url(),
948
1328
  headers=REQUEST_HEADERS_JSON,
949
1329
  cookies=self.cookie(),
950
- timeout=None,
1330
+ timeout=REQUEST_TIMEOUT,
951
1331
  )
952
1332
  if response.ok:
953
1333
  authenticate_dict = self.parse_request_response(
954
- response, "This can be normal during restart", False
1334
+ response_object=response,
1335
+ additional_error_message="This can be normal during restart",
1336
+ show_error=False,
955
1337
  )
956
1338
  if not authenticate_dict:
957
1339
  return None
958
1340
  return authenticate_dict
959
1341
  if response.status_code == 401 and retries == 0:
960
- logger.warning("Session has expired - try to re-authenticate...")
1342
+ self.logger.warning("Session has expired - try to re-authenticate...")
961
1343
  self.authenticate(revalidate=True)
962
1344
  retries += 1
963
- logger.error(response.text)
1345
+ self.logger.error(response.text)
964
1346
  return None
965
1347
 
966
1348
  # end method definition
@@ -970,25 +1352,33 @@ class OTAWP:
970
1352
  case_prefix: str,
971
1353
  description: str,
972
1354
  name: str,
973
- status: int
1355
+ status: int,
974
1356
  ) -> dict | None:
975
- """create category entity instance
1357
+ """Create category entity instance.
976
1358
 
977
1359
  Args:
978
- case_prefix (str): workspace_name
979
- description (str): description
980
- name (str): name
981
- status (str): status
1360
+ case_prefix (str):
1361
+ The prefix for the case.
1362
+ description (str):
1363
+ The description for the category.
1364
+ name (str):
1365
+ The name of the case.
1366
+ status (int):
1367
+ The status code.
1368
+
982
1369
  Returns:
983
- dict: Request response (dictionary) or None if the REST call fails
1370
+ dict:
1371
+ Request response (dictionary) or None if the REST call fails.
1372
+
984
1373
  """
1374
+
985
1375
  create_categoty = {
986
1376
  "Properties": {
987
- "CasePrefix": case_prefix,
988
- "Description": description,
989
- "Name": name,
990
- "Status": status
991
- }
1377
+ "CasePrefix": case_prefix,
1378
+ "Description": description,
1379
+ "Name": name,
1380
+ "Status": status,
1381
+ },
992
1382
  }
993
1383
  retries = 0
994
1384
  while True:
@@ -997,29 +1387,33 @@ class OTAWP:
997
1387
  json=create_categoty,
998
1388
  headers=REQUEST_HEADERS_JSON,
999
1389
  cookies=self.cookie(),
1000
- timeout=None,
1390
+ timeout=REQUEST_TIMEOUT,
1001
1391
  )
1002
1392
  if response.ok:
1003
- logger.info("Category created successfully")
1004
- return self.parse_request_response(response, "This can be normal during restart", False)
1393
+ self.logger.info("Category created successfully")
1394
+ return self.parse_request_response(
1395
+ response_object=response,
1396
+ additional_error_message="This can be normal during restart",
1397
+ show_error=False,
1398
+ )
1005
1399
  if response.status_code == 401 and retries == 0:
1006
- logger.warning("Session has expired - try to re-authenticate...")
1400
+ self.logger.warning("Session has expired - try to re-authenticate...")
1007
1401
  self.authenticate(revalidate=True)
1008
1402
  retries += 1
1009
- logger.error(response.text)
1403
+ self.logger.error(response.text)
1010
1404
  return None
1011
1405
 
1012
1406
  # end method definition
1013
1407
 
1014
- def get_all_categories(
1015
- self
1016
- ) -> dict | None:
1017
- """Get all categories entity intances
1408
+ def get_all_categories(self) -> dict | None:
1409
+ """Get all categories entity intances.
1018
1410
 
1019
1411
  Args:
1020
1412
  None
1021
1413
  Returns:
1022
- dict: Request response (dictionary) or None if the REST call fails
1414
+ dict:
1415
+ Request response (dictionary) or None if the REST call fails.
1416
+
1023
1417
  """
1024
1418
 
1025
1419
  retries = 0
@@ -1028,20 +1422,22 @@ class OTAWP:
1028
1422
  url=self.get_all_categories_url(),
1029
1423
  headers=REQUEST_HEADERS_JSON,
1030
1424
  cookies=self.cookie(),
1031
- timeout=None,
1425
+ timeout=REQUEST_TIMEOUT,
1032
1426
  )
1033
1427
  if response.ok:
1034
1428
  authenticate_dict = self.parse_request_response(
1035
- response, "This can be normal during restart", False
1429
+ response_object=response,
1430
+ additional_error_message="This can be normal during restart",
1431
+ show_error=False,
1036
1432
  )
1037
1433
  if not authenticate_dict:
1038
1434
  return None
1039
- return authenticate_dict
1435
+ return authenticate_dict
1040
1436
  if response.status_code == 401 and retries == 0:
1041
- logger.warning("Session has expired - try to re-authenticate...")
1437
+ self.logger.warning("Session has expired - try to re-authenticate...")
1042
1438
  self.authenticate(revalidate=True)
1043
1439
  retries += 1
1044
- logger.error(response.text)
1440
+ self.logger.error(response.text)
1045
1441
  return None
1046
1442
 
1047
1443
  # end method definition
@@ -1051,24 +1447,28 @@ class OTAWP:
1051
1447
  name: str,
1052
1448
  description: str,
1053
1449
  status: int,
1054
- parentid: int
1450
+ parent_id: int,
1055
1451
  ) -> dict | None:
1056
- """ create sub_categoy entity istances
1452
+ """Create sub categoy entity instances.
1057
1453
 
1058
1454
  Args:
1059
- name (str): name
1060
- description (str): description
1061
- status (int): status
1062
- parentid (int): parentid
1455
+ name (str):
1456
+ The name of the sub-category.
1457
+ description (str):
1458
+ The description for the sub-category.
1459
+ status (int):
1460
+ The status ID.
1461
+ parent_id (int):
1462
+ The parent ID of the category.
1463
+
1063
1464
  Returns:
1064
- dict: Request response (dictionary) or None if the REST call fails
1465
+ dict:
1466
+ Request response (dictionary) or None if the REST call fails.
1467
+
1065
1468
  """
1469
+
1066
1470
  create_sub_categoty = {
1067
- "Properties": {
1068
- "Name": name,
1069
- "Description": description,
1070
- "Status": status
1071
- }
1471
+ "Properties": {"Name": name, "Description": description, "Status": status},
1072
1472
  }
1073
1473
  retries = 0
1074
1474
  while True:
@@ -1076,60 +1476,66 @@ class OTAWP:
1076
1476
  endpoint = "/app/entityRestService/api/OpentextCaseManagement/entities/Category/items/"
1077
1477
  child_path = "/childEntities/SubCategory?defaultinst_ct=abcd"
1078
1478
  response = requests.post(
1079
- url=base_url + endpoint + str(parentid) + child_path,
1479
+ url=base_url + endpoint + str(parent_id) + child_path,
1080
1480
  json=create_sub_categoty,
1081
1481
  headers=REQUEST_HEADERS_JSON,
1082
1482
  cookies=self.cookie(),
1083
- timeout=None,
1483
+ timeout=REQUEST_TIMEOUT,
1084
1484
  )
1085
1485
  if response.ok:
1086
- logger.info("Sub category created successfully")
1486
+ self.logger.info("Sub category created successfully")
1087
1487
  return self.parse_request_response(
1088
- response, "This can be normal during restart", False
1488
+ response_object=response,
1489
+ additional_error_message="This can be normal during restart",
1490
+ show_error=False,
1089
1491
  )
1090
1492
  if response.status_code == 401 and retries == 0:
1091
- logger.warning("Session has expired - try to re-authenticate...")
1493
+ self.logger.warning("Session has expired - try to re-authenticate...")
1092
1494
  self.authenticate(revalidate=True)
1093
1495
  retries += 1
1094
- logger.error(response.text)
1496
+ self.logger.error(response.text)
1095
1497
  return None
1096
1498
 
1097
1499
  # end method definition
1098
1500
 
1099
- def get_all_sub_categeries(
1100
- self,
1101
- parentid: int
1102
- ) -> dict | None:
1103
- """Get all sub categeries entity instances
1501
+ def get_all_sub_categeries(self, parent_id: int) -> dict | None:
1502
+ """Get all sub categeries entity instances.
1104
1503
 
1105
1504
  Args:
1106
- parentid (int): parentid
1505
+ parent_id (int):
1506
+ The parent ID of the sub categories.
1507
+
1107
1508
  Returns:
1108
- dict: Request response (dictionary) or None if the REST call fails
1509
+ dict:
1510
+ Request response (dictionary) or None if the REST call fails.
1511
+
1109
1512
  """
1513
+
1110
1514
  retries = 0
1111
1515
  while True:
1112
1516
  base_url = self.baseurl()
1113
1517
  endpoint = "/app/entityRestService/api/OpentextCaseManagement/entities/Category/items/"
1114
1518
  child_path = "/childEntities/SubCategory"
1115
1519
  response = requests.get(
1116
- url=base_url + endpoint + str(parentid) + child_path,
1520
+ url=base_url + endpoint + str(parent_id) + child_path,
1117
1521
  headers=REQUEST_HEADERS_JSON,
1118
1522
  cookies=self.cookie(),
1119
- timeout=None,
1523
+ timeout=REQUEST_TIMEOUT,
1120
1524
  )
1121
1525
  if response.ok:
1122
1526
  authenticate_dict = self.parse_request_response(
1123
- response, "This can be normal during restart", False
1527
+ response_object=response,
1528
+ additional_error_message="This can be normal during restart",
1529
+ show_error=False,
1124
1530
  )
1125
1531
  if not authenticate_dict:
1126
1532
  return None
1127
- return authenticate_dict
1533
+ return authenticate_dict
1128
1534
  if response.status_code == 401 and retries == 0:
1129
- logger.warning("Session has expired - try to re-authenticate...")
1535
+ self.logger.warning("Session has expired - try to re-authenticate...")
1130
1536
  self.authenticate(revalidate=True)
1131
1537
  retries += 1
1132
- logger.error(response.text)
1538
+ self.logger.error(response.text)
1133
1539
  return None
1134
1540
 
1135
1541
  # end method definition
@@ -1142,12 +1548,11 @@ class OTAWP:
1142
1548
  loan_duration_in_months: str,
1143
1549
  category: str,
1144
1550
  subcategory: str,
1145
- piority: str,
1551
+ priority: str,
1146
1552
  service: str,
1147
- customer: str
1148
-
1553
+ customer: str,
1149
1554
  ) -> dict | None:
1150
- """create loan entity instance
1555
+ """Create loan entity instance.
1151
1556
 
1152
1557
  Args:
1153
1558
  subject (str): subject
@@ -1156,12 +1561,14 @@ class OTAWP:
1156
1561
  loan_duration_in_months (str): loan_duration_in_months
1157
1562
  category (str): category
1158
1563
  subcategory (str): subcategory
1159
- piority (str): piority
1564
+ priority (str): priority
1160
1565
  service (str): service
1161
1566
  customer (str): customer
1162
1567
  Returns:
1163
1568
  dict: Request response (dictionary) or None if the REST call fails
1569
+
1164
1570
  """
1571
+
1165
1572
  create_loan = f"""<SOAP:Envelope xmlns:SOAP=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n
1166
1573
  <SOAP:Body>\r\n
1167
1574
  <CreateCase xmlns=\"http://schemas/OpentextCaseManagement/Case/operations\">\r\n
@@ -1192,7 +1599,7 @@ class OTAWP:
1192
1599
  \r\n
1193
1600
  <ns0:Priority>\r\n
1194
1601
  <ns3:Priority-id xmlns:ns3=\"http://schemas/OpentextCaseManagement/Priority\">\r\n
1195
- <ns3:Id>{piority}</ns3:Id>\r\n
1602
+ <ns3:Id>{priority}</ns3:Id>\r\n
1196
1603
  </ns3:Priority-id>\r\n
1197
1604
  </ns0:Priority>\r\n
1198
1605
  \r\n
@@ -1214,29 +1621,30 @@ class OTAWP:
1214
1621
  data=create_loan,
1215
1622
  headers=REQUEST_HEADERS,
1216
1623
  cookies=self.cookie(),
1217
- timeout=None,
1624
+ timeout=REQUEST_TIMEOUT,
1218
1625
  )
1219
1626
  if response.ok:
1220
- logger.info("Loan created successfully")
1221
- return self.parse_xml(response.text)
1627
+ self.logger.info("Loan created successfully")
1628
+ return self.parse_xml(response.text)
1222
1629
  if response.status_code == 401 and retries == 0:
1223
- logger.warning("Session has expired - try to re-authenticate...")
1630
+ self.logger.warning("Session has expired - try to re-authenticate...")
1224
1631
  self.authenticate(revalidate=True)
1225
1632
  retries += 1
1226
- logger.error(response.text)
1633
+ self.logger.error(response.text)
1227
1634
  return None
1228
1635
 
1229
1636
  # end method definition
1230
1637
 
1231
- def get_all_loan(
1232
- self
1233
- ) -> dict | None:
1234
- """get all loan entity instances
1638
+ def get_all_loan(self) -> dict | None:
1639
+ """Get all loan entity instances.
1235
1640
 
1236
1641
  Args:
1237
1642
  None
1643
+
1238
1644
  Returns:
1239
- dict: Request response (dictionary) or None if the REST call fails
1645
+ dict:
1646
+ Request response (dictionary) or None if the REST call fails.
1647
+
1240
1648
  """
1241
1649
 
1242
1650
  retries = 0
@@ -1245,32 +1653,29 @@ class OTAWP:
1245
1653
  url=self.get_all_loans_url(),
1246
1654
  headers=REQUEST_HEADERS_JSON,
1247
1655
  cookies=self.cookie(),
1248
- timeout=None,
1656
+ timeout=REQUEST_TIMEOUT,
1249
1657
  )
1250
1658
  if response.ok:
1251
1659
  authenticate_dict = self.parse_request_response(
1252
- response, "This can be normal during restart", False
1660
+ response_object=response,
1661
+ additional_error_message="This can be normal during restart",
1662
+ show_error=False,
1253
1663
  )
1254
1664
  if not authenticate_dict:
1255
1665
  return None
1256
1666
  return authenticate_dict
1257
1667
  if response.status_code == 401 and retries == 0:
1258
- logger.warning("Session has expired - try to re-authenticate...")
1668
+ self.logger.warning("Session has expired - try to re-authenticate...")
1259
1669
  self.authenticate(revalidate=True)
1260
1670
  retries += 1
1261
1671
  else:
1262
- logger.error(response.text)
1672
+ self.logger.error(response.text)
1263
1673
  return None
1264
1674
 
1265
1675
  # end method definition
1266
1676
 
1267
- def validate_workspace_response(
1268
- self,
1269
- response: str,
1270
- workspace_name: str
1271
- ) -> bool:
1272
- """
1273
- Verify if the workspace exists or was created successfully.
1677
+ def validate_workspace_response(self, response: str, workspace_name: str) -> bool:
1678
+ """Verify if the workspace exists or was created successfully.
1274
1679
 
1275
1680
  Args:
1276
1681
  response (str): response to validate
@@ -1278,16 +1683,17 @@ class OTAWP:
1278
1683
 
1279
1684
  Returns:
1280
1685
  bool: True if the workspace exists or was created successfully, else False.
1686
+
1281
1687
  """
1282
1688
 
1283
1689
  if "Object already exists" in response or "createWorkspaceResponse" in response:
1284
- logger.info(
1690
+ self.logger.info(
1285
1691
  "The workspace already exists or was created with the name -> '%s'",
1286
1692
  workspace_name,
1287
1693
  )
1288
1694
  return True
1289
1695
 
1290
- logger.info(
1696
+ self.logger.info(
1291
1697
  "The workspace -> '%s' does not exist or was not created. Please verify configurtion!",
1292
1698
  workspace_name,
1293
1699
  )
@@ -1295,41 +1701,61 @@ class OTAWP:
1295
1701
 
1296
1702
  # end method definition
1297
1703
 
1298
- def is_workspace_already_exists(
1299
- self,
1300
- response: str,
1301
- workspace_name: str
1302
- ) -> bool:
1303
- """verify is workspace exists
1704
+ def is_workspace_already_exists(self, response: str, workspace_name: str) -> bool:
1705
+ """Verify if workspace exists.
1706
+
1304
1707
  Args:
1305
- workspace_name (str): workspace_name
1708
+ response (str):
1709
+ The response.
1710
+ workspace_name (str):
1711
+ The name of the workspace.
1712
+
1306
1713
  Returns:
1307
- bool: return true if workspace exist else return false
1714
+ bool:
1715
+ Return True if workspace exist else return false.
1716
+
1308
1717
  """
1309
1718
 
1310
1719
  if "Object already exists" in response:
1311
- logger.info(
1312
- "The workspace already exists with the name -> '%s'", workspace_name
1720
+ self.logger.info(
1721
+ "The workspace already exists with the name -> '%s'",
1722
+ workspace_name,
1313
1723
  )
1314
1724
  return True
1315
- logger.info(
1316
- "The Workspace has been created with the name -> '%s'", workspace_name
1725
+ self.logger.info(
1726
+ "The Workspace has been created with the name -> '%s'",
1727
+ workspace_name,
1317
1728
  )
1318
1729
  return False
1319
1730
 
1320
1731
  # end method definition
1321
1732
 
1322
- def create_workspace_with_retry(self, workspace_name: str, workspace_gui_id: str) -> dict | None:
1323
- """
1324
- Calls create_workspace and retries if the response contains specific error messages.
1733
+ def create_workspace_with_retry(
1734
+ self,
1735
+ workspace_name: str,
1736
+ workspace_gui_id: str,
1737
+ ) -> dict | None:
1738
+ """Call create_workspace and retries if the response contains specific error messages.
1739
+
1325
1740
  Retries until the response does not contain the errors or a max retry limit is reached.
1741
+
1742
+ Args:
1743
+ workspace_name (str):
1744
+ The workspace name.
1745
+ workspace_gui_id (str):
1746
+ The workspace GUI ID.
1747
+
1748
+ Returns:
1749
+ dict | None:
1750
+ The response of the workspace creation or None in case an error occured.
1751
+
1326
1752
  """
1327
1753
 
1328
1754
  max_retries = 20 # Define the maximum number of retries
1329
1755
  retries = 0
1330
1756
  error_messages = [
1331
1757
  "Collaborative Workspace Service Container is not able to handle the SOAP request",
1332
- "Service Group Lookup failure"
1758
+ "Service Group Lookup failure",
1333
1759
  ]
1334
1760
 
1335
1761
  while retries < max_retries:
@@ -1337,15 +1763,19 @@ class OTAWP:
1337
1763
 
1338
1764
  # Check if any error message is in the response
1339
1765
  if any(error_message in response for error_message in error_messages):
1340
- logger.info("Workspace service error, waiting 60 seconds to retry... (Retry %d of %d)", retries + 1, max_retries)
1766
+ self.logger.info(
1767
+ "Workspace service error, waiting 60 seconds to retry... (Retry %d of %d)",
1768
+ retries + 1,
1769
+ max_retries,
1770
+ )
1341
1771
  time.sleep(60)
1342
1772
  retries += 1
1343
1773
  else:
1344
- logger.info("Collaborative Workspace Service Container is ready")
1774
+ self.logger.info("Collaborative Workspace Service Container is ready")
1345
1775
  return response
1346
1776
 
1347
1777
  # After max retries, log and return the response or handle as needed
1348
- logger.error(
1778
+ self.logger.error(
1349
1779
  "Max retries reached for workspace -> '%s', unable to create successfully.",
1350
1780
  workspace_name,
1351
1781
  )
@@ -1354,367 +1784,474 @@ class OTAWP:
1354
1784
  # end method definition
1355
1785
 
1356
1786
  def loan_management_runtime(self) -> dict | None:
1357
- """it will create all runtime objects for loan management application
1787
+ """Create all runtime objects for loan management application.
1788
+
1358
1789
  Args:
1359
1790
  None
1360
1791
  Returns:
1361
1792
  None
1793
+
1362
1794
  """
1363
1795
 
1364
- logger.debug(" RUNTIME -->> Category instance creation started ........ ")
1796
+ self.logger.debug(" RUNTIME -->> Category instance creation started ........ ")
1365
1797
  category_resp_dict = []
1366
1798
  if not self.verify_category_exists("Short Term Loan"):
1367
- self.create_category("LOAN","Short Term Loan","Short Term Loan",1)
1799
+ self.create_category("LOAN", "Short Term Loan", "Short Term Loan", 1)
1368
1800
  if not self.verify_category_exists("Long Term Loan"):
1369
- self.create_category("LOAN","Long Term Loan","Long Term Loan",1)
1801
+ self.create_category("LOAN", "Long Term Loan", "Long Term Loan", 1)
1370
1802
  if not self.verify_category_exists("Flexi Loan"):
1371
- self.create_category("LOAN","Flexi Loan","Flexi Loan",1)
1803
+ self.create_category("LOAN", "Flexi Loan", "Flexi Loan", 1)
1372
1804
  category_resp_dict = self.get_category_lists()
1373
- logger.debug(" RUNTIME -->> Category instance creation ended")
1805
+ self.logger.debug(" RUNTIME -->> Category instance creation ended")
1374
1806
 
1375
1807
  ############################# Sub category
1376
- logger.debug(" RUNTIME -->> Sub Category instance creation started ........")
1808
+ self.logger.debug(
1809
+ " RUNTIME -->> Sub Category instance creation started ........",
1810
+ )
1377
1811
  stl = 0
1378
1812
  ltl = 0
1379
1813
  fl = 0
1380
- if not self.verify_sub_category_exists("Business",0,category_resp_dict):
1381
- response_dict = self.create_sub_categoy("Business","Business",1,category_resp_dict[0])
1814
+ if not self.verify_sub_category_exists("Business", 0, category_resp_dict):
1815
+ response_dict = self.create_sub_categoy(
1816
+ "Business",
1817
+ "Business",
1818
+ 1,
1819
+ category_resp_dict[0],
1820
+ )
1382
1821
  stl = response_dict["Identity"]["Id"]
1383
- logger.info("Sub category id stl: %s ", stl)
1822
+ self.logger.info("Sub category id stl: %s ", stl)
1384
1823
  else:
1385
- stl = self.return_sub_category_exists_id("Business",0,category_resp_dict)
1386
- logger.info("Sub category id stl -> %s ", stl)
1824
+ stl = self.return_sub_category_exists_id("Business", 0, category_resp_dict)
1825
+ self.logger.info("Sub category id stl -> %s ", stl)
1387
1826
 
1388
- if not self.verify_sub_category_exists("Business",1,category_resp_dict):
1389
- response_dict=self.create_sub_categoy("Business","Business",1,category_resp_dict[1])
1827
+ if not self.verify_sub_category_exists("Business", 1, category_resp_dict):
1828
+ response_dict = self.create_sub_categoy(
1829
+ "Business",
1830
+ "Business",
1831
+ 1,
1832
+ category_resp_dict[1],
1833
+ )
1390
1834
  ltl = response_dict["Identity"]["Id"]
1391
- logger.info("Sub category id ltl -> %s ", ltl)
1835
+ self.logger.info("Sub category id ltl -> %s ", ltl)
1392
1836
  else:
1393
- ltl = self.return_sub_category_exists_id("Business",1,category_resp_dict)
1394
- logger.info("Sub category id ltl -> %s ", ltl)
1395
- if not self.verify_sub_category_exists("Business",2,category_resp_dict):
1396
- response_dict= self.create_sub_categoy("Business","Business",1,category_resp_dict[2])
1837
+ ltl = self.return_sub_category_exists_id(name="Business", index=1, category_resp_dict=category_resp_dict)
1838
+ self.logger.info("Sub category id ltl -> %s ", ltl)
1839
+ if not self.verify_sub_category_exists(name="Business", index=2, category_resp_dict=category_resp_dict):
1840
+ response_dict = self.create_sub_categoy(
1841
+ "Business",
1842
+ "Business",
1843
+ 1,
1844
+ category_resp_dict[2],
1845
+ )
1397
1846
  fl = response_dict["Identity"]["Id"]
1398
- logger.info("Sub category id fl -> %s ", fl)
1847
+ self.logger.info("Sub category id fl -> %s ", fl)
1399
1848
  else:
1400
- fl = self.return_sub_category_exists_id("Business",2,category_resp_dict)
1401
- logger.info("Sub category id fl -> %s ", fl)
1402
- logger.debug(" RUNTIME -->> Sub Category instance creation ended")
1849
+ fl = self.return_sub_category_exists_id(name="Business", index=2, category_resp_dict=category_resp_dict)
1850
+ self.logger.info("Sub category id fl -> %s ", fl)
1851
+ self.logger.debug(" RUNTIME -->> Sub Category instance creation ended")
1403
1852
 
1404
1853
  ############################# Case Types
1405
- logger.debug(" RUNTIME -->> Case Types instance creation started ........")
1854
+ self.logger.debug(" RUNTIME -->> Case Types instance creation started ........")
1406
1855
  case_type_list = []
1407
1856
 
1408
1857
  if not self.vverify_case_type_exists("Query"):
1409
- self.create_case_type("Query","Query",1)
1858
+ self.create_case_type("Query", "Query", 1)
1410
1859
  if not self.vverify_case_type_exists("Help"):
1411
- self.create_case_type("Help","Help",1)
1860
+ self.create_case_type("Help", "Help", 1)
1412
1861
  if not self.vverify_case_type_exists("Update Contact Details"):
1413
- self.create_case_type("Update Contact Details","Update Contact Details",1)
1862
+ self.create_case_type("Update Contact Details", "Update Contact Details", 1)
1414
1863
  if not self.vverify_case_type_exists("New Loan Request"):
1415
- self.create_case_type("New Loan Request","New Loan Request",1)
1864
+ self.create_case_type("New Loan Request", "New Loan Request", 1)
1416
1865
  if not self.vverify_case_type_exists("Loan Closure"):
1417
- self.create_case_type("Loan Closure","Loan Closure",1)
1866
+ self.create_case_type("Loan Closure", "Loan Closure", 1)
1418
1867
  case_type_list = self.get_case_type_lists()
1419
- logger.debug(" RUNTIME -->> Case Types instance creation ended")
1868
+ self.logger.debug(" RUNTIME -->> Case Types instance creation ended")
1420
1869
 
1421
1870
  ############################# CUSTMOR
1422
- logger.debug(" RUNTIME -->> Customer instance creation stated ........")
1871
+ self.logger.debug(" RUNTIME -->> Customer instance creation stated ........")
1423
1872
  customer_list = []
1424
1873
  if not self.verify_customer_exists("InaPlex Limited"):
1425
- self.create_customer("InaPlex Limited","InaPlex Limited","InaPlex Limited")
1874
+ self.create_customer(
1875
+ "InaPlex Limited",
1876
+ "InaPlex Limited",
1877
+ "InaPlex Limited",
1878
+ )
1426
1879
 
1427
1880
  if not self.verify_customer_exists("Interwoven, Inc"):
1428
- self.create_customer("Interwoven, Inc","Interwoven, Inc","Interwoven, Inc")
1881
+ self.create_customer(
1882
+ "Interwoven, Inc",
1883
+ "Interwoven, Inc",
1884
+ "Interwoven, Inc",
1885
+ )
1429
1886
 
1430
1887
  if not self.verify_customer_exists("Jones Lang LaSalle"):
1431
- self.create_customer("Jones Lang LaSalle","Jones Lang LaSalle","Jones Lang LaSalle")
1888
+ self.create_customer(
1889
+ "Jones Lang LaSalle",
1890
+ "Jones Lang LaSalle",
1891
+ "Jones Lang LaSalle",
1892
+ )
1432
1893
 
1433
1894
  if not self.verify_customer_exists("Key Point Consulting"):
1434
- self.create_customer("Key Point Consulting","Key Point Consulting","Key Point Consulting")
1895
+ self.create_customer(
1896
+ "Key Point Consulting",
1897
+ "Key Point Consulting",
1898
+ "Key Point Consulting",
1899
+ )
1435
1900
 
1436
1901
  customer_list = self.get_customer_lists()
1437
- logger.debug(" RUNTIME -->> Customer instance creation ended")
1902
+ self.logger.debug(" RUNTIME -->> Customer instance creation ended")
1438
1903
 
1439
1904
  ######################################## PRIORITY
1440
- logger.debug(" RUNTIME -->> priority instance creation started ........")
1905
+ self.logger.debug(" RUNTIME -->> priority instance creation started ........")
1441
1906
  prioity_list = []
1442
1907
  if not self.verify_priority_exists("High"):
1443
- self.create_priority("High","High",1)
1908
+ self.create_priority("High", "High", 1)
1444
1909
  if not self.verify_priority_exists("Medium"):
1445
- self.create_priority("Medium","Medium",1)
1910
+ self.create_priority("Medium", "Medium", 1)
1446
1911
  if not self.verify_priority_exists("Low"):
1447
- self.create_priority("Low","Low",1)
1912
+ self.create_priority("Low", "Low", 1)
1448
1913
  prioity_list = self.get_priority_lists()
1449
- logger.debug(" RUNTIME -->> priority instance creation ended")
1914
+ self.logger.debug(" RUNTIME -->> priority instance creation ended")
1450
1915
 
1451
1916
  ############################# LOAN
1452
1917
  loan_for_business = "Loan for Business1"
1453
1918
  loan_for_corporate_business = "Loan for Corporate Business1"
1454
1919
  loan_for_business_loan_request = "Loan for Business Loan Request1"
1455
1920
 
1456
- logger.debug(" RUNTIME -->> loan instance creation started ........")
1921
+ self.logger.debug(" RUNTIME -->> loan instance creation started ........")
1457
1922
  loan_resp_dict = self.get_all_loan()
1458
1923
  names = [item["Properties"]["Subject"] for item in loan_resp_dict["_embedded"]["AllCasesList"]]
1459
1924
  if loan_for_business in names:
1460
- logger.info("Customer record Loan_for_business exists")
1925
+ self.logger.info("Customer record Loan_for_business exists")
1461
1926
  else:
1462
- logger.info("Creating customer Record with Loan_for_business ")
1927
+ self.logger.info("Creating customer Record with Loan_for_business ")
1463
1928
  response_dict = self.create_loan(
1464
- loan_for_business,
1465
- loan_for_business,
1466
- 1,
1467
- 2,
1468
- category_resp_dict[0],
1469
- stl,
1470
- prioity_list[0],
1471
- case_type_list[0],
1472
- customer_list[0],
1929
+ subject=loan_for_business,
1930
+ description=loan_for_business,
1931
+ loan_amount=1,
1932
+ loan_duration_in_months=2,
1933
+ category=category_resp_dict[0],
1934
+ subcategory=stl,
1935
+ priority=prioity_list[0],
1936
+ service=case_type_list[0],
1937
+ customer=customer_list[0],
1473
1938
  )
1474
1939
 
1475
1940
  if loan_for_corporate_business in names:
1476
- logger.info("Customer record Loan_for_Corporate_Business exists")
1941
+ self.logger.info("Customer record Loan_for_Corporate_Business exists")
1477
1942
  else:
1478
- logger.info("Creating customer Record with Loan_for_Corporate_Business ")
1943
+ self.logger.info(
1944
+ "Creating customer Record with Loan_for_Corporate_Business ",
1945
+ )
1479
1946
  response_dict = self.create_loan(
1480
- loan_for_corporate_business,
1481
- loan_for_corporate_business,
1482
- 1,
1483
- 2,
1484
- category_resp_dict[1],
1485
- ltl,
1486
- prioity_list[1],
1487
- case_type_list[1],
1488
- customer_list[1],
1947
+ subject=loan_for_corporate_business,
1948
+ description=loan_for_corporate_business,
1949
+ loan_amount=1,
1950
+ loan_duration_in_months=2,
1951
+ category=category_resp_dict[1],
1952
+ subcategory=ltl,
1953
+ priority=prioity_list[1],
1954
+ service=case_type_list[1],
1955
+ customer=customer_list[1],
1489
1956
  )
1490
1957
 
1491
1958
  if loan_for_business_loan_request in names:
1492
- logger.info("Customer record Loan_for_business_Loan_Request exists")
1959
+ self.logger.info("Customer record Loan_for_business_Loan_Request exists")
1493
1960
  else:
1494
- logger.info("Creating customer Record with loan_for_business_loan_request")
1961
+ self.logger.info(
1962
+ "Creating customer Record with loan_for_business_loan_request",
1963
+ )
1495
1964
  response_dict = self.create_loan(
1496
- loan_for_business_loan_request,
1497
- loan_for_business_loan_request,
1498
- 1,
1499
- 2,
1500
- category_resp_dict[2],
1501
- fl,
1502
- prioity_list[2],
1503
- case_type_list[2],
1504
- customer_list[2],
1965
+ subject=loan_for_business_loan_request,
1966
+ description=loan_for_business_loan_request,
1967
+ loan_amount=1,
1968
+ loan_duration_in_months=2,
1969
+ category=category_resp_dict[2],
1970
+ subcategory=fl,
1971
+ priority=prioity_list[2],
1972
+ service=case_type_list[2],
1973
+ customer=customer_list[2],
1505
1974
  )
1506
- logger.debug(" RUNTIME -->> loan instance creation ended")
1975
+ self.logger.debug(" RUNTIME -->> loan instance creation ended")
1507
1976
 
1508
1977
  # end method definition
1509
1978
 
1510
1979
  def get_category_lists(self) -> list:
1511
- """get All category entty instances id's
1980
+ """Get All category entty instances id's.
1981
+
1512
1982
  Args:
1513
1983
  None
1514
1984
  Returns:
1515
1985
  list: list of category IDs
1986
+
1516
1987
  """
1517
1988
 
1518
1989
  category_resp_dict = []
1519
1990
  categoy_resp_dict = self.get_all_categories()
1520
1991
  for item in categoy_resp_dict["_embedded"]["CategoryList"]:
1521
1992
  first_item_href = item["_links"]["item"]["href"]
1522
- integer_value = int(re.search(r'\d+', first_item_href).group())
1523
- logger.info("Category created with ID -> %d", integer_value)
1993
+ integer_value = int(re.search(r"\d+", first_item_href).group())
1994
+ self.logger.info("Category created with ID -> %d", integer_value)
1524
1995
  category_resp_dict.append(integer_value)
1525
- logger.info("All extracted category IDs -> %s", category_resp_dict)
1996
+ self.logger.info("All extracted category IDs -> %s", category_resp_dict)
1526
1997
 
1527
1998
  return category_resp_dict
1528
1999
 
1529
2000
  # end method definition
1530
2001
 
1531
2002
  def get_case_type_lists(self) -> list:
1532
- """Get All CaseType entity instances IDs
2003
+ """Get All CaseType entity instances IDs.
2004
+
1533
2005
  Args:
1534
2006
  None
2007
+
1535
2008
  Returns:
1536
- list: list contains CaseType IDs
2009
+ list:
2010
+ List of all case type IDs.
2011
+
1537
2012
  """
1538
2013
 
1539
2014
  case_type_list = []
1540
2015
  casetype_resp_dict = self.get_all_case_type()
1541
2016
  for item in casetype_resp_dict["_embedded"]["AllCaseTypes"]:
1542
2017
  first_item_href = item["_links"]["item"]["href"]
1543
- integer_value = int(re.search(r'\d+', first_item_href).group())
1544
- logger.info("Case type created with ID -> %d", integer_value)
2018
+ integer_value = int(re.search(r"\d+", first_item_href).group())
2019
+ self.logger.info("Case type created with ID -> %d", integer_value)
1545
2020
  case_type_list.append(integer_value)
1546
- logger.info("All extracted case type IDs -> %s", case_type_list)
2021
+ self.logger.info("All extracted case type IDs -> %s", case_type_list)
1547
2022
 
1548
2023
  return case_type_list
1549
2024
 
1550
2025
  # end method definition
1551
2026
 
1552
2027
  def get_customer_lists(self) -> list:
1553
- """Get all customer entity instances id's
2028
+ """Get all customer entity instances id's.
2029
+
1554
2030
  Args:
1555
2031
  None
1556
2032
  Returns:
1557
- list: list of customer IDs
2033
+ list:
2034
+ A list of all customer IDs.
2035
+
1558
2036
  """
1559
2037
 
1560
2038
  customer_list = []
1561
2039
  customer_resp_dict = self.get_all_customers()
1562
2040
  for item in customer_resp_dict["_embedded"]["CustomerList"]:
1563
2041
  first_item_href = item["_links"]["item"]["href"]
1564
- integer_value = int(re.search(r'\d+', first_item_href).group())
1565
- logger.info("Customer created with ID -> %d", integer_value)
2042
+ integer_value = int(re.search(r"\d+", first_item_href).group())
2043
+ self.logger.info("Customer created with ID -> %d", integer_value)
1566
2044
  customer_list.append(integer_value)
1567
- logger.info("All extracted Customer IDs -> %s ", customer_list)
2045
+ self.logger.info("All extracted Customer IDs -> %s ", customer_list)
2046
+
1568
2047
  return customer_list
1569
2048
 
1570
2049
  # end method definition
1571
2050
 
1572
2051
  def get_priority_lists(self) -> list:
1573
- """get all priority entity instances IDs
2052
+ """Get all priority entity instances IDs.
2053
+
1574
2054
  Args:
1575
2055
  None
1576
2056
  Returns:
1577
- list: list contains priority IDs
2057
+ list:
2058
+ A list with all priority IDs.
2059
+
1578
2060
  """
1579
2061
 
1580
2062
  prioity_list = []
1581
2063
  authenticate_dict = self.get_all_priorities()
1582
2064
  for item in authenticate_dict["_embedded"]["PriorityList"]:
1583
2065
  first_item_href = item["_links"]["item"]["href"]
1584
- integer_value = int(re.search(r'\d+', first_item_href).group())
1585
- logger.info("Priority created with ID -> %d", integer_value)
2066
+ integer_value = int(re.search(r"\d+", first_item_href).group())
2067
+ self.logger.info("Priority created with ID -> %d", integer_value)
1586
2068
  prioity_list.append(integer_value)
1587
- logger.info("All extracted priority IDs -> %s ", prioity_list)
2069
+ self.logger.info("All extracted priority IDs -> %s ", prioity_list)
1588
2070
 
1589
2071
  return prioity_list
1590
2072
 
1591
2073
  # end method definition
1592
2074
 
1593
2075
  def verify_category_exists(self, name: str) -> bool:
1594
- """verify category entity instance already exists
2076
+ """Verify category entity instance already exists.
2077
+
1595
2078
  Args:
1596
- name (str): name of the category
2079
+ name (str):
2080
+ The name of the category.
2081
+
1597
2082
  Returns:
1598
- bool: returns True if already record exists with same name, else returns False
2083
+ bool:
2084
+ Returns True if already record exists with same name, else returns False.
2085
+
1599
2086
  """
1600
2087
 
1601
2088
  categoy_resp_dict = self.get_all_categories()
1602
2089
  names = [item["Properties"]["Name"] for item in categoy_resp_dict["_embedded"]["CategoryList"]]
1603
2090
  if name in names:
1604
- logger.info("Category record -> '%s' already exists", name)
2091
+ self.logger.info("Category record -> '%s' already exists", name)
1605
2092
  return True
1606
- logger.info("Creating category record -> '%s'", name)
2093
+ self.logger.info("Creating category record -> '%s'", name)
1607
2094
 
1608
2095
  return False
1609
2096
 
1610
2097
  # end method definition
1611
2098
 
1612
2099
  def vverify_case_type_exists(self, name: str) -> bool:
1613
- """verify case type entity instance already exists
2100
+ """Verify case type entity instance already exists.
2101
+
1614
2102
  Args:
1615
- name (str): name of the case type
2103
+ name (str):
2104
+ The name of the case type.
2105
+
1616
2106
  Returns:
1617
- bool: returns True if already record exists with same name, else returns False
2107
+ bool:
2108
+ Returns True if already record exists with same name, else returns False.
2109
+
1618
2110
  """
1619
2111
 
1620
2112
  casetype_resp_dict = self.get_all_case_type()
1621
2113
  names = [item["Properties"]["Name"] for item in casetype_resp_dict["_embedded"]["AllCaseTypes"]]
1622
2114
  if name in names:
1623
- logger.info("Case type record -> '%s' already exists", name)
2115
+ self.logger.info("Case type record -> '%s' already exists", name)
1624
2116
  return True
1625
- logger.info("Creating case type record -> '%s'", name)
2117
+ self.logger.info("Creating case type record -> '%s'", name)
1626
2118
 
1627
2119
  return False
1628
2120
 
1629
2121
  # end method definition
1630
2122
 
1631
2123
  def verify_customer_exists(self, name: str) -> bool:
1632
- """verify cusomer entty instance already exists
2124
+ """Verify cusomer entty instance already exists.
2125
+
1633
2126
  Args:
1634
- name (str): name of the customer
2127
+ name (str):
2128
+ The name of the customer.
2129
+
1635
2130
  Returns:
1636
- bool: returns True if already record exists with same name, else returns False
2131
+ bool:
2132
+ Returns True if already record exists with same name, else returns False
2133
+
1637
2134
  """
2135
+
1638
2136
  customer_resp_dict = self.get_all_customers()
1639
2137
  names = [item["Properties"]["CustomerName"] for item in customer_resp_dict["_embedded"]["CustomerList"]]
1640
2138
  if name in names:
1641
- logger.info("Customer -> '%s' already exists", name)
2139
+ self.logger.info("Customer -> '%s' already exists", name)
1642
2140
  return True
1643
- logger.info("Creating customer -> '%s'", name)
2141
+ self.logger.info("Creating customer -> '%s'", name)
1644
2142
  return False
1645
2143
 
1646
2144
  # end method definition
1647
2145
 
1648
2146
  def verify_priority_exists(self, name: str) -> bool:
1649
- """verify piority entity instance already exists
2147
+ """Verify priority entity instance already exists.
2148
+
1650
2149
  Args:
1651
- name (str): name of the priority
2150
+ name (str):
2151
+ The name of the priority.
2152
+
1652
2153
  Returns:
1653
- bool: returns True if already record exists with same name, else returns False
2154
+ bool:
2155
+ Returns True if already record exists with same name, else returns False
2156
+
1654
2157
  """
1655
2158
 
1656
2159
  authenticate_dict = self.get_all_priorities()
1657
2160
  names = [item["Properties"]["Name"] for item in authenticate_dict["_embedded"]["PriorityList"]]
1658
2161
  if name in names:
1659
- logger.info("Priority -> '%s' already exists", name)
2162
+ self.logger.info("Priority -> '%s' already exists", name)
1660
2163
  return True
1661
- logger.info("Creating priority -> '%s'", name)
2164
+ self.logger.info("Creating priority -> '%s'", name)
1662
2165
 
1663
2166
  return False
1664
2167
 
1665
2168
  # end method definition
1666
2169
 
1667
- def verify_sub_category_exists(self, name: str, index: int, category_resp_dict: list) -> bool:
1668
- """verify sub category entity instance already exists
2170
+ def verify_sub_category_exists(
2171
+ self,
2172
+ name: str,
2173
+ index: int,
2174
+ category_resp_dict: list,
2175
+ ) -> bool:
2176
+ """Verify sub category entity instance already exists.
2177
+
1669
2178
  Args:
1670
- name (str): name of the sub category
2179
+ name (str):
2180
+ The name of the sub category.
2181
+ index (int):
2182
+ The index of the sub category.
2183
+ category_resp_dict (list):
2184
+ TODO: add description
2185
+
1671
2186
  Returns:
1672
- bool: returns true if record already exists with same name, else returns false
2187
+ bool:
2188
+ Returns true if record already exists with same name, else returns false.
2189
+
1673
2190
  """
1674
2191
 
1675
2192
  subcategoy_resp_dict = self.get_all_sub_categeries(category_resp_dict[index])
1676
2193
  names = [item["Properties"]["Name"] for item in subcategoy_resp_dict["_embedded"]["SubCategory"]]
1677
- stl=0
2194
+ stl = 0
1678
2195
  if name in names:
1679
- logger.info("Sub category -> '%s' already exists", name)
2196
+ self.logger.info("Sub category -> '%s' already exists", name)
1680
2197
  for item in subcategoy_resp_dict["_embedded"]["SubCategory"]:
1681
2198
  stl = item["Identity"]["Id"]
1682
- logger.info("Sub category created with ID -> %s", stl)
2199
+ self.logger.info("Sub category created with ID -> %s", stl)
1683
2200
  return True
1684
- logger.info("Creating sub category -> '%s'", name)
2201
+ self.logger.info("Creating sub category -> '%s'", name)
1685
2202
 
1686
2203
  return False
1687
2204
 
1688
2205
  # end method definition
1689
2206
 
1690
- def return_sub_category_exists_id(self, name: str, index: int, category_resp_dict: list) -> int:
1691
- """verify sub category entity instance id already exists
2207
+ def return_sub_category_exists_id(
2208
+ self,
2209
+ name: str,
2210
+ index: int,
2211
+ category_resp_dict: list,
2212
+ ) -> int:
2213
+ """Verify sub category entity instance id already exists.
2214
+
1692
2215
  Args:
1693
- name (str): name of the sub-category
2216
+ name (str):
2217
+ The name of the sub-category.
2218
+ index (int):
2219
+ TODO: add description
2220
+ category_resp_dict (list):
2221
+ TODO: add description!
2222
+
1694
2223
  Returns:
1695
- bool: returns true if record already exists with same name, else returns false
2224
+ bool:
2225
+ Returns true if record already exists with same name, else returns false.
2226
+
1696
2227
  """
1697
2228
 
1698
2229
  subcategoy_resp_dict = self.get_all_sub_categeries(category_resp_dict[index])
1699
2230
  names = [item["Properties"]["Name"] for item in subcategoy_resp_dict["_embedded"]["SubCategory"]]
1700
- stl=0
1701
- if name in names:
1702
- logger.info("Sub category record -> '%s' already exists", name)
2231
+ stl = 0
2232
+ if name in names:
2233
+ self.logger.info("Sub category record -> '%s' already exists", name)
1703
2234
  for item in subcategoy_resp_dict["_embedded"]["SubCategory"]:
1704
2235
  stl = item["Identity"]["Id"]
1705
- logger.info("Sub category created with ID -> %s", stl)
2236
+ self.logger.info("Sub category created with ID -> %s", stl)
1706
2237
  return stl
1707
2238
 
1708
2239
  return None
1709
2240
 
1710
2241
  # end method definition
1711
2242
 
1712
- def create_users_from_config_file(self, otawpsection: str, _otds: OTDS):
1713
- """read user information from customizer file and call create user method
2243
+ def create_users_from_config_file(self, otawpsection: str, _otds: OTDS) -> None:
2244
+ """Read user information from customizer file and call create user method.
2245
+
1714
2246
  Args:
1715
- otawpsection (str): yaml bock related to appworks
2247
+ otawpsection (str):
2248
+ YAML block related to appworks
2249
+ _otds:
2250
+ The OTDS object.
2251
+
1716
2252
  Returns:
1717
2253
  None
2254
+
1718
2255
  """
1719
2256
 
1720
2257
  otds = otawpsection.get("otds", {})
@@ -1735,29 +2272,35 @@ class OTAWP:
1735
2272
  for role in roles:
1736
2273
  _otds.add_user_to_group(
1737
2274
  user.get("name") + "@" + user.get("partition"),
1738
- # user.get('name'),
1739
2275
  role.get("name"),
1740
2276
  )
1741
2277
  else:
1742
- logger.error(
1743
- "Verifying Users section: roles section not presented in yaml for otds users"
2278
+ self.logger.error(
2279
+ "Verifying Users section: roles section not presented in yaml for otds users",
1744
2280
  )
1745
2281
  else:
1746
- logger.error(
1747
- "Verifying Users section: user section not presented in yaml"
2282
+ self.logger.error(
2283
+ "Verifying Users section: user section not presented in yaml",
1748
2284
  )
1749
2285
  else:
1750
- logger.error("Verifying Users section: otds section not presented in yaml")
2286
+ self.logger.error(
2287
+ "Verifying Users section: otds section not presented in yaml",
2288
+ )
1751
2289
 
1752
2290
  # end method definition
1753
2291
 
1754
- def create_roles_from_config_file(self, otawpsection: str, _otds: OTDS):
1755
- """read grop information from customizer file and call create grop method
2292
+ def create_roles_from_config_file(self, otawpsection: str, _otds: OTDS) -> None:
2293
+ """Read grop information from customizer file and call create grop method.
2294
+
1756
2295
  Args:
1757
- otawpsection (str): yaml bock related to appworks
1758
- _otds (object): the OTDS object used to access the OTDS REST API
2296
+ otawpsection (str):
2297
+ YAML block related to appworks.
2298
+ _otds (object):
2299
+ The OTDS object used to access the OTDS REST API.
2300
+
1759
2301
  Returns:
1760
2302
  None
2303
+
1761
2304
  """
1762
2305
 
1763
2306
  otds = otawpsection.get("otds", {})
@@ -1773,20 +2316,26 @@ class OTAWP:
1773
2316
  role.get("description"),
1774
2317
  )
1775
2318
  else:
1776
- logger.error(
1777
- "Verifying roles section: roles section not presented in yaml"
2319
+ self.logger.error(
2320
+ "Verifying roles section: roles section not presented in yaml",
1778
2321
  )
1779
2322
  else:
1780
- logger.error("Verifying roles section: otds section not presented in yaml")
2323
+ self.logger.error(
2324
+ "Verifying roles section: otds section not presented in yaml",
2325
+ )
1781
2326
 
1782
2327
  # end method definition
1783
2328
 
1784
- def create_loanruntime_from_config_file(self, platform: str):
1785
- """verify flag and call loan_management_runtime()
2329
+ def create_loanruntime_from_config_file(self, platform: str) -> None:
2330
+ """Verify flag and call loan_management_runtime().
2331
+
1786
2332
  Args:
1787
- platform (str): yaml bock related to platform
2333
+ platform (str):
2334
+ YAML block related to platform.
2335
+
1788
2336
  Returns:
1789
2337
  None
2338
+
1790
2339
  """
1791
2340
 
1792
2341
  runtime = platform.get("runtime", {})
@@ -1797,14 +2346,344 @@ class OTAWP:
1797
2346
  if app_name == "loanManagement":
1798
2347
  self.loan_management_runtime()
1799
2348
  else:
1800
- logger.error(
1801
- "Verifying runtime section: loanManagement not exits in yaml entry"
2349
+ self.logger.error(
2350
+ "Verifying runtime section: loanManagement not exits in yaml entry",
1802
2351
  )
1803
2352
  else:
1804
- logger.error(
1805
- "Verifying runtime section: App name section is empty in yaml"
2353
+ self.logger.error(
2354
+ "Verifying runtime section: App name section is empty in yaml",
1806
2355
  )
1807
2356
  else:
1808
- logger.error("Verifying runtime section: Runtime section is empty in yaml")
2357
+ self.logger.error(
2358
+ "Verifying runtime section: Runtime section is empty in yaml",
2359
+ )
2360
+
2361
+ # end method definition
2362
+ def create_cws_config(
2363
+ self,
2364
+ partition: str,
2365
+ resource_name: str,
2366
+ otcs_url: str,
2367
+ ) -> dict | None:
2368
+ """Create a workspace configuration in CWS.
2369
+
2370
+ Args:
2371
+ partition (str): The partition name for the workspace.
2372
+ resource_name (str): The resource name.
2373
+ otcs_url (str): The OTCS endpoint URL.
2374
+
2375
+ Returns:
2376
+ dict | None: Response dictionary if successful, or None if the request fails.
2377
+
2378
+ """
2379
+ self.logger.info("Creating CWS config for partition '%s' and resource '%s'...", partition, resource_name)
2380
+
2381
+ # Construct the SOAP request body
2382
+ cws_config_req_xml = f"""
2383
+ <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
2384
+ <SOAP:Header>
2385
+ <header xmlns="http://schemas.cordys.com/General/1.0/">
2386
+ <Logger/>
2387
+ </header>
2388
+ <i18n:international xmlns:i18n="http://www.w3.org/2005/09/ws-i18n">
2389
+ <i18n:locale>en-US</i18n:locale>
2390
+ </i18n:international>
2391
+ </SOAP:Header>
2392
+ <SOAP:Body>
2393
+ <UpdateXMLObject xmlns="http://schemas.cordys.com/1.0/xmlstore">
2394
+ <tuple lastModified="{int(time.time() * 1000)}"
2395
+ key="/com/ot-ps/csws/otcs_ws_config.xml"
2396
+ level="organization"
2397
+ name="otcs_ws_config.xml"
2398
+ original="/com/ot-ps/csws/otcs_ws_config.xml"
2399
+ version="organization">
2400
+ <new>
2401
+ <CSWSConfig>
2402
+ <Partition>{partition}</Partition>
2403
+ <EndPointUrl>{otcs_url}/cws/services/Authentication</EndPointUrl>
2404
+ <Resources>
2405
+ <Resource type="Cordys">
2406
+ <Name>__OTDS#Shared#Platform#Resource__</Name>
2407
+ <Space>shared</Space>
2408
+ </Resource>
2409
+ <Resource type="OTCS">
2410
+ <Name>{resource_name}</Name>
2411
+ <Space>shared</Space>
2412
+ </Resource>
2413
+ </Resources>
2414
+ </CSWSConfig>
2415
+ </new>
2416
+ </tuple>
2417
+ </UpdateXMLObject>
2418
+ </SOAP:Body>
2419
+ </SOAP:Envelope>
2420
+ """
2421
+
2422
+ retries = 0
2423
+ max_retries = 20 # Maximum retry limit
2424
+ error_messages = [
2425
+ "Collaborative Workspace Service Container is not able to handle the SOAP request",
2426
+ "Service Group Lookup failure",
2427
+ ]
2428
+
2429
+ while retries < max_retries:
2430
+ try:
2431
+ response = requests.post(
2432
+ url=self.gateway_url(),
2433
+ data=cws_config_req_xml,
2434
+ headers=REQUEST_HEADERS,
2435
+ cookies=self.cookie(),
2436
+ timeout=None,
2437
+ )
2438
+
2439
+ # Handle successful response
2440
+ if response.ok:
2441
+ if any(error_message in response.text for error_message in error_messages):
2442
+ self.logger.warning(
2443
+ "Service error detected, retrying in 60 seconds... (Retry %d of %d)",
2444
+ retries + 1,
2445
+ max_retries,
2446
+ )
2447
+ time.sleep(60)
2448
+ retries += 1
2449
+ else:
2450
+ self.logger.info("CWS config created successfully.")
2451
+ return response.text
2452
+
2453
+ # Handle session expiration
2454
+ if response.status_code == 401 and retries == 0:
2455
+ self.logger.warning("Session expired. Re-authenticating...")
2456
+ self.authenticate(revalidate=True)
2457
+ retries += 1
2458
+ continue
2459
+
2460
+ # Handle case where object has been changed by another user
2461
+ if "Object has been changed by other user" in response.text:
2462
+ self.logger.info("CWS config already exists")
2463
+ return response.text
2464
+
2465
+ # Log errors for failed requests
2466
+ self.logger.error("Failed to create CWS config: %s", response.text)
2467
+ time.sleep(60)
2468
+ retries += 1
2469
+
2470
+ except requests.RequestException:
2471
+ self.logger.error("Request failed during CWS config creation")
2472
+ retries += 1
2473
+
2474
+ # Log when retries are exhausted
2475
+ self.logger.error("Retry limit exceeded. CWS config creation failed.")
2476
+ return None
2477
+
2478
+ # end method definition
2479
+ def verify_user_having_role(self, organization: str, user_name: str, role_name: str) -> bool:
2480
+ """Verify if the user has the specified role.
2481
+
2482
+ Args:
2483
+ organization(str): organization name
2484
+ user_name (str): The username to verify.
2485
+ role_name (str): The role to check for the user.
2486
+
2487
+ Returns:
2488
+ bool: True if the user has the role, False if not, or None if request fails.
2489
+
2490
+ """
2491
+ self.logger.info("Verifying user '%s' has role '%s' started.", user_name, role_name)
2492
+
2493
+ # Construct the SOAP request body
2494
+ cws_config_req_xml = f"""
2495
+ <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
2496
+ <SOAP:Header xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
2497
+ <header xmlns="http://schemas.cordys.com/General/1.0/">
2498
+ <Logger xmlns="http://schemas.cordys.com/General/1.0/"/>
2499
+ </header>
2500
+ <i18n:international xmlns:i18n="http://www.w3.org/2005/09/ws-i18n">
2501
+ <i18n:locale>en-US</i18n:locale>
2502
+ </i18n:international>
2503
+ </SOAP:Header>
2504
+ <SOAP:Body>
2505
+ <SearchLDAP xmlns:xfr="http://schemas.cordys.com/1.0/xforms/runtime" xmlns="http://schemas.cordys.com/1.0/ldap">
2506
+ <dn xmlns="http://schemas.cordys.com/1.0/ldap">cn=organizational users,o={organization},cn=cordys,cn=defaultInst,o=opentext.net</dn>
2507
+ <scope xmlns="http://schemas.cordys.com/1.0/ldap">1</scope>
2508
+ <filter xmlns="http://schemas.cordys.com/1.0/ldap">&amp;(objectclass=busorganizationaluser)(&amp;(!(cn=SYSTEM))(!(cn=anonymous))(!(cn=wcpLicUser)))(|(description=*{user_name}*)(&amp;(!(description=*))(cn=*{user_name}*)))</filter>
2509
+ <sort xmlns="http://schemas.cordys.com/1.0/ldap">ascending</sort>
2510
+ <sortBy xmlns="http://schemas.cordys.com/1.0/ldap"/>
2511
+ <returnValues xmlns="http://schemas.cordys.com/1.0/ldap">false</returnValues>
2512
+ <return xmlns="http://schemas.cordys.com/1.0/ldap"/>
2513
+ </SearchLDAP>
2514
+ </SOAP:Body>
2515
+ </SOAP:Envelope>
2516
+ """
2517
+
2518
+ retries = 0
2519
+ max_retries = 6 # Maximum retry limit
2520
+ while retries < max_retries:
2521
+ try:
2522
+ response = requests.post(
2523
+ url=self.gateway_url(),
2524
+ data=cws_config_req_xml,
2525
+ headers=REQUEST_HEADERS,
2526
+ cookies=self.cookie(),
2527
+ timeout=None,
2528
+ )
2529
+
2530
+ # Handle successful response
2531
+ if response.ok:
2532
+ if (
2533
+ role_name in response.text
2534
+ ): # Corrected syntax for checking if 'Developer' is in the response text
2535
+ self.logger.info("Verifyied user '%s' already has the role '%s'.", user_name, role_name)
2536
+ return True # Assuming the user has the role if the response contains 'Developer'
2537
+ else:
2538
+ self.logger.info("Verifyied User '%s' not having role '%s'.", user_name, role_name)
2539
+ return False
2540
+ # Handle session expiration
2541
+ if response.status_code == 401 and retries == 0:
2542
+ self.logger.warning("Session expired. Re-authenticating...")
2543
+ self.authenticate(revalidate=True)
2544
+ retries += 1
2545
+ continue
2546
+
2547
+ # Log errors for failed requests
2548
+ self.logger.error("Failed to verify user role: %s", response.text)
2549
+ time.sleep(60)
2550
+ retries += 1
2551
+
2552
+ except requests.RequestException:
2553
+ self.logger.error("Request failed during user role verification")
2554
+ retries += 1
2555
+
2556
+ # Log when retries are exhausted
2557
+ self.logger.error("Retry limit exceeded. User role verification failed.")
2558
+ return False # Return False if the retries limit is exceeded
1809
2559
 
1810
2560
  # end method definition
2561
+
2562
+ def assign_developer_role_to_user(self, organization: str, user_name: str, role_name: str) -> bool:
2563
+ """Assign the 'Developer' role to the user and verify the role assignment.
2564
+
2565
+ Args:
2566
+ organization (str): The organization name.
2567
+ user_name (str): The username to verify.
2568
+ role_name (str): The role to be assigned.
2569
+
2570
+ Returns:
2571
+ bool: True if the user has the 'Developer' role, False otherwise.
2572
+
2573
+ """
2574
+ self.logger.info("Assigning 'Developer' role to user '%s' in organization '%s'...", user_name, organization)
2575
+
2576
+ # Check if user already has the role before making the request
2577
+ if self.verify_user_having_role(organization, user_name, role_name):
2578
+ return True
2579
+
2580
+ # Construct the SOAP request body
2581
+ cws_config_req_xml = f"""\
2582
+ <SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
2583
+ <SOAP:Header xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
2584
+ <header xmlns="http://schemas.cordys.com/General/1.0/">
2585
+ <Logger xmlns="http://schemas.cordys.com/General/1.0/"/>
2586
+ </header>
2587
+ <i18n:international xmlns:i18n="http://www.w3.org/2005/09/ws-i18n">
2588
+ <i18n:locale>en-US</i18n:locale>
2589
+ </i18n:international>
2590
+ </SOAP:Header>
2591
+ <SOAP:Body>
2592
+ <Update xmlns="http://schemas.cordys.com/1.0/ldap">
2593
+ <tuple>
2594
+ <old>
2595
+ <entry dn="cn=sysadmin,cn=organizational users,o={organization},cn=cordys,cn=defaultInst,o=opentext.net">
2596
+ <role>
2597
+ <string>cn=everyoneIn{organization},cn=organizational roles,o={organization},cn=cordys,cn=defaultInst,o=opentext.net</string>
2598
+ <string>cn=Administrator,cn=Cordys@Work,cn=cordys,cn=defaultInst,o=opentext.net</string>
2599
+ <string>cn=OTDS Push Service,cn=OpenText OTDS Platform Push Connector,cn=cordys,cn=defaultInst,o=opentext.net</string>
2600
+ </role>
2601
+ <description>
2602
+ <string>{user_name}</string>
2603
+ </description>
2604
+ <cn>
2605
+ <string>{user_name}</string>
2606
+ </cn>
2607
+ <objectclass>
2608
+ <string>top</string>
2609
+ <string>busorganizationalobject</string>
2610
+ <string>busorganizationaluser</string>
2611
+ </objectclass>
2612
+ <authenticationuser>
2613
+ <string>cn={user_name},cn=authenticated users,cn=cordys,cn=defaultInst,o=opentext.net</string>
2614
+ </authenticationuser>
2615
+ </entry>
2616
+ </old>
2617
+ <new>
2618
+ <entry dn="cn={user_name},cn=organizational users,o={organization},cn=cordys,cn=defaultInst,o=opentext.net">
2619
+ <role>
2620
+ <string>cn=everyoneIn{organization},cn=organizational roles,o={organization},cn=cordys,cn=defaultInst,o=opentext.net</string>
2621
+ <string>cn=Administrator,cn=Cordys@Work,cn=cordys,cn=defaultInst,o=opentext.net</string>
2622
+ <string>cn=OTDS Push Service,cn=OpenText OTDS Platform Push Connector,cn=cordys,cn=defaultInst,o=opentext.net</string>
2623
+ <string>cn=Developer,cn=Cordys@Work,cn=cordys,cn=defaultInst,o=opentext.net</string>
2624
+ </role>
2625
+ <description>
2626
+ <string>{user_name}</string>
2627
+ </description>
2628
+ <cn>
2629
+ <string>{user_name}</string>
2630
+ </cn>
2631
+ <objectclass>
2632
+ <string>top</string>
2633
+ <string>busorganizationalobject</string>
2634
+ <string>busorganizationaluser</string>
2635
+ </objectclass>
2636
+ <authenticationuser>
2637
+ <string>cn={user_name},cn=authenticated users,cn=cordys,cn=defaultInst,o=opentext.net</string>
2638
+ </authenticationuser>
2639
+ </entry>
2640
+ </new>
2641
+ </tuple>
2642
+ </Update>
2643
+ </SOAP:Body>
2644
+ </SOAP:Envelope>
2645
+ """
2646
+ retries = 0
2647
+ max_retries = 6
2648
+ retry_delay = 30 # Time in seconds
2649
+
2650
+ while retries < max_retries:
2651
+ try:
2652
+ response = requests.post(
2653
+ url=self.gateway_url(),
2654
+ data=cws_config_req_xml,
2655
+ headers=REQUEST_HEADERS,
2656
+ cookies=self.cookie(),
2657
+ timeout=30,
2658
+ )
2659
+
2660
+ if response.ok and role_name in response.text:
2661
+ self.logger.info("User '%s' successfully assigned the '%s' role.", user_name, role_name)
2662
+ return True
2663
+
2664
+ # Handle session expiration
2665
+ if response.status_code == 401 and retries == 0:
2666
+ self.logger.warning("Session expired. Re-authenticating...")
2667
+ self.authenticate(revalidate=True)
2668
+ retries += 1
2669
+ continue # Retry immediately after re-authentication
2670
+
2671
+ # Log failure response
2672
+ self.logger.error(
2673
+ "Failed to assign role to user '%s': HTTP %s - %s",
2674
+ user_name,
2675
+ response.status_code,
2676
+ response.text,
2677
+ )
2678
+
2679
+ except requests.RequestException:
2680
+ self.logger.error("Request failed:")
2681
+
2682
+ retries += 1
2683
+ self.logger.info("Retrying... Attempt %d/%d", retries, max_retries)
2684
+ time.sleep(retry_delay)
2685
+
2686
+ self.logger.error("Retry limit exceeded. Role assignment failed for user '%s'.", user_name)
2687
+ return False
2688
+
2689
+ # end method definition