diff --git a/app/Domains/Catalog/Models/CatalogItem.php b/app/Domains/Catalog/Models/CatalogItem.php index 4d7034c..9c5ec7a 100644 --- a/app/Domains/Catalog/Models/CatalogItem.php +++ b/app/Domains/Catalog/Models/CatalogItem.php @@ -7,7 +7,6 @@ use App\Domains\Catalog\Enums\CatalogItemType; use App\Domains\Catalog\Enums\EventProductType; use App\Domains\Catalog\Enums\InventoryPolicy; use App\Domains\Catalog\Services\CatalogInventoryService; -use App\Domains\Event\Models\Event; use App\Domains\Tenant\Models\Tenant; use App\Domains\Ticket\Models\Ticket; use App\Domains\Ticket\Models\ValidityTime; @@ -20,7 +19,6 @@ use Illuminate\Database\Eloquent\Relations\HasMany; #[Fillable([ 'tenant_code', - 'event_id', 'event_product_type', 'category_id', 'brand_id', @@ -55,7 +53,6 @@ class CatalogItem extends Model 'category_id' => 'integer', 'brand_id' => 'integer', 'inventory_id' => 'integer', - 'event_id' => 'integer', 'event_product_type' => EventProductType::class, 'type' => CatalogItemType::class, 'precio' => 'decimal:2', @@ -72,12 +69,6 @@ class CatalogItem extends Model return $this->belongsTo(Tenant::class, 'tenant_code', 'codigo'); } - /** @return BelongsTo */ - public function event(): BelongsTo - { - return $this->belongsTo(Event::class); - } - /** @return BelongsTo */ public function category(): BelongsTo { diff --git a/app/Domains/Catalog/Requests/StoreCatalogItemRequest.php b/app/Domains/Catalog/Requests/StoreCatalogItemRequest.php index 248be56..304c746 100644 --- a/app/Domains/Catalog/Requests/StoreCatalogItemRequest.php +++ b/app/Domains/Catalog/Requests/StoreCatalogItemRequest.php @@ -26,18 +26,9 @@ class StoreCatalogItemRequest extends FormRequest return [ 'tenant_code' => ['prohibited'], 'type' => ['sometimes', Rule::enum(CatalogItemType::class)], - 'event_id' => [ - 'sometimes', - 'nullable', - 'required_with:event_product_type', - Rule::exists('events', 'id')->where( - fn ($query) => $query->where('tenant_code', $tenantCode) - ), - ], 'event_product_type' => [ 'sometimes', 'nullable', - 'required_with:event_id', Rule::enum(EventProductType::class), ], 'category_id' => [ @@ -93,7 +84,7 @@ class StoreCatalogItemRequest extends FormRequest 'nullable', 'integer', Rule::exists('event_dates', 'id')->where( - fn ($query) => $query->where('event_id', $this->input('event_id')) + fn ($query) => $query->where('tenant_code', $tenantCode) ), ], 'variants.*.inventory_id' => ['prohibited'], diff --git a/app/Domains/Catalog/Resources/CatalogItemDetailResource.php b/app/Domains/Catalog/Resources/CatalogItemDetailResource.php index 0e6dd1d..92ca8ec 100644 --- a/app/Domains/Catalog/Resources/CatalogItemDetailResource.php +++ b/app/Domains/Catalog/Resources/CatalogItemDetailResource.php @@ -23,7 +23,6 @@ class CatalogItemDetailResource extends JsonResource return [ 'id' => $this->id, 'type' => $this->type->value, - 'event_id' => $this->event_id, 'event_product_type' => $this->event_product_type?->value, 'category_id' => $this->category_id, 'brand_id' => $this->brand_id, @@ -38,9 +37,7 @@ class CatalogItemDetailResource extends JsonResource 'has_tickets' => $this->has_tickets, 'validity_time_id' => $this->validity_time_id, 'validity_time' => ValidityTimeResource::make($this->validityTime), - 'attributes' => $this->itemAttributes - ->map(fn (ItemAttribute $itemAttribute): array => $this->attributeData($itemAttribute)) - ->values(), + 'attributes' => $this->attributesData(), 'stock_tecnico' => $this->when( $selectedVariant === null, fn () => $this->availableStock(), @@ -111,19 +108,70 @@ class CatalogItemDetailResource extends JsonResource ]; } + /** @return Collection> */ + private function attributesData(): Collection + { + $attributes = $this->itemAttributes + ->map(fn (ItemAttribute $itemAttribute): array => $this->attributeData($itemAttribute)); + + if ($this->variants->isEmpty() || $this->variants->contains( + fn (Variant $variant): bool => $variant->event_date_id === null + )) { + return $attributes->values(); + } + + $eventDateAttribute = [ + 'id' => -1, + 'codigo' => 'event_date', + 'nombre' => 'Fecha', + 'is_required' => true, + 'metadata_schema' => null, + 'type' => 'event_date', + 'options' => $this->variants + ->pluck('eventDate') + ->filter() + ->unique('id') + ->sortBy(fn ($eventDate): string => $eventDate->date->format('Y-m-d').' '.$eventDate->time_start) + ->values() + ->map(fn ($eventDate, int $index): array => [ + 'id' => $eventDate->id, + 'value' => (string) $eventDate->id, + 'label' => $eventDate->date->format('d/m/Y').' · ' + .substr($eventDate->time_start, 0, 5).' a ' + .substr($eventDate->time_end, 0, 5), + 'sort_order' => $index, + 'validity_time_id' => null, + 'validity_time' => null, + 'metadata' => [ + 'date' => $eventDate->date->format('Y-m-d'), + 'time_start' => $eventDate->time_start, + 'time_end' => $eventDate->time_end, + ], + ]), + ]; + + return collect([$eventDateAttribute])->concat($attributes)->values(); + } + /** @return array */ private function variantData(Variant $variant): array { + $values = $variant->definitions + ->mapWithKeys(fn ($definition) => [ + $definition->itemAttribute?->attribute?->codigo => $definition->value, + ]) + ->filter(fn ($value, $key): bool => $key !== null); + + if ($variant->event_date_id !== null) { + $values->put('event_date', (string) $variant->event_date_id); + } + return [ 'id' => $variant->id, 'event_date_id' => $variant->event_date_id, 'event_date' => $variant->eventDate?->date?->format('Y-m-d'), 'stock_tecnico' => $this->variantStock($variant), - 'values' => $variant->definitions - ->mapWithKeys(fn ($definition) => [ - $definition->itemAttribute?->attribute?->codigo => $definition->value, - ]) - ->filter(fn ($value, $key): bool => $key !== null), + 'values' => $values, ]; } diff --git a/app/Domains/Catalog/Resources/CatalogItemResource.php b/app/Domains/Catalog/Resources/CatalogItemResource.php index ab642d5..f26ce08 100644 --- a/app/Domains/Catalog/Resources/CatalogItemResource.php +++ b/app/Domains/Catalog/Resources/CatalogItemResource.php @@ -16,7 +16,6 @@ class CatalogItemResource extends JsonResource return [ 'id' => $this->id, 'type' => $this->type->value, - 'event_id' => $this->event_id, 'event_product_type' => $this->event_product_type?->value, 'category_id' => $this->category_id, 'brand_id' => $this->brand_id, diff --git a/app/Domains/Catalog/Services/CatalogService.php b/app/Domains/Catalog/Services/CatalogService.php index b9eacd1..829ad52 100644 --- a/app/Domains/Catalog/Services/CatalogService.php +++ b/app/Domains/Catalog/Services/CatalogService.php @@ -12,7 +12,6 @@ use App\Domains\Catalog\Models\Category; use App\Domains\Catalog\Models\Inventory; use App\Domains\Catalog\Models\ItemAttribute; 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 Illuminate\Database\Eloquent\Builder; @@ -47,7 +46,14 @@ class CatalogService ); $hasVariants = $attributeCodes !== [] || $hasEventDateVariants; - $this->validateEventData($data); + if ($hasEventDateVariants && in_array('event_date', $attributeCodes, true)) { + throw ValidationException::withMessages([ + 'attribute_codes' => ['The event_date code is reserved for event dates.'], + ]); + } + + $this->validateEventProductType($data); + $this->validateUniqueVariantCombinations($variants, $attributeCodes); if ($type === CatalogItemType::Bundle) { $this->validateBundleData($data, $components); @@ -127,7 +133,6 @@ class CatalogService 'inventory', 'category', 'brand', - 'event', 'validityTime', 'itemAttributes.attribute', 'variants.inventory', @@ -147,7 +152,6 @@ class CatalogService 'inventory', 'category', 'brand', - 'event', 'validityTime', 'itemAttributes.attribute.options.validityTime', 'variants' => fn ($query) => $query->orderBy('id'), @@ -492,16 +496,15 @@ class CatalogService if ( $eventDateId !== null && ( - $catalogItem->event_id === null - || ! EventDate::query() + ! EventDate::query() ->whereKey($eventDateId) - ->where('event_id', $catalogItem->event_id) + ->where('tenant_code', $catalogItem->tenant_code) ->exists() ) ) { throw ValidationException::withMessages([ "variants.{$index}.event_date_id" => [ - 'The event date must belong to the catalog item event.', + 'The event date must belong to the catalog item tenant.', ], ]); } @@ -533,30 +536,14 @@ class CatalogService } /** @param array $data */ - private function validateEventData(array $data): void + private function validateEventProductType(array $data): void { - $eventId = $data['event_id'] ?? null; $eventProductType = $data['event_product_type'] ?? null; - if (($eventId === null) !== ($eventProductType === null)) { - throw ValidationException::withMessages([ - 'event_id' => ['Event and event product type must be provided together.'], - ]); - } - - if ($eventId === null) { + if ($eventProductType === null) { return; } - if (! Event::query() - ->whereKey($eventId) - ->where('tenant_code', $data['tenant_code'] ?? null) - ->exists()) { - throw ValidationException::withMessages([ - 'event_id' => ['The event must belong to the catalog item tenant.'], - ]); - } - if (! in_array($eventProductType, EventProductType::values(), true)) { throw ValidationException::withMessages([ 'event_product_type' => ['The event product type is invalid.'], @@ -564,6 +551,35 @@ class CatalogService } } + /** + * @param array> $variants + * @param array $attributeCodes + */ + private function validateUniqueVariantCombinations(array $variants, array $attributeCodes): void + { + $seen = []; + $attributeCodes = array_values(array_unique($attributeCodes)); + sort($attributeCodes); + + foreach (array_values($variants) as $index => $variant) { + $combination = [(string) ($variant['event_date_id'] ?? '')]; + + foreach ($attributeCodes as $attributeCode) { + $value = trim((string) ($variant['values'][$attributeCode] ?? '')); + $combination[] = Str::ascii(mb_strtolower($value)); + } + + $key = implode('|', $combination); + if (isset($seen[$key])) { + throw ValidationException::withMessages([ + "variants.{$index}" => ['The variant combination must be unique.'], + ]); + } + + $seen[$key] = true; + } + } + /** * @param array $data * @param array> $variants diff --git a/app/Domains/Event/Controllers/AdminApp/EventController.php b/app/Domains/Event/Controllers/AdminApp/EventController.php index a31c2c9..b6036d9 100644 --- a/app/Domains/Event/Controllers/AdminApp/EventController.php +++ b/app/Domains/Event/Controllers/AdminApp/EventController.php @@ -15,14 +15,14 @@ class EventController extends Controller public function show(Request $request): EventResource { return EventResource::make( - $this->eventService->activeForTenant($request->user()->tenant()->firstOrFail()) + $this->eventService->forTenant($request->user()->tenant()->firstOrFail()) ); } public function update(UpdateEventRequest $request): EventResource { return EventResource::make( - $this->eventService->updateActiveForTenant( + $this->eventService->updateForTenant( $request->user()->tenant()->firstOrFail(), $request->validated() ) diff --git a/app/Domains/Event/Models/Event.php b/app/Domains/Event/Models/Event.php deleted file mode 100644 index 15582f7..0000000 --- a/app/Domains/Event/Models/Event.php +++ /dev/null @@ -1,48 +0,0 @@ - */ - public function tenant(): BelongsTo - { - return $this->belongsTo(Tenant::class, 'tenant_code', 'codigo'); - } - - /** @return HasMany */ - public function dates(): HasMany - { - return $this->hasMany(EventDate::class)->orderBy('date')->orderBy('time_start'); - } - - /** @return HasMany */ - public function catalogItems(): HasMany - { - return $this->hasMany(CatalogItem::class); - } - - /** @return HasMany */ - public function purchases(): HasMany - { - return $this->hasMany(Purchase::class); - } -} diff --git a/app/Domains/Event/Models/EventDate.php b/app/Domains/Event/Models/EventDate.php index 48714e6..9fb05ae 100644 --- a/app/Domains/Event/Models/EventDate.php +++ b/app/Domains/Event/Models/EventDate.php @@ -3,6 +3,7 @@ namespace App\Domains\Event\Models; use App\Domains\Catalog\Models\Variant; +use App\Domains\Tenant\Models\Tenant; use Carbon\CarbonInterface; use Illuminate\Database\Eloquent\Attributes\Fillable; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -12,7 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Carbon; #[Fillable([ - 'event_id', + 'tenant_code', 'date', 'time_start', 'time_end', @@ -26,15 +27,14 @@ class EventDate extends Model protected function casts(): array { return [ - 'event_id' => 'integer', 'date' => 'date:Y-m-d', ]; } - /** @return BelongsTo */ - public function event(): BelongsTo + /** @return BelongsTo */ + public function tenant(): BelongsTo { - return $this->belongsTo(Event::class); + return $this->belongsTo(Tenant::class, 'tenant_code', 'codigo'); } /** @return HasMany */ diff --git a/app/Domains/Event/Resources/EventResource.php b/app/Domains/Event/Resources/EventResource.php index ef566a3..4ef58cd 100644 --- a/app/Domains/Event/Resources/EventResource.php +++ b/app/Domains/Event/Resources/EventResource.php @@ -2,29 +2,29 @@ namespace App\Domains\Event\Resources; -use App\Domains\Event\Models\Event; +use App\Domains\Tenant\Models\Tenant; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; -/** @mixin Event */ +/** @mixin Tenant */ class EventResource extends JsonResource { /** @return array */ public function toArray(Request $request): array { - $socialMedia = $this->tenant->socialMedia->keyBy('code'); + $socialMedia = $this->socialMedia->keyBy('code'); return [ 'id' => $this->id, - 'title' => $this->name, - 'location' => $this->address, - 'dates' => $this->dates->map(fn ($eventDate): array => [ + 'title' => $this->event_title, + 'location' => $this->event_location, + 'dates' => $this->eventDates->map(fn ($eventDate): array => [ 'id' => $eventDate->id, 'date' => $eventDate->date->format('Y-m-d'), 'start_time' => substr($eventDate->time_start, 0, 5), 'end_time' => substr($eventDate->time_end, 0, 5), ])->values(), - 'social_media' => $this->tenant->socialMedia->map(fn ($item): array => [ + 'social_media' => $this->socialMedia->map(fn ($item): array => [ 'code' => $item->code, 'url' => $item->pivot->url, 'orden' => $item->pivot->orden, diff --git a/app/Domains/Event/Services/EventService.php b/app/Domains/Event/Services/EventService.php index e8d610f..793d546 100644 --- a/app/Domains/Event/Services/EventService.php +++ b/app/Domains/Event/Services/EventService.php @@ -2,7 +2,6 @@ namespace App\Domains\Event\Services; -use App\Domains\Event\Models\Event; use App\Domains\Tenant\Models\Tenant; use Illuminate\Support\Facades\DB; @@ -14,53 +13,36 @@ class EventService 'facebook_url' => 'facebook', ]; - public function activeForTenant(Tenant $tenant): Event + public function forTenant(Tenant $tenant): Tenant { - return $tenant->events() - ->whereKey($tenant->active_event_id) - ->with(['dates', 'tenant.socialMedia']) - ->firstOrFail(); + return $tenant->load(['eventDates', 'socialMedia']); } /** @param array $data */ - public function updateActiveForTenant(Tenant $tenant, array $data): Event + public function updateForTenant(Tenant $tenant, array $data): Tenant { - return DB::transaction(function () use ($tenant, $data): Event { + return DB::transaction(function () use ($tenant, $data): Tenant { $tenant = Tenant::query()->whereKey($tenant->getKey())->lockForUpdate()->firstOrFail(); - $event = $tenant->active_event_id === null - ? $tenant->events()->create([ - 'name' => $data['title'], - 'address' => $data['location'], - ]) - : $tenant->events() - ->whereKey($tenant->active_event_id) - ->lockForUpdate() - ->firstOrFail(); - - $event->update([ - 'name' => $data['title'], - 'address' => $data['location'], + $tenant->update([ + 'event_title' => $data['title'], + 'event_location' => $data['location'], ]); - if ($tenant->active_event_id === null) { - $tenant->update(['active_event_id' => $event->id]); - } - - $this->syncDates($event, $data['dates']); + $this->syncDates($tenant, $data['dates']); if (array_key_exists('social_media', $data)) { $this->syncSocialMedia($tenant, $data['social_media']); } else { $this->syncLegacyContact($tenant, $data['contact']); } - return $event->load(['dates', 'tenant.socialMedia']); + return $tenant->load(['eventDates', 'socialMedia']); }); } /** @param array $dates */ - private function syncDates(Event $event, array $dates): void + private function syncDates(Tenant $tenant, array $dates): void { - $existingDates = $event->dates()->get()->values(); + $existingDates = $tenant->eventDates()->get()->values(); foreach (array_values($dates) as $index => $date) { $attributes = [ @@ -74,12 +56,12 @@ class EventService if ($existingDate) { $existingDate->update($attributes); } else { - $event->dates()->create($attributes); + $tenant->eventDates()->create($attributes); } } $existingDates->slice(count($dates))->each->delete(); - $event->unsetRelation('dates'); + $tenant->unsetRelation('eventDates'); } /** @param array $contact */ diff --git a/app/Domains/Purchase/Models/Purchase.php b/app/Domains/Purchase/Models/Purchase.php index 698f4df..a5dcb11 100644 --- a/app/Domains/Purchase/Models/Purchase.php +++ b/app/Domains/Purchase/Models/Purchase.php @@ -4,7 +4,6 @@ namespace App\Domains\Purchase\Models; use App\Domains\Auth\Models\User; use App\Domains\Cart\Models\Cart; -use App\Domains\Event\Models\Event; use App\Domains\Logging\Models\Concerns\LogsValueChanges; use App\Domains\Purchase\Events\PurchasePaid; use App\Domains\Tenant\Models\Tenant; @@ -20,7 +19,6 @@ use Illuminate\Support\Facades\DB; #[Fillable([ 'cart_id', 'tenant_codigo', - 'event_id', 'user_id', 'status', 'payment_method', @@ -72,7 +70,6 @@ class Purchase extends Model { return [ 'cart_id' => 'integer', - 'event_id' => 'integer', 'user_id' => 'integer', 'expires_at' => 'datetime', 'total' => 'decimal:2', @@ -87,12 +84,6 @@ class Purchase extends Model return $this->belongsTo(Tenant::class, 'tenant_codigo', 'codigo'); } - /** @return BelongsTo */ - public function event(): BelongsTo - { - return $this->belongsTo(Event::class); - } - /** * @return BelongsTo */ diff --git a/app/Domains/Purchase/Resources/PurchaseResource.php b/app/Domains/Purchase/Resources/PurchaseResource.php index 161c7cf..b383adc 100644 --- a/app/Domains/Purchase/Resources/PurchaseResource.php +++ b/app/Domains/Purchase/Resources/PurchaseResource.php @@ -42,7 +42,6 @@ class PurchaseResource extends JsonResource 'id' => $this->id, 'cart_id' => $this->cart_id, 'tenant_codigo' => $this->tenant_codigo, - 'event_id' => $this->event_id, 'user_id' => $this->user_id, 'created_at' => $this->created_at, 'status' => $this->status, diff --git a/app/Domains/Purchase/Services/Checkout/StartCheckoutService.php b/app/Domains/Purchase/Services/Checkout/StartCheckoutService.php index cfc7a78..fc772f8 100644 --- a/app/Domains/Purchase/Services/Checkout/StartCheckoutService.php +++ b/app/Domains/Purchase/Services/Checkout/StartCheckoutService.php @@ -229,7 +229,6 @@ class StartCheckoutService ...$purchaseData, 'cart_id' => $cartId, 'tenant_codigo' => $tenant->codigo, - 'event_id' => $tenant->active_event_id, 'user_id' => $userId, 'status' => Purchase::STATUS_CREATED, 'payment_method' => null, diff --git a/app/Domains/Tenant/Models/Tenant.php b/app/Domains/Tenant/Models/Tenant.php index cd0c4d8..e19b470 100644 --- a/app/Domains/Tenant/Models/Tenant.php +++ b/app/Domains/Tenant/Models/Tenant.php @@ -7,7 +7,7 @@ use App\Domains\Catalog\Enums\GroupLayout; use App\Domains\Catalog\Enums\ProductLayout; use App\Domains\Catalog\Models\CatalogItem; use App\Domains\Catalog\Models\Category; -use App\Domains\Event\Models\Event; +use App\Domains\Event\Models\EventDate; use App\Domains\Menu\Models\Menu; use App\Domains\Menu\Models\TenantMenu; use Illuminate\Database\Eloquent\Attributes\Fillable; @@ -33,7 +33,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany; 'search_product_layout', 'search_group_layout', 'search_items_per_page', - 'active_event_id', + 'event_title', + 'event_location', ])] class Tenant extends Model { @@ -61,7 +62,6 @@ class Tenant extends Model 'search_product_layout' => ProductLayout::class, 'search_group_layout' => GroupLayout::class, 'search_items_per_page' => 'integer', - 'active_event_id' => 'integer', ]; } @@ -94,16 +94,12 @@ class Tenant extends Model return $this->hasMany(CatalogItem::class, 'tenant_code', 'codigo'); } - /** @return HasMany */ - public function events(): HasMany + /** @return HasMany */ + public function eventDates(): HasMany { - return $this->hasMany(Event::class, 'tenant_code', 'codigo'); - } - - /** @return BelongsTo */ - public function activeEvent(): BelongsTo - { - return $this->belongsTo(Event::class, 'active_event_id'); + return $this->hasMany(EventDate::class, 'tenant_code', 'codigo') + ->orderBy('date') + ->orderBy('time_start'); } /** diff --git a/app/Domains/Tenant/Resources/TenantResource.php b/app/Domains/Tenant/Resources/TenantResource.php index 354b398..903d45b 100644 --- a/app/Domains/Tenant/Resources/TenantResource.php +++ b/app/Domains/Tenant/Resources/TenantResource.php @@ -32,14 +32,12 @@ class TenantResource extends JsonResource 'header_bg_color' => $this->header_bg_color, 'footer_bg_color' => $this->footer_bg_color, 'website_type_code' => $this->website_type_code, - 'active_event_id' => $this->active_event_id, - 'active_event' => $this->whenLoaded('activeEvent', fn () => $this->activeEvent === null + 'event' => $this->whenLoaded('eventDates', fn () => $this->event_title === null ? null : [ - 'id' => $this->activeEvent->id, - 'name' => $this->activeEvent->name, - 'address' => $this->activeEvent->address, - 'dates' => $this->activeEvent->dates->map(fn ($eventDate): array => [ + 'title' => $this->event_title, + 'location' => $this->event_location, + 'dates' => $this->eventDates->map(fn ($eventDate): array => [ 'id' => $eventDate->id, 'date' => $eventDate->date->format('Y-m-d'), 'time_start' => $eventDate->time_start, diff --git a/app/Domains/Tenant/Services/TenantInformationService.php b/app/Domains/Tenant/Services/TenantInformationService.php index 0f47a1d..32d7844 100644 --- a/app/Domains/Tenant/Services/TenantInformationService.php +++ b/app/Domains/Tenant/Services/TenantInformationService.php @@ -15,7 +15,7 @@ class TenantInformationService 'footerLogo', 'socialMedia', 'websiteExtras.websiteTypeExtra', - 'activeEvent.dates', + 'eventDates', ]; /** diff --git a/database/migrations/2026_08_07_000000_move_event_onto_tenant.php b/database/migrations/2026_08_07_000000_move_event_onto_tenant.php new file mode 100644 index 0000000..b8f439e --- /dev/null +++ b/database/migrations/2026_08_07_000000_move_event_onto_tenant.php @@ -0,0 +1,125 @@ +string('event_title')->nullable()->after('nombre'); + $table->string('event_location')->nullable()->after('event_title'); + }); + + Schema::table('event_dates', function (Blueprint $table): void { + $table->string('tenant_code')->nullable()->after('id'); + }); + + DB::table('tenants') + ->whereNotNull('active_event_id') + ->orderBy('id') + ->each(function (object $tenant): void { + $event = DB::table('events')->where('id', $tenant->active_event_id)->first(); + + if ($event === null) { + return; + } + + DB::table('tenants')->where('id', $tenant->id)->update([ + 'event_title' => $event->name, + 'event_location' => $event->address, + ]); + }); + + DB::table('events')->orderBy('id')->each(function (object $event): void { + DB::table('event_dates') + ->where('event_id', $event->id) + ->update(['tenant_code' => $event->tenant_code]); + }); + + Schema::table('tenants', function (Blueprint $table): void { + $table->dropConstrainedForeignId('active_event_id'); + }); + Schema::table('catalog_items', function (Blueprint $table): void { + $table->dropConstrainedForeignId('event_id'); + }); + Schema::table('compras', function (Blueprint $table): void { + $table->dropConstrainedForeignId('event_id'); + }); + Schema::table('event_dates', function (Blueprint $table): void { + $table->dropConstrainedForeignId('event_id'); + $table->string('tenant_code')->nullable(false)->change(); + $table->foreign('tenant_code') + ->references('codigo') + ->on('tenants') + ->cascadeOnUpdate() + ->cascadeOnDelete(); + }); + + Schema::dropIfExists('events'); + } + + public function down(): void + { + Schema::create('events', function (Blueprint $table): void { + $table->id(); + $table->string('tenant_code'); + $table->string('name'); + $table->string('address'); + $table->foreign('tenant_code') + ->references('codigo') + ->on('tenants') + ->cascadeOnUpdate() + ->cascadeOnDelete(); + }); + + Schema::table('tenants', function (Blueprint $table): void { + $table->foreignId('active_event_id')->nullable(); + }); + Schema::table('catalog_items', function (Blueprint $table): void { + $table->foreignId('event_id')->nullable(); + }); + Schema::table('compras', function (Blueprint $table): void { + $table->foreignId('event_id')->nullable(); + }); + Schema::table('event_dates', function (Blueprint $table): void { + $table->foreignId('event_id')->nullable(); + }); + + DB::table('tenants')->orderBy('id')->each(function (object $tenant): void { + if ($tenant->event_title === null && $tenant->event_location === null) { + return; + } + + $eventId = DB::table('events')->insertGetId([ + 'tenant_code' => $tenant->codigo, + 'name' => $tenant->event_title ?? $tenant->nombre, + 'address' => $tenant->event_location ?? '', + ]); + + DB::table('tenants')->where('id', $tenant->id)->update(['active_event_id' => $eventId]); + DB::table('catalog_items')->where('tenant_code', $tenant->codigo)->update(['event_id' => $eventId]); + DB::table('compras')->where('tenant_codigo', $tenant->codigo)->update(['event_id' => $eventId]); + DB::table('event_dates')->where('tenant_code', $tenant->codigo)->update(['event_id' => $eventId]); + }); + + Schema::table('tenants', function (Blueprint $table): void { + $table->foreign('active_event_id')->references('id')->on('events')->nullOnDelete(); + $table->dropColumn(['event_title', 'event_location']); + }); + Schema::table('catalog_items', function (Blueprint $table): void { + $table->foreign('event_id')->references('id')->on('events')->nullOnDelete(); + }); + Schema::table('compras', function (Blueprint $table): void { + $table->foreign('event_id')->references('id')->on('events')->nullOnDelete(); + }); + Schema::table('event_dates', function (Blueprint $table): void { + $table->dropForeign(['tenant_code']); + $table->dropColumn('tenant_code'); + $table->foreign('event_id')->references('id')->on('events')->cascadeOnDelete(); + }); + } +}; diff --git a/database/migrations/2026_08_07_000100_allow_event_date_attribute_combinations.php b/database/migrations/2026_08_07_000100_allow_event_date_attribute_combinations.php new file mode 100644 index 0000000..8410619 --- /dev/null +++ b/database/migrations/2026_08_07_000100_allow_event_date_attribute_combinations.php @@ -0,0 +1,30 @@ +index(['catalog_item_id', 'event_date_id']); + }); + + Schema::table('variantes', function (Blueprint $table): void { + $table->dropUnique(['catalog_item_id', 'event_date_id']); + }); + } + + public function down(): void + { + Schema::table('variantes', function (Blueprint $table): void { + $table->unique(['catalog_item_id', 'event_date_id']); + }); + + Schema::table('variantes', function (Blueprint $table): void { + $table->dropIndex(['catalog_item_id', 'event_date_id']); + }); + } +}; diff --git a/database/seeders/FiestaFutbolInfantilProductSeeder.php b/database/seeders/FiestaFutbolInfantilProductSeeder.php index 5070b91..2d533f2 100644 --- a/database/seeders/FiestaFutbolInfantilProductSeeder.php +++ b/database/seeders/FiestaFutbolInfantilProductSeeder.php @@ -12,7 +12,6 @@ use App\Domains\Catalog\Models\CatalogItem; use App\Domains\Catalog\Models\Category; use App\Domains\Catalog\Models\FeaturedGroup; use App\Domains\Catalog\Services\CatalogService; -use App\Domains\Event\Models\Event; use App\Domains\Tenant\Models\Tenant; use App\Domains\Ticket\Enums\ValidityTimeType; use App\Domains\Ticket\Models\ValidityTime; @@ -38,18 +37,15 @@ class FiestaFutbolInfantilProductSeeder extends Seeder ->update(['categoria_id' => null]); Category::query()->where('tenant_code', $tenant->codigo)->delete(); - $event = Event::query()->updateOrCreate( - [ - 'tenant_code' => $tenant->codigo, - 'name' => 'Fiesta Nacional del Fútbol Infantil', - ], - ['address' => 'Sunchales, Santa Fe'], - ); - $event->dates()->delete(); + $tenant->update([ + 'event_title' => 'Fiesta Nacional del Fútbol Infantil', + 'event_location' => 'Sunchales, Santa Fe', + ]); + $tenant->eventDates()->delete(); $eventDates = collect(['2026-10-09', '2026-10-10', '2026-10-11', '2026-10-12']) - ->mapWithKeys(function (string $date) use ($event): array { - $eventDate = $event->dates()->create([ + ->mapWithKeys(function (string $date) use ($tenant): array { + $eventDate = $tenant->eventDates()->create([ 'date' => $date, 'time_start' => '00:00:00', 'time_end' => '23:59:59', @@ -58,9 +54,6 @@ class FiestaFutbolInfantilProductSeeder extends Seeder return [$date => $eventDate]; }); - $tenant->active_event_id = $event->id; - $tenant->save(); - $ticketCategory = Category::query()->firstOrCreate([ 'nombre' => 'Entradas', 'tenant_code' => $tenant->codigo, @@ -89,7 +82,6 @@ class FiestaFutbolInfantilProductSeeder extends Seeder $generalAdmission = $this->catalogService->create([ 'tenant_code' => $tenant->codigo, - 'event_id' => $event->id, 'event_product_type' => EventProductType::Entry->value, 'category_id' => $ticketCategory->id, 'slug' => 'entrada-general', @@ -121,7 +113,6 @@ class FiestaFutbolInfantilProductSeeder extends Seeder foreach ($items as $item) { $createdItems[$item['slug']] = $this->catalogService->create([ 'tenant_code' => $tenant->codigo, - 'event_id' => $event->id, 'event_product_type' => EventProductType::Product->value, 'descripcion' => $item['descripcion'] ?? $item['nombre'], 'inventory_policy' => InventoryPolicy::Unlimited->value, @@ -133,7 +124,6 @@ class FiestaFutbolInfantilProductSeeder extends Seeder $this->catalogService->create([ 'tenant_code' => $tenant->codigo, - 'event_id' => $event->id, 'event_product_type' => EventProductType::Entry->value, 'type' => CatalogItemType::Bundle->value, 'slug' => 'entrada-general-todos-los-dias', @@ -152,7 +142,6 @@ class FiestaFutbolInfantilProductSeeder extends Seeder $this->catalogService->create([ 'tenant_code' => $tenant->codigo, - 'event_id' => $event->id, 'event_product_type' => EventProductType::Product->value, 'type' => CatalogItemType::Bundle->value, 'slug' => 'combo-2-panchos-2-hamburguesas', diff --git a/tests/Feature/Catalog/CatalogItemDetailControllerTest.php b/tests/Feature/Catalog/CatalogItemDetailControllerTest.php index c392e7a..accdcf3 100644 --- a/tests/Feature/Catalog/CatalogItemDetailControllerTest.php +++ b/tests/Feature/Catalog/CatalogItemDetailControllerTest.php @@ -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, diff --git a/tests/Feature/Catalog/CatalogSchemaTest.php b/tests/Feature/Catalog/CatalogSchemaTest.php index 643ae38..ed6e8ea 100644 --- a/tests/Feature/Catalog/CatalogSchemaTest.php +++ b/tests/Feature/Catalog/CatalogSchemaTest.php @@ -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')); } } diff --git a/tests/Feature/Catalog/CatalogServiceTest.php b/tests/Feature/Catalog/CatalogServiceTest.php index 5215b8f..264d5f0 100644 --- a/tests/Feature/Catalog/CatalogServiceTest.php +++ b/tests/Feature/Catalog/CatalogServiceTest.php @@ -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'); diff --git a/tests/Feature/Event/AdminAppEventControllerTest.php b/tests/Feature/Event/AdminAppEventControllerTest.php index b30dcb0..34030e4 100644 --- a/tests/Feature/Event/AdminAppEventControllerTest.php +++ b/tests/Feature/Event/AdminAppEventControllerTest.php @@ -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(); } } diff --git a/tests/Feature/Purchase/StorePurchaseTest.php b/tests/Feature/Purchase/StorePurchaseTest.php index e8e3b6f..6cbc361 100644 --- a/tests/Feature/Purchase/StorePurchaseTest.php +++ b/tests/Feature/Purchase/StorePurchaseTest.php @@ -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, diff --git a/tests/Feature/Seeders/FiestaFutbolInfantilProductSeederTest.php b/tests/Feature/Seeders/FiestaFutbolInfantilProductSeederTest.php index 6661cb0..02f87fb 100644 --- a/tests/Feature/Seeders/FiestaFutbolInfantilProductSeederTest.php +++ b/tests/Feature/Seeders/FiestaFutbolInfantilProductSeederTest.php @@ -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( diff --git a/tests/Unit/Catalog/CatalogModelsTest.php b/tests/Unit/Catalog/CatalogModelsTest.php index 5e51a85..356a964 100644 --- a/tests/Unit/Catalog/CatalogModelsTest.php +++ b/tests/Unit/Catalog/CatalogModelsTest.php @@ -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()); diff --git a/tests/Unit/Event/EventModelsTest.php b/tests/Unit/Event/EventModelsTest.php index 070f880..de442d5 100644 --- a/tests/Unit/Event/EventModelsTest.php +++ b/tests/Unit/Event/EventModelsTest.php @@ -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()); } }