Wien an Odoo aus Opträg, Helpdesk-Tickete a Zäiterfaassung ofrechent, kennt d'Resultat: E Client kritt um Enn vum Mount net eng Rechnung, mee fënnef. All eenzel staamt aus engem anere Optrag oder Ticket, all ass fachlech korrekt – an trotzdem freet de Client, ob dat net op een Dokument géif passen.
Genau dofir gëtt et an Odoo 19 Community keng propper Léisung. Dat bekannt OCA-Modul account_invoice_merge ass fir Odoo 19 nach net fräigegeff, an et léist de Problem op eng Aart, déi fir Déngschtleeschter e seriéist Risiko duerstellt: Gläich Positioune ginn zesummegefaasst, a domat geet d'Verbindung zréck zum Optrag, zur Aufgab an zur erfaasster Zäit verluer.
Fir eis eege Odoo-19-Community-Installatioun hu mir dofir de Modul Merge Draft Invoices entwéckelt. Well dëse Problem net nëmmen eis betrëfft, stellen mir en ënner der fräier AGPL-3-Lizenz gratis op GitHub zur Verfügung.
Zum Projet op GitHub:
Firwat e eegene Modul amplaz vun der OCA-Léisung?
D'OCA pflegt zënter ville Joren account_invoice_merge am Repository OCA/account-invoicing. Zum Zäitpunkt vun dësem Bäitrag ass d'Migratioun op 19.0 do nach en oppene Pull Request, kee verëffentlechte Modul.
Méi wichteg ass awer, dass déi zwee Moduler ënnerschiddlech Saache maachen:
| OCA account_invoice_merge | Merge Draft Invoices | |
|---|---|---|
| Resultat | gëtt an eng vun den ausgewielte Rechnunge zesummegeféiert | ëmmer eng nei Rechnung |
| Positiounen | gläich Positioune ginn zesummegefaasst, Quantitéite ginn addéiert | all Positioun gëtt eent zu eent iwwerholl |
| Hierkonft | invoice_origin / payment_reference am Kapp zesummegehaangen | Hierkonftsfelder pro Positioun iwwer dem Odoo säin eegenen _copy_data_extend_business_fields-Hook kopéiert |
| Zäiterfaassung | net berécksiichtegt | timesheet_invoice_id gëtt op déi nei Rechnung ëmgehaange |
| Liesbar fir de Client | näischt | eng Iwwerschrëft iwwer de Positioune vun all Quell mat Optrag an Ticket |
| Quellrechnungen | ginn stornéiert | stornéieren (Standard), läschen oder behalen – mat kloer benannte Konsequenzen |
D'Zesummefaassen vu gläiche Positioune ass dee entscheedenden Ënnerscheed. Eng zesummegefaasst Positioun ka just eng Hierkonft droen. Soubal zwou Zeilen aus zwee verschiddenen Opträg gläich ausgesinn, ass d'Verbindung vun der Rechnung zréck zum Optrag, zur Aufgab an zur Zäitbuchung fort. An engem Déngschtleeschtungsbetrib, an deem d'Ofrechnung iwwer Ticket → Zäiterfaassung → Rechnung leeft, heescht dat: Déi selwecht Stonne ginn duebel verrechent oder verschwannen.
Eise Modul faasst dofir grondsätzlech näischt zesummen. Déi zesummegeféiert Rechnung huet exakt esou vill Positiounen wéi hir Quellen zesummen.
Et gouf kee Code aus dem OCA-Modul iwwerholl. Béid Moduler stinn ënner AGPL-3.
Wat de Modul mécht
An der Rechnungslëscht-View zwee oder méi Entwërf markéieren, am Aktiounsmenü Rechnungsentwërf zesummeféieren wielen – en Assistent weist d'Auswiel, d'Préifungen an d'Optioune fir d'Quellrechnungen. Nom Bestätegen landet een direkt op der neier Rechnung.
Virum Zesummeféiere préift de Modul, an zwar all Punkten op eemol, fir dass een net no all Korrektur den nächste Feeler gesäit:
- mindestens zwou Rechnunge ausgewielt
- all am Status Entworf
- keng gouf jeemools verbucht (e Beleg, deen op Entworf zréckgesat gouf, behält seng Verbuchungshistorie a gëtt ofgeleent)
- keng gouf scho zesummegeféiert
- all sinn Rechnung, Lieferantenrechnung, Gutschrëft oder Beleg – keng reng Verbuchungssätz
- selwechte Partner, Belegtyp, Entreprise, Währung a Journal
Ënnerscheeder bei Zuelungsbedingung, Steierzouuerdnung, Liwweradress, Bankkonto oder Verkeefer blockéieren net. Den Assistent warnt an iwwerhëlt de Wäert vun der eelster ausgewielter Rechnung.
Wat erhale bleift
De Kär vum Modul ass, dass all Verbindung, déi eng Rechnungspositioun zu hirer Hierkonft huet, och op der neier Rechnung existéiert:
| Verknëppung | Behandlung |
|---|---|
| Verkafsoptragspositiounen (sale_line_ids) | pro Positioun iwwer Odoo säin _copy_data_extend_business_fields kopéiert |
| Akafsoptragspositiounen (purchase_line_id) | genee sou |
| Käschtestellenverdeelung (analytic_distribution) | pro Positioun kopéiert |
| aner Hierkonftsfelder pro Positioun | automatesch, wann de liwwerende Modul den dokumentéierten Odoo-Hook implementéiert |
| Hierkonft a Referenz am Rechnungskapp | zesummegeféiert, dedupliséiert, am Assistent editéierbar |
| Verkafsoptrag: invoice_ids, invoice_status, qty_invoiced | ginn aus de Positioune berechent – den Optrag erkennt déi nei Rechnung vun eleng |
| Zäiterfaassung (timesheet_invoice_id) | gëtt op déi nei Rechnung ëmgehaange, ier d'Quelle ongëlteg ginn |
| Helpdesk-Ticket | hänkt un der Zäiterfaassung a weist doduerch automatesch op déi nei Rechnung |
| Chatter | Noriicht op der neier Rechnung mat alle Quellen, Noriicht op all Quell mat Link zur neier |
| merged_into_move_id / merged_from_move_ids | gespäichert Verknëppung an déi zwou Richtungen |
Steierzeilen, Zeilen vun der Zuelungsbedingung, Ofrënnungs- a Skontozeile ginn net kopéiert, mee vun Odoo aus dem Inhalt nei berechent. Déi zesummegeféiert Rechnung huet also eng Steierzeil pro Steiersaz, net eng pro Quell. Si gëtt onnummeréiert als Entworf ugeluecht; d'Zesummeféiere selwer verbraucht keng Belegnummer.
Iwwerschrëften: De Client gesäit, vu wou all Positioun staamt
Dat ass d'Funktioun, déi am Alldag den Ënnerscheed mécht. Iwwer de Positioune vun all Quellrechnung setzt de Modul eng Ofschnëttszeil – dat selwecht Element, dat Odoo selwer fir den Ofschnëtt „Acompten" benotzt:
BE10181 <- Iwwerschrëft
22,500 x Technikerstonn 3.577,50
Zwëschesumm 3.577,50
BE10182 · Ticket: HT00219 <- Iwwerschrëft
3,000 x Technikerstonn 477,00
Zwëschesumm 477,00
NETTOBETRAG 4.054,50
D'Iwwerschrëft gëtt um Dokument gedréckt, dat de Client kritt, an dem Odoo säi Standard-Rechnungsbericht ergänzt vun sech aus eng Zwëschesumm pro Ofschnëtt. De Client gesäit doduerch och, wat all Deel kascht huet.
D'Beschriftung gëtt aus deem zesummegesat, wat d'Quell tatsächlech huet:
- d'Opträg, direkt aus de Positiounsverknëppungen – d'Nimm sinn doduerch exakt; feele Optragsverknëppungen, gëtt de Fräitext aus invoice_origin benotzt
- d'Tickete, iwwer d'Zäiterfaassung ermëttelt – ausgi als Ticket: HT00219 oder Tickets: …, begrenzt op fënnef plus „an N weider"
- gëtt et béides net: d'Nummer vun der Quellrechnung, duerno hir Referenz
- gëtt et guer näischt: en neutrale „Weider Positiounen", fir dass d'Zeile vun enger Quell ni roueg am Block driwwer verschwannen
Wat feelt, gëtt ewechgelooss, net erfonnt. D'Ticket gëtt mat senger eegener Nummer gedréckt – helpdesk_mgmt-Nummer, Enterprise-ticket_ref oder den Uweisungsnumm vum Modell – ni mat der Datebank-ID.
D'Iwwerschrëfte ginn an der Sprooch vum Client geschriwwen, esou wéi Odoo et beim Erstelle vu Rechnungen aus Opträg mécht. De Chatter bleift an der Sprooch vum Notzer.
Eng Iwwerschrëft dréit kee Produkt, keng Mengt, kee Präis, keng Steier, kee Konto a keng Käschtestellenverdeelung. Si kann Summen, Steierbasis a Käschterechnung net beaflossen. Wien d'Iwwerschrëften am Assistent ausschalt, kritt exakt déi Rechnung, déi ouni dës Funktioun entstanen wier – en Test vergläicht béid Resultater bis op de Cent.
Wat mat de Quellrechnunge geschitt
Den Assistent bitt dräi Optiounen:
- Stornéieren (Standard, recommandéiert). Dat Stornéieren vun engem Entworf ass folgenlos: keng Belegnummer, keng Buchung. D'Rechnunge bleiwen als stornéiert Belege mat Chatter a Link zur neier Rechnung an der Datebank. qty_invoiced um Verkafsoptrag iwwerspréngt stornéiert Belege, näischt gëtt duebel gezielt. Dat ass d'Optioun, déi och an sechs Méint nach nachvollziehbar ass.
- Läschen. Onwiderruflech. Chatter a Réckverweis stierwen mam Datesaz; nëmmen d'Noriicht op der neier Rechnung bleift. Sënnvoll fir Wegwerf-Entwërf, déi keen méi gesi soll.
- Als Entworf loossen. D'Quelle bleiwen oppen. Hir Verkafsopträg zielen dann Quell an nei Rechnung als fakturéiert – d'Aarbecht gesäit duebel ofgerechent aus, bis een d'Entwërf vun Hand botzt. Geduecht fir de seltenen Fall, dass ee virun der Entscheedung wëll vergläichen. En Test hält genau dës Duebelzielung fest, fir dass se kee iwwerrascht.
Grenzen – wat de Modul bewosst net mécht
W.e.g. virum Produktiveinsatz liesen:
- Nëmmen Entwërf. Verbuchte Rechnunge ginn net zesummegeféiert. Dat ass eng Gutschrëften-Aufgab, kee Kopéiervirgang.
- Eemol verbucht, zréckgesaten Entwërf ginn ofgeleent. Si hunn eng Nummer an eng Verbuchungshistorie; dat an engem anere Dokument ze verstoppen ass näischt, wat eng Sammelaktioun roueg soll erledegen.
- Kee Zesummeféiere iwwer Partner, Währungen, Entreprisen oder Journaler ewech. Et gëtt dofir keen sënnvollen Eenzelwäert, also leent de Modul of, amplaz ze roden.
- payment_reference gëtt net iwwerholl. Strukturéiert Zuelungsreferenze identifizéieren e Beleg; zwou zesummegehaangen passen op näischt bei der Bank. Déi nei Rechnung kritt beim Verbuche hir eege.
- Acomptepositioune ginn wéi all aner Positioun kopéiert. Enthalen d'Quelle Acomptezeile aus sale, ass d'Resultat virum Verbuche ze préiwen.
- Nëmmen timesheet_invoice_id gëtt automatesch ëmgehaange. All aner Modell mat engem Many2one op account.move (eege Ofrechnungsläf, Abo-Verknëppungen, EDI-Iwwermëttlungen) weist weiderhin op d'Quell. Dofir gëtt et den Hook _merge_draft_relink.
- Keng Zesummefaassung vu gläiche Positiounen – absichtlech. Wien eng kuerz, opgeraumt Rechnung wëll, ass hei falsch a géif dofir mat de Hierkonftsverknëppunge bezuelen.
- Iwwerschrëfte ginn eemoleg beim Zesummeféiere generéiert. Duerno sinn et normal Ofschnëttszeilen: editéierbar, läschbar an net aktualiséiert, wann Optrag oder Ticket spéider ëmbenannt ginn.
- Eng Iwwerschrëft nennt d'Tickete vun der ganzer Quellrechnung, net vun der eenzeler Positioun.
Installatioun an Odoo 19 Community
D'Installatioun geschitt wéi bei engem üblechen Odoo-Zousazmodul:
- De Modulverzeechnes an e konfiguréierten Addons-Pfad kopéieren.
- D'App-Lëscht an Odoo aktualiséieren.
- De Modul account_invoice_merge_draft installéieren.
De Modul hänkt just vun account of. Alles, wat en iwwer sale, purchase, project, hr_timesheet, sale_timesheet oder e Helpdesk-Modul weess, gëtt zur Laufzäit ermëttelt – en installéiert a funktionéiert och op enger reiner Ofrechnungsdatebank.
Duerno: Comptabilitéit → Clienten → Rechnungen (oder Lieferanten → Rechnungen), zwee oder méi Entwërf markéieren, Zännrad-Menü → Rechnungsentwërf zesummeféieren. D'Aktioun steet allen Notzer mat der Grupp Ofrechnung / Fakturéierung zur Verfügung.
Wien vun enger fréierer Versioun vum Modul aktualiséiert, sollt eemol mat -u account_invoice_merge_draft --i18n-overwrite updaten, fir dass geännert Feldbezeichnunge an der däitscher Iwwersetzung ukommen. Eng Neiinstallatioun ass dovun net betraff.
Fir Entwéckler: API an Hooks
D'Zesummeféiere léisst sech och aus eegene Code ofruffen:
python
merged = draft_moves.merge_draft_moves(
extra_vals={"invoice_date": date(2026, 3, 31), "ref": "Q1"},
source_handling="cancel", # "delete" oder "keep"
add_source_sections=True, # Iwwerschrëften; Standard True
)
merge_draft_moves geheit en UserError mat allen Ofleenungsgrënn, wann d'Auswiel net zesummeféierbar ass. _merge_draft_get_errors() liwwert déiselwecht Grënn als Lëscht ouni Exception.
Wien eege Réckverweiser op account.move huet, iwwerschreift _merge_draft_relink:
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}
)
Wien e Réckverweis op der Rechnungspositioun huet, brauch dëse Modul guer net: dem Odoo säin eegenen Hook account.move.line._copy_data_extend_business_fields geet duer, an d'Feld gëtt beim Zesummeféieren, beim Stornéieren a beim Duplizéieren gläichermoossen iwwerholl. Fir aner Helpdesk-Moduler oder eng aner Formuléierung vun den Iwwerschrëften gëtt et _merge_draft_get_source_tickets() an _merge_draft_section_name().
Getest, ier et op Produktivdaten leeft
48 Tester decken gemëschte Statussen, ënnerschiddlech Partner, Währungen a Belegtypen of, Positiounen mat an ouni Verkafs- oder Akafsoptrag, Steieren, Ofschnëtter an Notizen, Käschtestellenverdeelungen, d'Ëmhänke vun der Zäiterfaassung, all dräi Optioune fir d'Quellrechnungen, den Assistent an d'Iwwerschrëften – dass se standardméisseg aktiv sinn, dass hiert Ausschalten dat ale Resultat bis op de Cent reproduzéiert, dass eng Iwwerschrëft keng Beträg oder Konte dréit, dass d'Positioune vun enger Quell zesummebleiwen, dass d'Ticket mat senger Nummer an ni mat der Datebank-ID erscheint.
D'Testdate bauen op dem virhandene Kontenplang vun der aktiver Firma op amplaz op AccountTestInvoicingCommon – dësen Helper start op migréierte Produktivdatebanke dacks net, an genau op esou enge soll de Modul lafen.
odoo-bin -d <db> -u account_invoice_merge_draft --test-enable \
--test-tags /account_invoice_merge_draft --stop-after-init
Wéi bei all Erweiderung am Comptabilitéitsberäich recommandéiere mir, d'Installatioun fir d'éischt an engem Testëmfeld mat enger Kopie vun der eegener Datebank ze préiwen.
Gratis an Open Source fir d'Odoo Community
Mir bei Biricon IT Services GmbH entwéckele Léisunge fir d'éischt fir konkret Ufuerderungen aus eisem eegene Betrib. Wann doraus e allgemeng notzbare Modul entsteet, wëlle mir en net an enger eenzeger Installatioun verstoppen.
Merge Draft Invoices steet dofir gratis als Open-Source-Projet zur Verfügung. De Quellcode kann ageséit, gepréift, ugepasst an am Rahmen vun der AGPL-3-Lizenz weiderentwéckelt ginn.
Eist Zil war net déi kierzestméiglech Rechnung, mee eng Rechnung, bei där och an engem Joer nach all Positioun zu hirem Optrag, hirem Ticket an hirer Zäitbuchung zréckféiert.
Projet, Quellcode a Matarbecht
De komplette Quellcode, d'Installatiounshiweiser an déi technesch Dokumentatioun si op GitHub verfügbar:
Odoo 19 Merge Draft Invoices op GitHub opmaachen
Mir freeën eis iwwer Praxiserfarungen, Feelerberichter, Verbesserungsvirschléi a Bäiträg aus der Odoo Community.
Gratis. Nachvollziehbar. Open Source. Fir Odoo 19 Community.