Introduzione
In Odoo i modelli definiscono la forma dei dati e come vengono salvati nel database. Qualsiasi informazione aziendale — dagli ordini di acquisto alle fatture e alle giacenze — è rappresentata da un record appartenente a un modello specifico.
Capire i modelli Odoo è fondamentale sia per chi fa configurazione funzionale sia per chi sviluppa. I modelli stabiliscono campi, relazioni e la logica di business che reggono l'intera piattaforma.
Qui ci concentriamo su un modello chiave per gli acquisti: purchase.order. Che tu stia sviluppando moduli personalizzati, collegando sistemi esterni o impostando processi di approvvigionamento, prima o poi lavorerai con questo modello.
Che cos'è il modello purchase.order
Il modello purchase.order rappresenta in Odoo sia le richieste di offerta (RFQ) sia gli ordini di acquisto confermati. È il contenitore principale dove si registrano le transazioni di procurement fino a che non diventano ricevute di merce o fatture fornitori.
Il Purchase module utilizza questo modello: quando un buyer crea una RFQ nasce un record purchase.order; alla conferma del fornitore o all'approvazione interna lo stato passa da bozza a confermato. Lo stesso record copre RFQ e ordini: è il campo state a segnare il ciclo di vita.
Altri moduli ampliano il modello tramite ereditarietà dei modelli. Inventory aggiunge logiche di ricevimento e picking; Accounting aggiunge i collegamenti alle fatture; Manufacturing può generare ordini a partire dalle distinte base. Ogni modulo aggiunge solo ciò che gli serve mantenendo la struttura centrale unica.
Campi chiave nel modello
Di seguito i campi più rilevanti del modello purchase.order: conoscerli ti rende più veloce e preciso nella configurazione, nello sviluppo e nell'integrazione.
1. name
Tipo: Char. Identificatore dell'ordine (es. PO00042). Di solito viene generato automaticamente e appare nelle viste elenco e nei documenti: è il riferimento principale per l'ordine di acquisto.
2. state
Tipo: Selection. Tiene traccia dello stato dell'ordine. Valori comuni: draft (RFQ), sent (inviato al fornitore), to approve (in attesa di approvazione), purchase (confermato), done (ricevuto e fatturato), cancel (annullato). Lo stato determina le azioni disponibili sull'ordine.
3. partner_id
Tipo: Many2one (res.partner). Il fornitore. Campo obbligatorio che collega l'ordine al contatto o alla società venditrice e viene usato in tutta la logica di vendor e nei report.
4. partner_ref
Tipo: Char. Il riferimento fornito dal venditore (numero ordine del fornitore). Utile per riconciliare documenti e viene mostrato sui documenti stampati.
5. date_order
Tipo: Datetime. Data dell'ordine: per le bozze è la data di creazione, per gli ordini confermati è la data di conferma. Serve per report, ordinamenti e come data di riferimento per le linee.
6. date_approve
Tipo: Datetime. Data di approvazione o conferma. Viene impostata quando lo stato diventa purchase. Campo di sola lettura utile per audit e reportistica.
7. order_line
Tipo: One2many (purchase.order.line). Le righe d'ordine: prodotto, quantità, prezzo e tasse. Rappresentano il dettaglio operativo dell'ordine.
8. amount_untaxed
Tipo: Float. Subtotale senza imposte. Calcolato dalle righe d'ordine e usato per mostrine e reportistica.
9. amount_tax
Tipo: Float. Totale imposte. Calcolato in base alle tasse applicate alle righe; visibile sull'ordine e riportato nella fattura fornitore.
10. amount_total
Tipo: Float. Totale comprensivo di imposte: l'importo principale usato per fatturazione e report.
11. currency_id
Tipo: Many2one (res.currency). La valuta dell'ordine, normalmente ereditata dall'azienda o dal fornitore; tutti i campi monetari si riferiscono a questa valuta.
12. origin
Tipo: Char. Documento sorgente: ad esempio un ordine di vendita o un ordine di produzione che ha generato l'acquisto. Utile per ricostruire la tracciabilità.
13. dest_address_id
Tipo: Many2one (res.partner). Indirizzo di consegna: se non impostato usa l'indirizzo dell'azienda. Fondamentale per i casi di dropshipping, quando la merce va direttamente al cliente.
14. priority
Tipo: Selection. Priorità dell'ordine: Normal o Urgent. Utile per ordinare gli elenchi e per evidenziare ordini che richiedono attenzione particolare.
15. invoice_status
Tipo: Selection. Stato di fatturazione: no (non fatturato), to invoice (da fatturare), invoiced (completamente fatturato). Influisce sulla visibilità dell'azione Crea Fattura.
16. invoice_count
Tipo: Integer. Numero di fatture fornitore collegate. Campo calcolato per mostrare rapidamente quante fatture sono state generate.
17. invoice_ids
Tipo: One2many (account.move). Collegamento alle fatture fornitore che permette riconciliazioni e monitoraggio dei pagamenti.
18. picking_ids
Tipo: One2many (stock.picking). Relazione con le consegne o i ricevimenti collegati all'ordine, attiva quando il modulo Inventory è installato.
19. picking_count
Tipo: Integer. Numero di pickings collegati. Campo calcolato per consentire l'apertura rapida dell'elenco di ricevimenti.
20. create_date
Tipo: Datetime. Data/ora di creazione del record, gestita automaticamente da Odoo; utile per audit e analisi temporali.
21. write_date
Tipo: Datetime. Data/ora dell'ultima modifica; anche questa gestita automaticamente e utile per tracciare aggiornamenti.
22. notes
Tipo: Text. Note interne o termini e condizioni. Può essere stampato sull'ordine e servire da istruzione per il fornitore.
23. company_id
Tipo: Many2one (res.company). In scenari multi-società identifica a quale entità appartiene l'ordine, influenzando visibilità e permessi.
24. user_id
Tipo: Many2one (res.users). L'utente responsabile o il buyer. Utilizzato nei workflow di approvazione e per assegnare attività.
25. fiscal_position_id
Tipo: Many2one (account.fiscal.position). Posizione fiscale per rimappare le imposte quando il fornitore è in regime diverso o in altro Paese.
26. payment_term_id
Tipo: Many2one (account.payment.term). Condizioni di pagamento (es. 30 gg data fattura, acconto 50%). Vengono usate nella generazione delle fatture fornitore.
27. display_name
Tipo: Char. Nome visualizzato, costruito combinando riferimento e info sul fornitore. Appare nei dropdown e nei risultati di ricerca; campo di sola lettura.
28. active
Tipo: Boolean. Flag di archivio: quando False il record è nascosto dalle viste predefinite ma non cancellato fisicamente, preservando la cronologia.
Come questo modello viene usato nei flussi aziendali
1. Da RFQ a Ordine di Acquisto
Il buyer crea una RFQ in bozza, aggiunge righe e la invia al fornitore. Alla conferma del venditore o con approvazione interna lo stato diventa purchase: da quel momento si possono generare ricevute e fatture.
2. Ricevimento merce
All'arrivo della merce si crea un documento di ricezione collegato all'ordine: i picking vengono associati, le quantità a magazzino aggiornate e, se previsto, il costo del prodotto aggiornato dal prezzo di acquisto.
3. Fattura fornitore
Da un ordine confermato si genera la fattura fornitore: le righe vengono riportate, e campi come condizioni di pagamento e posizione fiscale vengono ereditati dall'ordine. invoice_status riflette lo stato della fatturazione.
4. Dropshipping
Quando una vendita genera un acquisto, origin collega l'ordine di acquisto all'ordine di vendita e dest_address_id viene impostato sull'indirizzo cliente: il fornitore spedisce direttamente al cliente finale.
5. Produzione e MRP
Se un ordine di produzione richiede materiali esterni, il sistema può creare purchase.order per le materie prime: origin traccia il collegamento all'ordine di produzione, integrando il ciclo procure-to-pay.
Come gli sviluppatori estendono questo modello
Gli sviluppatori estendono purchase.order con diversi pattern; l'ereditarietà dei modelli è lo strumento principale per aggiungere campi e logiche senza duplicare il core.
Ereditarietà del modello
Si usa _inherit = 'purchase.order' per estendere il modello: si possono aggiungere nuovi campi, sovrascrivere metodi o aggiungere vincoli. Le estensioni restano nel modulo personalizzato, facilitando aggiornamenti e manutenzione.
Aggiungere campi
Dichiarare nuovi campi nel modello ereditato usando il tipo corretto (Char, Many2one, Boolean, Integer, Text, Selection). Valuta se servono campi dipendenti dall'azienda per ambienti multi-company.
Estensioni in Python
Sovrascrivi metodi come button_confirm, create o write quando serve logica custom, ma richiama sempre super() per preservare il comportamento esistente. Presta attenzione ai campi calcolati e alle dipendenze per evitare incoerenze.
Odoo Studio
Odoo Studio permette di aggiungere campi senza codice ed è utile per cambi rapidi, ma per logiche complesse o per installazioni soggette ad aggiornamenti conviene creare moduli personalizzati. Il modello purchase.order è accessibile anche via API (XML-RPC, JSON-RPC) per integrazioni.
Buone pratiche
- Usa lo stato corretto in ogni fase: non saltare passaggi né aggirare la logica di conferma.
- Imposta partner_ref quando il fornitore fornisce un proprio riferimento: facilita la riconciliazione tra ordini, ricevute e fatture.
- Usa il campo origin per tracciare la provenienza degli ordini: è cruciale in dropshipping e nella filiera di produzione.
- Per integrazioni API utilizza XML-RPC o JSON-RPC e mappa con cura gli ID esterni: il modello purchase.order è esposto e accetta operazioni remote.
- Per i campi personalizzati usa il prefisso x_ o un prefisso modulare per evitare collisioni con futuri campi standard di Odoo.
Errori comuni
- Modificare ordini confermati senza rispettare lo stato. Gli ordini confermati limitano alcune modifiche: se serve, crea un nuovo ordine o segui il workflow previsto.
- Confondere partner_id con dest_address_id: partner_id indica il fornitore, dest_address_id è il luogo di consegna (utile per dropshipping).
- Sovrascrivere button_confirm senza chiamare super(): questo può rompere integrazioni o comportamenti attesi di altri moduli.
- Aggiungere campi obbligatori senza fornire default: le righe o gli ordini esistenti potrebbero fallire nelle convalide dopo l'aggiornamento.
- Dimenticare di impostare currency_id in scenari multi-valuta: una valuta sbagliata può causare prezzi errati e problemi di fatturazione.
Conclusione
Il modello purchase.order è il cuore del modulo Acquisti in Odoo: contiene RFQ e ordini confermati. Conoscere i suoi campi e come viene esteso aiuta a configurare, personalizzare e integrare Odoo in modo efficace.
Che tu sia un consulente funzionale che disegna processi di acquisto o uno sviluppatore che crea moduli, padroneggiare purchase.order evita perdite di tempo e molti errori pratici.
Hai bisogno di aiuto con la tua implementazione Odoo?
Dasolo supporta aziende nell'implementazione, personalizzazione e ottimizzazione di Odoo, con particolare esperienza in integrazioni API e sviluppo su misura. Conosciamo a fondo l'architettura dati di Odoo e modelli come purchase.order.
Se vuoi supporto per la tua implementazione Odoo, moduli custom o integrazioni, possiamo aiutarti. Prenota una demo per discutere il tuo progetto.