refactor(seeders): move DevSeeder to new form-builder structure

Adds UserObserver::created() that firstOrCreate's a user_profiles row
for every User. Registered in AppServiceProvider alongside PersonObserver.
Covers DevSeeder (3 scattered User::create sites: DatabaseSeeder super admin,
DevSeeder org staff, DevSeeder volunteer users) and all future creation
paths (invite/register/import) with zero per-caller boilerplate.

New FormBuilderDevSeeder seeder class holds canonical 16-field registration
template (borrowed from the legacy RegistrationFieldTemplateService list so
test data stays recognisable). Produces per-org:
- 16 form_templates (system, schema_snapshot per ARCH §4.6.1)
- 1 FormSchema per event (event_registration, owner=event, draft_single
  mode, is_published mirrors event.status lifecycle)
- 16 FormFields per schema
- 1 FormSubmission per person whose status ∈ applied/approved/no_show
  (same rule as MigrateLegacyFormsData), with 6 realistic FormValues each

DevSeeder::run() now wraps the whole seed body in
ActivityLog::suppressed(...) so the ~80 field creates + ~277 submission
lifecycle triggers don't flood activity_log. Also removes the legacy
RegistrationFieldTemplateService::seedSystemTemplates call — the 16
system templates now land directly in form_templates.

Post-seed totals (dev DB):
  5 form_schemas, 80 form_fields, 277 form_submissions, 1662 form_values,
  16 form_templates, 270 user_profiles (1:1 with users).

forms:verify-data-integrity on freshly seeded DB: exit 0.
php artisan test: 910/910.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-17 14:08:43 +02:00
parent 72892d38f4
commit 021a3cd079
4 changed files with 291 additions and 10 deletions

View File

@@ -20,6 +20,7 @@ use App\Models\TimeSlot;
use App\Models\User;
use App\Models\UserOrganisationTag;
use App\Models\VolunteerAvailability;
use App\Support\ActivityLog;
use Illuminate\Database\Seeder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
@@ -45,12 +46,17 @@ class DevSeeder extends Seeder
{
$this->call(RoleSeeder::class);
$this->seedOrganisation();
$this->seedEchtFeesten();
$this->seedBraderie();
$this->seedIJsbaan();
$this->seedKoningsdag();
$this->seedNachtVanDeKaap();
// Suppress all activity-log writes during bulk fixture generation.
// Hundreds of logSchemaChange/logFieldChange + Organisation-trait
// entries would otherwise flood activity_log without useful value.
ActivityLog::suppressed(function (): void {
$this->seedOrganisation();
$this->seedEchtFeesten();
$this->seedBraderie();
$this->seedIJsbaan();
$this->seedKoningsdag();
$this->seedNachtVanDeKaap();
});
}
// =========================================================================
@@ -152,11 +158,11 @@ class DevSeeder extends Seeder
$this->personTags[$data['name']] = $tag;
}
// ── Registration Field Templates (system defaults) ──
// ── Form Builder: system templates (new structure) ──
\App\Services\RegistrationFieldTemplateService::seedSystemTemplates($this->org);
$templatesCreated = FormBuilderDevSeeder::seedSystemTemplates($this->org);
$this->command->info(' Organisation, 8 users, 6 companies, 7 crowd types, 10 person tags, 16 registration templates created');
$this->command->info(" Organisation, 8 users, 6 companies, 7 crowd types, 10 person tags, {$templatesCreated} form_templates created");
});
}
@@ -916,6 +922,10 @@ class DevSeeder extends Seeder
]);
}
$formSchema = FormBuilderDevSeeder::seedEventSchema($festival);
$submissions = FormBuilderDevSeeder::seedSubmissionsForEvent($festival, $formSchema);
$this->command->info(" Form schema + 16 fields + {$submissions} submissions created");
$this->command->info(' Echt Feesten 2026 complete');
});
}
@@ -978,6 +988,10 @@ class DevSeeder extends Seeder
$this->linkUsersToApprovedPersons($braderie);
$formSchema = FormBuilderDevSeeder::seedEventSchema($braderie);
$submissions = FormBuilderDevSeeder::seedSubmissionsForEvent($braderie, $formSchema);
$this->command->info(" Form schema + 16 fields + {$submissions} submissions created");
$this->command->info(' Braderie Dorpstown 2026 complete');
});
}
@@ -1149,6 +1163,10 @@ class DevSeeder extends Seeder
$personCount = Person::where('event_id', $ijsbaan->id)->count();
$this->command->info(" {$personCount} persons, " . count($allShifts) . ' shifts created');
$formSchema = FormBuilderDevSeeder::seedEventSchema($ijsbaan);
$submissions = FormBuilderDevSeeder::seedSubmissionsForEvent($ijsbaan, $formSchema);
$this->command->info(" Form schema + 16 fields + {$submissions} submissions created");
});
}
@@ -1317,6 +1335,10 @@ class DevSeeder extends Seeder
$personCount = Person::where('event_id', $koningsdag->id)->count();
$assignCount = ShiftAssignment::whereIn('shift_id', collect($kShifts)->pluck('id'))->count();
$this->command->info(" {$personCount} persons, 12 shifts, {$assignCount} assignments");
$formSchema = FormBuilderDevSeeder::seedEventSchema($koningsdag);
$submissions = FormBuilderDevSeeder::seedSubmissionsForEvent($koningsdag, $formSchema);
$this->command->info(" Form schema + 16 fields + {$submissions} submissions created");
});
}
@@ -1347,7 +1369,9 @@ class DevSeeder extends Seeder
TimeSlot::create(['event_id' => $event->id, 'name' => 'Nacht', 'person_type' => 'VOLUNTEER', 'date' => '2026-09-12', 'start_time' => '20:00', 'end_time' => '04:00', 'duration_hours' => 8.00]);
$this->command->info(' Empty draft event created');
FormBuilderDevSeeder::seedEventSchema($event);
$this->command->info(' Empty draft event created (with form schema, 0 submissions)');
});
}