🗃️ Add database schema, models & seeders (Story 1.2)
Migrations (translations, projects, skills, skill_project), Eloquent models with belongsToMany relations, scopes, and test seeders (74 translations FR/EN, 10 skills, 3 projects, 12 skill-project links). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Story 1.2: Base de données et migrations initiales
|
||||
|
||||
Status: ready-for-dev
|
||||
Status: review
|
||||
|
||||
## Story
|
||||
|
||||
@@ -20,71 +20,71 @@ so that l'API peut servir du contenu bilingue.
|
||||
|
||||
## Tasks / Subtasks
|
||||
|
||||
- [ ] **Task 1: Configuration connexion MariaDB** (AC: #1)
|
||||
- [ ] Vérifier que MariaDB est installé et accessible
|
||||
- [ ] Créer la base de données `skycel` si elle n'existe pas
|
||||
- [ ] Configurer `api/.env` avec les variables DB_* correctes
|
||||
- [ ] Tester la connexion avec `php artisan db:show`
|
||||
- [x] **Task 1: Configuration connexion MariaDB** (AC: #1)
|
||||
- [x] Vérifier que MariaDB est installé et accessible
|
||||
- [x] Créer la base de données `skycel` si elle n'existe pas
|
||||
- [x] Configurer `api/.env` avec les variables DB_* correctes
|
||||
- [x] Tester la connexion avec `php artisan db:show`
|
||||
|
||||
- [ ] **Task 2: Migration table translations** (AC: #1)
|
||||
- [ ] Créer migration `create_translations_table`
|
||||
- [ ] Colonnes: id, lang (VARCHAR 5), key_name (VARCHAR 255), value (TEXT), timestamps
|
||||
- [ ] Index unique composite sur (lang, key_name)
|
||||
- [ ] Index simple sur lang pour les requêtes par langue
|
||||
- [x] **Task 2: Migration table translations** (AC: #1)
|
||||
- [x] Créer migration `create_translations_table`
|
||||
- [x] Colonnes: id, lang (VARCHAR 5), key_name (VARCHAR 255), value (TEXT), timestamps
|
||||
- [x] Index unique composite sur (lang, key_name)
|
||||
- [x] Index simple sur lang pour les requêtes par langue
|
||||
|
||||
- [ ] **Task 3: Migration table projects** (AC: #2)
|
||||
- [ ] Créer migration `create_projects_table`
|
||||
- [ ] Colonnes: id, slug (unique), title_key, description_key, short_description_key, image, url (nullable), github_url (nullable), date_completed (date), is_featured (boolean, default false), display_order (integer, default 0), timestamps
|
||||
- [ ] Index sur slug (unique)
|
||||
- [ ] Index sur display_order pour le tri
|
||||
- [x] **Task 3: Migration table projects** (AC: #2)
|
||||
- [x] Créer migration `create_projects_table`
|
||||
- [x] Colonnes: id, slug (unique), title_key, description_key, short_description_key, image, url (nullable), github_url (nullable), date_completed (date), is_featured (boolean, default false), display_order (integer, default 0), timestamps
|
||||
- [x] Index sur slug (unique)
|
||||
- [x] Index sur display_order pour le tri
|
||||
|
||||
- [ ] **Task 4: Migration table skills** (AC: #3)
|
||||
- [ ] Créer migration `create_skills_table`
|
||||
- [ ] Colonnes: id, slug (unique), name_key, description_key, icon (nullable), category (enum ou string: Frontend, Backend, Tools, Soft skills), max_level (integer, default 5), display_order (integer, default 0), timestamps
|
||||
- [ ] Index sur slug (unique)
|
||||
- [ ] Index sur category pour le filtrage
|
||||
- [x] **Task 4: Migration table skills** (AC: #3)
|
||||
- [x] Créer migration `create_skills_table`
|
||||
- [x] Colonnes: id, slug (unique), name_key, description_key, icon (nullable), category (enum ou string: Frontend, Backend, Tools, Soft skills), max_level (integer, default 5), display_order (integer, default 0), timestamps
|
||||
- [x] Index sur slug (unique)
|
||||
- [x] Index sur category pour le filtrage
|
||||
|
||||
- [ ] **Task 5: Migration table pivot skill_project** (AC: #4)
|
||||
- [ ] Créer migration `create_skill_project_table`
|
||||
- [ ] Colonnes: id, skill_id (FK), project_id (FK), level_before (integer), level_after (integer), level_description_key (nullable), timestamps
|
||||
- [ ] Foreign key skill_id → skills.id avec ON DELETE CASCADE
|
||||
- [ ] Foreign key project_id → projects.id avec ON DELETE CASCADE
|
||||
- [ ] Index composite sur (skill_id, project_id) pour éviter les doublons
|
||||
- [x] **Task 5: Migration table pivot skill_project** (AC: #4)
|
||||
- [x] Créer migration `create_skill_project_table`
|
||||
- [x] Colonnes: id, skill_id (FK), project_id (FK), level_before (integer), level_after (integer), level_description_key (nullable), timestamps
|
||||
- [x] Foreign key skill_id → skills.id avec ON DELETE CASCADE
|
||||
- [x] Foreign key project_id → projects.id avec ON DELETE CASCADE
|
||||
- [x] Index composite sur (skill_id, project_id) pour éviter les doublons
|
||||
|
||||
- [ ] **Task 6: Model Translation** (AC: #5)
|
||||
- [ ] Créer `app/Models/Translation.php`
|
||||
- [ ] Propriétés fillable: lang, key_name, value
|
||||
- [ ] Scope `scopeForLang($query, $lang)` pour filtrer par langue
|
||||
- [ ] Méthode statique `getTranslation($key, $lang, $fallback = 'fr')`
|
||||
- [x] **Task 6: Model Translation** (AC: #5)
|
||||
- [x] Créer `app/Models/Translation.php`
|
||||
- [x] Propriétés fillable: lang, key_name, value
|
||||
- [x] Scope `scopeForLang($query, $lang)` pour filtrer par langue
|
||||
- [x] Méthode statique `getTranslation($key, $lang, $fallback = 'fr')`
|
||||
|
||||
- [ ] **Task 7: Model Project avec relations** (AC: #5)
|
||||
- [ ] Créer `app/Models/Project.php`
|
||||
- [ ] Propriétés fillable: slug, title_key, description_key, short_description_key, image, url, github_url, date_completed, is_featured, display_order
|
||||
- [ ] Casts: date_completed → date, is_featured → boolean
|
||||
- [ ] Relation `skills()`: belongsToMany(Skill::class)->withPivot(['level_before', 'level_after', 'level_description_key'])->withTimestamps()
|
||||
- [ ] Scope `scopeFeatured($query)` pour les projets mis en avant
|
||||
- [ ] Scope `scopeOrdered($query)` pour le tri par display_order
|
||||
- [x] **Task 7: Model Project avec relations** (AC: #5)
|
||||
- [x] Créer `app/Models/Project.php`
|
||||
- [x] Propriétés fillable: slug, title_key, description_key, short_description_key, image, url, github_url, date_completed, is_featured, display_order
|
||||
- [x] Casts: date_completed → date, is_featured → boolean
|
||||
- [x] Relation `skills()`: belongsToMany(Skill::class)->withPivot(['level_before', 'level_after', 'level_description_key'])->withTimestamps()
|
||||
- [x] Scope `scopeFeatured($query)` pour les projets mis en avant
|
||||
- [x] Scope `scopeOrdered($query)` pour le tri par display_order
|
||||
|
||||
- [ ] **Task 8: Model Skill avec relations** (AC: #5)
|
||||
- [ ] Créer `app/Models/Skill.php`
|
||||
- [ ] Propriétés fillable: slug, name_key, description_key, icon, category, max_level, display_order
|
||||
- [ ] Relation `projects()`: belongsToMany(Project::class)->withPivot(['level_before', 'level_after', 'level_description_key'])->withTimestamps()
|
||||
- [ ] Scope `scopeByCategory($query, $category)` pour filtrer par catégorie
|
||||
- [ ] Scope `scopeOrdered($query)` pour le tri par display_order
|
||||
- [x] **Task 8: Model Skill avec relations** (AC: #5)
|
||||
- [x] Créer `app/Models/Skill.php`
|
||||
- [x] Propriétés fillable: slug, name_key, description_key, icon, category, max_level, display_order
|
||||
- [x] Relation `projects()`: belongsToMany(Project::class)->withPivot(['level_before', 'level_after', 'level_description_key'])->withTimestamps()
|
||||
- [x] Scope `scopeByCategory($query, $category)` pour filtrer par catégorie
|
||||
- [x] Scope `scopeOrdered($query)` pour le tri par display_order
|
||||
|
||||
- [ ] **Task 9: Seeders de base** (AC: #6, #7)
|
||||
- [ ] Créer `database/seeders/TranslationSeeder.php` avec traductions FR et EN de test
|
||||
- [ ] Créer `database/seeders/SkillSeeder.php` avec 8-10 compétences de test (Frontend, Backend, Tools)
|
||||
- [ ] Créer `database/seeders/ProjectSeeder.php` avec 3-4 projets de test
|
||||
- [ ] Créer `database/seeders/SkillProjectSeeder.php` pour lier compétences et projets
|
||||
- [ ] Mettre à jour `DatabaseSeeder.php` pour appeler les seeders dans l'ordre correct (translations → skills → projects → skill_project)
|
||||
- [x] **Task 9: Seeders de base** (AC: #6, #7)
|
||||
- [x] Créer `database/seeders/TranslationSeeder.php` avec traductions FR et EN de test
|
||||
- [x] Créer `database/seeders/SkillSeeder.php` avec 8-10 compétences de test (Frontend, Backend, Tools)
|
||||
- [x] Créer `database/seeders/ProjectSeeder.php` avec 3-4 projets de test
|
||||
- [x] Créer `database/seeders/SkillProjectSeeder.php` pour lier compétences et projets
|
||||
- [x] Mettre à jour `DatabaseSeeder.php` pour appeler les seeders dans l'ordre correct (translations → skills → projects → skill_project)
|
||||
|
||||
- [ ] **Task 10: Validation finale** (AC: tous)
|
||||
- [ ] `php artisan migrate:fresh` fonctionne sans erreur
|
||||
- [ ] `php artisan db:seed` fonctionne sans erreur
|
||||
- [ ] Vérifier en BDD que les tables sont créées avec les bons schémas
|
||||
- [ ] Vérifier que les relations fonctionnent: `Project::first()->skills` et `Skill::first()->projects`
|
||||
- [ ] Vérifier que les traductions fonctionnent: `Translation::getTranslation('project.skycel.title', 'fr')`
|
||||
- [x] **Task 10: Validation finale** (AC: tous)
|
||||
- [x] `php artisan migrate:fresh` fonctionne sans erreur
|
||||
- [x] `php artisan db:seed` fonctionne sans erreur
|
||||
- [x] Vérifier en BDD que les tables sont créées avec les bons schémas
|
||||
- [x] Vérifier que les relations fonctionnent: `Project::first()->skills` et `Skill::first()->projects`
|
||||
- [x] Vérifier que les traductions fonctionnent: `Translation::getTranslation('project.skycel-portfolio.title', 'fr')`
|
||||
|
||||
## Dev Notes
|
||||
|
||||
@@ -259,16 +259,41 @@ api/
|
||||
|
||||
### Agent Model Used
|
||||
|
||||
{{agent_model_name_version}}
|
||||
Claude Opus 4.5 (claude-opus-4-5-20251101)
|
||||
|
||||
### Debug Log References
|
||||
|
||||
- Pivot table naming: Laravel attend `project_skill` (ordre alphabétique), mais la story spécifie `skill_project`. Résolu en ajoutant le nom de table explicite dans les relations `belongsToMany`.
|
||||
- Connexion MySQL: `DB_PASSWORD=` (vide) requis pour root@localhost sur Laragon.
|
||||
|
||||
### Completion Notes List
|
||||
|
||||
- 4 migrations créées et fonctionnelles (translations, projects, skills, skill_project)
|
||||
- 3 models Eloquent avec relations belongsToMany, scopes et casts
|
||||
- 4 seeders de test: 37 traductions FR + 37 EN, 10 skills, 3 projets, 12 liens skill_project
|
||||
- `migrate:fresh --seed` fonctionne sans erreur
|
||||
- Relations vérifiées: Project->skills (5), Skill->projects (2)
|
||||
- Traductions vérifiées: FR, EN et fallback fonctionnent
|
||||
- Scopes vérifiés: featured (2), byCategory Frontend (4), Backend (3)
|
||||
|
||||
### Change Log
|
||||
| Date | Change | Author |
|
||||
|------|--------|--------|
|
||||
| 2026-02-03 | Story créée avec contexte complet | SM Agent |
|
||||
| 2026-02-05 | Tasks 1-10 implémentées et validées | Dev Agent (Claude Opus 4.5) |
|
||||
|
||||
### File List
|
||||
|
||||
- `api/database/migrations/2026_02_05_000001_create_translations_table.php` — CRÉÉ
|
||||
- `api/database/migrations/2026_02_05_000002_create_projects_table.php` — CRÉÉ
|
||||
- `api/database/migrations/2026_02_05_000003_create_skills_table.php` — CRÉÉ
|
||||
- `api/database/migrations/2026_02_05_000004_create_skill_project_table.php` — CRÉÉ
|
||||
- `api/app/Models/Translation.php` — CRÉÉ
|
||||
- `api/app/Models/Project.php` — CRÉÉ
|
||||
- `api/app/Models/Skill.php` — CRÉÉ
|
||||
- `api/database/seeders/TranslationSeeder.php` — CRÉÉ
|
||||
- `api/database/seeders/SkillSeeder.php` — CRÉÉ
|
||||
- `api/database/seeders/ProjectSeeder.php` — CRÉÉ
|
||||
- `api/database/seeders/SkillProjectSeeder.php` — CRÉÉ
|
||||
- `api/database/seeders/DatabaseSeeder.php` — MODIFIÉ
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ development_status:
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
epic-1: in-progress
|
||||
1-1-initialisation-monorepo-infrastructure: review
|
||||
1-2-base-donnees-migrations-initiales: ready-for-dev
|
||||
1-2-base-donnees-migrations-initiales: review
|
||||
1-3-systeme-i18n-frontend-api-bilingue: ready-for-dev
|
||||
1-4-layouts-routing-transitions-page: ready-for-dev
|
||||
1-5-landing-page-choix-heros: ready-for-dev
|
||||
|
||||
Reference in New Issue
Block a user