Documentation Architecture API — ERP Rayhan
PFE Ali Guennari — SUARL Rayhan
Architecture Technique
┌─────────────────────────────────────────────────────────┐
│ Application Flutter (Client) │
│ (Windows Desktop / Web / Android) │
└─────────────────────┬───────────────────────────────────┘
│ HTTP/HTTPS (JWT Bearer Token)
▼
┌─────────────────────────────────────────────────────────┐
│ API REST Spring Boot (Port 8090) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │Controller│→ │ Service │→ │Repository│ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ │
│ │ JPA/ │ │
│ │Hibernate │ │
└──────────────────────────────┴────┬─────┴──────────────┘
│ JDBC
▼
┌─────────────────────┐
│ MySQL 8 (DB) │
│ rayhan_erp_db │
└─────────────────────┘
Pattern d'Architecture N-Tiers
L'API suit rigoureusement le pattern Controller → Service → Repository → Model :
| Couche |
Rôle |
Exemple |
| Controller |
Reçoit les requêtes HTTP, délègue au service, retourne la réponse |
ArticleController.java |
| Service |
Contient la logique métier (règles, validations, transactions) |
StockService.java |
| Repository |
Abstraction d'accès à la base de données (Spring Data JPA) |
ArticleRepository.java |
| Model |
Entités JPA mappées sur les tables MySQL |
Article.java |
Tous les Endpoints de l'API
Authentification (Public — sans token)
| Méthode |
URL |
Description |
| POST |
/api/auth/signin |
Connexion → retourne JWT |
| POST |
/api/auth/signup |
Créer un utilisateur |
Articles (Catalogue)
| Méthode |
URL |
Rôles autorisés |
| 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) |
Clients
| Méthode |
URL |
Rôles autorisés |
| GET |
/api/clients |
PDG, Vente |
| GET |
/api/clients/search?q= |
PDG, Vente |
| GET |
/api/clients/{id} |
PDG, Vente |
| POST |
/api/clients |
PDG, Vente |
| PUT |
/api/clients/{id} |
PDG, Vente |
Fournisseurs
| Méthode |
URL |
Rôles autorisés |
| GET |
/api/fournisseurs |
PDG, Achat |
| GET |
/api/fournisseurs/search?q= |
PDG, Achat |
| GET |
/api/fournisseurs/{id} |
PDG, Achat |
| POST |
/api/fournisseurs |
PDG, Achat |
| PUT |
/api/fournisseurs/{id} |
PDG, Achat |
Cycle d'Achat
| Méthode |
URL |
Rôles autorisés |
| GET |
/api/purchase-orders |
PDG, Achat |
| POST |
/api/purchase-orders |
PDG, Achat |
| POST |
/api/purchase-orders/{id}/receive |
PDG, Achat, Magasinier |
Flux automatique lors de la réception :
POST /receive → Crée le BR → StockService.entreeStock() → Mise à jour Article.stockActuel + création StockMovement
Cycle de Vente
| Méthode |
URL |
Rôles autorisés |
| GET |
/api/sales-orders |
PDG, Vente |
| POST |
/api/sales-orders |
PDG, Vente |
| POST |
/api/sales-orders/{id}/deliver |
PDG, Vente, Magasinier |
Flux automatique lors de la livraison :
POST /deliver → Crée le BL → StockService.sortieStock() → Mise à jour Article.stockActuel + création StockMovement
Cycle de Production
| Méthode |
URL |
Rôles autorisés |
| GET |
/api/production/bom/{produitFiniId} |
PDG, Production |
| POST |
/api/production/bom |
PDG, Production |
| DELETE |
/api/production/bom/{id} |
PDG, Production |
| GET |
/api/production/orders |
PDG, Production |
| POST |
/api/production/orders/plan |
PDG, Production |
| POST |
/api/production/orders/{id}/launch |
PDG, Production |
| POST |
/api/production/orders/{id}/complete |
PDG, Production |
Cycle de vie d'un OF :
PLANIFIE → (vérif stock MP) → LANCE → (consomme MP) → TERMINE → (entre PF en stock)
Gestion du Stock
| Méthode |
URL |
Rôles autorisés |
| GET |
/api/stock/historique/{articleId} |
PDG, Magasinier, Production |
| POST |
/api/stock/adjust |
PDG, Magasinier |
Tableau de Bord (KPIs)
| Méthode |
URL |
Rôles autorisés |
| GET |
/api/dashboard |
PDG uniquement |
Modèle de Données Relationnel
users (id, username, email, password, firstName, lastName, enabled)
└── user_roles (user_id, role_id)
roles (id, name: ERole)
tiers (id, raisonSociale, matriculeFiscal, adresse, telephone, email, ville, actif)
├── clients (tiers_id FK, typeClient, plafondCredit, delaiPaiement)
└── fournisseurs (tiers_id FK, pays, categorieProduit, delaiLivraison, modePaiement)
articles (id, reference, designation, type: MP|PSF|PF, uniteMesure, prixUnitaire, stockActuel, stockMinimum, actif)
bom_lines (id, produit_fini_id FK→articles, composant_id FK→articles, quantiteParUnite)
production_orders (id, reference, produit_fini_id FK, quantitePlanifiee, quantiteRealisee, datePlanifiee, dateLancement, dateTerminaison, statut)
purchase_orders (id, reference, fournisseur_id FK, dateCommande, statut, totalHT, totalTVA, totalTTC)
└── purchase_order_lines (id, purchase_order_id FK, article_id FK, quantiteCommandee, quantiteRecue, prixUnitaireHT, tauxTVA)
goods_receipts (id, reference, purchase_order_id FK, dateReception)
└── goods_receipt_lines (id, goods_receipt_id FK, purchase_order_line_id FK, article_id FK, quantiteRecue)
sales_orders (id, reference, client_id FK, dateCommande, statut, totalHT, totalTVA, totalTTC)
└── sales_order_lines (id, sales_order_id FK, article_id FK, quantiteCommandee, quantiteLivree, prixUnitaireHT, tauxTVA)
delivery_notes (id, reference, sales_order_id FK, dateLivraison, statut)
└── delivery_note_lines (id, delivery_note_id FK, sales_order_line_id FK, article_id FK, quantiteLivree)
stock_movements (id, article_id FK, type: IN|OUT, quantite, stockAvant, stockApres, sourceDocument, referenceDocument, motif, dateHeure, user_id FK)
Sécurité
Mécanisme JWT
- Le client envoie
POST /api/auth/signin avec username/password
- Le serveur retourne un JWT signé (valide 24h)
- Le client inclut
Authorization: Bearer <token> dans chaque requête
AuthTokenFilter intercepte et valide le token avant chaque endpoint sécurisé
Contrôle d'Accès par Rôle (@PreAuthorize)
Chaque endpoint est annoté avec les rôles autorisés :
@PreAuthorize("hasAnyRole('ROLE_PDG', 'ROLE_RESPONSABLE_VENTE')")
Démarrage de l'Application
# Via Docker Compose
docker compose up -d
# Vérifier que les conteneurs tournent
docker ps
# Voir les logs
docker logs rayhan-backend -f
# Premier démarrage : admin créé automatiquement
# username: admin | password: Rayhan2024!