François Castets

Journal

3 November 20263 November 2026 10 min de lecturemin read Commerce en ligneOnline retail

Facturer au nom de quelqu’un d’autreInvoicing in somebody else's name

djplays est l'agent commercial des DJs, donc chaque commande émet une facture au nom du DJ et non au nom de la plateforme. Ce que ce choix impose au code.djplays acts as the commercial agent of the DJs, so every order issues an invoice in the name of the DJ rather than that of the platform. What that choice imposes on the code.

Sur une boutique ordinaire, la question ne se pose pas : le client paie, le vendeur facture, et le vendeur est celui dont le nom figure en haut du document. djplays n’est pas une boutique ordinaire. Le producteur paie pour que des DJs écoutent son titre, mais l’argent ne reste pas chez la plateforme : il revient en grande partie aux DJs. Et dès qu’on reverse de l’argent à des tiers, savoir au nom de qui part la facture cesse d’être une formalité.On an ordinary shop the question does not come up: the customer pays, the seller invoices, and the seller is the one whose name sits at the top of the document. djplays is not an ordinary shop. The producer pays for DJs to listen to their track, but the money does not stay with the platform: most of it goes back to the DJs. And as soon as you pass money on to third parties, knowing whose name is on the invoice stops being a formality.

Le projet est en accès anticipé, et ce module a été écrit avant la première commande réelle, précisément parce qu’il est plus facile de poser ces règles sur une base vide que de les rattraper ensuite. Voici le raisonnement qui a conduit au choix retenu, et ce qu’il coûte en code.The project is in early access, and this module was written before the first real order, precisely because it is easier to set these rules on an empty database than to catch up with them later. Here is the reasoning that led to the chosen approach, and what it costs in code.

Pourquoi la plateforme ne peut pas facturer à son nomWhy the platform cannot invoice in its own name

La solution la plus simple serait d’émettre une seule facture, au nom de djplays, pour la totalité de ce que paie le producteur, puis de reverser leur part aux DJs. C’est tentant parce que ça ne demande qu’un seul gabarit et un seul compteur. Le problème est que cette facture décrirait une vente que la plateforme n’a pas faite : ce n’est pas elle qui écoute le titre, ni elle qui le joue.The simplest option would be to issue a single invoice, in the name of djplays, for everything the producer pays, then pass each DJ their share. It is tempting because it needs only one template and one counter. The problem is that this invoice would describe a sale the platform did not make: the platform is not the one listening to the track, nor the one playing it.

La conséquence est comptable avant d’être juridique. Si la plateforme facture l’intégralité, elle enregistre un produit qu’elle ne garde pas, puis verse des sommes à des DJs qui, eux, n’ont facturé personne. Chacun se retrouve avec un mouvement d’argent sans document en face. Le DJ ne peut pas justifier ce qu’il a touché, le producteur ne sait pas qui lui a rendu le service, et la plateforme déclare une activité qui n’est pas la sienne.The consequence is an accounting one before it is a legal one. If the platform invoices the whole amount, it records revenue it does not keep, then pays sums to DJs who have invoiced nobody. Everyone ends up with a movement of money and no document facing it. The DJ cannot account for what they received, the producer does not know who performed the service, and the platform declares activity that is not its own.

La position de départ est donc écrite noir sur blanc dans le projet : djplays est l’agent commercial des DJs. La plateforme vend un service qui appartient au DJ, elle encaisse pour son compte, elle prend une commission. Tout le module de facturation découle de cette seule phrase, et c’est le mandat de facturation qui lui donne sa forme technique : un mécanisme par lequel un tiers émet des factures au nom et pour le compte de quelqu’un d’autre.The starting position is therefore written down explicitly in the project: djplays is the commercial agent of the DJs. The platform sells a service that belongs to the DJ, it collects on their behalf, it takes a commission. The whole invoicing module follows from that one sentence, and it is the invoicing mandate that gives it its technical shape: a mechanism by which a third party issues invoices in the name and on behalf of somebody else.

Côté code, cela veut dire que l’identité de l’émetteur n’est pas une constante du site mais une donnée tirée de la fiche du DJ au moment de l’émission. Le gabarit de facture est le même pour tout le monde ; l’émetteur change à chaque document. C’est une inversion simple à décrire et facile à rater, parce que la quasi-totalité des exemples de code qu’on trouve supposent un émetteur unique, posé une fois dans la configuration.In code terms, this means the issuer identity is not a site constant but a value read from the DJ record at the moment of issue. The invoice template is the same for everyone; the issuer changes with every document. It is an inversion that is easy to describe and easy to get wrong, because almost every code example you will find assumes a single issuer, set once in the configuration.

