# Highlift Atelier — Gestion des réparations machines

## Contexte métier
Application de suivi des réparations pour la société **Highlift.be**.
Remplace les feuilles de travail manuscrites par un système de scan QR code.
Développée par Dimitri Simons (CIP S.A.) pour le compte de Highlift.

## Environnements
| Env | URL | Serveur |
|---|---|---|
| Dev/Test | atelier.simons.eu | OVH mutualisé simons.eu |
| Production | atelier.highlift.be | OVH mutualisé highlift.be |

## Repo Git
- **GitHub** : privé, nom `highlift-atelier` (compte Dimitri Simons)
- Déploiement : GitHub Actions via SFTP (même pattern que checkingatwork)
- Branche principale : `main`
- Branche dev : `develop`

## Stack technique
- **Backend** : PHP 8.4, mysqli
- **Base de données** : MySQL (OVH) — une DB par environnement
- **Frontend** : HTML + JS vanilla (pas de framework)
- **PDF** : mPDF
- **QR Code** : endroid/qr-code via Composer
- **Authentification** : session PHP simple, pas de OAuth
- **Config DB** : fichier `clientmysql.php` (pattern identique aux autres projets CIP/Highlift)

## Structure du projet
```
/highlift-atelier
  CONTEXT.md                  ← ce fichier, toujours à jour
  CLAUDE.md                   ← instructions Claude Code
  clientmysql.php             ← config DB (ignoré par Git, à créer sur chaque serveur)
  clientmysql.php.example     ← template config DB
  .gitignore
  composer.json
  /public                     ← interface ouvrier (scan QR, session active)
    index.php                 ← point d'entrée scan
    session.php               ← affichage session en cours
  /admin                      ← interface back-office
    index.php                 ← dashboard journalier
    machines.php              ← gestion machines + impression étiquettes
    users.php                 ← gestion ouvriers + assignation douchettes
    rapports.php              ← rapports par date / machine / ouvrier
  /api                        ← endpoints JSON appelés par le frontend
    scan.php                  ← reçoit un scan QR, route vers la bonne action
    start.php                 ← démarre une session de réparation
    stop.php                  ← clôture une session
    addpiece.php              ← ajoute une pièce à la session en cours
    rapport.php               ← génère le rapport journalier PDF
  /sync                       ← scripts CRON
    sync_odoo_pieces.php      ← sync catalogue pièces Odoo → MySQL (quotidien)
  /labels                     ← génération étiquettes QR
    generate.php              ← génère PDF étiquette pour une machine
  /lib                        ← librairies tierces (composer ou manuelles)
  /sql
    schema.sql                ← structure complète de la DB
    seeds.sql                 ← données de test
```

## Base de données — schéma
```sql
-- Ouvriers
CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nom VARCHAR(100) NOT NULL,
  prenom VARCHAR(100),
  douchette_id VARCHAR(50) UNIQUE,   -- identifiant unique de la douchette assignée
  badge_qr VARCHAR(50) UNIQUE,       -- QR code du badge personnel
  actif TINYINT DEFAULT 1,
  created_at DATETIME DEFAULT NOW()
);

-- Machines
CREATE TABLE machines (
  id INT AUTO_INCREMENT PRIMARY KEY,
  qr_code VARCHAR(50) UNIQUE NOT NULL,  -- ex: MCH-0042
  nom VARCHAR(150) NOT NULL,
  marque VARCHAR(100),
  modele VARCHAR(100),
  numero_serie VARCHAR(100),
  date_entree DATE,
  actif TINYINT DEFAULT 1,
  created_at DATETIME DEFAULT NOW()
);

-- Sessions de réparation
CREATE TABLE reparations (
  id INT AUTO_INCREMENT PRIMARY KEY,
  machine_id INT NOT NULL,
  user_id INT NOT NULL,
  debut DATETIME NOT NULL,
  fin DATETIME,
  duree_minutes INT,                -- calculé à la clôture
  statut ENUM('en_cours','terminee','annulee') DEFAULT 'en_cours',
  notes TEXT,
  created_at DATETIME DEFAULT NOW(),
  FOREIGN KEY (machine_id) REFERENCES machines(id),
  FOREIGN KEY (user_id) REFERENCES users(id)
);

-- Pièces utilisées par réparation
CREATE TABLE reparation_pieces (
  id INT AUTO_INCREMENT PRIMARY KEY,
  reparation_id INT NOT NULL,
  piece_ref VARCHAR(100) NOT NULL,  -- référence Odoo
  piece_nom VARCHAR(200),
  quantite DECIMAL(10,2) DEFAULT 1,
  scanned_at DATETIME DEFAULT NOW(),
  FOREIGN KEY (reparation_id) REFERENCES reparations(id)
);

-- Cache catalogue pièces (sync depuis Odoo)
CREATE TABLE pieces_cache (
  id INT AUTO_INCREMENT PRIMARY KEY,
  odoo_id INT,
  reference VARCHAR(100) UNIQUE NOT NULL,
  nom VARCHAR(200) NOT NULL,
  unite VARCHAR(20),
  categorie VARCHAR(100),
  actif TINYINT DEFAULT 1,
  synced_at DATETIME
);

-- Log des scans bruts (debug + audit)
CREATE TABLE scan_log (
  id INT AUTO_INCREMENT PRIMARY KEY,
  raw_value VARCHAR(255),
  user_id INT,
  action VARCHAR(50),
  resultat VARCHAR(50),
  scanned_at DATETIME DEFAULT NOW()
);
```

