from datetime import datetime from typing import List, Optional from pydantic import BaseModel, Field, field_validator class PreTestTemplateCreate(BaseModel): name: str = Field(..., description="模板名称") note: Optional[str] = Field(None, description="模板备注") platform: Optional[str] = Field(None, description="投放平台(AD/QIANCHUAN/LOCAL)") external_action: Optional[str] = Field(None, description="转化目标") cpa_bid: Optional[float] = Field(None, description="目标转化成本:[1, 10000]") audience_gender: Optional[str] = Field(None, description="性别(ALL/MALE/FEMALE)") audience_age: Optional[List[str]] = Field(None, description="受众年龄列表") audience_region: Optional[List[int]] = Field(None, description="受众地区code列表") audience_network: Optional[List[str]] = Field(None, description="网络类型列表") cus_name: Optional[str] = Field(None, description="客户主体名称") pricing_type: Optional[str] = Field(None, description="出价类型(OCPC/CPA/OCPM)") cost_cap: Optional[bool] = Field(None, description="是否最优成本出价(仅AD支持)") target_cost: Optional[bool] = Field(None, description="是否稳定成本出价(仅AD支持)") nobid: Optional[bool] = Field(None, description="是否最大转化出价(仅AD支持)") cpc_bid: Optional[float] = Field(None, description="目标点击成本:[1, 10000]") budget: Optional[float] = Field(None, description="预算金额:[1, 10000]") is_default: Optional[bool] = Field(None, description="是否设为默认模板") @field_validator('platform') def validate_platform(cls, v): if v is None: return v allowed = ["AD", "QIANCHUAN", "LOCAL"] if v not in allowed: raise ValueError(f"platform must be one of {allowed}") return v @field_validator('pricing_type') def validate_pricing_type(cls, v): if v is None: return v allowed = ["OCPC", "CPA", "OCPM"] if v not in allowed: raise ValueError(f"pricing_type must be one of {allowed}") return v @field_validator('audience_gender') def validate_gender(cls, v): if v is None: return v allowed = ["ALL", "MALE", "FEMALE"] if v not in allowed: raise ValueError(f"audience_gender must be one of {allowed}") return v class PreTestTemplateUpdate(BaseModel): name: Optional[str] = Field(None, description="模板名称") note: Optional[str] = Field(None, description="模板备注") platform: Optional[str] = Field(None, description="投放平台") external_action: Optional[str] = Field(None, description="转化目标") cpa_bid: Optional[float] = Field(None, description="目标转化成本") audience_gender: Optional[str] = Field(None, description="性别") audience_age: Optional[List[str]] = Field(None, description="受众年龄列表") audience_region: Optional[List[int]] = Field(None, description="受众地区code列表") audience_network: Optional[List[str]] = Field(None, description="网络类型列表") cus_name: Optional[str] = Field(None, description="客户主体名称") pricing_type: Optional[str] = Field(None, description="出价类型") cost_cap: Optional[bool] = Field(None, description="是否最优成本出价") target_cost: Optional[bool] = Field(None, description="是否稳定成本出价") nobid: Optional[bool] = Field(None, description="是否最大转化出价") cpc_bid: Optional[float] = Field(None, description="目标点击成本") budget: Optional[float] = Field(None, description="预算金额") is_default: Optional[bool] = Field(None, description="是否设为默认模板") class PreTestTemplateOut(BaseModel): id: str = Field(..., description="主键") name: str = Field(..., description="模板名称") note: Optional[str] = Field(None, description="模板备注") platform: Optional[str] = Field(None, description="投放平台") external_action: Optional[str] = Field(None, description="转化目标") cpa_bid: Optional[float] = Field(None, description="目标转化成本") audience_gender: Optional[str] = Field(None, description="性别") audience_age: Optional[List[str]] = Field(None, description="受众年龄列表") audience_region: Optional[List[int]] = Field(None, description="受众地区code列表") audience_network: Optional[List[str]] = Field(None, description="网络类型列表") cus_name: Optional[str] = Field(None, description="客户主体名称") pricing_type: Optional[str] = Field(None, description="出价类型") cost_cap: Optional[bool] = Field(None, description="是否最优成本出价") target_cost: Optional[bool] = Field(None, description="是否稳定成本出价") nobid: Optional[bool] = Field(None, description="是否最大转化出价") cpc_bid: Optional[float] = Field(None, description="目标点击成本") budget: Optional[float] = Field(None, description="预算金额") is_default: Optional[bool] = Field(None, description="是否默认模板") user_id: str = Field(..., description="用户id") created_at: datetime = Field(..., description="创建时间") updated_at: datetime = Field(..., description="更新时间") model_config = {"from_attributes": True} class PaginationInfo(BaseModel): page: int = Field(..., description="当前页码") page_size: int = Field(..., description="每页数量") total: int = Field(..., description="总记录数") total_pages: int = Field(..., description="总页数") class PreTestTemplateListResponse(BaseModel): code: int = Field(0, description="返回码") message: str = Field("查询成功", description="返回消息") data: List[PreTestTemplateOut] = Field(..., description="模板列表") pagination: PaginationInfo = Field(..., description="分页信息")