Une facture par DJ, puis une par passage prouvéOne invoice per DJ, then one per proven play

Une commande peut viser plusieurs DJs d’un coup : le producteur choisit sa sélection et paie en une fois. Mais il n’y a pas un vendeur en face, il y en a autant que de DJs retenus. Le découpage est donc le suivant.An order can target several DJs at once: the producer picks a selection and pays in one go. But there is not one seller facing them, there are as many as there are DJs chosen. The breakdown is therefore the following.

  • Une facture par DJ et par commande, pour l’écoute : c’est le service que le DJ s’engage à rendre au moment où le producteur paie.One invoice per DJ and per order, for the listen: that is the service the DJ undertakes to perform at the moment the producer pays.
  • Puis une facture par passage prouvé, émise quand la preuve est validée, parce que le passage n’est pas acquis à la commande.Then one invoice per proven play, issued when the proof is validated, because the play is not secured at order time.
  • Et, en sens inverse, une facture de commission adressée par djplays au DJ, pour la part qui revient à la plateforme.And, going the other way, a commission invoice addressed by djplays to the DJ, for the share that goes to the platform.

Ce découpage suit la réalité du parcours plutôt que la facilité du paiement. Le producteur paie une fois, mais il achète deux choses qui ne se produisent pas au même moment : une écoute avec réponse, et éventuellement un passage dont la preuve arrivera des semaines plus tard. Une facture émise dès la commande pour un passage qui n’a pas encore eu lieu serait une facture à annuler dans la majorité des cas, et annuler coûte plus cher qu’attendre.This breakdown follows the reality of the journey rather than the convenience of the payment. The producer pays once, but buys two things that do not happen at the same time: a listen with a written reply, and possibly a play whose proof will arrive weeks later. An invoice issued at order time for a play that has not happened yet would be an invoice to cancel in most cases, and cancelling costs more than waiting.

La commission, réglée par compensationThe commission, settled by set-off

La plateforme garde la moitié du prix d’écoute et le tiers du prix de passage. Reste à savoir comment elle les perçoit. On pourrait adresser au DJ une facture de commission et attendre qu’il la règle, comme n’importe quel fournisseur attend son virement. Personne ne ferait ça : le DJ attend de l’argent, pas une facture à payer, et lui demander de sortir sa carte pour toucher sa part serait absurde.The platform keeps half of the listen price and a third of the play price. The question is how it collects them. You could send the DJ a commission invoice and wait for them to pay it, the way any supplier waits for a transfer. Nobody would do that: the DJ is expecting money, not a bill, and asking them to get their card out in order to receive their share would be absurd.

La commission est donc réglée par compensation sur les sommes encaissées pour le compte du DJ. En clair : la plateforme a encaissé pour lui, elle lui doit sa part, il lui doit sa commission, et les deux dettes s’annulent à hauteur de la plus petite. Le DJ reçoit la différence, et il a en main les deux documents qui l’expliquent, sa propre facture au producteur et la facture de commission qui vient en déduction.The commission is therefore settled by set-off against the sums collected on behalf of the DJ. Plainly: the platform collected for them, it owes them their share, they owe it its commission, and the two debts cancel each other out up to the smaller one. The DJ receives the difference, and holds the two documents that explain it, their own invoice to the producer and the commission invoice deducted from it.

Pour le code, la compensation a un effet qu’il faut assumer : une facture de commission est émise et marquée réglée dans le même mouvement, sans qu’aucun paiement ne la traverse. Il faut donc que l’état de la facture et l’état du versement racontent la même histoire, faute de quoi la comptabilité du DJ ne se boucle pas et il reste des factures en attente qui n’attendent rien.In code terms, set-off has a consequence you have to accept: a commission invoice is issued and marked as settled in the same movement, with no payment passing through it. The state of the invoice and the state of the payout therefore have to tell the same story, failing which the accounts of the DJ do not balance and you are left with pending invoices that are not waiting for anything.

Les avoirs, parce qu'une facture ne se corrige pasCredit notes, because an invoice is not corrected

Un DJ ne répond pas sous sept jours : le crédit revient automatiquement au producteur. Il faut donc défaire un encaissement, et la tentation est de retoucher la facture correspondante, voire de la supprimer puisque personne ne l’a réclamée. Ni l’un ni l’autre n’est acceptable : une facture émise est un document remis à un tiers, qui l’a peut-être déjà enregistré de son côté.A DJ does not reply within seven days: the credit automatically returns to the producer. An amount collected has to be undone, and the temptation is to amend the matching invoice, or even delete it since nobody has asked for it. Neither is acceptable: an issued invoice is a document handed to a third party, who may already have recorded it on their side.

