Commit graph

12 commits

Author SHA1 Message Date
761ea35047 Warenwirtschaft: Bestandsrechnung auf der Rohstoff-Detailseite nachvollziehbar
Neuer Klappbereich „Bestandsrechnung nachvollziehen" zeigt alle gebuchten
Eingänge – auch aufgebrauchte mit Rest 0 – mit Produktionsverbrauch,
Ausschuss mit Chargenbezug und dem nach FEFO zugerechneten Ausschuss ohne
Chargenbezug; Summenzeile bis zum Gesamtbestand identisch zur Kopfzahl.
Alt-Ausschuss ohne Chargenbezug wird einzeln mit Grund/Notiz/Bearbeiter
gelistet. Anlass: Live-Fall Sonnenblumenöl (doppelte Korrektur vom 28.07.).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 10:34:04 +00:00
6bd867cbe7 Warenwirtschaft: AP-53 — Nacharbeit zur Prüfung 10.09.2026 (Toleranzregel zentral, Sockelrand, Chargenzeile, Ausschuss-Meldung, Auflösung/Obergrenze)
Prüfbericht pruefung-ap53-mengenpraezision-2026-09-10.md, alle Punkte umgesetzt:
- AP53-01: Toleranz nur noch in ProductionService (TOLERANCE_RATIO 0,05, TOLERANCE_FLOOR 0,005, COMPARE_EPSILON); das Produktions-JS rendert die Konstanten aus dem Service statt eigener Zahlen (Ampel hatte noch Sockel 0,05 g).
- AP53-02: withinTolerance() vergleicht mit Float-Ausgleich 1e-9 — 0,025 g auf 0,020 g Soll ist wieder zulässig, 0,026 g nicht; Sollwerte werden nicht gerundet.
- AP53-03: Chargen-Hauptzeile und Standortsumme im Rohstoff-Detail mit formatWawiQuantity(…, 0) (0,125 g statt 0 g).
- AP53-04: Ausschuss-Fehlermeldungen (Request ohne/mit Charge, Controller-Wiederholung) mit formatWawiQuantity().
- 4.1: Obergrenze decimal(12,3) bewusst akzeptiert (Live max. 49.000 g) und als InventoryService::QUANTITY_MAX validiert; Bereichsprüfung + Rollback-Hinweis in der Deploy-Checkliste.
- 4.2: normalizeWawiQuantity() (parsen + drei Stellen) in Bestell-/Wareneingangs-/Ausschuss-Requests, parseQuantity() rundet kanonisch für batch_key- und stock_entry_id-Zeilen; Untergrenze 0,001 g; ml-Eingaben, die umgerechnet 0,000 g ergeben, werden abgelehnt (Store/Update/Receive).
- 4.3: Einkaufs-JS trennt formatQuantity (3), formatPrice (2, wie vor AP-53) und formatDensity (4).
- 4.4: Hinweise präzisiert (Übersichten ganzzahlig, Rundungs-/Untergrenzregel), Leitfaden §26 mit Sockelrand-, Hauptzeilen- und Meldungs-Prüfschritten, Plan V7 und README aktualisiert, Prüfbericht Abschnitt 6 mit Nacharbeitsstand.

Tests: QuantityPrecisionTest +6 (AP53-01…04, 4.2 Rundung/Untergrenze/Obergrenze, ml→0 g). Suite 384 grün / 1.592 Assertions.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 07:25:11 +00:00
b8180a06a1 Warenwirtschaft: AP-53 — Gramm-Mengen mit drei Nachkommastellen (Produktion, Wareneingang, Ausschuss)
Kundennachtrag 09.09.2026: Ist-Mengen je Charge in der Produktion sollen auf das Milligramm eingegeben werden können (z. B. 0,125 g). Bisher rundeten Datenbank (decimal 12,2), Bestandslogik, Anzeige und Toleranzsockel auf zwei Stellen; „0,125" wurde still zu 0,13, „0.125" nach der Punkt-Regel zu 125 g.

