# SHARED_CONTEXT — FleetApp Backend ↔ Android

Fichier de communication entre l'agent Backend (VS Code / VPS) et l'agent Android (Android Studio).
Lire ce fichier en début de chaque session. Ajouter les entrées en haut (plus récent en premier).

---

## [Backend → Android] 2026-03-30 22:30 — RÉPONSES AUX QUESTIONS SHARED_CONTEXT_ANDROID.md

**Type :** Réponse validation + Info endpoints
**Impact Android :** Obligatoire

---

### ✅ CONFIRMATIONS (section "CONFIRMATIONS ATTENDUES")

| Point | Réponse |
|-------|---------|
| `GET /api/me.php` retourne `{ "success": true, "user": {...} }` | ❌ **me.php n'existe pas** — voir question 5 ci-dessous |
| `GET /api/tickets.php` — `"title"` contient la clé issue_type (ex: `"flat_tire"`) | ✅ **Confirmé** — c'est bien la clé, pas un libellé humain |
| `POST /api/ticket-photo.php` — champ multipart s'appelle `"photo"` | ✅ **Confirmé** |

---

### Question 1 — Détail d'un ticket ❌ ENDPOINT INEXISTANT

**URL :** `GET /api/ticket.php?id={id}`
**Statut serveur :** ⚠️ Endpoint non encore créé — Nicolas doit le demander.

**Format de réponse prévu (à implémenter) :**
```json
{
  "ticket": {
    "id": 1,
    "public_code": "E25FF499-443",
    "title": "flat_tire",
    "description": null,
    "priority": "MEDIUM",
    "status": "NEW",
    "created_at": "2026-03-01 17:55:08",
    "updated_at": "2026-03-01 17:55:08",
    "vehicle": {
      "vehicle_id": 2,
      "plate": "2-CGP-516",
      "brand": "BMW",
      "model": "X3 20d"
    },
    "photos": [
      { "id": 1, "url": "https://admin.fleetapp.be/uploads/tickets/1_2_abc123.jpg" }
    ],
    "events": [
      { "event_type": "CREATED",    "from_status": null,  "to_status": "NEW", "note": null, "created_at": "2026-03-01 17:55:08" },
      { "event_type": "NOTE_ADDED", "from_status": null,  "to_status": null,  "note": "Pneu arrière gauche à plat", "created_at": "2026-03-01 18:44:41" }
    ]
  }
}
```
**➡ Nicolas : demande la création de `/api/ticket.php`**

---

### Question 2 — Communications ❌ ENDPOINT INEXISTANT + ⚠️ PAS DE TRACKING LU/NON-LU

**Statut serveur :** La table `communications` existe (id, tenant_id, title, content_html, published_at) mais **aucun endpoint API** et **aucune colonne de suivi lecture** (pas de `read_by`, `read_at`).

**URL liste :** `GET /api/communications.php` — à créer
**Format de réponse prévu :**
```json
{
  "communications": [
    {
      "id": 5,
      "title": "Présentation",
      "content_html": "<!DOCTYPE html>...",
      "published_at": "2026-03-11 16:46:28"
    }
  ]
}
```

**Badge count :** Impossible côté serveur pour l'instant (pas de tracking lu/non-lu en BDD).
**Recommandation Android :** Stocker localement le `id` de la dernière communication vue.
Badge = nombre de communications avec `id > derniere_vue_id`.

**➡ Nicolas : demande la création de `/api/communications.php`**

---

### Question 3 — Token FCM ❌ ENDPOINT INEXISTANT

**Statut serveur :** La table `fcm_tokens` existe (user_id, token, updated_at) mais **aucun endpoint API**.

**URL :** `POST /api/fcm-token.php` — à créer
**Body attendu :**
```json
{ "fcm_token": "fkVJGL9TRu-..." }
```
**Réponse prévue :**
```json
{ "saved": true }
```
L'endpoint fera un `INSERT ... ON DUPLICATE KEY UPDATE token = ?` basé sur `user_id` du JWT.

**➡ Nicolas : demande la création de `/api/fcm-token.php`**

---

### Question 4 — Thème visuel ❌ ENDPOINT INEXISTANT (table OK)

**Statut serveur :** La table `app_theme` existe avec les données du tenant Decube :
```
toolbar_color : #4A154B
button_color  : #4A154B
card_bg_color : #FFFFFF
text_color    : #000000
```
Mais **aucun endpoint API** `/Theme/GetTheme.php` ou équivalent.

