diff --git a/lib/feature/delivery/detail/presentation/steps/step_summary.dart b/lib/feature/delivery/detail/presentation/steps/step_summary.dart index cc218bb..cf60e12 100644 --- a/lib/feature/delivery/detail/presentation/steps/step_summary.dart +++ b/lib/feature/delivery/detail/presentation/steps/step_summary.dart @@ -56,6 +56,7 @@ class StepSummary extends StatelessWidget { _PaymentMethodPicker( delivery: delivery, overrideId: wfState.paymentMethodOverrideId, + credit: details.creditOf(delivery.id), ), const SizedBox(height: 16), const _SignHint(), @@ -213,6 +214,17 @@ class _DeliveredRow extends StatelessWidget { } } +/// Offener Betrag der Lieferung in Euro: Warenwert (Σ Stückpreis × gelieferte +/// Menge) − Anzahlung − Gutschrift, nie negativ. Einzige Quelle dieser Formel — +/// genutzt von der Zahlungs-Übersicht UND der Zahlungsmethoden-Auswahl. +double _openAmount(Delivery delivery, DeliveryCredit? credit) { + final creditEuros = (credit?.amountCents ?? 0) / 100.0; + final warenwert = + delivery.items.fold(0, (acc, item) => acc + item.lineTotal); + return (warenwert - delivery.prepaidAmount - creditEuros) + .clamp(0.0, double.infinity); +} + class _PaymentSummary extends StatelessWidget { const _PaymentSummary({required this.delivery, required this.credit}); @@ -222,15 +234,13 @@ class _PaymentSummary extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); - // Exakt aus Cent (nicht gerundet) — Gutschrift kann Cent-Beträge haben. - final creditEuros = (credit?.amountCents ?? 0) / 100.0; // Warenwert = Σ Stückpreis × ausgelieferte Menge (entfernte/teil-entfernte // Positionen fallen automatisch raus). final warenwert = delivery.items .fold(0, (acc, item) => acc + item.lineTotal); - // Offener Betrag = Warenwert − Anzahlung − Gutschrift, nie negativ. - final open = (warenwert - delivery.prepaidAmount - creditEuros) - .clamp(0.0, double.infinity); + // Offener Betrag über den gemeinsamen Helper (gleiche Formel wie die + // Zahlungsmethoden-Auswahl). + final open = _openAmount(delivery, credit); return Card( margin: EdgeInsets.zero, child: Padding( @@ -349,10 +359,12 @@ class _PaymentMethodPicker extends StatelessWidget { const _PaymentMethodPicker({ required this.delivery, required this.overrideId, + required this.credit, }); final Delivery delivery; final String? overrideId; + final DeliveryCredit? credit; @override Widget build(BuildContext context) { @@ -407,6 +419,11 @@ class _PaymentMethodPicker extends StatelessWidget { // abgeschlossener/abgebrochener/pausierter Lieferung zeigt das // Dropdown den gewählten Stand, ist aber gesperrt. final active = delivery.state == DeliveryState.active; + // Steht kein offener Betrag mehr aus (vollständig vorab bezahlt + // oder per Gutschrift ausgeglichen), ist keine Zahlungsweise zu + // wählen → Auswahl deaktivieren. + final hasOpenAmount = _openAmount(delivery, credit) > 0; + final editable = active && hasOpenAmount; return Card( margin: EdgeInsets.zero, child: Padding( @@ -428,7 +445,7 @@ class _PaymentMethodPicker extends StatelessWidget { ), ], // `null` deaktiviert das Dropdown (Flutter-Konvention). - onChanged: active + onChanged: editable ? (newId) { if (newId == null) return; context.read().add( @@ -447,27 +464,15 @@ class _PaymentMethodPicker extends StatelessWidget { ), if (!active) ...[ const SizedBox(height: 8), - Row( - children: [ - Icon(Icons.lock_outline, - size: 16, - color: Theme.of(context).colorScheme.onSurfaceVariant), - const SizedBox(width: 8), - Expanded( - child: Text( - 'Lieferung abgeschlossen — Zahlungsmethode nicht ' - 'mehr änderbar.', - style: Theme.of(context) - .textTheme - .bodySmall - ?.copyWith( - color: Theme.of(context) - .colorScheme - .onSurfaceVariant, - ), - ), - ), - ], + const _PickerHint( + text: 'Lieferung abgeschlossen — Zahlungsmethode nicht ' + 'mehr änderbar.', + ), + ] else if (!hasOpenAmount) ...[ + const SizedBox(height: 8), + const _PickerHint( + text: 'Kein offener Betrag — Auswahl der Zahlungsweise ' + 'nicht erforderlich.', ), ], ], @@ -479,6 +484,31 @@ class _PaymentMethodPicker extends StatelessWidget { } } +/// Dezenter Sperr-/Info-Hinweis unter dem Zahlungsmethoden-Dropdown +/// (Schloss-Icon + Text in gedämpfter Farbe). +class _PickerHint extends StatelessWidget { + const _PickerHint({required this.text}); + + final String text; + + @override + Widget build(BuildContext context) { + final muted = Theme.of(context).colorScheme.onSurfaceVariant; + return Row( + children: [ + Icon(Icons.lock_outline, size: 16, color: muted), + const SizedBox(width: 8), + Expanded( + child: Text( + text, + style: Theme.of(context).textTheme.bodySmall?.copyWith(color: muted), + ), + ), + ], + ); + } +} + class _SignHint extends StatelessWidget { const _SignHint();