# Champ "Utilisation" pour les périphériques ## Contexte Chaque périphérique peut être soit en stockage, soit utilisé par un appareil/hôte spécifique. Le champ `utilisation` permet de tracer où chaque périphérique est utilisé. ## Implémentation ### 1. Migration base de données **Fichier**: `migrations/015_add_utilisation.sql` ```sql ALTER TABLE peripherals ADD COLUMN utilisation VARCHAR(255); CREATE INDEX idx_peripherals_utilisation ON peripherals(utilisation); ``` **Application**: ```bash python3 backend/apply_migration_015.py ``` ### 2. Modèle mis à jour **Fichier**: `backend/app/models/peripheral.py` (ligne 60) ```python etat = Column(String(50), default="Neuf", index=True) localisation = Column(String(255)) proprietaire = Column(String(100)) utilisation = Column(String(255)) # Host from host.yaml or "non-utilisé" ← NOUVEAU tags = Column(Text) notes = Column(Text) ``` ### 3. Schéma mis à jour **Fichier**: `backend/app/schemas/peripheral.py` **PeripheralBase** (ligne 46): ```python etat: Optional[str] = Field("Neuf", max_length=50) localisation: Optional[str] = Field(None, max_length=255) proprietaire: Optional[str] = Field(None, max_length=100) utilisation: Optional[str] = Field(None, max_length=255) # ← NOUVEAU tags: Optional[str] = None ``` **PeripheralUpdate** (ligne 132): ```python etat: Optional[str] = Field(None, max_length=50) localisation: Optional[str] = Field(None, max_length=255) proprietaire: Optional[str] = Field(None, max_length=100) utilisation: Optional[str] = Field(None, max_length=255) # ← NOUVEAU tags: Optional[str] = None ``` ### 4. Configuration des hôtes **Fichier**: `config/host.yaml` ```yaml hosts: - nom: Bureau-PC localisation: Bureau - nom: Serveur-NAS localisation: Salon - nom: Atelier-RPi localisation: Atelier - nom: Portable-Work localisation: Bureau ``` Les hôtes définis ici apparaissent dans le menu déroulant du champ "Utilisation". ### 5. API Endpoint **Fichier**: `backend/app/api/endpoints/peripherals.py` (lignes 105-120) ```python @router.get("/config/hosts", response_model=dict) def get_hosts(): """ Get hosts list from host.yaml configuration. Returns list of hosts with their names and locations. """ try: hosts = yaml_loader.get_hosts() return { "success": True, "hosts": hosts } except Exception as e: raise HTTPException(status_code=500, detail=f"Failed to load hosts: {str(e)}") ``` **Route**: `GET /api/peripherals/config/hosts` **Réponse**: ```json { "success": true, "hosts": [ {"nom": "Bureau-PC", "localisation": "Bureau"}, {"nom": "Serveur-NAS", "localisation": "Salon"}, {"nom": "Atelier-RPi", "localisation": "Atelier"}, {"nom": "Portable-Work", "localisation": "Bureau"} ] } ``` ### 6. Frontend #### HTML - `frontend/peripherals.html` (lignes 243-251) ```html
``` #### JavaScript - `frontend/js/peripherals.js` **Fonction de chargement des hosts** (lignes 1262-1283): ```javascript // Cache for hosts from API let hostsCache = null; // Load hosts from API async function loadHostsFromAPI() { if (hostsCache) { return hostsCache; } try { const result = await apiRequest('/peripherals/config/hosts'); if (result.success && result.hosts) { hostsCache = result.hosts; return result.hosts; } } catch (error) { console.error('Failed to load hosts from API:', error); } // Fallback to default if API fails return []; } ``` **Fonction de chargement des options** (lignes 1285-1309): ```javascript // Load utilisation options (hosts + "Non utilisé") async function loadUtilisationOptions() { const utilisationSelect = document.getElementById('utilisation'); if (!utilisationSelect) return; // Clear current options utilisationSelect.innerHTML = ''; // Add "Non utilisé" as first option const nonUtiliseOption = document.createElement('option'); nonUtiliseOption.value = 'Non utilisé'; nonUtiliseOption.textContent = 'Non utilisé'; utilisationSelect.appendChild(nonUtiliseOption); // Load hosts from API const hosts = await loadHostsFromAPI(); // Add each host as an option hosts.forEach(host => { const option = document.createElement('option'); option.value = host.nom; option.textContent = `${host.nom}${host.localisation ? ' (' + host.localisation + ')' : ''}`; utilisationSelect.appendChild(option); }); } ``` **Appel au chargement** (ligne 535): ```javascript async function showAddModal() { document.getElementById('form-add-peripheral').reset(); document.getElementById('modal-add').style.display = 'block'; await loadUtilisationOptions(); // Load hosts from host.yaml updateUtilisationFields(); updatePhotoUrlAddUI(); } ``` **Sauvegarde de la valeur** (lignes 566-568): ```javascript // Handle utilisation field - store the host name or "Non utilisé" const utilisation = document.getElementById('utilisation')?.value || 'Non utilisé'; data.utilisation = utilisation; ``` ## Utilisation ### Ajouter/Modifier un périphérique 1. Ouvrir le formulaire d'ajout/modification 2. Dans la section "État et localisation", le champ **Utilisation** affiche: - **Non utilisé** (par défaut) - **Bureau-PC (Bureau)** - **Serveur-NAS (Salon)** - **Atelier-RPi (Atelier)** - **Portable-Work (Bureau)** 3. Sélectionner l'hôte où le périphérique est utilisé 4. Enregistrer ### Ajouter un nouvel hôte Pour ajouter un nouvel hôte dans la liste: 1. Éditer le fichier `config/host.yaml` 2. Ajouter une entrée: ```yaml - nom: Nouveau-PC localisation: Chambre ``` 3. Redémarrer le backend (si en développement) ou attendre le rechargement automatique 4. Le nouvel hôte apparaîtra automatiquement dans le menu déroulant ## Exemples de valeurs | Valeur | Description | |--------|-------------| | `Non utilisé` | Périphérique en stockage | | `Bureau-PC` | Périphérique utilisé par le PC du bureau | | `Serveur-NAS` | Périphérique utilisé par le serveur NAS | | `Atelier-RPi` | Périphérique utilisé par le Raspberry Pi de l'atelier | | `Portable-Work` | Périphérique utilisé par l'ordinateur portable de travail | ## Bénéfices ✅ **Traçabilité**: Savoir où chaque périphérique est utilisé ✅ **Configuration centralisée**: Les hôtes sont définis dans `host.yaml` ✅ **Interface simplifiée**: Menu déroulant au lieu de saisie libre ✅ **Cohérence**: Évite les fautes de frappe et les variations (ex: "bureau-pc" vs "Bureau PC") ✅ **Extensible**: Facile d'ajouter de nouveaux hôtes ✅ **Indexé**: Recherches rapides par utilisation ## Requêtes utiles ### Trouver tous les périphériques non utilisés ```python peripherals = session.query(Peripheral).filter( Peripheral.utilisation == 'Non utilisé' ).all() ``` ### Trouver tous les périphériques d'un hôte ```python peripherals = session.query(Peripheral).filter( Peripheral.utilisation == 'Bureau-PC' ).all() ``` ### Compter les périphériques par hôte ```python from sqlalchemy import func stats = session.query( Peripheral.utilisation, func.count(Peripheral.id) ).group_by(Peripheral.utilisation).all() ``` ## Fichiers modifiés 1. **migrations/015_add_utilisation.sql** - Migration SQL 2. **backend/apply_migration_015.py** - Script d'application 3. **backend/app/models/peripheral.py** - Ajout du champ 4. **backend/app/schemas/peripheral.py** - Ajout au schéma (2 endroits) 5. **backend/app/api/endpoints/peripherals.py** - Endpoint `/config/hosts` 6. **frontend/peripherals.html** - Modification du select 7. **frontend/js/peripherals.js** - Chargement dynamique des options ## Migration des données existantes Si des périphériques existaient avant l'ajout du champ: - La valeur par défaut est `NULL` - Recommandé de définir à `'Non utilisé'` pour les périphériques en stockage ```sql UPDATE peripherals SET utilisation = 'Non utilisé' WHERE utilisation IS NULL; ``` ## Conclusion Le champ `utilisation` permet un suivi précis de l'emplacement et de l'usage de chaque périphérique, avec une gestion centralisée des hôtes via le fichier `host.yaml` et un chargement dynamique dans l'interface.