pyxecm 1.6__py3-none-any.whl → 2.0.1__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.
- pyxecm/__init__.py +7 -4
- pyxecm/avts.py +727 -254
- pyxecm/coreshare.py +686 -467
- pyxecm/customizer/__init__.py +16 -4
- pyxecm/customizer/__main__.py +58 -0
- pyxecm/customizer/api/__init__.py +5 -0
- pyxecm/customizer/api/__main__.py +6 -0
- pyxecm/customizer/api/app.py +163 -0
- pyxecm/customizer/api/auth/__init__.py +1 -0
- pyxecm/customizer/api/auth/functions.py +92 -0
- pyxecm/customizer/api/auth/models.py +13 -0
- pyxecm/customizer/api/auth/router.py +78 -0
- pyxecm/customizer/api/common/__init__.py +1 -0
- pyxecm/customizer/api/common/functions.py +47 -0
- pyxecm/customizer/api/common/metrics.py +92 -0
- pyxecm/customizer/api/common/models.py +21 -0
- pyxecm/customizer/api/common/payload_list.py +870 -0
- pyxecm/customizer/api/common/router.py +72 -0
- pyxecm/customizer/api/settings.py +128 -0
- pyxecm/customizer/api/terminal/__init__.py +1 -0
- pyxecm/customizer/api/terminal/router.py +87 -0
- pyxecm/customizer/api/v1_csai/__init__.py +1 -0
- pyxecm/customizer/api/v1_csai/router.py +87 -0
- pyxecm/customizer/api/v1_maintenance/__init__.py +1 -0
- pyxecm/customizer/api/v1_maintenance/functions.py +100 -0
- pyxecm/customizer/api/v1_maintenance/models.py +12 -0
- pyxecm/customizer/api/v1_maintenance/router.py +76 -0
- pyxecm/customizer/api/v1_otcs/__init__.py +1 -0
- pyxecm/customizer/api/v1_otcs/functions.py +61 -0
- pyxecm/customizer/api/v1_otcs/router.py +179 -0
- pyxecm/customizer/api/v1_payload/__init__.py +1 -0
- pyxecm/customizer/api/v1_payload/functions.py +179 -0
- pyxecm/customizer/api/v1_payload/models.py +51 -0
- pyxecm/customizer/api/v1_payload/router.py +499 -0
- pyxecm/customizer/browser_automation.py +721 -286
- pyxecm/customizer/customizer.py +1076 -1425
- pyxecm/customizer/exceptions.py +35 -0
- pyxecm/customizer/guidewire.py +1186 -0
- pyxecm/customizer/k8s.py +901 -379
- pyxecm/customizer/log.py +107 -0
- pyxecm/customizer/m365.py +2967 -920
- pyxecm/customizer/nhc.py +1169 -0
- pyxecm/customizer/openapi.py +258 -0
- pyxecm/customizer/payload.py +18228 -7820
- pyxecm/customizer/pht.py +717 -286
- pyxecm/customizer/salesforce.py +516 -342
- pyxecm/customizer/sap.py +58 -41
- pyxecm/customizer/servicenow.py +611 -372
- pyxecm/customizer/settings.py +445 -0
- pyxecm/customizer/successfactors.py +408 -346
- pyxecm/customizer/translate.py +83 -48
- pyxecm/helper/__init__.py +5 -2
- pyxecm/helper/assoc.py +83 -43
- pyxecm/helper/data.py +2406 -870
- pyxecm/helper/logadapter.py +27 -0
- pyxecm/helper/web.py +229 -101
- pyxecm/helper/xml.py +596 -171
- pyxecm/maintenance_page/__init__.py +5 -0
- pyxecm/maintenance_page/__main__.py +6 -0
- pyxecm/maintenance_page/app.py +51 -0
- pyxecm/maintenance_page/settings.py +28 -0
- pyxecm/maintenance_page/static/favicon.avif +0 -0
- pyxecm/maintenance_page/templates/maintenance.html +165 -0
- pyxecm/otac.py +235 -141
- pyxecm/otawp.py +2668 -1220
- pyxecm/otca.py +569 -0
- pyxecm/otcs.py +7956 -3237
- pyxecm/otds.py +2178 -925
- pyxecm/otiv.py +36 -21
- pyxecm/otmm.py +1272 -325
- pyxecm/otpd.py +231 -127
- pyxecm-2.0.1.dist-info/METADATA +122 -0
- pyxecm-2.0.1.dist-info/RECORD +76 -0
- {pyxecm-1.6.dist-info → pyxecm-2.0.1.dist-info}/WHEEL +1 -1
- pyxecm-1.6.dist-info/METADATA +0 -53
- pyxecm-1.6.dist-info/RECORD +0 -32
- {pyxecm-1.6.dist-info → pyxecm-2.0.1.dist-info/licenses}/LICENSE +0 -0
- {pyxecm-1.6.dist-info → pyxecm-2.0.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1186 @@
|
|
|
1
|
+
"""Guidewire Module to interact with the Guidewire REST API ("Cloud API").
|
|
2
|
+
|
|
3
|
+
See: https://www.guidewire.com/de/developers/apis/cloud-apis
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__author__ = "Dr. Marc Diefenbruch"
|
|
7
|
+
__copyright__ = "Copyright (C) 2024-2025, OpenText"
|
|
8
|
+
__credits__ = ["Kai-Philip Gatzweiler"]
|
|
9
|
+
__maintainer__ = "Dr. Marc Diefenbruch"
|
|
10
|
+
__email__ = "mdiefenb@opentext.com"
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
import platform
|
|
14
|
+
import sys
|
|
15
|
+
import urllib.parse
|
|
16
|
+
from importlib.metadata import version
|
|
17
|
+
|
|
18
|
+
import requests
|
|
19
|
+
from requests.auth import HTTPBasicAuth
|
|
20
|
+
|
|
21
|
+
APP_NAME = "pyxecm"
|
|
22
|
+
APP_VERSION = version("pyxecm")
|
|
23
|
+
MODULE_NAME = APP_NAME + ".customizer.guidewire"
|
|
24
|
+
|
|
25
|
+
PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
26
|
+
OS_INFO = f"{platform.system()} {platform.release()}"
|
|
27
|
+
ARCH_INFO = platform.machine()
|
|
28
|
+
REQUESTS_VERSION = requests.__version__
|
|
29
|
+
|
|
30
|
+
USER_AGENT = (
|
|
31
|
+
f"{APP_NAME}/{APP_VERSION} ({MODULE_NAME}/{APP_VERSION}; "
|
|
32
|
+
f"Python/{PYTHON_VERSION}; {OS_INFO}; {ARCH_INFO}; Requests/{REQUESTS_VERSION})"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
default_logger = logging.getLogger(MODULE_NAME)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Guidewire:
|
|
39
|
+
"""Class Guidewire is used to retrieve and automate stettings and objects in Guidewire."""
|
|
40
|
+
|
|
41
|
+
_config: dict
|
|
42
|
+
_scope = None
|
|
43
|
+
_access_token = None
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
base_url: str,
|
|
48
|
+
auth_type: str,
|
|
49
|
+
client_id: str = "",
|
|
50
|
+
client_secret: str = "",
|
|
51
|
+
username: str = "",
|
|
52
|
+
password: str = "",
|
|
53
|
+
scope: str = "",
|
|
54
|
+
logger: logging.Logger = default_logger,
|
|
55
|
+
) -> None:
|
|
56
|
+
"""Initialize the Guidewire API client.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
base_url (str):
|
|
60
|
+
The base URL of the Guidewire Cloud API.
|
|
61
|
+
auth_type (str):
|
|
62
|
+
The authorization type, either "oauth" or "basic".
|
|
63
|
+
client_id (str):
|
|
64
|
+
The Client ID for authentication (optional, required for client credential flow).
|
|
65
|
+
client_secret (str):
|
|
66
|
+
The Client Secret for authentication (optional, required for client credential flow).
|
|
67
|
+
username (str):
|
|
68
|
+
The username for authentication (optional, required for password-based authentication).
|
|
69
|
+
password (str):
|
|
70
|
+
The password for authentication (optional, required for password-based authentication).
|
|
71
|
+
scope (str):
|
|
72
|
+
The OAuth2 scope (optional).
|
|
73
|
+
logger:
|
|
74
|
+
The logging object used for all log messages. Default is default_logger.
|
|
75
|
+
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
if logger != default_logger:
|
|
79
|
+
self.logger = logger.getChild("guidewire")
|
|
80
|
+
for logfilter in logger.filters:
|
|
81
|
+
self.logger.addFilter(logfilter)
|
|
82
|
+
|
|
83
|
+
self._scope = scope
|
|
84
|
+
|
|
85
|
+
guidewire_config = {}
|
|
86
|
+
# Store the credentials and parameters in a config dictionary:
|
|
87
|
+
guidewire_config["baseUrl"] = base_url.rstrip("/")
|
|
88
|
+
guidewire_config["authType"] = auth_type
|
|
89
|
+
guidewire_config["clientId"] = client_id
|
|
90
|
+
guidewire_config["clientSecret"] = client_secret
|
|
91
|
+
guidewire_config["username"] = username
|
|
92
|
+
guidewire_config["password"] = password
|
|
93
|
+
guidewire_config["restUrl"] = guidewire_config["baseUrl"] + "/rest" # "/api/v1"
|
|
94
|
+
guidewire_config["tokenUrl"] = guidewire_config["restUrl"] + "/oauth2/token"
|
|
95
|
+
|
|
96
|
+
guidewire_config["adminUrl"] = guidewire_config["restUrl"] + "/admin/v1"
|
|
97
|
+
guidewire_config["claimUrl"] = guidewire_config["restUrl"] + "/claim/v1"
|
|
98
|
+
guidewire_config["accountUrl"] = guidewire_config["restUrl"] + "/account/v1"
|
|
99
|
+
|
|
100
|
+
self._config = guidewire_config
|
|
101
|
+
|
|
102
|
+
self._session = requests.Session()
|
|
103
|
+
|
|
104
|
+
# end method definition
|
|
105
|
+
|
|
106
|
+
def config(self) -> dict:
|
|
107
|
+
"""Return the configuration dictionary.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
dict:
|
|
111
|
+
The configuration dictionary with all settings.
|
|
112
|
+
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
return self._config
|
|
116
|
+
|
|
117
|
+
# end method definition
|
|
118
|
+
|
|
119
|
+
def authenticate(self, auth_type: str) -> HTTPBasicAuth | str | None:
|
|
120
|
+
"""Authenticate with the Guidewire API using either client credentials or username/password.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
auth_type (str):
|
|
124
|
+
The Authorization type. This can be "basic" or "oauth".
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
bool:
|
|
128
|
+
True if authentication is successful, False otherwise.
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
self._session.headers.update(self.request_header())
|
|
133
|
+
|
|
134
|
+
if auth_type == "basic":
|
|
135
|
+
username = self.config()["username"]
|
|
136
|
+
password = self.config()["password"]
|
|
137
|
+
if not self._session:
|
|
138
|
+
self._session = requests.Session()
|
|
139
|
+
self._session.auth = HTTPBasicAuth(username, password)
|
|
140
|
+
return self._session.auth
|
|
141
|
+
|
|
142
|
+
request_url = self.config()["tokenUrl"]
|
|
143
|
+
|
|
144
|
+
if self.config()["clientId"] and self.config()["clientSecret"]:
|
|
145
|
+
auth_data = {
|
|
146
|
+
"grant_type": "client_credentials",
|
|
147
|
+
"client_id": self.config()["clientId"],
|
|
148
|
+
"client_secret": self.config()["clientSecret"],
|
|
149
|
+
}
|
|
150
|
+
elif self.config()["username"] and self.config()["password"]:
|
|
151
|
+
auth_data = {
|
|
152
|
+
"grant_type": "password",
|
|
153
|
+
"username": self.config()["username"],
|
|
154
|
+
"password": self.config()["password"],
|
|
155
|
+
"client_id": self.config()["clientId"], # Required for some OAuth2 flows
|
|
156
|
+
"client_secret": self.config()["clientSecret"], # Required for some OAuth2 flows
|
|
157
|
+
}
|
|
158
|
+
else:
|
|
159
|
+
self.logger.error("Authentication requires either client credentials or username/password.")
|
|
160
|
+
return False
|
|
161
|
+
|
|
162
|
+
if self._scope:
|
|
163
|
+
auth_data["scope"] = self._scope
|
|
164
|
+
|
|
165
|
+
response = requests.post(request_url, data=auth_data)
|
|
166
|
+
if response.status_code == 200:
|
|
167
|
+
self.token = response.json().get("access_token")
|
|
168
|
+
return True
|
|
169
|
+
|
|
170
|
+
return False
|
|
171
|
+
|
|
172
|
+
# end method definition
|
|
173
|
+
|
|
174
|
+
def request_header(self, content_type: str = "application/json") -> dict:
|
|
175
|
+
"""Generate request headers including authentication token.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
content_type (str, optional):
|
|
179
|
+
Custom content type for the request.
|
|
180
|
+
Typical value for Guidewire is application/json.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
dict:
|
|
184
|
+
A dictionary containing authorization headers.
|
|
185
|
+
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
request_header = {
|
|
189
|
+
"User-Agent": USER_AGENT,
|
|
190
|
+
"Content-Type": content_type,
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if self.config()["authType"] == "oauth":
|
|
194
|
+
if not self._access_token:
|
|
195
|
+
self.logger.error("Authentication required. Call authenticate() first.")
|
|
196
|
+
return None
|
|
197
|
+
request_header["Authorization"] = ("Bearer {}".format(self._access_token),)
|
|
198
|
+
|
|
199
|
+
return request_header
|
|
200
|
+
|
|
201
|
+
# end method definition
|
|
202
|
+
|
|
203
|
+
def do_request(self, method: str, url: str, data: dict | None = None, params: dict | None = None) -> dict:
|
|
204
|
+
"""Send a request to the Guidewire REST API.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
method (str):
|
|
208
|
+
The HTTP method to use (GET, POST, PUT, DELETE).
|
|
209
|
+
url (str):
|
|
210
|
+
The API endpoint to call.
|
|
211
|
+
data (dict):
|
|
212
|
+
The request payload (if applicable).
|
|
213
|
+
params (dict):
|
|
214
|
+
The URL parameters (if applicable).
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
dict:
|
|
218
|
+
Response as a dictionary.
|
|
219
|
+
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
response = self._session.request(
|
|
223
|
+
method=method, url=url, headers=self.request_header(), data=data, params=params
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
return response.json() if response.content else {}
|
|
227
|
+
|
|
228
|
+
# end method definition
|
|
229
|
+
|
|
230
|
+
def process_parameters(
|
|
231
|
+
self, fields: list | None = None, filters: list | None = None, page_size: int | None = 25
|
|
232
|
+
) -> str | None:
|
|
233
|
+
"""Determine the request parameters (filters, fields).
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
fields (list | None, optional):
|
|
237
|
+
List of filter values. Defaults to None.
|
|
238
|
+
filters (list | None, optional):
|
|
239
|
+
List of filter values. Defaults to None.
|
|
240
|
+
page_size (int, optional):
|
|
241
|
+
The maximum number of groups to return.
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
str | None:
|
|
245
|
+
Encoded URL parameters for the request URL.
|
|
246
|
+
|
|
247
|
+
"""
|
|
248
|
+
|
|
249
|
+
query = {}
|
|
250
|
+
|
|
251
|
+
if fields:
|
|
252
|
+
fields = ",".join(fields)
|
|
253
|
+
query["fields"] = fields
|
|
254
|
+
|
|
255
|
+
for filter_dict in filters or []:
|
|
256
|
+
if "op" not in filter_dict:
|
|
257
|
+
filter_dict["op"] = "eq"
|
|
258
|
+
if "attribute" not in filter_dict:
|
|
259
|
+
self.logger.error("Missing attribute in filter condition!")
|
|
260
|
+
return None
|
|
261
|
+
if "value" not in filter_dict:
|
|
262
|
+
self.logger.error("Missing value(s) in filter condition!")
|
|
263
|
+
return None
|
|
264
|
+
elif isinstance(filter_dict["value"], list):
|
|
265
|
+
filter_dict["value"] = ",".join(filter_dict["value"])
|
|
266
|
+
query["filter"] = (
|
|
267
|
+
filter_dict.get("attribute") + ":" + filter_dict.get("op") + ":" + filter_dict.get("value")
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
if page_size:
|
|
271
|
+
query["pageSize"] = page_size
|
|
272
|
+
|
|
273
|
+
encoded_query = urllib.parse.urlencode(query=query, doseq=True)
|
|
274
|
+
|
|
275
|
+
return encoded_query
|
|
276
|
+
|
|
277
|
+
# end method definition
|
|
278
|
+
|
|
279
|
+
def get_groups(
|
|
280
|
+
self,
|
|
281
|
+
fields: list | None = None,
|
|
282
|
+
filters: list | None = None,
|
|
283
|
+
page_size: int = 25,
|
|
284
|
+
next_page_url: str | None = None,
|
|
285
|
+
) -> dict:
|
|
286
|
+
"""Retrieve a list of Guidewire groups.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
fields (list):
|
|
290
|
+
The list of fields in the results. If None, all default
|
|
291
|
+
fields are returned.
|
|
292
|
+
Fields for Guidewire accounts:
|
|
293
|
+
- *all = return all fields
|
|
294
|
+
- *default = return just the default list of fields
|
|
295
|
+
- *summary = return the fields defined for giving a summary
|
|
296
|
+
- *detail = details
|
|
297
|
+
- displayName
|
|
298
|
+
- groupType
|
|
299
|
+
- id
|
|
300
|
+
- loadFactor
|
|
301
|
+
- name
|
|
302
|
+
- organization
|
|
303
|
+
- parent
|
|
304
|
+
- securityZone
|
|
305
|
+
- supervisor
|
|
306
|
+
filters (list):
|
|
307
|
+
List of dictionaries with three keys each:
|
|
308
|
+
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
309
|
+
- "op" - operator:
|
|
310
|
+
* eq - equal
|
|
311
|
+
* ne - not equal
|
|
312
|
+
* lt - less than - also usable for dates (before)
|
|
313
|
+
* gt - greater than - also usable for dates (after)
|
|
314
|
+
* le - less or equal
|
|
315
|
+
* ge - greater or equal
|
|
316
|
+
* in - is in list
|
|
317
|
+
* ni - is NOT in list
|
|
318
|
+
* sw - starts with
|
|
319
|
+
* cn - contains
|
|
320
|
+
- "value": the value to filter for. Either literal or list of values
|
|
321
|
+
page_size (int, optional):
|
|
322
|
+
The maximum number of groups to return.
|
|
323
|
+
next_page_url (str, optional):
|
|
324
|
+
The Guidewire URL to retrieve the next page of Guidewire groups (pagination).
|
|
325
|
+
This is used for the iterator get_groups_iterator() below.
|
|
326
|
+
|
|
327
|
+
Returns:
|
|
328
|
+
dict:
|
|
329
|
+
JSON response containing account data. None in case of an error.
|
|
330
|
+
|
|
331
|
+
Example reponse:
|
|
332
|
+
{
|
|
333
|
+
'count': 25,
|
|
334
|
+
'data': [
|
|
335
|
+
{
|
|
336
|
+
'attributes': {
|
|
337
|
+
'displayName': 'Actuary Unit',
|
|
338
|
+
'groupType': {...},
|
|
339
|
+
'id': 'pc:S_I-NOU3hb3FU0qTfu8fd',
|
|
340
|
+
'loadFactor': 100,
|
|
341
|
+
'name': 'Actuary Unit',
|
|
342
|
+
'organization': {...},
|
|
343
|
+
'parent': {...},
|
|
344
|
+
'securityZone': {...},
|
|
345
|
+
'supervisor': {...}
|
|
346
|
+
},
|
|
347
|
+
'checksum': '0',
|
|
348
|
+
'links': {
|
|
349
|
+
'self': {...}
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
...
|
|
353
|
+
],
|
|
354
|
+
'links': {
|
|
355
|
+
'first': {
|
|
356
|
+
'href': '/admin/v1/groups?fields=%2Adefault',
|
|
357
|
+
'methods': ['get']
|
|
358
|
+
},
|
|
359
|
+
'next': {
|
|
360
|
+
'href': '/admin/v1/groups?fields=%2Adefault&pageOffset=25',
|
|
361
|
+
'methods': ['get']
|
|
362
|
+
},
|
|
363
|
+
'self': {...}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
"""
|
|
368
|
+
|
|
369
|
+
if not next_page_url:
|
|
370
|
+
request_url = self.config()["adminUrl"] + "/groups"
|
|
371
|
+
|
|
372
|
+
encoded_query = self.process_parameters(fields=fields, filters=filters, page_size=page_size)
|
|
373
|
+
if encoded_query:
|
|
374
|
+
request_url += "?" + encoded_query
|
|
375
|
+
else:
|
|
376
|
+
request_url = self.config()["restUrl"] + next_page_url
|
|
377
|
+
|
|
378
|
+
return self.do_request(method="GET", url=request_url)
|
|
379
|
+
|
|
380
|
+
# end method definition
|
|
381
|
+
|
|
382
|
+
def get_groups_iterator(self, fields: list | None = None, filters: list | None = None, page_size: int = 25) -> iter:
|
|
383
|
+
"""Get an iterator object that can be used to traverse all Guidewire groups.
|
|
384
|
+
|
|
385
|
+
Returning a generator avoids loading a large number of nodes into memory at once. Instead you
|
|
386
|
+
can iterate over the potential large list of groups.
|
|
387
|
+
|
|
388
|
+
Example usage:
|
|
389
|
+
groups = guidewire_object.get_groups_iterator()
|
|
390
|
+
for group in groups:
|
|
391
|
+
logger.info("Traversing Guidewire group -> '%s'...", group.get("attributes", {}).get("displayName"))
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
iter:
|
|
395
|
+
A generator yielding one Guidewire group per iteration.
|
|
396
|
+
If the REST API fails, returns no value.
|
|
397
|
+
|
|
398
|
+
"""
|
|
399
|
+
|
|
400
|
+
next_page_url = None
|
|
401
|
+
|
|
402
|
+
while True:
|
|
403
|
+
response = self.get_groups(fields=fields, filters=filters, page_size=page_size, next_page_url=next_page_url)
|
|
404
|
+
if not response or "data" not in response:
|
|
405
|
+
# Don't return None! Plain return is what we need for iterators.
|
|
406
|
+
# Natural Termination: If the generator does not yield, it behaves
|
|
407
|
+
# like an empty iterable when used in a loop or converted to a list:
|
|
408
|
+
return
|
|
409
|
+
|
|
410
|
+
# Yield users one at a time:
|
|
411
|
+
yield from response["data"]
|
|
412
|
+
|
|
413
|
+
# See if we have an additional result page.
|
|
414
|
+
# If not terminate the iterator and return
|
|
415
|
+
# no value.
|
|
416
|
+
next_page_url = response.get("links", {}).get("next", {}).get("href")
|
|
417
|
+
if not next_page_url:
|
|
418
|
+
# Don't return None! Plain return is what we need for iterators.
|
|
419
|
+
# Natural Termination: If the generator does not yield, it behaves
|
|
420
|
+
# like an empty iterable when used in a loop or converted to a list:
|
|
421
|
+
return
|
|
422
|
+
|
|
423
|
+
# end method definition
|
|
424
|
+
|
|
425
|
+
def get_group(self, group_id: str) -> dict:
|
|
426
|
+
"""Retrieve details of a specific group.
|
|
427
|
+
|
|
428
|
+
Args:
|
|
429
|
+
group_id: The unique identifier of the group.
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
dict: JSON response containing group details.
|
|
433
|
+
|
|
434
|
+
Example response;
|
|
435
|
+
{
|
|
436
|
+
'data': {
|
|
437
|
+
'attributes': {
|
|
438
|
+
'displayName': 'Actuary Unit',
|
|
439
|
+
'groupType': {
|
|
440
|
+
'code': 'actuary',
|
|
441
|
+
'name': 'Actuary unit'
|
|
442
|
+
},
|
|
443
|
+
'id': 'pc:S_I-NOU3hb3FU0qTfu8fd',
|
|
444
|
+
'loadFactor': 100,
|
|
445
|
+
'name': 'Actuary Unit',
|
|
446
|
+
'organization': {
|
|
447
|
+
'displayName': 'Enigma Fire & Casualty',
|
|
448
|
+
'id': 'systemTables:1',
|
|
449
|
+
'type': 'Organization',
|
|
450
|
+
'uri': '/admin/v1/organizations/systemTables:1'
|
|
451
|
+
},
|
|
452
|
+
'parent': {
|
|
453
|
+
'displayName': 'Enigma Fire & Casualty',
|
|
454
|
+
'id': 'systemTables:1',
|
|
455
|
+
'type': 'Group',
|
|
456
|
+
'uri': '/admin/v1/groups/systemTables:1'
|
|
457
|
+
},
|
|
458
|
+
'securityZone': {
|
|
459
|
+
'displayName': 'HO UW',
|
|
460
|
+
'id': 'pc:So-lJXKuecOco_hGZ_8iR'
|
|
461
|
+
},
|
|
462
|
+
'supervisor': {
|
|
463
|
+
'displayName': 'Super Visor',
|
|
464
|
+
'id': 'pc:S1cZ06yduoQadHVOcVCyv',
|
|
465
|
+
'type': 'User',
|
|
466
|
+
'uri': '/admin/v1/users/pc:S1cZ06yduoQadHVOcVCyv'
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
'checksum': '0',
|
|
470
|
+
'links': {...}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
"""
|
|
475
|
+
|
|
476
|
+
request_url = self.config()["adminUrl"] + "/groups/" + str(group_id)
|
|
477
|
+
|
|
478
|
+
return self.do_request(method="GET", url=request_url)
|
|
479
|
+
|
|
480
|
+
# end method definition
|
|
481
|
+
|
|
482
|
+
def get_users(
|
|
483
|
+
self,
|
|
484
|
+
fields: list | None = None,
|
|
485
|
+
filters: list | None = None,
|
|
486
|
+
page_size: int = 25,
|
|
487
|
+
next_page_url: str | None = None,
|
|
488
|
+
) -> dict:
|
|
489
|
+
"""Retrieve a list of Guidewire users.
|
|
490
|
+
|
|
491
|
+
Args:
|
|
492
|
+
fields (list):
|
|
493
|
+
The list of fields in the results. If None, all default
|
|
494
|
+
fields are returned.
|
|
495
|
+
Fields for Guidewire accounts:
|
|
496
|
+
- *all = return all fields
|
|
497
|
+
- *default = return just the default list of fields
|
|
498
|
+
- *summary = return the fields defined for giving a summary
|
|
499
|
+
- *detail = details
|
|
500
|
+
- displayName
|
|
501
|
+
- groupType
|
|
502
|
+
- id
|
|
503
|
+
- loadFactor
|
|
504
|
+
- name
|
|
505
|
+
- organization
|
|
506
|
+
- parent
|
|
507
|
+
- securityZone
|
|
508
|
+
- supervisor
|
|
509
|
+
filters (list):
|
|
510
|
+
List of dictionaries with three keys each:
|
|
511
|
+
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
512
|
+
- "op" - operator:
|
|
513
|
+
* eq - equal
|
|
514
|
+
* ne - not equal
|
|
515
|
+
* lt - less than - also usable for dates (before)
|
|
516
|
+
* gt - greater than - also usable for dates (after)
|
|
517
|
+
* le - less or equal
|
|
518
|
+
* ge - greater or equal
|
|
519
|
+
* in - is in list
|
|
520
|
+
* ni - is NOT in list
|
|
521
|
+
* sw - starts with
|
|
522
|
+
* cn - contains
|
|
523
|
+
- "value": the value to filter for. Either literal or list of values
|
|
524
|
+
page_size (int, optional):
|
|
525
|
+
The maximum number of groups to return.
|
|
526
|
+
next_page_url (str, optional):
|
|
527
|
+
The Guidewire URL to retrieve the next page of Guidewire groups (pagination).
|
|
528
|
+
This is used for the iterator get_groups_iterator() below.
|
|
529
|
+
|
|
530
|
+
Returns:
|
|
531
|
+
dict:
|
|
532
|
+
JSON response containing account data.
|
|
533
|
+
|
|
534
|
+
Example reponse:
|
|
535
|
+
{
|
|
536
|
+
'count': 10,
|
|
537
|
+
'data': [
|
|
538
|
+
{
|
|
539
|
+
'attributes': {
|
|
540
|
+
'active': True,
|
|
541
|
+
'displayName': 'Alice Applegate',
|
|
542
|
+
'externalUser': False,
|
|
543
|
+
'firstName': 'Alice',
|
|
544
|
+
'groups': [
|
|
545
|
+
{
|
|
546
|
+
'displayName': 'Eastern Region Underwriting',
|
|
547
|
+
'id': 'pc:SDrypgK62o6oS1TxOGcvF',
|
|
548
|
+
'type': 'Group',
|
|
549
|
+
'uri': '/admin/v1/groups/pc:SDrypgK62o6oS1TxOGcvF'
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
'displayName': 'Los Angeles Branch UW',
|
|
553
|
+
'id': 'pc:SJxAbEha2jYpG9Mb5_KAo',
|
|
554
|
+
'type': 'Group',
|
|
555
|
+
'uri': '/admin/v1/groups/pc:SJxAbEha2jYpG9Mb5_KAo'
|
|
556
|
+
}
|
|
557
|
+
],
|
|
558
|
+
'id': 'pc:Si6MBM-35EAhneDubeFsl',
|
|
559
|
+
'lastName': 'Applegate',
|
|
560
|
+
'organization': {
|
|
561
|
+
'displayName': 'Enigma Fire & Casualty',
|
|
562
|
+
'id': 'systemTables:1',
|
|
563
|
+
'type': 'Organization',
|
|
564
|
+
'uri': '/admin/v1/organizations/systemTables:1'
|
|
565
|
+
},
|
|
566
|
+
'roles': [
|
|
567
|
+
{
|
|
568
|
+
'displayName': 'Reinsurance Manager',
|
|
569
|
+
'id': 'reinsurance_manager',
|
|
570
|
+
'type': 'Role',
|
|
571
|
+
'uri': '/admin/v1/roles/reinsurance_manager'
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
'displayName': 'Underwriter',
|
|
575
|
+
'id': 'underwriter',
|
|
576
|
+
'type': 'Role',
|
|
577
|
+
'uri': '/admin/v1/roles/underwriter'
|
|
578
|
+
}
|
|
579
|
+
],
|
|
580
|
+
'useOrgAddress': True,
|
|
581
|
+
'useProducerCodeSecurity': False,
|
|
582
|
+
'userType': {
|
|
583
|
+
'code': 'underwriter',
|
|
584
|
+
'name': 'Underwriter'
|
|
585
|
+
},
|
|
586
|
+
'username': 'aapplegate',
|
|
587
|
+
'uwAuthorityProfiles': [
|
|
588
|
+
{
|
|
589
|
+
'displayName': 'Underwriter 1',
|
|
590
|
+
'id': 'pc:underwriter1',
|
|
591
|
+
'type': 'UWAuthorityProfile',
|
|
592
|
+
'uri': '/admin/v1/uw-authority-profiles/pc:underwriter1'
|
|
593
|
+
}
|
|
594
|
+
],
|
|
595
|
+
'vacationStatus': {
|
|
596
|
+
'code': 'atwork',
|
|
597
|
+
'name': 'At work'
|
|
598
|
+
},
|
|
599
|
+
'workPhone': {
|
|
600
|
+
'displayName': '213-555-8164',
|
|
601
|
+
'number': '2135558164'
|
|
602
|
+
}
|
|
603
|
+
},
|
|
604
|
+
'checksum': 'ec4710cd2af59bdc1cd7e15a18707d84',
|
|
605
|
+
'links': {
|
|
606
|
+
'self': {'href': '/admin/v1/users/pc:Si6MBM-35EAhneDubeFsl', 'methods': ['delete', 'get', 'patch']}
|
|
607
|
+
}
|
|
608
|
+
},
|
|
609
|
+
...
|
|
610
|
+
],
|
|
611
|
+
'links': {
|
|
612
|
+
'first': {'href': '/admin/v1/users?fields=%2Adefault&pageSize=20', 'methods': ['get']},
|
|
613
|
+
'next': {'href': '/admin/v1/users?fields=%2Adefault&pageSize=20&pageOffset=20', 'methods': ['get']},
|
|
614
|
+
'self': {'href': '/admin/v1/users?fields=%2Adefault&pageSize=20', 'methods': ['get']}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
"""
|
|
619
|
+
|
|
620
|
+
if not next_page_url:
|
|
621
|
+
request_url = self.config()["adminUrl"] + "/users"
|
|
622
|
+
|
|
623
|
+
encoded_query = self.process_parameters(fields=fields, filters=filters, page_size=page_size)
|
|
624
|
+
if encoded_query:
|
|
625
|
+
request_url += "?" + encoded_query
|
|
626
|
+
else:
|
|
627
|
+
request_url = self.config()["restUrl"] + next_page_url
|
|
628
|
+
|
|
629
|
+
return self.do_request(method="GET", url=request_url)
|
|
630
|
+
|
|
631
|
+
# end method definition
|
|
632
|
+
|
|
633
|
+
def get_users_iterator(self, fields: list | None = None, filters: list | None = None, page_size: int = 25) -> iter:
|
|
634
|
+
"""Get an iterator object that can be used to traverse all Guidewire users.
|
|
635
|
+
|
|
636
|
+
Returning a generator avoids loading a large number of nodes into memory at once. Instead you
|
|
637
|
+
can iterate over the potential large list of users.
|
|
638
|
+
|
|
639
|
+
Example usage:
|
|
640
|
+
users = guidewire_object.get_users_iterator()
|
|
641
|
+
for user in users:
|
|
642
|
+
logger.info("Traversing Guidewire user -> '%s'...", user.get("attributes", {}).get("displayName"))
|
|
643
|
+
|
|
644
|
+
Args:
|
|
645
|
+
fields (list):
|
|
646
|
+
The list of fields in the results. If None, all default
|
|
647
|
+
fields are returned.
|
|
648
|
+
Fields for Guidewire accounts:
|
|
649
|
+
- *all = return all fields
|
|
650
|
+
- *default = return just the default list of fields
|
|
651
|
+
- *summary = return the fields defined for giving a summary
|
|
652
|
+
- *detail = details
|
|
653
|
+
- active
|
|
654
|
+
- displayName
|
|
655
|
+
- externalUser
|
|
656
|
+
- firstName
|
|
657
|
+
- id
|
|
658
|
+
- lastName
|
|
659
|
+
- organization
|
|
660
|
+
- useOrgAddress
|
|
661
|
+
- useProducerCodeSecurity
|
|
662
|
+
- username
|
|
663
|
+
filters (list):
|
|
664
|
+
List of dictionaries with three keys each:
|
|
665
|
+
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
666
|
+
- "op" - operator:
|
|
667
|
+
* eq - equal
|
|
668
|
+
* ne - not equal
|
|
669
|
+
* lt - less than - also usable for dates (before)
|
|
670
|
+
* gt - greater than - also usable for dates (after)
|
|
671
|
+
* le - less or equal
|
|
672
|
+
* ge - greater or equal
|
|
673
|
+
* in - is in list
|
|
674
|
+
* ni - is NOT in list
|
|
675
|
+
* sw - starts with
|
|
676
|
+
* cn - contains
|
|
677
|
+
- "value": the value to filter for. Either literal or list of values
|
|
678
|
+
page_size (int, optional):
|
|
679
|
+
The maximum number of groups to return.
|
|
680
|
+
next_page_url (str, optional):
|
|
681
|
+
The Guidewire URL to retrieve the next page of Guidewire groups (pagination).
|
|
682
|
+
This is used for the iterator get_groups_iterator() below.
|
|
683
|
+
|
|
684
|
+
Returns:
|
|
685
|
+
iter:
|
|
686
|
+
A generator yielding one Guidewire user per iteration.
|
|
687
|
+
If the REST API fails, returns no value.
|
|
688
|
+
|
|
689
|
+
"""
|
|
690
|
+
|
|
691
|
+
next_page_url = None
|
|
692
|
+
|
|
693
|
+
while True:
|
|
694
|
+
response = self.get_users(fields=fields, filters=filters, page_size=page_size, next_page_url=next_page_url)
|
|
695
|
+
if not response or "data" not in response:
|
|
696
|
+
# Don't return None! Plain return is what we need for iterators.
|
|
697
|
+
# Natural Termination: If the generator does not yield, it behaves
|
|
698
|
+
# like an empty iterable when used in a loop or converted to a list:
|
|
699
|
+
return
|
|
700
|
+
|
|
701
|
+
# Yield users one at a time:
|
|
702
|
+
yield from response["data"]
|
|
703
|
+
|
|
704
|
+
# See if we have an additional result page.
|
|
705
|
+
# If not terminate the iterator and return
|
|
706
|
+
# no value.
|
|
707
|
+
next_page_url = response.get("links", {}).get("next", {}).get("href")
|
|
708
|
+
if not next_page_url:
|
|
709
|
+
# Don't return None! Plain return is what we need for iterators.
|
|
710
|
+
# Natural Termination: If the generator does not yield, it behaves
|
|
711
|
+
# like an empty iterable when used in a loop or converted to a list:
|
|
712
|
+
return
|
|
713
|
+
|
|
714
|
+
# end method definition
|
|
715
|
+
|
|
716
|
+
def get_user(self, user_id: str) -> dict:
|
|
717
|
+
"""Retrieve details of a specific user.
|
|
718
|
+
|
|
719
|
+
Args:
|
|
720
|
+
user_id:
|
|
721
|
+
The unique identifier of the group.
|
|
722
|
+
|
|
723
|
+
Returns:
|
|
724
|
+
dict:
|
|
725
|
+
JSON response containing group details.
|
|
726
|
+
|
|
727
|
+
Example response;
|
|
728
|
+
{
|
|
729
|
+
'data': {
|
|
730
|
+
'attributes': {
|
|
731
|
+
'active': True,
|
|
732
|
+
'displayName': 'Alice Applegate',
|
|
733
|
+
'externalUser': False,
|
|
734
|
+
'firstName': 'Alice',
|
|
735
|
+
'groups': [{...}, {...}],
|
|
736
|
+
'id': 'pc:Si6MBM-35EAhneDubeFsl',
|
|
737
|
+
'lastName': 'Applegate',
|
|
738
|
+
'organization': {
|
|
739
|
+
'displayName': 'Enigma Fire & Casualty',
|
|
740
|
+
'id': 'systemTables:1',
|
|
741
|
+
'type': 'Organization',
|
|
742
|
+
'uri': '/admin/v1/organizations/systemTables:1'
|
|
743
|
+
},
|
|
744
|
+
'roles': [{...}, {...}],
|
|
745
|
+
'useOrgAddress': True,
|
|
746
|
+
'useProducerCodeSecurity': False,
|
|
747
|
+
'userType': {
|
|
748
|
+
'code': 'underwriter',
|
|
749
|
+
'name': 'Underwriter'
|
|
750
|
+
},
|
|
751
|
+
'username': 'aapplegate',
|
|
752
|
+
'uwAuthorityProfiles': [{...}],
|
|
753
|
+
'vacationStatus': {
|
|
754
|
+
'code': 'atwork',
|
|
755
|
+
'name': 'At work'
|
|
756
|
+
},
|
|
757
|
+
'workPhone': {
|
|
758
|
+
'displayName': '213-555-8164',
|
|
759
|
+
'number': '2135558164'
|
|
760
|
+
}
|
|
761
|
+
},
|
|
762
|
+
'checksum': 'ec4710cd2af59bdc1cd7e15a18707d84',
|
|
763
|
+
'links': {
|
|
764
|
+
'producer-codes': {
|
|
765
|
+
'href': '/admin/v1/users/pc:Si6MBM-35EAhneDubeFsl/producer-codes',
|
|
766
|
+
'methods': [...]
|
|
767
|
+
},
|
|
768
|
+
'self': {
|
|
769
|
+
'href': '/admin/v1/users/pc:Si6MBM-35EAhneDubeFsl',
|
|
770
|
+
'methods': [...]
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
"""
|
|
777
|
+
|
|
778
|
+
request_url = self.config()["adminUrl"] + "/users/" + str(user_id)
|
|
779
|
+
|
|
780
|
+
return self.do_request(method="GET", url=request_url)
|
|
781
|
+
|
|
782
|
+
# end method definition
|
|
783
|
+
|
|
784
|
+
def update_user(self, user_id: str, user_data: dict) -> dict:
|
|
785
|
+
"""Update an existing user.
|
|
786
|
+
|
|
787
|
+
Args:
|
|
788
|
+
user_id:
|
|
789
|
+
The unique identifier of the user.
|
|
790
|
+
user_data:
|
|
791
|
+
Dictionary containing updated user information.
|
|
792
|
+
|
|
793
|
+
Returns:
|
|
794
|
+
dict:
|
|
795
|
+
Response with updated user details.
|
|
796
|
+
|
|
797
|
+
"""
|
|
798
|
+
|
|
799
|
+
request_url = self.config()["adminUrl"] + "/users/" + str(user_id)
|
|
800
|
+
|
|
801
|
+
return self.do_request(method="PUT", url=request_url, data=user_data)
|
|
802
|
+
|
|
803
|
+
# end method definition
|
|
804
|
+
|
|
805
|
+
def get_accounts(
|
|
806
|
+
self,
|
|
807
|
+
fields: list | None = None,
|
|
808
|
+
filters: list | None = None,
|
|
809
|
+
page_size: int = 25,
|
|
810
|
+
next_page_url: str | None = None,
|
|
811
|
+
) -> dict | None:
|
|
812
|
+
"""Retrieve a list of accounts.
|
|
813
|
+
|
|
814
|
+
Args:
|
|
815
|
+
fields (list):
|
|
816
|
+
The list of fields in the results. If None, all default
|
|
817
|
+
fields are returned.
|
|
818
|
+
Fields for Guidewire accounts:
|
|
819
|
+
- *all = return all fields
|
|
820
|
+
- *default = return just the default list of fields
|
|
821
|
+
- *summary = return the fields defined for giving a summary
|
|
822
|
+
- *detail = details
|
|
823
|
+
- accountNumber
|
|
824
|
+
- accountHolder
|
|
825
|
+
- accountStatus
|
|
826
|
+
- businessOperationsDescription
|
|
827
|
+
- createdDate
|
|
828
|
+
- frozen
|
|
829
|
+
- id
|
|
830
|
+
- industryCode
|
|
831
|
+
- organizationType
|
|
832
|
+
- preferredCoverageCurrency
|
|
833
|
+
- preferredSettlementCurrency
|
|
834
|
+
- primaryLanguage
|
|
835
|
+
- primaryLocale
|
|
836
|
+
- primaryLocation
|
|
837
|
+
- producerCodes
|
|
838
|
+
filters (list):
|
|
839
|
+
List of dictionaries with three keys each:
|
|
840
|
+
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
841
|
+
- "op" - operator:
|
|
842
|
+
* eq - equal
|
|
843
|
+
* ne - not equal
|
|
844
|
+
* lt - less than - also usable for dates (before)
|
|
845
|
+
* gt - greater than - also usable for dates (after)
|
|
846
|
+
* le - less or equal
|
|
847
|
+
* ge - greater or equal
|
|
848
|
+
* in - is in list
|
|
849
|
+
* ni - is NOT in list
|
|
850
|
+
* sw - starts with
|
|
851
|
+
* cn - contains
|
|
852
|
+
- "value": the filue to filter for. Either literal or list of values
|
|
853
|
+
page_size (int, optional):
|
|
854
|
+
The maximum number of groups to return.
|
|
855
|
+
next_page_url (str, optional):
|
|
856
|
+
The Guidewire URL to retrieve the next page of Guidewire groups (pagination).
|
|
857
|
+
This is used for the iterator get_groups_iterator() below.
|
|
858
|
+
|
|
859
|
+
Returns:
|
|
860
|
+
dict:
|
|
861
|
+
JSON response containing account data. None in case of an error.
|
|
862
|
+
|
|
863
|
+
"""
|
|
864
|
+
|
|
865
|
+
if not next_page_url:
|
|
866
|
+
request_url = self.config()["accountUrl"] + "/accounts"
|
|
867
|
+
|
|
868
|
+
encoded_query = self.process_parameters(fields=fields, filters=filters, page_size=page_size)
|
|
869
|
+
if encoded_query:
|
|
870
|
+
request_url += "?" + encoded_query
|
|
871
|
+
else:
|
|
872
|
+
request_url = self.config()["restUrl"] + next_page_url
|
|
873
|
+
|
|
874
|
+
return self.do_request(method="GET", url=request_url)
|
|
875
|
+
|
|
876
|
+
# end method definition
|
|
877
|
+
|
|
878
|
+
def get_accounts_iterator(
|
|
879
|
+
self, fields: list | None = None, filters: list | None = None, page_size: int = 25
|
|
880
|
+
) -> iter:
|
|
881
|
+
"""Get an iterator object that can be used to traverse all Guidewire accounts.
|
|
882
|
+
|
|
883
|
+
Returning a generator avoids loading a large number of nodes into memory at once. Instead you
|
|
884
|
+
can iterate over the potential large list of groups.
|
|
885
|
+
|
|
886
|
+
Example usage:
|
|
887
|
+
accounts = guidewire_object.get_accounts_iterator()
|
|
888
|
+
for account in accounts:
|
|
889
|
+
logger.info("Traversing Guidewire account -> '%s'...", account.get("attributes", {}).get("displayName"))
|
|
890
|
+
|
|
891
|
+
Returns:
|
|
892
|
+
iter:
|
|
893
|
+
A generator yielding one Guidewire account per iteration.
|
|
894
|
+
If the REST API fails, returns no value.
|
|
895
|
+
|
|
896
|
+
"""
|
|
897
|
+
|
|
898
|
+
next_page_url = None
|
|
899
|
+
|
|
900
|
+
while True:
|
|
901
|
+
response = self.get_accounts(
|
|
902
|
+
fields=fields, filters=filters, page_size=page_size, next_page_url=next_page_url
|
|
903
|
+
)
|
|
904
|
+
if not response or "data" not in response:
|
|
905
|
+
# Don't return None! Plain return is what we need for iterators.
|
|
906
|
+
# Natural Termination: If the generator does not yield, it behaves
|
|
907
|
+
# like an empty iterable when used in a loop or converted to a list:
|
|
908
|
+
return
|
|
909
|
+
|
|
910
|
+
# Yield users one at a time:
|
|
911
|
+
yield from response["data"]
|
|
912
|
+
|
|
913
|
+
# See if we have an additional result page.
|
|
914
|
+
# If not terminate the iterator and return
|
|
915
|
+
# no value.
|
|
916
|
+
next_page_url = response.get("links", {}).get("next", {}).get("href")
|
|
917
|
+
if not next_page_url:
|
|
918
|
+
# Don't return None! Plain return is what we need for iterators.
|
|
919
|
+
# Natural Termination: If the generator does not yield, it behaves
|
|
920
|
+
# like an empty iterable when used in a loop or converted to a list:
|
|
921
|
+
return
|
|
922
|
+
|
|
923
|
+
# end method definition
|
|
924
|
+
|
|
925
|
+
def get_account(self, account_id: str) -> dict:
|
|
926
|
+
"""Retrieve details of a specific account.
|
|
927
|
+
|
|
928
|
+
Args:
|
|
929
|
+
account_id:
|
|
930
|
+
The unique identifier of the account.
|
|
931
|
+
|
|
932
|
+
Returns:
|
|
933
|
+
dict:
|
|
934
|
+
JSON response containing account details.
|
|
935
|
+
|
|
936
|
+
"""
|
|
937
|
+
|
|
938
|
+
request_url = self.config()["accountUrl"] + "/accounts/" + str(account_id)
|
|
939
|
+
|
|
940
|
+
return self.do_request(method="GET", url=request_url)
|
|
941
|
+
|
|
942
|
+
# end method definition
|
|
943
|
+
|
|
944
|
+
def add_account(self, account_data: dict) -> dict:
|
|
945
|
+
"""Create a new account.
|
|
946
|
+
|
|
947
|
+
Args:
|
|
948
|
+
account_data:
|
|
949
|
+
Dictionary containing account information.
|
|
950
|
+
|
|
951
|
+
Returns:
|
|
952
|
+
dict:
|
|
953
|
+
JSON response with created account details.
|
|
954
|
+
|
|
955
|
+
"""
|
|
956
|
+
|
|
957
|
+
request_url = self.config()["accountUrl"] + "/accounts"
|
|
958
|
+
|
|
959
|
+
return self.do_request(method="POST", url=request_url, data=account_data)
|
|
960
|
+
|
|
961
|
+
# end method definition
|
|
962
|
+
|
|
963
|
+
def update_account(self, account_id: str, account_data: dict) -> dict:
|
|
964
|
+
"""Update an existing account.
|
|
965
|
+
|
|
966
|
+
Args:
|
|
967
|
+
account_id:
|
|
968
|
+
The unique identifier of the account.
|
|
969
|
+
account_data:
|
|
970
|
+
Dictionary containing updated account information.
|
|
971
|
+
|
|
972
|
+
Returns:
|
|
973
|
+
dict:
|
|
974
|
+
JSON response with updated account details.
|
|
975
|
+
|
|
976
|
+
"""
|
|
977
|
+
|
|
978
|
+
request_url = self.config()["accountUrl"] + "/accounts/" + str(account_id)
|
|
979
|
+
|
|
980
|
+
return self.do_request(method="PUT", url=request_url, data=account_data)
|
|
981
|
+
|
|
982
|
+
# end method definition
|
|
983
|
+
|
|
984
|
+
def delete_account(self, account_id: str) -> dict:
|
|
985
|
+
"""Delete an account.
|
|
986
|
+
|
|
987
|
+
Args:
|
|
988
|
+
account_id: The unique identifier of the account to delete.
|
|
989
|
+
|
|
990
|
+
Returns:
|
|
991
|
+
dict: JSON response indicating deletion success.
|
|
992
|
+
|
|
993
|
+
"""
|
|
994
|
+
|
|
995
|
+
request_url = self.config()["accountUrl"] + "/accounts/" + str(account_id)
|
|
996
|
+
|
|
997
|
+
return self.do_request(method="DELETE", url=request_url)
|
|
998
|
+
|
|
999
|
+
# end method definition
|
|
1000
|
+
|
|
1001
|
+
def get_claims(
|
|
1002
|
+
self,
|
|
1003
|
+
fields: list | None = None,
|
|
1004
|
+
filters: list | None = None,
|
|
1005
|
+
page_size: int = 25,
|
|
1006
|
+
next_page_url: str | None = None,
|
|
1007
|
+
) -> dict | None:
|
|
1008
|
+
"""Retrieve a list of claims.
|
|
1009
|
+
|
|
1010
|
+
fields (list):
|
|
1011
|
+
The list of fields in the results. If None, all default
|
|
1012
|
+
fields are returned.
|
|
1013
|
+
Fields for Guidewire accounts:
|
|
1014
|
+
- *all = return all fields
|
|
1015
|
+
- *default = return just the default list of fields
|
|
1016
|
+
- *summary = return the fields defined for giving a summary
|
|
1017
|
+
- *detail = details
|
|
1018
|
+
- displayName
|
|
1019
|
+
- groupType
|
|
1020
|
+
- id
|
|
1021
|
+
- loadFactor
|
|
1022
|
+
- name
|
|
1023
|
+
- organization
|
|
1024
|
+
- parent
|
|
1025
|
+
- securityZone
|
|
1026
|
+
- supervisor
|
|
1027
|
+
filters (list):
|
|
1028
|
+
List of dictionaries with three keys each:
|
|
1029
|
+
- "attribute" - name of the attribute to use for the filter (available attributes see above)
|
|
1030
|
+
- "op" - operator:
|
|
1031
|
+
* eq - equal
|
|
1032
|
+
* ne - not equal
|
|
1033
|
+
* lt - less than - also usable for dates (before)
|
|
1034
|
+
* gt - greater than - also usable for dates (after)
|
|
1035
|
+
* le - less or equal
|
|
1036
|
+
* ge - greater or equal
|
|
1037
|
+
* in - is in list
|
|
1038
|
+
* ni - is NOT in list
|
|
1039
|
+
* sw - starts with
|
|
1040
|
+
* cn - contains
|
|
1041
|
+
- "value": the value to filter for. Either literal or list of values
|
|
1042
|
+
page_size (int, optional):
|
|
1043
|
+
The maximum number of groups to return.
|
|
1044
|
+
next_page_url (str, optional):
|
|
1045
|
+
The Guidewire URL to retrieve the next page of Guidewire groups (pagination).
|
|
1046
|
+
This is used for the iterator get_groups_iterator() below.
|
|
1047
|
+
|
|
1048
|
+
Returns:
|
|
1049
|
+
dict | None:
|
|
1050
|
+
JSON response containing claim data.
|
|
1051
|
+
|
|
1052
|
+
"""
|
|
1053
|
+
|
|
1054
|
+
if not next_page_url:
|
|
1055
|
+
request_url = self.config()["claimUrl"] + "/claim-infos"
|
|
1056
|
+
|
|
1057
|
+
encoded_query = self.process_parameters(fields=fields, filters=filters, page_size=page_size)
|
|
1058
|
+
if encoded_query:
|
|
1059
|
+
request_url += "?" + encoded_query
|
|
1060
|
+
else:
|
|
1061
|
+
request_url = self.config()["restUrl"] + next_page_url
|
|
1062
|
+
|
|
1063
|
+
return self.do_request(method="GET", url=request_url)
|
|
1064
|
+
|
|
1065
|
+
# end method definition
|
|
1066
|
+
|
|
1067
|
+
def get_claims_iterator(self, fields: list | None = None, filters: list | None = None, page_size: int = 25) -> iter:
|
|
1068
|
+
"""Get an iterator object that can be used to traverse all Guidewire claims.
|
|
1069
|
+
|
|
1070
|
+
Returning a generator avoids loading a large number of nodes into memory at once. Instead you
|
|
1071
|
+
can iterate over the potential large list of groups.
|
|
1072
|
+
|
|
1073
|
+
Example usage:
|
|
1074
|
+
claims = guidewire_object.get_claims_iterator()
|
|
1075
|
+
for claim in claims:
|
|
1076
|
+
logger.info("Traversing Guidewire claim -> '%s'...", claim.get("attributes", {}).get("displayName"))
|
|
1077
|
+
|
|
1078
|
+
Returns:
|
|
1079
|
+
iter:
|
|
1080
|
+
A generator yielding one Guidewire claim per iteration.
|
|
1081
|
+
If the REST API fails, returns no value.
|
|
1082
|
+
|
|
1083
|
+
"""
|
|
1084
|
+
|
|
1085
|
+
next_page_url = None
|
|
1086
|
+
|
|
1087
|
+
while True:
|
|
1088
|
+
response = self.get_claims(fields=fields, filters=filters, page_size=page_size, next_page_url=next_page_url)
|
|
1089
|
+
if not response or "data" not in response:
|
|
1090
|
+
# Don't return None! Plain return is what we need for iterators.
|
|
1091
|
+
# Natural Termination: If the generator does not yield, it behaves
|
|
1092
|
+
# like an empty iterable when used in a loop or converted to a list:
|
|
1093
|
+
return
|
|
1094
|
+
|
|
1095
|
+
# Yield users one at a time:
|
|
1096
|
+
yield from response["data"]
|
|
1097
|
+
|
|
1098
|
+
# See if we have an additional result page.
|
|
1099
|
+
# If not terminate the iterator and return
|
|
1100
|
+
# no value.
|
|
1101
|
+
next_page_url = response.get("links", {}).get("next", {}).get("href")
|
|
1102
|
+
if not next_page_url:
|
|
1103
|
+
# Don't return None! Plain return is what we need for iterators.
|
|
1104
|
+
# Natural Termination: If the generator does not yield, it behaves
|
|
1105
|
+
# like an empty iterable when used in a loop or converted to a list:
|
|
1106
|
+
return
|
|
1107
|
+
|
|
1108
|
+
# end method definition
|
|
1109
|
+
|
|
1110
|
+
def get_claim(self, claim_id: str) -> dict:
|
|
1111
|
+
"""Retrieve details of a specific claim.
|
|
1112
|
+
|
|
1113
|
+
Args:
|
|
1114
|
+
claim_id:
|
|
1115
|
+
The unique identifier of the claim.
|
|
1116
|
+
|
|
1117
|
+
Returns:
|
|
1118
|
+
dict:
|
|
1119
|
+
JSON response containing claim details.
|
|
1120
|
+
|
|
1121
|
+
"""
|
|
1122
|
+
|
|
1123
|
+
request_url = self.config()["claimUrl"] + "/claims/" + str(claim_id)
|
|
1124
|
+
|
|
1125
|
+
return self.do_request(method="GET", url=request_url)
|
|
1126
|
+
|
|
1127
|
+
# end method definition
|
|
1128
|
+
|
|
1129
|
+
def add_claim(self, claim_data: dict) -> dict:
|
|
1130
|
+
"""Create a new claim.
|
|
1131
|
+
|
|
1132
|
+
Args:
|
|
1133
|
+
claim_data (dict):
|
|
1134
|
+
Dictionary containing claim information.
|
|
1135
|
+
|
|
1136
|
+
Returns:
|
|
1137
|
+
dict:
|
|
1138
|
+
JSON response with created claim details.
|
|
1139
|
+
|
|
1140
|
+
"""
|
|
1141
|
+
|
|
1142
|
+
request_url = self.config()["claimUrl"] + "/claims"
|
|
1143
|
+
|
|
1144
|
+
return self.do_request(method="POST", url=request_url, data=claim_data)
|
|
1145
|
+
|
|
1146
|
+
# end method definition
|
|
1147
|
+
|
|
1148
|
+
def update_claim(self, claim_id: str, claim_data: dict) -> dict:
|
|
1149
|
+
"""Update an existing claim.
|
|
1150
|
+
|
|
1151
|
+
Args:
|
|
1152
|
+
claim_id:
|
|
1153
|
+
The unique identifier of the claim.
|
|
1154
|
+
claim_data:
|
|
1155
|
+
Dictionary containing updated claim information.
|
|
1156
|
+
|
|
1157
|
+
Returns:
|
|
1158
|
+
dict:
|
|
1159
|
+
Response with updated claim details.
|
|
1160
|
+
|
|
1161
|
+
"""
|
|
1162
|
+
|
|
1163
|
+
request_url = self.config()["claimUrl"] + "/claims/" + str(claim_id)
|
|
1164
|
+
|
|
1165
|
+
return self.do_request(method="PUT", url=request_url, data=claim_data)
|
|
1166
|
+
|
|
1167
|
+
# end method definition
|
|
1168
|
+
|
|
1169
|
+
def delete_claim(self, claim_id: str) -> dict:
|
|
1170
|
+
"""Delete a claim.
|
|
1171
|
+
|
|
1172
|
+
Args:
|
|
1173
|
+
claim_id (str):
|
|
1174
|
+
The unique identifier of the claim to delete.
|
|
1175
|
+
|
|
1176
|
+
Returns:
|
|
1177
|
+
dict:
|
|
1178
|
+
Response indicating deletion success.
|
|
1179
|
+
|
|
1180
|
+
"""
|
|
1181
|
+
|
|
1182
|
+
request_url = self.config()["claimUrl"] + "/claims/" + str(claim_id)
|
|
1183
|
+
|
|
1184
|
+
return self.do_request(method="DELETE", url=request_url)
|
|
1185
|
+
|
|
1186
|
+
# end method definition
|