Een nuttige audit van een Odoo-connector begint niet bij de tests. Hij begint bij het log en bij één echte bewerking van begin tot eind: een bestelling die binnenkomt, een zending die vertrekt, een terugbetaling die terugkomt. De Mirakl-connector haalde zijn suite groen op Odoo 19, 18 en 17 en verborg 18 bevestigde fouten; een andere marketplace-connector scoorde 236 van 236 op echte Odoo.sh-builds en verborg 20 contractfouten en 12 versiefouten. Dat artikel vertelt over de fout; dit artikel over de methode: tien punten op volgorde, het symptoom dat elk punt verraadt en de controle die in een middag past.
Kernidee: de connector die je erft vertelt je al wat er mis is, in de logtabel en in de uitgeschakelde crons.
Wat je verzamelt voordat je gaat zitten
Vier gegevens die niet afhangen van wie de connector bouwde. De echte Odoo-versie: SELECT latest_version FROM ir_module_module WHERE name = 'base';. De versie van de API van de derde partij die de code veronderstelt, bijna altijd zichtbaar in de basis-URL. De datum van de laatste wijziging aan de mocks: git log -1 --format=%cd -- tests/. En wie de fouten ontvangt: een e-mail, een activiteit, een bestand of niemand.
De tien punten, op volgorde
1. Schrijft het log echt?
Symptoom: de logtabel heeft nul rijen na maanden crons. Controle: SELECT last_value FROM pg_sequences WHERE sequencename = '<tabla_log>_id_seq';. Een NULL daar betekent dat die reeks nooit is gelezen: niemand verwijderde de rijen, er is er simpelweg nooit een geschreven. Dat kwam naar voren in de productie van de Mirakl-connector. De helper die het logmodel teruggeeft, gaf bij succes een lege recordset terug, en in Odoo is een lege recordset onwaar, dus if not log_model: return False slaagde altijd en elk "dit loggen we" was een no-op. De oplossing is if log_model is False.
2. De afkapdatum van de synchronisatie
Symptoom: een bestelling die 's ochtends is aangemaakt en 's middags verzonden, blijft in Odoo op de status van de ochtend staan. Controle: drie bestellingen die gisteren op de marketplace van status veranderden, vergeleken met write_date en de status in Odoo. Bij Mirakl vroeg de connector start_date op, dat op aanmaakdatum filtert, in plaats van start_update_date, dat op wijzigingsdatum filtert.
3. Idempotentie: dubbele bestelling, dubbele terugbetaling
Symptoom: twee sale.order met dezelfde externe referentie, of een terugbetaling die twee keer op de marketplace verschijnt. Controle: SELECT client_order_ref, count(*) FROM sale_order GROUP BY 1 HAVING count(*) > 1;, en maak een duplicaat aan vanuit odoo shell om te zien of de database het echt weigert: een constraint die in het model staat, betekent niet dat hij in Postgres bestaat. In Odoo 19 maakt een geërfde _sql_constraints niets meer aan en laat de ORM alleen een waarschuwing in het log achter, dus je verliest de garantie zonder het te merken; andersom is het luidruchtig, want models.Constraint bestaat niet in 17 en 18 en daar wordt de module niet eens geïmporteerd. En de HTTP-client: bij Mirakl werd bij 5xx en timeout voor elke methode opnieuw geprobeerd, ook bij de PUT van de terugbetaling.
4. HTTP-fouten en retries
Symptoom: het account wordt wakker als "niet geautoriseerd" en alle synchronisatie ligt stil. Controle: lokaliseer een 401, een 429 en, indien mogelijk, een quota-403 door ze uit te lokken. In het tweede geval kwam de quota-403 niet in het gedocumenteerde foutformaat en werd hij gelezen als een rechtenfout: een snelheidslimiet legde alles stil. Wat je moet zien: Retry-After gerespecteerd en met een plafond, 5xx en timeouts alleen bij leesacties opnieuw geprobeerd, de 429 ook bij schrijfacties omdat de server hem weigerde zonder te verwerken, en het account alleen geblokkeerd bij een echte authenticatiefout.
5. Mocks versus het echte contract
Symptoom: een veld dat altijd leeg aankomt, een filter dat "niet filtert". Controle: zet de actuele OpenAPI van de leverancier in de repository en vergelijk de parameters van elke wrapper, de sleutels van elke schrijfbody en de velden die elke parser leest. In het tweede geval kwamen zo 16 afwijkingen naar voren in 88 bewerkingen, en vier meer alleen door aan te roepen: een relatieve paginatieheader maakte het onmogelijk om ook maar één bestelling vanaf pagina één te importeren.
6. Rechten en SSRF via redirect
Symptoom: geen, en daarom staat het op de lijst. Controle: grep -rn "allow_redirects\|\.sudo()\|has_group" models/. Elke uitgaande aanroep moet allow_redirects=False hebben en een 3xx weigeren, omdat requests standaard redirects volgt en een gecompromitteerde host je naar een intern IP kan sturen. En elke action_* die met sudo() werkt, moet de groep op de server controleren: de groups= van de knop is alleen interface. In juli 2026 pasten we dit toe op zo'n zestien eigen connectoren.
7. Crons: numbercall en intervallen
Symptoom: "de cron stopte op dinsdag", zonder fout of spoor. Controle in Odoo 17: SELECT cron_name, active, numbercall, nextcall FROM ir_cron WHERE cron_name ILIKE '%conector%';. In 17 is numbercall standaard 1, dus een cron die zonder dit wordt gedeclareerd draait één keer en deactiveert zichzelf, zoals in de ir_cron.py van de 17.0-serie staat. Odoo 18 schafte het veld af en 19 heeft het niet, dus wie op 18 of 19 testte, zag het nooit. En kijk naar het interval: een volledige synchronisatie elke tien minuten eindigt in een 429.
8. De Odoo-versie die de code veronderstelt
Symptoom: een formulier zonder chatter, een leeg tabblad "payload", een bestelling die op de marketplace is geannuleerd maar in Odoo bevestigd blijft. Controle: grep -rn "<chatter/>\|widget=\"json\"\|read_group\|<tree\|<list" views/ models/. Bij Mirakl kwamen alle vier tegelijk voor: <chatter/> bestaat vanaf 18, widget="json" alleen in 19, read_group is deprecated in 19, en sale.order.action_cancel() geeft in 17 en 18 een wizard terug voor een bevestigde bestelling, dus de annulering gebeurde nooit. Het is de lijst van een module die compileert in Odoo 19 en zich niet laat installeren.
9. Migratie van de historische gegevens
Symptoom: je repareert de berekening en de oude bestellingen blijven fout, omdat de connector een bestaande bestelling niet opnieuw aanraakt. Controle: tel de records van vóór de correctie die de nieuwe regel overtreden en kies tussen een migratiescript en een eenmalige, gedocumenteerde correctie. Bij Mirakl ging het om 18 bestellingen met dubbele btw in het totaal; de 15 actieve werden gecorrigeerd, alleen als het totaal overeenkwam met dat van de marketplace. En een valkuil: de noupdate-gegevens van base, inclusief de groepen daarin, worden bij een update niet opnieuw toegepast, dus een wijziging van lidmaatschap laat de groep leeg in productie en gevuld in je schone database.
10. Documentatie van de derde partij versus echt gedrag
Symptoom: de code doet wat de PDF zegt en de server doet iets anders. Controle: één echte aanroep per endpointfamilie en een controle van welke endpoints vandaag deprecated zijn. Bij Mirakl was het importmodel via bestand nog van kracht, maar de berichtenservice gebruikte een deprecated endpoint. In het tweede geval accepteerde een endpoint één enkele waarde waar de documentatie een lijst noemde, en die referentietabel was vanaf het begin leeg. Het staat als laatste omdat het de duurste is.
De middag, samengevat
| Punt | Symptoom | Controle |
|---|---|---|
| Log | Nul rijen na maanden crons | count(*) en pg_sequences.last_value |
| Afkapdatum | Bevroren statussen | Bestellingen van gisteren tegenover write_date |
| Idempotentie | Duplicaten, dubbele terugbetaling | GROUP BY HAVING; weigert de database het duplicaat? |
| HTTP-fouten | "Niet geautoriseerd" na een 429/403 | 401, 429, 403 uitlokken |
| Mocks | Veld altijd leeg | Actuele OpenAPI tegenover wrappers en parsers |
| SSRF en rechten | Geen | grep allow_redirects, sudo(), has_group |
| Crons | Gaat zonder fout uit (17) | SELECT active, numbercall FROM ir_cron |
| Odoo-versie | Lege chatter of payload | grep chatter, widget json, read_group, tree/list |
| Historie | Het oude blijft fout na de reparatie | Eerdere records tellen die de regel overtreden |
| Documentatie | De server doet niet wat de PDF zegt | Eén echte aanroep per endpointfamilie |
Wat de audit oplevert: een rapport met ernst, geen verlanglijstje
Het rapport ordent op schade: eerst geld (dubbele terugbetaling, dubbele bestelling, btw twee keer), dan gegevens (bevroren status, log dat niet schrijft, uitgeschakelde cron), dan ergonomie. Elke bevinding heeft zijn reproductie en wat zich niet laat reproduceren wordt doorgehaald: bij de Mirakl-audit waren er 121 kandidaten, 33 werden weerlegd in een sceptische ronde en slechts 18 overleefden.
De tweede uitkomst is de gate: de bestaande suite, groen vóór en na, bewijst de correctie niet. Het bewijs is de run in de drie series op echte builds, 163 van 163 in 19, 18 en 17 voor Mirakl, plus een verificatie live. Dat is wat een goed gemaakte native connector scheidt van een tussenlaag die overleeft doordat hij zich nergens aan vastlegt.
Wanneer je patcht en wanneer je herschrijft
Je patcht als het datamodel klopt (een tabel per object van de derde partij, een log, een unieke externe referentie) en de fouten in de HTTP-laag, de vensters en de versies zitten: het past in één versie, zoals bij Mirakl. Je herschrijft als de basis faalt: een API die de leverancier heeft ingetrokken, geen log of externe referentie, schrijfacties die door hun ontwerp niet idempotent zijn, of een connector die aan één Odoo-serie vastzit terwijl je er drie nodig hebt. Het is de beslissing die we voorbereiden voor adviesbureaus en technologiepartners die integraties erven, en ook wanneer de connector die van hun eigen software is.
Veelgestelde vragen
Waarom niet beginnen bij de testsuite?
Omdat een groene suite zegt dat de code overeenkomt met zijn mock, niet met de leverancier of met productie. De suite komt aan het eind, als gate voor de correctie.
Is toegang tot productie nodig?
Voor de punten 1, 2, 3, 7 en 9 ja, of tot een kopie: de reeks van het log, de bevroren statussen, de duplicaten en de uitgeschakelde crons zie je alleen in echte gegevens.
Wat leveren jullie aan het eind op?
Een rapport met elke bevinding bewezen en geordend op geld, gegevens en ergonomie; het advies om te patchen of te herschrijven; en, als er wordt gecorrigeerd, de oplossing met zijn gate in de Odoo-series van de klant. De details staan bij diensten.
Nuttige links binnen FlexigoTech
Wat wij hieraan doen
Een connector geërfd die faalt of die niemand vertrouwt?
Vertel ons wat hij integreert, op welke Odoo-versie hij draait en welk symptoom je ziet. Wij zeggen je welke punten van de lijst we het eerst zouden bekijken en wat er nodig is om dat te doen. Mail naar comercial@flexigobe.com of bel +34 616 809 504.

