diff --git a/app/integrations/llm/schemas/report.py b/app/integrations/llm/schemas/report.py index dc14bec..8f175b7 100644 --- a/app/integrations/llm/schemas/report.py +++ b/app/integrations/llm/schemas/report.py @@ -68,16 +68,18 @@ class RegistryData(BaseModel): class ClinicSnapshot(BaseModel): - name: str - name_en: str - staff_count: int - lead_doctor: LeadDoctor - overall_rating: float - total_reviews: int - certifications: list[str] - location: str - phone: str - domain: str + # _build_clinic_snapshot은 source 데이터 있을 때만 채움 (`if x:` 가드). + # required면 강남언니/홈페이지 누락 병원에서 ValidationError로 리포트 실패. + name: str | None = None + name_en: str | None = None + staff_count: int | None = None + lead_doctor: LeadDoctor | None = None + overall_rating: float | None = None + total_reviews: int | None = None + certifications: list[str] = [] + location: str | None = None + phone: str | None = None + domain: str | None = None logo_images: LogoImages | None = None brand_colors: BrandColors | None = None source: DataSource | None = None @@ -121,21 +123,23 @@ class TopVideo(BaseModel): class YouTubeAudit(BaseModel): - channel_name: str - handle: str - subscribers: int - total_videos: int - total_views: int - weekly_view_growth: WeeklyViewGrowth - estimated_monthly_revenue: EstimatedRevenue - avg_video_length: str - upload_frequency: str - channel_created_date: str - channel_description: str - linked_urls: list[LinkedUrl] - playlists: list[str] - top_videos: list[TopVideo] - diagnosis: list[DiagnosisItem] + # YouTube 미수집 병원에서 _build_youtube_audit가 채울 수 없는 필드 빔. + # required면 ValidationError로 리포트 실패 → Optional로 받아 부분 응답 허용. + channel_name: str | None = None + handle: str | None = None + subscribers: int | None = None + total_videos: int | None = None + total_views: int | None = None + weekly_view_growth: WeeklyViewGrowth | None = None + estimated_monthly_revenue: EstimatedRevenue | None = None + avg_video_length: str | None = None + upload_frequency: str | None = None + channel_created_date: str | None = None + channel_description: str | None = None + linked_urls: list[LinkedUrl] = [] + playlists: list[str] = [] + top_videos: list[TopVideo] = [] + diagnosis: list[DiagnosisItem] = [] # --- Instagram --- diff --git a/app/models/report.py b/app/models/report.py index a99f59d..67fa655 100644 --- a/app/models/report.py +++ b/app/models/report.py @@ -66,16 +66,18 @@ class RegistryData(CamelModel): class ClinicSnapshot(CamelModel): - name: str - name_en: str - staff_count: int - lead_doctor: LeadDoctor - overall_rating: float - total_reviews: int - certifications: list[str] - location: str - phone: str - domain: str + # _build_clinic_snapshot은 source 데이터 있을 때만 필드 추가 (`if x:` 가드). + # 강남언니/홈페이지 수집 누락된 병원에서 required면 ValidationError로 리포트 전체 실패. + name: str | None = None + name_en: str | None = None + staff_count: int | None = None + lead_doctor: LeadDoctor | None = None + overall_rating: float | None = None + total_reviews: int | None = None + certifications: list[str] = [] + location: str | None = None + phone: str | None = None + domain: str | None = None logo_images: LogoImages | None = None brand_colors: BrandColors | None = None source: DataSource | None = None @@ -115,42 +117,45 @@ class TopVideo(CamelModel): class YouTubeAudit(CamelModel): - channel_name: str - handle: str - subscribers: int - total_videos: int - total_views: int - weekly_view_growth: WeeklyViewGrowth - estimated_monthly_revenue: EstimatedRevenue - avg_video_length: str - upload_frequency: str - channel_created_date: str - channel_description: str - linked_urls: list[LinkedUrl] - playlists: list[str] - top_videos: list[TopVideo] - diagnosis: list[DiagnosisItem] + # YouTube 채널 없는 병원이면 _build_youtube_audit가 채울 수 없는 필드들 (channel_name 등)이 빔. + # required면 ValidationError로 리포트 실패 → Optional로 받아 부분 응답 허용. + channel_name: str | None = None + handle: str | None = None + subscribers: int | None = None + total_videos: int | None = None + total_views: int | None = None + weekly_view_growth: WeeklyViewGrowth | None = None + estimated_monthly_revenue: EstimatedRevenue | None = None + avg_video_length: str | None = None + upload_frequency: str | None = None + channel_created_date: str | None = None + channel_description: str | None = None + linked_urls: list[LinkedUrl] = [] + playlists: list[str] = [] + top_videos: list[TopVideo] = [] + diagnosis: list[DiagnosisItem] = [] class InstagramAccount(CamelModel): - handle: str - language: Language - label: str - posts: int - followers: int - following: int - category: str - profile_link: str - highlights: list[str] - reels_count: int - content_format: str - profile_photo: str - bio: str + # 인스타 계정(KR/EN) 미수집 시 빈 필드 가능 — Optional. + handle: str | None = None + language: Language | None = None + label: str | None = None + posts: int | None = None + followers: int | None = None + following: int | None = None + category: str | None = None + profile_link: str | None = None + highlights: list[str] = [] + reels_count: int | None = None + content_format: str | None = None + profile_photo: str | None = None + bio: str | None = None class InstagramAudit(CamelModel): - accounts: list[InstagramAccount] - diagnosis: list[DiagnosisItem] + accounts: list[InstagramAccount] = [] + diagnosis: list[DiagnosisItem] = [] class BrandInconsistencyValue(CamelModel): @@ -167,31 +172,32 @@ class BrandInconsistency(CamelModel): class FacebookPage(CamelModel): - url: str - page_name: str - language: Language - label: str - followers: int - following: int - category: str - bio: str - logo: str - logo_description: str - link: str - linked_domain: str - reviews: int - recent_post_age: str - has_whatsapp: bool + # 페북 페이지(KR/EN) 미수집 시 빈 필드 가능 — Optional. + url: str | None = None + page_name: str | None = None + language: Language | None = None + label: str | None = None + followers: int | None = None + following: int | None = None + category: str | None = None + bio: str | None = None + logo: str | None = None + logo_description: str | None = None + link: str | None = None + linked_domain: str | None = None + reviews: int | None = None + recent_post_age: str | None = None + has_whatsapp: bool | None = None post_frequency: str | None = None top_content_type: str | None = None engagement: str | None = None class FacebookAudit(CamelModel): - pages: list[FacebookPage] - diagnosis: list[DiagnosisItem] - brand_inconsistencies: list[BrandInconsistency] - consolidation_recommendation: str + pages: list[FacebookPage] = [] + diagnosis: list[DiagnosisItem] = [] + brand_inconsistencies: list[BrandInconsistency] = [] + consolidation_recommendation: str | None = None class OtherChannel(CamelModel):