"""竞品机构 Schema""" from typing import Optional from datetime import datetime, date from enum import Enum from pydantic import BaseModel, Field class Positioning(str, Enum): """机构定位枚举""" HIGH = "high" # 高端 MEDIUM = "medium" # 中端 BUDGET = "budget" # 大众 class PriceSource(str, Enum): """价格来源枚举""" OFFICIAL = "official" # 官网 MEITUAN = "meituan" # 美团 DIANPING = "dianping" # 大众点评 SURVEY = "survey" # 实地调研 # ============ 竞品机构 Schema ============ class CompetitorBase(BaseModel): """竞品机构基础字段""" competitor_name: str = Field(..., min_length=1, max_length=100, description="机构名称") address: Optional[str] = Field(None, max_length=200, description="地址") distance_km: Optional[float] = Field(None, ge=0, description="距离(公里)") positioning: Positioning = Field(Positioning.MEDIUM, description="定位") contact: Optional[str] = Field(None, max_length=50, description="联系方式") is_key_competitor: bool = Field(False, description="是否重点关注") is_active: bool = Field(True, description="是否启用") class CompetitorCreate(CompetitorBase): """创建竞品机构请求""" pass class CompetitorUpdate(BaseModel): """更新竞品机构请求""" competitor_name: Optional[str] = Field(None, min_length=1, max_length=100, description="机构名称") address: Optional[str] = Field(None, max_length=200, description="地址") distance_km: Optional[float] = Field(None, ge=0, description="距离(公里)") positioning: Optional[Positioning] = Field(None, description="定位") contact: Optional[str] = Field(None, max_length=50, description="联系方式") is_key_competitor: Optional[bool] = Field(None, description="是否重点关注") is_active: Optional[bool] = Field(None, description="是否启用") class CompetitorResponse(CompetitorBase): """竞品机构响应""" id: int price_count: int = Field(0, description="价格记录数") last_price_update: Optional[date] = Field(None, description="最后价格更新日期") created_at: datetime updated_at: datetime class Config: from_attributes = True # ============ 竞品价格 Schema ============ class CompetitorPriceBase(BaseModel): """竞品价格基础字段""" project_id: Optional[int] = Field(None, description="关联本店项目ID") project_name: str = Field(..., min_length=1, max_length=100, description="竞品项目名称") original_price: float = Field(..., gt=0, description="原价") promo_price: Optional[float] = Field(None, gt=0, description="促销价") member_price: Optional[float] = Field(None, gt=0, description="会员价") price_source: PriceSource = Field(..., description="价格来源") collected_at: date = Field(..., description="采集日期") remark: Optional[str] = Field(None, max_length=200, description="备注") class CompetitorPriceCreate(CompetitorPriceBase): """创建竞品价格请求""" pass class CompetitorPriceUpdate(BaseModel): """更新竞品价格请求""" project_id: Optional[int] = Field(None, description="关联本店项目ID") project_name: Optional[str] = Field(None, min_length=1, max_length=100, description="竞品项目名称") original_price: Optional[float] = Field(None, gt=0, description="原价") promo_price: Optional[float] = Field(None, gt=0, description="促销价") member_price: Optional[float] = Field(None, gt=0, description="会员价") price_source: Optional[PriceSource] = Field(None, description="价格来源") collected_at: Optional[date] = Field(None, description="采集日期") remark: Optional[str] = Field(None, max_length=200, description="备注") class CompetitorPriceResponse(CompetitorPriceBase): """竞品价格响应""" id: int competitor_id: int competitor_name: Optional[str] = Field(None, description="竞品机构名称") created_at: datetime updated_at: datetime class Config: from_attributes = True