Introduzione
In Odoo i modelli descrivono la struttura dei dati: ogni record di business — dall'anagrafica cliente alla fattura — vive dentro un modello che definisce quali informazioni vengono memorizzate e come si collegano fra loro.
Per chi configura Odoo o sviluppa moduli, comprendere i modelli è fondamentale. Sono la colonna portante dell'architettura dati: definiscono campi, relazioni e la logica che regola i comportamenti delle entità aziendali.
Questo testo esplora uno dei modelli più usati nel modulo Vendite: sale.order.line. Che tu stia creando personalizzazioni, collegando sistemi esterni o impostando listini e sconti, prima o poi lavorerai su questo oggetto.
Cos'è il modello sale.order.line
Il modello sale.order.line rappresenta ogni singola riga di una proposta commerciale o di un ordine cliente. Ogni riga descrive un item: prodotto o servizio, quantità, prezzo e imposte associate.
Sale.order.line fa parte del modulo sale e eredita funzionalità utili al tracciamento analitico e all'integrazione con timesheet. Quando si aggiunge un articolo a un preventivo si crea una riga di vendita corrispondente.
La definizione di base si trova nel modulo sale; altri moduli la estendono con ereditarietà dei modelli. Ad esempio, moduli di magazzino aggiungono campi di consegna, moduli per il calcolo degli utili aggiungono logiche di marginalità: ogni componente arricchisce il modello senza riscriverne il nucleo.
Campi chiave del modello
Di seguito trovi i campi principali di sale.order.line: conoscerli ti aiuterà a gestire correttamente preventivi e ordini e a evitare sorprese nelle integrazioni.
1. order_id
Tipo: Many2one (sale.order). Campo obbligatorio. Collega la riga al suo ordine padre; la relazione è a cascata, quindi se l'ordine viene eliminato anche le righe lo saranno.
2. sequence
Tipo: Integer. Default 10. Determina l'ordine di visualizzazione delle righe dentro l'ordine; utile per ordinare sezioni, note e articoli.
3. company_id
Tipo: Many2one (res.company). Derivato da order_id. Necessario per regole multi-società e controllo degli accessi.
4. currency_id
Tipo: Many2one (res.currency). Derivato da order_id. Usato per tutti i valori monetari della riga, garantendo coerenza di valuta.
5. order_partner_id
Tipo: Many2one (res.partner). Derivato da order_id. Rappresenta il cliente; influisce su listini e imposte applicabili.
6. salesman_id
Tipo: Many2one (res.users). Derivato da order_id. Identifica il venditore, utile per commissioni e reportistica.
7. state
Tipo: Selection. Derivato da order_id. Indica lo stato dell'ordine (es. draft, sent, sale, done, cancel) e condiziona la modifica dei campi.
8. display_type
Tipo: Selection. Valori: line_section o line_note. Se impostato la riga è una intestazione o una nota e non contiene dati prodotto.
9. is_downpayment
Tipo: Boolean. Segnala che la riga è un acconto, che viene fatturato separatamente.
10. is_expense
Tipo: Boolean. Vero se la riga proviene da una nota spese o da una fattura fornitore; utile per il controllo dei costi di progetto.
11. product_id
Tipo: Many2one (product.product). Il prodotto venduto. Il dominio limita ai prodotti vendibili. Richiesto per le righe prodotto.
12. product_template_id
Tipo: Many2one (product.template). Calcolato da product_id. Utilizzato dal configuratore per selezionare varianti.
13. name
Tipo: Text. Descrizione della riga. Viene costruita da prodotto e attributi personalizzati e include dettagli di variante se presenti.
14. product_uom_qty
Tipo: Float. Obbligatorio. Quantità ordinata. Default 1.0. Può essere influenzato dal packaging.
15. product_uom
Tipo: Many2one (uom.uom). Unità di misura. Di default deriva dal prodotto; impatta quantità e prezzo.
16. tax_id
Tipo: Many2many (account.tax). Imposte applicate alla riga. Spesso calcolate da prodotto e posizione fiscale.
17. price_unit
Tipo: Float. Obbligatorio. Prezzo unitario per unità di misura. Derivato da listino o prodotto; può essere modificato manualmente.
18. discount
Tipo: Float. Percentuale di sconto applicata al price_unit prima delle imposte.
19. price_subtotal
Tipo: Monetary. Subtotale ante imposte. Calcolato da quantità, prezzo unitario e sconto.
20. price_tax
Tipo: Float. Importo totale imposte. Derivato da price_subtotal e tax_id.
21. price_total
Tipo: Monetary. Totale compresa imposte. È l'importo principale per la fatturazione.
22. product_packaging_id
Tipo: Many2one (product.packaging). Packaging opzionale (es. scatola da 12). Influenza la quantità quando impostato.
23. customer_lead
Tipo: Float. Lead time in giorni: tempo tra conferma ordine e spedizione; usato per calcolare le date di consegna.
24. qty_delivered
Tipo: Float. Quantità consegnata. Aggiornata dai movimenti di magazzino o manualmente; rilevante per fatturazioni parziali.
25. qty_invoiced
Tipo: Float. Quantità già fatturata. Derivata dalle righe di fattura collegate.
26. qty_to_invoice
Tipo: Float. Quantità residua da fatturare. Calcolata da qty_delivered e qty_invoiced.
27. invoice_status
Tipo: Selection. Valori: upselling, invoiced, to invoice, no. Indica lo stato di fatturazione della riga.
28. invoice_lines
Tipo: Many2many (account.move.line). Collega le righe di fattura create da questa riga di vendita per tracciabilità.
29. create_date
Tipo: Datetime. Data di creazione del record. Gestita automaticamente da Odoo.
30. write_date
Tipo: Datetime. Data dell'ultima modifica. Utile per controllo e audit.
Come viene usato questo modello nei processi aziendali
1. Preventivo e ordine di vendita
Quando un commerciale compila un preventivo aggiunge righe prodotto: ogni articolo diventa una sale.order.line che mostra quantità, prezzo, sconto e totale. Il preventivo si trasforma in ordine quando il cliente accetta.
2. Listini e sconti
I listini agiscono riga per riga: price_unit e discount vengono calcolati in base alle regole di listino — inclusi sconti per quantità o prezzi dedicati per cliente.
3. Consegna e fatturazione
La consegna aggiorna qty_delivered; la fatturazione può avvenire per singola consegna o a ordine completo. invoice_status aiuta l'utente a capire cosa resta da fatturare.
4. Progetti e servizi
Per prodotti di tipo servizio, le righe si collegano a task e timesheet: l'ereditarietà analitica permette di monitorare costi e ricavi per progetto.
5. E‑commerce e portale
Nel negozio online le righe del carrello diventano sale.order.line alla creazione dell'ordine. Il configuratore usa il template prodotto e gli attributi per costruire la descrizione e la variante.
Come gli sviluppatori estendono questo modello
Gli sviluppatori possono estendere sale.order.line con diversi approcci: l'ereditarietà dei modelli è lo strumento principale e più pulito.
Ereditarietà del modello
Impostando _inherit = 'sale.order.line' si aggiungono campi, si sovrascrivono metodi o si definiscono vincoli. L'estensione in un modulo separato preserva l'aggiornabilità del core.
Aggiunta di campi
Definisci nuovi campi nel modello ereditato usando i tipi corretti (Char, Many2one, Boolean, Integer, Text, Selection). Valuta se i campi devono essere company-dependent in scenari multi-azienda.
Estensioni in Python
Sovrascrivi metodi di calcolo come _compute_price_unit o _compute_price_subtotal o aggancia logica in create/write; quando richiami il comportamento originale usa super() e cura le dipendenze dei campi computati.
Odoo Studio
Studio è comodo per aggiustamenti rapidi senza codice, ma per logiche complesse o per mantenibilità a lungo termine è preferibile un modulo personalizzato.
Buone pratiche
- Usa display_type per creare sezioni e note invece di righe prodotto fittizie: così il reporting e le convalide restano coerenti.
- Per integrazioni API crea le righe passando l'order_id: lavora via order_line_ids sul sale.order usando il formato di comandi corretto per evitare righe orfane.
- Rispetta i vincoli SQL: una riga prodotto richiede product_id e product_uom, mentre una riga sezione o nota deve avere display_type impostato.
- Per prezzi personalizzati, sfrutta le regole di listino quando possibile; sovrascrivi i metodi di calcolo solo se il comportamento necessario non è supportato dai listini.
- Per campi custom utilizza il prefisso x_ o un prefisso del tuo modulo per ridurre il rischio di collisioni con futuri campi core.
Errori comuni
- Non creare righe senza order_id: il campo è obbligatorio. Inserisci sempre le righe nel contesto di un ordine esistente.
- Non confondere product_id con product_template_id: per le righe prodotto imposta product_id; per i flussi di configurazione usa product_template_id per scegliere varianti.
- Evitare di modificare price_unit o discount dopo la fatturazione: se qty_invoiced > 0 cambiare prezzi può generare incongruenze contabili.
- Non sovrascrivere metodi core senza chiamare super(): questo può rompere l'integrazione con altri moduli e complicare gli aggiornamenti futuri.
- Ricordati di impostare display_type per righe di sezione o nota: senza quel valore la riga verrà trattata come prodotto e fallirà le validazioni.
Conclusione
Il modello sale.order.line è il cuore del processo vendite in Odoo: contiene ogni riga di prodotto o servizio presente in preventivi e ordini. Capirne i campi e le estensioni aiuta a configurare, sviluppare e integrare con sicurezza.
Che tu sia un consulente funzionale che disegna processi o uno sviluppatore che costruisce moduli, conoscere sale.order.line riduce tempi di implementazione ed errori operativi.
Serve assistenza per la tua implementazione Odoo?
Dasolo supporta aziende nell'implementazione, personalizzazione e ottimizzazione di Odoo. Siamo esperti in integrazioni API e sviluppo su misura, con profonda conoscenza dell'architettura dati e di modelli come sale.order.line.
Se ti serve supporto per implementazioni Odoo, sviluppo di moduli personalizzati o integrazioni, possiamo affiancarti nel progetto. Prenota una demo per parlare del tuo progetto.