Přeskočit na obsah

Sleva se ztratí, když se částka pro bránu skládá znovu z položek

import { Aside } from ‘@astrojs/starlight/components’;

Zákazník s věrnostní slevou zaplatí na platební bráně plnou cenu bez slevy. Objednávka v DB má správný total (se slevou), platba na bráně je vyšší — účetní pak „platbu nevidí”, protože ji hledá podle částky objednávky, která na bráně neexistuje. Projeví se jen u objednávek se slevou, takže bug dlouho uniká (většina objednávek slevu nemá).

Kód pro start platby skládal Total znovu ze zdrojových položek:

// PŘED — sleva se ztratí
let total = items.reduce((s, it) => s + it.ItemTotal, 0);
if (shipping > 0) total += shipping;
// order.total = subtotal - discount + shipping ← discount nikde

Objednávka přitom měla discount_amount uložený a promítnutý do total. Stejný vzor byl na dvou místech: v checkoutu i v „zaplatit znovu” flow (které vzniklo později kopií téže logiky — druhá cesta bug zdvojila). Druhá brána (starší integrace) slevu řešila kuponem, takže bug se projevil až po migraci.

Sleva jako záporná položka — brána záporné ItemTotal akceptuje (ověřeno testovací platbou proti živému API, která se nechá expirovat):

// PO — total sedí na order.total
if (discountAmount > 0) {
items.push({ Name: `Sleva ${discountPercent} %`, Quantity: 1, Unit: 'ks',
UnitPrice: -discountAmount, ItemTotal: -discountAmount });
total -= discountAmount;
}

V měně brány ≠ měně objednávky pozor: pokud položky používají vlastní ceníkové ceny (ne kurzový přepočet), slevu počítat procentem ze součtu položek v měně brány, ne přepočtem uložené částky.

Přeplatky dohledat SQL porovnáním zaplacené částky z payment logu proti total objednávky a vrátit partial refundem.

-- zaplaceno vs. total objednávky (payment log vs orders)
SELECT o.order_number, paid.amount, o.total
FROM orders o JOIN payment_log paid ON ...
WHERE paid.amount <> o.total;

Každé místo, kde se před voláním brány objevuje reduce((s, it) => s + it.price), je podezřelé — grep na stavbu gateway items a kontrola, že výsledek prochází assertem proti uloženému totalu.

Přidal aiarchitekt.cz · 19. 7. 2026 2:00
Provozuje aiarchitekt.cz