from sqlalchemy import Column, String, Integer, Float, DateTime, JSON, ForeignKey from sqlalchemy.dialects.mysql import DECIMAL from sqlalchemy.sql import func, select from pydantic import BaseModel, Field from typing import Optional, List from datetime import datetime from .database import Base from app.core.utils import CommonUtils from app.core.imageprocessor import process_image, ImageFormat # 数据库模型 class MerchantDB(Base): __tablename__ = "merchants" id = Column(Integer, primary_key=True, autoincrement=True) user_id = Column(Integer, ForeignKey("users.userid"), nullable=False) # 归属用户 name = Column(String(100), nullable=False) business_hours = Column(String(100), nullable=False) # 营业时间,如 "09:00-22:00" address = Column(String(200), nullable=False) longitude = Column(DECIMAL(9, 6), nullable=False) # 经度,精确到小数点后6位 latitude = Column(DECIMAL(9, 6), nullable=False) # 纬度,精确到小数点后6位 phone = Column(String(20), nullable=False) brand_image_url = Column(String(200)) # 品牌图片地址 pay_gift_points_rate = Column(DECIMAL(4,2), nullable=False, default=0.00) # 支付赠送积分比例,默认0% pay_share_rate = Column(DECIMAL(4,2), nullable=False, default=0.00) # 在线买单分润比例,默认0% create_time = Column(DateTime(timezone=True), server_default=func.now()) update_time = Column(DateTime(timezone=True), onupdate=func.now()) category_id = Column(Integer, ForeignKey("merchant_categories.id"), nullable=True) @property def optimized_brand_image_url(self): return process_image(self.brand_image_url).quality(80).thumbnail(width=450, height=450).format(ImageFormat.WEBP).build() class MerchantCreate(BaseModel): user_id: int name: str = Field(..., max_length=100) business_hours: str = Field(..., max_length=100) address: str = Field(..., max_length=200) longitude: float = Field(..., ge=-180, le=180, description="经度") latitude: float = Field(..., ge=-90, le=90, description="纬度") phone: str = Field(..., max_length=20, pattern=r'^\d+$') pay_gift_points_rate: Optional[float] = Field(10.00, ge=0, le=100) # 支付赠送积分比例 pay_share_rate: Optional[float] = Field(0.00, ge=0, le=100) # 在线买单分润比例 brand_image_url: Optional[str] = Field(None, max_length=200) category_id: Optional[int] = None class MerchantUpdate(BaseModel): user_id: Optional[int] = None name: Optional[str] = Field(None, max_length=100) business_hours: Optional[str] = Field(None, max_length=100) address: Optional[str] = Field(None, max_length=200) longitude: Optional[float] = Field(None, ge=-180, le=180, description="经度") latitude: Optional[float] = Field(None, ge=-90, le=90, description="纬度") phone: Optional[str] = Field(None, max_length=20, pattern=r'^\d+$') pay_gift_points_rate: Optional[float] = Field(None, ge=0, le=100) # 支付赠送积分比例 pay_share_rate: Optional[float] = Field(None, ge=0, le=100) # 在线买单分润比例 brand_image_url: Optional[str] = Field(None, max_length=200) category_id: Optional[int] = None class MerchantInfo(BaseModel): id: int user_id: int user_phone: Optional[str] = None user_nickname: Optional[str] = None online_pay_count: Optional[int] = 0 name: str business_hours: str address: str longitude: float latitude: float distance: Optional[int] = None # 距离(米) phone: str pay_gift_points_rate: float pay_share_rate: float brand_image_url: Optional[str] = None optimized_brand_image_url: Optional[str] = None create_time: datetime update_time: Optional[datetime] distance: Optional[int] = None # 距离(米) category_id: Optional[int] = None category_name: Optional[str] = None # 用于关联查询显示分类名称 class Config: from_attributes = True