refactor(event): move event configuration onto tenant
This commit is contained in:
@@ -170,6 +170,33 @@ class CatalogItemDetailControllerTest extends TestCase
|
||||
->assertJsonPath('data.variants.0.stock_tecnico', null);
|
||||
}
|
||||
|
||||
public function test_it_exposes_event_dates_as_a_dynamic_variant_attribute(): void
|
||||
{
|
||||
$tenant = $this->createTenant('detail-event-date');
|
||||
$tenant->update([
|
||||
'event_title' => 'Festival',
|
||||
'event_location' => 'Rosario',
|
||||
]);
|
||||
$eventDate = $tenant->eventDates()->create([
|
||||
'date' => '2026-10-09',
|
||||
'time_start' => '09:00',
|
||||
'time_end' => '18:00',
|
||||
]);
|
||||
$item = $this->createItem($tenant, 'Entry');
|
||||
$variant = $this->createVariant($item, 10, 0);
|
||||
$variant->update(['event_date_id' => $eventDate->id]);
|
||||
|
||||
$this->getJson("/api/tenants/{$tenant->codigo}/catalog-items/{$item->id}")
|
||||
->assertOk()
|
||||
->assertJsonPath('data.attributes.0.id', -1)
|
||||
->assertJsonPath('data.attributes.0.codigo', 'event_date')
|
||||
->assertJsonPath('data.attributes.0.type', 'event_date')
|
||||
->assertJsonPath('data.attributes.0.options.0.id', $eventDate->id)
|
||||
->assertJsonPath('data.attributes.0.options.0.value', (string) $eventDate->id)
|
||||
->assertJsonPath('data.attributes.0.options.0.label', '09/10/2026 · 09:00 a 18:00')
|
||||
->assertJsonPath('data.variants.0.values.event_date', (string) $eventDate->id);
|
||||
}
|
||||
|
||||
private function createItem(
|
||||
Tenant $tenant,
|
||||
string $name,
|
||||
|
||||
@@ -32,7 +32,6 @@ class CatalogSchemaTest extends TestCase
|
||||
$this->assertEqualsCanonicalizing([
|
||||
'id',
|
||||
'tenant_code',
|
||||
'event_id',
|
||||
'event_product_type',
|
||||
'category_id',
|
||||
'brand_id',
|
||||
@@ -186,21 +185,21 @@ class CatalogSchemaTest extends TestCase
|
||||
]));
|
||||
}
|
||||
|
||||
public function test_events_and_event_dates_are_linked_to_the_catalog(): void
|
||||
public function test_event_configuration_and_dates_belong_to_the_tenant(): void
|
||||
{
|
||||
$this->assertFalse(Schema::hasTable('events'));
|
||||
$this->assertTrue(Schema::hasColumns('tenants', [
|
||||
'event_title',
|
||||
'event_location',
|
||||
]));
|
||||
$this->assertEqualsCanonicalizing([
|
||||
'id',
|
||||
'tenant_code',
|
||||
'name',
|
||||
'address',
|
||||
], Schema::getColumnListing('events'));
|
||||
$this->assertEqualsCanonicalizing([
|
||||
'id',
|
||||
'event_id',
|
||||
'date',
|
||||
'time_start',
|
||||
'time_end',
|
||||
], Schema::getColumnListing('event_dates'));
|
||||
$this->assertTrue(Schema::hasColumn('tenants', 'active_event_id'));
|
||||
$this->assertFalse(Schema::hasColumn('catalog_items', 'event_id'));
|
||||
$this->assertFalse(Schema::hasColumn('compras', 'event_id'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,68 @@ class CatalogServiceTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function test_it_allows_the_same_event_date_with_different_attribute_values(): void
|
||||
{
|
||||
$sector = $this->createAttribute('sector');
|
||||
$eventDate = $this->tenant->eventDates()->create([
|
||||
'date' => '2026-10-09',
|
||||
'time_start' => '09:00',
|
||||
'time_end' => '18:00',
|
||||
]);
|
||||
|
||||
$item = $this->service->create([
|
||||
'tenant_code' => $this->tenant->codigo,
|
||||
'slug' => 'entry-by-sector',
|
||||
'nombre' => 'Entry by sector',
|
||||
'precio' => 100,
|
||||
'attribute_codes' => [$sector->codigo],
|
||||
'variants' => [
|
||||
[
|
||||
'event_date_id' => $eventDate->id,
|
||||
'values' => ['sector' => 'General'],
|
||||
],
|
||||
[
|
||||
'event_date_id' => $eventDate->id,
|
||||
'values' => ['sector' => 'VIP'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertCount(2, $item->variants);
|
||||
$this->assertSame(
|
||||
[$eventDate->id, $eventDate->id],
|
||||
$item->variants->pluck('event_date_id')->all(),
|
||||
);
|
||||
}
|
||||
|
||||
public function test_it_rejects_duplicate_variant_combinations(): void
|
||||
{
|
||||
$sector = $this->createAttribute('sector');
|
||||
$eventDate = $this->tenant->eventDates()->create([
|
||||
'date' => '2026-10-09',
|
||||
'time_start' => '09:00',
|
||||
'time_end' => '18:00',
|
||||
]);
|
||||
|
||||
try {
|
||||
$this->service->create([
|
||||
'tenant_code' => $this->tenant->codigo,
|
||||
'slug' => 'duplicate-entry',
|
||||
'nombre' => 'Duplicate entry',
|
||||
'precio' => 100,
|
||||
'attribute_codes' => [$sector->codigo],
|
||||
'variants' => [
|
||||
['event_date_id' => $eventDate->id, 'values' => ['sector' => 'VIP']],
|
||||
['event_date_id' => $eventDate->id, 'values' => ['sector' => ' vip ']],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->fail('A validation exception was not thrown.');
|
||||
} catch (ValidationException $exception) {
|
||||
$this->assertArrayHasKey('variants.1', $exception->errors());
|
||||
}
|
||||
}
|
||||
|
||||
public function test_it_rejects_direct_inventory_together_with_variants(): void
|
||||
{
|
||||
$attribute = $this->createAttribute('size');
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Tests\Feature\Event;
|
||||
|
||||
use App\Domains\Auth\Models\User;
|
||||
use App\Domains\Authorization\Enums\RoleCode;
|
||||
use App\Domains\Event\Models\Event;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Domains\Tenant\Models\WebsiteType;
|
||||
use Database\Seeders\AuthorizationSeeder;
|
||||
@@ -50,17 +49,14 @@ class AdminAppEventControllerTest extends TestCase
|
||||
->assertJsonPath('data.contact.instagram_url', 'https://instagram.com/acme')
|
||||
->assertJsonPath('data.contact.facebook_url', null);
|
||||
|
||||
$eventId = $response->json('data.id');
|
||||
|
||||
$this->assertDatabaseHas('events', [
|
||||
'id' => $eventId,
|
||||
'tenant_code' => $tenant->codigo,
|
||||
'name' => 'Festival Acme',
|
||||
'address' => 'Predio Ferial, Rosario',
|
||||
$this->assertSame($tenant->id, $response->json('data.id'));
|
||||
$this->assertDatabaseHas('tenants', [
|
||||
'id' => $tenant->id,
|
||||
'event_title' => 'Festival Acme',
|
||||
'event_location' => 'Predio Ferial, Rosario',
|
||||
]);
|
||||
$this->assertSame($eventId, $tenant->fresh()->active_event_id);
|
||||
$this->assertDatabaseHas('event_dates', [
|
||||
'event_id' => $eventId,
|
||||
'tenant_code' => $tenant->codigo,
|
||||
'date' => '2026-10-09',
|
||||
'time_start' => '09:00:00',
|
||||
'time_end' => '18:30:00',
|
||||
@@ -86,24 +82,27 @@ class AdminAppEventControllerTest extends TestCase
|
||||
->assertJsonMissing(['title' => 'Other Event']);
|
||||
}
|
||||
|
||||
public function test_reading_a_tenant_without_an_active_event_returns_not_found(): void
|
||||
public function test_reading_a_tenant_without_event_configuration_returns_empty_values(): void
|
||||
{
|
||||
$tenant = $this->createTenant('acme');
|
||||
Sanctum::actingAs($this->createAdminAppUser($tenant));
|
||||
|
||||
$this->getJson('/api/v1/adminapp/tenant/event')->assertNotFound();
|
||||
$this->getJson('/api/v1/adminapp/tenant/event')
|
||||
->assertOk()
|
||||
->assertJsonPath('data.title', null)
|
||||
->assertJsonCount(0, 'data.dates');
|
||||
}
|
||||
|
||||
public function test_updating_reuses_the_active_event_and_synchronizes_dates_and_contact(): void
|
||||
{
|
||||
$tenant = $this->createTenant('acme');
|
||||
$event = $this->createActiveEvent($tenant, 'Old Event');
|
||||
$firstDate = $event->dates()->create([
|
||||
$eventTenant = $this->createActiveEvent($tenant, 'Old Event');
|
||||
$firstDate = $eventTenant->eventDates()->create([
|
||||
'date' => '2026-10-01',
|
||||
'time_start' => '08:00',
|
||||
'time_end' => '12:00',
|
||||
]);
|
||||
$removedDate = $event->dates()->create([
|
||||
$removedDate = $eventTenant->eventDates()->create([
|
||||
'date' => '2026-10-02',
|
||||
'time_start' => '08:00',
|
||||
'time_end' => '12:00',
|
||||
@@ -127,7 +126,7 @@ class AdminAppEventControllerTest extends TestCase
|
||||
|
||||
$this->putJson('/api/v1/adminapp/tenant/event', $payload)
|
||||
->assertOk()
|
||||
->assertJsonPath('data.id', $event->id)
|
||||
->assertJsonPath('data.id', $tenant->id)
|
||||
->assertJsonPath('data.dates.0.id', $firstDate->id)
|
||||
->assertJsonPath('data.contact.facebook_url', null);
|
||||
|
||||
@@ -175,7 +174,7 @@ class AdminAppEventControllerTest extends TestCase
|
||||
'contact.whatsapp_url',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseCount('events', 0);
|
||||
$this->assertNull($tenant->fresh()->event_title);
|
||||
}
|
||||
|
||||
public function test_social_media_accepts_any_registered_code_and_rejects_unknown_codes(): void
|
||||
@@ -257,14 +256,13 @@ class AdminAppEventControllerTest extends TestCase
|
||||
]);
|
||||
}
|
||||
|
||||
private function createActiveEvent(Tenant $tenant, string $name): Event
|
||||
private function createActiveEvent(Tenant $tenant, string $name): Tenant
|
||||
{
|
||||
$event = $tenant->events()->create([
|
||||
'name' => $name,
|
||||
'address' => 'Rosario',
|
||||
$tenant->update([
|
||||
'event_title' => $name,
|
||||
'event_location' => 'Rosario',
|
||||
]);
|
||||
$tenant->update(['active_event_id' => $event->id]);
|
||||
|
||||
return $event;
|
||||
return $tenant->fresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Catalog\Models\Category;
|
||||
use App\Domains\Catalog\Models\Inventory;
|
||||
use App\Domains\Catalog\Models\Variant;
|
||||
use App\Domains\Event\Models\Event;
|
||||
use App\Domains\Purchase\Models\Purchase;
|
||||
use App\Domains\Purchase\Services\CheckoutService;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
@@ -34,12 +33,10 @@ class StorePurchaseTest extends TestCase
|
||||
public function test_it_creates_an_independent_purchase_snapshot_from_cart(): void
|
||||
{
|
||||
$tenant = $this->createTenant('sonder', 'Sonder', 'sonder.com.ar');
|
||||
$event = Event::query()->create([
|
||||
'tenant_code' => $tenant->codigo,
|
||||
'name' => 'Sonder Fest',
|
||||
'address' => 'Test address',
|
||||
$tenant->update([
|
||||
'event_title' => 'Sonder Fest',
|
||||
'event_location' => 'Test address',
|
||||
]);
|
||||
$tenant->update(['active_event_id' => $event->id]);
|
||||
$user = User::factory()->create([
|
||||
'email' => 'buyer@example.com',
|
||||
]);
|
||||
@@ -92,7 +89,6 @@ class StorePurchaseTest extends TestCase
|
||||
$response->assertJsonPath('data.nombre_apellido', null);
|
||||
$response->assertJsonPath('data.email', null);
|
||||
$response->assertJsonPath('data.tenant_codigo', 'sonder');
|
||||
$response->assertJsonPath('data.event_id', $event->id);
|
||||
$response->assertJsonPath('data.status', Purchase::STATUS_CREATED);
|
||||
$response->assertJsonPath('data.items_source', 'purchase');
|
||||
$response->assertJsonCount(1, 'data.items');
|
||||
@@ -105,7 +101,6 @@ class StorePurchaseTest extends TestCase
|
||||
'id' => $purchaseId,
|
||||
'cart_id' => $cartId,
|
||||
'tenant_codigo' => 'sonder',
|
||||
'event_id' => $event->id,
|
||||
'user_id' => $user->id,
|
||||
'dni' => null,
|
||||
'telefono' => null,
|
||||
|
||||
@@ -14,7 +14,6 @@ use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Catalog\Models\Category;
|
||||
use App\Domains\Catalog\Models\FeaturedGroup;
|
||||
use App\Domains\Catalog\Models\Inventory;
|
||||
use App\Domains\Event\Models\Event;
|
||||
use App\Domains\Event\Models\EventDate;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Domains\Ticket\Enums\ValidityTimeType;
|
||||
@@ -96,15 +95,11 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase
|
||||
->all(),
|
||||
);
|
||||
|
||||
$event = Event::query()
|
||||
->where('tenant_code', $tenant->codigo)
|
||||
->with('dates')
|
||||
->sole();
|
||||
|
||||
$this->assertSame($event->id, $tenant->fresh()->active_event_id);
|
||||
$this->assertCount(4, $event->dates);
|
||||
$this->assertSame(1, Event::query()->where('tenant_code', $tenant->codigo)->count());
|
||||
$this->assertSame(4, EventDate::query()->where('event_id', $event->id)->count());
|
||||
$tenant->refresh()->load('eventDates');
|
||||
$this->assertSame('Fiesta Nacional del Fútbol Infantil', $tenant->event_title);
|
||||
$this->assertSame('Sunchales, Santa Fe', $tenant->event_location);
|
||||
$this->assertCount(4, $tenant->eventDates);
|
||||
$this->assertSame(4, EventDate::query()->where('tenant_code', $tenant->codigo)->count());
|
||||
|
||||
$generalAdmission = CatalogItem::query()
|
||||
->where('tenant_code', $tenant->codigo)
|
||||
@@ -113,7 +108,6 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase
|
||||
->sole();
|
||||
|
||||
$this->assertNull($generalAdmission->inventory_id);
|
||||
$this->assertTrue($generalAdmission->event->is($event));
|
||||
$this->assertSame(EventProductType::Entry, $generalAdmission->event_product_type);
|
||||
$this->assertCount(0, $generalAdmission->itemAttributes);
|
||||
$this->assertCount(4, $generalAdmission->variants);
|
||||
@@ -133,7 +127,6 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase
|
||||
|
||||
$this->assertCount(7, $standardItems);
|
||||
foreach ($standardItems as $standardItem) {
|
||||
$this->assertSame($event->id, $standardItem->event_id);
|
||||
$this->assertSame(
|
||||
'2026-10-09 00:00:00',
|
||||
$standardItem->validityTime->fixed_starts_at->format('Y-m-d H:i:s'),
|
||||
@@ -154,7 +147,6 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase
|
||||
$this->assertSame('40000.00', $allDaysItem->precio);
|
||||
$this->assertNull($allDaysItem->inventory_id);
|
||||
$this->assertFalse($allDaysItem->has_tickets);
|
||||
$this->assertSame($event->id, $allDaysItem->event_id);
|
||||
$this->assertSame(EventProductType::Entry, $allDaysItem->event_product_type);
|
||||
$this->assertCount(4, $allDaysItem->bundleComponents);
|
||||
$this->assertEqualsCanonicalizing(
|
||||
|
||||
@@ -21,7 +21,6 @@ use App\Domains\Catalog\Models\Inventory;
|
||||
use App\Domains\Catalog\Models\ItemAttribute;
|
||||
use App\Domains\Catalog\Models\Variant;
|
||||
use App\Domains\Catalog\Models\VariantDefinition;
|
||||
use App\Domains\Event\Models\Event;
|
||||
use App\Domains\Event\Models\EventDate;
|
||||
use App\Domains\Shared\Enums\FieldType;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
@@ -65,7 +64,6 @@ class CatalogModelsTest extends TestCase
|
||||
'category_id' => '10',
|
||||
'brand_id' => '20',
|
||||
'inventory_id' => '30',
|
||||
'event_id' => '40',
|
||||
'event_product_type' => EventProductType::Entry->value,
|
||||
'type' => CatalogItemType::Standard->value,
|
||||
'precio' => '12.50',
|
||||
@@ -78,14 +76,12 @@ class CatalogModelsTest extends TestCase
|
||||
$this->assertSame(10, $item->category_id);
|
||||
$this->assertSame(20, $item->brand_id);
|
||||
$this->assertSame(30, $item->inventory_id);
|
||||
$this->assertSame(40, $item->event_id);
|
||||
$this->assertSame(EventProductType::Entry, $item->event_product_type);
|
||||
$this->assertSame(CatalogItemType::Standard, $item->type);
|
||||
$this->assertSame('12.50', $item->precio);
|
||||
$this->assertSame(InventoryPolicy::Tracked, $item->inventory_policy);
|
||||
$this->assertTrue($item->has_tickets);
|
||||
$this->assertInstanceOf(Tenant::class, $item->tenant()->getRelated());
|
||||
$this->assertInstanceOf(Event::class, $item->event()->getRelated());
|
||||
$this->assertInstanceOf(Category::class, $item->category()->getRelated());
|
||||
$this->assertInstanceOf(Brand::class, $item->brand()->getRelated());
|
||||
$this->assertInstanceOf(Inventory::class, $item->inventory()->getRelated());
|
||||
|
||||
@@ -2,48 +2,35 @@
|
||||
|
||||
namespace Tests\Unit\Event;
|
||||
|
||||
use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Catalog\Models\Variant;
|
||||
use App\Domains\Event\Models\Event;
|
||||
use App\Domains\Event\Models\EventDate;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use Tests\TestCase;
|
||||
|
||||
class EventModelsTest extends TestCase
|
||||
{
|
||||
public function test_event_maps_its_tenant_dates_and_catalog_items(): void
|
||||
{
|
||||
$event = new Event;
|
||||
|
||||
$this->assertFalse($event->usesTimestamps());
|
||||
$this->assertInstanceOf(Tenant::class, $event->tenant()->getRelated());
|
||||
$this->assertInstanceOf(EventDate::class, $event->dates()->getRelated());
|
||||
$this->assertInstanceOf(CatalogItem::class, $event->catalogItems()->getRelated());
|
||||
}
|
||||
|
||||
public function test_event_date_maps_schedule_and_variants(): void
|
||||
{
|
||||
$eventDate = new EventDate;
|
||||
$eventDate->setRawAttributes([
|
||||
'event_id' => '10',
|
||||
'tenant_code' => 'acme',
|
||||
'date' => '2026-10-09',
|
||||
'time_start' => '09:00:00',
|
||||
'time_end' => '18:30:00',
|
||||
]);
|
||||
|
||||
$this->assertFalse($eventDate->usesTimestamps());
|
||||
$this->assertSame(10, $eventDate->event_id);
|
||||
$this->assertSame('acme', $eventDate->tenant_code);
|
||||
$this->assertSame('2026-10-09 09:00:00', $eventDate->startsAt()->format('Y-m-d H:i:s'));
|
||||
$this->assertSame('2026-10-09 18:30:00', $eventDate->endsAt()->format('Y-m-d H:i:s'));
|
||||
$this->assertInstanceOf(Event::class, $eventDate->event()->getRelated());
|
||||
$this->assertInstanceOf(Tenant::class, $eventDate->tenant()->getRelated());
|
||||
$this->assertInstanceOf(Variant::class, $eventDate->variants()->getRelated());
|
||||
}
|
||||
|
||||
public function test_tenant_has_many_events_and_one_active_event(): void
|
||||
public function test_tenant_has_many_event_dates(): void
|
||||
{
|
||||
$tenant = new Tenant;
|
||||
|
||||
$this->assertInstanceOf(Event::class, $tenant->events()->getRelated());
|
||||
$this->assertInstanceOf(Event::class, $tenant->activeEvent()->getRelated());
|
||||
$this->assertInstanceOf(EventDate::class, $tenant->eventDates()->getRelated());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user