from typing import Optional, List from pydantic import BaseModel, Field from datetime import datetime class CategoryBase(BaseModel): parent_id: Optional[int] = None level: int = 1 code: str = Field(..., max_length=50) name: str = Field(..., max_length=100) description: Optional[str] = None sort_order: int = 0 class CategoryCreate(CategoryBase): pass class CategoryUpdate(BaseModel): parent_id: Optional[int] = None code: Optional[str] = Field(None, max_length=50) name: Optional[str] = Field(None, max_length=100) description: Optional[str] = None sort_order: Optional[int] = None class CategoryOut(CategoryBase): id: int created_at: datetime class Config: from_attributes = True class CategoryTree(CategoryOut): children: List["CategoryTree"] = [] class DataLevelOut(BaseModel): id: int code: str name: str description: Optional[str] = None color: str control_requirements: Optional[dict] = None sort_order: int class Config: from_attributes = True class RecognitionRuleBase(BaseModel): template_id: int category_id: Optional[int] = None level_id: Optional[int] = None rule_type: str = Field(..., max_length=20) # regex, keyword, enum rule_name: Optional[str] = Field(None, max_length=100) rule_content: str target_field: str = Field(default="column_name", max_length=20) priority: int = 100 is_active: bool = True class RecognitionRuleCreate(RecognitionRuleBase): pass class RecognitionRuleUpdate(BaseModel): category_id: Optional[int] = None level_id: Optional[int] = None rule_type: Optional[str] = Field(None, max_length=20) rule_name: Optional[str] = Field(None, max_length=100) rule_content: Optional[str] = None target_field: Optional[str] = Field(None, max_length=20) priority: Optional[int] = None is_active: Optional[bool] = None class RecognitionRuleOut(RecognitionRuleBase): id: int hit_count: int created_at: datetime category_name: Optional[str] = None level_name: Optional[str] = None level_color: Optional[str] = None class Config: from_attributes = True class TemplateOut(BaseModel): id: int name: str industry_type: str version: str description: Optional[str] = None is_builtin: bool is_active: bool created_at: datetime class Config: from_attributes = True