mirror of
https://github.com/pacnpal/thrillwiki_laravel.git
synced 2025-12-20 06:11:09 -05:00
feat: Implement rides management with CRUD functionality
- Added rides index view with search and filter options. - Created rides show view to display ride details. - Implemented API routes for rides. - Developed authentication routes for user registration, login, and email verification. - Created tests for authentication, email verification, password reset, and user profile management. - Added feature tests for rides and operators, including creation, updating, deletion, and searching. - Implemented soft deletes and caching for rides and operators. - Enhanced manufacturer and operator model tests for various functionalities.
This commit is contained in:
@@ -4,26 +4,34 @@ namespace App\Models;
|
||||
|
||||
use App\Enums\RideCategory;
|
||||
use App\Enums\RideStatus;
|
||||
use App\Traits\HasSlugHistory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class Ride extends Model
|
||||
{
|
||||
use SoftDeletes, HasSlugHistory;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'slug',
|
||||
'description',
|
||||
'status',
|
||||
'category',
|
||||
'opening_date',
|
||||
'closing_date',
|
||||
'park_id',
|
||||
'park_area_id',
|
||||
'manufacturer_id',
|
||||
'designer_id',
|
||||
'ride_model_id',
|
||||
'category',
|
||||
'status',
|
||||
'post_closing_status',
|
||||
'status_since',
|
||||
'opening_date',
|
||||
'closing_date',
|
||||
'min_height_in',
|
||||
'max_height_in',
|
||||
'capacity_per_hour',
|
||||
@@ -35,13 +43,14 @@ class Ride extends Model
|
||||
'category' => RideCategory::class,
|
||||
'opening_date' => 'date',
|
||||
'closing_date' => 'date',
|
||||
'status_since' => 'date',
|
||||
'min_height_in' => 'integer',
|
||||
'max_height_in' => 'integer',
|
||||
'capacity_per_hour' => 'integer',
|
||||
'ride_duration_seconds' => 'integer',
|
||||
];
|
||||
|
||||
// Base Relationships
|
||||
// Core Relationships (Django Parity)
|
||||
public function park(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Park::class);
|
||||
@@ -54,7 +63,7 @@ class Ride extends Model
|
||||
|
||||
public function manufacturer(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Manufacturer::class);
|
||||
return $this->belongsTo(Manufacturer::class, 'manufacturer_id');
|
||||
}
|
||||
|
||||
public function designer(): BelongsTo
|
||||
@@ -67,23 +76,51 @@ class Ride extends Model
|
||||
return $this->belongsTo(RideModel::class);
|
||||
}
|
||||
|
||||
// Extended Relationships
|
||||
public function coasterStats(): HasOne
|
||||
{
|
||||
return $this->hasOne(RollerCoasterStats::class);
|
||||
}
|
||||
|
||||
// Photo Relationships (Polymorphic)
|
||||
public function photos(): MorphMany
|
||||
{
|
||||
return $this->morphMany(Photo::class, 'photosable');
|
||||
}
|
||||
|
||||
// Review Relationships
|
||||
public function reviews(): HasMany
|
||||
public function reviews(): MorphMany
|
||||
{
|
||||
return $this->hasMany(Review::class);
|
||||
return $this->morphMany(Review::class, 'reviewable');
|
||||
}
|
||||
|
||||
public function approvedReviews(): HasMany
|
||||
public function approvedReviews(): MorphMany
|
||||
{
|
||||
return $this->reviews()->approved();
|
||||
return $this->reviews()->where('status', 'approved');
|
||||
}
|
||||
|
||||
// Review Methods
|
||||
// Query Scopes
|
||||
public function scopeActive($query)
|
||||
{
|
||||
return $query->where('status', 'operating');
|
||||
}
|
||||
|
||||
public function scopeByCategory($query, $category)
|
||||
{
|
||||
return $query->where('category', $category);
|
||||
}
|
||||
|
||||
public function scopeInPark($query, $parkId)
|
||||
{
|
||||
return $query->where('park_id', $parkId);
|
||||
}
|
||||
|
||||
public function scopeByManufacturer($query, $manufacturerId)
|
||||
{
|
||||
return $query->where('manufacturer_id', $manufacturerId);
|
||||
}
|
||||
|
||||
// Attributes & Helper Methods
|
||||
public function getAverageRatingAttribute(): ?float
|
||||
{
|
||||
return $this->approvedReviews()->avg('rating');
|
||||
@@ -94,6 +131,32 @@ class Ride extends Model
|
||||
return $this->approvedReviews()->count();
|
||||
}
|
||||
|
||||
public function getDisplayNameAttribute(): string
|
||||
{
|
||||
return $this->name . ' at ' . $this->park->name;
|
||||
}
|
||||
|
||||
public function getIsOperatingAttribute(): bool
|
||||
{
|
||||
return $this->status === RideStatus::OPERATING;
|
||||
}
|
||||
|
||||
public function getHeightRequirementTextAttribute(): ?string
|
||||
{
|
||||
if (!$this->min_height_in) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$text = "Must be at least {$this->min_height_in}\" tall";
|
||||
|
||||
if ($this->max_height_in) {
|
||||
$text .= " and no taller than {$this->max_height_in}\" tall";
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
// Review Management Methods
|
||||
public function canBeReviewedBy(?int $userId): bool
|
||||
{
|
||||
if (!$userId) {
|
||||
@@ -112,7 +175,32 @@ class Ride extends Model
|
||||
'rating' => $data['rating'],
|
||||
'title' => $data['title'] ?? null,
|
||||
'content' => $data['content'],
|
||||
'status' => ReviewStatus::PENDING,
|
||||
'status' => 'pending',
|
||||
]);
|
||||
}
|
||||
|
||||
// Cache Management (Future: will use HasCaching trait)
|
||||
public function getCacheKey(string $suffix = ''): string
|
||||
{
|
||||
return "ride:{$this->id}" . ($suffix ? ":{$suffix}" : '');
|
||||
}
|
||||
|
||||
public function clearRelatedCache(): void
|
||||
{
|
||||
cache()->forget($this->getCacheKey('reviews'));
|
||||
cache()->forget($this->getCacheKey('statistics'));
|
||||
cache()->forget($this->getCacheKey('photos'));
|
||||
}
|
||||
|
||||
// Statistics Management (Future: will use HasStatistics trait)
|
||||
public function updateStatistics(): void
|
||||
{
|
||||
// Placeholder for future HasStatistics trait integration
|
||||
// For now, manually manage statistics
|
||||
$totalReviews = $this->reviews()->count();
|
||||
$averageRating = $this->reviews()->avg('rating');
|
||||
|
||||
// Update any related statistics tracking
|
||||
$this->clearRelatedCache();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user