docs(onboarding): merchant intake checklist (EN + FR)
All checks were successful
All checks were successful
Practical field-by-field intake doc for the first merchants — maps each question to its DB column so the call → admin UI is 1:1. Includes a section on marketing-material reuse aimed at franchisees, with written-authorization clauses for the future marketing module. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
340
docs/proposals/merchant-intake-checklist-fr.md
Normal file
340
docs/proposals/merchant-intake-checklist-fr.md
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
# Fiche d'intégration commerçant — Premier point de vente
|
||||||
|
|
||||||
|
Liste pratique de toutes les données à collecter auprès d'un nouveau
|
||||||
|
commerçant avant de mettre en service son premier point de vente sur la
|
||||||
|
plateforme de fidélité. Chaque champ est rattaché à la colonne de base
|
||||||
|
de données correspondante, de sorte que ce qui est collecté lors de la
|
||||||
|
réunion d'intégration se reporte 1:1 dans l'interface d'administration.
|
||||||
|
|
||||||
|
À utiliser comme formulaire à partager, ou comme trame de discussion
|
||||||
|
pour le premier appel d'intégration.
|
||||||
|
|
||||||
|
## Comment utiliser ce document
|
||||||
|
|
||||||
|
1. Envoyer au commerçant les sections **« Ce que vous devez nous
|
||||||
|
fournir »** (1–7) avant la réunion de lancement, pour qu'il
|
||||||
|
prépare les logos, numéros de TVA et informations du personnel.
|
||||||
|
2. Utiliser les sections **décisions métier** (3, 5) pour structurer
|
||||||
|
l'appel — ce sont les choix que seul le commerçant peut faire.
|
||||||
|
3. Après l'appel, remplir l'interface d'administration dans l'ordre
|
||||||
|
ci-dessous ; le modèle impose cette chaîne de dépendances
|
||||||
|
(commerçant → point de vente → programme de fidélité → personnel).
|
||||||
|
|
||||||
|
## TL;DR — ce sans quoi vous ne pouvez absolument pas lancer
|
||||||
|
|
||||||
|
- Raison sociale + numéro de TVA + adresse de l'entreprise
|
||||||
|
- E-mail du propriétaire (identifiant et destinataire de l'invitation)
|
||||||
|
- Nom du point de vente + code de point de vente (slug URL)
|
||||||
|
- Type de programme de fidélité (tampons / points / hybride) et
|
||||||
|
structure de récompense
|
||||||
|
- URL de la politique de confidentialité (RGPD)
|
||||||
|
- Logo de la marque (PNG carré, fond transparent)
|
||||||
|
- Couleur principale de la marque (hex)
|
||||||
|
- Au moins un code PIN du personnel
|
||||||
|
|
||||||
|
Tout le reste peut être complété de manière itérative après le
|
||||||
|
lancement.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Identité de l'entreprise (entité **commerçant**)
|
||||||
|
|
||||||
|
Un par commerçant — alimente la table `merchants`.
|
||||||
|
|
||||||
|
| Champ | Requis ? | Colonne BDD | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Raison sociale | ✅ | `name` | Apparaît sur les factures et pieds d'e-mails |
|
||||||
|
| Nom commercial (si différent) | optionnel | (utiliser `name`) | Le nom que voient les clients |
|
||||||
|
| Description de l'activité | recommandé | `description` | Slogan d'une ligne |
|
||||||
|
| Numéro de TVA | ✅ UE | `tax_number` | Format LU : `LU12345678` |
|
||||||
|
| Numéro d'immatriculation | ✅ | `tax_number` (ou champ séparé si disponible) | LU : `RCS Lxxxxxx` |
|
||||||
|
| Adresse de l'entreprise | ✅ | `business_address` | Rue + ville + code postal + pays |
|
||||||
|
| E-mail de contact principal | ✅ | `contact_email` | Pour factures et alertes plateforme |
|
||||||
|
| Téléphone principal | recommandé | `contact_phone` | Pour rappels du support |
|
||||||
|
| URL du site web | optionnel | `website` | Lié depuis le pied de page du storefront |
|
||||||
|
|
||||||
|
## 2. Compte propriétaire / administrateur
|
||||||
|
|
||||||
|
La personne qui se connecte en tant que propriétaire du commerçant.
|
||||||
|
|
||||||
|
| Champ | Requis ? | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Nom complet | ✅ | Affiché dans les journaux d'audit |
|
||||||
|
| E-mail (identifiant) | ✅ | L'invitation y est envoyée — doit être livrable |
|
||||||
|
| Téléphone | recommandé | |
|
||||||
|
| Langue d'interface préférée (en / fr / de / lb) | ✅ | Pilote la langue du tableau de bord d'admin |
|
||||||
|
|
||||||
|
## 3. Chaque point de vente
|
||||||
|
|
||||||
|
À répéter par emplacement. Alimente la table `stores`. La plateforme
|
||||||
|
supporte le multi-emplacement dès le premier jour — même les
|
||||||
|
commerçants mono-magasin vivent dans cette structure.
|
||||||
|
|
||||||
|
| Champ | Requis ? | Colonne BDD | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Nom du point de vente | ✅ | `name` | Ex. : « Fashion Hub City Concorde » |
|
||||||
|
| Code interne du point de vente | ✅ | `store_code` | Slug en MAJUSCULES, sans espaces — utilisé dans les URLs (`/store/FASHIONHUB`). À choisir une fois, difficile à modifier |
|
||||||
|
| Sous-domaine | optionnel | `subdomain` | Ex. : `fashionhub.rewardflow.lu` pour le storefront |
|
||||||
|
| Adresse physique | ✅ | `business_address` | Par emplacement, remplace l'adresse du commerçant si différente |
|
||||||
|
| E-mail de contact local | optionnel | `contact_email` | Remplace l'e-mail commerçant si le point de vente a le sien |
|
||||||
|
| Téléphone local | optionnel | `contact_phone` | |
|
||||||
|
| Taux de TVA par défaut % | optionnel | `letzshop_default_tax_rate` | Par défaut 17 % (TVA standard LU) |
|
||||||
|
| Langue d'interface par défaut | ✅ | `default_language` / `dashboard_language` | Langue d'ouverture du terminal du personnel |
|
||||||
|
| Langues client | ✅ | `storefront_languages` | Sous-ensemble de `{en, fr, de, lb}` pour LU |
|
||||||
|
| Horaires d'ouverture | optionnel | pas encore dans le schéma | Contexte utile pour le support |
|
||||||
|
|
||||||
|
## 4. Personnel (par point de vente, pour chaque caissier)
|
||||||
|
|
||||||
|
Alimente `users` + `store_users` (flux d'invitation).
|
||||||
|
|
||||||
|
| Champ | Requis ? | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Nom complet | ✅ | Affiché sur l'écran PIN de la tablette |
|
||||||
|
| E-mail | ✅ si accès web nécessaire | Les opérateurs uniquement-PIN-tablette n'ont pas besoin de compte |
|
||||||
|
| Code PIN à 4 chiffres | ✅ | Ils le choisissent ; vous le configurez dans `/admin/loyalty/pins` ; saisi à chaque transaction sur la tablette |
|
||||||
|
| Identifiant / numéro d'employé | optionnel | Affiché à côté du nom dans la piste d'audit |
|
||||||
|
| Rôle | ✅ | Un parmi : `merchant_owner`, `store_admin`, `store_staff` |
|
||||||
|
|
||||||
|
## 5. Programme de fidélité — les **décisions métier**
|
||||||
|
|
||||||
|
Un programme par commerçant. Alimente la table `loyalty_programs`.
|
||||||
|
C'est ici que se déroule l'essentiel de la discussion de lancement —
|
||||||
|
aidez-les à choisir.
|
||||||
|
|
||||||
|
### 5.1 Type de programme
|
||||||
|
|
||||||
|
| Type | Quand le recommander |
|
||||||
|
|---|---|
|
||||||
|
| **Tampons** | Modèle « achetez-en 10, le suivant est offert ». Cafés, coiffeurs, restaurants, partout où il existe une unité de vente claire |
|
||||||
|
| **Points** | « Gagnez X points par €, échangez-les contre des récompenses ». Commerce avec paniers variés |
|
||||||
|
| **Hybride** | Les deux à la fois. Rare en v1 — à différer |
|
||||||
|
|
||||||
|
### 5.2 Si tampons
|
||||||
|
|
||||||
|
| Champ | Valeur typique | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| `stamps_target` | 10 | Tampons pour remplir une carte |
|
||||||
|
| `stamps_reward_description` | « Café offert » | Nom de la récompense côté client |
|
||||||
|
| `stamps_reward_value_cents` | 500 (= 5 €) | Valeur interne pour l'analytique |
|
||||||
|
|
||||||
|
### 5.3 Si points
|
||||||
|
|
||||||
|
| Champ | Valeur typique | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| `points_per_euro` | 1, 5 ou 10 | Taux d'acquisition |
|
||||||
|
| `welcome_bonus_points` | 50–100 | Attribués à l'inscription, donnent une bonne première impression |
|
||||||
|
| `minimum_purchase_cents` | 500 (= 5 €) | Montant minimum de vente pour gagner — élimine les achats de chewing-gums |
|
||||||
|
| `minimum_redemption_points` | 100 | Points minimum pour échanger quoi que ce soit |
|
||||||
|
| `points_expiration_days` | 365 | Au-delà, les points non utilisés expirent |
|
||||||
|
| `points_rewards` (liste JSON) | voir ci-dessous | Le menu des récompenses |
|
||||||
|
|
||||||
|
Chaque entrée de `points_rewards` doit contenir : `name`,
|
||||||
|
`points_required`, `description`, `value`. Exemple :
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{"name": "Bon de 5 €", "points_required": 100, "description": "À utiliser en caisse", "value": 500},
|
||||||
|
{"name": "Bon de 15 €", "points_required": 250, "description": "À utiliser en caisse", "value": 1500},
|
||||||
|
{"name": "Produit XYZ offert", "points_required": 400, "description": "Retrait en magasin", "value": null}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.4 Garde-fous anti-fraude
|
||||||
|
|
||||||
|
| Champ | Défaut | Quand modifier |
|
||||||
|
|---|---|---|
|
||||||
|
| `cooldown_minutes` | 0 | Mettre 30–60 pour les cafés à fort volume, pour limiter les abus du personnel |
|
||||||
|
| `max_daily_stamps` | 10 | Réduire si volume faible ; plafonne les tampons quotidiens d'une carte |
|
||||||
|
| `require_staff_pin` | true | Recommandé `true` dès qu'il y a >1 employé ; la tablette gère hors ligne |
|
||||||
|
|
||||||
|
### 5.5 Comportement multi-emplacement
|
||||||
|
|
||||||
|
Ces paramètres sont sur les réglages commerçant
|
||||||
|
(`merchant_loyalty_settings`), pas sur le programme :
|
||||||
|
|
||||||
|
| Paramètre | Défaut | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| `allow_cross_location_redemption` | ✅ activé | Gagner en A et échanger en B ? Oui pour les chaînes, non pour des indépendants partageant l'infrastructure |
|
||||||
|
| `allow_void_transactions` | ✅ activé | Certains commerçants désactivent pour contrôler la fraude |
|
||||||
|
| `require_order_reference` | désactivé | Utile si intégration avec leur caisse — relie chaque transaction de fidélité à un numéro de ticket |
|
||||||
|
|
||||||
|
## 6. Éléments de marque
|
||||||
|
|
||||||
|
À collecter sous forme de **fichiers**, pas de liens — nous les
|
||||||
|
hébergeons.
|
||||||
|
|
||||||
|
| Élément | Format | Taille | Champ BDD |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Logo principal | PNG, fond transparent | 600×600 min, carré | `logo_url` |
|
||||||
|
| Bannière hero | JPG / PNG | 1200×400 | `hero_image_url` |
|
||||||
|
| Couleur principale | Hex | ex. `#7C3AED` | `card_color` |
|
||||||
|
| Couleur secondaire | Hex | ex. `#10B981` | `card_secondary_color` |
|
||||||
|
| Nom affiché de la carte | Chaîne courte | ex. « Fashion Hub Rewards » | `card_name` |
|
||||||
|
|
||||||
|
Le logo sert aussi de **logo Google Wallet**, donc 600×600 minimum
|
||||||
|
avec fond transparent est le plancher pratique — Google exige une
|
||||||
|
bonne lisibilité.
|
||||||
|
|
||||||
|
## 7. Conformité & RGPD
|
||||||
|
|
||||||
|
Requis pour le go-live, en particulier au Luxembourg.
|
||||||
|
|
||||||
|
| Champ | Requis ? | Champ BDD | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| URL de la politique de confidentialité | ✅ UE | `privacy_url` | Lié depuis le formulaire d'inscription. Leur site ou votre CMS |
|
||||||
|
| CGU de fidélité | ✅ | `terms_text` ou `terms_cms_page_slug` | Texte en ligne ou slug de page CMS. À couvrir : fonctionnement des points, expiration, conditions de révocation, contact en cas de litige |
|
||||||
|
| Contact DPO (si applicable) | dépend de la taille | pas dans le schéma | Règle LU : >5 000 enregistrements clients → DPO désigné requis |
|
||||||
|
| Consentement marketing | implicite | (case à cocher sur le formulaire d'inscription) | Obligatoire si envoi d'e-mails anniversaire / réengagement |
|
||||||
|
|
||||||
|
## 8. Tablettes (si vous fournissez le matériel POS)
|
||||||
|
|
||||||
|
| Question | Pourquoi |
|
||||||
|
|---|---|
|
||||||
|
| Combien de tablettes par point de vente ? | Détermine le nombre d'appairages à configurer |
|
||||||
|
| Tablettes Android existantes ? Modèle + OS ? | Nécessite Android 8.0+ (API 26), Play Services. Fire OS ne fonctionnera pas |
|
||||||
|
| Sourcer les tablettes pour eux ? | Lenovo Tab M11 ou Samsung Galaxy Tab A9 (100–200 € l'unité) — modèles éprouvés |
|
||||||
|
| Montage ? Support comptoir ou mural ? | Influe sur le plan d'alimentation/recharge |
|
||||||
|
| Wi-Fi à chaque emplacement | La file d'attente hors ligne gère les coupures brèves, pas une journée entière. Confirmer le Wi-Fi au comptoir |
|
||||||
|
|
||||||
|
## 9. Migration de données initiales (optionnel mais utile)
|
||||||
|
|
||||||
|
| Question | Pourquoi |
|
||||||
|
|---|---|
|
||||||
|
| Liste clients fidélité existante ? | S'ils passent d'un autre système ou de cartes papier, import en masse via CSV (e-mail, nom, solde, date d'inscription) |
|
||||||
|
| Nombre approximatif de clients initiaux ? | Dimensionne la discussion de capacité |
|
||||||
|
| Volume mensuel actuel de transactions | Idem |
|
||||||
|
|
||||||
|
## 10. Réutilisation de matériel marketing (pour le futur module marketing)
|
||||||
|
|
||||||
|
Beaucoup de nos premiers commerçants sont franchisés (chaînes de mode,
|
||||||
|
restauration, beauté) et reçoivent en continu du matériel de campagne
|
||||||
|
du franchiseur — bannières, modèles d'e-mails, publications sociales,
|
||||||
|
promotions saisonnières. Le futur module marketing vise à
|
||||||
|
**republier** ce matériel au niveau du point de vente local : un
|
||||||
|
franchisé ne devrait pas avoir à concevoir lui-même un e-mail
|
||||||
|
anniversaire alors que le siège en produit cinq par an.
|
||||||
|
|
||||||
|
À l'intégration, posez les questions sous forme d'autorisation pour
|
||||||
|
avoir le feu vert *avant* de construire la chaîne d'ingestion. On ne
|
||||||
|
leur demande rien aujourd'hui — on inventorie les sources et on
|
||||||
|
obtient une autorisation écrite.
|
||||||
|
|
||||||
|
### 10.1 Matériel marketing existant — inventaire
|
||||||
|
|
||||||
|
| Question | Pourquoi |
|
||||||
|
|---|---|
|
||||||
|
| Le commerçant est-il franchisé ? De quelle enseigne ? | Détermine les sources institutionnelles potentielles |
|
||||||
|
| Reçoit-il une **newsletter régulière** du franchiseur ? Nous transférer 3–5 récentes | Permet d'évaluer le type de contenu, la fréquence, le mix linguistique et le formatage |
|
||||||
|
| Existe-t-il un **extranet / portail franchiseur** où sont publiées les campagnes ? URL + identifiants en lecture seule | Source idéale : structurée, datée, multilingue |
|
||||||
|
| **Comptes sociaux** sur lesquels le franchiseur publie (Instagram, Facebook, LinkedIn) | Public, scrapable, mais ratio signal/bruit faible |
|
||||||
|
| **Groupes WhatsApp / Telegram** de diffusion auxquels ils appartiennent | Parfois le seul canal — transfert manuel peut être l'unique voie |
|
||||||
|
| Packs **PDF / images** reçus par e-mail ou lien de téléchargement | Fréquent pour les campagnes saisonnières ; demander les derniers |
|
||||||
|
| Fréquence : hebdomadaire / mensuelle / par campagne | Dimensionne le volume d'ingestion |
|
||||||
|
| Langues de publication du franchiseur | Détermine si on réutilise tel quel ou si on retraduit |
|
||||||
|
|
||||||
|
### 10.2 Autorisation de réutilisation — à obtenir par écrit
|
||||||
|
|
||||||
|
Avant tout scraping ou republication, le commerçant doit nous
|
||||||
|
autoriser. À recueillir à l'intégration (case à cocher sur le
|
||||||
|
formulaire ou clause dans le contrat commerçant) :
|
||||||
|
|
||||||
|
- ✅ **« J'autorise {plateforme} à ingérer le matériel marketing que je
|
||||||
|
transfère, partage ou rends accessible, et à le republier en mon nom
|
||||||
|
via les canaux de fidélité/marketing offerts par la plateforme. »**
|
||||||
|
- ✅ **« Je confirme avoir le droit (en tant que franchisé) d'utiliser
|
||||||
|
ce matériel en marketing local, et que les chartes de marque ou
|
||||||
|
conditions de licence du franchiseur autorisent la republication via
|
||||||
|
des plateformes tierces. »**
|
||||||
|
- ✅ Nous transférer les **chartes de marque / politique de marketing
|
||||||
|
collaboratif** du franchiseur si elle existe. Cela détermine ce qui
|
||||||
|
peut être fait en toute sécurité.
|
||||||
|
|
||||||
|
### 10.3 Voies pratiques de capture (du plus simple au plus complexe)
|
||||||
|
|
||||||
|
Pour le futur module marketing, par ordre de facilité de mise en
|
||||||
|
œuvre :
|
||||||
|
|
||||||
|
1. **Transfert vers une boîte dédiée.** Donner au commerçant un alias
|
||||||
|
par point de vente, ex. `marketing+FASHIONHUB@rewardflow.lu`. Il
|
||||||
|
transfère tout e-mail du franchiseur là-bas. On parse et on
|
||||||
|
catégorise.
|
||||||
|
2. **Téléversement glisser-déposer.** Une page où le commerçant colle
|
||||||
|
une URL ou téléverse un PDF/image ; on OCR/parse et on met en file
|
||||||
|
pour validation.
|
||||||
|
3. **Récupération authentifiée sur extranet.** Ils nous fournissent
|
||||||
|
des identifiants en lecture seule au portail franchiseur ; on
|
||||||
|
sonde régulièrement. Signal le plus élevé, exigence légale la plus
|
||||||
|
haute — nécessite l'aval explicite du franchiseur.
|
||||||
|
4. **Scraping social public.** En dernier recours, uniquement pour le
|
||||||
|
matériel publié ouvertement par le franchiseur. Respecter
|
||||||
|
`robots.txt` et les CGU des plateformes.
|
||||||
|
|
||||||
|
### 10.4 Canaux de republication sur lesquels brancher
|
||||||
|
|
||||||
|
Ce qu'on **fait** de ce matériel une fois capté :
|
||||||
|
|
||||||
|
- Rotation de la **bannière storefront** (déjà dans le CMS)
|
||||||
|
- E-mails **fidélité bienvenue / réengagement / anniversaire** (module
|
||||||
|
loyalty v1 — modèles fixes ; module marketing v2 — pilotés par
|
||||||
|
campagne)
|
||||||
|
- **SMS / WhatsApp** (module marketing v2, différé)
|
||||||
|
- **Notifications push** via la carte Wallet (Google Wallet prend en
|
||||||
|
charge les mises à jour au niveau de la classe — push à chaque
|
||||||
|
téléphone client)
|
||||||
|
|
||||||
|
### 10.5 Signaux d'alerte à remonter au commerçant
|
||||||
|
|
||||||
|
Si l'un de ces points apparaît à l'intégration, signaler pour revue
|
||||||
|
juridique **avant** de toucher au matériel :
|
||||||
|
|
||||||
|
- Présence de marques du franchiseur sans licence explicite du
|
||||||
|
franchisé pour cet usage
|
||||||
|
- Références à des marques tierces (co-promotions) — ces marques n'ont
|
||||||
|
pas consenti à notre plateforme
|
||||||
|
- Matériel dans une langue que la clientèle du commerçant ne parle pas
|
||||||
|
— on ne traduit pas automatiquement sans autorisation
|
||||||
|
- Données personnelles de personnes nommées (témoignages, photos) —
|
||||||
|
la chaîne de consentement RGPD ne s'étend peut-être pas à nous
|
||||||
|
|
||||||
|
## 11. Client de test pour vérification
|
||||||
|
|
||||||
|
Avant d'ouvrir aux vrais clients, dérouler les 8 tests utilisateur de
|
||||||
|
bout en bout avec deux comptes de test :
|
||||||
|
|
||||||
|
- L'e-mail personnel du propriétaire commerçant
|
||||||
|
- Un membre de l'équipe ou votre propre e-mail
|
||||||
|
|
||||||
|
La liste de tests E2E se trouve dans
|
||||||
|
[`app/modules/loyalty/docs/user-journeys.md`](../modules/loyalty/user-journeys.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ordre de saisie suggéré dans l'interface d'administration
|
||||||
|
|
||||||
|
Le modèle a des dépendances de clés étrangères strictes, donc à
|
||||||
|
remplir dans cet ordre :
|
||||||
|
|
||||||
|
1. **Créer le commerçant** (`/admin/merchants/new`) — nécessite § 1.
|
||||||
|
2. **Inviter le propriétaire** — nécessite § 2.
|
||||||
|
3. **Créer le(s) point(s) de vente** (`/admin/stores/new`) —
|
||||||
|
nécessite § 3.
|
||||||
|
4. **Créer le programme de fidélité**
|
||||||
|
(`/admin/loyalty/programs/new`) — nécessite §§ 5, 6, 7.
|
||||||
|
5. **Créer les codes PIN du personnel**
|
||||||
|
(`/admin/loyalty/pins/new` par point de vente) — nécessite § 4.
|
||||||
|
6. **Configurer les paramètres multi-emplacement**
|
||||||
|
(`/admin/loyalty/settings/{merchant}`) — nécessite § 5.5.
|
||||||
|
7. **(Optionnel) importer les clients en masse** via CSV —
|
||||||
|
nécessite § 9.
|
||||||
|
8. **Appairer la/les tablette(s)** à chaque point de vente
|
||||||
|
(`/admin/loyalty/terminals/new`, QR ou manuel) — nécessite § 8.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Référence
|
||||||
|
|
||||||
|
- Modèles de base de données : `models/database/{merchants,stores,loyalty}.py`
|
||||||
|
- Plan de lancement production fidélité : [`app/modules/loyalty/docs/production-launch-plan.md`](../modules/loyalty/production-launch-plan.md)
|
||||||
|
- Synthèse de prêt-au-lancement : [`loyalty-go-live-readiness.md`](loyalty-go-live-readiness.md)
|
||||||
|
- Tests E2E utilisateur : [`app/modules/loyalty/docs/user-journeys.md`](../modules/loyalty/user-journeys.md)
|
||||||
|
- Version anglaise : [`merchant-intake-checklist.md`](merchant-intake-checklist.md)
|
||||||
323
docs/proposals/merchant-intake-checklist.md
Normal file
323
docs/proposals/merchant-intake-checklist.md
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
# Merchant Intake Checklist — First Store Onboarding
|
||||||
|
|
||||||
|
A practical list of every datum to collect from a new merchant before
|
||||||
|
flipping their first store live on the loyalty platform. Each field is
|
||||||
|
mapped to the actual database column behind it, so what you collect in
|
||||||
|
the intake meeting maps 1:1 to the admin UI you'll fill in afterwards.
|
||||||
|
|
||||||
|
Use this as a sharable form, or as a script for the first onboarding
|
||||||
|
call.
|
||||||
|
|
||||||
|
## How to use this doc
|
||||||
|
|
||||||
|
1. Send the merchant the **"What you need to send us"** sections (1–7)
|
||||||
|
ahead of the kickoff call, so they have logos / VAT numbers / staff
|
||||||
|
info ready.
|
||||||
|
2. Use the **business decisions** sections (3, 5) to drive the actual
|
||||||
|
conversation — these are the choices only they can make.
|
||||||
|
3. After the call, populate the admin UI in the order below; the model
|
||||||
|
enforces this dependency chain (merchant → store → loyalty program →
|
||||||
|
staff).
|
||||||
|
|
||||||
|
## TL;DR — what you absolutely cannot launch without
|
||||||
|
|
||||||
|
- Legal business name + VAT number + business address
|
||||||
|
- Owner email (login + invitation target)
|
||||||
|
- Store name + store code (URL slug)
|
||||||
|
- Loyalty program type (stamps / points / hybrid) + reward structure
|
||||||
|
- Privacy policy URL (GDPR)
|
||||||
|
- Brand logo (square PNG, transparent bg)
|
||||||
|
- Brand primary color (hex)
|
||||||
|
- At least one staff PIN
|
||||||
|
|
||||||
|
Everything else can be filled in iteratively post-launch.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Business identity (the **merchant** entity)
|
||||||
|
|
||||||
|
One per merchant — feeds the `merchants` table.
|
||||||
|
|
||||||
|
| Field | Required? | DB column | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Legal business name | ✅ | `name` | Appears on invoices + email footers |
|
||||||
|
| Trading name (if different) | optional | (use `name`) | The name customers see |
|
||||||
|
| Business description | recommended | `description` | One-line tagline |
|
||||||
|
| VAT / tax number | ✅ EU | `tax_number` | LU format: `LU12345678` |
|
||||||
|
| Business registration number | ✅ | `tax_number` (or separate field if available) | LU: `RCS Lxxxxxx` |
|
||||||
|
| Business address | ✅ | `business_address` | Street + city + ZIP + country |
|
||||||
|
| Primary contact email | ✅ | `contact_email` | Where invoices + platform alerts go |
|
||||||
|
| Primary contact phone | recommended | `contact_phone` | For support callbacks |
|
||||||
|
| Website URL | optional | `website` | Linked from storefront footer |
|
||||||
|
|
||||||
|
## 2. Owner / admin account
|
||||||
|
|
||||||
|
The human who logs in as merchant owner.
|
||||||
|
|
||||||
|
| Field | Required? | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Full name | ✅ | Shown on audit logs |
|
||||||
|
| Email (login) | ✅ | Invitation goes here — must be deliverable |
|
||||||
|
| Phone | recommended | |
|
||||||
|
| Preferred UI language (en / fr / de / lb) | ✅ | Drives the admin dashboard's language |
|
||||||
|
|
||||||
|
## 3. Each store / point of sale
|
||||||
|
|
||||||
|
Repeat per location. Feeds the `stores` table. The platform supports
|
||||||
|
multi-location from day one — even single-store merchants live in this
|
||||||
|
shape.
|
||||||
|
|
||||||
|
| Field | Required? | DB column | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Store name | ✅ | `name` | E.g. "Fashion Hub City Concorde" |
|
||||||
|
| Internal store code | ✅ | `store_code` | UPPERCASE slug, no spaces — used in URLs (`/store/FASHIONHUB`). Pick once, hard to change |
|
||||||
|
| Subdomain | optional | `subdomain` | E.g. `fashionhub.rewardflow.lu` for the storefront |
|
||||||
|
| Physical address | ✅ | `business_address` | Per-location, overrides merchant address if different |
|
||||||
|
| Local contact email | optional | `contact_email` | Overrides merchant-level if store has its own |
|
||||||
|
| Local phone | optional | `contact_phone` | |
|
||||||
|
| Default tax rate % | optional | `letzshop_default_tax_rate` | Defaults to 17% (LU standard VAT) |
|
||||||
|
| Default UI language | ✅ | `default_language` / `dashboard_language` | What the staff terminal opens in |
|
||||||
|
| Customer-facing languages | ✅ | `storefront_languages` | Subset of `{en, fr, de, lb}` for LU |
|
||||||
|
| Opening hours | optional | not in schema yet | Useful context for support |
|
||||||
|
|
||||||
|
## 4. Staff (per store, for each cashier)
|
||||||
|
|
||||||
|
Feeds `users` + `store_users` (invitation flow).
|
||||||
|
|
||||||
|
| Field | Required? | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| Full name | ✅ | Shown on the tablet PIN screen |
|
||||||
|
| Email | ✅ if web access needed | Owner-only PIN-on-tablet operators don't need an account |
|
||||||
|
| 4-digit PIN | ✅ | They pick it; you set it on `/admin/loyalty/pins`; staff types it on the tablet for every transaction |
|
||||||
|
| Employee ID / staff number | optional | Shown alongside name in audit trail |
|
||||||
|
| Role | ✅ | One of: `merchant_owner`, `store_admin`, `store_staff` |
|
||||||
|
|
||||||
|
## 5. Loyalty program — the **business decisions**
|
||||||
|
|
||||||
|
One program per merchant. Feeds the `loyalty_programs` table. This is
|
||||||
|
where most of the kickoff conversation happens — help them choose.
|
||||||
|
|
||||||
|
### 5.1 Program type
|
||||||
|
|
||||||
|
| Type | When to recommend |
|
||||||
|
|---|---|
|
||||||
|
| **Stamps** | "Buy 10, get 1 free" model. Cafés, hairdressers, lunch spots, anywhere with a clear unit of sale |
|
||||||
|
| **Points** | "Earn X points per €, redeem on rewards menu". Retail with varied basket sizes |
|
||||||
|
| **Hybrid** | Both at once. Rare for v1 — defer |
|
||||||
|
|
||||||
|
### 5.2 If stamps
|
||||||
|
|
||||||
|
| Field | Typical value | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| `stamps_target` | 10 | Stamps to fill a card |
|
||||||
|
| `stamps_reward_description` | "Free coffee" | Customer-facing reward name |
|
||||||
|
| `stamps_reward_value_cents` | 500 (= €5) | Internal value for analytics |
|
||||||
|
|
||||||
|
### 5.3 If points
|
||||||
|
|
||||||
|
| Field | Typical value | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| `points_per_euro` | 1, 5, or 10 | The earn rate |
|
||||||
|
| `welcome_bonus_points` | 50–100 | Awarded on enrollment, makes new customers feel rewarded |
|
||||||
|
| `minimum_purchase_cents` | 500 (= €5) | Minimum sale to earn anything — kills chewing-gum farming |
|
||||||
|
| `minimum_redemption_points` | 100 | Minimum points to redeem anything |
|
||||||
|
| `points_expiration_days` | 365 | After this, unredeemed points lapse |
|
||||||
|
| `points_rewards` (JSON list) | see below | The reward menu |
|
||||||
|
|
||||||
|
Each entry in `points_rewards` needs: `name`, `points_required`,
|
||||||
|
`description`, `value`. Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{"name": "€5 voucher", "points_required": 100, "description": "Apply at checkout", "value": 500},
|
||||||
|
{"name": "€15 voucher", "points_required": 250, "description": "Apply at checkout", "value": 1500},
|
||||||
|
{"name": "Free product XYZ", "points_required": 400, "description": "Pickup in store", "value": null}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.4 Anti-fraud knobs
|
||||||
|
|
||||||
|
| Field | Default | When to change |
|
||||||
|
|---|---|---|
|
||||||
|
| `cooldown_minutes` | 0 | Set 30–60 for high-volume cafés to stop staff abuse |
|
||||||
|
| `max_daily_stamps` | 10 | Lower if low-volume; this caps a single card's daily stamps |
|
||||||
|
| `require_staff_pin` | true | Recommended `true` for >1 staff member; tablet handles offline |
|
||||||
|
|
||||||
|
### 5.5 Cross-location behaviour
|
||||||
|
|
||||||
|
This is on the merchant settings (`merchant_loyalty_settings`), not the
|
||||||
|
program:
|
||||||
|
|
||||||
|
| Setting | Default | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| `allow_cross_location_redemption` | ✅ on | Earn at Store A, redeem at Store B? Yes for chains, no for indies sharing infrastructure |
|
||||||
|
| `allow_void_transactions` | ✅ on | Some merchants disable for fraud control |
|
||||||
|
| `require_order_reference` | off | Useful if integrating with their POS/till — links each loyalty transaction to a sale receipt |
|
||||||
|
|
||||||
|
## 6. Branding assets
|
||||||
|
|
||||||
|
Collect as **files**, not links — we host them.
|
||||||
|
|
||||||
|
| Asset | Format | Size | DB field |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Primary logo | PNG, transparent bg | 600×600 min, square | `logo_url` |
|
||||||
|
| Hero banner | JPG / PNG | 1200×400 | `hero_image_url` |
|
||||||
|
| Brand primary color | Hex | e.g. `#7C3AED` | `card_color` |
|
||||||
|
| Brand secondary color | Hex | e.g. `#10B981` | `card_secondary_color` |
|
||||||
|
| Card display name | Short string | e.g. "Fashion Hub Rewards" | `card_name` |
|
||||||
|
|
||||||
|
The logo doubles as the **Google Wallet pass logo**, so 600×600 minimum
|
||||||
|
with transparent background is the practical floor — Google enforces
|
||||||
|
clarity.
|
||||||
|
|
||||||
|
## 7. Compliance & GDPR
|
||||||
|
|
||||||
|
Required for go-live, especially in Luxembourg.
|
||||||
|
|
||||||
|
| Field | Required? | DB field | Notes |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Privacy policy URL | ✅ EU | `privacy_url` | Linked from enrollment form. Their site or your CMS |
|
||||||
|
| Loyalty T&C | ✅ | `terms_text` or `terms_cms_page_slug` | Inline text or CMS page slug. Cover: how points work, expiry, when rewards can be revoked, contact for issues |
|
||||||
|
| DPO contact (if applicable) | depends on size | not in schema | LU rule: >5k customer records → designated DPO |
|
||||||
|
| Marketing consent | implicit | (enrollment form has the checkbox) | Required if you'll send birthday / re-engagement emails |
|
||||||
|
|
||||||
|
## 8. Tablets (if you provide the POS hardware)
|
||||||
|
|
||||||
|
| Question | Why |
|
||||||
|
|---|---|
|
||||||
|
| How many tablets per store? | Determines how many device pairings to set up |
|
||||||
|
| Existing Android tablets? Model + OS? | Need Android 8.0+ (API 26), Play Services. Fire OS won't work |
|
||||||
|
| Source tablets for them? | Lenovo Tab M11 or Samsung Galaxy Tab A9 (€100–200 each) — known good |
|
||||||
|
| Mounting? Counter stand or wall? | Affects power/charging plan |
|
||||||
|
| Wifi at each location | Offline queue handles brief outages, not all-day. Confirm wifi at the counter |
|
||||||
|
|
||||||
|
## 9. Initial data migration (nice-to-have)
|
||||||
|
|
||||||
|
| Question | Why |
|
||||||
|
|---|---|
|
||||||
|
| Existing loyalty customer list? | If they're switching from another system or paper cards, bulk-import via CSV (email, name, balance, enrollment date) |
|
||||||
|
| Approximate initial customer count? | Sizes capacity discussion |
|
||||||
|
| Current monthly transaction volume | Same |
|
||||||
|
|
||||||
|
## 10. Marketing material reuse (for the future marketing module)
|
||||||
|
|
||||||
|
Many of our early merchants are franchisees (e.g. fashion, food, beauty
|
||||||
|
chains) and receive a steady stream of campaign material from their
|
||||||
|
franchisor — banners, email templates, social posts, seasonal
|
||||||
|
promotions. The future marketing module aims to **republish** this
|
||||||
|
material at the local-store level: a franchisee shouldn't have to design
|
||||||
|
their own birthday email when corporate already produces five a year.
|
||||||
|
|
||||||
|
At intake, ask permission-style questions so we have a green light
|
||||||
|
*before* we build the ingestion pipeline. We are not asking them to do
|
||||||
|
anything today — we're inventorying sources and getting written
|
||||||
|
authorization.
|
||||||
|
|
||||||
|
### 10.1 Existing marketing material — what to inventory
|
||||||
|
|
||||||
|
| Question | Why we ask |
|
||||||
|
|---|---|
|
||||||
|
| Is the merchant a franchisee? Of which brand? | Determines which corporate sources may exist |
|
||||||
|
| Do they receive a regular **email newsletter** from the franchisor? Forward us 3–5 recent ones | Lets us assess content type, frequency, language mix, formatting |
|
||||||
|
| Is there a **franchisor extranet / portal** where campaigns are published? URL + their login (read-only) | The ideal source: structured, dated, multilingual |
|
||||||
|
| **Social handles** the franchisor posts under (Instagram, Facebook, LinkedIn) | Public, scrapeable, but low signal-to-noise |
|
||||||
|
| **WhatsApp / Telegram broadcast groups** they're part of | Sometimes the only channel — manual forwarding may be the only path |
|
||||||
|
| **PDF / image packs** received by email or download link | Common for seasonal campaigns; ask them to share the latest |
|
||||||
|
| Frequency: weekly / monthly / per-campaign | Sizes ingestion volume |
|
||||||
|
| Languages the franchisor publishes in | Influences whether we re-use or re-translate |
|
||||||
|
|
||||||
|
### 10.2 Reuse authorization — get this in writing
|
||||||
|
|
||||||
|
Before any scraping or republishing happens, the merchant must
|
||||||
|
authorize us. Capture in the intake (a checkbox on the onboarding form
|
||||||
|
or a clause in the merchant agreement):
|
||||||
|
|
||||||
|
- ✅ **"I authorize {platform} to ingest marketing material I forward,
|
||||||
|
share, or grant access to, and to republish it on my behalf via the
|
||||||
|
loyalty/marketing channels offered by the platform."**
|
||||||
|
- ✅ **"I confirm I have the right (as franchisee) to use this material
|
||||||
|
in local marketing, and that the franchisor's brand guidelines or
|
||||||
|
licensing terms allow republication via third-party platforms."**
|
||||||
|
- ✅ Forward us the **franchisor's brand guidelines / co-op marketing
|
||||||
|
policy** if one exists. This determines what we can and can't do
|
||||||
|
safely.
|
||||||
|
|
||||||
|
### 10.3 Practical capture paths (least-effort first)
|
||||||
|
|
||||||
|
For the future marketing module, in order of how easy they are to
|
||||||
|
implement:
|
||||||
|
|
||||||
|
1. **Forward-to-inbox.** Give the merchant a per-store email alias like
|
||||||
|
`marketing+FASHIONHUB@rewardflow.lu`. They forward any
|
||||||
|
franchisor email there. We parse + categorize.
|
||||||
|
2. **Drag-and-drop upload.** A page where the merchant pastes a URL or
|
||||||
|
uploads a PDF/image; we OCR/parse + queue for review.
|
||||||
|
3. **Authenticated extranet pull.** They give us read-only credentials
|
||||||
|
to the franchisor portal; we poll. Highest signal, highest legal
|
||||||
|
bar — needs explicit franchisor clearance.
|
||||||
|
4. **Public social scrape.** Last resort, only for material the
|
||||||
|
franchisor publishes openly. Respect robots.txt and platform ToS.
|
||||||
|
|
||||||
|
### 10.4 Republish channels we can plug into
|
||||||
|
|
||||||
|
What we *do* with this material once captured:
|
||||||
|
|
||||||
|
- **Storefront banner** rotation (already exists in CMS)
|
||||||
|
- **Loyalty welcome / re-engagement / birthday emails** (loyalty module
|
||||||
|
v1 — fixed templates; marketing module v2 — campaign-driven)
|
||||||
|
- **SMS / WhatsApp** (marketing module v2, deferred)
|
||||||
|
- **Push notifications** via the Wallet pass (Google Wallet supports
|
||||||
|
this — class-level updates push to every customer's phone)
|
||||||
|
|
||||||
|
### 10.5 Red flags to surface back to the merchant
|
||||||
|
|
||||||
|
If during intake any of these come up, flag for legal review **before**
|
||||||
|
we touch the material:
|
||||||
|
|
||||||
|
- Material contains the franchisor's trademarks in a way the franchisee
|
||||||
|
doesn't have explicit license to use
|
||||||
|
- Material references third-party brands (co-promotions with other
|
||||||
|
brands) — those brands didn't consent to our platform
|
||||||
|
- Material is in a language the merchant's customer base doesn't speak
|
||||||
|
— we don't auto-translate without permission
|
||||||
|
- Personal data of named individuals (testimonials, photos) — GDPR
|
||||||
|
consent chain may not extend to us
|
||||||
|
|
||||||
|
## 11. Test customer for verification
|
||||||
|
|
||||||
|
Before sending the merchant to real customers, run the 8 user-journey
|
||||||
|
tests with two test accounts:
|
||||||
|
|
||||||
|
- The merchant owner's personal email
|
||||||
|
- A team member or your own email
|
||||||
|
|
||||||
|
The end-to-end test list lives in
|
||||||
|
[`app/modules/loyalty/docs/user-journeys.md`](../modules/loyalty/user-journeys.md).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Suggested fill-in order in the admin UI
|
||||||
|
|
||||||
|
The model has hard FK dependencies, so do it in this order:
|
||||||
|
|
||||||
|
1. **Create the merchant** (`/admin/merchants/new`) — needs § 1.
|
||||||
|
2. **Invite the owner** — needs § 2.
|
||||||
|
3. **Create the store(s)** (`/admin/stores/new`) — needs § 3.
|
||||||
|
4. **Create the loyalty program** (`/admin/loyalty/programs/new`) —
|
||||||
|
needs § 5 + § 6 + § 7.
|
||||||
|
5. **Create staff PINs** (`/admin/loyalty/pins/new` per store) — needs
|
||||||
|
§ 4.
|
||||||
|
6. **Configure cross-location settings**
|
||||||
|
(`/admin/loyalty/settings/{merchant}`) — needs § 5.5.
|
||||||
|
7. **(Optional) bulk-import customers** via CSV — needs § 9.
|
||||||
|
8. **Pair tablet(s)** at each store (`/admin/loyalty/terminals/new`,
|
||||||
|
QR or manual) — needs § 8.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- Database models: `models/database/{merchants,stores,loyalty}.py`
|
||||||
|
- Loyalty production launch plan: [`app/modules/loyalty/docs/production-launch-plan.md`](../modules/loyalty/production-launch-plan.md)
|
||||||
|
- Go-live readiness snapshot: [`loyalty-go-live-readiness.md`](loyalty-go-live-readiness.md)
|
||||||
|
- User-journey E2E tests: [`app/modules/loyalty/docs/user-journeys.md`](../modules/loyalty/user-journeys.md)
|
||||||
@@ -339,6 +339,8 @@ nav:
|
|||||||
- Store Login Platform Detection: proposals/store-login-platform-detection.md
|
- Store Login Platform Detection: proposals/store-login-platform-detection.md
|
||||||
- Test API Deps Auth Dependencies: proposals/test-api-deps-auth-dependencies.md
|
- Test API Deps Auth Dependencies: proposals/test-api-deps-auth-dependencies.md
|
||||||
- Post Soft-Delete Follow-ups: proposals/post-soft-delete-followups.md
|
- Post Soft-Delete Follow-ups: proposals/post-soft-delete-followups.md
|
||||||
|
- Merchant Intake Checklist: proposals/merchant-intake-checklist.md
|
||||||
|
- "Merchant Intake Checklist (FR)": proposals/merchant-intake-checklist-fr.md
|
||||||
|
|
||||||
# --- Archive ---
|
# --- Archive ---
|
||||||
- Archive:
|
- Archive:
|
||||||
|
|||||||
Reference in New Issue
Block a user