# Plan d'implémentation - SOO API

## 1. Vue d'ensemble

**Projet** : SOO API  
**Objectif** : Transformer l'architecture modulaire existante (PlatformAPI) en une API Laravel dédiée à la gestion import/export de données, avec gestion douanière, expéditions, facturation, documents associés, et contrôle d'accès par rôles.  
**Base de départ** : Laravel 12 + React + architecture modulaire `nwidart/laravel-modules` (9 modules existants).  
**Approche** : API-first, avec une interface admin React minimale et un portail client optionnel.  
**Version cible** : `0.1` (MVP), puis `1.1` (modules reportés).

---

## 2. Décisions architecturales clés

| Sujet | Décision | Justification |
|---|---|---|
| **Authentification** | JWT (tymon/jwt-auth) pour les sessions web/app + Sanctum pour les clés API / intégrations | JWT stateless pour le front React, Sanctum pour les tokens d'accès programmatiques. |
| **Multi-tenant** | Suppression du concept `Projects` | Les données sont liées directement aux clients/utilisateurs. |
| **Documents** | Création d'un module `Documents` dans `Core` | Gestion centralisée des pièces jointes polymorphes pour toutes les entités. |
| **Frontend** | API + interface admin React minimale | Conserver React pour l'admin, mais la priorité est l'API. |
| **Base de données** | MySQL / MariaDB | Standard Laravel, performant pour le métier transactionnel. |
| **Versionnement API** | `/api/v1/` | Permet l'évolution sans rupture. |
| **Format de réponse** | Envelope standard `{data, meta, links}` | Cohérence des réponses API et compatibilité pagination. |
| **Import/Export** | Endpoints API sécurisés, traités en file d'attente | Gestion des volumes et suivi de progression. |
| **Notifications** | Email + in-app selon les rôles | Alertes sur les changements de statut critiques. |
| **Comptes clients** | Optionnels, activables par l'admin | Un client peut être une simple entité ou un utilisateur connecté. |

---

## 3. Phase 0 — Restructuration des modules (prototypage / fondation)

### 3.1 Modules à supprimer (non utilisés par SOO)

Ces modules seront désactivés dans `modules_statuses.json`, puis supprimés physiquement une fois la migration des données inutiles confirmée.

| Module | Statut |
|---|---|
| `Projects` | Supprimer |
| `Collections` | Supprimer |
| `Content` | Supprimer |
| `Assets` | Supprimer (remplacé par `Documents`) |
| `Webhooks` | Supprimer (à réintroduire en V1.1 si besoin) |
| `Templates` | Supprimer |

### 3.2 Modules à conserver et adapter

| Module | Adaptation |
|---|---|
| `Core` | Conserver la base (middleware, providers). Supprimer `ProjectAccess`. Ajouter le module `Documents` comme sous-module métier partagé. |
| `Auth` | Adapter les contrôleurs pour supporter JWT (login/refresh/logout) ET Sanctum (création/révocation de tokens API). Supprimer les pages web non utilisées. |
| `UserManagement` | Adapter `User` avec rôles SOO. Ajouter `Client` comme entité liée optionnellement à un utilisateur. |

### 3.3 Modules à créer

| Module | Phase |
|---|---|
| `Core\Documents` | Phase 1 (géré dans Core) |
| `Douane` | Phase 2 |
| `Expedition` | Phase 2 |
| `Facturation` | Phase 2 |
| `Stock` | V1.1 |
| `Flotte` | V1.1 |

### 3.4 Structure cible des modules

