From d4e7ff8e3ddb8d8afa1d4b59f51d29525588cb66 Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Wed, 22 Jul 2026 11:21:14 +0200 Subject: [PATCH] Ablauf-Warnungen + Packungen-Spalte + Farbcodierung - Backend: ProductOut.expired_count (Anzahl abgelaufener Chargen je Produkt). - Einlagern: Inline-Warnung pro Charge, wenn MHD in der Vergangenheit liegt. - Produkte-Liste: Badge "N abgelaufen"; neue Spalte "Packungen" (Bestand/Packungsgroesse, bei Stueck-Produkten = Bestand). - Produktdetail: abgelaufene Chargen rot, Warnfrist gelb (Warnfrist aus Settings), Warnbanner bei abgelaufenem Bestand. - Uebersicht: alle Ablaufzeilen gelb, abgelaufene rot; deutlicher Warnbanner. - units.js: daysUntil/isExpired/expiryRowClass/amountText. Co-Authored-By: Claude Opus 4.8 --- backend/app/crud.py | 14 +++++++++++++- backend/app/schemas.py | 1 + web/src/pages/CheckIn.jsx | 8 ++++++-- web/src/pages/Dashboard.jsx | 8 +++++++- web/src/pages/ProductForm.jsx | 35 +++++++++++++++++++++++++++-------- web/src/pages/Products.jsx | 17 +++++++++++++++-- web/src/styles.css | 2 ++ web/src/units.js | 25 +++++++++++++++++++++++++ 8 files changed, 96 insertions(+), 14 deletions(-) diff --git a/backend/app/crud.py b/backend/app/crud.py index 2197aec..d8ef056 100644 --- a/backend/app/crud.py +++ b/backend/app/crud.py @@ -2,10 +2,12 @@ from __future__ import annotations +from datetime import date + from fastapi import HTTPException, status from sqlalchemy.orm import Session -from .models import Product +from .models import Lot, Product from .schemas import ProductOut from .services.stock import current_stock @@ -13,6 +15,16 @@ from .services.stock import current_stock def product_to_out(db: Session, product: Product) -> ProductOut: out = ProductOut.model_validate(product) out.stock = current_stock(db, product.id) + out.expired_count = ( + db.query(Lot) + .filter( + Lot.product_id == product.id, + Lot.best_before.isnot(None), + Lot.best_before < date.today(), + Lot.quantity > 0, + ) + .count() + ) return out diff --git a/backend/app/schemas.py b/backend/app/schemas.py index 2182211..ac60ae8 100644 --- a/backend/app/schemas.py +++ b/backend/app/schemas.py @@ -110,6 +110,7 @@ class ProductOut(BaseModel): created_at: datetime # angereichert: stock: float = 0.0 + expired_count: int = 0 class LookupResult(BaseModel): diff --git a/web/src/pages/CheckIn.jsx b/web/src/pages/CheckIn.jsx index 7f43293..78f8d92 100644 --- a/web/src/pages/CheckIn.jsx +++ b/web/src/pages/CheckIn.jsx @@ -4,7 +4,7 @@ import { api } from "../api"; import { useAuth } from "../auth"; import Icon from "../components/Icon"; import { guessGroup, suggestionToProduct } from "../offUtils"; -import { fmt, unitOptions, unitShort } from "../units"; +import { fmt, isExpired, unitOptions, unitShort } from "../units"; const emptyLine = () => ({ quantity: "", best_before: "" }); @@ -251,7 +251,11 @@ export default function CheckIn() {