RideStatus::class, 'category' => RideCategory::class, 'opening_date' => 'date', 'closing_date' => 'date', 'min_height_in' => 'integer', 'max_height_in' => 'integer', 'capacity_per_hour' => 'integer', 'ride_duration_seconds' => 'integer', ]; // Base Relationships public function park(): BelongsTo { return $this->belongsTo(Park::class); } public function parkArea(): BelongsTo { return $this->belongsTo(ParkArea::class); } public function manufacturer(): BelongsTo { return $this->belongsTo(Manufacturer::class); } public function designer(): BelongsTo { return $this->belongsTo(Designer::class); } public function rideModel(): BelongsTo { return $this->belongsTo(RideModel::class); } public function coasterStats(): HasOne { return $this->hasOne(RollerCoasterStats::class); } // Review Relationships public function reviews(): HasMany { return $this->hasMany(Review::class); } public function approvedReviews(): HasMany { return $this->reviews()->approved(); } // Review Methods public function getAverageRatingAttribute(): ?float { return $this->approvedReviews()->avg('rating'); } public function getReviewCountAttribute(): int { return $this->approvedReviews()->count(); } public function canBeReviewedBy(?int $userId): bool { if (!$userId) { return false; } return !$this->reviews() ->where('user_id', $userId) ->exists(); } public function addReview(array $data): Review { return $this->reviews()->create([ 'user_id' => Auth::id(), 'rating' => $data['rating'], 'title' => $data['title'] ?? null, 'content' => $data['content'], 'status' => ReviewStatus::PENDING, ]); } }