Zum Hauptinhalt springen
Odoo · Audit-Methode

Einen geerbten Odoo-Konnektor auditieren: Was Sie an einem Nachmittag prüfen, bevor Sie eine Zeile anfassen

Sie haben einen Konnektor für Marktplatz, Zusteller, Signatur oder EDI geerbt, den jemand anderes gebaut hat. Er fällt aus, oder niemand vertraut ihm. Zehn Punkte, das Symptom, das jeden verrät, und die Abfrage, die ihn in Minuten bestätigt.

Formular einer Instanz des Mirakl-Konnektors in Odoo: Verbindungstest OK, 206 Angebote und der Zähler der Aufrufprotokolle bei 0

Ein brauchbares Audit eines Odoo-Konnektors beginnt nicht bei den Tests. Es beginnt beim Log und bei einem echten Vorgang von Anfang bis Ende: eine Bestellung, die hereinkommt, eine Sendung, die hinausgeht, eine Rückerstattung, die zurückläuft. Der Mirakl-Konnektor bestand seine Testsuite grün in Odoo 19, 18 und 17 und versteckte 18 bestätigte Fehler; ein anderer Marktplatz-Konnektor erreichte 236 von 236 in echten Odoo.sh-Builds und versteckte 20 Vertragsfehler und 12 Versionsfehler. Jener Artikel erzählt den Fehler; dieser die Methode: zehn Punkte der Reihe nach, das Symptom, das jeden verrät, und die Prüfung, die in einen Nachmittag passt.

Kernidee: Der Konnektor, den Sie erben, sagt Ihnen bereits, was ihm fehlt, in der Log-Tabelle und in den abgeschalteten Crons.

Was Sie sammeln, bevor Sie sich hinsetzen

Vier Angaben, die nicht davon abhängen, wer den Konnektor gebaut hat. Die tatsächliche Odoo-Version: SELECT latest_version FROM ir_module_module WHERE name = 'base';. Die API-Version des Drittanbieters, die der Code voraussetzt, fast immer in der Basis-URL sichtbar. Das Datum der letzten Änderung an den Mocks: git log -1 --format=%cd -- tests/. Und wer die Fehler erhält: eine E-Mail, eine Aktivität, eine Datei oder niemand.

Die zehn Punkte der Reihe nach

1. Schreibt das Log wirklich?

Symptom: Die Log-Tabelle hat nach Monaten voller Crons null Zeilen. Prüfung: SELECT last_value FROM pg_sequences WHERE sequencename = '<tabla_log>_id_seq';. Ein NULL dort bedeutet, dass diese Sequenz nie gelesen wurde: Niemand hat Zeilen gelöscht, es wurde schlicht keine geschrieben. Genau das kam in der Produktion des Mirakl-Konnektors heraus. Der Helfer, der das Log-Modell zurückgibt, lieferte bei Erfolg ein leeres Recordset, und in Odoo ist ein leeres Recordset falsch, sodass if not log_model: return False immer zutraf und jedes «das protokollieren wir» ein No-op war. Die Korrektur ist if log_model is False.

2. Der Stichtag der Synchronisation

Symptom: Eine Bestellung, die morgens angelegt und nachmittags versendet wurde, bleibt in Odoo auf dem Status vom Morgen. Prüfung: drei Bestellungen, die gestern im Marktplatz den Status gewechselt haben, verglichen mit write_date und dem Status in Odoo. Bei Mirakl fragte der Konnektor start_date ab, das nach Erstellungsdatum filtert, statt start_update_date, das nach Änderungsdatum filtert.

3. Idempotenz: doppelte Bestellung, doppelte Rückerstattung

Symptom: zwei sale.order mit derselben externen Referenz oder eine Rückerstattung, die im Marktplatz doppelt erscheint. Prüfung: SELECT client_order_ref, count(*) FROM sale_order GROUP BY 1 HAVING count(*) > 1;, und ein Duplikat über odoo shell anlegen, um zu sehen, ob die Datenbank es wirklich ablehnt: Dass die Constraint im Modell steht, heißt nicht, dass es sie in Postgres gibt. In Odoo 19 legt ein geerbtes _sql_constraints nichts mehr an, und das ORM hinterlässt nur eine Warnung im Log, sodass Sie die Garantie verlieren, ohne es zu merken; umgekehrt ist es laut, denn models.Constraint gibt es in 17 und 18 nicht, und dort lässt sich das Modul nicht einmal importieren. Und der HTTP-Client: Bei Mirakl wurde bei 5xx und Timeout für jede Methode wiederholt, auch für den PUT der Rückerstattung.

4. HTTP-Fehler und Retries

