Továbbugrás a tartalomhoz

Odoo 19 Community: piszkozatszámlák összevonása – nyílt forráskódú Merge Draft Invoices modulunk

2026. szeptember 18. által
Odoo 19 Community: piszkozatszámlák összevonása – nyílt forráskódú Merge Draft Invoices modulunk
Alexander Biringer | Biricon IT Services GmbH

Aki az Odoo-ban megrendelésekből, helpdesk-jegyekből és időnyilvántartásból számláz, ismeri az eredményt: egy ügyfél a hónap végén nem egy, hanem öt számlát kap. Mindegyik másik megrendelésből vagy jegyből származik, mindegyik szakmailag helyes – és az ügyfél mégis megkérdezi, hogy nem férne-e el mindez egyetlen dokumentumon.

Pontosan erre nincs tiszta megoldás az Odoo 19 Community-ben. Az ismert OCA-modul, az account_invoice_merge az Odoo 19-hez még nincs kiadva, és olyan módon oldja meg a problémát, amely a szolgáltatók számára komoly kockázatot jelent: az azonos tételeket összevonja, és ezzel elvész a kapcsolat a megrendeléshez, a feladathoz és a rögzített időhöz.

Saját Odoo 19 Community-telepítésünkhöz ezért kifejlesztettük a Merge Draft Invoices modult. Mivel ez a probléma nem csak minket érint, a szabad AGPL-3-licenc alatt ingyenesen elérhetővé tesszük a GitHubon.

A projekthez a GitHubon:

Odoo 19 Merge Draft Invoices

Miért saját modul az OCA-megoldás helyett?

Az OCA évek óta gondozza az account_invoice_merge modult az OCA/account-invoicing tárolóban. E bejegyzés időpontjában a 19.0-ra történő migráció ott még nyitott pull request, nem pedig közzétett modul.

Fontosabb azonban, hogy a két modul különböző dolgokat csinál:


OCA account_invoice_mergeMerge Draft Invoices
Eredménya kiválasztott számlák egyikébe vonja összemindig egy új számla
Tételekaz azonos tételeket összevonja, a mennyiségeket összeadjaminden tételt egy az egyben átvesz
Eredetinvoice_origin / payment_reference a fejlécben összefűzveaz eredetmezők tételenként az Odoo saját _copy_data_extend_business_fields hookján keresztül másolva
Időnyilvántartásnem veszi figyelembea timesheet_invoice_id átkerül az új számlára
Olvasható az ügyfél számárasemmifejléc a tételek felett minden forrásnál, a megrendeléssel és a jeggyel
Forrásszámláksztornózásra kerülneksztornózás (alapértelmezett), törlés vagy megtartás – egyértelműen megnevezett következményekkel

Az azonos tételek összevonása a döntő különbség. Egy összevont tétel csak egy eredetet hordozhat. Amint két különböző megrendelésből származó két sor egyformának látszik, megszakad a kapcsolat a számlától vissza a megrendelésig, a feladatig és az időkönyveléshez. Egy olyan szolgáltató vállalkozásnál, ahol az elszámolás a Ticket → Időnyilvántartás → Számla útvonalon fut, ez azt jelenti: ugyanazokat az órákat kétszer számlázzák ki, vagy eltűnnek.

Modulunk ezért alapvetően semmit nem von össze. Az összevont számlának pontosan annyi tétele van, mint a forrásainak együttvéve.

Az OCA-modulból nem vettünk át kódot. Mindkét modul AGPL-3 alatt áll.

Mit csinál a modul

A számlalista nézetben jelöljön ki két vagy több piszkozatot, a műveleti menüben válassza a Piszkozatszámlák összevonása lehetőséget – egy varázsló megmutatja a kijelölést, az ellenőrzéseket és a forrásszámlákra vonatkozó beállításokat. A megerősítés után közvetlenül az új számlán köt ki.

Az összevonás előtt a modul ellenőriz, mégpedig az összes pontot egyszerre, hogy ne minden javítás után a következő hibát lássuk:

  • legalább két számla kijelölve
  • mind Piszkozat állapotban
  • egyiket sem könyvelték soha (a piszkozatra visszaállított bizonylat megtartja a könyvelési előzményeit, és elutasításra kerül)
  • egyiket sem vonták még össze
  • mind számla, szállítói számla, jóváíró számla vagy bizonylat – nem tisztán könyvelési tételek
  • azonos partner, bizonylattípus, vállalkozás, pénznem és napló

