Initial commit

This commit is contained in:
dahoud
2025-10-01 01:37:34 +00:00
commit f2bb633142
310 changed files with 86051 additions and 0 deletions

View File

@@ -0,0 +1,360 @@
# 🏗️ CONCEPT: CHANTIER
## 📌 Vue d'ensemble
Le concept **CHANTIER** est le **cœur métier** de l'application BTPXpress. Il représente un projet de construction BTP avec toutes ses caractéristiques : localisation, dates, budget, statut, phases, et relations avec les clients, devis, factures, etc.
**Importance**: ⭐⭐⭐⭐⭐ (Concept central)
---
## 🗂️ Fichiers concernés
### **Entités JPA** (`domain/core/entity/`)
| Fichier | Description | Lignes |
|---------|-------------|--------|
| `Chantier.java` | Entité principale représentant un chantier BTP | 224 |
| `StatutChantier.java` | Enum des statuts possibles d'un chantier | 24 |
| `TypeChantier.java` | Entité type de chantier (configurable) | ~150 |
| `TypeChantierBTP.java` | Enum types BTP prédéfinis | ~50 |
| `Phase.java` | Phase générique de chantier | ~100 |
| `PhaseChantier.java` | Phase spécifique à un chantier | ~180 |
| `PhaseTemplate.java` | Template de phase réutilisable | ~120 |
| `SousPhaseTemplate.java` | Sous-phase de template | ~80 |
| `TacheTemplate.java` | Template de tâche | ~100 |
| `StatutPhaseChantier.java` | Enum statuts de phase | ~40 |
| `TypePhaseChantier.java` | Enum types de phase | ~30 |
| `PrioritePhase.java` | Enum priorités de phase | ~25 |
### **DTOs** (`domain/shared/dto/`)
| Fichier | Description |
|---------|-------------|
| `ChantierCreateDTO.java` | DTO pour créer/modifier un chantier |
| `PhaseChantierDTO.java` | DTO pour les phases de chantier |
### **Services** (`application/service/`)
| Fichier | Description |
|---------|-------------|
| `ChantierService.java` | Service métier principal pour les chantiers |
| `PhaseChantierService.java` | Service pour la gestion des phases |
| `PhaseTemplateService.java` | Service pour les templates de phases |
| `TacheTemplateService.java` | Service pour les templates de tâches |
### **Resources (API REST)** (`adapter/http/`)
| Fichier | Description |
|---------|-------------|
| `ChantierResource.java` | Endpoints REST pour les chantiers |
| `PhaseChantierResource.java` | Endpoints REST pour les phases |
---
## 📊 Modèle de données
### **Entité Chantier**
<augment_code_snippet path="btpxpress-server/src/main/java/dev/lions/btpxpress/domain/core/entity/Chantier.java" mode="EXCERPT">
````java
@Entity
@Table(name = "chantiers")
@Data
@Builder
public class Chantier extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@NotBlank(message = "Le nom du chantier est obligatoire")
@Column(name = "nom", nullable = false, length = 200)
private String nom;
@Column(name = "code", unique = true, length = 50)
private String code;
@NotBlank(message = "L'adresse du chantier est obligatoire")
@Column(name = "adresse", nullable = false, length = 500)
private String adresse;
@Enumerated(EnumType.STRING)
@Column(name = "statut", nullable = false)
private StatutChantier statut = StatutChantier.PLANIFIE;
@Column(name = "montant_prevu", precision = 10, scale = 2)
private BigDecimal montantPrevu;
// Relations
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "client_id", nullable = false)
private Client client;
@OneToMany(mappedBy = "chantier", cascade = CascadeType.ALL)
private List<Devis> devis;
@OneToMany(mappedBy = "chantier", cascade = CascadeType.ALL)
private List<Facture> factures;
// ...
}
````
</augment_code_snippet>
### **Enum StatutChantier**
<augment_code_snippet path="btpxpress-server/src/main/java/dev/lions/btpxpress/domain/core/entity/StatutChantier.java" mode="EXCERPT">
````java
public enum StatutChantier {
PLANIFIE("Planifié"),
EN_COURS("En cours"),
TERMINE("Terminé"),
ANNULE("Annulé"),
SUSPENDU("Suspendu");
private final String label;
StatutChantier(String label) {
this.label = label;
}
public String getLabel() {
return label;
}
}
````
</augment_code_snippet>
### **Champs principaux**
| Champ | Type | Obligatoire | Description |
|-------|------|-------------|-------------|
| `id` | UUID | Oui | Identifiant unique |
| `nom` | String(200) | Oui | Nom du chantier |
| `code` | String(50) | Non | Code unique du chantier |
| `description` | TEXT | Non | Description détaillée |
| `adresse` | String(500) | Oui | Adresse du chantier |
| `codePostal` | String(10) | Non | Code postal |
| `ville` | String(100) | Non | Ville |
| `dateDebut` | LocalDate | Oui | Date de début |
| `dateDebutPrevue` | LocalDate | Non | Date de début prévue |
| `dateDebutReelle` | LocalDate | Non | Date de début réelle |
| `dateFinPrevue` | LocalDate | Non | Date de fin prévue |
| `dateFinReelle` | LocalDate | Non | Date de fin réelle |
| `statut` | StatutChantier | Oui | Statut actuel (défaut: PLANIFIE) |
| `montantPrevu` | BigDecimal | Non | Montant prévu |
| `montantReel` | BigDecimal | Non | Montant réel |
| `typeChantier` | TypeChantierBTP | Non | Type de chantier |
| `actif` | Boolean | Oui | Chantier actif (défaut: true) |
| `dateCreation` | LocalDateTime | Auto | Date de création |
| `dateModification` | LocalDateTime | Auto | Date de modification |
### **Relations**
| Relation | Type | Entité cible | Description |
|----------|------|--------------|-------------|
| `client` | ManyToOne | Client | Client propriétaire (obligatoire) |
| `chefChantier` | ManyToOne | User | Chef de chantier responsable |
| `devis` | OneToMany | Devis | Liste des devis associés |
| `factures` | OneToMany | Facture | Liste des factures |
---
## 🔌 API REST
### **Base URL**: `/api/v1/chantiers`
### **Endpoints disponibles**
| Méthode | Endpoint | Description | Authentification |
|---------|----------|-------------|------------------|
| GET | `/api/v1/chantiers` | Liste tous les chantiers | Optionnelle |
| GET | `/api/v1/chantiers/actifs` | Liste chantiers actifs | Optionnelle |
| GET | `/api/v1/chantiers/{id}` | Détails d'un chantier | Optionnelle |
| POST | `/api/v1/chantiers` | Créer un chantier | Optionnelle |
| PUT | `/api/v1/chantiers/{id}` | Modifier un chantier | Optionnelle |
| DELETE | `/api/v1/chantiers/{id}` | Supprimer un chantier | Optionnelle |
| GET | `/api/v1/chantiers/statut/{statut}` | Chantiers par statut | Optionnelle |
| GET | `/api/v1/chantiers/client/{clientId}` | Chantiers d'un client | Optionnelle |
| GET | `/api/v1/chantiers/search` | Recherche de chantiers | Optionnelle |
| GET | `/api/v1/chantiers/stats` | Statistiques chantiers | Optionnelle |
### **Paramètres de requête (Query Params)**
| Paramètre | Type | Description | Exemple |
|-----------|------|-------------|---------|
| `search` | String | Terme de recherche | `?search=villa` |
| `statut` | String | Filtrer par statut | `?statut=EN_COURS` |
| `clientId` | UUID | Filtrer par client | `?clientId=uuid` |
---
## 💻 Exemples d'utilisation
### **1. Récupérer tous les chantiers**
```bash
curl -X GET http://localhost:8080/api/v1/chantiers \
-H "Accept: application/json"
```
**Réponse** (200 OK):
```json
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"nom": "Construction Villa Moderne",
"code": "CHANT-2025-001",
"adresse": "123 Avenue des Champs",
"codePostal": "75008",
"ville": "Paris",
"statut": "EN_COURS",
"montantPrevu": 250000.00,
"dateDebut": "2025-01-15",
"dateFinPrevue": "2025-12-31",
"actif": true
}
]
```
### **2. Créer un nouveau chantier**
```bash
curl -X POST http://localhost:8080/api/v1/chantiers \
-H "Content-Type: application/json" \
-d '{
"nom": "Rénovation Appartement",
"adresse": "45 Rue de la Paix",
"codePostal": "75002",
"ville": "Paris",
"dateDebut": "2025-10-01",
"dateFinPrevue": "2025-12-15",
"montantPrevu": 75000.00,
"clientId": "client-uuid-here",
"statut": "PLANIFIE"
}'
```
**Réponse** (201 Created):
```json
{
"id": "generated-uuid",
"nom": "Rénovation Appartement",
"statut": "PLANIFIE",
"dateCreation": "2025-09-30T10:30:00"
}
```
### **3. Rechercher des chantiers**
```bash
# Par nom
curl -X GET "http://localhost:8080/api/v1/chantiers?search=villa"
# Par statut
curl -X GET "http://localhost:8080/api/v1/chantiers?statut=EN_COURS"
# Par client
curl -X GET "http://localhost:8080/api/v1/chantiers?clientId=uuid-client"
```
### **4. Obtenir les statistiques**
```bash
curl -X GET http://localhost:8080/api/v1/chantiers/stats
```
**Réponse**:
```json
{
"totalChantiers": 45,
"chantiersActifs": 38,
"enCours": 12,
"planifies": 8,
"termines": 15,
"suspendus": 2,
"annules": 1,
"montantTotalPrevu": 5250000.00,
"montantTotalReel": 4890000.00
}
```
---
## 🔧 Services métier
### **ChantierService**
**Méthodes principales**:
| Méthode | Description | Retour |
|---------|-------------|--------|
| `findAll()` | Récupère tous les chantiers | `List<Chantier>` |
| `findActifs()` | Récupère chantiers actifs | `List<Chantier>` |
| `findById(UUID id)` | Récupère par ID | `Optional<Chantier>` |
| `create(ChantierCreateDTO dto)` | Crée un chantier | `Chantier` |
| `update(UUID id, ChantierCreateDTO dto)` | Met à jour | `Chantier` |
| `delete(UUID id)` | Supprime (soft delete) | `void` |
| `findByStatut(StatutChantier statut)` | Filtre par statut | `List<Chantier>` |
| `findByClient(UUID clientId)` | Chantiers d'un client | `List<Chantier>` |
| `search(String term)` | Recherche textuelle | `List<Chantier>` |
| `getStatistics()` | Statistiques globales | `Object` |
---
## 🔐 Permissions requises
| Permission | Description | Rôles autorisés |
|------------|-------------|-----------------|
| `CHANTIERS_READ` | Lecture des chantiers | ADMIN, MANAGER, CHEF_CHANTIER, COMPTABLE, OUVRIER |
| `CHANTIERS_CREATE` | Création de chantiers | ADMIN, MANAGER |
| `CHANTIERS_UPDATE` | Modification de chantiers | ADMIN, MANAGER, CHEF_CHANTIER |
| `CHANTIERS_DELETE` | Suppression de chantiers | ADMIN, MANAGER |
| `CHANTIERS_PHASES` | Gestion des phases | ADMIN, MANAGER, CHEF_CHANTIER |
| `CHANTIERS_BUDGET` | Gestion du budget | ADMIN, MANAGER, COMPTABLE |
---
## 📈 Relations avec autres concepts
### **Dépendances directes**:
- **CLIENT** ⬅️ Un chantier appartient à un client (obligatoire)
- **USER** ⬅️ Un chantier peut avoir un chef de chantier
- **DEVIS** ➡️ Un chantier peut avoir plusieurs devis
- **FACTURE** ➡️ Un chantier peut avoir plusieurs factures
- **PHASE** ➡️ Un chantier est divisé en phases
- **BUDGET** ➡️ Un chantier a un budget associé
- **PLANNING** ➡️ Un chantier a un planning
- **DOCUMENT** ➡️ Un chantier peut avoir des documents (plans, photos, etc.)
---
## 🧪 Tests
### **Tests unitaires**
- Fichier: `ChantierServiceTest.java`
- Couverture: Logique métier, validations, calculs
### **Tests d'intégration**
- Fichier: `ChantierResourceTest.java`
- Couverture: Endpoints REST, sérialisation JSON
### **Commande pour exécuter les tests**:
```bash
cd btpxpress-server
./mvnw test -Dtest=ChantierServiceTest
./mvnw test -Dtest=ChantierResourceTest
```
---
## 📚 Références
- [API Documentation complète](../API.md#chantiers)
- [Schéma de base de données](../DATABASE.md#table-chantiers)
- [Guide d'architecture](../architecture/domain-model.md#chantier)
- [Service ChantierService](../../src/main/java/dev/lions/btpxpress/application/service/ChantierService.java)
- [Resource ChantierResource](../../src/main/java/dev/lions/btpxpress/adapter/http/ChantierResource.java)
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0
**Auteur**: Documentation BTPXpress

380
docs/concepts/02-CLIENT.md Normal file
View File

@@ -0,0 +1,380 @@
# 👤 CONCEPT: CLIENT
## 📌 Vue d'ensemble
Le concept **CLIENT** représente les clients de l'entreprise BTP, qu'ils soient **particuliers** ou **professionnels**. Il gère toutes les informations de contact, coordonnées, et relations avec les chantiers et devis.
**Importance**: ⭐⭐⭐⭐⭐ (Concept fondamental)
---
## 🗂️ Fichiers concernés
### **Entités JPA** (`domain/core/entity/`)
| Fichier | Description | Lignes |
|---------|-------------|--------|
| `Client.java` | Entité principale représentant un client | 113 |
| `TypeClient.java` | Enum des types de clients (PARTICULIER, PROFESSIONNEL) | 21 |
### **DTOs** (`domain/shared/dto/`)
| Fichier | Description |
|---------|-------------|
| `ClientCreateDTO.java` | DTO pour créer/modifier un client |
### **Services** (`application/service/`)
| Fichier | Description |
|---------|-------------|
| `ClientService.java` | Service métier pour la gestion des clients |
### **Resources (API REST)** (`adapter/http/`)
| Fichier | Description |
|---------|-------------|
| `ClientResource.java` | Endpoints REST pour les clients |
---
## 📊 Modèle de données
### **Entité Client**
<augment_code_snippet path="btpxpress-server/src/main/java/dev/lions/btpxpress/domain/core/entity/Client.java" mode="EXCERPT">
````java
@Entity
@Table(name = "clients")
@Data
@Builder
public class Client extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@NotBlank(message = "Le nom est obligatoire")
@Column(name = "nom", nullable = false, length = 100)
private String nom;
@NotBlank(message = "Le prénom est obligatoire")
@Column(name = "prenom", nullable = false, length = 100)
private String prenom;
@Column(name = "entreprise", length = 200)
private String entreprise;
@Email(message = "Email invalide")
@Column(name = "email", unique = true, length = 255)
private String email;
@Pattern(regexp = "^(?:(?:\\+|00)33|0)\\s*[1-9](?:[\\s.-]*\\d{2}){4}$")
@Column(name = "telephone", length = 20)
private String telephone;
@Enumerated(EnumType.STRING)
@Column(name = "type_client", length = 20)
private TypeClient type = TypeClient.PARTICULIER;
// Relations
@OneToMany(mappedBy = "client", cascade = CascadeType.ALL)
private List<Chantier> chantiers;
@OneToMany(mappedBy = "client", cascade = CascadeType.ALL)
private List<Devis> devis;
}
````
</augment_code_snippet>
### **Enum TypeClient**
<augment_code_snippet path="btpxpress-server/src/main/java/dev/lions/btpxpress/domain/core/entity/TypeClient.java" mode="EXCERPT">
````java
public enum TypeClient {
PARTICULIER("Particulier"),
PROFESSIONNEL("Professionnel");
private final String label;
TypeClient(String label) {
this.label = label;
}
public String getLabel() {
return label;
}
}
````
</augment_code_snippet>
### **Champs principaux**
| Champ | Type | Obligatoire | Description |
|-------|------|-------------|-------------|
| `id` | UUID | Oui | Identifiant unique |
| `nom` | String(100) | Oui | Nom du client |
| `prenom` | String(100) | Oui | Prénom du client |
| `entreprise` | String(200) | Non | Nom de l'entreprise (si professionnel) |
| `email` | String(255) | Non | Email (unique) |
| `telephone` | String(20) | Non | Téléphone (format français validé) |
| `adresse` | String(500) | Non | Adresse postale |
| `codePostal` | String(10) | Non | Code postal |
| `ville` | String(100) | Non | Ville |
| `numeroTVA` | String(20) | Non | Numéro de TVA intracommunautaire |
| `siret` | String(14) | Non | Numéro SIRET (entreprises françaises) |
| `type` | TypeClient | Oui | Type de client (défaut: PARTICULIER) |
| `actif` | Boolean | Oui | Client actif (défaut: true) |
| `dateCreation` | LocalDateTime | Auto | Date de création |
| `dateModification` | LocalDateTime | Auto | Date de modification |
### **Relations**
| Relation | Type | Entité cible | Description |
|----------|------|--------------|-------------|
| `chantiers` | OneToMany | Chantier | Liste des chantiers du client |
| `devis` | OneToMany | Devis | Liste des devis du client |
---
## 🔌 API REST
### **Base URL**: `/api/v1/clients`
### **Endpoints disponibles**
| Méthode | Endpoint | Description | Permission |
|---------|----------|-------------|------------|
| GET | `/api/v1/clients` | Liste tous les clients | CLIENTS_READ |
| GET | `/api/v1/clients/{id}` | Détails d'un client | CLIENTS_READ |
| POST | `/api/v1/clients` | Créer un client | CLIENTS_CREATE |
| PUT | `/api/v1/clients/{id}` | Modifier un client | CLIENTS_UPDATE |
| DELETE | `/api/v1/clients/{id}` | Supprimer un client | CLIENTS_DELETE |
| GET | `/api/v1/clients/search` | Rechercher des clients | CLIENTS_READ |
| GET | `/api/v1/clients/stats` | Statistiques clients | CLIENTS_READ |
### **Paramètres de requête (Query Params)**
| Paramètre | Type | Description | Exemple |
|-----------|------|-------------|---------|
| `page` | Integer | Numéro de page (0-based) | `?page=0` |
| `size` | Integer | Taille de la page | `?size=20` |
| `search` | String | Terme de recherche | `?search=dupont` |
---
## 💻 Exemples d'utilisation
### **1. Récupérer tous les clients**
```bash
curl -X GET http://localhost:8080/api/v1/clients \
-H "Accept: application/json"
```
**Réponse** (200 OK):
```json
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"nom": "Dupont",
"prenom": "Jean",
"email": "jean.dupont@example.com",
"telephone": "+33 6 12 34 56 78",
"adresse": "123 Rue de la Paix",
"codePostal": "75002",
"ville": "Paris",
"type": "PARTICULIER",
"actif": true,
"dateCreation": "2025-01-15T10:30:00"
},
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"nom": "Martin",
"prenom": "Sophie",
"entreprise": "BTP Solutions SARL",
"email": "contact@btpsolutions.fr",
"telephone": "+33 1 23 45 67 89",
"siret": "12345678901234",
"numeroTVA": "FR12345678901",
"type": "PROFESSIONNEL",
"actif": true
}
]
```
### **2. Créer un nouveau client particulier**
```bash
curl -X POST http://localhost:8080/api/v1/clients \
-H "Content-Type: application/json" \
-d '{
"nom": "Durand",
"prenom": "Pierre",
"email": "pierre.durand@example.com",
"telephone": "+33 6 98 76 54 32",
"adresse": "45 Avenue des Champs",
"codePostal": "75008",
"ville": "Paris",
"type": "PARTICULIER"
}'
```
**Réponse** (201 Created):
```json
{
"id": "generated-uuid",
"nom": "Durand",
"prenom": "Pierre",
"email": "pierre.durand@example.com",
"type": "PARTICULIER",
"actif": true,
"dateCreation": "2025-09-30T14:25:00"
}
```
### **3. Créer un client professionnel**
```bash
curl -X POST http://localhost:8080/api/v1/clients \
-H "Content-Type: application/json" \
-d '{
"nom": "Entreprise",
"prenom": "Construction",
"entreprise": "ABC Construction SA",
"email": "contact@abc-construction.fr",
"telephone": "+33 1 45 67 89 01",
"adresse": "10 Boulevard Haussmann",
"codePostal": "75009",
"ville": "Paris",
"siret": "98765432109876",
"numeroTVA": "FR98765432109",
"type": "PROFESSIONNEL"
}'
```
### **4. Rechercher des clients**
```bash
# Par nom
curl -X GET "http://localhost:8080/api/v1/clients/search?search=dupont"
# Avec pagination
curl -X GET "http://localhost:8080/api/v1/clients?page=0&size=10"
```
### **5. Obtenir les statistiques**
```bash
curl -X GET http://localhost:8080/api/v1/clients/stats
```
**Réponse**:
```json
{
"totalClients": 156,
"clientsActifs": 142,
"particuliers": 98,
"professionnels": 58,
"nouveauxCeMois": 12,
"avecChantiers": 87,
"sansChantiers": 69
}
```
---
## 🔧 Services métier
### **ClientService**
**Méthodes principales**:
| Méthode | Description | Retour |
|---------|-------------|--------|
| `findAll()` | Récupère tous les clients | `List<Client>` |
| `findAll(int page, int size)` | Récupère avec pagination | `List<Client>` |
| `findById(UUID id)` | Récupère par ID | `Optional<Client>` |
| `findByIdRequired(UUID id)` | Récupère par ID (exception si absent) | `Client` |
| `create(ClientCreateDTO dto)` | Crée un client | `Client` |
| `update(UUID id, ClientCreateDTO dto)` | Met à jour | `Client` |
| `delete(UUID id)` | Supprime (soft delete) | `void` |
| `search(String term)` | Recherche textuelle | `List<Client>` |
| `findByType(TypeClient type)` | Filtre par type | `List<Client>` |
| `findActifs()` | Clients actifs uniquement | `List<Client>` |
| `getStatistics()` | Statistiques globales | `Object` |
---
## 🔐 Permissions requises
| Permission | Description | Rôles autorisés |
|------------|-------------|-----------------|
| `CLIENTS_READ` | Lecture des clients | ADMIN, MANAGER, CHEF_CHANTIER, COMPTABLE |
| `CLIENTS_CREATE` | Création de clients | ADMIN, MANAGER |
| `CLIENTS_UPDATE` | Modification de clients | ADMIN, MANAGER |
| `CLIENTS_DELETE` | Suppression de clients | ADMIN, MANAGER |
| `CLIENTS_ASSIGN` | Assignation à des chantiers | ADMIN, MANAGER |
---
## 📈 Relations avec autres concepts
### **Dépendances directes**:
- **CHANTIER** ➡️ Un client peut avoir plusieurs chantiers
- **DEVIS** ➡️ Un client peut avoir plusieurs devis
- **FACTURE** ➡️ Un client peut avoir plusieurs factures (via chantiers)
### **Utilisé par**:
- **CHANTIER** - Chaque chantier appartient à un client
- **DEVIS** - Chaque devis est lié à un client
- **FACTURE** - Chaque facture est adressée à un client
---
## ✅ Validations
### **Validations automatiques**:
- ✅ **Nom** : Obligatoire, max 100 caractères
- ✅ **Prénom** : Obligatoire, max 100 caractères
- ✅ **Email** : Format email valide, unique
- ✅ **Téléphone** : Format français valide (regex)
- ✅ **SIRET** : 14 caractères (si renseigné)
- ✅ **Type** : PARTICULIER ou PROFESSIONNEL
### **Règles métier**:
- Un client professionnel devrait avoir un SIRET et/ou numéro TVA
- Un client particulier n'a généralement pas d'entreprise
- L'email doit être unique dans le système
- Le téléphone doit respecter le format français
---
## 🧪 Tests
### **Tests unitaires**
- Fichier: `ClientServiceTest.java`
- Couverture: Logique métier, validations, recherche
### **Tests d'intégration**
- Fichier: `ClientResourceTest.java`
- Couverture: Endpoints REST, sérialisation JSON
### **Commande pour exécuter les tests**:
```bash
cd btpxpress-server
./mvnw test -Dtest=ClientServiceTest
./mvnw test -Dtest=ClientResourceTest
```
---
## 📚 Références
- [API Documentation complète](../API.md#clients)
- [Schéma de base de données](../DATABASE.md#table-clients)
- [Guide d'architecture](../architecture/domain-model.md#client)
- [Service ClientService](../../src/main/java/dev/lions/btpxpress/application/service/ClientService.java)
- [Resource ClientResource](../../src/main/java/dev/lions/btpxpress/adapter/http/ClientResource.java)
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0
**Auteur**: Documentation BTPXpress

View File

@@ -0,0 +1,417 @@
# 🔧 CONCEPT: MATERIEL
## 📌 Vue d'ensemble
Le concept **MATERIEL** gère l'ensemble des équipements, outils, véhicules et matériaux de l'entreprise BTP. Il inclut la gestion du stock, de la maintenance, des réservations, et des caractéristiques techniques ultra-détaillées.
**Importance**: ⭐⭐⭐⭐⭐ (Concept stratégique)
---
## 🗂️ Fichiers concernés
### **Entités JPA** (`domain/core/entity/`)
| Fichier | Description | Lignes |
|---------|-------------|--------|
| `Materiel.java` | Entité principale du matériel | 226 |
| `MaterielBTP.java` | Matériel BTP ultra-détaillé (spécifications techniques) | ~300 |
| `StatutMateriel.java` | Enum statuts (DISPONIBLE, UTILISE, MAINTENANCE, etc.) | 15 |
| `TypeMateriel.java` | Enum types (VEHICULE, OUTIL_ELECTRIQUE, etc.) | 20 |
| `ProprieteMateriel.java` | Enum propriété (PROPRE, LOUE, SOUS_TRAITANCE) | ~25 |
| `MarqueMateriel.java` | Entité marque de matériel | ~80 |
| `CompetenceMateriel.java` | Compétences requises pour utiliser le matériel | ~60 |
| `OutillageMateriel.java` | Outillage associé au matériel | ~70 |
| `TestQualiteMateriel.java` | Tests qualité du matériel | ~90 |
| `DimensionsTechniques.java` | Dimensions techniques détaillées | ~100 |
| `AdaptationClimatique.java` | Adaptation aux zones climatiques | ~80 |
| `ContrainteConstruction.java` | Contraintes de construction | ~70 |
### **Services** (`application/service/`)
| Fichier | Description |
|---------|-------------|
| `MaterielService.java` | Service métier principal |
| `MaterielFournisseurService.java` | Gestion relation matériel-fournisseur |
### **Resources (API REST)** (`adapter/http/`)
| Fichier | Description |
|---------|-------------|
| `MaterielResource.java` | Endpoints REST pour le matériel |
---
## 📊 Modèle de données
### **Entité Materiel**
<augment_code_snippet path="btpxpress-server/src/main/java/dev/lions/btpxpress/domain/core/entity/Materiel.java" mode="EXCERPT">
````java
@Entity
@Table(name = "materiels")
@Data
@Builder
public class Materiel extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@NotBlank(message = "Le nom du matériel est obligatoire")
@Column(name = "nom", nullable = false, length = 100)
private String nom;
@Column(name = "marque", length = 100)
private String marque;
@Column(name = "modele", length = 100)
private String modele;
@Column(name = "numero_serie", unique = true, length = 100)
private String numeroSerie;
@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "type", nullable = false)
private TypeMateriel type;
@Enumerated(EnumType.STRING)
@Column(name = "statut", nullable = false)
private StatutMateriel statut = StatutMateriel.DISPONIBLE;
@Column(name = "quantite_stock", precision = 10, scale = 3)
private BigDecimal quantiteStock = BigDecimal.ZERO;
@Column(name = "seuil_minimum", precision = 10, scale = 3)
private BigDecimal seuilMinimum = BigDecimal.ZERO;
// Relations
@OneToMany(mappedBy = "materiel", cascade = CascadeType.ALL)
private List<MaintenanceMateriel> maintenances;
@ManyToMany(mappedBy = "materiels")
private List<PlanningEvent> planningEvents;
}
````
</augment_code_snippet>
### **Enum StatutMateriel**
<augment_code_snippet path="btpxpress-server/src/main/java/dev/lions/btpxpress/domain/core/entity/StatutMateriel.java" mode="EXCERPT">
````java
public enum StatutMateriel {
DISPONIBLE, // Disponible pour utilisation
UTILISE, // Actuellement utilisé
MAINTENANCE, // En maintenance préventive
HORS_SERVICE, // Hors service (panne)
RESERVE, // Réservé pour un chantier
EN_REPARATION // En cours de réparation
}
````
</augment_code_snippet>
### **Enum TypeMateriel**
<augment_code_snippet path="btpxpress-server/src/main/java/dev/lions/btpxpress/domain/core/entity/TypeMateriel.java" mode="EXCERPT">
````java
public enum TypeMateriel {
VEHICULE, // Véhicules (camions, fourgons)
OUTIL_ELECTRIQUE, // Outils électriques (perceuse, scie)
OUTIL_MANUEL, // Outils manuels (marteau, pelle)
ECHAFAUDAGE, // Échafaudages
BETONIERE, // Bétonnières
GRUE, // Grues
COMPRESSEUR, // Compresseurs
GENERATEUR, // Générateurs électriques
ENGIN_CHANTIER, // Engins de chantier (pelleteuse, bulldozer)
MATERIEL_MESURE, // Matériel de mesure (niveau laser, théodolite)
EQUIPEMENT_SECURITE, // Équipements de sécurité (casques, harnais)
OUTILLAGE, // Outillage général
MATERIAUX_CONSTRUCTION, // Matériaux de construction
AUTRE // Autre type
}
````
</augment_code_snippet>
### **Champs principaux**
| Champ | Type | Obligatoire | Description |
|-------|------|-------------|-------------|
| `id` | UUID | Oui | Identifiant unique |
| `nom` | String(100) | Oui | Nom du matériel |
| `marque` | String(100) | Non | Marque du matériel |
| `modele` | String(100) | Non | Modèle |
| `numeroSerie` | String(100) | Non | Numéro de série (unique) |
| `type` | TypeMateriel | Oui | Type de matériel |
| `description` | String(1000) | Non | Description détaillée |
| `dateAchat` | LocalDate | Non | Date d'achat |
| `valeurAchat` | BigDecimal | Non | Valeur d'achat |
| `valeurActuelle` | BigDecimal | Non | Valeur actuelle (amortissement) |
| `statut` | StatutMateriel | Oui | Statut actuel (défaut: DISPONIBLE) |
| `localisation` | String(200) | Non | Localisation actuelle |
| `proprietaire` | String(200) | Non | Propriétaire (si location) |
| `coutUtilisation` | BigDecimal | Non | Coût d'utilisation (par heure/jour) |
| `quantiteStock` | BigDecimal | Oui | Quantité en stock (défaut: 0) |
| `seuilMinimum` | BigDecimal | Oui | Seuil minimum de stock (défaut: 0) |
| `unite` | String(20) | Non | Unité de mesure (pièce, kg, m, etc.) |
| `actif` | Boolean | Oui | Matériel actif (défaut: true) |
| `dateCreation` | LocalDateTime | Auto | Date de création |
| `dateModification` | LocalDateTime | Auto | Date de modification |
### **Relations**
| Relation | Type | Entité cible | Description |
|----------|------|--------------|-------------|
| `maintenances` | OneToMany | MaintenanceMateriel | Historique des maintenances |
| `planningEvents` | ManyToMany | PlanningEvent | Événements de planning |
| `catalogueEntrees` | OneToMany | CatalogueFournisseur | Offres fournisseurs |
| `reservations` | OneToMany | ReservationMateriel | Réservations |
---
## 🔌 API REST
### **Base URL**: `/api/v1/materiels`
### **Endpoints disponibles**
| Méthode | Endpoint | Description | Permission |
|---------|----------|-------------|------------|
| GET | `/api/v1/materiels` | Liste tous les matériels | MATERIELS_READ |
| GET | `/api/v1/materiels/{id}` | Détails d'un matériel | MATERIELS_READ |
| POST | `/api/v1/materiels` | Créer un matériel | MATERIELS_CREATE |
| PUT | `/api/v1/materiels/{id}` | Modifier un matériel | MATERIELS_UPDATE |
| DELETE | `/api/v1/materiels/{id}` | Supprimer un matériel | MATERIELS_DELETE |
| GET | `/api/v1/materiels/disponibles` | Matériels disponibles | MATERIELS_READ |
| GET | `/api/v1/materiels/type/{type}` | Matériels par type | MATERIELS_READ |
| GET | `/api/v1/materiels/stock-faible` | Matériels en stock faible | MATERIELS_READ |
| GET | `/api/v1/materiels/stats` | Statistiques matériel | MATERIELS_READ |
---
## 💻 Exemples d'utilisation
### **1. Récupérer tous les matériels**
```bash
curl -X GET http://localhost:8080/api/v1/materiels \
-H "Accept: application/json"
```
**Réponse** (200 OK):
```json
[
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"nom": "Perceuse sans fil Makita",
"marque": "Makita",
"modele": "DHP484",
"numeroSerie": "MAK-2025-001",
"type": "OUTIL_ELECTRIQUE",
"statut": "DISPONIBLE",
"quantiteStock": 5,
"seuilMinimum": 2,
"unite": "pièce",
"valeurAchat": 250.00,
"valeurActuelle": 200.00,
"actif": true
},
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"nom": "Camion benne Renault",
"marque": "Renault",
"modele": "Master",
"numeroSerie": "REN-2024-042",
"type": "VEHICULE",
"statut": "UTILISE",
"quantiteStock": 1,
"coutUtilisation": 150.00,
"localisation": "Chantier Villa Moderne",
"actif": true
}
]
```
### **2. Créer un nouveau matériel**
```bash
curl -X POST http://localhost:8080/api/v1/materiels \
-H "Content-Type: application/json" \
-d '{
"nom": "Bétonnière électrique",
"marque": "Altrad",
"modele": "B180",
"type": "BETONIERE",
"description": "Bétonnière électrique 180L",
"dateAchat": "2025-09-15",
"valeurAchat": 450.00,
"quantiteStock": 2,
"seuilMinimum": 1,
"unite": "pièce",
"statut": "DISPONIBLE"
}'
```
**Réponse** (201 Created):
```json
{
"id": "generated-uuid",
"nom": "Bétonnière électrique",
"type": "BETONIERE",
"statut": "DISPONIBLE",
"quantiteStock": 2,
"dateCreation": "2025-09-30T15:10:00"
}
```
### **3. Rechercher matériels disponibles**
```bash
curl -X GET http://localhost:8080/api/v1/materiels/disponibles
```
### **4. Matériels en stock faible**
```bash
curl -X GET http://localhost:8080/api/v1/materiels/stock-faible
```
**Réponse**:
```json
[
{
"id": "uuid",
"nom": "Casques de sécurité",
"quantiteStock": 3,
"seuilMinimum": 10,
"unite": "pièce",
"alerte": "STOCK_CRITIQUE"
}
]
```
### **5. Statistiques matériel**
```bash
curl -X GET http://localhost:8080/api/v1/materiels/stats
```
**Réponse**:
```json
{
"totalMateriels": 245,
"disponibles": 180,
"utilises": 45,
"enMaintenance": 12,
"horsService": 8,
"valeurTotale": 125000.00,
"stockFaible": 15,
"parType": {
"OUTIL_ELECTRIQUE": 85,
"VEHICULE": 12,
"ENGIN_CHANTIER": 8,
"ECHAFAUDAGE": 45
}
}
```
---
## 🔧 Services métier
### **MaterielService**
**Méthodes principales**:
| Méthode | Description | Retour |
|---------|-------------|--------|
| `findAll()` | Récupère tous les matériels | `List<Materiel>` |
| `findById(UUID id)` | Récupère par ID | `Optional<Materiel>` |
| `create(MaterielDTO dto)` | Crée un matériel | `Materiel` |
| `update(UUID id, MaterielDTO dto)` | Met à jour | `Materiel` |
| `delete(UUID id)` | Supprime (soft delete) | `void` |
| `findDisponibles()` | Matériels disponibles | `List<Materiel>` |
| `findByType(TypeMateriel type)` | Filtre par type | `List<Materiel>` |
| `findStockFaible()` | Stock sous seuil minimum | `List<Materiel>` |
| `changerStatut(UUID id, StatutMateriel statut)` | Change le statut | `Materiel` |
| `ajusterStock(UUID id, BigDecimal quantite)` | Ajuste le stock | `Materiel` |
| `getStatistics()` | Statistiques globales | `Object` |
---
## 🔐 Permissions requises
| Permission | Description | Rôles autorisés |
|------------|-------------|-----------------|
| `MATERIELS_READ` | Lecture du matériel | ADMIN, MANAGER, CHEF_CHANTIER, OUVRIER |
| `MATERIELS_CREATE` | Création de matériel | ADMIN, MANAGER |
| `MATERIELS_UPDATE` | Modification de matériel | ADMIN, MANAGER, CHEF_CHANTIER |
| `MATERIELS_DELETE` | Suppression de matériel | ADMIN, MANAGER |
| `MATERIELS_STOCK` | Gestion du stock | ADMIN, MANAGER, CHEF_CHANTIER |
---
## 📈 Relations avec autres concepts
### **Dépendances directes**:
- **MAINTENANCE** ➡️ Un matériel a un historique de maintenances
- **RESERVATION_MATERIEL** ➡️ Un matériel peut être réservé
- **PLANNING** ➡️ Un matériel apparaît dans le planning
- **FOURNISSEUR** ➡️ Un matériel peut avoir plusieurs fournisseurs (catalogue)
- **LIVRAISON** ➡️ Un matériel peut être livré
### **Utilisé par**:
- **CHANTIER** - Matériel affecté aux chantiers
- **EMPLOYE** - Matériel utilisé par les employés
- **BON_COMMANDE** - Matériel commandé
---
## ✅ Validations
### **Validations automatiques**:
- ✅ **Nom** : Obligatoire, max 100 caractères
- ✅ **Type** : Obligatoire, valeur de l'enum TypeMateriel
- ✅ **Numéro de série** : Unique si renseigné
- ✅ **Quantité stock** : Nombre positif ou zéro
- ✅ **Seuil minimum** : Nombre positif ou zéro
### **Règles métier**:
- Le stock ne peut pas être négatif
- Alerte si quantiteStock < seuilMinimum
- Un matériel HORS_SERVICE ne peut pas être réservé
- Un matériel en MAINTENANCE ne peut pas être utilisé
---
## 🧪 Tests
### **Tests unitaires**
- Fichier: `MaterielServiceTest.java`
- Couverture: Logique métier, gestion stock, validations
### **Tests d'intégration**
- Fichier: `MaterielResourceTest.java`
- Couverture: Endpoints REST, sérialisation JSON
### **Commande pour exécuter les tests**:
```bash
cd btpxpress-server
./mvnw test -Dtest=MaterielServiceTest
./mvnw test -Dtest=MaterielResourceTest
```
---
## 📚 Références
- [API Documentation complète](../API.md#materiels)
- [Schéma de base de données](../DATABASE.md#table-materiels)
- [Concept MAINTENANCE](./12-MAINTENANCE.md)
- [Concept RESERVATION_MATERIEL](./04-RESERVATION_MATERIEL.md)
- [Service MaterielService](../../src/main/java/dev/lions/btpxpress/application/service/MaterielService.java)
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0
**Auteur**: Documentation BTPXpress

View File

@@ -0,0 +1,186 @@
# 📅 CONCEPT: RESERVATION_MATERIEL
## 📌 Vue d'ensemble
Le concept **RESERVATION_MATERIEL** gère les réservations et affectations de matériel aux chantiers. Il permet de planifier l'utilisation du matériel, éviter les conflits, et optimiser l'allocation des ressources.
**Importance**: ⭐⭐⭐ (Concept important)
---
## 🗂️ Fichiers concernés
### **Entités JPA** (`domain/core/entity/`)
| Fichier | Description | Lignes |
|---------|-------------|--------|
| `ReservationMateriel.java` | Entité principale de réservation | ~180 |
| `StatutReservationMateriel.java` | Enum statuts (PLANIFIEE, VALIDEE, EN_COURS, TERMINEE, REFUSEE, ANNULEE) | ~20 |
| `PrioriteReservation.java` | Enum priorités de réservation | ~25 |
| `PlanningMateriel.java` | Planning d'utilisation du matériel | ~200 |
| `StatutPlanning.java` | Enum statuts de planning | ~30 |
| `TypePlanning.java` | Enum types de planning | ~25 |
### **Services** (`application/service/`)
| Fichier | Description |
|---------|-------------|
| `ReservationMaterielService.java` | Service métier pour les réservations |
| `PlanningMaterielService.java` | Service de gestion du planning matériel |
---
## 📊 Modèle de données
### **Entité ReservationMateriel**
```java
@Entity
@Table(name = "reservations_materiel")
public class ReservationMateriel extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne
@JoinColumn(name = "materiel_id", nullable = false)
private Materiel materiel;
@ManyToOne
@JoinColumn(name = "chantier_id", nullable = false)
private Chantier chantier;
@Column(name = "date_debut", nullable = false)
private LocalDate dateDebut;
@Column(name = "date_fin", nullable = false)
private LocalDate dateFin;
@Enumerated(EnumType.STRING)
@Column(name = "statut", nullable = false)
private StatutReservationMateriel statut = StatutReservationMateriel.PLANIFIEE;
@Column(name = "quantite", precision = 10, scale = 3)
private BigDecimal quantite;
@Enumerated(EnumType.STRING)
@Column(name = "priorite")
private PrioriteReservation priorite;
}
```
### **Enum StatutReservationMateriel**
```java
public enum StatutReservationMateriel {
PLANIFIEE, // Réservation planifiée
VALIDEE, // Réservation validée
EN_COURS, // Réservation en cours d'utilisation
TERMINEE, // Réservation terminée
REFUSEE, // Réservation refusée
ANNULEE // Réservation annulée
}
```
### **Champs principaux**
| Champ | Type | Obligatoire | Description |
|-------|------|-------------|-------------|
| `id` | UUID | Oui | Identifiant unique |
| `materiel` | Materiel | Oui | Matériel réservé |
| `chantier` | Chantier | Oui | Chantier destinataire |
| `dateDebut` | LocalDate | Oui | Date de début de réservation |
| `dateFin` | LocalDate | Oui | Date de fin de réservation |
| `statut` | StatutReservationMateriel | Oui | Statut actuel |
| `quantite` | BigDecimal | Non | Quantité réservée |
| `priorite` | PrioriteReservation | Non | Priorité de la réservation |
| `commentaire` | String | Non | Commentaire |
---
## 🔌 API REST
### **Base URL**: `/api/v1/reservations-materiel`
### **Endpoints disponibles**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/reservations-materiel` | Liste toutes les réservations |
| GET | `/api/v1/reservations-materiel/{id}` | Détails d'une réservation |
| POST | `/api/v1/reservations-materiel` | Créer une réservation |
| PUT | `/api/v1/reservations-materiel/{id}` | Modifier une réservation |
| DELETE | `/api/v1/reservations-materiel/{id}` | Annuler une réservation |
| GET | `/api/v1/reservations-materiel/materiel/{id}` | Réservations d'un matériel |
| GET | `/api/v1/reservations-materiel/chantier/{id}` | Réservations d'un chantier |
| GET | `/api/v1/reservations-materiel/conflits` | Détecter les conflits |
---
## 💻 Exemples d'utilisation
### **1. Créer une réservation**
```bash
curl -X POST http://localhost:8080/api/v1/reservations-materiel \
-H "Content-Type: application/json" \
-d '{
"materielId": "materiel-uuid",
"chantierId": "chantier-uuid",
"dateDebut": "2025-10-01",
"dateFin": "2025-10-15",
"quantite": 2,
"priorite": "NORMALE"
}'
```
### **2. Vérifier les conflits**
```bash
curl -X GET "http://localhost:8080/api/v1/reservations-materiel/conflits?materielId=uuid&dateDebut=2025-10-01&dateFin=2025-10-15"
```
---
## 🔧 Services métier
### **ReservationMaterielService**
**Méthodes principales**:
- `create(ReservationDTO dto)` - Créer une réservation
- `verifierDisponibilite(UUID materielId, LocalDate debut, LocalDate fin)` - Vérifier disponibilité
- `detecterConflits(UUID materielId, LocalDate debut, LocalDate fin)` - Détecter conflits
- `valider(UUID id)` - Valider une réservation
- `annuler(UUID id)` - Annuler une réservation
---
## 📈 Relations avec autres concepts
- **MATERIEL** ⬅️ Une réservation concerne un matériel
- **CHANTIER** ⬅️ Une réservation est liée à un chantier
- **PLANNING** ➡️ Les réservations alimentent le planning
- **LIVRAISON** ➡️ Une réservation peut générer une livraison
---
## ✅ Validations
- ✅ Date de fin doit être après date de début
- ✅ Le matériel doit être disponible
- ✅ Pas de conflit avec d'autres réservations
- ✅ Quantité disponible suffisante
---
## 📚 Références
- [Concept MATERIEL](./03-MATERIEL.md)
- [Concept CHANTIER](./01-CHANTIER.md)
- [Concept PLANNING](./13-PLANNING.md)
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0
**Auteur**: Documentation BTPXpress

View File

@@ -0,0 +1,213 @@
# 🚚 CONCEPT: LIVRAISON
## 📌 Vue d'ensemble
Le concept **LIVRAISON** gère la logistique et le suivi des livraisons de matériel sur les chantiers. Il couvre le transport, le suivi en temps réel, et la gestion des transporteurs.
**Importance**: ⭐⭐⭐ (Concept important)
---
## 🗂️ Fichiers concernés
### **Entités JPA** (`domain/core/entity/`)
| Fichier | Description | Lignes |
|---------|-------------|--------|
| `LivraisonMateriel.java` | Entité principale de livraison | ~200 |
| `StatutLivraison.java` | Enum statuts (PLANIFIEE, EN_PREPARATION, EN_TRANSIT, LIVREE, ANNULEE, RETARDEE) | ~30 |
| `ModeLivraison.java` | Enum modes de livraison | ~25 |
| `TypeTransport.java` | Enum types de transport | ~20 |
### **Services** (`application/service/`)
| Fichier | Description |
|---------|-------------|
| `LivraisonMaterielService.java` | Service métier pour les livraisons |
---
## 📊 Modèle de données
### **Entité LivraisonMateriel**
```java
@Entity
@Table(name = "livraisons_materiel")
public class LivraisonMateriel extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne
@JoinColumn(name = "reservation_id")
private ReservationMateriel reservation;
@Column(name = "date_livraison_prevue", nullable = false)
private LocalDateTime dateLivraisonPrevue;
@Column(name = "date_livraison_reelle")
private LocalDateTime dateLivraisonReelle;
@Enumerated(EnumType.STRING)
@Column(name = "statut", nullable = false)
private StatutLivraison statut = StatutLivraison.PLANIFIEE;
@Column(name = "transporteur", length = 200)
private String transporteur;
@Column(name = "numero_suivi", length = 100)
private String numeroSuivi;
@Enumerated(EnumType.STRING)
@Column(name = "mode_livraison")
private ModeLivraison modeLivraison;
@Column(name = "adresse_livraison", length = 500)
private String adresseLivraison;
@Column(name = "cout_livraison", precision = 10, scale = 2)
private BigDecimal coutLivraison;
}
```
### **Enum StatutLivraison**
```java
public enum StatutLivraison {
PLANIFIEE, // Livraison planifiée
EN_PREPARATION, // En cours de préparation
EN_TRANSIT, // En transit
LIVREE, // Livrée avec succès
ANNULEE, // Livraison annulée
RETARDEE // Livraison retardée
}
```
### **Champs principaux**
| Champ | Type | Obligatoire | Description |
|-------|------|-------------|-------------|
| `id` | UUID | Oui | Identifiant unique |
| `reservation` | ReservationMateriel | Non | Réservation associée |
| `dateLivraisonPrevue` | LocalDateTime | Oui | Date/heure prévue |
| `dateLivraisonReelle` | LocalDateTime | Non | Date/heure réelle |
| `statut` | StatutLivraison | Oui | Statut actuel |
| `transporteur` | String(200) | Non | Nom du transporteur |
| `numeroSuivi` | String(100) | Non | Numéro de suivi |
| `modeLivraison` | ModeLivraison | Non | Mode de livraison |
| `adresseLivraison` | String(500) | Non | Adresse de livraison |
| `coutLivraison` | BigDecimal | Non | Coût de la livraison |
---
## 🔌 API REST
### **Base URL**: `/api/v1/livraisons`
### **Endpoints disponibles**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/livraisons` | Liste toutes les livraisons |
| GET | `/api/v1/livraisons/{id}` | Détails d'une livraison |
| POST | `/api/v1/livraisons` | Créer une livraison |
| PUT | `/api/v1/livraisons/{id}` | Modifier une livraison |
| PUT | `/api/v1/livraisons/{id}/statut` | Changer le statut |
| GET | `/api/v1/livraisons/en-cours` | Livraisons en cours |
| GET | `/api/v1/livraisons/retardees` | Livraisons retardées |
| GET | `/api/v1/livraisons/stats` | Statistiques livraisons |
---
## 💻 Exemples d'utilisation
### **1. Créer une livraison**
```bash
curl -X POST http://localhost:8080/api/v1/livraisons \
-H "Content-Type: application/json" \
-d '{
"reservationId": "reservation-uuid",
"dateLivraisonPrevue": "2025-10-05T09:00:00",
"transporteur": "Transport Express",
"modeLivraison": "STANDARD",
"adresseLivraison": "123 Rue du Chantier, 75001 Paris"
}'
```
### **2. Mettre à jour le statut**
```bash
curl -X PUT http://localhost:8080/api/v1/livraisons/{id}/statut \
-H "Content-Type: application/json" \
-d '{
"statut": "EN_TRANSIT",
"numeroSuivi": "TRACK123456"
}'
```
### **3. Livraisons en cours**
```bash
curl -X GET http://localhost:8080/api/v1/livraisons/en-cours
```
**Réponse**:
```json
[
{
"id": "uuid",
"statut": "EN_TRANSIT",
"transporteur": "Transport Express",
"numeroSuivi": "TRACK123456",
"dateLivraisonPrevue": "2025-10-05T09:00:00",
"adresseLivraison": "123 Rue du Chantier"
}
]
```
---
## 🔧 Services métier
### **LivraisonMaterielService**
**Méthodes principales**:
- `create(LivraisonDTO dto)` - Créer une livraison
- `changerStatut(UUID id, StatutLivraison statut)` - Changer le statut
- `findEnCours()` - Livraisons en cours
- `findRetardees()` - Livraisons retardées
- `calculerDelai(UUID id)` - Calculer le délai
- `getStatistics()` - Statistiques
---
## 📈 Relations avec autres concepts
- **RESERVATION_MATERIEL** ⬅️ Une livraison peut être liée à une réservation
- **CHANTIER** ⬅️ Une livraison est destinée à un chantier
- **MATERIEL** ⬅️ Une livraison concerne du matériel
---
## ✅ Validations
- ✅ Date de livraison prévue obligatoire
- ✅ Adresse de livraison valide
- ✅ Statut cohérent avec les transitions
- ✅ Coût de livraison positif
---
## 📚 Références
- [Concept RESERVATION_MATERIEL](./04-RESERVATION_MATERIEL.md)
- [Concept MATERIEL](./03-MATERIEL.md)
- [Concept CHANTIER](./01-CHANTIER.md)
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0
**Auteur**: Documentation BTPXpress

View File

@@ -0,0 +1,254 @@
# 🏪 CONCEPT: FOURNISSEUR
## 📌 Vue d'ensemble
Le concept **FOURNISSEUR** gère les fournisseurs de matériel et services BTP. Il inclut le catalogue produits, les comparaisons de prix, et les conditions commerciales.
**Importance**: ⭐⭐⭐⭐ (Concept stratégique)
---
## 🗂️ Fichiers concernés
### **Entités JPA** (`domain/core/entity/`)
| Fichier | Description | Lignes |
|---------|-------------|--------|
| `Fournisseur.java` | Entité principale fournisseur | ~150 |
| `FournisseurMateriel.java` | Relation fournisseur-matériel | ~80 |
| `CatalogueFournisseur.java` | Catalogue produits fournisseur | ~120 |
| `ComparaisonFournisseur.java` | Comparaison entre fournisseurs | ~100 |
| `StatutFournisseur.java` | Enum statuts (ACTIF, INACTIF, SUSPENDU, BLOQUE) | ~20 |
| `SpecialiteFournisseur.java` | Enum spécialités (MATERIAUX_GROS_OEUVRE, etc.) | ~70 |
| `ConditionsPaiement.java` | Enum conditions de paiement | ~40 |
| `CritereComparaison.java` | Enum critères de comparaison | ~25 |
### **DTOs** (`domain/shared/dto/`)
| Fichier | Description |
|---------|-------------|
| `FournisseurDTO.java` | DTO fournisseur avec enum TypeFournisseur |
### **Services** (`application/service/`)
| Fichier | Description |
|---------|-------------|
| `FournisseurService.java` | Service métier fournisseurs |
| `ComparaisonFournisseurService.java` | Service de comparaison |
---
## 📊 Modèle de données
### **Entité Fournisseur**
```java
@Entity
@Table(name = "fournisseurs")
public class Fournisseur extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Column(name = "nom", nullable = false, length = 100)
private String nom;
@Column(name = "siret", length = 20)
private String siret;
@Column(name = "numero_tva", length = 15)
private String numeroTva;
@Email
@Column(name = "email", length = 100)
private String email;
@Column(name = "telephone", length = 20)
private String telephone;
@Column(name = "adresse", length = 200)
private String adresse;
@Enumerated(EnumType.STRING)
@Column(name = "statut")
private StatutFournisseur statut = StatutFournisseur.ACTIF;
@ElementCollection
@CollectionTable(name = "fournisseur_specialites")
@Enumerated(EnumType.STRING)
private List<SpecialiteFournisseur> specialites;
@Enumerated(EnumType.STRING)
@Column(name = "conditions_paiement")
private ConditionsPaiement conditionsPaiement;
@Column(name = "delai_paiement_jours")
private Integer delaiPaiementJours;
}
```
### **Enum SpecialiteFournisseur**
```java
public enum SpecialiteFournisseur {
// Matériaux de construction
MATERIAUX_GROS_OEUVRE("Matériaux gros œuvre", "Béton, ciment, parpaings"),
MATERIAUX_CHARPENTE("Matériaux charpente", "Bois de charpente"),
MATERIAUX_COUVERTURE("Matériaux couverture", "Tuiles, ardoises"),
MATERIAUX_ISOLATION("Matériaux isolation", "Isolants thermiques"),
// Équipements techniques
PLOMBERIE("Plomberie", "Tuyauterie, robinetterie"),
ELECTRICITE("Électricité", "Câbles, tableaux électriques"),
CHAUFFAGE("Chauffage", "Chaudières, radiateurs"),
// Équipements et outils
LOCATION_MATERIEL("Location matériel", "Location engins et outils"),
OUTILLAGE("Outillage", "Outils électriques et manuels"),
// Services
TRANSPORT("Transport", "Transport de matériaux"),
MULTI_SPECIALITES("Multi-spécialités", "Fournisseur généraliste"),
AUTRE("Autre", "Autre spécialité")
}
```
### **Champs principaux**
| Champ | Type | Obligatoire | Description |
|-------|------|-------------|-------------|
| `id` | Long | Oui | Identifiant unique |
| `nom` | String(100) | Oui | Nom du fournisseur |
| `siret` | String(20) | Non | Numéro SIRET |
| `numeroTva` | String(15) | Non | Numéro TVA |
| `email` | String(100) | Non | Email de contact |
| `telephone` | String(20) | Non | Téléphone |
| `adresse` | String(200) | Non | Adresse |
| `statut` | StatutFournisseur | Oui | Statut (défaut: ACTIF) |
| `specialites` | List<SpecialiteFournisseur> | Non | Spécialités |
| `conditionsPaiement` | ConditionsPaiement | Non | Conditions de paiement |
| `delaiPaiementJours` | Integer | Non | Délai de paiement en jours |
---
## 🔌 API REST
### **Base URL**: `/api/v1/fournisseurs`
### **Endpoints disponibles**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/fournisseurs` | Liste tous les fournisseurs |
| GET | `/api/v1/fournisseurs/{id}` | Détails d'un fournisseur |
| POST | `/api/v1/fournisseurs` | Créer un fournisseur |
| PUT | `/api/v1/fournisseurs/{id}` | Modifier un fournisseur |
| DELETE | `/api/v1/fournisseurs/{id}` | Supprimer un fournisseur |
| GET | `/api/v1/fournisseurs/specialite/{specialite}` | Par spécialité |
| GET | `/api/v1/fournisseurs/comparer` | Comparer des fournisseurs |
| GET | `/api/v1/fournisseurs/stats` | Statistiques |
---
## 💻 Exemples d'utilisation
### **1. Créer un fournisseur**
```bash
curl -X POST http://localhost:8080/api/v1/fournisseurs \
-H "Content-Type: application/json" \
-d '{
"nom": "Matériaux Pro",
"siret": "12345678901234",
"email": "contact@materiauxpro.fr",
"telephone": "+33 1 23 45 67 89",
"adresse": "10 Rue de l Industrie, 75001 Paris",
"specialites": ["MATERIAUX_GROS_OEUVRE", "MATERIAUX_ISOLATION"],
"conditionsPaiement": "NET_30",
"delaiPaiementJours": 30
}'
```
### **2. Rechercher par spécialité**
```bash
curl -X GET "http://localhost:8080/api/v1/fournisseurs/specialite/MATERIAUX_GROS_OEUVRE"
```
### **3. Comparer des fournisseurs**
```bash
curl -X GET "http://localhost:8080/api/v1/fournisseurs/comparer?materielId=uuid&fournisseurIds=id1,id2,id3"
```
**Réponse**:
```json
{
"materiel": "Ciment Portland 25kg",
"comparaisons": [
{
"fournisseur": "Matériaux Pro",
"prix": 8.50,
"delaiLivraison": 2,
"conditionsPaiement": "NET_30",
"note": 4.5
},
{
"fournisseur": "BTP Discount",
"prix": 7.90,
"delaiLivraison": 5,
"conditionsPaiement": "NET_45",
"note": 4.2
}
]
}
```
---
## 🔧 Services métier
### **FournisseurService**
**Méthodes principales**:
- `findAll()` - Tous les fournisseurs
- `findBySpecialite(SpecialiteFournisseur)` - Par spécialité
- `findActifs()` - Fournisseurs actifs
- `create(FournisseurDTO)` - Créer
- `update(Long id, FournisseurDTO)` - Modifier
### **ComparaisonFournisseurService**
**Méthodes principales**:
- `comparerPrix(UUID materielId, List<Long> fournisseurIds)` - Comparer prix
- `getMeilleurFournisseur(UUID materielId, CritereComparaison)` - Meilleur fournisseur
---
## 📈 Relations avec autres concepts
- **MATERIEL** ➡️ Un fournisseur propose du matériel (catalogue)
- **BON_COMMANDE** ➡️ Un fournisseur reçoit des bons de commande
- **FACTURE** ➡️ Un fournisseur émet des factures
---
## ✅ Validations
- ✅ Nom obligatoire
- ✅ Email au format valide
- ✅ SIRET 14 caractères si renseigné
- ✅ Au moins une spécialité
---
## 📚 Références
- [Concept MATERIEL](./03-MATERIEL.md)
- [Concept BON_COMMANDE](./08-BON_COMMANDE.md)
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0
**Auteur**: Documentation BTPXpress

182
docs/concepts/07-STOCK.md Normal file
View File

@@ -0,0 +1,182 @@
# 📦 CONCEPT: STOCK
## 📌 Vue d'ensemble
Le concept **STOCK** gère les stocks de matériaux et fournitures avec suivi des mouvements, alertes de rupture, et inventaires.
**Importance**: ⭐⭐⭐ (Concept important)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `Stock.java` | Entité principale stock |
| `CategorieStock.java` | Catégorie de stock |
| `SousCategorieStock.java` | Sous-catégorie |
| `StatutStock.java` | Enum (DISPONIBLE, RESERVE, RUPTURE, COMMANDE, PERIME) |
| `UniteMesure.java` | Enum unités (UNITE, KG, M, L, etc.) |
| `UnitePrix.java` | Enum unités de prix |
### **Services**
| Fichier | Description |
|---------|-------------|
| `StockService.java` | Service métier stock |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "stocks")
public class Stock extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(name = "designation", nullable = false)
private String designation;
@Column(name = "reference", unique = true)
private String reference;
@ManyToOne
@JoinColumn(name = "categorie_id")
private CategorieStock categorie;
@Column(name = "quantite", precision = 10, scale = 3)
private BigDecimal quantite = BigDecimal.ZERO;
@Column(name = "seuil_alerte", precision = 10, scale = 3)
private BigDecimal seuilAlerte;
@Enumerated(EnumType.STRING)
@Column(name = "unite")
private UniteMesure unite;
@Enumerated(EnumType.STRING)
@Column(name = "statut")
private StatutStock statut = StatutStock.DISPONIBLE;
@Column(name = "prix_unitaire", precision = 10, scale = 2)
private BigDecimal prixUnitaire;
}
```
### **Enum UniteMesure**
```java
public enum UniteMesure {
UNITE, PAIRE, LOT, KIT, // Quantité
GRAMME, KILOGRAMME, TONNE, // Poids
MILLIMETRE, CENTIMETRE, METRE, // Longueur
METRE_CARRE, METRE_CUBE, // Surface/Volume
LITRE, MILLILITRE, // Volume liquide
AUTRE
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/stocks` | Liste stocks |
| GET | `/api/v1/stocks/{id}` | Détails stock |
| POST | `/api/v1/stocks` | Créer stock |
| PUT | `/api/v1/stocks/{id}` | Modifier stock |
| POST | `/api/v1/stocks/{id}/mouvement` | Enregistrer mouvement |
| GET | `/api/v1/stocks/alertes` | Stocks en alerte |
| GET | `/api/v1/stocks/stats` | Statistiques |
---
## 💻 Exemples
### **Créer un article en stock**
```bash
curl -X POST http://localhost:8080/api/v1/stocks \
-H "Content-Type: application/json" \
-d '{
"designation": "Ciment Portland 25kg",
"reference": "CIM-PORT-25",
"categorieId": 1,
"quantite": 100,
"seuilAlerte": 20,
"unite": "UNITE",
"prixUnitaire": 8.50
}'
```
### **Enregistrer un mouvement**
```bash
curl -X POST http://localhost:8080/api/v1/stocks/{id}/mouvement \
-H "Content-Type: application/json" \
-d '{
"type": "SORTIE",
"quantite": 10,
"motif": "Chantier Villa Moderne",
"chantierId": "uuid"
}'
```
### **Stocks en alerte**
```bash
curl -X GET http://localhost:8080/api/v1/stocks/alertes
```
**Réponse**:
```json
[
{
"id": "uuid",
"designation": "Ciment Portland 25kg",
"quantite": 15,
"seuilAlerte": 20,
"statut": "ALERTE_STOCK"
}
]
```
---
## 🔧 Services métier
**StockService - Méthodes**:
- `findAll()` - Tous les stocks
- `ajouterStock(UUID id, BigDecimal quantite)` - Ajouter
- `retirerStock(UUID id, BigDecimal quantite)` - Retirer
- `findAlertes()` - Stocks en alerte
- `inventaire()` - Inventaire complet
---
## 📈 Relations
- **MATERIEL** ⬅️ Un stock peut être lié à du matériel
- **BON_COMMANDE** ➡️ Commandes pour réapprovisionner
- **CHANTIER** ➡️ Sorties de stock pour chantiers
---
## ✅ Validations
- ✅ Quantité ne peut pas être négative
- ✅ Seuil d'alerte positif
- ✅ Référence unique
- ✅ Unité de mesure cohérente
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

View File

@@ -0,0 +1,229 @@
# 📋 CONCEPT: BON_COMMANDE
## 📌 Vue d'ensemble
Le concept **BON_COMMANDE** gère les bons de commande auprès des fournisseurs pour l'achat de matériel, fournitures et services.
**Importance**: ⭐⭐⭐ (Concept important)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `BonCommande.java` | Entité principale bon de commande |
| `LigneBonCommande.java` | Ligne de bon de commande |
| `StatutBonCommande.java` | Enum (BROUILLON, VALIDEE, ENVOYEE, CONFIRMEE, LIVREE, ANNULEE) |
| `StatutLigneBonCommande.java` | Enum statuts ligne |
| `TypeBonCommande.java` | Enum types (ACHAT, LOCATION, PRESTATIONS, etc.) |
| `PrioriteBonCommande.java` | Enum priorités |
### **Services**
| Fichier | Description |
|---------|-------------|
| `BonCommandeService.java` | Service métier |
| `LigneBonCommandeService.java` | Service lignes |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "bons_commande")
public class BonCommande extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(name = "numero", unique = true, nullable = false)
private String numero;
@ManyToOne
@JoinColumn(name = "fournisseur_id", nullable = false)
private Fournisseur fournisseur;
@Column(name = "date_commande", nullable = false)
private LocalDate dateCommande;
@Column(name = "date_livraison_souhaitee")
private LocalDate dateLivraisonSouhaitee;
@Enumerated(EnumType.STRING)
@Column(name = "statut", nullable = false)
private StatutBonCommande statut = StatutBonCommande.BROUILLON;
@Enumerated(EnumType.STRING)
@Column(name = "type")
private TypeBonCommande type;
@OneToMany(mappedBy = "bonCommande", cascade = CascadeType.ALL)
private List<LigneBonCommande> lignes;
@Column(name = "montant_total", precision = 10, scale = 2)
private BigDecimal montantTotal = BigDecimal.ZERO;
@Column(name = "commentaire", length = 1000)
private String commentaire;
}
```
### **Enum StatutBonCommande**
```java
public enum StatutBonCommande {
BROUILLON, // En cours de rédaction
VALIDEE, // Validée en interne
ENVOYEE, // Envoyée au fournisseur
CONFIRMEE, // Confirmée par le fournisseur
LIVREE, // Livrée
ANNULEE // Annulée
}
```
### **Enum TypeBonCommande**
```java
public enum TypeBonCommande {
ACHAT, // Achat de matériel
LOCATION, // Location de matériel
PRESTATIONS, // Prestations de service
FOURNITURES, // Fournitures consommables
TRAVAUX, // Travaux sous-traités
MAINTENANCE, // Maintenance
TRANSPORT, // Transport
AUTRE
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/bons-commande` | Liste bons de commande |
| GET | `/api/v1/bons-commande/{id}` | Détails |
| POST | `/api/v1/bons-commande` | Créer |
| PUT | `/api/v1/bons-commande/{id}` | Modifier |
| PUT | `/api/v1/bons-commande/{id}/valider` | Valider |
| PUT | `/api/v1/bons-commande/{id}/envoyer` | Envoyer |
| DELETE | `/api/v1/bons-commande/{id}` | Annuler |
| GET | `/api/v1/bons-commande/stats` | Statistiques |
---
## 💻 Exemples
### **Créer un bon de commande**
```bash
curl -X POST http://localhost:8080/api/v1/bons-commande \
-H "Content-Type: application/json" \
-d '{
"fournisseurId": 1,
"dateCommande": "2025-10-01",
"dateLivraisonSouhaitee": "2025-10-10",
"type": "ACHAT",
"lignes": [
{
"designation": "Ciment Portland 25kg",
"quantite": 50,
"prixUnitaire": 8.50,
"unite": "UNITE"
},
{
"designation": "Sable 0/4 - 1 tonne",
"quantite": 10,
"prixUnitaire": 45.00,
"unite": "TONNE"
}
],
"commentaire": "Livraison sur chantier Villa Moderne"
}'
```
**Réponse**:
```json
{
"id": "uuid",
"numero": "BC-2025-001",
"fournisseur": "Matériaux Pro",
"dateCommande": "2025-10-01",
"statut": "BROUILLON",
"montantTotal": 875.00,
"lignes": [
{
"designation": "Ciment Portland 25kg",
"quantite": 50,
"prixUnitaire": 8.50,
"montant": 425.00
},
{
"designation": "Sable 0/4 - 1 tonne",
"quantite": 10,
"prixUnitaire": 45.00,
"montant": 450.00
}
]
}
```
### **Valider un bon de commande**
```bash
curl -X PUT http://localhost:8080/api/v1/bons-commande/{id}/valider
```
### **Envoyer au fournisseur**
```bash
curl -X PUT http://localhost:8080/api/v1/bons-commande/{id}/envoyer \
-H "Content-Type: application/json" \
-d '{
"emailFournisseur": "contact@materiauxpro.fr",
"message": "Veuillez trouver ci-joint notre bon de commande"
}'
```
---
## 🔧 Services métier
**BonCommandeService - Méthodes**:
- `create(BonCommandeDTO)` - Créer
- `valider(UUID id)` - Valider
- `envoyer(UUID id)` - Envoyer au fournisseur
- `annuler(UUID id)` - Annuler
- `calculerMontantTotal(UUID id)` - Calculer total
- `findByStatut(StatutBonCommande)` - Par statut
- `findByFournisseur(Long fournisseurId)` - Par fournisseur
---
## 📈 Relations
- **FOURNISSEUR** ⬅️ Un bon de commande est adressé à un fournisseur
- **CHANTIER** ⬅️ Un bon peut être lié à un chantier
- **STOCK** ➡️ Réception met à jour le stock
---
## ✅ Validations
- ✅ Numéro unique et obligatoire
- ✅ Fournisseur obligatoire
- ✅ Au moins une ligne
- ✅ Quantités positives
- ✅ Prix unitaires positifs
- ✅ Transitions de statut cohérentes
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

278
docs/concepts/09-DEVIS.md Normal file
View File

@@ -0,0 +1,278 @@
# 💰 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<LigneDevis> 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

142
docs/concepts/10-BUDGET.md Normal file
View File

@@ -0,0 +1,142 @@
# 💵 CONCEPT: BUDGET
## 📌 Vue d'ensemble
Le concept **BUDGET** gère les budgets prévisionnels et réels des chantiers avec suivi des dépenses et écarts.
**Importance**: ⭐⭐⭐ (Concept important)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `Budget.java` | Entité principale budget |
### **Services**
| Fichier | Description |
|---------|-------------|
| `BudgetService.java` | Service métier budget |
### **Resources**
| Fichier | Description |
|---------|-------------|
| `BudgetResource.java` | API REST budget |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "budgets")
public class Budget extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@OneToOne
@JoinColumn(name = "chantier_id", nullable = false)
private Chantier chantier;
@Column(name = "montant_prevu", precision = 12, scale = 2)
private BigDecimal montantPrevu;
@Column(name = "montant_depense", precision = 12, scale = 2)
private BigDecimal montantDepense = BigDecimal.ZERO;
@Column(name = "montant_restant", precision = 12, scale = 2)
private BigDecimal montantRestant;
@Column(name = "pourcentage_utilise", precision = 5, scale = 2)
private BigDecimal pourcentageUtilise = BigDecimal.ZERO;
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/budgets` | Liste budgets |
| GET | `/api/v1/budgets/{id}` | Détails |
| GET | `/api/v1/budgets/chantier/{id}` | Budget d'un chantier |
| POST | `/api/v1/budgets` | Créer |
| PUT | `/api/v1/budgets/{id}` | Modifier |
| POST | `/api/v1/budgets/{id}/depense` | Enregistrer dépense |
| GET | `/api/v1/budgets/{id}/ecarts` | Analyse écarts |
---
## 💻 Exemples
### **Créer un budget**
```bash
curl -X POST http://localhost:8080/api/v1/budgets \
-H "Content-Type: application/json" \
-d '{
"chantierId": "chantier-uuid",
"montantPrevu": 250000.00
}'
```
### **Enregistrer une dépense**
```bash
curl -X POST http://localhost:8080/api/v1/budgets/{id}/depense \
-H "Content-Type: application/json" \
-d '{
"montant": 5000.00,
"categorie": "MATERIAUX",
"description": "Achat ciment et sable"
}'
```
### **Analyse des écarts**
```bash
curl -X GET http://localhost:8080/api/v1/budgets/{id}/ecarts
```
**Réponse**:
```json
{
"montantPrevu": 250000.00,
"montantDepense": 180000.00,
"montantRestant": 70000.00,
"pourcentageUtilise": 72.00,
"ecart": -70000.00,
"statut": "DANS_BUDGET",
"alertes": []
}
```
---
## 🔧 Services métier
**BudgetService - Méthodes**:
- `create(BudgetDTO)` - Créer
- `enregistrerDepense(UUID id, BigDecimal montant)` - Dépense
- `calculerEcarts(UUID id)` - Calculer écarts
- `getStatutBudget(UUID id)` - Statut
---
## 📈 Relations
- **CHANTIER** ⬅️ Un budget est lié à un chantier (OneToOne)
- **DEVIS** ⬅️ Le budget initial vient du devis
- **FACTURE** ➡️ Les factures impactent le budget
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

252
docs/concepts/11-EMPLOYE.md Normal file
View File

@@ -0,0 +1,252 @@
# 👷 CONCEPT: EMPLOYE
## 📌 Vue d'ensemble
Le concept **EMPLOYE** gère les ressources humaines : employés, compétences, équipes, et affectations aux chantiers.
**Importance**: ⭐⭐⭐⭐ (Concept stratégique)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `Employe.java` | Entité principale employé |
| `EmployeCompetence.java` | Compétences d'un employé |
| `FonctionEmploye.java` | Enum fonctions |
| `StatutEmploye.java` | Enum (ACTIF, CONGE, ARRET_MALADIE, FORMATION, INACTIF) |
| `NiveauCompetence.java` | Enum niveaux de compétence |
| `Equipe.java` | Entité équipe |
| `StatutEquipe.java` | Enum (ACTIVE, INACTIVE, EN_MISSION, DISPONIBLE) |
### **Services**
| Fichier | Description |
|---------|-------------|
| `EmployeService.java` | Service métier employés |
| `EquipeService.java` | Service métier équipes |
### **Resources**
| Fichier | Description |
|---------|-------------|
| `EmployeResource.java` | API REST employés |
| `EquipeResource.java` | API REST équipes |
---
## 📊 Modèle de données
### **Entité Employe**
```java
@Entity
@Table(name = "employes")
public class Employe extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(name = "nom", nullable = false)
private String nom;
@Column(name = "prenom", nullable = false)
private String prenom;
@Column(name = "email", unique = true)
private String email;
@Column(name = "telephone")
private String telephone;
@Enumerated(EnumType.STRING)
@Column(name = "fonction")
private FonctionEmploye fonction;
@Enumerated(EnumType.STRING)
@Column(name = "statut")
private StatutEmploye statut = StatutEmploye.ACTIF;
@Column(name = "date_embauche")
private LocalDate dateEmbauche;
@Column(name = "taux_horaire", precision = 10, scale = 2)
private BigDecimal tauxHoraire;
@ManyToOne
@JoinColumn(name = "equipe_id")
private Equipe equipe;
@OneToMany(mappedBy = "employe", cascade = CascadeType.ALL)
private List<EmployeCompetence> competences;
}
```
### **Enum FonctionEmploye**
```java
public enum FonctionEmploye {
CHEF_CHANTIER,
CONDUCTEUR_TRAVAUX,
MACON,
ELECTRICIEN,
PLOMBIER,
CHARPENTIER,
COUVREUR,
PEINTRE,
CARRELEUR,
MENUISIER,
TERRASSIER,
GRUTIER,
MANOEUVRE,
AUTRE
}
```
### **Enum StatutEmploye**
```java
public enum StatutEmploye {
ACTIF, // Actif et disponible
CONGE, // En congé
ARRET_MALADIE, // Arrêt maladie
FORMATION, // En formation
INACTIF // Inactif (démission, licenciement)
}
```
---
## 🔌 API REST
### **Endpoints Employés**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/employes` | Liste employés |
| GET | `/api/v1/employes/{id}` | Détails |
| POST | `/api/v1/employes` | Créer |
| PUT | `/api/v1/employes/{id}` | Modifier |
| DELETE | `/api/v1/employes/{id}` | Supprimer |
| GET | `/api/v1/employes/disponibles` | Employés disponibles |
| GET | `/api/v1/employes/fonction/{fonction}` | Par fonction |
| GET | `/api/v1/employes/stats` | Statistiques |
### **Endpoints Équipes**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/equipes` | Liste équipes |
| GET | `/api/v1/equipes/{id}` | Détails |
| POST | `/api/v1/equipes` | Créer |
| PUT | `/api/v1/equipes/{id}` | Modifier |
| POST | `/api/v1/equipes/{id}/membres` | Ajouter membre |
| DELETE | `/api/v1/equipes/{id}/membres/{employeId}` | Retirer membre |
---
## 💻 Exemples
### **Créer un employé**
```bash
curl -X POST http://localhost:8080/api/v1/employes \
-H "Content-Type: application/json" \
-d '{
"nom": "Martin",
"prenom": "Pierre",
"email": "pierre.martin@btpxpress.fr",
"telephone": "+33 6 12 34 56 78",
"fonction": "MACON",
"dateEmbauche": "2025-01-15",
"tauxHoraire": 25.00,
"competences": [
{
"nom": "Maçonnerie traditionnelle",
"niveau": "EXPERT"
},
{
"nom": "Coffrage",
"niveau": "CONFIRME"
}
]
}'
```
### **Créer une équipe**
```bash
curl -X POST http://localhost:8080/api/v1/equipes \
-H "Content-Type: application/json" \
-d '{
"nom": "Équipe Gros Œuvre A",
"chefEquipeId": "employe-uuid",
"membreIds": ["uuid1", "uuid2", "uuid3"]
}'
```
### **Employés disponibles**
```bash
curl -X GET http://localhost:8080/api/v1/employes/disponibles
```
**Réponse**:
```json
[
{
"id": "uuid",
"nom": "Martin",
"prenom": "Pierre",
"fonction": "MACON",
"statut": "ACTIF",
"equipe": "Équipe Gros Œuvre A",
"competences": ["Maçonnerie", "Coffrage"]
}
]
```
---
## 🔧 Services métier
### **EmployeService**
**Méthodes principales**:
- `findAll()` - Tous les employés
- `findDisponibles()` - Employés disponibles
- `findByFonction(FonctionEmploye)` - Par fonction
- `create(EmployeDTO)` - Créer
- `update(UUID id, EmployeDTO)` - Modifier
- `changerStatut(UUID id, StatutEmploye)` - Changer statut
### **EquipeService**
**Méthodes principales**:
- `create(EquipeDTO)` - Créer équipe
- `ajouterMembre(UUID equipeId, UUID employeId)` - Ajouter membre
- `retirerMembre(UUID equipeId, UUID employeId)` - Retirer membre
---
## 📈 Relations
- **EQUIPE** ⬅️ Un employé appartient à une équipe
- **CHANTIER** ➡️ Un employé peut être affecté à des chantiers
- **USER** ⬅️ Un employé peut avoir un compte utilisateur
---
## ✅ Validations
- ✅ Nom et prénom obligatoires
- ✅ Email unique
- ✅ Fonction obligatoire
- ✅ Taux horaire positif
- ✅ Date d'embauche cohérente
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

