stepxmlclient 1.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.
- stepxmlclient/__init__.py +22 -0
- stepxmlclient/client.py +373 -0
- stepxmlclient/creator.py +317 -0
- stepxmlclient/model/__init__.py +418 -0
- stepxmlclient/model/asset.py +250 -0
- stepxmlclient/model/attribute.py +288 -0
- stepxmlclient/model/business.py +233 -0
- stepxmlclient/model/classification.py +409 -0
- stepxmlclient/model/complex_elements.py +260 -0
- stepxmlclient/model/deletion.py +87 -0
- stepxmlclient/model/entity.py +368 -0
- stepxmlclient/model/metadata.py +199 -0
- stepxmlclient/model/organization.py +167 -0
- stepxmlclient/model/product.py +519 -0
- stepxmlclient/model/relations.py +105 -0
- stepxmlclient/model/replacement.py +417 -0
- stepxmlclient/parser.py +2805 -0
- stepxmlclient/rest_client/__init__.py +16 -0
- stepxmlclient/rest_client/base.py +388 -0
- stepxmlclient/rest_client/client.py +127 -0
- stepxmlclient/rest_client/exceptions.py +97 -0
- stepxmlclient/rest_client/models/__init__.py +175 -0
- stepxmlclient/rest_client/models/asset.py +253 -0
- stepxmlclient/rest_client/models/attribute.py +112 -0
- stepxmlclient/rest_client/models/background_process.py +23 -0
- stepxmlclient/rest_client/models/batch.py +41 -0
- stepxmlclient/rest_client/models/classification.py +57 -0
- stepxmlclient/rest_client/models/collection.py +26 -0
- stepxmlclient/rest_client/models/common.py +192 -0
- stepxmlclient/rest_client/models/context.py +16 -0
- stepxmlclient/rest_client/models/data_type_group.py +15 -0
- stepxmlclient/rest_client/models/entity.py +63 -0
- stepxmlclient/rest_client/models/event_processor.py +15 -0
- stepxmlclient/rest_client/models/import_export.py +43 -0
- stepxmlclient/rest_client/models/integration_endpoint.py +16 -0
- stepxmlclient/rest_client/models/product.py +200 -0
- stepxmlclient/rest_client/models/relations.py +280 -0
- stepxmlclient/rest_client/models/system_information.py +11 -0
- stepxmlclient/rest_client/models/user.py +28 -0
- stepxmlclient/rest_client/models/workflow.py +30 -0
- stepxmlclient/rest_client/operations/__init__.py +54 -0
- stepxmlclient/rest_client/operations/assets.py +652 -0
- stepxmlclient/rest_client/operations/attributes.py +252 -0
- stepxmlclient/rest_client/operations/background_processes.py +84 -0
- stepxmlclient/rest_client/operations/batch.py +28 -0
- stepxmlclient/rest_client/operations/classifications.py +248 -0
- stepxmlclient/rest_client/operations/collection_groups.py +46 -0
- stepxmlclient/rest_client/operations/collections.py +67 -0
- stepxmlclient/rest_client/operations/contexts.py +88 -0
- stepxmlclient/rest_client/operations/data_type_groups.py +68 -0
- stepxmlclient/rest_client/operations/entities.py +295 -0
- stepxmlclient/rest_client/operations/event_processors.py +109 -0
- stepxmlclient/rest_client/operations/exports.py +153 -0
- stepxmlclient/rest_client/operations/gateway.py +53 -0
- stepxmlclient/rest_client/operations/inbound.py +472 -0
- stepxmlclient/rest_client/operations/outbound.py +64 -0
- stepxmlclient/rest_client/operations/products.py +489 -0
- stepxmlclient/rest_client/operations/relations.py +349 -0
- stepxmlclient/rest_client/operations/reports.py +27 -0
- stepxmlclient/rest_client/operations/system_information.py +28 -0
- stepxmlclient/rest_client/operations/user_groups.py +79 -0
- stepxmlclient/rest_client/operations/users.py +119 -0
- stepxmlclient/rest_client/operations/workflow_tasks.py +61 -0
- stepxmlclient/rest_client/operations/workflows.py +50 -0
- stepxmlclient/upload.py +293 -0
- stepxmlclient-1.0.0.dist-info/METADATA +666 -0
- stepxmlclient-1.0.0.dist-info/RECORD +70 -0
- stepxmlclient-1.0.0.dist-info/WHEEL +5 -0
- stepxmlclient-1.0.0.dist-info/licenses/LICENSE +21 -0
- stepxmlclient-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""Common REST API models and utilities.
|
|
2
|
+
|
|
3
|
+
Provides shared Pydantic models for pagination, error responses, and generic
|
|
4
|
+
API response envelopes used across all REST operations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, Generic, List, Optional, TypeVar
|
|
8
|
+
|
|
9
|
+
from pydantic import BaseModel, ConfigDict, Field, computed_field
|
|
10
|
+
|
|
11
|
+
T = TypeVar('T')
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PageInfo(BaseModel):
|
|
15
|
+
"""Pagination metadata for paginated responses.
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
offset: Current offset in result set
|
|
19
|
+
limit: Number of results per page
|
|
20
|
+
total: Total number of items available (if known)
|
|
21
|
+
has_more: Whether more results are available (computed)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
model_config = ConfigDict(
|
|
25
|
+
json_schema_extra={
|
|
26
|
+
"example": {
|
|
27
|
+
"offset": 0,
|
|
28
|
+
"limit": 20,
|
|
29
|
+
"total": 150,
|
|
30
|
+
"has_more": True
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
offset: int = Field(0, ge=0, description="Current offset in result set")
|
|
36
|
+
limit: int = Field(20, ge=1, le=1000, description="Number of results per page")
|
|
37
|
+
total: Optional[int] = Field(None, ge=0, description="Total number of items available")
|
|
38
|
+
|
|
39
|
+
@computed_field
|
|
40
|
+
@property
|
|
41
|
+
def has_more(self) -> bool:
|
|
42
|
+
"""Calculate if more results are available."""
|
|
43
|
+
if self.total is None:
|
|
44
|
+
return False
|
|
45
|
+
return (self.offset + self.limit) < self.total
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class PagedResponse(BaseModel, Generic[T]):
|
|
49
|
+
"""Generic paginated response wrapper.
|
|
50
|
+
|
|
51
|
+
Wraps list results with pagination metadata.
|
|
52
|
+
|
|
53
|
+
Attributes:
|
|
54
|
+
items: List of items in this page
|
|
55
|
+
pagination: Pagination metadata
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
model_config = ConfigDict(
|
|
59
|
+
json_schema_extra={
|
|
60
|
+
"example": {
|
|
61
|
+
"items": [],
|
|
62
|
+
"pagination": {
|
|
63
|
+
"offset": 0,
|
|
64
|
+
"limit": 20,
|
|
65
|
+
"total": 100,
|
|
66
|
+
"has_more": True
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
items: List[T] = Field(default_factory=list, description="Items in this page")
|
|
73
|
+
pagination: Optional[PageInfo] = Field(None, description="Pagination metadata")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class ErrorDetail(BaseModel):
|
|
77
|
+
"""Individual error detail in an error response.
|
|
78
|
+
|
|
79
|
+
Attributes:
|
|
80
|
+
code: Machine-readable error code
|
|
81
|
+
message: Human-readable error message
|
|
82
|
+
field: Field name if error is field-specific
|
|
83
|
+
details: Additional context-specific details
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
code: str = Field(..., description="Machine-readable error code")
|
|
87
|
+
message: str = Field(..., description="Human-readable error message")
|
|
88
|
+
field: str | None = Field(None, description="Field name if field-specific")
|
|
89
|
+
details: Optional[Dict[str, Any]] = Field(None, description="Additional details")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class ErrorResponse(BaseModel):
|
|
93
|
+
"""Standard API error response.
|
|
94
|
+
|
|
95
|
+
Attributes:
|
|
96
|
+
error_code: Primary error code
|
|
97
|
+
error_message: Primary error message
|
|
98
|
+
status: HTTP status code
|
|
99
|
+
timestamp: ISO 8601 timestamp of error occurrence
|
|
100
|
+
request_id: Unique request identifier for debugging
|
|
101
|
+
error_details: List of detailed error information
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
model_config = ConfigDict(
|
|
105
|
+
json_schema_extra={
|
|
106
|
+
"example": {
|
|
107
|
+
"error_code": "VALIDATION_ERROR",
|
|
108
|
+
"error_message": "Request validation failed",
|
|
109
|
+
"status": 400,
|
|
110
|
+
"timestamp": "2024-02-04T10:30:00Z",
|
|
111
|
+
"request_id": "req-12345",
|
|
112
|
+
"error_details": [
|
|
113
|
+
{
|
|
114
|
+
"code": "REQUIRED_FIELD",
|
|
115
|
+
"message": "Field 'name' is required",
|
|
116
|
+
"field": "name"
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
error_code: str = Field(..., description="Primary error code")
|
|
124
|
+
error_message: str = Field(..., description="Primary error message")
|
|
125
|
+
status: int = Field(..., ge=400, le=599, description="HTTP status code")
|
|
126
|
+
timestamp: str | None = Field(None, description="ISO 8601 timestamp")
|
|
127
|
+
request_id: str | None = Field(None, description="Unique request identifier")
|
|
128
|
+
error_details: Optional[List[ErrorDetail]] = Field(None, description="Detailed error info")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class ApiResponse(BaseModel, Generic[T]):
|
|
132
|
+
"""Generic API response envelope.
|
|
133
|
+
|
|
134
|
+
Standard wrapper for single-item API responses.
|
|
135
|
+
|
|
136
|
+
Attributes:
|
|
137
|
+
data: Response data of generic type T
|
|
138
|
+
metadata: Optional metadata about the response
|
|
139
|
+
success: Whether the operation was successful
|
|
140
|
+
timestamp: ISO 8601 timestamp of response
|
|
141
|
+
"""
|
|
142
|
+
model_config = ConfigDict(
|
|
143
|
+
json_schema_extra={
|
|
144
|
+
"example": {
|
|
145
|
+
"data": {},
|
|
146
|
+
"success": True,
|
|
147
|
+
"timestamp": "2024-02-04T10:30:00Z"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
data: Optional[T] = Field(None, description="Response data")
|
|
153
|
+
metadata: Optional[Dict[str, Any]] = Field(None, description="Response metadata")
|
|
154
|
+
success: bool = Field(True, description="Operation success flag")
|
|
155
|
+
timestamp: str | None = Field(None, description="ISO 8601 timestamp")
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
class SearchFilter(BaseModel):
|
|
159
|
+
"""Search filter specification.
|
|
160
|
+
|
|
161
|
+
Attributes:
|
|
162
|
+
field: Field name to filter on
|
|
163
|
+
value: Filter value
|
|
164
|
+
operator: Comparison operator (eq, ne, gt, lt, contains, in, etc.)
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
field: str = Field(..., description="Field name")
|
|
168
|
+
value: Any = Field(..., description="Filter value")
|
|
169
|
+
operator: str = Field("eq", description="Comparison operator")
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class SearchRequest(BaseModel):
|
|
173
|
+
"""Generic search request.
|
|
174
|
+
|
|
175
|
+
Attributes:
|
|
176
|
+
query: Free-text search query
|
|
177
|
+
filters: List of search filters
|
|
178
|
+
limit: Maximum results to return
|
|
179
|
+
offset: Offset for pagination
|
|
180
|
+
sort: Sort specification (field:asc|desc)
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
query: str | None = Field(None, description="Free-text search query")
|
|
184
|
+
filters: Optional[List[SearchFilter]] = Field(None, description="Search filters")
|
|
185
|
+
limit: int = Field(20, ge=1, le=1000, description="Maximum results")
|
|
186
|
+
offset: int = Field(0, ge=0, description="Result offset")
|
|
187
|
+
sort: str | None = Field(None, description="Sort specification")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
# Type aliases for common response types
|
|
191
|
+
SuccessResponse = ApiResponse[Dict[str, Any]]
|
|
192
|
+
ListResponse = PagedResponse[Dict[str, Any]]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Context models for STEP REST API v2."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ContextResponse(BaseModel):
|
|
9
|
+
"""STEP context representation (Context / ContextDetails)."""
|
|
10
|
+
model_config = ConfigDict(extra="allow")
|
|
11
|
+
|
|
12
|
+
id: str
|
|
13
|
+
name: str | None = None
|
|
14
|
+
locale: str | None = None
|
|
15
|
+
dimension_points: Optional[list[str]] = None
|
|
16
|
+
values: Optional[dict[str, Any]] = None
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Data type group model for STEP REST API v2."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DataTypeGroupResponse(BaseModel):
|
|
9
|
+
"""STEP data type group representation."""
|
|
10
|
+
model_config = ConfigDict(extra="allow")
|
|
11
|
+
|
|
12
|
+
id: str
|
|
13
|
+
name: str | None = None
|
|
14
|
+
parent: str | None = None
|
|
15
|
+
values: dict[str, Any] | None = None
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Entity model classes for STEP REST API v2."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class EntityResponse(BaseModel):
|
|
9
|
+
"""Response from entity GET/POST operation."""
|
|
10
|
+
|
|
11
|
+
id: str = Field(..., description="Entity ID")
|
|
12
|
+
objectType: str | None = Field(None, description="Entity object type ID")
|
|
13
|
+
name: str | None = Field(None, description="Entity name")
|
|
14
|
+
parent: str | None = Field(None, description="Parent entity ID")
|
|
15
|
+
values: Optional[Dict[str, Any]] = Field(None, description="Attribute values")
|
|
16
|
+
references: Optional[Dict[str, Any]] = Field(None, description="References")
|
|
17
|
+
attributeLinks: Optional[Dict[str, Any]] = Field(None, description="Attribute links")
|
|
18
|
+
dataContainers: Optional[Dict[str, Any]] = Field(None, description="Data containers")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class EntityListResponse(BaseModel):
|
|
22
|
+
"""Response from entity list/search operations."""
|
|
23
|
+
|
|
24
|
+
items: List[EntityResponse] = Field(default_factory=list, description="List of entities")
|
|
25
|
+
total: Optional[int] = Field(None, description="Total number of entities")
|
|
26
|
+
limit: Optional[int] = Field(None, description="Result limit")
|
|
27
|
+
offset: Optional[int] = Field(None, description="Result offset")
|
|
28
|
+
hasMore: Optional[bool] = Field(None, description="Whether more results available")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class EntityCreateRequest(BaseModel):
|
|
32
|
+
"""Request model for entity creation (POST /entities).
|
|
33
|
+
|
|
34
|
+
Object type and a parent entity must be specified. An 'id' must not be supplied.
|
|
35
|
+
An auto ID pattern must be configured for the object type.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
objectType: str = Field(..., description="Entity object type ID (required)")
|
|
39
|
+
parent: str = Field(..., description="Parent entity ID (required)")
|
|
40
|
+
name: str | None = Field(None, description="Entity name")
|
|
41
|
+
values: Optional[Dict[str, Any]] = Field(None, description="Attribute values")
|
|
42
|
+
references: Optional[Dict[str, Any]] = Field(None, description="References")
|
|
43
|
+
attributeLinks: Optional[Dict[str, Any]] = Field(None, description="Attribute links")
|
|
44
|
+
dataContainers: Optional[Dict[str, Any]] = Field(None, description="Data containers")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class EntityUpdateRequest(BaseModel):
|
|
48
|
+
"""Request model for entity updates (PATCH /entities/{id})."""
|
|
49
|
+
|
|
50
|
+
name: str | None = Field(None, description="Updated entity name")
|
|
51
|
+
parent: str | None = Field(None, description="Updated parent entity ID")
|
|
52
|
+
values: Optional[Dict[str, Any]] = Field(None, description="Updated attribute values")
|
|
53
|
+
references: Optional[Dict[str, Any]] = Field(None, description="Updated references")
|
|
54
|
+
attributeLinks: Optional[Dict[str, Any]] = Field(None, description="Updated attribute links")
|
|
55
|
+
dataContainers: Optional[Dict[str, Any]] = Field(None, description="Updated data containers")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class EntityRelationshipResponse(BaseModel):
|
|
59
|
+
"""Response from entity references operations."""
|
|
60
|
+
|
|
61
|
+
id: str | None = Field(None, description="Entity ID")
|
|
62
|
+
references: Optional[Dict[str, Any]] = Field(None, description="References data")
|
|
63
|
+
total: Optional[int] = Field(None, description="Total number of references")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Event processor models for STEP REST API v2."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class EventProcessorResponse(BaseModel):
|
|
9
|
+
"""STEP event processor (summary/details)."""
|
|
10
|
+
model_config = ConfigDict(extra="allow")
|
|
11
|
+
|
|
12
|
+
id: str
|
|
13
|
+
name: str | None = None
|
|
14
|
+
user: str | None = None
|
|
15
|
+
values: Optional[dict[str, Any]] = None
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Import/Export model classes for STEP REST API v2."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ExportJobCreateRequest(BaseModel):
|
|
9
|
+
"""Request to create an export job."""
|
|
10
|
+
|
|
11
|
+
model_config = ConfigDict(json_schema_extra={
|
|
12
|
+
"example": {
|
|
13
|
+
"entityType": "Product",
|
|
14
|
+
"format": "XML",
|
|
15
|
+
"filters": {"status": "ACTIVE"},
|
|
16
|
+
"config": {"includeRelations": True}
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
entityType: str = Field(..., description="Entity type to export (Product, Asset, Classification, Entity)")
|
|
21
|
+
format: str | None = Field("XML", description="Export format (XML, JSON, CSV)")
|
|
22
|
+
filters: Optional[Dict[str, Any]] = Field(None, description="Export filters")
|
|
23
|
+
config: Optional[Dict[str, Any]] = Field(None, description="Export configuration")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class BackgroundProcessResponse(BaseModel):
|
|
27
|
+
"""Response from export/import trigger operations.
|
|
28
|
+
|
|
29
|
+
Matches the STEP REST API v2 ``BackgroundProcessIdentification`` schema:
|
|
30
|
+
``POST /export/{id}`` and ``POST /import/{id}`` both return only the
|
|
31
|
+
background-process ``id`` so the caller can poll for status.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
model_config = ConfigDict(populate_by_name=True, json_schema_extra={
|
|
35
|
+
"example": {"id": "bg-process-0042"}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
id: str | None = Field(None, description="Background process ID")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# Backward-compatible alias so existing imports don't break immediately.
|
|
42
|
+
ExportJobResponse = BackgroundProcessResponse
|
|
43
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Integration endpoint models for STEP REST API v2."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class IntegrationEndpointResponse(BaseModel):
|
|
9
|
+
"""STEP integration endpoint (summary/details) — Inbound, Outbound, Gateway."""
|
|
10
|
+
model_config = ConfigDict(extra="allow")
|
|
11
|
+
|
|
12
|
+
id: str
|
|
13
|
+
name: str | None = None
|
|
14
|
+
description: str | None = None
|
|
15
|
+
user: str | None = None
|
|
16
|
+
values: dict[str, Any] | None = None
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""Product-related REST API models.
|
|
2
|
+
|
|
3
|
+
Provides Pydantic models aligned with STEP REST API v2 product schemas.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Any, Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ProductResponse(BaseModel):
|
|
12
|
+
"""Single product response data.
|
|
13
|
+
|
|
14
|
+
Mirrors the REST API Product schema:
|
|
15
|
+
- objectType/parent describe product placement and type
|
|
16
|
+
- values/references are dynamic maps keyed by ID
|
|
17
|
+
- attributeLinks/dataContainers are typed arrays/maps from API
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
model_config = ConfigDict(
|
|
21
|
+
json_schema_extra={
|
|
22
|
+
"example": {
|
|
23
|
+
"id": "PROD123",
|
|
24
|
+
"name": "Example Product",
|
|
25
|
+
"objectType": "SalesItem",
|
|
26
|
+
"parent": "I-Level3-122",
|
|
27
|
+
"values": {
|
|
28
|
+
"UPC": {
|
|
29
|
+
"value": {
|
|
30
|
+
"value": "445555555575"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"references": {
|
|
35
|
+
"Accessory": {
|
|
36
|
+
"references": [
|
|
37
|
+
{
|
|
38
|
+
"target": "I-SalesItem-1111"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"attributeLinks": [],
|
|
44
|
+
"dataContainers": {}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
id: str = Field(..., description="Product ID")
|
|
50
|
+
name: str | None = Field(None, description="Product name/description")
|
|
51
|
+
objectType: str | None = Field(None, description="Object type ID")
|
|
52
|
+
parent: str | None = Field(None, description="Parent product ID")
|
|
53
|
+
values: Optional[Dict[str, Any]] = Field(None, description="Product values keyed by attribute ID")
|
|
54
|
+
references: Optional[Dict[str, Any]] = Field(None, description="References keyed by reference type ID")
|
|
55
|
+
attributeLinks: Optional[List[Dict[str, Any]]] = Field(None, description="Attribute links")
|
|
56
|
+
dataContainers: Optional[Dict[str, Any]] = Field(None, description="Data containers keyed by type ID")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ProductListResponse(BaseModel):
|
|
60
|
+
"""Paginated product list response.
|
|
61
|
+
|
|
62
|
+
Attributes:
|
|
63
|
+
items: List of ProductResponse objects
|
|
64
|
+
total: Total number of products
|
|
65
|
+
limit: Items per page
|
|
66
|
+
offset: Current offset
|
|
67
|
+
has_more: Whether more results are available
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
model_config = ConfigDict(
|
|
71
|
+
json_schema_extra={
|
|
72
|
+
"example": {
|
|
73
|
+
"items": [],
|
|
74
|
+
"total": 150,
|
|
75
|
+
"limit": 20,
|
|
76
|
+
"offset": 0,
|
|
77
|
+
"has_more": True
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
items: List[ProductResponse] = Field(default_factory=list, description="Products in this page")
|
|
83
|
+
total: Optional[int] = Field(None, ge=0, description="Total number of products")
|
|
84
|
+
limit: int = Field(20, ge=1, le=1000, description="Items per page")
|
|
85
|
+
offset: int = Field(0, ge=0, description="Current offset")
|
|
86
|
+
has_more: bool = Field(False, description="Whether more results are available")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class ProductSearchRequest(BaseModel):
|
|
90
|
+
"""Search request for products.
|
|
91
|
+
|
|
92
|
+
Attributes:
|
|
93
|
+
query: Free-text search query
|
|
94
|
+
object_type: Filter by object type
|
|
95
|
+
modified_since: Only products modified after this date (ISO 8601)
|
|
96
|
+
limit: Max results to return
|
|
97
|
+
offset: Result offset for pagination
|
|
98
|
+
include_values: Whether to include product values
|
|
99
|
+
include_attributes: Whether to include attributes
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
model_config = ConfigDict(
|
|
103
|
+
json_schema_extra={
|
|
104
|
+
"example": {
|
|
105
|
+
"query": "*",
|
|
106
|
+
"object_type": "SalesItem",
|
|
107
|
+
"limit": 20,
|
|
108
|
+
"offset": 0,
|
|
109
|
+
"include_values": True,
|
|
110
|
+
"include_attributes": True
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
query: str = Field("*", description="Free-text search query (default: all)")
|
|
116
|
+
object_type: str | None = Field(None, description="Filter by object type")
|
|
117
|
+
modified_since: str | None = Field(None, description="ISO 8601 timestamp filter")
|
|
118
|
+
limit: int = Field(20, ge=1, le=1000, description="Max results")
|
|
119
|
+
offset: int = Field(0, ge=0, description="Result offset")
|
|
120
|
+
include_values: bool = Field(True, description="Include product values")
|
|
121
|
+
include_attributes: bool = Field(True, description="Include product attributes")
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class ProductCreateRequest(BaseModel):
|
|
125
|
+
"""Request to create a new product.
|
|
126
|
+
|
|
127
|
+
Attributes:
|
|
128
|
+
objectType: Object type ID (required)
|
|
129
|
+
parent: Parent product ID (required)
|
|
130
|
+
name: Product name/description
|
|
131
|
+
values: Product values map keyed by attribute ID
|
|
132
|
+
references: Product references map keyed by reference/link type ID
|
|
133
|
+
attributeLinks: Product attribute links
|
|
134
|
+
dataContainers: Product data containers keyed by data container type ID
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
model_config = ConfigDict(
|
|
138
|
+
json_schema_extra={
|
|
139
|
+
"example": {
|
|
140
|
+
"objectType": "SalesItem",
|
|
141
|
+
"parent": "I-Level3-122",
|
|
142
|
+
"name": "New Product",
|
|
143
|
+
"values": {
|
|
144
|
+
"UPC": {
|
|
145
|
+
"value": {
|
|
146
|
+
"value": "445555555575"
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"references": {},
|
|
151
|
+
"attributeLinks": [],
|
|
152
|
+
"dataContainers": {}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
objectType: str = Field(..., description="Object type ID")
|
|
158
|
+
parent: str = Field(..., description="Parent product ID")
|
|
159
|
+
name: str | None = Field(None, description="Product name/description")
|
|
160
|
+
values: Optional[Dict[str, Any]] = Field(None, description="Product values")
|
|
161
|
+
references: Optional[Dict[str, Any]] = Field(None, description="Product references")
|
|
162
|
+
attributeLinks: Optional[List[Dict[str, Any]]] = Field(None, description="Product attribute links")
|
|
163
|
+
dataContainers: Optional[Dict[str, Any]] = Field(None, description="Product data containers")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class ProductUpdateRequest(BaseModel):
|
|
167
|
+
"""Request to update an existing product.
|
|
168
|
+
|
|
169
|
+
Attributes:
|
|
170
|
+
name: Updated product name/description
|
|
171
|
+
parent: Optional new parent product ID
|
|
172
|
+
values: Updated product values
|
|
173
|
+
references: Updated references
|
|
174
|
+
attributeLinks: Updated attribute links
|
|
175
|
+
dataContainers: Updated data containers
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
model_config = ConfigDict(
|
|
179
|
+
json_schema_extra={
|
|
180
|
+
"example": {
|
|
181
|
+
"name": "Updated Product Name",
|
|
182
|
+
"parent": "ElectricGuitars",
|
|
183
|
+
"values": {
|
|
184
|
+
"Body": {
|
|
185
|
+
"value": {
|
|
186
|
+
"value": "Alder"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"references": {}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
name: str | None = Field(None, description="Updated product name")
|
|
196
|
+
parent: str | None = Field(None, description="Updated parent product ID")
|
|
197
|
+
values: Optional[Dict[str, Any]] = Field(None, description="Values to update")
|
|
198
|
+
references: Optional[Dict[str, Any]] = Field(None, description="References to update")
|
|
199
|
+
attributeLinks: Optional[List[Dict[str, Any]]] = Field(None, description="Attribute links to update")
|
|
200
|
+
dataContainers: Optional[Dict[str, Any]] = Field(None, description="Data containers to update")
|