- Migration 2026_09_09_100000: production_ingredients.quantity_used, stock_entries.ordered_quantity/received_quantity, stock_disposals.quantity → decimal(12,3); Casts decimal:3. Auf der Dev-DB (Live-Kopie) ausgeführt, 53/78/7 Zeilen unverändert.
- InventoryService::QUANTITY_DECIMALS = 3; roundWawiQuantity() ersetzt alle round(…, 2) in InventoryService, ProductionService, StockDisposalController/-Request, StockEntryRepository/-Controller, RawMaterialStockController.
- formatWawiQuantity($v, $min = 2): bis drei Stellen, mindestens zwei — Produktionsdetail, Einkauf Liste/Detail/Formular, Ausschuss-Liste, Chargen-Rest im Rohstoff-Detail.
- Eingaberegel (reFormatWawiNumber, JS parseGerman/parseNumber): zusätzlich „0.xxx" als Dezimalzahl; „1.500" bleibt 1500. Produktions-JS: fmt() bis drei Stellen, fmtInput() schreibt gespeicherte Zahlen deutsch ins Feld (1,125 statt 1.125 = 1125).
- Soll-Ist-Toleranz: Sockel 0,05 → 0,005 g; Ausschuss min 0,001.
- Doku: Hinweise (Neu/geändert), Leitfaden Version 3.1 mit Abschnitt 26, Plan V7 AP-53, README (Deploy-Checkliste, Suite 378).

Tests: QuantityPrecisionTest (6) — Parsing, Anzeige, Produktion 0,125 g exakt + Rest 9,875 g, Entwurf 1,125 wiederöffnen, Toleranz Kleinmengen, Ausschuss 0,005 g.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 15:54:29 +00:00
313c6277ce Warenwirtschaft: N-01/N-03/N-05 — Entwurfsmenge ohne Charge, Snapshot-Signatur je Produkt, Alt-Ausschuss in Chargenverfügbarkeit
- N-01: Ist-Menge ohne gewählte Charge bleibt im Entwurf erhalten (Filter in
  Request und Service, formBatchKey liefert '' für chargenlose Zeilen).
- N-03: outputSignature summiert Stückzahlen je Produkt — ein Chargensplit
  ersetzt den historischen Verpackungs-Snapshot nicht mehr.
- N-05: Ausschuss ohne Chargenbezug (Altbestand) wird für die Verfügbarkeit je
  Standort FEFO auf die Chargen angerechnet (applyUnboundDisposals, lesend);
  Chargen-Ausschussprüfung nutzt dieselbe Verfügbarkeit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 11:48:02 +00:00
abd202a02e Warenwirtschaft: AP-43 — Produktion zwischenspeichern (Entwurf) + „abschließen"
Der Speicher-Button heißt jetzt „Produktion abschließen"; daneben gibt es
„Zwischenspeichern (Entwurf)". Ein Entwurf sichert den Stand ohne Pflichtfeld-
und ohne Bestandsprüfung und bucht KEINEN Bestand (Roh-/Produkt-/Verpackung).
Erst „abschließen" prüft vollständig und bucht.

- Migration: productions.status (default 'completed'; Bestand ist bereits gebucht).
- Production-Model: STATUS_DRAFT/COMPLETED, isDraft(), scopeBooked().
- InventoryService: Entwürfe fallen aus allen Verbrauchs-/Bestandsjoins heraus
  (status != draft an den 4 productions-Joins).
- ProductionService store()/updateProduction() bekommen $draft: Entwurf
  überspringt Rezeptur-/Mengen-/Bestandsprüfung + Buchungen, sichert nur
  vollständige Chargen-Zeilen (filterCompleteLines) und die angegebenen Outputs.
  Ein abgeschlossene Produktion kann NICHT zurück in den Entwurf (sonst
  verwaisen die Buchungen) — Guard wirft ValidationException.
- StoreProductionRequest: save_mode=draft => nur Kopfdaten Pflicht, Chargen/
  Ergebnis optional; validatedPayload filtert unvollständige Zeilen/Outputs.
- Controller: Entwurf löst Chargen tolerant auf (nicht auflösbare Chargen werden
  übersprungen, Entwurf ist immer speicherbar) und leitet zur Bearbeitung zurück.
- Views: create/edit „abschließen" + „Zwischenspeichern"-Button (nur solange
  Entwurf); Entwurf-Badge in Liste + Bearbeiten-Kopf.

Tests: 5 neue (kein Produktbestand, kein Rohstoffverbrauch, Abschluss bucht,
Rück-Entwurf verboten, HTTP-Entwurf ohne Ergebnis ok / Abschluss erzwingt
Ergebnis). Migration auf Dev-/Live-DB. Suite 336 grün.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-28 09:59:42 +00:00
d34f0a77f4 Warenwirtschaft: Audit-Niedrigbefunde N-2/3/4/5/7/8/9/15
- N-2: Letzter Netto-Preis je Lieferant nur aus tatsächlichen
  Eingängen (status received).