View File

@@ -0,0 +1,222 @@
# 🔧 CONCEPT: MAINTENANCE
## 📌 Vue d'ensemble
Le concept **MAINTENANCE** gère la maintenance préventive et corrective du matériel BTP avec planification et historique.
**Importance**: ⭐⭐⭐ (Concept important)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `MaintenanceMateriel.java` | Entité principale maintenance |
| `StatutMaintenance.java` | Enum (PLANIFIEE, EN_COURS, TERMINEE, ANNULEE, REPORTEE) |
| `TypeMaintenance.java` | Enum (PREVENTIVE, CORRECTIVE, CURATIVE, PREDICTIVE) |
### **Services**
| Fichier | Description |
|---------|-------------|
| `MaintenanceService.java` | Service métier maintenance |
### **Resources**
| Fichier | Description |
|---------|-------------|
| `MaintenanceResource.java` | API REST maintenance |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "maintenances_materiel")
public class MaintenanceMateriel extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne
@JoinColumn(name = "materiel_id", nullable = false)
private Materiel materiel;
@Enumerated(EnumType.STRING)
@Column(name = "type", nullable = false)
private TypeMaintenance type;
@Enumerated(EnumType.STRING)
@Column(name = "statut", nullable = false)
private StatutMaintenance statut = StatutMaintenance.PLANIFIEE;
@Column(name = "date_prevue", nullable = false)
private LocalDate datePrevue;
@Column(name = "date_realisee")
private LocalDate dateRealisee;
@Column(name = "description", length = 1000)
private String description;
@Column(name = "cout", precision = 10, scale = 2)
private BigDecimal cout;
@Column(name = "technicien", length = 100)
private String technicien;
@Column(name = "observations", length = 2000)
private String observations;
}
```
### **Enum TypeMaintenance**
```java
public enum TypeMaintenance {
PREVENTIVE, // Maintenance préventive planifiée
CORRECTIVE, // Correction d'un dysfonctionnement
CURATIVE, // Réparation d'une panne
PREDICTIVE // Maintenance prédictive (IoT, capteurs)
}
```
### **Enum StatutMaintenance**
```java
public enum StatutMaintenance {
PLANIFIEE, // Planifiée
EN_COURS, // En cours de réalisation
TERMINEE, // Terminée avec succès
ANNULEE, // Annulée
REPORTEE // Reportée à une date ultérieure
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/maintenances` | Liste maintenances |
| GET | `/api/v1/maintenances/{id}` | Détails |
| POST | `/api/v1/maintenances` | Créer |
| PUT | `/api/v1/maintenances/{id}` | Modifier |
| PUT | `/api/v1/maintenances/{id}/terminer` | Terminer |
| GET | `/api/v1/maintenances/materiel/{id}` | Maintenances d'un matériel |
| GET | `/api/v1/maintenances/planifiees` | Maintenances planifiées |
| GET | `/api/v1/maintenances/stats` | Statistiques |
---
## 💻 Exemples
### **Créer une maintenance préventive**
```bash
curl -X POST http://localhost:8080/api/v1/maintenances \
-H "Content-Type: application/json" \
-d '{
"materielId": "materiel-uuid",
"type": "PREVENTIVE",
"datePrevue": "2025-11-01",
"description": "Révision annuelle - Vidange et contrôle général",
"technicien": "Service Maintenance"
}'
```
### **Terminer une maintenance**
```bash
curl -X PUT http://localhost:8080/api/v1/maintenances/{id}/terminer \
-H "Content-Type: application/json" \
-d '{
"dateRealisee": "2025-11-01",
"cout": 250.00,
"observations": "Révision effectuée. Remplacement filtre à huile. Matériel en bon état."
}'
```
### **Historique maintenance d'un matériel**
```bash
curl -X GET http://localhost:8080/api/v1/maintenances/materiel/{materielId}
```
**Réponse**:
```json
[
{
"id": "uuid",
"type": "PREVENTIVE",
"statut": "TERMINEE",
"datePrevue": "2025-11-01",
"dateRealisee": "2025-11-01",
"description": "Révision annuelle",
"cout": 250.00,
"technicien": "Service Maintenance"
},
{
"id": "uuid2",
"type": "CORRECTIVE",
"statut": "TERMINEE",
"datePrevue": "2025-08-15",
"dateRealisee": "2025-08-16",
"description": "Réparation système hydraulique",
"cout": 450.00
}
]
```
### **Maintenances planifiées**
```bash
curl -X GET http://localhost:8080/api/v1/maintenances/planifiees
```
---
## 🔧 Services métier
**MaintenanceService - Méthodes**:
- `create(MaintenanceDTO)` - Créer maintenance
- `terminer(UUID id, MaintenanceTermineeDTO)` - Terminer
- `reporter(UUID id, LocalDate nouvelleDate)` - Reporter
- `findByMateriel(UUID materielId)` - Historique matériel
- `findPlanifiees()` - Maintenances planifiées
- `findEnRetard()` - Maintenances en retard
- `planifierPreventive(UUID materielId)` - Planifier préventive
---
## 📈 Relations
- **MATERIEL** ⬅️ Une maintenance concerne un matériel
- **EMPLOYE** ⬅️ Un technicien (employé) peut réaliser la maintenance
---
## ✅ Validations
- ✅ Matériel obligatoire
- ✅ Type obligatoire
- ✅ Date prévue obligatoire
- ✅ Coût positif
- ✅ Date réalisée >= date prévue
---
## 📚 Références
- [Concept MATERIEL](./03-MATERIEL.md)
- [Concept EMPLOYE](./11-EMPLOYE.md)
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

View File

@@ -0,0 +1,151 @@
# 📅 CONCEPT: PLANNING
## 📌 Vue d'ensemble
Le concept **PLANNING** gère le planning général avec événements, rendez-vous, affectations de ressources et calendrier.
**Importance**: ⭐⭐⭐⭐ (Concept stratégique)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `PlanningEvent.java` | Événement de planning |
| `StatutPlanningEvent.java` | Enum statuts |
| `TypePlanningEvent.java` | Enum types |
| `PrioritePlanningEvent.java` | Enum priorités |
| `RappelPlanningEvent.java` | Rappels |
| `TypeRappel.java` | Enum types rappel |
| `VuePlanning.java` | Enum vues (JOUR, SEMAINE, MOIS, ANNEE) |
### **Services**
| Fichier | Description |
|---------|-------------|
| `PlanningService.java` | Service métier planning |
### **Resources**
| Fichier | Description |
|---------|-------------|
| `PlanningResource.java` | API REST planning |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "planning_events")
public class PlanningEvent extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(name = "titre", nullable = false)
private String titre;
@Column(name = "description", length = 2000)
private String description;
@Column(name = "date_debut", nullable = false)
private LocalDateTime dateDebut;
@Column(name = "date_fin", nullable = false)
private LocalDateTime dateFin;
@Enumerated(EnumType.STRING)
@Column(name = "type")
private TypePlanningEvent type;
@Enumerated(EnumType.STRING)
@Column(name = "statut")
private StatutPlanningEvent statut;
@Enumerated(EnumType.STRING)
@Column(name = "priorite")
private PrioritePlanningEvent priorite;
@ManyToOne
@JoinColumn(name = "chantier_id")
private Chantier chantier;
@ManyToMany
@JoinTable(name = "planning_event_employes")
private List<Employe> employes;
@ManyToMany
@JoinTable(name = "planning_event_materiels")
private List<Materiel> materiels;
@Column(name = "lieu", length = 500)
private String lieu;
@Column(name = "tout_la_journee")
private Boolean toutLaJournee = false;
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/planning` | Liste événements |
| GET | `/api/v1/planning/{id}` | Détails |
| POST | `/api/v1/planning` | Créer |
| PUT | `/api/v1/planning/{id}` | Modifier |
| DELETE | `/api/v1/planning/{id}` | Supprimer |
| GET | `/api/v1/planning/periode` | Par période |
| GET | `/api/v1/planning/chantier/{id}` | Par chantier |
| GET | `/api/v1/planning/employe/{id}` | Par employé |
---
## 💻 Exemples
### **Créer un événement**
```bash
curl -X POST http://localhost:8080/api/v1/planning \
-H "Content-Type: application/json" \
-d '{
"titre": "Coulage dalle béton",
"description": "Coulage de la dalle du RDC",
"dateDebut": "2025-10-15T08:00:00",
"dateFin": "2025-10-15T17:00:00",
"type": "CHANTIER",
"priorite": "HAUTE",
"chantierId": "chantier-uuid",
"employeIds": ["emp1-uuid", "emp2-uuid"],
"materielIds": ["mat1-uuid"],
"lieu": "Chantier Villa Moderne"
}'
```
### **Événements par période**
```bash
curl -X GET "http://localhost:8080/api/v1/planning/periode?debut=2025-10-01&fin=2025-10-31"
```
---
## 🔧 Services métier
**PlanningService - Méthodes**:
- `create(PlanningEventDTO)` - Créer
- `findByPeriode(LocalDate debut, LocalDate fin)` - Par période
- `findByChantier(UUID chantierId)` - Par chantier
- `findByEmploye(UUID employeId)` - Par employé
- `detecterConflits(PlanningEventDTO)` - Détecter conflits
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

