*/ protected function casts(): array { return [ 'product_type' => ProductType::class, 'status' => ProductStatus::class, 'price_type' => PriceType::class, 'dimensions_specific' => 'array', 'is_curated' => 'boolean', 'curated_at' => 'datetime', 'is_available' => 'boolean', 'productIsAvailable' => 'boolean', 'certificates' => 'array', 'assembly_service' => 'boolean', 'is_regional_production' => 'boolean', 'visible_from' => 'date', 'visible_until' => 'date', 'co2_footprint_kg' => 'decimal:2', ]; } /** * Produkt gehört zu einem Partner (Händler oder Hersteller). */ public function partner(): BelongsTo { return $this->belongsTo(Partner::class); } /** * Produkt gehört zu einer Marke. */ public function brand(): BelongsTo { return $this->belongsTo(Brand::class); } /** * Produkt gehört zu einer Kollektion. */ public function collection(): BelongsTo { return $this->belongsTo(Collection::class); } /** * Produkt gehört zu einem Hub (regionale Zuordnung). */ public function hub(): BelongsTo { return $this->belongsTo(Hub::class); } /** * User, der das Produkt kuratiert/freigegeben hat. */ public function curator(): BelongsTo { return $this->belongsTo(User::class, 'curated_by'); } /** * Produkt kann mehreren Kategorien zugeordnet sein. */ public function categories(): BelongsToMany { return $this->belongsToMany(Category::class); } /** * Produkt kann mehrere Tags haben. */ public function tags(): BelongsToMany { return $this->belongsToMany(Tag::class); } /** * Produkt hat mehrere Varianten (Farben, Größen, etc.). */ public function variants(): HasMany { return $this->hasMany(ProductVariant::class); } /** * Polymorphe Beziehung zu Media (Bilder, Videos, PDFs). */ public function media(): MorphMany { return $this->morphMany(Media::class, 'model'); } /** * Holzherkunft-Einträge für EUDR-Compliance. */ public function woodOrigins(): HasMany { return $this->hasMany(ProductWoodOrigin::class); } /** * Änderungshistorie. */ public function activities(): HasMany { return $this->hasMany(ProductActivity::class); } /** * Verwandte Produkte. */ public function relatedProducts(): BelongsToMany { return $this->belongsToMany(self::class, 'related_products', 'product_id', 'related_product_id'); } /** * Scope: Nur aktive Produkte. */ public function scopeActive(Builder $query): void { $query->where('status', ProductStatus::Active); } /** * Scope: Nur kuratierte/freigegebene Produkte. */ public function scopeCurated(Builder $query): void { $query->where('is_curated', true); } /** * Scope: Nur Produkte, die auf Freigabe warten. */ public function scopePending(Builder $query): void { $query->where('status', ProductStatus::Pending); } /** * Scope: Nur Local Stock Produkte (Säule A). */ public function scopeLocalStock(Builder $query): void { $query->where('product_type', ProductType::LocalStock); } /** * Scope: Nur Smart Order Produkte (Säule B). */ public function scopeSmartOrder(Builder $query): void { $query->where('product_type', ProductType::SmartOrder); } /** * Scope: Produkte in einem bestimmten Hub. */ public function scopeInHub(Builder $query, int $hubId): void { $query->where('hub_id', $hubId); } /** * Scope: Verfügbare Produkte (aktiv, kuratiert, verfügbar). */ public function scopeAvailable(Builder $query): void { $query->active()->curated()->where('is_available', true); } }