rayhan-erp/Livrables/rapport-projet.md

558 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "Rapport de Projet — ERP SUARL Rayhan"
subtitle: "Projet de Fin d'Études — Ali Guennari"
author: "Ali Guennari"
date: "Avril 2026"
lang: fr
---
# Rapport de Projet de Fin d'Études
## ERP Sur Mesure pour SUARL Rayhan
**Étudiant :** Ali Guennari
**Entreprise d'accueil :** SUARL Rayhan — Plasturgie, Tataouine, Tunisie
**Encadrant académique :** À compléter
**Encadrant professionnel :** À compléter
**Année universitaire :** 2025 / 2026
---
# Chapitre 1 — Présentation du Projet
## 1.1 Contexte
SUARL Rayhan est une entreprise tunisienne spécialisée dans la fabrication d'emballages plastiques (sacs Bertel, sacs poubelles, sacs alimentaires, film rétractable) implantée à Tataouine. Face à une gestion manuelle de ses processus métier — achats, ventes, production, stock — la direction a exprimé le besoin d'un système d'information intégré permettant de centraliser et automatiser ces opérations.
## 1.2 Objectif du Projet
Ce projet de fin d'études consiste à concevoir et développer un **ERP (Enterprise Resource Planning) sur mesure**, adapté aux spécificités de SUARL Rayhan, couvrant :
- La gestion du référentiel articles (matières premières, produits semi-finis, produits finis)
- Le cycle d'achat complet (commandes fournisseurs → bons de réception → mise à jour du stock)
- Le cycle de vente complet (commandes clients → bons de livraison → sortie de stock)
- La gestion de la production (nomenclatures BOM, ordres de fabrication)
- Le suivi des stocks en temps réel avec alertes
- Un tableau de bord KPI pour la direction
## 1.3 Périmètre Fonctionnel
| Module | Description |
|--------|-------------|
| Authentification | Connexion sécurisée avec rôles différenciés |
| Articles | Gestion du catalogue (MP, PSF, PF) |
| Clients & Fournisseurs | Annuaire des tiers commerciaux |
| Cycle Achat | Commande → Réception → Stock |
| Cycle Vente | Commande → Livraison → Stock |
| Production | BOM + Ordres de Fabrication |
| Stock | Mouvements, historique, alertes seuil minimum |
| Tableau de bord | KPIs temps réel pour le PDG |
---
# Chapitre 2 — Architecture Technique
## 2.1 Stack Technologique
| Couche | Technologie | Version |
|--------|-------------|---------|
| Backend API | Spring Boot | 3.2.5 |
| Langage | Java | 17 LTS |
| Sécurité | Spring Security + JWT | JJWT 0.12.5 |
| Persistance | Spring Data JPA / Hibernate | 6.4.4 |
| Base de données | MySQL | 8.0 |
| Conteneurisation | Docker + Docker Compose | — |
| Frontend (à venir) | Flutter | 3.x |
## 2.2 Architecture N-Tiers
L'API suit rigoureusement le patron d'architecture **Controller → Service → Repository → Model** :
```
┌─────────────────────────────────────────────────────────┐
│ Application Flutter (Client) │
└─────────────────────┬───────────────────────────────────┘
│ HTTP/HTTPS (JWT Bearer Token)
┌─────────────────────────────────────────────────────────┐
│ API REST Spring Boot (Port 8090) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Controller│→ │ Service │→ │Repository│ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ │
│ │ JPA / │ │
│ │Hibernate │ │
└──────────────────────────────┴────┬─────┴──────────────┘
│ JDBC
┌─────────────────────┐
│ MySQL 8 │
│ rayhan_erp_db │
└─────────────────────┘
```
## 2.3 Sécurité — Mécanisme JWT
Le système utilise une authentification **stateless** basée sur les JSON Web Tokens :
1. Le client envoie ses identifiants à `POST /api/auth/signin`
2. Le serveur valide et retourne un JWT signé (valable 24h)
3. Le client inclut `Authorization: Bearer <token>` dans chaque requête
4. Le filtre `AuthTokenFilter` intercepte et valide le token avant chaque endpoint
### Rôles et Contrôle d'Accès
| Rôle | Périmètre d'accès |
|------|-------------------|
| `ROLE_PDG` | Accès complet + tableau de bord |
| `ROLE_RESPONSABLE_VENTE` | Ventes, clients |
| `ROLE_RESPONSABLE_ACHAT` | Achats, fournisseurs |
| `ROLE_RESPONSABLE_PRODUCTION` | Production, BOM, ordres de fabrication |
| `ROLE_MAGASINIER` | Stock, mouvements de stock |
| `ROLE_RH` | Ressources humaines, paie |
Chaque endpoint est protégé par l'annotation `@PreAuthorize` :
```java
@PreAuthorize("hasAnyRole('ROLE_PDG', 'ROLE_RESPONSABLE_VENTE')")
```
## 2.4 Modèle de Données Relationnel
La base de données `rayhan_erp_db` contient les tables suivantes :
- **users / roles / user_roles** — authentification et droits
- **tiers** (table mère), **clients**, **fournisseurs** — gestion des tiers (héritage JOINED)
- **articles** — catalogue produits avec types MP / PSF / PF
- **bom_lines** — nomenclatures de production (Bill of Materials)
- **production_orders** — ordres de fabrication avec cycle PLANIFIE → LANCE → TERMINE
- **purchase_orders / purchase_order_lines** — commandes fournisseurs
- **goods_receipts / goods_receipt_lines** — bons de réception
- **sales_orders / sales_order_lines** — commandes clients
- **delivery_notes / delivery_note_lines** — bons de livraison
- **stock_movements** — historique complet de tous les mouvements de stock
---
# Chapitre 3 — Endpoints de l'API
## 3.1 Authentification
| Méthode | URL | Description |
|---------|-----|-------------|
| POST | `/api/auth/signin` | Connexion → retourne JWT |
| POST | `/api/auth/signup` | Créer un utilisateur |
## 3.2 Articles
| Méthode | URL | Rôles |
|---------|-----|-------|
| GET | `/api/articles` | Tous |
| GET | `/api/articles/{id}` | Tous |
| GET | `/api/articles/type/{type}` | Tous (MP, PF, PSF) |
| GET | `/api/articles/alertes-stock` | PDG, Magasinier, Production |
| POST | `/api/articles` | PDG, Production, Magasinier |
| PUT | `/api/articles/{id}` | PDG, Production |
| DELETE | `/api/articles/{id}` | PDG (désactivation logique) |
## 3.3 Clients & Fournisseurs
| Méthode | URL | Rôles |
|---------|-----|-------|
| GET | `/api/clients` | PDG, Vente |
| POST | `/api/clients` | PDG, Vente |
| PUT | `/api/clients/{id}` | PDG, Vente |
| GET | `/api/fournisseurs` | PDG, Achat |
| POST | `/api/fournisseurs` | PDG, Achat |
## 3.4 Cycle d'Achat
| Méthode | URL | Description |
|---------|-----|-------------|
| GET | `/api/purchase-orders` | Liste des commandes |
| POST | `/api/purchase-orders` | Créer une commande fournisseur |
| POST | `/api/purchase-orders/{id}/receive` | Réceptionner → crée BR + entre en stock |
## 3.5 Cycle de Vente
| Méthode | URL | Description |
|---------|-----|-------------|
| GET | `/api/sales-orders` | Liste des commandes |
| POST | `/api/sales-orders` | Créer une commande client |
| POST | `/api/sales-orders/{id}/deliver` | Livrer → crée BL + sort du stock |
## 3.6 Production
| Méthode | URL | Description |
|---------|-----|-------------|
| POST | `/api/production/bom` | Définir une nomenclature |
| POST | `/api/production/orders/plan` | Planifier un ordre de fabrication |
| POST | `/api/production/orders/{id}/launch` | Lancer → consomme les MP |
| POST | `/api/production/orders/{id}/complete` | Terminer → entre les PF en stock |
## 3.7 Stock & Tableau de Bord
| Méthode | URL | Description |
|---------|-----|-------------|
| GET | `/api/stock/historique/{articleId}` | Historique des mouvements |
| POST | `/api/stock/adjust` | Ajustement manuel |
| GET | `/api/dashboard` | KPIs pour le PDG |
---
# Chapitre 4 — Déploiement
## 4.1 Infrastructure
L'application est déployée via Docker Compose, accessible publiquement derrière un reverse proxy HTTPS. Deux conteneurs sont en production :
- **rayhan-mysql** — MySQL 8, base de données `rayhan_erp_db`
- **rayhan-backend** — Spring Boot, accessible sur le port **8090**
## 4.2 Docker Compose
```yaml
services:
mysql:
image: mysql:8.0
container_name: rayhan-mysql
environment:
MYSQL_DATABASE: rayhan_erp_db
volumes:
- mysql_data:/var/lib/mysql
backend:
build: ./backend
container_name: rayhan-backend
ports:
- "8090:8080"
depends_on:
mysql:
condition: service_healthy
```
## 4.3 Dockerfile — Build Multi-Étapes
```dockerfile
# Étape 1 : Compilation Maven
FROM maven:3.9.6-eclipse-temurin-17 AS build
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests
# Étape 2 : Image d'exécution légère
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=build /app/target/erp-1.0.0-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
```
## 4.4 Accès à l'Application
| Service | URL |
|---------|-----|
| API REST | https://rayhan-erp.bolbol.tn |
| Documentation Swagger UI | https://rayhan-erp.bolbol.tn/swagger-ui/index.html |
| Dépôt source (Gitea) | https://gitea.bolbol.tn/bolbol/rayhan-erp |
---
# Chapitre 5 — Tests et Validation
## 5.1 Interface Swagger UI
L'API intègre **Swagger UI** (SpringDoc OpenAPI 2.5.0), accessible depuis n'importe quel navigateur. Cette interface permet de :
- Visualiser tous les endpoints disponibles
- Tester chaque endpoint directement depuis le navigateur
- S'authentifier avec le JWT via le bouton "Authorize"
**Procédure de test :**
1. Ouvrir https://rayhan-erp.bolbol.tn/swagger-ui/index.html
2. Exécuter `POST /api/auth/signin` avec `{"username":"admin","password":"Rayhan2024!"}`
3. Copier le token de la réponse
4. Cliquer sur **Authorize 🔒** → coller le token → Authorize
5. Tester librement tous les endpoints
## 5.2 Scénario de Test Complet
| Étape | Action | Résultat attendu |
|-------|--------|-----------------|
| 1 | Connexion admin | Token JWT retourné |
| 2 | Créer article MP-HDPE | Article créé, stock = 0 |
| 3 | Créer commande fournisseur | Statut CONFIRMEE |
| 4 | Réceptionner commande | Stock MP augmente |
| 5 | Créer nomenclature BOM | Lien PF ↔ MP créé |
| 6 | Planifier + Lancer OF | Stock MP diminue (consommation) |
| 7 | Terminer OF | Stock PF augmente |
| 8 | Créer commande client | Statut CONFIRMEE |
| 9 | Livrer commande | Stock PF diminue |
| 10 | Tableau de bord | KPIs mis à jour |
---
# Chapitre 6 — Ce qui reste à faire
## 6.1 Frontend Flutter
Le frontend mobile/desktop sera développé avec Flutter et se connectera à l'API REST via des appels HTTP avec token JWT.
**Écrans à développer (par priorité) :**
1. **Écran de connexion** — formulaire login/password, stockage du token
2. **Tableau de bord** — affichage des KPIs (chiffre d'affaires, alertes stock, OF en cours)
3. **Articles** — liste, recherche, fiche détail, ajout/modification
4. **Cycle de vente** — liste commandes, création, bon de livraison
5. **Cycle d'achat** — liste commandes, création, bon de réception
6. **Production** — BOM, ordres de fabrication, lancement/terminaison
7. **Stock** — historique des mouvements, ajustements
**Architecture Flutter proposée :**
- **State management :** Provider ou Riverpod
- **HTTP client :** `http` ou `dio`
- **Stockage local :** `shared_preferences` (token JWT)
- **Navigation :** `go_router`
## 6.2 Modules Complémentaires API
| Module | Description | Priorité |
|--------|-------------|----------|
| Facturation | Génération de factures PDF | Haute |
| Paie / RH | Gestion des employés et salaires | Moyenne |
| Rapports | Export Excel/PDF des données | Moyenne |
---
# Annexes
## A — Initialisation Automatique
Au premier démarrage, le système crée automatiquement :
- Les 6 rôles dans la base de données
- L'utilisateur administrateur : **admin / Rayhan2024!** avec le rôle PDG
## B — Variables d'Environnement Docker
| Variable | Valeur |
|----------|--------|
| `SPRING_DATASOURCE_URL` | `jdbc:mysql://mysql:3306/rayhan_erp_db` |
| `SPRING_DATASOURCE_USERNAME` | `root` |
| `SPRING_DATASOURCE_PASSWORD` | `rayhan_erp_2024` |
| `RAYHAN_ERP_JWTSECRET` | Clé secrète JWT (256 bits) |
| `RAYHAN_ERP_JWTEXPIRATIONMS` | `86400000` (24 heures) |
## C — Commandes Docker Utiles
```bash
# Démarrer l'application
docker compose up -d
# Reconstruire après modification du code
docker compose up -d --build
# Voir les logs en temps réel
docker logs rayhan-backend -f
# Accéder à MySQL
docker exec -it rayhan-mysql mysql -u root -prayhan_erp_2024 rayhan_erp_db
```
---
# Chapitre 5 — Réalisation Frontend (Application Mobile Flutter)
## 5.1 Choix Technologique
L'interface utilisateur de l'ERP Rayhan est développée avec **Flutter**, le framework de Google permettant de créer des applications mobiles multiplateformes (Android et iOS) à partir d'une seule base de code Dart.
### Justification du choix Flutter
| Critère | Flutter | React Native | Natif Android/iOS |
|---------|---------|--------------|-------------------|
| Code partagé Android/iOS | 100% | ~85% | 0% |
| Performance | Excellente | Bonne | Excellente |
| Courbe d'apprentissage | Moyenne | Moyenne | Élevée |
| Écosystème packages | Riche | Riche | Natif |
| Rendu UI | Moteur propre (Skia) | Bridge natif | Natif |
Flutter a été retenu pour sa capacité à produire une application unique couvrant les deux plateformes mobiles majeures, tout en offrant des performances proches du natif grâce à son moteur de rendu indépendant.
## 5.2 Architecture du Projet Flutter
L'architecture adoptée suit le pattern **Provider + Services** :
```
frontend/
├── lib/
│ ├── main.dart # Point d'entrée, routing, thème
│ ├── screens/ # Écrans de l'application
│ │ ├── login_screen.dart # Écran de connexion
│ │ └── dashboard_screen.dart # Tableau de bord KPI
│ ├── providers/ # Gestion d'état (Provider)
│ │ └── auth_provider.dart # État authentification
│ ├── services/ # Appels API
│ │ ├── api_client.dart # Client Dio + intercepteur JWT
│ │ └── auth_service.dart # Service authentification
│ ├── models/ # Modèles de données Dart
│ └── widgets/ # Composants réutilisables
├── pubspec.yaml # Dépendances Flutter
└── android/ # Configuration Android
```
### Dépendances principales
| Package | Version | Rôle |
|---------|---------|------|
| `dio` | ^5.4.0 | Client HTTP avec intercepteurs |
| `provider` | ^6.1.1 | Gestion d'état réactive |
| `shared_preferences` | ^2.2.2 | Stockage local du token JWT |
| `go_router` | ^13.2.0 | Navigation déclarative |
| `fl_chart` | ^0.67.0 | Graphiques pour le dashboard |
| `intl` | ^0.19.0 | Formatage dates et nombres |
## 5.3 Authentification et Sécurité
### Flux d'authentification
Le flux d'authentification suit le protocole JWT standard :
1. L'utilisateur saisit son identifiant et mot de passe
2. L'application envoie une requête `POST /api/auth/signin`
3. Le serveur retourne un token JWT signé (validité 24h)
4. Le token est stocké localement via `shared_preferences`
5. Chaque requête API suivante inclut automatiquement `Authorization: Bearer <token>`
6. À la déconnexion, le token est supprimé du stockage local
### Intercepteur JWT automatique
La classe `ApiClient` centralise toutes les communications HTTP et injecte automatiquement le token JWT dans les en-têtes via un intercepteur `Dio` :
```dart
class _AuthInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
final prefs = await SharedPreferences.getInstance();
final token = prefs.getString('jwt_token');
if (token != null) {
options.headers['Authorization'] = 'Bearer $token';
}
handler.next(options);
}
}
```
Cette approche centralise la gestion du token et évite sa répétition dans chaque appel API.
### Redirection automatique (GoRouter)
Le routeur détecte l'état d'authentification et redirige automatiquement :
- Un utilisateur non connecté est redirigé vers `/login`
- Un utilisateur déjà connecté accédant à `/login` est redirigé vers `/dashboard`
## 5.4 Écran de Connexion
L'écran de connexion (`LoginScreen`) présente une interface épurée et professionnelle :
**Composants UI :**
- Logo de l'application avec icône usine (représentant l'industrie plasturgie)
- Titre "RAYHAN ERP" et sous-titre
- Formulaire de connexion avec validation :
- Champ identifiant avec icône
- Champ mot de passe avec bouton afficher/masquer
- Message d'erreur contextuel en cas d'échec
- Bouton de connexion avec indicateur de chargement
- Footer © SUARL Rayhan
**Gestion des états :**
- État initial : formulaire vide
- État chargement : spinner animé, bouton désactivé
- État erreur : bandeau rouge avec message explicite
- État succès : redirection automatique vers le dashboard
---
## 5.5 Tableau de Bord KPI (Dashboard)
### Objectif
Le tableau de bord est l'écran central de l'application, accessible uniquement aux utilisateurs ayant le rôle **PDG**. Il synthétise en temps réel l'état de l'entreprise à travers des indicateurs clés de performance (KPI).
### Données affichées
L'écran récupère les données depuis l'endpoint `GET /api/dashboard` et les affiche en trois sections :
**Section Ventes (mois en cours)**
| KPI | Description |
|-----|-------------|
| Chiffre d'affaires | Montant total des ventes du mois en TND |
| Commandes ce mois | Nombre de bons de commande clients créés |
| Commandes en cours | Commandes en attente de livraison |
**Section Achats & Production**
| KPI | Description |
|-----|-------------|
| Achats en attente | Bons de commande fournisseurs non réceptionnés |
| OF en cours | Ordres de fabrication au statut LANCE |
| OF planifiés | Ordres de fabrication au statut PLANIFIE |
**Section Stock**
- Nombre d'articles dont le stock est inférieur au seuil minimum
- Liste détaillée des articles en alerte avec leur quantité en stock actuelle
### Architecture technique
La gestion du dashboard suit le pattern **Provider** :
```
GET /api/dashboard
DashboardService.fetchKpis()
DashboardProvider (ChangeNotifier)
├── isLoading
├── error
└── kpi: DashboardKpi
├── VentesKpi
├── AchatsKpi
├── ProductionKpi
└── StockKpi
DashboardScreen (Consumer)
├── KpiCard × 6 (grille 2 colonnes)
└── _StockSection (liste alertes)
```
### Navigation (Drawer)
Un menu latéral (`AppDrawer`) permet la navigation entre tous les modules :
- Tableau de bord
- Articles
- Ventes
- Achats
- Production
- Stock
- Déconnexion
Le drawer affiche le rôle de l'utilisateur connecté et met en surbrillance la section active.
### Comportement UI
- **Pull-to-refresh** : glisser vers le bas recharge les KPIs
- **Bouton actualiser** dans l'AppBar
- **État chargement** : spinner centré
- **État erreur** : message avec bouton "Réessayer"
- **Alertes stock** : icône verte si tout va bien, rouge avec liste si alertes
---
*[Section à compléter avec captures d'écran lors de la finalisation du rapport]*