Aus_F / models /event_models.py
minhvtt's picture
Upload 19 files
ea06065 verified
"""
Event-Centric Pydantic Models for MongoDB
Author: AI Generated
Created: 2025-11-24
Purpose: Define schemas for event-specific analysis results
"""
from pydantic import BaseModel, Field
from typing import List, Dict, Optional, Any
from datetime import datetime
from bson import ObjectId
class PyObjectId(ObjectId):
"""Custom ObjectId type for Pydantic v2"""
@classmethod
def __get_pydantic_core_schema__(cls, source_type, handler):
from pydantic_core import core_schema
return core_schema.union_schema([
core_schema.is_instance_schema(ObjectId),
core_schema.chain_schema([
core_schema.str_schema(),
core_schema.no_info_plain_validator_function(cls.validate),
])
],
serialization=core_schema.plain_serializer_function_ser_schema(
lambda x: str(x)
))
@classmethod
def validate(cls, v):
if isinstance(v, ObjectId):
return v
if isinstance(v, str):
if not ObjectId.is_valid(v):
raise ValueError(f"Invalid ObjectId: {v}")
return ObjectId(v)
raise ValueError(f"Expected ObjectId or string, got {type(v)}")
class MarketingContent(BaseModel):
"""Marketing email content generated by AI"""
email_subject: str
email_body: str
status: str = "Draft" # Draft, Approved, Sent
generated_at: datetime = Field(default_factory=datetime.utcnow)
approved_at: Optional[datetime] = None
approved_by: Optional[str] = None
class EventAudienceSegment(BaseModel):
"""
Audience segment specific to an event.
Stores clustering results and marketing content for Event Owner review.
"""
id: Optional[PyObjectId] = Field(default=None, alias="_id")
event_code: str = Field(..., description="Event identifier")
segment_name: str = Field(..., description="Human-readable segment name in Vietnamese")
segment_type: str = Field(..., description="Segment category (e.g., VIP, Potential, Dormant)")
user_count: int = Field(..., description="Number of users in this segment")
user_ids: List[PyObjectId] = Field(default_factory=list, description="List of user ObjectIds in this segment")
criteria: Dict[str, Any] = Field(
default_factory=dict,
description="Average statistics for this segment (e.g., avg_spend, avg_tickets, avg_recency)"
)
marketing_content: Optional[MarketingContent] = Field(
default=None,
description="AI-generated marketing email (Draft, pending approval)"
)
created_at: datetime = Field(default_factory=datetime.utcnow)
last_updated: datetime = Field(default_factory=datetime.utcnow)
class Config:
populate_by_name = True
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}
class AIInsights(BaseModel):
"""AI-generated insights from sentiment analysis"""
summary: str = Field(..., description="Overall sentiment summary in Vietnamese")
top_issues: List[str] = Field(default_factory=list, description="Top 5 recurring issues")
improvement_suggestions: List[str] = Field(default_factory=list, description="Actionable suggestions")
predicted_nps: Optional[float] = Field(None, description="Predicted Net Promoter Score (0-100)")
class EventSentimentSummary(BaseModel):
"""
Aggregated sentiment analysis summary for an event.
Provides Event Owner with quick insights about attendee feedback.
"""
id: Optional[PyObjectId] = Field(default=None, alias="_id")
event_code: str = Field(..., description="Event identifier")
total_comments: int = Field(default=0, description="Total number of comments analyzed")
sentiment_distribution: Dict[str, int] = Field(
default_factory=dict,
description="Count of Positive, Negative, Neutral comments"
)
avg_confidence: float = Field(default=0.0, description="Average confidence score of sentiment predictions")
top_keywords: List[str] = Field(
default_factory=list,
description="Most frequently mentioned keywords/phrases"
)
ai_insights: Optional[AIInsights] = Field(
default=None,
description="AI-generated insights and recommendations"
)
last_updated: datetime = Field(default_factory=datetime.utcnow)
class Config:
populate_by_name = True
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}