760 lines
24 KiB
Python
760 lines
24 KiB
Python
# purchase - 认购群API路由
|
||
# Version: 0.3.0 (2026-05-02)
|
||
# 新增:管理员审批功能
|
||
# 认购群、成员、藏品管理
|
||
|
||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||
from sqlalchemy.orm import Session
|
||
from pydantic import BaseModel
|
||
from typing import Optional, List
|
||
from datetime import datetime
|
||
from app.core.database import get_db
|
||
from app.core.auth import get_current_user
|
||
from app.models.models import User
|
||
from app.models.purchase import PurchaseGroup, PurchaseMember, PurchaseCollection
|
||
|
||
router = APIRouter(prefix="/api/purchase", tags=["认购"])
|
||
|
||
# ============ Schema ============
|
||
class PurchaseGroupCreate(BaseModel):
|
||
name: str
|
||
description: str
|
||
total_members: int
|
||
total_collections: int
|
||
cycle_months: int
|
||
start_date: str
|
||
|
||
class PurchaseGroupResponse(BaseModel):
|
||
cycle_months: Optional[int] = None
|
||
start_date: Optional[datetime] = None
|
||
id: str
|
||
group_code: str
|
||
name: str
|
||
description: Optional[str]
|
||
creator_id: str
|
||
creator_name: Optional[str]
|
||
status: str
|
||
total_members: int
|
||
total_pending: int
|
||
total_collections: int
|
||
total_confirmed: int
|
||
total_amount: float
|
||
avg_price: Optional[float] = None
|
||
created_at: Optional[datetime]
|
||
|
||
class PurchaseCollectionCreate(BaseModel):
|
||
collection_name: Optional[str] = None
|
||
collection_code: Optional[str] = None
|
||
number: Optional[str] = None
|
||
collection_code: Optional[str] = None
|
||
grading: Optional[str] = None
|
||
boss_name: Optional[str] = None
|
||
price: Optional[float] = None
|
||
source: Optional[str] = None
|
||
paid: Optional[bool] = False
|
||
|
||
class PurchaseCollectionUpdate(BaseModel):
|
||
collection_name: Optional[str] = None
|
||
number: Optional[str] = None
|
||
grading: Optional[str] = None
|
||
boss_name: Optional[str] = None
|
||
price: Optional[float] = None
|
||
source: Optional[str] = None
|
||
paid: Optional[bool] = None
|
||
status: Optional[str] = None
|
||
|
||
class PurchaseCollectionResponse(BaseModel):
|
||
id: str
|
||
group_id: str
|
||
user_id: str
|
||
user_name: Optional[str]
|
||
collection_name: Optional[str]
|
||
collection_code: Optional[str]
|
||
number: Optional[str] = None
|
||
collection_code: Optional[str] = None
|
||
grading: Optional[str] = None
|
||
boss_name: Optional[str] = None
|
||
price: Optional[float] = None
|
||
source: Optional[str] = None
|
||
paid: bool
|
||
status: str
|
||
submit_date: Optional[datetime]
|
||
submitted_at: Optional[datetime]
|
||
|
||
class MemberResponse(BaseModel):
|
||
id: str
|
||
user_id: str
|
||
user_name: Optional[str]
|
||
user_avatar: Optional[str]
|
||
role: str
|
||
status: str
|
||
joined_at: Optional[datetime]
|
||
wechat_name: Optional[str] = None
|
||
contact: Optional[str] = None
|
||
purchase_count: Optional[int] = 0
|
||
paid_amount: Optional[float] = 0
|
||
notes: Optional[str] = None
|
||
|
||
# ============ 工具函数 ============
|
||
def generate_group_code(db: Session) -> str:
|
||
"""生成群编码:年+序号,如 26001"""
|
||
year = datetime.now().year % 100 # 26
|
||
# 查找当前年份最大的编号
|
||
last = db.query(PurchaseGroup).filter(
|
||
PurchaseGroup.group_code.like(f"{year}%")
|
||
).order_by(PurchaseGroup.group_code.desc()).first()
|
||
|
||
if last and last.group_code:
|
||
try:
|
||
num = int(last.group_code) + 1
|
||
except:
|
||
num = 1
|
||
else:
|
||
num = 1
|
||
|
||
return f"{year}{num:03d}" # 26001
|
||
|
||
# ============ 认购群API ============
|
||
|
||
@router.get("/groups", response_model=List[PurchaseGroupResponse])
|
||
def get_groups(
|
||
status: str = Query("active", description="过滤状态"),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取所有认购群列表"""
|
||
query = db.query(PurchaseGroup)
|
||
if status:
|
||
query = query.filter(PurchaseGroup.status == status)
|
||
groups = query.order_by(PurchaseGroup.created_at.desc()).all()
|
||
return groups
|
||
|
||
@router.get("/my-groups", response_model=List[PurchaseGroupResponse])
|
||
def get_my_groups(
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取我参与的认购群(仅已批准的)"""
|
||
if not current_user:
|
||
return []
|
||
|
||
member_groups = db.query(PurchaseMember).filter(
|
||
PurchaseMember.user_id == current_user.f99_90_id,
|
||
PurchaseMember.status == "approved"
|
||
).all()
|
||
|
||
group_ids = [m.group_id for m in member_groups]
|
||
if not group_ids:
|
||
return []
|
||
|
||
groups = db.query(PurchaseGroup).filter(
|
||
PurchaseGroup.id.in_(group_ids)
|
||
).all()
|
||
|
||
return groups
|
||
|
||
@router.get("/groups/{group_id}/pending-members", response_model=List[MemberResponse])
|
||
def get_pending_members(
|
||
group_id: str,
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取待审批成员列表"""
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
|
||
if group.creator_id != current_user.f99_90_id:
|
||
raise HTTPException(status_code=403, detail="只有群主可以查看")
|
||
|
||
members = db.query(PurchaseMember).filter(
|
||
PurchaseMember.group_id == group_id,
|
||
PurchaseMember.status == "pending"
|
||
).order_by(PurchaseMember.joined_at.asc()).all()
|
||
|
||
return members
|
||
|
||
@router.post("/groups/{group_id}/members/{member_id}/approve")
|
||
def approve_member(
|
||
group_id: str,
|
||
member_id: str,
|
||
action: str = Query(..., description="approve/reject"),
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""审批或拒绝成员"""
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
|
||
if group.creator_id != current_user.f99_90_id:
|
||
raise HTTPException(status_code=403, detail="只有群主可以审批")
|
||
|
||
member = db.query(PurchaseMember).filter(
|
||
PurchaseMember.id == member_id,
|
||
PurchaseMember.group_id == group_id
|
||
).first()
|
||
|
||
if not member:
|
||
raise HTTPException(status_code=404, detail="成员不存在")
|
||
|
||
if action == "approve":
|
||
member.status = "approved"
|
||
group.total_members += 1
|
||
group.total_pending -= 1
|
||
db.commit()
|
||
return {"message": "已批准加入"}
|
||
elif action == "reject":
|
||
member.status = "rejected"
|
||
group.total_pending -= 1
|
||
db.commit()
|
||
return {"message": "已拒绝加入"}
|
||
else:
|
||
raise HTTPException(status_code=400, detail="无效操作")
|
||
|
||
@router.post("/groups", response_model=PurchaseGroupResponse)
|
||
def create_group(
|
||
data: PurchaseGroupCreate,
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""创建认购群"""
|
||
if not current_user:
|
||
raise HTTPException(status_code=401, detail="请先登录")
|
||
|
||
# 普通用户最多创建3个认购群
|
||
if current_user.role not in ["admin", "superadmin"]:
|
||
existing_count = db.query(PurchaseGroup).filter(
|
||
PurchaseGroup.creator_id == current_user.f99_90_id
|
||
).count()
|
||
if existing_count >= 3:
|
||
raise HTTPException(status_code=400, detail="普通用户最多创建3个认购群")
|
||
|
||
group_code = generate_group_code(db)
|
||
|
||
# 处理日期
|
||
start_date = None
|
||
if data.start_date:
|
||
try:
|
||
start_date = datetime.fromisoformat(data.start_date.replace('Z', '+08:00'))
|
||
except:
|
||
start_date = datetime.now()
|
||
|
||
# 管理员直接创建通过审批
|
||
if current_user.role in ["admin", "superadmin"]:
|
||
initial_status = "active"
|
||
else:
|
||
# 普通用户创建需要审批
|
||
initial_status = "pending"
|
||
|
||
group = PurchaseGroup(
|
||
group_code=group_code,
|
||
name=data.name,
|
||
description=data.description,
|
||
creator_id=current_user.f99_90_id,
|
||
creator_name=current_user.f01_01_name,
|
||
status=initial_status,
|
||
total_members=data.total_members,
|
||
total_collections=data.total_collections,
|
||
cycle_months=data.cycle_months,
|
||
start_date=start_date
|
||
)
|
||
db.add(group)
|
||
db.commit()
|
||
|
||
# 创建者直接成为成员
|
||
member = PurchaseMember(
|
||
group_id=group.id,
|
||
user_id=current_user.f99_90_id,
|
||
user_name=current_user.f01_01_name,
|
||
user_avatar=current_user.avatar,
|
||
role="creator",
|
||
status="approved"
|
||
)
|
||
db.add(member)
|
||
group.total_members = 1
|
||
db.commit()
|
||
db.refresh(group)
|
||
|
||
return group
|
||
|
||
@router.get("/groups/{group_id}", response_model=PurchaseGroupResponse)
|
||
def get_group(group_id: str, db: Session = Depends(get_db)):
|
||
"""获取认购群详情"""
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
return group
|
||
|
||
@router.post("/groups/{group_id}/join")
|
||
def join_group(
|
||
group_id: str,
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""申请加入认购群"""
|
||
if not current_user:
|
||
raise HTTPException(status_code=401, detail="请先登录")
|
||
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
|
||
if group.status == "pending":
|
||
raise HTTPException(status_code=400, detail="该认购群正在等待审批,请耐心等待")
|
||
|
||
if group.status == "rejected":
|
||
raise HTTPException(status_code=400, detail="该认购群申请已被拒绝")
|
||
|
||
if group.status != "active":
|
||
raise HTTPException(status_code=400, detail="该认购群已结束")
|
||
|
||
existing = db.query(PurchaseMember).filter(
|
||
PurchaseMember.group_id == group_id,
|
||
PurchaseMember.user_id == current_user.f99_90_id
|
||
).first()
|
||
|
||
if existing:
|
||
if existing.status == "approved":
|
||
raise HTTPException(status_code=400, detail="您已加入该认购群")
|
||
else:
|
||
# pending/rejected/其他状态:重新激活为pending
|
||
existing.status = "pending"
|
||
existing.joined_at = datetime.now()
|
||
existing.user_name = current_user.f01_01_name
|
||
group.total_pending += 1
|
||
db.commit()
|
||
return {"message": "申请成功,等待审批"}
|
||
|
||
member = PurchaseMember(
|
||
group_id=group_id,
|
||
user_id=current_user.f99_90_id,
|
||
user_name=current_user.f01_01_name,
|
||
user_avatar=current_user.avatar,
|
||
role="member",
|
||
status="pending"
|
||
)
|
||
db.add(member)
|
||
group.total_pending += 1
|
||
db.commit()
|
||
|
||
return {"message": "申请成功,等待群主审批"}
|
||
|
||
@router.get("/groups/{group_id}/members", response_model=List[MemberResponse])
|
||
def get_group_members(
|
||
group_id: str,
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取认购群成员列表"""
|
||
members = db.query(PurchaseMember).filter(
|
||
PurchaseMember.group_id == group_id,
|
||
PurchaseMember.status == "approved"
|
||
).order_by(PurchaseMember.joined_at.asc()).all()
|
||
|
||
return [
|
||
{
|
||
"id": m.id,
|
||
"user_id": m.user_id,
|
||
"user_name": m.user_name,
|
||
"user_avatar": m.user_avatar,
|
||
"role": m.role,
|
||
"status": m.status,
|
||
"joined_at": m.joined_at,
|
||
"wechat_name": m.wechat_name,
|
||
"contact": m.contact,
|
||
"purchase_count": m.purchase_count or 0,
|
||
"paid_amount": float(m.paid_amount or 0),
|
||
"notes": m.notes
|
||
}
|
||
for m in members
|
||
]
|
||
|
||
@router.get("/groups/{group_id}/collections", response_model=List[PurchaseCollectionResponse])
|
||
def get_group_collections(group_id: str, db: Session = Depends(get_db)):
|
||
"""获取认购群藏品列表"""
|
||
collections = db.query(PurchaseCollection).filter(
|
||
PurchaseCollection.group_id == group_id
|
||
).order_by(PurchaseCollection.submitted_at.desc()).all()
|
||
|
||
return [
|
||
{
|
||
"id": c.id,
|
||
"group_id": c.group_id,
|
||
"user_id": c.user_id,
|
||
"user_name": c.user_name,
|
||
"collection_name": c.collection_name,
|
||
"collection_code": c.collection_code,
|
||
"number": c.number,
|
||
"grading": c.grading,
|
||
"boss_name": c.boss_name,
|
||
"price": float(c.price),
|
||
"source": c.source,
|
||
"paid": c.paid,
|
||
"status": c.status,
|
||
"submit_date": c.submit_date,
|
||
"submitted_at": c.submitted_at
|
||
}
|
||
for c in collections
|
||
]
|
||
|
||
@router.post("/groups/{group_id}/collections", response_model=PurchaseCollectionResponse)
|
||
def add_collection(
|
||
group_id: str,
|
||
data: PurchaseCollectionCreate,
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""提交认购藏品"""
|
||
if not current_user:
|
||
raise HTTPException(status_code=401, detail="请先登录")
|
||
|
||
# All fields now optional - frontend will send what it has
|
||
# No validation needed as all fields are Optional in schema
|
||
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
|
||
member = db.query(PurchaseMember).filter(
|
||
PurchaseMember.group_id == group_id,
|
||
PurchaseMember.user_id == current_user.f99_90_id,
|
||
PurchaseMember.status == "approved"
|
||
).first()
|
||
|
||
if not member:
|
||
raise HTTPException(status_code=400, detail="请先加入该认购群并通过审批")
|
||
|
||
max_code = db.query(PurchaseCollection).filter(
|
||
PurchaseCollection.group_id == group_id
|
||
).order_by(PurchaseCollection.collection_code.desc()).first()
|
||
|
||
if max_code and max_code.collection_code:
|
||
try:
|
||
next_num = int(max_code.collection_code) + 1
|
||
except:
|
||
next_num = 1
|
||
else:
|
||
next_num = 1
|
||
|
||
collection_code = f"{next_num:03d}"
|
||
|
||
collection = PurchaseCollection(
|
||
group_id=group_id,
|
||
user_id=current_user.f99_90_id,
|
||
user_name=current_user.f01_01_name,
|
||
collection_name=data.collection_name,
|
||
collection_code=collection_code,
|
||
number=data.number,
|
||
grading=data.grading,
|
||
boss_name=data.boss_name,
|
||
price=data.price,
|
||
source=data.source,
|
||
paid=data.paid,
|
||
status="pending"
|
||
)
|
||
db.add(collection)
|
||
|
||
group.total_collections += 1
|
||
from decimal import Decimal
|
||
group.total_amount += Decimal(str(data.price))
|
||
if group.total_collections > 0:
|
||
group.avg_price = group.total_amount / group.total_collections
|
||
|
||
db.commit()
|
||
db.refresh(collection)
|
||
|
||
return collection
|
||
|
||
@router.put("/groups/{group_id}/collections/{collection_id}", response_model=PurchaseCollectionResponse)
|
||
def update_collection(
|
||
group_id: str,
|
||
collection_id: str,
|
||
data: PurchaseCollectionUpdate,
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""编辑认购藏品 (仅群主可操作)"""
|
||
if not current_user:
|
||
raise HTTPException(status_code=401, detail="请先登录")
|
||
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
|
||
if group.creator_id != current_user.f99_90_id:
|
||
raise HTTPException(status_code=403, detail="只有群主可以编辑")
|
||
|
||
collection = db.query(PurchaseCollection).filter(
|
||
PurchaseCollection.id == collection_id,
|
||
PurchaseCollection.group_id == group_id
|
||
).first()
|
||
|
||
if not collection:
|
||
raise HTTPException(status_code=404, detail="藏品不存在")
|
||
|
||
old_price = float(collection.price)
|
||
|
||
# 更新字段
|
||
if data.collection_name is not None:
|
||
collection.collection_name = data.collection_name
|
||
if data.number is not None:
|
||
collection.number = data.number
|
||
if data.grading is not None:
|
||
collection.grading = data.grading
|
||
if data.boss_name is not None:
|
||
collection.boss_name = data.boss_name
|
||
if data.source is not None:
|
||
collection.source = data.source
|
||
if data.paid is not None:
|
||
collection.paid = data.paid
|
||
|
||
# 处理状态变化
|
||
new_status = data.status
|
||
if new_status and new_status != collection.status:
|
||
if new_status == "confirmed" and collection.status != "confirmed":
|
||
group.total_confirmed += 1
|
||
elif collection.status == "confirmed" and new_status != "confirmed":
|
||
group.total_confirmed -= 1
|
||
collection.status = new_status
|
||
|
||
# 处理价格变化
|
||
if data.price is not None and data.price != old_price:
|
||
from decimal import Decimal
|
||
group.total_amount = group.total_amount - Decimal(str(old_price)) + Decimal(str(data.price))
|
||
if group.total_collections > 0:
|
||
group.avg_price = group.total_amount / group.total_collections
|
||
|
||
db.commit()
|
||
db.refresh(collection)
|
||
|
||
return collection
|
||
|
||
@router.post("/groups/{group_id}/close")
|
||
def close_group(
|
||
group_id: str,
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""结束认购群"""
|
||
if not current_user:
|
||
raise HTTPException(status_code=401, detail="请先登录")
|
||
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
|
||
if group.creator_id != current_user.f99_90_id:
|
||
raise HTTPException(status_code=403, detail="只有群主可以结束认购群")
|
||
|
||
group.status = "closed"
|
||
db.commit()
|
||
|
||
return {"message": "认购群已结束"}
|
||
@router.delete("/groups/{group_id}")
|
||
def delete_group(
|
||
group_id: str,
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""删除认购群 (仅管理员可操作)"""
|
||
if not current_user:
|
||
raise HTTPException(status_code=401, detail="请先登录")
|
||
|
||
# 管理员权限检查
|
||
if current_user.role not in ["admin", "superadmin"]:
|
||
raise HTTPException(status_code=403, detail="只有管理员可以删除认购群")
|
||
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
|
||
# 删除相关成员和藏品
|
||
db.query(PurchaseMember).filter(PurchaseMember.group_id == group_id).delete()
|
||
db.query(PurchaseCollection).filter(PurchaseCollection.group_id == group_id).delete()
|
||
db.delete(group)
|
||
db.commit()
|
||
|
||
return {"message": "认购群已删除"}
|
||
|
||
class MemberUpdate(BaseModel):
|
||
user_name: Optional[str] = None
|
||
wechat_name: Optional[str] = None
|
||
contact: Optional[str] = None
|
||
purchase_count: Optional[int] = None
|
||
paid_amount: Optional[float] = None
|
||
notes: Optional[str] = None
|
||
|
||
class GroupUpdate(BaseModel):
|
||
name: Optional[str] = None
|
||
description: Optional[str] = None
|
||
cycle_months: Optional[int] = None
|
||
start_date: Optional[str] = None
|
||
|
||
# 更新成员信息
|
||
@router.put("/groups/{group_id}/members/{member_id}")
|
||
def update_member(
|
||
group_id: str,
|
||
member_id: str,
|
||
data: MemberUpdate,
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""更新成员信息 (成员自己或群主可编辑)"""
|
||
if not current_user:
|
||
raise HTTPException(status_code=401, detail="请先登录")
|
||
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
|
||
member = db.query(PurchaseMember).filter(
|
||
PurchaseMember.id == member_id,
|
||
PurchaseMember.group_id == group_id
|
||
).first()
|
||
|
||
if not member:
|
||
raise HTTPException(status_code=404, detail="成员不存在")
|
||
|
||
# 只有成员自己或群主可以修改
|
||
if member.user_id != current_user.f99_90_id and group.creator_id != current_user.f99_90_id:
|
||
raise HTTPException(status_code=403, detail="无权修改")
|
||
|
||
if data.user_name is not None:
|
||
member.user_name = data.user_name
|
||
if data.wechat_name is not None:
|
||
member.wechat_name = data.wechat_name
|
||
if data.contact is not None:
|
||
member.contact = data.contact
|
||
if data.purchase_count is not None:
|
||
member.purchase_count = data.purchase_count
|
||
if data.paid_amount is not None:
|
||
from decimal import Decimal
|
||
member.paid_amount = Decimal(str(data.paid_amount))
|
||
if data.notes is not None:
|
||
member.notes = data.notes
|
||
|
||
db.commit()
|
||
db.refresh(member)
|
||
|
||
return {"message": "更新成功", "member_id": member.id}
|
||
|
||
# 更新群信息
|
||
@router.put("/groups/{group_id}", response_model=PurchaseGroupResponse)
|
||
def update_group(
|
||
group_id: str,
|
||
data: GroupUpdate,
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""更新群信息 (仅群主可编辑)"""
|
||
if not current_user:
|
||
raise HTTPException(status_code=401, detail="请先登录")
|
||
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
|
||
if group.creator_id != current_user.f99_90_id:
|
||
raise HTTPException(status_code=403, detail="只有群主可以修改")
|
||
|
||
if data.name is not None:
|
||
group.name = data.name
|
||
if data.description is not None:
|
||
group.description = data.description
|
||
if data.cycle_months is not None:
|
||
group.cycle_months = data.cycle_months
|
||
if data.start_date is not None:
|
||
try:
|
||
group.start_date = datetime.fromisoformat(data.start_date.replace('Z', '+08:00'))
|
||
except:
|
||
pass
|
||
|
||
db.commit()
|
||
db.refresh(group)
|
||
|
||
return group
|
||
|
||
# ============ 管理员审批API ============
|
||
|
||
class GroupApprovalResponse(BaseModel):
|
||
id: str
|
||
group_code: str
|
||
name: str
|
||
description: Optional[str]
|
||
creator_id: str
|
||
creator_name: Optional[str]
|
||
status: str
|
||
total_members: int
|
||
total_collections: int
|
||
created_at: Optional[datetime]
|
||
|
||
@router.get("/pending-approval", response_model=List[GroupApprovalResponse])
|
||
def get_pending_approval_groups(
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取待审批的认购群列表(仅管理员可见)"""
|
||
if not current_user:
|
||
raise HTTPException(status_code=401, detail="请先登录")
|
||
|
||
if current_user.role not in ["admin", "superadmin"]:
|
||
raise HTTPException(status_code=403, detail="只有管理员可以查看待审批列表")
|
||
|
||
groups = db.query(PurchaseGroup).filter(
|
||
PurchaseGroup.status == "pending"
|
||
).order_by(PurchaseGroup.created_at.asc()).all()
|
||
|
||
return groups
|
||
|
||
@router.post("/groups/{group_id}/approve")
|
||
def approve_group(
|
||
group_id: str,
|
||
action: str = Query(..., description="approve/reject"),
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""管理员审批或拒绝认购群"""
|
||
if not current_user:
|
||
raise HTTPException(status_code=401, detail="请先登录")
|
||
|
||
if current_user.role not in ["admin", "superadmin"]:
|
||
raise HTTPException(status_code=403, detail="只有管理员可以审批认购群")
|
||
|
||
group = db.query(PurchaseGroup).filter(PurchaseGroup.id == group_id).first()
|
||
if not group:
|
||
raise HTTPException(status_code=404, detail="认购群不存在")
|
||
|
||
if group.status != "pending":
|
||
raise HTTPException(status_code=400, detail="该认购群不在待审批状态")
|
||
|
||
if action == "approve":
|
||
group.status = "active"
|
||
group.approved_by = current_user.f99_90_id
|
||
group.approved_at = datetime.now()
|
||
db.commit()
|
||
return {"message": "已批准该认购群", "status": "active"}
|
||
elif action == "reject":
|
||
group.status = "rejected"
|
||
group.approved_by = current_user.f99_90_id
|
||
group.approved_at = datetime.now()
|
||
db.commit()
|
||
return {"message": "已拒绝该认购群", "status": "rejected"}
|
||
else:
|
||
raise HTTPException(status_code=400, detail="无效操作")
|
||
|
||
@router.get("/my-pending-groups", response_model=List[PurchaseGroupResponse])
|
||
def get_my_pending_groups(
|
||
current_user = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取我创建的待审批认购群"""
|
||
if not current_user:
|
||
return []
|
||
|
||
groups = db.query(PurchaseGroup).filter(
|
||
PurchaseGroup.creator_id == current_user.f99_90_id,
|
||
PurchaseGroup.status == "pending"
|
||
).all()
|
||
|
||
return groups
|