Files
fridge-tracker/app/routes.py

229 lines
5.6 KiB
Python

from datetime import datetime
from flask import Blueprint, redirect, render_template, request, url_for
from sqlalchemy import distinct, select
from werkzeug.wrappers.response import Response
from app.db import SessionLocal
from app.models import Drink, Transaction
bp = Blueprint("main", __name__)
@bp.get("/")
def index() -> str:
return render_template("index.html")
@bp.get("/add")
def create_drink_get() -> str:
return render_template("add.html")
@bp.post("/add")
def create_drink_post() -> Response | tuple[str, int]:
name = request.form.get("name")
stock_raw = request.form.get("stock")
price_raw = request.form.get("price")
contact = request.form.get("phone_number")
if name is None or stock_raw is None or price_raw is None or contact is None:
return "Missing required fields", 400
name = name.strip()
contact = contact.strip()
try:
stock = int(stock_raw)
price = float(price_raw)
except ValueError:
return "Invalid numeric input", 400
if stock <= 0 or price <= 0:
return "Invalid stock or price", 400
session = SessionLocal()
drink = Drink(name=name, stock=stock, price=price, stocked_by=contact)
session.add(drink)
session.commit()
return redirect(url_for("main.list_drinks_get", id=drink.id))
@bp.get("/drink/<id>/manage")
def manage_drink_get(id: int) -> str | tuple[str, int]: # noqa: A002
session = SessionLocal()
drink = session.get(Drink, id)
if drink is None:
return "Drink not found", 404
return render_template("drink_manage.html", drink=drink)
@bp.post("/drink/<id>/restock")
def restock_drink_post(id: int) -> Response | tuple[str, int]: # noqa: A002
session = SessionLocal()
drink = session.get(Drink, id)
if drink is None:
return "Drink not found", 404
amount_raw = request.form.get("amount")
if amount_raw is None:
return "Missing fields", 400
try:
amount = int(amount_raw)
except ValueError:
return "Non numeric amount", 400
if amount <= 0:
return "Invalid amount", 400
drink.stock += amount
session.commit()
return redirect(url_for("main.manage_drink_get", id=id))
@bp.post("/drink/<id>/price")
def change_price_post(id: int) -> Response | tuple[str, int]: # noqa: A002
session = SessionLocal()
drink = session.get(Drink, id)
if drink is None:
return "Drink not found", 404
price_raw = request.form.get("price")
if price_raw is None:
return "Missing fields", 400
try:
price = float(price_raw)
except ValueError:
return "Non numeric amount", 400
if price <= 0:
return "Invalid price", 400
drink.price = price
session.commit()
return redirect(url_for("main.manage_drink_get", id=id))
@bp.post("/drink/<id>/delete")
def delete_drink_post(id: int) -> Response | tuple[str, int]: # noqa: A002
session = SessionLocal()
drink = session.get(Drink, id)
if drink is None:
return "Drink not found", 404
session.delete(drink)
session.commit()
return redirect(url_for("main.list_drinks_get"))
@bp.get("/drinks")
def list_drinks_get() -> str:
session = SessionLocal()
stmt = select(Drink)
result = session.execute(stmt)
drinks = [row[0] for row in result if row[0]]
return render_template("drink_list.html", drinks=drinks)
@bp.get("/drink/<id>")
def buy_drink_get(id: int) -> str | tuple[str, int]: # noqa: A002
session = SessionLocal()
drink = session.get(Drink, id)
if drink is None:
return "Drink not found", 404
# Find user names
stmt = select(distinct(Transaction.user_name)).order_by(Transaction.user_name)
result = session.execute(stmt).all()
names = [row[0] for row in result if row[0]]
return render_template("drink_buy.html", drink=drink, names=names)
@bp.post("/drink/<id>/buy")
def buy_drink_post(id: int) -> Response | tuple[str, int]: # noqa: A002
session = SessionLocal()
drink = session.get(Drink, id)
if drink is None:
return "Drink not found", 404
name = request.form.get("name")
qty_raw = request.form.get("quantity")
if name is None or qty_raw is None:
return "Missing fields", 400
name = name.strip()
try:
quantity = int(qty_raw)
except ValueError:
return "Invalid quantity", 400
if quantity <= 0:
return "Quantity must be positive", 400
if drink.stock < quantity:
return "Not enough stock", 400
# Update stock
drink.stock -= quantity
# Calculate cost
cost = drink.price * quantity
# Create transaction
transaction = Transaction(
drink=drink.id, user_name=name, quantity=quantity, cost=cost, timestamp=datetime.now().astimezone()
)
session.add(transaction)
session.commit()
return redirect(url_for("main.list_drinks_get", id=id))
@bp.get("/transactions")
def list_transactions_get() -> str:
session = SessionLocal()
stmt = select(Transaction).order_by(Transaction.timestamp)
result = session.execute(stmt).all()
txs: list[Transaction] = [row[0] for row in result if row[0]]
stmt = select(Drink)
result = session.execute(stmt).all()
drinks: dict[int, Drink] = {row[0].id: row[0] for row in result if row[0]}
patched = [
{
"drink_name": drinks[t.drink].name if t.drink in drinks else "<removed drink>",
"user_name": t.user_name,
"quantity": t.quantity,
"cost": t.cost,
"timestamp": t.timestamp,
}
for t in txs
]
return render_template("transactions.html", transactions=patched)