brynq-sdk-brynq 4.2.6.dev0__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 brynq-sdk-brynq might be problematic. Click here for more details.
- brynq_sdk_brynq/__init__.py +1 -0
- brynq_sdk_brynq/brynq.py +289 -0
- brynq_sdk_brynq/credentials.py +157 -0
- brynq_sdk_brynq/customers.py +88 -0
- brynq_sdk_brynq/interfaces.py +234 -0
- brynq_sdk_brynq/mappings.py +107 -0
- brynq_sdk_brynq/organization_chart.py +251 -0
- brynq_sdk_brynq/roles.py +272 -0
- brynq_sdk_brynq/scenarios.py +3495 -0
- brynq_sdk_brynq/schemas/__init__.py +52 -0
- brynq_sdk_brynq/schemas/credentials.py +37 -0
- brynq_sdk_brynq/schemas/customers.py +108 -0
- brynq_sdk_brynq/schemas/interfaces.py +237 -0
- brynq_sdk_brynq/schemas/organization_chart.py +70 -0
- brynq_sdk_brynq/schemas/roles.py +95 -0
- brynq_sdk_brynq/schemas/scenarios.py +419 -0
- brynq_sdk_brynq/schemas/users.py +126 -0
- brynq_sdk_brynq/source_systems.py +175 -0
- brynq_sdk_brynq/users.py +405 -0
- brynq_sdk_brynq-4.2.6.dev0.dist-info/METADATA +17 -0
- brynq_sdk_brynq-4.2.6.dev0.dist-info/RECORD +23 -0
- brynq_sdk_brynq-4.2.6.dev0.dist-info/WHEEL +5 -0
- brynq_sdk_brynq-4.2.6.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Scenarios schemas for an active template interface in BrynQ API (2.0.0).
|
|
3
|
+
By default, this endpoint returns the most recent live version. If the latest version is not yet published (still a draft), the draft version is returned instead.
|
|
4
|
+
|
|
5
|
+
These schemas represent the exact structure of the response schema (application/json).
|
|
6
|
+
|
|
7
|
+
For parsed/processed scenario models and business logic, see brynq_sdk_brynq.scenarios.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from enum import Enum
|
|
12
|
+
from typing import Any, Dict, List, Literal, Optional, Union, TypedDict
|
|
13
|
+
from uuid import UUID
|
|
14
|
+
|
|
15
|
+
from pydantic import BaseModel, ConfigDict, Field, RootModel, EmailStr, field_validator
|
|
16
|
+
from pydantic.types import AwareDatetime
|
|
17
|
+
from typing_extensions import Annotated
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# ============================================================================
|
|
21
|
+
# 1. Type Aliases & Enums
|
|
22
|
+
# ============================================================================
|
|
23
|
+
|
|
24
|
+
class FieldType(str, Enum):
|
|
25
|
+
"""Enumeration of field type.
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
CUSTOM = "CUSTOM"
|
|
29
|
+
LIBRARY = "LIBRARY"
|
|
30
|
+
FIXED = "FIXED"
|
|
31
|
+
EMPTY = "EMPTY"
|
|
32
|
+
CONFIGURATION = "CONFIGURATION"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SystemType(str, Enum):
|
|
36
|
+
"""Enumeration of system type.
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
SOURCE = "source"
|
|
40
|
+
TARGET = "target"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class RelationType(str, Enum):
|
|
44
|
+
"""Cardinality of the mapping.
|
|
45
|
+
|
|
46
|
+
Defines if a record represents a simple 1:1 map or a complex N:N explosion.
|
|
47
|
+
"""
|
|
48
|
+
ONE_TO_ONE = "one_to_one"
|
|
49
|
+
ONE_TO_MANY = "one_to_many"
|
|
50
|
+
MANY_TO_ONE = "many_to_one"
|
|
51
|
+
MANY_TO_MANY = "many_to_many"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ConfigurationType(str, Enum):
|
|
55
|
+
"""Enumeration of configuration field types.
|
|
56
|
+
|
|
57
|
+
Defines the type of configuration field used in ConfigFieldValues.
|
|
58
|
+
"""
|
|
59
|
+
ATTACHMENT = "ATTACHMENT"
|
|
60
|
+
TEXT = "TEXT"
|
|
61
|
+
EMAIL = "EMAIL"
|
|
62
|
+
NUMBER = "NUMBER"
|
|
63
|
+
RICHTEXT = "RICHTEXT"
|
|
64
|
+
DATEPICKER = "DATEPICKER"
|
|
65
|
+
SELECTION = "SELECTION"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# ============================================================================
|
|
69
|
+
# 2. Value level API Models
|
|
70
|
+
# ============================================================================
|
|
71
|
+
# These classes define the shape of the values of the json returned by BrynQ API.
|
|
72
|
+
|
|
73
|
+
class MultiLanguageText(TypedDict):
|
|
74
|
+
"""Multi-language text dictionary with English and Dutch labels.
|
|
75
|
+
|
|
76
|
+
Attributes:
|
|
77
|
+
en: English text
|
|
78
|
+
nl: Dutch text
|
|
79
|
+
"""
|
|
80
|
+
en: str
|
|
81
|
+
nl: str
|
|
82
|
+
|
|
83
|
+
# VALUES
|
|
84
|
+
class MappingValue(BaseModel):
|
|
85
|
+
"""Represents a single translation rule (e.g., 'CEO' -> '96').
|
|
86
|
+
|
|
87
|
+
Both input and output dictionaries use field identifier keys (UUIDs or schema.name patterns)
|
|
88
|
+
that need to be converted to readable field names. The values are the actual data values.
|
|
89
|
+
|
|
90
|
+
Attributes:
|
|
91
|
+
input: Dictionary mapping source field identifiers (UUIDs or schema.name patterns) to source values.
|
|
92
|
+
Example: {"work_schema-title": "CEO"} means source field "work_schema-title" has value "CEO".
|
|
93
|
+
The key is a field identifier (not a readable field name) and needs conversion.
|
|
94
|
+
output: Dictionary mapping target field identifiers (UUIDs or schema.name patterns) to target values.
|
|
95
|
+
Example: {"ea06ce9f-e10e-484e-bdf0-ec58087f15c5": "96"} means target field with UUID should get value "96".
|
|
96
|
+
The key is a UUID (not a readable field name) and needs conversion.
|
|
97
|
+
"""
|
|
98
|
+
input: Dict[str, str]
|
|
99
|
+
output: Dict[str, str]
|
|
100
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class CustomDataValues(BaseModel):
|
|
104
|
+
"""Schema for custom fields from the source system.
|
|
105
|
+
|
|
106
|
+
Attributes:
|
|
107
|
+
uuid: Unique identifier
|
|
108
|
+
name: Human-readable label
|
|
109
|
+
technical_name: System ID (aliased as "technicalName" in API)
|
|
110
|
+
source: Category bucket
|
|
111
|
+
description: Business context
|
|
112
|
+
"""
|
|
113
|
+
uuid: str = Field(..., description="Unique identifier")
|
|
114
|
+
name: str = Field(..., description="Human-readable label")
|
|
115
|
+
technical_name: str = Field(..., alias="technicalName", description="System ID")
|
|
116
|
+
source: str = Field(..., description="Category bucket")
|
|
117
|
+
description: str = Field(..., description="Business context")
|
|
118
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class LibraryFieldValues(BaseModel):
|
|
122
|
+
"""Schema for BrynQ Library fields.
|
|
123
|
+
|
|
124
|
+
Attributes:
|
|
125
|
+
id: integer identifier
|
|
126
|
+
uuid: str or schema field identifier (e.g., "people_schema-work.employeeIdInCompany")
|
|
127
|
+
required: Whether this field is required
|
|
128
|
+
field: Field name/identifier
|
|
129
|
+
field_label: Multi-language label dictionary (aliased as "fieldLabel" in API)
|
|
130
|
+
app_id: Application ID (aliased as "appId" in API)
|
|
131
|
+
category: Category metadata dictionary
|
|
132
|
+
"""
|
|
133
|
+
id: Optional[int] = None
|
|
134
|
+
uuid: Optional[str] = None
|
|
135
|
+
required: Optional[bool] = None
|
|
136
|
+
field: Optional[str] = None
|
|
137
|
+
field_label: Optional[Dict[str, str]] = Field(default=None, alias="fieldLabel")
|
|
138
|
+
app_id: Optional[int] = Field(default=None, alias="appId")
|
|
139
|
+
category: Optional[Dict[str, Any]] = None
|
|
140
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
141
|
+
|
|
142
|
+
class ConfigFieldValuesSelection(BaseModel):
|
|
143
|
+
"""Configuration field of type SELECTION.
|
|
144
|
+
|
|
145
|
+
Attributes:
|
|
146
|
+
uuid: str identifier
|
|
147
|
+
question: Multi-language question dictionary with "en" (English) and "nl" (Dutch) keys
|
|
148
|
+
value: List of selection options, each with "en" and "nl" keys
|
|
149
|
+
type: Always "SELECTION"
|
|
150
|
+
"""
|
|
151
|
+
uuid: str
|
|
152
|
+
question: MultiLanguageText = Field(..., description="Question asked to customer.")
|
|
153
|
+
value: List[MultiLanguageText] = Field(..., description="List of selection options with en/nl labels")
|
|
154
|
+
type: Literal[ConfigurationType.SELECTION] = ConfigurationType.SELECTION
|
|
155
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class ConfigFieldValuesText(BaseModel):
|
|
159
|
+
"""Configuration field of type TEXT.
|
|
160
|
+
|
|
161
|
+
Attributes:
|
|
162
|
+
uuid: str identifier
|
|
163
|
+
question: Multi-language question dictionary with "en" (English) and "nl" (Dutch) keys
|
|
164
|
+
value: Text string response
|
|
165
|
+
type: Always "TEXT"
|
|
166
|
+
"""
|
|
167
|
+
uuid: str
|
|
168
|
+
question: MultiLanguageText = Field(..., description="Question asked to customer.")
|
|
169
|
+
value: str = Field(..., description="Text response")
|
|
170
|
+
type: Literal[ConfigurationType.TEXT] = ConfigurationType.TEXT
|
|
171
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class ConfigFieldValuesEmail(BaseModel):
|
|
175
|
+
"""Configuration field of type EMAIL.
|
|
176
|
+
|
|
177
|
+
Attributes:
|
|
178
|
+
uuid: str identifier
|
|
179
|
+
question: Multi-language question dictionary with "en" (English) and "nl" (Dutch) keys
|
|
180
|
+
value: Email address string (validated as email format)
|
|
181
|
+
type: Always "EMAIL"
|
|
182
|
+
"""
|
|
183
|
+
uuid: str
|
|
184
|
+
question: MultiLanguageText = Field(..., description="Question asked to customer.")
|
|
185
|
+
value: EmailStr = Field(..., description="Email address response")
|
|
186
|
+
type: Literal[ConfigurationType.EMAIL] = ConfigurationType.EMAIL
|
|
187
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class ConfigFieldValuesNumber(BaseModel):
|
|
191
|
+
"""Configuration field of type NUMBER.
|
|
192
|
+
|
|
193
|
+
Attributes:
|
|
194
|
+
uuid: str identifier
|
|
195
|
+
question: Multi-language question dictionary with "en" (English) and "nl" (Dutch) keys
|
|
196
|
+
value: Numeric value (integer or float)
|
|
197
|
+
type: Always "NUMBER"
|
|
198
|
+
"""
|
|
199
|
+
uuid: str
|
|
200
|
+
question: MultiLanguageText = Field(..., description="Question asked to customer.")
|
|
201
|
+
value: Union[int, float] = Field(..., description="Numeric response")
|
|
202
|
+
type: Literal[ConfigurationType.NUMBER] = ConfigurationType.NUMBER
|
|
203
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class ConfigFieldValuesRichtext(BaseModel):
|
|
207
|
+
"""Configuration field of type RICHTEXT.
|
|
208
|
+
|
|
209
|
+
Attributes:
|
|
210
|
+
uuid: str identifier
|
|
211
|
+
question: Multi-language question dictionary with "en" (English) and "nl" (Dutch) keys
|
|
212
|
+
value: Rich text string (may include HTML elements)
|
|
213
|
+
type: Always "RICHTEXT"
|
|
214
|
+
"""
|
|
215
|
+
uuid: str
|
|
216
|
+
question: MultiLanguageText = Field(..., description="Question asked to customer.")
|
|
217
|
+
value: str = Field(..., description="Rich text response (may include HTML)")
|
|
218
|
+
type: Literal[ConfigurationType.RICHTEXT] = ConfigurationType.RICHTEXT
|
|
219
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class ConfigFieldValuesDatepicker(BaseModel):
|
|
223
|
+
"""Configuration field of type DATEPICKER.
|
|
224
|
+
|
|
225
|
+
Handles both single dates and date ranges because the API
|
|
226
|
+
does not distinguish between them in the 'type' field.
|
|
227
|
+
"""
|
|
228
|
+
uuid: str
|
|
229
|
+
question: MultiLanguageText = Field(..., description="Question asked to customer.")
|
|
230
|
+
value: Union[AwareDatetime, List[AwareDatetime]] = Field(
|
|
231
|
+
...,
|
|
232
|
+
description="Single datetime or list of 2 datetimes (ISO format with timezone)"
|
|
233
|
+
)
|
|
234
|
+
type: Literal[ConfigurationType.DATEPICKER] = ConfigurationType.DATEPICKER
|
|
235
|
+
|
|
236
|
+
@field_validator('value')
|
|
237
|
+
@classmethod
|
|
238
|
+
def validate_range_length(cls, v: Union[datetime, List[datetime]]) -> Union[datetime, List[datetime]]:
|
|
239
|
+
"""Validate list length if input is a list."""
|
|
240
|
+
if isinstance(v, list) and len(v) != 2:
|
|
241
|
+
raise ValueError(f"Date range must contain exactly 2 datetime items, got {len(v)}")
|
|
242
|
+
return v
|
|
243
|
+
|
|
244
|
+
model_config = ConfigDict(frozen=True, strict=False, populate_by_name=True)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class ConfigFieldValuesAttachment(BaseModel):
|
|
248
|
+
"""Configuration field of type ATTACHMENT.
|
|
249
|
+
|
|
250
|
+
Attributes:
|
|
251
|
+
uuid: str identifier
|
|
252
|
+
question: Multi-language question dictionary with "en" (English) and "nl" (Dutch) keys
|
|
253
|
+
value: Always None for attachment type
|
|
254
|
+
type: Always "ATTACHMENT"
|
|
255
|
+
"""
|
|
256
|
+
uuid: str
|
|
257
|
+
question: MultiLanguageText = Field(..., description="Question asked to customer.")
|
|
258
|
+
value: None = Field(None, description="Always None for attachment type")
|
|
259
|
+
type: Literal[ConfigurationType.ATTACHMENT] = ConfigurationType.ATTACHMENT
|
|
260
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
# Discriminated union for ConfigFieldValues based on type field
|
|
264
|
+
ConfigFieldValues = Annotated[
|
|
265
|
+
Union[
|
|
266
|
+
ConfigFieldValuesSelection,
|
|
267
|
+
ConfigFieldValuesText,
|
|
268
|
+
ConfigFieldValuesEmail,
|
|
269
|
+
ConfigFieldValuesNumber,
|
|
270
|
+
ConfigFieldValuesRichtext,
|
|
271
|
+
ConfigFieldValuesDatepicker,
|
|
272
|
+
ConfigFieldValuesAttachment,
|
|
273
|
+
],
|
|
274
|
+
Field(discriminator="type")
|
|
275
|
+
]
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
# ============================================================================
|
|
279
|
+
# 2. Field (or key) level API Models
|
|
280
|
+
# ============================================================================
|
|
281
|
+
# These classes define the shape of the fields of the json returned by BrynQ API. They contain values via data, and are a of a certain type.
|
|
282
|
+
class CustomSourceOrTargetField(BaseModel):
|
|
283
|
+
"""Custom field type from external system.
|
|
284
|
+
|
|
285
|
+
Attributes:
|
|
286
|
+
type: Always "CUSTOM" for this field type
|
|
287
|
+
data: List of custom field descriptors
|
|
288
|
+
"""
|
|
289
|
+
type: Literal["CUSTOM"] = "CUSTOM"
|
|
290
|
+
data: List[CustomDataValues]
|
|
291
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class LibrarySourceOrTargetField(BaseModel):
|
|
295
|
+
"""Library field type from BrynQ library.
|
|
296
|
+
|
|
297
|
+
Attributes:
|
|
298
|
+
type: Always "LIBRARY" for this field type
|
|
299
|
+
data: List of library field identifiers or metadata objects
|
|
300
|
+
"""
|
|
301
|
+
type: Literal["LIBRARY"] = "LIBRARY"
|
|
302
|
+
data: List[Union[str, LibraryFieldValues]]
|
|
303
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
class EmptySourceOrTargetField(BaseModel):
|
|
307
|
+
"""Empty field type (no value).
|
|
308
|
+
|
|
309
|
+
Attributes:
|
|
310
|
+
type: Always "EMPTY" for this field type
|
|
311
|
+
data: Empty list (no data for empty fields)
|
|
312
|
+
"""
|
|
313
|
+
type: Literal['EMPTY'] = "EMPTY"
|
|
314
|
+
data: List[Any] = Field(default_factory=list)
|
|
315
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
class FixedSourceOrTargetField(BaseModel):
|
|
319
|
+
"""Fixed/literal value field type.
|
|
320
|
+
|
|
321
|
+
Attributes:
|
|
322
|
+
type: Always "FIXED" for this field type
|
|
323
|
+
data: The fixed literal value string
|
|
324
|
+
"""
|
|
325
|
+
type: Literal["FIXED"] = "FIXED"
|
|
326
|
+
data: str
|
|
327
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
class ConfigurationSourceOrTargetField(BaseModel):
|
|
331
|
+
"""Configuration field type.
|
|
332
|
+
|
|
333
|
+
Attributes:
|
|
334
|
+
type: Always "CONFIGURATION" for this field type
|
|
335
|
+
data: List of configuration field values
|
|
336
|
+
"""
|
|
337
|
+
type: Literal["CONFIGURATION"] = "CONFIGURATION"
|
|
338
|
+
data: List[ConfigFieldValues]
|
|
339
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True, extra="allow")
|
|
340
|
+
|
|
341
|
+
# General field class that can be any of the above types, distinguished by the 'type' value.
|
|
342
|
+
SourceOrTargetField = Annotated[
|
|
343
|
+
Union[CustomSourceOrTargetField, LibrarySourceOrTargetField, FixedSourceOrTargetField, EmptySourceOrTargetField, ConfigurationSourceOrTargetField],
|
|
344
|
+
Field(discriminator="type")
|
|
345
|
+
]
|
|
346
|
+
|
|
347
|
+
# ============================================================================
|
|
348
|
+
# 2. Scenario Structure API Models
|
|
349
|
+
# ============================================================================
|
|
350
|
+
class ScenarioMappingConfiguration(BaseModel):
|
|
351
|
+
"""Value mapping configuration for translating source values to target values.
|
|
352
|
+
|
|
353
|
+
Attributes:
|
|
354
|
+
values: Explicit mapping values when value mapping is required
|
|
355
|
+
default_value: Fallback value applied when no mapping match is found (aliased as "defaultValue" in API)
|
|
356
|
+
"""
|
|
357
|
+
values: List[MappingValue] = Field(default_factory=list)
|
|
358
|
+
default_value: str = Field(default="", alias="defaultValue")
|
|
359
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
class ScenarioDetail(BaseModel):
|
|
363
|
+
"""Represents a single detail/mapping within a scenario. Called a 'record' when parsed.
|
|
364
|
+
|
|
365
|
+
Represents the content fields of a scenario detail mapping:
|
|
366
|
+
- id: Primary key of the detail record
|
|
367
|
+
- logic: Optional transformation logic
|
|
368
|
+
- unique: Whether this mapping must be unique across the scenario
|
|
369
|
+
- required: Whether the field is mandatory
|
|
370
|
+
- mapping_required: Indicates if an explicit mapping table is required (aliased as "mappingRequired" in API)
|
|
371
|
+
- source: Source field definition
|
|
372
|
+
- target: Target field definition
|
|
373
|
+
- mapping: Mapping or value-translation configuration (may be absent)
|
|
374
|
+
"""
|
|
375
|
+
id: str = Field(..., description="Primary key of the detail record")
|
|
376
|
+
logic: str = Field(default="", description="Optional transformation logic")
|
|
377
|
+
unique: bool = Field(default=False, description="Must this mapping be unique across the scenario?")
|
|
378
|
+
required: bool = Field(default=False, description="Is the field mandatory?")
|
|
379
|
+
mapping_required: Optional[bool] = Field(default=False, alias="mappingRequired", description="Flag indicating whether an explicit mapping table is needed")
|
|
380
|
+
source: SourceOrTargetField = Field(..., description="One or more source fields, each of type 'CUSTOM', 'LIBRARY', 'FIXED', 'EMPTY', or 'CONFIGURATION'.")
|
|
381
|
+
target: SourceOrTargetField = Field(..., description="One or more target fields, each of type 'CUSTOM', 'LIBRARY', 'FIXED', or 'CONFIGURATION'.")
|
|
382
|
+
mapping: Optional[ScenarioMappingConfiguration] = Field(default=None, description="Mapping/value-translation configuration (may be absent)")
|
|
383
|
+
model_config = ConfigDict(frozen=True, strict=True, populate_by_name=True)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
# ============================================================================
|
|
387
|
+
# 3. Scenario API Model
|
|
388
|
+
# ============================================================================
|
|
389
|
+
class Scenario(BaseModel):
|
|
390
|
+
"""Raw scenario model as returned by the API.
|
|
391
|
+
|
|
392
|
+
Attributes:
|
|
393
|
+
id: Scenario identifier
|
|
394
|
+
name: Scenario display name
|
|
395
|
+
description: Scenario business context
|
|
396
|
+
details: Collection of field-level mappings
|
|
397
|
+
"""
|
|
398
|
+
id: str = Field(..., description="Scenario identifier")
|
|
399
|
+
name: str = Field(..., description="Scenario display name")
|
|
400
|
+
description: str = Field(default="", description="Scenario business context")
|
|
401
|
+
details: List[ScenarioDetail] = Field(..., description="Collection of field-level mappings")
|
|
402
|
+
|
|
403
|
+
class Config:
|
|
404
|
+
frozen = True
|
|
405
|
+
strict = True
|
|
406
|
+
populate_by_name = True
|
|
407
|
+
|
|
408
|
+
# ============================================================================
|
|
409
|
+
# 4. Template API Model
|
|
410
|
+
# ============================================================================
|
|
411
|
+
class Template(RootModel[List[Scenario]]):
|
|
412
|
+
"""Template model representing a list of scenarios.
|
|
413
|
+
|
|
414
|
+
In JSON format, this is represented as an array of scenario objects:
|
|
415
|
+
[{scenario}, {scenario}, ...]
|
|
416
|
+
|
|
417
|
+
The root value is a list of Scenario objects.
|
|
418
|
+
"""
|
|
419
|
+
model_config = ConfigDict(frozen=True, strict=True)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from typing import List, Optional, Dict
|
|
2
|
+
from pydantic import BaseModel, Field, validator
|
|
3
|
+
|
|
4
|
+
class UserProducts(BaseModel):
|
|
5
|
+
"""Schema for user product settings"""
|
|
6
|
+
qlik_sense_analyzer: bool = Field(..., alias="qlikSenseAnalyzer", description="Whether user has Qlik Sense Analyzer access")
|
|
7
|
+
qlik_sense_professional: bool = Field(..., alias="qlikSenseProfessional", description="Whether user has Qlik Sense Professional access")
|
|
8
|
+
|
|
9
|
+
class Config:
|
|
10
|
+
frozen = True
|
|
11
|
+
strict = True
|
|
12
|
+
populate_by_name = True
|
|
13
|
+
|
|
14
|
+
class UserCreate(BaseModel):
|
|
15
|
+
"""Schema for creating a user"""
|
|
16
|
+
name: str = Field(..., description="User name")
|
|
17
|
+
username: str = Field(..., description="Username")
|
|
18
|
+
email: str = Field(..., description="User email")
|
|
19
|
+
language: str = Field(..., description="User language preference")
|
|
20
|
+
products: UserProducts = Field(..., description="User product access settings")
|
|
21
|
+
|
|
22
|
+
class Config:
|
|
23
|
+
frozen = True
|
|
24
|
+
strict = True
|
|
25
|
+
populate_by_name = True
|
|
26
|
+
|
|
27
|
+
class UserUpdate(BaseModel):
|
|
28
|
+
"""Schema for updating a user"""
|
|
29
|
+
name: Optional[str] = Field(None, description="User name")
|
|
30
|
+
username: Optional[str] = Field(None, description="Username")
|
|
31
|
+
email: Optional[str] = Field(None, description="User email")
|
|
32
|
+
roles: Optional[List[int]] = Field(None, description="List of role IDs to assign")
|
|
33
|
+
language: Optional[str] = Field(None, description="User language preference")
|
|
34
|
+
products: Optional[dict] = Field(None, description="User product access settings")
|
|
35
|
+
|
|
36
|
+
class Config:
|
|
37
|
+
frozen = True
|
|
38
|
+
strict = True
|
|
39
|
+
populate_by_name = True
|
|
40
|
+
|
|
41
|
+
class UserInvite(BaseModel):
|
|
42
|
+
"""Schema for inviting a user"""
|
|
43
|
+
email: str = Field(..., description="User email")
|
|
44
|
+
products: Optional[dict] = Field(None, description="User product access settings")
|
|
45
|
+
|
|
46
|
+
class Config:
|
|
47
|
+
frozen = True
|
|
48
|
+
strict = True
|
|
49
|
+
populate_by_name = True
|
|
50
|
+
|
|
51
|
+
class QlikDashboardRight(BaseModel):
|
|
52
|
+
"""Schema for Qlik dashboard right"""
|
|
53
|
+
guid: str = Field(..., description="Dashboard GUID")
|
|
54
|
+
data_model_edit: bool = Field(..., alias="dataModelEdit", description="Whether data model is editable")
|
|
55
|
+
editable: bool = Field(..., description="Whether dashboard is editable")
|
|
56
|
+
organigrams: List[int] = Field(default_factory=list, description="List of organigram IDs")
|
|
57
|
+
|
|
58
|
+
class Config:
|
|
59
|
+
frozen = True
|
|
60
|
+
strict = True
|
|
61
|
+
populate_by_name = True
|
|
62
|
+
|
|
63
|
+
class QlikDashboardRightsPayload(BaseModel):
|
|
64
|
+
"""Schema for Qlik dashboard rights payload"""
|
|
65
|
+
dashboard_rights: List[QlikDashboardRight] = Field(..., alias="dashboardRights", description="List of dashboard rights")
|
|
66
|
+
|
|
67
|
+
class Config:
|
|
68
|
+
frozen = True
|
|
69
|
+
strict = True
|
|
70
|
+
populate_by_name = True
|
|
71
|
+
|
|
72
|
+
class DashboardRight(BaseModel):
|
|
73
|
+
"""Schema for dashboard right"""
|
|
74
|
+
dashboard_id: int = Field(..., alias="dashboardId", description="Dashboard ID")
|
|
75
|
+
editable: bool = Field(..., description="Whether dashboard is editable")
|
|
76
|
+
organigrams: List[int] = Field(default_factory=list, description="List of organigram IDs")
|
|
77
|
+
|
|
78
|
+
class Config:
|
|
79
|
+
frozen = True
|
|
80
|
+
strict = True
|
|
81
|
+
populate_by_name = True
|
|
82
|
+
|
|
83
|
+
class DashboardRightsPayload(BaseModel):
|
|
84
|
+
"""Schema for dashboard rights payload"""
|
|
85
|
+
dashboard_rights: List[DashboardRight] = Field(..., alias="dashboardRights", description="List of dashboard rights")
|
|
86
|
+
|
|
87
|
+
class Config:
|
|
88
|
+
frozen = True
|
|
89
|
+
strict = True
|
|
90
|
+
populate_by_name = True
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class UserEntitiesPayload(BaseModel):
|
|
94
|
+
"""Schema for user entities payload"""
|
|
95
|
+
entities: List[int] = Field(..., description="List of entity IDs to assign")
|
|
96
|
+
|
|
97
|
+
class Config:
|
|
98
|
+
frozen = True
|
|
99
|
+
strict = True
|
|
100
|
+
populate_by_name = True
|
|
101
|
+
|
|
102
|
+
class User(BaseModel):
|
|
103
|
+
"""Schema for user data"""
|
|
104
|
+
id: int = Field(..., description="User ID")
|
|
105
|
+
name: str = Field(..., description="User name")
|
|
106
|
+
email: str = Field(..., description="User email")
|
|
107
|
+
|
|
108
|
+
roles: List[int] = Field(default_factory=list, description="User roles")
|
|
109
|
+
organization_chart_entities: List[int] = Field(default_factory=list, description="Organization chart entities")
|
|
110
|
+
qlik_dashboards: List[dict] = Field(default_factory=list, description="Qlik dashboards")
|
|
111
|
+
dashboards: List[dict] = Field(default_factory=list, description="Standard dashboards")
|
|
112
|
+
|
|
113
|
+
class Config:
|
|
114
|
+
frozen = True
|
|
115
|
+
strict = True
|
|
116
|
+
populate_by_name = True
|
|
117
|
+
|
|
118
|
+
class QlikAppUserAuthorization(BaseModel):
|
|
119
|
+
"""Schema for Qlik app user authorization"""
|
|
120
|
+
username: Optional[str] = None
|
|
121
|
+
user_id: int = Field(alias="userId")
|
|
122
|
+
entity_codes: List[str] = Field(default_factory=list, alias="entityCodes")
|
|
123
|
+
|
|
124
|
+
class Config:
|
|
125
|
+
frozen = True
|
|
126
|
+
populate_by_name = True
|