Bosanska lokalizacija Odoo: Modul reconcile_payment_priority 16.0.1.1.0 - prošireno pokrivanje obaveza na dobavljačkim kontima


O čemu se radi?

Modul reconcile_payment_priority postoji da bi spriječio jedan veoma neugodan obrazac u Odoo bankarskom usaglašavanju: kada je faktura dobavljača već plaćena preko registrovanog plaćanja (account.payment), banka uvozni izvod treba povezati sa tim plaćanjem, a ne direktno sa fakturom. Bez ovog modula, OCA reconcile widget radije matchuje izvod na fakturu, što ostavlja originalno plaćanje “viseće” na prelaznom kontu (kod nas: konto 20093 – “Plaćanja u toku”).

Originalna verzija (16.0.1.0.0) bila je svjesno ograničena na fakture dobavljača (move_type in ('in_invoice', 'in_refund')). To je pokrivalo većinu slučajeva — ali ne sve.

Stvarni slučaj iz vlastitih knjiga

Prije nekoliko dana smo isplatili dividendu vlasniku. Tok knjiženja je bio sljedeći:

  1. Manualni nalog (RAZNO)cr 4320 (Obaveze prema dobavljačima) na osnovu odluke o raspodjeli dobiti. Ovdje se obaveza prema vlasniku tretira kao obična obaveza prema dobavljaču radi jednostavnosti naplate. move_type ovog naloga je entry (manualno knjiženje), ne in_invoice.

  2. Registrovano plaćanje (PUCB/…)cr 20093 (Plaćanja u toku) / dt 4320. Klasično plaćanje koje “očekuje” izvod banke da bi se zatvorilo.

  3. Bankovni izvod (UCB/…) sljedećeg dana — preko OCA reconcile forme.

Kad je računovođa otvorio reconcile formu za stavku iz UniCredit izvoda, OCA matcher je predložio dva kandidata na kontu 4320: i ovaj manualni RAZNO i dt 4320 stranu plaćanja. Naš reconcile_payment_priority trebao je tu da intervenira i preferira plaćanje — ali nije:

# stara logika
move = aml.move_id
if move.move_type not in ('in_invoice', 'in_refund'):
    return None    # ← ovdje smo izgubili dividendu

Pošto je RAZNO move_type='entry', hook se odmah vratio sa None. Računovođa je accept-ovao ono što je matcher ponudio (RAZNO obaveza) i izvod je zatvoren protiv RAZNO naloga. Plaćanje je ostalo nepovezano na 20093 - Plaćanja u toku, vidljivo kao otvoreno saldo na “Plaćanja/Naplata u toku” u izvještajima – iako je novac fizički već otišao iz banke.

GL je tehnički ravnotežan (i pad sa banke i pad obaveze su u jednom paru, samo kroz pogrešnu putanju), ali stanje suspense konta je vodljivo, a izvještaji koji prate “plaćanja u toku” pokazuju lažni dug.

Zašto je originalni filter promašio

Filter move_type in ('in_invoice', 'in_refund') je bio prečica — pretpostavljao je da samo fakture dobavljača kreiraju stavke na payable kontu. To je najčešći scenarij ali nije jedini:

  • Manualna knjiženja (RAZNO) za isplate dividende, kazne, donacije, ostale obaveze.
  • Knjiženje plata koje često bukira obaveze prema radnicima/fondovima na payable kontima preko payroll naloga (move_type='entry').
  • Privremena knjiženja kod prebacivanja salda između dobavljača (npr. kompenzacije) gdje se manualno kreira par stavki na payable kontu.

Sve ove stavke izgledaju identično kao stavka fakture dobavljača iz perspektive konta — payable konto, partner, iznos. Razlika je samo u move_type polju roditeljskog naloga, što nije relevantno za logiku usaglašavanja.

Šta smo promijenili u 16.0.1.1.0

Diskriminator pomjeren sa nivoa naloga na nivo same stavke:

# nova logika
if aml.account_id.account_type != 'liability_payable':
    return None

Drugim riječima: ako je matchovana stavka na payable kontu, hook radi posao – bez obzira da li je njen roditelj faktura, manualno knjiženje, payroll nalog, ili bilo šta drugo.

Pored toga:

  • Strategija 1 (praćenje partial-reconcile lanca) sad čita iz same matchovane stavke umjesto da iterira sve sibling payable stavke na nalogu.
  • Strategija 2 (traženje neuparenog plaćanja po partneru i iznosu) koristi abs(aml.balance) umjesto move.amount_total. Tačnije za parcijalna plaćanja i multi-currency naloge gdje payable stavka ne mora imati isti iznos kao ukupan iznos naloga.
  • Smjer plaćanja (outbound/inbound) se sada izvodi iz debit/credit znaka same stavke – tako da i obrnuti tok (povrat od dobavljača preko inbound plaćanja) bude pokriven simetrično.

Tipovi obaveza koje su sada pokrivene

Sve što završi sa stavkom na kontu tipa liability_payable:

  • ✅ Fakture dobavljača (in_invoice, in_refund) — isto kao prije
  • ✅ Manualna knjiženja obaveza (RAZNO, entry) — isplate dividende, kompenzacije, kazne
  • ✅ Payroll obaveze knjiženje preko entry naloga
  • ✅ Privremena knjiženja na “ostali dobavljači” kontima
  • ✅ Inbound flow (povrat od dobavljača) — Strategija 2 sada bira payment_type iz znaka stavke

Smoke test

Prije commit-a smo simulirali novu Strategiju 2 protiv već zatvorene grupe nepovezanih plaćanja u našoj produkciji. Na slučaju iz uvoda, pretraga account.payment.search na partneru dividende + iznos + is_matched=False + payment_type=outbound u manje od 50ms vraća upravo ono plaćanje koje je trebalo biti uparen sa izvodom. Bug je u smislu reproduciran i fix verifikovan.

Da bi se aktivirala promjena na već postojećim “viseším” plaćanjima, dovoljno je:

  1. Razdvojiti pogrešno upareni izvod (od RAZNO obaveze).
  2. Ponovo otvoriti reconcile formu za istu izvodnu stavku.
  3. Sada novi modul predlaže 20093 (Plaćanja u toku) stranu plaćanja kao primarni kandidat – računovođa potvrđuje i matching je tačan.

Verzija i zavisnosti

PoljeVrijednost
Modulreconcile_payment_priority
Verzija16.0.1.1.0 (sa 16.0.1.0.0)
Odoo serija16.0
Zavisi odaccount, account_reconcile_oca
LicencaAGPL-3
Repogithub.com/bringout/odoo-bringout-reconcile_payment_priority

Migracija nije potrebna — postojeća plaćanja se ne diraju automatski; samo nova ili ručno otvorena uparivanja koriste novu logiku.

Lekcija za druge timove

Ako pišete custom Odoo override hook koji se bavi računovodstvenim transakcijama, pažljivo birajte diskriminator. Filter na nivou stavke (account_id.account_type, account_id.reconcile, partner_id) je gotovo uvijek robusniji od filtera na nivou naloga (move_type). Move type je dobra heuristika za “koji formular to dolazi iz”, ali ne garantuje šta zapravo se nalazi u stavkama. Dvoje istih obrazaca knjiženja mogu doći iz različitih move_type putanja — i obrnuto.

To je posebno bitno u BiH kontekstu gdje smo skloni RAZNO nalozima za sve što ne pase u standardni Odoo invoice/payment flow (raspodjela dobiti, kompenzacije, korekcije, prijenosi između firmi).

Napomena

Generisano od strane Claude 🤖


Ernad Husremović, hernad@bring.out.ba