@pisapp/core 7.0.0-dev.20260916-153034
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.
- package/LICENSE +28 -0
- package/THIRD-PARTY-NOTICES.txt +43 -0
- package/catalogs.d.ts +7725 -0
- package/catalogs.js +3 -0
- package/chunks/catalogs-domain-DJxK_B5E.js +9060 -0
- package/chunks/catalogs-domain-DJxK_B5E.js.map +1 -0
- package/chunks/classifications-domain-DdIJaF1D.js +1980 -0
- package/chunks/classifications-domain-DdIJaF1D.js.map +1 -0
- package/chunks/icons-shared-B8v5z3BE.js +1387 -0
- package/chunks/icons-shared-B8v5z3BE.js.map +1 -0
- package/chunks/products-domain-99vJaUyI.js +22587 -0
- package/chunks/products-domain-99vJaUyI.js.map +1 -0
- package/classifications.d.ts +7725 -0
- package/classifications.js +3 -0
- package/core.d.ts +7711 -0
- package/core.js +7 -0
- package/index.d.ts +7992 -0
- package/index.js +12 -0
- package/migration/API_V1_TO_V2_MIGRATION.md +1424 -0
- package/migration/legacy-option-rules.json +93 -0
- package/migration/v7.json +4101 -0
- package/migration/v7.schema.json +595 -0
- package/package.json +68 -0
- package/pis-csp.js +97 -0
- package/pis-csp.js.map +1 -0
- package/pis.js +105 -0
- package/pis.js.map +1 -0
- package/products.d.ts +7746 -0
- package/products.js +2 -0
- package/styles/fonts.css +1 -0
- package/styles/pis.css +1 -0
- package/styles/theme-abb.css +1 -0
- package/styles/theme-abb.optimized.css +1 -0
- package/styles/theme-cux2-blue-dark.css +1 -0
- package/styles/theme-cux2-blue-dark.optimized.css +1 -0
- package/styles/theme-cux2-blue-light.css +1 -0
- package/styles/theme-cux2-blue-light.optimized.css +1 -0
- package/styles/theme-cux2-lilac-dark.css +1 -0
- package/styles/theme-cux2-lilac-dark.optimized.css +1 -0
- package/styles/theme-cux2-lilac-light.css +1 -0
- package/styles/theme-cux2-lilac-light.optimized.css +1 -0
- package/styles/theme-cux2-mono-dark.css +1 -0
- package/styles/theme-cux2-mono-dark.optimized.css +1 -0
- package/styles/theme-cux2-mono-light.css +1 -0
- package/styles/theme-cux2-mono-light.optimized.css +1 -0
- package/styles/theme-cux2-red-dark.css +1 -0
- package/styles/theme-cux2-red-dark.optimized.css +1 -0
- package/styles/theme-cux2-red-light.css +1 -0
- package/styles/theme-cux2-red-light.optimized.css +1 -0
- package/types.d.ts +8893 -0
- package/types.js +0 -0
|
@@ -0,0 +1,1424 @@
|
|
|
1
|
+
# PIS API v1 to v2 Migration
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
This is the living migration guide for breaking request-contract changes between PIS API v1 and v2.
|
|
6
|
+
|
|
7
|
+
Update this document in the same change set as every v2 contract change. For each change, record the affected endpoint or shared request model, v1 and v2 JSON shapes, compatibility behavior, validation, implementation status, and tests.
|
|
8
|
+
|
|
9
|
+
## Versioning Policy
|
|
10
|
+
|
|
11
|
+
- v1 remains supported for existing consumers and its request contracts must not change.
|
|
12
|
+
- v2 uses explicit API-versioned actions and separate v2 request types where the request shape changes.
|
|
13
|
+
- A v2 response remains identical to v1 unless the change is explicitly documented here.
|
|
14
|
+
- Unknown legacy JSON properties are ignored by the current Newtonsoft.Json configuration. This supports phased client migration, but clients should stop sending removed properties.
|
|
15
|
+
|
|
16
|
+
## Change Log
|
|
17
|
+
|
|
18
|
+
| Change | Status | First tracked |
|
|
19
|
+
| -------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------- |
|
|
20
|
+
| Replace v2 `AppSettings.Filters.PuId` with `InclusionCriteria` for `ProducingUnit` | Standard contract mapping implemented; application-profile sales-status logic remains query-composer behavior | 2026-08-25 |
|
|
21
|
+
| Remove `AppSettings.Filters.BuId` from v2 | Implemented | 2026-08-11 |
|
|
22
|
+
| Replace v2 `AppSettings.Filters.SuId` with `InclusionCriteria` rules for `LocSalOrg` fields | Contract mapping implemented; recursive v2 query compilation pending | 2026-08-25 |
|
|
23
|
+
| Represent v1 `AppSettings.Filters.SalesErp` as inclusion or exclusion criteria | Internal contract mapping implemented; recursive v2 query compilation pending | 2026-08-25 |
|
|
24
|
+
| Replace v2 `InclusionCriteria` list with a recursive `Criteria` tree | Contract and validation implemented; includes the target replacement shape for `BuId`; Solr query compilation pending | 2026-08-11 |
|
|
25
|
+
| Replace the combined v2 criteria DTO with `CriteriaGroup`/`Criterion` and rename search `filterSettings` to `filter` | Implemented | 2026-09-04 |
|
|
26
|
+
| Allow v2 `CriteriaGroup.rules` to be omitted, `null`, or empty | Implemented with focused validator tests; non-empty trees retain recursive validation | 2026-09-07 |
|
|
27
|
+
| Rename the criterion value type and OpenAPI schema from `CriteriaValue` to `CriterionValue` | Implemented; JSON value shape unchanged | 2026-09-04 |
|
|
28
|
+
| Add `Criteria.operator: HasValue` | Implemented for application inclusion/exclusion criteria and search filter settings | 2026-09-01 |
|
|
29
|
+
| Remove `AppSettings.AppSpecific.AssociatedGroups` and `FrontEndFilter` from v2 | Implemented with a dedicated `AppSpecificSettings` contract | 2026-09-01 |
|
|
30
|
+
| Move `AppSettings.AppSpecific.TableRowMatching` to `AppSettings.Filters.TableRowMatching` in v2 | Implemented with v1-to-internal-v2 conversion | 2026-09-01 |
|
|
31
|
+
| Move Detail `AppSettings.AppSpecific.RelatedProducts` to `DataTypes` in v2 | Implemented with v1 compatibility conversion in `DetailService` | 2026-09-01 |
|
|
32
|
+
| Move Search `AppSettings.AppSpecific.TreeDepth` to top-level `SearchQuery.TreeDepth` | Implemented with v1 compatibility handling in `SearchService` | 2026-09-02 |
|
|
33
|
+
| Rename `AppSettings.InternalUser` to `IncludeInternalData` in v2 | Implemented with v1-to-internal conversion | 2026-09-04 |
|
|
34
|
+
| Remove obsolete `InteractiveGuides` data types and response properties from v2 | Implemented in OpenAPI and runtime JSON | 2026-09-07 |
|
|
35
|
+
| Remove the `V2` suffix from v2 OpenAPI schema names | Implemented without collision exceptions | 2026-09-02 |
|
|
36
|
+
| Shorten v2 `Criterion` derived OpenAPI schema names | Implemented | 2026-09-04 |
|
|
37
|
+
| Make optional v2 boolean request properties nullable | Implemented with explicit runtime fallbacks; shared catalog alias setting also changes in v1 | 2026-09-02 |
|
|
38
|
+
| Replace Translation `Components` with enum-based `Domains` and response `Component` with `Domain` in v2 | Implemented | 2026-09-03 |
|
|
39
|
+
| Return criterion-ready values from v2 catalog and product FilterValues endpoints | Implemented; focused response-contract tests pending | 2026-09-07 |
|
|
40
|
+
| Split v2 product and relationship Filters metadata from FilterValues | Implemented; relationship v1 compatibility tests retained | 2026-09-11 |
|
|
41
|
+
| Split v2 catalog Filters metadata from FilterValues | Implemented | 2026-09-14 |
|
|
42
|
+
| Add filter metadata settings to v2 catalog product Search | Implemented | 2026-09-14 |
|
|
43
|
+
| Reduce v2 Search filter responses to metadata and add optional filter limiting | Implemented | 2026-09-11 |
|
|
44
|
+
| Require at least one v2 Search `dataTypes` value | Implemented | 2026-09-11 |
|
|
45
|
+
| Add optional `IncludeRawValues` to v2 product queries | Implemented; focused response-contract tests pending | 2026-09-09 |
|
|
46
|
+
| Add v2 sitemap products endpoint | Implemented for `AppSettings` and flat scalar criteria | 2026-08-11 |
|
|
47
|
+
| Remove properties marked `[Obsolete]` from v2 JSON responses | Implemented with version-aware System.Text.Json metadata | 2026-09-09 |
|
|
48
|
+
| Load v2 product variant table groups incrementally | Implemented; v2 Detail returns sparse groups and `Variants/Table` loads one full group | 2026-09-16 |
|
|
49
|
+
| Remove `AppSettings.Client` from product v2 requests | Implemented; use standard HTTP headers and connection metadata | 2026-09-16 |
|
|
50
|
+
|
|
51
|
+
## Product AppSettings.Client
|
|
52
|
+
|
|
53
|
+
Product v2 requests no longer expose `appSettings.client`. Client connection metadata belongs to the HTTP request rather than application settings. This change applies to requests that use the product `AppSettingsV2` contract. Catalog v2 requests currently share `CatalogAppSettings` with v1 and are not changed by this migration item.
|
|
54
|
+
|
|
55
|
+
### v1
|
|
56
|
+
|
|
57
|
+
V1 continues to accept client metadata in the request body for compatibility:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"appSettings": {
|
|
62
|
+
"appCode": "example-app",
|
|
63
|
+
"client": {
|
|
64
|
+
"ipAddress": "192.0.2.1",
|
|
65
|
+
"userAgent": "Mozilla/5.0 ..."
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Request headers take precedence over these legacy body values.
|
|
72
|
+
|
|
73
|
+
### v2
|
|
74
|
+
|
|
75
|
+
Remove `client` from `appSettings`:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"appSettings": {
|
|
80
|
+
"appCode": "example-app"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Use the existing HTTP headers instead:
|
|
86
|
+
|
|
87
|
+
```http
|
|
88
|
+
Component-Version: 4.12.0
|
|
89
|
+
User-Agent: Mozilla/5.0 ...
|
|
90
|
+
X-Forwarded-For: 192.0.2.1
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- `Component-Version` remains unchanged and identifies the PIS component version.
|
|
94
|
+
- `User-Agent` supplies browser or caller information used for analytics, device and crawler detection, and client rate limiting.
|
|
95
|
+
- `X-Forwarded-For` supplies the end-user IP when a backend or reverse proxy calls PIS on the user's behalf.
|
|
96
|
+
- For a browser calling PIS directly, no IP header is required; PIS uses the connection `RemoteIpAddress`.
|
|
97
|
+
- For a backend-to-backend request without an end user, omit `X-Forwarded-For`; the backend connection address is used.
|
|
98
|
+
|
|
99
|
+
The original client address must be first when a controlled proxy chain contains multiple addresses:
|
|
100
|
+
|
|
101
|
+
```http
|
|
102
|
+
X-Forwarded-For: 192.0.2.1, 198.51.100.10
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Rate Limiting and Proxy Requirements
|
|
106
|
+
|
|
107
|
+
PIS applies both IP and client rate limiting. A backend or reverse proxy that does not forward the end-user IP and `User-Agent` causes its users to share the backend's rate-limit identities and may produce `429 TooManyRequests` responses.
|
|
108
|
+
|
|
109
|
+
Only a server-side caller that obtained the address from the incoming connection should set `X-Forwarded-For`. An internet-facing proxy must overwrite an untrusted incoming value with the address that connected to it. It must not blindly append to a caller-provided value, because callers can forge HTTP headers and evade IP-based limits.
|
|
110
|
+
|
|
111
|
+
### Compatibility and Tests
|
|
112
|
+
|
|
113
|
+
- V1 body fallback remains supported.
|
|
114
|
+
- Product v2 ignores legacy `appSettings.client` for request metadata; unknown JSON properties remain tolerated during migration.
|
|
115
|
+
- Existing `Component-Version`, `User-Agent`, and `X-Forwarded-For` names are retained; no new PIS-prefixed alternatives are introduced.
|
|
116
|
+
- Focused middleware tests cover header extraction, IP-chain deduplication, direct connection fallback, v1 body compatibility, and product v2 body removal.
|
|
117
|
+
|
|
118
|
+
## Obsolete Response Properties
|
|
119
|
+
|
|
120
|
+
Properties marked with `[Obsolete]` remain serialized by v1 endpoints for backward compatibility. V2 endpoints omit those properties from JSON responses, matching their removal from the v2 OpenAPI document. This applies recursively to shared response DTOs, including `ProductAttribute.IsInternal`; its replacement is `ProductAttribute.Internal`.
|
|
121
|
+
|
|
122
|
+
## Product Attribute Raw Values
|
|
123
|
+
|
|
124
|
+
The v2 product Autocomplete, Detail, List, Preview, Relationship Autocomplete, Search, and Sitemap Products requests
|
|
125
|
+
accept the optional top-level `includeRawValues` property:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"includeRawValues": true,
|
|
130
|
+
"appSettings": {
|
|
131
|
+
"context": {
|
|
132
|
+
"localization": {
|
|
133
|
+
"language": "en"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
When `includeRawValues` is `true`, each returned product `AttributeValue` includes a criterion-ready `rawValue`.
|
|
141
|
+
Clients can pass this object directly as an item in `AttributeCriterion.values`. For scalar and enumeration
|
|
142
|
+
attributes, `rawValue.V` contains the source value or enumeration code. For multidimensional attributes, the object
|
|
143
|
+
also preserves the applicable header in `H` and unit of measure in `U`:
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"text": "50 mm",
|
|
148
|
+
"rawValue": {
|
|
149
|
+
"H": "Width",
|
|
150
|
+
"V": "50",
|
|
151
|
+
"U": "mm"
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Omitting `includeRawValues`, or sending `null` or `false`, leaves `rawValue` unset. The option changes only the
|
|
157
|
+
attribute-value response data; it does not affect product matching, attribute selection, or formatted display text.
|
|
158
|
+
The v1 request contracts are unchanged.
|
|
159
|
+
|
|
160
|
+
## Optional CriteriaGroup Rules
|
|
161
|
+
|
|
162
|
+
The shared v2 `CriteriaGroup` request model accepts `rules` when it is omitted, explicitly `null`, or an empty array. This permits clients to send an inactive filter group such as `{"type":"group","condition":"And","rules":[]}`. Non-empty groups continue to validate every nested criterion recursively. This only relaxes v2 request validation; v1 request contracts are unchanged.
|
|
163
|
+
|
|
164
|
+
## Optional Boolean Request Properties
|
|
165
|
+
|
|
166
|
+
Optional boolean request properties in v2 use nullable JSON values. For the properties listed below, omitting the property or sending `null` leaves the option unspecified. The service layer resolves an unspecified value to `false`, preserving the previous behavior:
|
|
167
|
+
|
|
168
|
+
- `SearchQuery.includeProductClassifications`, `SearchQuery.includeExtendedObjectData`
|
|
169
|
+
- `ListQuery.includeProductClassifications`
|
|
170
|
+
- `AutocompleteQuery.categorySearch`, `categoryKeywordSearch`, `autoCategoryNavigation`, `fetchProductImages`, `fetchCategoryImages`
|
|
171
|
+
- `PrmAutocompleteQuery.fetchProductImages`
|
|
172
|
+
- `AutocompleteQuery.includeRawValues`, `DetailQuery.includeRawValues`, `ListQuery.includeRawValues`, `PreviewQuery.includeRawValues`
|
|
173
|
+
- `PrmAutocompleteQuery.includeRawValues`, `SearchQuery.includeRawValues`, `SitemapProductSearchQuery.includeRawValues`
|
|
174
|
+
- `CatalogProductAutocompleteQuery.fetchProductImages`
|
|
175
|
+
- `AppSettings.filters.tableRowMatching`
|
|
176
|
+
- `AppSettings.appSpecific.genericizeAttName`, `allReplacements`
|
|
177
|
+
- `CompareSearchSettings.differencesOnly`, `specialDocumentHandling`
|
|
178
|
+
- `ClassificationSearchSettings.configurators`
|
|
179
|
+
- `CatalogAppSettings.appSpecific.configuredItemAliasesEnabled`
|
|
180
|
+
|
|
181
|
+
`CompareSearchSettings.strictMode` is also nullable, but retains its documented default of `true`. Omitting it or sending `null` enables strict mode; clients must send `false` to disable it.
|
|
182
|
+
|
|
183
|
+
The OpenAPI v2 schema represents the false-fallback properties with `nullable: true` and `default: null`. It represents `strictMode` with `nullable: true` and `default: true`.
|
|
184
|
+
|
|
185
|
+
The Compare and classification settings use dedicated v2 request types, so their v1 property types remain non-nullable. `CatalogAppSpecificSettings` remains shared by both API versions and is changed directly; consequently, `configuredItemAliasesEnabled` is nullable in both v1 and v2.
|
|
186
|
+
|
|
187
|
+
## AppSettings.InternalUser
|
|
188
|
+
|
|
189
|
+
### v1
|
|
190
|
+
|
|
191
|
+
The v1 `AppSettings` contract uses `internalUser` to request internal-only data:
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"appSettings": {
|
|
196
|
+
"internalUser": true
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### v2
|
|
202
|
+
|
|
203
|
+
Rename the property to `includeInternalData`:
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"appSettings": {
|
|
208
|
+
"includeInternalData": true
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The new name describes the requested response and filtering behavior instead of identifying the caller. The property remains nullable: omitting it, sending `null`, or sending `false` does not enable internal data. Application-level authorization is still required when the value is `true`.
|
|
214
|
+
|
|
215
|
+
### Compatibility and Validation
|
|
216
|
+
|
|
217
|
+
- The v1 request contract and `internalUser` behavior are unchanged.
|
|
218
|
+
- During v1 conversion, `internalUser` is copied to `AppSettingsInternal.IncludeInternalData`.
|
|
219
|
+
- V2 requests use `includeInternalData`, which is copied to the same internal execution property.
|
|
220
|
+
- The legacy `internalUser` property is absent from the v2 OpenAPI schema. If sent in a v2 payload, it is treated as an unknown property and ignored by the current Newtonsoft.Json configuration.
|
|
221
|
+
- Responses are unchanged.
|
|
222
|
+
|
|
223
|
+
## ApplicationFilters.PuId
|
|
224
|
+
|
|
225
|
+
### v1
|
|
226
|
+
|
|
227
|
+
```json
|
|
228
|
+
{
|
|
229
|
+
"appSettings": {
|
|
230
|
+
"filters": {
|
|
231
|
+
"puId": ["FIDRI", "SEMOT"]
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`AppSettings.Filters.PuId` is a list of Producing Unit codes. The standard v1 query composer removes empty values and filters the `ProducingUnit` attribute, combining supplied values with `OR`.
|
|
238
|
+
|
|
239
|
+
### v2
|
|
240
|
+
|
|
241
|
+
Replace `appSettings.filters.puId` with one `ProducingUnit` rule in `appSettings.filters.inclusionCriteria`:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"appSettings": {
|
|
246
|
+
"filters": {
|
|
247
|
+
"inclusionCriteria": {
|
|
248
|
+
"condition": "And",
|
|
249
|
+
"rules": [
|
|
250
|
+
{
|
|
251
|
+
"type": "attribute",
|
|
252
|
+
"code": "ProducingUnit",
|
|
253
|
+
"values": [{ "V": "FIDRI" }, { "V": "SEMOT" }],
|
|
254
|
+
"operator": "In"
|
|
255
|
+
}
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The values of one `ProducingUnit` rule are alternatives, so this means `ProducingUnit = FIDRI OR ProducingUnit = SEMOT`. Place the rule in the root `And` group alongside any other inclusion rules.
|
|
264
|
+
|
|
265
|
+
### Application Profile Sales-Status Logic
|
|
266
|
+
|
|
267
|
+
When the current application's `ApplicationProfile` enables `ExtraPuIdProductSalesStatusLogic`, clients still send only the `ProducingUnit` criterion shown above. During query compilation, PIS automatically expands every `ProducingUnit` value with an `OR` alternative for `ProductSalesStatus_PU{producingUnit}` equal to `A`, `O`, or `P`.
|
|
268
|
+
|
|
269
|
+
For example, with `FIDRI`, PIS applies `ProducingUnit = FIDRI OR ProductSalesStatus_PUFIDRI = A|O|P`. Do not add `ProductSalesStatus_PU...` rules to the v2 request; the application profile controls whether the expansion is active.
|
|
270
|
+
|
|
271
|
+
### Compatibility and Validation
|
|
272
|
+
|
|
273
|
+
- The v1-to-internal-v2 conversion removes empty `puId` entries and adds one `ProducingUnit` rule to `inclusionCriteria` when values remain.
|
|
274
|
+
- The `ExtraPuIdProductSalesStatusLogic` application-profile flag changes query composition to also match `ProductSalesStatus_PU{puId}` values `A`, `O`, and `P`. The `ProducingUnit` criteria compiler applies this profile-dependent behavior, preserving the v1 result set.
|
|
275
|
+
- The standard `ProducingUnit` replacement is a flat scalar criterion supported by `POST /v2/Sitemap/Products`.
|
|
276
|
+
- Other product endpoints do not execute `Criteria` yet.
|
|
277
|
+
|
|
278
|
+
## ApplicationFilters.BuId
|
|
279
|
+
|
|
280
|
+
### v1
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
{
|
|
284
|
+
"appSettings": {
|
|
285
|
+
"filters": {
|
|
286
|
+
"buId": ["3127", "3119", "3129"]
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
`AppSettings.Filters.BuId` is a `List<string>` and limits results by ABB Detail Group.
|
|
293
|
+
|
|
294
|
+
The current v1 query composer creates one filter for the attribute field `BuId` and combines the supplied values with `OR`. For example, `["3127", "3119", "3129"]` means: product `BuId` is `3127` OR product `BuId` is `3119` OR product `BuId` is `3129`.
|
|
295
|
+
|
|
296
|
+
### v2
|
|
297
|
+
|
|
298
|
+
`appSettings.filters.buId` is removed from `ApplicationFilters`.
|
|
299
|
+
|
|
300
|
+
The v2 replacement is `appSettings.filters.inclusionCriteria` with `code` set to `BuId`:
|
|
301
|
+
|
|
302
|
+
```json
|
|
303
|
+
{
|
|
304
|
+
"appSettings": {
|
|
305
|
+
"filters": {
|
|
306
|
+
"inclusionCriteria": {
|
|
307
|
+
"condition": "And",
|
|
308
|
+
"rules": [
|
|
309
|
+
{
|
|
310
|
+
"type": "attribute",
|
|
311
|
+
"code": "BuId",
|
|
312
|
+
"values": [{ "V": "3127" }, { "V": "3119" }, { "V": "3129" }],
|
|
313
|
+
"operator": "In"
|
|
314
|
+
}
|
|
315
|
+
]
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
This is a single `Criteria` group, not an array. The group contains one `BuId` rule whose values have the expected semantics `BuId = 3127 OR BuId = 3119 OR BuId = 3129`, matching v1.
|
|
323
|
+
|
|
324
|
+
Do not send `H` or `U` for `BuId`. Put each ABB Detail Group code directly in `values[].V`.
|
|
325
|
+
|
|
326
|
+
### Client Migration
|
|
327
|
+
|
|
328
|
+
1. Stop sending `appSettings.filters.buId` to v2 endpoints.
|
|
329
|
+
2. Use one `inclusionCriteria` group with `condition: "And"` and one `BuId` rule in `rules`.
|
|
330
|
+
3. Copy every v1 `buId` list item to a separate `rules[0].values[].V` entry.
|
|
331
|
+
4. Use the replacement in `POST /v2/Sitemap/Products`; other product endpoints do not execute `Criteria` yet.
|
|
332
|
+
5. Send the remaining supported v2 filter properties unchanged until their own migration entry says otherwise.
|
|
333
|
+
|
|
334
|
+
### Compatibility and Validation
|
|
335
|
+
|
|
336
|
+
- v1 behavior is unchanged.
|
|
337
|
+
- A v2 payload containing legacy `buId` is currently accepted and the unknown property is ignored.
|
|
338
|
+
- `BuId` is not present in the v2 OpenAPI schema and is not validated by the v2 application-settings validator.
|
|
339
|
+
|
|
340
|
+
## ApplicationFilters.SuId
|
|
341
|
+
|
|
342
|
+
### v1
|
|
343
|
+
|
|
344
|
+
```json
|
|
345
|
+
{
|
|
346
|
+
"appSettings": {
|
|
347
|
+
"filters": {
|
|
348
|
+
"suId": ["SUDESTO", "SUNOCRL"]
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
`AppSettings.Filters.SuId` identifies sales units. The v1 query composer discards empty values and values shorter than three characters. For each remaining value it queries the attribute field `LocSalOrg` followed by the value starting at index `2`, and compares that field with the complete `SuId` value. Multiple `SuId` filters are combined with `OR`.
|
|
355
|
+
|
|
356
|
+
### v2
|
|
357
|
+
|
|
358
|
+
Apply the same logic with an `Or` group in `appSettings.filters.inclusionCriteria`:
|
|
359
|
+
|
|
360
|
+
```json
|
|
361
|
+
{
|
|
362
|
+
"appSettings": {
|
|
363
|
+
"filters": {
|
|
364
|
+
"inclusionCriteria": {
|
|
365
|
+
"condition": "And",
|
|
366
|
+
"rules": [
|
|
367
|
+
{
|
|
368
|
+
"type": "group",
|
|
369
|
+
"condition": "Or",
|
|
370
|
+
"rules": [
|
|
371
|
+
{
|
|
372
|
+
"type": "attribute",
|
|
373
|
+
"code": "LocSalOrgDESTO",
|
|
374
|
+
"values": [{ "V": "SUDESTO" }],
|
|
375
|
+
"operator": "In"
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
"type": "attribute",
|
|
379
|
+
"code": "LocSalOrgNOCRL",
|
|
380
|
+
"values": [{ "V": "SUNOCRL" }],
|
|
381
|
+
"operator": "In"
|
|
382
|
+
}
|
|
383
|
+
]
|
|
384
|
+
}
|
|
385
|
+
]
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
For every valid `suId`, create one rule with `code` equal to `LocSalOrg` plus `suId.substring(2)`, and place the complete `suId` in `values[0].value`. Put all generated rules in one `Or` group. Place that group in the root `And` group alongside any other inclusion rules, preserving the v1 behavior.
|
|
393
|
+
|
|
394
|
+
### Compatibility and Validation
|
|
395
|
+
|
|
396
|
+
- When a v1 `AppSettings` request is converted to internal v2 criteria, `SuId` is mapped to the nested `Or` group described above.
|
|
397
|
+
- Values that are empty after cleanup or shorter than three characters do not produce a criterion, matching the v1 query composer.
|
|
398
|
+
- `POST /v2/Sitemap/Products` currently rejects nested `rules`; therefore it cannot execute the multi-`SuId` v2 shape until recursive query compilation is implemented.
|
|
399
|
+
- Other product endpoints do not execute `Criteria` yet.
|
|
400
|
+
|
|
401
|
+
## ApplicationFilters.SalesErp
|
|
402
|
+
|
|
403
|
+
### v1
|
|
404
|
+
|
|
405
|
+
````json
|
|
406
|
+
{
|
|
407
|
+
"appSettings": {
|
|
408
|
+
"filters": {
|
|
409
|
+
"salesErp": true
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
### v2
|
|
413
|
+
|
|
414
|
+
`ApplicationFilters.SalesErp` remains supported and has the same boolean behavior. The equivalent criteria representation used for the internal v1-to-v2 conversion is:
|
|
415
|
+
|
|
416
|
+
```json
|
|
417
|
+
{
|
|
418
|
+
"appSettings": {
|
|
419
|
+
"filters": {
|
|
420
|
+
"inclusionCriteria": {
|
|
421
|
+
"condition": "And",
|
|
422
|
+
"rules": [
|
|
423
|
+
{
|
|
424
|
+
"type": "attribute",
|
|
425
|
+
"code": "SalesErp",
|
|
426
|
+
"values": [{ "V": "Y" }],
|
|
427
|
+
"operator": "In"
|
|
428
|
+
}
|
|
429
|
+
]
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
````
|
|
435
|
+
|
|
436
|
+
For `salesErp: false`, use the same rule in `exclusionCriteria` instead:
|
|
437
|
+
|
|
438
|
+
```json
|
|
439
|
+
{
|
|
440
|
+
"appSettings": {
|
|
441
|
+
"filters": {
|
|
442
|
+
"exclusionCriteria": {
|
|
443
|
+
"condition": "And",
|
|
444
|
+
"rules": [
|
|
445
|
+
{
|
|
446
|
+
"type": "attribute",
|
|
447
|
+
"code": "SalesErp",
|
|
448
|
+
"values": [{ "V": "Y" }],
|
|
449
|
+
"operator": "In"
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### Compatibility and Validation
|
|
459
|
+
|
|
460
|
+
- The v1-to-internal-v2 conversion adds `SalesErp = "Y"` to `inclusionCriteria` for `true` and to `exclusionCriteria` for `false`.
|
|
461
|
+
- `salesErp: null` does not add a criterion.
|
|
462
|
+
- `ApplicationFilters.SalesErp` remains available for v2 clients and is passed through unchanged.
|
|
463
|
+
- `POST /v2/Sitemap/Products` supports only flat scalar criteria; both examples above are flat scalar groups, although recursive query composition remains pending for other endpoints.
|
|
464
|
+
|
|
465
|
+
## ApplicationFilters.InclusionCriteria
|
|
466
|
+
|
|
467
|
+
### v1
|
|
468
|
+
|
|
469
|
+
```json
|
|
470
|
+
{
|
|
471
|
+
"appSettings": {
|
|
472
|
+
"filters": {
|
|
473
|
+
"inclusionCriteria": [
|
|
474
|
+
{
|
|
475
|
+
"code": "Color",
|
|
476
|
+
"values": ["Red", "Blue"]
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
"code": "Voltage",
|
|
480
|
+
"values": ["230"]
|
|
481
|
+
}
|
|
482
|
+
]
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
```csharp
|
|
489
|
+
public List<Criteria>? InclusionCriteria { get; set; }
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### v2
|
|
493
|
+
|
|
494
|
+
```json
|
|
495
|
+
{
|
|
496
|
+
"appSettings": {
|
|
497
|
+
"filters": {
|
|
498
|
+
"inclusionCriteria": {
|
|
499
|
+
"condition": "And",
|
|
500
|
+
"rules": [
|
|
501
|
+
{
|
|
502
|
+
"type": "attribute",
|
|
503
|
+
"code": "Color",
|
|
504
|
+
"values": [{ "V": "Red" }, { "V": "Blue" }],
|
|
505
|
+
"operator": "In"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
"type": "attribute",
|
|
509
|
+
"code": "Voltage",
|
|
510
|
+
"values": [
|
|
511
|
+
{ "V": "230", "U": "V" },
|
|
512
|
+
{ "V": "400", "U": "V" }
|
|
513
|
+
],
|
|
514
|
+
"operator": "In"
|
|
515
|
+
}
|
|
516
|
+
]
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
```csharp
|
|
524
|
+
public CriteriaGroup? InclusionCriteria { get; set; }
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
The root is always a `CriteriaGroup` with `condition` and `rules`. Every item in `rules` is a polymorphic `Criterion`
|
|
528
|
+
and requires `type: "attribute"` or `type: "group"`. An `AttributeCriterion` has `code`, optional `values`, and
|
|
529
|
+
`operator`; a nested `CriteriaGroup` has its own `condition` and `rules`. The root does not require `type` because its
|
|
530
|
+
contract type is already `CriteriaGroup`.
|
|
531
|
+
|
|
532
|
+
Each item in `AttributeCriterion.values` uses the `CriterionValue` .NET type and OpenAPI schema. This replaces the
|
|
533
|
+
previous `CriteriaValue` name so that the value is associated with one criterion. Its JSON representation remains
|
|
534
|
+
unchanged and contains required `V` plus optional `H` and `U` properties.
|
|
535
|
+
|
|
536
|
+
### Replacing BuId with InclusionCriteria
|
|
537
|
+
|
|
538
|
+
To migrate this v1 request:
|
|
539
|
+
|
|
540
|
+
```json
|
|
541
|
+
{
|
|
542
|
+
"appSettings": {
|
|
543
|
+
"filters": {
|
|
544
|
+
"buId": ["3127", "3119", "3129"]
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
send this v2 request shape instead:
|
|
551
|
+
|
|
552
|
+
```json
|
|
553
|
+
{
|
|
554
|
+
"appSettings": {
|
|
555
|
+
"filters": {
|
|
556
|
+
"inclusionCriteria": {
|
|
557
|
+
"condition": "And",
|
|
558
|
+
"rules": [
|
|
559
|
+
{
|
|
560
|
+
"type": "attribute",
|
|
561
|
+
"code": "BuId",
|
|
562
|
+
"values": [{ "V": "3127" }, { "V": "3119" }, { "V": "3129" }],
|
|
563
|
+
"operator": "In"
|
|
564
|
+
}
|
|
565
|
+
]
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
The compiler for a product endpoint must translate the nested `BuId` rule to one exact attribute filter on `BuId` and OR its values. It must not require `H` or `U`, and it must not translate the codes as display labels.
|
|
573
|
+
|
|
574
|
+
The criteria model contains:
|
|
575
|
+
|
|
576
|
+
| Property | Requirement in v2 | Notes |
|
|
577
|
+
| ------------ | ---------------------------------------------------------- | ------------------------------------------------------------------- |
|
|
578
|
+
| `type` | Required for every item in `rules`: `attribute` or `group` | Not required on the root `CriteriaGroup`. |
|
|
579
|
+
| `condition` | Required for a `CriteriaGroup`: `And` or `Or` | Combines the group's nested `rules`. |
|
|
580
|
+
| `code` | Required for an `AttributeCriterion`, non-empty | Attribute code or `CID`. |
|
|
581
|
+
| `values` | Required and non-empty for `In`; omitted for `HasValue` | Every `In` item requires a non-empty `V`. |
|
|
582
|
+
| `values[].H` | Optional | Used for multidimensional values. |
|
|
583
|
+
| `values[].U` | Optional | Used for multidimensional values. |
|
|
584
|
+
| `rules` | Required for a `CriteriaGroup`, non-empty recursive list | Every nested item is an `AttributeCriterion` or `CriteriaGroup`. |
|
|
585
|
+
| `operator` | Required for an `AttributeCriterion`: `In` or `HasValue` | `In` matches one of `values`; `HasValue` matches any indexed value. |
|
|
586
|
+
|
|
587
|
+
### HasValue Operator
|
|
588
|
+
|
|
589
|
+
Use `HasValue` when only the presence of an indexed attribute value matters:
|
|
590
|
+
|
|
591
|
+
```json
|
|
592
|
+
{
|
|
593
|
+
"condition": "And",
|
|
594
|
+
"rules": [
|
|
595
|
+
{
|
|
596
|
+
"type": "attribute",
|
|
597
|
+
"code": "BimRelevance",
|
|
598
|
+
"operator": "HasValue"
|
|
599
|
+
}
|
|
600
|
+
]
|
|
601
|
+
}
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
Do not send `values` for this operator. The validator rejects a non-empty `values` collection because its contents
|
|
605
|
+
would be ignored. Query composition emits a Solr field-existence filter (`field:*`); exclusion criteria negate that
|
|
606
|
+
filter. For translated attributes, PIS checks the active language, English fallback, and country-specific language
|
|
607
|
+
fields. The v1 request contract is unchanged and does not expose this operator. Responses and cache behavior are
|
|
608
|
+
unchanged.
|
|
609
|
+
|
|
610
|
+
### Client Migration
|
|
611
|
+
|
|
612
|
+
1. Replace the v1 array with one root `CriteriaGroup`.
|
|
613
|
+
2. Set the group's `condition` and put each attribute criterion in `rules`.
|
|
614
|
+
3. Add `type: "attribute"` to attribute criteria and `type: "group"` to nested groups.
|
|
615
|
+
4. Convert each v1 string value to `{ "V": "..." }` in the matching rule's `values`.
|
|
616
|
+
5. For a `BuId` migration, use a `BuId` rule and preserve the v1 list as OR alternatives in that rule's `values`.
|
|
617
|
+
6. Use `H`, `V`, and `U` for multidimensional filter values instead of exposing the internal index separator.
|
|
618
|
+
|
|
619
|
+
### Search Filter Property Rename
|
|
620
|
+
|
|
621
|
+
The v2 search contracts for product search, PRM search, product preview, and catalog product search replace
|
|
622
|
+
`filterSettings` with `filter`:
|
|
623
|
+
|
|
624
|
+
```csharp
|
|
625
|
+
public CriteriaGroup? Filter { get; set; }
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
This is a breaking request-contract change. Clients must stop sending `search.filterSettings`; unknown legacy
|
|
629
|
+
properties are ignored and therefore do not filter results. The v1 contracts retain their existing
|
|
630
|
+
`List<FilterSettings>? FilterSettings` property.
|
|
631
|
+
|
|
632
|
+
### Current Implementation Status
|
|
633
|
+
|
|
634
|
+
- `ApplicationFilters.InclusionCriteria` and `ExclusionCriteria` use `CriteriaGroup`.
|
|
635
|
+
- Recursive groups are represented by `CriteriaGroup`; leaves are represented by `AttributeCriterion` through the polymorphic `Criterion` base type.
|
|
636
|
+
- Recursive structure and required values are validated by `CriteriaGroupValidator` and `AttributeCriterionValidator`.
|
|
637
|
+
- Product query composition supports recursive inclusion/exclusion groups, `In`, `HasValue`, multidimensional values, and `CID` criteria.
|
|
638
|
+
- Search `filter` processing preserves the existing filter-settings behavior: direct attribute rules are combined with AGM predefined filters and applied to product queries.
|
|
639
|
+
- The v2 `Translations` endpoint accepts `AppSettings`, but it does not apply product filters. Its availability does not imply that v2 search filtering is available.
|
|
640
|
+
|
|
641
|
+
## AppSettings.AppSpecific
|
|
642
|
+
|
|
643
|
+
`AppSettings.AppSpecific` uses the dedicated `AppSpecificSettings` contract. The `associatedGroups` and
|
|
644
|
+
`frontEndFilter` properties are removed from this object. In v2, apply them through attribute criteria in
|
|
645
|
+
`appSettings.filters`.
|
|
646
|
+
|
|
647
|
+
### AssociatedGroups
|
|
648
|
+
|
|
649
|
+
#### v1
|
|
650
|
+
|
|
651
|
+
`AppSettings.AppSpecific.AssociatedGroups` restricts results to products belonging to one of the specified associated
|
|
652
|
+
groups:
|
|
653
|
+
|
|
654
|
+
```json
|
|
655
|
+
{
|
|
656
|
+
"appSettings": {
|
|
657
|
+
"appSpecific": {
|
|
658
|
+
"associatedGroups": ["0229/0x Platform63", "0229/1x Platform63"]
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
#### v2
|
|
665
|
+
|
|
666
|
+
Move the non-empty values to one `AssociatedGroups` rule in `appSettings.filters.inclusionCriteria`:
|
|
667
|
+
|
|
668
|
+
```json
|
|
669
|
+
{
|
|
670
|
+
"appSettings": {
|
|
671
|
+
"filters": {
|
|
672
|
+
"inclusionCriteria": {
|
|
673
|
+
"condition": "And",
|
|
674
|
+
"rules": [
|
|
675
|
+
{
|
|
676
|
+
"type": "attribute",
|
|
677
|
+
"code": "AssociatedGroups",
|
|
678
|
+
"values": [{ "V": "0229/0x Platform63" }, { "V": "0229/1x Platform63" }],
|
|
679
|
+
"operator": "In"
|
|
680
|
+
}
|
|
681
|
+
]
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
The values in this rule are alternatives. A product is included when its `AssociatedGroups` attribute equals
|
|
689
|
+
`0229/0x Platform63` OR `0229/1x Platform63`. Place the rule in the root `And` inclusion group alongside other
|
|
690
|
+
inclusion rules.
|
|
691
|
+
|
|
692
|
+
#### Client Migration
|
|
693
|
+
|
|
694
|
+
1. Stop sending `appSettings.appSpecific.associatedGroups` to v2 endpoints.
|
|
695
|
+
2. Add one rule with `code: "AssociatedGroups"` and `operator: "In"` to `appSettings.filters.inclusionCriteria.rules`.
|
|
696
|
+
3. Copy every non-empty v1 list item to a separate `values[].V` entry.
|
|
697
|
+
4. Preserve existing inclusion rules in the same root `And` group.
|
|
698
|
+
|
|
699
|
+
### FrontEndFilter
|
|
700
|
+
|
|
701
|
+
#### v1
|
|
702
|
+
|
|
703
|
+
`AppSettings.AppSpecific.FrontEndFilter` excludes products whose `FrontEndFilter` attribute matches one of the
|
|
704
|
+
specified values:
|
|
705
|
+
|
|
706
|
+
```json
|
|
707
|
+
{
|
|
708
|
+
"appSettings": {
|
|
709
|
+
"appSpecific": {
|
|
710
|
+
"frontEndFilter": ["FlameScanner", "LsoCATBXEcatalog"]
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
#### v2
|
|
717
|
+
|
|
718
|
+
Move the non-empty values to one `FrontEndFilter` rule in `appSettings.filters.exclusionCriteria`:
|
|
719
|
+
|
|
720
|
+
```json
|
|
721
|
+
{
|
|
722
|
+
"appSettings": {
|
|
723
|
+
"filters": {
|
|
724
|
+
"exclusionCriteria": {
|
|
725
|
+
"condition": "And",
|
|
726
|
+
"rules": [
|
|
727
|
+
{
|
|
728
|
+
"type": "attribute",
|
|
729
|
+
"code": "FrontEndFilter",
|
|
730
|
+
"values": [{ "V": "FlameScanner" }, { "V": "LsoCATBXEcatalog" }],
|
|
731
|
+
"operator": "In"
|
|
732
|
+
}
|
|
733
|
+
]
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
The values in this rule are alternatives. A product is excluded when its `FrontEndFilter` attribute equals
|
|
741
|
+
`FlameScanner` OR `LsoCATBXEcatalog`. Place the rule in the root `And` exclusion group alongside other exclusion
|
|
742
|
+
rules.
|
|
743
|
+
|
|
744
|
+
#### Client Migration
|
|
745
|
+
|
|
746
|
+
1. Stop sending `appSettings.appSpecific.frontEndFilter` to v2 endpoints.
|
|
747
|
+
2. Add one rule with `code: "FrontEndFilter"` and `operator: "In"` to `appSettings.filters.exclusionCriteria.rules`.
|
|
748
|
+
3. Copy every non-empty v1 list item to a separate `values[].V` entry.
|
|
749
|
+
4. Preserve existing exclusion rules in the same root `And` group.
|
|
750
|
+
|
|
751
|
+
### Compatibility and Validation
|
|
752
|
+
|
|
753
|
+
- v1 requests and behavior are unchanged. During conversion, `associatedGroups` becomes an `AssociatedGroups` rule in the root `And` group of `inclusionCriteria`, and `frontEndFilter` becomes a `FrontEndFilter` rule in the root `And` group of `exclusionCriteria`.
|
|
754
|
+
- Each converted list becomes the `V` values of an `In` rule. Empty entries are discarded, matching the existing v1 query behavior.
|
|
755
|
+
- `AppSettingsInternal.AppSpecific` uses `AppSpecificSettings`, so the removed fields do not exist in the canonical execution model.
|
|
756
|
+
- Supported v1 and v2 app-specific settings are copied into that v2 internal contract.
|
|
757
|
+
- A v2 payload containing legacy `associatedGroups` or `frontEndFilter` is currently accepted and those unknown properties are ignored.
|
|
758
|
+
- The removed properties are absent from the v2 OpenAPI schema. Responses are unchanged.
|
|
759
|
+
|
|
760
|
+
## Search TreeDepth
|
|
761
|
+
|
|
762
|
+
### v1
|
|
763
|
+
|
|
764
|
+
The Search endpoint accepts `TreeDepth` as an application-specific setting. Although the property is part of the
|
|
765
|
+
shared `AppSettings.AppSpecific` contract, it is used only by `POST /v1/Products/Search`; other v1 controllers do not
|
|
766
|
+
consume it:
|
|
767
|
+
|
|
768
|
+
```json
|
|
769
|
+
{
|
|
770
|
+
"dataTypes": ["Classifications"],
|
|
771
|
+
"appSettings": {
|
|
772
|
+
"appSpecific": {
|
|
773
|
+
"treeDepth": 2
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
It controls how deeply the classification tree in the Search response is expanded. A missing value or `0` keeps the
|
|
780
|
+
default behavior.
|
|
781
|
+
|
|
782
|
+
### v2
|
|
783
|
+
|
|
784
|
+
Move the property to the top level of `SearchQuery`:
|
|
785
|
+
|
|
786
|
+
```json
|
|
787
|
+
{
|
|
788
|
+
"dataTypes": ["Classifications"],
|
|
789
|
+
"treeDepth": 2,
|
|
790
|
+
"appSettings": {
|
|
791
|
+
"appCode": "example"
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
`TreeDepth` is an option of `POST /v2/Products/Search`, alongside other response-shaping settings such as
|
|
797
|
+
`MaxClassificationImages`. It is not part of the shared `SearchSettings` contract and does not affect product
|
|
798
|
+
matching. The property is nullable and defaults to `null`. A missing value, `null`, or `0` preserves the existing
|
|
799
|
+
default behavior.
|
|
800
|
+
|
|
801
|
+
### Client Migration
|
|
802
|
+
|
|
803
|
+
1. Stop sending `appSettings.appSpecific.treeDepth` to the v2 Search endpoint.
|
|
804
|
+
2. Send the same integer as top-level `treeDepth` in `SearchQuery`.
|
|
805
|
+
3. Keep `search.cid` and the remaining search criteria under `search` unchanged.
|
|
806
|
+
|
|
807
|
+
### Compatibility and Validation
|
|
808
|
+
|
|
809
|
+
- The v1 request contract and behavior are unchanged. `SearchService` reads the legacy value from
|
|
810
|
+
`AppSettings.AppSpecific.TreeDepth` for v1 requests.
|
|
811
|
+
- The v2 Search endpoint reads only top-level `SearchQuery.TreeDepth` and treats `null` as `0`.
|
|
812
|
+
- A v2 payload containing legacy `appSettings.appSpecific.treeDepth` is currently accepted and the unknown property is
|
|
813
|
+
ignored.
|
|
814
|
+
- This move does not add range validation; accepted values retain the existing Search behavior.
|
|
815
|
+
- The classification response shape, facet selection behavior, and cache behavior are unchanged.
|
|
816
|
+
- `SearchSettings` remains unchanged because it is shared by other queries.
|
|
817
|
+
- The Classifications endpoint remains unchanged and continues to use `ClassificationSearchSettings.TreeDepth`.
|
|
818
|
+
- `TreeDepth` is removed from the v2 `AppSpecificSettings` OpenAPI schema and exposed as a nullable property directly
|
|
819
|
+
on `SearchQuery`.
|
|
820
|
+
|
|
821
|
+
## AppSpecific.TableRowMatching
|
|
822
|
+
|
|
823
|
+
### v1
|
|
824
|
+
|
|
825
|
+
`TableRowMatching` is an application-specific setting:
|
|
826
|
+
|
|
827
|
+
```json
|
|
828
|
+
{
|
|
829
|
+
"appSettings": {
|
|
830
|
+
"appSpecific": {
|
|
831
|
+
"tableRowMatching": true
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
When enabled, criteria for attributes stored in product tables are evaluated against individual rows instead of the
|
|
838
|
+
entire table data set.
|
|
839
|
+
|
|
840
|
+
### v2
|
|
841
|
+
|
|
842
|
+
Move the property under `appSettings.filters` using the same name:
|
|
843
|
+
|
|
844
|
+
```json
|
|
845
|
+
{
|
|
846
|
+
"appSettings": {
|
|
847
|
+
"filters": {
|
|
848
|
+
"tableRowMatching": true
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
### Client Migration
|
|
855
|
+
|
|
856
|
+
1. Stop sending `appSettings.appSpecific.tableRowMatching` to v2 endpoints.
|
|
857
|
+
2. Send the same boolean value as `appSettings.filters.tableRowMatching`.
|
|
858
|
+
3. Keep table attribute criteria in the applicable inclusion, exclusion, or search filter settings.
|
|
859
|
+
|
|
860
|
+
### Compatibility and Validation
|
|
861
|
+
|
|
862
|
+
- v1 requests and behavior are unchanged. The v1-to-internal-v2 conversion copies a true value from `AppSpecific` to `ApplicationFilters`.
|
|
863
|
+
- `AppSpecificSettings` no longer exposes `TableRowMatching`; `ApplicationFilters` exposes it with a default value of `false`.
|
|
864
|
+
- A v2 payload containing legacy `appSpecific.tableRowMatching` is currently accepted and the unknown property is ignored.
|
|
865
|
+
- The move changes only the v2 request shape. Table-row query and facet behavior are unchanged.
|
|
866
|
+
|
|
867
|
+
## Detail RelatedProducts
|
|
868
|
+
|
|
869
|
+
### v1
|
|
870
|
+
|
|
871
|
+
The Detail endpoint accepts `RelatedProducts` as an application-specific setting:
|
|
872
|
+
|
|
873
|
+
```json
|
|
874
|
+
{
|
|
875
|
+
"dataTypes": ["ProductDetails"],
|
|
876
|
+
"appSettings": {
|
|
877
|
+
"appSpecific": {
|
|
878
|
+
"relatedProducts": true
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
### v2
|
|
885
|
+
|
|
886
|
+
Request related products directly as a Detail response section:
|
|
887
|
+
|
|
888
|
+
```json
|
|
889
|
+
{
|
|
890
|
+
"dataTypes": ["RelatedProducts"],
|
|
891
|
+
"appSettings": {
|
|
892
|
+
"appCode": "example"
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
`ProductDetails` and `RelatedProducts` are independent response sections. Include both values in `dataTypes` when
|
|
898
|
+
both sections are required.
|
|
899
|
+
|
|
900
|
+
### Client Migration
|
|
901
|
+
|
|
902
|
+
1. Stop sending `appSettings.appSpecific.relatedProducts` to the v2 Detail endpoint.
|
|
903
|
+
2. Add `RelatedProducts` to the top-level `dataTypes` set when the related-products section is required.
|
|
904
|
+
3. Add `ProductDetails` separately when the core product-detail section is also required.
|
|
905
|
+
|
|
906
|
+
### Compatibility and Validation
|
|
907
|
+
|
|
908
|
+
- The v1 request contract is unchanged. For `DetailQuery`, a true legacy setting is converted to an effective
|
|
909
|
+
`RelatedProducts` data type without modifying the request object.
|
|
910
|
+
- `AppSpecificSettings` and the canonical internal app-specific settings no longer expose `RelatedProducts`.
|
|
911
|
+
- A v2 payload containing legacy `appSpecific.relatedProducts` is currently accepted and the unknown property is
|
|
912
|
+
ignored; only `dataTypes` controls the v2 response section.
|
|
913
|
+
- The response DTOs are unchanged. The service no longer returns `ProductDetails` implicitly when only related
|
|
914
|
+
products are requested, or related products when only product details are requested.
|
|
915
|
+
- The v2 OpenAPI schema exposes `RelatedProducts` in `DetailDataTypeEnum` and omits it from
|
|
916
|
+
`AppSpecificSettings`.
|
|
917
|
+
|
|
918
|
+
## Product Variant Table Groups
|
|
919
|
+
|
|
920
|
+
V2 product details now support incremental loading of variant table groups. This reduces the initial Detail response
|
|
921
|
+
while preserving the complete v1 response contract.
|
|
922
|
+
|
|
923
|
+
### v1
|
|
924
|
+
|
|
925
|
+
The v1 Detail endpoint continues to return `ProductVariantsTable` with every group containing both
|
|
926
|
+
`variantAttributes` and `products` when `ProductVariantsTable` is requested. The v1 request and response contracts are
|
|
927
|
+
unchanged.
|
|
928
|
+
|
|
929
|
+
### v2 Detail
|
|
930
|
+
|
|
931
|
+
When `dataTypes` contains `ProductVariantsTable`, the first available group is returned with its complete
|
|
932
|
+
`variantAttributes` and `products` lists. Remaining groups contain only `attributeCode`, `attributeName`, and
|
|
933
|
+
`attributeValueText`; their `variantAttributes` and `products` properties are omitted from JSON.
|
|
934
|
+
|
|
935
|
+
```json
|
|
936
|
+
{
|
|
937
|
+
"productVariantsTable": {
|
|
938
|
+
"items": [
|
|
939
|
+
{
|
|
940
|
+
"attributeCode": "Color",
|
|
941
|
+
"attributeName": "Color",
|
|
942
|
+
"attributeValueText": "Red",
|
|
943
|
+
"variantAttributes": [],
|
|
944
|
+
"products": []
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
"attributeCode": "Voltage",
|
|
948
|
+
"attributeName": "Voltage",
|
|
949
|
+
"attributeValueText": "230 V"
|
|
950
|
+
}
|
|
951
|
+
]
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
The first group means the first group with a non-empty value for the selected product, following the configured
|
|
957
|
+
variant attribute order. The response uses a v2-specific DTO with nullable sparse properties; v1 continues to use its
|
|
958
|
+
required properties.
|
|
959
|
+
|
|
960
|
+
### Load One Group
|
|
961
|
+
|
|
962
|
+
Use the v2 endpoint below to load a complete group after receiving the sparse Detail response:
|
|
963
|
+
|
|
964
|
+
`POST /v2/Products/Variants/Table`
|
|
965
|
+
|
|
966
|
+
```json
|
|
967
|
+
{
|
|
968
|
+
"search": {
|
|
969
|
+
"productId": "example-product"
|
|
970
|
+
},
|
|
971
|
+
"attributeCode": "Voltage",
|
|
972
|
+
"attributeCodes": ["CatalogNumber"],
|
|
973
|
+
"appSettings": {
|
|
974
|
+
"appCode": "example"
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
```
|
|
978
|
+
|
|
979
|
+
The response is a `ProductVariantsTableSearchResultV2` wrapper containing exactly one full item:
|
|
980
|
+
|
|
981
|
+
```json
|
|
982
|
+
{
|
|
983
|
+
"items": [
|
|
984
|
+
{
|
|
985
|
+
"attributeCode": "Voltage",
|
|
986
|
+
"attributeName": "Voltage",
|
|
987
|
+
"attributeValueText": "230 V",
|
|
988
|
+
"variantAttributes": [],
|
|
989
|
+
"products": []
|
|
990
|
+
}
|
|
991
|
+
]
|
|
992
|
+
}
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
`attributeCode` is required and must identify a visible variant group available for the requested product and
|
|
996
|
+
application context. Empty, unknown, unavailable, or inaccessible codes return `400 Bad Request`. The endpoint uses
|
|
997
|
+
the same application filters, country and tenant context, internal-data visibility, authorization, and short-lived
|
|
998
|
+
output caching as the Detail variant query. `attributeCodes` controls additional serialized attributes on returned
|
|
999
|
+
variant products.
|
|
1000
|
+
|
|
1001
|
+
### Client Migration
|
|
1002
|
+
|
|
1003
|
+
1. Request `ProductVariantsTable` from v2 Detail.
|
|
1004
|
+
2. Render the first full group and retain metadata for the remaining groups.
|
|
1005
|
+
3. Call `POST /v2/Products/Variants/Table` with the selected `attributeCode` when another group is needed.
|
|
1006
|
+
4. Replace the sparse group with the returned full group.
|
|
1007
|
+
|
|
1008
|
+
An equivalent v2 Dropdown action is not part of this change and may be added separately in the `Variants` controller.
|
|
1009
|
+
|
|
1010
|
+
### Compatibility and Validation
|
|
1011
|
+
|
|
1012
|
+
- V1 Detail behavior and DTOs are unchanged.
|
|
1013
|
+
- V2 Detail changes only the `ProductVariantsTable` response shape when that data type is requested.
|
|
1014
|
+
- Selector and Dropdown response sections keep their existing behavior.
|
|
1015
|
+
- The new endpoint is v2-only and uses the standard v2 authorization, validation, error, logging, and cache pipeline.
|
|
1016
|
+
- The new endpoint does not add pagination; the returned group may contain all matching variant products.
|
|
1017
|
+
|
|
1018
|
+
## Filters and Filter Values
|
|
1019
|
+
|
|
1020
|
+
V2 separates filter discovery from loading selectable values. This reduces the response size of product Search and
|
|
1021
|
+
allows clients to request values only for filters that are currently expanded or otherwise needed.
|
|
1022
|
+
|
|
1023
|
+
- `POST /v2/Products/Filters` returns available filter metadata without `values`.
|
|
1024
|
+
- `POST /v2/Products/FilterValues` returns values for the selected `search.attributeCodes`.
|
|
1025
|
+
- `POST /v2/Products/RelationshipFilters` returns available relationship filter metadata without `values`.
|
|
1026
|
+
- `POST /v2/Products/RelationshipFilterValues` returns values for selected relationship filters.
|
|
1027
|
+
- `POST /v2/Products/Search` returns metadata without `values` in `filters` when `dataTypes` contains `Filters`.
|
|
1028
|
+
- `POST /v2/Catalogs/Products/Filters` returns available catalog filter metadata without `values`.
|
|
1029
|
+
- `POST /v2/Catalogs/Products/FilterValues` returns criterion-ready values for selected catalog filters.
|
|
1030
|
+
|
|
1031
|
+
### v1
|
|
1032
|
+
|
|
1033
|
+
The v1 `Products/Filters` and `Products/RelationshipFilters` endpoints continue to accept attribute codes under
|
|
1034
|
+
`search.attributeCodes` and return `FilterValueSearchResult`. Each filter contains its selectable `values`, exposes
|
|
1035
|
+
both deprecated `isPromoted` and replacement `promoted`, and uses `name` plus an optional `code` for each value:
|
|
1036
|
+
|
|
1037
|
+
```json
|
|
1038
|
+
{
|
|
1039
|
+
"items": [
|
|
1040
|
+
{
|
|
1041
|
+
"attributeCode": "Color",
|
|
1042
|
+
"attributeName": "Color",
|
|
1043
|
+
"attributeNameHtml": "Color",
|
|
1044
|
+
"hitCount": 42,
|
|
1045
|
+
"isPromoted": true,
|
|
1046
|
+
"promoted": true,
|
|
1047
|
+
"internal": false,
|
|
1048
|
+
"values": [
|
|
1049
|
+
{
|
|
1050
|
+
"name": "Red",
|
|
1051
|
+
"code": "RD",
|
|
1052
|
+
"hitCount": 17
|
|
1053
|
+
}
|
|
1054
|
+
]
|
|
1055
|
+
}
|
|
1056
|
+
]
|
|
1057
|
+
}
|
|
1058
|
+
```
|
|
1059
|
+
|
|
1060
|
+
For ordinary text attributes, `code` can be absent or null and `name` contains the value to filter by. For
|
|
1061
|
+
enumerations, `name` is localized display text and `code` is the criterion value. For multidimensional attributes,
|
|
1062
|
+
`name` is formatted display text and `code` contains the encoded source value.
|
|
1063
|
+
|
|
1064
|
+
### v2 Filter Discovery
|
|
1065
|
+
|
|
1066
|
+
Use `Products/Filters` or `Catalogs/Products/Filters` to retrieve product filter metadata:
|
|
1067
|
+
|
|
1068
|
+
```json
|
|
1069
|
+
{
|
|
1070
|
+
"search": {
|
|
1071
|
+
"cid": "Root"
|
|
1072
|
+
},
|
|
1073
|
+
"filters": {
|
|
1074
|
+
"attributeCodes": ["Color", "Voltage"]
|
|
1075
|
+
},
|
|
1076
|
+
"appSettings": {
|
|
1077
|
+
"appCode": "example"
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
```
|
|
1081
|
+
|
|
1082
|
+
`filters.attributeCodes` is optional. When supplied, it selects the metadata to return and overrides the
|
|
1083
|
+
default AGM parametric or predefined filter list. The response contains no selectable values:
|
|
1084
|
+
|
|
1085
|
+
```json
|
|
1086
|
+
{
|
|
1087
|
+
"items": [
|
|
1088
|
+
{
|
|
1089
|
+
"attributeCode": "Color",
|
|
1090
|
+
"attributeName": "Color",
|
|
1091
|
+
"attributeNameHtml": "Color",
|
|
1092
|
+
"hitCount": 42,
|
|
1093
|
+
"promoted": true,
|
|
1094
|
+
"internal": false
|
|
1095
|
+
}
|
|
1096
|
+
],
|
|
1097
|
+
"totalCount": 12
|
|
1098
|
+
}
|
|
1099
|
+
```
|
|
1100
|
+
|
|
1101
|
+
`totalCount` is the number of available filters before optional response limiting. The same metadata-only shape is
|
|
1102
|
+
used by `SearchResult.filters` and the v2 `RelationshipFilters` response. V2 omits obsolete `isPromoted`.
|
|
1103
|
+
|
|
1104
|
+
For `POST /v2/Products/Search`, optional top-level `filterSettings` is effective only when `dataTypes` contains
|
|
1105
|
+
`Filters`:
|
|
1106
|
+
|
|
1107
|
+
```json
|
|
1108
|
+
{
|
|
1109
|
+
"dataTypes": ["Products", "Filters"],
|
|
1110
|
+
"filterSettings": {
|
|
1111
|
+
"maxFilterAttributes": 10,
|
|
1112
|
+
"attributeCodes": ["Color", "Voltage"]
|
|
1113
|
+
},
|
|
1114
|
+
"appSettings": {
|
|
1115
|
+
"appCode": "example"
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
```
|
|
1119
|
+
|
|
1120
|
+
V2 Search requires `dataTypes` to contain at least one value. Omitting it, sending `null`, or sending an empty array
|
|
1121
|
+
returns `400`. Clients should request only the response sections they consume; v1 Search validation remains
|
|
1122
|
+
unchanged.
|
|
1123
|
+
|
|
1124
|
+
`maxFilterAttributes` limits non-promoted filters. Promoted filters are not limited unless explicit
|
|
1125
|
+
`attributeCodes` are supplied.
|
|
1126
|
+
|
|
1127
|
+
### v2 Filter Values
|
|
1128
|
+
|
|
1129
|
+
Use `Products/FilterValues` or `Catalogs/Products/FilterValues` to retrieve values for selected product filters.
|
|
1130
|
+
For both endpoints, `search.attributeCodes` is required,
|
|
1131
|
+
must be non-empty, accepts at most 100 codes, and every code must be non-empty:
|
|
1132
|
+
|
|
1133
|
+
```json
|
|
1134
|
+
{
|
|
1135
|
+
"search": {
|
|
1136
|
+
"cid": "Root",
|
|
1137
|
+
"attributeCodes": ["Color"]
|
|
1138
|
+
},
|
|
1139
|
+
"appSettings": {
|
|
1140
|
+
"appCode": "example"
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
```
|
|
1144
|
+
|
|
1145
|
+
The response uses `FilterValueSearchResultV2`. Each selectable value replaces v1 `name` and `code` with `text` and a
|
|
1146
|
+
required criterion-ready `CriterionValue` object:
|
|
1147
|
+
|
|
1148
|
+
```json
|
|
1149
|
+
{
|
|
1150
|
+
"items": [
|
|
1151
|
+
{
|
|
1152
|
+
"attributeCode": "Color",
|
|
1153
|
+
"attributeName": "Color",
|
|
1154
|
+
"attributeNameHtml": "Color",
|
|
1155
|
+
"hitCount": 42,
|
|
1156
|
+
"promoted": true,
|
|
1157
|
+
"internal": false,
|
|
1158
|
+
"values": [
|
|
1159
|
+
{
|
|
1160
|
+
"text": "Red",
|
|
1161
|
+
"value": { "V": "RD" },
|
|
1162
|
+
"hitCount": 17
|
|
1163
|
+
}
|
|
1164
|
+
]
|
|
1165
|
+
}
|
|
1166
|
+
]
|
|
1167
|
+
}
|
|
1168
|
+
```
|
|
1169
|
+
|
|
1170
|
+
For ordinary text and table attributes, `text` is the display text and `value.V` contains the same raw facet value.
|
|
1171
|
+
For enumerations, `text` is the localized label and `value.V` contains the enumeration code. Multidimensional values
|
|
1172
|
+
are returned without their legacy encoded representation:
|
|
1173
|
+
|
|
1174
|
+
```json
|
|
1175
|
+
{
|
|
1176
|
+
"text": "50 mm",
|
|
1177
|
+
"value": {
|
|
1178
|
+
"H": "",
|
|
1179
|
+
"V": "50",
|
|
1180
|
+
"U": "MM"
|
|
1181
|
+
},
|
|
1182
|
+
"hitCount": 8
|
|
1183
|
+
}
|
|
1184
|
+
```
|
|
1185
|
+
|
|
1186
|
+
Relationship filters use the same split. `RelationshipFilters` accepts `PrmSearchSettings` plus optional
|
|
1187
|
+
`filters.attributeCodes`; `RelationshipFilterValues` accepts the relationship search fields and requires
|
|
1188
|
+
`search.attributeCodes`. Both preserve the PRM block-join facet domain and relationship-specific AGM ordering.
|
|
1189
|
+
|
|
1190
|
+
### Client Migration
|
|
1191
|
+
|
|
1192
|
+
1. Use `Filters` or `Search` with `dataTypes: ["Filters"]` to discover available filter metadata.
|
|
1193
|
+
2. When the client needs selectable product or catalog values, call the corresponding `FilterValues` endpoint with those codes in `search.attributeCodes`.
|
|
1194
|
+
3. Apply the same flow to `RelationshipFilters` and `RelationshipFilterValues` for PRM results.
|
|
1195
|
+
4. Read display text from `values[].text` and pass `values[].value` directly to a v2 attribute criterion.
|
|
1196
|
+
5. Preserve all returned `H`, `V`, and `U` fields for multidimensional filters; do not parse display text.
|
|
1197
|
+
6. Read only `promoted`; obsolete `isPromoted` is not present in v2 responses.
|
|
1198
|
+
|
|
1199
|
+
### Compatibility and Validation
|
|
1200
|
+
|
|
1201
|
+
- V1 `Filters` and `RelationshipFilters` routes, requests, and `FilterValueSearchResult` responses are unchanged.
|
|
1202
|
+
- Sending a former v2 product or catalog `Filters` request with `search.attributeCodes` no longer requests values. The
|
|
1203
|
+
unknown `attributeCodes` property under `search` is ignored by the current JSON configuration; use `filters`
|
|
1204
|
+
for metadata selection or the corresponding `FilterValues` endpoint for values.
|
|
1205
|
+
- V2 `FilterValues`, `RelationshipFilterValues`, and catalog `FilterValues` reject missing, null, empty, over-100, or
|
|
1206
|
+
blank attribute-code selections.
|
|
1207
|
+
- Existing product search criteria and recursive `search.filter` criteria remain available on the product, relationship,
|
|
1208
|
+
and catalog v2 filter endpoints.
|
|
1209
|
+
- Product matching, relationship matching, hit counts, localization, criterion-ready values, and HTTP status behavior
|
|
1210
|
+
are unchanged.
|
|
1211
|
+
- `POST /v2/Catalogs/Products/Filters` returns metadata and `POST /v2/Catalogs/Products/FilterValues` returns values.
|
|
1212
|
+
- V2 OpenAPI exposes `FilterSearchResult` for discovery and `FilterValueSearchResult`, `FilterValueItem`, and
|
|
1213
|
+
`FilterValue` for value responses after the global v2 schema-name rule removes implementation suffixes.
|
|
1214
|
+
- Relationship v1 service tests cover the compatibility path; focused v2 response-contract tests remain pending.
|
|
1215
|
+
|
|
1216
|
+
## Interactive Guides
|
|
1217
|
+
|
|
1218
|
+
The v2 OpenAPI document omits `InteractiveGuides` from `SearchDataTypeEnum` and `DetailDataTypeEnum`. It also omits
|
|
1219
|
+
the obsolete `interactiveGuides` response properties from Search and Detail responses. The v1 OpenAPI document
|
|
1220
|
+
continues to expose these enum values and response properties for backward compatibility.
|
|
1221
|
+
|
|
1222
|
+
Clients migrating to `POST /v2/Products/Search` or `POST /v2/Products/Detail` must stop including
|
|
1223
|
+
`"InteractiveGuides"` in `dataTypes`. Interactive guides are no longer populated in responses.
|
|
1224
|
+
|
|
1225
|
+
This is currently an OpenAPI contract change only. Because v1 and v2 share the underlying .NET enum types, the v2
|
|
1226
|
+
JSON converter can still deserialize `"InteractiveGuides"`; v2 validation does not reject it. Runtime rejection
|
|
1227
|
+
would require a separate validation change or dedicated v2 enum types.
|
|
1228
|
+
|
|
1229
|
+
Verification confirms that the served v1 OpenAPI document retains `InteractiveGuides`, while the served v2 OpenAPI
|
|
1230
|
+
document contains no `InteractiveGuides` enum values, descriptions, or response properties.
|
|
1231
|
+
|
|
1232
|
+
## OpenAPI Schema Names
|
|
1233
|
+
|
|
1234
|
+
The v2 OpenAPI document removes the trailing `V2` suffix from component schema names. This keeps implementation
|
|
1235
|
+
versioning details out of the public model names displayed by Scalar and consumed by OpenAPI client generators.
|
|
1236
|
+
|
|
1237
|
+
The rule has no collision exceptions. Version-specific Compare and Favorite Views responses ensure that legacy
|
|
1238
|
+
`AttributeGroup` and `SearchSettings` schemas are not referenced by v2 operations. Their v2 counterparts are exposed
|
|
1239
|
+
as `AttributeGroup` and `SearchSettings` in the v2 document.
|
|
1240
|
+
|
|
1241
|
+
Polymorphic types derived from `Criterion` also use their direct type names. The v2 component schemas are exposed as
|
|
1242
|
+
`AttributeCriterion` and `CriteriaGroup`, rather than the default concatenated names `CriterionAttributeCriterion`
|
|
1243
|
+
and `CriterionCriteriaGroup`. The base schema remains `Criterion`, and its discriminator mappings and `$ref` values
|
|
1244
|
+
point to the shortened component names.
|
|
1245
|
+
|
|
1246
|
+
This change affects only schema keys under `components.schemas` and their `$ref` values in the v2 OpenAPI document.
|
|
1247
|
+
It does not rename C# types, JSON properties, routes, request or response payloads, or schemas in the v1 OpenAPI
|
|
1248
|
+
document. Clients regenerated from the v2 specification may receive model type renames even though their serialized
|
|
1249
|
+
JSON contracts are unchanged.
|
|
1250
|
+
|
|
1251
|
+
## Translation Domains
|
|
1252
|
+
|
|
1253
|
+
`POST /v2/Translations` replaces free-form component names with a fixed set of translation domains. The response
|
|
1254
|
+
uses the same domain enum and no longer exposes the legacy component property.
|
|
1255
|
+
|
|
1256
|
+
### v1
|
|
1257
|
+
|
|
1258
|
+
```json
|
|
1259
|
+
{
|
|
1260
|
+
"components": ["products", "common"],
|
|
1261
|
+
"appSettings": {
|
|
1262
|
+
"appCode": "example"
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
```
|
|
1266
|
+
|
|
1267
|
+
The v1 response continues to use a string `component`:
|
|
1268
|
+
|
|
1269
|
+
```json
|
|
1270
|
+
[
|
|
1271
|
+
{
|
|
1272
|
+
"component": "products",
|
|
1273
|
+
"key": "Product.Title",
|
|
1274
|
+
"value": "Product"
|
|
1275
|
+
}
|
|
1276
|
+
]
|
|
1277
|
+
```
|
|
1278
|
+
|
|
1279
|
+
### v2
|
|
1280
|
+
|
|
1281
|
+
```json
|
|
1282
|
+
{
|
|
1283
|
+
"domains": ["Products", "Common"],
|
|
1284
|
+
"appSettings": {
|
|
1285
|
+
"appCode": "example"
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
```
|
|
1289
|
+
|
|
1290
|
+
`domains` accepts only `Catalogs`, `Classifications`, `Common`, and `Products`. If it is omitted, null, or empty,
|
|
1291
|
+
translations from all four supported domains are returned.
|
|
1292
|
+
|
|
1293
|
+
The v2 response uses `TranslationItemV2`, where `domain` is the same enum:
|
|
1294
|
+
|
|
1295
|
+
```json
|
|
1296
|
+
[
|
|
1297
|
+
{
|
|
1298
|
+
"domain": "Products",
|
|
1299
|
+
"key": "Product.Title",
|
|
1300
|
+
"value": "Product"
|
|
1301
|
+
}
|
|
1302
|
+
]
|
|
1303
|
+
```
|
|
1304
|
+
|
|
1305
|
+
### Client Migration
|
|
1306
|
+
|
|
1307
|
+
1. Replace `components` with `domains` in v2 translation requests.
|
|
1308
|
+
2. Change lowercase free-form component strings to the corresponding enum names.
|
|
1309
|
+
3. Read `domain` instead of `component` from each v2 response item.
|
|
1310
|
+
|
|
1311
|
+
### Compatibility and Validation
|
|
1312
|
+
|
|
1313
|
+
- The v1 request and response contracts are unchanged.
|
|
1314
|
+
- A v2 payload containing legacy `components` is accepted by the current JSON configuration, but the unknown
|
|
1315
|
+
property is ignored; omitting `domains` therefore returns all supported domains.
|
|
1316
|
+
- Values outside the four declared domains are rejected during v2 request binding.
|
|
1317
|
+
- Translation lookup, language fallback, output caching, and HTTP status behavior are unchanged.
|
|
1318
|
+
- The v2 OpenAPI operation exposes enum-based `domains` in the request and enum-based `domain` in its response.
|
|
1319
|
+
|
|
1320
|
+
## Query-Scoped Relationship and Variant Settings
|
|
1321
|
+
|
|
1322
|
+
V2 no longer exposes `productRelationshipFiltering` or `variant` inside `appSettings`. These options describe the
|
|
1323
|
+
result of the current query, so they are now scoped to the query that uses them. The v1 `AppSettings` contract and all
|
|
1324
|
+
v1 behavior remain unchanged.
|
|
1325
|
+
|
|
1326
|
+
`variants` uses `VariantSettingsV2`:
|
|
1327
|
+
|
|
1328
|
+
```json
|
|
1329
|
+
{
|
|
1330
|
+
"variants": {
|
|
1331
|
+
"clustering": true,
|
|
1332
|
+
"attributeCodes": ["Color", "Voltage_*"]
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
```
|
|
1336
|
+
|
|
1337
|
+
`clustering` controls the Solr variant collapse for product search results, counts, filter metadata, filter values,
|
|
1338
|
+
and autocomplete. `attributeCodes` requests additional serialized product attributes. In `Detail`, it applies to the
|
|
1339
|
+
variant products returned by the selected variant data types.
|
|
1340
|
+
|
|
1341
|
+
`relationships` uses `RelationshipSettingsV2`:
|
|
1342
|
+
|
|
1343
|
+
```json
|
|
1344
|
+
{
|
|
1345
|
+
"relationships": {
|
|
1346
|
+
"productRelationshipFiltering": true,
|
|
1347
|
+
"attributeCodes": ["RelationshipAttribute", "Voltage_*"],
|
|
1348
|
+
"pager": {
|
|
1349
|
+
"page": 1,
|
|
1350
|
+
"pageSize": 20
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
```
|
|
1355
|
+
|
|
1356
|
+
The relationship settings control relationship filter metadata, additional attributes for related products, and public
|
|
1357
|
+
pagination of relationship products. In `Detail`, the existing internal `relationshipPager` is replaced by the public
|
|
1358
|
+
`relationships.pager`. `PrmQueryV2` and `PrmAutocompleteQueryV2` likewise use `relationships.pager`; their former
|
|
1359
|
+
top-level v2 pager is no longer used. `PrmQueryV2` also places relationship attribute selection under
|
|
1360
|
+
`relationships.attributeCodes`.
|
|
1361
|
+
|
|
1362
|
+
The query coverage is:
|
|
1363
|
+
|
|
1364
|
+
| Setting | v2 query contracts |
|
|
1365
|
+
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1366
|
+
| `variants` | `SearchQueryV2`, `AutocompleteQueryV2`, `CountQueryV2`, `FiltersQueryV2`, `FilterValueQueryV2`, `DetailQueryV2`, and `ClassificationQueryV2` |
|
|
1367
|
+
| `relationships` | `DetailQueryV2`, `PrmQueryV2`, `PrmFiltersQueryV2`, `PrmFilterValueQueryV2`, and `PrmAutocompleteQueryV2` |
|
|
1368
|
+
|
|
1369
|
+
Legacy v2 payloads that still put these properties under `appSettings` are not transformed; the old properties are
|
|
1370
|
+
unknown to `AppSettingsV2` and are ignored by JSON binding. Clients must move them to the query-level sections above.
|
|
1371
|
+
|
|
1372
|
+
## Query-Scoped Attribute Sorting
|
|
1373
|
+
|
|
1374
|
+
V2 attribute sort mappings are no longer supplied through `appSettings.sort`. The v2 `SearchQuery` and
|
|
1375
|
+
`PriceListQuery` contracts expose `SortSettingsV2`, which combines the regular field/direction sort with optional
|
|
1376
|
+
attribute mappings:
|
|
1377
|
+
|
|
1378
|
+
```json
|
|
1379
|
+
{
|
|
1380
|
+
"sort": {
|
|
1381
|
+
"field": "Relevance",
|
|
1382
|
+
"direction": "Descending",
|
|
1383
|
+
"map": [
|
|
1384
|
+
{
|
|
1385
|
+
"attributeCode": "ProductStatus",
|
|
1386
|
+
"values": ["Preferred", "Standard"]
|
|
1387
|
+
}
|
|
1388
|
+
]
|
|
1389
|
+
},
|
|
1390
|
+
"appSettings": {
|
|
1391
|
+
"appCode": "example"
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
```
|
|
1395
|
+
|
|
1396
|
+
`sort.map` is supported by `SearchQueryV2` and `PriceListQueryV2` only. The map is applied to the Solr request for
|
|
1397
|
+
the current query. `Count`, `Filters`, `FilterValues`, `Detail`, autocomplete, and relationship queries do not accept
|
|
1398
|
+
this setting. The v1 `AppSettings.Sort` contract remains unchanged.
|
|
1399
|
+
|
|
1400
|
+
## Endpoint Rollout
|
|
1401
|
+
|
|
1402
|
+
| Endpoint | v2 request contract | Filter execution | Status |
|
|
1403
|
+
| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------- |
|
|
1404
|
+
| `POST /v2/Translations` | `TranslationQuery` with enum-based `Domains` and `TranslationItem` response with enum-based `Domain` | Not applicable | Implemented |
|
|
1405
|
+
| `POST /v2/Sitemap/Products` | `SitemapProductSearchQuery` with `AppSettings`; `SitemapProductSearchSettings` is unchanged | Flat scalar `Criteria` is mapped to the v1 Solr filter path; nested and multidimensional criteria return `400` | Implemented |
|
|
1406
|
+
| `POST /v2/Products/Search` | `SearchQuery` with optional `filterSettings` when `dataTypes` contains `Filters` | Returns filter metadata only; requested codes and maximum count can reduce the filter response | Implemented |
|
|
1407
|
+
| `POST /v2/Catalogs/Products/Search` | `CatalogProductSearchQueryV2` with optional `filterSettings` when `dataTypes` contains `Filters` | Returns catalog filter metadata with the requested codes and maximum count applied | Implemented |
|
|
1408
|
+
| `POST /v2/Products/Filters` | `FiltersQuery` with optional search and metadata `filters` | Returns available `FilterSearchResult` metadata without selectable values | Implemented |
|
|
1409
|
+
| `POST /v2/Products/FilterValues` | `FilterValueQuery` with required `search.attributeCodes` | Returns criterion-ready `FilterValueSearchResult` values for selected attributes | Implemented |
|
|
1410
|
+
| `POST /v2/Products/RelationshipFilters` | `PrmFiltersQuery` with optional metadata `filters` | Returns relationship filter metadata using the PRM block-join domain | Implemented |
|
|
1411
|
+
| `POST /v2/Products/RelationshipFilterValues` | `PrmFilterValueQuery` with required `search.attributeCodes` | Returns criterion-ready relationship filter values using the PRM block-join domain | Implemented |
|
|
1412
|
+
| `POST /v2/Catalogs/Products/Filters` | `CatalogProductFiltersQueryV2` with optional metadata `filters` | Returns catalog product filter metadata | Implemented |
|
|
1413
|
+
| `POST /v2/Catalogs/Products/FilterValues` | `CatalogProductFilterValuesQueryV2` with required `search.attributeCodes` | Returns criterion-ready catalog filter values | Implemented |
|
|
1414
|
+
| Product search, count, list, autocomplete, and related endpoints | To be added | Pending `Criteria` query compilation | Not started |
|
|
1415
|
+
|
|
1416
|
+
## Update Checklist
|
|
1417
|
+
|
|
1418
|
+
When adding the next v2 migration item:
|
|
1419
|
+
|
|
1420
|
+
1. Add the v1 and v2 JSON examples.
|
|
1421
|
+
2. State whether legacy input is ignored, rejected, or transformed.
|
|
1422
|
+
3. Identify endpoint coverage and response impact.
|
|
1423
|
+
4. Add validation, service, query-composition, cache, and OpenAPI status.
|
|
1424
|
+
5. Add focused tests and update the change-log status.
|