mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2026-01-02 01:27:03 -05:00
feat: Implement initial schema and add various API, service, and management command enhancements across the application.
This commit is contained in:
@@ -81,23 +81,15 @@ class RideListOutputSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField()
|
||||
name = serializers.CharField()
|
||||
slug = serializers.CharField()
|
||||
category = RichChoiceFieldSerializer(
|
||||
choice_group="categories",
|
||||
domain="rides"
|
||||
)
|
||||
status = RichChoiceFieldSerializer(
|
||||
choice_group="statuses",
|
||||
domain="rides"
|
||||
)
|
||||
category = RichChoiceFieldSerializer(choice_group="categories", domain="rides")
|
||||
status = RichChoiceFieldSerializer(choice_group="statuses", domain="rides")
|
||||
description = serializers.CharField()
|
||||
|
||||
# Park info
|
||||
park = RideParkOutputSerializer()
|
||||
|
||||
# Statistics
|
||||
average_rating = serializers.DecimalField(
|
||||
max_digits=3, decimal_places=2, allow_null=True
|
||||
)
|
||||
average_rating = serializers.DecimalField(max_digits=3, decimal_places=2, allow_null=True)
|
||||
capacity_per_hour = serializers.IntegerField(allow_null=True)
|
||||
|
||||
# Dates
|
||||
@@ -178,18 +170,10 @@ class RideDetailOutputSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField()
|
||||
name = serializers.CharField()
|
||||
slug = serializers.CharField()
|
||||
category = RichChoiceFieldSerializer(
|
||||
choice_group="categories",
|
||||
domain="rides"
|
||||
)
|
||||
status = RichChoiceFieldSerializer(
|
||||
choice_group="statuses",
|
||||
domain="rides"
|
||||
)
|
||||
category = RichChoiceFieldSerializer(choice_group="categories", domain="rides")
|
||||
status = RichChoiceFieldSerializer(choice_group="statuses", domain="rides")
|
||||
post_closing_status = RichChoiceFieldSerializer(
|
||||
choice_group="post_closing_statuses",
|
||||
domain="rides",
|
||||
allow_null=True
|
||||
choice_group="post_closing_statuses", domain="rides", allow_null=True
|
||||
)
|
||||
description = serializers.CharField()
|
||||
|
||||
@@ -209,9 +193,7 @@ class RideDetailOutputSerializer(serializers.Serializer):
|
||||
ride_duration_seconds = serializers.IntegerField(allow_null=True)
|
||||
|
||||
# Statistics
|
||||
average_rating = serializers.DecimalField(
|
||||
max_digits=3, decimal_places=2, allow_null=True
|
||||
)
|
||||
average_rating = serializers.DecimalField(max_digits=3, decimal_places=2, allow_null=True)
|
||||
|
||||
# Companies
|
||||
manufacturer = serializers.SerializerMethodField()
|
||||
@@ -273,9 +255,7 @@ class RideDetailOutputSerializer(serializers.Serializer):
|
||||
"""Get all approved photos for this ride."""
|
||||
from apps.rides.models import RidePhoto
|
||||
|
||||
photos = RidePhoto.objects.filter(ride=obj, is_approved=True).order_by(
|
||||
"-is_primary", "-created_at"
|
||||
)[
|
||||
photos = RidePhoto.objects.filter(ride=obj, is_approved=True).order_by("-is_primary", "-created_at")[
|
||||
:10
|
||||
] # Limit to 10 photos
|
||||
|
||||
@@ -285,9 +265,7 @@ class RideDetailOutputSerializer(serializers.Serializer):
|
||||
"image_url": photo.image.url if photo.image else None,
|
||||
"image_variants": (
|
||||
{
|
||||
"thumbnail": (
|
||||
f"{photo.image.url}/thumbnail" if photo.image else None
|
||||
),
|
||||
"thumbnail": (f"{photo.image.url}/thumbnail" if photo.image else None),
|
||||
"medium": f"{photo.image.url}/medium" if photo.image else None,
|
||||
"large": f"{photo.image.url}/large" if photo.image else None,
|
||||
"public": f"{photo.image.url}/public" if photo.image else None,
|
||||
@@ -309,9 +287,7 @@ class RideDetailOutputSerializer(serializers.Serializer):
|
||||
from apps.rides.models import RidePhoto
|
||||
|
||||
try:
|
||||
photo = RidePhoto.objects.filter(
|
||||
ride=obj, is_primary=True, is_approved=True
|
||||
).first()
|
||||
photo = RidePhoto.objects.filter(ride=obj, is_primary=True, is_approved=True).first()
|
||||
|
||||
if photo and photo.image:
|
||||
return {
|
||||
@@ -356,9 +332,7 @@ class RideDetailOutputSerializer(serializers.Serializer):
|
||||
|
||||
try:
|
||||
latest_photo = (
|
||||
RidePhoto.objects.filter(
|
||||
ride=obj, is_approved=True, image__isnull=False
|
||||
)
|
||||
RidePhoto.objects.filter(ride=obj, is_approved=True, image__isnull=False)
|
||||
.order_by("-created_at")
|
||||
.first()
|
||||
)
|
||||
@@ -407,9 +381,7 @@ class RideDetailOutputSerializer(serializers.Serializer):
|
||||
|
||||
try:
|
||||
latest_photo = (
|
||||
RidePhoto.objects.filter(
|
||||
ride=obj, is_approved=True, image__isnull=False
|
||||
)
|
||||
RidePhoto.objects.filter(ride=obj, is_approved=True, image__isnull=False)
|
||||
.order_by("-created_at")
|
||||
.first()
|
||||
)
|
||||
@@ -451,7 +423,7 @@ class RideImageSettingsInputSerializer(serializers.Serializer):
|
||||
# The ride will be validated in the view
|
||||
return value
|
||||
except RidePhoto.DoesNotExist:
|
||||
raise serializers.ValidationError("Photo not found")
|
||||
raise serializers.ValidationError("Photo not found") from None
|
||||
return value
|
||||
|
||||
def validate_card_image_id(self, value):
|
||||
@@ -464,7 +436,7 @@ class RideImageSettingsInputSerializer(serializers.Serializer):
|
||||
# The ride will be validated in the view
|
||||
return value
|
||||
except RidePhoto.DoesNotExist:
|
||||
raise serializers.ValidationError("Photo not found")
|
||||
raise serializers.ValidationError("Photo not found") from None
|
||||
return value
|
||||
|
||||
|
||||
@@ -474,9 +446,7 @@ class RideCreateInputSerializer(serializers.Serializer):
|
||||
name = serializers.CharField(max_length=255)
|
||||
description = serializers.CharField(allow_blank=True, default="")
|
||||
category = serializers.ChoiceField(choices=ModelChoices.get_ride_category_choices())
|
||||
status = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_ride_status_choices(), default="OPERATING"
|
||||
)
|
||||
status = serializers.ChoiceField(choices=ModelChoices.get_ride_status_choices(), default="OPERATING")
|
||||
|
||||
# Required park
|
||||
park_id = serializers.IntegerField()
|
||||
@@ -490,18 +460,10 @@ class RideCreateInputSerializer(serializers.Serializer):
|
||||
status_since = serializers.DateField(required=False, allow_null=True)
|
||||
|
||||
# Optional specs
|
||||
min_height_in = serializers.IntegerField(
|
||||
required=False, allow_null=True, min_value=30, max_value=90
|
||||
)
|
||||
max_height_in = serializers.IntegerField(
|
||||
required=False, allow_null=True, min_value=30, max_value=90
|
||||
)
|
||||
capacity_per_hour = serializers.IntegerField(
|
||||
required=False, allow_null=True, min_value=1
|
||||
)
|
||||
ride_duration_seconds = serializers.IntegerField(
|
||||
required=False, allow_null=True, min_value=1
|
||||
)
|
||||
min_height_in = serializers.IntegerField(required=False, allow_null=True, min_value=30, max_value=90)
|
||||
max_height_in = serializers.IntegerField(required=False, allow_null=True, min_value=30, max_value=90)
|
||||
capacity_per_hour = serializers.IntegerField(required=False, allow_null=True, min_value=1)
|
||||
ride_duration_seconds = serializers.IntegerField(required=False, allow_null=True, min_value=1)
|
||||
|
||||
# Optional companies
|
||||
manufacturer_id = serializers.IntegerField(required=False, allow_null=True)
|
||||
@@ -517,18 +479,14 @@ class RideCreateInputSerializer(serializers.Serializer):
|
||||
closing_date = attrs.get("closing_date")
|
||||
|
||||
if opening_date and closing_date and closing_date < opening_date:
|
||||
raise serializers.ValidationError(
|
||||
"Closing date cannot be before opening date"
|
||||
)
|
||||
raise serializers.ValidationError("Closing date cannot be before opening date")
|
||||
|
||||
# Height validation
|
||||
min_height = attrs.get("min_height_in")
|
||||
max_height = attrs.get("max_height_in")
|
||||
|
||||
if min_height and max_height and min_height > max_height:
|
||||
raise serializers.ValidationError(
|
||||
"Minimum height cannot be greater than maximum height"
|
||||
)
|
||||
raise serializers.ValidationError("Minimum height cannot be greater than maximum height")
|
||||
|
||||
# Park area validation when park changes
|
||||
park_id = attrs.get("park_id")
|
||||
@@ -537,6 +495,7 @@ class RideCreateInputSerializer(serializers.Serializer):
|
||||
if park_id and park_area_id:
|
||||
try:
|
||||
from apps.parks.models import ParkArea
|
||||
|
||||
park_area = ParkArea.objects.get(id=park_area_id)
|
||||
if park_area.park_id != park_id:
|
||||
raise serializers.ValidationError(
|
||||
@@ -554,12 +513,8 @@ class RideUpdateInputSerializer(serializers.Serializer):
|
||||
|
||||
name = serializers.CharField(max_length=255, required=False)
|
||||
description = serializers.CharField(allow_blank=True, required=False)
|
||||
category = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_ride_category_choices(), required=False
|
||||
)
|
||||
status = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_ride_status_choices(), required=False
|
||||
)
|
||||
category = serializers.ChoiceField(choices=ModelChoices.get_ride_category_choices(), required=False)
|
||||
status = serializers.ChoiceField(choices=ModelChoices.get_ride_status_choices(), required=False)
|
||||
post_closing_status = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_ride_post_closing_choices(),
|
||||
required=False,
|
||||
@@ -576,18 +531,10 @@ class RideUpdateInputSerializer(serializers.Serializer):
|
||||
status_since = serializers.DateField(required=False, allow_null=True)
|
||||
|
||||
# Specs
|
||||
min_height_in = serializers.IntegerField(
|
||||
required=False, allow_null=True, min_value=30, max_value=90
|
||||
)
|
||||
max_height_in = serializers.IntegerField(
|
||||
required=False, allow_null=True, min_value=30, max_value=90
|
||||
)
|
||||
capacity_per_hour = serializers.IntegerField(
|
||||
required=False, allow_null=True, min_value=1
|
||||
)
|
||||
ride_duration_seconds = serializers.IntegerField(
|
||||
required=False, allow_null=True, min_value=1
|
||||
)
|
||||
min_height_in = serializers.IntegerField(required=False, allow_null=True, min_value=30, max_value=90)
|
||||
max_height_in = serializers.IntegerField(required=False, allow_null=True, min_value=30, max_value=90)
|
||||
capacity_per_hour = serializers.IntegerField(required=False, allow_null=True, min_value=1)
|
||||
ride_duration_seconds = serializers.IntegerField(required=False, allow_null=True, min_value=1)
|
||||
|
||||
# Companies
|
||||
manufacturer_id = serializers.IntegerField(required=False, allow_null=True)
|
||||
@@ -603,18 +550,14 @@ class RideUpdateInputSerializer(serializers.Serializer):
|
||||
closing_date = attrs.get("closing_date")
|
||||
|
||||
if opening_date and closing_date and closing_date < opening_date:
|
||||
raise serializers.ValidationError(
|
||||
"Closing date cannot be before opening date"
|
||||
)
|
||||
raise serializers.ValidationError("Closing date cannot be before opening date")
|
||||
|
||||
# Height validation
|
||||
min_height = attrs.get("min_height_in")
|
||||
max_height = attrs.get("max_height_in")
|
||||
|
||||
if min_height and max_height and min_height > max_height:
|
||||
raise serializers.ValidationError(
|
||||
"Minimum height cannot be greater than maximum height"
|
||||
)
|
||||
raise serializers.ValidationError("Minimum height cannot be greater than maximum height")
|
||||
|
||||
return attrs
|
||||
|
||||
@@ -626,9 +569,7 @@ class RideFilterInputSerializer(serializers.Serializer):
|
||||
search = serializers.CharField(required=False, allow_blank=True)
|
||||
|
||||
# Category filter
|
||||
category = serializers.MultipleChoiceField(
|
||||
choices=ModelChoices.get_ride_category_choices(), required=False
|
||||
)
|
||||
category = serializers.MultipleChoiceField(choices=ModelChoices.get_ride_category_choices(), required=False)
|
||||
|
||||
# Status filter
|
||||
status = serializers.MultipleChoiceField(
|
||||
@@ -707,33 +648,16 @@ class RollerCoasterStatsOutputSerializer(serializers.Serializer):
|
||||
"""Output serializer for roller coaster statistics."""
|
||||
|
||||
id = serializers.IntegerField()
|
||||
height_ft = serializers.DecimalField(
|
||||
max_digits=6, decimal_places=2, allow_null=True
|
||||
)
|
||||
length_ft = serializers.DecimalField(
|
||||
max_digits=7, decimal_places=2, allow_null=True
|
||||
)
|
||||
speed_mph = serializers.DecimalField(
|
||||
max_digits=5, decimal_places=2, allow_null=True
|
||||
)
|
||||
height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True)
|
||||
length_ft = serializers.DecimalField(max_digits=7, decimal_places=2, allow_null=True)
|
||||
speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, allow_null=True)
|
||||
inversions = serializers.IntegerField()
|
||||
ride_time_seconds = serializers.IntegerField(allow_null=True)
|
||||
track_type = serializers.CharField()
|
||||
track_material = RichChoiceFieldSerializer(
|
||||
choice_group="track_materials",
|
||||
domain="rides"
|
||||
)
|
||||
roller_coaster_type = RichChoiceFieldSerializer(
|
||||
choice_group="coaster_types",
|
||||
domain="rides"
|
||||
)
|
||||
max_drop_height_ft = serializers.DecimalField(
|
||||
max_digits=6, decimal_places=2, allow_null=True
|
||||
)
|
||||
propulsion_system = RichChoiceFieldSerializer(
|
||||
choice_group="propulsion_systems",
|
||||
domain="rides"
|
||||
)
|
||||
track_material = RichChoiceFieldSerializer(choice_group="track_materials", domain="rides")
|
||||
roller_coaster_type = RichChoiceFieldSerializer(choice_group="coaster_types", domain="rides")
|
||||
max_drop_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, allow_null=True)
|
||||
propulsion_system = RichChoiceFieldSerializer(choice_group="propulsion_systems", domain="rides")
|
||||
train_style = serializers.CharField()
|
||||
trains_count = serializers.IntegerField(allow_null=True)
|
||||
cars_per_train = serializers.IntegerField(allow_null=True)
|
||||
@@ -755,30 +679,16 @@ class RollerCoasterStatsCreateInputSerializer(serializers.Serializer):
|
||||
"""Input serializer for creating roller coaster statistics."""
|
||||
|
||||
ride_id = serializers.IntegerField()
|
||||
height_ft = serializers.DecimalField(
|
||||
max_digits=6, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
length_ft = serializers.DecimalField(
|
||||
max_digits=7, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
speed_mph = serializers.DecimalField(
|
||||
max_digits=5, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, required=False, allow_null=True)
|
||||
length_ft = serializers.DecimalField(max_digits=7, decimal_places=2, required=False, allow_null=True)
|
||||
speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, required=False, allow_null=True)
|
||||
inversions = serializers.IntegerField(default=0)
|
||||
ride_time_seconds = serializers.IntegerField(required=False, allow_null=True)
|
||||
track_type = serializers.CharField(max_length=255, allow_blank=True, default="")
|
||||
track_material = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_coaster_track_choices(), default="STEEL"
|
||||
)
|
||||
roller_coaster_type = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_coaster_type_choices(), default="SITDOWN"
|
||||
)
|
||||
max_drop_height_ft = serializers.DecimalField(
|
||||
max_digits=6, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
propulsion_system = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_propulsion_system_choices(), default="CHAIN"
|
||||
)
|
||||
track_material = serializers.ChoiceField(choices=ModelChoices.get_coaster_track_choices(), default="STEEL")
|
||||
roller_coaster_type = serializers.ChoiceField(choices=ModelChoices.get_coaster_type_choices(), default="SITDOWN")
|
||||
max_drop_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, required=False, allow_null=True)
|
||||
propulsion_system = serializers.ChoiceField(choices=ModelChoices.get_propulsion_system_choices(), default="CHAIN")
|
||||
train_style = serializers.CharField(max_length=255, allow_blank=True, default="")
|
||||
trains_count = serializers.IntegerField(required=False, allow_null=True)
|
||||
cars_per_train = serializers.IntegerField(required=False, allow_null=True)
|
||||
@@ -788,33 +698,17 @@ class RollerCoasterStatsCreateInputSerializer(serializers.Serializer):
|
||||
class RollerCoasterStatsUpdateInputSerializer(serializers.Serializer):
|
||||
"""Input serializer for updating roller coaster statistics."""
|
||||
|
||||
height_ft = serializers.DecimalField(
|
||||
max_digits=6, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
length_ft = serializers.DecimalField(
|
||||
max_digits=7, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
speed_mph = serializers.DecimalField(
|
||||
max_digits=5, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, required=False, allow_null=True)
|
||||
length_ft = serializers.DecimalField(max_digits=7, decimal_places=2, required=False, allow_null=True)
|
||||
speed_mph = serializers.DecimalField(max_digits=5, decimal_places=2, required=False, allow_null=True)
|
||||
inversions = serializers.IntegerField(required=False)
|
||||
ride_time_seconds = serializers.IntegerField(required=False, allow_null=True)
|
||||
track_type = serializers.CharField(max_length=255, allow_blank=True, required=False)
|
||||
track_material = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_coaster_track_choices(), required=False
|
||||
)
|
||||
roller_coaster_type = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_coaster_type_choices(), required=False
|
||||
)
|
||||
max_drop_height_ft = serializers.DecimalField(
|
||||
max_digits=6, decimal_places=2, required=False, allow_null=True
|
||||
)
|
||||
propulsion_system = serializers.ChoiceField(
|
||||
choices=ModelChoices.get_propulsion_system_choices(), required=False
|
||||
)
|
||||
train_style = serializers.CharField(
|
||||
max_length=255, allow_blank=True, required=False
|
||||
)
|
||||
track_material = serializers.ChoiceField(choices=ModelChoices.get_coaster_track_choices(), required=False)
|
||||
roller_coaster_type = serializers.ChoiceField(choices=ModelChoices.get_coaster_type_choices(), required=False)
|
||||
max_drop_height_ft = serializers.DecimalField(max_digits=6, decimal_places=2, required=False, allow_null=True)
|
||||
propulsion_system = serializers.ChoiceField(choices=ModelChoices.get_propulsion_system_choices(), required=False)
|
||||
train_style = serializers.CharField(max_length=255, allow_blank=True, required=False)
|
||||
trains_count = serializers.IntegerField(required=False, allow_null=True)
|
||||
cars_per_train = serializers.IntegerField(required=False, allow_null=True)
|
||||
seats_per_car = serializers.IntegerField(required=False, allow_null=True)
|
||||
|
||||
Reference in New Issue
Block a user