Refactor test utilities and enhance ASGI settings

- Cleaned up and standardized assertions in ApiTestMixin for API response validation.
- Updated ASGI settings to use os.environ for setting the DJANGO_SETTINGS_MODULE.
- Removed unused imports and improved formatting in settings.py.
- Refactored URL patterns in urls.py for better readability and organization.
- Enhanced view functions in views.py for consistency and clarity.
- Added .flake8 configuration for linting and style enforcement.
- Introduced type stubs for django-environ to improve type checking with Pylance.
This commit is contained in:
pacnpal
2025-08-20 19:51:59 -04:00
parent 69c07d1381
commit 66ed4347a9
230 changed files with 15094 additions and 11578 deletions

View File

@@ -6,7 +6,6 @@ Following Django styleguide pattern for business logic encapsulation.
from typing import Optional, Dict, Any, TYPE_CHECKING
from django.db import transaction
from django.db.models import Q
from django.core.exceptions import ValidationError
if TYPE_CHECKING:
from django.contrib.auth.models import AbstractUser
@@ -32,11 +31,11 @@ class ParkService:
size_acres: Optional[float] = None,
website: str = "",
location_data: Optional[Dict[str, Any]] = None,
created_by: Optional['AbstractUser'] = None
created_by: Optional["AbstractUser"] = None,
) -> Park:
"""
Create a new park with validation and location handling.
Args:
name: Park name
description: Park description
@@ -50,10 +49,10 @@ class ParkService:
website: Park website URL
location_data: Dictionary containing location information
created_by: User creating the park
Returns:
Created Park instance
Raises:
ValidationError: If park data is invalid
"""
@@ -67,16 +66,18 @@ class ParkService:
closing_date=closing_date,
operating_season=operating_season,
size_acres=size_acres,
website=website
website=website,
)
# Set foreign key relationships if provided
if operator_id:
from parks.models import Company
park.operator = Company.objects.get(id=operator_id)
if property_owner_id:
from parks.models import Company
park.property_owner = Company.objects.get(id=property_owner_id)
# CRITICAL STYLEGUIDE FIX: Call full_clean before save
@@ -85,10 +86,7 @@ class ParkService:
# Handle location if provided
if location_data:
LocationService.create_park_location(
park=park,
**location_data
)
LocationService.create_park_location(park=park, **location_data)
return park
@@ -97,19 +95,19 @@ class ParkService:
*,
park_id: int,
updates: Dict[str, Any],
updated_by: Optional['AbstractUser'] = None
updated_by: Optional["AbstractUser"] = None,
) -> Park:
"""
Update an existing park with validation.
Args:
park_id: ID of park to update
updates: Dictionary of field updates
updated_by: User performing the update
Returns:
Updated Park instance
Raises:
Park.DoesNotExist: If park doesn't exist
ValidationError: If update data is invalid
@@ -129,23 +127,25 @@ class ParkService:
return park
@staticmethod
def delete_park(*, park_id: int, deleted_by: Optional['AbstractUser'] = None) -> bool:
def delete_park(
*, park_id: int, deleted_by: Optional["AbstractUser"] = None
) -> bool:
"""
Soft delete a park by setting status to DEMOLISHED.
Args:
park_id: ID of park to delete
deleted_by: User performing the deletion
Returns:
True if successfully deleted
Raises:
Park.DoesNotExist: If park doesn't exist
"""
with transaction.atomic():
park = Park.objects.select_for_update().get(id=park_id)
park.status = 'DEMOLISHED'
park.status = "DEMOLISHED"
# CRITICAL STYLEGUIDE FIX: Call full_clean before save
park.full_clean()
@@ -159,31 +159,27 @@ class ParkService:
park_id: int,
name: str,
description: str = "",
created_by: Optional['AbstractUser'] = None
created_by: Optional["AbstractUser"] = None,
) -> ParkArea:
"""
Create a new area within a park.
Args:
park_id: ID of the parent park
name: Area name
description: Area description
created_by: User creating the area
Returns:
Created ParkArea instance
Raises:
Park.DoesNotExist: If park doesn't exist
ValidationError: If area data is invalid
"""
park = Park.objects.get(id=park_id)
area = ParkArea(
park=park,
name=name,
description=description
)
area = ParkArea(park=park, name=name, description=description)
# CRITICAL STYLEGUIDE FIX: Call full_clean before save
area.full_clean()
@@ -195,10 +191,10 @@ class ParkService:
def update_park_statistics(*, park_id: int) -> Park:
"""
Recalculate and update park statistics (ride counts, ratings).
Args:
park_id: ID of park to update statistics for
Returns:
Updated Park instance with fresh statistics
"""
@@ -211,19 +207,18 @@ class ParkService:
# Calculate ride counts
ride_stats = Ride.objects.filter(park=park).aggregate(
total_rides=Count('id'),
coaster_count=Count('id', filter=Q(category__in=['RC', 'WC']))
total_rides=Count("id"),
coaster_count=Count("id", filter=Q(category__in=["RC", "WC"])),
)
# Calculate average rating
avg_rating = ParkReview.objects.filter(
park=park,
is_published=True
).aggregate(avg_rating=Avg('rating'))['avg_rating']
park=park, is_published=True
).aggregate(avg_rating=Avg("rating"))["avg_rating"]
# Update park fields
park.ride_count = ride_stats['total_rides'] or 0
park.coaster_count = ride_stats['coaster_count'] or 0
park.ride_count = ride_stats["total_rides"] or 0
park.coaster_count = ride_stats["coaster_count"] or 0
park.average_rating = avg_rating
# CRITICAL STYLEGUIDE FIX: Call full_clean before save
@@ -246,11 +241,11 @@ class LocationService:
city: str = "",
state: str = "",
country: str = "",
postal_code: str = ""
postal_code: str = "",
) -> Location:
"""
Create a location for a park.
Args:
park: Park instance
latitude: Latitude coordinate
@@ -260,24 +255,24 @@ class LocationService:
state: State/region name
country: Country name
postal_code: Postal/ZIP code
Returns:
Created Location instance
Raises:
ValidationError: If location data is invalid
"""
location = Location(
content_object=park,
name=park.name,
location_type='park',
location_type="park",
latitude=latitude,
longitude=longitude,
street_address=street_address,
city=city,
state=state,
country=country,
postal_code=postal_code
postal_code=postal_code,
)
# CRITICAL STYLEGUIDE FIX: Call full_clean before save
@@ -288,20 +283,18 @@ class LocationService:
@staticmethod
def update_park_location(
*,
park_id: int,
location_updates: Dict[str, Any]
*, park_id: int, location_updates: Dict[str, Any]
) -> Location:
"""
Update location information for a park.
Args:
park_id: ID of the park
location_updates: Dictionary of location field updates
Returns:
Updated Location instance
Raises:
Location.DoesNotExist: If location doesn't exist
ValidationError: If location data is invalid
@@ -314,8 +307,7 @@ class LocationService:
except Location.DoesNotExist:
# Create location if it doesn't exist
return LocationService.create_park_location(
park=park,
**location_updates
park=park, **location_updates
)
# Apply updates