# NACEF : de la création du client au QR code fiscal

Guide complet, pas à pas. Il couvre tout le parcours :

1. le **super administrateur** crée un nouveau client (locataire) ;
2. le client **configure sa société** (identité fiscale, taxes, caisse) ;
3. on **installe les logiciels NACEF** sur la machine de la caisse ;
4. on **appaire l'équipement** et on obtient le certificat ;
5. on encaisse une vente et on **vérifie le QR code**.

Chaque partie indique **où** vous êtes (cloud d'administration, caisse cloud du
client, ou machine physique du magasin). C'est la source de confusion la plus
fréquente.

---

## 0. Vue d'ensemble

### Les deux espaces cloud

| Espace | Adresse | Qui s'y connecte | Sert à |
|---|---|---|---|
| **Administration** | `https://admin.kaissflow.com` | CAMELSOFT (super admin) | créer et suivre les clients |
| **Caisse du client** | `https://<client>.kaissflow.com` | le commerçant | vendre, configurer sa société |

Chaque client a **sa propre base de données**. Le sous-domaine est déduit du nom
de la base : le certificat TLS est un **wildcard** `*.kaissflow.com`, donc un
nouveau client ne demande **aucune** manipulation DNS ni serveur. Rien à faire
sur le VPS pour un nouveau commerçant.

### Le chemin de la signature

```
  Cloud (Roubaix)             <client>.kaissflow.com
                                       │  page ouverte dans le navigateur DE LA CAISSE
  Machine de la caisse (magasin)
     Navigateur  ──CORS──►  Connecteur CAMELSOFT :10016
                                       │
                                       ▼
                              SIC Agent :10006 ──► SMDF :10004 ──► NACEF
```

> **Le serveur cloud ne joint jamais votre caisse.** Il est hébergé ailleurs,
> la caisse est derrière la box du magasin : aucune connexion n'est possible
> dans ce sens, et ce n'est pas nécessaire. C'est le **navigateur**, seul à voir
> les deux côtés, qui va chercher la signature auprès du S-MDF local et la
> transmet au cloud. Aucun port à ouvrir, aucun VPN.

**Conséquence pratique :** la caisse doit être ouverte **dans le navigateur de
la machine où tourne le S-MDF**. Ouvrir la même page depuis un autre PC ne
signera rien.

### Les trois logiciels de la caisse

| Logiciel | Rôle | Port |
|---|---|---|
| **SMDF Server** (fourni par NACEF) | boîte fiscale, parle au Ministère | 10004 |
| **SIC Agent** (fourni par NACEF) | interface locale, signe les tickets | 10006 |
| **Connecteur CAMELSOFT** | autorise la page cloud à appeler le SIC | 10016 |

> La caisse a besoin d'**Internet** pour ouvrir la page cloud. Si NACEF est
> indisponible, le SMDF signe **hors-ligne** dans la limite de son quota
> (20 tickets) et se synchronise plus tard : automatique, rien à faire.

### À réunir avant de commencer

- Un compte sur **homologation.nacef.tn** avec **IP fixe déclarée et validée**.
- L'**IMDF**, le **Store ID**, la **référence d'accréditation** et le
  **code de pairing** (obtenus sur ce portail).
- Le **paquet NACEF** correspondant au système de la caisse.
- Le dossier **`tools/`** de ce dépôt.
- **Python 3** (déjà présent sur Ubuntu, à installer sur Windows).
- Le **téléphone** dont le numéro est enregistré chez NACEF (il reçoit les OTP).

---

## Partie 1 : créer le client (super administrateur)

**Où :** `https://admin.kaissflow.com`

1. Connectez-vous avec le compte d'administration.
2. **NACEF Control Plane → Locataires → Nouveau**.
3. Renseignez :

   | Champ | Contenu |
   |---|---|
   | **Nom** | raison sociale. Il détermine le sous-domaine : « Boulangerie Nacef » donne `boulangerienacef.kaissflow.com` |
   | **Matricule fiscal** | matricule du commerçant, obligatoire |
   | **Type d'activité** | choisit le préréglage de caisse |
   | **Représentant légal / CIN / Mobile / Email** | contact du dossier |
   | **Email admin** | ce sera l'**identifiant de connexion** du commerçant |

