deliveryman-api/app/models/community.py
2025-03-14 23:10:40 +08:00

138 lines
5.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from typing import Optional
import enum
from sqlalchemy import Column, Integer, String, DECIMAL, DateTime, Enum, ForeignKey
from sqlalchemy.sql import func
from pydantic import BaseModel, Field, model_validator
from .database import Base
from sqlalchemy.orm import relationship, backref
from app.core.imageprocessor import process_image, ImageFormat
from app.core import utils
class CommunityStatus(str, enum.Enum):
UNOPEN = "UNOPEN" # 未运营
OPENING = "OPENING" # 已运营
# 数据库模型
class CommunityDB(Base):
__tablename__ = "communities"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(100), nullable=False)
address = Column(String(200), nullable=False)
longitude = Column(DECIMAL(9,6), nullable=False) # 经度精确到小数点后6位
latitude = Column(DECIMAL(9,6), nullable=False) # 纬度精确到小数点后6位
status = Column(Enum(CommunityStatus), nullable=False, default=CommunityStatus.UNOPEN)
qy_group_qrcode = Column(String(200), nullable=True) # 企业微信群二维码地址
webot_webhook = Column(String(200), nullable=True) # 企业微信机器人webhook
# 小区定价
base_price = Column(DECIMAL(10,2), nullable=False, default=3.0) # 基础费用
extra_package_price = Column(DECIMAL(10,2), nullable=False, default=1.0) # 额外包裹费用
extra_package_threshold = Column(Integer, nullable=False, default=2) # 额外收费阈值
more_station_price = Column(DECIMAL(10,2), nullable=False, default=2.0) # 多驿站加价
create_time = Column(DateTime(timezone=True), server_default=func.now())
update_time = Column(DateTime(timezone=True), onupdate=func.now())
admin_id = Column(Integer, ForeignKey("users.userid"), nullable=True)
# 关联管理员 - 明确指定外键
admin = relationship("UserDB", foreign_keys=[admin_id], backref=backref("managed_communities", lazy="dynamic"))
# 通过映射表关联的社区分润
community_profit_sharing = relationship("CommunityProfitSharing", backref="community", uselist=False)
# 关联社区集合
community_set_mappings = relationship("CommunitySetMapping", backref="community")
@property
def optimized_qy_group_qrcode(self):
if self.qy_group_qrcode:
return process_image(self.qy_group_qrcode).thumbnail(800, 800).format(ImageFormat.WEBP).build()
return None
# Pydantic 模型
class CommunityCreate(BaseModel):
name: str = Field(..., max_length=100)
address: str = Field(..., max_length=200)
longitude: float = Field(..., ge=-180, le=180)
latitude: float = Field(..., ge=-90, le=90)
status: CommunityStatus = Field(default=CommunityStatus.UNOPEN)
qy_group_qrcode: Optional[str] = Field(None, max_length=200)
webot_webhook: Optional[str] = Field(None, max_length=200)
class CommunityUpdate(BaseModel):
name: Optional[str] = Field(None, max_length=100)
address: Optional[str] = Field(None, max_length=200)
longitude: Optional[float] = Field(None, ge=-180, le=180)
latitude: Optional[float] = Field(None, ge=-90, le=90)
status: Optional[CommunityStatus] = None
qy_group_qrcode: Optional[str] = Field(None, max_length=200)
webot_webhook: Optional[str] = Field(None, max_length=200)
base_price: Optional[float] = Field(None)
extra_package_price: Optional[float] = Field(None)
extra_package_threshold: Optional[int] = Field(None)
more_station_price: Optional[float] = Field(None)
admin_id: Optional[int] = Field(None)
class CommunityInfo(BaseModel):
id: int
name: str
address: str
latitude: float
longitude: float
admin_id: Optional[int] = None
status: CommunityStatus
qy_group_qrcode: Optional[str] = None
webot_webhook: Optional[str] = None
base_price: Optional[float] = None
extra_package_price: Optional[float] = None
extra_package_threshold: Optional[int] = None
more_station_price: Optional[float] = None
optimized_qy_group_qrcode: Optional[str] = None
distance: Optional[float] = None # 距离,单位:米
# 添加分润信息字段
profit_sharing: Optional[dict] = None
# 添加管理员信息字段
admin: Optional[object] = None
class Config:
from_attributes = True
@model_validator(mode='after')
def set_admin(self):
if hasattr(self, 'admin') and getattr(self, 'admin') is not None:
admin = getattr(self, 'admin')
# 检查admin是否已经是字典类型
if isinstance(admin, dict):
return self
# 处理UserDB对象
try:
self.admin = {
"id": admin.userid,
"nickname": admin.nickname if hasattr(admin, 'nickname') else None,
"phone": utils.CommonUtils.desensitize_phone(admin.phone) if hasattr(admin, 'phone') and admin.phone else None,
"avatar": admin.avatar if hasattr(admin, 'avatar') else None
}
except Exception as e:
# 如果处理失败设置为None
self.admin = None
return self
@model_validator(mode='after')
def set_profit_sharing(self):
# 从ORM对象中获取分润信息
if hasattr(self, 'community_profit_sharing') and getattr(self, 'community_profit_sharing') is not None:
profit_sharing = getattr(self, 'community_profit_sharing')
self.profit_sharing = {
"id": profit_sharing.id,
"platform_rate": profit_sharing.platform_rate,
"partner_rate": profit_sharing.partner_rate,
"admin_rate": profit_sharing.admin_rate,
"delivery_rate": profit_sharing.delivery_rate
}
return self