-
Notifications
You must be signed in to change notification settings - Fork 24
feat(events): add database migrations for event management infrastructure #225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 4.x
Are you sure you want to change the base?
Changes from all commits
6ff8e90
8c6642e
da5d8a0
cb75eec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use Illuminate\Database\Migrations\Migration; | ||
| use Illuminate\Database\Schema\Blueprint; | ||
| use Illuminate\Support\Facades\Schema; | ||
|
|
||
| return new class extends Migration | ||
| { | ||
| public function up(): void | ||
| { | ||
| Schema::table('events_talks', function (Blueprint $table): void { | ||
| $table->dropForeign('events_talks_event_id_foreign'); | ||
| $table->dropColumn('event_id'); | ||
| }); | ||
|
|
||
| Schema::table('events_attendees', function (Blueprint $table): void { | ||
| $table->dropForeign('events_attendees_event_id_foreign'); | ||
| $table->dropColumn('event_id'); | ||
| }); | ||
|
|
||
| Schema::table('events_sponsors', function (Blueprint $table): void { | ||
| $table->dropForeign('events_sponsors_event_id_foreign'); | ||
| $table->dropColumn('event_id'); | ||
| }); | ||
|
|
||
| Schema::table('events_agenda', function (Blueprint $table): void { | ||
| $table->dropForeign('events_agenda_event_id_foreign'); | ||
| $table->dropColumn('event_id'); | ||
| }); | ||
|
Comment on lines
+12
to
+31
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Você pode inicialmente só criar uma migration pra dropar toda a estrutura de events antiga. Fica mais limpo pra darmos track e limpar no futuro. Também tem o ponto que usamos o prefixo de módulo pras tabelas:
O prefixo é pra facilitar tanto pra gente que está desenvolvendo, quando pra qualquer agente entender os limites de cada módulo, logo:
Faça esse refactor e vamos tentando entender o que se encaixaria por aqui.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blz |
||
|
|
||
| Schema::dropIfExists('events'); | ||
|
|
||
| Schema::create('events', function (Blueprint $table): void { | ||
| $table->uuid('id')->primary(); | ||
| $table->foreignId('tenant_id')->nullable()->constrained('tenants')->nullOnDelete(); | ||
| $table->string('event_type'); | ||
| $table->boolean('active')->default(true); | ||
| $table->string('slug')->unique(); | ||
| $table->string('title'); | ||
| $table->text('description'); | ||
| $table->timestamp('event_at'); | ||
| $table->timestamp('start_at'); | ||
| $table->timestamp('end_at'); | ||
| $table->string('location'); | ||
| $table->integer('max_attendees'); | ||
| $table->integer('attendees_count')->default(0); | ||
| $table->integer('waitlist_count')->default(0); | ||
| $table->timestamps(); | ||
| }); | ||
|
|
||
| Schema::table('events_talks', function (Blueprint $table): void { | ||
| $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); | ||
| }); | ||
|
|
||
| Schema::table('events_attendees', function (Blueprint $table): void { | ||
| $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); | ||
| }); | ||
|
|
||
| Schema::table('events_sponsors', function (Blueprint $table): void { | ||
| $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); | ||
| }); | ||
|
|
||
| Schema::table('events_agenda', function (Blueprint $table): void { | ||
| $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); | ||
| }); | ||
|
Comment on lines
+13
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid destructive UUID conversion that drops existing event links. Line 13 through Line 67 removes all existing Safer migration strategy (non-destructive)
🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| public function down(): void | ||
| { | ||
| Schema::table('events_talks', function (Blueprint $table): void { | ||
| $table->dropForeign('events_talks_event_id_foreign'); | ||
| $table->dropColumn('event_id'); | ||
| }); | ||
|
|
||
| Schema::table('events_attendees', function (Blueprint $table): void { | ||
| $table->dropForeign('events_attendees_event_id_foreign'); | ||
| $table->dropColumn('event_id'); | ||
| }); | ||
|
|
||
| Schema::table('events_sponsors', function (Blueprint $table): void { | ||
| $table->dropForeign('events_sponsors_event_id_foreign'); | ||
| $table->dropColumn('event_id'); | ||
| }); | ||
|
|
||
| Schema::table('events_agenda', function (Blueprint $table): void { | ||
| $table->dropForeign('events_agenda_event_id_foreign'); | ||
| $table->dropColumn('event_id'); | ||
| }); | ||
|
|
||
| Schema::dropIfExists('events'); | ||
|
|
||
| Schema::create('events', function (Blueprint $table): void { | ||
| $table->id(); | ||
| $table->foreignId('tenant_id')->nullable()->constrained('tenants')->nullOnDelete(); | ||
| $table->string('event_type'); | ||
| $table->boolean('active'); | ||
| $table->string('slug'); | ||
| $table->string('title'); | ||
| $table->text('description'); | ||
| $table->timestamp('event_at'); | ||
| $table->timestamp('start_at'); | ||
| $table->timestamp('end_at'); | ||
| $table->string('location'); | ||
| $table->integer('max_attendees'); | ||
| $table->integer('attendees_count')->default(0); | ||
| $table->integer('waitlist_count')->default(0); | ||
| $table->timestamps(); | ||
| }); | ||
|
|
||
| Schema::table('events_talks', function (Blueprint $table): void { | ||
| $table->foreignId('event_id')->constrained('events')->cascadeOnDelete(); | ||
| }); | ||
|
|
||
| Schema::table('events_attendees', function (Blueprint $table): void { | ||
| $table->foreignId('event_id')->constrained('events')->cascadeOnDelete(); | ||
| }); | ||
|
|
||
| Schema::table('events_sponsors', function (Blueprint $table): void { | ||
| $table->foreignId('event_id')->constrained('events')->cascadeOnDelete(); | ||
| }); | ||
|
|
||
| Schema::table('events_agenda', function (Blueprint $table): void { | ||
| $table->foreignId('event_id')->constrained('events')->cascadeOnDelete(); | ||
| }); | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,37 @@ | ||||||
| <?php | ||||||
|
|
||||||
| declare(strict_types=1); | ||||||
|
|
||||||
| use Illuminate\Database\Migrations\Migration; | ||||||
| use Illuminate\Database\Schema\Blueprint; | ||||||
| use Illuminate\Support\Facades\Schema; | ||||||
|
|
||||||
| return new class extends Migration | ||||||
| { | ||||||
| public function up(): void | ||||||
| { | ||||||
| Schema::create('event_enrollment_policies', function (Blueprint $table): void { | ||||||
| $table->uuid('id')->primary(); | ||||||
| $table->timestamps(); | ||||||
| $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); | ||||||
| $table->unique('event_id'); | ||||||
| $table->string('enrollment_method'); | ||||||
| $table->string('check_in_method'); | ||||||
| $table->integer('capacity'); | ||||||
| $table->boolean('has_waitlist')->default(false); | ||||||
| $table->integer('cancellation_deadline_h'); | ||||||
| $table->jsonb('application_form')->nullable(); | ||||||
| $table->boolean('requires_approval')->default(false); | ||||||
| $table->integer('xp_reward_rsvp')->default(0); | ||||||
| $table->integer('xp_reward_checkin')->default(0); | ||||||
| $table->integer('xp_reward_referral')->default(0); | ||||||
| $table->decimal('venue_lat', 11, 7)->nullable(); | ||||||
| $table->decimal('venue_lng', 12, 10)->nullable(); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix longitude precision/scale to support full valid range. Line 29 uses Suggested fix- $table->decimal('venue_lng', 12, 10)->nullable();
+ $table->decimal('venue_lng', 13, 10)->nullable();📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| }); | ||||||
| } | ||||||
|
|
||||||
| public function down(): void | ||||||
| { | ||||||
| Schema::dropIfExists('event_enrollment_policies'); | ||||||
| } | ||||||
| }; | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use Illuminate\Database\Migrations\Migration; | ||
| use Illuminate\Database\Schema\Blueprint; | ||
| use Illuminate\Support\Facades\Schema; | ||
|
|
||
| return new class extends Migration | ||
| { | ||
| public function up(): void | ||
| { | ||
| Schema::create('check_in_codes', function (Blueprint $table): void { | ||
| $table->uuid('id')->primary(); | ||
| $table->timestamps(); | ||
| $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); | ||
| $table->string('code'); | ||
| $table->timestamp('valid_from')->nullable(); | ||
| $table->timestamp('valid_until')->nullable(); | ||
| $table->integer('max_uses')->nullable(); | ||
| $table->unique(['event_id', 'code']); | ||
| }); | ||
| } | ||
|
|
||
| public function down(): void | ||
| { | ||
| Schema::dropIfExists('check_in_codes'); | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use Illuminate\Database\Migrations\Migration; | ||
| use Illuminate\Database\Schema\Blueprint; | ||
| use Illuminate\Support\Facades\Schema; | ||
|
|
||
| return new class extends Migration | ||
| { | ||
| public function up(): void | ||
| { | ||
| Schema::create('event_enrollments', function (Blueprint $table): void { | ||
| $table->uuid('id')->primary(); | ||
| $table->timestamps(); | ||
| $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); | ||
| $table->foreignUuid('user_id')->constrained('users')->cascadeOnDelete(); | ||
| $table->string('status')->index(); | ||
| $table->integer('waitlist_position')->nullable(); | ||
| $table->string('source')->nullable(); | ||
| $table->uuid('referral_id')->nullable(); | ||
| $table->jsonb('application_data')->nullable(); | ||
| $table->boolean('is_public')->default(false); | ||
| $table->string('rejection_reason')->nullable(); | ||
| $table->timestamp('enrolled_at')->nullable(); | ||
| $table->timestamp('approved_at')->nullable(); | ||
| $table->timestamp('confirmed_at')->nullable(); | ||
| $table->timestamp('cancelled_at')->nullable(); | ||
| $table->timestamp('checked_in_at')->nullable(); | ||
| $table->timestamp('completed_at')->nullable(); | ||
| $table->unique(['event_id', 'user_id']); | ||
| }); | ||
| } | ||
|
|
||
| public function down(): void | ||
| { | ||
| Schema::dropIfExists('event_enrollments'); | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use Illuminate\Database\Migrations\Migration; | ||
| use Illuminate\Database\Schema\Blueprint; | ||
| use Illuminate\Support\Facades\Schema; | ||
|
|
||
| return new class extends Migration | ||
| { | ||
| public function up(): void | ||
| { | ||
| Schema::create('enrollment_transitions', function (Blueprint $table): void { | ||
| $table->uuid('id')->primary(); | ||
| $table->timestamps(); | ||
| $table->foreignUuid('enrollment_id')->constrained('event_enrollments')->cascadeOnDelete(); | ||
| $table->string('from_status')->nullable(); | ||
| $table->string('to_status'); | ||
| $table->string('triggered_by'); | ||
| $table->foreignUuid('actor_user_id')->nullable()->constrained('users')->nullOnDelete(); | ||
| $table->text('reason')->nullable(); | ||
| $table->index(['enrollment_id', 'created_at']); | ||
| }); | ||
| } | ||
|
|
||
| public function down(): void | ||
| { | ||
| Schema::dropIfExists('enrollment_transitions'); | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use Illuminate\Database\Migrations\Migration; | ||
| use Illuminate\Database\Schema\Blueprint; | ||
| use Illuminate\Support\Facades\Schema; | ||
|
|
||
| return new class extends Migration | ||
| { | ||
| public function up(): void | ||
| { | ||
| Schema::create('event_check_ins', function (Blueprint $table): void { | ||
| $table->uuid('id')->primary(); | ||
| $table->timestamps(); | ||
| $table->foreignUuid('enrollment_id')->constrained('event_enrollments')->cascadeOnDelete(); | ||
| $table->string('method'); | ||
| $table->jsonb('payload')->nullable(); | ||
| $table->foreignUuid('verified_by_user_id')->nullable()->constrained('users')->nullOnDelete(); | ||
| $table->unique('enrollment_id'); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unique constraint on The unique constraint means each enrollment can have only one check-in record. This design prevents tracking:
If the business requirement truly enforces "one check-in per enrollment ever," this is correct. However, most event systems track all check-in attempts for audit and analytics. Consider removing this constraint to allow multiple check-in records per enrollment, or clarify in a comment that only the most recent/valid check-in is stored. 🤖 Prompt for AI Agents |
||
| }); | ||
| } | ||
|
|
||
| public function down(): void | ||
| { | ||
| Schema::dropIfExists('event_check_ins'); | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use Illuminate\Database\Migrations\Migration; | ||
| use Illuminate\Database\Schema\Blueprint; | ||
| use Illuminate\Support\Facades\Schema; | ||
|
|
||
| return new class extends Migration | ||
| { | ||
| public function up(): void | ||
| { | ||
| Schema::create('event_xp_rewards', function (Blueprint $table): void { | ||
| $table->uuid('id')->primary(); | ||
| $table->timestamps(); | ||
| $table->foreignUuid('user_id')->constrained('users')->cascadeOnDelete(); | ||
| $table->foreignUuid('event_id')->constrained('events')->cascadeOnDelete(); | ||
| $table->foreignUuid('enrollment_id')->constrained('event_enrollments')->cascadeOnDelete(); | ||
| $table->string('reason'); | ||
| $table->integer('xp_amount'); | ||
| $table->string('source_type'); | ||
| $table->uuid('source_id'); | ||
|
Comment on lines
+21
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Polymorphic relationship without referential integrity. The
While polymorphic foreign keys are not directly supported in SQL, consider:
Consider adding monitoring/alerts for orphaned 🤖 Prompt for AI Agents |
||
| $table->unique(['enrollment_id', 'reason']); | ||
| }); | ||
| } | ||
|
|
||
| public function down(): void | ||
| { | ||
| Schema::dropIfExists('event_xp_rewards'); | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use Illuminate\Database\Migrations\Migration; | ||
| use Illuminate\Database\Schema\Blueprint; | ||
| use Illuminate\Support\Facades\Schema; | ||
|
|
||
| return new class extends Migration | ||
| { | ||
| public function up(): void | ||
| { | ||
| Schema::create('magic_links', function (Blueprint $table): void { | ||
| $table->uuid('id')->primary(); | ||
| $table->timestamps(); | ||
| $table->foreignUuid('enrollment_id')->constrained('event_enrollments')->cascadeOnDelete(); | ||
| $table->string('token')->unique(); | ||
| $table->timestamp('expires_at')->nullable(); | ||
| $table->timestamp('used_at')->nullable(); | ||
| $table->string('sent_to_email'); | ||
| }); | ||
| } | ||
|
|
||
| public function down(): void | ||
| { | ||
| Schema::dropIfExists('magic_links'); | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| use Illuminate\Database\Migrations\Migration; | ||
| use Illuminate\Database\Schema\Blueprint; | ||
| use Illuminate\Support\Facades\Schema; | ||
|
|
||
| return new class extends Migration | ||
| { | ||
| public function up(): void | ||
| { | ||
| Schema::create('qr_tokens', function (Blueprint $table): void { | ||
| $table->uuid('id')->primary(); | ||
| $table->timestamps(); | ||
| $table->foreignUuid('enrollment_id')->constrained('event_enrollments')->cascadeOnDelete(); | ||
| $table->string('token')->unique(); | ||
| $table->timestamp('expires_at')->nullable(); | ||
| $table->timestamp('used_at')->nullable(); | ||
| }); | ||
|
Comment on lines
+13
to
+20
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pensando melhor: QR Tokens é uma abstração "fraca" creio eu. No final, se tivermos algum app de leitura ou algo do tipo, só precisamos ler o "uuid" da entrada dessa pessoa no evento e marcar como check-in, logo isso não é tão necessário. |
||
| } | ||
|
|
||
| public function down(): void | ||
| { | ||
| Schema::dropIfExists('qr_tokens'); | ||
| } | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
Repository: he4rt/heartdevs.com
Length of output: 158
🏁 Script executed:
Repository: he4rt/heartdevs.com
Length of output: 5909
🏁 Script executed:
Repository: he4rt/heartdevs.com
Length of output: 695
🏁 Script executed:
Repository: he4rt/heartdevs.com
Length of output: 8354
Use
disableForeignKeyConstraints()to handle SQLite FK operations safely.This migration manually drops foreign keys before altering the parent
eventstable, which technically works on SQLite. However, it bypasses Laravel's built-inSchema::disableForeignKeyConstraints()/enableForeignKeyConstraints()wrapper, which properly manages database-specific foreign key pragmas. Wrapping the entire migration logic (bothup()anddown()methods) with these methods would be more robust and maintainable, especially since the project uses SQLite as the default database withforeign_key_constraintsenabled by default.🤖 Prompt for AI Agents