013 Diriger

UBBFY

Architecte principal d’une plateforme ERP, CRM et RH multi-tenant, en production chez de nombreux clients.

Projet
2025 à aujourd’hui
Stack
Django / DRF / Vue 3 / Celery / PostgreSQL / Stripe / FedaPay

Une dizaine d’entreprises y font tourner leur exploitation, la plus grande gérant deux cents salariés et prestataires. La plateforme, c’est trente-trois modules côté serveur, 338 modèles de données et près de quatre cents écrans, servis en trois langues : KPS, Planus, Flowplan, Gotolearn et People&Skill sont les tenants en production.

Je suis arrivé sur un projet déjà commencé, écrit en Laravel sur MySQL, et la première décision a été de le restructurer vers Django et PostgreSQL. Migrer des données est un travail ingrat qui se facture tard : les horodatages repris de l’ancienne base arrivaient avec une heure de retard, et ce genre d’écart ne se voit pas en recette, il se voit en production sur la feuille de temps de quelqu’un.

Ce qui a décidé de l’architecture, ce sont les parties que personne ne voit. Des droits d’accès conçus pour être configurés plutôt que codés, de sorte qu’un nouveau tenant n’implique pas un nouveau déploiement. Un bus d’événements sur Celery, pour qu’un module puisse réagir à un autre sans l’importer. Une piste d’audit, parce qu’une plateforme qui héberge l’exploitation de plusieurs entreprises doit pouvoir dire ce qui s’est passé et qui l’a fait. La facturation passe par Stripe et FedaPay ensemble, ce qu’exige réellement le fait de servir des clients européens et ouest-africains.

Ce que je n’ai pas vu venir, c’est l’internationalisation. Je ne l’ai pas prévue au départ, et la rattraper sur une base déjà écrite a mis l’environnement de développement à terre plusieurs jours. Le problème n’était pas la traduction, c’était la frontière : les chaînes de l’interface sont à moi, le contenu saisi par un tenant est à lui et doit exister dans des langues que je ne choisis pas. Une notification part maintenant dans la langue de qui la lit, pas de qui la déclenche. C’est une décision que je prends désormais le premier jour d’un projet, pas au sixième mois.

Le socle est tenu par les tests : 3 146 côté serveur, 468 parcours de bout en bout dans le navigateur.

Architecture

Application métier

Vue 3, 35 modules, près de quatre cents écrans

Administration de la plateforme

Vue 3, tenants, rôles, réglages

HTTPS, jeton en cookie HttpOnly

API Django REST

33 modules, 338 modèles, droits par module configurés plutôt que codés

événements publiés

Bus Celery et Redis

un module réagit à un autre sans l’importer

Piste d’audit

ancienne et nouvelle valeur, à chaque écriture

écritures

PostgreSQL

MinIO

objets, URL signées

Stripe et FedaPay

Europe et Afrique de l’Ouest

Deux applications distinctes devant une seule API : une équipe d’exploitation et un utilisateur métier n’ont pas les mêmes écrans, et les réunir aurait produit une interface médiocre pour les deux. Les modules se parlent par le bus au lieu de s’importer, ce qui permet d’en ajouter un sans toucher aux autres, et chaque écriture laisse sa trace.

Tableau de bord d’UBBFY : effectif, absences, masse salariale nette et congés en attente, avec la clôture de paie du mois et le calendrier de la semaine.
L’écran d’arrivée d’un administrateur : ce qu’il doit savoir, et l’action qu’il vient faire. La clôture de paie est un bouton parce que c’est la tâche du mois, pas une entrée de menu à retrouver.
Écran des rôles d’UBBFY : dix rôles, chacun avec son nombre de permissions et son type, et un bouton pour en créer un nouveau.
Les droits, configurés plutôt que codés. Chaque rôle porte son compte de permissions par module, et un nouveau rôle se crée depuis cet écran : c’est ce qui fait qu’un nouveau client n’implique pas un nouveau déploiement.

Sommaire

022

UBBFY v2, le plan

Cinq chantiers qui portent la plateforme jusqu’en 2027, chiffrés en jours et ordonnés par ce qui dépend de quoi.