docs/40-relation/37-onboarding-pro.md —
ce document se lit aussi dans le dépôt, sans serveur.
Onboarding pro
Où : Relation → Comptes pro, et le bouton Comptes pro de la barre du haut, avec son compteur.
Le formulaire public est sur sav.monsieurcle.fr/onboarding/, un guichet du mini-site d'aide.
À quoi ça sert
Avant, monsieurcle.fr/pro/ demandait au candidat de créer lui-même un compte sur la boutique, puis d'envoyer son KBIS par courriel. François relevait la boîte, rapprochait le courriel du compte, et changeait le rôle à la main dans WordPress.
Trois gestes pour une information déjà saisie — et une boîte aux lettres qui sert de file d'attente. Une candidature qui dort dans une boîte ne se compte pas, ne se cherche pas, et ne dit pas depuis combien de temps elle attend.
Maintenant : un formulaire, une liste, une décision, et le compte s'ouvre.
Les deux comptes professionnels
Ce sont des rôles WordPress, pas une notion propre à Darsy.
| Rôle | Pour qui | |
|---|---|---|
client_pro | Les spécialistes de la serrurerie | « Pro 1 » à l'écran |
client_pro_deux | Le reste du bâtiment | « Pro 2 », remises standard |
L'écran des clients a déjà ses onglets sur ces deux rôles.
Le candidat déclare son activité — serrurerie, cordonnerie, service clé minute, menuiserie, métallerie, autre — et cette déclaration oriente la grille sans la décider. C'est le KBIS qui tranche, et c'est François qui le lit.
Les champs sont ceux de WooCommerce
Et dans le même ordre, à deux près.
Ce que le formulaire recueille devient, à l'acceptation, les métadonnées du compte chez WooCommerce. Une différence de champs se paierait en facture incomplète : prénom, nom, nom de l'entreprise, courriel, téléphone, puis l'adresse de facturation.
Deux champs n'existent pas à l'inscription ordinaire :
- le type d'activité, qui oriente la grille ;
- l'extrait KBIS, PDF ou photo.
« Pays / région » est un seul champ. C'est le libellé que WooCommerce donne à billing_country. En demander deux aurait produit une région qui n'irait nulle part.
Deux adresses, et la case qui évite d'en saisir une pour rien
Un serrurier facture au siège et se fait livrer à l'atelier. L'inscription WooCommerce ne demande que la facturation, et le découvrir à la première commande fait un aller-retour de plus.
La case « la même que l'adresse de facturation » est cochée par défaut, parce que c'est le cas courant. Décochée, elle ouvre le second bloc.
Quand elle est cochée, les colonnes de livraison restent vides plutôt que recopiées : recopier aurait donné deux vérités à tenir d'accord, et la correction de l'une aurait laissé l'autre périmée à côté.
Le KBIS ne va pas dans la racine web
Il porte le SIREN, l'adresse du siège et le nom du gérant.
Il est rangé dans storage/, hors de ce que le serveur sert, et se lit par une route qui demande une session. Le nom sur le disque n'a rien du nom annoncé par le déposant : un nom choisi par l'appelant est un chemin qu'il contrôle.
La leçon vient du formulaire SAV de la boutique, dont le dossier uploads est publiquement lisible alors que des clients y déposent des pièces d'identité. C'est écrit dans la migration des pièces jointes du SAV, et c'est ce qu'il ne faut pas refaire.
Il est purgé, et la date est posée à la décision
Dix-huit mois : assez pour justifier un statut accordé si la question se pose, pas assez pour que le dossier devienne une archive que personne n'ouvre et que personne n'ose vider.
L'effacement reste un geste mensuel fait à la main, avec aperçu — rien ne s'efface tout seul.
Accepter ouvre vraiment le compte
Le bouton ne classe pas une ligne. Il appelle le plugin de la boutique, qui appelle wc_create_new_customer() — la fonction que WooCommerce utilise lui-même — avec identifiant et mot de passe vides.
WooCommerce applique alors ses propres réglages et envoie son courriel de bienvenue, avec le lien pour choisir le mot de passe. On ne reproduit pas la mécanique WordPress : on la déclenche.
UnINSERTdanswp_usersproduirait une ligne, pas un client. Voir le pont vers la boutique.
L'ordre des deux écritures
La boutique d'abord, la décision ensuite, et seulement une fois l'identifiant du compte en main.
L'inverse aurait laissé, au premier appel qui échoue, une candidature marquée traitée sans compte derrière — et personne pour s'en apercevoir, puisqu'elle aurait quitté la liste des demandes en cours.
Une adresse qui a déjà un compte se met à jour
C'est le cas fréquent, pas l'exception : le professionnel a souvent commandé une fois en particulier, puis demandé ses tarifs.
L'écran affiche alors les deux versions côte à côte — le compte tel qu'il est, le dossier tel qu'il vient d'arriver — et une case par champ qui diffère. Le bouton devient « Mettre à jour et passer en pro ».
| Compte actuel | Dossier reçu | |
|---|---|---|
| Entreprise | ~~SARL DUPON~~ | SARL Dupont |
| Téléphone | vide | 01 42 00 00 00 |
| Ville | Paris | Paris |
Ce qui n'est pas coché garde sa valeur. C'est tout l'intérêt : le compte initial porte souvent des erreurs — c'est justement pour ça que le professionnel redépose un dossier propre — mais pas partout. Écraser en bloc remplacerait ce qui était juste par un formulaire rempli à la va-vite.
Les cases sont pré-cochées quand les deux valeurs diffèrent et que le dossier apporte quelque chose : un champ vide dans la candidature ne propose jamais d'effacer ce que le compte porte déjà.
Le client est prévenu, dans les deux cas
| Chemin | Ce que le client reçoit |
|---|---|
| Compte créé | la bienvenue WooCommerce (avec son mot de passe), puis le courrier des tarifs pro |
| Compte mis à jour | le courrier des tarifs pro seulement — il a déjà ses identifiants |
Le courrier des tarifs pro explique où les remises s'affichent, qu'elles s'appliquent au panier, et qu'on peut demander un devis sur les commandes spéciales. La bienvenue de WooCommerce ne dit rien de tout ça : elle dit « votre compte est créé » et porte le lien de mot de passe.
Il ne partait que sur la mise à jour. L'asymétrie avait changé de camp au lieu de disparaître : celui qui n'avait pas de compte apprenait donc le moins de choses, alors qu'il est précisément celui qui ne connaît rien. Corrigé le 23/10/2026.
Il passe par WC()->mailer()->wrap_message(), donc par l'en-tête et le pied d'e-mail de la boutique — ce que YayMail habille. Son texte vit dans le plugin, et le filtre darsy_mail_passage_pro_corps permet de le changer sans redéployer.
Sur une mise à jour, une case décide, et elle suit le rôle choisi :
| Rôle choisi | La case | Ce qu'elle dit |
|---|---|---|
| rien encore | décochée | « choisissez d'abord le type de compte » |
| le compte n'était pas pro | cochée | « prévenir de son passage en Pro 1 » |
| un palier différent | cochée | « prévenir de son passage en Pro 2 » |
| le même palier | décochée | « renvoyer le courrier — son palier ne change pas » |
Elle est dans la boîte de comparaison, pas près des boutons : à côté d'eux elle aurait été cochée sans y penser.
Le serveur refusait d'envoyer à un compte déjà pro, et c'était trop grossier. Ça attrapait deux cas légitimes : un passage de Pro 1 à Pro 2 — le palier change, donc les remises changent — et un renvoi demandé parce que le client dit n'avoir rien reçu. La politique vit maintenant dans l'écran, visible, et l'opérateur peut la contredire. Le plugin envoie si la case est cochée, point.
L'écran rapporte ce qui est réellement parti, pas ce qui était demandé : la boutique rend notifie, et le message final en découle.
Jusqu'au 23/10/2026, c'était un refus. « Changez son rôle depuis la fiche client, puis marquez cette candidature traitée. » Il fallait sortir de Darsy, retrouver le client dans l'administration WooCommerce, comparer de tête avec le dossier qu'on venait de lire, corriger, revenir. Et le seul point fixe entre les deux versions est l'adresse : tout le reste peut différer, donc « de tête » voulait dire au hasard.
Un compte du personnel est refusé, et aux trois étages
Si l'adresse appartient à un administrateur, un shop_manager, un éditeur, un auteur ou un contributeur, l'écran refuse et désactive le bouton.
La raison est brutale : set_role() remplace les rôles, il n'en ajoute pas. Passer un administrateur en client_pro lui retirerait l'accès à sa propre boutique — et il suffit qu'une candidature arrive sur l'adresse de François, ou sur celle d'un ancien employé, pour que le cas se présente.
Le contrôle est donc à trois endroits : l'écran (pour le dire avant le clic), le contrôleur (pour le refuser proprement), et le plugin — parce que c'est là que le rôle se pose, et qu'un garde-fou qui ne vit que dans l'appelant protège l'appelant, pas la boutique.
Deux routes, et elles ne font pas la même chose
| Route du plugin | Ce qu'elle fait |
|---|---|
POST /darsy/v1/client | idempotente : sur une adresse connue, rend l'identifiant et ne touche à rien |
POST /darsy/v1/client/maj | écrit : pose le rôle, et les seuls champs qu'on lui donne |
La première sert à rattacher une commande à un client — elle doit pouvoir être appelée mille fois sans conséquence. Les confondre laisserait un rattachement de commande changer un rôle par inadvertance, et c'est pourquoi la seconde est une route à part.
Refuser ne prévient personne
Aucun courriel ne part. La note interne garde le motif, pour vous.
Dire « non » par automate à un confrère serrurier se retourne parfois contre vous — et vous pouvez toujours lui écrire vous-même.
Le même e-mail peut postuler deux fois
Rien ne l'interdit : un KBIS illisible se renvoie.
L'écran montre les candidatures précédentes de la même adresse quand il y en a, pour qu'on ne traite pas deux fois la même entreprise sans le savoir — ou qu'on n'en refuse pas une déjà acceptée.
C'est l'anti-spam qui arrête les vagues, pas le schéma : trois candidatures par heure et par adresse IP. On ne postule pas en rafale, et le KBIS a déjà été préparé avant d'arriver.
Le piège anti-robot n'est pas celui des autres guichets
Sur le formulaire de contact, le champ-appât s'appelle societe. Ici, le nom de l'entreprise est un vrai champ.
Garder le même appât aurait refusé toutes les candidatures légitimes — et le défaut ne se serait vu nulle part à l'essai, puisqu'on laisse justement ce champ vide quand on teste un formulaire. Un formulaire qui marche sur le poste et jette tout en production.
L'appât s'appelle donc fax ici : plausible sur un formulaire professionnel, donc un robot le remplit ; et plus personne n'en a, donc aucun humain ne le cherche.
Ce qu'il faut pour que ça marche
Le sous-domaine sav.monsieurcle.fr | pointé sur darsy/public/sav |
CORS_ALLOWED_ORIGINS dans le .env | doit lister https://sav.monsieurcle.fr |
| Le plugin de la boutique | en version 1.11.0 ou plus |
La troisième est la seule qui ne se voie pas. Le plugin a appris à poser un rôle, à écrire la raison sociale et l'adresse de livraison à cette occasion : avec une version plus ancienne, accepter une candidature crée un compte client ordinaire, sans raison sociale, et rien ne le signale.
Le plugin se met en ligne par FTP, dossier darsy-plugin/ vers wp-content/plugins/darsy-plugin/. workers/plugin_doctor.php dit ce qu'il trouve.
La liste des pays est provisoire
Le formulaire propose la France et ses voisins francophones.
La vraie liste est un réglage WooCommerce — « pays vers lesquels vous vendez » — que le plugin n'expose pas encore. Elle est écrite en dur plutôt que devinée large : proposer un pays où la boutique ne livre pas ferait une candidature à refuser après coup, pour une raison que le candidat ne pouvait pas connaître.