fix: hamburger menu vertical stack, lock paid orders, order cancellation with balance refund, deduplicate admin drawer
This commit is contained in:
+92
-1
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import re
|
||||
import secrets
|
||||
import urllib.parse
|
||||
from datetime import datetime, timedelta, date
|
||||
from typing import Optional, Dict, List, Set
|
||||
from decimal import Decimal
|
||||
@@ -130,7 +131,14 @@ def seed_demo_users_if_needed(tenant: Tenant, db: Session):
|
||||
|
||||
|
||||
@app.get("/", response_class=HTMLResponse)
|
||||
def index(request: Request, event_id: Optional[int] = None, token: Optional[str] = None, db: Session = Depends(get_db)):
|
||||
def index(
|
||||
request: Request,
|
||||
event_id: Optional[int] = None,
|
||||
token: Optional[str] = None,
|
||||
success: Optional[str] = None,
|
||||
error: Optional[str] = None,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
tenant = resolve_tenant(request, db)
|
||||
if not tenant:
|
||||
return templates.TemplateResponse(request, "not_found_tenant.html", context={})
|
||||
@@ -207,6 +215,8 @@ def index(request: Request, event_id: Optional[int] = None, token: Optional[str]
|
||||
"existing_order": existing_order,
|
||||
"user_items": user_items,
|
||||
"order_count": order_count,
|
||||
"success": success,
|
||||
"error": error,
|
||||
"now": now
|
||||
})
|
||||
|
||||
@@ -456,6 +466,11 @@ async def place_order(
|
||||
).first()
|
||||
|
||||
if existing_order:
|
||||
if existing_order.is_paid:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail="Diese Bestellung wurde bereits als bezahlt verbucht und kann nicht mehr geändert werden. Bitte wende dich an deinen Organisator."
|
||||
)
|
||||
db.query(OrderItem).filter(OrderItem.order_id == existing_order.id).delete()
|
||||
existing_order.total_price = total_price
|
||||
existing_order.guest_display_name = guest_name_str
|
||||
@@ -484,6 +499,43 @@ async def place_order(
|
||||
return RedirectResponse(url=f"/order/{order_id}/success", status_code=status.HTTP_303_SEE_OTHER)
|
||||
|
||||
|
||||
@app.post("/order/cancel")
|
||||
def cancel_order(
|
||||
request: Request,
|
||||
event_id: int = Form(...),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
tenant = resolve_tenant(request, db)
|
||||
current_user = get_current_user(request, db)
|
||||
if not current_user:
|
||||
return RedirectResponse(url="/login", status_code=status.HTTP_303_SEE_OTHER)
|
||||
|
||||
event = db.query(Event).filter(Event.id == event_id, Event.tenant_id == tenant.id).first()
|
||||
if not event:
|
||||
raise HTTPException(status_code=404, detail="Event nicht gefunden")
|
||||
|
||||
if event.status != "open" or event.deadline < datetime.now():
|
||||
raise HTTPException(status_code=400, detail="Die Frist ist abgelaufen. Bestellungen können nicht mehr storniert werden.")
|
||||
|
||||
order = db.query(Order).filter(
|
||||
Order.tenant_id == tenant.id,
|
||||
Order.event_id == event.id,
|
||||
Order.user_id == current_user.id
|
||||
).first()
|
||||
|
||||
if not order:
|
||||
return RedirectResponse(url=f"/?event_id={event.id}", status_code=status.HTTP_303_SEE_OTHER)
|
||||
|
||||
if order.is_paid:
|
||||
raise HTTPException(status_code=400, detail="Bereits bezahlte Bestellungen können nur vom Organisator storniert werden.")
|
||||
|
||||
db.delete(order)
|
||||
db.commit()
|
||||
|
||||
success_msg = urllib.parse.quote("Deine Bestellung wurde erfolgreich storniert")
|
||||
return RedirectResponse(url=f"/?event_id={event.id}&success={success_msg}", status_code=status.HTTP_303_SEE_OTHER)
|
||||
|
||||
|
||||
@app.get("/order/{order_id}/success", response_class=HTMLResponse)
|
||||
def order_success(order_id: int, request: Request, db: Session = Depends(get_db)):
|
||||
tenant = resolve_tenant(request, db)
|
||||
@@ -1522,6 +1574,45 @@ def toggle_paid(order_id: int, request: Request, db: Session = Depends(get_db)):
|
||||
return RedirectResponse(url=f"/admin?event_id={ev_id}&tab=orders", status_code=status.HTTP_303_SEE_OTHER)
|
||||
|
||||
|
||||
@app.post("/admin/orders/{order_id}/delete")
|
||||
def admin_delete_order(
|
||||
order_id: int,
|
||||
request: Request,
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
tenant = resolve_tenant(request, db)
|
||||
actor = require_organizer_or_admin(request, db)
|
||||
|
||||
order = db.query(Order).filter(Order.id == order_id, Order.tenant_id == tenant.id).first()
|
||||
if not order:
|
||||
raise HTTPException(status_code=404, detail="Bestellung nicht gefunden")
|
||||
|
||||
ev_id = order.event_id
|
||||
|
||||
# Falls per Guthaben bezahlt, Betrag automatisch zurückerstatten!
|
||||
if order.is_paid and order.payment_method == "balance" and order.user:
|
||||
order.user.balance += order.total_price
|
||||
ev_title = order.event.title if order.event else "Brotzeit"
|
||||
tx = BalanceTransaction(
|
||||
tenant_id=tenant.id,
|
||||
user_id=order.user.id,
|
||||
order_id=order.id,
|
||||
amount=order.total_price,
|
||||
transaction_type="refund",
|
||||
description=f"Rückerstattung wegen Stornierung: {ev_title}",
|
||||
created_by_id=actor.id
|
||||
)
|
||||
db.add(tx)
|
||||
|
||||
db.delete(order)
|
||||
db.commit()
|
||||
|
||||
referer = request.headers.get("referer", "")
|
||||
if "/einkauf" in referer:
|
||||
return RedirectResponse(url=f"/einkauf?event_id={ev_id}&success=Bestellung erfolgreich storniert und ggf. erstattet", status_code=status.HTTP_303_SEE_OTHER)
|
||||
return RedirectResponse(url=f"/admin?event_id={ev_id}&tab=orders&success=Bestellung erfolgreich storniert und ggf. erstattet", status_code=status.HTTP_303_SEE_OTHER)
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health():
|
||||
return {"status": "ok", "app": "Schmankerl"}
|
||||
|
||||
Reference in New Issue
Block a user