Dopasowywanie płatności do wyciągu bankowego: gdzie leżą schody
Techniczne spojrzenie na reconciliation płatności: podłączenie do API bankowego, normalizacja, reguły dopasowania, fuzzy matching bez tytułu przelewu, idempotencja i reconciliation. Realne edge case'y.
Dopasowywanie przychodzących płatności do faktur brzmi jak trywialne zadanie. Przychodzi płatność, szuka się faktury po tytule przelewu, dopasowuje się. Dopóki płatnicy płacą z tytułem przelewu i wysyłają dokładne kwoty, jest to rzeczywiście proste. Z tym poradzi sobie nawet pudełkowy SaaS księgowy i nie ma sensu budować czegoś własnego.
Problem w tym, że rzeczywistość nie trzyma się tytułu przelewu. Płatnicy podają błędny numer, łączą trzy faktury w jedną płatność, wysyłają częściową zapłatę, płacą w innej walucie albo w komunikacie wpisują tylko nazwę firmy. I w tym momencie deterministyczne dopasowanie po tytule przelewu przestaje wystarczać. Ten artykuł jest o tym, gdzie dokładnie leżą schody i co z tym zrobić od strony technicznej.
Podłączenie do API bankowego: wyciąg to nie event
Pierwsza decyzja to skąd bierzemy dane. API bankowe typowo daje wyciągi — paczkę transakcji za okres, nie strumień zdarzeń w czasie rzeczywistym. To ma dwie konsekwencje.
Po pierwsze, tę samą transakcję zobaczymy kilka razy. Gdy pobierzemy wyciąg za dzisiejszy ranek, a potem znowu po południu, transakcje z rana pojawią się ponownie. Pipeline dopasowania musi to uwzględniać od początku — inaczej spárujemy jedną płatność dwa razy.
Po drugie, transakcje nie mają tego samego kształtu we wszystkich bankach. Jeden bank podaje tytuł przelewu w osobnym polu, inny chowa go w treści komunikatu, kolejny nie ma go wcale i zostaje tylko remittanceInformation. IBAN płatnika czasem jest, czasem nie. Data księgowania i data waluty się różnią. Dlatego pierwsza warstwa pipeline to nie dopasowanie, ale normalizacja — przeliczenie wyciągu z konkretnego banku do jednego wewnętrznego kształtu transakcji: kwota, waluta, data, kontrahent, IBAN, ustrukturyzowany tytuł (jeśli jest) i surowy tekst. Dopiero nad znormalizowaną formą można sensownie dopasowywać.
Reguły dopasowania: od pewnego do niepewnego
Dopasowywanie to nie jeden algorytm, to kaskada reguł ułożona od najbardziej pewnej do najmniej pewnej. Każda reguła albo dopasowuje, albo przekazuje dalej.
- Tytuł przelewu + zgodna kwota. Najsilniejszy sygnał. Gdy tytuł przelewu odpowiada fakturze i kwota zgadza się co do grosza, dopasowanie następuje automatycznie i sprawa jest zamknięta. Tu kończy się większość zwykłych płatności.
- Tytuł przelewu, ale kwota się nie zgadza. Tytuł wskazuje na fakturę, ale przyszło mniej lub więcej. To nie błąd dopasowania — to częściowa zapłata, nadpłata albo potrącona prowizja. Dopasować można, ale status faktury zostaje „częściowo opłacona", nie „opłacona".
- Brak tytułu przelewu. Tu deterministyczna reguła zawodzi i wchodzi fuzzy matching.
Ważne jest, żeby nie puszczać niepewnych reguł wcześniej, niż skończą pewne. Gdy zaczniesz dopasowywać po nazwie płatnika, ryzykujesz false positive. Kolejność kaskady chroni przed tym, żeby słabym dopasowaniem nadpisać to, które inaczej znalazłbyś na twardo.
Fuzzy matching: wynik, nie zgadywanie
Gdy brakuje tytułu przelewu, dopasowujesz według kombinacji słabszych sygnałów. Żaden z nich sam w sobie nie wystarczy, ale razem dają rozsądną pewność:
- Kwota — dokładna zgodność lub zgodność w granicach tolerancji (prowizja, różnica kursowa).
- Nazwa płatnika — rozmyte porównanie z odbiorcą na fakturze, bo „ACME sp. z o.o." i „ACME spzoo" i „Acme" to wciąż ta sama firma.
- IBAN płatnika — jeśli od tego kontrahenta już kiedyś dopasowaliśmy płatność, to silny sygnał.
- Data — płatność blisko terminu wymagalności jest bardziej prawdopodobna niż płatność sprzed pół roku.
- Treść komunikatu — czasem jest w niej numer faktury, czasem nazwa, czasem nic.
Z tych sygnałów oblicza się wynik dla każdego kandydata. Powyżej górnego progu następuje automatyczne dopasowanie. Poniżej dolnego progu — brak dopasowania. A pomiędzy progami — co jest strefą, w której rozstrzyga się zaufanie do całego systemu — transakcja trafia do ręcznej kolejki z propozycją. Księgowy nie dostaje pustego pola, ale „ta płatność prawdopodobnie należy do tej faktury, potwierdź lub popraw". To różnica między narzędziem oszczędzającym czas a czarną skrzynką, której nikt nie ufa.
Tu jest uczciwa granica: to nie jest research ML. To inżynierskie punktowanie na danych, które firma realnie posiada. Siłę czerpie nie z modelu, ale z tego, że sygnały są dobrze znormalizowane i progi są ustawione konserwatywnie.
Edge case'y, które psują naiwne dopasowanie
Kilka konkretnych sytuacji, na których pipeline „działa" zawodzi:
- Płatność zbiorcza. Płatnik opłaca trzy faktury jedną kwotą. Trzeba dopasować jedną transakcję do wielu faktur i dopiero suma ich kwot daje zgodność. Naiwne dopasowanie 1:1 tego nigdy nie znajdzie.
- Częściowa zapłata. Przyszła połowa. Faktura nie może przeskoczyć na „opłacona", ale też nie może spaść do niedopasowanych. Pozostała kwota musi zostać widoczna.
- Nadpłata. Przyszło więcej, niż wynosiła faktura. Różnica to albo zaliczka na następnym razem, albo zwrot. To już nie jest czysto decyzja dopasowania, ale dopasowanie musi umieć to oznaczyć.
- Wiele walut. Faktura w EUR, płatność w PLN. Bez przeliczenia po kursie z dnia płatności kwoty nigdy się nie zgodzą.
- Płatność zwrócona / storno. Ujemna transakcja, która cofa wcześniejszą płatność przychodzącą. Musi cofnąć dopasowanie, nie dodać kolejne.
- Duplikat pobrania wyciągu. Omówione wyżej — bez idempotencji podwójne dopasowanie.
Idempotencja: nie dopasowywać dwa razy
To element, który bywa niedoceniany, a decyduje o tym, czy można ufać systemowi. Job dopasowania będzie uruchamiany wielokrotnie, wyciągi się pokrywają, a prędzej czy później job zrestartuje w połowie paczki. Jeśli dopasowanie nie jest idempotentne, pojawią się zduplikowane wpłaty i zepsuty stan faktur.
Rozwiązanie jest takie samo jak przy innych durable integracjach: każda transakcja z wyciągu dostaje deterministyczny klucz (typowo z bankowego ID transakcji, nie z kolejności w pobranej paczce) i operacja dopasowania jest idempotentna. Gdy przychodzi transakcja, którą już przetworzyliśmy, krok ją rozpoznaje i nic nie dodaje. Ta sama zasada co przy idempotentnym wysyłaniu przy podłączeniu do regulowanych systemów państwowych — bez niej każdy retry to ryzyko.
Reconciliation i audyt: czy rzeczywistość się zgadza?
Automatyczne dopasowanie dopasowuje większość. Pytanie brzmi, jak poznasz, że reszta nie utknęła gdzieś cicho. Do tego służy reconciliation — periodyczna kontrola, która pyta: czy suma dopasowanych płatności zgadza się z zaksięgowanymi fakturami? Czy nie ma transakcji wiszącej w kolejce od tygodnia i nikt na nią nie spojrzał? Czy nie ma faktury oznaczonej jako opłacona bez powiązanej płatności? Bez reconciliation nie wiesz, czy dopasowanie działa — tylko masz nadzieję.
I nad tym wszystkim audit log. Każdy krok dopasowania — automatyczny i ręczny — zostawia zapis: która transakcja, do której faktury, według jakiej reguły, z jakim wynikiem, kto to ewentualnie potwierdził ręcznie. Gdy za pół roku pyta audytor albo księgowa „dlaczego ta płatność jest przy tej fakturze", odpowiedź jest w logu, nie w czyjejś pamięci. To powód, dla którego dopasowanie traktujemy jako durable reconciliation pattern, nie jako jednorazowy skrypt: idempotencja, retry, audyt każdego kroku i periodyczna kontrola „czy rzeczywistość się zgadza".
Kiedy warto robić to na miarę
Bądźmy szczerzy, żeby nie dokładać sobie pracy. Gdy większość płatności przychodzi z tytułem przelewu i dokładną kwotą, deterministyczne dopasowanie w pudełkowym SaaS wystarczy i nie ma sensu budować czegoś własnego. Własne rozwiązanie ma sens tam, gdzie pudełko zawodzi:
- masz własny ERP lub Dynamics 365 Business Central, do którego pudełkowe narzędzie nie dosięgnie,
- działasz na wolumenach enterprise, gdzie nawet kilka procent ręcznej pracy jest kosztowne,
- duża część płatności przychodzi bez tytułu przelewu i deterministyczne dopasowanie jest bezużyteczne,
- potrzebujesz reconciliation na poziomie audytowym, nie tylko „jakoś dopasowało".
To jest dokładnie obszar, którym się zajmujemy. Tę samą durable maszinerię — idempotencja, retry, reconciliation, audyt — zbudowaliśmy przy podłączeniu do regulowanego systemu państwowego, gdzie ponad 40 000 dokumentów musiało zostać dostarczonych do jednego. Przy automatyzacji dokumentów w środowisku bankowym skróciliśmy generowanie umów z 2 godzin do 3 minut. Ekstrakcję faktur rozwiązujemy jako wydobywanie AI z PDF z human-in-the-loop i audit logiem, nie jako czarną skrzynkę — i to samo podejście dotyczy dopasowywania płatności: podłączenie do API bankowego, fuzzy matching tam, gdzie brakuje tytułu przelewu, i wszystko wpięte do ERP.
Jeśli dopasowywanie płatności kosztuje cię ręczną pracę co miesiąc i pudełko nie wystarcza, napisz do nas — powiemy ci, gdzie twoje dopasowanie jest słabe i co można zautomatyzować.
FAQ
Kiedy wystarczy pudełkowy SaaS, a kiedy potrzebne jest własne dopasowywanie?
Standardowe przypadki z tytułem przelewu deterministycznie obsłuży nawet pudełkowy SaaS. Własne rozwiązanie ma sens tam, gdzie pudełko zawodzi: własny ERP, wolumeny enterprise, płatności bez tytułu przelewu, wiele walut i reconciliation na poziomie audytowym.
Jak dopasowywać płatności bez tytułu przelewu?
Fuzzy matching łączy kilka sygnałów: kwotę, nazwę płatnika, datę wymagalności, IBAN i treść komunikatu. Punktuje kandydatów i dopasowuje tylko tych powyżej progu pewności. Co jest poniżej progu, trafia do ręcznej kolejki z propozycją — nie do automatycznego dopasowania.
Jak zapobiec podwójnemu dopasowaniu tej samej płatności?
Idempotencją. Każda transakcja z wyciągu dostaje deterministyczny klucz, a krok dopasowania jest operacją idempotentną. Gdy wyciąg przyjdzie po raz drugi albo job zrestartuje w połowie, system rozpoznaje, że tę transakcję już przetworzył, i nie dopasowuje jej ponownie.