Files
thrilltrack-explorer/django/api/v1/endpoints/ride_models.py
pacnpal d6ff4cc3a3 Add email templates for user notifications and account management
- Created a base email template (base.html) for consistent styling across all emails.
- Added moderation approval email template (moderation_approved.html) to notify users of approved submissions.
- Added moderation rejection email template (moderation_rejected.html) to inform users of required changes for their submissions.
- Created password reset email template (password_reset.html) for users requesting to reset their passwords.
- Developed a welcome email template (welcome.html) to greet new users and provide account details and tips for using ThrillWiki.
2025-11-08 15:34:04 -05:00

248 lines
7.1 KiB
Python

"""
Ride Model endpoints for API v1.
Provides CRUD operations for RideModel entities with filtering and search.
"""
from typing import List, Optional
from uuid import UUID
from django.shortcuts import get_object_or_404
from django.db.models import Q
from ninja import Router, Query
from ninja.pagination import paginate, PageNumberPagination
from apps.entities.models import RideModel, Company
from ..schemas import (
RideModelCreate,
RideModelUpdate,
RideModelOut,
RideModelListOut,
ErrorResponse
)
router = Router(tags=["Ride Models"])
class RideModelPagination(PageNumberPagination):
"""Custom pagination for ride models."""
page_size = 50
@router.get(
"/",
response={200: List[RideModelOut]},
summary="List ride models",
description="Get a paginated list of ride models with optional filtering"
)
@paginate(RideModelPagination)
def list_ride_models(
request,
search: Optional[str] = Query(None, description="Search by model name"),
manufacturer_id: Optional[UUID] = Query(None, description="Filter by manufacturer"),
model_type: Optional[str] = Query(None, description="Filter by model type"),
ordering: Optional[str] = Query("-created", description="Sort by field (prefix with - for descending)")
):
"""
List all ride models with optional filters.
**Filters:**
- search: Search model names (case-insensitive partial match)
- manufacturer_id: Filter by manufacturer
- model_type: Filter by model type
- ordering: Sort results (default: -created)
**Returns:** Paginated list of ride models
"""
queryset = RideModel.objects.select_related('manufacturer').all()
# Apply search filter
if search:
queryset = queryset.filter(
Q(name__icontains=search) | Q(description__icontains=search)
)
# Apply manufacturer filter
if manufacturer_id:
queryset = queryset.filter(manufacturer_id=manufacturer_id)
# Apply model type filter
if model_type:
queryset = queryset.filter(model_type=model_type)
# Apply ordering
valid_order_fields = ['name', 'created', 'modified', 'installation_count']
order_field = ordering.lstrip('-')
if order_field in valid_order_fields:
queryset = queryset.order_by(ordering)
else:
queryset = queryset.order_by('-created')
# Annotate with manufacturer name
for model in queryset:
model.manufacturer_name = model.manufacturer.name if model.manufacturer else None
return queryset
@router.get(
"/{model_id}",
response={200: RideModelOut, 404: ErrorResponse},
summary="Get ride model",
description="Retrieve a single ride model by ID"
)
def get_ride_model(request, model_id: UUID):
"""
Get a ride model by ID.
**Parameters:**
- model_id: UUID of the ride model
**Returns:** Ride model details
"""
model = get_object_or_404(RideModel.objects.select_related('manufacturer'), id=model_id)
model.manufacturer_name = model.manufacturer.name if model.manufacturer else None
return model
@router.post(
"/",
response={201: RideModelOut, 400: ErrorResponse, 404: ErrorResponse},
summary="Create ride model",
description="Create a new ride model (requires authentication)"
)
def create_ride_model(request, payload: RideModelCreate):
"""
Create a new ride model.
**Authentication:** Required
**Parameters:**
- payload: Ride model data
**Returns:** Created ride model
"""
# TODO: Add authentication check
# if not request.auth:
# return 401, {"detail": "Authentication required"}
# Verify manufacturer exists
manufacturer = get_object_or_404(Company, id=payload.manufacturer_id)
model = RideModel.objects.create(**payload.dict())
model.manufacturer_name = manufacturer.name
return 201, model
@router.put(
"/{model_id}",
response={200: RideModelOut, 404: ErrorResponse, 400: ErrorResponse},
summary="Update ride model",
description="Update an existing ride model (requires authentication)"
)
def update_ride_model(request, model_id: UUID, payload: RideModelUpdate):
"""
Update a ride model.
**Authentication:** Required
**Parameters:**
- model_id: UUID of the ride model
- payload: Updated ride model data
**Returns:** Updated ride model
"""
# TODO: Add authentication check
# if not request.auth:
# return 401, {"detail": "Authentication required"}
model = get_object_or_404(RideModel.objects.select_related('manufacturer'), id=model_id)
# Update only provided fields
for key, value in payload.dict(exclude_unset=True).items():
setattr(model, key, value)
model.save()
model.manufacturer_name = model.manufacturer.name if model.manufacturer else None
return model
@router.patch(
"/{model_id}",
response={200: RideModelOut, 404: ErrorResponse, 400: ErrorResponse},
summary="Partial update ride model",
description="Partially update an existing ride model (requires authentication)"
)
def partial_update_ride_model(request, model_id: UUID, payload: RideModelUpdate):
"""
Partially update a ride model.
**Authentication:** Required
**Parameters:**
- model_id: UUID of the ride model
- payload: Fields to update
**Returns:** Updated ride model
"""
# TODO: Add authentication check
# if not request.auth:
# return 401, {"detail": "Authentication required"}
model = get_object_or_404(RideModel.objects.select_related('manufacturer'), id=model_id)
# Update only provided fields
for key, value in payload.dict(exclude_unset=True).items():
setattr(model, key, value)
model.save()
model.manufacturer_name = model.manufacturer.name if model.manufacturer else None
return model
@router.delete(
"/{model_id}",
response={204: None, 404: ErrorResponse},
summary="Delete ride model",
description="Delete a ride model (requires authentication)"
)
def delete_ride_model(request, model_id: UUID):
"""
Delete a ride model.
**Authentication:** Required
**Parameters:**
- model_id: UUID of the ride model
**Returns:** No content (204)
"""
# TODO: Add authentication check
# if not request.auth:
# return 401, {"detail": "Authentication required"}
model = get_object_or_404(RideModel, id=model_id)
model.delete()
return 204, None
@router.get(
"/{model_id}/installations",
response={200: List[dict], 404: ErrorResponse},
summary="Get ride model installations",
description="Get all ride installations of this model"
)
def get_ride_model_installations(request, model_id: UUID):
"""
Get all installations of a ride model.
**Parameters:**
- model_id: UUID of the ride model
**Returns:** List of rides using this model
"""
model = get_object_or_404(RideModel, id=model_id)
rides = model.rides.select_related('park').all().values(
'id', 'name', 'slug', 'status', 'park__name', 'park__id'
)
return list(rides)