This commit is contained in:
pacnpal
2026-01-08 13:44:37 -05:00
parent 40cba5bdb2
commit fe960e8b62
21 changed files with 2008 additions and 59 deletions

View File

@@ -0,0 +1,117 @@
# Generated by Django 5.2.9 on 2026-01-08 18:05
import pgtrigger.compiler
import pgtrigger.migrations
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('parks', '0028_add_date_precision_fields'),
]
operations = [
pgtrigger.migrations.RemoveTrigger(
model_name='company',
name='insert_insert',
),
pgtrigger.migrations.RemoveTrigger(
model_name='company',
name='update_update',
),
pgtrigger.migrations.RemoveTrigger(
model_name='park',
name='insert_insert',
),
pgtrigger.migrations.RemoveTrigger(
model_name='park',
name='update_update',
),
migrations.AddField(
model_name='company',
name='is_test_data',
field=models.BooleanField(default=False, help_text='Whether this is test/development data'),
),
migrations.AddField(
model_name='company',
name='source_url',
field=models.URLField(blank=True, help_text='Source URL for the data (e.g., official website, Wikipedia)'),
),
migrations.AddField(
model_name='companyevent',
name='is_test_data',
field=models.BooleanField(default=False, help_text='Whether this is test/development data'),
),
migrations.AddField(
model_name='companyevent',
name='source_url',
field=models.URLField(blank=True, help_text='Source URL for the data (e.g., official website, Wikipedia)'),
),
migrations.AddField(
model_name='park',
name='is_test_data',
field=models.BooleanField(default=False, help_text='Whether this is test/development data'),
),
migrations.AddField(
model_name='park',
name='source_url',
field=models.URLField(blank=True, help_text='Source URL for the data (e.g., official website, Wikipedia)'),
),
migrations.AddField(
model_name='parkevent',
name='is_test_data',
field=models.BooleanField(default=False, help_text='Whether this is test/development data'),
),
migrations.AddField(
model_name='parkevent',
name='source_url',
field=models.URLField(blank=True, help_text='Source URL for the data (e.g., official website, Wikipedia)'),
),
migrations.AlterField(
model_name='company',
name='founded_date_precision',
field=models.CharField(blank=True, choices=[('exact', 'Exact Date'), ('month', 'Month and Year'), ('year', 'Year Only'), ('decade', 'Decade'), ('century', 'Century'), ('approximate', 'Approximate')], help_text='Precision of the founding date', max_length=20),
),
migrations.AlterField(
model_name='companyevent',
name='founded_date_precision',
field=models.CharField(blank=True, choices=[('exact', 'Exact Date'), ('month', 'Month and Year'), ('year', 'Year Only'), ('decade', 'Decade'), ('century', 'Century'), ('approximate', 'Approximate')], help_text='Precision of the founding date', max_length=20),
),
migrations.AlterField(
model_name='park',
name='closing_date_precision',
field=models.CharField(blank=True, choices=[('exact', 'Exact Date'), ('month', 'Month and Year'), ('year', 'Year Only'), ('decade', 'Decade'), ('century', 'Century'), ('approximate', 'Approximate')], default='exact', help_text='Precision of the closing date', max_length=20),
),
migrations.AlterField(
model_name='park',
name='opening_date_precision',
field=models.CharField(blank=True, choices=[('exact', 'Exact Date'), ('month', 'Month and Year'), ('year', 'Year Only'), ('decade', 'Decade'), ('century', 'Century'), ('approximate', 'Approximate')], default='exact', help_text='Precision of the opening date', max_length=20),
),
migrations.AlterField(
model_name='parkevent',
name='closing_date_precision',
field=models.CharField(blank=True, choices=[('exact', 'Exact Date'), ('month', 'Month and Year'), ('year', 'Year Only'), ('decade', 'Decade'), ('century', 'Century'), ('approximate', 'Approximate')], default='exact', help_text='Precision of the closing date', max_length=20),
),
migrations.AlterField(
model_name='parkevent',
name='opening_date_precision',
field=models.CharField(blank=True, choices=[('exact', 'Exact Date'), ('month', 'Month and Year'), ('year', 'Year Only'), ('decade', 'Decade'), ('century', 'Century'), ('approximate', 'Approximate')], default='exact', help_text='Precision of the opening date', max_length=20),
),
pgtrigger.migrations.AddTrigger(
model_name='company',
trigger=pgtrigger.compiler.Trigger(name='insert_insert', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "parks_companyevent" ("average_rating", "banner_image_url", "card_image_url", "created_at", "description", "founded_date", "founded_date_precision", "founded_year", "id", "is_test_data", "logo_url", "name", "parks_count", "person_type", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "review_count", "rides_count", "roles", "slug", "source_url", "status", "updated_at", "website") VALUES (NEW."average_rating", NEW."banner_image_url", NEW."card_image_url", NEW."created_at", NEW."description", NEW."founded_date", NEW."founded_date_precision", NEW."founded_year", NEW."id", NEW."is_test_data", NEW."logo_url", NEW."name", NEW."parks_count", NEW."person_type", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."review_count", NEW."rides_count", NEW."roles", NEW."slug", NEW."source_url", NEW."status", NEW."updated_at", NEW."website"); RETURN NULL;', hash='8352ecabfefc26dab2c91be68a9e137a1e48cbd2', operation='INSERT', pgid='pgtrigger_insert_insert_35b57', table='parks_company', when='AFTER')),
),
pgtrigger.migrations.AddTrigger(
model_name='company',
trigger=pgtrigger.compiler.Trigger(name='update_update', sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD.* IS DISTINCT FROM NEW.*)', func='INSERT INTO "parks_companyevent" ("average_rating", "banner_image_url", "card_image_url", "created_at", "description", "founded_date", "founded_date_precision", "founded_year", "id", "is_test_data", "logo_url", "name", "parks_count", "person_type", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "review_count", "rides_count", "roles", "slug", "source_url", "status", "updated_at", "website") VALUES (NEW."average_rating", NEW."banner_image_url", NEW."card_image_url", NEW."created_at", NEW."description", NEW."founded_date", NEW."founded_date_precision", NEW."founded_year", NEW."id", NEW."is_test_data", NEW."logo_url", NEW."name", NEW."parks_count", NEW."person_type", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."review_count", NEW."rides_count", NEW."roles", NEW."slug", NEW."source_url", NEW."status", NEW."updated_at", NEW."website"); RETURN NULL;', hash='5d8b399ed7573fa0d5411042902c0a494785e071', operation='UPDATE', pgid='pgtrigger_update_update_d3286', table='parks_company', when='AFTER')),
),
pgtrigger.migrations.AddTrigger(
model_name='park',
trigger=pgtrigger.compiler.Trigger(name='insert_insert', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "parks_parkevent" ("average_rating", "banner_image_id", "card_image_id", "closing_date", "closing_date_precision", "coaster_count", "created_at", "description", "email", "id", "is_test_data", "name", "opening_date", "opening_date_precision", "opening_year", "operating_season", "operator_id", "park_type", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "phone", "property_owner_id", "ride_count", "search_text", "size_acres", "slug", "source_url", "status", "timezone", "updated_at", "url", "website") VALUES (NEW."average_rating", NEW."banner_image_id", NEW."card_image_id", NEW."closing_date", NEW."closing_date_precision", NEW."coaster_count", NEW."created_at", NEW."description", NEW."email", NEW."id", NEW."is_test_data", NEW."name", NEW."opening_date", NEW."opening_date_precision", NEW."opening_year", NEW."operating_season", NEW."operator_id", NEW."park_type", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."phone", NEW."property_owner_id", NEW."ride_count", NEW."search_text", NEW."size_acres", NEW."slug", NEW."source_url", NEW."status", NEW."timezone", NEW."updated_at", NEW."url", NEW."website"); RETURN NULL;', hash='cb0e4e056880e2e6febc5a0905a437e56dab89de', operation='INSERT', pgid='pgtrigger_insert_insert_66883', table='parks_park', when='AFTER')),
),
pgtrigger.migrations.AddTrigger(
model_name='park',
trigger=pgtrigger.compiler.Trigger(name='update_update', sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD.* IS DISTINCT FROM NEW.*)', func='INSERT INTO "parks_parkevent" ("average_rating", "banner_image_id", "card_image_id", "closing_date", "closing_date_precision", "coaster_count", "created_at", "description", "email", "id", "is_test_data", "name", "opening_date", "opening_date_precision", "opening_year", "operating_season", "operator_id", "park_type", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "phone", "property_owner_id", "ride_count", "search_text", "size_acres", "slug", "source_url", "status", "timezone", "updated_at", "url", "website") VALUES (NEW."average_rating", NEW."banner_image_id", NEW."card_image_id", NEW."closing_date", NEW."closing_date_precision", NEW."coaster_count", NEW."created_at", NEW."description", NEW."email", NEW."id", NEW."is_test_data", NEW."name", NEW."opening_date", NEW."opening_date_precision", NEW."opening_year", NEW."operating_season", NEW."operator_id", NEW."park_type", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."phone", NEW."property_owner_id", NEW."ride_count", NEW."search_text", NEW."size_acres", NEW."slug", NEW."source_url", NEW."status", NEW."timezone", NEW."updated_at", NEW."url", NEW."website"); RETURN NULL;', hash='dd10d0b79ed3bf1caca8d4ffb520cd0be298bc0d', operation='UPDATE', pgid='pgtrigger_update_update_19f56', table='parks_park', when='AFTER')),
),
]

View File

@@ -0,0 +1,72 @@
# Generated by Django 5.2.9 on 2026-01-08 18:20
import django.db.models.deletion
import pgtrigger.compiler
import pgtrigger.migrations
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('parks', '0029_add_source_url_is_test_data_and_date_precision'),
]
operations = [
pgtrigger.migrations.RemoveTrigger(
model_name='company',
name='insert_insert',
),
pgtrigger.migrations.RemoveTrigger(
model_name='company',
name='update_update',
),
migrations.AddField(
model_name='company',
name='banner_image_id',
field=models.CharField(blank=True, help_text='Cloudflare image ID for banner image', max_length=255),
),
migrations.AddField(
model_name='company',
name='card_image_id',
field=models.CharField(blank=True, help_text='Cloudflare image ID for card image', max_length=255),
),
migrations.AddField(
model_name='company',
name='headquarters_location',
field=models.CharField(blank=True, help_text="Headquarters location description (e.g., 'Los Angeles, CA, USA')", max_length=200),
),
migrations.AddField(
model_name='company',
name='location',
field=models.ForeignKey(blank=True, help_text='Linked location record for headquarters', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='companies_hq', to='parks.parklocation'),
),
migrations.AddField(
model_name='companyevent',
name='banner_image_id',
field=models.CharField(blank=True, help_text='Cloudflare image ID for banner image', max_length=255),
),
migrations.AddField(
model_name='companyevent',
name='card_image_id',
field=models.CharField(blank=True, help_text='Cloudflare image ID for card image', max_length=255),
),
migrations.AddField(
model_name='companyevent',
name='headquarters_location',
field=models.CharField(blank=True, help_text="Headquarters location description (e.g., 'Los Angeles, CA, USA')", max_length=200),
),
migrations.AddField(
model_name='companyevent',
name='location',
field=models.ForeignKey(blank=True, db_constraint=False, help_text='Linked location record for headquarters', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', related_query_name='+', to='parks.parklocation'),
),
pgtrigger.migrations.AddTrigger(
model_name='company',
trigger=pgtrigger.compiler.Trigger(name='insert_insert', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "parks_companyevent" ("average_rating", "banner_image_id", "banner_image_url", "card_image_id", "card_image_url", "created_at", "description", "founded_date", "founded_date_precision", "founded_year", "headquarters_location", "id", "is_test_data", "location_id", "logo_url", "name", "parks_count", "person_type", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "review_count", "rides_count", "roles", "slug", "source_url", "status", "updated_at", "website") VALUES (NEW."average_rating", NEW."banner_image_id", NEW."banner_image_url", NEW."card_image_id", NEW."card_image_url", NEW."created_at", NEW."description", NEW."founded_date", NEW."founded_date_precision", NEW."founded_year", NEW."headquarters_location", NEW."id", NEW."is_test_data", NEW."location_id", NEW."logo_url", NEW."name", NEW."parks_count", NEW."person_type", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."review_count", NEW."rides_count", NEW."roles", NEW."slug", NEW."source_url", NEW."status", NEW."updated_at", NEW."website"); RETURN NULL;', hash='9e3f8a98696e2655ada53342a59b11a71bfa384c', operation='INSERT', pgid='pgtrigger_insert_insert_35b57', table='parks_company', when='AFTER')),
),
pgtrigger.migrations.AddTrigger(
model_name='company',
trigger=pgtrigger.compiler.Trigger(name='update_update', sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD.* IS DISTINCT FROM NEW.*)', func='INSERT INTO "parks_companyevent" ("average_rating", "banner_image_id", "banner_image_url", "card_image_id", "card_image_url", "created_at", "description", "founded_date", "founded_date_precision", "founded_year", "headquarters_location", "id", "is_test_data", "location_id", "logo_url", "name", "parks_count", "person_type", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "review_count", "rides_count", "roles", "slug", "source_url", "status", "updated_at", "website") VALUES (NEW."average_rating", NEW."banner_image_id", NEW."banner_image_url", NEW."card_image_id", NEW."card_image_url", NEW."created_at", NEW."description", NEW."founded_date", NEW."founded_date_precision", NEW."founded_year", NEW."headquarters_location", NEW."id", NEW."is_test_data", NEW."location_id", NEW."logo_url", NEW."name", NEW."parks_count", NEW."person_type", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."review_count", NEW."rides_count", NEW."roles", NEW."slug", NEW."source_url", NEW."status", NEW."updated_at", NEW."website"); RETURN NULL;', hash='953a919e1969082370e189b0b47a2ce3fc9dafcf', operation='UPDATE', pgid='pgtrigger_update_update_d3286', table='parks_company', when='AFTER')),
),
]

View File

@@ -62,12 +62,15 @@ class Company(TrackedModel):
founded_year = models.PositiveIntegerField(blank=True, null=True, help_text="Year the company was founded")
founded_date = models.DateField(blank=True, null=True, help_text="Full founding date if known")
DATE_PRECISION_CHOICES = [
("YEAR", "Year only"),
("MONTH", "Month and year"),
("DAY", "Full date"),
("exact", "Exact Date"),
("month", "Month and Year"),
("year", "Year Only"),
("decade", "Decade"),
("century", "Century"),
("approximate", "Approximate"),
]
founded_date_precision = models.CharField(
max_length=10,
max_length=20,
choices=DATE_PRECISION_CHOICES,
blank=True,
help_text="Precision of the founding date",
@@ -78,6 +81,35 @@ class Company(TrackedModel):
banner_image_url = models.URLField(blank=True, help_text="Banner image for company page header")
card_image_url = models.URLField(blank=True, help_text="Card/thumbnail image for listings")
# Image ID fields (for frontend submissions - Cloudflare image IDs)
banner_image_id = models.CharField(
max_length=255,
blank=True,
help_text="Cloudflare image ID for banner image",
)
card_image_id = models.CharField(
max_length=255,
blank=True,
help_text="Cloudflare image ID for card image",
)
# Location relationship (for headquarters coordinates)
location = models.ForeignKey(
"ParkLocation",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="companies_hq",
help_text="Linked location record for headquarters",
)
# Text-based headquarters location (matches frontend schema)
headquarters_location = models.CharField(
max_length=200,
blank=True,
help_text="Headquarters location description (e.g., 'Los Angeles, CA, USA')",
)
# Rating & Review Aggregates (computed fields, updated by triggers/signals)
average_rating = models.DecimalField(
max_digits=3,
@@ -95,6 +127,16 @@ class Company(TrackedModel):
parks_count = models.IntegerField(default=0, help_text="Number of parks operated (auto-calculated)")
rides_count = models.IntegerField(default=0, help_text="Number of rides manufactured (auto-calculated)")
# Submission metadata fields (from frontend schema)
source_url = models.URLField(
blank=True,
help_text="Source URL for the data (e.g., official website, Wikipedia)",
)
is_test_data = models.BooleanField(
default=False,
help_text="Whether this is test/development data",
)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)

View File

@@ -55,17 +55,31 @@ class Park(StateMachineMixin, TrackedModel):
# Details
opening_date = models.DateField(null=True, blank=True, help_text="Opening date")
opening_date_precision = models.CharField(
max_length=10,
choices=[("YEAR", "Year"), ("MONTH", "Month"), ("DAY", "Day")],
default="DAY",
max_length=20,
choices=[
("exact", "Exact Date"),
("month", "Month and Year"),
("year", "Year Only"),
("decade", "Decade"),
("century", "Century"),
("approximate", "Approximate"),
],
default="exact",
blank=True,
help_text="Precision of the opening date (YEAR for circa dates)",
help_text="Precision of the opening date",
)
closing_date = models.DateField(null=True, blank=True, help_text="Closing date")
closing_date_precision = models.CharField(
max_length=10,
choices=[("YEAR", "Year"), ("MONTH", "Month"), ("DAY", "Day")],
default="DAY",
max_length=20,
choices=[
("exact", "Exact Date"),
("month", "Month and Year"),
("year", "Year Only"),
("decade", "Decade"),
("century", "Century"),
("approximate", "Approximate"),
],
default="exact",
blank=True,
help_text="Precision of the closing date",
)
@@ -146,6 +160,16 @@ class Park(StateMachineMixin, TrackedModel):
help_text="Timezone identifier for park operations (e.g., 'America/New_York')",
)
# Submission metadata fields (from frontend schema)
source_url = models.URLField(
blank=True,
help_text="Source URL for the data (e.g., official website, Wikipedia)",
)
is_test_data = models.BooleanField(
default=False,
help_text="Whether this is test/development data",
)
class Meta:
verbose_name = "Park"
verbose_name_plural = "Parks"