Overslaan naar inhoud

Odoo 19 documentnummers uit prefix, jaar en teller – module document_number_prefix_year en de valkuil bij gelijktijdig aanmaken

3 november 2026 | Odoo 19 Community | Eigen ontwikkeling
3 november 2026 in
Odoo 19 documentnummers uit prefix, jaar en teller – module document_number_prefix_year en de valkuil bij gelijktijdig aanmaken

Odoo 19-module document_number_prefix_year: documentnummers uit prefix, jaar en teller

“AN26000001” zegt meer dan “S00001”: het is een offerte, ze komt uit 2026 en het is de eerste. Veel bedrijven, vooral die van een ouder systeem op Odoo overstappen, willen hun documentnummers precies zo behouden. Odoo zelf nummert offertes, orders en leveringsbonnen met eigen reeksen (S00001, WH/OUT/00001, P00001) en facturen met het journaalprefix en het jaar (INV/2026/00001).

Wij hebben daarvoor de module Document Numbering by Prefix and Year (document_number_prefix_year) voor Odoo 19 geschreven. Hij staat als vrije software onder de LGPL-3-licentie op GitHub:

github.com/Alex0176/odoo-document-number-prefix-year

Vooraf een eerlijke duiding: Wij zetten de module bij Biricon IT Services niet in. Wij publiceren hem omdat hij af is, gedocumenteerd en voorzien van tests, en anderen werk kan besparen. Wie hem inzet, moet de gedeelten over Beperkingen en Tests lezen.

Het nummeringsschema

Elk nummer bestaat uit drie delen: een prefix per documentsoort, het jaar en een teller met een vast aantal posities. Het prefix, het jaarformaat (26 of 2026) en het aantal posities stelt u per bedrijf in onder Instellingen → Documentnummering.

Opbouw van het documentnummer AN26000001 uit prefix, jaar en teller, met tabel van de documentsoorten

Behandeld worden offertes, klantorders, klantfacturen en creditnota's, leveringsbonnen, goederenontvangsten en inkooporders. De prefixen in de afbeelding zijn slechts voorbeelden: AN, AU, RE, GU, LI, WE, BE. Wie een prefix leeg laat, behoudt voor die documentsoort de standaardnummering van Odoo. De module doet dus niets totdat u hem instelt.

Hoe de nummers zich gedragen

  • Elk jaar opnieuw. De teller begint bij de jaarwisseling weer bij 1.
  • Doorgaan na geïmporteerde nummers. De module zoekt het hoogste aanwezige nummer van hetzelfde prefix en jaar, ongeacht hoe lang het is. Staat er uit het oude systeem AN26119 in de database, dan luidt de volgende offerte AN26000120. Dat is de reden waarom de module geschikt is voor overstappen: oude documenten worden met hun oorspronkelijke nummers geïmporteerd en nieuwe documenten sluiten naadloos aan.
  • Nieuw ordernummer bij bevestiging. Een bevestigde offerte krijgt desgewenst een nummer uit de orderreeks. Het offertenummer blijft behouden in het veld Offertenummer bij de order en is zichtbaar in formulier, lijst en zoekfunctie.
  • Facturen bij het boeken. Klantfacturen en creditnota's krijgen hun nummer pas bij het boeken, niet bij het aanmaken. Verwijderde concepten laten daarom geen gat achter. Het jaar komt uit de factuurdatum: een factuur van 30-12-2025 die op 2-1-2026 wordt geboekt, heet RE25….
  • Al het andere blijft. Leveranciersfacturen, betalingen, boekingen en productieorders behouden de standaardreeksen van Odoo. Bestaande namen worden nooit herschreven, ook niet als u de module weer uitschakelt.

Het lastige deel: twee gebruikers tegelijk

Een eigen nummertoekenning ziet er eenvoudig uit: hoogste nummer zoeken, er één bij optellen. Dat is het niet zodra twee gebruikers op hetzelfde moment een offerte aanmaken. Beiden lezen “hoogste nummer = 0”, beiden kennen AN26000001 toe. Odoo heeft daarvoor bij zijn eigen reeksen databasesequenties. Bij een zelfgebouwd nummer ontbreekt dat, en voor offertes en inkooporders is er in Odoo bovendien geen uniciteitscontrole op de naam: twee documenten met hetzelfde nummer worden gewoon opgeslagen.