A fizetési feltételben, adó-hozzárendelésben, szállítási címben, bankszámlában vagy értékesítőben mutatkozó eltérések nem blokkolnak. A varázsló figyelmeztet, és a legrégebbi kijelölt számla értékét veszi át.

Ami megmarad

A modul lényege, hogy minden kapcsolat, amelyet egy számlatétel az eredetéhez fűz, az új számlán is létezik:

KapcsolatKezelés
Értékesítési megrendelés tételei (sale_line_ids)tételenként az Odoo _copy_data_extend_business_fields hookján keresztül másolva
Beszerzési megrendelés tételei (purchase_line_id)ugyanígy
Költséghelyi megosztás (analytic_distribution)tételenként másolva
egyéb eredetmezők tételenkéntautomatikusan, ha a szállító modul implementálja a dokumentált Odoo-hookot
Eredet és hivatkozás a számla fejlécébenösszevonva, duplikátumoktól megtisztítva, a varázslóban szerkeszthető
Értékesítési megrendelés: invoice_ids, invoice_status, qty_invoiceda tételekből kerülnek kiszámításra – a megrendelés magától felismeri az új számlát
Időnyilvántartás (timesheet_invoice_id)az új számlára kerül át, mielőtt a források érvénytelenné válnak
Helpdesk-jegyaz időnyilvántartáshoz kapcsolódik, és ezáltal automatikusan az új számlára mutat
Chatterüzenet az új számlán az összes forrással, üzenet minden forráson az újra mutató hivatkozással
merged_into_move_id / merged_from_move_idsmentett kapcsolat mindkét irányban

Az adósorokat, fizetési feltételi sorokat, kerekítési és skontósorokat nem másolja, hanem az Odoo számolja újra a tartalomból. Az összevont számlának tehát adókulcsonként egy adósora van, nem forrásonként egy. Számozatlan piszkozatként jön létre; maga az összevonás nem használ fel bizonylatszámot.

Fejlécek: az ügyfél látja, honnan származik az egyes tételek

Ez az a funkció, amely a mindennapokban különbséget jelent. Az egyes forrásszámlák tételei fölé a modul egy szakaszsort helyez – ugyanazt az elemet, amelyet az Odoo maga is használ az „Előlegek” szakaszhoz:

BE10181                                     <- Fejléc
  22,500 x Technikusi óra         3.577,50
                    Részösszeg    3.577,50
BE10182 · Ticket: HT00219                   <- Fejléc
   3,000 x Technikusi óra           477,00
                    Részösszeg      477,00
                      NETTÓ ÖSSZEG 4.054,50

A fejléc rákerül az ügyfélnek átadott dokumentumra, és az Odoo szabványos számlajelentése magától kiegészít egy részösszeget szakaszonként. Így az ügyfél azt is látja, mennyibe került az egyes rész.

A felirat abból áll össze, amivel a forrás ténylegesen rendelkezik:

  1. a megrendelések, közvetlenül a tételkapcsolatokból – a nevek így pontosak; ha hiányoznak a megrendelés-kapcsolatok, az invoice_origin szabad szövege kerül felhasználásra
  2. a ticketek, az időnyilvántartáson keresztül meghatározva – megjelenítve Ticket: HT00219 vagy Tickets: … formában, legfeljebb ötre korlátozva, plusz „és N további”
  3. ha egyik sincs: a forrásszámla száma, majd a hivatkozása
  4. ha semmi sincs: egy semleges „További tételek”, hogy egy forrás sorai soha ne tűnjenek el csendben a fölötte lévő blokkban

Ami hiányzik, azt elhagyja, nem találja ki. A ticket a saját számával kerül kinyomtatásra – helpdesk_mgmt-szám, Enterprise-ticket_ref vagy a modell megjelenített neve – soha nem az adatbázis-azonosítóval.

A fejlécek az ügyfél nyelvén íródnak, ahogyan az Odoo is teszi, amikor megrendelésekből számlákat hoz létre. A Chatter a felhasználó nyelvén marad.

Egy fejléc nem hordoz terméket, mennyiséget, árat, adót, számlát és költséghelyi megosztást. Nem befolyásolhatja az összegeket, az adóalapot és a költségszámítást. Aki a varázslóban kikapcsolja a fejléceket, pontosan azt a számlát kapja, amely ezen funkció nélkül keletkezne – egy teszt fillérre pontosan összeveti a két eredményt.

