Étapes 6-9 + types de lieux + picker + filtres

- Étape 6 : formulaire de saisie dynamique des relevés (piloté par source_type_fields, calendriers grégorien/julien/républicain)
- Étape 7 : workflow de statut des sources + notifications mail+DB (SourceAValider, SourceRejetee)
- Étape 8 : recherche fulltext PostgreSQL avec filtres type/lieu/années et CTE récursive pour les subdivisions de lieux
- Étape 9 : export GEDCOM 5.5.1 (GedcomExportService + DateConversionService)
- Types de lieux : CRUD admin (LieuTypeController) avec champ ordre
- Composant lieu-picker : modale Alpine.js avec recherche AJAX + debounce
- Filtres sources : statut, type, lieu (CTE récursive), période annee_debut/annee_fin
- Filtres lieux : type, texte, lieu parent avec descendants (CTE récursive)
- Migration : lieu_id + annee_debut + annee_fin sur sources

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 17:17:53 +02:00
parent 7609d35287
commit d064f8d28e
54 changed files with 2861 additions and 116 deletions
+150 -10
View File
@@ -2,24 +2,164 @@
namespace Database\Seeders;
use App\Enums\FieldType;
use App\Enums\SourceStatus;
use App\Enums\UserRole;
use App\Models\Depot;
use App\Models\Lieu;
use App\Models\LieuType;
use App\Models\Releve;
use App\Models\Section;
use App\Models\Source;
use App\Models\SourceType;
use App\Models\SourceTypeField;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
class DatabaseSeeder extends Seeder
{
use WithoutModelEvents;
/**
* Seed the application's database.
*/
public function run(): void
{
// User::factory(10)->create();
// ── Utilisateurs ────────────────────────────────────────────────────
$admin = User::create([
'name' => 'Administrateur',
'email' => 'admin@mesreleves.local',
'password' => Hash::make('password'),
'role' => UserRole::Admin,
]);
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
$responsable = User::create([
'name' => 'Responsable Bordeaux',
'email' => 'responsable@mesreleves.local',
'password' => Hash::make('password'),
'role' => UserRole::SectionManager,
]);
$membre = User::create([
'name' => 'Marie Durand',
'email' => 'membre@mesreleves.local',
'password' => Hash::make('password'),
'role' => UserRole::Member,
]);
// ── Types de lieux ──────────────────────────────────────────────────
$typePays = LieuType::create(['nom' => 'Pays', 'ordre' => 0]);
$typeRegion = LieuType::create(['nom' => 'Région', 'ordre' => 10]);
$typeDept = LieuType::create(['nom' => 'Département', 'ordre' => 20]);
$typeVille = LieuType::create(['nom' => 'Ville', 'ordre' => 30]);
$typeCommune = LieuType::create(['nom' => 'Commune', 'ordre' => 35]);
$typeParoisse = LieuType::create(['nom' => 'Paroisse', 'ordre' => 40]);
$typeLieuDit = LieuType::create(['nom' => 'Lieu-dit', 'ordre' => 50]);
// ── Lieux ───────────────────────────────────────────────────────────
$france = Lieu::create(['nom' => 'France', 'lieu_type_id' => $typePays->id]);
$gironde = Lieu::create(['nom' => 'Gironde', 'code' => '33', 'lieu_type_id' => $typeDept->id, 'lieu_parent_id' => $france->id]);
$bordeaux = Lieu::create(['nom' => 'Bordeaux', 'code' => '33063', 'lieu_type_id' => $typeVille->id, 'lieu_parent_id' => $gironde->id,
'latitude' => 44.8378, 'longitude' => -0.5792]);
$begles = Lieu::create(['nom' => 'Bègles', 'code' => '33032', 'lieu_type_id' => $typeCommune->id, 'lieu_parent_id' => $gironde->id]);
// ── Section ─────────────────────────────────────────────────────────
$section = Section::create([
'nom' => 'Section Gironde',
'lieu_id' => $bordeaux->id,
'email_contact' => 'gironde@cgl.fr',
]);
$section->membres()->attach($responsable->id, ['role_in_section' => 'section_manager']);
$section->membres()->attach($membre->id, ['role_in_section' => 'member']);
// ── Dépôt ───────────────────────────────────────────────────────────
$depot = Depot::create([
'nom' => 'Archives Départementales de la Gironde',
'adresse_postale' => '72 cours Balguerie-Stuttenberg, 33000 Bordeaux',
'url' => 'https://archives.gironde.fr',
]);
// ── Type de source : État civil Naissance ────────────────────────────
$stNaissance = SourceType::create([
'nom' => 'État civil — Naissance',
'description' => 'Actes de naissance (format post-révolutionnaire)',
]);
$champsNaissance = [
['name' => 'nom', 'label' => 'Nom', 'type' => FieldType::Text, 'required' => true, 'order' => 0],
['name' => 'prenom', 'label' => 'Prénom(s)', 'type' => FieldType::Text, 'required' => true, 'order' => 1],
['name' => 'date_evenement', 'label' => 'Date de naissance', 'type' => FieldType::Date, 'required' => true, 'order' => 2],
['name' => 'lieu_naissance', 'label' => 'Lieu de naissance', 'type' => FieldType::Text, 'required' => false, 'order' => 3],
['name' => 'numero_acte', 'label' => 'N° acte', 'type' => FieldType::Number, 'required' => false, 'order' => 4],
['name' => 'nom_pere', 'label' => 'Nom du père', 'type' => FieldType::Text, 'required' => false, 'order' => 5],
['name' => 'prenom_pere', 'label' => 'Prénom du père', 'type' => FieldType::Text, 'required' => false, 'order' => 6],
['name' => 'nom_mere', 'label' => 'Nom de la mère', 'type' => FieldType::Text, 'required' => false, 'order' => 7],
['name' => 'prenom_mere', 'label' => 'Prénom de la mère', 'type' => FieldType::Text, 'required' => false, 'order' => 8],
['name' => 'note', 'label' => 'Note', 'type' => FieldType::Textarea, 'required' => false, 'order' => 9],
];
foreach ($champsNaissance as $champ) {
SourceTypeField::create(['source_type_id' => $stNaissance->id, ...$champ]);
}
// ── Type de source : Mariage ─────────────────────────────────────────
$stMariage = SourceType::create(['nom' => 'État civil — Mariage']);
$champsMariage = [
['name' => 'nom_epoux', 'label' => 'Nom de l\'époux', 'type' => FieldType::Text, 'required' => true, 'order' => 0],
['name' => 'prenom_epoux', 'label' => 'Prénom de l\'époux','type' => FieldType::Text, 'required' => true, 'order' => 1],
['name' => 'nom_epouse', 'label' => 'Nom de l\'épouse', 'type' => FieldType::Text, 'required' => true, 'order' => 2],
['name' => 'prenom_epouse', 'label' => 'Prénom de l\'épouse','type'=> FieldType::Text, 'required' => true, 'order' => 3],
['name' => 'date_mariage', 'label' => 'Date du mariage', 'type' => FieldType::Date, 'required' => true, 'order' => 4],
['name' => 'numero_acte', 'label' => 'N° acte', 'type' => FieldType::Number,'required'=> false, 'order' => 5],
['name' => 'note', 'label' => 'Note', 'type' => FieldType::Textarea,'required'=> false,'order'=> 6],
];
foreach ($champsMariage as $champ) {
SourceTypeField::create(['source_type_id' => $stMariage->id, ...$champ]);
}
// ── Source : naissances Bordeaux (en cours, membre assigné) ──────────
$sourceNaissances = Source::create([
'nom' => 'Naissances Bordeaux 18201830',
'source_type_id' => $stNaissance->id,
'depot_id' => $depot->id,
'cote' => '4E 756',
'auteur' => 'Marie Durand',
'status' => SourceStatus::EnCours,
]);
$sourceNaissances->membres()->attach($membre->id);
// ── Relevés de la source naissances ──────────────────────────────────
$releves = [
['nom' => 'DUPONT', 'prenom' => 'Jean Marie', 'date_evenement' => ['valeur' => '1821-04-03', 'calendrier' => 'gregorien'], 'lieu_naissance' => 'Bordeaux', 'numero_acte' => 12, 'nom_pere' => 'DUPONT', 'prenom_pere' => 'Pierre', 'nom_mere' => 'MARTIN', 'prenom_mere' => 'Jeanne', 'note' => null],
['nom' => 'MARTIN', 'prenom' => 'Marie Anne', 'date_evenement' => ['valeur' => '1822-07-15', 'calendrier' => 'gregorien'], 'lieu_naissance' => 'Bordeaux', 'numero_acte' => 34, 'nom_pere' => 'MARTIN', 'prenom_pere' => 'Louis', 'nom_mere' => 'BERNARD', 'prenom_mere' => 'Claire', 'note' => null],
['nom' => 'BERNARD', 'prenom' => 'Pierre Louis', 'date_evenement' => ['valeur' => '1823-01-28', 'calendrier' => 'gregorien'], 'lieu_naissance' => 'Bègles', 'numero_acte' => 8, 'nom_pere' => 'BERNARD', 'prenom_pere' => 'Jacques', 'nom_mere' => 'LEBRUN', 'prenom_mere' => 'Marie', 'note' => 'Né prématurément'],
['nom' => 'LEBRUN', 'prenom' => 'Céleste', 'date_evenement' => ['valeur' => '6 Vendémiaire An XI', 'calendrier' => 'republicain'], 'lieu_naissance' => 'Bordeaux', 'numero_acte' => 51, 'nom_pere' => null, 'prenom_pere' => null, 'nom_mere' => 'LEBRUN', 'prenom_mere' => 'Angélique', 'note' => 'Père inconnu'],
['nom' => 'ROUX', 'prenom' => 'Henri Gustave', 'date_evenement' => ['valeur' => '1825-11-02', 'calendrier' => 'gregorien'], 'lieu_naissance' => 'Bordeaux', 'numero_acte' => 89, 'nom_pere' => 'ROUX', 'prenom_pere' => 'Étienne', 'nom_mere' => 'PETIT', 'prenom_mere' => 'Louise', 'note' => null],
];
foreach ($releves as $data) {
Releve::create([
'source_id' => $sourceNaissances->id,
'created_by' => $membre->id,
'updated_by' => $membre->id,
'data' => $data,
]);
}
// ── Source : mariages (à valider) ────────────────────────────────────
Source::create([
'nom' => 'Mariages Bordeaux 18151820',
'source_type_id' => $stMariage->id,
'depot_id' => $depot->id,
'cote' => '4E 750',
'status' => SourceStatus::AValider,
]);
// ── Source : à faire ─────────────────────────────────────────────────
Source::create([
'nom' => 'Naissances Bègles 18301840',
'source_type_id' => $stNaissance->id,
'depot_id' => $depot->id,
'cote' => '4E 820',
'status' => SourceStatus::AFaire,
]);
}
}