jiachenlong/backend/app/routers/deal.py

503 lines
10 KiB
Python
Raw Permalink Normal View History

# deal - 成交行情路由
# Version: 1.2.85
# 更新:
from fastapi import APIRouter, Depends, Query, HTTPException
# 更新:
# Version: 1.2.x
# 更新:
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),
# 更新:
2026-04-15 17:48:30 +08:00
page_size: int = Query(20, ge=1, le=1000),
# 更新:
2026-04-15 17:48:30 +08:00
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)
# 更新:
# 更新:
2026-04-15 17:48:30 +08:00
# 我的行情:只查看自己的(管理员也只看自己的)
# 更新:
2026-04-15 17:48:30 +08:00
if user_only and current_user:
# 更新:
2026-04-15 17:48:30 +08:00
query = query.filter(DealInfo.user_id == current_user.f99_90_id)
# 更新:
2026-04-15 17:48:30 +08:00
# 更新:
# 成交日期过滤
# 更新:
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": "删除成功"}
# 更新: