Skip to Content

Odoo 19 Community: Slå sammen kladdefakturaer – vår åpen kildekode-modul Merge Draft Invoices

18. september 2026 etter
Odoo 19 Community: Slå sammen kladdefakturaer – vår åpen kildekode-modul Merge Draft Invoices
Alexander Biringer | Biricon IT Services GmbH

Den som fakturerer fra ordrer, helpdesk-tickets og timeregistrering i Odoo, kjenner resultatet: En kunde får ved månedsslutt ikke én faktura, men fem. Hver av dem stammer fra en annen ordre eller ticket, hver av dem er faglig korrekt – og likevel spør kunden om ikke dette kunne passe på ett dokument.

Nettopp for dette finnes det ingen ryddig løsning i Odoo 19 Community. Den kjente OCA-modulen account_invoice_merge er ennå ikke frigitt for Odoo 19, og den løser problemet på en måte som innebærer en alvorlig risiko for tjenesteleverandører: Like linjer slås sammen, og dermed går koblingen tilbake til ordren, oppgaven og den registrerte tiden tapt.

For vår egen Odoo 19 Community-installasjon har vi derfor utviklet modulen Merge Draft Invoices. Fordi dette problemet ikke bare gjelder oss, stiller vi den gratis til disposisjon på GitHub under den frie AGPL-3-lisensen.

Til prosjektet på GitHub:

Odoo 19 Merge Draft Invoices

Hvorfor en egen modul i stedet for OCA-løsningen?

OCA har i mange år vedlikeholdt account_invoice_merge i repositoriet OCA/account-invoicing. På tidspunktet for dette innlegget er migreringen til 19.0 der fortsatt en åpen pull request, ikke en publisert modul.

Viktigere er det imidlertid at de to modulene gjør ulike ting:


OCA account_invoice_mergeMerge Draft Invoices
Resultatslås sammen til én av de valgte fakturaenealltid en ny faktura
Linjerlike linjer slås sammen, mengder legges sammenhver linje overtas én til én
Opprinnelseinvoice_origin / payment_reference føyd sammen i toppenOpprinnelsesfelt per linje kopiert via Odoos egen _copy_data_extend_business_fields-hook
Timeregistreringikke tatt hensyn tiltimesheet_invoice_id flyttes over til den nye fakturaen
Leselig for kundeningentingen overskrift over linjene fra hver kilde med ordre og ticket
Kildefakturaerblir kansellertkansellere (standard), slette eller beholde – med tydelig benevnte konsekvenser

Sammenslåingen av like linjer er den avgjørende forskjellen. En sammenslått linje kan bare ha én opprinnelse. Så snart to linjer fra to forskjellige ordrer ser like ut, er koblingen fra fakturaen tilbake til ordren, oppgaven og timeposteringen borte. I en tjenesteytende virksomhet der faktureringen går via ticket → timeregistrering → faktura, betyr det: De samme timene faktureres dobbelt eller forsvinner.

Modulen vår slår derfor i prinsippet ikke sammen noe. Den sammenslåtte fakturaen har nøyaktig like mange linjer som kildene til sammen.

Det er ikke overtatt kode fra OCA-modulen. Begge modulene står under AGPL-3.

Hva modulen gjør

Marker to eller flere kladder i fakturalisten, velg Slå sammen kladdefakturaer i handlingsmenyen – en veiviser viser utvalget, kontrollene og alternativene for kildefakturaene. Etter bekreftelsen havner man direkte på den nye fakturaen.

Før sammenslåingen kontrollerer modulen, og det alle punktene på én gang, slik at man ikke ser neste feil etter hver korrigering:

  • minst to fakturaer valgt
  • alle med status Kladd
  • ingen har noen gang vært bokført (et dokument som er tilbakestilt til kladd beholder sin posteringshistorikk og avvises)
  • ingen er allerede slått sammen
  • alle er faktura, leverandørfaktura, kreditnota eller kvittering – ingen rene bilag
  • samme partner, dokumenttype, virksomhet, valuta og journal

Forskjeller i betalingsbetingelser, skattetilordning, leveringsadresse, bankkonto eller selger blokkerer ikke. Veiviseren advarer og overtar verdien fra den eldste valgte fakturaen.

Hva som beholdes

Kjernen i modulen er at hver kobling en fakturalinje har til sin opprinnelse, også finnes på den nye fakturaen:

KoblingBehandling
Salgsordrelinjer (sale_line_ids)kopiert per linje via Odoos _copy_data_extend_business_fields
Innkjøpsordrelinjer (purchase_line_id)likeledes
Kostnadsstedsfordeling (analytic_distribution)kopiert per linje
andre opprinnelsesfelt per linjeautomatisk, hvis modulen som leverer feltet implementerer den dokumenterte Odoo-hooken
Opprinnelse og referanse i fakturahodetslått sammen, deduplisert, kan redigeres i veiviseren
Salgsordre: invoice_ids, invoice_status, qty_invoicedberegnes ut fra linjene – ordren oppdager den nye fakturaen av seg selv
Timeregistrering (timesheet_invoice_id)flyttes over til den nye fakturaen før kildene blir ugyldige
Helpdesk-tickethenger på timeregistreringen og peker dermed automatisk på den nye fakturaen
ChatterMelding på den nye fakturaen med alle kilder, melding på hver kilde med lenke til den nye
merged_into_move_id / merged_from_move_idslagret kobling i begge retninger

