item-track/api/main.py
2026-04-23 20:41:32 +08:00

176 lines
4.5 KiB
Python

from decimal import Decimal
from config import settings
from fastapi import FastAPI, Depends
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, field_validator
from typing import List, Optional
from datetime import datetime, timedelta, date
from SQLAlchemy import ItemTrackManager, ItemTrack
from auth import get_current_user
app = FastAPI(title=settings.TITLE, version=settings.VERSION, debug=settings.DEBUG)
itemTrackManager = ItemTrackManager(settings.DATABASE_URL)
# CORS 配置
app.add_middleware(
CORSMiddleware,
allow_credentials=True,
allow_origin_regex=r"http[s]?://172\.30\.0\..*:5173|http[s]?://.*\.yuany3721\.site|http[s]?://yuany3721\.site",
allow_methods=["GET", "POST"],
allow_headers=["*"],
)
# 认证依赖 - 所有路由都需要认证
dependencies = [Depends(get_current_user)]
@app.get("/item_track/")
async def root():
return {"api": "item_track", "message": "tracking items backend", "auth": "Protected by Authentik OIDC"}
@app.get("/item_track/get_all_items", dependencies=dependencies)
async def get_all_items():
"""
获取所有未删除的商品
Returns:
list: 商品列表
"""
items = itemTrackManager.get_all_items()
res = [item.__dict__ for item in items]
for r in res:
r.pop("_sa_instance_state", None)
if isinstance(r["discontinued_at"], datetime):
r["till_now"] = (datetime.now() - r["discontinued_at"]).days
r["inuse"] = False
else:
r["till_now"] = (datetime.now() - r["start_at"]).days
r["inuse"] = True
return res
@app.get("/item_track/get_item/{item_id}", dependencies=dependencies)
async def get_item(item_id: int):
"""
获取指定ID的商品
Args:
item_id: 商品ID
Returns:
ItemTrack: 商品数据
"""
item = itemTrackManager.get_item_by_id(item_id)
if item:
res = item.__dict__
res.pop("_sa_instance_state", None)
if isinstance(res["discontinued_at"], datetime):
res["till_now"] = (datetime.now() - res["discontinued_at"]).days
res["inuse"] = False
else:
res["till_now"] = (datetime.now() - res["start_at"]).days
res["inuse"] = True
return res
return {}
class CreateItemRequest(BaseModel):
name: str
price: Decimal = Decimal("0")
start_at: date = datetime.now().date()
discontinued_at: Optional[date] = None
discontinued_price: Decimal = Decimal("0")
notes: str = ""
@field_validator('discontinued_at', mode='before')
def handle_empty_string(cls, v):
if v == "":
return None
return v
@app.post("/item_track/create_item", dependencies=dependencies)
async def create_item(item: CreateItemRequest):
"""
创建新商品
Args:
item: 商品数据
Returns:
BaseModel: 创建的商品
"""
return itemTrackManager.create_item(
name=item.name,
price=item.price,
start_at=item.start_at,
discontinued_at=item.discontinued_at,
discontinued_price=item.discontinued_price,
notes=item.notes,
)
class UpdateItemRequest(BaseModel):
id: int
name: str
price: Decimal = Decimal("0")
start_at: date = datetime.now().date()
discontinued_at: Optional[date] = None
discontinued_price: Decimal = Decimal("0")
notes: str = ""
@field_validator('discontinued_at', mode='before')
def handle_empty_string(cls, v):
if v == "":
return None
return v
@app.post("/item_track/update_item", dependencies=dependencies)
async def update_item(item: UpdateItemRequest):
"""
更新商品信息
Args:
item: 商品数据
Returns:
BaseModel: 更新的商品
"""
print(item)
return itemTrackManager.update_item(
id=item.id,
name=item.name,
price=item.price,
start_at=item.start_at,
discontinued_at=item.discontinued_at,
discontinued_price=item.discontinued_price,
notes=item.notes,
)
class DeleteItemRequest(BaseModel):
id: int
@app.post("/item_track/delete_item", dependencies=dependencies)
async def delete_item(request: DeleteItemRequest):
"""
软删除商品
Args:
id: 商品ID
Returns:
bool: 是否删除成功
"""
return itemTrackManager.delete_item(request.id)
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=7023, reload=settings.DEBUG)