Mi történik a forrásszámlákkal

A varázsló három lehetőséget kínál:

  • Sztornózás (alapértelmezett, ajánlott). Egy piszkozat sztornózása következmények nélküli: nincs bizonylatszám, nincs könyvelés. A számlák sztornózott bizonylatként, Chatterrel és az új számlára mutató hivatkozással maradnak az adatbázisban. Az értékesítési megrendelés qty_invoiced mezője átugorja a sztornózott bizonylatokat, semmi nem számít kétszer. Ez az a lehetőség, amely hat hónap múlva is követhető.
  • Törlés. Visszavonhatatlan. A Chatter és a visszahivatkozás az adatrekorddal együtt megszűnik; csak az új számlán lévő üzenet marad. Értelmes az eldobható piszkozatoknál, amelyeket senkinek sem kell többé látnia.
  • Piszkozatként hagyás. A források nyitva maradnak. Értékesítési megrendeléseik ekkor a forrást és az új számlát is kiszámlázottként számolják – a munka kétszer elszámoltnak látszik, amíg valaki kézzel ki nem takarítja a piszkozatokat. Arra a ritka esetre szánt, amikor a döntés előtt össze szeretnénk hasonlítani. Egy teszt éppen ezt a kettős számolást rögzíti, hogy ne lepjen meg senkit.

Korlátok – amit a modul szándékosan nem tesz

Kérjük, éles használat előtt olvassa el:

  • Csak piszkozatok. A könyvelt számlákat nem vonja össze. Ez jóváíró számlás feladat, nem másolási folyamat.
  • Az egyszer könyvelt, visszaállított piszkozatokat elutasítja. Van számuk és könyvelési előzményük; ennek egy másik dokumentumban való elrejtése nem olyasmi, amit egy tömeges művelet csendben elintézhet.
  • Nincs összevonás partnerek, pénznemek, vállalkozások vagy naplók között. Ehhez nincs értelmes egyetlen érték, ezért a modul elutasítja, ahelyett hogy találgatna.
  • A payment_reference nem kerül átvételre. A strukturált fizetési hivatkozások egy bizonylatot azonosítanak; kettő összefűzve semmire sem illik a banknál. Az új számla könyveléskor megkapja a sajátját.
  • Az előlegtételeket úgy másolja, mint bármely más tételt. Ha a források a sale modulból származó előlegsorokat tartalmaznak, az eredményt könyvelés előtt ellenőrizni kell.
  • Csak a timesheet_invoice_id kerül automatikusan átkötésre. Minden más, account.move-ra mutató Many2one-nal rendelkező modell (saját elszámolási futások, előfizetési kapcsolatok, EDI-átviteli folyamatok) továbbra is a forrásra mutat. Erre való a _merge_draft_relink hook.
  • Nincs azonos tételek összevonása – szándékosan. Aki rövid, rendezett számlát szeretne, rossz helyen jár, és az eredetkapcsolatokkal fizetne érte.
  • A fejlécek egyszer, az összevonáskor keletkeznek. Ezután normál szakaszsorok: szerkeszthetők, törölhetők, és nem frissülnek, ha a megrendelést vagy a ticketet később átnevezik.
  • Egy fejléc a teljes forrásszámla ticketjeit nevezi meg, nem az egyes tételekét.

Telepítés az Odoo 19 Community-ben

A telepítés ugyanúgy történik, mint egy szokásos Odoo-kiegészítő modulnál:

  1. A modulkönyvtárat másolja be egy beállított addons-útvonalra.
  2. Frissítse az alkalmazáslistát az Odoo-ban.
  3. Telepítse az account_invoice_merge_draft modult.

A modul csak az account-tól függ. Mindazt, amit a sale, purchase, project, hr_timesheet, sale_timesheet vagy egy helpdesk-modul felől tud, futásidőben határozza meg – egy tisztán számlázási adatbázison is települ és működik.

Ezután: Könyvelés → Vevők → Számlák (vagy Szállítók → Számlák), jelöljön ki két vagy több piszkozatot, fogaskerék-menü → Piszkozatszámlák összevonása. A művelet minden olyan felhasználó számára elérhető, aki az Elszámolás / Számlázás csoport tagja.

