""" 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)