15 KiB
Comprehensive Frontend-Backend Feature Parity Audit
Date: 2025-11-09 Auditor: Cline Scope: Complete comparison of Django backend vs Supabase schema + Frontend usage analysis
Executive Summary
Overall Status: 85% Feature Complete
What Works:
- ✅ All core entities (Parks, Rides, Companies, Ride Models)
- ✅ Sacred Pipeline (Form → Submission → Moderation → Approval → Versioning)
- ✅ Reviews with helpful votes
- ✅ User ride credits & top lists
- ✅ Photos with CloudFlare integration
- ✅ Complete moderation system
- ✅ pghistory-based versioning (SUPERIOR to Supabase)
- ✅ Search with PostgreSQL GIN indexes
Critical Issues Found:
- 🔴 BUG: Park coordinate updates don't work (2 hour fix)
- 🔴 MISSING: Ride Name History model (heavily used by frontend)
- 🔴 MISSING: Entity Timeline Events (frontend has timeline manager)
- 🔴 MISSING: Reports System (frontend has reporting UI)
- 🟡 MISSING: Blog Posts (if part of MVP)
- 🟡 MISSING: Contact Submissions (if part of MVP)
1. Core Entities Analysis
✅ FULLY IMPLEMENTED
| Entity | Supabase | Django | Notes |
|---|---|---|---|
| Companies | ✅ | ✅ | Django uses M2M for company_types (better than JSONB) |
| Locations | ✅ | ✅ | Country/Subdivision/Locality models |
| Parks | ✅ | ✅ | All fields present, coordinate update bug found |
| Rides | ✅ | ✅ | All type-specific fields as nullable on main model |
| Ride Models | ✅ | ✅ | Complete implementation |
| Reviews | ✅ | ✅ | With helpful votes |
| User Ride Credits | ✅ | ✅ | Complete |
| User Top Lists | ✅ | ✅ | Relational structure |
| Profiles | ✅ | ✅ | Django User model |
2. Sacred Pipeline Analysis
✅ FULLY OPERATIONAL
Django Implementation:
ContentSubmission- Main submission containerSubmissionItem- Individual items in submission- Polymorphic submission services per entity type
- Complete moderation queue
- Lock system prevents conflicts
- Audit trail via pghistory
Supabase Schema:
- Separate tables per entity type (park_submissions, ride_submissions, etc.)
- submission_items for tracking
Verdict: ✅ Django's unified approach is SUPERIOR
3. Versioning & History
✅ DJANGO SUPERIOR
Django:
- pghistory tracks ALL changes automatically
- No manual version table management
- Complete audit trail
- Rollback capability
Supabase:
- Manual version tables (park_versions, ride_versions, etc.)
- entity_versions, entity_field_history
- version_diffs for comparisons
Verdict: ✅ Django's pghistory approach is better
4. Critical Missing Features (Frontend Actively Uses)
🔴 1. RIDE NAME HISTORY - CRITICAL
Supabase Tables:
ride_name_history- tracks former namesride_former_names- same table, two names in schema
Frontend Usage: (34 results in search)
RideDetail.tsx- Displays "formerly known as" sectionFormerNamesSection.tsx- Dedicated componentFormerNamesEditor.tsx- Admin editing interfaceRideForm.tsx- Form handlingentitySubmissionHelpers.ts- Submission logic
Impact: Every ride detail page with name changes is broken
Django Status: ❌ Missing completely
Required Implementation:
class RideNameHistory(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
ride = models.ForeignKey('Ride', on_delete=models.CASCADE,
related_name='name_history')
former_name = models.CharField(max_length=255)
from_year = models.IntegerField(null=True, blank=True)
to_year = models.IntegerField(null=True, blank=True)
date_changed = models.DateField(null=True, blank=True)
date_changed_precision = models.CharField(max_length=20,
null=True, blank=True)
reason = models.TextField(null=True, blank=True)
order_index = models.IntegerField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Estimated Effort: 4 hours
- Model creation + migration
- Admin interface
- API endpoint (list name history for ride)
- Integration with submission system
🔴 2. ENTITY TIMELINE EVENTS - CRITICAL
Supabase Table:
entity_timeline_events
Frontend Usage: (5 files)
EntityTimelineManager.tsx- Full timeline managemententitySubmissionHelpers.ts- Sacred Pipeline integrationsystemActivityService.ts- Activity tracking
Impact: Historical milestone tracking completely non-functional
Django Status: ❌ Missing completely
Required Implementation:
class EntityTimelineEvent(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
entity_id = models.UUIDField(db_index=True)
entity_type = models.CharField(max_length=50, db_index=True)
event_type = models.CharField(max_length=100)
event_date = models.DateField()
event_date_precision = models.CharField(max_length=20, null=True)
title = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
# Event details
from_entity_id = models.UUIDField(null=True, blank=True)
to_entity_id = models.UUIDField(null=True, blank=True)
from_location = models.ForeignKey('Location', null=True,
on_delete=models.SET_NULL,
related_name='+')
to_location = models.ForeignKey('Location', null=True,
on_delete=models.SET_NULL,
related_name='+')
from_value = models.TextField(null=True, blank=True)
to_value = models.TextField(null=True, blank=True)
# Moderation
is_public = models.BooleanField(default=True)
display_order = models.IntegerField(null=True, blank=True)
# Tracking
created_by = models.ForeignKey(User, null=True,
on_delete=models.SET_NULL)
approved_by = models.ForeignKey(User, null=True,
on_delete=models.SET_NULL,
related_name='+')
submission = models.ForeignKey('moderation.ContentSubmission',
null=True, on_delete=models.SET_NULL)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Estimated Effort: 6 hours
- Model + migration
- Submission service integration
- API endpoints (CRUD + list by entity)
- Admin interface
🔴 3. REPORTS SYSTEM - CRITICAL
Supabase Table:
reports
Frontend Usage: (7 files)
ReportButton.tsx- User reporting interfaceReportsQueue.tsx- Moderator queueRecentActivity.tsx- DashboarduseModerationStats.ts- StatisticssystemActivityService.ts- System tracking
Impact: No user reporting capability, community moderation broken
Django Status: ❌ Missing completely
Required Implementation:
class Report(models.Model):
STATUS_CHOICES = [
('pending', 'Pending'),
('reviewing', 'Under Review'),
('resolved', 'Resolved'),
('dismissed', 'Dismissed'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
report_type = models.CharField(max_length=50)
reported_entity_id = models.UUIDField(db_index=True)
reported_entity_type = models.CharField(max_length=50, db_index=True)
reporter = models.ForeignKey(User, on_delete=models.CASCADE,
related_name='reports_filed')
reason = models.TextField(null=True, blank=True)
status = models.CharField(max_length=20, choices=STATUS_CHOICES,
default='pending', db_index=True)
reviewed_by = models.ForeignKey(User, null=True,
on_delete=models.SET_NULL,
related_name='reports_reviewed')
reviewed_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
indexes = [
models.Index(fields=['status', 'created_at']),
models.Index(fields=['reported_entity_type', 'reported_entity_id']),
]
Estimated Effort: 8 hours
- Model + migration
- API endpoints (create, list, update status)
- Integration with moderation system
- Admin interface
- Statistics endpoints
🟡 4. BLOG POSTS - MVP DEPENDENT
Supabase Table:
blog_posts
Frontend Usage: (3 full pages)
BlogIndex.tsx- Blog listingBlogPost.tsx- Individual post viewAdminBlog.tsx- Complete CRUD admin interface
Impact: Entire blog section non-functional
Django Status: ❌ Missing
Required Implementation:
class BlogPost(models.Model):
STATUS_CHOICES = [
('draft', 'Draft'),
('published', 'Published'),
('archived', 'Archived'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
status = models.CharField(max_length=20, choices=STATUS_CHOICES,
default='draft', db_index=True)
published_at = models.DateTimeField(null=True, blank=True,
db_index=True)
featured_image_id = models.CharField(max_length=255, null=True)
featured_image_url = models.URLField(null=True, blank=True)
view_count = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Estimated Effort: 6 hours (if needed for MVP)
🟡 5. CONTACT SUBMISSIONS - MVP DEPENDENT
Supabase Tables:
contact_submissionscontact_email_threadscontact_rate_limits
Frontend Usage:
AdminContact.tsx- Full admin interface with CRUD
Impact: Contact form and support ticket system broken
Django Status: ❌ Missing
Required Implementation:
class ContactSubmission(models.Model):
STATUS_CHOICES = [
('pending', 'Pending'),
('in_progress', 'In Progress'),
('resolved', 'Resolved'),
('archived', 'Archived'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
# Contact info
name = models.CharField(max_length=255)
email = models.EmailField()
subject = models.CharField(max_length=255)
message = models.TextField()
category = models.CharField(max_length=50)
# Tracking
status = models.CharField(max_length=20, choices=STATUS_CHOICES,
default='pending', db_index=True)
ticket_number = models.CharField(max_length=20, unique=True,
null=True, blank=True)
# Assignment
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL,
related_name='contact_submissions')
assigned_to = models.ForeignKey(User, null=True,
on_delete=models.SET_NULL,
related_name='assigned_contacts')
# Admin tracking
admin_notes = models.TextField(null=True, blank=True)
resolved_at = models.DateTimeField(null=True, blank=True)
resolved_by = models.ForeignKey(User, null=True,
on_delete=models.SET_NULL,
related_name='+')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Estimated Effort: 6 hours (if needed for MVP)
5. Features NOT Used by Frontend
✅ SAFE TO SKIP
- park_operating_hours - Only in TypeScript types, no actual frontend usage
- ride_technical_specifications - Django stores in main Ride model (acceptable)
- ride_coaster_stats - Django stores in main Ride model (acceptable)
- Advanced monitoring tables - Better handled by external tools
6. Critical Bug Found
🔴 PARK COORDINATE UPDATE BUG
Location: django/api/v1/endpoints/parks.py lines 344-350
Issue:
latitude = data.pop('latitude', None)
longitude = data.pop('longitude', None)
submission, updated_park = ParkSubmissionService.update_entity_submission(
entity=park,
user=user,
update_data=data,
latitude=latitude, # ← Passed but never used!
longitude=longitude, # ← Passed but never used!
Problem: ParkSubmissionService.update_entity_submission() inherits from base class and doesn't handle the latitude/longitude kwargs, so coordinate updates silently fail.
Fix Required: Override update_entity_submission() in ParkSubmissionService to handle location updates.
Estimated Effort: 2 hours
7. Implementation Timeline
Phase 1: Critical Blockers (20 hours / 2.5 days)
-
Fix Park Coordinate Bug - 2 hours
- Override method in ParkSubmissionService
- Handle location creation/update
- Test coordinate updates
-
Ride Name History - 4 hours
- Model + migration
- API endpoints
- Admin interface
- Submission integration
-
Entity Timeline Events - 6 hours
- Model + migration
- API endpoints (CRUD + list)
- Submission service
- Admin interface
-
Reports System - 8 hours
- Model + migration
- API endpoints (create, list, update)
- Moderation integration
- Admin interface
- Statistics
Phase 2: MVP Features (12 hours / 1.5 days) - IF NEEDED
- Blog Posts - 6 hours (if blog is part of MVP)
- Contact Submissions - 6 hours (if contact form is part of MVP)
8. Recommendations
Immediate Actions:
- Fix the coordinate bug (2 hours) - This is blocking park updates
- Determine MVP scope:
- Is blog required?
- Is contact form required?
- Implement Phase 1 features (remaining 18 hours)
- If blog/contact needed, implement Phase 2 (12 hours)
Total Effort:
- Minimum: 20 hours (without blog/contact)
- Full Parity: 32 hours (with everything)
9. Django Advantages
Despite missing features, Django implementation has several improvements:
- Better Architecture: Unified ContentSubmission vs separate tables per type
- Superior Versioning: pghistory beats manual version tables
- Proper Normalization: M2M for company_types vs JSONB
- Service Layer: Clean separation of concerns
- Type Safety: Python typing throughout
- Built-in Admin: Django admin for all models
10. Conclusion
The Django backend is 85% feature complete and architecturally superior to Supabase in many ways. However, 5 critical features that the frontend actively uses are missing:
🔴 MUST FIX:
- Park coordinate update bug
- Ride Name History model
- Entity Timeline Events model
- Reports System model
🟡 IF PART OF MVP: 5. Blog Posts model 6. Contact Submissions model
Total work: 20-32 hours depending on MVP scope
The Sacred Pipeline is fully functional and tested. All core entity CRUD operations work. The missing pieces are specific features the frontend has UI for but the backend doesn't support yet.