Symptom: Das Konto steht morgens «nicht autorisiert», die gesamte Synchronisation steht still. Prüfung: Lösen Sie ein 401, ein 429 und, wenn möglich, ein 403 wegen Kontingent aus. Im zweiten Fall kam das 403 wegen Kontingent nicht im dokumentierten Fehlerformat und wurde als Berechtigungsfehler gelesen: Ein Ratenlimit legte alles lahm. Zu sehen sein muss: Retry-After beachtet und mit Obergrenze, 5xx und Timeouts nur bei Lesezugriffen wiederholt, das 429 auch bei Schreibzugriffen, weil der Server es ablehnte, ohne zu verarbeiten, und das Konto nur bei einem echten Authentifizierungsfehler gesperrt.

5. Mocks gegenüber dem echten Vertrag

Symptom: ein Feld, das immer leer ankommt, ein Filter, der «nicht filtert». Prüfung: Legen Sie die aktuelle OpenAPI des Anbieters ins Repository und vergleichen Sie die Parameter jedes Wrappers, die Schlüssel jedes Schreib-Bodys und die Felder, die jeder Parser liest. Im zweiten Fall ergaben sich so 16 Abweichungen bei 88 Operationen, und vier weitere erst durch Aufrufe: Ein relativer Paginierungs-Header verhinderte, dass ab Seite eins auch nur eine Bestellung importiert wurde.

6. Berechtigungen und SSRF über Weiterleitung

Symptom: keines, und deshalb steht der Punkt auf der Liste. Prüfung: grep -rn "allow_redirects\|\.sudo()\|has_group" models/. Jeder ausgehende Aufruf muss allow_redirects=False tragen und ein 3xx ablehnen, denn requests folgt standardmäßig Weiterleitungen, und ein kompromittierter Host kann Sie auf eine interne IP schicken. Und jede action_*, die mit sudo() arbeitet, muss die Gruppe auf dem Server prüfen: Das groups= der Schaltfläche ist nur Oberfläche. Im Juli 2026 haben wir das auf rund sechzehn eigene Konnektoren angewandt.

7. Crons: numbercall und Intervalle

Symptom: «Der Cron läuft seit Dienstag nicht mehr», ohne Fehler und ohne Spur. Prüfung in Odoo 17: SELECT cron_name, active, numbercall, nextcall FROM ir_cron WHERE cron_name ILIKE '%conector%';. In 17 ist numbercall standardmäßig 1, sodass ein ohne dieses Feld deklarierter Cron einmal läuft und sich selbst deaktiviert, wie es im ir_cron.py der Serie 17.0 steht. Odoo 18 hat das Feld entfernt und 19 kennt es nicht, wer also in 18 oder 19 getestet hat, hat es nie gesehen. Und sehen Sie sich das Intervall an: Eine vollständige Synchronisation alle zehn Minuten endet in einem 429.

8. Die Odoo-Version, die der Code voraussetzt

Symptom: ein Formular ohne Chatter, ein leerer Tab «payload», eine im Marktplatz stornierte Bestellung, die in Odoo bestätigt bleibt. Prüfung: grep -rn "<chatter/>\|widget=\"json\"\|read_group\|<tree\|<list" views/ models/. Bei Mirakl traten alle vier gleichzeitig auf: <chatter/> gibt es seit 18, widget="json" nur in 19, read_group ist in 19 veraltet, und sale.order.action_cancel() liefert in 17 und 18 für eine bestätigte Bestellung einen Assistenten zurück, sodass die Stornierung nie stattfand. Es ist die Liste aus einem Modul, das in Odoo 19 kompiliert und sich nicht installieren lässt.

9. Migration der historischen Daten

Symptom: Sie korrigieren die Berechnung, und die alten Bestellungen bleiben falsch, weil der Konnektor eine bestehende Bestellung nie wieder anfasst. Prüfung: Zählen Sie die Datensätze vor der Korrektur, die die neue Regel verletzen, und entscheiden Sie zwischen einem Migrationsskript und einer einmaligen, dokumentierten Korrektur. Bei Mirakl waren es 18 Bestellungen mit doppelter MwSt. in der Summe; die 15 aktiven wurden korrigiert, nur wenn die Summe mit der des Marktplatzes übereinstimmte. Und eine Falle: Die noupdate-Daten von base, auch die Gruppen darin, werden beim Update nicht erneut angewandt, sodass eine Änderung der Zugehörigkeit die Gruppe in der Produktion leer und in Ihrer sauberen Datenbank gefüllt zurücklässt.

10. Dokumentation des Drittanbieters gegenüber dem tatsächlichen Verhalten

Symptom: Der Code tut, was das PDF sagt, und der Server tut etwas anderes. Prüfung: ein echter Aufruf pro Endpoint-Familie und eine Durchsicht, welche Endpoints heute veraltet sind. Bei Mirakl war das Modell des Dateiimports weiterhin gültig, aber die Nachrichtenfunktion nutzte einen veralteten Endpoint. Im zweiten Fall akzeptierte ein Endpoint einen einzelnen Wert, wo die Dokumentation eine Liste nannte, und dieses Referenzverzeichnis war von Anfang an leer. Er steht zuletzt, weil er der teuerste ist.

Der Nachmittag in Kürze

