From 861d5258fb01baeca1e2a89656034b988184cf42 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Wed, 12 Mar 2025 12:40:43 +0800 Subject: [PATCH] update --- app/api/endpoints/community.py | 11 ++++++-- app/api/endpoints/coupon_activity.py | 4 +-- app/core/utils.py | 7 +++++ app/models/community.py | 38 ++++++++++++++++++++++++--- app/models/user.py | 5 +++- jobs.sqlite | Bin 24576 -> 24576 bytes 6 files changed, 56 insertions(+), 9 deletions(-) diff --git a/app/api/endpoints/community.py b/app/api/endpoints/community.py index 2fb5cac..c0be386 100644 --- a/app/api/endpoints/community.py +++ b/app/api/endpoints/community.py @@ -11,6 +11,7 @@ from app.models.user import UserDB from app.core.response import success_response, error_response, ResponseModel from app.models.community_profit_sharing import CommunityProfitSharing from app.api.endpoints.community_profit_sharing import CommunityProfitSharingResponse +from app.core import utils router = APIRouter() @@ -71,7 +72,7 @@ async def get_communities( """获取社区列表""" # 构建查询, 关联社区分润 # 使用一次查询获取所有需要的数据,减少数据库连接使用时间 - query = db.query(CommunityDB).options(joinedload(CommunityDB.community_profit_sharing)) + query = db.query(CommunityDB).options(joinedload(CommunityDB.community_profit_sharing), joinedload(CommunityDB.admin)) # 状态过滤 if status: @@ -96,6 +97,12 @@ async def get_communities( "base_price": float(community.base_price), "extra_package_price": float(community.extra_package_price), "extra_package_threshold": community.extra_package_threshold, + "admin": None if community.admin is None else { + "id": community.admin.userid, + "nickname": community.admin.nickname, + "phone": utils.CommonUtils.desensitize_phone(community.admin.phone), + "avatar": community.admin.avatar + }, "profit_sharing": None if community.community_profit_sharing is None else { "id": community.community_profit_sharing.id, "platform_rate": float(community.community_profit_sharing.platform_rate), @@ -148,7 +155,7 @@ async def get_community( db: Session = Depends(get_db) ): """获取社区详情""" - community = db.query(CommunityDB).options(joinedload(CommunityDB.community_profit_sharing)).filter(CommunityDB.id == community_id).first() + community = db.query(CommunityDB).options(joinedload(CommunityDB.community_profit_sharing), joinedload(CommunityDB.admin)).filter(CommunityDB.id == community_id).first() if not community: return error_response(code=404, message="社区不存在") return success_response(data=CommunityInfo.model_validate(community)) diff --git a/app/api/endpoints/coupon_activity.py b/app/api/endpoints/coupon_activity.py index 17b2c7e..6c6deb3 100644 --- a/app/api/endpoints/coupon_activity.py +++ b/app/api/endpoints/coupon_activity.py @@ -84,7 +84,6 @@ async def get_coupon_activity( if activity.total_limit > 0: user_receive_count = db.query(func.count(CouponReceiveRecordDB.id)).filter( CouponReceiveRecordDB.activity_id == activity_id, - CouponReceiveRecordDB.user_id == current_user.userid ).scalar() if user_receive_count >= activity.total_limit: can_receive = False @@ -160,12 +159,11 @@ async def check_activity_can_receive( # 检查总领取次数 total_receive_count = db.query(func.count(CouponReceiveRecordDB.id)).filter( - CouponReceiveRecordDB.user_id == current_user.userid, CouponReceiveRecordDB.activity_id == activity_id ).scalar() if activity.total_limit > 0 and total_receive_count >= activity.total_limit: - return False, f"您只能领取 {activity.total_limit} 次", activity + return False, f"优惠券活动已领完", activity # 检查今日领取次数 today = datetime.now().date() diff --git a/app/core/utils.py b/app/core/utils.py index 0dd5751..63d0a92 100644 --- a/app/core/utils.py +++ b/app/core/utils.py @@ -37,6 +37,13 @@ class CommonUtils: timestamp = str(int(time.time() * 1000))[-6:] return f"{prefix}{date_str}{timestamp}" + @staticmethod + def desensitize_phone(phone: str) -> str: + """ + 手机号脱敏 + """ + return f"{phone[:3]}****{phone[7:]}" + @staticmethod def generate_verify_code() -> str: """ diff --git a/app/models/community.py b/app/models/community.py index 81d4886..f17d53b 100644 --- a/app/models/community.py +++ b/app/models/community.py @@ -1,11 +1,12 @@ from typing import Optional import enum -from sqlalchemy import Column, Integer, String, DECIMAL, DateTime, 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 +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" # 未运营 @@ -32,6 +33,11 @@ class CommunityDB(Base): 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) @@ -65,13 +71,14 @@ class CommunityUpdate(BaseModel): base_price: Optional[float] = Field(None) extra_package_price: Optional[float] = Field(None) extra_package_threshold: Optional[int] = 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 @@ -83,9 +90,34 @@ class CommunityInfo(BaseModel): # 添加分润信息字段 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): diff --git a/app/models/user.py b/app/models/user.py index f5e7902..234267b 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -9,7 +9,7 @@ import enum import random import string from app.core.imageprocessor import process_image, ImageFormat -from sqlalchemy.orm import relationship +from sqlalchemy.orm import relationship, backref class UserRole(str, enum.Enum): USER = "user" @@ -52,6 +52,9 @@ class UserDB(Base): update_time = Column(DateTime(timezone=True), onupdate=func.now()) community_id = Column(Integer, ForeignKey("communities.id"), nullable=True) # 归属小区 is_auth = Column(Boolean, nullable=False, default=False) + + # 用户所属小区关系 + community = relationship("CommunityDB", foreign_keys=[community_id], backref=backref("residents", lazy="dynamic")) @property def optimized_avatar(self): diff --git a/jobs.sqlite b/jobs.sqlite index b6dcd28672a0ba76bbf5234bbaafa524612735a6..4be9602c08688d48e83a585a6285d26f73f07702 100644 GIT binary patch delta 124 zcmZoTz}Rqrae_2s??f4A#@>wy3;B5&7#JA2D;c;exfe6-+}N1Sy;)4Wokf6){}lrx z|0y8ie+7b@1r2ubPd=rupa#?+3dCrD3&>~W|IWbwo&O#G5B?uO^>_Iv25?P&XV0