first commit

This commit is contained in:
pacnpal
2024-10-28 17:09:57 -04:00
commit 1339baec59
9993 changed files with 1182741 additions and 0 deletions

0
companies/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

17
companies/admin.py Normal file
View File

@@ -0,0 +1,17 @@
from django.contrib import admin
from simple_history.admin import SimpleHistoryAdmin
from .models import Company, Manufacturer
@admin.register(Company)
class CompanyAdmin(SimpleHistoryAdmin):
list_display = ('name', 'headquarters', 'website', 'created_at')
search_fields = ('name', 'headquarters', 'description')
prepopulated_fields = {'slug': ('name',)}
readonly_fields = ('created_at', 'updated_at')
@admin.register(Manufacturer)
class ManufacturerAdmin(SimpleHistoryAdmin):
list_display = ('name', 'headquarters', 'website', 'created_at')
search_fields = ('name', 'headquarters', 'description')
prepopulated_fields = {'slug': ('name',)}
readonly_fields = ('created_at', 'updated_at')

9
companies/apps.py Normal file
View File

@@ -0,0 +1,9 @@
from django.apps import AppConfig
class CompaniesConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'companies'
verbose_name = 'Companies'
def ready(self):
import companies.signals # noqa

View File

@@ -0,0 +1,105 @@
# Generated by Django 5.1.2 on 2024-10-28 20:17
import django.db.models.deletion
import simple_history.models
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Company',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('slug', models.SlugField(max_length=255, unique=True)),
('headquarters', models.CharField(blank=True, max_length=255)),
('description', models.TextField(blank=True)),
('website', models.URLField(blank=True)),
('founded_date', models.DateField(blank=True, null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
options={
'verbose_name_plural': 'companies',
'ordering': ['name'],
},
),
migrations.CreateModel(
name='Manufacturer',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('slug', models.SlugField(max_length=255, unique=True)),
('headquarters', models.CharField(blank=True, max_length=255)),
('description', models.TextField(blank=True)),
('website', models.URLField(blank=True)),
('founded_date', models.DateField(blank=True, null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
],
options={
'ordering': ['name'],
},
),
migrations.CreateModel(
name='HistoricalCompany',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('slug', models.SlugField(max_length=255)),
('headquarters', models.CharField(blank=True, max_length=255)),
('description', models.TextField(blank=True)),
('website', models.URLField(blank=True)),
('founded_date', models.DateField(blank=True, null=True)),
('created_at', models.DateTimeField(blank=True, editable=False)),
('updated_at', models.DateTimeField(blank=True, editable=False)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical company',
'verbose_name_plural': 'historical companies',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
migrations.CreateModel(
name='HistoricalManufacturer',
fields=[
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('slug', models.SlugField(max_length=255)),
('headquarters', models.CharField(blank=True, max_length=255)),
('description', models.TextField(blank=True)),
('website', models.URLField(blank=True)),
('founded_date', models.DateField(blank=True, null=True)),
('created_at', models.DateTimeField(blank=True, editable=False)),
('updated_at', models.DateTimeField(blank=True, editable=False)),
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField(db_index=True)),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'historical manufacturer',
'verbose_name_plural': 'historical manufacturers',
'ordering': ('-history_date', '-history_id'),
'get_latest_by': ('history_date', 'history_id'),
},
bases=(simple_history.models.HistoricalChanges, models.Model),
),
]

View File

@@ -0,0 +1,53 @@
# Generated by Django 5.1.2 on 2024-10-28 20:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('companies', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='company',
name='total_parks',
field=models.PositiveIntegerField(default=0),
),
migrations.AddField(
model_name='company',
name='total_rides',
field=models.PositiveIntegerField(default=0),
),
migrations.AddField(
model_name='historicalcompany',
name='total_parks',
field=models.PositiveIntegerField(default=0),
),
migrations.AddField(
model_name='historicalcompany',
name='total_rides',
field=models.PositiveIntegerField(default=0),
),
migrations.AddField(
model_name='historicalmanufacturer',
name='total_rides',
field=models.PositiveIntegerField(default=0),
),
migrations.AddField(
model_name='historicalmanufacturer',
name='total_roller_coasters',
field=models.PositiveIntegerField(default=0),
),
migrations.AddField(
model_name='manufacturer',
name='total_rides',
field=models.PositiveIntegerField(default=0),
),
migrations.AddField(
model_name='manufacturer',
name='total_roller_coasters',
field=models.PositiveIntegerField(default=0),
),
]

View File

83
companies/models.py Normal file
View File