Aki a modul egy korábbi verziójáról frissít, egyszer futtassa a -u account_invoice_merge_draft --i18n-overwrite frissítést, hogy a módosított mezőmegnevezések megjelenjenek a német fordításban. Az új telepítést ez nem érinti.

Fejlesztőknek: API és hookok

Az összevonás saját kódból is meghívható:

python

merged = draft_moves.merge_draft_moves(
    extra_vals={"invoice_date": date(2026, 3, 31), "ref": "Q1"},
    source_handling="cancel",   # "delete" vagy "keep"
    add_source_sections=True,   # fejlécek; alapértelmezett True
)

A merge_draft_moves UserError-t dob az összes elutasítási okkal, ha a kijelölés nem vonható össze. A _merge_draft_get_errors() ugyanezeket az okokat listaként adja vissza, kivétel nélkül.

Aki saját visszahivatkozásokkal rendelkezik az account.move-ra, felülírja a _merge_draft_relink-et:

python

class AccountMove(models.Model):
    _inherit = "account.move"

    def _merge_draft_relink(self, new_move):
        super()._merge_draft_relink(new_move)
        if "my_move_id" not in self.env["my.model"]._fields:
            return
        self.env["my.model"].search([("my_move_id", "in", self.ids)]).write(
            {"my_move_id": new_move.id}
        )

Aki a számlatételen rendelkezik visszahivatkozással, azoknak erre a modulra egyáltalán nincs szükségük: az Odoo saját account.move.line._copy_data_extend_business_fields hookja elegendő, és a mező összevonáskor, sztornózáskor és duplikáláskor egyaránt átvételre kerül. Más helpdesk-modulokhoz vagy a fejlécek másféle megfogalmazásához ott van a _merge_draft_get_source_tickets() és a _merge_draft_section_name().

Tesztelve, mielőtt éles adatokon futna

48 teszt fedi le a vegyes állapotokat, a különböző partnereket, pénznemeket és bizonylattípusokat, az értékesítési vagy beszerzési megrendeléssel rendelkező és azok nélküli tételeket, az adókat, szakaszokat és jegyzeteket, a költséghelyi megosztásokat, az időnyilvántartás átkötését, a forrásszámlákra vonatkozó mindhárom lehetőséget, a varázslót és a fejléceket – hogy alapértelmezetten aktívak, hogy kikapcsolásuk fillérre pontosan reprodukálja a régi eredményt, hogy egy fejléc nem hordoz összegeket vagy számlákat, hogy egy forrás tételei együtt maradnak, hogy a ticket a saját számával jelenik meg, és soha nem az adatbázis-azonosítóval.

A tesztadatok az aktív vállalkozás meglévő számlatükrére épülnek, nem az AccountTestInvoicingCommonra – ez a helper a migrált éles adatbázisokon gyakran nem indul el, és a modulnak éppen ilyeneken kell futnia.

odoo-bin -d <db> -u account_invoice_merge_draft --test-enable \
         --test-tags /account_invoice_merge_draft --stop-after-init

Mint minden könyvelési területen alkalmazott bővítménynél, javasoljuk, hogy a telepítést először tesztkörnyezetben, a saját adatbázis másolatával ellenőrizze.

Ingyenes és nyílt forráskódú az Odoo Community számára

Mi, a Biricon IT Services GmbH-nál, a megoldásokat először a saját üzemünk konkrét igényeire fejlesztjük. Ha ebből általánosan használható modul születik, nem szeretnénk egyetlen telepítésben elrejteni.

A Merge Draft Invoices ezért ingyenesen, nyílt forráskódú projektként elérhető. A forráskód megtekinthető, ellenőrizhető, módosítható és az AGPL-3-licenc keretein belül továbbfejleszthető.

Célunk nem a lehető legrövidebb számla volt, hanem egy olyan számla, amelyen egy év múlva is minden tétel visszavezet a megrendeléséhez, a ticketjéhez és az időkönyveléséhez.

Projekt, forráskód és közreműködés

A teljes forráskód, a telepítési útmutató és a műszaki dokumentáció elérhető a GitHubon:

Az Odoo 19 Merge Draft Invoices megnyitása a GitHubon

Örülünk a gyakorlati tapasztalatoknak, hibajelentéseknek, fejlesztési javaslatoknak és az Odoo Community hozzájárulásainak.

Ingyenes. Követhető. Nyílt forráskódú. Az Odoo 19 Community számára.