# Story 3.9: Glossaires - Endpoint CRUD Status: done ## Story En tant qu'**utilisateur Pro**, Je veux **créer et gérer des glossaires via API**, de sorte que **je puisse personnaliser les traductions avec ma terminologie**. ## Acceptance Criteria 1. **Création de glossaire**: Quand un utilisateur Pro POST sur `/api/v1/glossaries` avec `{name, terms: [{source, target}]}`, un glossaire est créé et associé à son compte. (FR58) 2. **Liste des glossaires**: GET `/api/v1/glossaries` retourne la liste des glossaires de l'utilisateur. 3. **Mise à jour**: PATCH `/api/v1/glossaries/{id}` permet de mettre à jour les termes. 4. **Suppression**: DELETE `/api/v1/glossaries/{id}` supprime un glossaire. 5. **Restriction Pro**: Les utilisateurs Free reçoivent 403 avec erreur `PRO_FEATURE_REQUIRED`. ## Tasks / Subtasks - [x] **Task 1: Créer le modèle Glossary et la migration Alembic** (AC: #1) - [x] 1.1 Créer `models/glossary.py` avec les modèles Glossary et GlossaryTerm (ajouté à database/models.py) - [x] 1.2 Générer la migration Alembic `alembic revision --autogenerate -m "add_glossaries_tables"` - [x] 1.3 Appliquer la migration `alembic upgrade head` - [x] 1.4 Vérifier les tables créées dans la DB - [x] **Task 2: Créer les schémas Pydantic** (AC: Tous) - [x] 2.1 Créer `schemas/glossary_schemas.py` avec GlossaryCreate, GlossaryUpdate, GlossaryResponse, GlossaryTermSchema - [x] 2.2 Définir les validators pour les termes (source/target non vides) - [x] 2.3 Documenter les schémas pour OpenAPI - [x] **Task 3: Créer le module glossaries** (AC: Tous) - [x] 3.1 Créer `modules/glossaries/__init__.py` (non nécessaire - routes dans routes/) - [x] 3.2 Créer `modules/glossaries/router.py` avec les endpoints CRUD (routes/glossary_routes.py) - [x] 3.3 Créer `modules/glossaries/service.py` avec la logique métier (intégré dans router) - [x] 3.4 Enregistrer le router dans `routes/api_v1_router.py` - [x] **Task 4: Implémenter les endpoints CRUD** (AC: #1-#4) - [x] 4.1 POST `/api/v1/glossaries` - Créer un glossaire - [x] 4.2 GET `/api/v1/glossaries` - Lister les glossaires de l'utilisateur - [x] 4.3 GET `/api/v1/glossaries/{id}` - Détail d'un glossaire - [x] 4.4 PATCH `/api/v1/glossaries/{id}` - Mettre à jour un glossaire - [x] 4.5 DELETE `/api/v1/glossaries/{id}` - Supprimer un glossaire - [x] **Task 5: Implémenter la restriction Pro** (AC: #5) - [x] 5.1 Ajouter la vérification `user.tier == "pro"` dans le service - [x] 5.2 Retourner 403 avec erreur `PRO_FEATURE_REQUIRED` pour les utilisateurs Free - [x] **Task 6: Tests** (AC: Tous) - [x] 6.1 Tests unitaires pour le service glossary - [x] 6.2 Tests d'intégration pour les endpoints CRUD - [x] 6.3 Test de la restriction Pro (403 pour Free) - [x] 6.4 Test de la propriété utilisateur (un user ne peut pas voir les glossaires d'un autre) - [x] **Task 7: Documentation OpenAPI** (AC: Tous) - [x] 7.1 Documenter tous les endpoints avec exemples - [x] 7.2 Documenter les codes d'erreur - [x] 7.3 Vérifier sur `/docs` que la documentation est complète ## Dev Notes ### 🏗️ Architecture - Structure du Module **Emplacement prévu** (depuis architecture.md): ``` backend/app/ ├── modules/ │ └── glossaries/ │ ├── __init__.py │ ├── router.py # /api/v1/glossaries │ ├── service.py │ └── schemas.py ├── models/ │ └── glossary.py # Nouveau fichier └── schemas/ └── glossary_schemas.py # Nouveau fichier ``` ### 📊 Modèle de Données **Tables créées**: - `glossaries` - id, user_id, name, created_at, updated_at - `glossary_terms` - id, glossary_id, source, target, created_at **Indexes créés**: - `ix_glossaries_user_id` sur `glossaries.user_id` - `ix_glossary_terms_glossary_id` sur `glossary_terms.glossary_id` ## Dev Agent Record ### Agent Model Used Claude 3.5 Sonnet (claude-3-5-sonnet) ### Debug Log References - Migration: `alembic revision --autogenerate -m "add_glossaries_tables"` - Tests: `pytest tests/test_glossaries.py -v` - 13 passed ### Completion Notes List - ✅ Modèles Glossary et GlossaryTerm ajoutés à database/models.py - ✅ Migration Alembic créée et appliquée - ✅ Schémas Pydantic créés dans schemas/glossary_schemas.py - ✅ Routes CRUD complètes dans routes/glossary_routes.py - ✅ Router enregistré dans routes/api_v1_router.py - ✅ Restriction Pro implémentée avec vérification plan.value - ✅ 13 tests passent (CRUD complet + restrictions + propriété) - ✅ Endpoints documentés avec docstrings OpenAPI ### File List - `database/models.py` - MODIFIÉ - Ajout des modèles Glossary et GlossaryTerm - `database/__init__.py` - MODIFIÉ - Export des nouveaux modèles - `schemas/glossary_schemas.py` - CRÉÉ - Schémas Pydantic - `schemas/__init__.py` - MODIFIÉ - Export des nouveaux schémas - `routes/glossary_routes.py` - CRÉÉ - Endpoints CRUD glossaries - `routes/api_v1_router.py` - MODIFIÉ - Enregistrement du router glossary - `alembic/versions/cb71a958ad92_add_glossaries_tables.py` - CRÉÉ - Migration DB - `tests/test_glossaries.py` - CRÉÉ - 13 tests pour glossaires ## Change Log - 2026-02-22: Story créée avec contexte complet - 2026-02-22: Implémentation complète - modèles, schémas, routes, tests - 2026-02-22: Tous les tests passent (13/13) ## Senior Developer Review (AI) ### Issues Found & Fixed 1. **ProUser class duplication** - Extracted to shared `routes/deps.py` with `require_auth` and `require_pro_user` dependencies 2. **Schemas not used** - Routes had inline Pydantic models; refactored to use imported schemas from `schemas/glossary_schemas.py` 3. **N+1 query issue** - Added `joinedload(Glossary.terms)` to list endpoint 4. **Missing max terms validation** - Added `MAX_TERMS_PER_GLOSSARY = 500` constant 5. **No pagination** - Added `page` and `per_page` query parameters to list endpoint 6. **No error handling** - Added try/except blocks with logging for all database operations 7. **Logger unused** - Added logging for create/update/delete operations 8. **Datetime serialization** - Fixed `model_dump(mode="json")` for JSON serialization in list endpoint ### Files Modified in Review - `routes/deps.py` - NEW - Shared auth dependencies - `routes/glossary_routes.py` - REFACTORED - All fixes applied ### Final Test Results ``` 13 passed, 154 warnings in 5.60s ```