View File

@@ -0,0 +1,128 @@
# 📄 CONCEPT: DOCUMENT
## 📌 Vue d'ensemble
Le concept **DOCUMENT** gère la GED (Gestion Électronique des Documents) : plans, photos, rapports, contrats, etc.
**Importance**: ⭐⭐⭐ (Concept important)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `Document.java` | Entité principale document |
| `TypeDocument.java` | Enum types (PLAN, PERMIS, RAPPORT, PHOTO, CONTRAT, etc.) |
### **Services**
| Fichier | Description |
|---------|-------------|
| `DocumentService.java` | Service métier documents |
### **Resources**
| Fichier | Description |
|---------|-------------|
| `DocumentResource.java` | API REST documents |
| `PhotoResource.java` | API REST photos |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "documents")
public class Document extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(name = "nom", nullable = false)
private String nom;
@Enumerated(EnumType.STRING)
@Column(name = "type")
private TypeDocument type;
@Column(name = "chemin_fichier", nullable = false)
private String cheminFichier;
@Column(name = "taille_octets")
private Long tailleOctets;
@Column(name = "mime_type")
private String mimeType;
@ManyToOne
@JoinColumn(name = "chantier_id")
private Chantier chantier;
@Column(name = "description", length = 1000)
private String description;
@Column(name = "date_upload")
private LocalDateTime dateUpload;
}
```
### **Enum TypeDocument**
```java
public enum TypeDocument {
PLAN, // Plans architecturaux
PERMIS_CONSTRUIRE, // Permis de construire
RAPPORT_CHANTIER, // Rapports de chantier
PHOTO_CHANTIER, // Photos de chantier
CONTRAT, // Contrats
DEVIS, // Devis
FACTURE, // Factures
CERTIFICAT, // Certificats
AUTRE
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/documents` | Liste documents |
| GET | `/api/v1/documents/{id}` | Détails |
| POST | `/api/v1/documents/upload` | Upload document |
| GET | `/api/v1/documents/{id}/download` | Télécharger |
| DELETE | `/api/v1/documents/{id}` | Supprimer |
| GET | `/api/v1/documents/chantier/{id}` | Par chantier |
| GET | `/api/v1/documents/type/{type}` | Par type |
---
## 💻 Exemples
### **Upload document**
```bash
curl -X POST http://localhost:8080/api/v1/documents/upload \
-F "file=@plan.pdf" \
-F "nom=Plan RDC" \
-F "type=PLAN" \
-F "chantierId=chantier-uuid" \
-F "description=Plan du rez-de-chaussée"
```
### **Télécharger document**
```bash
curl -X GET http://localhost:8080/api/v1/documents/{id}/download \
--output document.pdf
```
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

114
docs/concepts/15-MESSAGE.md Normal file
View File

@@ -0,0 +1,114 @@
# 💬 CONCEPT: MESSAGE
## 📌 Vue d'ensemble
Le concept **MESSAGE** gère la messagerie interne entre utilisateurs avec catégorisation et priorités.
**Importance**: ⭐⭐ (Concept utile)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `Message.java` | Entité principale message |
| `TypeMessage.java` | Enum types (NORMAL, CHANTIER, MAINTENANCE, URGENT, etc.) |
| `PrioriteMessage.java` | Enum priorités |
### **Services**
| Fichier | Description |
|---------|-------------|
| `MessageService.java` | Service métier messages |
### **Resources**
| Fichier | Description |
|---------|-------------|
| `MessageResource.java` | API REST messages |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "messages")
public class Message extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne
@JoinColumn(name = "expediteur_id", nullable = false)
private User expediteur;
@ManyToOne
@JoinColumn(name = "destinataire_id", nullable = false)
private User destinataire;
@Column(name = "sujet", nullable = false)
private String sujet;
@Column(name = "contenu", length = 5000, nullable = false)
private String contenu;
@Enumerated(EnumType.STRING)
@Column(name = "type")
private TypeMessage type;
@Enumerated(EnumType.STRING)
@Column(name = "priorite")
private PrioriteMessage priorite;
@Column(name = "lu")
private Boolean lu = false;
@Column(name = "date_envoi")
private LocalDateTime dateEnvoi;
@Column(name = "date_lecture")
private LocalDateTime dateLecture;
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/messages` | Liste messages |
| GET | `/api/v1/messages/{id}` | Détails |
| POST | `/api/v1/messages` | Envoyer |
| PUT | `/api/v1/messages/{id}/lire` | Marquer comme lu |
| DELETE | `/api/v1/messages/{id}` | Supprimer |
| GET | `/api/v1/messages/recus` | Messages reçus |
| GET | `/api/v1/messages/envoyes` | Messages envoyés |
| GET | `/api/v1/messages/non-lus` | Messages non lus |
---
## 💻 Exemples
### **Envoyer un message**
```bash
curl -X POST http://localhost:8080/api/v1/messages \
-H "Content-Type: application/json" \
-d '{
"destinataireId": "user-uuid",
"sujet": "Livraison matériel",
"contenu": "La livraison de ciment est prévue demain à 9h",
"type": "CHANTIER",
"priorite": "NORMALE"
}'
```
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

View File

@@ -0,0 +1,109 @@
# 🔔 CONCEPT: NOTIFICATION
## 📌 Vue d'ensemble
Le concept **NOTIFICATION** gère les notifications système pour alerter les utilisateurs d'événements importants.
**Importance**: ⭐⭐ (Concept utile)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `Notification.java` | Entité principale notification |
| `TypeNotification.java` | Enum types |
| `PrioriteNotification.java` | Enum priorités |
### **Services**
| Fichier | Description |
|---------|-------------|
| `NotificationService.java` | Service métier notifications |
### **Resources**
| Fichier | Description |
|---------|-------------|
| `NotificationResource.java` | API REST notifications |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "notifications")
public class Notification extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
@Column(name = "titre", nullable = false)
private String titre;
@Column(name = "message", length = 1000)
private String message;
@Enumerated(EnumType.STRING)
@Column(name = "type")
private TypeNotification type;
@Column(name = "lue")
private Boolean lue = false;
@Column(name = "date_creation")
private LocalDateTime dateCreation;
@Column(name = "date_lecture")
private LocalDateTime dateLecture;
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/notifications` | Liste notifications |
| GET | `/api/v1/notifications/non-lues` | Non lues |
| PUT | `/api/v1/notifications/{id}/lire` | Marquer comme lue |
| PUT | `/api/v1/notifications/tout-lire` | Tout marquer comme lu |
| DELETE | `/api/v1/notifications/{id}` | Supprimer |
---
## 💻 Exemples
### **Notifications non lues**
```bash
curl -X GET http://localhost:8080/api/v1/notifications/non-lues
```
**Réponse**:
```json
[
{
"id": "uuid",
"titre": "Stock faible",
"message": "Le stock de ciment est en dessous du seuil minimum",
"type": "ALERTE",
"lue": false,
"dateCreation": "2025-09-30T10:00:00"
}
]
```
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

144
docs/concepts/17-USER.md Normal file
View File

@@ -0,0 +1,144 @@
# 👤 CONCEPT: USER
## 📌 Vue d'ensemble
Le concept **USER** gère les utilisateurs, authentification, rôles et permissions via Keycloak.
**Importance**: ⭐⭐⭐⭐⭐ (Concept fondamental)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `User.java` | Entité principale utilisateur |
| `UserRole.java` | Enum (ADMIN, MANAGER, CHEF_CHANTIER, COMPTABLE, OUVRIER) |
| `UserStatus.java` | Enum (ACTIVE, INACTIVE, LOCKED, SUSPENDED) |
| `Permission.java` | Enum permissions |
### **Services**
| Fichier | Description |
|---------|-------------|
| `UserService.java` | Service métier utilisateurs |
| `PermissionService.java` | Service permissions |
### **Resources**
| Fichier | Description |
|---------|-------------|
| `UserResource.java` | API REST utilisateurs |
| `AuthResource.java` | API authentification |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "users")
public class User extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(name = "keycloak_id", unique = true)
private String keycloakId;
@Column(name = "username", unique = true, nullable = false)
private String username;
@Column(name = "email", unique = true, nullable = false)
private String email;
@Column(name = "nom")
private String nom;
@Column(name = "prenom")
private String prenom;
@Enumerated(EnumType.STRING)
@Column(name = "role")
private UserRole role;
@Enumerated(EnumType.STRING)
@Column(name = "status")
private UserStatus status = UserStatus.ACTIVE;
@OneToOne
@JoinColumn(name = "employe_id")
private Employe employe;
}
```
### **Enum UserRole**
```java
public enum UserRole {
ADMIN, // Administrateur système
MANAGER, // Manager/Directeur
CHEF_CHANTIER, // Chef de chantier
COMPTABLE, // Comptable
OUVRIER // Ouvrier
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/users` | Liste utilisateurs |
| GET | `/api/v1/users/{id}` | Détails |
| POST | `/api/v1/users` | Créer |
| PUT | `/api/v1/users/{id}` | Modifier |
| DELETE | `/api/v1/users/{id}` | Supprimer |
| GET | `/api/v1/users/me` | Utilisateur connecté |
| POST | `/api/v1/auth/login` | Connexion |
| POST | `/api/v1/auth/logout` | Déconnexion |
---
## 💻 Exemples
### **Créer un utilisateur**
```bash
curl -X POST http://localhost:8080/api/v1/users \
-H "Content-Type: application/json" \
-d '{
"username": "jdupont",
"email": "jean.dupont@btpxpress.fr",
"nom": "Dupont",
"prenom": "Jean",
"role": "CHEF_CHANTIER",
"password": "SecurePass123!"
}'
```
### **Utilisateur connecté**
```bash
curl -X GET http://localhost:8080/api/v1/users/me \
-H "Authorization: Bearer $TOKEN"
```
---
## 🔐 Authentification
L'authentification se fait via **Keycloak** avec OAuth2/OIDC :
1. L'utilisateur se connecte via Keycloak
2. Keycloak retourne un JWT token
3. Le token est envoyé dans le header `Authorization: Bearer <token>`
4. Le backend valide le token auprès de Keycloak
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

View File

@@ -0,0 +1,53 @@
# 🏢 CONCEPT: ENTREPRISE
## 📌 Vue d'ensemble
Le concept **ENTREPRISE** gère les profils d'entreprises BTP et leurs avis/évaluations.
**Importance**: ⭐⭐ (Concept secondaire)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `EntrepriseProfile.java` | Profil entreprise |
| `AvisEntreprise.java` | Avis sur entreprise |
| `StatutAvis.java` | Enum (EN_ATTENTE, PUBLIE, REJETE, SIGNALE, ARCHIVE) |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "entreprises_profiles")
public class EntrepriseProfile extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(name = "nom", nullable = false)
private String nom;
@Column(name = "siret")
private String siret;
@Column(name = "description", length = 2000)
private String description;
@Column(name = "note_moyenne", precision = 3, scale = 2)
private BigDecimal noteMoyenne;
@OneToMany(mappedBy = "entreprise")
private List<AvisEntreprise> avis;
}
```
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

View File

@@ -0,0 +1,65 @@
# 📆 CONCEPT: DISPONIBILITE
## 📌 Vue d'ensemble
Le concept **DISPONIBILITE** gère les disponibilités des employés et du matériel pour la planification.
**Importance**: ⭐⭐ (Concept secondaire)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `DisponibiliteEmploye.java` | Disponibilité employé |
| `DisponibiliteMateriel.java` | Disponibilité matériel |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "disponibilites_employe")
public class DisponibiliteEmploye extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@ManyToOne
@JoinColumn(name = "employe_id", nullable = false)
private Employe employe;
@Column(name = "date_debut", nullable = false)
private LocalDate dateDebut;
@Column(name = "date_fin", nullable = false)
private LocalDate dateFin;
@Column(name = "disponible", nullable = false)
private Boolean disponible = true;
@Column(name = "motif", length = 500)
private String motif;
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/disponibilites/employe/{id}` | Disponibilités employé |
| POST | `/api/v1/disponibilites/employe` | Créer disponibilité |
| GET | `/api/v1/disponibilites/materiel/{id}` | Disponibilités matériel |
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

View File

@@ -0,0 +1,78 @@
# 🌡️ CONCEPT: ZONE_CLIMATIQUE
## 📌 Vue d'ensemble
Le concept **ZONE_CLIMATIQUE** gère les zones climatiques pour adapter les matériaux et techniques de construction.
**Importance**: ⭐ (Concept spécialisé)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `ZoneClimatique.java` | Zone climatique |
| `TypeZoneClimatique.java` | Enum types |
| `NiveauHumidite.java` | Enum niveaux humidité |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "zones_climatiques")
public class ZoneClimatique extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(name = "nom", nullable = false)
private String nom;
@Enumerated(EnumType.STRING)
@Column(name = "type")
private TypeZoneClimatique type;
@Column(name = "temperature_min")
private BigDecimal temperatureMin;
@Column(name = "temperature_max")
private BigDecimal temperatureMax;
@Enumerated(EnumType.STRING)
@Column(name = "niveau_humidite")
private NiveauHumidite niveauHumidite;
}
```
### **Enum TypeZoneClimatique**
```java
public enum TypeZoneClimatique {
OCEANIQUE,
CONTINENTAL,
MEDITERRANEEN,
MONTAGNARD,
TROPICAL
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/zones-climatiques` | Liste zones |
| GET | `/api/v1/zones-climatiques/{id}` | Détails |
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

View File

@@ -0,0 +1,80 @@
# 💳 CONCEPT: ABONNEMENT
## 📌 Vue d'ensemble
Le concept **ABONNEMENT** gère les abonnements et plans tarifaires pour les entreprises utilisant BTPXpress.
**Importance**: ⭐⭐ (Concept commercial)
---
## 🗂️ Fichiers concernés
### **Entités JPA**
| Fichier | Description |
|---------|-------------|
| `Abonnement.java` | Entité abonnement |
---
## 📊 Modèle de données
```java
@Entity
@Table(name = "abonnements")
public class Abonnement extends PanacheEntityBase {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@Column(name = "nom_plan", nullable = false)
private String nomPlan;
@Column(name = "prix_mensuel", precision = 10, scale = 2)
private BigDecimal prixMensuel;
@Column(name = "date_debut", nullable = false)
private LocalDate dateDebut;
@Column(name = "date_fin")
private LocalDate dateFin;
@Column(name = "actif")
private Boolean actif = true;
@Column(name = "nombre_utilisateurs_max")
private Integer nombreUtilisateursMax;
@Column(name = "nombre_chantiers_max")
private Integer nombreChantiersMax;
}
```
---
## 🔌 API REST
### **Endpoints**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/abonnements` | Liste abonnements |
| GET | `/api/v1/abonnements/{id}` | Détails |
| POST | `/api/v1/abonnements` | Créer |
| PUT | `/api/v1/abonnements/{id}` | Modifier |
---
## 💻 Plans disponibles
| Plan | Prix/mois | Utilisateurs | Chantiers |
|------|-----------|--------------|-----------|
| STARTER | 49€ | 3 | 5 |
| BUSINESS | 99€ | 10 | 20 |
| ENTERPRISE | 199€ | Illimité | Illimité |
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0

View File

@@ -0,0 +1,237 @@
# ⚙️ CONCEPT: SERVICES_TRANSVERSES
## 📌 Vue d'ensemble
Le concept **SERVICES_TRANSVERSES** regroupe les services utilitaires et techniques utilisés par l'ensemble de l'application.
**Importance**: ⭐⭐⭐ (Concept technique)
---
## 🗂️ Fichiers concernés
### **Services** (`application/service/`)
| Fichier | Description |
|---------|-------------|
| `EmailService.java` | Service d'envoi d'emails |
| `PdfGeneratorService.java` | Génération de PDF |
| `ExportService.java` | Export de données (Excel, CSV) |
| `ImportService.java` | Import de données |
---
## 📊 Services disponibles
### **1. EmailService**
Service d'envoi d'emails transactionnels et notifications.
**Méthodes principales**:
```java
public class EmailService {
void sendEmail(String to, String subject, String body);
void sendEmailWithAttachment(String to, String subject, String body, File attachment);
void sendTemplateEmail(String to, String templateName, Map<String, Object> variables);
}
```
**Exemples d'utilisation**:
- Envoi de devis par email
- Notifications de livraison
- Alertes de stock faible
- Rappels de maintenance
---
### **2. PdfGeneratorService**
Service de génération de documents PDF.
**Méthodes principales**:
```java
public class PdfGeneratorService {
byte[] genererDevisPdf(UUID devisId);
byte[] genererFacturePdf(UUID factureId);
byte[] genererBonCommandePdf(UUID bonCommandeId);
byte[] genererRapportChantierPdf(UUID chantierId);
}
```
**Technologies utilisées**:
- iText ou Apache PDFBox
- Templates HTML/CSS convertis en PDF
- Génération de graphiques et tableaux
---
### **3. ExportService**
Service d'export de données vers différents formats.
**Méthodes principales**:
```java
public class ExportService {
byte[] exportToExcel(List<?> data, String sheetName);
byte[] exportToCsv(List<?> data);
byte[] exportToJson(List<?> data);
}
```
**Cas d'usage**:
- Export liste de chantiers
- Export inventaire matériel
- Export historique factures
- Export planning mensuel
---
### **4. ImportService**
Service d'import de données depuis fichiers externes.
**Méthodes principales**:
```java
public class ImportService {
ImportResult importFromExcel(MultipartFile file, String entityType);
ImportResult importFromCsv(MultipartFile file, String entityType);
ValidationResult validateImportData(List<?> data);
}
```
**Fonctionnalités**:
- Import en masse de matériel
- Import de clients
- Import de fournisseurs
- Validation des données avant import
---
## 🔌 API REST
### **Endpoints Export**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| GET | `/api/v1/export/chantiers/excel` | Export chantiers Excel |
| GET | `/api/v1/export/materiels/csv` | Export matériel CSV |
| GET | `/api/v1/export/factures/pdf` | Export factures PDF |
### **Endpoints Import**
| Méthode | Endpoint | Description |
|---------|----------|-------------|
| POST | `/api/v1/import/materiels` | Import matériel |
| POST | `/api/v1/import/clients` | Import clients |
| POST | `/api/v1/import/validate` | Valider données |
---
## 💻 Exemples
### **Export Excel**
```bash
curl -X GET http://localhost:8080/api/v1/export/chantiers/excel \
-H "Accept: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" \
--output chantiers.xlsx
```
### **Import matériel**
```bash
curl -X POST http://localhost:8080/api/v1/import/materiels \
-F "file=@materiels.xlsx" \
-F "validateOnly=false"
```
**Réponse**:
```json
{
"success": true,
"totalRows": 150,
"imported": 145,
"errors": 5,
"errorDetails": [
{
"row": 12,
"error": "Référence déjà existante"
},
{
"row": 45,
"error": "Type de matériel invalide"
}
]
}
```
---
## 🔧 Configuration
### **Email (application.properties)**
```properties
# Configuration SMTP
quarkus.mailer.host=smtp.gmail.com
quarkus.mailer.port=587
quarkus.mailer.username=noreply@btpxpress.fr
quarkus.mailer.password=${SMTP_PASSWORD}
quarkus.mailer.from=noreply@btpxpress.fr
quarkus.mailer.tls=true
```
### **PDF Generator**
```properties
# Configuration PDF
pdf.generator.font.path=/fonts/
pdf.generator.logo.path=/images/logo.png
pdf.generator.template.path=/templates/pdf/
```
---
## 📈 Utilisation
Ces services sont utilisés par de nombreux concepts :
- **DEVIS** ➡️ PdfGeneratorService, EmailService
- **FACTURE** ➡️ PdfGeneratorService, EmailService
- **BON_COMMANDE** ➡️ PdfGeneratorService, EmailService
- **MATERIEL** ➡️ ExportService, ImportService
- **CHANTIER** ➡️ ExportService, PdfGeneratorService
- **NOTIFICATION** ➡️ EmailService
---
## ✅ Bonnes pratiques
### **Gestion des erreurs**
- Validation des données avant traitement
- Logs détaillés des erreurs
- Retry automatique pour les emails
### **Performance**
- Génération asynchrone des PDF volumineux
- Cache des templates
- Compression des exports
### **Sécurité**
- Validation des fichiers uploadés
- Limitation de la taille des fichiers
- Scan antivirus des uploads
---
## 📚 Références
- [Configuration Quarkus Mailer](https://quarkus.io/guides/mailer)
- [iText PDF Library](https://itextpdf.com/)
- [Apache POI (Excel)](https://poi.apache.org/)
---
**Dernière mise à jour**: 2025-09-30
**Version**: 1.0
**Auteur**: Documentation BTPXpress