- N-3: Verbrauchsfenster exakt (kein startOfDay-Off-by-one).
- N-4: Kritisch-Zählung vereinheitlicht — Controller liefert die
  Kachel-Zählweise (inkl. critical_ordered), tote View-Überschreibung
  entfernt; Sidenav-Badge bleibt bewusst ohne bestellte Kritische.
- N-5: Ausschuss-Liste zeigt das 500er-Limit an + "Alle anzeigen"
  (?all=1), analog OPT-3.
- N-7: parseQuantity parst Strings konsequent im deutschen Format —
  Server und UI-Ampel interpretieren "1.500" jetzt identisch.
- N-8: Produktions-Kopie übernimmt keine alten Chargen-Nummern mehr
  (Auto-Vorschlag Präfix+ttmmjj greift).
- N-9: recordProductionStock lädt Produkte withTrashed — Korrektur-
  Gegenbuchungen soft-gelöschter Output-Produkte werden nicht mehr
  übersprungen.
- N-15: Hinweise/Leitfaden-Markdown mit html_input=strip +
  allow_unsafe_links=false gerendert.

Bewusst offen (Kundenentscheid/Design): N-1 (Chargen-Gruppierung ohne
supplier_id), N-6 (reFormatNumber-Konvention app-weit), N-10 (manuelle
Bewegung darf ins Minus, Inventur-Korrekturen), N-13 (mfg_row_phase-
Fallback auf phasenlos).

Suite: 231 grün, 823 Assertions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 12:57:26 +00:00
84450385e3 Warenwirtschaft: OPT-6 Bestandswahrheit — Ausschuss in Chargen-Restmengen (Audit H-1, M-5)
- consumedByStockEntry(): chargen-bezogener Ausschuss zählt jetzt als
  Verbrauch — entsorgte Chargen verschwinden aus Rohstoff-Detail,
  Produktions-FEFO/Dropdown und AP-27-Batch-Check.
- Rohstoff-Detail: Kopfwert aus remainingByIngredient() (identisch zur
  Index-Seite, inkl. Ausschuss ohne Chargenbezug).
- Aggregationen iterieren über die Key-Vereinigung (received ∪ consumed
  ∪ disposed) — negative Bestände werden nicht mehr als 0 maskiert.
- Standort-Aggregation: Chargen-Ausschuss zählt am Standort der Charge
  (COALESCE), nicht am frei gewählten Formular-Standort.

Tests: neuer ChargeDisposalConsistencyTest (5). Suite: 219 grün, 795 Assertions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 12:42:46 +00:00
35b9076cbc Warenwirtschaft: AP-31 Löschen mit Soft-Delete + Abhängigkeitsprüfung
Anforderung 15.07.2026: Nahezu alle WaWi-Einträge sind jetzt löschbar
(Soft-Delete, deleted_at), mit Abhängigkeitsprüfung und Bestätigungs-
warnung vor jeder Löschung.

- Migration: deleted_at auf 14 WaWi-Tabellen (Stammdaten, ingredients,
  stock_entries, stock_disposals, productions); SoftDeletes-Trait in
  den Models (suppliers/packaging_items hatten es bereits).
- Neuer App\Services\DeletionGuard: zentrale Abhängigkeitsprüfung je
  Entität — referenzierte Einträge sind nicht löschbar, Fehlermeldung
  nennt die Verwendungen (behebt auch Audit M-4: kein 500er/stiller
  Cascade-Verlust mehr beim Löschen verwendeter Stammdaten).
- SettingCrudController::destroy() prüft Blocker; Supplier-,
  PackagingItem-, Ingredient-destroy ebenso (Ingredient: vollständige
  Prüfung inkl. Produktion/Ausschuss, Route GET→DELETE, Audit M-6).
- Wareneingänge: auch gebuchte Eingänge löschbar, sofern kein
  Produktions-Verbrauch/Ausschuss darauf gebucht ist.
- Ausschuss: löschbar (Menge steht dem Bestand wieder zur Verfügung).
- Produktionen: löschbar (admin >= 7); Produktbestand wird per
  Gegenbuchung zurückgeführt (reverseProductionStock, append-only,
  withTrashed), Rohstoffverbrauch zählt nicht mehr (Bestandsqueries
  schließen gelöschte Produktionen aus).