Un remboursement donne donc lieu à un avoir, c’est-à-dire à un second document qui annule le premier sans y toucher. La facture reste, l’avoir la neutralise, et la trace des deux opérations subsiste. Cela fait plus de documents et plus de lignes dans la table, mais c’est la seule forme qui se relise des mois plus tard sans avoir besoin de quelqu’un pour raconter ce qui s’est passé.A refund therefore gives rise to a credit note, that is, a second document that cancels the first without touching it. The invoice remains, the credit note neutralises it, and the trace of both operations survives. It means more documents and more rows in the table, but it is the only form that can be read back months later without someone there to narrate what happened.

Une facture n’est pas un affichage qu’on rafraîchit, c’est un document qui est parti. Tout ce qui a besoin de changer après coup doit prendre la forme d’un deuxième document, jamais d’une modification du premier.An invoice is not a view you refresh, it is a document that has left the building. Anything that needs to change afterwards has to take the form of a second document, never a modification of the first.

Une numérotation qui ne peut pas trébucherA numbering that cannot stumble

La numérotation est continue par année : un préfixe, l’année, puis un numéro qui repart à un au premier janvier. Continue veut dire sans trou et sans doublon, et tous types confondus : la facture au nom du DJ, la facture de passage, la facture de commission et l’avoir puisent dans la même suite. Une seule série, donc un seul compteur à surveiller.The numbering runs continuously by year: a prefix, the year, then a number that restarts at one on the first of January. Continuous means no gaps and no duplicates, and all types share it: the invoice in the name of the DJ, the play invoice, the commission invoice and the credit note all draw from the same series. One series, so one counter to watch.

Le point délicat n’est pas de calculer le numéro suivant, c’est d’empêcher deux traitements simultanés d’obtenir le même. Un paiement confirmé par Stripe pendant qu’une tâche planifiée émet des factures de commission, et deux documents portent le même numéro. La protection n’est pas dans le code applicatif mais dans le schéma : la table des factures porte une contrainte d’unicité sur le couple année et séquence.The delicate part is not calculating the next number, it is preventing two simultaneous processes from obtaining the same one. A payment confirmed by Stripe while a scheduled job is issuing commission invoices, and two documents carry the same number. The protection does not sit in the application code but in the schema: the invoice table carries a uniqueness constraint on the year and sequence pair.

C’est le genre de garde-fou qui ne sert à rien tant qu’il ne sert pas. Le jour où deux traitements se croisent, le second échoue proprement au lieu d’écrire un doublon, et il reste une erreur à traiter plutôt qu’une comptabilité à démêler. Une contrainte posée dans la base vaut mieux qu’une vérification faite juste avant l’insertion, parce qu’elle ne peut pas être oubliée par un appelant que personne n’avait prévu.It is the kind of guardrail that is useless right up until it is not. The day two processes cross, the second fails cleanly instead of writing a duplicate, and you are left with an error to handle rather than accounts to untangle. A constraint placed in the database is worth more than a check made just before insertion, because it cannot be forgotten by a caller nobody anticipated.

Le JSON qui fige ce qui est impriméThe JSON that freezes what is printed

Voici la décision qui m’a demandé le plus de réflexion. Une facture s’affiche à partir de données : le nom du DJ, son adresse, son statut, le nom du producteur, les montants. Si on régénère le document à chaque consultation en relisant ces données, la facture change quand les données changent. Un DJ qui déménage réécrit alors toutes ses factures passées sans le savoir, et personne ne s’en aperçoit avant un contrôle.Here is the decision that took me the most thinking. An invoice is rendered from data: the DJ name, their address, their status, the producer name, the amounts. If you regenerate the document on every view by reading that data back, the invoice changes when the data changes. A DJ who moves house then rewrites all of their past invoices without knowing it, and nobody notices until someone checks.

Chaque facture garde donc en JSON, dans une colonne dédiée, tout ce qui est imprimé dessus. Les identités du moment sont recopiées à l’émission et ne bougent plus après coup. Le document affiché n’interroge plus la fiche du DJ ni celle du producteur : il relit sa propre copie, et cette copie est la seule version qui compte.Every invoice therefore keeps, as JSON in a dedicated column, everything printed on it. The identities of the moment are copied at issue time and do not move afterwards. The displayed document no longer queries the DJ record or the producer record: it reads back its own copy, and that copy is the only version that counts.

