feat(zahlung): eigener Step "Zahlung" vor der Uebersicht
- Neuer Workflow-Step "Zahlung" zeigt ausgelieferte Artikel mit Menge und Preis, Betragsaufstellung, Zahlungsstatus und einen grossen Button "Zahlung abwickeln" (fest unten) - Zahlungs-Modal: grosser offener Betrag, Methoden als Cards aus den Backend-Stammdaten, bei EC-Karte gross die Kundennummer; schliesst nur ueber Abbrechen, "Zahlung erhalten" oder "Lieferung abbrechen" (mit Grund) - Bestaetigung wird am Server protokolliert (RecordDeliveryPayment); bis dahin sind "Weiter" und die Uebersicht gesperrt, ausser es ist nichts offen (bereits bezahlt). Aendert sich der Betrag danach, wird die Zahlung als veraltet markiert und muss erneut abgewickelt werden - Uebersicht zeigt die abgewickelte Zahlung statt eigener Methodenauswahl; Unterschrift-Flow ohne doppelte Inkasso-Stufe; Abschluss sendet Methode und Inkasso-Flag der gueltigen Zahlung - DeliveryPaymentStatus als einzige Quelle fuer offenen Betrag (gleiche Formel wie Backend); Artikelliste/Betragskarte als geteilte Widgets; Begruendungs-Dialog geteilt mit Info-Step - API-Client aus aktueller Backend-Spec neu generiert - Tests fuer Zahlungsstatus und Modal Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@ -39,8 +39,5 @@ class DeliveryWorkflowBloc
|
||||
final next = [...state.pendingImageNotes]..removeAt(e.index);
|
||||
emit(state.copyWith(pendingImageNotes: next));
|
||||
});
|
||||
on<WorkflowOverridePaymentMethod>((e, emit) => emit(
|
||||
state.copyWith(paymentMethodOverrideId: e.paymentMethodId),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,10 +34,3 @@ class WorkflowRemovePendingImage extends DeliveryWorkflowEvent {
|
||||
const WorkflowRemovePendingImage(this.index);
|
||||
final int index;
|
||||
}
|
||||
|
||||
// ─── Payment-Auswahl ────────────────────────────────────────────────────
|
||||
|
||||
class WorkflowOverridePaymentMethod extends DeliveryWorkflowEvent {
|
||||
const WorkflowOverridePaymentMethod({required this.paymentMethodId});
|
||||
final String? paymentMethodId;
|
||||
}
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
/// Die 5 Steps der Auslieferungs-Detail-Page. Reihenfolge ≙ Index.
|
||||
/// Die 6 Steps der Auslieferungs-Detail-Page. Reihenfolge ≙ Index.
|
||||
enum WorkflowStep {
|
||||
info,
|
||||
notes,
|
||||
articles,
|
||||
services,
|
||||
payment,
|
||||
summary,
|
||||
}
|
||||
|
||||
@ -15,6 +16,7 @@ extension WorkflowStepX on WorkflowStep {
|
||||
WorkflowStep.notes => 'Notizen',
|
||||
WorkflowStep.articles => 'Artikel & Gutschriften',
|
||||
WorkflowStep.services => 'Checkliste',
|
||||
WorkflowStep.payment => 'Zahlung',
|
||||
WorkflowStep.summary => 'Übersicht',
|
||||
};
|
||||
|
||||
@ -24,6 +26,7 @@ extension WorkflowStepX on WorkflowStep {
|
||||
WorkflowStep.notes => 'Notizen',
|
||||
WorkflowStep.articles => 'Artikel',
|
||||
WorkflowStep.services => 'Checkliste',
|
||||
WorkflowStep.payment => 'Zahlung',
|
||||
WorkflowStep.summary => 'Übersicht',
|
||||
};
|
||||
}
|
||||
@ -38,8 +41,9 @@ class PendingImageNote {
|
||||
final DateTime pickedAt;
|
||||
}
|
||||
|
||||
/// State des Detail-Workflows. Ein State, ein Bloc — der Step-Wechsel,
|
||||
/// die Drafts und die Payment-Auswahl liegen alle hier. So sieht jede
|
||||
/// State des Detail-Workflows. Ein State, ein Bloc — der Step-Wechsel und
|
||||
/// die Drafts liegen hier. Die Zahlung ist KEIN lokaler Draft mehr: Sie wird
|
||||
/// im Step „Zahlung" am Server protokolliert und kommt über die Tour zurück. So sieht jede
|
||||
/// Step-Page denselben kohärenten Zustand und ein Step kann Daten aus
|
||||
/// einem anderen lesen (z. B. Summary liest Article-Drafts).
|
||||
class DeliveryWorkflowState {
|
||||
@ -47,7 +51,6 @@ class DeliveryWorkflowState {
|
||||
required this.deliveryId,
|
||||
required this.step,
|
||||
required this.pendingImageNotes,
|
||||
required this.paymentMethodOverrideId,
|
||||
});
|
||||
|
||||
factory DeliveryWorkflowState.initial(String deliveryId) =>
|
||||
@ -55,7 +58,6 @@ class DeliveryWorkflowState {
|
||||
deliveryId: deliveryId,
|
||||
step: WorkflowStep.info,
|
||||
pendingImageNotes: const [],
|
||||
paymentMethodOverrideId: null,
|
||||
);
|
||||
|
||||
final String deliveryId;
|
||||
@ -64,24 +66,14 @@ class DeliveryWorkflowState {
|
||||
/// Lokal gehaltene Bild-Notizen — solange kein Upload-Endpoint da ist.
|
||||
final List<PendingImageNote> pendingImageNotes;
|
||||
|
||||
/// Wenn der Fahrer im Summary die Zahlungsmethode überschreibt, landet
|
||||
/// die neue Id hier. `null` = Methode der Lieferung bleibt.
|
||||
final String? paymentMethodOverrideId;
|
||||
|
||||
DeliveryWorkflowState copyWith({
|
||||
WorkflowStep? step,
|
||||
List<PendingImageNote>? pendingImageNotes,
|
||||
Object? paymentMethodOverrideId = _sentinel,
|
||||
}) {
|
||||
return DeliveryWorkflowState(
|
||||
deliveryId: deliveryId,
|
||||
step: step ?? this.step,
|
||||
pendingImageNotes: pendingImageNotes ?? this.pendingImageNotes,
|
||||
paymentMethodOverrideId: identical(paymentMethodOverrideId, _sentinel)
|
||||
? this.paymentMethodOverrideId
|
||||
: paymentMethodOverrideId as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const Object _sentinel = Object();
|
||||
|
||||
Reference in New Issue
Block a user