TraQL 1.0.0 pour Odoo 18.0
Ce qui est livré, ce qui répond, ce qui ne répond pas.
Quelles versions
TraQL 1.0.0, pour Odoo 18.0. La version est lue
dans ir_module_module, sur le module base, dont le champ
latest_version vaut 18.0.1.3 — le 18.0 est la
version d'Odoo, le 1.3 la révision du module.
La base d'épreuve n'est pas une base ordinaire, et c'est voulu. Elle
porte deux sociétés, et ses pièces sont libellées dans
deux devises, avec un taux de change déclaré pour le dollar au
1er janvier 2026. Le périmètre déclaré est donc
company_id IN (1, 2).
C'est l'inverse de la base d'épreuve de Dolibarr, qui est mono-société et mono-devise. Les hypothèses déclarées ne sont pas les mêmes d'un logiciel à l'autre, et elles changent ce que les chiffres veulent dire. Un intégrateur qui compare les deux pages doit le savoir avant de comparer les chiffres.
Le paquet
35 fichiers, 135,6 kB compressés, 426,9 kB décompressés.
Deux dossiers : cartographe/ et bibliotheque/.
Ce paquet a été assemblé le 31 août 2026 à 07:44 UTC — la date est
dans paquet.json, sous assemble_le, et c'est elle qui dit de quel
assemblage cette page parle.
Les 20 fichiers de cartographe/ :
LISEZ-MOI-CLIENT-odoo.md— le mode d'emploilecteur3.js— le moteurusage.js·demandes.jsbase-odoo.json·contrat-odoo.json·lecture-odoo.json·schema-odoo.json·menus-odoo.json·confrontations-odoo.jsonpatrons.json·vocabulaire-matiere.json·territoire-langue.json·mots-outils.json·listes-client.jsonconnexion-exemple.json·clown-exemple.json·modele-exemple.json·modele-distant-exemple.json·modele-vllm-exemple.json
confrontations-odoo.json n'est pas recopié de nos fichiers de
travail : il est produit au moment où le paquet est fabriqué. Il porte ce que les
autres écrans d'Odoo répondent à la même question, et ce que chacun compte en trop
— rien de plus. La règle complète de ces écrans, et l'endroit du code de l'éditeur où elle
est écrite, restent chez nous.
Un fichier de plus que pour Dolibarr : menus-odoo.json, qui n'a pas
d'équivalent de l'autre côté.
Ce qui n'en sort pas. Les outils d'atelier ne sont pas dans le
paquet — pas seulement inactifs : absents. Ils sont dix-sept :
banc, epreuve-gardes, couverture,
sonder, verifier, assembler,
diagnostic, check, comparer,
mutation, catalogue, banc-reconnaissance,
identites, avec-et-sans, carte,
epreuve-couverture, interface.
L'installation
1. Créez un compte de lecture sur votre base.
CREATE USER traql WITH PASSWORD 'votre_mot_de_passe'; GRANT USAGE ON SCHEMA public TO traql; GRANT SELECT ON ALL TABLES IN SCHEMA public TO traql;
2. Remplissez le fichier de connexion. Copiez
cartographe/connexion-exemple.json en
cartographe/connexion-odoo.json et renseignez l'hôte, le port, le nom de la
base et le compte. Le mot de passe n'y figure pas : vous le posez au lancement.
export TRAQL_DB_PASSWORD='votre_mot_de_passe' # Linux, macOS $env:TRAQL_DB_PASSWORD='votre_mot_de_passe' # Windows PowerShell
3. Posez une question.
node cartographe/lecteur3.js --logiciel=odoo "mon chiffre d'affaires 2026"
Il rend la requête et sa définition, sans rien exécuter. Pour qu'il l'exécute aussi :
node cartographe/lecteur3.js --logiciel=odoo --executer "mon chiffre d'affaires 2026"
Les prérequis
Node.js, version 18 ou plus récente. Et un compte de base
en lecture seule : GRANT SELECT sur le schéma
public, rien d'autre.
Ce compte est la garantie. TraQL ne peut pas écrire parce que votre base le lui
refuse, pas parce que son code s'en abstient. Vous pouvez le vérifier vous-même :
essayez un UPDATE avec ce compte, il sera rejeté.
Ce que TraQL ne demande jamais : aucun droit d'écriture, aucun accès administrateur, aucun port ouvert, aucune connexion sortante. Il n'interroge pas non plus Odoo par son interface ni par son service web — il lit la base.
Les dépendances et leurs licences
27 paquets npm, dont 2 directes :
mysql2 3.23.2 et pg 8.22.0, tous deux sous licence MIT. Les
versions sont exactes, pas des plages : deux installations à deux dates posent le même
pilote.
Aucune licence non permissive. Sur les 27 : 23 MIT, 2 Apache-2.0
(denque, long), 2 ISC (pg-int8,
split2). Aucun paquet sans licence déclarée. Ce sont exactement les mêmes
27 paquets aux mêmes versions que pour Dolibarr : les deux pilotes sont livrés
ensemble, quel que soit le logiciel.
Un emprunt de code, déclaré. La table de correspondances de
bibliotheque/decouper — celle qui fait se rejoindre « Straße » et
« Strasse » — vient d'OpenRefine (FingerprintKeyer), sous licence BSD, Copyright 2010
Google Inc. C'est le seul emprunt du paquet, et il est nommé dans le code lui-même.
Ce qui répond
18 questions, déclinées en 33 combinaisons question × périmètre. Une question déclinée sur plusieurs périmètres ne compte que pour une, et son verdict est le pire de ses déclinaisons : elle ne « marche » que si elle marche partout.
Quatorze répondent sans réserve :
- combien il y en a
- les factures d'une période
- votre chiffre d'affaires — le total de ce que vous avez facturé
- ce qu'on vous doit
- ce que vos clients ont réellement payé
- la taxe d'une période
- les devis qui expirent
- les devis d'une période
- le prix d'un article
- l'historique d'un client
- les commandes d'une période
- les notes de frais d'une période
- ce que vous avez en banque aujourd'hui
- ce que vous avez acheté — le total de vos factures fournisseur
Deux répondent sous une réserve déclarée, et c'est la même pour les
deux : la devise n'est pas une colonne de crm_lead, c'est une valeur
déclarée — 'EUR' AS devise. Elle est vraie tant que ce client ne facture
que dans une seule devise.
- vos projets et opportunités en cours
- les opportunités commerciales remportées
Deux sont sans objet chez Odoo, et ce n'est pas un manque de TraQL. Ce sont deux questions que Dolibarr sait poser et qu'Odoo n'a pas :
- le contrat d'abonnement — absent de l'édition communautaire, où c'est un module Enterprise. Vérifié dans le dépôt et dans la base : aucune table de contrat ni d'abonnement.
- le don reçu — aucun module de don dans le standard Odoo. Ce que Dolibarr appelle un don serait ici une facture de vente ordinaire.
C'est déclaré dans le fichier de lecture, avec la date de la mesure, pour que personne ne les cherche et pour qu'un client sache que ce n'est pas TraQL qui ne sait pas.
Deux hypothèses valent pour toutes les questions, et elles se
changent dans un fichier de déclaration : le périmètre porte les deux sociétés
(company_id IN (1, 2)), et celui qui interroge est supposé voir tous les
tiers.
Ce que TraQL ne fait pas
Il ne choisit pas le périmètre à la question. Chez Odoo, les sociétés qu'un utilisateur voit dépendent de sa session ou de son compte. TraQL n'a ni session ni compte Odoo : il lit un périmètre déclaré, le même pour toutes les questions. Un utilisateur qui ne verrait qu'une société chez son éditeur en verra deux ici. Le périmètre est écrit, relisible, et le moteur s'arrête s'il ne couvre pas la base.
Il ne dit pas si votre Odoo est en édition Community ou Enterprise.
Cette information ne se lit pas en base : le gabarit qui l'affiche l'écrit en dur et ne
consulte aucune table. Il existe un indice dans ir_module_module.license,
mais un indice présenté comme un constat est exactement ce que TraQL refuse de faire.
Il ne vérifie pas le SENS de vos colonnes. Ce qu'il contrôle, c'est que les colonnes déclarées existent bien dans votre base. Si un module a détourné une colonne pour y ranger autre chose, il ne le verra pas.
Il ne voit que les droits du compte que vous lui donnez. Sa lecture des privilèges est sincère, pas exhaustive : c'est la question posée, et le rapport nomme toujours le compte.
Le sondage de votre base
Il a eu lieu à la fabrication, pas chez vous. La base a été
regardée avant que ce paquet soit fait, et cartographe/schema-odoo.json
porte ce qui y a été constaté. La date du sondage est dans paquet.json,
sous base_sondee_le.
Ce que ça vous donne : le lecteur n'ouvre pas votre base pour produire une requête — il relit ce fichier. C'est ce qui rend ses réponses reproductibles : la même question, sur le même paquet, rend la même requête.
Ce qui a été lu, et pourquoi.
- Le schéma — 12 tables, 569 colonnes. Pour savoir quelles colonnes existent réellement chez vous, et prendre celle que votre base porte plutôt que la première d'une liste.
- L'exercice, lu sur
res_company:fiscalyear_last_monthvaut 12 etfiscalyear_last_dayvaut 31, donc l'exercice commence au mois 1. Sans lui, « cette année » répondrait sur l'année civile même si vous clôturez ailleurs. - La devise — EUR, lue par
res_company.currency_idpuisres_currency.name: chez Odoo la colonne porte une clé, pas un code, et le chemin est déclaré. C'est elle qui permet d'écrireen EURà côté d'un total, et de refuser d'additionner deux monnaies sans le dire. - Les sociétés — 2, comptées sur
res_company, identifiants 1 et 2. Ce nombre décide de la justesse de toutes les clauses de périmètre : au-delà d'une société, une réduction que TraQL fait cesse d'être exacte, et il s'arrête plutôt que de la faire quand même. - Les règles de périmètre — 9 tables regardées. Odoo écrit sa
règle de visibilité dans
ir_rule, et TraQL la reprend en entier ou pas du tout. Six sont reproduites :account_move,account_move_line,sale_order,account_payment,account_bank_statement_line,hr_expense_sheet. Trois ne le sont pas, et le sondage dit pourquoi pour chacune —res_partneretproduct_templateemploient l'opérateurparent_of, que TraQL ne sait pas poser en SQL ;crm_leadporte un séparateur que le sondeur ne sait pas lire. Sur ces trois-là, l'écran d'Odoo peut montrer d'autres lignes que TraQL, et c'est écrit plutôt que tu.
Ce qui n'a pas été lu. Aucune valeur de donnée métier : pas un
montant, pas un nom de tiers, pas une ligne de facture. Les seules lectures sont
information_schema pour des noms de colonnes, la version du serveur,
res_company pour des réglages, et ir_rule pour le texte des
règles de l'éditeur.
Le sondeur sait aussi compter des lignes — un COUNT(*) qui rend un
nombre, jamais une valeur. Sur votre base, le seul lancé a compté les sociétés.
Quand votre base change — montée de version, module installé, réglage modifié — demandez un paquet à jour. Le sondage se fait à la fabrication : un paquet ne se met pas à jour tout seul, et TraQL ne devine pas qu'une règle a bougé.
Les chiffres de référence
Obtenus sur la base d'épreuve décrite plus haut — deux sociétés, deux devises — avec le compte en lecture seule.
« mon chiffre d'affaires 2026 »
ton chiffre d affaires — le total de ce que tu as facture HT · année 2026 en EUR
3 250,13 (sur 12 lignes)
« la taxe 2026 »
la taxe d'une période taxe · année 2026 UNITÉ NON BORNÉE
360,00 (sur 12 lignes)
ce total additionne sans borner la devise — si cette base en porte plusieurs, il les mélange
Le second chiffre est le plus utile des deux, et c'est celui qui montre ce que TraQL fait. Ces 360,00 sont 160,00 EUR sur 10 lignes plus 200,00 USD sur 2 lignes — deux monnaies additionnées comme si c'était la même. Le total est arithmétiquement exact et économiquement faux.
TraQL refuse de le présenter comme un montant parce que la colonne
sommée ne porte pas de devise : il ne peut donc pas garantir que tout ce total est dans
la même monnaie, et un montant dont on ignore l'unité ne se défend pas devant un
comptable. Alors il l'écrit — UNITÉ NON BORNÉE — au lieu de le taire.
Pour le chiffre d'affaires, la même base rend en EUR : là, la devise est
bornée, et c'est la différence entre les deux lignes.
Et voici ce qu'il rend quand on lui demande le détail. On y regarde trois choses : la règle appliquée avec l'endroit du logiciel où elle est écrite, la requête produite mot pour mot, et les autres réponses que votre propre logiciel donne à la même question — avec ce que chacune compte en trop ou en moins.
node cartographe/lecteur3.js --logiciel=odoo --executer --details "mon chiffre d'affaires 2026"
« mon chiffre d'affaires 2026 »
ton chiffre d affaires — le total de ce que tu as facture HT · année 2026 en EUR
3 250,13 (sur 12 lignes)
SELECT ROUND(SUM(account_move.amount_untaxed_signed), 2), COUNT(*) FROM account_move WHERE move_type IN ('out_invoice','out_refund') AND state = 'posted' AND account_move.company_id IN (1, 2) AND account_move.invoice_date BETWEEN ? AND ?
valeurs : "2026-01-01" · "2026-12-31"
votre logiciel répond aussi à cette question, autrement :
(1) leur rapport de facturation (Comptabilite > Analyse) — les ACHATS et les AVOIRS, avec un signe negatif — ce rapport mesure une marge, pas un chiffre d'affaires
(2) les ventes seules, tous etats confondus — les brouillons et les annulees, et toutes les societes
en EUR — cette colonne y est déjà convertie, rien à borner
note : activité = hors taxes, c'est ce qui s'appelle ton chiffre d'affaires
Cette sortie se reproduit à l'identique chez qui relance la même commande sur la même version : c'est ce qui la rend vérifiable. Vous n'avez pas à nous croire sur parole, vous pouvez comparer.
Ce qui est connu et pas corrigé
Rien pour cette version. Les défauts ouverts aujourd'hui sont des défauts d'atelier : ils portent sur les outils de fabrication et de contrôle, qui ne sont pas dans le paquet. Aucun n'est visible depuis ce qui est livré. Cette section existe pour être remplie le jour où ce ne sera plus le cas.
Les chiffres de cette page ont été mesurés le 31 août 2026, sur le dépôt
au commit 17d9143. Ils y ont été relevés un par un, pas repris de mémoire.