7609d35287
- Laravel 12 sur PHP 8.5, Breeze (Blade/Tailwind/Alpine.js) - Docker Compose dev (PostgreSQL 18 + Redis) et prod (stack complète + nginx) - Migrations et models : lieux, sections, dépôts, source_types/fields, sources, relevés - Colonne JSONB data sur releves avec colonnes générées indexées (nom, prenom, date_evenement) - Index GIN pour la recherche fulltext - Enums : UserRole, SourceStatus (avec transitions), CalendarType, FieldType - RoleMiddleware (alias `role`) + helpers isAdmin/isSectionManager sur User - CRUD Lieux (arbre hiérarchique, calcul nom_long en cascade) - CRUD admin : Sections (+ gestion membres), Dépôts, Types de sources (+ champs dynamiques, drag & drop) - CRUD Sources : visibilité filtrée par rôle, assignation membres, workflow de statut Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
159 lines
6.9 KiB
Markdown
159 lines
6.9 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
**MesRelevés** — Application web PHP/PostgreSQL pour une association de généalogie. Elle permet la saisie systématique de relevés d'actes (naissance, mariage, décès, etc.), la recherche dans ces relevés, et l'export au format GEDCOM.
|
|
|
|
## Tech Stack
|
|
|
|
- **Backend** : PHP 8.2+, framework **Laravel 11**
|
|
- **Base de données** : **PostgreSQL 16** (JSONB pour les champs variables des relevés, full-text search natif)
|
|
- **Frontend** : Blade templates + **Alpine.js** (interactivité légère) + **Tailwind CSS**
|
|
- **Auth** : Laravel Breeze (sessions, middleware de rôles custom)
|
|
- **Cache** : Redis (Laravel Cache) pour les listes de lieux et requêtes fréquentes
|
|
|
|
## Development Commands
|
|
|
|
```bash
|
|
# Installation
|
|
composer install
|
|
npm install && npm run build
|
|
cp .env.example .env && php artisan key:generate
|
|
|
|
# Base de données
|
|
php artisan migrate
|
|
php artisan migrate:fresh --seed # reset + données de test
|
|
|
|
# Serveur de développement
|
|
php artisan serve # http://localhost:8000
|
|
npm run dev # Vite en watch (CSS/JS)
|
|
|
|
# Tests
|
|
php artisan test # tous les tests
|
|
php artisan test --filter=NomTest # un test précis
|
|
php artisan test --testsuite=Feature
|
|
|
|
# Qualité de code
|
|
./vendor/bin/pint # formatage PHP (Laravel Pint)
|
|
./vendor/bin/phpstan analyse # analyse statique
|
|
```
|
|
|
|
## Architecture
|
|
|
|
```
|
|
app/
|
|
Models/ # Eloquent models
|
|
Http/
|
|
Controllers/ # un controller par entité métier
|
|
Middleware/ # RoleMiddleware (admin, section_manager, member)
|
|
Requests/ # Form requests avec validation
|
|
Policies/ # Autorisation par modèle (Laravel Gates/Policies)
|
|
Services/ # Logique métier complexe (ex: GedcomExportService, DateConversionService)
|
|
Enums/ # SourceStatus, UserRole, CalendarType
|
|
database/
|
|
migrations/
|
|
seeders/
|
|
resources/
|
|
views/
|
|
layouts/
|
|
sections/
|
|
sources/
|
|
releves/ # formulaires dynamiques pilotés par source_type
|
|
lieux/
|
|
admin/
|
|
routes/
|
|
web.php # routes principales
|
|
admin.php # routes admin (prefix /admin, middleware admin)
|
|
```
|
|
|
|
## Domain Model (entités clés)
|
|
|
|
### Utilisateurs et rôles
|
|
- `users` : id, name, email, role (`admin` | `section_manager` | `member`)
|
|
- `section_user` (pivot) : user_id, section_id, role_in_section
|
|
- Un utilisateur peut appartenir à plusieurs sections locales.
|
|
|
|
### Sections locales
|
|
- Champs : nom, lieu_id (FK), adresse, email_contact, url
|
|
|
|
### Dépôts d'archives
|
|
- Champs : nom, description, adresse_postale, url
|
|
|
|
### Lieux
|
|
- Champs : nom, code, lieu_parent_id (FK self-référentiel), nom_long (calculé), latitude, longitude, note
|
|
- `nom_long` est généré automatiquement en concaténant les noms des ancêtres (ex. "Bordeaux, Gironde, France").
|
|
|
|
### Types de sources (SourceType)
|
|
- Définissent les **champs dynamiques** du formulaire de saisie.
|
|
- Stocké comme : `source_types` (id, nom, description) + `source_type_fields` (id, source_type_id, name, label, type, required, order, options JSON)
|
|
- Types de champ possibles : `text`, `date`, `boolean`, `select`, `textarea`, `number`
|
|
- L'ajout/modification d'un type de source ne doit pas casser les relevés existants (les champs JSONB contiennent toujours l'ancienne structure).
|
|
|
|
### Sources
|
|
- Champs : nom, description, source_type_id, depot_id, cote, auteur, status
|
|
- Status (enum) : `a_faire` → `en_cours` → `a_valider` → `termine`
|
|
- Une source est créée uniquement par admin ou responsable de section, avec status initial `a_faire`.
|
|
- Table pivot `source_user` : assignation des membres à une source.
|
|
- Visibilité des relevés : status `termine` → visible par tous les membres ; sinon → visible uniquement par admin et membres de section assignés.
|
|
|
|
### Relevés (`releves`)
|
|
- **Schéma** : `id`, `source_id`, `data` (JSONB — champs variables selon le source_type), `created_by`, `created_at`, `updated_by`, `updated_at`
|
|
- Le JSONB est la solution retenue pour la flexibilité et la performance (pas de colonnes dynamiques, pas d'ALTER TABLE).
|
|
- Les colonnes les plus recherchées (nom, prénom, date) sont extraites dans des colonnes indexées générées : `ALTER TABLE releves ADD COLUMN nom TEXT GENERATED ALWAYS AS (data->>'nom') STORED;` + index GIN sur `data` pour la recherche fulltext.
|
|
- Pagination obligatoire (25 par page minimum), jamais de `SELECT *` sans `LIMIT`.
|
|
|
|
### Dates
|
|
- Chaque date stocke : `{ "valeur": "1792-09-22", "calendrier": "republicain" }`
|
|
- Calendriers supportés : `gregorien`, `julien`, `republicain`
|
|
- Service `DateConversionService` gère la conversion vers/depuis le calendrier républicain (An I = 22 sept 1792).
|
|
|
|
## Règles d'autorisation
|
|
|
|
| Action | Admin | Resp. Section | Membre assigné | Membre | Visiteur |
|
|
|---|---|---|---|---|---|
|
|
| Créer une source | ✓ | ✓ (sa section) | | | |
|
|
| Assigner un membre à une source | ✓ | ✓ (sa section) | | | |
|
|
| Saisir/modifier un relevé | ✓ | ✓ | ✓ | | |
|
|
| Voir relevés (status `termine`) | ✓ | ✓ | ✓ | ✓ | |
|
|
| Voir relevés (autres status) | ✓ | ✓ (sa section) | ✓ (assigné) | | |
|
|
| Passer status → `a_valider` | ✓ | ✓ | ✓ (assigné) | | |
|
|
| Passer status → `termine` | ✓ | ✓ (sa section) | | | |
|
|
| Gérer utilisateurs / sections | ✓ | | | | |
|
|
|
|
## Workflow de statut d'une source
|
|
|
|
```
|
|
a_faire → en_cours → a_valider → termine
|
|
↑____________| (rejet possible par admin/resp.)
|
|
```
|
|
Lors du passage en `a_valider`, une notification (mail + notification interne) est envoyée à l'admin et au(x) responsable(s) de la section.
|
|
|
|
## Performance
|
|
|
|
- Index GIN sur `releves.data` (recherche JSONB).
|
|
- Colonnes générées stockées + index B-tree pour les champs les plus filtrés (nom, date_evenement).
|
|
- Eager loading systématique (`with()`) pour éviter les requêtes N+1.
|
|
- Cache Redis (TTL 1h) sur la liste des lieux (arbre hiérarchique).
|
|
- Pagination curseur (keyset) plutôt qu'offset pour les listes de relevés volumineuses.
|
|
|
|
## Export GEDCOM
|
|
|
|
- `GedcomExportService` : génère un fichier `.ged` à partir d'une source ou d'une sélection de relevés.
|
|
- Format GEDCOM 5.5.1.
|
|
- Conversion des dates : toujours en grégorien dans le GEDCOM (les calendriers julien/républicain sont convertis).
|
|
|
|
## Étapes de construction (ordre suggéré)
|
|
|
|
1. Scaffold Laravel + config PostgreSQL + auth Breeze + middleware rôles
|
|
2. Migrations et modèles : `lieux`, `sections`, `users`, `depots`, `source_types`, `source_type_fields`, `sources`, `source_user`, `releves`
|
|
3. CRUD Lieux (avec arbre hiérarchique et calcul `nom_long`)
|
|
4. CRUD Sections, Dépôts, Types de sources (admin)
|
|
5. CRUD Sources + assignation de membres
|
|
6. Formulaire de saisie dynamique des relevés (piloté par `source_type_fields`)
|
|
7. Workflow de statut + notifications
|
|
8. Recherche dans les relevés (fulltext PostgreSQL)
|
|
9. Export GEDCOM
|
|
10. Interface admin (gestion utilisateurs, statistiques)
|