@@ -0,0 +1,83 @@
from django.db import models
from django.contrib.contenttypes.fields import GenericRelation
from django.utils.text import slugify
from simple_history.models import HistoricalRecords
class Company(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
headquarters = models.CharField(max_length=255, blank=True)
description = models.TextField(blank=True)
website = models.URLField(blank=True)
founded_date = models.DateField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
photos = GenericRelation('media.Photo')
history = HistoricalRecords()
# Stats fields
total_parks = models.PositiveIntegerField(default=0)
total_rides = models.PositiveIntegerField(default=0)
class Meta:
verbose_name_plural = "companies"
ordering = ['name']
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
@classmethod
def get_by_slug(cls, slug):
"""Get company by current or historical slug"""
try:
return cls.objects.get(slug=slug), False
except cls.DoesNotExist:
# Check historical slugs
history = cls.history.filter(slug=slug).order_by('-history_date').first()
if history:
return cls.objects.get(id=history.id), True
raise cls.DoesNotExist("No company found with this slug")
class Manufacturer(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
headquarters = models.CharField(max_length=255, blank=True)
description = models.TextField(blank=True)
website = models.URLField(blank=True)
founded_date = models.DateField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
photos = GenericRelation('media.Photo')
history = HistoricalRecords()
# Stats fields
total_rides = models.PositiveIntegerField(default=0)
total_roller_coasters = models.PositiveIntegerField(default=0)
class Meta:
ordering = ['name']
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
@classmethod
def get_by_slug(cls, slug):
"""Get manufacturer by current or historical slug"""
try:
return cls.objects.get(slug=slug), False
except cls.DoesNotExist:
# Check historical slugs
history = cls.history.filter(slug=slug).order_by('-history_date').first()
if history:
return cls.objects.get(id=history.id), True
raise cls.DoesNotExist("No manufacturer found with this slug")

41
companies/signals.py Normal file
View File

@@ -0,0 +1,41 @@
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from parks.models import Park
from rides.models import Ride
from .models import Company, Manufacturer
@receiver([post_save, post_delete], sender=Park)
def update_company_stats(sender, instance, **kwargs):
"""Update company statistics when a park is added, modified, or deleted."""
if instance.owner:
# Update total parks
total_parks = Park.objects.filter(owner=instance.owner).count()
total_rides = Ride.objects.filter(park__owner=instance.owner).count()
Company.objects.filter(id=instance.owner.id).update(
total_parks=total_parks,
total_rides=total_rides
)
@receiver([post_save, post_delete], sender=Ride)
def update_manufacturer_stats(sender, instance, **kwargs):
"""Update manufacturer statistics when a ride is added, modified, or deleted."""
if instance.manufacturer:
# Update total rides and roller coasters
total_rides = Ride.objects.filter(manufacturer=instance.manufacturer).count()
total_roller_coasters = Ride.objects.filter(
manufacturer=instance.manufacturer,
category='RC'
).count()
Manufacturer.objects.filter(id=instance.manufacturer.id).update(
total_rides=total_rides,
total_roller_coasters=total_roller_coasters
)
@receiver(post_save, sender=Ride)
def update_company_ride_stats(sender, instance, **kwargs):
"""Update company ride statistics when a ride is added or modified."""
if instance.park and instance.park.owner:
total_rides = Ride.objects.filter(park__owner=instance.park.owner).count()
Company.objects.filter(id=instance.park.owner.id).update(total_rides=total_rides)

3
companies/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

14
companies/urls.py Normal file
View File

@@ -0,0 +1,14 @@
from django.urls import path
from . import views
app_name = 'companies'
urlpatterns = [
# Company URLs
path('', views.CompanyListView.as_view(), name='company_list'),
path('<slug:slug>/', views.CompanyDetailView.as_view(), name='company_detail'),
# Manufacturer URLs
path('manufacturers/', views.ManufacturerListView.as_view(), name='manufacturer_list'),
path('manufacturers/<slug:slug>/', views.ManufacturerDetailView.as_view(), name='manufacturer_detail'),
]

105
companies/views.py Normal file
View File

@@ -0,0 +1,105 @@
from django.views.generic import DetailView, ListView
from django.shortcuts import get_object_or_404
from .models import Company, Manufacturer
from rides.models import Ride
from parks.models import Park
from core.views import SlugRedirectMixin
class CompanyDetailView(SlugRedirectMixin, DetailView):
model = Company
template_name = 'companies/company_detail.html'
context_object_name = 'company'
def get_object(self, queryset=None):
if queryset is None:
queryset = self.get_queryset()
slug = self.kwargs.get(self.slug_url_kwarg)
# Try to get by current or historical slug
return self.model.get_by_slug(slug)[0]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['parks'] = Park.objects.filter(
owner=self.object
).select_related('owner')
return context
def get_redirect_url_pattern(self):
return 'company_detail'
class ManufacturerDetailView(SlugRedirectMixin, DetailView):
model = Manufacturer
template_name = 'companies/manufacturer_detail.html'
context_object_name = 'manufacturer'
def get_object(self, queryset=None):
if queryset is None:
queryset = self.get_queryset()
slug = self.kwargs.get(self.slug_url_kwarg)
# Try to get by current or historical slug
return self.model.get_by_slug(slug)[0]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['rides'] = Ride.objects.filter(
manufacturer=self.object
).select_related('park', 'coaster_stats')
return context
def get_redirect_url_pattern(self):
return 'manufacturer_detail'
class CompanyListView(ListView):
model = Company
template_name = 'companies/company_list.html'
context_object_name = 'companies'
paginate_by = 12
def get_queryset(self):
queryset = Company.objects.all()
# Filter by country if specified
country = self.request.GET.get('country')
if country:
queryset = queryset.filter(headquarters__icontains=country)
# Search by name if specified
search = self.request.GET.get('search')
if search:
queryset = queryset.filter(name__icontains=search)
return queryset.order_by('name')
class ManufacturerListView(ListView):
model = Manufacturer
template_name = 'companies/manufacturer_list.html'
context_object_name = 'manufacturers'
paginate_by = 12
def get_queryset(self):
queryset = Manufacturer.objects.all()
# Filter by country if specified
country = self.request.GET.get('country')
if country:
queryset = queryset.filter(headquarters__icontains=country)
# Search by name if specified
search = self.request.GET.get('search')
if search:
queryset = queryset.filter(name__icontains=search)
return queryset.order_by('name')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Add stats for filtering
context['total_manufacturers'] = self.model.objects.count()
context['total_rides'] = Ride.objects.filter(
manufacturer__isnull=False
).count()
context['total_roller_coasters'] = Ride.objects.filter(
manufacturer__isnull=False,
category='RC'
).count()
return context