Files
2026-02-24 18:30:51 +09:00

200 lines
5.3 KiB
Python

import uvicorn
from fastapi import FastAPI, Depends, HTTPException
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from typing import List
from datetime import datetime
import models, database
import dashboard
import logging
from read_weight import read_cart_weight
CART_ITEMS = []
EXPECTED_WEIGHT = 0.0
app = FastAPI()
models.Base.metadata.create_all(bind=database.engine)
# 대시보드 라우터 등록
app.include_router(dashboard.router)
app.mount("/static", StaticFiles(directory="static"), name="static")
def get_db():
db = database.SessionLocal()
try: yield db
finally: db.close()
# 무게 검증 로직
def is_movable(expected, real):
if expected <= 0: return True
diff_ratio = abs(real - expected) / expected
return diff_ratio <= 0.2
# 페이지 라우팅
@app.get("/dashboard")
async def dashboard_view(): return FileResponse("templates/dashboard.html")
@app.get("/inventory")
async def inventory_view(): return FileResponse("templates/inventory.html")
# 카트 무게 기준값 설정
@app.post("/cart/tare")
def tare_cart():
global EXPECTED_WEIGHT
EXPECTED_WEIGHT = read_cart_weight()
return {"expected_weight": EXPECTED_WEIGHT}
@app.get("/items", response_model=List[models.ItemSchema])
def read_all_items(db: Session = Depends(get_db)):
return db.query(models.Item).all()
# 상품 추가
@app.post("/cart/add/{item_id}")
def add_item(item_id: int, db: Session = Depends(get_db)):
global EXPECTED_WEIGHT, CART_ITEMS
item = db.query(models.Item).filter(models.Item.id == item_id).first()
if not item:
raise HTTPException(404, "Item not found")
CART_ITEMS.append({
"id": item.id,
"name": item.name,
"price": item.price,
"weight": item.weight
})
EXPECTED_WEIGHT += item.weight
real = read_cart_weight()
movable = is_movable(EXPECTED_WEIGHT, real)
return {
"action": "add",
"id": item.id,
"item": item.name,
"price": item.price,
"expected_weight": EXPECTED_WEIGHT,
"real_weight": real,
"diff": abs(real - EXPECTED_WEIGHT),
"movable": movable
}
# 상품 제거
@app.post("/cart/remove/{item_id}")
def remove_item(item_id: int):
global EXPECTED_WEIGHT, CART_ITEMS
for i, item in enumerate(CART_ITEMS):
if item["id"] == item_id:
removed = CART_ITEMS.pop(i)
EXPECTED_WEIGHT -= removed["weight"]
break
else:
raise HTTPException(404, "Item not in cart")
EXPECTED_WEIGHT = max(EXPECTED_WEIGHT, 0)
real = read_cart_weight()
movable = is_movable(EXPECTED_WEIGHT, real)
return {
"action": "remove",
"id": removed["id"],
"item": removed["name"],
"price": removed["price"],
"expected_weight": EXPECTED_WEIGHT,
"real_weight": real,
"movable": movable
}
# 장바구니 조회
@app.get("/cart")
def get_cart():
total_price = sum(item["price"] for item in CART_ITEMS)
return {
"items": CART_ITEMS,
"total_count": len(CART_ITEMS),
"total_price": total_price,
"expected_weight": EXPECTED_WEIGHT
}
# 무게 체크
@app.get("/cart/check_weight")
def check_cart():
real = read_cart_weight()
movable = is_movable(EXPECTED_WEIGHT, real)
return {
"expected_weight": EXPECTED_WEIGHT,
"real_weight": real,
"diff": abs(real - EXPECTED_WEIGHT),
"movable": movable
}
# 대시보드 상태 조회
@app.get("/cart/status")
def get_cart_status_for_dashboard():
global EXPECTED_WEIGHT, CART_ITEMS
real = read_cart_weight()
movable = is_movable(EXPECTED_WEIGHT, real)
system_status = "NORMAL" if movable else "WARNING_WEIGHT_MISMATCH"
return {
"real_weight": real,
"expected_weight": EXPECTED_WEIGHT,
"cart_items": CART_ITEMS,
"total_price": sum(item["price"] for item in CART_ITEMS),
"total_count": len(CART_ITEMS),
"system_status": system_status,
"movable": movable
}
# 결제
@app.post("/cart/pay")
def pay_cart(db: Session = Depends(get_db)):
global CART_ITEMS, EXPECTED_WEIGHT
if not CART_ITEMS:
raise HTTPException(status_code=400, detail="장바구니가 비어있습니다.")
total_price = sum(item["price"] for item in CART_ITEMS)
new_pay = models.Pay(
total_price=total_price,
created_at=datetime.now()
)
db.add(new_pay)
db.commit()
reset_cart()
return {"msg": "결제 완료", "amount": total_price}
# 결제 내역 조회
@app.get("/payments", response_model=List[models.PaySchema])
def get_payment_history(db: Session = Depends(get_db)):
return db.query(models.Pay).order_by(models.Pay.created_at.desc()).all()
# 카트 초기화
@app.post("/cart/reset")
def reset_cart():
global EXPECTED_WEIGHT, CART_ITEMS
EXPECTED_WEIGHT = 0.0
CART_ITEMS.clear()
return {"ok": True}
# 로그 필터
class EndpointFilter(logging.Filter):
def filter(self, record: logging.LogRecord) -> bool:
msg = record.getMessage()
return all(x not in msg for x in ["/bot/check", "/bot/report", "/cart/status"])
logging.getLogger("uvicorn.access").addFilter(EndpointFilter())
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)