243 lines
7.1 KiB
Python
243 lines
7.1 KiB
Python
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=500),
|
||
current_user: Optional = Depends(get_current_user),
|
||
db: Session = Depends(get_db)
|
||
):
|
||
"""获取成交行情列表"""
|
||
query = db.query(DealInfo).filter(DealInfo.status == status)
|
||
|
||
# 成交日期过滤
|
||
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": "删除成功"} |