Skattelinjer, linjer for betalingsbetingelser, avrundings- og kontantrabattlinjer kopieres ikke, men beregnes på nytt av Odoo ut fra innholdet. Den sammenslåtte fakturaen har altså én skattelinje per skattesats, ikke én per kilde. Den opprettes uten nummer som kladd; selve sammenslåingen bruker ikke opp noe dokumentnummer.

Overskrifter: Kunden ser hvor hver linje stammer fra

Dette er funksjonen som utgjør forskjellen i hverdagen. Over linjene fra hver kildefaktura setter modulen en seksjonslinje – det samme elementet som Odoo selv bruker for seksjonen «Forskuddsbetalinger»:

BE10181                                     <- Overskrift
  22,500 x Teknikertime           3.577,50
                         Delsum 3.577,50
BE10182 · Ticket: HT00219                   <- Overskrift
   3,000 x Teknikertime             477,00
                         Delsum   477,00
                      NETTOBELØP 4.054,50

Overskriften trykkes på dokumentet kunden får, og Odoos standard fakturarapport legger av seg selv til en delsum per seksjon. Kunden ser dermed også hva hver del har kostet.

Betegnelsen settes sammen av det kilden faktisk har:

  1. ordrene, direkte fra linjekoblingene – navnene er dermed nøyaktige; hvis ordrekoblinger mangler, brukes fritekst fra invoice_origin
  2. ticketene, funnet via timeregistreringen – vist som Ticket: HT00219 eller Tickets: …, begrenset til fem pluss «og N til»
  3. finnes ingen av delene: nummeret til kildefakturaen, deretter dens referanse
  4. finnes ingenting: et nøytralt «Flere linjer», slik at linjene fra en kilde aldri i det stille forsvinner i blokken over

Det som mangler, utelates, ikke diktes opp. Ticketen trykkes med sitt eget nummer – helpdesk_mgmt-nummer, Enterprise-ticket_ref eller visningsnavnet til modellen – aldri med database-ID-en.

Overskriftene skrives på kundens språk, slik Odoo gjør det når den oppretter fakturaer fra ordrer. Chatter forblir på brukerens språk.

En overskrift har ikke noe produkt, ingen mengde, ingen pris, ingen skatt, ingen konto og ingen kostnadsstedsfordeling. Den kan ikke påvirke summer, skattegrunnlag og kostnadsregnskap. Den som slår av overskriftene i veiviseren, får nøyaktig den fakturaen som ville oppstått uten denne funksjonen – en test sammenligner begge resultatene helt ned til øret.

Hva som skjer med kildefakturaene

Veiviseren tilbyr tre alternativer:

  • Kansellere (standard, anbefalt). Å kansellere en kladd har ingen konsekvenser: ikke noe dokumentnummer, ingen bokføring. Fakturaene blir liggende i databasen som kansellerte dokumenter med chatter og lenke til den nye fakturaen. qty_invoiced på salgsordren hopper over kansellerte dokumenter, ingenting telles dobbelt. Dette er alternativet som også er etterprøvbart om seks måneder.
  • Slette. Uigjenkallelig. Chatter og tilbakehenvisning forsvinner med posten; bare meldingen på den nye fakturaen blir igjen. Fornuftig for kast-kladder som ingen skal se mer.
  • La stå som kladd. Kildene blir åpne. Salgsordrene deres teller da kilden og den nye fakturaen som fakturert – arbeidet ser ut til å være fakturert dobbelt til noen rydder opp i kladdene for hånd. Tenkt for det sjeldne tilfellet at man vil sammenligne før man bestemmer seg. En test fastholder nettopp denne dobbelttellingen, slik at den ikke overrasker noen.

Begrensninger – hva modulen bevisst ikke gjør

Vennligst les før produksjonsbruk:

  • Bare kladder. Bokførte fakturaer slås ikke sammen. Det er en oppgave for kreditnotaer, ikke en kopieringsprosess.
  • Kladder som en gang har vært bokført og er tilbakestilt, avvises. De har et nummer og en posteringshistorikk; å skjule dette i et annet dokument er ikke noe en samlehandling bør gjøre i det stille.
  • Ingen sammenslåing på tvers av partnere, valutaer, virksomheter eller journaler. Det finnes ingen fornuftig enkeltverdi for dette, så modulen avviser i stedet for å gjette.
  • payment_reference overtas ikke. Strukturerte betalingsreferanser identifiserer ett dokument; to sammenføyde passer ikke til noe hos banken. Den nye fakturaen får sin egen ved bokføring.
  • Forskuddslinjer kopieres som alle andre linjer. Hvis kildene inneholder forskuddslinjer fra sale, må resultatet kontrolleres før bokføring.
  • Bare timesheet_invoice_id flyttes automatisk over. Enhver annen modell med en Many2one til account.move (egne faktureringskjøringer, abonnementskoblinger, EDI-overføringer) peker fortsatt på kilden. For dette finnes hooken _merge_draft_relink.
  • Ingen sammenslåing av like linjer – med vilje. Den som vil ha en kort, ryddig faktura, er på feil sted her og ville betale for det med opprinnelseskoblingene.
  • Overskrifter opprettes én gang ved sammenslåingen. Etterpå er de vanlige seksjonslinjer: kan redigeres, kan slettes og oppdateres ikke hvis ordre eller ticket senere får nytt navn.
  • En overskrift nevner ticketene til hele kildefakturaen, ikke til den enkelte linjen.

