Files
serv_benchmark/docs/FEATURE_UTILISATION_FIELD.md
2026-01-11 23:41:30 +01:00

303 lines
8.4 KiB
Markdown

# 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
<div class="form-group">
<label for="utilisation">
Utilisation
<span class="help-text-inline">(Hôte ou appareil)</span>
</label>
<select id="utilisation" name="utilisation">
<option value="">Chargement...</option>
</select>
</div>
```
#### 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.