CatalogItemType::Standard->value, 'inventory_policy' => InventoryPolicy::Tracked->value, 'has_tickets' => false, ]; protected function casts(): array { return [ 'category_id' => 'integer', 'brand_id' => 'integer', 'inventory_id' => 'integer', 'event_id' => 'integer', 'event_product_type' => EventProductType::class, 'type' => CatalogItemType::class, 'precio' => 'decimal:2', 'inventory_policy' => InventoryPolicy::class, 'has_tickets' => 'boolean', 'maximum_use_date' => 'datetime', 'minimum_use_date' => 'datetime', ]; } /** @return BelongsTo */ public function tenant(): BelongsTo { 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 { return $this->belongsTo(Category::class); } /** @return BelongsTo */ public function brand(): BelongsTo { return $this->belongsTo(Brand::class); } /** @return BelongsTo */ public function inventory(): BelongsTo { return $this->belongsTo(Inventory::class); } /** @return HasMany */ public function bundleComponents(): HasMany { return $this->hasMany(BundleComponent::class, 'bundle_catalog_item_id'); } /** @return HasMany */ public function bundleComponentUsages(): HasMany { return $this->hasMany(BundleComponent::class, 'component_catalog_item_id'); } /** @return HasMany */ public function variants(): HasMany { return $this->hasMany(Variant::class); } /** @return HasMany */ public function sourceTickets(): HasMany { return $this->hasMany(Ticket::class, 'source_catalog_item_id'); } /** @return BelongsToMany */ public function attributes(): BelongsToMany { return $this->belongsToMany(Attribute::class, 'item_attributes') ->withTimestamps(); } /** @return HasMany */ public function itemAttributes(): HasMany { return $this->hasMany(ItemAttribute::class); } /** @return HasMany */ public function featuredItems(): HasMany { return $this->hasMany(FeaturedItem::class); } /** @return BelongsToMany */ public function attachments(): BelongsToMany { return $this->belongsToMany( Attachment::class, 'catalog_items_attachments', 'catalog_item_id', 'attachment_id' ) ->withPivot('orden') ->wherePivotNull('variant_id') ->orderByPivot('orden'); } public function availableStock(): ?int { return app(CatalogInventoryService::class)->availableQuantity($this); } public function isAvailable(): bool { if ($this->type === CatalogItemType::Bundle) { $availableStock = $this->availableStock(); return $availableStock === null || $availableStock > 0; } if ($this->inventory_policy === InventoryPolicy::Unlimited) { return true; } return ($this->availableStock() ?? 0) > 0; } public function getPrice(): float { return (float) $this->precio; } public function getName(): string { return $this->nombre; } public function getMinimumUseDate(): ?CarbonInterface { return $this->minimum_use_date; } public function getMaximumUseDate(): ?CarbonInterface { return $this->maximum_use_date; } public function isBundle(): bool { return $this->type === CatalogItemType::Bundle; } }