Configurator

Hoe de configurator werkt

Concepten achter configureerbare producten, het schema en het prijsmodel.

Bekijk als Markdown

Met configureerbare producten kan een merchant artikelen verkopen die geprijsd worden op basis van afmetingen en opties in plaats van een vaste prijs: veranda's geprijsd op breedte en diepte, panelen op maat, meubels op bestelling met keuzes voor materiaal en accessoires. De storefront-flow is:

  1. Haal het product op met GET /v1/api/commerce/products/{id}. Een configureerbaar product heeft "capability": "made_to_measure". Bied de configurator alleen aan zolang capability_active true is.
  2. Haal het configuratieschema op met GET /v1/api/commerce/configurator/products/{id}/schema en render daaruit een configurator-UI.
  3. Stuur bij elke wijziging in de selectie van de koper de actuele selectie naar POST /v1/api/commerce/configurator/products/{id}/quote om de live prijs met een regel-voor-regel uitsplitsing op te halen.

Beide configurator-endpoints gebruiken dezelfde authenticatie als de catalogus-endpoints: een tenant-API-key die je meestuurt als Authorization: Bearer {api_key}. Een key met de scope catalog:read of commerce:read wordt geaccepteerd. De gate is de configurator-module: heeft de winkel die niet ingeschakeld, dan antwoorden beide endpoints 403 {"error":"Module not enabled: configurator"} en rapporteren made-to-measure-producten capability_active: false. Het quote-endpoint is een pure berekening; het maakt geen cart of order aan en heeft daarom geen schrijfscope nodig.

Bouwstenen

Een configureerbaar product wordt beschreven door vier soorten entiteiten. Alle ID's zijn UUID's.

Dimensies

Een dimensie is een numerieke invoer die de koper moet opgeven, bijvoorbeeld breedte en diepte. Elke dimensie heeft een key (de request-key die je in quote-calls gebruikt), een weergave-label, een weergave-unit als string (bijvoorbeeld "cm") en een integer min en max. Dimensiewaarden zijn gehele getallen. Dimensies zijn geordend op positie; die volgorde bepaalt hoe dimensiewaarden op de assen van de prijsmatrix worden afgebeeld (de eerste dimensie is dim1, de tweede is dim2).

Een dimensie kan constraints hebben: aanscherpingen van het toegestane bereik per keuze. Wanneer de koper een keuze selecteert die een constraint op een dimensie heeft, wordt de effectieve min van de dimensie verhoogd naar de min van de constraint (als die hoger is) en de effectieve max verlaagd naar de max van de constraint (als die lager is). Constraints maken het bereik alleen ooit krapper, nooit ruimer.

Optiegroepen en keuzes

Opties zijn georganiseerd in groepen. Een groep heeft een type van single (de koper mag maximaal één keuze uit de groep kiezen) of multi (elk aantal), en een required-vlag (er moet minstens één keuze uit de groep geselecteerd zijn). Zowel groepen als keuzes zijn geordend op positie.

Elke keuze kan de prijs beïnvloeden via een delta:

delta_typeBetekenis van delta_value
fixedBedrag in minor units (centen), eenmalig opgeteld.
per_areaTarief in minor units per vierkante meter. De delta is delta_value maal de oppervlakte, waarbij de oppervlakte dim1 * dim2 / 10000 vierkante meter is (afmetingen worden ingevoerd in cm). Vereist dat het product precies twee dimensies heeft; anders mislukt de quote met een 422.
percentPercentage van de basisprijs, opgeslagen maal 100: een delta_value van 1050 betekent 10,50 procent. De delta is base * delta_value / 10000.
percent_of_totalZelfde codering, maar toegepast op het subtotaal na alle andere delta's (zie de prijsberekening hieronder).

Keuzes hebben daarnaast is_default (een UI-hint voor de initiële selectie), een images-array en een requires_quote-vlag. Wanneer requires_quote true is, hoort de storefront de koper naar een handmatige offerteaanvraag te leiden in plaats van naar checkout; het quote-endpoint prijst de configuratie nog steeds, de vlag is informatief.

Keuzeregels

Regels leggen relaties tussen keuzes over groepen heen:

  • requires: de keuze is alleen geldig wanneer minstens één van de vereiste targets geselecteerd is. Targets worden gegroepeerd per optiegroep van de target: binnen één targetgroep is de relatie OR (elke willekeurige target voldoet), tussen targetgroepen is het AND (aan de eis van elke groep moet worden voldaan).
  • excludes: de keuze kan niet gecombineerd worden met de target-keuze.

