diff --git a/src/allmende_payment_system/api/shop.py b/src/allmende_payment_system/api/shop.py
index c5a64dc..db05c3c 100644
--- a/src/allmende_payment_system/api/shop.py
+++ b/src/allmende_payment_system/api/shop.py
@@ -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},
+ )
diff --git a/src/allmende_payment_system/templates/index.html.jinja b/src/allmende_payment_system/templates/index.html.jinja
index f73dbc2..88b2cd6 100644
--- a/src/allmende_payment_system/templates/index.html.jinja
+++ b/src/allmende_payment_system/templates/index.html.jinja
@@ -44,21 +44,26 @@
{% if transactions and transactions|length > 0 %}
{% for transaction in transactions[:10] %}
-
-
{{ transaction.type|transaction_type_de }}
-
- {{ transaction.timestamp }}
-
-
-
-
- {{ '%+.2f' | format(transaction.total_amount | default(0)) }} €
-
- {% if transaction.quantity %}
-
{{ transaction.quantity }} €
- {% endif %}
-
-
+
+
{{ transaction.type|transaction_type_de }}
+
+ {{ transaction.timestamp | timestamp_de }}
+
+ {% if transaction.type == "order" %}
+
+ {% endif %}
+
+
+
+ {{ '%+.2f' | format(transaction.total_amount | default(0)) }} €
+
+ {% if transaction.quantity %}
+
{{ transaction.quantity }} €
+ {% endif %}
+
+
{% endfor %}
{% else %}
diff --git a/src/allmende_payment_system/templates/cart.html.jinja b/src/allmende_payment_system/templates/order.html.jinja
similarity index 80%
rename from src/allmende_payment_system/templates/cart.html.jinja
rename to src/allmende_payment_system/templates/order.html.jinja
index 4d78641..be2fe5f 100644
--- a/src/allmende_payment_system/templates/cart.html.jinja
+++ b/src/allmende_payment_system/templates/order.html.jinja
@@ -1,11 +1,11 @@
{% extends "base.html.jinja" %}
{% block content %}
-
Warenkorb
-
Überprüfe deine Artikel und fahre zur Kasse fort.
+
{% if is_cart %}Warenkorb{% else %}Einkauf #{{ order.id }}{% endif %}
+ {% if not is_cart %}
Einkauf abgeschickt: {{ order.transaction.timestamp | timestamp_de }}
{% endif %}
- {% set items = user.shopping_cart.items %}
+ {% set items = order.items %}
{% if items|length == 0 %}
@@ -34,15 +34,19 @@
{{ item.description or '' }}
+ {% if is_cart %}
+ {% else %}
+ {{ item.quantity | format_number }}
+ {% endif %}
|
{{ item.product.price | format_number }} € |
{{ item.total_amount | format_number }} € |
- Entfernen
+ {% if is_cart %}Entfernen{% endif %}
|
{% endfor %}
@@ -50,19 +54,21 @@
| Gesamtsumme |
- {{ user.shopping_cart.total_amount | format_number }} € |
+ {{ order.total_amount | format_number }} € |
|
+ {% if is_cart %}
+ {% endif %}
{% endif %}
{% endblock %}
diff --git a/src/allmende_payment_system/tools.py b/src/allmende_payment_system/tools.py
index dc80968..c38065a 100644
--- a/src/allmende_payment_system/tools.py
+++ b/src/allmende_payment_system/tools.py
@@ -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
diff --git a/test/test_shop.py b/test/test_shop.py
index 64697aa..8fae41b 100644
--- a/test/test_shop.py
+++ b/test/test_shop.py
@@ -1,5 +1,7 @@
from decimal import Decimal
+from unittest import mock
+import pytest
from fake_data import fake
from starlette.testclient import TestClient
@@ -29,14 +31,33 @@ def create_user_with_account(test_db, username: str, balance: float | None = Non
return user
-def test_add_item_to_cart(client: TestClient, test_db):
+def add_finalized_order_to_user(test_db, user, product) -> Order:
+ order = Order(user=user)
+ total_amount = product.price
+ order.items.append(
+ OrderItem(product=product, quantity=1, total_amount=total_amount)
+ )
+ order.transaction = Transaction(total_amount=total_amount, type="order")
+ order.transaction.account = user.accounts[0]
+ test_db.add(order)
+ test_db.flush()
+ return order
+
+
+@pytest.fixture
+def product(test_db):
area = Area(**fake.area())
test_db.add(area)
product = Product(**fake.product())
product.area = area
test_db.add(product)
test_db.flush()
- form_data = {"product_id": product.id, "quantity": 2, "area_id": area.id}
+ return product
+
+
+def test_add_item_to_cart(client: TestClient, test_db, product):
+
+ form_data = {"product_id": product.id, "quantity": 2, "area_id": product.area.id}
response = client.post(
"/shop/cart/add",
@@ -47,13 +68,7 @@ def test_add_item_to_cart(client: TestClient, test_db):
assert response.status_code == 302
-def test_finalize_order(client: TestClient, test_db):
- area = Area(**fake.area())
- test_db.add(area)
- product = Product(**fake.product())
- product.area = area
- test_db.add(product)
- test_db.flush()
+def test_finalize_order(client: TestClient, test_db, product):
user = create_user_with_account(test_db, "test", balance=100.0)
@@ -69,3 +84,24 @@ def test_finalize_order(client: TestClient, test_db):
assert len(user.orders) == 2 # shopping cart + finalized order
assert user.accounts[0].balance == Decimal(100.0) - (product.price * 2)
+
+
+def test_view_order(client: TestClient, test_db, product):
+ user = create_user_with_account(test_db, "test")
+
+ order = add_finalized_order_to_user(test_db, user, product)
+
+ response = client.get(f"/shop/order/{order.id}")
+ assert response.status_code == 200
+ assert f"Einkauf #{order.id}" in response.text
+ assert product.name in response.text
+
+
+def test_view_order_wrong_user(client: TestClient, test_db, product):
+ user = create_user_with_account(test_db, "test")
+
+ order = add_finalized_order_to_user(test_db, user, product)
+
+ with mock.patch.dict("os.environ", {"APS_username": "other_user"}):
+ response = client.get(f"/shop/order/{order.id}")
+ assert response.status_code == 403