from fastapi import APIRouter, Depends, Query, HTTPException from sqlalchemy.orm import Session from pydantic import BaseModel from typing import Optional from datetime import datetime, date from app.core.database import get_db from app.core.auth import get_current_user from app.models.deal_info import DealInfo router = APIRouter(prefix="/api/deal", tags=["成交行情"]) # ============ Schema ============ class DealInfoCreate(BaseModel): title: str content: Optional[str] = None deal_price: Optional[float] = None deal_date: Optional[str] = None # YYYY-MM-DD packaging: Optional[str] = None category: Optional[str] = None is_graded: Optional[bool] = False grading_company: Optional[str] = None grading_score: Optional[str] = None tail_number: Optional[str] = None size_type: Optional[str] = None version: Optional[str] = None platform: Optional[str] = None seller: Optional[str] = None buyer: Optional[str] = None class DealInfoUpdate(BaseModel): title: Optional[str] = None content: Optional[str] = None deal_price: Optional[float] = None deal_date: Optional[str] = None packaging: Optional[str] = None category: Optional[str] = None is_graded: Optional[bool] = None grading_company: Optional[str] = None grading_score: Optional[str] = None tail_number: Optional[str] = None size_type: Optional[str] = None version: Optional[str] = None platform: Optional[str] = None seller: Optional[str] = None buyer: Optional[str] = None status: Optional[str] = None class DealInfoResponse(BaseModel): id: str user_id: Optional[str] title: str content: Optional[str] deal_price: Optional[float] deal_date: Optional[date] deal_no: Optional[str] packaging: Optional[str] category: Optional[str] is_graded: Optional[bool] grading_company: Optional[str] grading_score: Optional[str] tail_number: Optional[str] size_type: Optional[str] version: Optional[str] platform: Optional[str] seller: Optional[str] buyer: Optional[str] status: str view_count: int contact_count: int created_at: Optional[datetime] updated_at: Optional[datetime] class Config: from_attributes = True # 生成行情编号 def generate_deal_no(db: Session): """生成行情编号,从A000001开始递增""" last = db.query(DealInfo).order_by(DealInfo.deal_no.desc()).first() if last and last.deal_no: # 例如 A000001 -> 2 -> A000002 num = int(last.deal_no[1:]) + 1 return f"A{num:06d}" return "A000001" # ============ API ============ @router.get("/list", response_model=list[DealInfoResponse]) def get_deal_list( status: str = Query("active"), deal_date: Optional[str] = Query(None), page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=1000), user_only: bool = Query(False), # 是否只查看自己的 current_user: Optional = Depends(get_current_user), db: Session = Depends(get_db) ): """获取成交行情列表""" query = db.query(DealInfo).filter(DealInfo.status == status) # 我的行情:只查看自己的(管理员也只看自己的) if user_only and current_user: query = query.filter(DealInfo.user_id == current_user.f99_90_id) # 成交日期过滤 if deal_date: query = query.filter(DealInfo.deal_date == deal_date) # 排序:优先成交日期倒序,同日按编号倒序 query = query.order_by(DealInfo.deal_date.desc().nullslast(), DealInfo.deal_no.desc().nullslast()) # 分页 offset = (page - 1) * page_size items = query.offset(offset).limit(page_size).all() return items @router.get("/stats") def get_deal_stats( db: Session = Depends(get_db) ): """获取成交行情统计""" total = db.query(DealInfo).filter(DealInfo.status == "active").count() # 按日期统计 from sqlalchemy import func date_stats = db.query( DealInfo.deal_date, func.count(DealInfo.id).label('count') ).filter( DealInfo.status == "active", DealInfo.deal_date.isnot(None) ).group_by(DealInfo.deal_date).order_by(DealInfo.deal_date.desc()).limit(10).all() return { "total": total, "by_date": [{"date": str(d.deal_date), "count": d.count} for d in date_stats] } @router.post("", response_model=DealInfoResponse) def create_deal( data: DealInfoCreate, current_user = Depends(get_current_user), db: Session = Depends(get_db) ): """创建成交行情""" if not current_user: raise HTTPException(status_code=401, detail="请先登录") # 生成行情编号 deal_no = generate_deal_no(db) # 解析日期 deal_date = None if data.deal_date: try: deal_date = datetime.strptime(data.deal_date, "%Y-%m-%d").date() except: pass deal = DealInfo( user_id=current_user.f99_90_id if current_user else None, title=data.title, content=data.content, deal_price=data.deal_price, deal_date=deal_date, deal_no=deal_no, packaging=data.packaging, category=data.category, is_graded=data.is_graded or False, grading_company=data.grading_company, grading_score=data.grading_score, tail_number=data.tail_number, size_type=data.size_type, version=data.version, platform=data.platform, seller=data.seller, buyer=data.buyer, status="active" ) db.add(deal) db.commit() db.refresh(deal) return deal @router.get("/{deal_id}", response_model=DealInfoResponse) def get_deal( deal_id: str, current_user = Depends(get_current_user), db: Session = Depends(get_db) ): """获取成交行情详情""" deal = db.query(DealInfo).filter(DealInfo.id == deal_id).first() if not deal: raise HTTPException(status_code=404, detail="成交行情不存在") # 增加浏览数 deal.view_count += 1 db.commit() return deal @router.put("/{deal_id}", response_model=DealInfoResponse) def update_deal( deal_id: str, data: DealInfoUpdate, current_user = Depends(get_current_user), db: Session = Depends(get_db) ): """更新成交行情""" if not current_user: raise HTTPException(status_code=401, detail="请先登录") deal = db.query(DealInfo).filter(DealInfo.id == deal_id).first() if not deal: raise HTTPException(status_code=404, detail="成交行情不存在") # 处理日期 if data.deal_date: try: data.deal_date = datetime.strptime(data.deal_date, "%Y-%m-%d").date() except: data.deal_date = None for key, value in data.model_dump(exclude_unset=True).items(): setattr(deal, key, value) db.commit() db.refresh(deal) return deal @router.delete("/{deal_id}") def delete_deal( deal_id: str, current_user = Depends(get_current_user), db: Session = Depends(get_db) ): """删除成交行情""" if not current_user: raise HTTPException(status_code=401, detail="请先登录") deal = db.query(DealInfo).filter(DealInfo.id == deal_id).first() if not deal: raise HTTPException(status_code=404, detail="成交行情不存在") deal.status = "deleted" db.commit() return {"message": "删除成功"}