```
Modules/
├── Core/
│   ├── app/
│   │   ├── Http/Middleware/           # Middleware partagés
│   │   ├── Providers/
│   │   └── Documents/                  # Sous-module Documents
│   │       ├── Models/Document.php
│   │       ├── Services/DocumentService.php
│   │       └── Http/Controllers/Api/DocumentController.php
│   ├── database/migrations/
│   └── routes/api.php
├── Auth/
│   ├── app/Http/Controllers/Api/
│   │   ├── JwtAuthController.php       # login / refresh / logout / me
│   │   └── ApiTokenController.php      # Sanctum tokens
│   └── routes/api.php
├── UserManagement/
│   ├── app/Models/
│   │   ├── User.php
│   │   └── Client.php
│   ├── app/Http/Controllers/Api/
│   │   ├── UserController.php
│   │   ├── RoleController.php
│   │   ├── PermissionController.php
│   │   └── ClientController.php
│   └── database/migrations/
├── Douane/
│   ├── app/Models/
│   │   ├── DossierDouanier.php
│   │   ├── DeclarationDouane.php
│   │   └── StatutDouanier.php
│   ├── app/Http/Controllers/Api/
│   │   └── DossierDouanierController.php
│   └── database/migrations/
├── Expedition/
│   ├── app/Models/
│   │   ├── Expedition.php
│   │   ├── Cargaison.php
│   │   ├── EtapeExpedition.php
│   │   └── Itineraire.php
│   ├── app/Http/Controllers/Api/
│   │   └── ExpeditionController.php
│   └── database/migrations/
├── Facturation/
│   ├── app/Models/
│   │   ├── Facture.php
│   │   ├── PaiementInterne.php
│   │   └── Avoir.php
│   ├── app/Http/Controllers/Api/
│   │   └── FactureController.php
│   └── database/migrations/
├── Stock/          (V1.1)
├── Flotte/         (V1.1)
```

---

## 4. Phase 1 — Socle (2-3 semaines)

### 4.1 Dépendances à ajouter

```bash
composer require tymon/jwt-auth
composer require maatwebsite/excel        # ou spatie/simple-excel selon préférence
composer require predis/predis            # si Redis pour les queues
composer require laravel/scribe           # documentation API
```

### 4.2 Configuration de l'authentification

- **JWT** : configurer `config/jwt.php`, générer les clés, adapter `config/auth.php` avec le guard `api` basé sur JWT.
- **Sanctum** : activer les tokens d'accès personnels. Endpoint dédié pour créer/révoquer des tokens API (`/api/v1/auth/api-tokens`).
- **Double guard** :
  - `api` → JWT pour les utilisateurs front React.
  - `api-token` → Sanctum pour les intégrations tierces.

### 4.3 Rôles et permissions (Spatie)

Rôles SOO à créer via seeders :

| Rôle | Accès principal |
|---|---|
| `super-admin` | Accès total, gestion des utilisateurs/rôles |
| `admin` / `direction` | Vue globale, rapports, validation dossiers/factures |
| `agent-import-export` | Module Douane + Expedition (création/suivi) |
| `comptabilite` | Module Facturation (lecture/écriture) |
| `chauffeur-logistique` | Module Flotte (ses affectations), mise à jour statuts expédition |
| `client` | Portail limité : suivi de ses expéditions/factures |

Permissions (exemples) : `dossiers.view`, `dossiers.create`, `dossiers.validate`, `expeditions.view`, `expeditions.update_status`, `factures.view`, `factures.create`, `clients.view`, `imports.run`, `exports.run`, `users.manage`, etc.

### 4.4 Module UserManagement enrichi

- `User` : garde `HasRoles`, ajoute `client_id` (nullable), `is_active`, `last_login_at`.
- `Client` : entité avec `code`, `nom`, `email`, `telephone`, `adresse`, `pays`, `numero_contribuable`, `user_id` (nullable pour activer le portail).
- Relations : `User` → `belongsTo(Client)`; `Client` → `hasOne(User)`, `hasMany(DossierDouanier)`, etc.

### 4.5 Module Documents (Core)

- `Document` polymorphe : `documentable_type`, `documentable_id`, `type`, `nom_fichier`, `chemin`, `mime`, `taille`, `meta`, `uploaded_by`.
- `DocumentService` : upload, suppression, liens signés temporaires.
- Endpoints API : CRUD documents liés à n'importe quelle entité.

### 4.6 Standards API

- Envelope : `App\Http\Resources\ApiResponse` avec `data`, `message`, `errors`, `meta`, `links`.
- Codes HTTP standard.
- Gestion des exceptions centralisée via `app/Exceptions/Handler.php`.
- Pagination Laravel par défaut intégrée dans l'envelope.
- Rate limiting différencié par guard (JWT vs Sanctum).

### 4.7 Interface admin React minimale

