feat: Add analytics, incident, and alert models and APIs, along with user permissions and bulk profile lookups.

This commit is contained in:
pacnpal
2026-01-07 11:07:36 -05:00
parent 4da7e52fb0
commit 3ec5a4857d
46 changed files with 4012 additions and 199 deletions

View File

@@ -9,6 +9,8 @@ This module tests end-to-end moderation workflows including:
- Bulk operation workflow
"""
from datetime import timedelta
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.test import TestCase
@@ -37,7 +39,7 @@ class SubmissionApprovalWorkflowTests(TestCase):
"""
Test complete edit submission approval workflow.
Flow: User submits → Moderator reviews → Moderator approves → Changes applied
Flow: User submits → Moderator claims → Moderator approves → Changes applied
"""
from apps.moderation.models import EditSubmission
from apps.parks.models import Company
@@ -61,6 +63,13 @@ class SubmissionApprovalWorkflowTests(TestCase):
self.assertIsNone(submission.handled_by)
self.assertIsNone(submission.handled_at)
# Moderator claims the submission first
submission.transition_to_claimed(user=self.moderator)
submission.save()
submission.refresh_from_db()
self.assertEqual(submission.status, "CLAIMED")
# Moderator approves
submission.transition_to_approved(user=self.moderator)
submission.handled_by = self.moderator
@@ -78,6 +87,8 @@ class SubmissionApprovalWorkflowTests(TestCase):
Flow: User submits photo → Moderator reviews → Moderator approves → Photo created
"""
from django_cloudflareimages_toolkit.models import CloudflareImage
from apps.moderation.models import PhotoSubmission
from apps.parks.models import Company, Park
@@ -87,6 +98,13 @@ class SubmissionApprovalWorkflowTests(TestCase):
name="Test Park", slug="test-park", operator=operator, status="OPERATING", timezone="America/New_York"
)
# Create mock CloudflareImage for the photo submission
mock_image = CloudflareImage.objects.create(
cloudflare_id="test-cf-image-id-12345",
user=self.regular_user,
expires_at=timezone.now() + timedelta(days=365),
)
# User submits a photo
content_type = ContentType.objects.get_for_model(park)
submission = PhotoSubmission.objects.create(
@@ -94,12 +112,18 @@ class SubmissionApprovalWorkflowTests(TestCase):
content_type=content_type,
object_id=park.id,
status="PENDING",
photo_type="GENERAL",
description="Beautiful park entrance",
photo=mock_image,
caption="Beautiful park entrance",
)
self.assertEqual(submission.status, "PENDING")
# Moderator claims the submission first (required FSM step)
submission.claim(user=self.moderator)
submission.refresh_from_db()
self.assertEqual(submission.status, "CLAIMED")
# Moderator approves
submission.transition_to_approved(user=self.moderator)
submission.handled_by = self.moderator
@@ -144,7 +168,13 @@ class SubmissionRejectionWorkflowTests(TestCase):
reason="Name change request",
)
# Moderator rejects
# Moderator claims and then rejects
submission.transition_to_claimed(user=self.moderator)
submission.save()
submission.refresh_from_db()
self.assertEqual(submission.status, "CLAIMED")
submission.transition_to_rejected(user=self.moderator)
submission.handled_by = self.moderator
submission.handled_at = timezone.now()
@@ -193,7 +223,13 @@ class SubmissionEscalationWorkflowTests(TestCase):
reason="Major name change",
)
# Moderator escalates
# Moderator claims and then escalates
submission.transition_to_claimed(user=self.moderator)
submission.save()
submission.refresh_from_db()
self.assertEqual(submission.status, "CLAIMED")
submission.transition_to_escalated(user=self.moderator)
submission.notes = "Escalated: Major change needs admin review"
submission.save()
@@ -447,11 +483,13 @@ class ModerationQueueWorkflowTests(TestCase):
from apps.moderation.models import ModerationQueue
queue_item = ModerationQueue.objects.create(
queue_type="SUBMISSION_REVIEW",
item_type="SUBMISSION_REVIEW",
status="PENDING",
priority="MEDIUM",
item_type="edit_submission",
item_id=123,
title="Review edit submission #123",
description="Review and process edit submission",
entity_type="edit_submission",
entity_id=123,
)
self.assertEqual(queue_item.status, "PENDING")