feature/OVPAY-2007-Products-LayerInfo #24

Merged
maxmartens merged 7 commits from feature/OVPAY-2007-Products-LayerInfo into develop 2025-08-28 09:26:23 +00:00
Showing only changes of commit 7de54cbd86 - Show all commits

View File

@ -778,6 +778,7 @@ paths:
{ {
"productId": 1, "productId": 1,
"parentProductId": null, "parentProductId": null,
"layerInfo": null,
"fikoArticleNumber": "1234", "fikoArticleNumber": "1234",
"isValid": true, "isValid": true,
"isArchived": false, "isArchived": false,
@ -839,7 +840,7 @@ paths:
}, },
"requiredCustomerLevel": { "requiredCustomerLevel": {
"requiredCustomerLevelId": 1, "requiredCustomerLevelId": 1,
"name": "anonymous" "name": "guest"
}, },
"requiredProducts": null, "requiredProducts": null,
"incompatibleProducts": [ "incompatibleProducts": [
@ -952,6 +953,7 @@ paths:
{ {
"productId": 2, "productId": 2,
"parentProductId": null, "parentProductId": null,
"layerInfo": null,
"fikoArticleNumber": "1234", "fikoArticleNumber": "1234",
"isValid": true, "isValid": true,
"isArchived": false, "isArchived": false,
@ -1013,7 +1015,7 @@ paths:
}, },
"requiredCustomerLevel": { "requiredCustomerLevel": {
"requiredCustomerLevelId": 1, "requiredCustomerLevelId": 1,
"name": "anonymous" "name": "guest"
}, },
"requiredProducts": null, "requiredProducts": null,
"incompatibleProducts": [ "incompatibleProducts": [
@ -1176,17 +1178,18 @@ paths:
"timestamp": "2024-09-03T08:38:24.000+00:00" "timestamp": "2024-09-03T08:38:24.000+00:00"
} }
] ]
} }
getDetailsGboPadProduct: getDetailsGboPadProduct:
summary: GBO product (PAD required, renewable, serviceOptions, forbiddenPaymentMethods) summary: GBO product (PAD required, renewable, serviceOptions, forbiddenPaymentMethods)
value: value:
{ {
"productId": 3, "productId": 3,
"parentProductId": null, "parentProductId": null,
"layerInfo": null,
"fikoArticleNumber": "1234", "fikoArticleNumber": "1234",
"isValid": true, "isValid": true,
"isArchived": false, "isArchived": false,
"gboPackageTemplateId": "35301", "gboPackageTemplateId": "33610",
"tapConnectProductCode": null, "tapConnectProductCode": null,
"productName": "HTM Regio Vrij DH73", "productName": "HTM Regio Vrij DH73",
"productDescription": "Voor een vast bedrag onbeperkt reizen met EBS, HTM en RET in het gekozen gebied in de regio Rotterdam Den Haag.", "productDescription": "Voor een vast bedrag onbeperkt reizen met EBS, HTM en RET in het gekozen gebied in de regio Rotterdam Den Haag.",
@ -1223,6 +1226,237 @@ paths:
"name": "Ooievaarspas-gerechtigde" "name": "Ooievaarspas-gerechtigde"
} }
], ],
"allowedGboAgeProfiles": [
{
"gboAgeProfileId": 2,
"name": "Kind (4 t/m 11 jaar)",
"ageFromInclusive": 4,
"ageToInclusive": 11
},
{
"gboAgeProfileId": 3,
"name": "Jongere (12 t/m 18 jaar)",
"ageFromInclusive": 12,
"ageToInclusive": 18
},
{
"gboAgeProfileId": 4,
"name": "Volwassene (19 t/m 64 jaar)",
"ageFromInclusive": 19,
"ageToInclusive": 64
},
{
"gboAgeProfileId": 5,
"name": "Oudere (65 jaar of ouder)",
"ageFromInclusive": 65,
"ageToInclusive": 999
}
],
"productCategory": {
"productCategoryId": 3,
"isTravelProduct": true,
"name": "Afgekocht reisrecht"
},
"requiredCustomerLevel": {
"requiredCustomerLevelId": 3,
"name": "profile"
},
"requiredProducts": null,
"incompatibleProducts": [
{
"incompatibleProductId": 3,
"productName": "HTM Regio Vrij DH73",
"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": [
{
"serviceOptionId": 1,
"action": "cancellableTermAhead",
"description": "Per termijn vooruit opzegbaar"
}
],
"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": 1,
"name": "Credit Card",
"issuer": "American Express"
}
],
"sellingPrices": [
{
"sellingPriceId": 5,
"amountExclTax": 5413,
"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": 0,
"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,
"layerInfoId": {
"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": 6,
"name": "Student"
},
{
"customerSegmentId": 7,
"name": "Ooievaarspas-gerechtigde"
}
],
"allowedGboAgeProfiles": [ "allowedGboAgeProfiles": [
{ {
"gboAgeProfileId": 2, "gboAgeProfileId": 2,
@ -1244,33 +1478,25 @@ paths:
}, },
"requiredCustomerLevel": { "requiredCustomerLevel": {
"requiredCustomerLevelId": 3, "requiredCustomerLevelId": 3,
"name": "account" "name": "profile"
}, },
"requiredProducts": null, "requiredProducts": null,
"incompatibleProducts": [ "incompatibleProducts": [
{ {
"incompatibleProductId": 3, "incompatibleProductId": 4,
"productName": "HTM Regio Vrij DH73", "productName": "HTM Regio Vrij DH73 Reductietarief",
"description": "Kan niet combineren met zichzelf" "description": "Kan niet combineren met zichzelf"
} }
], ],
"mandatoryCustomerDataItems": [ "mandatoryCustomerDataItems": [
{
"mandatoryCustomerDataItemId": 3,
"customerDataItem": "dateOfBirth"
},
{ {
"mandatoryCustomerDataItemId": 4, "mandatoryCustomerDataItemId": 4,
"customerDataItem": "emailAddress" "customerDataItem": "emailAddress"
}, },
{ {
"mandatoryCustomerDataItemId": 5, "mandatoryCustomerDataItemId": 8,
"customerDataItem": "ovPayToken" "customerDataItem": "padBirthDate"
}, },
{
"mandatoryCustomerDataItemId": 6,
"customerDataItem": "directDebitMandate"
}
], ],
"requiredGboPersonalAttributes": [ "requiredGboPersonalAttributes": [
{ {
@ -1981,6 +2207,53 @@ paths:
$ref: '#/components/schemas/500Response' $ref: '#/components/schemas/500Response'
components: components:
schemas: schemas:
LayerInfoResponse:
type: object
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). \
**PMT should ensure that all products in the same "product-branch" (same `parentProductId`) have the same `layerInfoId`
referenced. If a product is found to be in violation of this rule, its attribtue `isValid` should be set to `false`.**
required:
- layerInfoId
- choiceKey
- choiceLabel
- isCustomChoice
properties:
layerInfoId:
example: 1
type: integer
choiceKey:
example: isRenewable
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
the goal, so touchoints can keep their triggers simple and prevent duplication of
similar choiceKeys to trigger the same behaviour.
choiceLabel:
example: Kies voor een doorlopend abonnement of een enkele termijn
type: string
description: >-
Contains a human-readable label for the choice that the customer has to make - this label
should be something that is easy to understand for the customer. Only one label (and thus, one language)
is supported; label translations should be handled by the touchpoint.
isCustomChoice:
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`.
GboAgeProfileResponse: GboAgeProfileResponse:
type: object type: object
required: required:
@ -2246,6 +2519,8 @@ components:
parentProductId: parentProductId:
type: integer type: integer
example: 1 example: 1
layerInfo:
$ref: '#/components/schemas/LayerInfoResponse'
fikoArticleNumber: fikoArticleNumber:
type: string type: string
description: The article number of the product in FIKO description: The article number of the product in FIKO
@ -2367,7 +2642,7 @@ components:
example: 1 example: 1
name: name:
type: string type: string
example: anonymous example: guest
requiredProducts: requiredProducts:
type: array type: array
items: items:
@ -2599,6 +2874,10 @@ components:
type: integer type: integer
description: The ID of the parent product (if any) description: The ID of the parent product (if any)
example: 1 example: 1
layerInfoId:
type: integer
description: Only relevant when `parentProductId != null`; the ID of the layerInfo reference, giving information on why this layer of product-variants exists (PMT should enforce that this is filled for all products for which `parentProductId != null`)
example: 1
fikoArticleNumber: fikoArticleNumber:
type: string type: string
description: The article number of the product in FIKO description: The article number of the product in FIKO
@ -2972,6 +3251,10 @@ components:
type: integer type: integer
description: The ID of the parent product (if any) description: The ID of the parent product (if any)
example: 1 example: 1
layerInfoId:
type: integer
description: Only relevant when `parentProductId != null`; the ID of the layerInfo reference, giving information on why this layer of product-variants exists (PMT should enforce that this is filled for all products for which `parentProductId != null`)
example: 1
fikoArticleNumber: fikoArticleNumber:
type: string type: string
description: The article number of the product in FIKO description: The article number of the product in FIKO