mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2026-02-05 07:45:18 -05:00
feat: Add analytics, incident, and alert models and APIs, along with user permissions and bulk profile lookups.
This commit is contained in:
@@ -67,6 +67,7 @@ class EditSubmissionSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for EditSubmission with UI metadata for Nuxt frontend."""
|
||||
|
||||
submitted_by = UserBasicSerializer(source="user", read_only=True)
|
||||
handled_by = UserBasicSerializer(read_only=True)
|
||||
claimed_by = UserBasicSerializer(read_only=True)
|
||||
content_type_name = serializers.CharField(source="content_type.model", read_only=True)
|
||||
|
||||
@@ -87,22 +88,24 @@ class EditSubmissionSerializer(serializers.ModelSerializer):
|
||||
"content_type",
|
||||
"content_type_name",
|
||||
"object_id",
|
||||
"submission_type",
|
||||
"changes",
|
||||
"moderator_changes",
|
||||
"rejection_reason",
|
||||
"reason",
|
||||
"source",
|
||||
"notes",
|
||||
"submitted_by",
|
||||
"reviewed_by",
|
||||
"handled_by",
|
||||
"claimed_by",
|
||||
"claimed_at",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"time_since_created",
|
||||
]
|
||||
read_only_fields = [
|
||||
"id",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"submitted_by",
|
||||
"handled_by",
|
||||
"claimed_by",
|
||||
"claimed_at",
|
||||
"status_color",
|
||||
@@ -163,6 +166,7 @@ class EditSubmissionListSerializer(serializers.ModelSerializer):
|
||||
fields = [
|
||||
"id",
|
||||
"status",
|
||||
"submission_type", # Added for frontend compatibility
|
||||
"content_type_name",
|
||||
"object_id",
|
||||
"submitted_by_username",
|
||||
@@ -195,6 +199,101 @@ class EditSubmissionListSerializer(serializers.ModelSerializer):
|
||||
return icons.get(obj.status, "heroicons:question-mark-circle")
|
||||
|
||||
|
||||
class CreateEditSubmissionSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
Serializer for creating edit submissions.
|
||||
|
||||
This replaces the Supabase RPC 'create_submission_with_items' function.
|
||||
Accepts entity type as a string and resolves it to ContentType.
|
||||
"""
|
||||
|
||||
entity_type = serializers.CharField(write_only=True, help_text="Entity type: park, ride, company, ride_model")
|
||||
|
||||
class Meta:
|
||||
model = EditSubmission
|
||||
fields = [
|
||||
"entity_type",
|
||||
"object_id",
|
||||
"submission_type",
|
||||
"changes",
|
||||
"reason",
|
||||
"source",
|
||||
]
|
||||
|
||||
def validate_entity_type(self, value):
|
||||
"""Convert entity_type string to ContentType."""
|
||||
entity_type_map = {
|
||||
"park": ("parks", "park"),
|
||||
"ride": ("rides", "ride"),
|
||||
"company": ("parks", "company"),
|
||||
"ride_model": ("rides", "ridemodel"),
|
||||
"manufacturer": ("parks", "company"),
|
||||
"designer": ("parks", "company"),
|
||||
"operator": ("parks", "company"),
|
||||
"property_owner": ("parks", "company"),
|
||||
}
|
||||
|
||||
if value.lower() not in entity_type_map:
|
||||
raise serializers.ValidationError(
|
||||
f"Invalid entity_type. Must be one of: {', '.join(entity_type_map.keys())}"
|
||||
)
|
||||
|
||||
return value.lower()
|
||||
|
||||
def validate_changes(self, value):
|
||||
"""Validate changes is a proper JSON object."""
|
||||
if not isinstance(value, dict):
|
||||
raise serializers.ValidationError("Changes must be a JSON object")
|
||||
if not value:
|
||||
raise serializers.ValidationError("Changes cannot be empty")
|
||||
return value
|
||||
|
||||
def validate(self, attrs):
|
||||
"""Cross-field validation."""
|
||||
submission_type = attrs.get("submission_type", "EDIT")
|
||||
object_id = attrs.get("object_id")
|
||||
|
||||
# For EDIT submissions, object_id is required
|
||||
if submission_type == "EDIT" and not object_id:
|
||||
raise serializers.ValidationError(
|
||||
{"object_id": "object_id is required for EDIT submissions"}
|
||||
)
|
||||
|
||||
# For CREATE submissions, object_id should be null
|
||||
if submission_type == "CREATE" and object_id:
|
||||
raise serializers.ValidationError(
|
||||
{"object_id": "object_id must be null for CREATE submissions"}
|
||||
)
|
||||
|
||||
return attrs
|
||||
|
||||
def create(self, validated_data):
|
||||
"""Create a new submission."""
|
||||
entity_type = validated_data.pop("entity_type")
|
||||
|
||||
# Map entity_type to ContentType
|
||||
entity_type_map = {
|
||||
"park": ("parks", "park"),
|
||||
"ride": ("rides", "ride"),
|
||||
"company": ("parks", "company"),
|
||||
"ride_model": ("rides", "ridemodel"),
|
||||
"manufacturer": ("parks", "company"),
|
||||
"designer": ("parks", "company"),
|
||||
"operator": ("parks", "company"),
|
||||
"property_owner": ("parks", "company"),
|
||||
}
|
||||
|
||||
app_label, model_name = entity_type_map[entity_type]
|
||||
content_type = ContentType.objects.get(app_label=app_label, model=model_name)
|
||||
|
||||
# Set automatic fields
|
||||
validated_data["user"] = self.context["request"].user
|
||||
validated_data["content_type"] = content_type
|
||||
validated_data["status"] = "PENDING"
|
||||
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Moderation Report Serializers
|
||||
# ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user