From 506f8a5176910fd5aee3890223302ad6db5f315b Mon Sep 17 00:00:00 2001 From: ncoronel Date: Tue, 22 Sep 2026 10:32:25 -0300 Subject: [PATCH] feat(event): add slug field to events and update related resources and routes --- app/Domains/Ticketing/Event/Models/Event.php | 2 +- .../Event/Resources/EventResource.php | 1 + .../Event/Resources/PublicEventResource.php | 1 + app/Domains/Ticketing/Event/routes/api.php | 4 +- .../2026_09_22_010000_add_slugs_to_events.php | 46 +++++++++++++++++++ .../seeders/DesfilePuraTendenciaSeeder.php | 1 + database/seeders/MenuSeeder.php | 2 +- tests/Feature/Seeders/MenuSeederTest.php | 2 +- 8 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 database/migrations/2026_09_22_010000_add_slugs_to_events.php diff --git a/app/Domains/Ticketing/Event/Models/Event.php b/app/Domains/Ticketing/Event/Models/Event.php index 1379c7c..e31c9ca 100644 --- a/app/Domains/Ticketing/Event/Models/Event.php +++ b/app/Domains/Ticketing/Event/Models/Event.php @@ -13,7 +13,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; -#[Fillable(['tenant_code', 'event_category_id', 'title', 'subtitle', 'description', 'location', 'exact_location', 'date_text', 'published_at', 'attachment_id'])] +#[Fillable(['tenant_code', 'slug', 'event_category_id', 'title', 'subtitle', 'description', 'location', 'exact_location', 'date_text', 'published_at', 'attachment_id'])] class Event extends Model { use HasFactory; diff --git a/app/Domains/Ticketing/Event/Resources/EventResource.php b/app/Domains/Ticketing/Event/Resources/EventResource.php index 7baf104..29ff0b3 100644 --- a/app/Domains/Ticketing/Event/Resources/EventResource.php +++ b/app/Domains/Ticketing/Event/Resources/EventResource.php @@ -17,6 +17,7 @@ class EventResource extends JsonResource return [ 'id' => $this->id, + 'slug' => $this->slug, 'title' => $this->title, 'subtitle' => $this->subtitle, 'description' => $this->description, diff --git a/app/Domains/Ticketing/Event/Resources/PublicEventResource.php b/app/Domains/Ticketing/Event/Resources/PublicEventResource.php index c7c4133..b656676 100644 --- a/app/Domains/Ticketing/Event/Resources/PublicEventResource.php +++ b/app/Domains/Ticketing/Event/Resources/PublicEventResource.php @@ -14,6 +14,7 @@ class PublicEventResource extends JsonResource { return [ 'id' => $this->id, + 'slug' => $this->slug, 'event_category_id' => $this->event_category_id, 'title' => $this->title, 'subtitle' => $this->subtitle, diff --git a/app/Domains/Ticketing/Event/routes/api.php b/app/Domains/Ticketing/Event/routes/api.php index 37eef63..135ac80 100644 --- a/app/Domains/Ticketing/Event/routes/api.php +++ b/app/Domains/Ticketing/Event/routes/api.php @@ -6,9 +6,9 @@ use Illuminate\Support\Facades\Route; require __DIR__.'/adminapp.php'; -Route::prefix('tenants/{tenant:codigo}')->group(function (): void { +Route::prefix('tenants/{tenant:codigo}')->scopeBindings()->group(function (): void { Route::get('events', [PublicEventController::class, 'index']); - Route::get('events/{event}', [PublicEventController::class, 'show']); + Route::get('events/{event:slug}', [PublicEventController::class, 'show']); }); Route::middleware('auth:sanctum')->post( diff --git a/database/migrations/2026_09_22_010000_add_slugs_to_events.php b/database/migrations/2026_09_22_010000_add_slugs_to_events.php new file mode 100644 index 0000000..4fbb077 --- /dev/null +++ b/database/migrations/2026_09_22_010000_add_slugs_to_events.php @@ -0,0 +1,46 @@ +string('slug')->nullable()->after('tenant_code'); + }); + + $usedSlugsByTenant = []; + + foreach (DB::table('events')->orderBy('tenant_code')->orderBy('id')->get() as $event) { + $baseSlug = Str::slug((string) $event->title); + $baseSlug = $baseSlug !== '' ? mb_substr($baseSlug, 0, 240) : 'evento-'.$event->id; + $slug = $baseSlug; + $suffix = 2; + + while (isset($usedSlugsByTenant[$event->tenant_code][$slug])) { + $slug = $baseSlug.'-'.$suffix; + $suffix++; + } + + DB::table('events')->where('id', $event->id)->update(['slug' => $slug]); + $usedSlugsByTenant[$event->tenant_code][$slug] = true; + } + + Schema::table('events', function (Blueprint $table): void { + $table->unique(['tenant_code', 'slug']); + }); + } + + public function down(): void + { + Schema::table('events', function (Blueprint $table): void { + $table->dropUnique(['tenant_code', 'slug']); + $table->dropColumn('slug'); + }); + } +}; diff --git a/database/seeders/DesfilePuraTendenciaSeeder.php b/database/seeders/DesfilePuraTendenciaSeeder.php index d3d3fc9..9f6b8c9 100644 --- a/database/seeders/DesfilePuraTendenciaSeeder.php +++ b/database/seeders/DesfilePuraTendenciaSeeder.php @@ -115,6 +115,7 @@ class DesfilePuraTendenciaSeeder extends Seeder ]); $event = $tenant->events()->create([ + 'slug' => 'desfile-pura-tendencia', 'title' => 'Desfile Pura Tendencia', 'location' => 'Salón Centro Recreativo Luz y Fuerza', 'date_text' => '16 de Octubre 2026', diff --git a/database/seeders/MenuSeeder.php b/database/seeders/MenuSeeder.php index 02d980e..f698f67 100644 --- a/database/seeders/MenuSeeder.php +++ b/database/seeders/MenuSeeder.php @@ -26,7 +26,7 @@ class MenuSeeder extends Seeder [ 'code' => 'event.detail', 'label' => 'Detalle de evento', - 'route' => '/evento/:id', + 'route' => '/evento/:slug', ], [ 'code' => 'product.category', diff --git a/tests/Feature/Seeders/MenuSeederTest.php b/tests/Feature/Seeders/MenuSeederTest.php index 9214e1b..10d323c 100644 --- a/tests/Feature/Seeders/MenuSeederTest.php +++ b/tests/Feature/Seeders/MenuSeederTest.php @@ -194,7 +194,7 @@ class MenuSeederTest extends TestCase foreach ([ 'event.index' => '/', 'event.category' => '/eventos/categoria/:id', - 'event.detail' => '/evento/:id', + 'event.detail' => '/evento/:slug', ] as $code => $route) { $menu = Menu::query()->where('code', $code)->firstOrFail();