← Retour aux travaux
2023 · Migration Salesforce → Odoo

DISH Digital Solutions

Une stack Salesforce à plusieurs millions d'euros, rebâtie sur Odoo 16 pour la branche restauration-tech de METRO — le back-office commercial qui propulse DISH pour des dizaines de milliers de restaurants indépendants en Europe. Nous avons mené la recréation fonctionnelle : passerelle FastAPI, bus d'événements RabbitMQ, téléphonie Vonage, flux de vente et catalogue produit.

Rôle
Recréation fonctionnelle · API · intégrations · flux de vente
Durée
2023 – 2025, ~22 mois
Équipe
1 ingénieur Hazenfield, intégré
VISUEL DE PROJET · PLACEHOLDER
FIG. 01
Contexte

DISH est la branche restauration-tech de METRO — la plateforme SaaS qu'utilisent des dizaines de milliers de restaurants indépendants en Europe pour prendre des réservations, créer leur site web, gérer leur menu et accepter des commandes. BSS — Business Support Software — est le back-office commercial derrière : abonnements, facturation, pipeline commercial, support client, téléphonie, plateforme partenaire.

Le brief : une migration Salesforce vers Odoo — sortir toute la stack commerciale d'un abonnement à plusieurs millions d'euros par an et la rebâtir sur Odoo 16. L'argument économique était simple. L'exécution ne l'a pas été — plus de quatre-vingt-dix modules Odoo personnalisés, une équipe distincte sur la migration des données, et une équipe d'ingénierie côté client répartie entre plusieurs prestataires.

Nous avons mené la recréation fonctionnelle, intégrés dans cette équipe. La migration des données était portée par un autre groupe ; nous n'avons pas pris en charge la comptabilité. Partout ailleurs — la passerelle FastAPI que les autres outils DISH appellent, le bus RabbitMQ qui garde Odoo synchronisé avec ses systèmes voisins, l'intégration Vonage portée depuis Salesforce, le flux de vente et les consents de signature, le catalogue produit et le cycle de vie des abonnements — nous avons écrit, maintenu ou été la voix senior dans la pièce.

Nous avons aussi imposé des pratiques d'ingénierie ramenées d'ailleurs : un protocole de tests unitaires que les nouveaux modules devaient franchir avant merge, un workflow de revue de code plus net, et des décisions d'architecture écrites dans le repo, là où les futurs équipiers les retrouveraient vraiment.

Périmètre

Ce que nous avons bâti.

dish_api01

Passerelle REST FastAPI — le contrat hors-Odoo que les systèmes voisins appellent. Mainteneur.

dish_rabbit_mq02

Publication / souscription RabbitMQ ; garde Odoo et ses systèmes voisins synchronisés. Mainteneur.

dish_vonage03

Téléphonie Vonage, portée depuis une intégration Salesforce : numéroteur, enregistrement, présence.

dish_vonage_user_helpdesk04

Présence de file, routage, webhooks de fin de canal pour l'équipe helpdesk.

dish_sale + modules sœurs05

Flux de commande de bout en bout sur Odoo : devis, consents de signature, passation au projet, attribution du référent.

dish_sales_settings06

Configuration transverse du domaine vente.

dish_product + dish_product_catalog07

Master produit et catalogue exposé à la vente et à l'API.

dish_product_subscription08

Cycle de vie des abonnements : cycle de facturation, renouvellement, résiliation.

dish_product_upgrade_downgrade09

Changements de plan qui respectent les périodes de facturation, avec prorata là où il est dû.

dish_crm10

Extensions CRM pour la forme marketplace. Mainteneur.

dish_partner_handshakes11

Réconciliation des identités partenaires entre systèmes. Mainteneur.

dish_send_message + dish_whatsapp_widget12

Surfaces de messagerie sortante. Mainteneur.

Protocole de tests13

Verrou de tests unitaires que chaque nouveau module devait franchir avant merge, avec seuils de couverture imposés en CI.

Approche

À quoi ressemble le travail, en 4 pièces.

01

Parité fonctionnelle, pas défauts Odoo

Recréation de l'expérience Salesforce vivante à l'intérieur d'Odoo, module par module — vente, produits, CRM, helpdesk, téléphonie — pendant qu'une autre équipe déplaçait les données. L'objectif n'était pas « l'idée qu'a Odoo d'un flux de vente » mais celle de DISH, avec les raccourcis que les agents connaissaient déjà.

02

