View order

This commit is contained in:
2025-12-13 12:25:00 +01:00
parent fd544fcebc
commit 5d2dfe37c1
5 changed files with 101 additions and 34 deletions

View File

@@ -1,12 +1,12 @@
from decimal import Decimal
from fastapi import APIRouter, Request
from fastapi import APIRouter, HTTPException, Request
from sqlalchemy import select
from starlette import status
from starlette.responses import RedirectResponse
from allmende_payment_system.api.dependencies import SessionDep, UserDep
from allmende_payment_system.models import Area, OrderItem, Product
from allmende_payment_system.models import Area, Order, OrderItem, Product
from allmende_payment_system.tools import get_jinja_renderer
shop_router = APIRouter()
@@ -28,8 +28,8 @@ async def get_shop(request: Request, session: SessionDep):
async def get_cart(request: Request, session: SessionDep, user: UserDep):
return templates.TemplateResponse(
"cart.html.jinja",
context={"request": request, "user": user},
"order.html.jinja",
context={"request": request, "order": user.shopping_cart, "is_cart": True},
)
@@ -76,3 +76,22 @@ async def add_to_cart(request: Request, session: SessionDep, user: UserDep):
return RedirectResponse(
url=f"/shop/area/{form_data['area_id']}", status_code=status.HTTP_302_FOUND
)
@shop_router.get("/shop/order/{order_id}")
async def add_to_cart(
request: Request, session: SessionDep, user: UserDep, order_id: int
):
query = select(Order).where(Order.id == order_id)
order = session.scalars(query).one()
if user.id != order.user_id:
raise HTTPException(
status_code=403, detail=f"User not authorized to view this order."
)
return templates.TemplateResponse(
"order.html.jinja",
context={"request": request, "order": order, "is_cart": False},
)

View File

@@ -44,21 +44,26 @@
{% if transactions and transactions|length > 0 %}
{% for transaction in transactions[:10] %}
<div class="list-group-item d-flex justify-content-between align-items-start py-3">
<div class="flex-grow-1">
<div class="fw-semibold">{{ transaction.type|transaction_type_de }}</div>
<small class="text-muted">
{{ transaction.timestamp }}
</small>
</div>
<div class="text-end ms-3">
<span class="fs-5 fw-bold {% if transaction.total_amount < 0 %}text-danger{% else %}text-success{% endif %}">
{{ '%+.2f' | format(transaction.total_amount | default(0)) }} €
</span>
{% if transaction.quantity %}
<div class="small text-muted">{{ transaction.quantity }} €</div>
{% endif %}
</div>
</div>
<div class="flex-grow-1">
<div class="fw-semibold d-inline">{{ transaction.type|transaction_type_de }}</div>
<small class="text-muted d-inline ms-2">
{{ transaction.timestamp | timestamp_de }}
</small>
{% if transaction.type == "order" %}
<div class="mt-2">
<a href="/shop/order/{{ transaction.order_id }}" class="btn btn-sm btn-outline-primary">Einkauf ansehen</a>
</div>
{% endif %}
</div>
<div class="text-end ms-3">
<span class="fs-5 fw-bold {% if transaction.total_amount < 0 %}text-danger{% else %}text-success{% endif %}">
{{ '%+.2f' | format(transaction.total_amount | default(0)) }} €
</span>
{% if transaction.quantity %}
<div class="small text-muted">{{ transaction.quantity }} €</div>
{% endif %}
</div>
</div>
{% endfor %}
{% else %}
<div class="list-group-item text-center py-5 text-muted">

View File

@@ -1,11 +1,11 @@
{% extends "base.html.jinja" %}
{% block content %}
<div class="mb-4">
<h2 class="h4 mb-3">Warenkorb</h2>
<p class="text-muted">Überprüfe deine Artikel und fahre zur Kasse fort.</p>
<h2 class="h4 mb-3">{% if is_cart %}Warenkorb{% else %}Einkauf #{{ order.id }}{% endif %}</h2>
{% if not is_cart %}<p class="text-muted">Einkauf abgeschickt: {{ order.transaction.timestamp | timestamp_de }}</p>{% endif %}
</div>
{% set items = user.shopping_cart.items %}
{% set items = order.items %}
{% if items|length == 0 %}
<div class="alert alert-info">Dein Warenkorb ist leer. <a href="/shop" class="alert-link">Weiter einkaufen</a>.</div>
@@ -34,15 +34,19 @@
<div class="text-muted small">{{ item.description or '' }}</div>
</td>
<td class="text-center" style="width:180px;">
{% if is_cart %}
<form method="post" action="/cart/update/{{ item.id }}" class="d-flex align-items-center justify-content-center">
<input type="number" name="quantity" value="{{ qty }}" min="1" step="0.01" class="form-control form-control-sm me-2" style="width:80px;">
<button class="btn btn-sm btn-outline-secondary" type="submit">Aktualisieren</button>
</form>
{% else %}
{{ item.quantity | format_number }}
{% endif %}
</td>
<td class="text-end">{{ item.product.price | format_number }} €</td>
<td class="text-end">{{ item.total_amount | format_number }} €</td>
<td class="text-end">
<a href="/cart/remove/{{ item.id }}" class="btn btn-sm btn-outline-danger">Entfernen</a>
{% if is_cart %}<a href="/cart/remove/{{ item.id }}" class="btn btn-sm btn-outline-danger">Entfernen</a>{% endif %}
</td>
</tr>
{% endfor %}
@@ -50,19 +54,21 @@
<tfoot>
<tr>
<td colspan="3" class="text-end fw-semibold">Gesamtsumme</td>
<td class="text-end fw-bold">{{ user.shopping_cart.total_amount | format_number }} €</td>
<td class="text-end fw-bold">{{ order.total_amount | format_number }} €</td>
<td></td>
</tr>
</tfoot>
</table>
</div>
{% if is_cart %}
<div class="d-flex justify-content-between align-items-center mt-3">
<div>
<a href="/cart/clear" class="btn btn-outline-danger me-2">Warenkorb leeren</a>
<a href="/shop/finalize_order" class="btn btn-primary">Jetzt Buchen</a>
</div>
</div>
{% endif %}
{% endif %}
{% endblock %}

View File

@@ -15,7 +15,7 @@ UNITS_OF_MEASURE = {"piece": "Stück"}
def format_number(value: float):
try:
return f"{value:n}"
return f"{value:.2f}".replace(".", ",")
except TypeError:
return value
@@ -25,4 +25,5 @@ def get_jinja_renderer() -> Jinja2Templates:
renderer.env.filters["transaction_type_de"] = lambda x: TRANSACTION_TYPE_DE[x]
renderer.env.filters["units_of_measure_de"] = lambda x: UNITS_OF_MEASURE.get(x, x)
renderer.env.filters["format_number"] = format_number
renderer.env.filters["timestamp_de"] = lambda x: x.strftime("%d.%m.%Y %H:%M")
return renderer