PunktSymptomPrüfung
LogNull Zeilen nach Monaten voller Cronscount(*) und pg_sequences.last_value
StichtagEingefrorene StatusGestrige Bestellungen gegen write_date
IdempotenzDuplikate, doppelte RückerstattungGROUP BY HAVING; lehnt die Datenbank das Duplikat ab?
HTTP-Fehler«Nicht autorisiert» nach einem 429/403401, 429, 403 auslösen
MocksFeld immer leerAktuelle OpenAPI gegen Wrapper und Parser
SSRF und BerechtigungenKeinesgrep allow_redirects, sudo(), has_group
CronsSchaltet sich ohne Fehler ab (17)SELECT active, numbercall FROM ir_cron
Odoo-VersionLeerer Chatter oder leeres payloadgrep chatter, widget json, read_group, tree/list
HistorieAltes bleibt nach der Korrektur falschFrühere Datensätze zählen, die die Regel verletzen
DokumentationDer Server tut nicht, was das PDF sagtEin echter Aufruf pro Endpoint-Familie

Was das Audit liefert: ein Bericht mit Schweregrad, keine Wunschliste

Der Bericht ordnet nach Schaden: zuerst Geld (doppelte Rückerstattung, doppelte Bestellung, MwSt. zweimal), dann Daten (eingefrorener Status, Log, das nicht schreibt, abgeschalteter Cron), dann Ergonomie. Jeder Befund trägt seine Reproduktion, und was sich nicht reproduzieren lässt, wird gestrichen: Beim Mirakl-Audit gab es 121 Kandidaten, 33 wurden in einem skeptischen Durchgang widerlegt, und nur 18 blieben übrig.

Das zweite Ergebnis ist das Gate: Die vorhandene Suite, vor und nach der Korrektur grün, beweist die Korrektur nicht. Der Beweis ist der Lauf in den drei Serien auf echten Builds, 163 von 163 in 19, 18 und 17 für Mirakl, plus eine Live-Prüfung. Das unterscheidet einen gut gemachten nativen Konnektor von einer Zwischenschicht, die nur überlebt, weil sie sich auf nichts festlegt.

Wann man flickt und wann man neu schreibt

Man flickt, wenn das Datenmodell stimmt (eine Tabelle pro Objekt des Drittanbieters, ein Log, eine eindeutige externe Referenz) und die Fehler in der HTTP-Schicht, in den Zeitfenstern und in den Versionen liegen: Das passt in eine Version, wie bei Mirakl. Man schreibt neu, wenn das Fundament fehlerhaft ist: eine API, die der Anbieter eingestellt hat, kein Log und keine externe Referenz, von Haus aus nicht idempotente Schreibzugriffe oder ein Konnektor, der an eine Odoo-Serie gebunden ist, obwohl Sie drei brauchen. Diese Entscheidung bereiten wir für Beratungen und Technologiepartner vor, die Integrationen erben, und ebenso, wenn es um den Konnektor Ihrer eigenen Software geht.

Häufige Fragen

Warum nicht mit der Testsuite beginnen?

Weil eine grüne Suite nur sagt, dass der Code zu seinem Mock passt, nicht zum Anbieter und nicht zur Produktion. Die Suite kommt ans Ende, als Gate der Korrektur.

Ist Zugriff auf die Produktion nötig?

Für die Punkte 1, 2, 3, 7 und 9 ja, oder auf eine Kopie: Die Log-Sequenz, eingefrorene Status, Duplikate und abgeschaltete Crons zeigen sich nur in echten Daten.

Was liefern Sie am Ende?

Einen Bericht mit jedem bewiesenen Befund, geordnet nach Geld, Daten und Ergonomie; die Empfehlung, zu flicken oder neu zu schreiben; und, falls Sie die Korrektur beauftragen, den Fix samt Gate in den Odoo-Serien des Kunden. Die Einzelheiten finden Sie unter Leistungen.

Nützliche Links bei FlexigoTech

Die Tests waren grün und der Konnektor funktionierte nicht32 Fehler, die die Suite nicht sahMirakl-Odoo-KonnektorWas er in einem echten Marktplatz lösen mussOdoo-Engineering für BeratungenAudit und Support für geerbte IntegrationenTechnologiepartnerWie wir mit Odoo-Partnern arbeitenOdoo-Konnektor für Ihre SoftwareWenn der zu auditierende Konnektor der Ihrer Plattform ist

Was wir dazu tun

Individuelle IntegrationenWas sie leistet, Screenshots, Versionen und Preis.

Einen Konnektor geerbt, der ausfällt oder dem niemand vertraut?

Sagen Sie uns, was er integriert, in welcher Odoo-Version er läuft und welches Symptom Sie sehen. Wir sagen Ihnen, welche Punkte der Liste wir zuerst prüfen würden und was dafür nötig ist. Schreiben Sie an comercial@flexigobe.com oder rufen Sie an unter +34 616 809 504.

Mit einem Ingenieur sprechen