# Contrat d'erreurs API Ce document définit le format standard des erreurs de l'API HomeStock. --- ## Format des réponses d'erreur ### Erreurs métier (HTTPException) Toutes les erreurs métier utilisent `fastapi.HTTPException` et retournent : ```json { "detail": "Message d'erreur lisible" } ``` ### Erreurs de validation (Pydantic / FastAPI) Les erreurs de validation des paramètres ou du corps de requête retournent automatiquement : ```json { "detail": [ { "type": "validation_error", "loc": ["body", "name"], "msg": "String should have at least 1 character", "input": "" } ] } ``` ### Erreurs internes (500) Le gestionnaire global (`main.py`) retourne : ```json { "detail": "Message technique (dev) ou 'Erreur interne du serveur' (prod)", "type": "internal_server_error" } ``` En développement, le message contient les détails de l'exception. En production, le message est masqué pour la sécurité. --- ## Codes HTTP utilisés | Code | Signification | Usage | |------|---------------|-------| | **200** | OK | GET, PUT, PATCH réussis | | **201** | Created | POST réussi (création de ressource) | | **204** | No Content | DELETE réussi (documents) | | **400** | Bad Request | Données invalides (type de fichier, taille, auto-référence) | | **404** | Not Found | Ressource inexistante (item, catégorie, emplacement, boutique, document, fichier physique) | | **409** | Conflict | Conflit d'unicité (nom dupliqué, n° de série) ou dépendance empêchant la suppression | | **422** | Unprocessable Entity | Erreur de validation Pydantic (format automatique FastAPI) | | **500** | Internal Server Error | Exception non gérée | --- ## Codes d'erreur par domaine ### Items (`/api/v1/items`) | Code HTTP | Situation | Message | |-----------|-----------|---------| | 404 | Item non trouvé | `Objet {id} non trouvé` | | 404 | Catégorie référencée inexistante | `Catégorie {id} non trouvée` | | 404 | Emplacement référencé inexistant | `Emplacement {id} non trouvé` | | 409 | N° de série déjà utilisé | `Un objet avec le numéro de série '{sn}' existe déjà` | ### Catégories (`/api/v1/categories`) | Code HTTP | Situation | Message | |-----------|-----------|---------| | 404 | Catégorie non trouvée | `Catégorie {id} non trouvée` | | 409 | Nom déjà utilisé | `Une catégorie avec le nom '{name}' existe déjà` | | 409 | Suppression avec items liés | `Impossible de supprimer : {n} objet(s) utilisent cette catégorie` | ### Emplacements (`/api/v1/locations`) | Code HTTP | Situation | Message | |-----------|-----------|---------| | 404 | Emplacement non trouvé | `Emplacement {id} non trouvé` | | 404 | Parent inexistant | `Emplacement parent {id} non trouvé` | | 400 | Auto-référence | `Un emplacement ne peut pas être son propre parent` | | 409 | Suppression avec items liés | `Impossible de supprimer : {n} objet(s) utilisent cet emplacement` | | 409 | Suppression avec sous-emplacements | `Impossible de supprimer : cet emplacement a {n} sous-emplacement(s)` | ### Boutiques (`/api/v1/shops`) | Code HTTP | Situation | Message | |-----------|-----------|---------| | 404 | Boutique non trouvée | `Boutique {id} non trouvée` | | 409 | Nom déjà utilisé | `Une boutique avec le nom '{name}' existe déjà` | | 409 | Suppression avec items liés | `Impossible de supprimer : {n} objet(s) sont associés à cette boutique` | ### Documents (`/api/v1/documents`) | Code HTTP | Situation | Message | |-----------|-----------|---------| | 404 | Item parent inexistant | `Item {id} non trouvé` | | 404 | Document non trouvé | `Document non trouvé` | | 404 | Fichier physique manquant | `Fichier non trouvé sur le disque` | | 400 | Type MIME non autorisé | `Type de fichier non autorisé : {mime}. Types acceptés : images (JPEG, PNG, GIF, WebP) et PDF` | | 400 | Photo sans image | `Le type 'photo' nécessite un fichier image` | | 400 | Fichier trop volumineux | `Fichier trop volumineux ({size} Mo). Taille max : 10 Mo` | ### Import CSV (`/api/v1/import`) | Code HTTP | Situation | Message | |-----------|-----------|---------| | 400 | Fichier non CSV | `Le fichier doit être un CSV (.csv)` | | 400 | Indices de sélection invalides | `Format d'indices invalide` | | 400 | Statut d'item invalide | `Statut invalide : {status}` | --- ## Conventions ### Champs obligatoires Toute réponse d'erreur contient au minimum le champ `detail` (string ou array). ### Messages - Les messages sont en **français**, destinés à l'utilisateur final - Ils incluent le contexte nécessaire (ID de la ressource, nom dupliqué, taille du fichier) - En production (500), le message technique est masqué ### Gestion côté client Le frontend intercepte les erreurs via un intercepteur Axios (`api/client.ts`) qui log l'erreur dans la console. Le champ `detail` est affiché à l'utilisateur. --- ## Schéma de réponse (schemas/common.py) ```python class ErrorResponse(BaseModel): detail: str # Message d'erreur type: str # Type d'erreur (ex: "internal_server_error") class SuccessResponse(BaseModel): message: str # Message de succès id: int | None # ID de l'élément concerné ```