Fouten in kortingslogica kunnen checkout-totalen breken. Leer stapelregels, uitsluitingen en testbare patronen om dubbele kortingen en negatieve totalen te voorkomen.

Promoties lijken simpel totdat je ze in een echte checkout zet. Een winkelwagen verandert continu, maar kortingen worden vaak als losse regels geschreven. Die kloof is waar de meeste fouten in kortingslogica optreden.
Het lastige is dat één nieuwe regel overal totalen kan veranderen. Voeg “10% korting, maar niet op uitverkoopartikelen” toe en je moet beslissen wat “uitverkoop” betekent, wanneer het gecontroleerd wordt en op welk bedrag die 10% wordt toegepast. Als een andere promo ook dezelfde items raakt, doet volgorde ertoe, en volgorde verandert de prijs.
Veel teams vermengen ook wiskunde met businessregels. Een snelle fix zoals “beperk korting tot subtotal” wordt op drie plekken gekopieerd, en al snel krijg je verschillende antwoorden afhankelijk van waar het totaal wordt berekend (winkelwagenpagina, checkout, factuur, e-mail).
Hoog-risico-momenten zijn de keren dat je systeem prijzen herberekent:
Een klein voorbeeld: een klant voegt een bundle toe, past een “$20 off $100” code toe en verwijdert daarna één item. Als je code nog “herinnert” wat de oude subtotal was, kun je per ongeluk $20 korting geven op een winkelwagen van $85, of zelfs een negatief regelbedrag veroorzaken.
Aan het eind van dit artikel zou je in staat moeten zijn de meest voorkomende promo-fouten te voorkomen: dubbele kortingen, niet-overeenkomende totalen tussen schermen, negatieve totalen, kortingen op uitgesloten items en refunds die niet overeenkomen met wat de klant oorspronkelijk betaalde.
De meeste fouten in kortingslogica beginnen met één ontbrekende zin: welke kortingen mogen samen worden toegepast en in welke volgorde. Als je stapelregels niet in gewone taal kunt uitleggen, zal je winkelwagen uiteindelijk iets verrassends doen.
Definieer stapelen met simpele ja/nee-uitspraken. Bijvoorbeeld: “Één handmatige coupon per bestelling. Automatische promoties kunnen nog steeds gelden tenzij de coupon ze blokkeert.” Die ene regel voorkomt willekeurige combinaties die leiden tot dubbele kortingen.
Scheid vroeg item-niveau kortingen van order-niveau kortingen. Item-niveau regels veranderen de prijs van specifieke producten (zoals 20% korting op schoenen). Order-niveau regels veranderen de totaalprijs (zoals $10 korting op de hele winkelwagen). Het door elkaar gebruiken zonder structuur is hoe totalen tussen productpagina, winkelwagen en checkout gaan afwijken.
Bepaal wat “beste deal” betekent voordat je gaat coderen. Veel teams kiezen “maximale besparing”, maar dat kan prijsvloeren breken. Je hebt mogelijk ook regels nodig zoals “nooit beneden kostprijs korten” of “verzendkosten nooit negatief maken.” Kies één duidelijke regelwinnende strategie zodat de engine niet hoeft te gokken.
Een eenvoudige prioriteitsvolgorde houdt conflicten voorspelbaar:
Voorbeeld: een winkelwagen heeft een automatische 10% korting op alle items en daarnaast een ingevoerde coupon van $15 voor bestellingen boven $100. Als je prioriteit zegt dat automatische promoties eerst komen, kun je duidelijk beantwoorden: gebruikt de $100-drempel het subtotal vóór korting of het verlaagde subtotal? Schrijf het op en hou het overal consistent.
Zodra deze keuzes zijn vastgelegd, worden je stapelregels testbare regels in plaats van verborgen gedrag. Dat is de snelste manier om later couponproblemen te vermijden.
Veel fouten in kortingslogica ontstaan wanneer kortingen verspreid in if-else-blokken door de checkout-code zitten. Een veiligere aanpak is om elke promo als data te behandelen met een duidelijk type, omvang en limieten. Dan wordt je winkelwagen-wiskunde een kleine, voorspelbare evaluator.
Begin met het benoemen van het kortings-type, niet van de marketingnaam. De meeste promoties passen in een paar vormen: procentuele korting, vast bedrag korting, gratis item (of buy X get Y) en gratis verzending. Als je een promo kunt uitdrukken met één van deze types, voorkom je special cases die lastig te testen zijn.
Maak daarna de scope expliciet. Dezelfde procentuele korting gedraagt zich heel anders afhankelijk van wat het target. Definieer of het van toepassing is op de hele bestelling, een categorie, een product, een enkele regelpost, of verzending. Als de scope onduidelijk is, ga je per ongeluk het verkeerde subtotal korten of twee keer korten.
Leg constraints vast als velden, niet als codecommentaar. Veel voorkomende zijn minimum besteding, alleen eerste bestelling en datum bereik. Noteer ook hoe het zich moet gedragen bij bestaande uitverkoopprijzen: stapelen, toepassen op de oorspronkelijke prijs of uitverkoop-items uitsluiten.
Een compact regelschema kan bevatten:
Voeg tenslotte prijsvloeren toe waar de engine zich altijd aan moet houden: totalen mogen nooit onder nul gaan, en als je bedrijf dat nodig heeft, mogen items nooit onder kostprijs of een gedefinieerde minimumprijs komen. Als je dit ingebouwd hebt, voorkom je negatieve totalen en ongemakkelijke “wij betalen de klant”-randgevallen.
Als je een prototype van een discount-engine maakt in Koder.ai, houd deze velden zichtbaar in je planningsmodus zodat de evaluator eenvoudig en testbaar blijft als je meer promoties toevoegt.
Veel fouten ontstaan wanneer geschiktheidschecks en rekenwerk door elkaar lopen. Een veiliger patroon is tweefasig: bepaal eerst wat kan gelden, bereken daarna pas bedragen. Die scheiding houdt regels leesbaar en maakt slechte toestanden (zoals negatieve totalen) eenvoudiger te voorkomen.
Gebruik elke keer dezelfde volgorde, zelfs als promoties in een andere volgorde binnenkomen via UI of API. Determinisme is belangrijk omdat het van “waarom veranderde deze winkelwagen?” een vraag maakt die je kunt beantwoorden.
Een simpel flow die goed werkt:
Als je promos toepast, sla dan niet alleen een enkel “kortingtotaal” op. Houd een breakdown per regelpost en voor de bestelling zodat je totalen kunt reconciliëren en uitleggen.
Leg op z’n minst vast:
Voorbeeld: een winkelwagen heeft twee items, eentje is al in de uitverkoop. Fase 1 markeert de code als alleen geldig voor het full-price item. Fase 2 past dan 10% toe op die regel, laat de uitverkoopregel ongemoeid en herberekent ordertotalen vanuit de regel-breakdown zodat je niet per ongeluk dubbel kort.
Veel fouten ontstaan wanneer uitsluitingen verborgen zitten in special-case takken zoals “als code X, sla Y over.” Het werkt voor één promo, maar breekt zodra de volgende promo arriveert.
Een veiliger patroon is: hou één enkele evaluatiestroom en maak uitsluitingen een set checks die een promo-combinatie kunnen afwijzen voordat je geld gaat berekenen. Zo halverwege toegepaste kortingen bestaan niet.
In plaats van hardcoded gedrag, geef elke promo een klein, expliciet “compatibiliteitsprofiel.” Bijvoorbeeld: promo-type (coupon vs automatische sale), scope (items, verzending, bestelling) en combinatieregels.
Ondersteun zowel:
Het sleutelidee is dat je engine dezelfde vragen stelt voor elke promo en dan beslist of de set valide is.
Automatische uitverkopen worden vaak eerst toegepast, daarna komt er een coupon en die overschrijft stilletjes. Bepaal vooraf wat er moet gebeuren:
Kies per promo één van deze opties en codeer het als een check, niet als een alternatieve berekeningsroute.
Een praktische manier om verrassingen te vermijden is symmetrie te valideren. Als “WELCOME10 niet combineert met FREESHIP” bedoeld is als wederkerig, codeer het dan zodat beide richtingen blokkeren. Als het niet wederkerig is, maak dat dan intentioneel en zichtbaar in de data.
Voorbeeld: er loopt een site-brede automatische 15% uitverkoop. Een klant voert een 20% coupon in die bedoeld is voor full-price items. Je checks moeten uitverkoopitems voor die coupon afwijzen voordat je totalen berekent, in plaats van ze eerst af te korten en later te proberen de cijfers te repareren.
Als je je discountregels bouwt in een platform zoals Koder.ai, houd deze checks als een aparte, testbare laag zodat je regels kunt wijzigen zonder de wiskunde te herprogrammeren.
De meeste kortingsdisputen gaan niet over de kopkorting. Ze gebeuren wanneer dezelfde winkelwagen op twee iets verschillende manieren wordt berekend en de klant dan één bedrag in de winkelwagen ziet en een ander bij de checkout.
Begin met het vastzetten van je volgorde van bewerkingen. Bepaal en documenteer of item-niveau kortingen gebeuren vóór order-niveau kortingen en waar verzending past. Een veelgebruikte regel is: eerst itemkortingen, daarna orderkorting op het resterende subtotal, daarna verzendkortingen. Wat je ook kiest, gebruik exact dezelfde volgorde overal waar je een totaal toont.
Belasting is de volgende valkuil. Als je prijzen inclusief belasting zijn, vermindert een korting ook het belastingdeel. Als prijzen exclusief belasting zijn, wordt belasting berekend ná kortingen. Het mixen van deze modellen in verschillende delen van de flow is een klassieke fout omdat twee correcte berekeningen toch van elkaar kunnen afwijken als ze verschillende belastingbasissen aannemen.
Afrondingsproblemen lijken klein maar veroorzaken veel supporttickets. Kies of je afrondt per regelpost (elk SKU na korting) of alleen op orderniveau en houd je aan de valuta-precisie. Bij procentuele coupons kan regel-afronding enkele centen afwijken vergeleken met order-afronding, zeker bij veel goedkope items.
Hier zijn randgevallen die het waard zijn expliciet te behandelen:
Een concreet voorbeeld: een 10% order-coupon plus gratis verzending boven $50. Als de coupon vóór de drempelcheck wordt toegepast, kan het verlaagde subtotal onder $50 komen en stopt gratis verzending. Kies één interpretatie, codeer het als regel en maak het consistent in winkelwagen, checkout en refunds.
De meeste fouten in kortingslogica verschijnen wanneer de winkelwagen door meer dan één pad wordt geëvalueerd. Een promo kan op regulijniveau worden toegepast op één plek en opnieuw op orderniveau op een andere plek, en beide lijken “correct” los van elkaar.
Hier zijn de bugs die het vaakst voorkomen en de gebruikelijke oorzaak achter elk:
Een concreet voorbeeld: een winkelwagen heeft twee items, één eligible en één uitgesloten. Als de engine het “eligible subtotal” correct berekent voor de procentuele promo, maar later een vast-bedrag korting aftrekt van het volledige ordertotaal, krijgt het uitgesloten item effectief toch korting.
Het veiligste patroon is om elke promo te berekenen tegen een expliciet “eligible amount” en een begrensde aanpassing terug te geven (nooit onder nul), plus een duidelijke trace van wat het raakte. Als je je discount-engine genereert in een tool zoals Koder.ai, laat deze trace als platte data uitkomen zodat je tests precies kunnen asserten welke regels eligible waren en welk subtotal gebruikt werd.
Veel fouten duiken op omdat tests alleen het eindtotaal controleren. Een goede suite test zowel geschiktheid (hoort deze promo te gelden?) als wiskunde (hoeveel moet hij afhalen?), met een leesbare breakdown die je in de loop van de tijd kunt vergelijken.
Begin met unit-tests die één regel tegelijk isoleren. Houd de input klein en breid uit naar volledige winkelwagentoestanden.
Als je dekking hebt, voeg dan een paar “altijd waar” checks toe. Deze vangen de rare gevallen die je niet met de hand bedacht hebt.
Stel je een winkelwagen met 2 items voor: een T-shirt van $40 (eligible) en een cadeaukaart van $30 (uitgesloten). Verzendkosten $7. Een promo is “20% korting op kleding, max $15”, plus een tweede promo “$10 korting bij orders boven $50” die niet samen mag met procentuele kortingen.
Je scenario-test zou moeten asserten welke promo wint (prioriteit), bevestigen dat de cadeaukaart is uitgesloten en verifiëren de exacte toewijzing: 20% van $40 is $8, verzending blijft ongemoeid, eindtotaal klopt. Sla die breakdown op als een gouden snapshot zodat latere refactors niet stilletjes veranderen welke promo geldt of beginnen uitsluitingen te negeren.
Voordat je een nieuwe promo live zet, doe nog één laatste ronde met een checklist die de fouten vangt waar klanten meteen over klagen: rare totalen, verwarrende boodschappen en refunds die niet optellen. Deze checks helpen ook om de meeste fouten te voorkomen omdat ze je regels dwingen overal hetzelfde te gedragen.
Draai deze checks tegen een kleine set “bekend lastige” winkelwagens (één item, veel items, gemengde belastingtarieven, verzending en één regel met hoge hoeveelheid). Sla de winkelwagens op zodat je ze opnieuw kunt draaien elke keer dat je prijslogica wijzigt.
Als je je discountregels in een generator zoals Koder.ai bouwt, voeg deze gevallen toe als geautomatiseerde tests naast de regedefinities. Het doel is simpel: elke toekomstige promo moet snel falen in tests in plaats van te falen in de winkelwagen van een klant.
Hier is een kleine winkelwagen die de meeste fouten blootlegt zonder ingewikkeld te worden.
Stel deze regels voor (schrijf ze exact zo op in je systeem):
Cart:
| Line | Price | Notes |
|---|---|---|
| Item A | $60 | full-price, eligible |
| Item B | $40 | full-price, eligible |
| Item C | $30 | sale item, excluded |
| Shipping | $8 | fee |
Promos:
Controleer couponminimum: eligible merchandise vóór kortingen is $60 + $40 = $100, dus de coupon kan gelden.
Pas Promo 1 toe (10% korting op eligible items): $100 x 10% = $10 korting. Eligible subtotal wordt $90.
Pas Promo 2 toe ($15 off): cap is $90, dus de volledige $15 geldt. Nieuw eligible subtotal: $75.
Totalen:
Verander nu één ding: de klant verwijdert Item B ($40). Eligible merchandise wordt $60, dus de $15 coupon faalt de minimum spend check. Alleen de automatische 10% promo blijft: Item A wordt $54, merchandise is $54 + $30 = $84, en het eindtotaal wordt $99.36. Dit is het soort “kleine wijziging” dat vaak winkelwagens breekt als geschiktheid en volgorde niet expliciet zijn.
De snelste manier om fouten te vermijden is promos te behandelen als productregels, niet als “een beetje wiskunde in checkout.” Voordat je live gaat, schrijf een korte specificatie die iedereen in het team kan lezen en waarover men het eens is.
Neem vier dingen op, in gewone taal:
Na release, monitor totalen zoals je errors monitort. Een kortingsbug ziet er vaak uit als een valide order totdat finance hem ziet.
Zet monitoring op die orders met ongewone patronen markeert, zoals near-zero totalen, negatieve totalen, kortingen groter dan het subtotal, of plotselinge pieken in “100% off” orders. Route alerts naar dezelfde plek als je checkout-errors en houd een kort draaiboek klaar voor hoe je een promo veilig uitschakelt.
Om nieuwe promos toe te voegen zonder regressies, gebruik een herhaalbare workflow: werk eerst de specificatie bij, codeer de regel als data (niet als branching code), voeg tests toe voor een paar normale winkelwagens plus één of twee lastige randgevallen, en draai de volledige discount-testsuite voordat je merge.
Als je sneller wilt implementeren en itereren, kun je promo-engine flows prototypen in Koder.ai met planningsmodus, en vervolgens snapshots en rollback gebruiken terwijl je tests verfijnt. Zo kun je snel regelaanpassingen proberen zonder een bekende goede versie te verliezen.