## Logique des QR codes
| Type | Format | Exemple | Action au scan |
|---|---|---|---|
| Machine | `MCH-XXXX` | `MCH-0042` | Démarre ou clôt une session |
| Badge ouvrier | `USR-XXXX` | `USR-003` | Identifie l'ouvrier (début de journée) |
| Pièce | `ART-XXXXX` | `ART-10421` | Ajoute la pièce à la session active |
| FIN | `ACTION-FIN` | `ACTION-FIN` | Clôture la session en cours |

## Flux ouvrier standard
```
1. Matin : scan badge USR → ouvrier identifié sur cette douchette
2. Scan MCH-XXXX → chrono démarre pour cet ouvrier sur cette machine
3. Scans ART-XXXXX (autant que nécessaire) → pièces ajoutées
4. Scan ACTION-FIN → chrono s'arrête, résumé affiché
5. Soir : rapport PDF généré (auto ou à la demande admin)
```

## Rapport journalier — format attendu
- Par machine : liste des interventions (ouvrier, heure début/fin, durée)
- Par intervention : liste des pièces scannées
- Total temps par machine et par ouvrier
- Export PDF + envoi mail optionnel
- En-tête : logo Highlift, date, "Rapport Atelier"

## Intégration Odoo
- **Instance** : Highlift (séparée de CIP) — credentials à fournir
- **Sync** : CRON quotidien (sync_odoo_pieces.php), lecture seule sur Odoo
- **API Odoo** : JSON-RPC (même méthode que projets CIP)
- **Phase 2** : mise à jour stock Odoo lors de la clôture d'une réparation

## Matériel douchettes
- Type recommandé : douchette WiFi industrielle IP65 (Zebra DS2278 ou équivalent)
- Comportement : émulation clavier, envoie la valeur QR + `Enter`
- Assignation : 1 douchette = 1 ouvrier (champ `douchette_id` en DB)
- Identification : scan badge QR en début de journée

## État d'avancement
- [x] Architecture définie
- [x] Schéma DB finalisé
- [x] CONTEXT.md créé
- [x] sql/schema.sql — schéma complet
- [x] sql/seeds.sql — données de test
- [x] clientmysql.php.example — template config DB
- [x] .gitignore
- [x] composer.json (mPDF + endroid/qr-code)
- [x] api/scan.php — cerveau scan QR (USR/MCH/ART/ACTION-FIN)
- [x] public/index.php — interface ouvrier (scan douchette)
- [x] admin/index.php — dashboard journalier
- [x] admin/machines.php — gestion machines + étiquettes
- [x] admin/users.php — gestion ouvriers
- [x] admin/rapports.php — rapports filtrables
- [x] api/rapport.php — génération PDF mPDF
- [x] labels/generate.php — étiquettes QR PDF
- [x] sync/sync_odoo_pieces.php — sync catalogue Odoo
- [x] .github/workflows/deploy.yml — GitHub Actions SFTP
- [x] Repo GitHub créé (`highlift-atelier`)
- [x] Secrets GitHub configurés (FTP_HOST_TEST, FTP_USER_TEST, FTP_PASS_TEST)
- [x] Sous-domaine `atelier.simons.eu` configuré (dossier /atelier/)
- [x] Schema DB déployé + clientmysql.php créé manuellement sur serveur test
- [x] Login sécurisé (email + mot de passe, credentials dans clientmysql.php)
- [x] Logo Highlift intégré dans tous les headers
- [x] Données de test chargées (3 machines, 3 ouvriers, 5 pièces)
- [x] Flux ouvrier testé au clavier (USR → MCH → ART → ACTION-FIN) — OK
- [ ] `composer install` — lib/vendor/ à générer (mPDF + endroid/qr-code manquants)
- [ ] Test rapport PDF (nécessite Composer)
- [ ] Test avec vrai lecteur QR (livraison prochaine)
- [ ] Format QR codes machines à confirmer avec Highlift (1 machine = 1 projet Odoo)
- [ ] Credentials Odoo Highlift obtenus + variables ODOO_* configurées
- [ ] Migration production atelier.highlift.be

## Décisions d'architecture (session 2026-05-29)
- vendor Composer mis dans lib/vendor/ (composer.json: "vendor-dir": "lib/vendor")
- Identification douchette : stockée dans localStorage du navigateur, saisie au premier démarrage
- Pas de session PHP côté ouvrier : l'identité passe par douchette_id dans chaque POST
- Le scan badge USR met à jour douchette_id en DB (réassignation possible en cours de journée)

## Conventions de code
- Fichier de config DB : `clientmysql.php` (jamais commité, dans .gitignore)
- Réponses API : JSON `{ "status": "ok|error", "data": ... }`
- Dates : stockées en UTC, affichées en Europe/Brussels
- Encodage : UTF-8 partout

## Contacts
- **Développeur** : Dimitri Simons — ds@cip-sa.be
- **Client** : Highlift.be
- **Hébergement test** : OVH simons.eu (Dimitri)
- **Hébergement prod** : OVH highlift.be
