mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 11:51:14 -05:00
- 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.
248 lines
7.1 KiB
Python
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)
|