docs: design plantes/variétés — Option B 2 tables + import graines
This commit is contained in:
163
docs/plans/2026-03-08-plantes-varietes-design.md
Normal file
163
docs/plans/2026-03-08-plantes-varietes-design.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# Plantes & Variétés — Design
|
||||
|
||||
> **Pour Claude :** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Restructurer la gestion des plantes en séparant niveau espèce (`plant`) et niveau variété (`plant_variety`), importer les données JSON des sachets de graines et arbustes, et ajouter le bouton "Ajouter variété" dans l'UI.
|
||||
|
||||
**Architecture:** Option B — deux tables distinctes (`plant` + `plant_variety`), migration des 21 plantes existantes, import one-shot des 14 graines + 4 arbustes, nouveaux endpoints CRUD variétés.
|
||||
|
||||
**Tech Stack:** FastAPI + SQLModel + SQLite (backend), Vue 3 + Pinia + Tailwind Gruvbox (frontend)
|
||||
|
||||
---
|
||||
|
||||
## Modèle de données
|
||||
|
||||
### Table `plant` (niveau espèce / nom commun)
|
||||
|
||||
Conserve toutes les colonnes actuelles **sauf** : `variete`, `boutique_nom`, `boutique_url`, `prix_achat`, `date_achat`, `poids`, `dluo`, `tags`
|
||||
|
||||
Nouvelles colonnes ajoutées :
|
||||
| Champ | Type | Notes |
|
||||
|---|---|---|
|
||||
| temp_germination | TEXT | Ex: "8-10°C" |
|
||||
| temps_levee_j | TEXT | Ex: "15-20 jours" |
|
||||
|
||||
### Table `plant_variety` (niveau variété)
|
||||
|
||||
| Champ | Type | Notes |
|
||||
|---|---|---|
|
||||
| id | INTEGER PK | |
|
||||
| plant_id | INTEGER FK → plant | |
|
||||
| variete | TEXT | "Nain", "Grimpant", "Stockarda"… |
|
||||
| tags | TEXT | Tags spécifiques à cette variété |
|
||||
| notes_variete | TEXT | Observations propres à la variété |
|
||||
| boutique_nom | TEXT | Enseigne d'achat |
|
||||
| boutique_url | TEXT | URL fiche produit |
|
||||
| prix_achat | REAL | En € |
|
||||
| date_achat | TEXT | ISO date |
|
||||
| poids | TEXT | Ex: "500 graines", "1g" |
|
||||
| dluo | TEXT | ISO date limite d'utilisation |
|
||||
| created_at | TEXT | ISO datetime |
|
||||
|
||||
### Photos sachet de graines
|
||||
→ Table `media` existante avec `entity_type='plant_variety'` et `entity_id=plant_variety.id`
|
||||
→ Deux photos par variété max (recto + verso sachet), type `photo_sachet`
|
||||
|
||||
---
|
||||
|
||||
## API REST
|
||||
|
||||
### Endpoints `plant` modifiés
|
||||
|
||||
```
|
||||
GET /api/plants → liste plant + varieties[] (jointure)
|
||||
GET /api/plants/{id} → détail plant + varieties[]
|
||||
POST /api/plants → créer une plante (sans variété)
|
||||
PUT /api/plants/{id} → modifier les champs espèce
|
||||
DEL /api/plants/{id} → supprimer (cascade varieties)
|
||||
```
|
||||
|
||||
### Nouveaux endpoints `plant_variety`
|
||||
|
||||
```
|
||||
GET /api/plants/{id}/varieties → liste des variétés d'une plante
|
||||
POST /api/plants/{id}/varieties → créer une variété
|
||||
PUT /api/plants/{id}/varieties/{vid} → modifier une variété
|
||||
DELETE /api/plants/{id}/varieties/{vid} → supprimer une variété
|
||||
```
|
||||
|
||||
### Import one-shot
|
||||
|
||||
```
|
||||
POST /api/plants/import-graines → importe docs/graine/ + docs/arbustre/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration BDD (script Python one-shot)
|
||||
|
||||
1. Créer table `plant_variety` avec toutes ses colonnes
|
||||
2. Pour chaque ligne `plant` actuelle → créer une `plant_variety` (copier variete, boutique_*, tags)
|
||||
3. Recréer `plant` sans les colonnes migrées + ajouter temp_germination + temps_levee_j
|
||||
4. Fusionner `haricot grimpant` (id=21) sous `Haricot` (id=7) comme variété, supprimer id=21
|
||||
|
||||
---
|
||||
|
||||
## Import JSON
|
||||
|
||||
### `docs/graine/caracteristiques_plantation.json` (14 entrées)
|
||||
|
||||
Mapping automatique `nom → plant.nom_commun` :
|
||||
|
||||
| JSON | nom_commun BDD | Action |
|
||||
|---|---|---|
|
||||
| Oignon Stockarda | Oignon (nouveau) | créer plant + variety |
|
||||
| Laitue Attraction | Laitue (id=4) | nouvelle variety |
|
||||
| Persil frise Moskrul 2 | Persil (id=13) | enrichir plant + nouvelle variety |
|
||||
| Courgette de Nice | Courgette (id=2) | nouvelle variety |
|
||||
| Pois à ecosser Merveille | Pois (id=8) | enrichir + nouvelle variety |
|
||||
| Tomates Moneymaker | Tomate (id=1) | nouvelle variety |
|
||||
| Poireau Bleu de Solaise | Poireau (id=9) | enrichir variety existante |
|
||||
| Echalion Zebrune | Échalote (id=14) | nouvelle variety |
|
||||
| Courge Musquée Sucrine | Courge (nouveau) | créer plant + variety |
|
||||
| Laitue Grosse Blonde | Laitue (id=4) | nouvelle variety |
|
||||
| Chou Pomme Brunswick | Chou (id=16) | enrichir + nouvelle variety |
|
||||
| Chou-fleur Nautilus HF1 | Chou-fleur (id=15) | enrichir variety existante |
|
||||
| Tomate Cornue Cornabel | Tomate (id=1) | nouvelle variety |
|
||||
| Pois mangetout Carouby | Pois (id=8) | nouvelle variety |
|
||||
|
||||
Champs JSON → colonnes `plant` :
|
||||
- `periode_semis` (ex: "III-IV") → `semis_exterieur_mois` (converti en liste mois "3,4")
|
||||
- `periode_recolte` → `recolte_mois`
|
||||
- `temperature` → `temp_germination`
|
||||
- `profondeur` → `profondeur_semis_cm` (extrait la valeur numérique)
|
||||
- `espacement` → `espacement_cm` (premier chiffre)
|
||||
- `exposition` → `besoin_soleil`
|
||||
- texte `arriere` → `astuces_culture`
|
||||
|
||||
Photos `IMG_*.jpg` → copiées dans `/data/uploads/` + entrées `media` (entity_type='plant_variety')
|
||||
|
||||
### `docs/arbustre/caracteristiques_arbustre.json` (4 entrées)
|
||||
|
||||
4 nouvelles plantes de catégorie `arbuste` avec leurs variétés.
|
||||
|
||||
---
|
||||
|
||||
## Frontend
|
||||
|
||||
### `PlantesView.vue` — modifications
|
||||
|
||||
- **GET /api/plants** retourne `plant + varieties[]` → groupage déjà géré
|
||||
- **Popup détail** : bouton **"+ Variété"** à gauche du bouton "Modifier"
|
||||
- **Popup variété** : formulaire pré-rempli depuis `plant` (nom commun) + champs variété-spécifiques :
|
||||
- Nom de variété (requis)
|
||||
- Tags, notes variété
|
||||
- Boutique (nom, URL, prix, date, poids, DLUO)
|
||||
- Section photos sachet : 2 uploads (recto + verso)
|
||||
- **Popup nom commun** : affiche `temp_germination` + `temps_levee_j` dans la section culture
|
||||
|
||||
### `frontend/src/api/plants.ts` — modifications
|
||||
|
||||
- Interface `Plant` : supprimer boutique/tags/variete, ajouter `temp_germination`, `temps_levee_j`, `varieties: PlantVariety[]`
|
||||
- Nouvelle interface `PlantVariety` : tous les champs variété
|
||||
- Nouveaux appels API : `createVariety`, `updateVariety`, `deleteVariety`
|
||||
|
||||
### `frontend/src/stores/plants.ts` — modifications
|
||||
|
||||
- Actions : `createVariety`, `updateVariety`, `deleteVariety`
|
||||
- `fetchAll` charge désormais les varieties intégrées
|
||||
|
||||
---
|
||||
|
||||
## Fichiers à créer / modifier
|
||||
|
||||
| Fichier | Action |
|
||||
|---|---|
|
||||
| `backend/app/models/plant.py` | Modifier : supprimer champs migrés, ajouter temp_germination + temps_levee_j + PlantVariety |
|
||||
| `backend/app/routers/plants.py` | Modifier : GET retourne varieties, + endpoints varieties CRUD |
|
||||
| `backend/app/migrate.py` | Modifier : ajouter section plant_variety |
|
||||
| `backend/scripts/migrate_plant_varieties.py` | Créer : script migration one-shot |
|
||||
| `backend/scripts/import_graines.py` | Créer : script import JSON graines + arbustre |
|
||||
| `frontend/src/api/plants.ts` | Modifier : Plant + PlantVariety interfaces |
|
||||
| `frontend/src/stores/plants.ts` | Modifier : actions variety |
|
||||
| `frontend/src/views/PlantesView.vue` | Modifier : bouton + variété + popup variété + champs nouveaux |
|
||||
Reference in New Issue
Block a user