Plomberie API & événementielle

dish_api est la passerelle REST FastAPI : authentification JWT, injection de dépendances, services et controllers nettement séparés, un contrat OpenAPI sur lequel les équipes appelantes se branchent sans toucher à Odoo. dish_rabbit_mq est le côté événement — Odoo publie ses événements métier, les services voisins les consomment, avec un chemin de publication de masse pour que les backfills ne saturent pas le broker.

03

Vonage, port depuis Salesforce

Salesforce avait livré à Vonage une intégration soignée ; nous l'avons remontée sur Odoo. Deux modules — dish_vonage pour le cœur (numéroteur, enregistrement, présence) et dish_vonage_user_helpdesk pour le routage, la présence de file et les webhooks de fin de canal dont le helpdesk dépend. Les webhooks sont sous tests : un renommage côté Vonage ne casse pas le numéroteur silencieusement.

04

Pratiques d'ingénierie, relevées

Avec une dizaine de prestataires dans la même base, le travail ne survit que si les règles sont écrites. Nous avons apporté un protocole de tests unitaires que les nouveaux modules devaient franchir avant merge, un template de revue de code avec les questions que les relecteurs devraient vraiment poser, et des décisions d'architecture conservées dans le repo plutôt qu'enterrées dans une recherche Confluence.

Choix techniques

Les solutions dont nous sommes le plus fiers.

01

Passerelle FastAPI comme contrat hors-Odoo

dish_api est la surface FastAPI que chaque autre service DISH appelle quand il a besoin de l'état Odoo. Bâti sur le module fastapi d'OCA avec notre propre dispatcher, services et controllers proprement séparés ; auth, cache, hooks et i18n chacun à leur place ; authentification JWT verrouillée par un fastapi_group. La spec OpenAPI est le contrat — les équipes voisines s'y branchent sans jamais toucher à l'ORM d'Odoo.

02

Pub / sub RabbitMQ pour la synchronisation

Odoo est le système de référence pour les partenaires, contacts et abonnements, mais les services voisins doivent savoir quand ils changent. dish_rabbit_mq publie ces événements et souscrit aux entrants. Cas limites appris par itération : actions automatisées qui se déclenchaient sur chaque enregistrement (resserrées par des domains plus stricts), suppressions d'établissement et de contact qui sélectionnaient les mauvais enregistrements (corrigées), et un chemin de publication de masse pour qu'un backfill ne nourrisse pas le broker un événement à la fois.

03

Téléphonie Vonage, port depuis Salesforce

Salesforce avait livré une intégration Vonage propre ; il a fallu la reconstruire sur Odoo. Deux modules — dish_vonage pour le cœur (numéroteur, enregistrement, présence) et dish_vonage_user_helpdesk pour le routage, la présence de file et les webhooks de fin de canal. Les webhooks sont sous tests — un renommage côté Vonage ne casse pas le numéroteur en silence.

04

Recréation du flux de vente

Les commerciaux DISH avaient une journée d'une forme particulière sur Salesforce — devis, consents de signature, passation projet en aval, attribution du référent. dish_sale et ses modules sœurs reproduisent ce flux à l'intérieur de sale.order avec les mêmes raccourcis et les mêmes conséquences en aval. La passation vers dish_sale_project ferme la boucle.

05

Cycle de vie d'abonnement avec changements de plan

Un SaaS B2B vit par ses abonnements. dish_product_subscription porte le cycle de vie ; dish_product_upgrade_downgrade porte les changements de plan qui respectent les périodes de facturation — pas de débit-surprise en milieu de cycle, prorata là où il se doit — avec une suite de tests qui épingle la mathématique de facturation.

06

Pratiques d'ingénierie, écrites dans le repo

Protocole de tests unitaires importé d'un projet précédent : les nouveaux modules ont besoin d'une vraie suite de tests avant merge ; seuils de couverture imposés en CI. Template de revue de code avec les questions qu'on aurait aimé voir posées. Décisions d'architecture conservées dans le repo pour pouvoir évoluer plutôt que se perdre.

Résultats

Quelques chiffres, en formes brutes.

Multi-M€
Licence annuelle retirée
95
Modules Odoo dans BSS
7
Modules sous notre maintenance
~22 mois
Embarqués avec l'équipe

Stack
Odoo 16PythonFastAPIPostgreSQLRabbitMQVonageDockerOpenAPI

Un projet qui mérite ce niveau de soin ?

Démarrer une conversation