127 lines
4.0 KiB
Python
127 lines
4.0 KiB
Python
"""Pydantic models for database entities."""
|
|
from datetime import datetime
|
|
from typing import Optional, Dict, Any, List
|
|
from uuid import UUID
|
|
from pydantic import BaseModel, Field, ConfigDict
|
|
|
|
|
|
class DBModel(BaseModel):
|
|
"""Base model for database entities with extra fields ignored."""
|
|
model_config = ConfigDict(extra='ignore')
|
|
|
|
|
|
class Customer(DBModel):
|
|
"""Customer/Client model."""
|
|
id: Optional[UUID] = None
|
|
created_at: Optional[datetime] = None
|
|
updated_at: Optional[datetime] = None
|
|
name: str
|
|
email: Optional[str] = None
|
|
company_name: Optional[str] = None
|
|
linkedin_url: str
|
|
metadata: Dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class PostType(DBModel):
|
|
"""Post type model for categorizing different types of posts."""
|
|
id: Optional[UUID] = None
|
|
customer_id: UUID
|
|
created_at: Optional[datetime] = None
|
|
updated_at: Optional[datetime] = None
|
|
name: str
|
|
description: Optional[str] = None
|
|
identifying_hashtags: List[str] = Field(default_factory=list)
|
|
identifying_keywords: List[str] = Field(default_factory=list)
|
|
semantic_properties: Dict[str, Any] = Field(default_factory=dict)
|
|
analysis: Optional[Dict[str, Any]] = None
|
|
analysis_generated_at: Optional[datetime] = None
|
|
analyzed_post_count: int = 0
|
|
is_active: bool = True
|
|
|
|
|
|
class LinkedInProfile(DBModel):
|
|
"""LinkedIn profile model."""
|
|
id: Optional[UUID] = None
|
|
customer_id: UUID
|
|
scraped_at: Optional[datetime] = None
|
|
profile_data: Dict[str, Any]
|
|
name: Optional[str] = None
|
|
headline: Optional[str] = None
|
|
summary: Optional[str] = None
|
|
location: Optional[str] = None
|
|
industry: Optional[str] = None
|
|
|
|
|
|
class LinkedInPost(DBModel):
|
|
"""LinkedIn post model."""
|
|
id: Optional[UUID] = None
|
|
customer_id: UUID
|
|
scraped_at: Optional[datetime] = None
|
|
post_url: Optional[str] = None
|
|
post_text: str
|
|
post_date: Optional[datetime] = None
|
|
likes: int = 0
|
|
comments: int = 0
|
|
shares: int = 0
|
|
raw_data: Optional[Dict[str, Any]] = None
|
|
# Post type classification fields
|
|
post_type_id: Optional[UUID] = None
|
|
classification_method: Optional[str] = None # 'hashtag', 'keyword', 'semantic'
|
|
classification_confidence: Optional[float] = None
|
|
|
|
|
|
class Topic(DBModel):
|
|
"""Topic model."""
|
|
id: Optional[UUID] = None
|
|
customer_id: UUID
|
|
created_at: Optional[datetime] = None
|
|
title: str
|
|
description: Optional[str] = None
|
|
category: Optional[str] = None
|
|
extracted_from_post_id: Optional[UUID] = None
|
|
extraction_confidence: Optional[float] = None
|
|
is_used: bool = False
|
|
used_at: Optional[datetime] = None
|
|
target_post_type_id: Optional[UUID] = None # Target post type for this topic
|
|
|
|
|
|
class ProfileAnalysis(DBModel):
|
|
"""Profile analysis model."""
|
|
id: Optional[UUID] = None
|
|
customer_id: UUID
|
|
created_at: Optional[datetime] = None
|
|
writing_style: Dict[str, Any]
|
|
tone_analysis: Dict[str, Any]
|
|
topic_patterns: Dict[str, Any]
|
|
audience_insights: Dict[str, Any]
|
|
full_analysis: Dict[str, Any]
|
|
|
|
|
|
class ResearchResult(DBModel):
|
|
"""Research result model."""
|
|
id: Optional[UUID] = None
|
|
customer_id: UUID
|
|
created_at: Optional[datetime] = None
|
|
query: str
|
|
results: Dict[str, Any]
|
|
suggested_topics: List[Dict[str, Any]]
|
|
source: str = "perplexity"
|
|
target_post_type_id: Optional[UUID] = None # Target post type for this research
|
|
|
|
|
|
class GeneratedPost(DBModel):
|
|
"""Generated post model."""
|
|
id: Optional[UUID] = None
|
|
customer_id: UUID
|
|
created_at: Optional[datetime] = None
|
|
topic_id: Optional[UUID] = None
|
|
topic_title: str
|
|
post_content: str
|
|
iterations: int = 0
|
|
writer_versions: List[str] = Field(default_factory=list)
|
|
critic_feedback: List[Dict[str, Any]] = Field(default_factory=list)
|
|
status: str = "draft" # draft, approved, published, rejected
|
|
approved_at: Optional[datetime] = None
|
|
published_at: Optional[datetime] = None
|
|
post_type_id: Optional[UUID] = None # Post type used for this generated post
|