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//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//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//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/") 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//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 # Create transaction transaction = Transaction(drink=drink.id, user_name=name, quantity=quantity, 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 "", "user_name": t.user_name, "quantity": t.quantity, "timestamp": t.timestamp, } for t in txs ] return render_template("transactions.html", transactions=patched)