Odoo 20 sait enregistrer hors connexion. Au retour du réseau, la dernière synchronisation l'emporte, même quand elle porte la saisie la plus ancienne. Nos applications mobiles pour Odoo relisent Odoo avant d'écrire : quand deux saisies se croisent, rien n'est écrasé et l'utilisateur choisit.
Le test tient en trois lignes. L'utilisateur A passe hors ligne et enregistre « AAA ». L'utilisateur B, en ligne, enregistre « BBB » quelques secondes plus tard. A se reconnecte. Valeur finale : « AAA ». La saisie de B a disparu, et personne n'a reçu d'alerte.
On avait mesuré ce résultat sur Odoo 19.4 en juillet, dans notre audit du mode hors connexion. Le 23 octobre, on a rejoué le même protocole sur Odoo 20.0 : Odoo 20 hors ligne ne change pas ce point.
Ce que fait Odoo 20 hors ligne, et ce qu'il fait bien
Le test montre aussi ce qui marche.
- Deux utilisateurs modifient des champs différents : les deux modifications survivent, parce qu'Odoo 20 n'envoie que les champs modifiés.
- La fiche est supprimée pendant le hors ligne : la synchronisation échoue avec une
MissingError. Un badge rouge « Sync issues » apparaît en haut de l'écran, la modification reste dans la file et l'utilisateur peut l'abandonner. - Le même champ des deux côtés : la dernière synchronisation gagne, sans avertissement. Le chatter montre les deux changements dans l'ordre, mais il date la saisie hors ligne à l'heure de la synchronisation. Dans notre test, le technicien a saisi « AAA » huit secondes avant que le bureau saisisse « BBB ». Le chatter affiche « BBB → AAA » deux secondes après la saisie du bureau : à la lecture, c'est le technicien qui semble avoir corrigé le bureau.
Dans les sources de la 20.0 Community, les modifications sont mises en file dans IndexedDB puis rejouées une par une comme des appels web_save ordinaires (offline_plugin.js). Aucun contrôle de version du type write_date n'apparaît sur ce chemin. C'est exactement ce qu'on avait relevé dans la 19.4 : web_save exécute un write() nu.
Pour un utilisateur de bureau qui perd le Wi-Fi dix minutes, c'est acceptable : la probabilité qu'un collègue touche la même fiche dans ce laps de temps est faible. Pour un technicien qui passe sa journée en cave ou en zone blanche, elle ne l'est plus.
Le même test sur nos applications
Nos applications synchronisent une base SQLite locale avec Odoo. On leur a fait passer le scénario AAA/BBB, puis ses deux variantes. Le tableau met les résultats à côté de ceux d'Odoo 20.
| Scénario | Odoo 20 hors ligne | Applications ASKA |
|---|---|---|
| A et B modifient deux champs différents | Les deux gardées | Les deux gardées |
| A et B modifient le même champ | La dernière synchro gagne, sans alerte | Conflit signalé, rien n'est écrasé |
| La fiche est supprimée dans Odoo | Erreur en file, à abandonner | Conflit signalé, saisie gardée |
Sur les champs différents, Odoo 20 et nos applications font la même chose : seuls les champs modifiés partent. La différence se joue sur le même champ. Un technicien reste hors ligne des heures entières, la probabilité qu'un collègue touche la même fiche n'est plus faible, et on ne laisse pas la dernière synchronisation décider à sa place.
Comment on détecte un conflit avant d'écrire
La technique porte un nom : le verrou optimiste. On ne bloque personne pendant la saisie. On vérifie, au moment d'écrire, que personne n'a touché à la donnée entre-temps. Dans notre framework, ça se joue en trois temps (figure 1).
1. Noter ce qui change, et ce qu'il y avait avant. Un déclencheur SQLite enregistre chaque champ modifié sur le téléphone, avec sa valeur d'avant et la write_date que la fiche portait dans Odoo au dernier téléchargement.
2. Relire Odoo juste avant d'envoyer. Une seule requête search_read par lot relit la write_date et les champs concernés.
3. Comparer, puis écrire ou s'arrêter.
write_dateinchangée : la modification part.- Odoo a bougé, mais sur d'autres champs : les champs de A partent, ceux de B restent.
- Le même champ a changé des deux côtés, avec des valeurs différentes : c'est un conflit. Rien n'est écrit pour cette fiche, la saisie reste sur le téléphone, et le prochain téléchargement ne l'écrase pas.
- La fiche n'existe plus dans Odoo : conflit de suppression, la saisie est gardée.
write_date d'Odoo au dernier téléchargement.search_read par lot : write_date et champs concernés.Le conflit est stocké dans la base locale. Il survit à un redémarrage de l'application, ce qui compte sur un terminal qu'on éteint le soir.
Les modèles Odoo sans write_date n'ont pas ce contrôle. Pour eux, seuls les champs modifiés partent, ce qui règle déjà le cas des champs différents.
Le piège des faux conflits
Au troisième faux conflit de la journée, un utilisateur appuie sur le premier bouton venu sans lire. Le framework écarte donc les cas où Odoo reformule une valeur à l'enregistrement, ce qui ferait croire qu'elle a changé (figure 2).
Merci<p>Merci</p>html_normalize2/30,67Pour le HTML, le framework compare les valeurs sous la forme qu'Odoo stocke, relevée dans ses sources. Pour les nombres, il lit les décimales de chaque champ par fields_get (une fois par modèle) et compare après l'arrondi d'Odoo (float_round).
Il reste des faux conflits possibles, par exemple sur un montant arrondi selon la devise ou une valeur qu'Odoo recalcule à l'enregistrement. On les a documentés. La règle qu'on s'est donnée : dans le doute, un conflit en trop, jamais un écrasement.
Ce que voit l'utilisateur
Sans écran pour le résoudre, un conflit bloque la fiche sur le téléphone, et l'utilisateur ne le sait pas. Chaque application a donc reçu un écran dédié (figure 3), qui commence par une phrase :
« Quelqu'un a modifié les mêmes champs dans Odoo pendant que vous travailliez hors ligne. Rien n'a été écrasé : choisissez la version à garder. »
Pour chaque fiche, l'écran montre les deux valeurs côte à côte et propose deux boutons : Garder ma version ou Garder Odoo. Pour une fiche supprimée dans Odoo : Le recréer ou Le supprimer ici.
Dans une application de logistique, le choix a une conséquence de plus. Un préparateur peut avoir validé un transfert sur le téléphone, alors qu'un mouvement de ce transfert est en conflit sur la quantité. L'écran le dit avant le choix : avec « Garder Odoo », l'opération sera validée avec la quantité d'Odoo ; avec « Garder ma version », avec celle du téléphone.
Cet écran est dans nos cinq applications publiées sur l'App Store et Google Play : Field Service, Logistics, Events, Sales Force et Suite.
Avertir, fusionner ou laisser gagner la dernière synchro ?
C'est la question de fond de tout mode hors ligne, et la réponse dépend du champ (figure 4).
| Stratégie | Quand l'utiliser | Exemple |
|---|---|---|
| Avertir et laisser l'humain choisir | Saisie manuelle qui a un sens métier | Adresse, quantité comptée, remarque d'intervention |
| Fusionner | Valeur cumulative ou liste | Étiquettes ajoutées, quantités en delta, pièces jointes |
| Laisser gagner la dernière synchro | Donnée technique sans valeur pour l'utilisateur | Horodatage de consultation, préférence d'affichage |
Pour une application de terrain branchée sur Odoo, la majorité des champs tombe dans la première ligne. C'est pour ça qu'on a choisi d'avertir par défaut, et de fusionner là où c'est possible. Exemple concret : nos applications ajoutent ou retirent une étiquette ((4, id) et (3, id) dans l'ORM d'Odoo) au lieu de remplacer toute la liste.
Cinq questions à poser à votre application hors ligne
Que votre application vienne de chez nous, d'un autre éditeur ou d'Odoo lui-même, ces cinq questions se vérifient en une demi-heure avec deux appareils.
- Envoie-t-elle seulement les champs modifiés ? Test : A change un champ hors ligne, B en change un autre en ligne. Les deux doivent survivre.
- Relit-elle Odoo avant d'écrire ? Test : le scénario AAA/BBB. Vous devez voir un avertissement, pas « AAA » en silence.
- Que devient une saisie sur une fiche supprimée ? Elle ne doit ni disparaître en silence, ni bloquer la file pour toujours.
- Crie-t-elle au loup ? Modifiez un champ HTML ou un nombre à décimales sans conflit réel. Aucun avertissement ne doit apparaître.
- Le conflit survit-il à un redémarrage ? Éteignez l'appareil avant de résoudre. Le conflit doit être toujours là au rallumage.
FAQ
Odoo 20 fonctionne-t-il hors ligne ?
Oui, pour enregistrer des modifications sur des fiches déjà ouvertes. Les modifications sont mises en file puis rejouées au retour du réseau. En revanche, aucun contrôle de conflit n'est fait au rejeu : la dernière synchronisation gagne.
Que se passe-t-il si deux personnes modifient la même donnée dans Odoo, l'une hors ligne ?
Avec le mode hors ligne d'Odoo 20, la valeur envoyée en dernier remplace l'autre, même si elle a été saisie avant. Une application qui pratique le verrou optimiste relit la write_date avant d'écrire et signale le conflit au lieu d'écraser.
Comment éviter les faux conflits de synchronisation avec Odoo ?
En comparant les valeurs telles qu'Odoo les stocke : HTML normalisé, nombres arrondis selon les décimales du champ. Sans cette étape, une simple remarque ou une quantité à décimales déclenche des alertes à tort.
Conclusion
Une saisie écrasée sans alerte ne laisse aucune trace : personne chez vous ne sait combien vos techniciens en ont perdu ce mois-ci.
Si vos équipes saisissent dans Odoo 20 hors ligne, ou dans une application mobile branchée sur Odoo, qu'elle vienne de chez nous ou non, réservez 30 minutes avec nous. On rejoue le scénario AAA/BBB sur votre outil, avec deux de vos appareils. À la fin, vous savez si une saisie de terrain peut disparaître chez vous sans que personne ne soit prévenu, et vous recevez le résultat par écrit. Le diagnostic est offert.
Réserver mon diagnostic de 30 minutes
À lire aussi