De voor de hand liggende bescherming is een vergrendeling. De module neemt per bedrijf, prefix en jaar een vergrendeling van de database (PostgreSQL Advisory Lock), die tot het einde van de transactie blijft bestaan. De tweede gebruiker wacht tot de eerste klaar is. Dat is echter niet genoeg, en wij hebben dat ontdekt met een proef op een kopie van de productiedatabase:

Tijdsverloop van twee gebruikers: zonder tweede leesactie kennen beide hetzelfde nummer toe, met tweede leesactie krijgt de tweede het volgende nummer

Odoo werkt met het isolatieniveau REPEATABLE READ. De databasetoestand die een transactie ziet, wordt bij haar eerste opvraging bevroren. Gebruiker B heeft die toestand al, voordat A klaar is. Wacht B daarna op de vergrendeling en krijgt hij die, dan leest hij met zijn oude toestand “hoogste nummer = 0” en kent hij het nummer een tweede keer toe. De vergrendeling heeft de volgorde geregeld, maar de kennis niet bijgewerkt.

De oplossing is een tweede leesactie via een eigen, kortlevende databaseverbinding, die alle reeds bevestigde rijen ziet. De grootste van de twee waarden wint. De eerste leesactie blijft nodig, want alleen zij kent nummers die dezelfde transactie al heeft toegekend maar nog niet heeft bevestigd, bijvoorbeeld bij het importeren van meerdere documenten in één keer.

Wij hebben dit getest met twee transacties, waarbij de tweede aantoonbaar vóór de commit van de eerste haar toestand had opgehaald en daarna op de vergrendeling wachtte. Zonder de tweede leesactie kregen beide orders hetzelfde nummer, met haar de nummers 1 en 2.

Belangrijk voor de duiding: Deze proef is een handmatige controle. Ze maakt geen deel uit van de automatische tests, omdat daarvoor twee echte databaseverbindingen nodig zijn die de testomgeving van Odoo (één enkele transactie per test) niet biedt.

Technische uitvoering

DocumentAanhaakpunt
Offertesale.order.create, als de naam leeg, / of New is
Klantordersale.order.action_confirm, vóór de standaardbevestiging
Factuur, creditnotaaccount.move._set_next_sequence, wordt bij het boeken aangeroepen
Leveringsbon, goederenontvangststock.picking.create per bewerkingstype
Inkooporderpurchase.order.create
  • Teller. Het hoogste nummer wordt gevonden door een reguliere expressie (^<Stamm>([0-9]{1,15})$, de stam wordt gemaskeerd) per bedrijf, namen zonder bedrijf inbegrepen.
  • Facturen. _set_next_sequence schrijft de naam en roept _compute_split_sequence aan, zodat de reekslogica van Odoo (prefix, nummer, jaarherkenning voor de volgende factuur van het journaal) consistent blijft.
  • Instellingen. De bedrijfsvelden document_number_* worden gespiegeld in res.config.settings. De instellingen weigeren prefixen met spaties of een cijfer aan het einde.
  • Vertaling. Een Duitse vertaling is inbegrepen.

Installatie en configuratie

  1. Map document_number_prefix_year in het addonspad plaatsen.
  2. Appslijst bijwerken, module installeren. Vereist zijn Verkoop, Inkoop, Voorraad en Boekhouding.
  3. Onder Instellingen → Documentnummering prefixen, jaarformaat en aantal posities invoeren.
  4. Eerst op een kopie uitproberen. Het nummer van een document is later niet automatisch terug te draaien, en bij facturen is aan het nummer de bewaar- en controleplicht gekoppeld.

Beperkingen

Zes beperkingen van de module: winkelwagens, jaarformaat, één reeks per bedrijf, prefixregels, weinig tests, alleen genoemde documenten

  • Offertes worden bij het aanmaken genummerd. Verwijderde of geannuleerde offertes laten gaten achter. Hetzelfde geldt voor elke klantorder die een andere module aanmaakt: winkelwagens van de webshop (website_sale) zijn orders met de status Offerte en verbruiken elk een nummer. Alleen facturen en creditnota's zijn sluitend genummerd, omdat ze bij het boeken worden genummerd.
  • Jaarformaat niet wijzigen tijdens het gebruik. Met de stam AN26 leest de module een bestaande AN2026000001 als teller 26000001. Leg het formaat vast vóór het eerste document.
  • Teller maximaal 15 posities. Langere cijferreeksen na de stam worden bij het zoeken naar het hoogste nummer genegeerd.
  • Geen gescheiden reeksen per journaal of magazijn. De teller geldt per bedrijf, prefix en jaar. Meerdere verkoopjournalen delen de factuurteller.
  • Prefixen mogen geen spatie bevatten en niet op een cijfer eindigen, anders zijn prefix, jaar en teller niet meer te scheiden.
  • Alleen de genoemde documentsoorten worden behandeld.

