rayhan-erp/Livrables/rapport-projet.md

481 lines
18 KiB
Markdown

---
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
---
*[Section à compléter avec captures d'écran lors de la finalisation du rapport]*