Einführung
Das Monetäre Feld ist einer der nützlichsten und am häufigsten missbrauchten Feldtypen in Odoo. Es sieht aus wie eine Zahl, speichert wie ein Float, verhält sich aber wie keines von beidem. Sobald Sie verstehen, was es anders macht, werden Sie niemals wieder ein einfaches Float für einen finanziellen Wert verwenden.
Wenn Sie jemals einen Gesamtbetrag einer Verkaufsbestellung, einen Rechnungsbetrag oder einen Produktpreis in Odoo angesehen haben, haben Sie bereits ein Monetäres Feld verwendet. Sie sind überall im Odoo-Datenmodell zu finden und erledigen still und leise einen Großteil der schweren Arbeit rund um Währungsformatierung, Rundung und Präzision.
Dieser Leitfaden richtet sich an Odoo-Entwickler, Berater und technisch versierte Geschäftsanwender, die verstehen möchten, wie das Monetäre Feld tatsächlich funktioniert. Egal, ob Sie ein Odoo-Feld-Tutorial folgen, ein benutzerdefiniertes Modul erstellen oder einfach nur versuchen, zu verstehen, warum Ihre Beträge anders gerundet werden als erwartet, dies ist das Referenzwerk, das Sie benötigen.
Was ist das Monetäre Feld in Odoo
Der fields.Monetary Typ ist einer der Kernfeldtypen im Odoo-Framework. Er wurde speziell entwickelt, um währungsdenominierte Werte zu speichern: Preise, Beträge, Summen, Budgets oder jede Zahl, die Geld repräsentiert.
Was ihn von einem regulären Float unterscheidet, ist die zwingende Beziehung zu einer Währung. Ein Monetary-Feld weiß immer, mit welcher Währung es arbeitet, und verwendet diese Währung, um zu bestimmen, wie viele Dezimalstellen angezeigt werden sollen und wie die gespeicherten Werte gerundet werden.
Wie es in der Benutzeroberfläche erscheint
In der Odoo-Benutzeroberfläche zeigt ein Monetary-Feld den Wert formatiert gemäß der zugehörigen Währung an. Wenn die Währung Euro ist, sehen Sie etwas wie € 1.234,50. Wenn es der US-Dollar ist, sehen Sie $ 1.234,50. Die Anzahl der Dezimalstellen folgt der Konfiguration des Währungsdatensatzes.
Das Feld ist in Formularansichten vollständig bearbeitbar, wird in Listenansichten sauber angezeigt und integriert sich natürlich in Pivot-Tabellen und Finanzberichte. Endbenutzer müssen überhaupt nicht über die Formatierung nachdenken. Odoo kümmert sich transparent darum.
Der zugrunde liegende Datentyp
Auf Datenbankebene wird ein Monetary-Feld als Double-Precision-Float in PostgreSQL gespeichert. Die Währungsinformationen werden nicht in derselben Spalte gespeichert. Sie stammen aus einem verwandten res.currency Datensatz, der über ein separates Many2one-Feld im selben Modell verknüpft ist.
Diese Trennung von Wert und Währung ist absichtlich. Sie hält die Odoo-Datenbankfelder sauber und ermöglicht es, die Währung eines Datensatzes unabhängig von den gespeicherten Beträgen zu ändern.
Wie das Feld funktioniert
Das Verständnis der Mechanik hinter dem Monetary-Feld wird Ihnen helfen, es korrekt zu verwenden und die Art von Rundungs- oder Anzeigeproblemen zu vermeiden, die überraschend häufig in der benutzerdefinierten Odoo-Entwicklung auftreten.
Der currency_field Parameter
Jedes Monetary-Feld muss mit einem Many2one-Feld gekoppelt sein, das auf res.currency verweist. Standardmäßig sucht Odoo nach einem Feld mit dem Namen currency_id im selben Modell. Sie können dies mit dem currency_field Parameter überschreiben:
amount = fields.Monetary(string='Betrag', currency_field='currency_id')
Wenn das Währungsfeld in einem bestimmten Datensatz fehlt oder nicht gesetzt ist, fällt Odoo auf die Unternehmenswährung zurück. Dies verhindert schwerwiegende Fehler, führt jedoch in einer Multi-Währungs-Umgebung zu falschen Formatierungen. Deklarieren Sie das Währungsfeld immer ausdrücklich.
Rundung und Präzision
Einer der Hauptunterschiede zwischen Monetary und Float ist, wie die Rundung funktioniert. Das res.currency Modell definiert die Anzahl der Dezimalstellen und den Rundungsfaktor für jede Währung. Wenn Odoo einen monetären Wert liest oder anzeigt, wendet es diese Regeln automatisch an.
Das bedeutet, dass ein Wert, der als 1.2349999 für ein EUR-Feld gespeichert ist, als 1.23 angezeigt wird, nicht als 1.235 oder 1.23499. Dies ist entscheidend für Steuerberechnungen, Rechnungsbeträge und jeden finanziellen Abstimmungsprozess. Die Verwendung eines einfachen Float in diesen Kontexten wird letztendlich Rundungsabweichungen erzeugen, die schwer nachzuvollziehen sind.
Interaktion mit dem Odoo ORM
Im Odoo ORM gibt das Lesen eines monetären Feldes immer einen Python-Float zurück. Der Währungs-Kontext stammt aus dem zugehörigen Währungsfeld im selben Datensatz. Bei Berechnungen in Python, die monetäre Felder betreffen, verwenden Sie die round()-Methode der Währung, um die Präzision zu bewahren:
rounded_value = self.currency_id.round(self.amount)
Dies vermeidet Fehler durch die Ansammlung von Gleitkommazahlen, die in Mehrzeilen-Gesamtsummen oder iterativen Berechnungen auftreten können.
Monetäre Felder in QWeb-Berichten
In QWeb-Berichtsvorlagen integrieren sich monetäre Felder mit einem speziellen Widget, das den Wert korrekt in PDFs und Webberichten formatiert:
<span t-esc="record.amount"
t-options='{"widget": "monetary", "display_currency": record.currency_id}'/>
Dies stellt das korrekte Währungssymbol und die Dezimalformatierung in jedem generierten Dokument sicher, unabhängig von der Währung im Datensatz.
Geschäftsanwendungsfälle
Monetäre Felder werden in den Standardmodulen von Odoo verwendet. Hier sind fünf konkrete Beispiele, die veranschaulichen, wo und warum sie in realen Geschäftsabläufen wichtig sind.
1. Verkauf: Produktpreise und Bestellsummen
Felder wie price_unit, price_subtotal und amount_total auf Verkaufsaufträgen und Auftragszeilen sind allesamt monetäre Felder. Sie respektieren automatisch die Währung, die auf dem Kundenauftrag ausgewählt wurde, die von der Betriebskostenwährung des Unternehmens abweichen kann.
Wenn ein Vertriebsmitarbeiter einen Auftrag in USD für ein Unternehmen erstellt, das in EUR operiert, kümmert sich Odoo um die Anzeige, Rundung und Umrechnung, da das monetäre Feld immer im Kontext der Währung des Datensatzes arbeitet, nicht der Systemwährung.
2. Buchhaltung: Rechnungsbeträge und Steuerzeilen
Im Buchhaltungsmodul ist jede Betragskolonne auf einer Rechnung ein monetäres Feld: amount_untaxed, amount_tax, amount_total. Die auf der Rechnung festgelegte Währung bestimmt die Rundung all dieser Werte.
Das ist kein Detail. Falsche Rundungen bei Steuerzeilen führen zu Ungleichgewichten in den Buchungssätzen, die schmerzhaft zu bereinigen sind. Die währungsbewusste Rundung des monetären Feldes verhindert diese Probleme auf Datenebene.
3. CRM: Erwartete Einnahmen bei Chancen
Das expected_revenue Feld bei einer CRM-Chance ist ein monetäres Feld. Vertriebsteams können Pipeline-Werte in der Währung des Interessenten erfassen, während Dashboards und Berichte alles in die Unternehmenswährung für die Pipeline-Analyse und Prognose umrechnen.
Dieses Setup funktioniert reibungslos, genau weil monetäre Felder Währungsinformationen zusammen mit ihrem numerischen Wert tragen.
4. Einkauf: Anbieterpreise und Bestellungen
Bestellungen verwenden monetäre Felder für Stückpreise und Summen, die mit der vereinbarten Währung des Anbieters verknüpft sind. Eine Anbieterrechnung in Japanischen Yen wird auf die gleiche Weise behandelt wie eine in Euro. Das monetäre Feld kümmert sich um Präzision und Anzeige, ohne dass das Einkaufsteam manuell eingreifen muss.
5. Benutzerdefinierte Felder: Budget- und Zielverfolgung
Eine sehr häufige Anpassungsanfrage besteht darin, einen Budgetbetrag, ein Umsatzziel oder eine Kostenobergrenze für ein Projekt, eine Abteilung oder ein benutzerdefiniertes Modell hinzuzufügen. In all diesen Fällen ist ein Geldfeld die richtige Wahl. Es integriert sich natürlich in die Unternehmenswährung, wird korrekt in Formularen und Listen angezeigt und verhält sich in Berichten und Exporten vorhersehbar.
Die Verwendung eines Float für diese Art von Feld ist technisch möglich, führt jedoch zu Formatierungsinkonsistenzen und Rundungsproblemen, sobald Mehrwährungs-Szenarien auftreten.
Erstellen oder Anpassen des Feldes
Es gibt zwei Hauptwege, um ein Geldfeld zu einem Odoo-Modell hinzuzufügen: über Odoo Studio für einen No-Code-Ansatz oder über ein benutzerdefiniertes Python-Modul für volle Kontrolle.
Verwendung von Odoo Studio
Odoo Studio enthält einen Geldtyp in seinem Feld-Erstellungsbereich. Wenn Sie Odoo Studio-Felder verwenden, um ein Geldfeld zu einem Modell hinzuzufügen, fügt Studio automatisch ein currency_id-Feld hinzu, falls noch keines in diesem Modell vorhanden ist. Dies deckt die häufigsten Anwendungsfälle ab, ohne dass Code geschrieben werden muss.
Eine Sache, die zu beachten ist: Studio-erstellte Felder verwenden das x_-Präfix (zum Beispiel x_studio_budget). Wenn Ihr Modell bereits ein currency_id-Feld hat, wird das neue Geldfeld dieses verwenden. Andernfalls wird Studio ein neues erstellen. Wenn Sie mehrere Geldfelder im selben Modell mit potenziell unterschiedlichen Währungen haben, ist es ratsam, dieses gemeinsame Währungsfeld sorgfältig zu überprüfen, bevor Sie live gehen.
Für unkomplizierte Szenarien ist Studio der schnellste Weg, um Felder in Odoo zu erstellen, und funktioniert gut für Geschäftsanwender, die keinen Entwicklungszugang haben.
Technischer Ansatz: Python-Felder
In einem benutzerdefinierten Odoo-Modul erfordert die Erstellung eines Geldfeldes zwei Deklarationen: das Feld selbst und das zugehörige Währungsfeld. Dies ist das Standardmuster in der Entwicklung von Odoo-Python-Feldern:
from odoo import fields, models
class ProjectTask(models.Model):
_inherit = 'project.task'
x_budget = fields.Monetary(
string='Budget',
currency_field='x_budget_currency_id',
)
x_budget_currency_id = fields.Many2one(
comodel_name='res.currency',
string='Budgetwährung',
default=lambda self: self.env.company.currency_id,
)
Die Festlegung der Unternehmenswährung als Standard ist eine praktische Wahl für die meisten internen Felder. Sie verhindert, dass das Währungsfeld leer erscheint, wenn ein Benutzer einen Datensatz zum ersten Mal öffnet, was die Formatierung des Geldfeldes beeinträchtigen würde.
Berechnete Geldfelder
Geldfelder funktionieren gut als berechnete Felder in Odoo. Wenn Sie Zeilenbeträge summieren oder eine Formel anwenden müssen, die ein monetäres Ergebnis liefert, ist dies das Standardmuster:
x_total_budget = fields.Monetary(
string='Gesamtbudget',
currency_field='currency_id',
compute='_compute_total_budget',
store=True,
)
@api.depends('x_line_ids.x_amount')
def _compute_total_budget(self):
for record in self:
record.x_total_budget = sum(record.x_line_ids.mapped('x_amount'))
Das Attribut store=True ist wichtig, wenn Sie planen, dieses Feld in Listenansichten oder Berichten zu filtern, zu sortieren oder zu aggregieren. Nicht gespeicherte berechnete Felder können nicht in ORM-Domainfiltern verwendet werden.
Hinzufügen eines Geldfeldes über die API
Wenn Sie Felder in Odoo programmgesteuert über XML-RPC erstellen müssen (zum Beispiel als Teil eines Remote-Konfigurationsskripts), können Sie das Geldfeld über ir.model.fields erstellen:
models.execute_kw(ODOO_DB, uid, ODOO_API_KEY,
'ir.model.fields', 'create',
[{
'name': 'x_budget',
'field_description': 'Budget',
'model_id': model_id,
'ttype': 'monetary',
'currency_field': 'currency_id',
'state': 'manual',
}]
)
Dies ist Teil des umfassenderen Odoo-Anpassungstools, das über die XML-RPC-API verfügbar ist und in anderen Artikeln dieser Blogsammlung ausführlicher behandelt wird.
Beste Praktiken
Das Geldfeld ist einfach zu verwenden, sobald Sie die Muster kennen. Hier sind die Praktiken, die Ihre Implementierung sauber halten und Probleme in der Zukunft verhindern werden.
1. Verwenden Sie niemals Float für finanzielle Werte
Dies ist die wichtigste Regel in der Odoo-Entwicklung, wenn es um Geld geht. Wenn ein Feld einen Preis, einen Betrag, eine Summe, ein Budget oder eine beliebige währungsdenominierte Zahl darstellt, verwenden Sie fields.Monetary. Ein Float-Feld hat kein Währungsbewusstsein und wird nicht korrekt über verschiedene Währungen gerundet. Das Geldfeld existiert genau, um dieses Problem zu lösen.
2. Deklarieren Sie das Währungsfeld immer ausdrücklich
Verlassen Sie sich nicht auf Odoos Rückfall auf currency_id, es sei denn, dieses Feld existiert tatsächlich in Ihrem Modell. Setzen Sie den Parameter currency_field explizit und deklarieren Sie immer das entsprechende Many2one zu res.currency. Dies macht die Beziehung klar und verhindert ein stilles Rückfallverhalten in Multi-Währungs-Umgebungen.
3. Setzen Sie eine Standardwährung
Für interne Felder, die fast immer die Unternehmenswährung verwenden, setzen Sie einen Standard im Währungsfeld: default=lambda self: self.env.company.currency_id. Dies verhindert, dass das Feld bei neuen Datensätzen leer erscheint, was das Währungssymbol und die Formatierung in der Benutzeroberfläche entfernen würde.
4. Verwenden Sie store=True bei berechneten Geldwertfeldern, die Sie durchsuchen möchten
Wenn Sie ein berechnetes Geldwertfeld definieren und erwarten, dass Benutzer oder Berichte danach filtern oder sortieren, setzen Sie store=True. Nicht gespeicherte berechnete Felder können nicht in ORM-Domänen oder SQL-basierten Ansichten erscheinen. Dies ist eine häufige Quelle für Verwirrung beim Erstellen benutzerdefinierter Dashboards in Odoo.
5. Verwenden Sie Currency Round() für Zwischenberechnungen
Beim Schreiben von Python-Code, der mehrere arithmetische Schritte mit Geldwerten durchführt, wenden Sie self.currency_id.round(value) bei jedem bedeutenden Schritt an, anstatt nur am Ende. Gleitkommafehler summieren sich über mehrere Operationen, und frühzeitiges Runden verhindert Abweichungen in den Gesamtsummen.
6. Seien Sie absichtlich in Multi-Währungs-Berichten
Beim Aggregieren von Geldwerten über Datensätze mit unterschiedlichen Währungen summieren Sie nicht einfach die Rohzahlen. Konvertieren Sie zuerst alle Werte in eine gemeinsame Währung mit res.currency.compute() oder machen Sie den Bericht währungsspezifisch. Das Mischen von Währungen in einer Summe ergibt Zahlen, die auf Feldebene technisch korrekt, aber finanziell bedeutungslos sind.
Häufige Fallstricke
Selbst erfahrene Odoo-Entwickler stoßen auf Probleme mit Geldwertfeldern. Hier sind die häufigsten Fehler und wie man sie vermeidet.
Falle 1: Fehlendes Währungsfeld
Das häufigste Problem beim Hinzufügen eines Geldwertfeldes besteht darin, das zugehörige Währungs-Many2one-Feld zu vergessen. Wenn currency_id im Modell nicht existiert, wird Odoo in einigen Kontexten still auf die Unternehmenswährung zurückfallen und in anderen einen Fehler auslösen. Erstellen Sie immer das Währungsfeld zusammen mit dem Geldwertfeld, auch wenn Sie nie erwarten, dass Benutzer es ändern.
Falle 2: Zwei Währungsfelder teilen sich ein Währungsfeld mit unterschiedlichen beabsichtigten Währungen
Wenn Sie zwei Währungsfelder im selben Modell haben, die Werte in unterschiedlichen Währungen halten sollen (zum Beispiel einen Kundenpreis in EUR und einen Lieferantenkosten in USD), können sie nicht sicher ein einzelnes currency_id-Feld teilen. Jedes benötigt seinen eigenen Währungsbezug. Wenn Sie dies nicht tun, wird eine Währungseinstellung beide Felder überschreiben, was zu falschen Daten und verwirrendem UI-Verhalten führt.
Falle 3: Rundungsdifferenzen beim Aggregieren über Währungen hinweg
Das Summieren von Währungsfeldwerten über Datensätze mit unterschiedlichen Währungen hinweg wird Totale erzeugen, die falsch aussehen, weil Sie EUR-Beträge zu USD-Beträgen addieren, als wären sie dieselbe Einheit. Dies ist eine häufige Quelle für Berichtfehler in Unternehmen, die in mehreren Währungen tätig sind. Normalisieren Sie immer auf eine einzelne Währung, bevor Sie aggregieren.
Falle 4: Gleitkomma-Vergleiche in ORM-Suchen
Das Suchen eines Währungsfeldes mit einem genauen Gleichheitsvergleich (zum Beispiel das Suchen nach Datensätzen, bei denen amount = 10.0) kann Datensätze übersehen, aufgrund der Art und Weise, wie Fließkommazahlen in der Datenbank gespeichert werden. Verwenden Sie >= und <= mit einer kleinen Toleranz oder wenden Sie Währungsrundung an, bevor Sie Werte in der Python-Logik vergleichen. Dies ist ein allgemeines Odoo-ORM-Problem mit float-basierten Feldern, nicht spezifisch für Währungsfelder, aber es ist wichtiger, wenn es um Geld geht.
Falle 5: Ignorieren der Währungsrundung während des Datenimports
Beim Importieren von Datensätzen über CSV oder XML-RPC, die Währungsfeldwerte enthalten, werden die importierten Zahlen so gespeichert, wie sie bereitgestellt wurden, ohne automatische Rundung. Wenn Ihre Quelldaten mehr Dezimalstellen haben, als die Zielwährung zulässt, wird der gespeicherte Wert technisch korrekt sein, aber anders angezeigt als erwartet, und kann kleine Abweichungen in den Totals verursachen. Wenden Sie Währungsrundung in Ihren Import-Skripten oder Datenvorbereitungs-Schritten an, bevor Sie Werte an Odoo senden.
Fazit
Das Währungsfeld ist eines dieser Odoo-Feldtypen, das auf den ersten Blick einfach aussieht, aber viel wichtiges Verhalten darunter verbirgt. Seine enge Beziehung zum Währungsdatensatz macht es zuverlässig für Finanzdaten: korrekte Rundung, konsistente Formatierung und währungsbewusste Anzeige über die gesamte Odoo-Oberfläche und den Bericht-Engine.
Es korrekt zu verwenden, was bedeutet, es immer mit einem expliziten Währungsfeld zu kombinieren und niemals einen Float für Finanzwerte zu substituieren, wird Sie vor einer ganzen Kategorie subtiler Fehler bewahren, die notorisch schwer zu finden sind. Das Odoo-Datenmodell ist aus gutem Grund um diesen Feldtyp herum aufgebaut.
Egal, ob Sie einem Odoo-Entwicklerleitfaden folgen, ein Standardmodul anpassen oder etwas Neues von Grund auf neu erstellen, die korrekte Handhabung Ihrer Währungsfelder ist eine der grundlegenden Entscheidungen, die prägt, wie zuverlässig Ihre Odoo-Implementierung mit Geld umgeht.
Brauchen Sie Hilfe bei Ihrer Odoo-Implementierung?
Bei Dasolo helfen wir Unternehmen, Odoo in allen Größen und Konfigurationen zu implementieren, anzupassen und zu optimieren. Egal, ob Sie ein sauberes Datenmodell, eine benutzerdefinierte Feldstrategie, Mehrwährungsunterstützung oder einen vollständigen Odoo-Rollout benötigen, unser Team hat die technische und funktionale Tiefe, um es richtig zu machen.
Wenn Sie Fragen zu den monetären Feldern oder einem anderen Aspekt Ihrer Odoo-Implementierung haben, helfen wir Ihnen gerne weiter. Kontaktieren Sie uns und lassen Sie uns darüber sprechen, was Sie aufbauen.