diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9a4ca67 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +## [Unreleased] +- Analyse detaillee des consignes. +- Reference structure BDD. +- TODO projet global. + +## [0.1.0] - 2026-01-21 +- MVP core + DB SQLite (planifie). + +## [0.2.0] - 2026-??-?? +- Pieces jointes multiples + themes (planifie). + +## [1.0.0] - 2026-??-?? +- Full features + deploiement Docker (planifie). diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..39ab0d6 --- /dev/null +++ b/TODO.md @@ -0,0 +1,29 @@ +# TODO MatosBox + +## Priorite haute (MVP) +- [ ] Creer schemas Ent en francais : Objet, Categorie, Emplacement. +- [ ] Ajouter migrations initiales (Goose ou Atlas). +- [ ] CRUD API Objets/Categories/Emplacements (Gin). +- [ ] Endpoint upload multiple `POST /v1/objets/{id}/pieces_jointes`. +- [ ] Stockage pieces jointes + table PieceJointe. +- [ ] Activer WAL SQLite. +- [ ] Base frontend Nuxt + pages principales. + +## Priorite moyenne +- [ ] Swagger (Swaggo) pour la doc API. +- [ ] Taskfile pour build/test/migrate. +- [ ] Docker Compose (SQLite/Postgres). +- [ ] Composants UI : FileUploader, ObjetCard. + +## Extensions +- [ ] Analyse commandes hardware (lspci/lsusb). +- [ ] Imports CSV/JSON (Amazon/AliExpress). +- [ ] Garanties, prets, alertes. +- [ ] Tutos Markdown (EasyMDE) + endpoints. +- [ ] QR codes + backups ZIP. + +## UX/Theme +- [ ] Themes light/dark/monokai/gruvbox-dark (defaut seventies). +- [ ] Footer avec versions backend/frontend. +- [ ] Onglet settings (config.json). +- [ ] Onglet debug (logs backend/frontend). diff --git a/backend/go.mod b/backend/go.mod index a89c797..24e8541 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -2,4 +2,8 @@ module gitea.maison43.duckdns.org/gilles/matosbox go 1.23 -require github.com/gin-gonic/gin v1.10.0 +require ( + entgo.io/ent v0.13.1 + github.com/gin-gonic/gin v1.10.0 + github.com/google/uuid v1.6.0 +) diff --git a/backend/internal/data/ent/schema/categorie.go b/backend/internal/data/ent/schema/categorie.go new file mode 100644 index 0000000..b38671f --- /dev/null +++ b/backend/internal/data/ent/schema/categorie.go @@ -0,0 +1,56 @@ +package schema + +import ( + "time" + + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "github.com/google/uuid" +) + +// Categorie represente un noeud de l'arbre de categories. +type Categorie struct { + ent.Schema +} + +// Fields de l'entite Categorie. +func (Categorie) Fields() []ent.Field { + return []ent.Field{ + field.UUID("id", uuid.UUID{}). + Default(uuid.New). + Comment("Identifiant unique de la categorie"), + field.String("nom"). + NotEmpty(). + Comment("Nom de la categorie"), + field.UUID("parent_id", uuid.UUID{}). + Optional(). + Nillable(). + Comment("Identifiant du parent"), + field.String("slug"). + Optional(). + Nillable(). + Comment("Slug URL-friendly"), + field.String("icone"). + Optional(). + Nillable(). + Comment("Nom ou code d'icone"), + field.Time("created_at"). + Default(time.Now). + Comment("Date de creation"), + field.Time("updated_at"). + Default(time.Now). + UpdateDefault(time.Now). + Comment("Date de derniere mise a jour"), + } +} + +// Edges de l'entite Categorie. +func (Categorie) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("enfants", Categorie.Type). + From("parent"). + Unique(). + Field("parent_id"), + } +} diff --git a/backend/internal/data/ent/schema/emplacement.go b/backend/internal/data/ent/schema/emplacement.go new file mode 100644 index 0000000..50c740c --- /dev/null +++ b/backend/internal/data/ent/schema/emplacement.go @@ -0,0 +1,68 @@ +package schema + +import ( + "time" + + "entgo.io/ent" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" + "github.com/google/uuid" +) + +// Emplacement represente un noeud de l'arbre des emplacements. +type Emplacement struct { + ent.Schema +} + +// Fields de l'entite Emplacement. +func (Emplacement) Fields() []ent.Field { + return []ent.Field{ + field.UUID("id", uuid.UUID{}). + Default(uuid.New). + Comment("Identifiant unique de l'emplacement"), + field.String("nom"). + NotEmpty(). + Comment("Nom de l'emplacement"), + field.UUID("parent_id", uuid.UUID{}). + Optional(). + Nillable(). + Comment("Identifiant du parent"), + field.String("slug"). + Optional(). + Nillable(). + Comment("Slug URL-friendly"), + field.String("piece"). + Optional(). + Nillable(). + Comment("Piece associee"), + field.String("meuble"). + Optional(). + Nillable(). + Comment("Meuble associe"), + field.String("numero_boite"). + Optional(). + Nillable(). + Comment("Numero de boite"), + field.String("icone"). + Optional(). + Nillable(). + Comment("Nom ou code d'icone"), + field.Time("created_at"). + Default(time.Now). + Comment("Date de creation"), + field.Time("updated_at"). + Default(time.Now). + UpdateDefault(time.Now). + Comment("Date de derniere mise a jour"), + } +} + +// Edges de l'entite Emplacement. +func (Emplacement) Edges() []ent.Edge { + return []ent.Edge{ + edge.To("enfants", Emplacement.Type). + From("parent"). + Unique(). + Field("parent_id"), + } +} diff --git a/backend/internal/data/ent/schema/objet.go b/backend/internal/data/ent/schema/objet.go new file mode 100644 index 0000000..3610f3d --- /dev/null +++ b/backend/internal/data/ent/schema/objet.go @@ -0,0 +1,77 @@ +package schema + +import ( + "time" + + "entgo.io/ent" + "entgo.io/ent/schema/field" + "github.com/google/uuid" +) + +// Objet represente un element d'inventaire. +type Objet struct { + ent.Schema +} + +// Fields de l'entite Objet. +func (Objet) Fields() []ent.Field { + return []ent.Field{ + field.UUID("id", uuid.UUID{}). + Default(uuid.New). + Comment("Identifiant unique de l'objet"), + field.String("nom"). + NotEmpty(). + Comment("Nom de l'objet"), + field.String("description"). + Optional(). + Nillable(). + Comment("Description libre"), + field.Int("quantite"). + Default(0). + Comment("Quantite en stock"), + field.Float("prix_achat"). + Optional(). + Nillable(). + Comment("Prix d'achat"), + field.Time("date_achat"). + Optional(). + Nillable(). + Comment("Date d'achat"), + field.String("boutique"). + Optional(). + Nillable(). + Comment("Boutique ou fournisseur"), + field.String("numero_serie"). + Optional(). + Nillable(). + Comment("Numero de serie"), + field.String("numero_modele"). + Optional(). + Nillable(). + Comment("Numero de modele"), + field.String("fabricant"). + Optional(). + Nillable(). + Comment("Fabricant"), + field.Enum("statut"). + Values("en_stock", "pret", "hors_service", "archive"). + Default("en_stock"). + Comment("Statut de l'objet"), + field.JSON("caracteristiques", map[string]any{}). + Optional(). + Nillable(). + Comment("Caracteristiques personnalisees"), + field.Time("created_at"). + Default(time.Now). + Comment("Date de creation"), + field.Time("updated_at"). + Default(time.Now). + UpdateDefault(time.Now). + Comment("Date de derniere mise a jour"), + } +} + +// Edges de l'entite Objet. +func (Objet) Edges() []ent.Edge { + return nil +} diff --git a/doc_dev/05_analyse_detaillee.md b/doc_dev/05_analyse_detaillee.md new file mode 100644 index 0000000..7def764 --- /dev/null +++ b/doc_dev/05_analyse_detaillee.md @@ -0,0 +1,80 @@ +# Analyse detaillee des consignes + +## Objectif du projet +MatosBox est une application self-hosted d'inventaire de materiel (electronique, informatique, outillage, cuisine). L'app vise ~5000 objets, avec un focus sur simplicite, portabilite et extensibilite. + +## Langue et conventions +- UI, messages et commentaires de code en francais. +- Noms de tables et base en francais. +- Timezone cible : Europe/Paris. + +## Structure projet (mono-repo) +- `backend/` : application Go (Gin + Ent) +- `frontend/` : Nuxt 3 / Vue 3 +- `data/` : DB + pieces jointes + backups +- `docs/` : documentation Vitepress +- `migrations/` : scripts Goose/Atlas +- fichiers racine : `.gitlab-ci.yml`, `Taskfile.yml`, `docker-compose.yml`, `README.md`, `LICENSE` + +## Outils de developpement +Backend +- Go 1.23+ +- Gin (router HTTP) +- Ent (ORM + schema) +- Migrations : Goose ou Atlas + +Frontend +- Vue 3 + Nuxt.js (SSR/PWA) +- Tailwind CSS + shadcn-vue +- pnpm + +Infra / DevOps +- Docker + Docker Compose +- GitLab CI +- Vitepress (docs) +- Weblate (i18n) +- Swaggo (Swagger) + +## Backend - attentes clefs +- API REST versionnee `/v1`. +- CRUD Objets/Categories/Emplacements. +- Upload multiple : `POST /v1/objets/{id}/pieces_jointes`. +- Gestion pieces jointes (images, PDF, Markdown). +- Services annexes : QR, scan hardware (lsusb/lspci) dans une sandbox. +- Auth JWT (securite). + +## Frontend - attentes clefs +- Pages principales : `/objets`, `/objets/[id]`, `/emplacements`. +- Composants : `ObjetCard`, `FileUploader`, `MarkdownEditor`, `ThemeToggle`. +- Modals pour ajout rapide, upload, analyse commande. +- Themes : light, dark, monokai, gruvbox-dark (default style seventies). +- Footer : version backend + frontend. +- Onglets : settings (config.json), debug (logs). + +## Pieces jointes +- Multi-upload d'images/PDF/MD. +- Thumbnails + image principale. +- Stockage disque (ex: `data/pieces_jointes/`). +- Association via table `PieceJointe`. + +## Exigences BDD +- SQLite par defaut, Postgres optionnel. +- Tables en francais. +- Arbres recursifs pour `Categorie` et `Emplacement`. +- Champs customs via `ChampPersonnalise`. + +## Tests +- Go test (unitaires backend). +- Vitest (frontend). +- Cypress (E2E). +- Tests specifiques sur parsing lspci/lsusb et imports CSV. + +## Contraintes Git +- Commit et push apres chaque etape clef. +- Token Gitea dans `doc_dev/.env`. + +## Risques / points sensibles +- Conception Ent en francais + relations. +- Migration SQLite -> Postgres. +- Upload multi-fichiers et securite MIME. +- Limites d'upload (50MB/fichier). diff --git a/doc_dev/06_etape2_schemas.md b/doc_dev/06_etape2_schemas.md new file mode 100644 index 0000000..15be0eb --- /dev/null +++ b/doc_dev/06_etape2_schemas.md @@ -0,0 +1,19 @@ +# Etape 2 - Schemas Ent (realise) + +## Objectif +Mettre en place les schemas Ent en francais pour : Objet, Categorie, Emplacement. + +## Fichiers ajoutes +- `backend/internal/data/ent/schema/objet.go` +- `backend/internal/data/ent/schema/categorie.go` +- `backend/internal/data/ent/schema/emplacement.go` + +## Points cles +- Identifiants UUID par defaut. +- Champs principaux conformes aux consignes. +- Arbres recursifs pour Categorie et Emplacement via `parent_id`. +- Timestamps `created_at` et `updated_at`. + +## A faire ensuite +- Generer le code Ent + migrations. +- Ajouter les schemas manquants (PieceJointe, LienObjetEmplacement, etc.). diff --git a/doc_dev/structure_bdd.md b/doc_dev/structure_bdd.md new file mode 100644 index 0000000..f3a67bf --- /dev/null +++ b/doc_dev/structure_bdd.md @@ -0,0 +1,124 @@ +# Structure BDD - MatosBox (reference) + +## Base +- SQLite par defaut : `matosbox.db` +- Postgres optionnel : base `matosbox` + +## Tables principales + +### Objet +Champs : +- id +- nom +- description +- quantite +- prix_achat +- date_achat +- boutique +- numero_serie +- numero_modele +- fabricant +- statut (enum: en_stock, pret, hors_service, archive) +- caracteristiques (JSONB) + +Relations : +- 1..n `PieceJointe` +- 1..n `ChampPersonnalise` +- n..n `Emplacement` via `LienObjetEmplacement` + +### Categorie +Champs : +- id +- nom +- parent_id +- slug +- icone + +Relations : +- auto-reference (parent/enfant) + +### Emplacement +Champs : +- id +- nom +- parent_id +- slug +- piece +- meuble +- numero_boite +- icone + +Relations : +- auto-reference (parent/enfant) + +### LienObjetEmplacement +Champs : +- id +- objet_id +- emplacement_id +- type (enum: stocke, utilise_dans) + +### ChampPersonnalise +Champs : +- id +- objet_id +- nom_champ +- type_champ (string/int/bool/date) +- valeur +- unite + +### PieceJointe +Champs : +- id +- objet_id +- nom_fichier +- chemin +- type_mime +- est_principale +- categorie (image/pdf_notice/markdown_tuto) + +### HistoriqueAchat +Champs : +- id +- objet_id +- boutique +- numero_commande +- prix +- date +- quantite + +### Pret +Champs : +- id +- objet_id +- a_utilisateur +- date_debut +- date_fin +- notes + +### MouvementStock +Champs : +- id +- objet_id +- delta_quantite +- raison +- date + +### Garantie +Champs : +- id +- objet_id +- fournisseur +- duree_mois +- date_debut +- preuve (piece_jointe_id) + +## Relations notables +- Arbres recursifs pour `Categorie` et `Emplacement`. +- Historique achats, prets et mouvements relies a `Objet`. +- Pieces jointes liees a `Objet`. + +## Notes migration +- Migrations via Goose/Atlas. +- SQLite WAL a activer. +- Export/Import via CSV/JSON ou pgloader pour Postgres.