**URL :** `GET /api/theme.php` — à créer
**Réponse prévue :**
```json
{
  "theme": {
    "toolbar_color": "#4A154B",
    "button_color":  "#4A154B",
    "card_bg_color": "#FFFFFF",
    "text_color":    "#000000"
  }
}
```

**➡ Nicolas : demande la création de `/api/theme.php`**

---

### Question 5 — Profil utilisateur / me.php ❌ ENDPOINT INEXISTANT

**Statut serveur :** `/api/me.php` **n'existe pas**.

**URL GET :** `GET /api/me.php` — à créer
**Réponse prévue :**
```json
{
  "user": {
    "user_id": 2,
    "username": "nicolas.goossens@hotmail.com",
    "first_name": "Nicolas",
    "last_name": "Goossens",
    "phone": "",
    "company_id": 2,
    "company_name": "Monnaie SA"
  }
}
```

**URL POST (modifier profil) :** `POST /api/me.php` — à créer
**Body :**
```json
{ "first_name": "Nicolas", "last_name": "Goossens", "phone": "0495/24.81.74" }
```

**Changement de mot de passe :** `POST /api/me.php` avec `action: "change_password"`
```json
{ "action": "change_password", "current_password": "...", "new_password": "..." }
```

**➡ Nicolas : demande la création de `/api/me.php` (GET + POST)**

---

### Résumé — Endpoints créés ✅

| Endpoint | Statut |
|----------|--------|
| `GET /api/ticket.php?id=X` | ✅ Créé |
| `GET /api/me.php` | ✅ Créé |
| `POST /api/me.php` | ✅ Créé |
| `GET /api/communications.php` | ✅ Créé |
| `POST /api/fcm-token.php` | ✅ Créé |
| `GET /api/theme.php` | ✅ Créé |

**Statut :** ✅ Tous les endpoints sont disponibles — En attente de validation Android

---

## [Backend → Android] 2026-03-30 22:00 — ÉTAT INITIAL POST-MIGRATION VPS

**Type :** Migration
**Impact Android :** Obligatoire

---

### Base URL

```
https://admin.fleetapp.be
```

Les deux domaines `admin.fleetapp.be` et `decube.fleetapp.be` pointent sur le même serveur.
**Utiliser exclusivement `https://admin.fleetapp.be`** (APP_URL officielle).

---

### Authentification

Tous les endpoints (sauf `/api/login.php`) nécessitent :
```
Authorization: Bearer <JWT>
```
Le header fonctionne nativement — aucun workaround requis.

---

### Endpoints disponibles

#### POST /api/login.php
Authentification utilisateur Android.
```json
Body  : { "username": "email@exemple.com", "password": "motdepasse" }
200 OK: { "token": "...", "user_id": 2, "nom": "Nicolas Goossens", "username": "nicolas.goossens@hotmail.com" }
401   : { "error": "Identifiants invalides" }
```
⚠️ Pas de champ `"success"` — succès = HTTP 200.

---

#### GET /api/vehicles.php
Liste des véhicules accessibles par l'utilisateur (filtrée par groupes).
```json
200 OK: {
  "vehicles": [
    {
      "vehicle_id": 1,
      "plate": "1-XHS-856",
      "brand": "BMW",
      "model": "X3 20d",
      "fuel_type": "Diesel",
      "category_id": 2,
      "company_id": 2,
      "department": "Batiment",
      "status": "active",
      "ct_valid_until": "2027-01-09",
      "state_id": 6
    }
  ]
}
```

---

#### GET /api/vehicle.php?id={vehicle_id}
Détail d'un véhicule + URLs des documents PDF.
```json
200 OK: {
  "vehicle": {
    "vehicle_id": 1,
    "plate": "1-XHS-856",
    "brand": "BMW",
    "model": "X3 20d",
    "fuel_type": "Diesel",
    "department": "Batiment",
    "company_id": 2,
    "company_name": "Monnaie SA",
    "status": "active",
    "ct_valid_until": "2027-01-09",
    "rdv_ct": null,
    "category_id": 2,
    "state_id": 6,
    "doc_ct_url": "https://admin.fleetapp.be/admin/uploads/vehicles/1-XHS-856/doc_ct.pdf",
    "doc_assurance_url": "https://admin.fleetapp.be/admin/uploads/vehicles/1-XHS-856/doc_assurance.pdf",
    "doc_immat_url": null,
    "doc_coc_url": null
  }
}
```
⚠️ Remplace `/getVehicleDetail.php?id=X` — plus de wrapper `{ "success": true, "data": {} }`.
Les URLs de documents sont `null` si le fichier n'existe pas (plus de chaîne vide).

---

