Files
finance-talk/ft-app/app/routers/admin.py
T

152 lines
4.7 KiB
Python

from fastapi import APIRouter, Depends, Form, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from sqlalchemy.orm import Session
from app.database import get_db
from app.models import Product, Contract, DailyBar
from app.collector import sync_active_contracts, sync_one_contract
router = APIRouter(prefix="/admin", tags=["admin"])
EXCHANGES = ["CZCE", "DCE", "SHFE", "CFFEX", "INE"]
@router.get("/", response_class=HTMLResponse)
def admin_page(request: Request, db: Session = Depends(get_db)):
products = db.query(Product).order_by(Product.code).all()
product_data = []
for p in products:
contracts = (
db.query(Contract)
.filter(Contract.product_id == p.id)
.order_by(Contract.code)
.all()
)
contract_list = []
for c in contracts:
bar_count = (
db.query(DailyBar)
.filter(DailyBar.contract == c.code)
.count()
)
contract_list.append({
"id": c.id, "code": c.code, "name": c.name,
"is_active": c.is_active, "bar_count": bar_count,
})
product_data.append({
"id": p.id,
"code": p.code,
"name": p.name,
"exchange": p.exchange,
"contracts": contract_list,
})
total_contracts = sum(len(pd["contracts"]) for pd in product_data)
template = request.app.state.templates.get_template("admin.html")
return HTMLResponse(
template.render(
request=request,
active_nav="admin",
products=product_data,
total_contracts=total_contracts,
exchanges=EXCHANGES,
)
)
@router.post("/product")
def create_product(
request: Request,
code: str = Form(...),
name: str = Form(...),
exchange: str = Form(...),
db: Session = Depends(get_db),
):
existing = db.query(Product).filter(Product.code == code.upper()).first()
if not existing:
p = Product(code=code.upper(), name=name, exchange=exchange)
db.add(p)
db.commit()
return RedirectResponse("/admin/?tab=product", status_code=303)
@router.post("/contract")
def create_contract(
request: Request,
product_id: int = Form(...),
month: str = Form(...),
db: Session = Depends(get_db),
):
product = db.query(Product).filter(Product.id == product_id).first()
if not product:
return RedirectResponse("/admin/?tab=contract", status_code=303)
code = (product.code + month).upper()
name = month.upper()
existing = db.query(Contract).filter(Contract.code == code).first()
if not existing:
c = Contract(
product_id=product_id,
code=code,
name=name,
is_active=True,
)
db.add(c)
db.commit()
return RedirectResponse("/admin/?tab=contract", status_code=303)
@router.post("/contract/{contract_id}/toggle")
def toggle_contract(contract_id: int, db: Session = Depends(get_db)):
c = db.query(Contract).filter(Contract.id == contract_id).first()
if c:
c.is_active = not c.is_active
db.commit()
return RedirectResponse("/admin/?tab=contract", status_code=303)
@router.post("/contract/{contract_id}/delete")
def delete_contract(contract_id: int, db: Session = Depends(get_db)):
c = db.query(Contract).filter(Contract.id == contract_id).first()
if c:
db.delete(c)
db.commit()
return RedirectResponse("/admin/?tab=contract", status_code=303)
@router.post("/product/{product_id}/delete")
def delete_product(product_id: int, db: Session = Depends(get_db)):
p = db.query(Product).filter(Product.id == product_id).first()
if p:
db.delete(p)
db.commit()
return RedirectResponse("/admin/?tab=product", status_code=303)
@router.post("/sync")
def sync_all(request: Request):
results = sync_active_contracts()
total = sum(results.values())
print(f"[sync] Synced {total} bars across {len(results)} contracts: {results}")
return RedirectResponse(f"/admin/?tab=sync&synced={total}", status_code=303)
@router.post("/sync/{contract_code}")
def sync_single(contract_code: str):
count = sync_one_contract(contract_code.upper())
return RedirectResponse(f"/admin/?tab=sync&synced={count}", status_code=303)
@router.post("/sync/product/{product_id}")
def sync_product(product_id: int, request: Request, db: Session = Depends(get_db)):
contracts = db.query(Contract).filter(
Contract.product_id == product_id, Contract.is_active == True
).all()
total = 0
for c in contracts:
total += sync_one_contract(c.code)
return RedirectResponse(f"/admin/?tab=sync&synced={total}", status_code=303)