- lastNetPricePerSupplier: DB::query statt Model-Query (Global Scope
  auf Sub-Select-Alias).
- Debug-Log-Reste im PackagingItemController entfernt (Audit N-16).
- Views: Lösch-Buttons mit deutschen Bestätigungswarnungen (Ausschuss,
  Produktionen, gebuchte Wareneingänge, INCI als DELETE-Formular).

Tests: neuer InventoryDeletionTest (10 Tests), StorageSettingsTest an
neue Löschregel angepasst. Volle Suite: 214 grün, 783 Assertions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 12:31:11 +00:00
7a5b5e0f7b Warenwirtschaft: AP-27 Wareneingang gleiche Charge zusammenführen
- Chargen-Existenz-Check beim Buchen (JSON-Endpoint batch-check): Hinweis
  „Charge bereits im Haus" + Vorbelegung MHD/Qualität aus dem letzten Eingang
- Rohstoffbestand-Detail: Chargen je batch_number summiert
  (InventoryService::chargeGroupsForIngredient), Einkäufe als Unterzeilen
- Produktion: Charge-Dropdown je Charge mit Summen-Rest (batches im
  Recipe-Payload), Verbrauch wird per expandBatchLines FEFO auf die
  Einzel-Einkäufe der Charge verteilt; Service-API bleibt je stock_entry
- Jeder Einkauf bleibt eigener stock_entry (Preis/Datum/Audit)
- Hinweise-Doku + Plan V6.0 §6 fortgeschrieben

Tests: StockEntryChargeMergeTest (7 neu); Suite 193 grün, 698 Assertions

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 13:36:19 +00:00
e47d848d3d Warenwirtschaft: OPT-3 Index-Limits + OPT-4 show()-Refactoring
- Wareneingang-/Produktions-Uebersicht: Eingegangene auf 500 gedeckelt
  (offene Bestellungen immer vollstaendig), ?all=1 + Hinweis-Link;
  ungenutzte User-Eager-Loads entfernt
- RawMaterialStockController::show() entschlackt: Chargen-Restmengen (FEFO)
  und offene Bestellungen im InventoryService, letzter Netto-Preis je
  Lieferant als Window-Function-Query im StockEntryRepository

Tests: RawMaterialStockTest +2, volle Suite 186 gruen, 663 Assertions

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 12:23:20 +00:00
ea36067831 Warenwirtschaft: AP-20 Rohstoffbestand-Filter + Kein-Rohstoffbestand-Flag
- ingredients.exclude_from_stock (Checkbox im INCI-Formular, z. B. Allergene):
  erscheint nie im Rohstoffbestand und nicht im Kritisch-Badge
- Rohstoffbestand-Uebersicht: Umschalter "Alle" / "Nur aus Herstellerrezepturen"
  (?scope=recipe, nutzt scopeUsedInActiveRecipes aus AP-21)
- Fix: AP-21-Migrationen hatten identischen Timestamp (add_storage lief vor
  create_storage und scheiterte auf MySQL am FK) - umbenannt auf 120753,
  Teilreste bereinigt, Migrationen sauber ausgefuehrt
- Hinweise-Doku fortgeschrieben

Tests: RawMaterialStockTest +2 (volle Suite 172 gruen, 624 Assertions)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 11:42:55 +00:00
3ee2d756e9 Warenwirtschaft: AP-09 bis AP-13 (Produktbestand, Set-Produkte, Ausschuss, Konzepte)
- AP-09 Produktbestand inkl. Bewegungshistorie (product_stock_movements, ProductStockService)
- AP-10 Rohstoffbestand-Ansicht je Lager (RawMaterialStockController)
- AP-11 Bestandsschwellen / Out-of-Stock-Handling fuer Produkte und Shop
- AP-12 Ausgang/Ausschuss (stock_disposals, StockDisposalController, InventoryService)
- Set-Produkte (product_set_items) inkl. Aufloesung
- Produktentwicklung & Hinweise-Verwaltung (Notices)
- AP-13 Entwicklungskonzept Shop-Bestandsabzug im Plan dokumentiert
- Feature-Tests fuer neue Module + aktualisierter Entwicklungsplan

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 11:04:22 +00:00