This commit is contained in:
aaron 2025-03-12 12:40:43 +08:00
parent ab63e8541c
commit 861d5258fb
6 changed files with 56 additions and 9 deletions

View File

@ -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))

View File

@ -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()

View File

@ -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:
"""

View File

@ -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):

View File

@ -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):

Binary file not shown.