176 lines
4.5 KiB
Python
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)
|