115 lines
4.6 KiB
Python
115 lines
4.6 KiB
Python
"""
|
|
VOC 통계 분석 데이터 모델
|
|
|
|
통계 보고서 생성 및 분석 옵션을 정의하는 Pydantic 모델입니다.
|
|
데이터 유효성 검증, 기간 제한, 날짜 형식 검증 등을 수행합니다.
|
|
|
|
주요 모델:
|
|
- StatisticsReport: 통계 보고서 데이터
|
|
- StatisticsOptions: 분석 옵션
|
|
|
|
작성자: KH.Choi
|
|
최종 수정: 2026-02-18
|
|
버전: 1.1 (Pydantic v2 호환성 수정)
|
|
"""
|
|
import re
|
|
from datetime import datetime, timedelta
|
|
from typing import Optional, List, Dict, Any
|
|
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
|
|
|
|
class StatisticsReport(BaseModel):
|
|
"""
|
|
VOC 통계 분석 보고서 데이터 모델
|
|
|
|
통계 분석 결과를 담는 데이터 모델입니다.
|
|
기간별, 부서별, 상태별 통계와 키워드 분석 결과를 포함합니다.
|
|
"""
|
|
|
|
period_start: str = Field(..., description="분석 기간 시작일 (YYYY-MM-DD)")
|
|
period_end: str = Field(..., description="분석 기간 종료일 (YYYY-MM-DD)")
|
|
total_count: int = Field(0, description="총 VOC 건수", ge=0)
|
|
by_department: Dict[str, int] = Field(default_factory=dict, description="부서별 통계")
|
|
by_status: Dict[str, int] = Field(default_factory=dict, description="상태별 통계")
|
|
by_date: Dict[str, int] = Field(default_factory=dict, description="날짜별 통계")
|
|
top_keywords: List[tuple] = Field(default_factory=list, description="빈출 키워드 TOP 10")
|
|
charts: Dict[str, str] = Field(default_factory=dict, description="차트 이미지 경로")
|
|
generated_at: Optional[str] = Field(None, description="보고서 생성 시각")
|
|
|
|
@field_validator('period_start', 'period_end')
|
|
@classmethod
|
|
def validate_date_format(cls, v):
|
|
"""날짜 형식 검증 (YYYY-MM-DD)"""
|
|
pattern = r'^\d{4}-\d{2}-\d{2}$'
|
|
if not re.match(pattern, v):
|
|
raise ValueError(f"유효하지 않은 날짜 형식: {v} (YYYY-MM-DD 필요)")
|
|
|
|
try:
|
|
datetime.strptime(v, "%Y-%m-%d")
|
|
except ValueError as e:
|
|
raise ValueError(f"유효하지 않은 날짜: {v}")
|
|
return v
|
|
|
|
@model_validator(mode='after')
|
|
def validate_period(self):
|
|
"""기간 유효성 검증"""
|
|
start = self.period_start
|
|
end = self.period_end
|
|
|
|
if start and end:
|
|
start_date = datetime.strptime(start, "%Y-%m-%d")
|
|
end_date = datetime.strptime(end, "%Y-%m-%d")
|
|
|
|
if start_date > end_date:
|
|
raise ValueError("시작일이 종료일보다 늦을 수 없습니다.")
|
|
|
|
if (end_date - start_date).days > 365:
|
|
raise ValueError("분석 기간은 최대 1년까지만 가능합니다.")
|
|
return self
|
|
|
|
|
|
class StatisticsOptions(BaseModel):
|
|
"""
|
|
통계 분석 옵션 모델
|
|
"""
|
|
|
|
period_start: str = Field(..., description="분석 기간 시작일 (YYYY-MM-DD)")
|
|
period_end: str = Field(..., description="분석 기간 종료일 (YYYY-MM-DD)")
|
|
include_department: bool = Field(True, description="부서별 통계 포함 여부")
|
|
include_status: bool = Field(True, description="상태별 통계 포함 여부")
|
|
include_keywords: bool = Field(True, description="키워드 분석 포함 여부")
|
|
include_charts: bool = Field(True, description="차트 생성 여부")
|
|
output_format: str = Field("excel", pattern="^(excel|pdf|both)$", description="출력 형식")
|
|
output_path: Optional[str] = Field(None, description="저장 경로")
|
|
|
|
@field_validator('period_start', 'period_end')
|
|
@classmethod
|
|
def validate_date_format(cls, v):
|
|
"""날짜 형식 검증 (YYYY-MM-DD)"""
|
|
pattern = r'^\d{4}-\d{2}-\d{2}$'
|
|
if not re.match(pattern, v):
|
|
raise ValueError(f"유효하지 않은 날짜 형식: {v} (YYYY-MM-DD 필요)")
|
|
|
|
try:
|
|
datetime.strptime(v, "%Y-%m-%d")
|
|
except ValueError as e:
|
|
raise ValueError(f"유효하지 않은 날짜: {v}")
|
|
return v
|
|
|
|
@model_validator(mode='after')
|
|
def validate_period(self):
|
|
"""기간 유효성 검증"""
|
|
start = self.period_start
|
|
end = self.period_end
|
|
|
|
if start and end:
|
|
start_date = datetime.strptime(start, "%Y-%m-%d")
|
|
end_date = datetime.strptime(end, "%Y-%m-%d")
|
|
|
|
if start_date > end_date:
|
|
raise ValueError("시작일이 종료일보다 늦을 수 없습니다.")
|
|
|
|
if (end_date - start_date).days > 365:
|
|
raise ValueError("분석 기간은 최대 1년까지만 가능합니다.")
|
|
return self
|