- Pages : login, dashboard, utilisateurs, rôles, clients, profil.
- Utilisation de l'API `v1` côté front.
- Pas de pages complexes métier dans le MVP : l'admin reste utilisable via API/Postman, et le React admin se concentre sur le socle.

---

## 5. Phase 2 — MVP cœur métier (5-6 semaines)

### 5.1 Module Douane

#### Modèles
- `DossierDouanier` : `numero`, `client_id`, `type_operation` (import/export), `pays_origine`, `pays_destination`, `statut`, `date_creation`, `date_cloture`, `agent_id`, `montant_estime`, `devise`, `observations`.
- `DeclarationDouane` : `dossier_id`, `numero_declaration`, `date_declaration`, `bureau_douane`, `montant_taxes`, `statut`.
- `StatutDouanier` : `dossier_id`, `statut`, `commentaire`, `created_by`, `created_at` (historique des statuts).

#### Endpoints API
```
GET    /api/v1/dossiers-douaniers
POST   /api/v1/dossiers-douaniers
GET    /api/v1/dossiers-douaniers/{id}
PUT    /api/v1/dossiers-douaniers/{id}
DELETE /api/v1/dossiers-douaniers/{id}
PATCH  /api/v1/dossiers-douaniers/{id}/statut        # agent / admin
GET    /api/v1/dossiers-douaniers/{id}/statuts       # historique
GET    /api/v1/dossiers-douaniers/{id}/documents
POST   /api/v1/dossiers-douaniers/{id}/documents
```

### 5.2 Module Expedition

#### Modèles
- `Expedition` : `numero`, `client_id`, `dossier_douanier_id` (nullable), `mode_transport`, `incoterm`, `pays_depart`, `pays_arrivee`, `adresse_depart`, `adresse_arrivee`, `statut`, `date_expedition`, `date_arrivee_estimee`, `date_arrivee_reelle`, `agent_id`.
- `Cargaison` : `expedition_id`, `description`, `quantite`, `poids`, `volume`, `type_marchandise`, `valeur_declaree`.
- `EtapeExpedition` : `expedition_id`, `nom`, `statut`, `date_prevue`, `date_effective`, `lieu`, `commentaire`, `created_by`.
- `Itineraire` : `expedition_id`, `ordre`, `lieu`, `date_arrivee`, `date_depart`.

#### Endpoints API
```
GET    /api/v1/expeditions
POST   /api/v1/expeditions
GET    /api/v1/expeditions/{id}
PUT    /api/v1/expeditions/{id}
DELETE /api/v1/expeditions/{id}
GET    /api/v1/expeditions/{id}/cargaisons
POST   /api/v1/expeditions/{id}/cargaisons
PATCH  /api/v1/expeditions/{id}/statut
POST   /api/v1/expeditions/{id}/etapes
PUT    /api/v1/expeditions/{id}/etapes/{etape_id}
GET    /api/v1/expeditions/{id}/documents
POST   /api/v1/expeditions/{id}/documents
```

### 5.3 Module Facturation

#### Modèles
- `Facture` : `numero`, `client_id`, `type` (facture, avoir), `statut`, `date_emission`, `date_echeance`, `montant_ht`, `montant_tva`, `montant_ttc`, `devise`, `dossier_douanier_id`, `expedition_id`, `created_by`.
- `LigneFacture` : `facture_id`, `description`, `quantite`, `prix_unitaire`, `montant`, `taux_tva`.
- `PaiementInterne` : `facture_id`, `date_paiement`, `montant`, `mode_paiement`, `reference`, `created_by`.
- `Avoir` : `numero`, `facture_id`, `client_id`, `montant`, `motif`, `statut`.

#### Endpoints API
```
GET    /api/v1/factures
POST   /api/v1/factures
GET    /api/v1/factures/{id}
PUT    /api/v1/factures/{id}
DELETE /api/v1/factures/{id}
PATCH  /api/v1/factures/{id}/statut                  # admin/comptabilite
POST   /api/v1/factures/{id}/lignes
POST   /api/v1/factures/{id}/paiements
GET    /api/v1/factures/{id}/paiements
GET    /api/v1/factures/{id}/documents
POST   /api/v1/factures/{id}/documents
POST   /api/v1/avoirs
```

### 5.4 Import / Export API

#### Bibliothèques
- `maatwebsite/excel` (ou `spatie/simple-excel`) pour la lecture/écriture CSV/XLSX.

#### Traitement asynchrone
- `ImportJob` : lecture du fichier, validation ligne par ligne, insertion en base, rapport d'erreurs.
- `ExportJob` : génération du fichier, stockage temporaire, notification de disponibilité.
- `Import` / `Export` models : `id`, `type`, `status`, `file_path`, `result_path`, `errors`, `created_by`, `created_at`, `completed_at`.

#### Endpoints API
```
POST   /api/v1/imports/{type}              # type: clients, dossiers, expeditions, factures
GET    /api/v1/imports/{id}
GET    /api/v1/imports/{id}/download        # rapport d'erreurs
GET    /api/v1/exports/{type}
POST   /api/v1/exports/{type}              # avec filtres dans le body
GET    /api/v1/exports/{id}
GET    /api/v1/exports/{id}/download
GET    /api/v1/templates/{type}             # modèle CSV/Excel vierge
```

#### Sécurité
- Vérification des permissions `imports.run` / `exports.run`.
- Validation stricte du type MIME et de l'extension.
- Quotas/taille max configurables.

### 5.5 Notifications

- Événements : `DossierDouanierStatusChanged`, `ExpeditionStatusChanged`, `FactureCreated`, `FacturePaid`.
- Listeners : envoi d'email (`Mail::queue`) + création d'une notification in-app (`database` channel).
- Notification in-app model : `user_id`, `type`, `title`, `message`, `data`, `read_at`, `created_at`.
- Endpoint : `GET /api/v1/notifications`, `PATCH /api/v1/notifications/{id}/read`.

---

## 6. Phase 3 — Stabilisation & lancement (2-3 semaines)

### 6.1 Tests

- Tests unitaires Pest pour les services métier (Douane, Expedition, Facturation, Import/Export).
- Tests d'intégration API pour chaque module (authentification, permissions, CRUD, statuts).
- Tests des jobs d'import/export avec faux fichiers.
- Couverture des rôles : vérifier que chaque rôle accède uniquement à ses ressources.

### 6.2 Qualité

- `laravel/pint` : linting PHP.
- ESLint / Prettier : front React.
- Scribe : génération de la documentation API publique.

### 6.3 Migration des données Excel

Même si le démarrage est à blanc, préparer l'outil :
- Commande `php artisan soo:import-legacy` (ou endpoint admin) capable d'ingérer un fichier Excel standardisé.
- Mapping de colonnes configurable.
- Validation des doublons et rapport d'erreurs.

### 6.4 Production

- Configuration `.env` production (APP_ENV=production, cache config/route/view).
- Queue worker supervisé (Redis ou database).
- Horizon (optionnel) pour la surveillance des queues.
- HTTPS forcé, CORS restrictif, rate limiting agressif sur les endpoints publics.
- Logs structurés (canaux Laravel).
- Sauvegardes automatisées.

---

## 7. V1.1 — Modules reportés (post-MVP)

| Module | Description |
|---|---|
| `Stock` | Entrepôts, articles, mouvements de stock, réceptions/expéditions. |
| `Flotte` | Véhicules, chauffeurs, affectations, maintenance, disponibilité. |
| `Suivi GPS temps réel` | Intégration d'un service GPS (API externe) lié aux expéditions. |
| `Paiement en ligne` | Mobile Money / carte via passerelle de paiement (non interne). |

---

## 8. Matrice des rôles et permissions (MVP)

