Bosanska lokalizacija Odoo: Modul l10n_ba_auto_reconcile 16.0.1.3.1 - Pravilo 0, preview lista, provjera integriteta
O čemu se radi?
Modul l10n_ba_auto_reconcile postoji da automatizuje zatvaranje
otvorenih stavki glavne knjige po dva pravila:
- Pravilo 1 — stavke na istom kontu i istom partneru čiji rezidualni saldo iznosi nula
- Pravilo 2 — stavke u istoj klasi konta (prve dvije cifre) i istom partneru, gdje na nivou klase saldo iznosi nula, uz kreiranje preknjiženja između konta
Tokom dnevne upotrebe na produkcijskoj bazi naišli smo na klasu slučajeva koje pravila 1 i 2 nisu mogla zatvoriti — iako su stavke matematički bile uparene. Današnji update donosi Pravilo 0, preview listu, provjeru integriteta, i nekoliko bugfixova koji čine wizard pouzdaniji.
Verzije objavljene danas: 16.0.1.1.0 → 16.0.1.1.1 → 16.0.1.2.0 → 16.0.1.3.0 → 16.0.1.3.1.
Pravilo 0 — Finalizacija nezavršenih parcijalnih
Najveća promjena. U Odoo bazi smo zatekli desetine account_partial_reconcile redova kod kojih je full_reconcile_id bio prazan, iako su obje povezane stavke imale amount_residual = 0. Drugim riječima — uparivanje je matematički bilo završeno (parcijalni reconcile je potrošio kompletan saldo svih povezanih stavki), ali računovodstveni wrapper koji veže grupu — account.full.reconcile — nikad nije kreiran.
Zašto je to bilo nevidljivo
Odoo’s _compute_reconciled metod kalkuliše stored polje account.move.line.reconciled po pravilu:
if line.full_reconcile_id:
line.reconciled = True
elif line.matched_debit_ids or line.matched_credit_ids:
line.reconciled = float_is_zero(line.amount_residual, ...)
Drugi grananje znači: ako stavka ima parcijalni reconcile i rezidual = 0, Odoo je smatra zatvorenom — bez obzira na nedostatak full_reconcile_id. Posljedica: original wizard je filtrirao kandidate sa ('reconciled', '=', False) što je preskakalo upravo ovu klasu polu-zatvorenih stavki. One su godinama sjedile zaboravljene, blokiraju Open Items izvještaje i pojavljuju se kao “stara dugovanja” iako su zapravo plaćena.
Kako Pravilo 0 radi
Algoritam:
- SQL skenira sve
account_partial_reconcileredove gdje jefull_reconcile_id IS NULL, a obje linkovaneaccount_move_lineimajuamount_residual = 0i takođe nemajufull_reconcile_id. - Na grafu parcijalnih (čvor = stavka, ivica = parcijalni reconcile) se primjenjuje union-find algoritam za grupisanje povezanih komponenti.
- Za svaku komponentu (od po dvije ili više stavki) kreira se jedan
account.full.reconcilered. - Postojeći parcijalni i sve linkovane stavke dobijaju
full_reconcile_idpostavljen na novi wrapper.
@api.model
def _run_stale_partial_rule(self, results, dry_run=False):
"""Pravilo 0: finalizuje stale partial reconciliations."""
cur = self.env.cr
cur.execute("""
SELECT pr.id, pr.debit_move_id, pr.credit_move_id, pr.max_date
FROM account_partial_reconcile pr
JOIN account_move_line dml ON dml.id = pr.debit_move_id
JOIN account_move_line cml ON cml.id = pr.credit_move_id
WHERE pr.full_reconcile_id IS NULL
AND dml.amount_residual = 0
AND cml.amount_residual = 0
AND dml.full_reconcile_id IS NULL
AND cml.full_reconcile_id IS NULL
""")
# ... union-find, create full_reconcile, link partials and lines ...
Operacija je idempotentna — ako pokrenete wizard ponovo, naredni put broji se 0 jer SQL filter više ne pronalazi kandidate.
Šta Pravilo 0 NE radi
- Ne kreira nove parcijalne reconcile redove (postojeći su tačni).
- Ne mijenja saldo nijednog konta.
- Ne pravi nikakva knjiženja niti zaduženja.
To je čista metadata fix — popravljanje nedostajućih veza u bookkeeping sloju.
Preview lista — Stavke koje će biti zatvorene
Ranije je wizard nakon pokretanja prikazivao samo brojeve (npr. “Pravilo 1: zatvoreno 3 grupe, 6 stavki”). To nije dovoljno — operator nije mogao prije pokretanja vidjeti koje konkretno stavke će biti pogođene.
Sada wizard ima dva taba u rezultatu:
- Stavke (preview) — readonly tree sa svim stavkama koje će biti pogođene, kolone:
Pravilo(0_stale, 1_same, 1_pair, 2_class, 2_cross, integrity_*)Datum,Nalog,Konto,PartnerDuguje,Potražujesa sumama na dnu listeRezidualRazlog— slobodan tekst koji opisuje zašto je stavka pogođena
- Tekstualni rezultat — postojeći sažetak po pravilima
Ovo omogućava potpunu provjeru u Samo prikaz modu prije nego što kliknete Pokreni stvarno. Lista se dinamički gradi tokom svakog pravila — svaka stavka koja prolazi kroz reconcile logiku se prijavi u results['preview'] kroz {rule, line_id, reason} zapis.
Pravilo 1 — Zaštita od “naked full_reconcile”
Tokom prvog testiranja Pravila 0 na produkciji desila se još jedna manjа anomalija: dvije stavke su dobile full_reconcile_id postavljen, ali bez ijednog account_partial_reconcile reda ispod njega. Odoo je tu grupu vidio kao “kreiranu”, ali bez podloge.
Uzrok: kada Pravilo 1 pozove aml.reconcile() na stavkama čiji je amount_residual = 0 već prije ulaska u poziv (npr. zato što ih je upravo finalizovalo Pravilo 0 u istom run-u), Odoo’s _reconcile_plan_execute u tom slučaju kreira account.full.reconcile ali ne kreira nikakav novi parcijalni — jer nema neutrošenog rezidualа za potrošiti.
Rezultat: gola full_reconcile, lista stavki ide u nju ali bookkeeping veza je nepotpuna. _compute_reconciled ne reaguje jer ne mijenja se nijedna od polja od kojih zavisi (matched_debit_ids, matched_credit_ids, amount_residual). Stavka ostaje vidljiva u Open Items.
Fix: Pravilo 1 sada filtrira na ulazu — odbacuje stavke sa amount_residual = 0. Takve stavke su ili stvarno zatvorene, ili u stale-partial stanju koje Pravilo 0 obrađuje. Pravilo 1 se ne miješa.
lines = self._get_unreconciled_lines().filtered(
lambda l: abs(l.amount_residual) >= ROUNDING_PRECISION
)
Pored toga, Pravilo 0 sada eksplicitno upisuje reconciled=True zajedno sa full_reconcile_id, kako bi stored compute polje bilo konzistentno bez čekanja na re-trigger:
Line.browse(line_ids).write({
'full_reconcile_id': full.id,
'reconciled': True,
})
Provjera integriteta nakon svakog pokretanja
Najvažniji UX dodatak. Wizard nakon završetka pokretanja izvršava tri provjere bookkeeping invarijanti i prikazuje rezultat kao color-coded banner na vrhu forme.
Tri invarijante
-
Saldo svake
account.full.reconcilegrupe = 0Suma
balancepolja svih stavki povezanih jednimfull_reconcile_idmora biti 0. Ako nije, grupa je u pokvarenom stanju (npr. zaostala iz nekonzistentne transakcije). -
Nema “praznih grupa” (bez parcijalnih)
Svaki
account.full.reconcilered mora imati barem jedanaccount.partial.reconcilekoji ga referencira. Ako nema — to je upravo “naked full_reconcile” anomalija opisana iznad. -
Nema nezavršenih parcijalnih
Nakon Pravila 0, ne smije ostati ni jedan
account_partial_reconcilesafull_reconcile_id IS NULLčije obje stavke imaju rezidual = 0.
Banner
Kada sve tri provjere prođu — zelena alert traka na vrhu forme:
✓ Integritet OK: Sve provjere integriteta su prošle — 1223 zatvorenih
grupa, saldo=0 svuda, nema praznih grupa (bez parcijalnih), nema
nezavršenih parcijalnih.
Kada nešto nije u redu — crvena alert traka sa specifičnim brojkama:
⚠ Integritet problem: 3 grupa sa saldom različitim od 0;
1 praznih grupa (bez parcijalnih)
Ispod, u Stavke (preview) tabu, pojavljuju se konkretne stavke u problematičnim grupama, sa rule oznakom integrity_broken ili integrity_naked da operator može odmah otići do njih.
Vrijednost
Provjera integriteta je continuous health check — pokreće se nakon svakog Pokreni, čak i ako nijedno pravilo nije pronašlo kandidate. Rana detekcija anomalija u account_full_reconcile / account_partial_reconcile sloju je daleko jeftinija nego forenzički ispravljati ih nakon mjeseci.
Bosanske oznake
Ranije verzije su koristile direktne engleske termine u izvještaju (“naked full_reconcile”, “stale partials”). Sada wizard u potpunosti komunicira na bosanskom:
| Engleski (16.0.1.2.0) | Bosanski (16.0.1.3.1) |
|---|---|
| naked full_reconcile | prazne grupe (bez parcijalnih) |
| stale partials | nezavršeni parcijalni |
| saldo != 0 | saldo različit od 0 |
| Reconciled | Zatvoreno |
Operator i računovodstvo dobijaju lokaliziranu poruku — manje frikcije pri svakodnevnom korištenju.
Verzija i deploy
| Polje | Vrijednost |
|---|---|
| Modul | l10n_ba_auto_reconcile |
| Verzija | 16.0.1.3.1 (sa 16.0.1.0.0) |
| Odoo serija | 16.0 |
| Zavisi od | account |
| Licenca | AGPL-3 |
| Repo | github.com/bringout/odoo-bringout-l10n_ba_auto_reconcile |
Migracija nije potrebna — postojeći podaci se ne diraju automatski. Kada operator prvi put pokrene wizard nakon update-a, Pravilo 0 će obraditi sve nakupljene stale-partial slučajeve (kod nas je to bilo 31 grupa, 67 stavki, 36 parcijalnih).
Kratki zaključci za druge timove
-
Računajte na to da Odoo’s
reconciledflag nije pouzdana mjera zatvorenosti stavke. Za heath-check upite radije provjeravajte direktnofull_reconcile_id IS NOT NULLili balansirajte sumiranje poaccount_full_reconcilegrupama. -
Direktni
full_reconcile_idupis kroz ORM ne uvijek povlači re-compute stored polja koja od njega zavise. Eksplicitno upisivanjereconciled=Trueu istom write-u je sigurnije. -
Preview lista u svakom batch-tipu wizardu štedi sate analize. Ako vaš modul mijenja desetinu redova — neka operator vidi koje, prije nego što klikne Apply.
-
Continuous integrity checks su jeftine kada su izražene kao dva-tri SQL upita. Za GL provjeru:
SUM(balance) per full_reconcile_id, plus orphan / dangling detekcija. Stavite ih iza svakog batch operatora.
Napomena
Generisano od strane Claude 🤖
Ernad Husremović, hernad@bring.out.ba