# 💰 CONCEPT: DEVIS ## 📌 Vue d'ensemble Le concept **DEVIS** gère les devis et la facturation des chantiers. Il inclut les lignes de devis, calculs automatiques, et génération PDF. **Importance**: ⭐⭐⭐⭐ (Concept stratégique) --- ## 🗂️ Fichiers concernés ### **Entités JPA** | Fichier | Description | |---------|-------------| | `Devis.java` | Entité principale devis | | `LigneDevis.java` | Ligne de devis | | `StatutDevis.java` | Enum (BROUILLON, ENVOYE, ACCEPTE, REFUSE, EXPIRE) | | `Facture.java` | Entité facture | | `LigneFacture.java` | Ligne de facture | ### **Services** | Fichier | Description | |---------|-------------| | `DevisService.java` | Service métier devis | | `FactureService.java` | Service métier factures | | `PdfGeneratorService.java` | Génération PDF | ### **Resources** | Fichier | Description | |---------|-------------| | `DevisResource.java` | API REST devis | | `FactureResource.java` | API REST factures | --- ## 📊 Modèle de données ### **Entité Devis** ```java @Entity @Table(name = "devis") public class Devis extends PanacheEntityBase { @Id @GeneratedValue(strategy = GenerationType.UUID) private UUID id; @Column(name = "numero", unique = true, nullable = false) private String numero; @ManyToOne @JoinColumn(name = "client_id", nullable = false) private Client client; @ManyToOne @JoinColumn(name = "chantier_id") private Chantier chantier; @Column(name = "date_emission", nullable = false) private LocalDate dateEmission; @Column(name = "date_validite") private LocalDate dateValidite; @Enumerated(EnumType.STRING) @Column(name = "statut", nullable = false) private StatutDevis statut = StatutDevis.BROUILLON; @OneToMany(mappedBy = "devis", cascade = CascadeType.ALL) private List lignes; @Column(name = "montant_ht", precision = 10, scale = 2) private BigDecimal montantHT = BigDecimal.ZERO; @Column(name = "montant_tva", precision = 10, scale = 2) private BigDecimal montantTVA = BigDecimal.ZERO; @Column(name = "montant_ttc", precision = 10, scale = 2) private BigDecimal montantTTC = BigDecimal.ZERO; @Column(name = "taux_tva", precision = 5, scale = 2) private BigDecimal tauxTVA = new BigDecimal("20.00"); } ``` ### **Enum StatutDevis** ```java public enum StatutDevis { BROUILLON, // En cours de rédaction ENVOYE, // Envoyé au client ACCEPTE, // Accepté par le client REFUSE, // Refusé par le client EXPIRE // Expiré (date de validité dépassée) } ``` --- ## 🔌 API REST ### **Endpoints Devis** | Méthode | Endpoint | Description | |---------|----------|-------------| | GET | `/api/v1/devis` | Liste devis | | GET | `/api/v1/devis/{id}` | Détails | | POST | `/api/v1/devis` | Créer | | PUT | `/api/v1/devis/{id}` | Modifier | | PUT | `/api/v1/devis/{id}/envoyer` | Envoyer au client | | PUT | `/api/v1/devis/{id}/accepter` | Accepter | | PUT | `/api/v1/devis/{id}/refuser` | Refuser | | GET | `/api/v1/devis/{id}/pdf` | Générer PDF | | GET | `/api/v1/devis/stats` | Statistiques | ### **Endpoints Factures** | Méthode | Endpoint | Description | |---------|----------|-------------| | GET | `/api/v1/factures` | Liste factures | | GET | `/api/v1/factures/{id}` | Détails | | POST | `/api/v1/factures` | Créer | | POST | `/api/v1/factures/depuis-devis/{devisId}` | Créer depuis devis | | GET | `/api/v1/factures/{id}/pdf` | Générer PDF | --- ## 💻 Exemples ### **Créer un devis** ```bash curl -X POST http://localhost:8080/api/v1/devis \ -H "Content-Type: application/json" \ -d '{ "clientId": "client-uuid", "chantierId": "chantier-uuid", "dateEmission": "2025-10-01", "dateValidite": "2025-11-01", "tauxTVA": 20.00, "lignes": [ { "designation": "Terrassement et fondations", "quantite": 1, "unite": "FORFAIT", "prixUnitaireHT": 5000.00 }, { "designation": "Maçonnerie murs porteurs", "quantite": 45, "unite": "METRE_CARRE", "prixUnitaireHT": 120.00 }, { "designation": "Charpente traditionnelle", "quantite": 1, "unite": "FORFAIT", "prixUnitaireHT": 8000.00 } ] }' ``` **Réponse**: ```json { "id": "uuid", "numero": "DEV-2025-001", "client": "Jean Dupont", "chantier": "Construction Villa Moderne", "dateEmission": "2025-10-01", "dateValidite": "2025-11-01", "statut": "BROUILLON", "lignes": [ { "designation": "Terrassement et fondations", "quantite": 1, "prixUnitaireHT": 5000.00, "montantHT": 5000.00 }, { "designation": "Maçonnerie murs porteurs", "quantite": 45, "prixUnitaireHT": 120.00, "montantHT": 5400.00 }, { "designation": "Charpente traditionnelle", "quantite": 1, "prixUnitaireHT": 8000.00, "montantHT": 8000.00 } ], "montantHT": 18400.00, "montantTVA": 3680.00, "montantTTC": 22080.00 } ``` ### **Envoyer un devis** ```bash curl -X PUT http://localhost:8080/api/v1/devis/{id}/envoyer \ -H "Content-Type: application/json" \ -d '{ "emailClient": "jean.dupont@example.com", "message": "Veuillez trouver ci-joint notre devis" }' ``` ### **Générer PDF** ```bash curl -X GET http://localhost:8080/api/v1/devis/{id}/pdf \ -H "Accept: application/pdf" \ --output devis.pdf ``` ### **Créer facture depuis devis** ```bash curl -X POST http://localhost:8080/api/v1/factures/depuis-devis/{devisId} ``` --- ## 🔧 Services métier ### **DevisService** **Méthodes principales**: - `create(DevisDTO)` - Créer devis - `calculerMontants(UUID id)` - Calculer HT/TVA/TTC - `envoyer(UUID id)` - Envoyer au client - `accepter(UUID id)` - Accepter - `refuser(UUID id)` - Refuser - `genererPDF(UUID id)` - Générer PDF ### **FactureService** **Méthodes principales**: - `create(FactureDTO)` - Créer facture - `creerDepuisDevis(UUID devisId)` - Créer depuis devis - `genererPDF(UUID id)` - Générer PDF --- ## 📈 Relations - **CLIENT** ⬅️ Un devis est adressé à un client - **CHANTIER** ⬅️ Un devis peut être lié à un chantier - **FACTURE** ➡️ Un devis accepté génère une facture --- ## ✅ Validations - ✅ Numéro unique - ✅ Client obligatoire - ✅ Au moins une ligne - ✅ Montants positifs - ✅ Date validité > date émission - ✅ Taux TVA entre 0 et 100 --- ## 📚 Références - [Concept CLIENT](./02-CLIENT.md) - [Concept CHANTIER](./01-CHANTIER.md) - [Concept BUDGET](./10-BUDGET.md) --- **Dernière mise à jour**: 2025-09-30 **Version**: 1.0