| Permission | Super Admin | Admin | Agent I/E | Comptabilité | Chauffeur/Logistique | Client |
|---|---|---|---|---|---|---|
| `users.manage` | X | X | - | - | - | - |
| `roles.manage` | X | - | - | - | - | - |
| `clients.manage` | X | X | X | - | - | - |
| `dossiers.view.all` | X | X | X | - | - | - |
| `dossiers.view.own` | - | - | - | - | - | X (si client lié) |
| `dossiers.create` | X | X | X | - | - | - |
| `dossiers.update` | X | X | X | - | - | - |
| `dossiers.validate` | X | X | - | - | - | - |
| `expeditions.view.all` | X | X | X | - | X (affectations) | - |
| `expeditions.view.own` | - | - | - | - | - | X (si client lié) |
| `expeditions.create` | X | X | X | - | - | - |
| `expeditions.update_status` | X | X | X | - | X | - |
| `factures.view.all` | X | X | - | X | - | - |
| `factures.view.own` | - | - | - | - | - | X (si client lié) |
| `factures.create` | X | X | - | X | - | - |
| `factures.pay` | X | X | - | X | - | - |
| `imports.run` | X | X | X | - | - | - |
| `exports.run` | X | X | X | X | - | - |
| `documents.view.all` | X | X | X | X | X | - |
| `documents.view.own` | - | - | - | - | - | X (si client lié) |

**Règle de filtrage client** : les requêtes du rôle `client` doivent automatiquement filtrer sur `client_id = user.client_id`.

---

## 9. Modèle de données relationnel (MVP)

```
users
├── id
├── client_id (nullable)
├── name, email, email_verified_at, password
├── is_active, last_login_at
├── created_at, updated_at

clients
├── id
├── code, nom, email, telephone, adresse, pays
├── numero_contribuable, numero_registre
├── user_id (nullable, pour activer le portail)
├── created_at, updated_at

documents (polymorphic)
├── id
├── documentable_type, documentable_id
├── type (facture, piece_identite, bon_livraison, etc.)
├── nom_fichier, chemin, mime, taille, meta (JSON)
├── uploaded_by
├── created_at, updated_at

dossiers_douaniers
├── id, numero, client_id, agent_id
├── type_operation (import/export), pays_origine, pays_destination
├── statut, date_creation, date_cloture
├── montant_estime, devise, observations
├── created_at, updated_at

declarations_douane
├── id, dossier_douanier_id, numero_declaration
├── date_declaration, bureau_douane, montant_taxes, statut

statuts_douaniers
├── id, dossier_douanier_id, statut, commentaire, created_by

expeditions
├── id, numero, client_id, dossier_douanier_id (nullable), agent_id
├── mode_transport, incoterm
├── pays_depart, pays_arrivee, adresse_depart, adresse_arrivee
├── statut, date_expedition, date_arrivee_estimee, date_arrivee_reelle

cargaisons
├── id, expedition_id, description, quantite, poids, volume
├── type_marchandise, valeur_declaree

etapes_expeditions
├── id, expedition_id, nom, statut, ordre
├── date_prevue, date_effective, lieu, commentaire, created_by

itineraires
├── id, expedition_id, ordre, lieu, date_arrivee, date_depart

factures
├── id, numero, client_id, type (facture/avoir), statut
├── date_emission, date_echeance, montant_ht, montant_tva, montant_ttc, devise
├── dossier_douanier_id, expedition_id, created_by

lignes_factures
├── id, facture_id, description, quantite, prix_unitaire, montant, taux_tva

paiements_internes
├── id, facture_id, date_paiement, montant, mode_paiement, reference, created_by

avoirs
├── id, numero, facture_id, client_id, montant, motif, statut, created_by

imports / exports
├── id, type, status, file_path, result_path, errors, created_by, completed_at

notifications
├── id, user_id, type, title, message, data (JSON), read_at, created_at
```

---

## 10. Flux d'authentification

### 10.1 JWT (React Admin / App mobile)

```
POST /api/v1/auth/login     → email/password → retourne access_token + refresh_token
POST /api/v1/auth/refresh   → refresh_token → nouveau access_token
POST /api/v1/auth/logout    → invalide le token
GET  /api/v1/auth/me        → profil utilisateur + rôles/permissions
```

### 10.2 Sanctum (API clés / intégrations)

```
POST /api/v1/auth/api-tokens      → créer un token (nom + abilities)
GET  /api/v1/auth/api-tokens      → lister les tokens
DELETE /api/v1/auth/api-tokens/{id} → révoquer un token
```

---

## 11. Stratégie de sécurité