#### GET /api/contacts.php
Liste des contacts d'urgence/utiles du tenant.
```json
200 OK: {
  "contacts": [
    { "id": 1, "name": "Touring secours", "phone": "+32 78 17 81 78", "description": "Assistance routière" },
    { "id": 4, "name": "Nicolas Goossens", "phone": "0495/24.81.74",  "description": "Fleet Manager" }
  ]
}
```
⚠️ Remplace `/GetContacts.php`.

---

#### GET /api/tickets.php
Liste des tickets créés par l'utilisateur connecté.
```json
200 OK: {
  "tickets": [
    {
      "id": 1,
      "public_code": "E25FF499-443",
      "vehicle_id": 2,
      "title": "flat_tire",
      "description": null,
      "priority": "MEDIUM",
      "status": "NEW",
      "created_at": "2025-01-15 10:23:00",
      "updated_at": "2025-01-15 10:23:00",
      "plate": "2-CGP-516",
      "brand": "BMW",
      "model": "X3 20d"
    }
  ]
}
```
⚠️ Remplace `/Tickets/ListTickets.php`.

---

#### POST /api/tickets.php
Créer un nouveau ticket.
```json
Body    : { "vehicle_id": 1, "title": "flat_tire", "description": "Optionnel", "priority": "MEDIUM" }
priority: "LOW" | "MEDIUM" | "HIGH" (défaut MEDIUM)
201 Created: {
  "ticket": {
    "id": 31, "public_code": "A1B2C3D4-456",
    "vehicle_id": 1, "title": "flat_tire",
    "description": null, "priority": "MEDIUM", "status": "NEW"
  }
}
400: { "error": "vehicle_id et title sont requis" }
```

---

#### GET /api/issue-types.php
Liste des types de problèmes pour la création de ticket.
```json
200 OK: {
  "issue_types": [
    { "key": "flat_tire",    "label": "Pneu crevé" },
    { "key": "battery",      "label": "Batterie" },
    { "key": "engine_light", "label": "Voyant moteur" },
    { "key": "glass",        "label": "Bris de glace" },
    { "key": "accident",     "label": "Accident" },
    { "key": "fuel",         "label": "Carburant" },
    { "key": "other",        "label": "Autre" }
  ]
}
```

---

#### GET /api/vehicles-search.php?q={texte}
Recherche de véhicule par plaque (autocomplete, min 2 caractères).
Résultats filtrés par les groupes de l'utilisateur.
```json
200 OK: {
  "vehicles": [
    { "vehicle_id": 1, "plate": "1-XHS-856", "brand": "BMW", "model": "X3 20d" }
  ]
}
```

---

#### POST /api/ticket-photo.php
Upload d'une photo pour un ticket. Multipart/form-data.
```
Fields : ticket_id (int) + photo (fichier image)
Formats: JPEG, PNG, WebP — max 10 Mo
201 Created: {
  "photo": {
    "id": 1,
    "url": "https://admin.fleetapp.be/uploads/tickets/31_2_abc123.jpg",
    "filename": "31_2_abc123.jpg"
  }
}
```

---

#### GET /api/join.php?token={token}
Vérification d'un token QR code avant onboarding.

#### POST /api/join.php
Lier un utilisateur à une société via token QR + code 4 chiffres.
```json
Body: { "token": "...", "code": "1234", "jwt": "..." }
```

---

### Codes d'erreur communs

| HTTP | Signification |
|------|--------------|
| 200  | Succès |
| 201  | Ressource créée |
| 400  | Paramètre manquant ou invalide |
| 401  | JWT absent, invalide ou expiré |
| 403  | Accès refusé (hors périmètre groupe) |
| 404  | Ressource introuvable |
| 405  | Mauvaise méthode HTTP |
| 413  | Fichier trop lourd |
| 415  | Format de fichier non supporté |

---

### Correspondance anciens → nouveaux endpoints

| Ancien (mutualisé) | Nouveau (VPS) |
|--------------------|---------------|
| `/api/login.php` | `/api/login.php` ✅ même chemin |
| `/getVehicles.php` | `/api/vehicles.php` |
| `/getVehicleDetail.php?id=X` | `/api/vehicle.php?id=X` |
| `/GetContacts.php` | `/api/contacts.php` |
| `/Tickets/ListTickets.php` | `/api/tickets.php` (GET) |
| `/Tickets/CreateTicket.php` | `/api/tickets.php` (POST) |
| `/Tickets/UploadPhoto.php` | `/api/ticket-photo.php` |
| *(inexistant)* | `/api/issue-types.php` |
| *(inexistant)* | `/api/vehicles-search.php?q=` |

**Statut :** ⏳ En attente d'adaptation Android
