{
  "generatedAt": "2026-08-06T21:01:33.237Z",
  "siteUrl": "https://teranga-pms.jdidit.cloud",
  "productVersion": "2.89.0",
  "count": 40,
  "articles": [
    {
      "id": "connexion",
      "url": "https://teranga-pms.jdidit.cloud/documentation/connexion/",
      "title": "Se connecter à Teranga",
      "summary": "Connexion web et mobile, et aperçu des 7 rôles disponibles sur la plateforme.",
      "keywords": [
        "connexion",
        "login",
        "rôles",
        "RBAC",
        "application Android"
      ],
      "category": "Premiers pas",
      "modules": [
        "Utilisateurs & RBAC"
      ],
      "metiers": [],
      "roles": [
        "Owner",
        "DAF",
        "Manager",
        "Serveur",
        "Cuisinier",
        "Ménage",
        "POS"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "tableau-de-bord"
      ],
      "placeholder": false,
      "content": "## Interface web\n\n1. Ouvrez votre navigateur et accédez à l'adresse de votre établissement.\n2. Saisissez votre **adresse e-mail** et votre **mot de passe**.\n3. Cliquez sur **Se connecter**.\n\nVous êtes redirigé vers le tableau de bord correspondant à votre rôle.\n\n## Application mobile\n\n1. Ouvrez l'application **Teranga** sur votre appareil Android.\n2. Saisissez votre e-mail et votre mot de passe.\n3. Appuyez sur **Connexion**.\n\nL'application détecte automatiquement votre rôle et affiche l'interface adaptée — pas de configuration supplémentaire.\n\n## Les 7 rôles disponibles\n\n| Rôle | Accès principal |\n|------|------------------|\n| **Propriétaire (Owner)** | Accès complet : établissement, canaux de réservation |\n| **DAF** | Vue globale, approbations, rapports, finances |\n| **Manager** | Menu, personnel, rapports, canaux |\n| **Serveur** | Prise de commandes, QR codes, reçus |\n| **Cuisinier** | Commandes en cuisine |\n| **Ménage** | Pointage du nettoyage des chambres, notifications ciblées |\n| **POS** | Facturation et encaissement |\n\nChaque rôle ne voit que les fonctionnalités qui le concernent — un Serveur ne voit pas Réservations, Chambres ou Approbations, par exemple."
    },
    {
      "id": "tableau-de-bord",
      "url": "https://teranga-pms.jdidit.cloud/documentation/tableau-de-bord/",
      "title": "Le tableau de bord, par rôle",
      "summary": "Ce que chaque rôle voit en se connectant : Owner, DAF, Manager, Serveur, Cuisinier, Ménage.",
      "keywords": [
        "tableau de bord",
        "dashboard",
        "rôles",
        "indicateurs"
      ],
      "category": "Premiers pas",
      "modules": [
        "Utilisateurs & RBAC",
        "Rapports & Export",
        "Notifications temps réel"
      ],
      "metiers": [],
      "roles": [
        "Owner",
        "DAF",
        "Manager",
        "Serveur",
        "Cuisinier",
        "Ménage"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "3 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "connexion"
      ],
      "placeholder": false,
      "content": "Chaque rôle dispose d'un tableau de bord adapté à ses besoins — personne ne voit un écran surchargé d'informations qui ne le concernent pas.\n\n## Propriétaire (Owner)\n\nIdentique à celui du DAF, avec le titre « Propriétaire ». Accès à toutes les fonctionnalités, y compris la modification de l'établissement et les canaux de réservation.\n\n## DAF\n\n- **Bandeau d'approbation** : si des demandes sont en attente (création d'articles, d'employés...), un bandeau orange avec badge animé apparaît en haut — un clic mène directement aux approbations.\n- **Chambres** : disponibles, occupées, taux d'occupation.\n- **Réservations** : les plus récentes, avec statut.\n- **Commandes** : statistiques du jour, de la semaine, du mois.\n- **Indicateurs financiers** : flux de paiement, mouvements de stock, statut des chambres.\n- **Factures** : dernières factures et montants en attente.\n- **Graphiques** : occupation, stock, commandes par serveur, flux de paiement.\n\n## Manager\n\nChambres, réservations, commandes, alertes de stock bas, et les mêmes graphiques que le DAF (sans la vue financière consolidée).\n\n## Serveur\n\n- **État des chambres** : vue rapide (libres, occupées, nettoyage).\n- **Mes commandes** : uniquement les vôtres, par jour/semaine/mois.\n- **Commandes globales** : vue d'ensemble de l'établissement.\n\n## Cuisinier\n\nCommandes en attente, en préparation, prêtes — et un résumé du jour.\n\n## Ménage\n\nChambres à nettoyer, nettoyages en cours, chambres nettoyées aujourd'hui, avec accès rapide à la liste complète."
    },
    {
      "id": "onboarding",
      "url": "https://teranga-pms.jdidit.cloud/documentation/onboarding/",
      "title": "Premiers pas : l'onboarding guidé",
      "summary": "L'assistant en 6 étapes qui configure votre établissement au premier accès.",
      "keywords": [
        "onboarding",
        "premiers pas",
        "configuration initiale"
      ],
      "category": "Premiers pas",
      "modules": [
        "Onboarding guidé"
      ],
      "metiers": [],
      "roles": [
        "Owner"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "connexion",
        "gestion-utilisateurs"
      ],
      "placeholder": false,
      "content": "À la première connexion d'un nouveau tenant, un assistant guide le propriétaire en **6 étapes obligatoires** avant l'accès au dashboard.\n\n## Onboarding tenant (Phase A) — `/onboarding/...`\n\n1. **Établissement** — Nom, adresse, ville, pays, téléphone, email, devise, fuseau, classement étoiles. Crée l'établissement et inscrit le propriétaire comme `OWNER`.\n2. **Points de vente** (optionnel) — Restaurant, bar, piscine, room service, boutique, spa…\n3. **Chambres** — Au choix :\n   - **Modèle prédéfini** : 10 templates disponibles (maison d'hôtes, auberge, petit hôtel, hôtel boutique, hôtel d'affaires, hôtel moyen, grand hôtel, resort/lodge, motel, résidence). Crée les chambres en lot avec numérotation automatique (101, 102…).\n   - **Saisie manuelle** : ligne par ligne (numéro, type, prix/nuit, capacité).\n4. **Équipe** — Création des premiers comptes employés avec un **mot de passe temporaire généré** (copiable, regénérable). L'admin communique manuellement ce mot de passe à chaque employé. Les comptes sont flagués pour forcer le changement de mot de passe au premier login.\n5. **Paiements** (optionnel) — Cocher les méthodes acceptées : Espèces, Carte, Virement, Mobile Money (Orange/Wave/Free), Moov Money, Mixx by YAS, FedaPay.\n6. **Terminé** — Choix : démarrer directement OU **ajouter des données de démo** (5 clients fictifs, 4 réservations, 1 dépense — tous tagués `[DÉMO]`).\n\nL'état est stocké dans `Tenant.settings.onboarding`. L'utilisateur peut quitter et reprendre — il revient toujours à l'étape courante. **Aucun accès au reste de la plateforme tant que l'étape `done` n'est pas atteinte** (middleware `requireOnboardingCompleted`).\n\n## Onboarding utilisateur (Phase B) — premier login de chaque employé\n\nÀ chaque premier login d'un utilisateur invité, il enchaîne :\n\n1. **Changement de mot de passe** (bloquant) — Min 8 caractères, confirmation. Désactive le flag `mustChangePassword`.\n2. **Acceptation CGU** (bloquant) — Lecture intégrale puis case à cocher. Voir `docs/CGU.md`.\n3. **Acceptation RGPD** (bloquant) — Politique de protection des données en 8 points. Voir `docs/RGPD.md`.\n4. **Profil utilisateur** (skippable) — Téléphone, URL de photo, langue préférée (FR/EN/AR).\n5. **Bandeau cookies** (sur dashboard) — 3 choix : `Tout accepter` / `Essentiels uniquement` / `Refuser`. Disparaît après choix, persisté côté serveur (`User.cookieConsent`).\n\n## Tour produit\n\nAu premier passage sur le dashboard, un **popover en bas à droite** présente 3-4 fonctionnalités clés adaptées au rôle :\n\n- **OWNER** : Tableau de bord, Établissements, Chambres, Utilisateurs\n- **DAF** : Tableau de bord, Rapports, Décaissements\n- **MANAGER** : Réservations, Ménage, Approbations\n- **CLEANER** : Ménage, Badgeuse, Mes congés\n- **EMPLOYEE** : Badgeuse, Mes congés\n\nDismissible en un clic, mémorisé dans `localStorage` — n'est jamais re-présenté pour le même navigateur.\n\n## Suppression des données de démo\n\nSi vous avez choisi de générer des données de démo, un panneau **« Données de démonstration »** apparaît dans `/dashboard/settings` (visible uniquement quand des données démo existent). Le bouton **« Supprimer les données de démo »** efface tous les clients `[DÉMO]`, leurs réservations, factures, paiements et dépenses associées.\n\n> **⚠️ Important** : les textes CGU et RGPD sont des **placeholders**. Avant exploitation réelle, faites-les valider par un juriste/DPO et remplacez :\n> - `docs/CGU.md` et `frontend/src/app/user-onboarding/terms/page.tsx` (constante `CGU_TEXT`)\n> - `docs/RGPD.md` et `frontend/src/app/user-onboarding/rgpd/page.tsx` (constante `RGPD_TEXT`)"
    },
    {
      "id": "gestion-menu",
      "url": "https://teranga-pms.jdidit.cloud/documentation/gestion-menu/",
      "title": "Gérer le menu (Manager)",
      "summary": "Créer, organiser et faire approuver les articles du menu — catégories, prix, stock.",
      "keywords": [
        "menu",
        "articles",
        "catégories",
        "manager",
        "approbation"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Composition d'articles",
        "Points de vente (PdV)"
      ],
      "metiers": [],
      "roles": [
        "Manager",
        "DAF"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "connexion"
      ],
      "placeholder": false,
      "content": "Le Manager est responsable de la création des éléments du menu. Les articles sont organisés en **catégories dynamiques** créées par l'utilisateur (par défaut : Restaurant, Boissons, Loisirs, Location — vous pouvez en ajouter autant que nécessaire en ligne pendant la création d'un article).\n\n## Créer un article\n\n1. Allez dans **Menu & Articles** dans la barre latérale\n2. Cliquez sur le bouton **+ Article** en haut à droite\n3. Remplissez le formulaire :\n\n| Champ | Obligatoire | Description |\n|-------|:-----------:|-------------|\n| **Catégorie** | Oui | Sélectionnez une catégorie existante ou cliquez sur **+** pour en créer une nouvelle. La nouvelle catégorie apparaît immédiatement dans le POS web et dans les onglets de l'app mobile. |\n| **Nom** | Oui | Nom du plat ou de la boisson (ex : \"Poulet braisé\") |\n| **Prix de vente** | Oui | Prix en FCFA |\n| **Photo** | Non | Cliquez sur la zone d'upload pour ajouter une image depuis votre appareil (JPG, PNG ou WebP, max 5 Mo) |\n| **Description** | Non | Description visible par le serveur sur l'app mobile |\n| **Unité** | Non | Plat, Verre, Bouteille, Canette, etc. |\n| **SKU** | Non | Code interne optionnel |\n| **Prix d'achat** | Non | Pour le calcul des marges |\n\n4. La section **Stock & inventaire** est optionnelle. Pour les plats préparés, vous n'avez pas besoin de renseigner le stock.\n5. Cliquez sur **Créer l'article**\n\n**Important** : Les articles créés par un Manager sont en statut **\"En attente d'approbation\"** jusqu'à validation par le DAF. Ils n'apparaîtront pas dans le menu du serveur tant qu'ils ne sont pas approuvés.\n\n## Comprendre les erreurs\n\nLe formulaire affiche des messages d'erreur clairs sous chaque champ :\n- *\"Le nom de l'article est requis\"* → Saisissez un nom\n- *\"Le prix de vente est requis et doit être positif\"* → Entrez un prix valide\n- *\"Veuillez sélectionner une catégorie\"* → Choisissez une catégorie existante ou créez-en une via le bouton **+**\n- *\"L'image ne doit pas dépasser 5 Mo\"* → Réduisez la taille de votre photo\n\n## Voir le statut d'un article\n\nDans la liste des articles :\n- Badge **\"Validé\"** (vert) : l'article est actif et visible par les serveurs\n- Badge **\"En attente\"** (orange) : l'article attend la validation du DAF\n- Les articles en attente apparaissent en grisé\n\n## Filtrer les articles\n\nUtilisez les filtres en haut de la liste :\n- **Recherche** : tapez un nom ou un SKU\n- **Catégorie** : filtrez par Restaurant, Boissons ou autre"
    },
    {
      "id": "approbations-daf",
      "url": "https://teranga-pms.jdidit.cloud/documentation/approbations-daf/",
      "title": "Approuver les demandes (DAF)",
      "summary": "Le circuit d'approbation DAF pour les créations d'articles, d'employés et autres demandes en attente.",
      "keywords": [
        "approbation",
        "DAF",
        "workflow"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Utilisateurs & RBAC"
      ],
      "metiers": [],
      "roles": [
        "DAF"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "gestion-menu"
      ],
      "placeholder": false,
      "content": "Le DAF valide les demandes soumises par le Manager et les autres rôles.\n\n## Voir les demandes en attente\n\n1. Un **bandeau d'alerte** sur le dashboard indique le nombre de demandes en attente. Cliquez dessus.\n2. Vous pouvez aussi accéder à la page via **Approbations** dans la barre latérale.\n\n## Types de demandes\n\n| Type | Description |\n|------|-------------|\n| **Création article menu** | Un Manager a créé un nouvel article. Vous voyez le nom et le prix proposé. |\n| **Création employé** | Un Manager a créé un nouveau collaborateur. Vous voyez son nom, e-mail et rôle. |\n| **Création de chambre** | Un Manager a ajouté une chambre. |\n| **Mouvement de stock** | Un mouvement de stock nécessite votre validation. |\n| **Modification réservation** | Un Manager a modifié les dates d'une réservation. |\n\n## Approuver ou rejeter\n\n1. Pour **approuver** : cliquez sur l'icône vert (coche) à droite de la demande\n2. Pour **rejeter** : cliquez sur l'icône rouge (croix). Une fenêtre vous demande un motif optionnel.\n\nLorsqu'un article est approuvé, il devient immédiatement visible dans le menu des serveurs.\n\n## Filtrer les demandes\n\n- **Statut** : En attente, Approuvées, Rejetées\n- **Type** : filtrer par type de demande (article, employé, chambre, etc.)"
    },
    {
      "id": "prise-de-commandes",
      "url": "https://teranga-pms.jdidit.cloud/documentation/prise-de-commandes/",
      "title": "Prendre une commande (Serveur)",
      "summary": "Le flux de prise de commande côté serveur, du POS à la cuisine.",
      "keywords": [
        "commande",
        "serveur",
        "POS"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Restaurant & Bar (POS)"
      ],
      "metiers": [
        "Restaurant"
      ],
      "roles": [
        "Serveur"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "cuisine"
      ],
      "placeholder": false,
      "content": "Le serveur prend les commandes des clients et génère les QR codes de paiement.\n\n## Sur le web\n\n1. Allez dans **Commandes** dans la barre latérale\n2. Cliquez sur **+ Nouvelle commande**\n3. Remplissez le formulaire :\n   - **N° Table** (optionnel) : numéro ou nom de la table\n   - **Moyen de paiement** : Flooz (Moov Money), Yas (MTN), FedaPay, Espèces, Carte, etc.\n   - **Articles** : sélectionnez les articles dans la liste déroulante. Seuls les articles des catégories Restaurant et Boissons sont proposés. Ajustez la quantité. Cliquez sur *\"+ Ajouter un article\"* pour en ajouter d'autres.\n   - **Notes** (optionnel) : instructions spéciales\n   - **Date de l'opération** (optionnel) : permet de saisir aujourd'hui une vente effectuée hier ou avant-hier. Laissez vide pour utiliser la date du jour. Limite : 15 jours dans le passé (les rôles Owner/DAF/Manager peuvent dépasser).\n4. Cliquez sur **Créer la commande**\n5. Un **QR code de paiement** s'affiche automatiquement. Montrez-le au client pour qu'il scanne avec son application Flooz ou Yas.\n6. Si **FedaPay** est sélectionné : un bouton et un lien vers la gateway FedaPay s'affichent pour rediriger le client vers la page de paiement.\n\n## Sur l'application mobile\n\n1. Depuis le dashboard, appuyez sur le bouton **\"Accéder au menu\"**\n2. Le menu s'affiche avec deux onglets : **Restaurant** et **Boissons**\n3. Chaque article est présenté sous forme de carte avec :\n   - Photo du plat/boisson\n   - Nom\n   - Prix en FCFA\n   - Description\n4. Appuyez sur un article pour l'ajouter à la commande\n5. Sélectionnez le moyen de paiement (Flooz ou Yas)\n6. Validez la commande\n7. Le **QR code** s'affiche. Montrez-le au client.\n\n## Afficher le QR code d'une commande existante\n\nDans la liste des commandes, cliquez sur l'icône QR code (colonne \"Paiement\") pour réafficher le QR code d'une commande déjà créée.\n\n## Filtrer « mes commandes »\n\nDans la page **Commandes**, activez la case **Mes commandes** pour ne voir que les commandes qui vous concernent. Cette vue inclut :\n\n- Les commandes que **vous avez saisies**\n- Les commandes **saisies par le POS à votre nom** (serveur attribué)\n\nLes Manager, DAF, Owner et SuperAdmin disposent en plus d'un sélecteur **Serveur** pour filtrer les commandes d'un collaborateur spécifique.\n\n## Suivi des commandes\n\n- **En attente** : la commande vient d'être créée\n- **En préparation** : la cuisine a pris en charge la commande\n- **Prête** : la commande est prête à être servie\n- **Servie** : le serveur peut marquer la commande comme servie"
    },
    {
      "id": "cuisine",
      "url": "https://teranga-pms.jdidit.cloud/documentation/cuisine/",
      "title": "Suivre les commandes en cuisine",
      "summary": "L'interface cuisinier : statuts des commandes et notification du serveur.",
      "keywords": [
        "cuisine",
        "cuisinier",
        "commande"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Cuisine temps réel"
      ],
      "metiers": [
        "Restaurant"
      ],
      "roles": [
        "Cuisinier"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "prise-de-commandes"
      ],
      "placeholder": false,
      "content": "Le cuisinier gère la préparation des commandes.\n\n## Voir les commandes\n\n1. Allez dans **Cuisine** (web) ou ouvrez l'onglet Cuisine (mobile)\n2. Les commandes apparaissent par statut :\n   - **En attente** : nouvelles commandes à préparer\n   - **En préparation** : commandes en cours de préparation\n   - **Prêtes** : commandes terminées, en attente d'être servies\n\n## Changer le statut d'une commande\n\n- Cliquez sur **\"En préparation\"** pour signaler que vous commencez à préparer\n- Cliquez sur **\"Prête\"** pour signaler que la commande est terminée\n\nLe serveur sera notifié que la commande est prête à être servie."
    },
    {
      "id": "chambres-reservations",
      "url": "https://teranga-pms.jdidit.cloud/documentation/chambres-reservations/",
      "title": "Chambres et réservations",
      "summary": "Statuts de chambre, création et suivi des réservations, anti-double booking.",
      "keywords": [
        "chambres",
        "réservations",
        "hôtel"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Chambres & Statuts",
        "Réservations"
      ],
      "metiers": [
        "Hôtel"
      ],
      "roles": [
        "Manager",
        "DAF",
        "Owner"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "modification-reservation",
        "sync-ical"
      ],
      "placeholder": false,
      "content": "## Voir les chambres (DAF, Manager, Ménage)\n\n1. Allez dans **Chambres** dans la barre latérale\n2. Chaque chambre affiche son numéro et son statut :\n   - **Disponible** (vert) : prête à accueillir un client\n   - **Occupée** (rouge) : un client est en séjour\n   - **Nettoyage** (bleu) : en cours de nettoyage\n   - **Maintenance** (orange) : hors service temporaire\n\n## Créer une réservation (DAF, Manager)\n\n1. Allez dans **Réservations**\n2. Cliquez sur **+ Nouvelle réservation**\n3. Renseignez :\n   - Chambre (avec prix par nuit affiché)\n   - Nom du client, email, téléphone\n   - Dates d'arrivée et de départ\n   - Nombre de personnes, source\n   - **Moyen de paiement** : Espèces, Flooz, Yas, FedaPay, Carte, Mobile Money, Virement\n4. Cliquez sur **Créer la réservation**\n5. Une **facture est automatiquement générée** (FAC-YYYYMMDD-NNNN)\n6. Le **QR code de paiement** s'affiche automatiquement — montrez-le au client si paiement mobile\n7. Si **FedaPay** est sélectionné : un **bouton \"Payer avec FedaPay\"** et un **lien cliquable** vers la gateway de paiement s'affichent sous le QR code\n\n## Paiement de la réservation\n\nLa colonne **Paiement** dans la liste des réservations affiche :\n- Le **statut** de la facture (En attente / Payée)\n- Un bouton **QR code** pour afficher ou réafficher le QR code de paiement\n- Un bouton **téléchargement** pour obtenir le reçu PDF\n\n## Modifier une réservation (DAF, Owner — direct)\n\nUn DAF ou un Owner peut modifier directement une réservation existante :\n\n1. Dans la liste des réservations, cliquez sur l'icône **Modifier**\n2. Le modal de modification s'ouvre avec les champs modifiables :\n   - **Chambre** (avec prix par nuit mis à jour)\n   - **Dates** (arrivée / départ)\n   - **Nombre de personnes**\n   - **Source** (DIRECT, AIRBNB, BOOKING, etc.)\n   - **Règle de remise** (optionnel — les remises automatiques sont recalculées)\n3. Cliquez sur **Enregistrer**\n\nLe montant de la réservation est **recalculé automatiquement** (nuits × prix/nuit − remise). La facture associée est mise à jour immédiatement.\n\n> Si la facture est déjà **Payée**, la modification est bloquée — annulez d'abord la réservation ou créez-en une nouvelle.\n\n## Modifier une réservation (Manager — via approbation)\n\nUn Manager peut soumettre une modification de dates : la demande est envoyée au DAF pour approbation. Les autres champs (chambre, remise) ne sont modifiables que par le DAF ou l'Owner.\n\n## Check-in / Check-out\n\n- **Check-in** : confirmez l'arrivée du client. La chambre passe en statut \"Occupée\"\n- **Check-out** : confirmez le départ. La chambre passe automatiquement en statut \"Nettoyage\"\n\n> Le serveur voit l'état des chambres sur son dashboard mais n'a pas accès aux écrans Chambres et Réservations."
    },
    {
      "id": "factures-paiements",
      "url": "https://teranga-pms.jdidit.cloud/documentation/factures-paiements/",
      "title": "Factures et paiements",
      "summary": "Cycle de facturation et méthodes de paiement acceptées (espèces, carte, Mobile Money).",
      "keywords": [
        "factures",
        "paiements",
        "Mobile Money"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Facturation",
        "Paiements multi-méthodes"
      ],
      "metiers": [],
      "roles": [],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "recus-factures-pdf"
      ],
      "placeholder": false,
      "content": "## Voir les factures\n\n1. Allez dans **Factures** dans la barre latérale\n2. Les factures sont numérotées automatiquement : `FAC-YYYYMMDD-NNNN`\n3. Statuts possibles :\n   - **Émise** : facture créée, en attente de paiement\n   - **Payée** : paiement reçu\n   - **Annulée** : facture annulée\n   - **En retard** : paiement non reçu après la date limite\n\n## Factures automatiques\n\nChaque **commande** et chaque **réservation** créée génère automatiquement une facture. Vous n'avez pas besoin de créer manuellement une facture pour ces opérations.\n\n## Paiements\n\n1. Allez dans **Paiements**\n2. Vous pouvez enregistrer un paiement reçu et l'associer à une facture\n3. Les moyens de paiement : Espèces, Carte, Flooz, Yas, Mobile Money, Virement"
    },
    {
      "id": "recus-factures-pdf",
      "url": "https://teranga-pms.jdidit.cloud/documentation/recus-factures-pdf/",
      "title": "Télécharger reçus et factures PDF",
      "summary": "Comment retrouver et télécharger un reçu ou une facture au format PDF.",
      "keywords": [
        "reçu",
        "facture PDF",
        "téléchargement"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Facturation"
      ],
      "metiers": [],
      "roles": [
        "Serveur",
        "Manager",
        "DAF",
        "Owner"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "factures-paiements"
      ],
      "placeholder": false,
      "content": "Les rôles **Serveur**, **Manager**, **DAF**, **Owner** et **Super Admin** peuvent télécharger les documents PDF.\n\n## Télécharger un reçu (commandes)\n\n1. Allez dans **Commandes**\n2. Sur chaque ligne de commande, cliquez sur l'icône de téléchargement (flèche vers le bas) dans la colonne \"Paiement\"\n3. Un fichier PDF est téléchargé au format **ticket de caisse** (80mm)\n\nLe reçu contient :\n- En-tête : nom de l'établissement, adresse, téléphone, email\n- Numéro de commande et date\n- Numéro de table et nom du serveur\n- Liste des articles avec quantités et prix\n- Total en FCFA\n- Moyen de paiement\n- QR code de vérification\n- Message de remerciement\n\n## Télécharger un reçu (réservations)\n\n1. Allez dans **Réservations**\n2. Sur chaque ligne, cliquez sur l'icône de téléchargement dans la colonne \"Paiement\"\n3. Un fichier PDF est téléchargé au format **ticket de caisse** (80mm)\n\nLe reçu contient :\n- En-tête de l'établissement\n- Numéro de facture\n- Nom du client, téléphone\n- Chambre (numéro et type)\n- Dates d'arrivée et de départ\n- Détail : nombre de nuits × prix par nuit\n- Total en FCFA\n- Statut de paiement\n- QR code de vérification\n\n## Télécharger une facture PDF\n\n1. Allez dans **Factures**\n2. Sur chaque facture, cliquez sur l'icône de téléchargement (flèche vers le bas)\n3. Un fichier PDF est téléchargé au format **A4**\n\nLa facture contient :\n- En-tête de l'établissement\n- Numéro de facture, date, statut\n- **Bloc Client** : nom, email, téléphone (si réservation liée)\n- **Bloc Séjour** : chambre, dates d'arrivée/départ, nombre d'invités, source (si réservation liée)\n- Numéro de commande, table, serveur, moyen de paiement\n- Tableau détaillé des articles (description, quantité, prix unitaire, total)\n- Sous-total, taxe et total en FCFA\n- QR code de vérification"
    },
    {
      "id": "menage",
      "url": "https://teranga-pms.jdidit.cloud/documentation/menage/",
      "title": "Ménage et nettoyage des chambres",
      "summary": "Pointage du nettoyage par chambre et suivi des statuts de ménage.",
      "keywords": [
        "ménage",
        "nettoyage",
        "chambres"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Ménage & Pointage"
      ],
      "metiers": [
        "Hôtel"
      ],
      "roles": [
        "Ménage"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "chambres-reservations"
      ],
      "placeholder": false,
      "content": "## Démarrer un nettoyage depuis une notification\n\nLorsqu'un client quitte sa chambre (check-out), l'agent de ménage reçoit une **notification automatique**. Pour commencer le nettoyage :\n\n1. Cliquez sur la notification dans la barre latérale (icône cloche)\n2. La page Ménage s'ouvre automatiquement avec la **chambre pré-sélectionnée**\n3. Cliquez sur **Commencer** pour démarrer le nettoyage\n\n## Pointer un nettoyage manuellement\n\n1. Allez dans **Ménage** (web) ou ouvrez l'onglet Ménage (mobile)\n2. Cliquez sur **Pointer (début)**\n3. Sélectionnez la chambre dans la liste (les chambres \"Disponible\" et \"Nettoyage\" sont affichées)\n4. Ajoutez des notes si nécessaire (ex : nettoyage en profondeur)\n5. Cliquez sur **Commencer**\n\n## Terminer un nettoyage\n\n1. Dans la section **Sessions en cours**, trouvez votre session\n2. Cliquez sur **Pointer (fin)**\n3. La chambre repasse automatiquement en statut **\"Disponible\"**\n4. Une notification est envoyée au Manager/DAF\n\n## Suivi (web)\n\n- **Sessions en cours** : cartes avec le numéro de chambre, l'agent, l'heure de début\n- **Historique** : tableau avec chambre, agent, début, fin, durée, statut\n\n## Suivi (mobile)\n\nLe dashboard du ménage affiche :\n- Chambres à nettoyer\n- Sessions du jour\n- Durée moyenne de nettoyage\n- Résumé de l'état des chambres"
    },
    {
      "id": "notifications",
      "url": "https://teranga-pms.jdidit.cloud/documentation/notifications/",
      "title": "Notifications en temps réel",
      "summary": "Comment fonctionnent les notifications par rôle et par événement.",
      "keywords": [
        "notifications",
        "temps réel",
        "SSE"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Notifications temps réel"
      ],
      "metiers": [],
      "roles": [],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "menage"
      ],
      "placeholder": false,
      "content": "Le système envoie des notifications en temps réel selon votre rôle. Elles sont visibles via l'icône **cloche** dans la barre latérale.\n\n## Types de notifications\n\n| Notification | Destinataires | Action au clic |\n|-------------|---------------|----------------|\n| **Check-out chambre** | Ménage | Ouvre la page Ménage avec la chambre pré-sélectionnée |\n| **Nettoyage terminé** | Manager, DAF | Ouvre la page Ménage |\n| **Nouvelle commande** | Cuisinier | Ouvre la page Cuisine |\n| **Commande prête** | Serveur | Ouvre la page Commandes |\n| **Approbation requise** | DAF, Owner | Ouvre la page Approbations |\n| **Résultat approbation** | Demandeur | Ouvre la page Approbations |\n| **Alerte stock** | Manager, DAF | Ouvre la page Alertes stock |\n| **Synchronisation canal** | Manager, DAF, Owner | Ouvre la page Canaux |\n\n## Gérer les notifications\n\n- **Marquer comme lue** : cliquez sur la notification\n- **Tout marquer comme lu** : cliquez sur \"Tout lire\" en haut du panneau\n- **Indicateur** : un badge rouge sur la cloche indique le nombre de notifications non lues"
    },
    {
      "id": "profil-utilisateur",
      "url": "https://teranga-pms.jdidit.cloud/documentation/profil-utilisateur/",
      "title": "Modifier votre profil",
      "summary": "Mettre à jour vos informations personnelles et préférences de compte.",
      "keywords": [
        "profil",
        "compte",
        "préférences"
      ],
      "category": "Guide utilisateur",
      "modules": [],
      "metiers": [],
      "roles": [],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "connexion"
      ],
      "placeholder": false,
      "content": "## Modifier ses informations\n\n1. Cliquez sur **Profil** dans la barre latérale\n2. Modifiez votre nom, prénom ou e-mail\n3. Sauvegardez\n\n## Changer son mot de passe\n\n1. Allez dans **Profil**\n2. Renseignez l'ancien mot de passe, puis le nouveau (2 fois)\n3. Sauvegardez"
    },
    {
      "id": "application-mobile",
      "url": "https://teranga-pms.jdidit.cloud/documentation/application-mobile/",
      "title": "Application mobile Android",
      "summary": "Fonctionnement de l'application Android native, y compris hors ligne.",
      "keywords": [
        "application mobile",
        "Android",
        "hors ligne"
      ],
      "category": "Guide utilisateur",
      "modules": [],
      "metiers": [],
      "roles": [],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "mode-hors-ligne"
      ],
      "placeholder": false,
      "content": "## Installation\n\nL'application est disponible pour les appareils Android. Contactez votre administrateur pour obtenir le fichier APK ou l'accès via le Play Store interne.\n\n## Navigation\n\nLa barre de navigation en bas de l'écran affiche les sections accessibles selon votre rôle :\n\n| Rôle | Onglets visibles |\n|------|-----------------|\n| **Serveur** | Accueil, Commandes, POS |\n| **Cuisinier** | Accueil, Cuisine |\n| **Ménage** | Accueil, Ménage |\n| **Manager** | Accueil, Chambres, Réservations, Commandes, Stock, Approbations, POS |\n| **DAF** | Accueil, Chambres, Réservations, Commandes, Stock, Approbations |\n\n## Fonctionnalités clés par rôle\n\n**Serveur :**\n- Dashboard avec bouton \"Accéder au menu\" rouge\n- Menu en cartes avec onglets Restaurant/Boissons\n- Prise de commande en un clic sur l'article\n- QR code de paiement automatique\n- Stats personnelles (mes commandes, mes revenus du jour)\n- Vue de l'état des chambres\n\n**Cuisinier :**\n- Vue des commandes en attente, en préparation, prêtes\n- Changement de statut en un clic\n\n**Manager / DAF :**\n- Création de réservation avec sélection du moyen de paiement\n- QR code de paiement automatique après création\n- Bouton QR code sur chaque réservation pour réafficher le QR code\n- Statut de paiement visible (En attente / Payée)\n- Simulation de paiement (test)\n\n**Ménage :**\n- Clock-in / Clock-out sur les chambres\n- Suivi des sessions du jour\n\n## Connexion au serveur\n\nL'application se connecte au serveur backend via l'URL configurée. Si vous rencontrez des problèmes de connexion :\n1. Vérifiez que vous êtes connecté au même réseau que le serveur\n2. Vérifiez que l'URL du serveur est correcte dans les paramètres de l'application\n3. Vérifiez que votre compte est actif (approuvé par le DAF)"
    },
    {
      "id": "clients-fidelite-remises",
      "url": "https://teranga-pms.jdidit.cloud/documentation/clients-fidelite-remises/",
      "title": "Clients, fidélité et remises",
      "summary": "Fiche client consolidée, niveau de fidélité automatique, remises séjour et remises manuelles.",
      "keywords": [
        "CRM",
        "fidélité",
        "remises",
        "clients"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "CRM Clients & Fidélité",
        "Remises & Promotions"
      ],
      "metiers": [],
      "roles": [
        "Owner",
        "DAF",
        "Manager"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "chambres-reservations"
      ],
      "placeholder": false,
      "content": "Page **Clients** (OWNER, DAF, MANAGER) — barre latérale.\n\n- Liste consolidée des clients (réservations + commandes + paiements FedaPay)\n- Recherche par nom, email, téléphone\n- Tier `FIDELE` après **5 réservations payées**, sinon `NEW`\n- Fiche détaillée avec stats, historique des réservations et factures\n- Téléchargement d'une **carte de fidélité PDF** (badge or pour les FIDELE)\n- Liaison automatique des paiements FedaPay (web, mobile, channel manager) au client correspondant\n\nPage **Remises** (OWNER, DAF, MANAGER) — barre latérale.\n\n## Remises automatiques sur les réservations (intégrées)\n\n| Nuits | Remise |\n|-------|--------|\n| 1-2 | 0 % |\n| 3-5 | 10 % |\n| 6 | 20 % |\n| > 6 | 25 % |\n\nAppliquées automatiquement à la création d'une réservation. Si plusieurs règles sont éligibles, la **plus avantageuse** est retenue.\n\n## Remises manuelles sur les commandes\n\nLe OWNER crée des règles (PERCENTAGE ou FIXED) avec condition de panier minimum. Ces règles apparaissent dans un sélecteur sur la page **Commandes** et sur le **POS web** ; le serveur en applique une à la création."
    },
    {
      "id": "pos-attribution-serveur",
      "url": "https://teranga-pms.jdidit.cloud/documentation/pos-attribution-serveur/",
      "title": "Point de vente : attribution au serveur",
      "summary": "Comment une commande POS est rattachée à un serveur et à une date d'opération.",
      "keywords": [
        "POS",
        "attribution",
        "serveur",
        "date d'opération"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Points de vente (PdV)",
        "Restaurant & Bar (POS)"
      ],
      "metiers": [
        "Restaurant"
      ],
      "roles": [
        "Serveur",
        "POS",
        "Manager"
      ],
      "difficulty": "Intermédiaire",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "prise-de-commandes"
      ],
      "placeholder": false,
      "content": "## Le rôle POS en bref\n\nLe rôle **POS** (caissier) gère la prise de commandes en caisse pour le compte des serveurs. Il a accès au module **Point de vente** (`/dashboard/pos` sur le web, écran équivalent sur mobile) avec une interface optimisée pour saisir rapidement des articles et encaisser.\n\n## Attribuer une commande à un serveur\n\nDepuis la page **Point de vente** (web) ou l'écran POS mobile :\n\n1. Ajoutez les articles dans le panier\n2. Dans le panneau de droite, sélectionnez le **Serveur attribué** dans la liste déroulante\n3. Choisissez le **Moyen de paiement** et, si nécessaire, la **Date de l'opération**\n4. Validez la commande\n\n**Conséquences de l'attribution :**\n\n- Le serveur attribué voit la commande dans sa liste **Commandes > Mes commandes** (web et mobile)\n- Le serveur peut également encaisser cette commande et afficher son QR code\n- Dans les **Rapports** (graphique « Performance par serveur », tableau et exports CSV), les revenus sont comptabilisés pour le serveur attribué, pas pour le compte POS\n\n> **Distinction technique** — `createdById` : qui a saisi la commande (audit, jamais modifié). `serverId` : à qui la commande est attribuée (pour le reporting et la visibilité). Les deux peuvent être la même personne (commande prise directement par le serveur) ou différentes (commande saisie par le POS en caisse).\n\n## Date d'opération rétroactive\n\nUn oubli de saisie la veille ? Le sélecteur **Date de l'opération** permet d'enregistrer aujourd'hui une commande effectuée un jour précédent.\n\n**Disponible dans :**\n\n- POS web (`/dashboard/pos`) — sélecteur datetime-local\n- Page Commandes (`/dashboard/orders`) — champ datetime-local dans le formulaire de création\n- App mobile Android — puces rapides : **Aujourd'hui / Hier / Avant-hier / Il y a 3j** (et **Il y a 14j** pour les rôles superviseurs)\n\n**Effet sur les données :**\n\n- La date est utilisée comme `issueDate` de la facture générée\n- Le paiement enregistré au même moment est daté au `paidAt` = date d'opération\n- Les rapports (ventes du jour, encaissement, tableau de bord) prennent en compte cette date, pas la date de création technique\n\n**Limites :**\n\n| Rôle | Plage autorisée |\n|------|-----------------|\n| Serveur, POS, Maître d'hôtel | Jusqu'à **15 jours dans le passé** |\n| Owner, DAF, Manager, SuperAdmin | Illimité (override superviseur) |\n\nUne opération datée au-delà de la limite retourne une erreur de validation côté API.\n\n---"
    },
    {
      "id": "mode-hors-ligne",
      "url": "https://teranga-pms.jdidit.cloud/documentation/mode-hors-ligne/",
      "title": "Travailler en mode hors ligne",
      "summary": "Comment la plateforme continue de fonctionner sans connexion internet.",
      "keywords": [
        "hors ligne",
        "offline-first",
        "synchronisation"
      ],
      "category": "Guide utilisateur",
      "modules": [],
      "metiers": [],
      "roles": [],
      "difficulty": "Intermédiaire",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "application-mobile"
      ],
      "placeholder": false,
      "content": "Teranga PMS fonctionne en **mode hors ligne** lorsque la connexion internet est coupée ou instable. Le comportement diffère légèrement entre le web (PWA) et l'application mobile Android.\n\n## Sur le web (PWA)\n\nUn **badge rouge « Hors ligne »** s'affiche dans la barre de navigation dès que la connexion est perdue. Ce badge indique le nombre d'opérations en attente de synchronisation.\n\n**Ce qui fonctionne hors ligne :**\n- Saisie de commandes depuis le **POS** (`/dashboard/pos`) — les commandes sont mises en file d'attente\n- Affichage des articles depuis le **cache local** (les articles sont mis en cache au dernier chargement réussi)\n\n**Ce qui nécessite une connexion :**\n- Paiements Mobile Money (Flooz/Yas) — désactivés automatiquement hors ligne\n- Réservations, rapports, paramètres\n\n**Page File hors ligne** (`/dashboard/offline-queue`) :\n1. Allez dans **File hors ligne** dans la barre de navigation (visible uniquement hors ligne ou si des opérations sont en attente)\n2. La page liste toutes les commandes en attente avec leur statut (en attente, en cours, échoué)\n3. Cliquez sur **Synchroniser maintenant** pour forcer la synchronisation dès la reconnexion\n4. Cliquez sur la corbeille pour supprimer une opération de la file\n\n**Synchronisation automatique :**\nDès que la connexion revient, la file est drainée automatiquement dans l'ordre FIFO. En cas d'erreur temporaire, le système réessaie avec un délai exponentiel (1s, 2s, 4s…). Chaque opération a un identifiant unique (UUID) pour éviter les doublons si la même commande est soumise deux fois.\n\n## Sur l'application mobile Android\n\nL'application utilise Room DB pour stocker les commandes hors ligne. Un écran **File hors ligne** (accessible depuis le menu principal) affiche :\n- Les opérations en attente avec leur montant et statut\n- Un bouton **Synchroniser** pour forcer l'envoi\n- Un indicateur de connexion (en ligne / hors ligne)\n\nLa synchronisation automatique s'exécute toutes les 15 minutes via WorkManager, même si l'application est fermée."
    },
    {
      "id": "bon-proprietaire",
      "url": "https://teranga-pms.jdidit.cloud/documentation/bon-proprietaire/",
      "title": "Le bon propriétaire (offres internes)",
      "summary": "Marquer une commande comme offerte par l'établissement, pour traçabilité dans les rapports.",
      "keywords": [
        "bon propriétaire",
        "offre interne",
        "traçabilité"
      ],
      "category": "Guide utilisateur",
      "modules": [],
      "metiers": [],
      "roles": [
        "Owner",
        "DAF",
        "Manager"
      ],
      "difficulty": "Intermédiaire",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "depenses-decaissements"
      ],
      "placeholder": false,
      "content": "Le flag **Bon propriétaire** (`isVoucher`) permet d'indiquer qu'une commande est offerte par le propriétaire de l'établissement (repas d'équipe, offre commerciale, etc.).\n\n## Modifier le flag sur une commande existante\n\n1. Allez dans **Commandes**\n2. Trouvez la commande concernée dans la liste\n3. Cliquez sur l'icône **Bon propriétaire** (drapeau) dans la colonne Actions\n4. Un modal de confirmation s'affiche : **Activer** ou **Désactiver** le flag\n5. Confirmez\n\n**Rôles autorisés :** OWNER, DAF, MANAGER.\n\n**Effets :**\n- La commande est identifiée comme \"bon propriétaire\" dans les exports et rapports\n- Une demande d'approbation (`ApprovalRequest`) est créée pour traçabilité"
    },
    {
      "id": "modification-reservation",
      "url": "https://teranga-pms.jdidit.cloud/documentation/modification-reservation/",
      "title": "Modifier une réservation",
      "summary": "Changer les dates, la chambre ou les détails d'une réservation existante.",
      "keywords": [
        "modification",
        "réservation",
        "recalcul"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Réservations"
      ],
      "metiers": [
        "Hôtel"
      ],
      "roles": [
        "Manager",
        "DAF",
        "Owner"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "chambres-reservations"
      ],
      "placeholder": false,
      "content": "Voir la section [7. Chambres et réservations → Modifier une réservation](#7-chambres-et-réservations) pour les étapes détaillées.\n\n**Résumé des droits :**\n\n| Champ modifiable | Owner / DAF | Manager |\n|-----------------|:-----------:|:-------:|\n| Chambre | Oui (direct) | Via approbation |\n| Dates | Oui (direct) | Via approbation |\n| Nombre de personnes | Oui (direct) | Via approbation |\n| Source | Oui (direct) | Non |\n| Règle de remise | Oui (direct) | Non |\n\nLa facture est recalculée et mise à jour automatiquement lors de toute modification directe."
    },
    {
      "id": "commande-qr-client",
      "url": "https://teranga-pms.jdidit.cloud/documentation/commande-qr-client/",
      "title": "Commande QR client — procédure complète",
      "summary": "Le parcours complet du client qui scanne un QR code et commande sans compte.",
      "keywords": [
        "QR code",
        "commande client",
        "sans compte"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Commande QR client"
      ],
      "metiers": [
        "Restaurant",
        "Hôtel"
      ],
      "roles": [],
      "difficulty": "Débutant",
      "estimatedTime": "4 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "prise-de-commandes"
      ],
      "placeholder": false,
      "content": "## Vue d'ensemble\n\nUn client présent dans le restaurant scanne le QR code de sa table avec son téléphone. Sans créer de compte, il consulte le menu, compose sa commande et la valide. La commande apparaît instantanément en cuisine et dans la liste des commandes du staff, exactement comme une commande saisie manuellement.\n\nLe staff (POS, Serveur) peut toujours créer des commandes manuellement depuis le POS — les deux modes coexistent.\n\n---\n\n## Étape 1 — Configurer le mode d'attribution\n\nAccessible depuis **Dashboard → Tables → \"Mode attribution\"** (MAITRE_HOTEL, MANAGER, DAF, OWNER).\n\nSur l'app Android : icône QR code dans la barre d'actions de l'écran Commandes.\n\n| Mode | Comportement |\n|------|-------------|\n| **Désactivé** | QR codes inactifs. Seul le staff crée les commandes. Page client affiche \"non disponible\". |\n| **Pré-assigné** | Le MAITRE_HOTEL assigne un serveur à chaque table en début de service. La commande QR est automatiquement attribuée à ce serveur. |\n| **Premier répondant** | Commande non assignée. Tous les serveurs reçoivent une notification. Le premier à appuyer sur \"Prendre en charge\" obtient la commande. |\n| **Charge automatique** | La commande est auto-assignée au serveur actif avec le moins de commandes ouvertes dans la journée. |\n| **Manuel** | Commande non assignée. Le MAITRE_HOTEL reçoit une notification et assigne depuis le dashboard. |\n\n---\n\n## Étape 2 — Configurer les tables (mode Pré-assigné uniquement)\n\n1. Aller sur **Dashboard → Tables**\n2. Appuyer sur l'icône **👤** de la table à configurer\n3. Sélectionner le serveur dans la liste → Confirmer\n\nLe badge vert **\"Prénom Nom\"** s'affiche sur la carte de la table. En fin de service, désassigner en choisissant \"— Aucun serveur —\".\n\n---\n\n## Étape 3 — Générer et afficher le QR code\n\n1. Sur **Dashboard → Tables**, appuyer sur l'icône **QR** de la table\n2. Le QR code s'affiche dans une modale avec l'URL complète\n3. Appuyer sur **\"Télécharger le QR (SVG)\"** pour l'imprimer ou l'afficher sur un support de table\n\nL'URL du QR a la forme : `https://[domaine]/menu/[token-unique]`\n\nLe token est stable — le QR imprimé reste valide même après des modifications de la table.\n\n---\n\n## Étape 4 — Parcours client (scan QR)\n\n1. Le client scanne le QR code avec l'appareil photo de son téléphone\n2. Le navigateur s'ouvre sur la page du menu (aucune app à installer)\n3. Le client navigue par catégories, ajoute des articles au panier (+/-)\n4. Il peut renseigner son prénom et des remarques (allergies, préférences) — optionnel\n5. Il appuie sur **\"Commander\"**\n6. Un écran de confirmation affiche le numéro de commande et le total\n7. Le client peut passer une nouvelle commande depuis la même page\n\n---\n\n## Étape 5 — Prise en charge par le staff\n\n### Mode Pré-assigné\nLe serveur assigné à la table reçoit la commande directement dans sa liste. Il la voit dès le prochain rafraîchissement (polling 5s) ou via SSE.\n\n### Mode Premier répondant\n- Notification push reçue par tous les serveurs actifs : **\"Commande QR — Table 5\"**\n- Sur le dashboard web ou l'app Android, la commande apparaît avec le bouton **\"Prendre en charge\"** (visible en vert sur les commandes sans serveur)\n- Le premier serveur qui appuie sur ce bouton est assigné à la commande\n- Les autres serveurs voient le bouton disparaître\n\n### Mode Charge automatique\nAucune action requise. Le système attribue automatiquement au serveur le moins chargé. La commande apparaît dans sa liste.\n\n### Mode Manuel\n- Le MAITRE_HOTEL reçoit une notification push\n- La commande apparaît sans serveur dans la liste des commandes\n- Le MAITRE_HOTEL assigne depuis le tableau de bord (web ou Android) en modifiant le statut ou en utilisant l'interface d'attribution\n\n---\n\n## Étape 6 — Traitement en cuisine\n\nLa commande QR arrive en cuisine **exactement comme une commande staff** :\n- Elle apparaît dans **Dashboard → Cuisine** avec le numéro de table\n- La cuisine prépare, passe en **En préparation** puis **Prêt**\n- Si le client a laissé un prénom ou des remarques, ils apparaissent dans le champ **Notes** de la commande (ex : `\"Client : Marie — sans piment\"`)\n\n---\n\n## Étape 7 — Encaissement\n\nUne fois le service terminé, le serveur encaisse la commande normalement depuis l'écran Commandes (bouton **Encaisser**) ou le POS. Le flux de paiement est identique à une commande créée manuellement.\n\n---\n\n## Vérification du mode actif\n\nLe mode d'attribution en cours est affiché dans le sous-titre de la page Tables :\n> *\"12 tables · Mode QR : Pré-assigné (début de service)\"*"
    },
    {
      "id": "points-de-vente-pdv",
      "url": "https://teranga-pms.jdidit.cloud/documentation/points-de-vente-pdv/",
      "title": "Comprendre les points de vente (PdV)",
      "summary": "Ce qu'est un point de vente dans Teranga et comment plusieurs PdV cohabitent dans un établissement.",
      "keywords": [
        "point de vente",
        "PdV",
        "multi-PdV"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Points de vente (PdV)"
      ],
      "metiers": [],
      "roles": [
        "Manager",
        "Owner"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "pos-attribution-serveur"
      ],
      "placeholder": false,
      "content": "> **Accès** : Menu latéral → **Points de vente** (Propriétaire / DAF)\n\nUn **point de vente** est une unité d'exploitation sous l'établissement : Restaurant, Bar, Piscine, Room service, Boutique, Spa, Autre. Chaque PdV possède son propre **menu/articles**, son **stock**, ses **commandes**, ses **recettes** (Z de caisse par PdV) et son **personnel affecté**.\n\n## Créer et gérer les PdV\n\n1. **Points de vente** → **« Nouveau point de vente »**\n2. Choisir l'**Établissement**, le **Nom** et le **Type**, puis **Créer**\n3. Sur chaque fiche : **modifier**, **désactiver/réactiver**, et bouton **Personnel** pour affecter des membres (rôle Manager, Maître d'hôtel, Serveur, Caisse, Cuisinier)\n\nLe nombre de PdV actifs est **plafonné par l'abonnement** (`maxPointsOfSale` : Basic 1, Pro 5, Enterprise illimité). Le compteur « X / Y » est affiché en haut de page ; le bouton **Nouveau** est désactivé à la limite. Désactiver un PdV libère un emplacement.\n\n## Sélecteur de PdV (barre latérale)\n\nLorsqu'un établissement a plusieurs PdV, un sélecteur apparaît dans la barre latérale. Le PdV choisi **filtre** : Commandes, Caisse, Cuisine, Menu & Articles, Tables, Rapports et Export. Choisir **« Tous les points de vente »** retire le filtre.\n\n## Menu, stock et recettes par PdV\n\n- **Article** : le formulaire de création comporte un champ **Point de vente** (pré-rempli avec le PdV courant). L'article et son **stock** sont alors propres à ce PdV. L'option **« Aucun (article commun) »** rend l'article visible uniquement en vue « Tous ».\n- **Recettes** : les rapports (journalier, plage, résumé) et l'export acceptent le filtre PdV — on obtient un Z de caisse par point de vente.\n- **Accès** : un serveur/caissier/cuisinier ne voit que les commandes des PdV auxquels il est affecté.\n\n## Migration des données existantes\n\nLors de l'activation de la fonctionnalité, un **« Point de vente principal »** est créé automatiquement par établissement, et toutes les données existantes (commandes, articles, catégories, tables) y sont rattachées — aucune perte d'historique."
    },
    {
      "id": "composition-articles-recettes",
      "url": "https://teranga-pms.jdidit.cloud/documentation/composition-articles-recettes/",
      "title": "Composer des articles (recettes)",
      "summary": "Définir des recettes qui décrémentent automatiquement leurs ingrédients à la vente.",
      "keywords": [
        "recettes",
        "composition d'articles",
        "stock décimal"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "Composition d'articles"
      ],
      "metiers": [
        "Restaurant"
      ],
      "roles": [
        "Manager"
      ],
      "difficulty": "Intermédiaire",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "gestion-menu"
      ],
      "placeholder": false,
      "content": "> **Accès** : Menu latéral → **Menu & Articles** (DAF / Manager)\n\nUn article **composé** (cocktail, plat cuisiné) déclare les **matières** qui le composent. À la vente, ce sont **ses composants** qui sont décrémentés du stock — jamais l'article composé.\n\n## Créer une recette\n\n1. Dans le formulaire d'article, cochez **« Cet article est une recette (composition) »**.\n2. Ajoutez chaque **composant** (matière du même point de vente) et sa **quantité** (décimale : ex. `0.05` L).\n3. Le **coût de revient** s'affiche en direct (Σ coût composant × quantité).\n4. Un article composé n'a pas de stock propre : son champ de suivi de stock est masqué.\n\n## Règles\n\n- **Stock décimal** : les quantités de stock et de recette acceptent les décimales (5 cl = `0.05` L sur une bouteille de `0.7` L).\n- **Matière première** : décochez **« Vendable »** pour qu'une matière (ex. rhum) reste en stock sans apparaître au menu/à la caisse.\n- **Un seul niveau** : un composant ne peut pas être lui-même une recette.\n- **Même point de vente** : les composants doivent appartenir au PdV de la recette.\n\n## À la vente\n\nVendre 2 cocktails « Mojito » (recette : 0,05 L de rhum) décrémente le **rhum** de 0,10 L et émet un mouvement `SALE` sur le rhum. Une **alerte de stock bas** peut se déclencher sur un composant. L'annulation de la commande restaure le stock des composants."
    },
    {
      "id": "sira-assistant",
      "url": "https://teranga-pms.jdidit.cloud/documentation/sira-assistant/",
      "title": "Utiliser Sira, l'assistant IA",
      "summary": "Ce que Sira peut faire aujourd'hui, comment lui poser une question, et pourquoi elle refuse parfois de répondre.",
      "keywords": [
        "Sira",
        "IA",
        "assistant",
        "intelligence artificielle",
        "base documentaire"
      ],
      "category": "Guide utilisateur",
      "modules": [
        "IA — Sira"
      ],
      "metiers": [],
      "roles": [
        "Owner",
        "DAF",
        "Manager"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "3 min",
      "version": "à partir de 2.72.0",
      "lastUpdated": "2026-08-06",
      "related": [
        "tableau-de-bord",
        "rapports-exports"
      ],
      "placeholder": false,
      "content": "Sira est l'assistant IA de Teranga, disponible en option selon votre plan. Elle répond à partir des données réelles de votre établissement — pas d'une base générique déconnectée de votre activité.\n\n## Ce que Sira peut faire\n\n- **Répondre à partir de vos données de gestion** : occupation, ventes, stock, chiffre d'affaires.\n- **Chercher dans vos propres documents** : si vous lui fournissez des contrats ou documents, elle peut y puiser sa réponse plutôt que de se limiter aux données de gestion.\n- **Lire les analyses du module Pilotage** (si actif) : tendances, prévisions, anomalies — Sira peut les commenter directement plutôt que de vous laisser les interpréter seul.\n- **Aller chercher l'information via des agents dédiés**, plutôt que de se limiter à une conversation statique.\n\n## Pourquoi Sira refuse parfois de répondre\n\nC'est un choix de conception assumé, pas une limitation cachée. Quand l'historique ou les données disponibles ne permettent pas de répondre correctement à une question — par exemple un délai fournisseur jamais observé, ou une tendance sur une période trop courte — Sira le dit explicitement et explique pourquoi, plutôt que de produire une réponse plausible mais inventée.\n\n**Ce que cela signifie pour vous :** si Sira répond avec un chiffre ou une tendance, vous pouvez vous appuyer dessus pour décider. Si elle dit qu'elle ne sait pas, c'est une information en soi — pas une erreur à contourner.\n\n## Comment lui poser une question\n\nSira est accessible directement depuis le tableau de bord. Posez votre question en langage naturel — pas besoin de formulation technique. Si votre question touche à un document que vous lui avez fourni, mentionnez-le pour qu'elle sache où chercher.\n\n## Limites actuelles\n\n- Aucun SDK ou API dédiée à Sira n'est publique pour l'instant ; elle s'utilise depuis l'interface Teranga.\n- Sira est disponible en option selon votre plan — contactez-nous pour les modalités."
    },
    {
      "id": "sync-ical",
      "url": "https://teranga-pms.jdidit.cloud/documentation/sync-ical/",
      "title": "Synchroniser votre calendrier (iCal)",
      "summary": "Connecter vos chambres à Booking.com, Airbnb et Expedia via iCal, dans les deux sens.",
      "keywords": [
        "iCal",
        "channel manager",
        "Booking",
        "Airbnb",
        "Expedia"
      ],
      "category": "Automatisations",
      "modules": [
        "Réservations"
      ],
      "metiers": [
        "Hôtel"
      ],
      "roles": [
        "Owner",
        "Manager"
      ],
      "difficulty": "Intermédiaire",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "chambres-reservations",
        "channel-manager-factures"
      ],
      "placeholder": false,
      "content": "La synchronisation iCal permet de connecter les chambres aux plateformes de réservation externes pour éviter les doubles réservations.\n\n## Rôles autorisés\n\nSeuls les comptes **Owner**, **DAF** et **Manager** ont accès à la page **Canaux**.\n\n## Connecter une chambre\n\n1. Allez dans **Canaux** dans la barre latérale\n2. Cliquez sur **Connecter un canal**\n3. Sélectionnez la chambre et la plateforme (Airbnb, Booking.com, Expedia)\n4. Cliquez sur **Connecter**\n\n## Exporter les disponibilités\n\n1. Sur la connexion créée, cliquez sur l'icône **Copier** pour copier l'URL d'export\n2. Dans la plateforme externe : collez cette URL dans la section \"Importer un calendrier\"\n3. La plateforme synchronisera automatiquement les dates bloquées\n\n## Importer les réservations externes\n\n1. Dans la plateforme externe, trouvez l'option \"Exporter le calendrier\"\n2. Copiez l'URL iCal fournie\n3. Dans le PMS : collez l'URL dans le champ **URL d'import** de la connexion\n4. Cliquez sur **Synchroniser maintenant** pour tester\n5. La synchronisation automatique s'exécute toutes les minutes par défaut (configurable : 1 min à 24h)\n\n## Gestion des conflits\n\n- Le PMS a **priorité** : une réservation externe en conflit est ignorée\n- Les conflits sont visibles dans l'historique de synchronisation\n- Les annulations sur la plateforme externe sont automatiquement détectées\n\n## Sécurité\n\n- Chaque URL d'export contient un **token unique** (non devinable)\n- Si compromis, le token peut être **régénéré** (l'ancienne URL cesse de fonctionner)\n- Les feeds ne contiennent aucune donnée client"
    },
    {
      "id": "channel-manager-factures",
      "url": "https://teranga-pms.jdidit.cloud/documentation/channel-manager-factures/",
      "title": "Channel Manager : factures automatiques",
      "summary": "Comment les réservations importées génèrent automatiquement facture, paiement et fiche client.",
      "keywords": [
        "channel manager",
        "facturation automatique",
        "backfill"
      ],
      "category": "Automatisations",
      "modules": [
        "Réservations",
        "Facturation"
      ],
      "metiers": [
        "Hôtel"
      ],
      "roles": [
        "Owner",
        "DAF"
      ],
      "difficulty": "Avancé",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "sync-ical"
      ],
      "placeholder": false,
      "content": "Depuis la correction du moteur de synchronisation, **toutes les réservations importées via les canaux** (Airbnb, Booking.com, Expedia, site WordPress) génèrent automatiquement :\n\n- Une **facture** (`FAC-YYYYMMDD-NNNN`, statut `PAID`)\n- Un **paiement** avec la méthode appropriée (`FEDAPAY` pour les réservations en ligne, `OTHER` pour les réservations iCal)\n- Une **fiche client** si l'email du voyageur est disponible\n\nCes montants sont donc comptabilisés dans le **chiffre d'affaires** de l'établissement et apparaissent dans les rapports PDF/CSV.\n\n## Backfill des réservations historiques\n\nSi des réservations channel manager antérieures n'ont pas de facture, un outil de backfill permet de les régénérer.\n\n**Via l'interface :** OWNER, DAF, SUPERADMIN — bouton **Régénérer les factures manquantes** dans la page Canaux.\n\n**Via la ligne de commande (sur le serveur) :**\n\n```bash\n# Voir les réservations sans facture (dry-run, sans modification)\nnpx tsx backend/scripts/backfill-channel-invoices.ts --dry-run --slug mon-hotel\n\n# Générer les factures manquantes\nnpx tsx backend/scripts/backfill-channel-invoices.ts --slug mon-hotel\n\n# Via Docker\ndocker compose exec backend npx tsx scripts/backfill-channel-invoices.ts --slug mon-hotel\n```"
    },
    {
      "id": "wordpress-fedapay",
      "url": "https://teranga-pms.jdidit.cloud/documentation/wordpress-fedapay/",
      "title": "Réservation en ligne via WordPress + FedaPay",
      "summary": "Configurer le plugin WordPress et le paiement en ligne FedaPay pour les réservations directes.",
      "keywords": [
        "WordPress",
        "FedaPay",
        "réservation en ligne",
        "plugin"
      ],
      "category": "Intégrations",
      "modules": [
        "Paiements multi-méthodes"
      ],
      "metiers": [
        "Hôtel"
      ],
      "roles": [
        "Owner"
      ],
      "difficulty": "Intermédiaire",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "config-fedapay"
      ],
      "placeholder": false,
      "content": "Teranga PMS fournit un plugin WordPress pour permettre aux clients de réserver et payer directement depuis votre site internet via **FedaPay** (Mobile Money, carte bancaire, etc.).\n\n## Prérequis\n\n- Un site WordPress (v5.0+)\n- Un compte FedaPay ([app.fedapay.com](https://app.fedapay.com))\n- Une clé API Teranga PMS (demandez au SuperAdmin)\n\n## Installation du plugin\n\n1. Copiez le dossier `wordpress/teranga-booking/` dans votre répertoire `wp-content/plugins/`\n2. Dans WordPress : **Extensions → Extensions installées → Activer** « Teranga Booking »\n3. Allez dans **Réglages → Teranga Booking**\n\n## Configuration\n\n| Champ | Description |\n|---|---|\n| URL API Teranga PMS | L'adresse de votre API (ex: `https://api.mon-hotel.teranga.app`) |\n| Clé API Teranga | Fournie par le SuperAdmin (format `tpms_...`) |\n| Clé publique FedaPay | Depuis votre dashboard FedaPay (`pk_live_...` ou `pk_sandbox_...`) |\n| Clé secrète FedaPay | Depuis votre dashboard FedaPay |\n| Environnement | `sandbox` pour tester, `live` pour la production |\n| Page de confirmation | URL vers laquelle rediriger après paiement (ex: `/merci`) |\n\n## Configurer le webhook FedaPay\n\n1. Connectez-vous à [app.fedapay.com](https://app.fedapay.com)\n2. Allez dans **Paramètres → Webhooks → Ajouter**\n3. URL : `https://api.votre-hotel.teranga.app/api/webhooks/fedapay`\n4. Événement : `transaction.approved`\n5. Enregistrez\n\n## Ajouter le formulaire à une page\n\n1. Créez une page WordPress (ex: « Réserver »)\n2. Ajoutez le shortcode : `[teranga_booking]`\n3. Publiez la page\n\n## Parcours client\n\n1. Le client visite la page de réservation sur votre site\n2. Il remplit le formulaire (nom, chambre, dates, email, téléphone)\n3. Il clique sur **Payer et réserver avec FedaPay**\n4. La popup FedaPay s'ouvre : il choisit son moyen de paiement (MTN Mobile Money, Moov Money, carte Visa/Mastercard…)\n5. Paiement validé → la réservation est automatiquement créée dans Teranga PMS avec une facture marquée **Payée**\n6. Le client est redirigé vers la page de confirmation\n\n## Vérification côté PMS\n\n- La réservation apparaît dans **Réservations** avec la source **CHANNEL_MANAGER**\n- La facture est automatiquement générée et marquée **Payée**\n- Le paiement est enregistré avec la méthode **FEDAPAY** et la référence de transaction\n\n## Intégration avec BA Book Everything (existant)\n\nSi votre site utilise déjà le plugin **BA Book Everything** avec FedaPay, utilisez le plugin **Teranga BA Sync** à la place du formulaire standalone :\n\n1. Installez le plugin `teranga-ba-sync` dans WordPress\n2. Allez dans **Réglages → Teranga BA Sync**\n3. Configurez l'URL API et la clé API Teranga\n4. **Mapping des chambres** : associez chaque ID d'objet BA Book Everything au numéro de chambre dans Teranga PMS\n   - Trouvez les IDs dans **BA Book Everything → All Items** (colonne ID)\n   - Exemple : `{\"23\": \"101\", \"45\": \"102\", \"67\": \"201\"}`\n5. Choisissez le moment de synchronisation :\n   - **Paiement reçu** (recommandé) : dès que FedaPay confirme le paiement\n   - **Commande complétée** : après toutes les étapes de validation\n\nLe plugin fonctionne automatiquement : chaque réservation payée sur BA Book Everything est envoyée à Teranga PMS avec la facture et le paiement déjà enregistrés. Les annulations sont aussi propagées.\n\nL'historique des synchronisations est visible dans la page de configuration du plugin."
    },
    {
      "id": "config-fedapay",
      "url": "https://teranga-pms.jdidit.cloud/documentation/config-fedapay/",
      "title": "Configurer FedaPay (Owner)",
      "summary": "Paramétrer les clés et webhooks FedaPay pour accepter les paiements en ligne.",
      "keywords": [
        "FedaPay",
        "webhook",
        "paiement en ligne"
      ],
      "category": "Intégrations",
      "modules": [
        "Paiements multi-méthodes"
      ],
      "metiers": [],
      "roles": [
        "Owner"
      ],
      "difficulty": "Intermédiaire",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "wordpress-fedapay"
      ],
      "placeholder": false,
      "content": "Chaque propriétaire d'établissement peut connecter son propre compte FedaPay pour recevoir les paiements directement sur son compte.\n\n## Rôle autorisé\n\nSeul le rôle **Owner** a accès à la configuration FedaPay.\n\n## Connecter son compte FedaPay\n\n1. Allez dans **Paramètres** dans la barre latérale\n2. Dans la section **Intégration FedaPay**, cliquez sur **Connecter**\n3. Renseignez :\n   - **Clé secrète FedaPay** : depuis votre dashboard [app.fedapay.com](https://app.fedapay.com) (`sk_live_...` ou `sk_sandbox_...`)\n   - **Mode** : Sandbox (test) ou Live (production)\n   - **URL de callback** : URL de retour après paiement (optionnel)\n   - **URL Webhook WordPress** : pour notifier votre site WordPress des paiements (optionnel)\n4. Cliquez sur **Enregistrer**\n\n## Tester la connexion\n\nCliquez sur **Tester la connexion** pour vérifier que votre clé FedaPay est valide. Le système crée une transaction de test (100 XOF) puis la supprime.\n\n## Utilisation\n\nUne fois FedaPay configuré, lorsqu'une commande ou réservation est créée avec le moyen de paiement **FedaPay** :\n- Le QR code encode l'URL de la gateway FedaPay\n- Un **bouton \"Payer avec FedaPay\"** apparaît sous le QR code\n- Un **lien cliquable** vers la page de paiement est affiché\n- Le client peut payer par Mobile Money (MTN, Moov), carte bancaire, etc.\n\n## Sécurité\n\n- La clé secrète est stockée **chiffrée** (AES-256-GCM) dans la base de données\n- Elle n'est jamais visible en clair dans l'interface (masquée : `sk_sandbox_****...****`)\n- Chaque tenant a ses propres clés — aucun partage entre établissements\n\n## Déconnecter\n\nCliquez sur **Déconnecter** pour supprimer la configuration FedaPay. Les paiements FedaPay ne seront plus disponibles."
    },
    {
      "id": "faq-technique",
      "url": "https://teranga-pms.jdidit.cloud/documentation/faq-technique/",
      "title": "Dépannage — questions fréquentes",
      "summary": "Réponses aux blocages les plus courants : approbations, QR code, exports, mots de passe, clés API, webhooks FedaPay.",
      "keywords": [
        "dépannage",
        "FAQ",
        "clé API",
        "webhook FedaPay",
        "QR code",
        "export CSV"
      ],
      "category": "Dépannage",
      "modules": [
        "Utilisateurs & RBAC",
        "Commande QR client",
        "Rapports & Export",
        "Paiements multi-méthodes"
      ],
      "metiers": [],
      "roles": [
        "Owner",
        "DAF",
        "Manager",
        "Serveur"
      ],
      "difficulty": "Intermédiaire",
      "estimatedTime": "5 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "connexion",
        "tableau-de-bord"
      ],
      "placeholder": false,
      "content": "## Je n'arrive pas à créer un article\n\n- Vérifiez qu'une **catégorie** est sélectionnée (Restaurant ou Boissons).\n- Vérifiez qu'un **nom** et un **prix de vente** sont renseignés.\n- Le champ stock n'est pas obligatoire pour les plats préparés.\n- Si l'erreur persiste, lisez le message affiché sous le champ concerné.\n\n## Mon article n'apparaît pas dans le menu du serveur\n\nLes articles créés par un Manager nécessitent l'**approbation du DAF**. Demandez au DAF de le valider dans la page Approbations.\n\n## Le QR code ne s'affiche pas\n\n- Vérifiez que la commande ou la réservation a bien été créée.\n- Le QR code nécessite qu'une facture soit générée automatiquement.\n- Vous pouvez le réafficher en cliquant sur l'icône QR, colonne « Paiement ».\n\n## Je ne vois pas certains menus dans la barre latérale\n\nChaque rôle n'a accès qu'aux fonctionnalités qui le concernent. Le Serveur ne voit pas Réservations, Chambres, Stock ni Approbations ; le Cuisinier ne voit que Dashboard et Cuisine ; le Ménage, que Dashboard, Chambres et Ménage.\n\n## Comment exporter un rapport ?\n\n1. Connectez-vous en tant que Manager ou DAF.\n2. Allez dans **Rapports**.\n3. Cliquez sur un bouton d'export : Commandes, Chambres ou Serveurs.\n4. Un fichier CSV se télécharge automatiquement.\n\n## Comment changer le mot de passe d'un utilisateur ?\n\nContactez le DAF ou le Super Admin pour une réinitialisation.\n\n## Comment télécharger un reçu ou une facture en PDF ?\n\nDepuis Commandes, Réservations ou Factures, cliquez sur l'icône de téléchargement de la ligne concernée. Rôles autorisés : Serveur, Manager, DAF, Owner, Super Admin.\n\n## Je ne reçois pas de notification quand un client part\n\n- Vérifiez que le check-out a bien été effectué (la chambre doit passer en statut « Nettoyage »).\n- Une notification est envoyée automatiquement aux agents de ménage.\n- En secours, le système vérifie toutes les 30 secondes même sans connexion temps réel.\n\n## L'application mobile affiche « EMPLOYEE » au lieu de mon rôle\n\nDéconnectez-vous puis reconnectez-vous — l'application redétecte votre rôle.\n\n## Comment générer une clé API pour WordPress ?\n\n1. Connectez-vous en tant qu'Owner ou DAF.\n2. Allez dans **Clés API**.\n3. Cliquez sur **Nouvelle clé API**, donnez un nom, puis **Créer**.\n4. Copiez la clé affichée immédiatement — elle ne sera plus jamais visible ensuite.\n\n## J'ai perdu ma clé API\n\nSupprimez l'ancienne clé dans **Clés API**, créez-en une nouvelle, et mettez à jour la configuration WordPress avec la nouvelle valeur.\n\n## Le paiement FedaPay depuis WordPress ne crée pas la réservation\n\n- Vérifiez la clé API Teranga dans Réglages → Teranga Booking.\n- Vérifiez que l'URL API est accessible depuis le serveur WordPress.\n- Le webhook FedaPay doit être configuré sur `transaction.approved`.\n\n## Le webhook FedaPay ne met pas à jour le paiement\n\n- L'URL du webhook doit être en HTTPS en production.\n- Vérifiez dans le dashboard FedaPay que le webhook reçoit bien les événements.\n- Par sécurité, le paiement est aussi enregistré à la création de la réservation."
    },
    {
      "id": "cles-api",
      "url": "https://teranga-pms.jdidit.cloud/documentation/cles-api/",
      "title": "Gérer les clés API",
      "summary": "Créer, utiliser et révoquer les clés API pour vos intégrations externes (WordPress notamment).",
      "keywords": [
        "clé API",
        "intégration",
        "sécurité"
      ],
      "category": "Guide administrateur",
      "modules": [],
      "metiers": [],
      "roles": [
        "Owner",
        "DAF"
      ],
      "difficulty": "Intermédiaire",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "wordpress-fedapay"
      ],
      "placeholder": false,
      "content": "Les clés API permettent de connecter des systèmes externes (site WordPress, Channel Manager, etc.) à Teranga PMS de manière sécurisée.\n\n## Rôles autorisés\n\nSeuls les comptes **Owner** et **DAF** ont accès à la page **Clés API**.\n\n## Créer une clé API\n\n1. Allez dans **Clés API** dans la barre latérale\n2. Cliquez sur **Nouvelle clé API**\n3. Remplissez :\n   - **Nom** : un nom descriptif (ex: « Site WordPress », « Booking.com »)\n   - **Durée de validité** : 30 jours, 90 jours, 6 mois ou 1 an\n   - **IPs autorisées** : optionnel, restreint l'accès à certaines adresses IP\n4. Cliquez sur **Créer la clé**\n5. **Copiez immédiatement la clé affichée** — elle ne sera plus jamais visible\n\n## Gérer les clés\n\n- **Activer/Désactiver** : cliquez sur l'icône d'alimentation pour activer ou désactiver une clé sans la supprimer\n- **Supprimer** : cliquez sur l'icône corbeille (confirmation demandée). Toutes les intégrations utilisant cette clé cesseront de fonctionner\n- **Dernière utilisation** : la colonne indique la date de dernière utilisation de chaque clé\n\n## Utilisation dans WordPress\n\nCopiez la clé générée dans la configuration du plugin WordPress :\n- **Teranga Booking** : Réglages → Teranga Booking → Clé API Teranga\n- **Teranga BA Sync** : Réglages → Teranga BA Sync → Clé API Teranga\n\n## Sécurité\n\n- La clé est stockée sous forme de hash SHA256 — même les administrateurs ne peuvent pas la récupérer\n- Chaque clé possède un **préfixe** visible (ex: `tpms_a3b2c1...`) pour l'identifier\n- Les clés expirées sont automatiquement rejetées\n- La restriction par IP ajoute une couche de sécurité supplémentaire"
    },
    {
      "id": "gestion-utilisateurs",
      "url": "https://teranga-pms.jdidit.cloud/documentation/gestion-utilisateurs/",
      "title": "Gérer les utilisateurs",
      "summary": "Créer des comptes, attribuer des rôles et gérer les accès de votre équipe.",
      "keywords": [
        "utilisateurs",
        "rôles",
        "RBAC",
        "équipe"
      ],
      "category": "Guide administrateur",
      "modules": [
        "Utilisateurs & RBAC"
      ],
      "metiers": [],
      "roles": [
        "Owner",
        "DAF"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "connexion"
      ],
      "placeholder": false,
      "content": "## Créer un employé (Manager)\n\n1. Allez dans **Utilisateurs**\n2. Cliquez sur **+ Nouvel utilisateur**\n3. Renseignez : nom, prénom, e-mail, mot de passe, rôle (Serveur, Cuisinier ou Ménage)\n4. Validez\n\nL'employé sera créé en statut **\"En attente\"** jusqu'à validation par le DAF.\n\n## Approuver un employé (DAF)\n\n1. Allez dans **Approbations**\n2. Trouvez la demande de type \"Création employé\"\n3. Approuvez ou rejetez\n\nUne fois approuvé, l'employé peut se connecter avec ses identifiants."
    },
    {
      "id": "abonnement",
      "url": "https://teranga-pms.jdidit.cloud/documentation/abonnement/",
      "title": "Gérer votre abonnement",
      "summary": "Consulter votre plan, faire évoluer votre abonnement et gérer la facturation.",
      "keywords": [
        "abonnement",
        "plan",
        "facturation"
      ],
      "category": "Guide administrateur",
      "modules": [
        "Abonnements & Plans"
      ],
      "metiers": [],
      "roles": [
        "Owner"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [],
      "placeholder": false,
      "content": "La page **Abonnement** permet de consulter et gérer l'abonnement de l'établissement.\n\n## Rôles autorisés\n\n| Action | SUPERADMIN | Owner | DAF |\n|--------|:----------:|:-----:|:---:|\n| Voir l'abonnement | Oui | Oui | Oui |\n| Renouveler via FedaPay | Oui | Oui | Oui |\n| Activation manuelle | Oui | Non | Non |\n\n## Consulter l'abonnement\n\n1. Allez dans **Abonnement** dans la barre latérale\n2. La page affiche :\n   - **Plan actuel** : nom, statut (Essai, Actif, En retard, Suspendu, Annulé), prix\n   - **Période en cours** : dates de début et de fin, jours restants\n   - **Utilisation du plan** : barres de progression pour les chambres, utilisateurs et établissements vs les limites du plan\n   - **Historique des paiements** : tableau avec date, montant, période, statut et référence\n\n## Renouveler l'abonnement (Owner, DAF, SUPERADMIN)\n\n1. Cliquez sur **Renouveler via FedaPay** dans la section Actions\n2. Un nouvel onglet s'ouvre avec la page de paiement FedaPay\n3. Effectuez le paiement (Mobile Money, carte bancaire, etc.)\n4. L'abonnement est automatiquement mis à jour après confirmation du paiement\n\n## Activation manuelle (SUPERADMIN uniquement)\n\nPour les paiements en espèces ou par virement direct :\n\n1. Cliquez sur **Activation manuelle**\n2. Sélectionnez le plan\n3. Choisissez la fréquence (Mensuel / Annuel)\n4. Indiquez la durée en mois\n5. Cliquez sur **Activer**\n\nL'abonnement est immédiatement activé sans nécessiter de paiement en ligne.\n\n## Cycle de vie de l'abonnement\n\n| Statut | Description |\n|--------|-------------|\n| **Essai gratuit** | 14 jours d'essai après inscription, accès complet |\n| **Actif** | Abonnement payé et en cours de validité |\n| **Paiement en retard** | Abonnement expiré, période de grâce de 7 jours |\n| **Suspendu** | Accès bloqué après la période de grâce |\n| **Annulé** | Annulation définitive après 30 jours de suspension |\n\nDes notifications de rappel sont envoyées 7 jours et 3 jours avant l'expiration.\n\n## Alertes\n\nSi l'abonnement est en retard ou suspendu, un bandeau d'alerte s'affiche en haut de la page avec un bouton **Payer maintenant**."
    },
    {
      "id": "depenses-decaissements",
      "url": "https://teranga-pms.jdidit.cloud/documentation/depenses-decaissements/",
      "title": "Dépenses et décaissements",
      "summary": "Enregistrer les charges opérationnelles et suivre le solde encaissements/décaissements.",
      "keywords": [
        "dépenses",
        "décaissements",
        "trésorerie"
      ],
      "category": "Guide administrateur",
      "modules": [
        "Dépenses & Décaissements"
      ],
      "metiers": [],
      "roles": [
        "DAF",
        "Owner"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "rapports-exports"
      ],
      "placeholder": false,
      "content": "Le module **Dépenses** permet d'enregistrer les charges opérationnelles de l'établissement (achats de matières premières, frais divers, salaires, etc.) pour obtenir un solde de trésorerie réel dans les rapports.\n\n## Accès\n\nPage **Dépenses** (OWNER, DAF, MANAGER) — barre latérale.\n\n## Enregistrer une dépense\n\n1. Allez dans **Dépenses**\n2. Cliquez sur **+ Nouvelle dépense**\n3. Remplissez le formulaire :\n\n| Champ | Obligatoire | Description |\n|-------|:-----------:|-------------|\n| **Libellé** | Oui | Description de la dépense (ex: \"Achat légumes marché\") |\n| **Catégorie** | Oui | Matières premières, Charges fixes, Personnel, Divers, etc. |\n| **Montant** | Oui | Montant en FCFA |\n| **Date** | Oui | Date de la dépense (peut être rétroactive) |\n| **Note** | Non | Détails supplémentaires, numéro de facture fournisseur |\n\n4. Cliquez sur **Enregistrer**\n\n## Impact sur les rapports\n\nLes dépenses sont visibles dans les rapports PDF sous la section **Décaissements** :\n- Total des décaissements par catégorie pour la période\n- **Ligne Solde** = Total encaissements − Total décaissements\n\n> Un solde négatif indique que les dépenses ont dépassé les encaissements sur la période.\n\n## Filtres\n\n- Par catégorie\n- Par période (dates de début et de fin)\n- Par établissement (SUPERADMIN et OWNER multi-établissement)"
    },
    {
      "id": "fournisseurs-comptabilite",
      "url": "https://teranga-pms.jdidit.cloud/documentation/fournisseurs-comptabilite/",
      "title": "Fournisseurs, prestataires et comptabilité",
      "summary": "Gérer vos fournisseurs, leur historique d'approvisionnement et la comptabilité SYSCOHADA associée.",
      "keywords": [
        "fournisseurs",
        "SYSCOHADA",
        "comptabilité",
        "portail fournisseur"
      ],
      "category": "Guide administrateur",
      "modules": [
        "Fournisseurs & Prestataires",
        "Comptabilité fournisseurs SYSCOHADA",
        "Portail fournisseur"
      ],
      "metiers": [],
      "roles": [
        "DAF",
        "Owner"
      ],
      "difficulty": "Intermédiaire",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "depenses-decaissements"
      ],
      "placeholder": false,
      "content": "> **Accès** : Menu latéral → **Fournisseurs** (DAF / Manager)\n\n## Créer un fournisseur ou un prestataire\n1. **Nouveau** → renseigner le **Nom** et le **Type** : *Fournisseur (biens)* ou *Prestataire (services)*.\n2. Le **compte SYSCOHADA** (compte auxiliaire 401, ex. `40110001`) est attribué automatiquement (modifiable).\n3. Optionnel : **solde d'ouverture** (dette initiale), et pour un fournisseur de biens, cocher **les articles fournis**.\n4. Si un **email** est renseigné, un **compte fournisseur** est créé automatiquement et ses identifiants lui sont envoyés par email (voir SMTP en déploiement).\n\nOn peut **modifier** un tiers (crayon) et le **désactiver** (corbeille).\n\n## Compte / relevé (fiche fournisseur)\nIcône **Compte / Relevé** : affiche toutes ses infos (compte, contact, adresse), son **solde dû**, ses **articles fournis** (ajout/retrait), ses **articles en stock bas**, et son **grand-livre** (achats au crédit, règlements au débit) avec ajout d'**écriture manuelle**.\n- Les **achats** (mouvements de stock PURCHASE) créditent automatiquement son compte ; les **décaissements** rattachés le débitent.\n\n## Portail fournisseur\nUn fournisseur disposant d'un compte se connecte et accède à **son espace** (`/dashboard/supplier`) :\n- **Réapprovisionnement** : ses articles en stock bas, avec **« Accuser réception »**.\n- **Mes articles** : ce qu'il fournit + état du stock.\n- **Mon compte** : son relevé et son solde."
    },
    {
      "id": "ressources-humaines",
      "url": "https://teranga-pms.jdidit.cloud/documentation/ressources-humaines/",
      "title": "Ressources humaines (module RH)",
      "summary": "Fiches employés, pointage, congés, planning et paie SYSCOHADA — le module RH complet.",
      "keywords": [
        "RH",
        "paie",
        "congés",
        "planning",
        "pointage",
        "SYSCOHADA"
      ],
      "category": "Guide administrateur",
      "modules": [
        "Fiches employés (RH)",
        "Pointage & Feuille de temps",
        "Congés & Absences",
        "Planning & Shifts",
        "Paie SYSCOHADA"
      ],
      "metiers": [],
      "roles": [
        "DAF",
        "Owner"
      ],
      "difficulty": "Intermédiaire",
      "estimatedTime": "6 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "gestion-utilisateurs"
      ],
      "placeholder": false,
      "content": "Module complet en 5 phases, accessible aux rôles **OWNER**, **DAF** et **MANAGER** depuis la sidebar (la **Badgeuse** et **Mes congés** sont accessibles à tous). Le module entier peut être désactivé pour un utilisateur via `User.disabledModules` (clé `hr`) par le SUPERADMIN.\n\n## 33.1 — Fiches employé · `/dashboard/hr/employees`\n\n**Création**\n- Bouton **« Importer les utilisateurs existants »** : crée une fiche vierge pour chaque utilisateur qui n'en a pas (rapide pour démarrer).\n- Bouton **« Nouvelle fiche »** : sélectionne un utilisateur existant et crée sa fiche RH.\n\n**Édition** (page détail, 4 onglets)\n- **Identité** : date/lieu de naissance, nationalité, n° pièce d'identité, adresse, contact d'urgence.\n- **Contrat** : matricule, type (CDI/CDD/STAGE/INTERIM/SAISONNIER/CONSULTANT/AUTRE), poste, département, établissement principal, heures hebdo, dates (embauche, fin d'essai, fin CDD, sortie + motif), **PIN badgeuse** (utilisé pour la Phase 2).\n- **Rémunération** : salaire de base brut, devise (XOF par défaut), méthode de paiement, banque + n° compte/IBAN, n° sécurité sociale (CNSS/IPRES), n° identifiant fiscal. Bloc **Soldes de congés** éditable manuellement.\n- **Documents** : URL externe (Drive, S3…) + libellé + type (CONTRAT, CNI, DIPLOME, RIB…). L'upload de fichiers n'est pas encore branché (à venir).\n\n## 33.2 — Pointage & badgeuse\n\n**Badgeuse** · `/dashboard/hr/clock` (tous rôles)\n- Interface tactile avec clavier numérique et horloge live.\n- L'employé tape son PIN (défini par le RH dans la fiche, onglet Contrat) → reconnaissance auto → bouton **« Pointer l'entrée »** ou **« Pointer la sortie »** selon son état actuel.\n- Pointe automatiquement via le hook ménage : la clôture d'une session de nettoyage crée un `TimeEntry` source `Ménage` (idempotent).\n\n**Feuille de temps** · `/dashboard/hr/timesheet` (OWNER/DAF/MANAGER)\n- **Onglet Synthèse** : tableau récap par employé du mois sélectionné (heures totales, jours travaillés, nombre de pointages). Export CSV.\n- **Onglet Détail** : liste des pointages individuels, édition manuelle (corrections), source visible (Manuel/Badgeuse/Mobile/Ménage).\n\n## 33.3 — Congés & absences · `/dashboard/hr/leaves` (tous rôles)\n\n3 onglets adaptés au rôle :\n- **Mes demandes** : créer/voir/annuler ses propres demandes ; solde personnel affiché en haut.\n- **À approuver** (DAF) : demandes en attente avec boutons Approuver/Refuser (modal avec note optionnelle).\n- **Toutes** (Manager) : vue d'ensemble.\n\n**Types** : PAYÉ, MALADIE, SANS SOLDE, MATERNITÉ, PATERNITÉ, EXCEPTIONNEL, RÉCUPÉRATION.\n\n**Logique métier**\n- **Décompte en jours ouvrés** (lundi-vendredi, weekends exclus).\n- **Demi-journée** (0.5j) supportée si même date début/fin.\n- **Anti-chevauchement** : impossible de créer une demande chevauchant une autre demande active.\n- **Soldes** : `paye` et `recuperation` décomptés automatiquement à l'approbation ; les autres types sont indicatifs.\n- **Annulation d'une demande approuvée** par le DAF → **recrédit automatique** du solde.\n- **Notifications temps réel** : DAF/OWNER/MANAGER notifiés à la création ; employé notifié à l'approbation/refus.\n\n## 33.4 — Planning · `/dashboard/hr/planning` (OWNER/DAF/MANAGER)\n\nVue **grille hebdomadaire** : employés en ligne × 7 jours en colonne.\n\n- Navigation `‹ Semaine précédente · Aujourd'hui · Semaine suivante ›`.\n- Filtre par établissement (n'affiche que les employés rattachés).\n- Clic `+` dans une cellule → modal **« Nouveau shift »** pré-rempli (8h-16h).\n- Clic sur un shift existant → modal d'édition (employé, établissement, début/fin, poste, notes).\n- Couleur déterministe du shift selon le poste (cohérence visuelle).\n- Bouton **« Copier semaine »** : duplique tous les shifts de la semaine en cours vers la semaine N+1.\n\n**Détection de conflits** (warnings non bloquants à l'enregistrement) :\n- Chevauchement avec un autre shift du même employé.\n- Recouvrement avec un congé approuvé.\n\n## 33.5 — Paie · `/dashboard/hr/payroll` (OWNER/DAF uniquement)\n\nWorkflow mensuel par établissement.\n\n**Étape 1 — Génération** (bouton « Générer un mois »)\nSélectionne (établissement, année, mois). Le service :\n- Liste les employés actifs rattachés à l'établissement.\n- Agrège leurs `TimeEntry` du mois → heures et jours travaillés.\n- Agrège leurs `LeaveRequest APPROVED` → jours pris + déduction `SANS_SOLDE` au prorata du salaire de base journalier.\n- Crée une `PayrollLine` par employé, statut `Brouillon`.\n\n**Étape 2 — Ajustements** (mode `Brouillon` uniquement)\nPour chaque ligne, modal d'édition : heures supplémentaires (avec taux configurable, défaut 1.25), primes + libellé, retenues + libellé, mode de paiement, compte SYSCOHADA personnalisable (défaut **6611**).\n\n**Étape 3 — Verrouillage** (bouton « Verrouiller »)\nPasse en `Verrouillée`. Les lignes ne sont plus modifiables. **L'export comptable devient disponible**. Bouton « Rouvrir » disponible tant que pas payée.\n\n**Étape 4 — Paiement** (bouton « Marquer payée », date sélectionnable)\nPour chaque ligne :\n- Crée automatiquement un `Expense` dans le journal des dépenses (catégorie `SALARY`, libellé `« Salaire — Prénom Nom — Mois Année »`).\n- Le mode de paiement RH est mappé vers `PaymentMethod` (VIREMENT → BANK_TRANSFER, ESPECES → CASH, etc.).\n- Référence croisée `PayrollLine.expenseId` ↔ `Expense` (idempotent : relancer ne re-crée pas).\n\nStatut passe à `Payée`, **irréversible**.\n\n**Export comptable SYSCOHADA** (CSV téléchargeable dès `Verrouillée`)\n\nFormat : Date, Journal, Pièce, Compte, Libellé, Débit, Crédit, Devise.\n\n- **Constatation de la charge** (date fin de mois, journal `OD`, pièce `PAIE-YYYY-MM`) :\n  - Débit **6611** « Appointements salaires » (ou code custom) — par employé\n  - Crédit **421** « Personnel rémunérations dues » — par employé\n- **Paiement** (date de paiement, journal `BQ`, pièce `PAIE-YYYY-MM-PAY`) :\n  - Débit **421** Personnel\n  - Crédit **521** (Virement/Chèque), **571** (Espèces) ou **524** (Mobile Money) selon le mode\n\n**Bulletins PDF** : un par employé, téléchargeable depuis la page détail période (icône fichier). En-tête établissement, période, rubriques détaillées (base, heures sup, absences sans solde, primes, retenues), net à payer.\n\n> **⚠️ Périmètre V1** : Teranga calcule uniquement le **brut**. Le calcul des charges sociales (CNSS, IPRES), de l'IR et les déclarations fiscales doivent être effectués par votre logiciel comptable externe via l'import du CSV SYSCOHADA.\n\n---\n\n*Document mis à jour le 27 mai 2026 — Teranga PMS v2.14 (Onboarding A + B, RGPD, cookies, tour produit)*\n\n*Mises à jour précédentes : v2.13 (Module RH V1 — fiches employé, pointage, congés, planning, paie SYSCOHADA) · v2.12 (Comptabilité fournisseurs SYSCOHADA, comptes & portail fournisseur, prestataires, SMTP) · v2.11 (Composition / stock décimal) · v2.10 (Points de vente) · v2.9 (Commande QR)*\n\n**v2.8** : Mode hors ligne PWA + Android (file IndexedDB/Room DB, badge, sync auto), Dépenses & Décaissements (module complet + rapport PDF Solde), flag Bon propriétaire modifiable après création, modification complète de réservation avec recalcul facture, factures automatiques pour les réservations channel manager, script de backfill, informations client/séjour dans les factures PDF réservation.\n\n**v2.7** : Point de vente avec attribution au serveur (POS → serveur), date d'opération rétroactive web + mobile (15 j + override superviseur), rapports corrigés pour afficher le serveur attribué plutôt que le compte POS.\n\n**v2.6** : Module Clients & Fidélité, remises automatiques + manuelles, catégories d'articles dynamiques (web + Android), CA consolidé incluant les revenus de réservations, correctifs PDF (séparateurs de milliers + colonnes du détail des transactions)."
    },
    {
      "id": "rapports-exports",
      "url": "https://teranga-pms.jdidit.cloud/documentation/rapports-exports/",
      "title": "Rapports et exports",
      "summary": "Exporter vos données en CSV et lire les rapports PDF journaliers, y compris le chiffre d'affaires consolidé.",
      "keywords": [
        "rapports",
        "export CSV",
        "chiffre d'affaires",
        "PDF"
      ],
      "category": "Rapports",
      "modules": [
        "Rapports & Export"
      ],
      "metiers": [],
      "roles": [
        "Manager",
        "DAF"
      ],
      "difficulty": "Débutant",
      "estimatedTime": "2 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "depenses-decaissements"
      ],
      "placeholder": false,
      "content": "Accessible aux rôles **DAF** et **Manager** via **Rapports** dans la barre latérale.\n\n## Indicateurs disponibles\n\n| Indicateur | Description |\n|-----------|-------------|\n| **Taux d'occupation** | Pourcentage de chambres occupées |\n| **Revenus totaux** | Total des commandes enregistrées |\n| **Factures en attente** | Montant des factures non payées |\n| **Commandes du jour** | Nombre de commandes aujourd'hui, cette semaine, ce mois |\n\n## Graphiques\n\n- **Occupation des chambres** : camembert (disponibles, occupées, nettoyage, maintenance)\n- **Modes de paiement** : répartition Flooz, Yas, Espèces, Carte, etc.\n- **Performance par serveur** : histogramme double axe (nombre de commandes + revenus générés)\n- **Statut des commandes** : camembert (en attente, en cours, prêtes, servies, annulées)\n\n## Tableau des serveurs\n\nUn tableau détaillé affiche pour chaque serveur :\n- Nom\n- Nombre de commandes\n- Revenus générés\n- Moyenne par commande\n\n> **Attribution des commandes POS** : quand une commande est saisie par le POS pour le compte d'un serveur, c'est le **serveur attribué** qui apparaît dans les graphiques, le tableau et les exports CSV — pas le compte POS qui a tapé la commande en caisse.\n\n## Rapport PDF — Rapport de caisse\n\nLe bouton **Télécharger PDF** génère un rapport de caisse journalier ou sur une période. Il contient :\n\n| Section | Description |\n|---------|-------------|\n| **Encaissements** | Total des ventes par serveur, ventilé par moyen de paiement |\n| **Décaissements** | Dépenses enregistrées sur la période, par catégorie |\n| **Solde** | Encaissements − Décaissements = trésorerie nette de la période |\n| **Détail des transactions** | Liste de chaque commande avec date d'opération, serveur, montant |\n\n> **Date d'opération** : les commandes sont classées selon la **date d'opération** déclarée (pas la date de saisie système). Une commande saisie aujourd'hui mais datée d'hier apparaît dans le rapport d'hier.\n\n## Exporter les données\n\nTrois boutons d'export CSV sont disponibles en haut de la page :\n- **Commandes** : toutes les commandes avec numéro, date d'opération, serveur, total, statut, paiement\n- **Chambres** : toutes les chambres avec numéro, statut, type, étage\n- **Serveurs** (DAF uniquement) : performance par serveur\n\nLes fichiers sont téléchargés au format CSV, utilisables dans Excel ou Google Sheets.\n\nLe widget **Encaissement du jour** et le PDF de rapport quotidien comptabilisent désormais :\n- Les paiements de **commandes** (Resto + Bar + Loisirs + Location)\n- Les paiements de **réservations** (FedaPay, espèces, virement, etc.)\n\nLe PDF utilise un séparateur de milliers compatible Helvetica (les anciens \"/\" qui apparaissaient sont corrigés)."
    },
    {
      "id": "architecture-technique",
      "url": "https://teranga-pms.jdidit.cloud/documentation/architecture-technique/",
      "title": "Architecture technique",
      "summary": "Stack technique, structure du projet et principes de sécurité de la plateforme.",
      "keywords": [
        "architecture",
        "stack technique",
        "Next.js",
        "Prisma",
        "sécurité",
        "développeur"
      ],
      "category": "Guide développeur",
      "modules": [],
      "metiers": [],
      "roles": [],
      "difficulty": "Avancé",
      "estimatedTime": null,
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "api-reference",
        "rbac-permissions"
      ],
      "placeholder": false,
      "content": "## Structure du projet\n\n```\nteranga/\n├── backend/     # API REST — Node.js/Express + TypeScript + Prisma + PostgreSQL\n├── frontend/    # Interface Web — Next.js (App Router) + TypeScript + Tailwind CSS\n├── android/     # App mobile — Kotlin + Jetpack Compose + Hilt + Room DB\n├── wordpress/   # Plugins WordPress (Teranga Booking, BA Book Everything Sync)\n└── docker-compose.yml\n```\n\n## Stack technique\n\n| Couche | Technologie |\n|--------|-------------|\n| Frontend Web | Next.js, TypeScript, Tailwind CSS, React Query, Zustand, Recharts |\n| Backend API | Node.js, Express, TypeScript, Zod |\n| ORM / DB | Prisma + PostgreSQL |\n| Cache | Redis |\n| Auth | JWT (access + refresh tokens), bcryptjs, RBAC à 2 niveaux |\n| Paiement | FedaPay (abonnements + gateway intégrée + WordPress), Mobile Money via QR code |\n| Mobile | Kotlin, Jetpack Compose, Room DB, Retrofit, Hilt DI |\n| DevOps | Docker, Docker Compose, GitHub Actions CI/CD |\n\n## Multi-tenant\n\nIsolation par `tenant_id`, appliquée automatiquement par un middleware Prisma sur chaque requête — un tenant ne peut jamais accéder aux données d'un autre, y compris en cas d'erreur applicative (défense en profondeur avec Row Level Security PostgreSQL).\n\n## Sécurité\n\n- Isolation multi-tenant via middleware Prisma + Row Level Security PostgreSQL.\n- JWT signé, durée courte (15 min), refresh token en cookie HttpOnly (accepté aussi dans le body pour mobile).\n- Validation Zod (whitelist) sur tous les endpoints.\n- Rate limiting par IP et par tenant en production.\n- Réservations anti-double-booking en transaction Serializable.\n- Idempotence des opérations POS par UUID unique.\n- Recalcul des montants côté serveur (anti-manipulation) — jamais de confiance dans un montant envoyé par le client.\n- bcryptjs à 12 rounds, comparaison à temps constant.\n- Headers de sécurité (Helmet), CORS configurable par domaine.\n- Upload d'images limité en taille et en formats acceptés.\n- Journalisation structurée pour audit.\n\n## Design system\n\n- **Web** : terracotta, or, sauge — voir les tokens CSS partagés du site.\n- **Mobile (application Android)** : palette dédiée inspirée du Bénin (rouge Dahomey, or béninois, vert béninois, bronze Abomey)."
    },
    {
      "id": "api-reference",
      "url": "https://teranga-pms.jdidit.cloud/documentation/api-reference/",
      "title": "Référence API interne",
      "summary": "Panorama des principaux endpoints de l'API Teranga, organisés par domaine fonctionnel.",
      "keywords": [
        "API",
        "endpoints",
        "REST",
        "développeur",
        "intégration"
      ],
      "category": "Guide développeur",
      "modules": [],
      "metiers": [],
      "roles": [],
      "difficulty": "Avancé",
      "estimatedTime": null,
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "architecture-technique",
        "cles-api",
        "wordpress-fedapay"
      ],
      "placeholder": false,
      "content": "Panorama des principaux domaines de l'API REST. Les endpoints marqués **publics** ne nécessitent pas d'authentification (jeton dans l'URL ou clé API dédiée) ; tous les autres exigent un JWT de session ou une clé API tenant.\n\n## Authentification\n\n- `POST /api/auth/login` — Connexion (retourne les rattachements aux établissements)\n- `POST /api/auth/refresh` — Renouvellement du token\n- `POST /api/auth/logout` — Déconnexion\n- `GET /api/auth/me` — Profil courant\n\n## Établissements, chambres, points de vente\n\n- `/api/establishments`, `/api/rooms` (+ `PATCH /:id/status`)\n- `/api/points-of-sale` — CRUD, plafonné par l'abonnement ; `?pointOfSaleId=` filtre commandes, articles, catégories, tables, cuisine et rapports sur un point de vente précis\n\n## Réservations & commandes\n\n- `/api/reservations` (+ check-in, check-out, cancel) — facture auto-générée à la création\n- `PATCH /api/reservations/:id` — modification complète avec recalcul de facture\n- `POST /api/reservations/admin/backfill-channel-invoices` — régénération des factures manquantes (rôles superviseurs)\n- `/api/orders` (+ `GET /kitchen/:estId`, `?forUserId=` qui inclut les commandes saisies par *ou* attribuées à l'utilisateur)\n- `PATCH /api/orders/:id/voucher` — bascule le flag « bon propriétaire »\n- `POST /api/orders/:id/claim` — prise en charge d'une commande QR non assignée\n\n## Commandes QR (publiques, sans authentification)\n\n- `GET /api/public/menu/:token` — menu de l'établissement à partir du token de table\n- `POST /api/public/orders` — créer une commande depuis un scan QR\n\n## Facturation & paiements\n\n- `/api/invoices` (+ `GET /:id/qrcode`, `GET /:id/pdf`)\n- `/api/payments`\n\n## Menu, stock, fournisseurs\n\n- `/api/articles` — accepte `components` (recette → décrément des composants à la vente) et `sellable`\n- `/api/categories`, `/api/stock-movements`, `/api/stock-alerts`\n- `/api/suppliers` (+ `/:id/statement`, `/:id/ledger`) — comptabilité SYSCOHADA fournisseurs\n- `/api/supplier-portal/*` — portail fournisseur (rôle dédié)\n\n## Approbations & ménage\n\n- `/api/approvals` — demandes d'approbation (création employé, article, chambre, modification réservation)\n- `/api/cleaning` — sessions de ménage (clock-in/clock-out)\n\n## Abonnements\n\n- `GET /api/registration/plans` — liste des plans (public)\n- `POST /api/registration/register` — inscription\n- `/api/subscriptions` (+ `/renew`, `/activate`)\n- `POST /api/webhooks/fedapay` — webhook FedaPay (public)\n\n## Notifications\n\n- `GET /api/notifications` (+ `?unread=true`, `/unread-count`, `/read-all`)\n- `GET /api/notifications/stream` — flux temps réel (SSE)\n\n## Canaux de réservation (iCal)\n\n- `/api/channels` (+ `/:id/sync`, `/:id/regenerate-token`)\n- `GET /api/calendar/:token.ics` — flux iCal public (token dans l'URL, aucune donnée client)\n\n## Clés API\n\n- `GET/POST /api/api-keys` — la clé n'est retournée en clair qu'à la création\n- `PATCH/DELETE /api/api-keys/:id`\n\n## Intégrations externes\n\n- `GET /api/availability.json` / `GET /api/availability.ics`\n- `POST /api/external-bookings` — réservations Channel Manager par clé API, avec paiement FedaPay\n- `POST /api/pos/transactions` — transactions POS Android"
    },
    {
      "id": "rbac-permissions",
      "url": "https://teranga-pms.jdidit.cloud/documentation/rbac-permissions/",
      "title": "RBAC : rôles et permissions",
      "summary": "Architecture des rôles à deux niveaux, cloisonnement par point de vente, matrice de permissions complète et workflows automatiques.",
      "keywords": [
        "RBAC",
        "rôles",
        "permissions",
        "workflow",
        "approbation"
      ],
      "category": "Guide développeur",
      "modules": [
        "Utilisateurs & RBAC"
      ],
      "metiers": [],
      "roles": [],
      "difficulty": "Avancé",
      "estimatedTime": "12 min",
      "version": "toutes versions",
      "lastUpdated": "2026-08-06",
      "related": [
        "architecture-technique",
        "gestion-utilisateurs"
      ],
      "placeholder": false,
      "content": "## Architecture des rôles\n\nLe système utilise un RBAC à deux niveaux, plus un cloisonnement optionnel par point de vente :\n\n| Niveau | Rôles | Description |\n|--------|-------|-------------|\n| **Tenant** (plateforme) | `SUPERADMIN`, `EMPLOYEE`, `SUPPLIER` | Accès global / employé / portail fournisseur |\n| **Etablissement** | `OWNER`, `DAF`, `MANAGER`, `SERVER`, `POS`, `COOK`, `CLEANER`, `MAITRE_HOTEL` | Accès spécifique à un établissement |\n| **Point de vente** (optionnel) | mêmes rôles `EstablishmentRole` | Affectation d'un membre à un PdV précis (`PointOfSaleMember`) |\n\n---\n\n## Portail fournisseur (rôle `SUPPLIER`)\n\nÀ la création d'un fournisseur **avec email**, un compte de profil `SUPPLIER` est auto-provisionné et lié (`Supplier.userId`). Ce compte est **confiné à son portail** (`/api/supplier-portal`, page `/dashboard/supplier`) et n'a accès qu'à **ses propres données** :\n\n- ses **articles** (`ArticleSupplier`) et leurs **alertes de stock bas** ;\n- son **compte / relevé** (grand-livre auxiliaire 401, solde) en lecture seule ;\n- l'**accusé de réception** des demandes de réapprovisionnement (`StockAlert.supplierAckAt`).\n\nUn compte `SUPPLIER` n'a aucune appartenance d'établissement : le reste du dashboard lui est inaccessible (redirection automatique vers son portail). Il ne peut pas modifier le stock ni les écritures.\n\n> Type de tiers : `Supplier.type` = `GOODS` (fournisseur de biens, avec articles) ou `SERVICE` (**prestataire**, sans articles) — les deux disposent d'un compte 401 + grand-livre.\n\n---\n\n## Cloisonnement par point de vente (PdV)\n\nUn établissement peut être découpé en plusieurs **points de vente** (Restaurant, Bar, Piscine…). L'appartenance à un PdV est portée par `PointOfSaleMember (userId, pointOfSaleId, role)` et chargée dans le token de session (`req.user.pointOfSaleIds`).\n\nRègle de visibilité (`posScopeFor`, `src/middlewares/rbac.middleware.ts`) :\n\n- **Superviseurs** — `SUPERADMIN`, ou `OWNER` / `DAF` / `MANAGER` dans un établissement — voient **tous les PdV** de leur périmètre (aucune restriction).\n- **Autres rôles** — `SERVER`, `POS`, `COOK`, `MAITRE_HOTEL`, etc. — ne voient que les **articles, catégories, commandes et files cuisine** des **PdV auxquels ils sont affectés**.\n\nCe cloisonnement est **appliqué côté serveur** (non contournable) sur `/api/orders`, `/api/articles`, `/api/categories` et `/api/orders/kitchen/:estId`. Conséquence : un employé **non affecté à un PdV ne voit rien** (il faut l'affecter via *Points de vente → Personnel*). Le sélecteur de PdV de la barre latérale est masqué pour le personnel non-superviseur (le périmètre est imposé par l'affectation).\n\nLa gestion des PdV (création, désactivation, affectation du personnel) est réservée à **OWNER / DAF** ; la création est plafonnée par l'abonnement (`maxPointsOfSale`, middleware `checkPlanLimit('points_of_sale')`).\n\n---\n\n## Matrice des permissions par rôle\n\n### SuperAdmin\n\nAccès complet à toutes les fonctionnalités, tous les établissements.\n\n- Bypass de toutes les restrictions d'établissement\n- Dashboard complet avec toutes les statistiques\n- Gestion des utilisateurs et des établissements\n- **Gestion des abonnements** : voir, renouveler, et activation manuelle (paiements en espèces)\n\n---\n\n### Owner (Propriétaire)\n\nLe propriétaire a les mêmes permissions que le DAF, plus la gestion des canaux de réservation, des clés API et de l'abonnement.\n\n#### Permissions spécifiques (en plus du DAF)\n\n| Module | Action | Autorisé |\n|--------|--------|----------|\n| **Clés API** | Créer / modifier / supprimer | Oui |\n| **Canaux iCal** | Connecter / configurer | Oui |\n| **Configuration FedaPay** | Connecter / tester / déconnecter | Oui |\n| **Fournisseurs** | CRUD complet | Oui |\n| **Abonnement** | Voir / renouveler via FedaPay | Oui |\n| **Remises (Discount Rules)** | Créer / modifier / activer (hébergements et commandes) | Oui |\n| **Clients** | Voir liste, fiche, télécharger carte de fidélité PDF | Oui |\n| **Points de vente** | Créer / modifier / désactiver / affecter le personnel (DAF inclus) | Oui |\n| **Backfill factures channel** | `POST /api/reservations/admin/backfill-channel-invoices` | Oui |\n\n---\n\n### DAF (Directeur Administratif et Financier)\n\nLe DAF est l'administrateur de l'établissement. Il valide les actions sensibles soumises par le Manager.\n\n#### Permissions\n\n| Module | Action | Autorisé |\n|--------|--------|----------|\n| **Chambres** | Créer / modifier / supprimer | Oui (direct) |\n| **Réservations** | Créer / modifier tous les champs / annuler | Oui |\n| **Réservations** | Check-in / Check-out | Oui |\n| **Articles** | Créer / modifier / supprimer | Oui |\n| **Stock** | Mouvements de stock (direct) | Oui |\n| **Commandes** | Voir les commandes | Oui |\n| **Commandes** | Changer statut cuisine (EN_COURS / PRET) | Non |\n| **Commandes** | Marquer comme servie | Non |\n| **Commandes** | Annuler une commande | Oui |\n| **Commandes** | Basculer flag bon propriétaire (`isVoucher`) | Oui |\n| **Réservations** | Modifier tous les champs (direct, sans approbation) | Oui |\n| **Dépenses** | CRUD complet | Oui |\n| **Approbations** | Voir toutes les demandes | Oui |\n| **Approbations** | Approuver / rejeter | Oui |\n| **Cuisine** | Voir le tableau cuisine | Oui (lecture seule) |\n| **Ménage** | Pointage (clock-in/out) | Non |\n| **Clés API** | Créer / modifier / supprimer | Oui |\n| **Abonnement** | Voir / renouveler via FedaPay | Oui |\n| **Dashboard** | Stats Manager + financières | Oui (7 graphiques) |\n\n#### Dashboard DAF\n\nLe dashboard DAF inclut les 4 graphiques Manager + 3 graphiques supplémentaires :\n\n- Niveaux de stock (barres horizontales)\n- Occupation des chambres (camembert)\n- Commandes cuisine par jour (histogramme)\n- Commandes par serveur (histogramme)\n- **Flux de paiements mensuels** (histogramme)\n- **Mouvements de stock par type** (camembert)\n- **Temps de traitement moyen** (histogramme)\n\n---\n\n### Manager\n\nLe Manager gère l'établissement au quotidien. Certaines actions sensibles nécessitent la validation du DAF.\n\n#### Permissions\n\n| Module | Action | Autorisé | Approbation DAF |\n|--------|--------|----------|-----------------|\n| **Chambres** | Créer une chambre | Oui | Requise |\n| **Chambres** | Modifier / supprimer | Oui | - |\n| **Réservations** | Créer | Oui | - |\n| **Réservations** | Modifier les dates, chambre, remise, invités | Oui | Requise (via approbation DAF) |\n| **Réservations** | Check-in / Check-out | Oui | - |\n| **Articles** | Créer (avec image et description) | Oui | - |\n| **Articles** | Modifier / supprimer | Oui | - |\n| **Stock** | Mouvements de stock | Oui | Requise |\n| **Commandes** | Voir les commandes | Oui | - |\n| **Commandes** | Changer statut cuisine (EN_COURS / PRET) | Non | - |\n| **Commandes** | Marquer comme servie | Non | - |\n| **Commandes** | Annuler une commande | Oui | - |\n| **Cuisine** | Voir le tableau cuisine | Oui (lecture seule) | - |\n| **Ménage** | Pointage (clock-in/out) | Non | - |\n| **Ménage** | Assigner un ménage | Oui (aux CLEANERs) | - |\n| **Approbations** | Voir ses propres demandes | Oui | - |\n| **Approbations** | Approuver / rejeter | Non | - |\n\n#### Dashboard Manager\n\n4 graphiques :\n\n- Niveaux de stock (barres horizontales)\n- Occupation des chambres (camembert)\n- Commandes cuisine par jour (histogramme)\n- Commandes par serveur (histogramme)\n\n#### Workflow d'approbation Manager\n\n1. Le Manager soumet une action (création chambre, mouvement stock, modification dates)\n2. Une demande d'approbation est créée (statut `PENDING`)\n3. Le Manager peut voir le statut de sa demande dans la page **Approbations > Mes demandes**\n4. Le DAF voit la demande dans sa page **Approbations** et peut approuver ou rejeter\n5. Si approuvée, l'action est exécutée automatiquement (chambre créée, stock mis à jour, etc.)\n\n---\n\n### Serveur (Server)\n\nLe serveur gère les commandes en salle.\n\n#### Permissions\n\n| Module | Action | Autorisé |\n|--------|--------|----------|\n| **Commandes** | Créer une commande | Oui |\n| **Commandes** | Marquer comme servie (`SERVED`) | Oui |\n| **Commandes** | Changer statut cuisine (EN_COURS / PRET) | Non |\n| **Commandes** | Annuler une commande | Non |\n| **Commandes** | Basculer flag bon propriétaire (`isVoucher`) | Non |\n| **Commandes** | Voir ses commandes (créées par lui OU attribuées par le POS) | Oui |\n| **Commandes** | Saisir une commande avec date d'opération rétroactive (≤ 15 jours) | Oui |\n| **Commandes QR** | **Prendre en charge** une commande non assignée (`POST /orders/:id/claim`) | Oui |\n| **Chambres** | Créer / modifier | Non |\n| **Stock** | Mouvements de stock | Non |\n| **Ménage** | Pointage | Non |\n\n#### Dashboard Serveur\n\n- Statistiques de commandes globales\n- Statistiques de commandes personnelles (mes commandes du jour — inclut les commandes saisies par le POS en son nom)\n\n---\n\n### POS (Caissier)\n\nLe POS saisit les commandes en caisse pour le compte des serveurs.\n\n#### Permissions\n\n| Module | Action | Autorisé |\n|--------|--------|----------|\n| **Point de vente** | Accès à `/dashboard/pos` (web) et écran POS (mobile) | Oui |\n| **Commandes** | Créer une commande | Oui |\n| **Commandes** | **Attribuer une commande à un serveur** (sélecteur Serveur attribué) | Oui |\n| **Commandes** | Saisir avec date d'opération rétroactive (≤ 15 jours) | Oui |\n| **Commandes** | Saisir en mode hors ligne (file IndexedDB/Room DB) | Oui |\n| **Commandes** | Basculer flag bon propriétaire (`isVoucher`) | Non |\n| **Paiements** | Encaisser une commande (espèces, carte, mobile money) | Oui |\n| **Factures** | Voir les factures générées | Oui |\n| **Commandes** | Changer statut cuisine / annuler | Non |\n| **Chambres / Réservations / Stock** | Accès | Non |\n\n> **Attribution** — Lorsque le POS coche un serveur dans « Serveur attribué », la commande est enregistrée avec `createdById = POS` (audit de qui a tapé) et `serverId = serveur choisi` (pour le reporting). Le serveur verra la commande dans sa liste et dans ses stats ; les rapports l'attribuent au serveur, pas au POS.\n\n---\n\n### Cuisinier (Cook)\n\nLe cuisinier gère la préparation des commandes en cuisine.\n\n#### Permissions\n\n| Module | Action | Autorisé |\n|--------|--------|----------|\n| **Cuisine** | Voir les commandes | Oui |\n| **Cuisine** | Passer en `EN_COURS` (IN_PROGRESS) | Oui |\n| **Cuisine** | Passer en `PRET` (READY) | Oui |\n| **Cuisine** | Marquer comme servie | Non |\n| **Cuisine** | Annuler | Non |\n| **Chambres** | Accès | Non |\n| **Stock** | Accès | Non |\n| **Ménage** | Accès | Non |\n\n#### Dashboard Cuisinier\n\n- Statistiques cuisine uniquement (commandes en attente, en cours, prêtes)\n\n---\n\n### Maître d'Hôtel (MAITRE_HOTEL)\n\nLe maître d'hôtel supervise la salle et gère les commandes QR clients.\n\n#### Permissions\n\n| Module | Action | Autorisé |\n|--------|--------|----------|\n| **Commandes** | Voir toutes les commandes de l'établissement | Oui |\n| **Commandes** | Créer une commande | Oui |\n| **Commandes** | Marquer comme servie (`SERVED`) | Oui |\n| **Commandes** | Annuler une commande | Non |\n| **Commandes** | Basculer flag bon propriétaire (`isVoucher`) | Non |\n| **Commandes QR** | Prendre en charge une commande non assignée (`POST /orders/:id/claim`) | Oui |\n| **Tables** | Voir le plan de salle | Oui |\n| **Tables** | Assigner un serveur à une table (`PATCH /restaurant-tables/:id/assign-server`) | Oui |\n| **Tables** | Configurer le mode d'attribution QR (`PATCH /restaurant-tables/settings/qr-mode`) | Oui |\n| **Tables** | Voir les QR codes des tables | Oui |\n| **Date rétroactive** | Saisir avec `operationDate` (≤ 15 jours) | Oui |\n| **Chambres / Réservations / Stock** | Accès | Non |\n\n#### Dashboard Maître d'Hôtel\n\n- Statistiques de commandes globales\n- Vue du plan de salle avec statut des tables\n\n---\n\n### Ménage (Cleaner)\n\nLe personnel de ménage gère le nettoyage des chambres.\n\n#### Permissions\n\n| Module | Action | Autorisé |\n|--------|--------|----------|\n| **Ménage** | Pointage clock-in | Oui |\n| **Ménage** | Pointage clock-out | Oui |\n| **Ménage** | Voir les sessions de ménage | Oui |\n| **Chambres** | Créer / modifier | Non |\n| **Commandes** | Accès | Non |\n| **Stock** | Accès | Non |\n\n#### Dashboard Ménage\n\n- Section ménage uniquement\n- Résumé de l'état des chambres (disponibles, en nettoyage, occupées)\n\n---\n\n## Workflows automatiques\n\n### Création de commande → Facture automatique\n\nLorsqu'une commande est créée, une facture est automatiquement générée :\n\n- Numéro de facture : `FAC-YYYYMMDD-NNNN`\n- Statut : `ISSUED`\n- Montant : total de la commande\n- La facture est liée à la commande\n- Si `operationDate` est fournie : la facture utilise `issueDate = operationDate` (backdate), sinon la date courante\n\n### Attribution POS → Serveur\n\nLorsqu'une commande est créée depuis le module Point de vente (POS) avec un `serverId` :\n\n- `createdById` = ID du compte POS (audit : qui a saisi en caisse)\n- `serverId` = ID du serveur attribué (revenue credit)\n- Filtre `forUserId=X` : retourne les commandes où `createdById = X` **OU** `serverId = X` — le serveur voit toutes les commandes qui le concernent\n- Agrégations de rapports : `attributed = server || createdBy` — priorité au serveur attribué, fallback sur le créateur\n\n### Date d'opération (backdate)\n\nLe paramètre `operationDate` permet d'enregistrer aujourd'hui une opération datée d'hier :\n\n- Validation côté backend via `validateOperationDate(date, roleCtx)`\n- Rôles opérationnels (SERVER, POS, MAITRE_HOTEL) : rejetés au-delà de 15 jours dans le passé\n- Rôles superviseurs (OWNER, DAF, MANAGER, SUPERADMIN) : aucune limite\n- Propagé sur `Invoice.issueDate`, `Payment.paidAt`, `Order.occurredAt` selon le contexte\n\n### Création de réservation → Facture + QR code\n\nLorsqu'une réservation est créée (web, mobile ou WordPress) :\n\n- Facture auto-générée : `FAC-YYYYMMDD-NNNN`, statut `ISSUED`\n- Le moyen de paiement est stocké sur la facture\n- QR code de paiement disponible immédiatement\n- Moyen de paiement : Espèces, Mobile Money, Flooz, Yas, FedaPay, Carte, Virement\n- Si FedaPay : bouton + lien cliquable vers la gateway de paiement\n- Reçu PDF téléchargeable (format ticket 80mm)\n\n### Réservation WordPress + FedaPay\n\nLorsqu'un client réserve depuis un site WordPress :\n\n1. Paiement FedaPay (Mobile Money, carte)\n2. Plugin WordPress envoie la réservation via `POST /api/external-bookings` (instantané)\n3. Réservation créée + facture auto-générée + paiement enregistré (montant partiel supporté : acompte 60%)\n4. Webhook FedaPay confirme le paiement (double sécurité)\n5. Notification vers WordPress via webhook de paiement (si configuré)\n\n### Checkout → Nettoyage automatique\n\nLorsqu'un check-out est effectué sur une réservation :\n\n1. La réservation passe en statut `CHECKED_OUT`\n2. La chambre passe automatiquement en statut `CLEANING`\n3. Un cleaner peut ensuite faire un clock-in sur cette chambre\n4. Au clock-out, la chambre repasse en statut `AVAILABLE`\n\n---\n\n## Workflows automatiques (suite)\n\n### Décrémentation automatique du stock à la vente\n\nLorsqu'un article a `trackStock = true` et qu'une commande est créée ou qu'un article est ajouté :\n\n- Le stock est décrémenté atomiquement (transaction Serializable)\n- Un mouvement `SALE` est enregistré dans `stock_movements` avec le `orderId`\n- Si `currentStock <= 0` : la vente est **bloquée** avec une erreur 409 (web + Android)\n- En cas d'annulation de la commande : le stock est restauré (mouvement `RETURN`)\n\n### Synchronisation channel manager → Facture automatique\n\nLorsqu'une réservation est importée via iCal ou `/api/external-bookings` :\n\n1. La réservation est créée via `reservationService.create()` (pas d'insertion directe)\n2. Une facture `FAC-YYYYMMDD-NNNN` est générée automatiquement (statut `PAID`)\n3. Un paiement est enregistré (`FEDAPAY` pour les réservations en ligne, `OTHER` pour iCal)\n4. Une fiche client est créée ou mise à jour si l'email est disponible\n5. Ces revenus sont inclus dans les rapports quotidiens et le tableau de bord\n\n### Flag bon propriétaire (`isVoucher`)\n\n`PATCH /api/orders/:id/voucher` (OWNER, DAF, MANAGER) :\n\n- Bascule `isVoucher` sur l'`Order`\n- Met à jour la note sur la facture associée\n- Crée un `ApprovalRequest` de type `VOUCHER_FLAG` pour traçabilité DAF\n\n### Commande QR client → Attribution serveur\n\nUn client scanne le QR code sur sa table et passe une commande sans compte Teranga :\n\n1. Le client ouvre `https://<domaine>/menu/<token>` (page publique, sans authentification)\n2. Il consulte la carte, ajoute des articles au panier, saisit son nom (optionnel) et valide\n3. Le backend reçoit `POST /api/public/orders` et résout le `serverId` selon le mode configuré :\n\n| Mode | `qrServerMode` | Comportement |\n|------|----------------|--------------|\n| **Désactivé** | `DISABLED` | La page `/menu/[token]` affiche \"Commande en ligne indisponible\". Aucun endpoint public n'accepte de commande. |\n| **Pré-assigné** | `PRE_ASSIGNED` | Le serveur est celui enregistré sur `RestaurantTable.currentServerId`. Si aucun n'est défini, `serverId = null`. |\n| **Premier répondant** | `FIRST_RESPONDER` | `serverId = null` ; notification envoyée à tous les **SERVER** et **MAITRE_HOTEL** — le premier qui clique \"Prendre en charge\" prend la commande. |\n| **Charge auto** | `AUTO_LOAD` | Le serveur ayant le moins de commandes actives dans l'établissement est désigné automatiquement. |\n| **Manuel** | `MANUAL` | `serverId = null` ; notification envoyée aux superviseurs (MANAGER, MAITRE_HOTEL) pour assignation manuelle. |\n\n4. `createdById` = ID du compte OWNER de l'établissement (audit, requis par le modèle)\n5. Une notification est envoyée aux rôles concernés selon le mode\n6. En mode `FIRST_RESPONDER` ou `MANUAL` : un SERVER ou MAITRE_HOTEL peut appeler `POST /api/orders/:id/claim` pour prendre en charge la commande (idempotent — 409 si déjà assignée)\n7. La commande apparaît dans le tableau cuisine et dans la liste des commandes des serveurs\n\n> **Coexistence** — les commandes QR et les commandes saisies par le staff (POS, SERVER, MAITRE_HOTEL) fonctionnent en parallèle dans tous les modes actifs. Le mode `DISABLED` n'affecte que les endpoints `/api/public/*`.\n\n#### Configuration du mode QR\n\n- **Web** : page **Gestion des tables** → bouton **Mode attribution** (rôle MAITRE_HOTEL, MANAGER, OWNER, DAF)\n- **Android** : écran Commandes → icône QR dans la barre d'en-tête (rôle MAITRE_HOTEL+)\n- **Endpoint** : `PATCH /api/restaurant-tables/settings/qr-mode` `{ mode: \"PRE_ASSIGNED\" | \"FIRST_RESPONDER\" | \"AUTO_LOAD\" | \"MANUAL\" | \"DISABLED\" }`\n\n---\n\n### Mode hors ligne — file de synchronisation\n\nLe POS web utilise IndexedDB (Dexie) pour mettre en file d'attente les opérations hors ligne :\n\n- Chaque opération est stockée avec un UUID idempotent avant envoi\n- Le drain FIFO commence automatiquement à la reconnexion\n- En cas d'erreur 4xx (client) : l'opération est marquée `FAILED` (pas de retry infini)\n- En cas d'erreur 5xx (serveur) : backoff exponentiel avec max 5 tentatives\n\n---\n\n## Module RH (`hr`)\n\nLe module Ressources Humaines (`backend/src/routes/resource.routes.ts`, gates `requireModuleWrite('hr')`) est utilisable par tous les rôles tenant authentifiés, avec ces nuances :\n\n| Action | Rôles autorisés |\n|--------|-----------------|\n| Voir la badgeuse + pointer | Tout employé authentifié (OWNER, DAF, MANAGER, MAITRE_HOTEL, SERVER, POS, COOK, CLEANER) |\n| Créer/voir ses propres demandes de congé | Tout employé |\n| Annuler sa propre demande PENDING | Employé concerné |\n| Voir les fiches employé, planning, feuille de temps | OWNER, DAF, MANAGER |\n| Créer/modifier/supprimer une fiche employé | OWNER, DAF |\n| Approuver/refuser un congé · Annuler un congé APPROVED · Ajuster un solde | OWNER, DAF |\n| Créer/modifier/supprimer un shift planning | OWNER, DAF, MANAGER |\n| Générer une période de paie · Verrouiller/rouvrir/marquer payée | OWNER, DAF |\n| Exporter le CSV SYSCOHADA · Télécharger un bulletin PDF | OWNER, DAF, MANAGER |\n\n**Désactivation du module pour un utilisateur** : le SUPERADMIN peut ajouter `hr` à `User.disabledModules` pour révoquer les écritures (lecture conservée). Mécanisme générique partagé avec tous les autres modules.\n\n**Endpoints `/me/*`** (`/api/leaves/me`, `/api/time-entries/me/*`, `/api/shifts/me`) : restreints à l'utilisateur authentifié, accessibles à tout employé sans condition de rôle d'établissement.\n\n---\n\n## Onboarding (`/api/onboarding`)\n\nRoutes laissées **toujours accessibles** à un utilisateur authentifié, même s'il n'a pas terminé son onboarding :\n- `/api/auth/*`, `/api/onboarding/*`, `/api/registration/*`, `/api/public/*`, `/api/health`.\n\nPour toutes les autres routes, le middleware `requireOnboardingCompleted` (`backend/src/middlewares/onboarding.middleware.ts`) renvoie `403` avec un code :\n- `ONBOARDING_REQUIRED` — l'onboarding tenant (Phase A) n'est pas complet.\n- `PASSWORD_CHANGE_REQUIRED` — `User.mustChangePassword === true`.\n- `TERMS_NOT_ACCEPTED` — `User.termsAcceptedAt IS NULL`.\n- `RGPD_NOT_ACCEPTED` — `User.rgpdAcceptedAt IS NULL`.\n\nLe SUPERADMIN bypass intégralement ces vérifications.\n\nL'intercepteur axios frontend (`frontend/src/lib/api.ts`) lit le code et redirige vers la page correspondante (`/onboarding`, `/user-onboarding/password`, `/user-onboarding/terms`, `/user-onboarding/rgpd`).\n\n---\n\n## Types d'approbation\n\n| Type | Déclencheur | Action à l'approbation |\n|------|-------------|----------------------|\n| `ROOM_CREATION` | Manager crée une chambre | Chambre créée à partir du payload |\n| `STOCK_MOVEMENT` | Manager crée un mouvement de stock | Mouvement exécuté, stock article mis à jour |\n| `RESERVATION_MODIFICATION` | Manager modifie une réservation | Modification appliquée, facture recalculée |\n| `VOUCHER_FLAG` | Owner/DAF/Manager bascule `isVoucher` sur une commande | Enregistrement pour audit (pas d'action supplémentaire) |"
    },
    {
      "id": "cgu",
      "url": "https://teranga-pms.jdidit.cloud/documentation/cgu/",
      "title": "Conditions Générales d'Utilisation",
      "summary": "CGU de la plateforme Teranga — objet, compte utilisateur, données, disponibilité, responsabilité, propriété intellectuelle.",
      "keywords": [
        "CGU",
        "conditions générales",
        "utilisation",
        "légal"
      ],
      "category": "Légal",
      "modules": [],
      "metiers": [],
      "roles": [],
      "difficulty": "Débutant",
      "estimatedTime": null,
      "version": null,
      "lastUpdated": "2026-08-06",
      "related": [
        "rgpd"
      ],
      "placeholder": true,
      "content": "## 1. Objet\n\nLes présentes Conditions Générales d'Utilisation (ci-après « CGU ») ont pour objet de définir les modalités d'utilisation de la plateforme Teranga (ci-après « la Plateforme ») par ses utilisateurs (ci-après « l'Utilisateur »).\n\n## 2. Acceptation\n\nL'utilisation de la Plateforme est subordonnée à l'acceptation pleine et entière des présentes CGU. L'Utilisateur reconnaît avoir pris connaissance des CGU et déclare expressément les accepter sans restriction ni réserve.\n\n## 3. Compte utilisateur\n\nL'Utilisateur s'engage à fournir des informations exactes lors de la création de son compte, à les maintenir à jour, et à préserver la confidentialité de ses identifiants. Il est responsable de toute utilisation faite via son compte.\n\n## 4. Données\n\nLes données saisies par l'Utilisateur restent sa propriété. Elles sont hébergées dans un environnement sécurisé et ne sont pas partagées avec des tiers sans son consentement, sauf obligation légale.\n\n## 5. Disponibilité\n\nLa Plateforme est accessible 24h/24, 7j/7, sous réserve d'interruptions pour maintenance, mises à jour ou cas de force majeure. Aucune garantie de disponibilité totale ne peut être donnée.\n\n## 6. Responsabilité\n\nL'éditeur ne saurait être tenu responsable d'un préjudice résultant d'une mauvaise utilisation de la Plateforme, d'une saisie erronée, ou d'une panne externe (réseau, fournisseur tiers).\n\n## 7. Propriété intellectuelle\n\nTous les éléments de la Plateforme (logiciel, interface, marques) sont la propriété exclusive de l'éditeur. Toute reproduction non autorisée est interdite.\n\n## 8. Modification des CGU\n\nL'éditeur se réserve le droit de modifier les présentes CGU à tout moment. L'Utilisateur sera invité à les ré-accepter en cas de modification substantielle.\n\n## 9. Loi applicable\n\nLes présentes CGU sont soumises au droit en vigueur dans le pays d'exploitation principal de l'éditeur."
    },
    {
      "id": "rgpd",
      "url": "https://teranga-pms.jdidit.cloud/documentation/rgpd/",
      "title": "Politique de protection des données personnelles",
      "summary": "Données collectées, finalités, durées de conservation, droits RGPD, sécurité et cookies.",
      "keywords": [
        "RGPD",
        "données personnelles",
        "protection des données",
        "cookies",
        "DPO"
      ],
      "category": "Légal",
      "modules": [],
      "metiers": [],
      "roles": [],
      "difficulty": "Débutant",
      "estimatedTime": null,
      "version": null,
      "lastUpdated": "2026-08-06",
      "related": [
        "cgu"
      ],
      "placeholder": true,
      "content": "## 1. Responsable du traitement\n\nTeranga est responsable du traitement de vos données dans le cadre de votre utilisation de la plateforme. Pour toute question relative à vos données, contactez votre administrateur de tenant ou notre support.\n\n## 2. Données collectées\n\n- **Données d'identification** : nom, prénom, email, téléphone.\n- **Données professionnelles** : rôle, établissement, employeur, fiche RH si applicable (date de naissance, pièce d'identité, contrat, salaire, n° sécurité sociale).\n- **Données de connexion** : logs d'accès, adresses IP, navigateur, dernière connexion.\n- **Données métier** que vous saisissez : clients, réservations, paiements, dépenses, pointages, congés, planning, paie.\n\n## 3. Finalités du traitement\n\n- Authentification et sécurité de la plateforme.\n- Fonctionnement opérationnel (réservations, facturation, RH, comptabilité).\n- Support client et résolution d'incidents.\n- Statistiques internes anonymisées (utilisation produit, performance).\n- Respect d'obligations légales (comptables, fiscales, sociales — facturation, bulletins de paie, écritures SYSCOHADA, conservation décennale).\n\n## 4. Durée de conservation\n\n| Catégorie | Durée |\n|-----------|-------|\n| Données de compte (authentification) | Tant que le compte est actif + 12 mois après désactivation |\n| Données métier (factures, paiements, écritures) | 10 ans (obligation comptable) |\n| Données RH (fiches employé, paie) | 5 ans après fin de contrat |\n| Logs de connexion | 12 mois |\n| Données de démonstration | Supprimées à la demande de l'administrateur |\n\n## 5. Destinataires\n\nVos données **ne sont jamais vendues**. Elles peuvent être communiquées à des sous-traitants techniques (hébergeur, sauvegarde, envoi d'email) liés par un contrat de confidentialité et de conformité RGPD, ou aux autorités légales sur réquisition judiciaire dûment motivée.\n\nAucun cookie publicitaire ou de tracking tiers (Google Analytics, Meta Pixel, etc.) n'est utilisé sur la plateforme.\n\n## 6. Vos droits\n\nConformément au RGPD, vous disposez d'un droit d'accès, de rectification, d'effacement (« droit à l'oubli », sous réserve des obligations légales de conservation), de portabilité (export CSV/JSON disponible depuis le menu **Export données** pour les rôles OWNER/DAF), d'opposition et de limitation du traitement.\n\nPour exercer ces droits, contactez votre administrateur de tenant. Pour les demandes complexes ou en cas de désaccord, contactez notre DPO via le support.\n\n## 7. Sécurité\n\n- **Transit** : chiffrement TLS pour toutes les communications.\n- **Stockage** : base de données isolée par tenant, sauvegardes régulières chiffrées.\n- **Authentification** : JWT court (15 min) + refresh token, bcrypt 12 rounds, blocage de compte après tentatives échouées.\n- **Accès** : contrôle d'accès par rôle (RBAC), audit log des actions sensibles.\n- **Secrets** : clés tierces (FedaPay, SMTP) chiffrées en base au repos (AES-256-GCM).\n\n## 8. Cookies\n\nLors de votre première connexion au dashboard, un bandeau propose trois choix : **Tout accepter** (essentiels + analytique interne), **Essentiels uniquement** (session et préférences — choix par défaut recommandé), ou **Refuser** (seuls les cookies strictement nécessaires au fonctionnement sont déposés). Modifiable à tout moment depuis les paramètres du compte.\n\n## 9. Modification de la politique\n\nL'éditeur se réserve le droit de modifier la présente politique. Vous serez invité à la ré-accepter en cas de modification substantielle."
    }
  ]
}