Het schema stelt de requires- en excludes-arrays van elke keuze beschikbaar als lijsten van keuze-ID's, zodat de UI ongeldige combinaties vooraf kan uitschakelen. Het quote-endpoint handhaaft dezelfde regels server-side en retourneert bij een overtreding een 422 met een leesbare melding. Schema en quote zijn het altijd eens over welke keuzes bestaan: een keuze waarvan de requires niet vervuld kan worden door de andere gepubliceerde keuzes wordt helemaal niet gepubliceerd, dus het schema biedt nooit een keuze aan die het quote-endpoint zou afwijzen. Zie de zichtbaarheidsgaranties hieronder.

Prijsmatrices

Wanneer een product dimensies heeft, komt de basisprijs uit een prijsmatrix: een benoemde 2D-opzoektabel van dimensiebereiken naar prijzen. Elke matrix heeft een set conditions: keuze-ID's die allemaal geselecteerd moeten zijn om de matrix in aanmerking te laten komen. Een matrix zonder conditions komt altijd in aanmerking.

Matrixselectie: van alle matrices die in aanmerking komen (die waarvan de volledige set conditions in de selectie van de koper zit), wint de matrix met de meeste conditions. Bij gelijkspel beslist de aanmaakvolgorde (oudste eerst). Binnen de winnende matrix levert de rij waarvan de dim1- en dim2-bereiken de dimensiewaarden van de koper bevatten de basisprijs. Dimensiewaarden worden op dim1 en dim2 afgebeeld in volgorde van dimensiepositie.

Als geen enkele matrix in aanmerking komt, of de winnende matrix geen rij heeft die de dimensiewaarden dekt, mislukt de quote met een 422 not_priceable-fout. Een product zonder dimensies slaat matrices volledig over en gebruikt zijn eigen price_amount als basis; als die null is, is de quote eveneens not_priceable.

Prijsberekening stap voor stap

Bij een geldige selectie wordt het totaal berekend in twee passes, volledig in integer minor units, met PHP_ROUND_HALF_UP-afronding naar hele minor units bij elke percentage- of oppervlaktestap:

  1. Bepaal de basisprijs (matrixrij of productprijs). De uitsplitsing begint met een regel met label Base.
  2. Pass 1, in volgorde van groep- en keuzepositie: elke geselecteerde keuze die niet percent_of_total is, telt zijn delta op (fixed, per_area, of percent van de basis). Elke keuze voegt één uitsplitsingsregel toe met label {Group name}: {Choice name}, inclusief keuzes met delta nul, die verschijnen met bedrag 0.
  3. Pass 2: elke geselecteerde percent_of_total-keuze telt pass-1 subtotaal * delta_value / 10000 op, elk onafhankelijk berekend tegen hetzelfde subtotaal, zodat meerdere percent_of_total-keuzes elkaar niet versterken. Elke keuze voegt zijn eigen uitsplitsingsregel toe.

De total in de response is gelijk aan de basis plus alle delta's. De valuta is de valuta van het product.

Samenvatting van geld en eenheden

  • Alle bedragen zijn integers in minor units (centen), met de ISO-valutacode van het product.
  • Percentagewaarden worden opgeslagen maal 100: deel delta_value door 10000 voor de fractie.
  • per_area-tarieven zijn minor units per vierkante meter; afmetingen worden ingevoerd in centimeters en de oppervlakte is dim1 * dim2 / 10000 vierkante meter.
  • Dimensiewaarden in quote-requests en cart-regels moeten gehele getallen zijn, in de eenheid van de dimensie. 120 en 120.0 worden geaccepteerd; 120.5 wordt geweigerd.

Zichtbaarheidsgaranties

Het schema toont alleen beschikbare keuzes. Soft-deleted en gedeactiveerde keuzes worden eruit gefilterd, net als elke keuze waarvan de requires-regel niet langer vervuld kan worden door de keuzes die overblijven. Dat filteren werkt door: het achterhouden van één keuze kan de eis van een andere keuze onvervulbaar maken, en het schema is uitgefilterd voordat het wordt geretourneerd. Dimensieconstraints en requires- en excludes-lijsten worden teruggesnoeid tot de op dat moment beschikbare keuze-ID's, en een prijsmatrix met een condition op een niet-beschikbare keuze wordt in zijn geheel uit price_matrices weggelaten in plaats van getoond met een ingekorte conditielijst, omdat zo'n matrix nooit in aanmerking kan komen. Daardoor is elk keuze-ID dat ergens in het schema voorkomt binnen datzelfde schema oplosbaar en kan elke keuze die het schema toont geselecteerd en geprijsd worden.