Tests

De module bevat tien automatische tests. Ze controleren:

  • Offerte en bevestiging: offerte- en ordernummer, behoud van het offertenummer
  • Doortellen na een geïmporteerd nummer (AN26119 → AN26000120)
  • geen achteraf hernummeren van bestaande documenten
  • Factuur, creditnota en jaarwisseling volgens factuurdatum
  • Inkooporder en leveringsbonnen
  • leeg prefix: standaardnummer van Odoo blijft
  • viercijferig jaar
  • Prefix met speciale tekens
  • meerdere nummers in één transactie
  • zeer lange cijferreeksen worden genegeerd

Aanroep:

odoo-bin -d <Testdatenbank> -i document_number_prefix_year --test-enable --test-tags=/document_number_prefix_year --stop-after-init

De tests lopen met gewone transacties. Het gedrag bij gelijktijdig aanmaken door twee gebruikers hoort daar niet bij, het is zoals hierboven beschreven met de hand getest op een databasekopie. Wie de module gebruikt in een systeem met veel gelijktijdige gebruikers, moet deze proef op de eigen database herhalen.

Juridische opmerking over het factuurnummer

Facturen moeten volgens § 11 UStG een doorlopend nummer dragen dat voor de identificatie van de factuur eenmalig wordt toegekend. De module nummert facturen bij het boeken en met een eigen teller per prefix en jaar, wat daarbij past. Of uw concrete instelling (meerdere journalen, creditnota's met eigen prefix, jaarwisseling) voldoet aan de eisen van uw belastingadviseur, moet u met die adviseur afstemmen. Dit artikel is geen juridisch advies.

Veelgestelde vragen

Waarom niet gewoon de Odoo-reeksen aanpassen?

Voor facturen kan dat via het journaalprefix. Bij offertes, orders, leveringsbonnen en bestellingen bestaat echter geen gemeenschappelijk schema van prefix, jaar en teller met jaarwisseling, en de teller kent geen geïmporteerde oude nummers. Daar zet de module aan.

Wordt bestaande nummering overschreven?

Nee. De module kent alleen nieuwe nummers toe. Reeds opgeslagen namen blijven ongewijzigd, ook bij uitschakelen.

Hoe schakel ik hem weer uit?

Maak het prefix van de documentsoort leeg. Dan nummert Odoo haar weer zelf. Ook het deïnstalleren wijzigt geen toegekende nummers.

Zetten jullie hem zelf in?

Nee. Bij ons draaien de standaardnummers van Odoo. Wij hebben de module getest met de automatische tests en de beschreven handmatige proef, maar niet in een lopend bedrijf met veel gebruikers.

Werkt hij met Odoo 17 of 18?

Wij hebben hem alleen met Odoo 19.0 Community getest. Voor andere versies kan hij passen of niet, wij hebben het niet gecontroleerd.

Onder welke licentie staat hij?

Onder de LGPL-3. Fouten en verbeteringen zijn als issue in de GitHub-repository welkom.

Ondersteuning door Biricon IT Services

Wij beheren Odoo-installaties voor kleine en middelgrote bedrijven: van de invoering via aanpassingen en migraties tot de lopende exploitatie. Wilt u bij de overstap uw documentnummers behouden, de nummertoekenning onder belasting laten controleren of een module zoals deze veilig in uw productie-instantie laten brengen, dan helpen wij u graag. Meer eigen ontwikkelingen: Firmenbuch en adrescontrole voor Oostenrijkse klanten, Productsets in de offerte als sectie en Web RBL, de blokkeerlijst voor aanvalsverkeer.

Neem nu contact op

Stand per 3 november 2026. Moduleversie 19.0.1.0.0. Alle nummers in de voorbeelden en afbeeldingen zijn vrij gekozen.