4. Cliquez **Provisionner**. Le système :
   - clone la base modèle `nacef_tpl` (modules NACEF déjà installés) ;
   - nomme la base d'après la raison sociale (sous-domaine) ;
   - crée le compte administrateur avec l'email fourni et un **mot de passe
     temporaire** ;
   - inscrit la raison sociale et le matricule sur la fiche société.

5. Une fenêtre **« Accès locataire créé »** affiche **l'URL, l'identifiant et le
   mot de passe temporaire**. Notez-les : ils ne sont plus affichés ensuite.
   Transmettez-les au commerçant et demandez-lui de changer le mot de passe à
   la première connexion.

> **Erreur « Base modèle nacef_tpl introuvable »** : la base modèle n'existe pas
> encore sur ce serveur. Lancez `deploy/scripts/create-template.sh`, ou corrigez
> le paramètre système `nacef.tenant_template`.

> **Erreur « Access Denied »** au provisionnement : la gestion des bases est
> désactivée sur l'instance d'administration. `list_db = True` est **requis**
> dans `odoo-cp.conf` (l'API de duplication est protégée par ce réglage) ;
> l'écran des bases reste bloqué par nginx.

6. *(Facultatif, recommandé)* Dans la fiche du locataire, onglet **IMDFs**,
   ajoutez l'IMDF de l'équipement dès que vous le connaissez. Le control plane
   suit alors l'état du certificat et vous alerte avant expiration.

---

## Partie 2 : configurer la société (chez le client)

**Où :** `https://<client>.kaissflow.com`, connecté avec le compte admin fourni.

### 2.1 Identité fiscale

**Paramètres → Sociétés → votre société → onglet NACEF**

| Champ | Où le trouver |
|---|---|
| **Matricule fiscal** | déjà rempli par le provisionnement, vérifiez-le |
| **Nom commercial** | l'enseigne, si différente de la raison sociale |
| **Store ID** | portail homologation.nacef.tn, identifiant du **point de vente** déclaré. Un seul magasin : `000` |
| **Référence d'accréditation** | votre accréditation NACEF, format `ACC-2026-08` |
| **IMDF** | identifiant de l'équipement, donné par le portail |
| **Mode client** | **laissez « Mock »** pour l'instant |
| **URL de l'Agent S-MDF** | `http://127.0.0.1:10016` |

> **Pourquoi `127.0.0.1` pour tout le monde ?** Cette adresse est résolue par le
> **navigateur du caissier**, sur la machine de la caisse. Elle désigne donc la
> caisse elle-même. La même valeur convient à **toutes** les caisses de tous les
> clients : rien à personnaliser, rien à faire sur le VPS.

Les quatre champs **Matricule fiscal**, **Store ID**, **Référence
d'accréditation** et **URL de l'Agent S-MDF** sont **obligatoires** pour passer
en mode production. Tant qu'ils sont vides, le changement de mode est refusé
avec la liste des champs manquants.

### 2.2 Codes de taxe NACEF (Annexe A5)

**Comptabilité → Configuration → Taxes**

Le ticket fiscal transporte un **code de taxe A5**, pas un pourcentage.

| Taux | Code A5 | Reconnu automatiquement |
|---|---|---|
| TVA 7 % | `10` | oui |
| TVA 19 % | `11` | oui |
| Droit de timbre (montant fixe) | `20` | oui |
| **Tout autre taux** | à saisir | **non** |

Pour un taux non standard, ouvrez la taxe et renseignez **Code taxe NACEF
(A5)**. Sans code, la caisse **refuse la vente** en nommant la taxe fautive,
plutôt que d'envoyer un ticket invalide.

> **Piège classique :** les produits de démonstration d'Odoo portent une **TVA
> 15 %**, qui n'existe pas en Tunisie et n'a donc pas de code A5. Le S-MDF
> rejette alors le ticket **entier** avec `506 TICKET.SCHEMA_INVALID` sans
> préciser le champ en cause. Mettez vos produits en **19 %** ou **7 %**.

### 2.3 La caisse

**Point de Vente → Configuration → Points de vente → votre caisse**, section
**NACEF (fiscal)** :

| Champ | Valeur |
|---|---|
| **IMDF** | vide pour hériter de la société. À renseigner seulement si cette caisse a son propre S-MDF |
| **Store ID** | vide pour hériter de la société |
| **N° de série de la caisse** | le numéro de série **de la caisse** déclaré sur le portail, par exemple `POS-TEST-0001` |
| **URL de l'Agent S-MDF** | vide pour utiliser l'URL de la société |

> **Attention, erreur coûteuse :** le « N° de série de la caisse » est celui de
> la **caisse enregistreuse**, tel que déclaré au portail. Ce n'est **pas** le
> numéro de série du S-MDF. Une confusion ici fait échouer l'appairage avec
> l'erreur **104 (SEC_PAIRING_FAILED)**, sans indiquer le champ en cause.

### 2.4 Produits

Vérifiez que chaque produit vendu porte une taxe avec un code A5 valide
(voir 2.2). C'est tout ce qui est exigé côté catalogue.

---

## Partie 3 : installer les logiciels sur la caisse

**Où :** la machine physique du magasin, avec une **session bureau ouverte**
(l'appairage affiche des fenêtres).

### A. Ubuntu / Linux

1. Vérifier Python :
   ```bash
   python3 --version
   ```
2. Placer le paquet NACEF dans `~/Downloads/Gateway_SMDF_Linux`
   (il contient `SMDF.sh` et `SIC.sh`).
3. Tout installer en une commande :
   ```bash
   cd tools
   ./install-nacef-agent.sh
   ```
   Le script installe le SMDF, le SIC et le connecteur, puis affiche un
   contrôle vert/rouge. Il saute ce qui est déjà installé.
4. Vérifier :
   ```bash
   ./nacef-connector.sh status
   ```

Commandes utiles :
```bash
sudo ./nacef-connector.sh restart
sudo ./nacef-connector.sh uninstall
```

### B. Windows

1. Installer **Python 3** depuis <https://python.org>, en cochant
   **« Add python.exe to PATH »**.
2. Lancer les installateurs **Windows** du paquet NACEF (SMDF puis SIC). Ils
   installent les services sur les ports 10004 et 10006.
3. Installer le connecteur. Ouvrez **PowerShell en administrateur** (menu
   Démarrer, tapez `powershell`, clic droit, *Exécuter en tant
   qu'administrateur*), placez-vous dans le dossier `tools` :
   ```powershell
   .\nacef-connector.ps1 install
   ```

   > **Le fichier s'ouvre dans le Bloc-notes au lieu de s'installer ?** Vous
   > êtes dans l'**invite de commandes** (`cmd`), pas dans PowerShell. Le prompt
   > PowerShell commence par `PS `. Depuis `cmd` :
   > ```cmd
   > powershell -NoProfile -ExecutionPolicy Bypass -File "nacef-connector.ps1" install
   > ```

   Si PowerShell bloque le script :
   `Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass`, puis relancez.
   Si le fichier vient d'un téléchargement : `Unblock-File .\nacef-connector.ps1`.

4. Vérifier :
   ```powershell
   .\nacef-connector.ps1 status
   ```

Commandes utiles :
```powershell
.\nacef-connector.ps1 restart      # quand il ne répond plus
.\nacef-connector.ps1 run          # lancer dans la fenêtre, pour voir les erreurs
.\nacef-connector.ps1 uninstall
```

Le connecteur écrit un journal dans `%TEMP%\nacef-connector.log` (Windows) ou
`/tmp/nacef-connector.log` (Ubuntu) : c'est le seul endroit qui dit **pourquoi**
il ne démarre pas. Une tâche planifiée peut afficher « Running » alors que rien
n'écoute sur le port ; seul le journal fait la différence.

### Contrôle avant de continuer

`status` doit annoncer le connecteur **up** et le SIC **joignable**
(HTTP 401 est normal tant que l'équipement n'est pas appairé).

---

## Partie 4 : appairage, certificat, synchronisation

**Où :** navigateur **de la machine de la caisse**, sur
`https://<client>.kaissflow.com`.

### 4.1 Déclarer l'équipement au portail

Sur **homologation.nacef.tn** : déclarez l'équipement avec son **adresse MAC**,
vérifiez que l'**IP fixe déclarée est bien l'IP publique réelle du magasin** et
qu'elle est **validée**. Récupérez l'**IMDF** et le **code de pairing**.

> Une IP déclarée qui ne correspond pas à l'IP réelle donne l'erreur **512**
> (« Fatal error / network ») au moment de l'appairage.

### 4.2 Créer la fiche État S-MDF

**NACEF Fiscal → État S-MDF → Nouveau** : saisissez l'**IMDF**, enregistrez.
Le statut affiché est `FACTORY`.

### 4.3 Passer en mode production

**Paramètres → Sociétés → votre société → onglet NACEF** : **Mode client** =
**« Agent via browser (cloud POS, S-MDF on the till) »**. Enregistrez.

> **Indispensable.** En mode **« Agent »** simple, c'est le **serveur Odoo** qui
> appelle le S-MDF : impossible ici, le serveur est à Roubaix et n'atteint
> jamais le magasin. En mode **« Agent via browser »**, c'est le navigateur de
> la caisse qui va chercher la signature.

Si le changement est refusé, un message liste les champs manquants de la
partie 2.1. Remplissez-les et réessayez.

### 4.4 Tester la liaison

Sur la fiche État S-MDF, bouton **« Tester la connexion S-MDF »**.

- « S-MDF joignable » avec un statut : la chaîne complète fonctionne.
- **401** : joignable mais pas encore appairé. Normal à cette étape.
- « Connecteur injoignable » : le connecteur n'est pas démarré, ou vous n'êtes
  pas sur le navigateur de la caisse.

### 4.5 Demander le certificat

Bouton **« Request certificate »** (visible uniquement à l'état `FACTORY`).
Des **fenêtres du SIC** s'ouvrent **sur l'écran de la caisse** :

1. **IMDF + code de pairing** (étape 1/3)
2. **OTP** reçu par **SMS** (étape 2/3)
3. **PIN**, affiché en **image captcha** (étape 3/3). **Notez ce PIN**, il est
   redemandé à chaque synchronisation.

Le statut passe à `CERT_REQUESTED`.

### 4.6 Unité d'enregistrement

Prenez rendez-vous à l'**unité d'enregistrement**. NACEF émet le certificat et
vous notifie par e-mail, généralement sous 24 heures.

De retour sur la caisse, bouton **« Rafraîchir le manifeste »** : la
**Demande de certificat** doit afficher `CERTIFICATE_GENERATED`, avec les dates
d'émission et d'expiration (validité 1 an).

> Ne redemandez **jamais** un certificat à ce stade : vous obtiendriez
> **523 (SMDF_ALREADY_HAS_CERTIFICATE)**.

### 4.7 Synchroniser

Bouton **« Synchroniser »**. Une fenêtre demande un **OTP** (SMS) et votre
**code PIN**.

**Règles à respecter, dans l'ordre. Elles évitent la quasi-totalité des échecs :**

1. **Une seule demande à la fois.** Chaque clic sur Synchroniser envoie un
   **nouvel** OTP et **annule le précédent**. Si vous cliquez deux fois, le SMS
   que vous avez en main ne correspond plus à la fenêtre affichée.
2. **Le S-MDF se verrouille 10 minutes** pendant qu'une demande est en cours.
   Toute autre demande est refusée avec **517
   (SMDF_LOCKED_CERT_SYNC_REQUEST)**. Attendez, ne cliquez pas en boucle.
3. **Un échec consomme l'OTP.** Un PIN erroné brûle un SMS valide : la tentative
   suivante avec le même code échoue alors pour de bon. C'est ce qui produit la
   boucle « l'OTP que je reçois est toujours refusé ».
4. **Saisissez le PIN en entier**, celui du captcha de l'étape 4.5.
5. **Ne dépassez pas deux tentatives.** **115
   (SEC_INVALID_OTP_EXCEED_THRESHOLD)** est **définitif** et bloque
   l'équipement : la sortie passe alors par le support NACEF.

**Tentative propre :** fermez la fenêtre, attendez 10 minutes, préparez le
téléphone et le PIN, cliquez **une** fois sur Synchroniser, saisissez le SMS
qui arrive **dans la minute**.

**Résultat attendu :**

| Champ | Valeur |
|---|---|
| Statut | `SYNCHRONIZED` |
| Peut signer | coché |
| Tickets hors-ligne disponibles | 20 |
| Certificat | `CERTIFICATE_GENERATED`, expiration à un an |

Tant que **Peut signer** n'est pas coché, **inutile de tester une vente** :
elle échouera sur l'état de l'équipement, pas sur le contenu du ticket, et vous
chercherez au mauvais endroit.

---

## Partie 5 : première vente signée et QR code

**Où :** navigateur de la machine de la caisse.

1. **Point de Vente → votre caisse → Nouvelle session**.
2. Ajoutez un produit (avec une taxe à code A5 valide), **Paiement**,
   **Valider**.
3. Ce qui se passe alors, en quelques secondes :

   ```
   Odoo enregistre la commande, réserve une référence fiscale (sans trou)
     └─► le navigateur appelle le connecteur :10016
           └─► SIC :10006 ──► S-MDF :10004 : signature du ticket
                 └─► le navigateur renvoie la signature à Odoo
                       └─► Odoo enregistre la réf. MDF + le QR, et affiche le ticket
   ```

4. Le ticket affiche la **Réf. Transaction MDF** et le **QR fiscal**.

> Si la vente est refusée, **c'est voulu** : sans signature, pas de vente
> (règle E0302). Le message reprend mot pour mot ce qu'a répondu l'équipement.
> Voir le tableau des codes au dépannage.

### Vérifier que le QR est authentique

1. **Le QR vient du S-MDF, pas d'Odoo.** L'image est produite par l'équipement
   et transmise telle quelle. Odoo ne fabrique un QR lui-même qu'en mode
   **Mock**, jamais en mode production.
2. **Comparez avec la commande.** *Point de Vente → Commandes*, ouvrez la
   vente : le champ **Réf. Transaction MDF** (`nacef_ticket_identifier`) doit
   correspondre à ce que contient le QR scanné avec n'importe quel lecteur.
3. **Vérifiez la chaîne fiscale.** Les références fiscales se suivent **sans
   trou** (`00000001`, `00000002`, ...) : c'est l'exigence E0402. Un trou
   signale une vente non signée à régulariser.
4. **Contrôle au portail.** Le service de vérification de NACEF confirme que le
   ticket a bien été signé par l'IMDF déclaré.

Une vente signée laisse aussi une trace dans **NACEF Fiscal → Piste d'audit**
(journal chaîné, ni modifiable ni supprimable).

---

## Utilisation quotidienne

1. Allumez la machine : SMDF, SIC et connecteur démarrent seuls.
2. Ouvrez `https://<client>.kaissflow.com` **sur cette machine**, connectez-vous.
3. Vendez. Chaque ticket est signé localement et porte le QR fiscal.

Un contrôle de 5 secondes en début de journée :

```bash
./nacef-connector.sh status        # Ubuntu
```
```powershell
.\nacef-connector.ps1 status       # Windows
```

---

## Dépannage

### Codes renvoyés par l'équipement

| Code | Nom | Signification | Que faire |
|---|---|---|---|
| **104** | SEC_PAIRING_FAILED | données d'appairage invalides | vérifiez le **n° de série de la caisse** (pas celui du S-MDF) et le code de pairing |
| **105** | SEC_INVALID_OTP | OTP refusé | SMS le plus récent, PIN complet, une seule demande. Voir 4.7 |
| **115** | SEC_INVALID_OTP_EXCEED_THRESHOLD | trop de tentatives, **définitif** | support NACEF |
| **503** | SMDF_NOT_REACHABLE | le SIC n'atteint pas le **S-MDF** | le service SMDF (10004) tourne-t-il ? URL du S-MDF correcte dans l'agent ? |
| **506** | schéma de ticket invalide / état interdisant l'usage | deux causes possibles | lisez le **message**, pas le code : `TICKET.SCHEMA_INVALID` = code A5 manquant (2.2) ; sinon l'équipement n'est pas `SYNCHRONIZED` |
| **509** | SMDF_NOT_SYNCHRONIZED | ne peut plus signer | lancez une synchronisation (4.7) |
| **512** | NACEF_NOT_REACHABLE | plateforme NACEF injoignable | IP fixe déclarée et validée ? Internet ? |
| **517** | SMDF_LOCKED_CERT_SYNC_REQUEST | demande déjà en cours, verrou 10 min | attendez, ne cliquez pas en boucle |
| **518 / 519** | certificat expiré / révoqué | il faut un nouveau certificat | reprenez en 4.5 |
| **523** | SMDF_ALREADY_HAS_CERTIFICATE | certificat déjà valide | ne redemandez pas, synchronisez |

### Symptômes

| Symptôme | Cause probable | Solution |
|---|---|---|
| `status` : **connector is DOWN** | connecteur arrêté | `restart`, puis lisez `%TEMP%\nacef-connector.log` |
| **Connecteur injoignable** dans la caisse | page ouverte sur un **autre PC** | ouvrez la caisse sur la machine du S-MDF |
| **401 / non autorisé** | pas encore appairé | faites l'appairage (partie 4) |
| Aucune fenêtre à l'appairage | SIC lancé en service **sans écran** | opérez depuis la **session bureau** |
| **injoignable** alors que le connecteur répond en local | **Mode client** resté sur *Agent* | passez sur **« Agent via browser »** (4.3) |
| Ticket **« en attente de signature »** | le navigateur n'a pas joint le connecteur | `status` sur la caisse, puis rejouez la vente |
| **Pas de QR** sur le ticket, sans erreur | la vente n'a pas été signée | vérifiez **Peut signer** sur l'État S-MDF |
| Vente refusée : **code A5 manquant** | taxe non tunisienne (15 % de démo) | passez en 19 % ou 7 %, ou renseignez le code A5 (2.2) |
| **Tickets hors-ligne = 0** et statut `NOT_SYNCHRONIZED` | quota hors-ligne épuisé | synchronisez (4.7) : le quota repasse à 20 |
| Le menu **NACEF Fiscal** n'apparaît pas | l'utilisateur n'est pas dans le groupe opérateur NACEF | ajoutez-le au groupe, puis rechargez |

**Ports** : SMDF `10004`, SIC `10006`, connecteur `10016`.
**Journal du connecteur** : `%TEMP%\nacef-connector.log` (Windows),
`/tmp/nacef-connector.log` (Ubuntu). Personnalisable via la variable
d'environnement `NACEF_LOG`.

---

## Récapitulatif express

| # | Où | Action |
|---|---|---|
| 1 | admin.kaissflow.com | Locataires → Nouveau → **Provisionner**, noter les accès |
| 2 | client.kaissflow.com | Société → onglet NACEF : matricule, Store ID, accréditation, IMDF, URL `http://127.0.0.1:10016` |
| 3 | client.kaissflow.com | Taxes : code A5 (7 % → 10, 19 % → 11), produits en 19 % |
| 4 | client.kaissflow.com | Caisse : n° de série **de la caisse** |
| 5 | machine caisse | installer SMDF, SIC, connecteur ; `status` vert |
| 6 | portail NACEF | déclarer MAC + IP fixe validée, récupérer IMDF et code de pairing |
| 7 | client.kaissflow.com | État S-MDF → Nouveau (IMDF) ; Mode client → **Agent via browser** |
| 8 | client.kaissflow.com | Tester la connexion → **Request certificate** (3 fenêtres, noter le PIN) |
| 9 | unité d'enregistrement | rendez-vous, certificat émis sous 24 h |
| 10 | client.kaissflow.com | Rafraîchir le manifeste → **Synchroniser** (1 clic, SMS frais, PIN complet) |
| 11 | client.kaissflow.com | `SYNCHRONIZED` + **Peut signer** coché → vente test → **QR** |
