Přeskočit na obsah

Dvě cesty vystavení dokladu — párovač zná jen jednu, druhá tiše zamrzne flow

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

Klient zaplatil zálohovou fakturu. Platba se z banky správně automaticky spárovala (faktura přešla na PAID), ale navazující daňový doklad k přijaté platbě se nevystavil, smlouva zůstala ve stavu „záloha fakturována” a účetní nemohla vystavit finální vyúčtovací fakturu s odpočtem zálohy (systém by ji vytvořil jako plnou fakturu bez odpočtu). Žádný error log, žádná notifikace, žádný alert — flow prostě zamrzlo. U jiné, starší zakázky stejný bug způsobil, že finální faktura odešla na plnou částku bez odpočtu už zaplacené zálohy.

V systému existovaly dvě cesty, jak vystavit zálohovou fakturu ke smlouvě:

  1. novější — per splátka ze splátkového kalendáře (installments[] JSON na smlouvě); zapíše číslo faktury do installments[].invoiceNumber,
  2. legacy — automaticky při oboustranném podpisu smlouvy; zapíše číslo jen do contract.depositInvoiceNumber, kalendář nechá netknutý.

Párovač příchozích plateb rozhodoval podle přítomnosti kalendáře: má-li smlouva installments[], hledal zaplacenou fakturu jen podle installments[].invoiceNumber. Smlouva vzniklá ze šablony s kalendářem, ale s fakturou vystavenou legacy cestou, tak nikdy shodu nenašla — a větev končila:

if (!matchedInstallment) {
// Faktura není v scheduleu — ignoruj
return null; // ⟵ tichý no-op: žádný DD, žádný posun stavu, žádný alert
}

Tři vrstvy:

  1. Fix u zdroje — legacy vystavení zálohové faktury nově orazítkuje i splátkový kalendář (najde pending splátku se shodnou částkou ±0,01, jinak první neoraženou; zapíše invoiceNumber + status: "invoiced"), stejně jako to dělá novější cesta.
  2. Bezpečný fallback v párovači — když zaplacená faktura v kalendáři není, ale je to přímo contract.depositInvoiceNumber a v kalendáři existuje právě jedna neoražená nezaplacená splátka se shodnou částkou (±0,01), spáruje se s ní (daňový doklad + posun stavu + zpětné orazítkování). Podmínka „právě jedna” brání false-match u vícesplátkových kalendářů.
  3. Konec ticha — nespárovatelný případ vytvoří trvalý systémový alert (watchdog stránka „Zdraví systému”) + error log, aby backoffice doklad vystavil ručně a flow nezůstalo viset bez povšimnutí.

Regresní integrační testy pokrývají všechny tři větve (fallback, alert, orazítkování při vystavení).

  • Grep na return null / prázdné continue ve větvích párování plateb a workflow přechodů: každá „nenašel jsem” větev v money-flow musí něco emitovat (alert, notifikace, aspoň error log).
  • Máte-li dvě generace téhož procesu (legacy + nová), diffněte, jaká metadata každá zapisuje — konzument musí umět obě, nebo se starší cesta musí dorovnat.
  • SQL kontrola zaseknutých flow: zaplacené zálohové faktury bez navazujícího daňového dokladu (ZF PAID bez DD na téže smlouvě).
Přidal aiarchitekt.cz · 22. 7. 2026 2:00
Provozuje aiarchitekt.cz