up
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
"""股票集合 CRUD 路由"""
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
from database import get_connection, dict_from_row
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class CollectionCreate(BaseModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
user_id: str
|
||||
|
||||
|
||||
class CollectionUpdate(BaseModel):
|
||||
name: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
user_id: Optional[str] = None
|
||||
last_accessed_at: Optional[str] = None
|
||||
|
||||
|
||||
class StockAdd(BaseModel):
|
||||
stock_code: str
|
||||
stock_name: str
|
||||
added_price: Optional[float] = None
|
||||
|
||||
|
||||
@router.get("", summary="列表集合")
|
||||
async def list_collections(user_id: str = ""):
|
||||
conn = get_connection()
|
||||
try:
|
||||
rows = conn.execute(
|
||||
"SELECT * FROM stock_collections WHERE user_id = ? OR user_id = '' ORDER BY created_at DESC",
|
||||
(user_id,),
|
||||
).fetchall()
|
||||
collections = [dict_from_row(r) for r in rows]
|
||||
|
||||
# 更新空 user_id 的记录
|
||||
for c in collections:
|
||||
if not c["user_id"]:
|
||||
conn.execute("UPDATE stock_collections SET user_id = ? WHERE id = ?", (user_id, c["id"]))
|
||||
conn.commit()
|
||||
return collections
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.post("", summary="创建集合", status_code=201)
|
||||
async def create_collection(body: CollectionCreate):
|
||||
from datetime import datetime
|
||||
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
conn = get_connection()
|
||||
try:
|
||||
cur = conn.execute(
|
||||
"INSERT INTO stock_collections (name, description, user_id, last_accessed_at, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
(body.name, body.description, body.user_id, now, now, now),
|
||||
)
|
||||
conn.commit()
|
||||
row = conn.execute("SELECT * FROM stock_collections WHERE id = ?", (cur.lastrowid,)).fetchone()
|
||||
return dict_from_row(row)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.get("/{collection_id}", summary="获取集合详情")
|
||||
async def get_collection(collection_id: int):
|
||||
conn = get_connection()
|
||||
try:
|
||||
row = conn.execute("SELECT * FROM stock_collections WHERE id = ?", (collection_id,)).fetchone()
|
||||
if not row:
|
||||
raise HTTPException(status_code=404, detail="集合不存在")
|
||||
return dict_from_row(row)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.patch("/{collection_id}", summary="更新集合")
|
||||
async def update_collection(collection_id: int, body: CollectionUpdate):
|
||||
conn = get_connection()
|
||||
try:
|
||||
existing = conn.execute("SELECT * FROM stock_collections WHERE id = ?", (collection_id,)).fetchone()
|
||||
if not existing:
|
||||
raise HTTPException(status_code=404, detail="集合不存在")
|
||||
|
||||
updates = {}
|
||||
if body.name is not None:
|
||||
updates["name"] = body.name
|
||||
if body.description is not None:
|
||||
updates["description"] = body.description
|
||||
if body.user_id is not None:
|
||||
updates["user_id"] = body.user_id
|
||||
if body.last_accessed_at is not None:
|
||||
updates["last_accessed_at"] = body.last_accessed_at
|
||||
|
||||
if updates:
|
||||
from datetime import datetime
|
||||
updates["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
set_clause = ", ".join(f"{k} = ?" for k in updates)
|
||||
values = list(updates.values())
|
||||
values.append(collection_id)
|
||||
conn.execute(f"UPDATE stock_collections SET {set_clause} WHERE id = ?", values)
|
||||
conn.commit()
|
||||
|
||||
row = conn.execute("SELECT * FROM stock_collections WHERE id = ?", (collection_id,)).fetchone()
|
||||
return dict_from_row(row)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.delete("/{collection_id}", summary="删除集合")
|
||||
async def delete_collection(collection_id: int):
|
||||
conn = get_connection()
|
||||
try:
|
||||
existing = conn.execute("SELECT * FROM stock_collections WHERE id = ?", (collection_id,)).fetchone()
|
||||
if not existing:
|
||||
raise HTTPException(status_code=404, detail="集合不存在")
|
||||
conn.execute("DELETE FROM stock_collections WHERE id = ?", (collection_id,))
|
||||
conn.commit()
|
||||
return {"success": True}
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.get("/{collection_id}/stocks", summary="列表集合中的股票")
|
||||
async def list_stocks(collection_id: int):
|
||||
conn = get_connection()
|
||||
try:
|
||||
rows = conn.execute(
|
||||
"SELECT * FROM collection_stocks WHERE collection_id = ? ORDER BY added_at DESC",
|
||||
(collection_id,),
|
||||
).fetchall()
|
||||
return [dict_from_row(r) for r in rows]
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.post("/{collection_id}/stocks", summary="添加股票到集合", status_code=201)
|
||||
async def add_stock(collection_id: int, body: StockAdd):
|
||||
conn = get_connection()
|
||||
try:
|
||||
# 检查集合存在
|
||||
coll = conn.execute("SELECT id FROM stock_collections WHERE id = ?", (collection_id,)).fetchone()
|
||||
if not coll:
|
||||
raise HTTPException(status_code=404, detail="集合不存在")
|
||||
|
||||
try:
|
||||
cur = conn.execute(
|
||||
"INSERT INTO collection_stocks (collection_id, stock_code, stock_name, added_price) VALUES (?, ?, ?, ?)",
|
||||
(collection_id, body.stock_code, body.stock_name, body.added_price),
|
||||
)
|
||||
conn.commit()
|
||||
row = conn.execute("SELECT * FROM collection_stocks WHERE id = ?", (cur.lastrowid,)).fetchone()
|
||||
return dict_from_row(row)
|
||||
except Exception as e:
|
||||
if "UNIQUE constraint failed" in str(e):
|
||||
raise HTTPException(status_code=409, detail="该股票已在集合中")
|
||||
raise
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.get("/stock/{stock_code}", summary="在所有集合中查找股票记录")
|
||||
async def find_stock(stock_code: str):
|
||||
conn = get_connection()
|
||||
try:
|
||||
row = conn.execute(
|
||||
"SELECT * FROM collection_stocks WHERE stock_code = ? ORDER BY added_at DESC LIMIT 1",
|
||||
(stock_code,),
|
||||
).fetchone()
|
||||
if not row:
|
||||
return None
|
||||
return dict_from_row(row)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.delete("/{collection_id}/stocks/{stock_code}", summary="从集合移除股票")
|
||||
async def remove_stock(collection_id: int, stock_code: str):
|
||||
conn = get_connection()
|
||||
try:
|
||||
conn.execute(
|
||||
"DELETE FROM collection_stocks WHERE collection_id = ? AND stock_code = ?",
|
||||
(collection_id, stock_code),
|
||||
)
|
||||
conn.commit()
|
||||
return {"success": True}
|
||||
finally:
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user