Schemat księgi rozliczeń, który uzgadnia: faktury i płatności
Dowiedz się, jak zaprojektować schemat księgi rozliczeniowej z oddzielnymi tabelami faktur, płatności, kredytów i korekt, tak aby finanse mogły łatwo uzgadniać i audytować sumy.

Dlaczego dane rozliczeniowe przestają się zgadzać
Dla finansów „uzgodnić” to prosta obietnica: sumy w raportach odpowiadają rekordom źródłowym i każda liczba da się prześledzić. Jeśli miesiąc wykazuje 12 430 USD zebranych, powinieneś móc wskazać dokładne płatności (i zwroty), zobaczyć, do których faktur się odnoszą, i wytłumaczyć każdą różnicę datowanym zapisem.
Dane rozliczeniowe zwykle przestają się zgadzać, gdy baza trzyma wyniki zamiast faktów. Kolumny takie jak paid_amount, balance czy amount_due są aktualizowane w czasie przez logikę aplikacji. Jeden błąd, jedno ponowne wysłanie albo jedna ręczna „poprawka” mogą cicho zmienić historię. Tydzień później tabela faktur mówi, że faktura jest „opłacona”, ale wiersze płatności się nie zgadzają, albo istnieje zwrot bez dopasowanego kredytu.
Inną powszechną przyczyną jest mieszanie różnych typów dokumentów. Faktura to nie płatność. Nota kredytowa to nie zwrot. Korekta to nie to samo co rabat. Gdy wszystkie te rzeczy upchniesz do jednego wiersza „transactions” z wieloma opcjonalnymi polami, raportowanie staje się zgadywaniem, a audyty — kłótnią.
Podstawowe niezgodności są proste: aplikacje często dbają o bieżący stan („czy dostęp jest aktywny?”), podczas gdy finanse potrzebują śladu („co się stało, kiedy i dlaczego?”). Schemat księgi rozliczeniowej musi wspierać oba podejścia, ale to śledzenie zdarzeń powinno przeważać.
Projektuj z myślą o tym efekcie:
- Wyraźne sumy na klienta, na fakturę i na okres rozliczeniowy
- Każda zmiana zapisana jako nowy wiersz (nie nadpisywana)
- Pełne powiązanie od faktury do płatności, kredytów, zwrotów i korekt
- Możliwość przeliczenia sum z surowych wpisów i uzyskania tego samego wyniku
Przykład: jeśli klient zapłaci 100 USD, a potem dostanie kredyt 20 USD, raporty powinny pokazywać 100 USD zebrane, 20 USD skredytowane i 80 USD netto, bez edytowania pierwotnej kwoty faktury.
Separacja: faktury, płatności, kredyty i korekty
Jeśli chcesz schematu księgi rozliczeniowej, który się uzgadnia, traktuj każdy typ dokumentu jako inny rodzaj zdarzenia. Mieszanie ich w jedną tabelę „transactions” wygląda schludnie, ale zaciera znaczenie.
Faktura to roszczenie: „klient nam jest winien”. Przechowuj ją jako dokument z nagłówkiem (klient, numer faktury, data wystawienia, termin, waluta, sumy) oraz oddzielnymi pozycjami (co sprzedano, ilość, cena jednostkowa, kategoria podatkowa). Można trzymać sumy w nagłówku dla wydajności, ale zawsze powinieneś umieć je wyjaśnić z pozycji.
Płatność to ruch pieniędzy: „gotówka przeszła od klienta do nas”. W przepływach kart często widzisz autoryzację (bank zatwierdza) i przechwycenie (pieniądze faktycznie pobrane). Wiele systemów trzyma autoryzacje jako rekordy operacyjne i tylko przechwycone płatności wpisuje do księgi, żeby nie sztucznie zwiększać raportu gotówki.
Nota kredytowa zmniejsza to, co klient jest winien, bez konieczności wysyłania pieniędzy z powrotem. Zwrot to wypływ gotówki. Często występują razem, ale to nie to samo.
- Faktura: zwiększa należności i przychód (lub przychód odroczony)
- Płatność: zwiększa gotówkę i zmniejsza należności
- Nota kredytowa: zmniejsza należności
- Zwrot: zmniejsza gotówkę
Korekta to poprawka dokonana przez zespół, gdy rzeczywistość nie zgadza się z zapisami. Korekty wymagają kontekstu, aby finanse im ufały. Zapamiętaj, kto ją utworzył, kiedy zaksięgowano, kod powodu i krótką notatkę. Przykłady: „odpis 0,03 z powodu zaokrągleń” albo „migracja salda z systemu legacy”.
Praktyczna zasada: zapytaj „Czy to istniałoby, gdyby nikt nie popełnił błędu?” Faktury, płatności, noty kredytowe i zwroty nadal istnieją. Korekty powinny być rzadkie, wyraźnie oznaczone i łatwe do przeglądu.
Wybierz model księgi, który da się zbadać przez finanse
Schemat księgi rozliczeniowej, który się uzgadnia, zaczyna się od jednej idei: dokumenty opisują, co się stało, a księgowania dowodzą sum. Faktura, płatność czy nota kredytowa to dokument. Księga to zbiór wpisów, które się dodają — koniec.
Dokumenty kontra księgowania (przechowuj oba)
Zachowaj dokumenty (nagłówek i pozycje faktury, pokwitowanie płatności, nota kredytowa), bo ludzie muszą je czytać. Ale nie polegaj na samych sumach dokumentów jako źródle prawdy do rekonsyliacji.
Zamiast tego zaksięguj każdy dokument do tabeli księgi jako jeden lub więcej niezmiennych wpisów. Wtedy finanse mogą sumować wpisy według konta, klienta, waluty i daty księgowania i za każdym razem dostać ten sam wynik.
Prosty model przyjazny audytowi przestrzega kilku zasad:
- Immutable entries: nigdy nie edytuj zaksięgowanych kwot; zmiany to nowe wpisy.
- Clear posting event: każdy dokument tworzy partię księgowań z unikalnym odniesieniem.
- Balanced logic: wpisy się bilansują (często debet równa się kredytowi na poziomie firmy).
- Separate dates: przechowuj datę dokumentu (co widzi klient) i datę księgowania (co trafia do raportów).
- Stable references: przechowuj zewnętrzne referencje (numer faktury, identyfikator procesora płatności) wraz z wewnętrznymi ID.
Klucze naturalne kontra identyfikatory zastępcze
Używaj identyfikatorów zastępczych do joinów i wydajności, ale także przechowuj stabilny klucz naturalny, który przetrwa migracje i ponowne importy. Finanse będą pytać o „Invoice INV-10483” długo po tym, jak ID bazy danych się zmienią. Traktuj numery faktur i ID dostawców (np. identyfikator pobrania procesora płatności) jako pola pierwszorzędne.
Odwrócenia bez kasowania historii
Gdy coś trzeba cofnąć, nie usuwaj ani nie nadpisuj. Zamieść odwrócenie: nowe wpisy, które odzwierciedlają oryginalne kwoty z przeciwnym znakiem, powiązane z oryginalnym księgowaniem.
Przykład: płatność 100 USD zastosowana do złej faktury staje się dwoma krokami: odwróć błędne księgowanie, a potem zaksięguj nowe zastosowanie do właściwej faktury.
Krok po kroku: zarys schematu (tabele i klucze)
Schemat księgi rozliczeniowej uzgadnia się bardziej niezawodnie, gdy każdy typ dokumentu ma własną tabelę i łączysz je jawnie rekordami alokacji (zamiast domyślać się później relacji).
Zacznij od małego zestawu tabel rdzeniowych, każda z jasnym kluczem głównym (UUID lub bigserial) i wymaganymi kluczami obcymi:
- customers:
customer_id(PK), plus stabilne identyfikatory jakexternal_ref(unikalny) - invoices:
invoice_id(PK),customer_id(FK),invoice_number(unikalny),issue_date,due_date,currency - invoice_lines:
invoice_line_id(PK),invoice_id(FK),line_type,description,qty,unit_price,tax_code,amount - payments:
payment_id(PK),customer_id(FK),payment_date,method,currency,gross_amount - credits:
credit_id(PK),customer_id(FK),credit_number(unikalny),credit_date,currency,amount
Potem dodaj tabele, które czynią sumy audytowalnymi: alokacje. Płatność lub kredyt może pokrywać wiele faktur, a faktura może być opłacana wieloma płatnościami.
Używaj tabel łączących z własnymi kluczami (nie tylko klucze złożone):
- payment_allocations:
payment_allocation_id(PK),payment_id(FK),invoice_id(FK),allocated_amount,posted_at - credit_allocations:
credit_allocation_id(PK),credit_id(FK),invoice_id(FK),allocated_amount,posted_at
Na koniec trzymaj korekty oddzielnie, żeby finanse widziały, co i dlaczego się zmieniło. Tabela adjustments może odnosić się do docelowego rekordu przez invoice_id (nullable) i przechowywać kwotę delta, bez przepisywania historii.
Dodaj pola audytowe wszędzie, gdzie księgujesz pieniądze:
created_at,created_byreason_code(write-off, rounding, goodwill, chargeback)source_system(manual, import, Stripe, support tool)
Kredyty, zwroty i umorzenia bez zepsutych sum
Większość problemów z rekonsyliacją zaczyna się, gdy kredyty i zwroty zapisuje się jako „ujemne płatności”, albo gdy umorzenia miesza się z pozycjami faktury. Czysty schemat trzyma każdy typ dokumentu jako osobny rekord, a miejscem ich interakcji są jawne alokacje.
Kredyt powinien pokazać, dlaczego zmniejszyłeś to, co klient winien. Jeśli dotyczy jednej faktury, zarejestruj pojedynczą notę kredytową i przydziel ją do tej faktury. Jeśli dotyczy kilku faktur, alokuj tę samą notę do wielu faktur. Kredyt pozostaje jednym dokumentem z wieloma alokacjami.
Zwroty to zdarzenia podobne do płatności, a nie ujemne płatności. Zwrot to wypływ gotówki, więc traktuj go jako osobny rekord (często powiązany z oryginalną płatnością dla odniesienia), a potem alokuj go jak płatność. To utrzymuje czytelny ślad audytu, gdy wyciąg bankowy pokazuje zarówno wpływ, jak i wypływ.
Częściowe płatności i częściowe kredyty działają tak samo: trzymaj sumę płatności lub kredytu w oddzielnym wierszu i używaj wierszy alokacji, aby wskazać, ile zastosowano do każdej faktury.
Zasady księgowania zapobiegające podwójnemu liczeniu
Te zasady eliminują większość „tajemniczych różnic”:
- Nigdy nie zapisuj ujemnej płatności. Używaj rekordu zwrotu.
- Nigdy nie pomniejszaj sumy faktury po zaksięgowaniu. Użyj noty kredytowej lub korekty.
- Dokumenty księguj raz (z polem
posted_at) i nie edytuj kwot po zaksięgowaniu. - Jedyną rzeczą, która zmienia saldo faktury, jest suma zaksięgowanych alokacji.
- Umorzenie to korekta z kodem powodu, alokowana do faktury jak kredyt.
Podatki, opłaty, waluty i zasady zaokrągleń
Większość problemów z rekonsyliacją zaczyna się od sum, których nie potrafisz odtworzyć. Najbezpieczniejsza zasada jest prosta: zapisuj surowe pozycje, które stworzyły rachunek, i także zapisuj sumy przedstawione klientowi.
Podatki i opłaty: trzymaj je na poziomie pozycji
Przechowuj podatki i opłaty dla każdej pozycji, a nie tylko jako podsumowanie faktury. Różne produkty mogą mieć różne stawki podatkowe, opłaty mogą być opodatkowane lub nie, a zwolnienia często dotyczą tylko części faktury. Jeśli masz tylko tax_total na poziomie faktury, w końcu trafisz na przypadek, którego nie wyjaśnisz.
Zachowaj:
- Surowe pozycje (co sprzedano, ilość, cena jednostkowa, rabat)
- Obliczone sumy pozycji (line_subtotal, line_tax, line_total)
- Podsumowanie faktury (subtotal, tax_total, total)
- Stawkę podatku i typ podatku użyty
- Opłaty jako osobne pozycje (np. „Opłata za przetwarzanie płatności”)
To pozwala finansom odtworzyć sumy i potwierdzić, że podatek był obliczony w ten sam sposób za każdym razem.
Wielowalutowość: zapisuj, co się stało i jak raportujesz
Jeśli obsługujesz wiele walut, rejestruj zarówno walutę transakcji, jak i wartości do raportowania. Praktyczne minimum to: currency_code na każdym dokumencie pieniężnym, fx_rate użyty przy księgowaniu oraz oddzielne kwoty raportowe (np. amount_reporting), jeśli księgi zamykane są w jednej walucie.
Przykład: klient jest fakturowany 100,00 EUR plus 20,00 EUR VAT. Zapamiętaj te EUR linie i sumy oraz fx_rate użyty przy księgowaniu faktury i przeliczone sumy do celów raportowania.
Zaokrąglanie zasługuje na osobne traktowanie. Wybierz jedną zasadę zaokrąglania (na pozycji lub na fakturze) i trzymaj się jej. Gdy zaokrąglenie tworzy różnicę, zapisz ją jawnie jako pozycję korekty zaokrąglenia (lub mały wpis korekty), zamiast cicho zmieniać sumy.
Statusy, daty księgowania i czego nie przechowywać
Rekonsyliacja robi się chaotyczna, gdy „status” używany jest jako skrót do prawdy księgowej. Traktuj status jako etykietę workflow, a zaksięgowane wpisy jako źródło prawdy.
Uczyń statusy surowymi i nudnymi. Każdy powinien odpowiadać na pytanie: czy ten dokument może już wpływać na sumy?
- Draft: tylko wewnętrzne, nie zaksięgowane, nie powinno trafiać do raportów
- Issued: sfinalizowane i wysłane, gotowe do zaksięgowania (lub już zaksięgowane)
- Void: anulowane; jeśli było zaksięgowane, musi być odwrócone
- Paid: w pełni rozliczone przez zaksięgowane płatności i kredyty
- Refunded: pieniądze wyszły na zewnątrz przez zaksięgowany zwrot
Daty znaczą więcej, niż wiele zespołów się spodziewa. Finanse zapytają: „Do którego miesiąca to należało?” i Twoja odpowiedź nie powinna zależeć od logów UI.
issued_at: kiedy faktura stała się finalnaposted_at: kiedy liczy się w raportach księgowychsettled_at: kiedy środki rozliczono lub płatność potwierdzonovoided_at/refunded_at: kiedy odwrócenie stało się skuteczne
Czego nie trzymać jako prawdy: liczb pochodnych, których nie możesz odtworzyć z księgi. Pola jak balance_due, is_overdue czy customer_lifetime_value są OK jako widoki cache’owane tylko wtedy, gdy zawsze możesz je przeliczyć z faktur, płatności, kredytów, alokacji i korekt.
Mały przykład: ponowienie płatności trafia do bramki dwukrotnie. Bez idempotency_key zapisujesz dwie płatności, oznaczasz fakturę jako „paid”, a finanse widzą dodatkowe 100 USD w gotówce. Przechowuj unikalny idempotency_key na każde zewnętrzne żądanie pobrania i odrzucaj duplikaty na poziomie bazy.
Raporty, których finanse oczekują od pierwszego dnia
Schemat księgi rozliczeniowej udowadnia swoją wartość, gdy finanse potrafią szybko odpowiedzieć na podstawowe pytania i za każdym razem otrzymać te same sumy.
Większość zespołów zaczyna od:
- Aging należności: kwoty otwarte według klienta i przedziałów wiekowych (0-30, 31-60 itd.)
- Otrzymana gotówka: pieniądze zebrane dziennie, tygodniowo i miesięcznie, na podstawie dat księgowania płatności
- Przychód kontra gotówka: faktury zaksięgowane vs płatności zaksięgowane
- Ścieżka audytu dla eksportów: możliwość dojścia z linii eksportu do GK do dokładnego dokumentu i wierszy alokacji, które to stworzyły
Aging to miejsce, gdzie alokacje mają największe znaczenie. Aging to nie „suma faktury minus suma płatności”. To „co pozostało otwarte na każdej fakturze na dany dzień”. To wymaga przechowywania, jak każda płatność, kredyt czy korekta została zastosowana do konkretnych faktur i kiedy te alokacje były zaksięgowane.
Otrzymana gotówka powinna być napędzana tabelą płatności, nie statusem faktury. Klienci mogą płacić wcześniej, później lub częściowo.
Przychód kontra gotówka to powód, dla którego faktury i płatności muszą być oddzielne. Przykład: wystawiasz fakturę 1000 USD 30 marca, otrzymujesz 600 USD 5 kwietnia i wystawiasz notę kredytową 100 USD 20 kwietnia. Przychód należy do marca (księgowanie faktury), gotówka do kwietnia (księgowanie płatności), a nota kredytowa zmniejsza należności gdy zostanie zaksięgowana. Alokacje łączą to wszystko.
Przykładowy scenariusz: jeden klient, cztery typy dokumentów
Jeden klient, jeden miesiąc, cztery typy dokumentów. Każdy dokument zapisany raz, a pieniądze przepływają przez tabelę alokacji (czasami zwaną „applications”). To sprawia, że końcowe saldo jest łatwe do przeliczenia i zaudytowania.
Załóżmy klienta C-1001 (Acme Co.).
Rekordy, które tworzysz
invoices
| invoice_id | customer_id | invoice_date | posted_at | currency | total |
|---|---|---|---|---|---|
| INV-10 | C-1001 | 2026-01-05 | 2026-01-05 | USD | 120.00 |
payments
| payment_id | customer_id | received_at | posted_at | method | amount |
|---|---|---|---|---|---|
| PAY-77 | C-1001 | 2026-01-10 | 2026-01-10 | card | 70.00 |
credits (nota kredytowa, kredyt goodwill itp.)
| credit_id | customer_id | credit_date | posted_at | reason | amount |
|---|---|---|---|---|---|
| CR-5 | C-1001 | 2026-01-12 | 2026-01-12 | service issue | 20.00 |
adjustments (korekta po fakcie, nie nowa sprzedaż)
| adjustment_id | customer_id | adjustment_date | posted_at | note | amount |
|---|---|---|---|---|---|
| ADJ-3 | C-1001 | 2026-01-15 | 2026-01-15 | underbilled fee | 5.00 |
allocations (to one faktycznie uzgadnia saldo)
| allocation_id | doc_type_from | doc_id_from | doc_type_to | doc_id_to | posted_at | amount |
|---|---|---|---|---|---|---|
| AL-900 | payment | PAY-77 | invoice | INV-10 | 2026-01-10 | 70.00 |
| AL-901 | credit | CR-5 | invoice | INV-10 | 2026-01-12 | 20.00 |
Jak obliczane jest saldo faktury
Dla INV-10 audytor może przeliczyć otwarte saldo z rekordów źródłowych:
open_balance = invoice.total + sum(adjustments) - sum(allocations)
Zatem: 120.00 + 5.00 - (70.00 + 20.00) = 35.00 do zapłaty.
Aby prześledzić te 35,00:
- Zacznij od sumy faktury (INV-10)
- Dodaj zaksięgowane korekty powiązane z tą samą fakturą (ADJ-3)
- Odejmij każdą zaksięgowaną alokację zastosowaną do faktury (AL-900, AL-901)
- Potwierdź, że każda alokacja wskazuje na rzeczywisty dokument źródłowy (PAY-77, CR-5)
- Zweryfikuj daty i
posted_at, aby wyjaśnić harmonogram zdarzeń
Częste błędy łamiące rekonsyliację
Większość problemów nie wynika z „błędów arytmetycznych”. To brak reguł, więc ten sam realny zdarzenie bywa rejestrowane na różne sposoby w zależności od osoby.
Powszechna pułapka to używanie ujemnych wierszy jako skrótu. Ujemna pozycja faktury, ujemna płatność i ujemna linia podatkowa mogą znaczyć różne rzeczy. Jeśli pozwalasz na wartości ujemne, zdefiniuj jedną jasną politykę odwróceń (np. używaj tylko wierszy odwrotnych, które odnoszą się do oryginału, i nie mieszaj semantyki odwróceń z rabatami).
Inną częstą przyczyną jest zmienianie historii. Jeśli faktura została wystawiona, nie edytuj jej później, by dopasować nową cenę lub skorygowany adres. Zachowaj oryginalny dokument i zaksięguj korektę lub notę kredytową wyjaśniającą zmianę.
Wzorce, które zwykle psują sumy:
- Używanie ujemnych wierszy bez ścisłej reguły odwrócenia i odniesienia do oryginału
- Edytowanie starych faktur zamiast księgowania korekt lub not kredytowych
- Mieszanie ID transakcji bramki z wewnętrznymi ID bez tabeli mapującej i jasnego źródła prawdy
- Pozwalanie kodowi aplikacji obliczać sumy, gdy brakuje wierszy wspierających (podatek, opłata, zaokrąglenie, alokacje)
- Nieoddzielanie „ruchu pieniędzy” (przepływ gotówki) od „alokacji pieniędzy” (która faktura została opłacona)
Ten ostatni punkt powoduje najwięcej zamieszania. Przykład: klient płaci 100 USD, potem stosujesz 60 USD do Faktury A i 40 USD do Faktury B. Płatność to jeden ruch gotówki, ale tworzy dwie alokacje. Jeśli zapisujesz „płatność = faktura”, nie obsłużysz płatności częściowych, nadpłat ani przekształceń alokacji.
Lista kontrolna i dalsze kroki
Zanim dodasz więcej funkcji, upewnij się, że podstawy są stabilne. Schemat księgi rozliczeniowej uzgadnia się, gdy każdą sumę da się prześledzić do konkretnych wierszy, a każda zmiana ma ślad audytu.
Szybkie kontrole rekonsyliacji
Przeprowadź te kontrole na małej próbce (jeden klient, jeden miesiąc), a potem na pełnym zbiorze danych:
- Każda zaksięgowana liczba w raporcie prowadzi do rekordów źródłowych (pozycja faktury, płatność, nota kredytowa, korekta) z datą księgowania i walutą.
- Alokacje nigdy nie przekraczają dokumentu, który dotyczą (suma alokacji płatności <= suma płatności; to samo dla kredytów).
- Nic nie jest usuwane. Błędne wpisy odwraca się z powodem, potem poprawia nowym zaksięgowanym wierszem.
- Otwarte saldo jest obliczalne, nie przechowywane (otwarte saldo faktury = suma faktury minus zaksięgowane alokacje i kredyty).
- Sumy dokumentów zgadzają się z ich liniami (suma nagłówka = suma linii, podatków i opłat po zastosowaniu reguły zaokrągleń).
Następne kroki, by wypuścić coś używalnego
Gdy schemat jest solidny, zbuduj wokół niego workflow operacyjny:
- Ekrany administracyjne do tworzenia, księgowania i odwracania faktur, płatności, kredytów i korekt z wymaganymi notatkami
- Widok rekonsyliacji pokazujący dokumenty i alokacje obok siebie, w tym kto zaksięgował i kiedy
- Eksporty, których finanse oczekują (wg daty księgowania, klienta, mapowania do GK jeśli je masz)
- Workflow zamknięcia okresu: blokuj daty księgowania dla zamkniętych miesięcy i wymagaj wpisów odwrotnych dla poprawek po zamknięciu
- Scenariusze testowe (zwroty, płatności częściowe, umorzenia), które muszą dawać oczekiwane sumy
Jeśli chcesz szybszej drogi do działającego wewnętrznego portalu finansowego, AppMaster (appmaster.io) może pomóc w modelowaniu schematu PostgreSQL, generowaniu API i budowaniu ekranów administracyjnych z tego samego źródła, tak aby zasady księgowania i alokacji pozostały spójne w miarę rozwoju aplikacji.
FAQ
Rekonsyliacja oznacza, że każdą sumę z raportu można odtworzyć z rekordów źródłowych i prześledzić do datowanych wpisów. Jeśli raport mówi, że zebrano 12 430 USD, powinieneś wskazać dokładne zaksięgowane płatności i zwroty, które sumują się do tej kwoty, bez polegania na nadpisanych polach.
Najczęstszą przyczyną jest przechowywanie zmieniających się „wyników” jak paid_amount lub balance_due jako faktów. Jeśli te pola są aktualizowane przez powtórzenia, błędy lub ręczne edycje, tracisz ślad historyczny i sumy przestają odpowiadać rzeczywistości.
Ponieważ każdy z tych dokumentów odzwierciedla inne zdarzenie w rzeczywistości księgowej. Kiedy są upchnięte do jednego rekordu „transaction” z wieloma opcjonalnymi polami, raportowanie staje się zgadywaniem, a audyty zmieniają się w dyskusje o tym, co właściwie oznaczał dany wiersz.
Nota kredytowa zmniejsza kwotę należną przez klienta, ale nie oznacza wypływu środków. Zwrot to wypływ gotówki, zwykle powiązany z wcześniejszą płatnością. Traktowanie ich jako tego samego (lub jako ujemnych płatności) utrudnia raportowanie gotówki i dopasowanie do wyciągów bankowych.
Zamiast edytować lub usuwać, zamieść zapis odwrotny. Utwórz nowe wpisy o przeciwnych znakach, powiąż je z oryginalnym księgowaniem, a następnie zamieść poprawne alokacje — w ten sposób ścieżka audytu pokaże dokładnie, co i dlaczego zmieniono.
Używaj jawnych rekordów alokacji (applications), które łączą płatność lub kredyt z jednym lub kilkoma fakturami, z podaną kwotą i datą zaksięgowania. Saldo faktury powinno być obliczalne z sumy faktury plus korekty minus zaksięgowane alokacje.
Przechowuj zarówno datę dokumentu, jak i datę zaksięgowania. Data dokumentu to to, co widzi klient; posted_at steruje, kiedy coś pojawia się w raportach finansowych i zamknięciach okresów, więc wyniki miesiąca nie zmieniają się, bo ktoś edytował rekord później.
Przechowuj szczegóły podatków i opłat na poziomie pozycji, plus dokładne sumy pokazane klientowi. Jeśli zostawisz tylko pole tax_total na poziomie faktury, prędzej czy później trafisz na przypadek, którego nie będziesz w stanie wyjaśnić.
Przechowuj wartości w walucie transakcji oraz wartości do raportowania używając kursu FX zastosowanego przy księgowaniu. Wybierz jedną zasadę zaokrąglania i zapisuj ewentualne różnice zaokrągleń jako osobne korekty, żeby można było odtworzyć sumy dokładnie.
Status traktuj jako etykietę workflow (Draft, Issued, Void, Paid), a jako prawdę księgową wykorzystuj zaksięgowane, niemodyfikowalne wpisy i alokacje. Status może być błędny; niemodyfikowalne wpisy pozwalają finansom zawsze przeliczyć sumy w ten sam sposób.


