From 7e345bd71bc1c977630de34fd88d6f6e8bba0c4a Mon Sep 17 00:00:00 2001 From: Dennis Nemec Date: Tue, 23 Jun 2026 16:04:58 +0200 Subject: [PATCH] fix(articles): Mengen-Stepper beim Set-Entfernen wieder aktivieren MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ein Set kann mehrfach bestellt sein (Oberartikel-Menge = Set-Anzahl), daher bleibt der Mengen-Stepper beim Entfernen über den Oberartikel erhalten. Die gewählte Set-Anzahl kaskadiert PROPORTIONAL auf die Komponenten (Stückzahl je Set × entfernte Sets, geklemmt auf Restmenge) — funktioniert für 1:1-Mengen wie für Komponenten mit Stückzahl je Set. Einzelne Komponenten bleiben weiterhin nicht direkt entfernbar. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../presentation/steps/step_articles.dart | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/lib/feature/delivery/detail/presentation/steps/step_articles.dart b/lib/feature/delivery/detail/presentation/steps/step_articles.dart index 1eb59e1..853c886 100644 --- a/lib/feature/delivery/detail/presentation/steps/step_articles.dart +++ b/lib/feature/delivery/detail/presentation/steps/step_articles.dart @@ -217,34 +217,51 @@ class _ArticleManagementRow extends StatelessWidget { )); } - /// Entfernt das GANZE Set (Oberartikel + alle Komponenten) auf einmal — - /// „entweder Parent komplett oder gar nix". Kein Mengen-Stepper - /// (`maxQuantity: null` ⇒ jede Zeile komplett). - Future _openSetRemoveDialog(BuildContext context) async { + /// Entfernt eine Anzahl Sets über den Oberartikel und kaskadiert auf seine + /// Komponenten. Der Mengen-Stepper bleibt erhalten — ein Set kann mehrfach + /// bestellt sein (Oberartikel-Menge = Set-Anzahl). Die Komponenten werden + /// **proportional** mitreduziert (Stückzahl je Set × entfernte Sets), + /// geklemmt auf die jeweilige Restmenge. Einzelne Komponenten bleiben + /// nicht direkt entfernbar — nur dieser Weg über den Oberartikel. + Future _openSetRemoveDialog( + BuildContext context, { + required int remaining, + }) async { final tourBloc = context.read(); final actorCarId = _actorCarId(context); final result = await showReasonPickerSheet( context: context, - title: 'Grund für das Entfernen (ganzes Set)', + title: 'Grund für das Entfernen', presets: ReasonCatalog.itemRemove, - confirmLabel: 'Set entfernen', - maxQuantity: null, + confirmLabel: 'Entfernen', + maxQuantity: remaining, ); if (result == null) return; - // Oberartikel + jede Komponente komplett entfernen (quantity null). + final n = result.quantity ?? remaining; + final parentRequired = item.requiredQuantity; + + // Oberartikel um n Sets reduzieren. tourBloc.add(RemoveItem( deliveryItemId: item.id, reason: result.reason, actorCarId: actorCarId, - quantity: null, + quantity: n, saveReasonAsNote: true, )); + // Komponenten proportional mitreduzieren. for (final c in components) { + final cRemaining = c.requiredQuantity - c.scanProgress.creditedQuantity; + if (cRemaining <= 0) continue; + final proportional = parentRequired > 0 + ? (c.requiredQuantity * n / parentRequired).round() + : cRemaining; + final removeQty = proportional.clamp(0, cRemaining); + if (removeQty <= 0) continue; tourBloc.add(RemoveItem( deliveryItemId: c.id, reason: result.reason, actorCarId: actorCarId, - quantity: null, + quantity: removeQty, // Grund nur einmal (am Oberartikel) als Notiz festhalten. saveReasonAsNote: false, )); @@ -435,7 +452,7 @@ class _ArticleManagementRow extends StatelessWidget { ), onPressed: canCredit ? () => hasComponents - ? _openSetRemoveDialog(context) + ? _openSetRemoveDialog(context, remaining: remaining) : _openCreditDialog(context, remaining: remaining) : null, icon: Icon(