Einführung
Wer mit Odoo arbeitet, kennt Felder, deren Werte automatisch aus anderen Daten abgeleitet werden. Ein gespeichertes berechnetes Feld geht darüber hinaus: die berechnete Information wird nicht nur zur Laufzeit ermittelt, sondern dauerhaft in der Datenbank abgelegt.
Dieser Unterschied wirkt unscheinbar, hat aber große Folgen. Werte, die nur zur Laufzeit berechnet werden, lassen sich schlecht in Filtern, Gruppierungen oder Berichten verwenden. Ein gespeichertes Feld hingegen verhält sich wie jede gewöhnliche Spalte in der Datenbank und ist damit direkt durchsuch- und auswertbar.
Diese Übersicht erklärt alles Wichtige zu gespeicherten berechneten Feldern in Odoo: wie sie im Datenmodell funktionieren, wie man sie per Studio oder Python erstellt, typische Anwendungsfälle aus der Praxis und welche Fehler man vermeiden sollte.
Was ist ein gespeichertes berechnetes Feld in Odoo?
In Odoos ORM speichert jedes Feld einen Datenwert. Die meisten Felder nehmen Eingaben von Benutzern entgegen. Ein berechnetes Feld dagegen erhält seinen Wert aus einer Python-Funktion statt durch manuelle Eingabe.
Ein gespeichertes berechnetes Feld ist im Grunde ein berechnetes Feld mit store=True. Ändern sich die abhängigen Felder, führt Odoo die Compute-Funktion aus und schreibt das Ergebnis in die Datenbankspalte. Ab dann steht der Wert wie jeder andere Feldwert zur Verfügung.
Das Grundmuster in Python sieht typischerweise so aus:
total_amount = fields.Float(
string='Total Amount',
compute='_compute_total_amount',
store=True,
)
@api.depends('quantity', 'unit_price')
def _compute_total_amount(self):
for record in self:
record.total_amount = record.quantity * record.unit_price
Das optionale Argument store=True ist die entscheidende Abgrenzung. Fehlt es, wird der Wert bei jedem Zugriff neu berechnet, aber nicht in der Datenbank persistiert.
Für Anwender sieht ein gespeichertes berechnetes Feld in den Formularen, Listen und Berichten genauso aus wie ein normales Feld. Es gibt keinen sichtbaren Hinweis darauf, dass der Wert per Logik bestimmt wird — dafür lässt er sich filtern, gruppieren und exportieren.
Gespeicherte vs. nicht-gespeicherte berechnete Felder
Dieses Verständnis ist zentral für jede Odoo-Anpassung:
- Nicht-gespeichertes berechnetes Feld: Zur Laufzeit berechnet. Nicht als Such- oder Gruppierungskriterium verwendbar. Spart Speicher, ist aber für Datenbankabfragen nicht verfügbar.
- Gespeichertes berechnetes Feld: Bei Änderung der Abhängigkeiten berechnet und in die DB geschrieben. Suchbar, filterbar und exportierbar. Beansprucht Speicherplatz wie eine reguläre Spalte.
Die Wahl hängt vom Einsatzzweck ab: Nur Anzeige auf einem Formular? Dann reicht ein nicht-gespeichertes Feld. Sie benötigen Filter, Sortierung oder Aggregation? Dann ist store=True erforderlich.
Wie das Feld funktioniert
Beim Definieren eines gespeicherten berechneten Felds richtet das ORM automatische Auslösemechanismen ein, basierend auf den Feldern in @api.depends().
Wenn eines der abhängigen Felder geändert wird, markiert Odoo den Datensatz zur Neuberechnung, führt die Compute-Methode aus und schreibt das Ergebnis zurück in die Datenbankspalte.
Der Lebenszyklus der Neuberechnung
So läuft eine Neuberechnung typischerweise ab:
- Ein Nutzer oder ein automatisierter Prozess ändert ein Feld, das in @api.depends() genannt ist.
- Odoo erkennt die Änderung und ermittelt alle betroffenen Datensätze.
- Die Compute-Methode wird für diese Datensätze ausgeführt.
- Das berechnete Ergebnis wird in die entsprechende Datenbankspalte geschrieben.
- Der aktualisierte Wert steht für Suche, Filter und Export zur Verfügung.
Meistens geschieht die Neuberechnung synchron in derselben Transaktion. Bei großen Massenänderungen kann Odoo Berechnungen aber auch auf Hintergrundprozesse verlagern.
Abhängigkeiten über verknüpfte Modelle hinweg
@api.depends() erlaubt Punktpfade, um Felder auf verwandten Modellen zu referenzieren. Beispiel:
@api.depends('partner_id.country_id.name')
def _compute_country_name(self):
for record in self:
record.country_name = record.partner_id.country_id.name or ''
Odoo verfolgt hier Änderungen an partner_id, country_id und name über Modellgrenzen hinweg. Wenn sich der Ländername ändert, werden automatisch alle abhängigen Datensätze neu berechnet — eine starke Funktionalität des Frameworks.
Auswirkungen auf die Datenbank
Da das Feld gespeichert wird, legt Odoo eine echte Spalte in der PostgreSQL-Tabelle an. Dadurch werden Abfragen auf diesem Feld direkt durch SQL bedient und sind genauso performant wie bei normalen Feldern.
Praktische Geschäftsanwendungen
Fünf praxisnahe Beispiele aus dem Geschäftsalltag:
1. Vertrieb: Margenprozentsatz auf Verkaufspositionen
Vertriebsteams wollen Margen pro Verkaufsposition sofort sehen. Ein gespeichertes Feld berechnet die Marge aus Verkaufspreis und Einkaufspreis und speichert das Ergebnis. So lassen sich Positionen nach Marge filtern, unprofitable Artikel schnell identifizieren und Pivot-Auswertungen nach Margenstufen durchführen.
2. CRM: Tage ohne Aktivität bei Leads
Ein gespeichertes Feld auf Leads kann die Tage seit der letzten Aktivität abbilden. Zusammen mit einem geplanten Cronjob, der täglich neu berechnet, können Vertriebsmitarbeiter Leads nach Inaktivität filtern — automatische Nachverfolgung ohne manuelle Pflege.
3. Lager: Netto verfügbare Menge
Bei Produkten mit komplexen Regeln speichert ein berechnetes Feld vorab den verfügbaren Bestand (on-hand minus reserviert). Dadurch lassen sich Produktlisten nach Verfügbarkeit sortieren, ohne dass bei jeder Anzeige aufwändige Lagerberechnungen live laufen.
4. Buchhaltung: Anzahl überfälliger Rechnungen pro Kunde
Auf dem Kontaktmodell kann ein Feld die Zahl überfälliger Rechnungen speichern. Dann sortiert das Rechnungswesen die Kundenliste nach überfälligen Posten — möglich, weil der Wert in der Datenbank vorliegt.
5. Fertigung: Gesamte geschätzte Arbeitszeit
In Stücklisten summiert ein gespeichertes Feld die Zeiten aller Arbeitsgänge. Planer können Stücklisten nach Gesamtarbeitszeit filtern und so Kapazitätsplanung und Scheduling erleichtern. Änderungen an Arbeitsgängen aktualisieren die Summe automatisch.
Anlegen und Anpassen des Felds
Gespeicherte berechnete Felder lassen sich auf zwei Wegen erstellen: schnell per Odoo Studio oder flexibel per eigenem Python-Modul.
Arbeiten mit Odoo Studio
Studio erlaubt das Anlegen einfacher berechneter Felder ohne Code. Beim Erstellen von Integer-, Float- oder Monetary-Feldern kann eine Formel hinterlegt werden — oft eine Python-ähnliche Ausdruckslogik — und Studio kümmert sich um die Abhängigkeitsverfolgung.
Studio eignet sich für leichte Rechenlogik innerhalb desselben Datensatzes. Sobald Verknüpfungen zu Fremdmodellen, Bedingungen oder Aggregationen über Kinderdatensätze nötig sind, stößt Studio an seine Grenzen und ein Modul mit Python ist die bessere Wahl.
Kurz gesagt: Studio ist schnell und praktisch für einfache Fälle; für komplexe Geschäftslogik braucht es Python-Module.
Erstellen per eigenem Python-Modul
Für alles über Basisformeln hinaus definiert man das Feld in einem eigenen Odoo-Modul in Python. Beispiel: Hinzufügen eines Margen-Prozentfelds auf Verkaufspositionen.
from odoo import models, fields, api
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
x_margin_pct = fields.Float(
string='Margin %',
compute='_compute_margin_pct',
store=True,
digits=(5, 2),
)
@api.depends('price_unit', 'purchase_price')
def _compute_margin_pct(self):
for line in self:
if line.price_unit:
line.x_margin_pct = (
(line.price_unit - line.purchase_price) / line.price_unit
) * 100
else:
line.x_margin_pct = 0.0
Beim Installieren des Moduls legt Odoo die Spalte x_margin_pct in der Datenbank an, rechnet die Werte für vorhandene Datensätze und beginnt, Änderungen an price_unit und purchase_price nachzuverfolgen.
Das Präfix x_ ist die übliche Konvention für benutzerdefinierte Felder in Odoo, um Kollisionen mit Core-Feldern zu vermeiden.
Ein gespeichertes berechnetes Feld editierbar machen
Standardmäßig sind berechnete Felder schreibgeschützt. Sollten Anwender gelegentlich den berechneten Wert überschreiben dürfen, definiert man eine inverse-Methode. Diese läuft beim Schreiben auf das Feld und kann die zugrunde liegenden Quellfelder entsprechend anpassen — nützlich, wenn der berechnete Wert ein sinnvoller Default, aber nicht immer endgültig ist.
Odoo-Studio-Felder und das XML-RPC-API
Über das XML-RPC-API lassen sich Standardfelder via ir.model.fields anlegen. Logik für gespeicherte berechnete Felder hingegen muss serverseitig in Python leben. Das API ist praktisch zum automatisierten Provisioning einfacher Felder, doch komplexe Compute-Logik erfordert ein installiertes Modul auf dem Server.
Empfohlene Vorgehensweisen
Erprobte Praktiken für gespeicherte berechnete Felder
Deklarieren Sie alle Abhängigkeiten präzise
@api.depends() muss jede Feldreferenz enthalten, die Ihre Compute-Methode liest. Fehlt ein Eintrag, aktualisiert Odoo den Wert nicht bei Änderungen dieser Quelle. Gehen Sie die Compute-Logik Zeile für Zeile durch und listen Sie jede genutzte Feldzugriffskette im Decorator.
Halten Sie Compute-Methoden performant
Die Compute-Methode wird für alle betroffenen Datensätze ausgeführt — das können sehr viele sein. Vermeiden Sie zusätzliche Datenbank-Suchen in der Methode. Greifen Sie möglichst auf bereits geladene Relationen zu und minimieren Sie pro Datensatz ausgelöste Queries.
store=True nur bei Bedarf verwenden
Gespeicherte Felder belegen Speicher und verursachen Schreiboperationen bei jeder Neuberechnung. Wird das Feld nur angezeigt und nie gefiltert oder aggregiert, ist ein nicht-gespeichertes Feld effizienter. Treffen Sie diese Entscheidung bewusst.
Edge-Cases in der Compute-Methode berücksichtigen
Berücksichtigen Sie leere oder fehlende Werte. Division durch Null, fehlende Relationen oder Null-Werte sind häufige Ursachen für Fehler. Definieren Sie Fallbacks und sichere Defaults, wenn die normale Berechnung nicht möglich ist.
Initiale Neuberechnung bei großen Tabellen planen
Beim Installieren eines Moduls mit einem neuen gespeicherten Feld fährt Odoo die Neuberechnung für alle bestehenden Datensätze. Bei Hunderttausenden von Zeilen kann das lange dauern. Testen Sie Migrationen in einer Staging-Umgebung und planen Sie gegebenenfalls Hintergrundverarbeitung oder Wartungsfenster.
Zirkuläre Abhängigkeiten vermeiden
Wenn Feld A von Feld B abhängt und Feld B von Feld A, wirft Odoo beim Laden des Moduls einen Fehler. Gestalten Sie Abhängigkeiten so, dass sie nur in eine Richtung fließen.
Häufige Fallstricke
Vergessen von store=True
Das ist ein häufiger Fehler: Im Formular funktioniert alles, bis jemand versucht, das Feld als Filter oder in einem Bericht zu nutzen — dann fehlt die Persistenz. Entscheiden Sie vor dem Implementieren, ob das Feld suchbar sein muss, und setzen Sie gegebenenfalls store=True.
Fehlende Abhängigkeit im @api.depends
Wenn Ihre Methode partner_id.country_id liest, Sie aber nur partner_id in @api.depends angeben, aktualisiert Odoo das Feld nicht bei Länderänderungen. Tracen Sie vollständige Pfade und listen Sie jeden Schritt explizit im Decorator.
Stille Fehler in der Compute-Methode
Wenn eine Compute-Methode für einen Datensatz eine Ausnahme wirft, überspringt Odoo die Neuberechnung stillschweigend und behält den alten Wert. Solche Probleme tauchen oft nur in den Server-Logs auf und führen zu veralteten Werten. Testen Sie die Methode gegen Fälle mit fehlenden oder ungewöhnlichen Daten.
Performance-Probleme bei großen Datenmengen
Was in der Entwicklung schnell ist, kann in Produktion zum Engpass werden, wenn die Tabelle auf Zehntausende Datensätze wächst. Achten Sie auf die Anzahl der Queries pro Datensatz — ein zusätzlicher Query pro Datensatz kann bei 10.000 Datensätzen schnell zu tausenden zusätzlichen Abfragen werden.
sudo() innerhalb von Compute-Methoden verwenden
Ein Aufruf von sudo() in der Compute-Methode umgeht Rechteprüfungen und kann ein Sicherheitsrisiko darstellen. Wenn dadurch Daten sichtbar werden, die der aktuelle Benutzer nicht sehen sollte, untergräbt das Odoos Berechtigungsmodell. Verwenden Sie sudo() nur mit bedachtem Sicherheitskonzept.
Nicht in allen Kontexten mit sofortiger Neuberechnung rechnen
Interaktive Operationen führen meist zu synchroner Neuberechnung, bei Batch-Importen, Hintergrundjobs oder speziellen Kontextflags kann Odoo jedoch auf Aufschub setzen. Bauen Sie Geschäftslogik nicht darauf, dass der gespeicherte Wert unmittelbar nach jedem Schreiben bereits aktualisiert ist.
Fazit
Gespeicherte berechnete Felder gehören zu den mächtigsten Werkzeugen beim Aufbau und der Erweiterung von Odoo. Sie automatisieren Berechnungen, sorgen für Datenkonsistenz und machen Werte direkt für Suche und Berichte verfügbar — ohne manuelle Pflege.
Wichtige Takeaways:
- Verwenden Sie store=True, wenn das Feld suchbar, filterbar oder exportierbar sein soll.
- Deklarieren Sie alle Abhängigkeiten in @api.depends(), auch feldübergreifende Pfade.
- Halten Sie Compute-Methoden performant und behandeln Sie Randfälle explizit.
- Für einfache Formeln ist Odoo Studio schnell; bei komplexer Logik schreiben Sie Python.
- Planen Sie die initiale Neuberechnung bei großen Tabellen bei der Bereitstellung ein.
Ob Sie ein neues Modul bauen, ein bestehendes Modell erweitern oder Odoo-Feldtypen kennenlernen: Gespeicherte berechnete Felder verbinden ORM, Datenbank und Geschäftslogik und lohnen sich, wenn Sie sie richtig einsetzen.
Brauchen Sie Unterstützung bei Ihrer Odoo-Einführung?
Dasolo begleitet Unternehmen bei Implementierung, Anpassung und Optimierung von Odoo in vielen Geschäftsbereichen. Ob Sie berechnete Felder benötigen, Berichte auf Basis berechneter Werte bauen wollen oder Ihre Odoo-Entwicklung voranbringen möchten — unser Team bringt entsprechende Erfahrung mit.
Kontaktieren Sie uns gern, wenn Sie Unterstützung für Ihr Odoo-Projekt suchen. Wir besprechen Ihre Anforderungen und finden die passende Lösung für Ihr Unternehmen.