- Guards séparés pour JWT et Sanctum.
- Middleware `role` et `permission` de Spatie sur les routes API.
- Rate limiting : 60 requêtes/minute par JWT user, 1000/jour par token Sanctum (configurable).
- CORS configuré pour les domaines autorisés uniquement.
- Hashage des mots de passe avec Bcrypt (par défaut Laravel).
- Clés JWT et Sanctum stockées dans `.env` et jamais commitées.
- Upload de documents : validation MIME, taille maximale, stockage privé (local/S3), accès via liens signés.
- Imports : validation des en-têtes, sandbox pour les fichiers suspects, rollback possible via transaction.

---

## 12. Frontend React minimal (Phase 1)

Pages à conserver/développer :
- `/login` : formulaire JWT.
- `/dashboard` : statistiques globales (Super Admin/Admin).
- `/users` : CRUD utilisateurs.
- `/roles` : gestion des rôles/permissions.
- `/clients` : CRUD clients.
- `/profile` : profil et tokens API (Sanctum).
- Notifications in-app (badge + liste).

Pages métier (Phase 2) : minimal, lecture seule ou formulaires simples pour les tests internes. L'objectif principal reste l'API.

---

## 13. Commandes et outils recommandés

```bash
# Création d'un module
php artisan module:make Douane

# Génération des resources API
php artisan module:make-controller Api/DossierDouanierController Douane
php artisan module:make-request DossierDouanierRequest Douane
php artisan module:make-resource DossierDouanierResource Douane

# Tests
php artisan test
./vendor/bin/pest

# Documentation API
php artisan scribe:generate

# Linting
./vendor/bin/pint
npm run lint
npm run format:check

# Queue (dev)
php artisan queue:work
```

---

## 14. Planning indicatif

| Phase | Durée | Livrables |
|---|---|---|
| **Phase 0** | 1 semaine | Modules supprimés, structure SOO en place, socle fonctionnel. |
| **Phase 1** | 2-3 semaines | Auth JWT+Sanctum, rôles/permissions, users/clients, documents, standards API, admin React minimal. |
| **Phase 2** | 5-6 semaines | Modules Douane, Expedition, Facturation, import/export async, notifications. |
| **Phase 3** | 2-3 semaines | Tests, docs Scribe, outils de migration, mise en production. |
| **V1.1** | Post-MVP | Stock, Flotte, GPS, paiement en ligne. |

---

## 15. Variables d'environnement à ajouter

```env
# Base de données
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=soo_api
DB_USERNAME=root
DB_PASSWORD=

# JWT
JWT_SECRET=
JWT_ALGO=HS256
JWT_TTL=60
JWT_REFRESH_TTL=20160

# Sanctum
SANCTUM_STATEFUL_DOMAINS=localhost,localhost:3000
SESSION_DOMAIN=localhost

# Queue
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

# Fichiers
FILESYSTEM_DISK=local
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=
AWS_BUCKET=

# Mail (notifications)
MAIL_MAILER=smtp
MAIL_HOST=
MAIL_PORT=
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=
MAIL_FROM_ADDRESS=
MAIL_FROM_NAME="SOO API"
```

---

## 16. Points de vigilance

- **Ne pas conserver** les tables `projects`, `collections`, `content_entries`, `assets`, `webhooks`, `templates` dans le MVP.
- **Conserver la compatibilité** avec `nwidart/laravel-modules` : mettre à jour `modules_statuses.json` et `composer.json` après suppression des modules.
- **Tester les permissions** dès le début : elles sont critiques pour le portail client.
- **Prévoir l'export** dès la conception des tables pour éviter les refactors coûteux.
- **Séparer** clairement les guards JWT et Sanctum dans `config/auth.php` pour éviter les conflits.

---

## 17. Livrables du plan

1. Ce document `ncore/plan-implementation-soo.md`.
2. Les fichiers de conception détaillés par module (à créer au moment de l'implémentation) :
   - `ncore/conception-douane.md`
   - `ncore/conception-expedition.md`
   - `ncore/conception-facturation.md`
   - `ncore/conception-import-export.md`
   - `ncore/conception-auth.md`
3. Collection Postman / documentation Scribe de l'API.
4. Seeders de rôles/permissions et d'utilisateurs de test.
