mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2026-02-05 09:45:17 -05:00
fix(fsm): Fix StateLog.by capture and cycle validation; add photographer field to photos
## FSM State Machine Fixes ### StateLog.by Field Capture - Modified TransitionMethodFactory to pass 'user' as 'by' kwarg to enable django-fsm-log's @fsm_log_by decorator to correctly capture the user who performed the transition - Applied fix to both escalate_transition and create_transition_method - Uses exec() to dynamically create transition functions with correct __name__ before decorators are applied, ensuring django-fsm's method registration works ### Cycle Validation Behavior - Changed validate_no_cycles() to return ValidationWarning instead of ValidationError - Cycles are now treated as warnings, not blocking errors, since cycles are often intentional in operational status FSMs (e.g., reopening after temporary closure) ### Ride Status Transitions - Added TEMPORARY_CLOSURE -> OPERATING transition (reopen after temporary closure) - Added SBNO -> OPERATING transition (revival - ride returns to operation) ## Field Parity ### Photo Models - Added 'photographer' field to RidePhoto and ParkPhoto models - Maps to frontend 'photographer_credit' field for full schema parity - Includes corresponding migrations for both apps ### Serializers - Added 'photographer' to RidePhotoSerializer and ParkPhotoSerializer read_only_fields
This commit is contained in:
@@ -91,6 +91,7 @@ RIDE_STATUSES = [
|
||||
"css_class": "bg-yellow-100 text-yellow-800",
|
||||
"sort_order": 2,
|
||||
"can_transition_to": [
|
||||
"OPERATING", # Reopen after temporary closure
|
||||
"SBNO",
|
||||
"CLOSING",
|
||||
],
|
||||
@@ -109,6 +110,7 @@ RIDE_STATUSES = [
|
||||
"css_class": "bg-orange-100 text-orange-800",
|
||||
"sort_order": 3,
|
||||
"can_transition_to": [
|
||||
"OPERATING", # Revival - ride returns to operation
|
||||
"CLOSED_PERM",
|
||||
"DEMOLISHED",
|
||||
"RELOCATED",
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# Generated by Django 5.2.9 on 2026-01-08 18:48
|
||||
|
||||
import pgtrigger.compiler
|
||||
import pgtrigger.migrations
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('rides', '0038_company_schema_parity'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
pgtrigger.migrations.RemoveTrigger(
|
||||
model_name='ridephoto',
|
||||
name='insert_insert',
|
||||
),
|
||||
pgtrigger.migrations.RemoveTrigger(
|
||||
model_name='ridephoto',
|
||||
name='update_update',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ridephoto',
|
||||
name='photographer',
|
||||
field=models.CharField(blank=True, help_text='Photographer credit (maps to frontend photographer_credit)', max_length=200),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ridephotoevent',
|
||||
name='photographer',
|
||||
field=models.CharField(blank=True, help_text='Photographer credit (maps to frontend photographer_credit)', max_length=200),
|
||||
),
|
||||
pgtrigger.migrations.AddTrigger(
|
||||
model_name='ridephoto',
|
||||
trigger=pgtrigger.compiler.Trigger(name='insert_insert', sql=pgtrigger.compiler.UpsertTriggerSql(func='INSERT INTO "rides_ridephotoevent" ("alt_text", "caption", "created_at", "date_taken", "id", "image_id", "is_approved", "is_primary", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "photo_type", "photographer", "ride_id", "updated_at", "uploaded_by_id") VALUES (NEW."alt_text", NEW."caption", NEW."created_at", NEW."date_taken", NEW."id", NEW."image_id", NEW."is_approved", NEW."is_primary", _pgh_attach_context(), NOW(), \'insert\', NEW."id", NEW."photo_type", NEW."photographer", NEW."ride_id", NEW."updated_at", NEW."uploaded_by_id"); RETURN NULL;', hash='b426eed3a10c63be3db15a5a9477d66388f5dd2f', operation='INSERT', pgid='pgtrigger_insert_insert_0043a', table='rides_ridephoto', when='AFTER')),
|
||||
),
|
||||
pgtrigger.migrations.AddTrigger(
|
||||
model_name='ridephoto',
|
||||
trigger=pgtrigger.compiler.Trigger(name='update_update', sql=pgtrigger.compiler.UpsertTriggerSql(condition='WHEN (OLD.* IS DISTINCT FROM NEW.*)', func='INSERT INTO "rides_ridephotoevent" ("alt_text", "caption", "created_at", "date_taken", "id", "image_id", "is_approved", "is_primary", "pgh_context_id", "pgh_created_at", "pgh_label", "pgh_obj_id", "photo_type", "photographer", "ride_id", "updated_at", "uploaded_by_id") VALUES (NEW."alt_text", NEW."caption", NEW."created_at", NEW."date_taken", NEW."id", NEW."image_id", NEW."is_approved", NEW."is_primary", _pgh_attach_context(), NOW(), \'update\', NEW."id", NEW."photo_type", NEW."photographer", NEW."ride_id", NEW."updated_at", NEW."uploaded_by_id"); RETURN NULL;', hash='9728ec4736aea41ea171c3494de909aae3f68569', operation='UPDATE', pgid='pgtrigger_update_update_93a7e', table='rides_ridephoto', when='AFTER')),
|
||||
),
|
||||
]
|
||||
@@ -44,6 +44,11 @@ class RidePhoto(TrackedModel):
|
||||
)
|
||||
|
||||
caption = models.CharField(max_length=255, blank=True)
|
||||
photographer = models.CharField(
|
||||
max_length=200,
|
||||
blank=True,
|
||||
help_text="Photographer credit (maps to frontend photographer_credit)"
|
||||
)
|
||||
alt_text = models.CharField(max_length=255, blank=True)
|
||||
is_primary = models.BooleanField(default=False)
|
||||
is_approved = models.BooleanField(default=False)
|
||||
|
||||
Reference in New Issue
Block a user