La duplication de données fait grincer, et à juste titre dans la plupart des cas : deux copies d’une même information finissent par diverger. Ici, c’est exactement l’effet recherché. Les deux copies ne décrivent pas la même chose : la fiche décrit le DJ aujourd’hui, la facture décrit le DJ au jour où elle a été émise. Ce sont deux faits différents, et il n’y a aucune raison de les garder d’accord. Le coût est réel en revanche : il faut penser à mettre dans le JSON tout ce dont l’affichage aura besoin, et un oubli ne se voit qu’au moment où la donnée change. Je me pose donc une question avant d’ajouter un champ au gabarit : saurais-je le reconstruire dans cinq ans ? Si la réponse est non, il entre dans le JSON.Duplicating data sets teeth on edge, and rightly so in most cases: two copies of the same information end up diverging. Here that is precisely the point. The two copies do not describe the same thing: the record describes the DJ today, the invoice describes the DJ on the day it was issued. Those are two different facts, and there is no reason to keep them in agreement. The cost is real though: you have to remember to put into the JSON everything the rendering will need, and an omission only shows up at the moment the data changes. So I ask myself one question before adding a field to the template: would I be able to reconstruct it in five years? If the answer is no, it goes into the JSON.

La TVA dépend du DJ, pas de la plateformeVAT depends on the DJ, not on the platform

Puisque le vendeur est le DJ, c’est son régime qui s’applique et non celui de la plateforme. Deux cas : le DJ est assujetti et la facture porte une TVA à 20 %, ou il ne l’est pas et la facture porte la mention de TVA non applicable au titre de l’article 293 B du code général des impôts. Ce n’est pas un réglage du site, c’est une propriété de chaque DJ.Since the seller is the DJ, it is their regime that applies and not that of the platform. Two cases: the DJ is VAT registered and the invoice carries VAT at 20%, or they are not and the invoice carries the note that VAT does not apply under article 293 B of the French tax code. This is not a site setting, it is a property of each individual DJ.

C’est une donnée de la fiche du DJ, donc une donnée qui peut changer, donc une donnée qui part dans le JSON de la facture avec le reste. Deux factures du même DJ à six mois d’écart peuvent légitimement ne pas porter la même mention, et c’est tant mieux : chacune décrit la situation au moment où elle a été émise, et c’est précisément ce qu’on attend d’elle.It is a field of the DJ record, so a field that can change, so a field that goes into the invoice JSON with the rest. Two invoices from the same DJ six months apart may legitimately not carry the same note, and that is as it should be: each one describes the situation at the moment it was issued, which is exactly what is expected of it.

Une dernière conséquence, propre à la période : en bêta, sans clé de paiement configurée ou sur une commande marquée comme telle, les factures sont émises quand même, avec la mention bêta, non due. Cela peut sembler inutile puisque rien n’est encaissé. C’est au contraire le meilleur moment pour faire tourner la chaîne complète : les numéros se suivent, les gabarits s’impriment, les avoirs s’essaient, et les erreurs se découvrent sur des documents qui n’engagent personne.One last consequence, specific to this period: in beta, with no payment key configured or on an order marked as such, invoices are issued anyway, with a note saying beta, not due. That may look pointless since nothing is collected. On the contrary it is the best time to run the whole chain: numbers follow on, templates print, credit notes get tried out, and mistakes are discovered on documents that commit nobody.

Au total, ce module est plus lourd que la facturation d’une boutique classique, pour une raison unique : la plateforme ne vend pas, elle vend pour d’autres. Tout le reste en découle, l’émetteur variable, la facture de commission, la compensation, les avoirs et le JSON figé. Aucune de ces pièces n’a été ajoutée pour faire propre : chacune répond à une question qu’on finit par se poser, et à laquelle il est beaucoup moins cher de répondre avant la première commande.All in all this module is heavier than the invoicing of a conventional shop, for one single reason: the platform does not sell, it sells on behalf of others. Everything else follows from that: the variable issuer, the commission invoice, the set-off, the credit notes and the frozen JSON. None of these pieces was added for tidiness: each answers a question you end up asking, and one that is far cheaper to answer before the first order.

Le projet derrière cette noteThe project behind this note

Tout est parti de djplays, la place de marché. La fiche détaille le contexte, ce qui a été construit et ce que le client en a tiré.It all started with djplays, la place de marché. The project page covers the context, what was built and what the client got out of it.

À lire ensuiteRead next