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>
This commit is contained in:
Kevin Adametz 2026-07-15 12:57:26 +00:00
parent 9ed47c02f3
commit d34f0a77f4
10 changed files with 35 additions and 8 deletions

View file

@ -37,7 +37,8 @@ class NoticeController extends Controller
return view('admin.inventory.notices.index', [
'title' => $title,
'subtitle' => $subtitle,
'content' => Str::markdown($markdown),
// Audit N-15: Roh-HTML im Markdown strippen (Defense-in-Depth).
'content' => Str::markdown($markdown, ['html_input' => 'strip', 'allow_unsafe_links' => false]),
]);
}
}

View file

@ -181,6 +181,11 @@ class ProductionController extends Controller
'outputs',
]);
// Audit N-8: Chargen-Nummern nicht in die Kopie übernehmen — das neue
// Produktionsdatum erzeugt sonst Duplikat-Chargen mit falschem Datum;
// leer ⇒ JS-Vorschlag (Präfix + ttmmjj) greift.
$production->outputs->each(fn ($output) => $output->setAttribute('batch_number', null));
$defaultLocationId = $production->location_id;
return view('admin.inventory.productions.create', [

View file

@ -59,7 +59,8 @@ class RawMaterialStockController extends Controller
return view('admin.inventory.raw-material-stock.index', [
'rows' => $rows,
'criticalCount' => $rows->where('status', 'critical')->count(),
// Audit N-4: gleiche Zählweise wie die Kacheln (kritisch inkl. bereits bestellt).
'criticalCount' => $rows->whereIn('status', ['critical', 'critical_ordered'])->count(),
'horizonOptions' => $this->horizonOptions(),
'defaultHorizon' => 90,
'scope' => $scope,

View file

@ -32,9 +32,13 @@ class StockDisposalController extends Controller
$query->where('disposal_type', $request->query('type'));
}
// Audit N-5: Limit sichtbar machen statt still abzuschneiden (analog OPT-3).
$limit = $request->boolean('all') ? null : 500;
return view('admin.inventory.stock-disposals.index', [
'values' => $query->limit(500)->get(),
'values' => $limit !== null ? $query->limit($limit)->get() : $query->get(),
'typeFilter' => $request->query('type'),
'listLimit' => $limit,
]);
}