diff --git a/src/openapi/products/SE-products-SE.yaml b/src/openapi/products/SE-products-SE.yaml index 627cb36..b97f796 100644 --- a/src/openapi/products/SE-products-SE.yaml +++ b/src/openapi/products/SE-products-SE.yaml @@ -421,12 +421,20 @@ paths: All details (that the calling touchpoint is allowed to see) for the 20% Discount product.\ Even though this product has sellingPeriods for multiple touchpoints (3 and 4), only the currently active sellingPeriod and price for touchpointId 4 are returned. - This product has two `productVariants`: a single month variant and a subscription variant. + This product has two `productVariants`: a single month variant and a subscription variant.\ + The top-level parent contains `LayerInfo` to communicate what differentiates + the underlying product-variants.\ + When no `LayerInfo` is present, the touchpoint can conclude that the product is a final fulfillable product. value: { "productId": 126, "parentProductId": null, - "layerInfo": null, + "layerInfo": { + "layerInfoId": 1, + "choiceKey": "isRenewable", + "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", + "isCustomChoice": false, + }, "fikoArticleNumber": "1234", "gboPackageTemplateId": "30001", "tapConnectProductCode": null, @@ -529,12 +537,7 @@ paths: { "productId": 119, "parentProductId": 126, - "layerInfo": { - "layerInfoId": 1, - "choiceKey": "isRenewable", - "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", - "isCustomChoice": false, - }, + "layerInfo": null, "fikoArticleNumber": "1234", "gboPackageTemplateId": "30001", "tapConnectProductCode": null, @@ -649,12 +652,7 @@ paths: { "productId": 120, "parentProductId": 126, - "layerInfo": { - "layerInfoId": 1, - "choiceKey": "isRenewable", - "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", - "isCustomChoice": false, - }, + "layerInfo": null, "fikoArticleNumber": "1234", "gboPackageTemplateId": "30001", "tapConnectProductCode": null, @@ -774,12 +772,19 @@ paths: All details (that the calling touchpoint is allowed to see) for the parent Regio Vrij product and (7 out of 84 of) its productVariants; the full tree would be too huge to be useful as an example. - The full depth of the tree is included in the example for the HL62 Reduced Fare Variant. + The full depth of the tree is included in the example for the HL62 Reduced Fare Variant.\ + Each non-leaf-node product contains `LayerInfo` to communicate what differentiates the underlying product-variants.\ + When no `LayerInfo` is present, the touchpoint can conclude that the product is a final fulfillable product. value: { "productId": 49, "parentProductId": null, - "layerInfo": null, + "layerInfo": { + "layerInfoId": 2, + "choiceKey": "regio", + "choiceLabel": "Kies de gewenste regio", + "isCustomChoice": true, + }, "fikoArticleNumber": "1234", "gboPackageTemplateId": null, "tapConnectProductCode": null, @@ -922,10 +927,10 @@ paths: "productId": 109, "parentProductId": 49, "layerInfo": { - "layerInfoId": 2, - "choiceKey": "regio", - "choiceLabel": "Kies de gewenste regio", - "isCustomChoice": true, + "layerInfoId": 3, + "choiceKey": "allowedGboAgeProfiles", + "choiceLabel": "Wat is uw geboortedatum?", + "isCustomChoice": false, }, "fikoArticleNumber": "1234", "gboPackageTemplateId": "33615", @@ -1072,9 +1077,9 @@ paths: "productId": 114, "parentProductId": 109, "layerInfo": { - "layerInfoId": 3, - "choiceKey": "allowedGboAgeProfiles", - "choiceLabel": "Wat is uw geboortedatum?", + "layerInfoId": 1, + "choiceKey": "isRenewable", + "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", "isCustomChoice": false, }, "fikoArticleNumber": "1234", @@ -1222,9 +1227,9 @@ paths: "productId": 115, "parentProductId": 109, "layerInfo": { - "layerInfoId": 3, - "choiceKey": "allowedGboAgeProfiles", - "choiceLabel": "Wat is uw geboortedatum?", + "layerInfoId": 1, + "choiceKey": "isRenewable", + "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", "isCustomChoice": false, }, "fikoArticleNumber": "1234", @@ -1372,12 +1377,7 @@ paths: { "productId": 116, "parentProductId": 115, - "layerInfo": { - "layerInfoId": 1, - "choiceKey": "isRenewable", - "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", - "isCustomChoice": false, - }, + "layerInfo": null, "fikoArticleNumber": "1234", "gboPackageTemplateId": "33615", "tapConnectProductCode": null, @@ -1526,12 +1526,7 @@ paths: { "productId": 117, "parentProductId": 115, - "layerInfo": { - "layerInfoId": 1, - "choiceKey": "isRenewable", - "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", - "isCustomChoice": false, - }, + "layerInfo": null, "fikoArticleNumber": "1234", "gboPackageTemplateId": "33615", "tapConnectProductCode": null, @@ -1685,10 +1680,10 @@ paths: "productId": 112, "parentProductId": 49, "layerInfo": { - "layerInfoId": 2, - "choiceKey": "regio", - "choiceLabel": "Kies de gewenste regio", - "isCustomChoice": true, + "layerInfoId": 3, + "choiceKey": "allowedGboAgeProfiles", + "choiceLabel": "Wat is uw geboortedatum?", + "isCustomChoice": false, }, "fikoArticleNumber": "1234", "gboPackageTemplateId": "33618", @@ -1858,10 +1853,11 @@ components: description: >- Gives information on the choice that the customer has to make, to enable the touchpoint to proceed further "down the product-tree" by selecting (PATCH-ing) the correct product-variant. - LayerInfo is not a mandatory product-attribute, but it should always be present on all product for which - `parentProductId != null`. (LayerInfo makes no sense for top-level parents as there is always a single starting point). \ + LayerInfo is not a mandatory product-attribute, but it should always be present on all products for which + there are underlying products, i.e. for which `GET /products?parentProductId=...` returns a non-empty list. + When no LayerInfo is present, the touchpoint can conclude that the product is a final fulfillable product. \ - **PMT should ensure that all products in the same "product-branch" (same `parentProductId`) have the same `layerInfoId` + **PMT should ensure that all non-leaf-node products (i.e. products that have underlying products) have a `layerInfoId` referenced. If a product is found to be in violation of this rule, its attribtue `isValid` should be set to `false`.** required: - layerInfoId @@ -1877,12 +1873,12 @@ components: type: string description: >- Contains the JSON Key of the product-attribute that the customer has to make some - choice on (determined by PMT), so that te correct product-variant can be selected by the touchpoint. For some - decisions (like region), there is no product attribute, and thus `isCustomChoice` will be set - to `true`, and `choiceKey` can then be set to any string on which touchpoints can also trigger - behaviour if desired (think "region picker tool"). Therefore, reuse of choiceKeys should be + choice on (determined by PMT), so that te correct product-variant (one of the direct child-products) can be + selected by the touchpoint. For some decisions (like region), there is no product attribute, and thus + `isCustomChoice` will be set to `true`, and `choiceKey` can then be set to any string on which touchpoints + can also trigger behaviour if desired (think "region picker tool"). Therefore, reuse of `choiceKeys` should be the goal, so touchoints can keep their triggers simple and prevent duplication of - similar choiceKeys to trigger the same behaviour. + similar `choiceKeys` to trigger the same behaviour. choiceLabel: example: Kies voor een doorlopend abonnement of een enkele termijn type: string @@ -1894,12 +1890,10 @@ components: example: false type: boolean description: >- - Indicates if the choice is a custom choice. If `false`, the PMT should fill `choiceKey` with the - "differing attribute for this product-layer" and the user should not be able to override this. When - no single attribute can be pinpointed by PMT, the product will become invalid (`isValid == false`) until either - a situation with a single differing attribute is created, or if `isCustomChoice` is set to `true` - this would, - however, also mean that touchpoints should be notified of this, especially if the configured LayerInfo contains - a new, not previously used, `choiceKey`. + Indicates if the choice is a custom choice. If `false`, the PMT should validate that the `choiceKey` is a + differentiating attribute for the underlying product-variants. When the attribute denoted by the `choiceKey` is + the same for all underlying variants, PMT validation will fail and the product will become invalid (`isValid == false`) + until either the underlying products are updated, or a `LayerInfo` with `isCustomChoice == true` is configured. GboAgeProfileResponse: type: object required: diff --git a/src/openapi/products/SE-products-TP.yaml b/src/openapi/products/SE-products-TP.yaml index a4b15cb..da86e36 100644 --- a/src/openapi/products/SE-products-TP.yaml +++ b/src/openapi/products/SE-products-TP.yaml @@ -421,12 +421,20 @@ paths: All details (that the calling touchpoint is allowed to see) for the 20% Discount product.\ Even though this product has sellingPeriods for multiple touchpoints (3 and 4), only the currently active sellingPeriod and price for touchpointId 4 are returned. - This product has two `productVariants`: a single month variant and a subscription variant. + This product has two `productVariants`: a single month variant and a subscription variant.\ + The top-level parent contains `LayerInfo` to communicate what differentiates + the underlying product-variants.\ + When no `LayerInfo` is present, the touchpoint can conclude that the product is a final fulfillable product. value: { "productId": 126, "parentProductId": null, - "layerInfo": null, + "layerInfo": { + "layerInfoId": 1, + "choiceKey": "isRenewable", + "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", + "isCustomChoice": false, + }, "fikoArticleNumber": "1234", "gboPackageTemplateId": "30001", "tapConnectProductCode": null, @@ -529,12 +537,7 @@ paths: { "productId": 119, "parentProductId": 126, - "layerInfo": { - "layerInfoId": 1, - "choiceKey": "isRenewable", - "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", - "isCustomChoice": false, - }, + "layerInfo": null, "fikoArticleNumber": "1234", "gboPackageTemplateId": "30001", "tapConnectProductCode": null, @@ -649,12 +652,7 @@ paths: { "productId": 120, "parentProductId": 126, - "layerInfo": { - "layerInfoId": 1, - "choiceKey": "isRenewable", - "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", - "isCustomChoice": false, - }, + "layerInfo": null, "fikoArticleNumber": "1234", "gboPackageTemplateId": "30001", "tapConnectProductCode": null, @@ -774,12 +772,19 @@ paths: All details (that the calling touchpoint is allowed to see) for the parent Regio Vrij product and (7 out of 84 of) its productVariants; the full tree would be too huge to be useful as an example. - The full depth of the tree is included in the example for the HL62 Reduced Fare Variant. + The full depth of the tree is included in the example for the HL62 Reduced Fare Variant.\ + Each non-leaf-node product contains `LayerInfo` to communicate what differentiates the underlying product-variants.\ + When no `LayerInfo` is present, the touchpoint can conclude that the product is a final fulfillable product. value: { "productId": 49, "parentProductId": null, - "layerInfo": null, + "layerInfo": { + "layerInfoId": 2, + "choiceKey": "regio", + "choiceLabel": "Kies de gewenste regio", + "isCustomChoice": true, + }, "fikoArticleNumber": "1234", "gboPackageTemplateId": null, "tapConnectProductCode": null, @@ -922,10 +927,10 @@ paths: "productId": 109, "parentProductId": 49, "layerInfo": { - "layerInfoId": 2, - "choiceKey": "regio", - "choiceLabel": "Kies de gewenste regio", - "isCustomChoice": true, + "layerInfoId": 3, + "choiceKey": "allowedGboAgeProfiles", + "choiceLabel": "Wat is uw geboortedatum?", + "isCustomChoice": false, }, "fikoArticleNumber": "1234", "gboPackageTemplateId": "33615", @@ -1072,9 +1077,9 @@ paths: "productId": 114, "parentProductId": 109, "layerInfo": { - "layerInfoId": 3, - "choiceKey": "allowedGboAgeProfiles", - "choiceLabel": "Wat is uw geboortedatum?", + "layerInfoId": 1, + "choiceKey": "isRenewable", + "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", "isCustomChoice": false, }, "fikoArticleNumber": "1234", @@ -1222,9 +1227,9 @@ paths: "productId": 115, "parentProductId": 109, "layerInfo": { - "layerInfoId": 3, - "choiceKey": "allowedGboAgeProfiles", - "choiceLabel": "Wat is uw geboortedatum?", + "layerInfoId": 1, + "choiceKey": "isRenewable", + "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", "isCustomChoice": false, }, "fikoArticleNumber": "1234", @@ -1372,12 +1377,7 @@ paths: { "productId": 116, "parentProductId": 115, - "layerInfo": { - "layerInfoId": 1, - "choiceKey": "isRenewable", - "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", - "isCustomChoice": false, - }, + "layerInfo": null, "fikoArticleNumber": "1234", "gboPackageTemplateId": "33615", "tapConnectProductCode": null, @@ -1526,12 +1526,7 @@ paths: { "productId": 117, "parentProductId": 115, - "layerInfo": { - "layerInfoId": 1, - "choiceKey": "isRenewable", - "choiceLabel": "Kies voor een doorlopend abonnement of een enkele termijn", - "isCustomChoice": false, - }, + "layerInfo": null, "fikoArticleNumber": "1234", "gboPackageTemplateId": "33615", "tapConnectProductCode": null, @@ -1685,10 +1680,10 @@ paths: "productId": 112, "parentProductId": 49, "layerInfo": { - "layerInfoId": 2, - "choiceKey": "regio", - "choiceLabel": "Kies de gewenste regio", - "isCustomChoice": true, + "layerInfoId": 3, + "choiceKey": "allowedGboAgeProfiles", + "choiceLabel": "Wat is uw geboortedatum?", + "isCustomChoice": false, }, "fikoArticleNumber": "1234", "gboPackageTemplateId": "33618", @@ -1858,10 +1853,11 @@ components: description: >- Gives information on the choice that the customer has to make, to enable the touchpoint to proceed further "down the product-tree" by selecting (PATCH-ing) the correct product-variant. - LayerInfo is not a mandatory product-attribute, but it should always be present on all product for which - `parentProductId != null`. (LayerInfo makes no sense for top-level parents as there is always a single starting point). \ + LayerInfo is not a mandatory product-attribute, but it should always be present on all products for which + there are underlying products, i.e. for which `GET /products?parentProductId=...` returns a non-empty list. + When no LayerInfo is present, the touchpoint can conclude that the product is a final fulfillable product. \ - **PMT should ensure that all products in the same "product-branch" (same `parentProductId`) have the same `layerInfoId` + **PMT should ensure that all non-leaf-node products (i.e. products that have underlying products) have a `layerInfoId` referenced. If a product is found to be in violation of this rule, its attribtue `isValid` should be set to `false`.** required: - layerInfoId @@ -1877,12 +1873,12 @@ components: type: string description: >- Contains the JSON Key of the product-attribute that the customer has to make some - choice on (determined by PMT), so that te correct product-variant can be selected by the touchpoint. For some - decisions (like region), there is no product attribute, and thus `isCustomChoice` will be set - to `true`, and `choiceKey` can then be set to any string on which touchpoints can also trigger - behaviour if desired (think "region picker tool"). Therefore, reuse of choiceKeys should be + choice on (determined by PMT), so that te correct product-variant (one of the direct child-products) can be + selected by the touchpoint. For some decisions (like region), there is no product attribute, and thus + `isCustomChoice` will be set to `true`, and `choiceKey` can then be set to any string on which touchpoints + can also trigger behaviour if desired (think "region picker tool"). Therefore, reuse of `choiceKeys` should be the goal, so touchoints can keep their triggers simple and prevent duplication of - similar choiceKeys to trigger the same behaviour. + similar `choiceKeys` to trigger the same behaviour. choiceLabel: example: Kies voor een doorlopend abonnement of een enkele termijn type: string @@ -1894,12 +1890,10 @@ components: example: false type: boolean description: >- - Indicates if the choice is a custom choice. If `false`, the PMT should fill `choiceKey` with the - "differing attribute for this product-layer" and the user should not be able to override this. When - no single attribute can be pinpointed by PMT, the product will become invalid (`isValid == false`) until either - a situation with a single differing attribute is created, or if `isCustomChoice` is set to `true` - this would, - however, also mean that touchpoints should be notified of this, especially if the configured LayerInfo contains - a new, not previously used, `choiceKey`. + Indicates if the choice is a custom choice. If `false`, the PMT should validate that the `choiceKey` is a + differentiating attribute for the underlying product-variants. When the attribute denoted by the `choiceKey` is + the same for all underlying variants, PMT validation will fail and the product will become invalid (`isValid == false`) + until either the underlying products are updated, or a `LayerInfo` with `isCustomChoice == true` is configured. GboAgeProfileResponse: type: object required: diff --git a/src/openapi/products/products-crud.yaml b/src/openapi/products/products-crud.yaml index 814ab87..deb549a 100644 --- a/src/openapi/products/products-crud.yaml +++ b/src/openapi/products/products-crud.yaml @@ -1243,12 +1243,22 @@ paths: ] } getDetailsGboPadProduct: - summary: GBO product (PAD required, renewable, allowedGboAgeProfiles, padBirthDate) + summary: GBO product (PAD required, layerInfo, allowedGboAgeProfiles, padBirthDate) + description: >- + This product has `layerInfo` defined, which means that this product is not a final fulfillable product, but that there are underlying variants + that the customer has to choose between. The `layerInfo` defines what distinguishes the underlying variants - in this case the + `allowedGboAgeProfiles` array contains different values for the underlying variants. Based on age information provided by the customer, + the correct underlying variant can be selected. value: { "productId": 3, "parentProductId": null, - "layerInfo": null, + "layerInfo": { + "layerInfoId": 1, + "choiceKey": "allowedGboAgeProfiles", + "choiceLabel": "Wat is uw geboortedatum?", + "isCustomChoice": false + }, "fikoArticleNumber": "1234", "isValid": true, "isArchived": false, @@ -1279,16 +1289,7 @@ paths: "name": "B2C" } ], - "customerSegments": [ - { - "customerSegmentId": 5, - "name": "Student" - }, - { - "customerSegmentId": 6, - "name": "Ooievaarspas-gerechtigde" - } - ], + "customerSegments": null, "allowedGboAgeProfiles": [ { "gboAgeProfileId": 2, @@ -1377,221 +1378,8 @@ paths: "serviceOptions": [], "validityDuration": "P1M", "maxStartInFutureDuration": "P6W", - "isRenewable": true, - "sendInvoice": true, - "imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg", - "productPageUrl": "https://www.htm.nl/nog-onbekende-product-pagina", - "termsUrl": "https://www.htm.nl/nog-onbekende-productvoorwaarden-pagina", - "isSellableAtHtm": true, - "needsSolvencyCheckConsumer": false, - "needsSolvencyCheckBusiness": false, - "sellingPeriods": [ - { - "sellingPeriodId": 5, - "fromInclusive": "2024-09-01T00:00:00.000+00:00", - "toInclusive": "2024-12-31T23:59:59.999+00:00", - "salesTouchpoint": { - "salesTouchpointId": 3, - "name": "Website (Perplex)", - "isActive": true, - "retailer": { - "retailerId": 1001, - "name": "HTM externe touchpoints", - "street": "Koningin Julianaplein", - "number": "10", - "numberAddition": null, - "postalCode": "2595 AA", - "city": "Den Haag", - "country": "Nederland", - "emailAddress": "info@htm.nl", - "phoneNumber": "070 374 9002", - "taxId": "572309345923", - "imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg" - } - }, - "forbiddenPaymentMethods": [ - { - "forbiddenPaymentMethodId": 3, - "name": "creditcard", - "issuer": "American Express" - } - ], - "sellingPrices": [ - { - "sellingPriceId": 5, - "amountExclTax": null, - "amountInclTax": 5900, - "taxCode": "V09", - "taxPercentage": 9.0000, - "fromInclusive": "2024-09-01T00:00:00.000+00:00", - "toInclusive": "2024-12-31T23:59:59.999+00:00", - "internalPrice": 5413.0000 - } - ] - } - ], - "purchasePrices": [ - { - "purchasePriceId": 1, - "amountExclTax": null, - "taxCode": "V09", - "taxPercentage": 9.0000, - "amountInclTax": 0, - "fromInclusive": "2024-09-01T00:00:00.000+00:00", - "toInclusive": "2024-12-31T23:59:59.999+00:00" - } - ], - "auditTrail": [ - { - "auditTrailId": 2, - "action": "update", - "user": "api", - "timestamp": "2024-09-03T08:39:38.000+00:00" - }, - { - "auditTrailId": 1, - "action": "insert", - "user": "api", - "timestamp": "2024-09-03T08:38:24.000+00:00" - } - ] - } - getDetailsProductVariantWithParent: - summary: GBO product-variant, meaning that parentProductId and layerInfo are present - description: >- - This product is not a top-level parent, but a product-variant that refers to another product (via `parentProductId`). - This means that the `layerInfo` should be present for this product-variant. The parent product references is `productId 3`, - so the product in this example is an extension of that product-definition. MOre specifically: in this product-variant, we - removed some `allowedGboAgeProfiles` from the definition - this means that the customer has to provide the birthdate of - the token-owner (padBirthdate) in order to be able to buy this product-variant. - value: - { - "productId": 4, - "parentProductId": 3, - "layerInfo": { - "layerInfoId": 1, - "choiceKey": "allowedGboAgeProfiles", - "choiceLabel": "Wat is uw geboortedatum?", - "isCustomChoice": false - }, - "fikoArticleNumber": "1234", - "isValid": true, - "isArchived": false, - "gboPackageTemplateId": "33610", - "tapConnectProductCode": null, - "productName": "HTM Regio Vrij DH73 Reductietarief", - "productDescription": "Voor een vast bedrag onbeperkt reizen met EBS, HTM en RET in het gekozen gebied in de regio Rotterdam Den Haag.", - "validityPeriod": { - "validityPeriodId": 3, - "fromInclusive": "2024-09-01T00:00:00.000+00:00", - "toInclusive": "2024-12-31T23:59:59.999+00:00" - }, - "productTranslations": [ - { - "language": "en", - "name": "HTM Regio Free DH73", - "description": "For a fixed amount unlimited travel with EBS, HTM and RET in the chosen area in the Rotterdam The Hague region." - } - ], - "productOwner": { - "productOwnerId": 1, - "name": "Corneel Verstoep", - "organization": "HTM" - }, - "marketSegments": [ - { - "marketSegmentId": 1, - "name": "B2C" - } - ], - "customerSegments": [ - { - "customerSegmentId": 5, - "name": "Student" - }, - { - "customerSegmentId": 6, - "name": "Ooievaarspas-gerechtigde" - } - ], - "allowedGboAgeProfiles": [ - { - "gboAgeProfileId": 2, - "name": "Kind (4 t/m 11 jaar)", - "ageFromInclusive": 4, - "ageUntilInclusive": 11 - }, - { - "gboAgeProfileId": 3, - "name": "Jongere (12 t/m 18 jaar)", - "ageFromInclusive": 12, - "ageUntilInclusive": 18 - } - ], - "productCategory": { - "productCategoryId": 2, - "isTravelProduct": true, - "name": "Afgekocht reisrecht" - }, - "requiredCustomerLevel": { - "requiredCustomerLevelId": 3, - "name": "profile" - }, - "requiredProducts": null, - "incompatibleProducts": [ - { - "incompatibleProductId": 4, - "productName": "HTM Regio Vrij DH73 Reductietarief", - "description": "Kan niet combineren met zichzelf" - } - ], - "mandatoryCustomerDataItems": [ - { - "mandatoryCustomerDataItemId": 4, - "customerDataItem": "emailAddress" - }, - { - "mandatoryCustomerDataItemId": 8, - "customerDataItem": "padBirthDate" - }, - ], - "requiredGboPersonalAttributes": [ - { - "requiredGboPersonalAttributeId": 1, - "name": "NAME" - }, - { - "requiredGboPersonalAttributeId": 2, - "name": "BIRTHDATE" - }, - { - "requiredGboPersonalAttributeId": 3, - "name": "PHOTO" - } - ], - "tokenTypes": [ - { - "tokenTypeId": 1, - "name": "EMV" - }, - { - "tokenTypeId": 2, - "name": "OVpas physical" - }, - { - "tokenTypeId": 3, - "name": "OVpas digital" - } - ], - "paymentMoment": { - "paymentMomentId": 1, - "name": "prepaid" - }, - "serviceOptions": null, - "validityDuration": "P1M", - "maxStartInFutureDuration": "P6W", - "isRenewable": true, - "sendInvoice": true, + "isRenewable": null, + "sendInvoice": null, "imageReference": "https://www.htm.nl/media/leif2leu/htm-logo-mobile.svg", "productPageUrl": "https://www.htm.nl/nog-onbekende-product-pagina", "termsUrl": "https://www.htm.nl/nog-onbekende-productvoorwaarden-pagina", @@ -2663,10 +2451,11 @@ components: description: >- Gives information on the choice that the customer has to make, to enable the touchpoint to proceed further "down the product-tree" by selecting (PATCH-ing) the correct product-variant. - LayerInfo is not a mandatory product-attribute, but it should always be present on all product for which - `parentProductId != null`. (LayerInfo makes no sense for top-level parents as there is always a single starting point). \ + LayerInfo is not a mandatory product-attribute, but it should always be present on all products for which + there are underlying products, i.e. for which `GET /products?parentProductId=...` returns a non-empty list. + When no LayerInfo is present, the touchpoint can conclude that the product is a final fulfillable product. \ - **PMT should ensure that all products in the same "product-branch" (same `parentProductId`) have the same `layerInfoId` + **PMT should ensure that all non-leaf-node products (i.e. products that have underlying products) have a `layerInfoId` referenced. If a product is found to be in violation of this rule, its attribtue `isValid` should be set to `false`.** required: - layerInfoId @@ -2682,12 +2471,12 @@ components: type: string description: >- Contains the JSON Key of the product-attribute that the customer has to make some - choice on (determined by PMT), so that te correct product-variant can be selected by the touchpoint. For some - decisions (like region), there is no product attribute, and thus `isCustomChoice` will be set - to `true`, and `choiceKey` can then be set to any string on which touchpoints can also trigger - behaviour if desired (think "region picker tool"). Therefore, reuse of choiceKeys should be + choice on (determined by PMT), so that te correct product-variant (one of the direct child-products) can be + selected by the touchpoint. For some decisions (like region), there is no product attribute, and thus + `isCustomChoice` will be set to `true`, and `choiceKey` can then be set to any string on which touchpoints + can also trigger behaviour if desired (think "region picker tool"). Therefore, reuse of `choiceKeys` should be the goal, so touchoints can keep their triggers simple and prevent duplication of - similar choiceKeys to trigger the same behaviour. + similar `choiceKeys` to trigger the same behaviour. choiceLabel: example: Kies voor een doorlopend abonnement of een enkele termijn type: string @@ -2699,12 +2488,10 @@ components: example: false type: boolean description: >- - Indicates if the choice is a custom choice. If `false`, the PMT should fill `choiceKey` with the - "differing attribute for this product-layer" and the user should not be able to override this. When - no single attribute can be pinpointed by PMT, the product will become invalid (`isValid == false`) until either - a situation with a single differing attribute is created, or if `isCustomChoice` is set to `true` - this would, - however, also mean that touchpoints should be notified of this, especially if the configured LayerInfo contains - a new, not previously used, `choiceKey`. + Indicates if the choice is a custom choice. If `false`, the PMT should validate that the `choiceKey` is a + differentiating attribute for the underlying product-variants. When the attribute denoted by the `choiceKey` is + the same for all underlying variants, PMT validation will fail and the product will become invalid (`isValid == false`) + until either the underlying products are updated, or a `LayerInfo` with `isCustomChoice == true` is configured. GboAgeProfileResponse: type: object required: