Introductie
In Odoo vormt elk model de blauwdruk voor hoe gegevens worden opgeslagen. Alles wat je in je bedrijfsprocessen tegenkomt — offertes, facturen, contacten — leeft binnen zo'n model en bepaalt tegelijk welke velden, relaties en regels beschikbaar zijn.
Kennis van Odoo-modellen is onmisbaar voor zowel ontwikkelaars als functioneel consultants. Modellen zijn de ruggengraat van de datalaag: ze beschrijven welke informatie bewaard wordt, hoe records aan elkaar gelinkt zijn en welke logica automatisch draait.
Deze tekst zoomt in op een kernmodel van de Verkoopmodule: sale.order.line. Of je nu maatwerk bouwt, koppelt met externe systemen of prijsregels instelt, met dit model kom je vroeg of laat in aanraking.
Wat is het sale.order.line-model
Het sale.order.line-model beschrijft elk afzonderlijk regelitem op een offerte of verkooporder. Eén regel staat meestal voor één product of dienst en bevat aantal, prijs en belastingen.
Binnen Odoo hoort dit model bij de sales-module en erft het gedrag voor analytische registratie (analytic.mixin) zodat kosten en timesheets gekoppeld kunnen worden. Het toevoegen van een product aan een offerte creëert gewoonlijk één sale.order.line-record.
Het model zelf leeft in de sale-module; andere modules breiden het uit via Odoo-inheritance. Modules zoals sale_stock voegen bijvoorbeeld leveringsvelden toe, sale_margin rekent winstmarges uit — elk module voegt alleen toe wat nodig is, zonder de kernstructuur te dupliceren.
Belangrijkste velden in het model
Onderstaande velden zijn de meest gebruikte in sale.order.line. Wie ze kent, kan offertes en orders nauwkeurig configureren en debuggen.
1. order_id
Type: Many2one naar sale.order. Verplicht. Linkt de regel aan de bovenliggende verkooporder. Verwijnt meestal mee als de order verwijderd wordt.
2. sequence
Type: Integer. Standaard 10. Bepaalt de volgorde waarin regels getoond worden — handig voor secties, notities en producten.
3. company_id
Type: Many2one naar res.company. Afgeleid van order_id. Belangrijk voor multi-company-logs en toegangsregels.
4. currency_id
Type: Many2one naar res.currency. Afgeleid van order_id. Zorgt dat alle bedragen op de regel in de juiste valuta weergegeven en berekend worden.
5. order_partner_id
Type: Many2one naar res.partner. De klant gekoppeld aan de order. Wordt gebruikt bij prijslijsten en fiscale regels.
6. salesman_id
Type: Many2one naar res.users. Verantwoordelijke verkoper — relevant voor commissies en rapportage.
7. state
Type: Selection. Afgeleid van order_id. Geeft de status van de order weer (bv. concept, verzonden, bevestigd, gedaan, geannuleerd) en bepaalt bewerkbaarheid van velden.
8. display_type
Type: Selection. Mogelijke waardes: line_section of line_note. Zet je dit, dan is de regel een sectiekop of notitie — geen productregel — en blijven productvelden leeg.
9. is_downpayment
Type: Boolean. Geeft aan of de regel een voorschot is; zulke regels worden apart gefactureerd.
10. is_expense
Type: Boolean. True wanneer de regel voortkomt uit een onkostennota of leverancier; nuttig voor kostentoewijzing naar projecten.
11. product_id
Type: Many2one naar product.product. Het verkochte product. Domein beperkt tot verkoopbare producten; vereist voor productregels.
12. product_template_id
Type: Many2one naar product.template. Afgeleid uit product_id. Gebruikt door productconfiguratoren om varianten te kiezen.
13. name
Type: Text. Omschrijving van de regel. Wordt samengesteld uit productinformatie en eventuele eigenschappen; bevat variantdetails indien van toepassing.
14. product_uom_qty
Type: Float. Verplicht. Besteld aantal. Standaard 1.0. Kan gestuurd worden door verpakkingseenheden.
15. product_uom
Type: Many2one naar uom.uom. Eenheid van meting. Standaard gehaald uit het product; bepaalt hoeveelheid en prijsbasis.
16. tax_id
Type: Many2many naar account.tax. Belastingregels voor de regel; vaak afgeleid via product en fiscale positie.
17. price_unit
Type: Float. Verplicht. Eenheidsprijs per gekozen UoM. Wordt bepaald door prijslijst of product en kan manueel aangepast worden.
18. discount
Type: Float. Korting in procenten, toegepast vóór belastingberekening.
19. price_subtotal
Type: Monetary. Subtotaal exclusief btw. Automatisch berekend vanuit aantal, eenheidsprijs en korting.
20. price_tax
Type: Float. Totaalbedrag aan belasting. Afgeleid van subtotaal en toegepaste belastingen.
21. price_total
Type: Monetary. Totaal inclusief belasting. Dit is het belangrijkste factuurbedrag per regel.
22. product_packaging_id
Type: Many2one naar product.packaging. Optionele verpakking (bv. doos van 12). Bijgezet kan de hoeveelheid aangepast worden volgens verpakking.
23. customer_lead
Type: Float. Levertijd in dagen — de tijd tussen orderbevestiging en verzending; gebruikt bij leverdatumberekening.
24. qty_delivered
Type: Float. Hoeveelheid geleverd. Wordt geüpdatet door stockmoves of manueel; relevant voor gedeeltelijke facturatie.
25. qty_invoiced
Type: Float. Hoeveelheid die al gefactureerd is. Afgeleid van factuurlijnen.
26. qty_to_invoice
Type: Float. Te factureren restant. Afgeleid uit qty_delivered en qty_invoiced.
27. invoice_status
Type: Selection. Waardes zoals upselling, invoiced, to invoice, no. Geeft de facturatiestatus per regel aan.
28. invoice_lines
Type: Many2many naar account.move.line. Koppeling naar de factuurlijnen die uit deze verkoopregel zijn ontstaan; nuttig voor traceerbaarheid.
29. create_date
Type: Datetime. Datum en tijd van aanmaak. Beheerd door Odoo.
30. write_date
Type: Datetime. Laatste wijzigingsmoment. Handig voor auditdoeleinden.
Hoe dit model in bedrijfsprocessen wordt ingezet
1. Offerte en verkooporder
Verkopers bouwen offertes door producten toe te voegen; elk product wordt een losse regel met aantal, prijs, korting en totalen. Zodra de klant akkoord gaat, bevestig je de order en verplaatsen regels naar de bevestigde status.
2. Prijslijst en kortingen
Prijslijsten worden per regel toegepast: price_unit en discount komen voort uit prijslijstregels. Volumekortingen of klantgerichte prijzen worden hier geregeld.
3. Levering en facturatie
Bij het uitleveren worden qty_delivered-waarden bijgewerkt. Je kunt factureren per levering of alles in één keer factureren; invoice_status helpt beslissen wat nog moet worden gefactureerd.
4. Projecten en diensten
Voor diensten koppelen regels vaak aan projecttaken en timesheets. Dankzij analytic.mixin kan je kosten correct toewijzen aan een project.
5. E‑commerce en klantportaal
Webshops zetten winkelwagenregels om in sale.order.line wanneer een klant bestelt. De productconfigurator gebruikt template- en attribuutgegevens om varianten en opties samen te stellen.
Hoe ontwikkelaars dit model uitbreiden
Ontwikkelaars breiden sale.order.line uit via verschillende patronen; modelinheritance is de basisaanpak.
Modelinheritance
Maak een model aan met _inherit = 'sale.order.line' om velden toe te voegen, methodes te overschrijven of extra constraints te plaatsen. Zo blijf je aanpassingen in een apart module houden en vergemakkelijk je latere upgrades.
Extra velden toevoegen
Definieer nieuwe velden in je geërfde klasse met het juiste type: Char, Many2one, Boolean, Integer, Text, Selection enz. Denk ook aan company‑afhankelijke velden in multi‑company-omgevingen.
Python‑logica uitbreiden
Overschrijd berekeningsmethoden of schrijf hooks (bijv. _compute_price_unit, _compute_price_subtotal, create/write) om specifieke regels toe te voegen. Roep altijd super() aan waar nodig en let op computed fields en dependencies.
Odoo Studio
Studio is handig voor snelle aanpassingen zonder code, maar voor robuuste logica en toekomstbestendige upgrades blijft een custom module de betere keuze.
Handige richtlijnen
- Gebruik display_type voor secties en notities in plaats van lege productregels — dat houdt rapporten en validatie netjes.
- Bij API‑koppelingen: creëer regels in de context van een order. Gebruik de order_line-commandoformaten van sale.order zodat Odoo relaties en berekeningen automatisch uitvoert.
- Respecteer SQL‑ en modelconstraints: productregels vereisen product_id en product_uom; secties en notities moeten display_type gebruiken.
- Voor aangepaste prijsberekeningen: probeer eerst met prijslijstregels te werken; overschrijd compute-methodes alleen als de standaardfunctionaliteit niet toereikend is.
- Gebruik voor eigen velden een veilige naamgevingsconventie (x_ of modulenaam_prefix) om toekomstige naamconflicten met Odoo‑core of andere modules te voorkomen.
Veelgemaakte fouten
- Regels aanmaken zonder order_id. Omdat order_id verplicht is, maak regels altijd binnen de context van een order aan — losse regels leiden tot validatiefouten.
- product_id vs product_template_id verwisselen. Voor normale productregels stel je product_id in; bij configuratoren of variantkeuze werk je vaak via product_template_id.
- Prijs wijzigen na facturatie. Als qty_invoiced > 0 kunnen wijzigingen aan price_unit of discount leiden tot inconsistenties tussen verkooporder en reeds uitgereikte facturen.
- Coremethodes overschrijven zonder super(). Dat breekt compatibiliteit met andere modules en maakt upgrades riskant.
- Vergeten display_type te zetten voor secties of notities. Zonder display_type behandelt Odoo de regel als productregel en stuit je op validatiefouten.
Samenvatting
Het sale.order.line-model staat centraal in de Odoo‑verkoopstroom: elke productregel op offertes en orders wordt daarin opgeslagen. Goed begrip van de velden en uitbreidingsmogelijkheden bespaart tijd bij configuratie, maatwerk en integratie.
Of je nu processen in kaart brengt als functioneel consultant of maatwerk ontwikkelt als programmeur: stevige kennis van sale.order.line voorkomt faalpunten en maakt implementaties stabieler.
Hulp nodig bij jouw Odoo-implementatie?
Dasolo ondersteunt bedrijven bij implementatie, maatwerk en optimalisatie van Odoo. Wij specialiseren ons in API‑koppelingen en ontwikkeling en kennen de Odoo‑datamodellen, inclusief sale.order.line, door en door.
Heb je hulp nodig met implementatie, maatwerk of koppelingen rond Odoo? We helpen je graag verder. Plan een demo om je project te bespreken.