← cd ../
// notities

Een prijscalculator voor drukwerk met live leverdatum, zonder verzoek naar de backend

Hoe de calculators van Denia Print een prijs en een leverdatum met afteltimer tonen, in de browser berekend uit gegevens die al op de pagina staan, en hoe de server elke prijs opnieuw controleert.

gepubliceerd
auteur
Nicky Mitnick

Het probleem

Wie drukwerk bestelt, heeft eerst twee vragen: wat kost het en wanneer heb ik het. Op Denia Print wilde ik dat je op beide een antwoord krijgt terwijl je door de opties klikt, op een statische site, zonder laadicoon na elke keuze.

De prijs is de makkelijke helft. De leverdatum is lastiger. Die hangt af van de productiedagen van precies de combinatie die je kiest, van het dagelijkse besteltijdstip van de leverancier, van feestdagen in twee landen en van hoe laat het nu is.

De aanpak

Prijs. De site is statisch Astro op Cloudflare Pages. Voor de meeste producten leest de calculator een prijstabel die in de site is meegebouwd. Die tabel wordt elke week opnieuw opgebouwd uit de API van de leverancier en uitgerold. Een oplage of papiersoort kiezen kost dus geen enkel verzoek. Spandoeken hebben een prijs per maat en vragen daarom een klein endpoint om een live prijs. De uitgebreide catalogus doet hetzelfde, met een antwoord dat per variant 12 uur aan de edge in de cache staat.

Leverdatum. De calculator toont een regel als “Bestel vóór 11:30 (nog 2 u 14 min) en ontvang het wo 7 okt tot do 8 okt”. Die wordt in de browser berekend uit vier dingen:

  • de productiedagen van de gekozen combinatie, die al met de prijsgegevens meekomen
  • het besteltijdstip van de leverancier: 11:30 Amsterdamse tijd, maandag tot en met vrijdag
  • één werkdag voor mijn eigen afhandeling, omdat ik het bestand controleer voordat het naar de leverancier gaat
  • een lijst met feestdagen: de Nederlandse voor de productie, de Spaanse landelijke en die van de Comunitat Valenciana voor de bezorging in Dénia en de Marina Alta

Het besteltijdstip wordt in de Amsterdamse tijdzone berekend, zodat de browser zomer- en wintertijd afhandelt, en het wordt getoond in de tijdzone van de bezoeker. De regel wordt elke 30 seconden opnieuw getekend, en ook als het tabblad weer zichtbaar wordt of het vakje voor ophalen in het bestelformulier verandert. Haal je op in Dénia, dan staat er “beschikbaar vanaf” de latere datum. Schermlezers krijgen alleen de datum te horen als die verandert, nooit de lopende afteltimer.

Ik heb de regel geijkt op de minimale leverdatum van de leverancier zelf, voor 40 combinaties van product en snelheid. Besteldag plus productiedagen klopte 21 keer, viel 17 keer later uit en 2 keer eerder. Met mijn dag afhandeling erbovenop zit de periode die ik toon in 39 van de 40 gevallen aan de late kant. Een paar producten lopen trager dan hun productiedagen doen vermoeden. Die krijgen extra werkdagen uit een kleine tabel.

De datum gaat mee in de bestelregels en in de mails, zodat de klant en ik naar dezelfde belofte kijken.

De prijs opnieuw controleren. Een prijs die de browser heeft uitgerekend, kan de server niet vertrouwen. De winkelwagen staat in localStorage met maximaal 20 regels. Is opslag geblokkeerd, dan werkt de site gewoon per product. Voordat de winkelwagen wordt verstuurd, vraagt de pagina de prijzen opnieuw op bij dezelfde bronnen als de calculators. Een gewijzigde prijs of een product dat niet meer te koop is, wordt gemarkeerd en blokkeert het versturen. Er wordt nooit stil iets aangepast.

Daarna doet de server het voor elke regel nog een keer: tabelproducten tegen de prijstabel, spandoeken en catalogusartikelen tegen een live offerte van de leverancier. Een regel die niet klopt, krijgt een markering, en het dashboard houdt de bestelling bij de leverancier voor die regel tegen tot iemand ernaar heeft gekeken. Bij de uitgebreide catalogus kent de browser alleen de posities van de opties. De artikelcode van de leverancier blijft op de server.

De afwegingen

  • De datum is een schatting, en dat laat ik zien met een periode. Ik zit liever aan de late kant: elke getelde dag moet in beide landen een werkdag zijn. Een bestelling die een dag eerder komt is prima, andersom niet.
  • De feestdagenlijst is handwerk, één keer per jaar. Een test faalt twee maanden voordat de lijst op is, dus vergeten kan niet. Een ontbrekend jaar zou data rond die feestdagen hooguit één dag te optimistisch maken.
  • Het besteltijdstip staat vast in de code. Verschuift de leverancier het, dan moet ik mee. De ijking moet af en toe opnieuw.
  • De afteltimer gebruikt de klok van de bezoeker. Staat de klok van het apparaat verkeerd, dan klopt de timer niet.
  • Live offertes zijn begrensd. Hooguit 10 regels per bestelling krijgen een live offerte van de leverancier. De rest wordt gemarkeerd voor een controle met de hand, zodat één winkelwagen niet uitwaaiert in 20 aanroepen bij de leverancier.

Meer over de winkel staat op de projectpagina van Denia Print.