Files
mesreleves-php/CLAUDE.md
T
yann64 7609d35287 Initial scaffold : Laravel 12 + PostgreSQL + auth + domaine métier (étapes 1-5)
- 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>
2026-06-04 16:16:37 +02:00

6.9 KiB

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

# 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_faireen_coursa_validertermine
  • 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)