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 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-22 11:21:14 +02:00
parent a3dbb971f7
commit d4e7ff8e3d
8 changed files with 96 additions and 14 deletions

View File

@@ -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

View File

@@ -110,6 +110,7 @@ class ProductOut(BaseModel):
created_at: datetime
# angereichert:
stock: float = 0.0
expired_count: int = 0
class LookupResult(BaseModel):