Installasjon i Odoo 19 Community

Installasjonen skjer som for en vanlig Odoo-tilleggsmodul:

  1. Kopier modulmappen til en konfigurert addons-sti.
  2. Oppdater app-listen i Odoo.
  3. Installer modulen account_invoice_merge_draft.

Modulen avhenger bare av account. Alt den vet om sale, purchase, project, hr_timesheet, sale_timesheet eller en helpdesk-modul, avgjøres ved kjøretid – den installeres og fungerer også på en ren faktureringsdatabase.

Deretter: Regnskap → Kunder → Fakturaer (eller Leverandører → Fakturaer), marker to eller flere kladder, tannhjulmeny → Slå sammen kladdefakturaer. Handlingen er tilgjengelig for alle brukere med gruppen Fakturering / Fakturaoppgjør.

Den som oppdaterer fra en tidligere versjon av modulen, bør én gang oppdatere med -u account_invoice_merge_draft --i18n-overwrite, slik at endrede feltbetegnelser kommer med i den tyske oversettelsen. En nyinstallasjon påvirkes ikke av dette.

For utviklere: API og hooks

Sammenslåingen kan også kalles fra egen kode:

python

merged = draft_moves.merge_draft_moves(
    extra_vals={"invoice_date": date(2026, 3, 31), "ref": "Q1"},
    source_handling="cancel",   # "delete" eller "keep"
    add_source_sections=True,   # Overskrifter; standard True
)

merge_draft_moves kaster en UserError med alle avvisningsgrunner hvis utvalget ikke kan slås sammen. _merge_draft_get_errors() gir de samme grunnene som liste uten exception.

Den som har egne tilbakehenvisninger til account.move, overstyrer _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}
        )

Den som har en tilbakehenvisning på fakturalinjen, trenger ikke denne modulen i det hele tatt: Odoos egen hook account.move.line._copy_data_extend_business_fields er nok, og feltet overtas likt ved sammenslåing, ved kansellering og ved duplisering. For andre helpdesk-moduler eller en annen formulering av overskriftene finnes _merge_draft_get_source_tickets() og _merge_draft_section_name().

Testet før den kjøres på produksjonsdata

48 tester dekker blandede statuser, ulike partnere, valutaer og dokumenttyper, linjer med og uten salgs- eller innkjøpsordre, skatter, seksjoner og notater, kostnadsstedsfordelinger, flytting av timeregistreringen, alle tre alternativene for kildefakturaene, veiviseren og overskriftene – at de er aktive som standard, at avslåing av dem gjenskaper det gamle resultatet helt ned til øret, at en overskrift ikke har beløp eller kontoer, at linjene fra én kilde holdes samlet, og at ticketen vises med sitt nummer og aldri med database-ID-en.

Testdataene bygger på den eksisterende kontoplanen til det aktive firmaet i stedet for på AccountTestInvoicingCommon – denne hjelperen starter ofte ikke på migrerte produksjonsdatabaser, og nettopp på slike skal modulen kjøre.

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

Som for enhver utvidelse innen regnskap anbefaler vi å kontrollere installasjonen først i et testmiljø med en kopi av egen database.

Gratis og åpen kildekode for Odoo Community

Hos Biricon IT Services GmbH utvikler vi først og fremst løsninger for konkrete behov i vår egen drift. Når det blir en allment brukbar modul ut av det, vil vi ikke gjemme den bort i en enkelt installasjon.

Merge Draft Invoices er derfor tilgjengelig gratis som åpen kildekode-prosjekt. Kildekoden kan ses, kontrolleres, tilpasses og videreutvikles innenfor rammen av AGPL-3-lisensen.

Målet vårt var ikke den kortest mulige fakturaen, men en faktura der hver linje også om et år fortsatt fører tilbake til sin ordre, sin ticket og sin timepostering.

Prosjekt, kildekode og medvirkning

Hele kildekoden, installasjonsveiledningen og den tekniske dokumentasjonen er tilgjengelig på GitHub:

Åpne Odoo 19 Merge Draft Invoices på GitHub

Vi setter pris på praktiske erfaringer, feilrapporter, forbedringsforslag og bidrag fra Odoo Community.

Gratis. Etterprøvbar. Åpen kildekode. For Odoo 19 Community.