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>
This commit is contained in:
parent
b8180a06a1
commit
6bd867cbe7
18 changed files with 424 additions and 40 deletions
|
|
@ -19,6 +19,9 @@ class InventoryService
|
|||
*/
|
||||
public const QUANTITY_DECIMALS = 3;
|
||||
|
||||
/** Obergrenze der decimal(12,3)-Spalten (Prüfung AP-53, Punkt 4.1) — wird validiert. */
|
||||
public const QUANTITY_MAX = 999999999.999;
|
||||
|
||||
public function __construct(
|
||||
protected ProductionService $productionService,
|
||||
) {}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,21 @@ use Illuminate\Validation\ValidationException;
|
|||
|
||||
class ProductionService
|
||||
{
|
||||
/** AP-39/AP-53: Soll-Ist-Toleranz ±5 % mit absolutem Sockel 0,005 g (Prüfung AP-53: eine Quelle für PHP und JS). */
|
||||
public const TOLERANCE_RATIO = 0.05;
|
||||
|
||||
public const TOLERANCE_FLOOR = 0.005;
|
||||
|
||||
/** Ausgleich für binäre Float-Darstellung beim Grenzvergleich (AP53-02: 0,025 auf 0,020 ist exakt zulässig). */
|
||||
public const COMPARE_EPSILON = 1e-9;
|
||||
|
||||
public static function withinTolerance(float $sum, float $required): bool
|
||||
{
|
||||
$tolerance = max($required * self::TOLERANCE_RATIO, self::TOLERANCE_FLOOR);
|
||||
|
||||
return abs($sum - $required) <= $tolerance + self::COMPARE_EPSILON;
|
||||
}
|
||||
|
||||
public function __construct(
|
||||
protected ProductStockService $productStockService,
|
||||
) {}
|
||||
|
|
@ -291,8 +306,7 @@ class ProductionService
|
|||
// passen — gebucht wird der reale Ist-Wert. Toleranz ±5 % (mit kleinem
|
||||
// absolutem Sockel gegen Float-/Kleinmengen-Effekte); größere
|
||||
// Abweichungen fängt der Zahlendreher-Schutz weiterhin ab.
|
||||
$tolerance = max((float) $req * 0.05, 0.005); // AP-53: Sockel 5 mg
|
||||
if (abs($sum - $req) > $tolerance) {
|
||||
if (! self::withinTolerance((float) $sum, (float) $req)) {
|
||||
throw ValidationException::withMessages([
|
||||
'ingredient_lines' => __('Die Ist-Menge je INCI darf höchstens 5 % vom Soll abweichen (INCI :id: Soll :req g, Ist :sum g).', [
|
||||
'id' => $iid,
|
||||
|
|
@ -817,13 +831,15 @@ class ProductionService
|
|||
// Audit N-7: Zahlen (interne Aufrufer) direkt; Strings konsequent im
|
||||
// deutschen Format parsen — vorher wich „1.500" (Server: 1,5) von der
|
||||
// UI-Ampel (1500) ab.
|
||||
// Prüfung AP-53 (4.2): kanonische Menge — immer auf drei Stellen gerundet,
|
||||
// egal ob die Zeile per batch_key oder stock_entry_id kommt.
|
||||
if (is_int($value) || is_float($value)) {
|
||||
return (float) $value;
|
||||
return roundWawiQuantity($value);
|
||||
}
|
||||
|
||||
$n = reFormatWawiNumber((string) $value);
|
||||
|
||||
return $n !== null && $n !== '' && is_numeric($n) ? (float) $n : 0.0;
|
||||
return $n !== null && $n !== '' && is_numeric($n) ? roundWawiQuantity($n) : 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue