7 Commits

Author SHA1 Message Date
2b9d00678d Actualiser README.md 2026-04-23 17:24:40 +02:00
586cf6dc73 MAJ README.md 2026-04-23 17:15:19 +02:00
a3380ffdf5 Add README.md 2026-04-23 16:32:26 +02:00
1dcb3c35f2 MAJ update movement 2026-04-21 10:27:00 +02:00
oistig
2af5c1e015 fix 2026-04-20 15:07:30 +02:00
260fe71d4f MAJ ajout produit 2026-04-13 15:09:28 +02:00
94df917149 MAJ ajout de la méthode refresh 2025-12-11 14:54:37 +01:00
14 changed files with 704 additions and 76 deletions

View File

@@ -1,19 +1,23 @@
// Définition de l'espace de noms pour les DTO utilisés dans les requêtes liées aux mouvements
namespace API.DTO.Movement.Request
using PyroFetes.Models;
// Assure-toi d'importer tes enums
namespace PyroFetes.DTO.Movement.Request
{
// DTO utilisé pour créer un nouveau mouvement
public class CreateMovementDto
{
// Date à laquelle le mouvement est enregistré
public DateTime Date { get; set; }
public int ProductId { get; set; }
// Date et heure de début du mouvement
public MovementType Type { get; set; }
public int Quantity { get; set; }
public DateTime Date { get; set; } = DateTime.Now;
public DateTime Start { get; set; }
// Date et heure d'arrivée prévue du mouvement
public DateTime Arrival { get; set; }
// Quantité de matériaux ou objets impliqués dans le mouvement
public int Quantity { get; set; }
public int? SourceWarehouseId { get; set; }
public int? DestinationWarehouseId { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace PyroFetes.DTO.Refrresh.Request;
public class RefreshTokenDto
{
public string? Token { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace PyroFetes.DTO.Refrresh.Response;
public class GetRefreshDto
{
public string? Token { get; set; }
}

View File

@@ -1,6 +1,7 @@
using API.DTO.Movement.Request;
using API.DTO.Movement.Response;
using FastEndpoints;
using PyroFetes.DTO.Movement.Request;
namespace PyroFetes.Endpoints.Movement;
@@ -17,9 +18,11 @@ public class CreateMovementEndpoint(PyroFetesDbContext pyrofetesdbcontext) : End
Models.Movement movement = new ()
{
Date = req.Date,
ProductId = req.ProductId,
Start = req.Start,
Arrival = req.Arrival,
Quantity = req.Quantity
Quantity = req.Quantity,
Type = req.Type,
};
pyrofetesdbcontext.Movements.Add(movement);

View File

@@ -28,7 +28,7 @@ public class CreateProductEndpoint(PyroFetesDbContext db)
Image = req.Image!,
Link = req.Link!,
ProductCategoryId = req.ProductCategoryId,
ClassificationId = req.ClassificationId
ClassificationId = req.ClassificationId,
};
db.Products.Add(product);

View File

@@ -0,0 +1,74 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using FastEndpoints;
using FastEndpoints.Security;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using PyroFetes.DTO.Refrresh.Response;
namespace PyroFetes.Endpoints.Refresh;
public class RefreshTokenEndpoint(PyroFetesDbContext database) : EndpointWithoutRequest<GetRefreshDto>
{
public override void Configure()
{
Post("/refresh");
// [Authorize] est géré ici avec les rôles
Roles("Admin", "User");
}
public override async Task HandleAsync(CancellationToken ct)
{
try
{
// 1. 🚨 CORRECTION : Lire le claim 'Name' du jeton validé par le middleware
// Le claim 'Name' contient le nom d'utilisateur
string? userName = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value;
if (string.IsNullOrWhiteSpace(userName))
{
// Si le claim Name est manquant (ce qui ne devrait pas arriver)
await Send.UnauthorizedAsync(ct);
return;
}
// 2. 🚨 CORRECTION : Utiliser le Nom (Name) pour la recherche BDD
// Assurez-vous que la propriété de l'entité est 'Name' et qu'elle est unique
var login = await database.Users.FirstOrDefaultAsync(x => x.Name == userName, ct);
if (login == null)
{
await Send.UnauthorizedAsync(ct);
return;
}
// 3. Création du NOUVEAU jeton
string jwtToken = JwtBearer.CreateToken(
o =>
{
o.SigningKey = "ThisIsASuperSecretJwtKeyThatIsAtLeast32CharsLong";
o.ExpireAt = DateTime.UtcNow.AddMinutes(15);
// Assurez-vous que les claims sont corrects pour Angular
if (login.Fonction != null) o.User.Roles.Add(login.Fonction);
// Ajouter le claim Name (Nom d'utilisateur)
o.User.Claims.Add((ClaimTypes.Name, login.Name)!);
// Si votre API mettait d'autres claims, ajoutez-les ici (ex: "Username")
// o.User.Claims.Add(("Username", login.Name)!);
});
// 4. Envoi de la réponse
GetRefreshDto responseDto = new()
{
Token = jwtToken
};
await Send.OkAsync(responseDto, ct);
}
catch (Exception)
{
await Send.UnauthorizedAsync(ct);
}
}
}

View File

@@ -2,18 +2,42 @@
namespace PyroFetes.Models;
// 1. Définition des types possibles pour la logique métier
public enum MovementType
{
Entry, // Entrée (ex: Achat fournisseur)
Exit, // Sortie (ex: Vente, Casse)
Transfer, // Transfert entre deux entrepôts
Inventory // Ajustement manuel
}
public class Movement
{
[Key] public int Id { get; set; }
[Required] public DateTime Date { get; set; }
[Required] public DateTime Start {get; set;}
[Required] public DateTime Arrival {get; set;}
[Required] public int Quantity {get; set;}
[Key]
public int Id { get; set; }
public List<Product>? Products { get; set; }
[Required]
public DateTime Date { get; set; } = DateTime.Now;
public DateTime Start { get; set; }
public DateTime Arrival { get; set; }
[Required]
public int Quantity { get; set; }
[Required]
public MovementType Type { get; set; }
[Required]
public int ProductId { get; set; }
public Product? Product { get; set; }
public int? SourceWarehouseId { get; set; }
public Warehouse? SourceWarehouse { get; set; }
public int? DestinationWarehouseId { get; set; }
public Warehouse? DestinationWarehouse { get; set; }
[MaxLength(500)]
public string? Comment { get; set; }
}

View File

@@ -12,9 +12,9 @@ namespace PyroFetes.Models
[Required, MaxLength(100)] public string? ApprovalNumber { get; set; }
[Required] public decimal Weight { get; set; }
[Required] public decimal Nec { get; set; }
[Required] public string? Image { get; set; }
[Required, MaxLength(200)] public string? Link { get; set; }
[Required] public int MinimalQuantity { get; set; }
public string? Image { get; set; }
[MaxLength(200)] public string? Link { get; set; }
public int MinimalQuantity { get; set; }
// Relations
[Required] public int ClassificationId { get; set; }
@@ -23,8 +23,7 @@ namespace PyroFetes.Models
[Required] public int ProductCategoryId { get; set; }
public ProductCategory? ProductCategory { get; set; }
[Required] public int MovementId {get; set;}
public Movement? Movement {get; set;}
public List<Movement>? Movements { get; set; }
public List<ProductDelivery>? ProductDeliveries { get; set; }
public List<Brand>? Brands { get; set; }
@@ -36,6 +35,5 @@ namespace PyroFetes.Models
public List<WarehouseProduct>? WarehouseProducts { get; set; }
public List<ProductTimecode>? ProductTimecodes { get; set; }
}
}

View File

@@ -1,4 +1,4 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
namespace PyroFetes.Models;

View File

@@ -4,6 +4,8 @@ using FastEndpoints.Swagger;
using Microsoft.EntityFrameworkCore;
using PyroFetes;
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services

View File

@@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RollForward>Major</RollForward>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
@@ -22,8 +23,4 @@
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\" />
</ItemGroup>
</Project>

View File

@@ -6,6 +6,8 @@ namespace PyroFetes;
public class PyroFetesDbContext : DbContext
{
// Entities
public DbSet<Availability> Availabilities { get; set; }
public DbSet<Brand> Brands { get; set; }
@@ -55,9 +57,9 @@ public class PyroFetesDbContext : DbContext
{
string connectionString =
"Server=romaric-thibault.fr;" +
"Database=PyroFetes;" +
"User Id=pyrofetes;" +
"Password=Crablike8-Fringe-Swimmable;" +
"Database=PyroMana;" +
"User Id=matheo;" +
"Password=Onto9-Cage-Afflicted;" +
"TrustServerCertificate=true;";
optionsBuilder.UseSqlServer(connectionString);

281
PyroFetes/README.md Normal file
View File

@@ -0,0 +1,281 @@
# 🎆 Pyrofêtes — Backend
> API REST de gestion des entrepôts et produits pyrotechniques, développée avec **C#**, **ASP.NET Core** et **FastEndpoints**.
---
## 🛠️ Stack technique
| Technologie | Rôle |
|---|---|
| [C# / .NET 8](https://dotnet.microsoft.com/) | Langage et runtime principal |
| [ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/) | Framework web |
| [FastEndpoints](https://fast-endpoints.com/) | Bibliothèque d'endpoints REST performants |
| Entity Framework Core | ORM pour l'accès à la base de données |
| SQL Server | Base de données relationnelle |
| JWT Bearer | Authentification par token |
---
## 📁 Structure du projet
```
Pyrofetes.API/
├── Models/ # Entités de la base de données (EF Core)
├── DTO/ # Objets de transfert de données
│ ├── Brand/
│ │ ├── Request/
│ │ │ ├── CreateBrandDto.cs
│ │ │ └── UpdateBrandDto.cs
│ │ └── Response/
│ │ └── GetBrandDto.cs
│ ├── Classification/
│ ├── Color/
│ ├── Effect/
│ ├── Login/
│ ├── Material/
│ ├── Movement/
│ ├── Product/
│ ├── ProductCategory/
│ ├── ProductColor/
│ ├── ProductEffect/
│ ├── ProductSupplierPrice/
│ ├── ProductWarehouse/
│ ├── Refrresh/ # Token refresh
│ ├── Supplier/
│ └── Warehouse/
├── Endpoints/ # Endpoints FastEndpoints (CRUD par domaine)
│ ├── Brand/
│ │ ├── CreateBrandEndpoint.cs
│ │ ├── DeleteBrandEndpoint.cs
│ │ ├── GetAllBrandsEndpoint.cs
│ │ ├── GetBrandEndpoint.cs
│ │ └── UpdateBrandEndpoint.cs
│ ├── Classification/
│ ├── Color/
│ ├── Effect/
│ ├── Login/
│ ├── Material/
│ ├── Movement/
│ ├── Product/
│ ├── ProductCategory/
│ ├── Refresh/ # Refresh token JWT
│ ├── Supplier/
│ └── Warehouse/
├── Data/ # Contexte Entity Framework Core
│ └── AppDbContext.cs
├── Migrations/ # Migrations EF Core
├── appsettings.json # Configuration production
├── appsettings.Development.json # Configuration développement
└── Program.cs # Point d'entrée et configuration des services
```
---
## 🚀 Installation et lancement
### Prérequis
- [.NET SDK](https://dotnet.microsoft.com/download) >= 8.0
- SQL Server en cours d'exécution (local ou distant)
- [Entity Framework CLI](https://learn.microsoft.com/en-us/ef/core/cli/dotnet)
```bash
dotnet tool install --global dotnet-ef
```
### Installation
```bash
# Cloner le dépôt
git clone https://gitea.btssio-poitiers.fr/reignem/PyroFetes-Sujet1.git
cd pyrofetes-backend
```
### Migrations et base de données
```bash
# Créer la base de données et appliquer les migrations
dotnet ef database update
```
### Lancement
```bash
dotnet run
```
L'API sera disponible sur [http://localhost:5000](http://localhost:5000)
La documentation Swagger sera accessible sur [http://localhost:5000/swagger](http://localhost:5000/swagger)
---
## ⚙️ Configuration FastEndpoints + CORS
Dans `Program.cs` :
```csharp
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAngular", policy =>
policy.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod());
});
builder.Services.AddFastEndpoints();
builder.Services.AddJWTBearerAuth("votre-cle-secrete");
var app = builder.Build();
app.UseCors("AllowAngular");
app.UseAuthentication();
app.UseAuthorization();
app.UseFastEndpoints();
app.Run();
```
### Anatomie d'un endpoint
Chaque endpoint suit le pattern **Request → Handler → Response** de FastEndpoints :
```csharp
// Endpoints/Brand/GetAllBrandsEndpoint.cs
public class GetAllBrandsEndpoint : EndpointWithoutRequest<List<GetBrandDto>>
{
private readonly AppDbContext _db;
public GetAllBrandsEndpoint(AppDbContext db) => _db = db;
public override void Configure()
{
Get("/api/brands");
Roles("Admin", "User");
}
public override async Task HandleAsync(CancellationToken ct)
{
var brands = await _db.Brands
.Select(b => new GetBrandDto { Id = b.Id, Name = b.Name })
.ToListAsync(ct);
await SendOkAsync(brands, ct);
}
}
```
### Pattern DTO
```
DTO/
└── Brand/
├── Request/
│ ├── CreateBrandDto.cs ← payload entrant (POST)
│ └── UpdateBrandDto.cs ← payload entrant (PUT)
└── Response/
└── GetBrandDto.cs ← payload sortant (GET)
```
---
## 📡 Endpoints API
> Tous les endpoints (sauf `/api/auth/*` et `/api/auth/refresh`) requièrent un header `Authorization: Bearer <token>`.
### Authentification
| Méthode | Route | Description | Auth |
|---|---|---|---|
| `POST` | `/api/auth/login` | Connexion, retourne JWT + refresh token | ❌ |
| `POST` | `/api/auth/refresh` | Renouvellement du JWT via refresh token | ❌ |
### Marques (Brand)
| Méthode | Route | Description |
|---|---|---|
| `GET` | `/api/brands` | Liste toutes les marques |
| `GET` | `/api/brands/{id}` | Détail d'une marque |
| `POST` | `/api/brands` | Créer une marque |
| `PUT` | `/api/brands/{id}` | Modifier une marque |
| `DELETE` | `/api/brands/{id}` | Supprimer une marque |
### Produits (Product)
| Méthode | Route | Description |
|---|---|---|
| `GET` | `/api/products` | Liste tous les produits |
| `GET` | `/api/products/{id}` | Détail d'un produit |
| `POST` | `/api/products` | Créer un produit |
| `PUT` | `/api/products/{id}` | Modifier un produit |
| `DELETE` | `/api/products/{id}` | Supprimer un produit |
### Entrepôts (Warehouse)
| Méthode | Route | Description |
|---|---|---|
| `GET` | `/api/warehouses` | Liste tous les entrepôts |
| `GET` | `/api/warehouses/{id}` | Détail d'un entrepôt |
| `POST` | `/api/warehouses` | Créer un entrepôt |
| `PUT` | `/api/warehouses/{id}` | Modifier un entrepôt |
| `DELETE` | `/api/warehouses/{id}` | Supprimer un entrepôt |
### Fournisseurs (Supplier)
| Méthode | Route | Description |
|---|---|---|
| `GET` | `/api/suppliers` | Liste tous les fournisseurs |
| `GET` | `/api/suppliers/{id}` | Détail d'un fournisseur |
| `POST` | `/api/suppliers` | Créer un fournisseur |
| `PUT` | `/api/suppliers/{id}` | Modifier un fournisseur |
| `DELETE` | `/api/suppliers/{id}` | Supprimer un fournisseur |
### Autres domaines disponibles
| Domaine | Préfixe route |
|---|---|
| Classifications | `/api/classifications` |
| Couleurs | `/api/colors` |
| Effets | `/api/effects` |
| Matériaux | `/api/materials` |
| Mouvements de stock | `/api/movements` |
| Catégories produit | `/api/product-categories` |
| Couleurs produit | `/api/product-colors` |
| Effets produit | `/api/product-effects` |
| Prix fournisseur produit | `/api/product-supplier-prices` |
---
## 🔐 Authentification JWT
### Flux d'authentification
```
Client (Angular) API (FastEndpoints)
│ │
│── POST /api/auth/login ──▶│
│ │ Vérifie credentials
│◀── { token, refreshToken }│
│ │
│── GET /api/... ──────────▶│
│ Authorization: Bearer │ Valide le JWT
│◀── 200 OK ────────────────│
│ │
│── POST /api/auth/refresh ▶│ (token expiré)
│◀── { newToken } ──────────│
```
### Header requis
```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
---
## 📄 Licence
Ce projet est à usage interne — © Pyrofêtes. Tous droits réservés.

303
README.md
View File

@@ -1,50 +1,281 @@
# Gestionnaire de Stocks et Commandes
# 🎆 Pyrofêtes — Backend
Cette application web permet de **suivre les stocks**, **automatiser les commandes fournisseurs** et **gérer le cycle complet dapprovisionnement**.
Elle est conçue pour simplifier le travail des entreprises en offrant une vue en temps réel sur les produits, leurs fournisseurs et létat des livraisons.
> API REST de gestion des entrepôts et produits pyrotechniques, développée avec **C#**, **ASP.NET Core** et **FastEndpoints**.
---
## ✨ Fonctionnalités principales
## 🛠️ Stack technique
### 1⃣ Suivi et réapprovisionnement des stocks
- Définissez un **niveau minimal de stock** pour chaque produit.
- Surveillez les **niveaux en temps réel** grâce à une interface claire.
- Lorsquun produit atteint ou descend sous son seuil minimal, le système **génère automatiquement un bon de commande** pour le réapprovisionner.
### 2⃣ Gestion des fournisseurs
- Enregistrez les informations complètes des fournisseurs : nom, adresse, coordonnées, produits fournis, délais de livraison.
- **Associez un ou plusieurs fournisseurs** à chaque produit.
- Lorsquun bon de commande est créé, le système **propose automatiquement les fournisseurs appropriés**.
### 3⃣ Devis et bons de commande
- Créez des **devis personnalisés** : sélection des produits, quantités, prix, ajout dun logo, message ou conditions de vente.
- **Imprimez ou exportez** vos devis au format PDF.
- Générez des **bons de commande** en quelques clics, avec personnalisation (logo, conditions dachat) et exportation en PDF.
### 4⃣ Suivi des livraisons
- **Transformez un bon de commande en bon de livraison** dès lexpédition des produits par le fournisseur.
- Enregistrez toutes les informations importantes : date dexpédition, transporteur, numéro de suivi, date prévue et date effective de livraison.
- Recevez des **alertes en cas de retard**.
- Gérez la **réception des produits** et vérifiez leur conformité.
| Technologie | Rôle |
|---|---|
| [C# / .NET 8](https://dotnet.microsoft.com/) | Langage et runtime principal |
| [ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/) | Framework web |
| [FastEndpoints](https://fast-endpoints.com/) | Bibliothèque d'endpoints REST performants |
| Entity Framework Core | ORM pour l'accès à la base de données |
| SQL Server | Base de données relationnelle |
| JWT Bearer | Authentification par token |
---
## 🗂️ Livrables prévus
- **Modèle de données** : diagramme de classes commun à tous les groupes.
- **Interface utilisateur** : maquettes ou prototypes interactifs.
- **Code source commenté** pour une meilleure compréhension.
- **Documentation technique** : description des fonctionnalités, architecture de lapplication et API.
## 📁 Structure du projet
```
Pyrofetes.API/
├── Models/ # Entités de la base de données (EF Core)
├── DTO/ # Objets de transfert de données
│ ├── Brand/
│ │ ├── Request/
│ │ │ ├── CreateBrandDto.cs
│ │ │ └── UpdateBrandDto.cs
│ │ └── Response/
│ │ └── GetBrandDto.cs
│ ├── Classification/
│ ├── Color/
│ ├── Effect/
│ ├── Login/
│ ├── Material/
│ ├── Movement/
│ ├── Product/
│ ├── ProductCategory/
│ ├── ProductColor/
│ ├── ProductEffect/
│ ├── ProductSupplierPrice/
│ ├── ProductWarehouse/
│ ├── Refrresh/ # Token refresh
│ ├── Supplier/
│ └── Warehouse/
├── Endpoints/ # Endpoints FastEndpoints (CRUD par domaine)
│ ├── Brand/
│ │ ├── CreateBrandEndpoint.cs
│ │ ├── DeleteBrandEndpoint.cs
│ │ ├── GetAllBrandsEndpoint.cs
│ │ ├── GetBrandEndpoint.cs
│ │ └── UpdateBrandEndpoint.cs
│ ├── Classification/
│ ├── Color/
│ ├── Effect/
│ ├── Login/
│ ├── Material/
│ ├── Movement/
│ ├── Product/
│ ├── ProductCategory/
│ ├── Refresh/ # Refresh token JWT
│ ├── Supplier/
│ └── Warehouse/
├── Data/ # Contexte Entity Framework Core
│ └── AppDbContext.cs
├── Migrations/ # Migrations EF Core
├── appsettings.json # Configuration production
├── appsettings.Development.json # Configuration développement
└── Program.cs # Point d'entrée et configuration des services
```
---
## 👥 Équipe
- **Mathys**
- **Enzo**
- **Cristiano**
- **Arsène**
## 🚀 Installation et lancement
### Prérequis
- [.NET SDK](https://dotnet.microsoft.com/download) >= 8.0
- SQL Server en cours d'exécution (local ou distant)
- [Entity Framework CLI](https://learn.microsoft.com/en-us/ef/core/cli/dotnet)
```bash
dotnet tool install --global dotnet-ef
```
### Installation
```bash
# Cloner le dépôt
git clone https://gitea.btssio-poitiers.fr/reignem/PyroFetes-Sujet1.git
cd pyrofetes-backend
```
### Migrations et base de données
```bash
# Créer la base de données et appliquer les migrations
dotnet ef database update
```
### Lancement
```bash
dotnet run
```
L'API sera disponible sur [http://localhost:5000](http://localhost:5000)
La documentation Swagger sera accessible sur [http://localhost:5000/swagger](http://localhost:5000/swagger)
---
## 🚀 Objectif
Fournir un outil complet pour automatiser la gestion des stocks et des commandes, réduisant les erreurs humaines, améliorant le suivi des livraisons et facilitant la communication avec les fournisseurs.
## ⚙️ Configuration FastEndpoints + CORS
Dans `Program.cs` :
```csharp
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAngular", policy =>
policy.WithOrigins("http://localhost:4200")
.AllowAnyHeader()
.AllowAnyMethod());
});
builder.Services.AddFastEndpoints();
builder.Services.AddJWTBearerAuth("votre-cle-secrete");
var app = builder.Build();
app.UseCors("AllowAngular");
app.UseAuthentication();
app.UseAuthorization();
app.UseFastEndpoints();
app.Run();
```
### Anatomie d'un endpoint
Chaque endpoint suit le pattern **Request → Handler → Response** de FastEndpoints :
```csharp
// Endpoints/Brand/GetAllBrandsEndpoint.cs
public class GetAllBrandsEndpoint : EndpointWithoutRequest<List<GetBrandDto>>
{
private readonly AppDbContext _db;
public GetAllBrandsEndpoint(AppDbContext db) => _db = db;
public override void Configure()
{
Get("/api/brands");
Roles("Admin", "User");
}
public override async Task HandleAsync(CancellationToken ct)
{
var brands = await _db.Brands
.Select(b => new GetBrandDto { Id = b.Id, Name = b.Name })
.ToListAsync(ct);
await SendOkAsync(brands, ct);
}
}
```
### Pattern DTO
```
DTO/
└── Brand/
├── Request/
│ ├── CreateBrandDto.cs ← payload entrant (POST)
│ └── UpdateBrandDto.cs ← payload entrant (PUT)
└── Response/
└── GetBrandDto.cs ← payload sortant (GET)
```
---
## 📡 Endpoints API
> Tous les endpoints (sauf `/api/auth/*` et `/api/auth/refresh`) requièrent un header `Authorization: Bearer <token>`.
### Authentification
| Méthode | Route | Description | Auth |
|---|---|---|---|
| `POST` | `/api/auth/login` | Connexion, retourne JWT + refresh token | ❌ |
| `POST` | `/api/auth/refresh` | Renouvellement du JWT via refresh token | ❌ |
### Marques (Brand)
| Méthode | Route | Description |
|---|---|---|
| `GET` | `/api/brands` | Liste toutes les marques |
| `GET` | `/api/brands/{id}` | Détail d'une marque |
| `POST` | `/api/brands` | Créer une marque |
| `PUT` | `/api/brands/{id}` | Modifier une marque |
| `DELETE` | `/api/brands/{id}` | Supprimer une marque |
### Produits (Product)
| Méthode | Route | Description |
|---|---|---|
| `GET` | `/api/products` | Liste tous les produits |
| `GET` | `/api/products/{id}` | Détail d'un produit |
| `POST` | `/api/products` | Créer un produit |
| `PUT` | `/api/products/{id}` | Modifier un produit |
| `DELETE` | `/api/products/{id}` | Supprimer un produit |
### Entrepôts (Warehouse)
| Méthode | Route | Description |
|---|---|---|
| `GET` | `/api/warehouses` | Liste tous les entrepôts |
| `GET` | `/api/warehouses/{id}` | Détail d'un entrepôt |
| `POST` | `/api/warehouses` | Créer un entrepôt |
| `PUT` | `/api/warehouses/{id}` | Modifier un entrepôt |
| `DELETE` | `/api/warehouses/{id}` | Supprimer un entrepôt |
### Fournisseurs (Supplier)
| Méthode | Route | Description |
|---|---|---|
| `GET` | `/api/suppliers` | Liste tous les fournisseurs |
| `GET` | `/api/suppliers/{id}` | Détail d'un fournisseur |
| `POST` | `/api/suppliers` | Créer un fournisseur |
| `PUT` | `/api/suppliers/{id}` | Modifier un fournisseur |
| `DELETE` | `/api/suppliers/{id}` | Supprimer un fournisseur |
### Autres domaines disponibles
| Domaine | Préfixe route |
|---|---|
| Classifications | `/api/classifications` |
| Couleurs | `/api/colors` |
| Effets | `/api/effects` |
| Matériaux | `/api/materials` |
| Mouvements de stock | `/api/movements` |
| Catégories produit | `/api/product-categories` |
| Couleurs produit | `/api/product-colors` |
| Effets produit | `/api/product-effects` |
| Prix fournisseur produit | `/api/product-supplier-prices` |
---
## 🔐 Authentification JWT
### Flux d'authentification
```
Client (Angular) API (FastEndpoints)
│ │
│── POST /api/auth/login ──▶│
│ │ Vérifie credentials
│◀── { token, refreshToken }│
│ │
│── GET /api/... ──────────▶│
│ Authorization: Bearer │ Valide le JWT
│◀── 200 OK ────────────────│
│ │
│── POST /api/auth/refresh ▶│ (token expiré)
│◀── { newToken } ──────────│
```
### Header requis
```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
---
## 📄 Licence
Ce projet est à usage interne — © Pyrofêtes. Tous droits réservés.