Dvě cesty vystavení dokladu — párovač zná jen jednu, druhá tiše zamrzne flow
import { Aside } from ‘@astrojs/starlight/components’;
Symptom
Sekce “Symptom”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.
Root cause
Sekce “Root cause”V systému existovaly dvě cesty, jak vystavit zálohovou fakturu ke smlouvě:
- novější — per splátka ze splátkového kalendáře (
installments[]JSON na smlouvě); zapíše číslo faktury doinstallments[].invoiceNumber, - 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}Fix
Sekce “Fix”Tři vrstvy:
- 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. - Bezpečný fallback v párovači — když zaplacená faktura v kalendáři není, ale
je to přímo
contract.depositInvoiceNumbera 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ářů. - 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í).
Jak to najít u sebe
Sekce “Jak to najít u sebe”- Grep na
return null/ prázdnécontinueve 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 PAIDbezDDna téže smlouvě).