Verwaltbare Einheiten mit Umrechnung + Chargen bearbeiten + gezieltes Auslagern
Einheiten (neu):
- Tabelle units (name, kind=count|weight|volume, factor, is_builtin); eingebaut
Stueck/Gramm/Kilogramm/Milliliter/Liter, Admin kann eigene anlegen (z.B. Pfund=500g).
- Bestaende bleiben intern in kanonischer Basis (Stueck/Gramm/Milliliter);
Product.display_unit_id und Group.min_stock_unit_id als nullable FKs.
- Neuer Umrechnungs-Service (services/conversion.py) ersetzt die feste Einheitenlogik;
Ein-/Auslagern und Gruppen-Mindestbestand rechnen ueber den Faktor.
- Gruppen-Mindestbestand mit Einheit; Gruppenbestand summiert nur Produkte
passender Art. Neue Verwaltungsseite "Einheiten" (Admin).
- Schonende Migration beim Start: ADD COLUMN IF NOT EXISTS (Postgres), damit
bestehende Installationen ihre Daten behalten.
Chargen:
- PATCH /lots/{id} und DELETE /lots/{id}: Menge/MHD korrigieren, Charge loeschen
(wird als Korrektur-Bewegung protokolliert). Bearbeitung im Produktdetail.
Auslagern:
- Optionales lot_id: gezielt aus einer bestimmten Charge/MHD abbuchen statt FEFO;
Auswahl-Dropdown in der Auslagern-Seite.
Sonstiges: Roadmap aktualisiert, Tests fuer die Umrechnung.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from sqlalchemy import text
|
||||
|
||||
from .config import get_settings
|
||||
from .database import Base, SessionLocal, engine
|
||||
@@ -12,20 +13,44 @@ from .routers import (
|
||||
products,
|
||||
settings as settings_router,
|
||||
stock,
|
||||
units,
|
||||
users,
|
||||
views,
|
||||
)
|
||||
from .seed import ensure_first_admin
|
||||
from .seed import ensure_builtin_units, ensure_first_admin
|
||||
|
||||
settings = get_settings()
|
||||
|
||||
|
||||
def _ensure_schema() -> None:
|
||||
"""Schonende Migration: fehlende Spalten auf bestehenden Tabellen nachziehen.
|
||||
|
||||
create_all() legt nur fehlende Tabellen an, ändert aber keine bestehenden.
|
||||
Auf Postgres holen wir neue nullable-Spalten per ADD COLUMN IF NOT EXISTS nach,
|
||||
damit vorhandene Installationen ihre Daten behalten. Auf SQLite (Tests) sind
|
||||
die Spalten bereits durch create_all vorhanden.
|
||||
"""
|
||||
if engine.dialect.name != "postgresql":
|
||||
return
|
||||
stmts = [
|
||||
"ALTER TABLE products ADD COLUMN IF NOT EXISTS display_unit_id INTEGER "
|
||||
"REFERENCES units(id) ON DELETE SET NULL",
|
||||
"ALTER TABLE groups ADD COLUMN IF NOT EXISTS min_stock_unit_id INTEGER "
|
||||
"REFERENCES units(id) ON DELETE SET NULL",
|
||||
]
|
||||
with engine.begin() as conn:
|
||||
for stmt in stmts:
|
||||
conn.execute(text(stmt))
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# Tabellen anlegen (MVP: create_all statt Alembic-Migrationen).
|
||||
Base.metadata.create_all(bind=engine)
|
||||
_ensure_schema()
|
||||
db = SessionLocal()
|
||||
try:
|
||||
ensure_builtin_units(db)
|
||||
ensure_first_admin(db)
|
||||
finally:
|
||||
db.close()
|
||||
@@ -57,5 +82,6 @@ app.include_router(products.router)
|
||||
app.include_router(stock.router)
|
||||
app.include_router(locations.router)
|
||||
app.include_router(groups.router)
|
||||
app.include_router(units.router)
|
||||
app.include_router(views.router)
|
||||
app.include_router(settings_router.router)
|
||||
|
||||
Reference in New Issue
Block a user