← Retour au projet sur l'accueil

Iyabo Hair
Un outil qui gère les commandes et les fonds entre un commerçant et ses livreurs. Il permet de connaître ses stocks et surtout où va chaque franc, avec détails et historique des deux côtés. La démo montre les commandes, la caisse et les trois suivis sur des données fictives ; la gestion de stock n'en fait pas partie.
- Iyabo Hair, Dakar
- Conception et développement, seul
- 2026

Une commande, trois suivis
Iyabo HairQu'est-ce qui est réel ?
Simulation construite sur le code de Iyabo Hair, données fictives.
- Les règles de ce qui est dû, payé et restant, de ce qu'un livreur détient et remet, et de la façon dont un statut de livraison déplace le produit viennent du code d'Iyabo Hair, consolidées et vérifiées contre le calcul d'origine. Les statuts et les libellés sont ceux de l'application.
- Les vingt commandes, les trois livreurs, les produits et les prix sont inventés. Aucune cliente, aucun numéro de téléphone.
- L'interrupteur « Et si tout était un seul enregistrement ? » est une explication ajoutée par ce site. Ce n'est pas une fonction de l'application. La mise en page des écrans est aussi recomposée pour la démo.

Iyabo Hair
La démo ne se charge que si vous la demandez.
Le problème
Iyabo Hair vend des perruques dans tout Dakar. Une perruque peut quitter l'étagère le lundi, être livrée le mercredi et payée le vendredi, parfois partiellement, parfois au livreur plutôt qu'à la boutique. Un statut de commande unique ne sait pas raconter ces trois histoires.
Trois suivis
Chaque commande porte trois enregistrements séparés : où est le produit, où en est la livraison, et ce qui a été payé. Changer le statut de livraison déplace le produit physiquement (chez le livreur, livré, retourné) mais ne touche jamais à l'argent. Enregistrer un paiement ne change jamais un statut.
Sous le capot
La commande a un statut pour le produit, un statut pour la livraison, et aucun champ d'argent : l'argent se déduit des paiements typés.
// Les TROIS suivis indépendants productStatus ProductStatus @default(EN_STOCK) deliveryStatus DeliveryStatus @default(A_PREPARER) // Le suivi ARGENT est calculé à partir des Payment liés : // resteAPayer perruque = quantity * unitPrice - somme(Payment PERRUQUE) // resteAPayer livraison = deliveryFee - somme(Payment LIVRAISON) // Qui est prévu pour encaisser ce qui n'est pas encore payé // (détermine ce que le livreur doit récupérer à la livraison) perruqueEncaisseur PlannedCollector @default(LIVREUR) livraisonEncaisseur PlannedCollector @default(LIVREUR)Chaque franc a une place
Un paiement concerne soit la perruque, soit la livraison, jamais les deux, et il note qui l'a physiquement reçu. C'est ainsi que l'application sait répondre à « où est chaque franc ? ». Une livraison ne peut pas être clôturée avec un impayé silencieux : le livreur confirme ce qu'il a encaissé et comment, ou signale un problème.
Sous le capot
Avant de clôturer une livraison, le reste de chaque volet est calculé et tout solde impayé la bloque.
const payeP = order.payments .filter(function (p) { return p.type === "PERRUQUE"; }) .reduce(function (sum, p) { return sum + p.amount; }, 0); const payeL = order.payments .filter(function (p) { return p.type === "LIVRAISON"; }) .reduce(function (sum, p) { return sum + p.amount; }, 0); const restePerruque = order.quantity * order.unitPrice - payeP; const resteLivraison = order.deliveryFee - payeL; // Cohérence : si un montant restait dû et que le livreur ne // l'a pas reçu, il doit passer par "Problème" plutôt que // valider une livraison avec un impayé silencieux if (restePerruque > 0 && perruqueRecue !== "OUI") { return "La perruque n'est pas payée (" + restePerruque.toLocaleString("fr-FR") + " F). Encaisse-la ou signale un problème."; } if (resteLivraison > 0 && livraisonRecue !== "OUI") { return "La livraison n'est pas payée (" + resteLivraison.toLocaleString("fr-FR") + " F). Encaisse-la ou signale un problème."; }Des frais prépayés ne sont pas encore dus
Quand une cliente paie les frais de livraison d'avance, la boutique détient cet argent, mais il ne devient celui du livreur qu'une fois la commande livrée. Une livraison échouée ou reportée le laisse en attente. La remise de caisse d'un livreur, c'est l'argent qu'il détient moins les frais qui lui sont désormais dus.
Sous le capot
Les frais encaissés par la boutique ne sont dus au livreur que sur les commandes livrées ; les autres restent en attente.
const livraisonsAcquises = await prisma.payment.findMany({ where: { type: "LIVRAISON", remiseId: null, collectedBy: { role: "ADMIN" }, order: { livreurId: livreurId, deliveryStatus: "LIVREE" }, }, }); const totalAcquises = livraisonsAcquises.reduce(function (sum, p) { return sum + p.amount; }, 0); const livraisonsEnAttente = await prisma.payment.findMany({ where: { type: "LIVRAISON", remiseId: null, collectedBy: { role: "ADMIN" }, order: { livreurId: livreurId, deliveryStatus: { not: "LIVREE" } }, }, }); const totalEnAttente = livraisonsEnAttente.reduce(function (sum, p) { return sum + p.amount; }, 0);Essayez vous-même
Ouvrez une commande, changez son statut, enregistrez un paiement, livrez-la côté livreur, puis faites la remise de caisse d'un livreur et validez-la côté boutique. Activez la question sur l'enregistrement unique pour voir ce qu'un seul statut cacherait. Ce bloc est une illustration ajoutée par ce site, pas une fonction de l'application.
Ce que vous pouvez y faire
- Changer le statut de livraison de vingt commandes fictives
- Enregistrer un paiement et voir ce qui reste dû
- Clôturer une livraison en tant que livreur
- Remettre la caisse et la valider en tant que gérante
- Voir les suivis du produit, de la livraison et de l'argent se mettre à jour séparément
Stack
Next.js 16 · TypeScript · Tailwind CSS v4 · Prisma 7 · Neon Postgres · NextAuth v5 · Vercel
Contexte
Iyabo Hair vend des perruques dans tout Dakar. Les commandes arrivent par les réseaux sociaux, le stock circule entre quelques personnes, et des livreurs en moto encaissent en espèces ou en mobile money. Avant cette application, tout cela tenait dans des cahiers et des fils de discussion. Personne ne pouvait répondre à deux questions simples en même temps : qu'est-ce qu'on a vraiment en stock, et qui doit combien à qui.
Le problème
La gérante n'avait pas besoin d'une boutique en ligne. Elle avait besoin d'arrêter de perdre de l'argent dans l'écart entre trois choses qui n'avancent pas à la même vitesse : le produit, la livraison et l'argent. Une perruque peut quitter l'étagère le lundi, être livrée le mercredi et payée le vendredi, parfois partiellement, parfois au livreur plutôt qu'au commerce. Tout système qui traite cela comme un seul événement produit silencieusement de faux chiffres. Et dans ce métier, un faux chiffre, c'est le salaire de quelqu'un.
Contraintes
- L'équipe travaille exclusivement sur des téléphones Android de milieu de gamme, souvent en données mobiles instables
- Aucune caisse enregistreuse, aucun terminal de paiement, aucun logiciel comptable auquel se connecter
- Les paiements arrivent par Wave et Orange Money, ou en espèces à un livreur
- Les livreurs ne sont pas salariés et leur rémunération se calcule à la livraison
- L'équipe n'avait jamais utilisé d'outil interne : tout ce qui serait déroutant serait abandonné en une semaine
Ce que j'ai construit
- Saisie des commandes avec décrémentation du stock et marge par article
- Attribution des livraisons, suivi des statuts et règlement des livreurs
- Journal de caisse rapprochant mobile money, espèces et soldes en attente
- Rôles distincts pour la gérante, les administrateurs et les livreurs
- Codes de paiement Wave et Orange Money scannables, rattachés à chaque commande
- Application web progressive installable, ouverte depuis l'écran d'accueil comme n'importe quelle autre app
Décisions structurantes
Trois suivis qui ne s'écrivent jamais l'un dans l'autre
La conception évidente consiste à faire d'une commande un enregistrement unique qui met à jour le stock, la livraison et la caisse ensemble. Je l'ai écartée. Le produit, la livraison et l'argent sont suivis comme trois flux indépendants, et aucune action dans l'un ne modifie automatiquement les autres. Marquer une livraison comme terminée ne solde pas l'argent. Enregistrer un paiement ne clôt pas la livraison. Cela coûte quelques appuis supplémentaires, mais une erreur reste locale au lieu de corrompre silencieusement les deux autres suivis. Dans un commerce où les chiffres déterminent qui est payé, un montant faux coûte infiniment plus cher qu'un appui de trop.
Les frais de livraison ne sont jamais l'argent du commerce
Les frais de livraison appartiennent au livreur, le prix de la perruque appartient au commerce. Les deux sont séparés dès la saisie et ne sont jamais fusionnés nulle part, y compris dans les rapports. Cela paraît évident jusqu'au moment où une cliente règle le tout en un seul virement mobile money. Modéliser cela comme un montant unique à répartir plus tard, c'est exactement comme ça qu'un commerce dépense la paie de ses livreurs sans s'en rendre compte, puis en discute en fin de mois.
Le prépayé ne compte qu'une fois la livraison faite
Quand une cliente paie à l'avance, la rémunération du livreur est enregistrée mais n'entre dans ce qui lui est dû qu'une fois la livraison effectivement terminée. L'autre option, créditer dès le paiement, donne un solde livreur juste à l'écran et faux dans la réalité, et se retourne mal sur les retours et les livraisons échouées. Cette seule règle a supprimé toute une catégorie de litiges de fin de semaine.
Résultat
- Cahiers et fils de discussion remplacés par une source unique de vérité
- Installée sur les téléphones de l'équipe depuis l'écran d'accueil, sans passer par un store