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:
@ -6,6 +6,7 @@ import 'package:hl_lieferservice/domain/entity/contact_source.dart';
|
|||||||
import 'package:hl_lieferservice/domain/entity/customer.dart';
|
import 'package:hl_lieferservice/domain/entity/customer.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_payment.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_item.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_item.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_note.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_note.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_service_value.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_service_value.dart';
|
||||||
@ -335,6 +336,11 @@ extension ApiTourDetailsMapper on api.TourDetails {
|
|||||||
for (final c in credits) c.deliveryId: c.toDomain(),
|
for (final c in credits) c.deliveryId: c.toDomain(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Zahlungen: höchstens eine pro Lieferung (jüngster Eintrag).
|
||||||
|
final paymentsMap = <String, DeliveryPayment>{
|
||||||
|
for (final p in payments) p.deliveryId: p.toDomain(),
|
||||||
|
};
|
||||||
|
|
||||||
// Service-Definitionen (aktiv, sortiert) + Pro-Lieferung-Werte indizieren.
|
// Service-Definitionen (aktiv, sortiert) + Pro-Lieferung-Werte indizieren.
|
||||||
final servicesList =
|
final servicesList =
|
||||||
services.map((s) => s.toDomain()).toList(growable: false);
|
services.map((s) => s.toDomain()).toList(growable: false);
|
||||||
@ -367,6 +373,7 @@ extension ApiTourDetailsMapper on api.TourDetails {
|
|||||||
warehouses: warehousesMap,
|
warehouses: warehousesMap,
|
||||||
notesByDeliveryId: notesGrouped,
|
notesByDeliveryId: notesGrouped,
|
||||||
creditsByDeliveryId: creditsMap,
|
creditsByDeliveryId: creditsMap,
|
||||||
|
paymentsByDeliveryId: paymentsMap,
|
||||||
services: servicesList,
|
services: servicesList,
|
||||||
serviceValuesByDeliveryId: serviceValues,
|
serviceValuesByDeliveryId: serviceValues,
|
||||||
contactSourcesByDeliveryId: sourcesGrouped,
|
contactSourcesByDeliveryId: sourcesGrouped,
|
||||||
@ -406,3 +413,14 @@ extension ApiDeliveryCreditMapper on api.DeliveryCredit {
|
|||||||
reason: reason,
|
reason: reason,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension ApiDeliveryPaymentMapper on api.DeliveryPayment {
|
||||||
|
DeliveryPayment toDomain() => DeliveryPayment(
|
||||||
|
id: id,
|
||||||
|
deliveryId: deliveryId,
|
||||||
|
paymentMethodId: paymentMethodId,
|
||||||
|
paymentMethodCode: paymentMethodCode,
|
||||||
|
amountCents: amountCents,
|
||||||
|
recordedAt: recordedAt.toLocal(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import 'package:hl_lieferservice/data/mapper/tour_mapper.dart';
|
|||||||
import 'package:hl_lieferservice/domain/entity/address.dart';
|
import 'package:hl_lieferservice/domain/entity/address.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_payment.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_note.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_note.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_service_value.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_service_value.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/scan_intent.dart';
|
import 'package:hl_lieferservice/domain/entity/scan_intent.dart';
|
||||||
@ -435,6 +436,36 @@ class TourRepositoryImpl implements TourRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<DeliveryPayment> recordDeliveryPayment({
|
||||||
|
required String deliveryId,
|
||||||
|
required String clientEventId,
|
||||||
|
required String paymentMethodId,
|
||||||
|
required int expectedAmountCents,
|
||||||
|
String? actorCarId,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
final request = api.RecordDeliveryPaymentRequest((b) {
|
||||||
|
b
|
||||||
|
..clientEventId = clientEventId
|
||||||
|
..paymentMethodId = paymentMethodId
|
||||||
|
..expectedAmountCents = expectedAmountCents;
|
||||||
|
if (actorCarId != null) b.authorCarId = actorCarId;
|
||||||
|
});
|
||||||
|
final response = await _api.getDeliveriesApi().recordPayment(
|
||||||
|
deliveryId: deliveryId,
|
||||||
|
recordDeliveryPaymentRequest: request,
|
||||||
|
);
|
||||||
|
final payment = response.data?.payment;
|
||||||
|
if (payment == null) {
|
||||||
|
throw TourRepositoryException('Zahlung protokollieren: leere Antwort');
|
||||||
|
}
|
||||||
|
return payment.toDomain();
|
||||||
|
} on DioException catch (e) {
|
||||||
|
throw TourRepositoryException(_describe(e, 'Zahlung protokollieren'), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<DeliveryServiceValue> setDeliveryService({
|
Future<DeliveryServiceValue> setDeliveryService({
|
||||||
required String deliveryId,
|
required String deliveryId,
|
||||||
|
|||||||
32
lib/domain/entity/delivery_payment.dart
Normal file
32
lib/domain/entity/delivery_payment.dart
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/// Protokollierte Zahlungsabwicklung („Abkassieren") einer Lieferung —
|
||||||
|
/// spiegelt das Backend-Aggregat `DeliveryPayment`.
|
||||||
|
///
|
||||||
|
/// Das Backend liefert pro Lieferung nur den jüngsten Eintrag. Der Betrag ist
|
||||||
|
/// der offene Betrag zum Zeitpunkt der Bestätigung. Ändert sich der offene
|
||||||
|
/// Betrag danach (z. B. neue Gutschrift), ist der Eintrag veraltet — siehe
|
||||||
|
/// `DeliveryPaymentStatus`.
|
||||||
|
class DeliveryPayment {
|
||||||
|
const DeliveryPayment({
|
||||||
|
required this.id,
|
||||||
|
required this.deliveryId,
|
||||||
|
required this.paymentMethodId,
|
||||||
|
required this.paymentMethodCode,
|
||||||
|
required this.amountCents,
|
||||||
|
required this.recordedAt,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String id;
|
||||||
|
final String deliveryId;
|
||||||
|
final String paymentMethodId;
|
||||||
|
|
||||||
|
/// Snapshot des Methoden-Codes (`cash`, `ec_card`, `invoice`, …).
|
||||||
|
final String paymentMethodCode;
|
||||||
|
|
||||||
|
/// Abgewickelter Betrag in Cent.
|
||||||
|
final int amountCents;
|
||||||
|
final DateTime recordedAt;
|
||||||
|
|
||||||
|
/// Bar/EC = vor Ort kassiert. „Auf Rechnung" bleibt offen.
|
||||||
|
bool get isCollectedOnSite =>
|
||||||
|
paymentMethodCode == 'cash' || paymentMethodCode == 'ec_card';
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ import 'contact_source.dart';
|
|||||||
import 'customer.dart';
|
import 'customer.dart';
|
||||||
import 'delivery.dart';
|
import 'delivery.dart';
|
||||||
import 'delivery_credit.dart';
|
import 'delivery_credit.dart';
|
||||||
|
import 'delivery_payment.dart';
|
||||||
import 'delivery_item.dart';
|
import 'delivery_item.dart';
|
||||||
import 'delivery_note.dart';
|
import 'delivery_note.dart';
|
||||||
import 'delivery_service_value.dart';
|
import 'delivery_service_value.dart';
|
||||||
@ -28,6 +29,7 @@ class TourDetails {
|
|||||||
required this.warehouses,
|
required this.warehouses,
|
||||||
required this.notesByDeliveryId,
|
required this.notesByDeliveryId,
|
||||||
required this.creditsByDeliveryId,
|
required this.creditsByDeliveryId,
|
||||||
|
required this.paymentsByDeliveryId,
|
||||||
required this.services,
|
required this.services,
|
||||||
required this.serviceValuesByDeliveryId,
|
required this.serviceValuesByDeliveryId,
|
||||||
required this.contactSourcesByDeliveryId,
|
required this.contactSourcesByDeliveryId,
|
||||||
@ -56,6 +58,10 @@ class TourDetails {
|
|||||||
/// der Eintrag, gibt es aktuell keine Gutschrift.
|
/// der Eintrag, gibt es aktuell keine Gutschrift.
|
||||||
final Map<String, DeliveryCredit> creditsByDeliveryId;
|
final Map<String, DeliveryCredit> creditsByDeliveryId;
|
||||||
|
|
||||||
|
/// Pro Lieferung die jüngste protokollierte Zahlungsabwicklung. Fehlt der
|
||||||
|
/// Eintrag, wurde für diese Lieferung noch keine Zahlung abgewickelt.
|
||||||
|
final Map<String, DeliveryPayment> paymentsByDeliveryId;
|
||||||
|
|
||||||
/// Aktive Service-Definitionen (Stammdaten), nach `sortOrder`. Daraus
|
/// Aktive Service-Definitionen (Stammdaten), nach `sortOrder`. Daraus
|
||||||
/// rendert Phase 4 die Auswahl.
|
/// rendert Phase 4 die Auswahl.
|
||||||
final List<Service> services;
|
final List<Service> services;
|
||||||
@ -200,6 +206,10 @@ class TourDetails {
|
|||||||
DeliveryCredit? creditOf(String deliveryId) =>
|
DeliveryCredit? creditOf(String deliveryId) =>
|
||||||
creditsByDeliveryId[deliveryId];
|
creditsByDeliveryId[deliveryId];
|
||||||
|
|
||||||
|
/// Jüngste protokollierte Zahlung dieser Lieferung, oder `null`.
|
||||||
|
DeliveryPayment? paymentOf(String deliveryId) =>
|
||||||
|
paymentsByDeliveryId[deliveryId];
|
||||||
|
|
||||||
/// Gesetzter Service-Wert dieser Lieferung für einen Service, oder `null`.
|
/// Gesetzter Service-Wert dieser Lieferung für einen Service, oder `null`.
|
||||||
DeliveryServiceValue? serviceValueOf(String deliveryId, String serviceId) =>
|
DeliveryServiceValue? serviceValueOf(String deliveryId, String serviceId) =>
|
||||||
serviceValuesByDeliveryId[deliveryId]?[serviceId];
|
serviceValuesByDeliveryId[deliveryId]?[serviceId];
|
||||||
@ -398,6 +408,7 @@ class TourDetails {
|
|||||||
List<Delivery>? deliveries,
|
List<Delivery>? deliveries,
|
||||||
Map<String, List<DeliveryNote>>? notesByDeliveryId,
|
Map<String, List<DeliveryNote>>? notesByDeliveryId,
|
||||||
Map<String, DeliveryCredit>? creditsByDeliveryId,
|
Map<String, DeliveryCredit>? creditsByDeliveryId,
|
||||||
|
Map<String, DeliveryPayment>? paymentsByDeliveryId,
|
||||||
Map<String, Map<String, DeliveryServiceValue>>? serviceValuesByDeliveryId,
|
Map<String, Map<String, DeliveryServiceValue>>? serviceValuesByDeliveryId,
|
||||||
}) {
|
}) {
|
||||||
return TourDetails(
|
return TourDetails(
|
||||||
@ -409,6 +420,7 @@ class TourDetails {
|
|||||||
warehouses: warehouses,
|
warehouses: warehouses,
|
||||||
notesByDeliveryId: notesByDeliveryId ?? this.notesByDeliveryId,
|
notesByDeliveryId: notesByDeliveryId ?? this.notesByDeliveryId,
|
||||||
creditsByDeliveryId: creditsByDeliveryId ?? this.creditsByDeliveryId,
|
creditsByDeliveryId: creditsByDeliveryId ?? this.creditsByDeliveryId,
|
||||||
|
paymentsByDeliveryId: paymentsByDeliveryId ?? this.paymentsByDeliveryId,
|
||||||
services: services,
|
services: services,
|
||||||
serviceValuesByDeliveryId:
|
serviceValuesByDeliveryId:
|
||||||
serviceValuesByDeliveryId ?? this.serviceValuesByDeliveryId,
|
serviceValuesByDeliveryId ?? this.serviceValuesByDeliveryId,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_payment.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_note.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_note.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_service_value.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_service_value.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/scan_intent.dart';
|
import 'package:hl_lieferservice/domain/entity/scan_intent.dart';
|
||||||
@ -166,6 +167,18 @@ abstract interface class TourRepository {
|
|||||||
String? actorCarId,
|
String? actorCarId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Protokolliert die Zahlungsabwicklung („Abkassieren") einer Lieferung.
|
||||||
|
/// Append-only + idempotent über [clientEventId]. [expectedAmountCents] ist
|
||||||
|
/// der Betrag, den der Fahrer gesehen hat; weicht der Server-Betrag ab,
|
||||||
|
/// lehnt das Backend ab. Rückgabe: der protokollierte Eintrag.
|
||||||
|
Future<DeliveryPayment> recordDeliveryPayment({
|
||||||
|
required String deliveryId,
|
||||||
|
required String clientEventId,
|
||||||
|
required String paymentMethodId,
|
||||||
|
required int expectedAmountCents,
|
||||||
|
String? actorCarId,
|
||||||
|
});
|
||||||
|
|
||||||
/// Setzt (Upsert) den Wert eines Service für eine Lieferung. Genau das zum
|
/// Setzt (Upsert) den Wert eines Service für eine Lieferung. Genau das zum
|
||||||
/// Service-Typ passende Feld angeben. Rückgabe: der gespeicherte Wert.
|
/// Service-Typ passende Feld angeben. Rückgabe: der gespeicherte Wert.
|
||||||
Future<DeliveryServiceValue> setDeliveryService({
|
Future<DeliveryServiceValue> setDeliveryService({
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import 'package:uuid/uuid.dart';
|
|||||||
import 'package:hl_lieferservice/data/cache/attachment_cache.dart';
|
import 'package:hl_lieferservice/data/cache/attachment_cache.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_payment.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_item.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_item.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_note.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_note.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_service_value.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery_service_value.dart';
|
||||||
@ -50,6 +51,7 @@ class TourBloc extends Bloc<TourEvent, TourState> {
|
|||||||
on<UploadDeliveryNoteImage>(_onUploadDeliveryNoteImage);
|
on<UploadDeliveryNoteImage>(_onUploadDeliveryNoteImage);
|
||||||
on<SetDeliveryCredit>(_onSetDeliveryCredit);
|
on<SetDeliveryCredit>(_onSetDeliveryCredit);
|
||||||
on<RemoveDeliveryCredit>(_onRemoveDeliveryCredit);
|
on<RemoveDeliveryCredit>(_onRemoveDeliveryCredit);
|
||||||
|
on<RecordDeliveryPayment>(_onRecordDeliveryPayment);
|
||||||
on<SetDeliveryServiceValue>(_onSetDeliveryServiceValue);
|
on<SetDeliveryServiceValue>(_onSetDeliveryServiceValue);
|
||||||
on<RemoveDeliveryServiceValue>(_onRemoveDeliveryServiceValue);
|
on<RemoveDeliveryServiceValue>(_onRemoveDeliveryServiceValue);
|
||||||
}
|
}
|
||||||
@ -613,6 +615,45 @@ class TourBloc extends Bloc<TourEvent, TourState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── Zahlungsabwicklung ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Protokolliert die Zahlung. Bewusst NICHT optimistisch: Der Server
|
||||||
|
/// berechnet den Betrag autoritativ und kann ablehnen (z. B. Betrag hat
|
||||||
|
/// sich zwischenzeitlich geändert). Erst die Server-Antwort gibt den
|
||||||
|
/// Zahlungs-Step frei.
|
||||||
|
Future<void> _onRecordDeliveryPayment(
|
||||||
|
RecordDeliveryPayment event,
|
||||||
|
Emitter<TourState> emit,
|
||||||
|
) async {
|
||||||
|
if (state is! TourLoaded) return;
|
||||||
|
|
||||||
|
opBloc.add(StartOperation(message: 'Zahlung wird protokolliert …'));
|
||||||
|
try {
|
||||||
|
final payment = await tourRepository.recordDeliveryPayment(
|
||||||
|
deliveryId: event.deliveryId,
|
||||||
|
clientEventId: _uuid.v4(),
|
||||||
|
paymentMethodId: event.paymentMethodId,
|
||||||
|
expectedAmountCents: event.expectedAmountCents,
|
||||||
|
actorCarId: event.actorCarId,
|
||||||
|
);
|
||||||
|
final latest = state;
|
||||||
|
if (latest is TourLoaded) {
|
||||||
|
final next = Map<String, DeliveryPayment>.from(
|
||||||
|
latest.details.paymentsByDeliveryId,
|
||||||
|
)..[event.deliveryId] = payment;
|
||||||
|
emit(latest.copyWith(
|
||||||
|
details: latest.details.copyWith(paymentsByDeliveryId: next),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
opBloc.add(FinishOperation(message: 'Zahlung protokolliert'));
|
||||||
|
} catch (e, st) {
|
||||||
|
debugPrint('TourBloc.RecordDeliveryPayment fehlgeschlagen: $e\n$st');
|
||||||
|
opBloc.add(FailOperation(
|
||||||
|
message: _messageOf(e, 'Zahlung konnte nicht protokolliert werden'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ─── Betrags-Gutschrift ──────────────────────────────────────────────
|
// ─── Betrags-Gutschrift ──────────────────────────────────────────────
|
||||||
|
|
||||||
/// Tauscht die Gutschrift einer Lieferung im Aggregat aus (`null` = entfernt).
|
/// Tauscht die Gutschrift einer Lieferung im Aggregat aus (`null` = entfernt).
|
||||||
|
|||||||
@ -274,6 +274,22 @@ class RemoveDeliveryCredit extends TourEvent {
|
|||||||
final String actorCarId;
|
final String actorCarId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Protokolliert die Zahlungsabwicklung („Abkassieren") einer Lieferung.
|
||||||
|
/// [expectedAmountCents] ist der offene Betrag, den der Fahrer bestätigt hat.
|
||||||
|
class RecordDeliveryPayment extends TourEvent {
|
||||||
|
const RecordDeliveryPayment({
|
||||||
|
required this.deliveryId,
|
||||||
|
required this.paymentMethodId,
|
||||||
|
required this.expectedAmountCents,
|
||||||
|
required this.actorCarId,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String deliveryId;
|
||||||
|
final String paymentMethodId;
|
||||||
|
final int expectedAmountCents;
|
||||||
|
final String? actorCarId;
|
||||||
|
}
|
||||||
|
|
||||||
/// Setzt/ändert den Wert eines Service für eine Lieferung (Checkbox/Zahl).
|
/// Setzt/ändert den Wert eines Service für eine Lieferung (Checkbox/Zahl).
|
||||||
class SetDeliveryServiceValue extends TourEvent {
|
class SetDeliveryServiceValue extends TourEvent {
|
||||||
const SetDeliveryServiceValue({
|
const SetDeliveryServiceValue({
|
||||||
|
|||||||
@ -39,8 +39,5 @@ class DeliveryWorkflowBloc
|
|||||||
final next = [...state.pendingImageNotes]..removeAt(e.index);
|
final next = [...state.pendingImageNotes]..removeAt(e.index);
|
||||||
emit(state.copyWith(pendingImageNotes: next));
|
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);
|
const WorkflowRemovePendingImage(this.index);
|
||||||
final int 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';
|
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 {
|
enum WorkflowStep {
|
||||||
info,
|
info,
|
||||||
notes,
|
notes,
|
||||||
articles,
|
articles,
|
||||||
services,
|
services,
|
||||||
|
payment,
|
||||||
summary,
|
summary,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ extension WorkflowStepX on WorkflowStep {
|
|||||||
WorkflowStep.notes => 'Notizen',
|
WorkflowStep.notes => 'Notizen',
|
||||||
WorkflowStep.articles => 'Artikel & Gutschriften',
|
WorkflowStep.articles => 'Artikel & Gutschriften',
|
||||||
WorkflowStep.services => 'Checkliste',
|
WorkflowStep.services => 'Checkliste',
|
||||||
|
WorkflowStep.payment => 'Zahlung',
|
||||||
WorkflowStep.summary => 'Übersicht',
|
WorkflowStep.summary => 'Übersicht',
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,6 +26,7 @@ extension WorkflowStepX on WorkflowStep {
|
|||||||
WorkflowStep.notes => 'Notizen',
|
WorkflowStep.notes => 'Notizen',
|
||||||
WorkflowStep.articles => 'Artikel',
|
WorkflowStep.articles => 'Artikel',
|
||||||
WorkflowStep.services => 'Checkliste',
|
WorkflowStep.services => 'Checkliste',
|
||||||
|
WorkflowStep.payment => 'Zahlung',
|
||||||
WorkflowStep.summary => 'Übersicht',
|
WorkflowStep.summary => 'Übersicht',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -38,8 +41,9 @@ class PendingImageNote {
|
|||||||
final DateTime pickedAt;
|
final DateTime pickedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// State des Detail-Workflows. Ein State, ein Bloc — der Step-Wechsel,
|
/// State des Detail-Workflows. Ein State, ein Bloc — der Step-Wechsel und
|
||||||
/// die Drafts und die Payment-Auswahl liegen alle hier. So sieht jede
|
/// 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
|
/// Step-Page denselben kohärenten Zustand und ein Step kann Daten aus
|
||||||
/// einem anderen lesen (z. B. Summary liest Article-Drafts).
|
/// einem anderen lesen (z. B. Summary liest Article-Drafts).
|
||||||
class DeliveryWorkflowState {
|
class DeliveryWorkflowState {
|
||||||
@ -47,7 +51,6 @@ class DeliveryWorkflowState {
|
|||||||
required this.deliveryId,
|
required this.deliveryId,
|
||||||
required this.step,
|
required this.step,
|
||||||
required this.pendingImageNotes,
|
required this.pendingImageNotes,
|
||||||
required this.paymentMethodOverrideId,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
factory DeliveryWorkflowState.initial(String deliveryId) =>
|
factory DeliveryWorkflowState.initial(String deliveryId) =>
|
||||||
@ -55,7 +58,6 @@ class DeliveryWorkflowState {
|
|||||||
deliveryId: deliveryId,
|
deliveryId: deliveryId,
|
||||||
step: WorkflowStep.info,
|
step: WorkflowStep.info,
|
||||||
pendingImageNotes: const [],
|
pendingImageNotes: const [],
|
||||||
paymentMethodOverrideId: null,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
final String deliveryId;
|
final String deliveryId;
|
||||||
@ -64,24 +66,14 @@ class DeliveryWorkflowState {
|
|||||||
/// Lokal gehaltene Bild-Notizen — solange kein Upload-Endpoint da ist.
|
/// Lokal gehaltene Bild-Notizen — solange kein Upload-Endpoint da ist.
|
||||||
final List<PendingImageNote> pendingImageNotes;
|
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({
|
DeliveryWorkflowState copyWith({
|
||||||
WorkflowStep? step,
|
WorkflowStep? step,
|
||||||
List<PendingImageNote>? pendingImageNotes,
|
List<PendingImageNote>? pendingImageNotes,
|
||||||
Object? paymentMethodOverrideId = _sentinel,
|
|
||||||
}) {
|
}) {
|
||||||
return DeliveryWorkflowState(
|
return DeliveryWorkflowState(
|
||||||
deliveryId: deliveryId,
|
deliveryId: deliveryId,
|
||||||
step: step ?? this.step,
|
step: step ?? this.step,
|
||||||
pendingImageNotes: pendingImageNotes ?? this.pendingImageNotes,
|
pendingImageNotes: pendingImageNotes ?? this.pendingImageNotes,
|
||||||
paymentMethodOverrideId: identical(paymentMethodOverrideId, _sentinel)
|
|
||||||
? this.paymentMethodOverrideId
|
|
||||||
: paymentMethodOverrideId as String?,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Object _sentinel = Object();
|
|
||||||
|
|||||||
@ -0,0 +1,80 @@
|
|||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_payment.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
|
||||||
|
|
||||||
|
/// Zahlungsstand einer Lieferung — einzige Quelle für offenen Betrag und
|
||||||
|
/// „ist die Zahlung erledigt?". Genutzt von Zahlungs-Step, Übersicht und
|
||||||
|
/// Abschluss, damit alle exakt dieselben Zahlen sehen.
|
||||||
|
///
|
||||||
|
/// Offener Betrag = Warenwert (Σ Stückpreis × ausgelieferte Menge) −
|
||||||
|
/// Anzahlung − Gutschrift, nie negativ. Identische Formel und Rundung wie
|
||||||
|
/// im Backend (`open_amount_cents`), das den Betrag beim Protokollieren
|
||||||
|
/// gegenprüft.
|
||||||
|
class DeliveryPaymentStatus {
|
||||||
|
const DeliveryPaymentStatus._({
|
||||||
|
required this.goodsValue,
|
||||||
|
required this.prepaidAmount,
|
||||||
|
required this.creditAmount,
|
||||||
|
required this.openCents,
|
||||||
|
required this.latestPayment,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory DeliveryPaymentStatus.of(Delivery delivery, TourDetails details) {
|
||||||
|
final goods = delivery.items.fold<double>(
|
||||||
|
0,
|
||||||
|
(acc, item) => acc + item.lineTotal,
|
||||||
|
);
|
||||||
|
final credit = (details.creditOf(delivery.id)?.amountCents ?? 0) / 100.0;
|
||||||
|
final open = goods - delivery.prepaidAmount - credit;
|
||||||
|
return DeliveryPaymentStatus._(
|
||||||
|
goodsValue: goods,
|
||||||
|
prepaidAmount: delivery.prepaidAmount,
|
||||||
|
creditAmount: credit,
|
||||||
|
openCents: open <= 0 ? 0 : (open * 100).round(),
|
||||||
|
latestPayment: details.paymentOf(delivery.id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Warenwert in Euro.
|
||||||
|
final double goodsValue;
|
||||||
|
|
||||||
|
/// Bei Bestellung bezahlt (Anzahlung) in Euro.
|
||||||
|
final double prepaidAmount;
|
||||||
|
|
||||||
|
/// Aktuelle Geld-Gutschrift in Euro (0 = keine).
|
||||||
|
final double creditAmount;
|
||||||
|
|
||||||
|
/// Offener Betrag in Cent.
|
||||||
|
final int openCents;
|
||||||
|
|
||||||
|
/// Jüngste protokollierte Zahlung, egal ob noch gültig.
|
||||||
|
final DeliveryPayment? latestPayment;
|
||||||
|
|
||||||
|
double get openAmount => openCents / 100.0;
|
||||||
|
|
||||||
|
bool get hasOpenAmount => openCents > 0;
|
||||||
|
|
||||||
|
/// Die jüngste Zahlung, sofern sie zum aktuellen offenen Betrag passt.
|
||||||
|
DeliveryPayment? get validPayment {
|
||||||
|
final p = latestPayment;
|
||||||
|
if (p == null || !hasOpenAmount || p.amountCents != openCents) return null;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Es wurde abgewickelt, aber der offene Betrag hat sich seitdem geändert.
|
||||||
|
bool get isStale =>
|
||||||
|
latestPayment != null && hasOpenAmount && validPayment == null;
|
||||||
|
|
||||||
|
/// Zahlungs-Step erledigt: nichts offen oder gültig abgewickelt.
|
||||||
|
bool get isSettled => !hasOpenAmount || validPayment != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final NumberFormat _euro = NumberFormat.currency(locale: 'de_DE', symbol: '€');
|
||||||
|
|
||||||
|
/// Betrag in Euro im deutschen Format, z. B. `1.234,50 €`.
|
||||||
|
String formatEuro(double amount) => _euro.format(amount);
|
||||||
|
|
||||||
|
/// Cent-Betrag im deutschen Format, z. B. `1.234,50 €`.
|
||||||
|
String formatEuroCents(int cents) => _euro.format(cents / 100.0);
|
||||||
@ -2,19 +2,19 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/payment_method.dart';
|
|
||||||
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
|
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
|
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
|
||||||
import 'package:hl_lieferservice/feature/payment_methods/bloc/payment_methods_cubit.dart';
|
|
||||||
import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
|
import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart';
|
import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/presentation/delivery_sign.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/delivery_sign.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_bloc.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_bloc.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_event.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_event.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_state.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_state.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/model/delivery_payment_status.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_articles.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_articles.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_info.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_info.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_notes.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_notes.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_payment.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_services.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_services.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_summary.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step_summary.dart';
|
||||||
|
|
||||||
@ -32,10 +32,10 @@ import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step
|
|||||||
// entgegennimmt und den Key zurückgibt, dann hier
|
// entgegennimmt und den Key zurückgibt, dann hier
|
||||||
// `tourBloc.add(AddDeliveryNote(imageAttachment: key))` aufrufen.
|
// `tourBloc.add(AddDeliveryNote(imageAttachment: key))` aufrufen.
|
||||||
//
|
//
|
||||||
// * ~~B4 Zahlungsmethode beim Abschluss ändern~~ — ERLEDIGT: Die im
|
// * ~~B4 Zahlungsmethode beim Abschluss ändern~~ — ERLEDIGT und abgelöst:
|
||||||
// Summary gewählte Methode (`paymentMethodOverrideId` im Workflow-State)
|
// Die Zahlung wird im eigenen Step „Zahlung" abgewickelt und am Server
|
||||||
// reist beim Abschluss am `/complete`-Endpoint mit und wird atomar auf
|
// protokolliert (`POST /deliveries/{id}/payment`). Beim Abschluss reist
|
||||||
// der Lieferung persistiert (Server prüft existiert + aktiv).
|
// die Methode der gültigen Zahlung mit.
|
||||||
//
|
//
|
||||||
// * **B5 Unterschrift**: Signature-Pad-Bilder (Kunde + Fahrer)
|
// * **B5 Unterschrift**: Signature-Pad-Bilder (Kunde + Fahrer)
|
||||||
// hochladen + auf der Lieferung speichern. Backend hat dafür weder
|
// hochladen + auf der Lieferung speichern. Backend hat dafür weder
|
||||||
@ -51,7 +51,7 @@ import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step
|
|||||||
// SnackBar-Stub.
|
// SnackBar-Stub.
|
||||||
// ─────────────────────────────────────────────────────────────────────────
|
// ─────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/// Multi-Step Detail-Page einer einzelnen Lieferung. Hülle für 5 Steps;
|
/// Multi-Step Detail-Page einer einzelnen Lieferung. Hülle für 6 Steps;
|
||||||
/// jeder Step bekommt die aktuelle `Delivery` + `TourDetails` als Props,
|
/// jeder Step bekommt die aktuelle `Delivery` + `TourDetails` als Props,
|
||||||
/// damit die Steps keine eigenen Bloc-Subscriptions auf die Tour brauchen.
|
/// damit die Steps keine eigenen Bloc-Subscriptions auf die Tour brauchen.
|
||||||
///
|
///
|
||||||
@ -95,7 +95,8 @@ class _DeliveryDetailScaffoldState extends State<_DeliveryDetailScaffold> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final s = context.read<TourBloc>().state;
|
final s = context.read<TourBloc>().state;
|
||||||
if (s is TourLoaded && _findDelivery(s.details)?.state == DeliveryState.active) {
|
if (s is TourLoaded &&
|
||||||
|
_findDelivery(s.details)?.state == DeliveryState.active) {
|
||||||
_armed = true;
|
_armed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,7 +154,7 @@ class _DeliveryDetailScaffoldState extends State<_DeliveryDetailScaffold> {
|
|||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
const _StepHeader(),
|
_StepHeader(delivery: delivery, details: details),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _StepBody(delivery: delivery, details: details),
|
child: _StepBody(delivery: delivery, details: details),
|
||||||
@ -171,8 +172,23 @@ class _DeliveryDetailScaffoldState extends State<_DeliveryDetailScaffold> {
|
|||||||
|
|
||||||
// ─── Step-Header (Pills) ────────────────────────────────────────────────
|
// ─── Step-Header (Pills) ────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Steps hinter „Zahlung" sind gesperrt, solange bei einer aktiven
|
||||||
|
/// Lieferung ein offener Betrag noch nicht gültig abgewickelt ist.
|
||||||
|
bool _lockedByPayment(
|
||||||
|
WorkflowStep step,
|
||||||
|
Delivery delivery,
|
||||||
|
TourDetails details,
|
||||||
|
) {
|
||||||
|
if (step.index <= WorkflowStep.payment.index) return false;
|
||||||
|
if (delivery.state != DeliveryState.active) return false;
|
||||||
|
return !DeliveryPaymentStatus.of(delivery, details).isSettled;
|
||||||
|
}
|
||||||
|
|
||||||
class _StepHeader extends StatelessWidget {
|
class _StepHeader extends StatelessWidget {
|
||||||
const _StepHeader();
|
const _StepHeader({required this.delivery, required this.details});
|
||||||
|
|
||||||
|
final Delivery delivery;
|
||||||
|
final TourDetails details;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -189,9 +205,16 @@ class _StepHeader extends StatelessWidget {
|
|||||||
step: WorkflowStep.values[i],
|
step: WorkflowStep.values[i],
|
||||||
isActive: state.step.index == i,
|
isActive: state.step.index == i,
|
||||||
isPassed: state.step.index > i,
|
isPassed: state.step.index > i,
|
||||||
onTap: () => context
|
enabled:
|
||||||
.read<DeliveryWorkflowBloc>()
|
!_lockedByPayment(
|
||||||
.add(WorkflowGoToStep(WorkflowStep.values[i])),
|
WorkflowStep.values[i],
|
||||||
|
delivery,
|
||||||
|
details,
|
||||||
|
),
|
||||||
|
onTap:
|
||||||
|
() => context.read<DeliveryWorkflowBloc>().add(
|
||||||
|
WorkflowGoToStep(WorkflowStep.values[i]),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (i < WorkflowStep.values.length - 1)
|
if (i < WorkflowStep.values.length - 1)
|
||||||
@ -211,6 +234,7 @@ class _StepPill extends StatelessWidget {
|
|||||||
required this.step,
|
required this.step,
|
||||||
required this.isActive,
|
required this.isActive,
|
||||||
required this.isPassed,
|
required this.isPassed,
|
||||||
|
required this.enabled,
|
||||||
required this.onTap,
|
required this.onTap,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -218,6 +242,9 @@ class _StepPill extends StatelessWidget {
|
|||||||
final WorkflowStep step;
|
final WorkflowStep step;
|
||||||
final bool isActive;
|
final bool isActive;
|
||||||
final bool isPassed;
|
final bool isPassed;
|
||||||
|
|
||||||
|
/// `false` = Step gesperrt (z. B. Übersicht vor abgewickelter Zahlung).
|
||||||
|
final bool enabled;
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -248,8 +275,10 @@ class _StepPill extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: onTap,
|
onTap: enabled ? onTap : null,
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
child: Opacity(
|
||||||
|
opacity: enabled ? 1 : 0.4,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -264,12 +293,14 @@ class _StepPill extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: circleColor,
|
color: circleColor,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
border: isActive
|
border:
|
||||||
|
isActive
|
||||||
? Border.all(color: primary, width: 2)
|
? Border.all(color: primary, width: 2)
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: isPassed && !isActive
|
child:
|
||||||
|
isPassed && !isActive
|
||||||
? Icon(Icons.check, color: circleFg, size: 16)
|
? Icon(Icons.check, color: circleFg, size: 16)
|
||||||
: Text(
|
: Text(
|
||||||
'${index + 1}',
|
'${index + 1}',
|
||||||
@ -297,6 +328,7 @@ class _StepPill extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +345,8 @@ class _StepConnector extends StatelessWidget {
|
|||||||
child: Container(
|
child: Container(
|
||||||
width: 10,
|
width: 10,
|
||||||
height: 2,
|
height: 2,
|
||||||
color: isPassed
|
color:
|
||||||
|
isPassed
|
||||||
? theme.colorScheme.primary
|
? theme.colorScheme.primary
|
||||||
: theme.colorScheme.surfaceContainerHighest,
|
: theme.colorScheme.surfaceContainerHighest,
|
||||||
),
|
),
|
||||||
@ -343,6 +376,8 @@ class _StepBody extends StatelessWidget {
|
|||||||
return StepArticles(delivery: delivery, details: details);
|
return StepArticles(delivery: delivery, details: details);
|
||||||
case WorkflowStep.services:
|
case WorkflowStep.services:
|
||||||
return StepServices(delivery: delivery, details: details);
|
return StepServices(delivery: delivery, details: details);
|
||||||
|
case WorkflowStep.payment:
|
||||||
|
return StepPayment(delivery: delivery, details: details);
|
||||||
case WorkflowStep.summary:
|
case WorkflowStep.summary:
|
||||||
return StepSummary(delivery: delivery, details: details);
|
return StepSummary(delivery: delivery, details: details);
|
||||||
}
|
}
|
||||||
@ -365,59 +400,30 @@ class _BottomNav extends StatelessWidget {
|
|||||||
/// dann den `completed`-Status zeigt.
|
/// dann den `completed`-Status zeigt.
|
||||||
void _onSign(BuildContext context) {
|
void _onSign(BuildContext context) {
|
||||||
final tourBloc = context.read<TourBloc>();
|
final tourBloc = context.read<TourBloc>();
|
||||||
// Die im Summary-Step gewählte Zahlungsmethode lebt im Workflow-State.
|
// Kassiert wurde bereits im Step „Zahlung" (serverseitig protokolliert).
|
||||||
// Beim Abschluss reisen wir sie mit ans Backend (atomar mit der Signatur);
|
// Beim Abschluss reisen Methode und Inkasso-Flag der gültigen Zahlung
|
||||||
// `null` = die am Beleg hinterlegte Methode bleibt.
|
// mit; ohne offenen Betrag bleibt die Methode vom Beleg.
|
||||||
final paymentMethodOverrideId =
|
final payment = DeliveryPaymentStatus.of(delivery, details).validPayment;
|
||||||
context.read<DeliveryWorkflowBloc>().state.paymentMethodOverrideId;
|
|
||||||
|
|
||||||
// Offener Betrag = Warenwert − Anzahlung − Gutschrift (≥ 0). EXAKT die
|
|
||||||
// Formel aus StepSummary und dem Backend-Inkasso-Gate.
|
|
||||||
final creditEuros =
|
|
||||||
(details.creditOf(delivery.id)?.amountCents ?? 0) / 100.0;
|
|
||||||
final warenwert =
|
|
||||||
delivery.items.fold<double>(0, (acc, item) => acc + item.lineTotal);
|
|
||||||
final open = (warenwert - delivery.prepaidAmount - creditEuros)
|
|
||||||
.clamp(0.0, double.infinity)
|
|
||||||
.toDouble();
|
|
||||||
|
|
||||||
// Effektive Methode (Override > Beleg) auflösen, um Vor-Ort-Inkasso
|
|
||||||
// (Bar/EC) von „Auf Rechnung" zu unterscheiden.
|
|
||||||
final effectiveMethodId =
|
|
||||||
paymentMethodOverrideId ?? delivery.paymentMethodId;
|
|
||||||
final pmState = context.read<PaymentMethodsCubit>().state;
|
|
||||||
PaymentMethod? method;
|
|
||||||
if (pmState is PaymentMethodsLoaded) {
|
|
||||||
for (final m in pmState.methods) {
|
|
||||||
if (m.id == effectiveMethodId) {
|
|
||||||
method = m;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Inkasso-Pflicht: offener Betrag > 0 UND Bar/EC. „Auf Rechnung" → nein.
|
|
||||||
final requiresCollection =
|
|
||||||
open > 0 && (method?.code == 'cash' || method?.code == 'ec_card');
|
|
||||||
|
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute<void>(
|
MaterialPageRoute<void>(
|
||||||
builder: (routeContext) => SignatureView(
|
builder:
|
||||||
|
(routeContext) => SignatureView(
|
||||||
delivery: delivery,
|
delivery: delivery,
|
||||||
details: details,
|
details: details,
|
||||||
requiresCollection: requiresCollection,
|
|
||||||
openAmount: open,
|
|
||||||
paymentMethodLabel: method?.name ?? '',
|
|
||||||
onSigned: (result) {
|
onSigned: (result) {
|
||||||
tourBloc.add(CompleteDelivery(
|
tourBloc.add(
|
||||||
|
CompleteDelivery(
|
||||||
deliveryId: delivery.id,
|
deliveryId: delivery.id,
|
||||||
customerSignaturePng: result.customerSignaturePng,
|
customerSignaturePng: result.customerSignaturePng,
|
||||||
driverSignaturePng: result.driverSignaturePng,
|
driverSignaturePng: result.driverSignaturePng,
|
||||||
receiptConfirmed: result.receiptConfirmed,
|
receiptConfirmed: result.receiptConfirmed,
|
||||||
notesAcknowledged: result.notesAcknowledged,
|
notesAcknowledged: result.notesAcknowledged,
|
||||||
acknowledgedNoteIds: result.acknowledgedNoteIds,
|
acknowledgedNoteIds: result.acknowledgedNoteIds,
|
||||||
paymentMethodId: paymentMethodOverrideId,
|
paymentMethodId: payment?.paymentMethodId,
|
||||||
paymentCollected: result.paymentCollected,
|
paymentCollected: payment?.isCollectedOnSite ?? false,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
Navigator.of(routeContext).pop();
|
Navigator.of(routeContext).pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -438,11 +444,12 @@ class _BottomNav extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
OutlinedButton.icon(
|
OutlinedButton.icon(
|
||||||
onPressed: isFirst
|
onPressed:
|
||||||
|
isFirst
|
||||||
? null
|
? null
|
||||||
: () => context
|
: () => context.read<DeliveryWorkflowBloc>().add(
|
||||||
.read<DeliveryWorkflowBloc>()
|
const WorkflowPreviousStep(),
|
||||||
.add(const WorkflowPreviousStep()),
|
),
|
||||||
icon: const Icon(Icons.arrow_back),
|
icon: const Icon(Icons.arrow_back),
|
||||||
label: const Text('Zurück'),
|
label: const Text('Zurück'),
|
||||||
),
|
),
|
||||||
@ -451,26 +458,37 @@ class _BottomNav extends StatelessWidget {
|
|||||||
// Unterschreiben/Abschließen nur bei aktiver Lieferung.
|
// Unterschreiben/Abschließen nur bei aktiver Lieferung.
|
||||||
// Ist sie bereits abgeschlossen (oder pausiert/abgebrochen),
|
// Ist sie bereits abgeschlossen (oder pausiert/abgebrochen),
|
||||||
// bleibt der Button gesperrt.
|
// bleibt der Button gesperrt.
|
||||||
Builder(builder: (context) {
|
Builder(
|
||||||
final isActive =
|
builder: (context) {
|
||||||
delivery.state == DeliveryState.active;
|
final isActive = delivery.state == DeliveryState.active;
|
||||||
final isCompleted =
|
final isCompleted =
|
||||||
delivery.state == DeliveryState.completed;
|
delivery.state == DeliveryState.completed;
|
||||||
return FilledButton.icon(
|
return FilledButton.icon(
|
||||||
onPressed: isActive ? () => _onSign(context) : null,
|
onPressed: isActive ? () => _onSign(context) : null,
|
||||||
icon: Icon(isCompleted
|
icon: Icon(
|
||||||
|
isCompleted
|
||||||
? Icons.check_circle_outline
|
? Icons.check_circle_outline
|
||||||
: Icons.draw_outlined),
|
: Icons.draw_outlined,
|
||||||
|
),
|
||||||
label: Text(
|
label: Text(
|
||||||
isCompleted ? 'Abgeschlossen' : 'Unterschreiben',
|
isCompleted ? 'Abgeschlossen' : 'Unterschreiben',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
})
|
},
|
||||||
|
)
|
||||||
else
|
else
|
||||||
FilledButton.icon(
|
FilledButton.icon(
|
||||||
onPressed: () => context
|
// Aus „Zahlung" erst weiter, wenn abgewickelt/nichts offen.
|
||||||
.read<DeliveryWorkflowBloc>()
|
onPressed:
|
||||||
.add(const WorkflowNextStep()),
|
_lockedByPayment(
|
||||||
|
WorkflowStep.values[state.step.index + 1],
|
||||||
|
delivery,
|
||||||
|
details,
|
||||||
|
)
|
||||||
|
? null
|
||||||
|
: () => context.read<DeliveryWorkflowBloc>().add(
|
||||||
|
const WorkflowNextStep(),
|
||||||
|
),
|
||||||
icon: const Icon(Icons.arrow_forward),
|
icon: const Icon(Icons.arrow_forward),
|
||||||
label: const Text('Weiter'),
|
label: const Text('Weiter'),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -17,7 +17,6 @@ class SignatureResult {
|
|||||||
required this.receiptConfirmed,
|
required this.receiptConfirmed,
|
||||||
required this.notesAcknowledged,
|
required this.notesAcknowledged,
|
||||||
required this.acknowledgedNoteIds,
|
required this.acknowledgedNoteIds,
|
||||||
required this.paymentCollected,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
final Uint8List customerSignaturePng;
|
final Uint8List customerSignaturePng;
|
||||||
@ -25,18 +24,13 @@ class SignatureResult {
|
|||||||
final bool receiptConfirmed;
|
final bool receiptConfirmed;
|
||||||
final bool notesAcknowledged;
|
final bool notesAcknowledged;
|
||||||
final List<String> acknowledgedNoteIds;
|
final List<String> acknowledgedNoteIds;
|
||||||
|
|
||||||
/// Fahrer hat das Inkasso (Bar/EC) des offenen Betrags bestätigt. `false`,
|
|
||||||
/// wenn kein Inkasso anfiel (offen == 0 oder „Auf Rechnung").
|
|
||||||
final bool paymentCollected;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mehrstufiger Unterschrift-Flow zum Abschließen einer Lieferung.
|
/// Mehrstufiger Unterschrift-Flow zum Abschließen einer Lieferung.
|
||||||
///
|
///
|
||||||
/// Stufe 0 (Fahrer, optional): nur wenn beim Abschluss ein offener Betrag
|
/// Das Kassieren passiert vorher im eigenen Workflow-Step „Zahlung" und
|
||||||
/// per Vor-Ort-Inkasso (Bar/EC) zu kassieren ist ([requiresCollection]).
|
/// wird dort protokolliert — dieser Flow enthält nur noch die Unterschriften.
|
||||||
/// Der Fahrer bestätigt, dass der Betrag erhalten/abgerechnet wurde — VOR
|
///
|
||||||
/// beiden Unterschriften.
|
|
||||||
/// Stufe 1 (Kunde): sieht die Anmerkungen zur Lieferung, hakt zwei
|
/// Stufe 1 (Kunde): sieht die Anmerkungen zur Lieferung, hakt zwei
|
||||||
/// Bestätigungen ab (Anmerkungen-Kenntnisnahme — nur Pflicht, wenn Notizen
|
/// Bestätigungen ab (Anmerkungen-Kenntnisnahme — nur Pflicht, wenn Notizen
|
||||||
/// vorhanden; Empfangsbestätigung — immer Pflicht) und unterschreibt.
|
/// vorhanden; Empfangsbestätigung — immer Pflicht) und unterschreibt.
|
||||||
@ -51,31 +45,18 @@ class SignatureView extends StatefulWidget {
|
|||||||
required this.delivery,
|
required this.delivery,
|
||||||
required this.details,
|
required this.details,
|
||||||
required this.onSigned,
|
required this.onSigned,
|
||||||
this.requiresCollection = false,
|
|
||||||
this.openAmount = 0,
|
|
||||||
this.paymentMethodLabel = '',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
final Delivery delivery;
|
final Delivery delivery;
|
||||||
final TourDetails details;
|
final TourDetails details;
|
||||||
final void Function(SignatureResult result) onSigned;
|
final void Function(SignatureResult result) onSigned;
|
||||||
|
|
||||||
/// Offener Betrag muss vor Ort kassiert werden (offen > 0 UND Bar/EC).
|
|
||||||
/// Schaltet Stufe 0 (Inkasso-Bestätigung) frei.
|
|
||||||
final bool requiresCollection;
|
|
||||||
|
|
||||||
/// Offener Betrag in Euro (nur für die Anzeige in Stufe 0).
|
|
||||||
final double openAmount;
|
|
||||||
|
|
||||||
/// Anzeigename der Zahlungsmethode (z. B. „Bar", „EC-Karte").
|
|
||||||
final String paymentMethodLabel;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SignatureView> createState() => _SignatureViewState();
|
State<SignatureView> createState() => _SignatureViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stufen des Abschluss-Flows.
|
/// Stufen des Abschluss-Flows.
|
||||||
enum _SignStage { payment, customer, driver }
|
enum _SignStage { customer, driver }
|
||||||
|
|
||||||
class _SignatureViewState extends State<SignatureView> {
|
class _SignatureViewState extends State<SignatureView> {
|
||||||
static const String _receiptText =
|
static const String _receiptText =
|
||||||
@ -97,8 +78,7 @@ class _SignatureViewState extends State<SignatureView> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
late final List<DeliveryNote> _notes;
|
late final List<DeliveryNote> _notes;
|
||||||
late _SignStage _stage;
|
_SignStage _stage = _SignStage.customer;
|
||||||
bool _paymentConfirmed = false;
|
|
||||||
bool _receiptAccepted = false;
|
bool _receiptAccepted = false;
|
||||||
bool _notesAccepted = false;
|
bool _notesAccepted = false;
|
||||||
bool _customerEmpty = true;
|
bool _customerEmpty = true;
|
||||||
@ -109,10 +89,8 @@ class _SignatureViewState extends State<SignatureView> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
// Inkasso-Bestätigung (Stufe 0) nur wenn gefordert, sonst direkt zum Kunden.
|
_notes =
|
||||||
_stage =
|
widget.details.notesByDeliveryId[widget.delivery.id] ??
|
||||||
widget.requiresCollection ? _SignStage.payment : _SignStage.customer;
|
|
||||||
_notes = widget.details.notesByDeliveryId[widget.delivery.id] ??
|
|
||||||
const <DeliveryNote>[];
|
const <DeliveryNote>[];
|
||||||
_customerController.addListener(() {
|
_customerController.addListener(() {
|
||||||
if (_customerEmpty != _customerController.isEmpty) {
|
if (_customerEmpty != _customerController.isEmpty) {
|
||||||
@ -139,8 +117,6 @@ class _SignatureViewState extends State<SignatureView> {
|
|||||||
/// Ist der Primär-Button auf der aktuellen Stufe aktiv?
|
/// Ist der Primär-Button auf der aktuellen Stufe aktiv?
|
||||||
bool get _stageValid {
|
bool get _stageValid {
|
||||||
switch (_stage) {
|
switch (_stage) {
|
||||||
case _SignStage.payment:
|
|
||||||
return _paymentConfirmed;
|
|
||||||
case _SignStage.customer:
|
case _SignStage.customer:
|
||||||
return _customerStepValid;
|
return _customerStepValid;
|
||||||
case _SignStage.driver:
|
case _SignStage.driver:
|
||||||
@ -150,9 +126,6 @@ class _SignatureViewState extends State<SignatureView> {
|
|||||||
|
|
||||||
Future<void> _onPrimaryPressed() async {
|
Future<void> _onPrimaryPressed() async {
|
||||||
switch (_stage) {
|
switch (_stage) {
|
||||||
case _SignStage.payment:
|
|
||||||
setState(() => _stage = _SignStage.customer);
|
|
||||||
return;
|
|
||||||
case _SignStage.customer:
|
case _SignStage.customer:
|
||||||
setState(() => _stage = _SignStage.driver);
|
setState(() => _stage = _SignStage.driver);
|
||||||
return;
|
return;
|
||||||
@ -168,33 +141,20 @@ class _SignatureViewState extends State<SignatureView> {
|
|||||||
notesAcknowledged: _notesEmpty ? false : _notesAccepted,
|
notesAcknowledged: _notesEmpty ? false : _notesAccepted,
|
||||||
acknowledgedNoteIds:
|
acknowledgedNoteIds:
|
||||||
_notesEmpty ? const [] : _notes.map((n) => n.id).toList(),
|
_notesEmpty ? const [] : _notes.map((n) => n.id).toList(),
|
||||||
paymentCollected: widget.requiresCollection && _paymentConfirmed,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String get _paymentText {
|
|
||||||
final amount = widget.openAmount.toStringAsFixed(2).replaceAll('.', ',');
|
|
||||||
final via = widget.paymentMethodLabel.isEmpty
|
|
||||||
? ''
|
|
||||||
: ' per ${widget.paymentMethodLabel}';
|
|
||||||
return 'Ich bestätige, dass der offene Betrag von $amount €$via '
|
|
||||||
'erhalten bzw. abgerechnet wurde.';
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final customer = widget.details.customerOf(widget.delivery);
|
final customer = widget.details.customerOf(widget.delivery);
|
||||||
final date = DateFormat('dd.MM.yyyy').format(DateTime.now());
|
final date = DateFormat('dd.MM.yyyy').format(DateTime.now());
|
||||||
final isPayment = _stage == _SignStage.payment;
|
|
||||||
final isDriver = _stage == _SignStage.driver;
|
final isDriver = _stage == _SignStage.driver;
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
switch (_stage) {
|
switch (_stage) {
|
||||||
case _SignStage.payment:
|
|
||||||
title = 'Zahlung bestätigen';
|
|
||||||
case _SignStage.customer:
|
case _SignStage.customer:
|
||||||
title = 'Unterschrift des Kunden';
|
title = 'Unterschrift des Kunden';
|
||||||
case _SignStage.driver:
|
case _SignStage.driver:
|
||||||
@ -207,21 +167,6 @@ class _SignatureViewState extends State<SignatureView> {
|
|||||||
child: ListView(
|
child: ListView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
if (isPayment) ...[
|
|
||||||
// Stufe 0 — Fahrer kassiert (Bar/EC) und bestätigt VOR den
|
|
||||||
// Unterschriften.
|
|
||||||
_PaymentDueCard(
|
|
||||||
openAmount: widget.openAmount,
|
|
||||||
methodLabel: widget.paymentMethodLabel,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
_ConfirmTile(
|
|
||||||
value: _paymentConfirmed,
|
|
||||||
enabled: true,
|
|
||||||
label: _paymentText,
|
|
||||||
onChanged: (v) => setState(() => _paymentConfirmed = v),
|
|
||||||
),
|
|
||||||
] else ...[
|
|
||||||
if (!isDriver) ...[
|
if (!isDriver) ...[
|
||||||
_NotesSection(notes: _notes),
|
_NotesSection(notes: _notes),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
@ -241,13 +186,15 @@ class _SignatureViewState extends State<SignatureView> {
|
|||||||
],
|
],
|
||||||
Text(
|
Text(
|
||||||
'Lieferung an: ${customer?.name ?? '⟨Unbekannter Kunde⟩'}',
|
'Lieferung an: ${customer?.name ?? '⟨Unbekannter Kunde⟩'}',
|
||||||
style: theme.textTheme.titleSmall
|
style: theme.textTheme.titleSmall?.copyWith(
|
||||||
?.copyWith(fontWeight: FontWeight.w700),
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
_SignaturePad(
|
_SignaturePad(
|
||||||
controller: isDriver ? _driverController : _customerController,
|
controller: isDriver ? _driverController : _customerController,
|
||||||
onClear: () =>
|
onClear:
|
||||||
|
() =>
|
||||||
(isDriver ? _driverController : _customerController)
|
(isDriver ? _driverController : _customerController)
|
||||||
.clear(),
|
.clear(),
|
||||||
),
|
),
|
||||||
@ -256,7 +203,6 @@ class _SignatureViewState extends State<SignatureView> {
|
|||||||
'${customer?.address.city ?? ''}, den $date',
|
'${customer?.address.city ?? ''}, den $date',
|
||||||
style: theme.textTheme.bodySmall,
|
style: theme.textTheme.bodySmall,
|
||||||
),
|
),
|
||||||
],
|
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
FilledButton.icon(
|
FilledButton.icon(
|
||||||
onPressed: _stageValid ? _onPrimaryPressed : null,
|
onPressed: _stageValid ? _onPrimaryPressed : null,
|
||||||
@ -270,66 +216,6 @@ class _SignatureViewState extends State<SignatureView> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Inkasso-Hinweis (Stufe 0) ──────────────────────────────────────────────
|
|
||||||
|
|
||||||
class _PaymentDueCard extends StatelessWidget {
|
|
||||||
const _PaymentDueCard({required this.openAmount, required this.methodLabel});
|
|
||||||
|
|
||||||
final double openAmount;
|
|
||||||
final String methodLabel;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final theme = Theme.of(context);
|
|
||||||
final amount = openAmount.toStringAsFixed(2).replaceAll('.', ',');
|
|
||||||
return Card(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
color: theme.colorScheme.primary.withValues(alpha: 0.07),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'Offener Betrag',
|
|
||||||
style: theme.textTheme.titleMedium
|
|
||||||
?.copyWith(fontWeight: FontWeight.w700),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.payments_outlined, color: theme.colorScheme.primary),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Text(
|
|
||||||
'$amount €',
|
|
||||||
style: theme.textTheme.headlineSmall?.copyWith(
|
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
color: theme.colorScheme.primary,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
if (methodLabel.isNotEmpty)
|
|
||||||
Chip(
|
|
||||||
label: Text(methodLabel),
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
'Bitte den Betrag bar entgegennehmen oder über das EC-Gerät '
|
|
||||||
'abrechnen und anschließend bestätigen.',
|
|
||||||
style: theme.textTheme.bodySmall?.copyWith(
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── Notizen-Block ────────────────────────────────────────────────────────
|
// ─── Notizen-Block ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
class _NotesSection extends StatelessWidget {
|
class _NotesSection extends StatelessWidget {
|
||||||
@ -345,8 +231,9 @@ class _NotesSection extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'Anmerkungen zur Lieferung',
|
'Anmerkungen zur Lieferung',
|
||||||
style:
|
style: theme.textTheme.titleMedium?.copyWith(
|
||||||
theme.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w700),
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
if (notes.isEmpty)
|
if (notes.isEmpty)
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
|
|||||||
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_bloc.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_bloc.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_event.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_event.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_state.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_state.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/reason_dialog.dart';
|
||||||
|
|
||||||
/// Step 1 — Informationen zur Lieferung.
|
/// Step 1 — Informationen zur Lieferung.
|
||||||
///
|
///
|
||||||
@ -245,39 +246,6 @@ class _QuickActions extends StatelessWidget {
|
|||||||
await _call(context, picked.value);
|
await _call(context, picked.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> _askReason(BuildContext context, String title) async {
|
|
||||||
final controller = TextEditingController();
|
|
||||||
final result = await showDialog<String>(
|
|
||||||
context: context,
|
|
||||||
builder: (dialogContext) => AlertDialog(
|
|
||||||
title: Text(title),
|
|
||||||
content: TextField(
|
|
||||||
controller: controller,
|
|
||||||
autofocus: true,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Grund',
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.of(dialogContext).pop(null),
|
|
||||||
child: const Text('Abbrechen'),
|
|
||||||
),
|
|
||||||
FilledButton(
|
|
||||||
onPressed: () {
|
|
||||||
final text = controller.text.trim();
|
|
||||||
if (text.isEmpty) return;
|
|
||||||
Navigator.of(dialogContext).pop(text);
|
|
||||||
},
|
|
||||||
child: const Text('Bestätigen'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _onStatusSelected(
|
Future<void> _onStatusSelected(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
_StatusAction action,
|
_StatusAction action,
|
||||||
@ -285,11 +253,11 @@ class _QuickActions extends StatelessWidget {
|
|||||||
final tourBloc = context.read<TourBloc>();
|
final tourBloc = context.read<TourBloc>();
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case _StatusAction.hold:
|
case _StatusAction.hold:
|
||||||
final reason = await _askReason(context, 'Lieferung pausieren');
|
final reason = await showReasonDialog(context, 'Lieferung pausieren');
|
||||||
if (reason == null) return;
|
if (reason == null) return;
|
||||||
tourBloc.add(HoldDelivery(deliveryId: delivery.id, reason: reason));
|
tourBloc.add(HoldDelivery(deliveryId: delivery.id, reason: reason));
|
||||||
case _StatusAction.cancel:
|
case _StatusAction.cancel:
|
||||||
final reason = await _askReason(context, 'Lieferung abbrechen');
|
final reason = await showReasonDialog(context, 'Lieferung abbrechen');
|
||||||
if (reason == null) return;
|
if (reason == null) return;
|
||||||
tourBloc.add(CancelDelivery(deliveryId: delivery.id, reason: reason));
|
tourBloc.add(CancelDelivery(deliveryId: delivery.id, reason: reason));
|
||||||
case _StatusAction.resume:
|
case _StatusAction.resume:
|
||||||
|
|||||||
185
lib/feature/delivery/detail/presentation/steps/step_payment.dart
Normal file
185
lib/feature/delivery/detail/presentation/steps/step_payment.dart
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/car_selection/bloc/bloc.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/car_selection/bloc/state.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/model/delivery_payment_status.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/delivered_items_card.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/payment_breakdown_card.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/payment_record_card.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/payment_sheet.dart';
|
||||||
|
|
||||||
|
/// Step „Zahlung" — Zahlungsabwicklung („Abkassieren") vor der Übersicht.
|
||||||
|
///
|
||||||
|
/// Zeigt die ausgelieferten Artikel mit Menge und Preis, die Betrags-
|
||||||
|
/// aufstellung und den Zahlungsstatus. Über „Zahlung abwickeln" öffnet sich
|
||||||
|
/// das Zahlungs-Modal; die Bestätigung wird am Server protokolliert.
|
||||||
|
///
|
||||||
|
/// Ist nichts offen (bereits bezahlt), kann der Fahrer den Step
|
||||||
|
/// überspringen. Sonst gibt die Detail-Page „Weiter" erst frei, wenn eine
|
||||||
|
/// gültige Zahlung protokolliert ist (siehe `DeliveryPaymentStatus`).
|
||||||
|
class StepPayment extends StatelessWidget {
|
||||||
|
const StepPayment({super.key, required this.delivery, required this.details});
|
||||||
|
|
||||||
|
final Delivery delivery;
|
||||||
|
final TourDetails details;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final status = DeliveryPaymentStatus.of(delivery, details);
|
||||||
|
final canCollect =
|
||||||
|
delivery.state == DeliveryState.active && status.hasOpenAmount;
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ListView(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
|
||||||
|
children: [
|
||||||
|
const _SectionHeader(text: 'Ausgelieferte Artikel'),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
DeliveredItemsCard(delivery: delivery, details: details),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
const _SectionHeader(text: 'Betrag'),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
PaymentBreakdownCard(
|
||||||
|
status: status,
|
||||||
|
credit: details.creditOf(delivery.id),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
PaymentRecordCard(status: status),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (canCollect)
|
||||||
|
_CollectPanel(
|
||||||
|
status: status,
|
||||||
|
onCollect: () => _openPaymentSheet(context, status),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _openPaymentSheet(
|
||||||
|
BuildContext context,
|
||||||
|
DeliveryPaymentStatus status,
|
||||||
|
) async {
|
||||||
|
final tourBloc = context.read<TourBloc>();
|
||||||
|
final actorCarId = _actorCarId(context);
|
||||||
|
final customer = details.customerOf(delivery);
|
||||||
|
|
||||||
|
final result = await showPaymentSheet(
|
||||||
|
context,
|
||||||
|
openCents: status.openCents,
|
||||||
|
customerNumber: customer?.erpCustomerId ?? 0,
|
||||||
|
// Vorauswahl: zuletzt abgewickelte Methode, sonst die vom Beleg.
|
||||||
|
preselectedMethodId:
|
||||||
|
status.latestPayment?.paymentMethodId ?? delivery.paymentMethodId,
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case PaymentConfirmed(:final method):
|
||||||
|
tourBloc.add(
|
||||||
|
RecordDeliveryPayment(
|
||||||
|
deliveryId: delivery.id,
|
||||||
|
paymentMethodId: method.id,
|
||||||
|
expectedAmountCents: status.openCents,
|
||||||
|
actorCarId: actorCarId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
case DeliveryCancelRequested(:final reason):
|
||||||
|
tourBloc.add(CancelDelivery(deliveryId: delivery.id, reason: reason));
|
||||||
|
case null:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String? _actorCarId(BuildContext context) {
|
||||||
|
final state = context.read<CarSelectBloc>().state;
|
||||||
|
return state is CarSelectComplete ? state.selectedCar.id : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fester Bereich unten: offener Betrag + großer „Zahlung abwickeln"-Button.
|
||||||
|
/// Bleibt sichtbar, auch wenn die Artikelliste lang ist.
|
||||||
|
class _CollectPanel extends StatelessWidget {
|
||||||
|
const _CollectPanel({required this.status, required this.onCollect});
|
||||||
|
|
||||||
|
final DeliveryPaymentStatus status;
|
||||||
|
final VoidCallback onCollect;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final settled = status.validPayment != null;
|
||||||
|
return Material(
|
||||||
|
elevation: 6,
|
||||||
|
color: theme.colorScheme.surface,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 12),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text('Offener Betrag', style: theme.textTheme.titleMedium),
|
||||||
|
const Spacer(),
|
||||||
|
Text(
|
||||||
|
formatEuroCents(status.openCents),
|
||||||
|
style: theme.textTheme.headlineSmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
color: theme.colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
if (settled)
|
||||||
|
// Bereits abgewickelt: Korrektur möglich, aber nicht mehr im
|
||||||
|
// Vordergrund — „Weiter" ist jetzt der nächste Schritt.
|
||||||
|
OutlinedButton.icon(
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
minimumSize: const Size.fromHeight(52),
|
||||||
|
),
|
||||||
|
onPressed: onCollect,
|
||||||
|
icon: const Icon(Icons.edit_outlined),
|
||||||
|
label: const Text('Zahlung korrigieren'),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
FilledButton.icon(
|
||||||
|
style: FilledButton.styleFrom(
|
||||||
|
minimumSize: const Size.fromHeight(68),
|
||||||
|
textStyle: const TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: onCollect,
|
||||||
|
icon: const Icon(Icons.point_of_sale, size: 28),
|
||||||
|
label: const Text('Zahlung abwickeln'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SectionHeader extends StatelessWidget {
|
||||||
|
const _SectionHeader({required this.text});
|
||||||
|
final String text;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Text(
|
||||||
|
text,
|
||||||
|
style: Theme.of(
|
||||||
|
context,
|
||||||
|
).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w700),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,69 +1,50 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
|
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
|
||||||
import 'package:hl_lieferservice/domain/entity/delivery_item.dart';
|
|
||||||
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
|
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_bloc.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/model/delivery_payment_status.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_event.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/delivered_items_card.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/detail/bloc/workflow_state.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/payment_breakdown_card.dart';
|
||||||
import 'package:hl_lieferservice/feature/payment_methods/bloc/payment_methods_cubit.dart';
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/payment_record_card.dart';
|
||||||
|
|
||||||
/// Step 5 — Übersicht & Abschluss.
|
/// Step 6 — Übersicht & Abschluss.
|
||||||
///
|
///
|
||||||
/// Listet alle Artikel mit der **tatsächlich auszuliefernden Menge** auf
|
/// Listet alle Artikel mit der **tatsächlich auszuliefernden Menge** auf,
|
||||||
/// (Original-Soll minus lokaler Partial-Remove-Drafts minus
|
/// dazu die Betragsaufstellung und den Stand der Zahlung. Die Zahlungsart
|
||||||
/// Komplett-Removes). Dazu Anzahlung-Anzeige, optionale Gutschrift,
|
/// wird nicht mehr hier gewählt, sondern im Step „Zahlung" abgewickelt und
|
||||||
/// Zahlungsmethoden-Dropdown.
|
/// protokolliert — die Übersicht zeigt das Ergebnis nur an.
|
||||||
///
|
///
|
||||||
/// Der „Unterschreiben"-Button lebt in der Bottom-Navigation des
|
/// Der „Unterschreiben"-Button lebt in der Bottom-Navigation des
|
||||||
/// Page-Wrappers; hier zeigen wir den Resümee-Block, der direkt vor der
|
/// Page-Wrappers; hier zeigen wir den Resümee-Block, der direkt vor der
|
||||||
/// Unterschrift steht.
|
/// Unterschrift steht.
|
||||||
class StepSummary extends StatelessWidget {
|
class StepSummary extends StatelessWidget {
|
||||||
const StepSummary({
|
const StepSummary({super.key, required this.delivery, required this.details});
|
||||||
super.key,
|
|
||||||
required this.delivery,
|
|
||||||
required this.details,
|
|
||||||
});
|
|
||||||
|
|
||||||
final Delivery delivery;
|
final Delivery delivery;
|
||||||
final TourDetails details;
|
final TourDetails details;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<DeliveryWorkflowBloc, DeliveryWorkflowState>(
|
final status = DeliveryPaymentStatus.of(delivery, details);
|
||||||
builder: (context, wfState) {
|
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
|
padding: const EdgeInsets.fromLTRB(16, 16, 16, 24),
|
||||||
children: [
|
children: [
|
||||||
_SectionHeader(text: 'Ausgelieferte Artikel'),
|
const _SectionHeader(text: 'Ausgelieferte Artikel'),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
_DeliveredItems(
|
DeliveredItemsCard(delivery: delivery, details: details),
|
||||||
delivery: delivery,
|
|
||||||
details: details,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
_SectionHeader(text: 'Zahlung'),
|
const _SectionHeader(text: 'Zahlung'),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
_PaymentSummary(
|
PaymentBreakdownCard(
|
||||||
delivery: delivery,
|
status: status,
|
||||||
credit: details.creditOf(delivery.id),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
_SectionHeader(text: 'Zahlungsmethode'),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
_PaymentMethodPicker(
|
|
||||||
delivery: delivery,
|
|
||||||
overrideId: wfState.paymentMethodOverrideId,
|
|
||||||
credit: details.creditOf(delivery.id),
|
credit: details.creditOf(delivery.id),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
PaymentRecordCard(status: status),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
const _SignHint(),
|
const _SignHint(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,452 +56,9 @@ class _SectionHeader extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Text(
|
return Text(
|
||||||
text,
|
text,
|
||||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
style: Theme.of(
|
||||||
fontWeight: FontWeight.w700,
|
context,
|
||||||
),
|
).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w700),
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _DeliveredItems extends StatelessWidget {
|
|
||||||
const _DeliveredItems({
|
|
||||||
required this.delivery,
|
|
||||||
required this.details,
|
|
||||||
});
|
|
||||||
|
|
||||||
final Delivery delivery;
|
|
||||||
final TourDetails details;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final theme = Theme.of(context);
|
|
||||||
// Innerhalb einer Belegzeile: Oberartikel vor seinen Komponenten, damit
|
|
||||||
// Komponenten direkt darunter eingerückt erscheinen.
|
|
||||||
final items = List<DeliveryItem>.of(delivery.items)
|
|
||||||
..sort((a, b) {
|
|
||||||
final byLine = a.belegzeilenNr.compareTo(b.belegzeilenNr);
|
|
||||||
if (byLine != 0) return byLine;
|
|
||||||
final byParent =
|
|
||||||
(a.isComponent ? 1 : 0).compareTo(b.isComponent ? 1 : 0);
|
|
||||||
if (byParent != 0) return byParent;
|
|
||||||
return (a.komponentenArtikelNr ?? '')
|
|
||||||
.compareTo(b.komponentenArtikelNr ?? '');
|
|
||||||
});
|
|
||||||
if (items.isEmpty) {
|
|
||||||
return Card(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Text(
|
|
||||||
'Keine Artikel hinterlegt.',
|
|
||||||
style: TextStyle(
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
fontStyle: FontStyle.italic,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Card(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
for (int i = 0; i < items.length; i++) ...[
|
|
||||||
_DeliveredRow(
|
|
||||||
item: items[i],
|
|
||||||
details: details,
|
|
||||||
),
|
|
||||||
if (i < items.length - 1)
|
|
||||||
const Divider(height: 1, indent: 16, endIndent: 16),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _DeliveredRow extends StatelessWidget {
|
|
||||||
const _DeliveredRow({
|
|
||||||
required this.item,
|
|
||||||
required this.details,
|
|
||||||
});
|
|
||||||
|
|
||||||
final DeliveryItem item;
|
|
||||||
final TourDetails details;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final theme = Theme.of(context);
|
|
||||||
final article = details.articleOf(item.articleId);
|
|
||||||
// Ausgeliefert = Soll − Gutschrift (vom Backend). Voll gutgeschrieben
|
|
||||||
// (status removed) ⇒ credited == required ⇒ delivered 0.
|
|
||||||
final credited = item.scanProgress.creditedQuantity;
|
|
||||||
final delivered = (item.requiredQuantity - credited).clamp(
|
|
||||||
0,
|
|
||||||
item.requiredQuantity,
|
|
||||||
);
|
|
||||||
|
|
||||||
final Color avatarColor;
|
|
||||||
if (delivered == 0) {
|
|
||||||
avatarColor = Colors.red.shade400;
|
|
||||||
} else if (delivered < item.requiredQuantity) {
|
|
||||||
avatarColor = Colors.amber.shade700;
|
|
||||||
} else {
|
|
||||||
avatarColor = Colors.green.shade600;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ListTile(
|
|
||||||
// Komponenten um eine Stufe eingerückt (gehören zum Oberartikel darüber).
|
|
||||||
contentPadding:
|
|
||||||
EdgeInsets.only(left: item.isComponent ? 40 : 16, right: 16),
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor: avatarColor,
|
|
||||||
foregroundColor: theme.colorScheme.onPrimary,
|
|
||||||
child: Text(
|
|
||||||
'$delivered×',
|
|
||||||
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: Text(
|
|
||||||
'${item.isComponent ? '↳ ' : ''}${article?.name ?? '⟨Unbekannter Artikel⟩'}',
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
decoration: delivered == 0 ? TextDecoration.lineThrough : null,
|
|
||||||
color: delivered == 0 ? theme.colorScheme.onSurfaceVariant : null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
[
|
|
||||||
if (delivered < item.requiredQuantity)
|
|
||||||
'von ${item.requiredQuantity} bestellt · Gutschrift: $credited'
|
|
||||||
else
|
|
||||||
'Artikelnr. ${article?.articleNumber ?? item.articleId}',
|
|
||||||
'${item.unitPrice.toStringAsFixed(2)} € / Stück',
|
|
||||||
].join(' · '),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailing: Text(
|
|
||||||
'${item.lineTotal.toStringAsFixed(2)} €',
|
|
||||||
style: theme.textTheme.titleMedium?.copyWith(
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
decoration: delivered == 0 ? TextDecoration.lineThrough : null,
|
|
||||||
color: delivered == 0 ? theme.colorScheme.onSurfaceVariant : null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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<double>(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});
|
|
||||||
|
|
||||||
final Delivery delivery;
|
|
||||||
final DeliveryCredit? credit;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final theme = Theme.of(context);
|
|
||||||
// Warenwert = Σ Stückpreis × ausgelieferte Menge (entfernte/teil-entfernte
|
|
||||||
// Positionen fallen automatisch raus).
|
|
||||||
final warenwert = delivery.items
|
|
||||||
.fold<double>(0, (acc, item) => acc + item.lineTotal);
|
|
||||||
// Offener Betrag über den gemeinsamen Helper (gleiche Formel wie die
|
|
||||||
// Zahlungsmethoden-Auswahl).
|
|
||||||
final open = _openAmount(delivery, credit);
|
|
||||||
return Card(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
_SummaryRow(
|
|
||||||
icon: Icons.receipt_long_outlined,
|
|
||||||
label: 'Warenwert',
|
|
||||||
valueText: '${warenwert.toStringAsFixed(2)} €',
|
|
||||||
valueColor: theme.colorScheme.onSurface,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
_SummaryRow(
|
|
||||||
icon: Icons.savings_outlined,
|
|
||||||
label: 'Bei Bestellung bezahlt',
|
|
||||||
valueText: '− ${delivery.prepaidAmount.toStringAsFixed(2)} €',
|
|
||||||
valueColor: delivery.prepaidAmount > 0
|
|
||||||
? Colors.green.shade700
|
|
||||||
: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
if (credit != null) ...[
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
_SummaryRow(
|
|
||||||
icon: Icons.card_giftcard_outlined,
|
|
||||||
label: 'Gutschrift',
|
|
||||||
valueText: '− ${(credit!.amountCents / 100).toStringAsFixed(2)} €',
|
|
||||||
valueColor: Colors.amber.shade800,
|
|
||||||
subtitle: credit!.reason,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
const Divider(height: 24),
|
|
||||||
_SummaryRow(
|
|
||||||
icon: Icons.account_balance_wallet_outlined,
|
|
||||||
label: 'Offener Betrag',
|
|
||||||
valueText: '${open.toStringAsFixed(2)} €',
|
|
||||||
valueColor: open > 0
|
|
||||||
? theme.colorScheme.primary
|
|
||||||
: Colors.green.shade700,
|
|
||||||
emphasize: true,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SummaryRow extends StatelessWidget {
|
|
||||||
const _SummaryRow({
|
|
||||||
required this.icon,
|
|
||||||
required this.label,
|
|
||||||
required this.valueText,
|
|
||||||
required this.valueColor,
|
|
||||||
this.subtitle,
|
|
||||||
this.emphasize = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
final IconData icon;
|
|
||||||
final String label;
|
|
||||||
final String valueText;
|
|
||||||
final Color valueColor;
|
|
||||||
final String? subtitle;
|
|
||||||
|
|
||||||
/// Hebt Label + Wert hervor (für den „Offener Betrag"-Abschluss).
|
|
||||||
final bool emphasize;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final theme = Theme.of(context);
|
|
||||||
return Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 2),
|
|
||||||
child: Icon(icon, color: theme.colorScheme.primary),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
label,
|
|
||||||
style: emphasize
|
|
||||||
? const TextStyle(fontWeight: FontWeight.w700)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
if (subtitle != null)
|
|
||||||
Text(
|
|
||||||
subtitle!,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: theme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
valueText,
|
|
||||||
style: (emphasize
|
|
||||||
? theme.textTheme.titleLarge
|
|
||||||
: theme.textTheme.titleMedium)
|
|
||||||
?.copyWith(
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
color: valueColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
return BlocBuilder<PaymentMethodsCubit, PaymentMethodsState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
if (state is PaymentMethodsLoading || state is PaymentMethodsInitial) {
|
|
||||||
return const Card(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.all(16),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
child: CircularProgressIndicator(strokeWidth: 2),
|
|
||||||
),
|
|
||||||
SizedBox(width: 12),
|
|
||||||
Text('Zahlungsmethoden laden …'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (state is PaymentMethodsFailed) {
|
|
||||||
final onError = Theme.of(context).colorScheme.onErrorContainer;
|
|
||||||
return Card(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
color: Theme.of(context).colorScheme.errorContainer,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(16, 8, 8, 8),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
state.message,
|
|
||||||
style: TextStyle(color: onError),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Fehler ist kein Endzustand: der Fahrer kann das Laden
|
|
||||||
// direkt hier erneut anstoßen (z. B. nach Netz-Aussetzer).
|
|
||||||
TextButton.icon(
|
|
||||||
onPressed: () =>
|
|
||||||
context.read<PaymentMethodsCubit>().load(),
|
|
||||||
icon: Icon(Icons.refresh, color: onError),
|
|
||||||
label: Text(
|
|
||||||
'Erneut laden',
|
|
||||||
style: TextStyle(color: onError),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
final loaded = state as PaymentMethodsLoaded;
|
|
||||||
// Ausschließlich die Backend-Methoden — keine frontend-seitige
|
|
||||||
// Fabrikation/Hardcodierung. Es werden genau die angezeigt, die im
|
|
||||||
// Backend (Postgres `payment_methods`, aktiv) hinterlegt sind.
|
|
||||||
final methods = loaded.methods;
|
|
||||||
final selectedId = overrideId ?? delivery.paymentMethodId;
|
|
||||||
// Als Dropdown-Value nur setzen, wenn die Methode tatsächlich in der
|
|
||||||
// Backend-Liste ist (sonst würde Flutter asserten). Ist die zugewiesene
|
|
||||||
// Methode zwischenzeitlich deaktiviert/entfernt, bleibt das Feld leer.
|
|
||||||
final selectedValue =
|
|
||||||
methods.any((m) => m.id == selectedId) ? selectedId : null;
|
|
||||||
// Zahlungsmethode nur bei aktiver Lieferung änderbar. Bei
|
|
||||||
// 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(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
DropdownButtonFormField<String>(
|
|
||||||
initialValue: selectedValue,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Zahlungsmethode',
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
),
|
|
||||||
items: [
|
|
||||||
for (final m in methods)
|
|
||||||
DropdownMenuItem(
|
|
||||||
value: m.id,
|
|
||||||
child: Text(m.name),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
// `null` deaktiviert das Dropdown (Flutter-Konvention).
|
|
||||||
onChanged: editable
|
|
||||||
? (newId) {
|
|
||||||
if (newId == null) return;
|
|
||||||
context.read<DeliveryWorkflowBloc>().add(
|
|
||||||
WorkflowOverridePaymentMethod(
|
|
||||||
// Zurück auf die Original-Methode → Override
|
|
||||||
// löschen, damit das Domain-Modell "no
|
|
||||||
// override" kennt.
|
|
||||||
paymentMethodId:
|
|
||||||
newId == delivery.paymentMethodId
|
|
||||||
? null
|
|
||||||
: newId,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
if (!active) ...[
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
const _PickerHint(
|
|
||||||
text: 'Lieferung abgeschlossen — Zahlungsmethode nicht '
|
|
||||||
'mehr änderbar.',
|
|
||||||
),
|
|
||||||
] else if (!hasOpenAmount) ...[
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
const _PickerHint(
|
|
||||||
text: 'Keine Zahlung mehr offen (bereits bezahlt) — '
|
|
||||||
'Auswahl der Zahlungsweise nicht erforderlich.',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -547,10 +85,7 @@ class _SignHint extends StatelessWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Mit „Unterschreiben" unten schließt der Kunde den Vorgang ab.',
|
'Mit „Unterschreiben" unten schließt der Kunde den Vorgang ab.',
|
||||||
style: TextStyle(
|
style: TextStyle(fontSize: 13, color: theme.colorScheme.primary),
|
||||||
fontSize: 13,
|
|
||||||
color: theme.colorScheme.primary,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -0,0 +1,139 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_item.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/model/delivery_payment_status.dart';
|
||||||
|
|
||||||
|
/// Ausgelieferte Artikel einer Lieferung mit Menge, Stückpreis und
|
||||||
|
/// Zeilensumme. Gemeinsam genutzt von Zahlungs-Step und Übersicht.
|
||||||
|
///
|
||||||
|
/// Menge = tatsächlich ausgeliefert (Soll − Gutschrift). Komplett
|
||||||
|
/// gutgeschriebene Positionen erscheinen durchgestrichen.
|
||||||
|
class DeliveredItemsCard extends StatelessWidget {
|
||||||
|
const DeliveredItemsCard({
|
||||||
|
super.key,
|
||||||
|
required this.delivery,
|
||||||
|
required this.details,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Delivery delivery;
|
||||||
|
final TourDetails details;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
// Innerhalb einer Belegzeile: Oberartikel vor seinen Komponenten, damit
|
||||||
|
// Komponenten direkt darunter eingerückt erscheinen.
|
||||||
|
final items = List<DeliveryItem>.of(delivery.items)..sort((a, b) {
|
||||||
|
final byLine = a.belegzeilenNr.compareTo(b.belegzeilenNr);
|
||||||
|
if (byLine != 0) return byLine;
|
||||||
|
final byParent = (a.isComponent ? 1 : 0).compareTo(b.isComponent ? 1 : 0);
|
||||||
|
if (byParent != 0) return byParent;
|
||||||
|
return (a.komponentenArtikelNr ?? '').compareTo(
|
||||||
|
b.komponentenArtikelNr ?? '',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
if (items.isEmpty) {
|
||||||
|
return Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Text(
|
||||||
|
'Keine Artikel hinterlegt.',
|
||||||
|
style: TextStyle(
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
fontStyle: FontStyle.italic,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
for (int i = 0; i < items.length; i++) ...[
|
||||||
|
_DeliveredRow(item: items[i], details: details),
|
||||||
|
if (i < items.length - 1)
|
||||||
|
const Divider(height: 1, indent: 16, endIndent: 16),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DeliveredRow extends StatelessWidget {
|
||||||
|
const _DeliveredRow({required this.item, required this.details});
|
||||||
|
|
||||||
|
final DeliveryItem item;
|
||||||
|
final TourDetails details;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final article = details.articleOf(item.articleId);
|
||||||
|
// Ausgeliefert = Soll − Gutschrift (vom Backend). Voll gutgeschrieben
|
||||||
|
// (status removed) ⇒ credited == required ⇒ delivered 0.
|
||||||
|
final credited = item.scanProgress.creditedQuantity;
|
||||||
|
final delivered = (item.requiredQuantity - credited).clamp(
|
||||||
|
0,
|
||||||
|
item.requiredQuantity,
|
||||||
|
);
|
||||||
|
|
||||||
|
final Color avatarColor;
|
||||||
|
if (delivered == 0) {
|
||||||
|
avatarColor = Colors.red.shade400;
|
||||||
|
} else if (delivered < item.requiredQuantity) {
|
||||||
|
avatarColor = Colors.amber.shade700;
|
||||||
|
} else {
|
||||||
|
avatarColor = Colors.green.shade600;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ListTile(
|
||||||
|
// Komponenten um eine Stufe eingerückt (gehören zum Oberartikel darüber).
|
||||||
|
contentPadding: EdgeInsets.only(
|
||||||
|
left: item.isComponent ? 40 : 16,
|
||||||
|
right: 16,
|
||||||
|
),
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor: avatarColor,
|
||||||
|
foregroundColor: theme.colorScheme.onPrimary,
|
||||||
|
child: Text(
|
||||||
|
'$delivered×',
|
||||||
|
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
'${item.isComponent ? '↳ ' : ''}${article?.name ?? '⟨Unbekannter Artikel⟩'}',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
decoration: delivered == 0 ? TextDecoration.lineThrough : null,
|
||||||
|
color: delivered == 0 ? theme.colorScheme.onSurfaceVariant : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
[
|
||||||
|
if (delivered < item.requiredQuantity)
|
||||||
|
'von ${item.requiredQuantity} bestellt · Gutschrift: $credited'
|
||||||
|
else
|
||||||
|
'Artikelnr. ${article?.articleNumber ?? item.articleId}',
|
||||||
|
'${formatEuro(item.unitPrice)} / Stück',
|
||||||
|
].join(' · '),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: Text(
|
||||||
|
formatEuro(item.lineTotal),
|
||||||
|
style: theme.textTheme.titleMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
decoration: delivered == 0 ? TextDecoration.lineThrough : null,
|
||||||
|
color: delivered == 0 ? theme.colorScheme.onSurfaceVariant : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,134 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/model/delivery_payment_status.dart';
|
||||||
|
|
||||||
|
/// Betragsaufstellung einer Lieferung: Warenwert − Anzahlung − Gutschrift =
|
||||||
|
/// offener Betrag. Gemeinsam genutzt von Zahlungs-Step und Übersicht; die
|
||||||
|
/// Zahlen kommen aus [DeliveryPaymentStatus] (gleiche Formel wie Backend).
|
||||||
|
class PaymentBreakdownCard extends StatelessWidget {
|
||||||
|
const PaymentBreakdownCard({
|
||||||
|
super.key,
|
||||||
|
required this.status,
|
||||||
|
required this.credit,
|
||||||
|
});
|
||||||
|
|
||||||
|
final DeliveryPaymentStatus status;
|
||||||
|
final DeliveryCredit? credit;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
return Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_AmountRow(
|
||||||
|
icon: Icons.receipt_long_outlined,
|
||||||
|
label: 'Warenwert',
|
||||||
|
valueText: formatEuro(status.goodsValue),
|
||||||
|
valueColor: theme.colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
_AmountRow(
|
||||||
|
icon: Icons.savings_outlined,
|
||||||
|
label: 'Bei Bestellung bezahlt',
|
||||||
|
valueText: '− ${formatEuro(status.prepaidAmount)}',
|
||||||
|
valueColor:
|
||||||
|
status.prepaidAmount > 0
|
||||||
|
? Colors.green.shade700
|
||||||
|
: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
if (credit != null) ...[
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
_AmountRow(
|
||||||
|
icon: Icons.card_giftcard_outlined,
|
||||||
|
label: 'Gutschrift',
|
||||||
|
valueText: '− ${formatEuroCents(credit!.amountCents)}',
|
||||||
|
valueColor: Colors.amber.shade800,
|
||||||
|
subtitle: credit!.reason,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
const Divider(height: 24),
|
||||||
|
_AmountRow(
|
||||||
|
icon: Icons.account_balance_wallet_outlined,
|
||||||
|
label: 'Offener Betrag',
|
||||||
|
valueText: formatEuroCents(status.openCents),
|
||||||
|
valueColor:
|
||||||
|
status.hasOpenAmount
|
||||||
|
? theme.colorScheme.primary
|
||||||
|
: Colors.green.shade700,
|
||||||
|
emphasize: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AmountRow extends StatelessWidget {
|
||||||
|
const _AmountRow({
|
||||||
|
required this.icon,
|
||||||
|
required this.label,
|
||||||
|
required this.valueText,
|
||||||
|
required this.valueColor,
|
||||||
|
this.subtitle,
|
||||||
|
this.emphasize = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
final IconData icon;
|
||||||
|
final String label;
|
||||||
|
final String valueText;
|
||||||
|
final Color valueColor;
|
||||||
|
final String? subtitle;
|
||||||
|
|
||||||
|
/// Hebt Label + Wert hervor (für den „Offener Betrag"-Abschluss).
|
||||||
|
final bool emphasize;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 2),
|
||||||
|
child: Icon(icon, color: theme.colorScheme.primary),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
style:
|
||||||
|
emphasize
|
||||||
|
? const TextStyle(fontWeight: FontWeight.w700)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
if (subtitle != null)
|
||||||
|
Text(
|
||||||
|
subtitle!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
valueText,
|
||||||
|
style: (emphasize
|
||||||
|
? theme.textTheme.titleLarge
|
||||||
|
: theme.textTheme.titleMedium)
|
||||||
|
?.copyWith(fontWeight: FontWeight.w700, color: valueColor),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// Icon je Zahlungsmethode anhand des stabilen Backend-Codes. Unbekannte
|
||||||
|
/// Codes (neue Methoden aus den Stammdaten) bekommen ein neutrales Icon.
|
||||||
|
IconData paymentMethodIcon(String code) => switch (code) {
|
||||||
|
'cash' => Icons.payments_outlined,
|
||||||
|
'ec_card' => Icons.credit_card,
|
||||||
|
'invoice' => Icons.receipt_long_outlined,
|
||||||
|
_ => Icons.account_balance_wallet_outlined,
|
||||||
|
};
|
||||||
@ -0,0 +1,138 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_payment.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/model/delivery_payment_status.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/payment_method_icon.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/payment_methods/bloc/payment_methods_cubit.dart';
|
||||||
|
|
||||||
|
/// Status-Karte der Zahlungsabwicklung: erledigt, veraltet, noch offen oder
|
||||||
|
/// nicht nötig. Gemeinsam genutzt von Zahlungs-Step und Übersicht.
|
||||||
|
class PaymentRecordCard extends StatelessWidget {
|
||||||
|
const PaymentRecordCard({super.key, required this.status});
|
||||||
|
|
||||||
|
final DeliveryPaymentStatus status;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final valid = status.validPayment;
|
||||||
|
if (!status.hasOpenAmount) {
|
||||||
|
return const _StatusCard(
|
||||||
|
tone: _Tone.success,
|
||||||
|
icon: Icons.verified_outlined,
|
||||||
|
title: 'Bereits bezahlt',
|
||||||
|
text:
|
||||||
|
'Es ist kein Betrag mehr offen. Dieser Schritt kann '
|
||||||
|
'übersprungen werden.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (valid != null) {
|
||||||
|
return _StatusCard(
|
||||||
|
tone: _Tone.success,
|
||||||
|
icon: paymentMethodIcon(valid.paymentMethodCode),
|
||||||
|
title:
|
||||||
|
valid.isCollectedOnSite
|
||||||
|
? 'Zahlung erhalten'
|
||||||
|
: 'Zahlung auf Rechnung bestätigt',
|
||||||
|
text:
|
||||||
|
'${formatEuroCents(valid.amountCents)} per '
|
||||||
|
'${_methodName(context, valid)} · protokolliert um '
|
||||||
|
'${DateFormat('HH:mm').format(valid.recordedAt)} Uhr',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (status.isStale) {
|
||||||
|
return const _StatusCard(
|
||||||
|
tone: _Tone.warning,
|
||||||
|
icon: Icons.sync_problem_outlined,
|
||||||
|
title: 'Betrag hat sich geändert',
|
||||||
|
text:
|
||||||
|
'Seit der letzten Zahlungsabwicklung hat sich der offene Betrag '
|
||||||
|
'geändert (z. B. durch eine Gutschrift). Bitte die Zahlung erneut '
|
||||||
|
'abwickeln.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return const _StatusCard(
|
||||||
|
tone: _Tone.open,
|
||||||
|
icon: Icons.pending_outlined,
|
||||||
|
title: 'Zahlung noch nicht abgewickelt',
|
||||||
|
text:
|
||||||
|
'Bitte die Zahlung abwickeln, bevor es mit der Übersicht '
|
||||||
|
'weitergeht.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Anzeigename aus den Stammdaten; Fallback auf den Code-Snapshot, falls
|
||||||
|
/// die Methode inzwischen deaktiviert/umbenannt wurde.
|
||||||
|
String _methodName(BuildContext context, DeliveryPayment payment) {
|
||||||
|
final state = context.watch<PaymentMethodsCubit>().state;
|
||||||
|
if (state is PaymentMethodsLoaded) {
|
||||||
|
for (final m in state.methods) {
|
||||||
|
if (m.id == payment.paymentMethodId) return m.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return switch (payment.paymentMethodCode) {
|
||||||
|
'cash' => 'Bar',
|
||||||
|
'ec_card' => 'EC-Karte',
|
||||||
|
'invoice' => 'Rechnung',
|
||||||
|
final code => code,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum _Tone { success, warning, open }
|
||||||
|
|
||||||
|
class _StatusCard extends StatelessWidget {
|
||||||
|
const _StatusCard({
|
||||||
|
required this.tone,
|
||||||
|
required this.icon,
|
||||||
|
required this.title,
|
||||||
|
required this.text,
|
||||||
|
});
|
||||||
|
|
||||||
|
final _Tone tone;
|
||||||
|
final IconData icon;
|
||||||
|
final String title;
|
||||||
|
final String text;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final Color color = switch (tone) {
|
||||||
|
_Tone.success => Colors.green.shade700,
|
||||||
|
_Tone.warning => Colors.orange.shade800,
|
||||||
|
_Tone.open => theme.colorScheme.primary,
|
||||||
|
};
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(14),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: color.withValues(alpha: 0.08),
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: color.withValues(alpha: 0.4)),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Icon(icon, color: color),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: theme.textTheme.titleSmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: color,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(text, style: theme.textTheme.bodySmall),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,407 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
import 'package:hl_lieferservice/domain/entity/payment_method.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/model/delivery_payment_status.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/payment_method_icon.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/reason_dialog.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/payment_methods/bloc/payment_methods_cubit.dart';
|
||||||
|
|
||||||
|
/// Ergebnis des Zahlungs-Modals. `null` = abgebrochen, nichts passiert.
|
||||||
|
sealed class PaymentSheetResult {
|
||||||
|
const PaymentSheetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Der Fahrer hat bestätigt, dass die Zahlung per [method] erhalten wurde
|
||||||
|
/// (bzw. bei „Rechnung": dass auf Rechnung abgewickelt wird).
|
||||||
|
class PaymentConfirmed extends PaymentSheetResult {
|
||||||
|
const PaymentConfirmed(this.method);
|
||||||
|
final PaymentMethod method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Zahlung ist nicht möglich — die ganze Lieferung soll abgebrochen werden.
|
||||||
|
class DeliveryCancelRequested extends PaymentSheetResult {
|
||||||
|
const DeliveryCancelRequested(this.reason);
|
||||||
|
final String reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Öffnet das Zahlungs-Modal.
|
||||||
|
///
|
||||||
|
/// Zeigt groß den offenen Betrag, die Zahlungsmethoden als Cards (dynamisch
|
||||||
|
/// aus den Backend-Stammdaten) und bei EC-Karte groß die Kundennummer, die
|
||||||
|
/// der Fahrer am EC-Gerät eingibt. Schließt sich nur über „Abbrechen",
|
||||||
|
/// „Zahlung erhalten" oder „Lieferung abbrechen".
|
||||||
|
Future<PaymentSheetResult?> showPaymentSheet(
|
||||||
|
BuildContext context, {
|
||||||
|
required int openCents,
|
||||||
|
required int customerNumber,
|
||||||
|
required String? preselectedMethodId,
|
||||||
|
}) {
|
||||||
|
return showModalBottomSheet<PaymentSheetResult>(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
useSafeArea: true,
|
||||||
|
// Kein versehentliches Wegwischen: Das Modal endet nur über die Buttons.
|
||||||
|
isDismissible: false,
|
||||||
|
enableDrag: false,
|
||||||
|
showDragHandle: false,
|
||||||
|
builder:
|
||||||
|
(_) => _PaymentSheet(
|
||||||
|
openCents: openCents,
|
||||||
|
customerNumber: customerNumber,
|
||||||
|
preselectedMethodId: preselectedMethodId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaymentSheet extends StatefulWidget {
|
||||||
|
const _PaymentSheet({
|
||||||
|
required this.openCents,
|
||||||
|
required this.customerNumber,
|
||||||
|
required this.preselectedMethodId,
|
||||||
|
});
|
||||||
|
|
||||||
|
final int openCents;
|
||||||
|
final int customerNumber;
|
||||||
|
final String? preselectedMethodId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_PaymentSheet> createState() => _PaymentSheetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PaymentSheetState extends State<_PaymentSheet> {
|
||||||
|
String? _selectedId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
// Vorauswahl = am Beleg hinterlegte Methode. Der Fahrer kann wechseln.
|
||||||
|
_selectedId = widget.preselectedMethodId;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _cancelDelivery() async {
|
||||||
|
final navigator = Navigator.of(context);
|
||||||
|
final reason = await showReasonDialog(context, 'Lieferung abbrechen');
|
||||||
|
if (reason == null || !mounted) return;
|
||||||
|
navigator.pop(DeliveryCancelRequested(reason));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
return BlocBuilder<PaymentMethodsCubit, PaymentMethodsState>(
|
||||||
|
builder: (context, pmState) {
|
||||||
|
final methods =
|
||||||
|
pmState is PaymentMethodsLoaded
|
||||||
|
? pmState.methods.where((m) => m.active).toList()
|
||||||
|
: const <PaymentMethod>[];
|
||||||
|
PaymentMethod? selected;
|
||||||
|
for (final m in methods) {
|
||||||
|
if (m.id == _selectedId) selected = m;
|
||||||
|
}
|
||||||
|
final isInvoice = selected?.code == 'invoice';
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
padding: const EdgeInsets.fromLTRB(20, 20, 20, 8),
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Zahlung abwickeln',
|
||||||
|
style: theme.textTheme.titleLarge?.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
_AmountBanner(openCents: widget.openCents),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Text(
|
||||||
|
'Zahlungsart',
|
||||||
|
style: theme.textTheme.titleMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
..._methodSection(context, pmState, methods),
|
||||||
|
if (selected != null) ...[
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
_MethodHint(
|
||||||
|
method: selected,
|
||||||
|
customerNumber: widget.customerNumber,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SafeArea(
|
||||||
|
top: false,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(20, 8, 20, 12),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
FilledButton.icon(
|
||||||
|
style: FilledButton.styleFrom(
|
||||||
|
minimumSize: const Size.fromHeight(60),
|
||||||
|
textStyle: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed:
|
||||||
|
selected == null
|
||||||
|
? null
|
||||||
|
: () => Navigator.of(
|
||||||
|
context,
|
||||||
|
).pop(PaymentConfirmed(selected!)),
|
||||||
|
icon: const Icon(Icons.check_circle_outline),
|
||||||
|
label: Text(
|
||||||
|
isInvoice
|
||||||
|
? 'Auf Rechnung bestätigen'
|
||||||
|
: 'Zahlung erhalten',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 3,
|
||||||
|
child: OutlinedButton.icon(
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
minimumSize: const Size.fromHeight(48),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
),
|
||||||
|
foregroundColor: theme.colorScheme.error,
|
||||||
|
side: BorderSide(color: theme.colorScheme.error),
|
||||||
|
),
|
||||||
|
onPressed: _cancelDelivery,
|
||||||
|
icon: const Icon(Icons.block),
|
||||||
|
label: const Text('Lieferung abbrechen'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Expanded(
|
||||||
|
flex: 2,
|
||||||
|
child: TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
minimumSize: const Size.fromHeight(48),
|
||||||
|
),
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('Abbrechen'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _methodSection(
|
||||||
|
BuildContext context,
|
||||||
|
PaymentMethodsState state,
|
||||||
|
List<PaymentMethod> methods,
|
||||||
|
) {
|
||||||
|
if (state is PaymentMethodsFailed) {
|
||||||
|
return [
|
||||||
|
Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
color: Theme.of(context).colorScheme.errorContainer,
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(state.message),
|
||||||
|
trailing: TextButton.icon(
|
||||||
|
onPressed: () => context.read<PaymentMethodsCubit>().load(),
|
||||||
|
icon: const Icon(Icons.refresh),
|
||||||
|
label: const Text('Erneut laden'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (state is! PaymentMethodsLoaded) {
|
||||||
|
return const [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.all(16),
|
||||||
|
child: Center(child: CircularProgressIndicator()),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (methods.isEmpty) {
|
||||||
|
return const [Text('Keine Zahlungsmethoden hinterlegt.')];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
for (final m in methods)
|
||||||
|
_MethodCard(
|
||||||
|
method: m,
|
||||||
|
selected: m.id == _selectedId,
|
||||||
|
onTap: () => setState(() => _selectedId = m.id),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Der zu zahlende Betrag, bewusst sehr groß.
|
||||||
|
class _AmountBanner extends StatelessWidget {
|
||||||
|
const _AmountBanner({required this.openCents});
|
||||||
|
|
||||||
|
final int openCents;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final primary = theme.colorScheme.primary;
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 18, horizontal: 16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: primary.withValues(alpha: 0.08),
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
border: Border.all(color: primary.withValues(alpha: 0.35)),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text('Noch zu zahlen', style: theme.textTheme.titleSmall),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
child: Text(
|
||||||
|
formatEuroCents(openCents),
|
||||||
|
style: theme.textTheme.displayMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
color: primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MethodCard extends StatelessWidget {
|
||||||
|
const _MethodCard({
|
||||||
|
required this.method,
|
||||||
|
required this.selected,
|
||||||
|
required this.onTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
final PaymentMethod method;
|
||||||
|
final bool selected;
|
||||||
|
final VoidCallback onTap;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final scheme = Theme.of(context).colorScheme;
|
||||||
|
return Card(
|
||||||
|
margin: const EdgeInsets.only(bottom: 10),
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
elevation: selected ? 2 : 0,
|
||||||
|
color: selected ? scheme.primaryContainer : scheme.surface,
|
||||||
|
surfaceTintColor: Colors.transparent,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(14),
|
||||||
|
side: BorderSide(
|
||||||
|
color: selected ? scheme.primary : scheme.outlineVariant,
|
||||||
|
width: selected ? 2 : 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 18),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
paymentMethodIcon(method.code),
|
||||||
|
size: 30,
|
||||||
|
color: selected ? scheme.primary : scheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
method.name,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
selected ? Icons.radio_button_checked : Icons.radio_button_off,
|
||||||
|
color: selected ? scheme.primary : scheme.outline,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hinweis zur gewählten Methode. Bei EC-Karte groß die Kundennummer, die
|
||||||
|
/// der Fahrer am EC-Gerät eingeben muss.
|
||||||
|
class _MethodHint extends StatelessWidget {
|
||||||
|
const _MethodHint({required this.method, required this.customerNumber});
|
||||||
|
|
||||||
|
final PaymentMethod method;
|
||||||
|
final int customerNumber;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
if (method.code == 'ec_card') {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: theme.colorScheme.secondaryContainer,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Kundennummer am EC-Gerät eingeben',
|
||||||
|
style: theme.textTheme.titleSmall?.copyWith(
|
||||||
|
color: theme.colorScheme.onSecondaryContainer,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
child: SelectableText(
|
||||||
|
'$customerNumber',
|
||||||
|
style: theme.textTheme.displayMedium?.copyWith(
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
letterSpacing: 4,
|
||||||
|
fontFeatures: const [FontFeature.tabularFigures()],
|
||||||
|
color: theme.colorScheme.onSecondaryContainer,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final text = switch (method.code) {
|
||||||
|
'cash' => 'Betrag bar entgegennehmen und danach bestätigen.',
|
||||||
|
'invoice' =>
|
||||||
|
'Der Betrag wird per Rechnung beglichen. Es wird vor Ort '
|
||||||
|
'nichts kassiert.',
|
||||||
|
_ => 'Zahlung abwickeln und danach bestätigen.',
|
||||||
|
};
|
||||||
|
return Text(
|
||||||
|
text,
|
||||||
|
style: theme.textTheme.bodyMedium?.copyWith(
|
||||||
|
color: theme.colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// Fragt eine Pflicht-Begründung ab (z. B. für Pausieren/Abbrechen einer
|
||||||
|
/// Lieferung). Liefert den getrimmten Text oder `null` bei Abbruch.
|
||||||
|
Future<String?> showReasonDialog(BuildContext context, String title) async {
|
||||||
|
// Controller bewusst nicht disposen: Der Dialog nutzt ihn noch während
|
||||||
|
// der Schließ-Animation. Ohne Listener räumt der GC ihn ab.
|
||||||
|
final controller = TextEditingController();
|
||||||
|
return showDialog<String>(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(dialogContext) => AlertDialog(
|
||||||
|
title: Text(title),
|
||||||
|
content: TextField(
|
||||||
|
controller: controller,
|
||||||
|
autofocus: true,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Grund',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(dialogContext).pop(null),
|
||||||
|
child: const Text('Abbrechen'),
|
||||||
|
),
|
||||||
|
FilledButton(
|
||||||
|
onPressed: () {
|
||||||
|
final text = controller.text.trim();
|
||||||
|
if (text.isEmpty) return;
|
||||||
|
Navigator.of(dialogContext).pop(text);
|
||||||
|
},
|
||||||
|
child: const Text('Bestätigen'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -57,6 +57,154 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/belege/{belegnummer}": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"summary": "Liefert das **volle Detail-Paket** zu einer ERP-Belegnummer: die Lieferung\nmit Positionen (inkl. Scan-St\u00e4nden), Kunde + Ansprechpartner, referenzierte\nArtikel/Lager, Notizen, Geld-Gutschrift, Dienstleistungswerte und Kontakte \u2014\ndestilliert aus dem Tour-Aggregat. Jede Lieferung, unabh\u00e4ngig vom Status.\n`404`, wenn die Belegnummer unbekannt ist.",
|
||||||
|
"operationId": "belege_details",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "belegnummer",
|
||||||
|
"in": "path",
|
||||||
|
"description": "ERP-Belegnummer, z. B. V-30690291",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Volle Lieferdetails",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/DeliveryDetails"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Admin-API-Key fehlt/ung\u00fcltig"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Belegnummer unbekannt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"admin_api_key": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/admin/belege/{belegnummer}/positions-modified": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"summary": "Liefert zu **einer** ERP-Belegnummer, ob an der Lieferung Positionen\nver\u00e4ndert wurden (Menge reduziert/Zeile entfernt oder Geld-Gutschrift) \u2014\nunabh\u00e4ngig vom Zustand der Lieferung. `404`, wenn die Belegnummer unbekannt\nist. Gibt es mehrere Lieferungen mit derselben Belegnummer, ist das Flag\n`true`, sobald **eine** davon ver\u00e4ndert ist.",
|
||||||
|
"operationId": "positions_modified",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "belegnummer",
|
||||||
|
"in": "path",
|
||||||
|
"description": "ERP-Belegnummer, z. B. V-30690291",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "\u00c4nderungs-Flag der Belegpositionen",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/PositionsModifiedResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Admin-API-Key fehlt/ung\u00fcltig"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Belegnummer unbekannt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"admin_api_key": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/admin/completed-deliveries": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"summary": "Liefert **alle** abgeschlossenen (ausgelieferten) Lieferungen \u2014 optional auf\neinen Datumsbereich eingegrenzt, unabh\u00e4ngig vom Mail-Versand-Status.\nGefiltert wird \u00fcber den **Berliner** Kalendertag des Abschluss-Zeitpunkts\n(`completed_at`).",
|
||||||
|
"description": "Parameter (alle `DD-MM-YYYY`, alle optional): `day` = Einzeltag (Kurzform\n`from=to=day`), sonst `from`/`to` als **inklusive** Bereichsgrenzen (je\noffen). **Ohne jeden Parameter \u2192 ALLE ausgelieferten Belege** (kein\nDatumsfilter). Pro Lieferung: Belegnummer + `positions_modified` (Menge\nreduziert/Zeile entfernt oder Geld-Gutschrift). Die Halb-Grenzen-Variante ist\nf\u00fcr Range-Filter gedacht: `?from=\u2026` und `?to=\u2026` liefern je eine Menge, deren\nSQL-`AND`-Schnitt den Zeitraum ergibt.",
|
||||||
|
"operationId": "completed_deliveries",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "day",
|
||||||
|
"in": "query",
|
||||||
|
"description": "Einzeltag DD-MM-YYYY (Kurzform from=to)",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "from",
|
||||||
|
"in": "query",
|
||||||
|
"description": "Untere Grenze DD-MM-YYYY (inklusive)",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "to",
|
||||||
|
"in": "query",
|
||||||
|
"description": "Obere Grenze DD-MM-YYYY (inklusive)",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Ausgelieferte Lieferungen (optional bereichsgefiltert)",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/CompletedDeliveriesResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Ung\u00fcltiges Datum"
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Admin-API-Key fehlt/ung\u00fcltig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"admin_api_key": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/admin/delivered-belegnummern": {
|
"/admin/delivered-belegnummern": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -227,6 +375,87 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/admin/reviews": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"summary": "Listet alle ge\u00e4nderten Lieferscheine, die noch auf eine manuelle\nBest\u00e4tigung (Vier-Augen) warten \u2014 Entfernungen und/oder Geld-Gutschriften.",
|
||||||
|
"operationId": "list_reviews",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Offene Pr\u00fcfungen",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/PendingReviewResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Admin-API-Key fehlt/ung\u00fcltig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"admin_api_key": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/admin/reviews/{delivery_id}/resolve": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"admin"
|
||||||
|
],
|
||||||
|
"summary": "Best\u00e4tigt die Pr\u00fcfung einer ge\u00e4nderten Lieferung (Vier-Augen) \u2014 die\nLieferung verschwindet danach aus `GET /admin/reviews` (sofern nicht\nerneut ge\u00e4ndert).",
|
||||||
|
"operationId": "resolve_review",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "delivery_id",
|
||||||
|
"in": "path",
|
||||||
|
"description": "UUID der Lieferung",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/ResolveReviewRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"description": "Pr\u00fcfung best\u00e4tigt"
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Ung\u00fcltige delivery_id / Bearbeiter leer"
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Admin-API-Key fehlt/ung\u00fcltig"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Lieferung nicht gefunden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"admin_api_key": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/attachments/{id}": {
|
"/attachments/{id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -814,6 +1043,62 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/deliveries/{delivery_id}/payment": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"deliveries"
|
||||||
|
],
|
||||||
|
"summary": "Protokolliert die Zahlungsabwicklung (\u201eAbkassieren\") einer Lieferung.\nAppend-only, idempotent \u00fcber `clientEventId`. Der Server berechnet den\noffenen Betrag selbst; er muss > 0 sein und `expectedAmountCents`\nentsprechen. Nur bei aktiver Lieferung und aktiver Zahlungsmethode.",
|
||||||
|
"operationId": "record_payment",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "delivery_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/RecordDeliveryPaymentRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Zahlung protokolliert",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/DeliveryPaymentResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Lieferung nicht aktiv, Methode ung\u00fcltig, kein offener Betrag oder Betrag abweichend"
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Authentifizierung fehlgeschlagen"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Lieferung nicht gefunden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer_auth": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/deliveries/{delivery_id}/resume": {
|
"/deliveries/{delivery_id}/resume": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
@ -1129,16 +1414,27 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/me/tours/today": {
|
"/me/tours": {
|
||||||
"get": {
|
"get": {
|
||||||
"tags": [
|
"tags": [
|
||||||
"tours"
|
"tours"
|
||||||
],
|
],
|
||||||
"summary": "Listet heutige Touren des angemeldeten Fahrers (Filter aus dem JWT).",
|
"summary": "Listet die Touren des angemeldeten Fahrers (Filter aus dem JWT) f\u00fcr ein\nZiel-Datum. Ohne `?date=` gilt \u201eheute\". Der Fahrer w\u00e4hlt das Datum aktiv\nim Kopf-Kalender der App (z. B. um die Tour von morgen vorab zu sehen).",
|
||||||
"operationId": "list_my_tours_today",
|
"operationId": "list_my_tours",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "date",
|
||||||
|
"in": "query",
|
||||||
|
"description": "Ziel-Tourdatum YYYY-MM-DD (Default: heute)",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"description": "Liste der heutigen Touren",
|
"description": "Liste der Touren am Ziel-Datum",
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
@ -1147,6 +1443,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Ung\u00fcltiges Datum"
|
||||||
|
},
|
||||||
"401": {
|
"401": {
|
||||||
"description": "Authentifizierung fehlgeschlagen"
|
"description": "Authentifizierung fehlgeschlagen"
|
||||||
}
|
}
|
||||||
@ -1932,6 +2231,59 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"CompletedDeliveriesResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"count",
|
||||||
|
"deliveries"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"count": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Anzahl der abgeschlossenen Lieferungen im Bereich.",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"deliveries": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/CompletedDeliveryItem"
|
||||||
|
},
|
||||||
|
"description": "Die abgeschlossenen Lieferungen, aufsteigend nach Abschluss-Zeitpunkt."
|
||||||
|
},
|
||||||
|
"from": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"description": "Wirksame untere Grenze (ISO `YYYY-MM-DD`) oder `null` (offen)."
|
||||||
|
},
|
||||||
|
"to": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"description": "Wirksame obere Grenze (ISO `YYYY-MM-DD`) oder `null` (offen)."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"CompletedDeliveryItem": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Eine abgeschlossene Lieferung im Tagesabruf.",
|
||||||
|
"required": [
|
||||||
|
"belegnummer",
|
||||||
|
"positions_modified"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"belegnummer": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "ERP-Belegnummer der Lieferung."
|
||||||
|
},
|
||||||
|
"positions_modified": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "`true`, wenn an der Lieferung Positionen ver\u00e4ndert wurden \u2014 eine Zeile\nwurde entfernt oder in der Menge reduziert (St\u00fcck-Gutschrift) **oder** es\nliegt eine aktive Geld-Gutschrift vor."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ContactChannel": {
|
"ContactChannel": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Ein einzelner Kontaktkanal (Telefonnummer / Mobil / E-Mail / Web).\nMehrere pro [`ContactSource`] m\u00f6glich, die `position` h\u00e4lt die\n1-basierte ERP-Reihenfolge (`Telefon` \u2192 1, `Telefon2` \u2192 2 usw.) fest,\ndamit der \u201eprim\u00e4re\" Kanal je Art stabil identifizierbar bleibt.",
|
"description": "Ein einzelner Kontaktkanal (Telefonnummer / Mobil / E-Mail / Web).\nMehrere pro [`ContactSource`] m\u00f6glich, die `position` h\u00e4lt die\n1-basierte ERP-Reihenfolge (`Telefon` \u2192 1, `Telefon2` \u2192 2 usw.) fest,\ndamit der \u201eprim\u00e4re\" Kanal je Art stabil identifizierbar bleibt.",
|
||||||
@ -2421,6 +2773,120 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"DeliveryDetails": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"tour",
|
||||||
|
"delivery",
|
||||||
|
"customerContacts",
|
||||||
|
"articles",
|
||||||
|
"warehouses",
|
||||||
|
"notes",
|
||||||
|
"services",
|
||||||
|
"deliveryServices",
|
||||||
|
"contactSources",
|
||||||
|
"contactChannels"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"articles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Article"
|
||||||
|
},
|
||||||
|
"description": "Nur die von den Positionen referenzierten Artikel."
|
||||||
|
},
|
||||||
|
"contactChannels": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/ContactChannel"
|
||||||
|
},
|
||||||
|
"description": "Die zu `contactSources` geh\u00f6renden Einzel-Kan\u00e4le. Join per `sourceId`."
|
||||||
|
},
|
||||||
|
"contactSources": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/ContactSource"
|
||||||
|
},
|
||||||
|
"description": "Kontaktquellen der Lieferung (Liefer-/Rechnungsadresse, Ansprechpartner \u2026)."
|
||||||
|
},
|
||||||
|
"credit": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/DeliveryCredit",
|
||||||
|
"description": "Aktuelle Betrags-Gutschrift (`null`, wenn keine aktiv)."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"customer": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Customer",
|
||||||
|
"description": "Der Kunde der Lieferung (`null`, falls unauffindbar \u2014 sollte nicht\nvorkommen)."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"customerContacts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/CustomerContact"
|
||||||
|
},
|
||||||
|
"description": "Ansprechpartner des Kunden."
|
||||||
|
},
|
||||||
|
"delivery": {
|
||||||
|
"$ref": "#/components/schemas/DeliveryWithItems",
|
||||||
|
"description": "Die Lieferung selbst inkl. Positionen (mit Scan-St\u00e4nden) und `sortOrder`."
|
||||||
|
},
|
||||||
|
"deliveryServices": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/DeliveryServiceValue"
|
||||||
|
},
|
||||||
|
"description": "F\u00fcr diese Lieferung gesetzte Service-Werte."
|
||||||
|
},
|
||||||
|
"notes": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/DeliveryNote"
|
||||||
|
},
|
||||||
|
"description": "Notizen der Lieferung, aufsteigend nach `createdAt`."
|
||||||
|
},
|
||||||
|
"payment": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/DeliveryPayment",
|
||||||
|
"description": "J\u00fcngste protokollierte Zahlungsabwicklung (`None` = keine)."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"services": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Service"
|
||||||
|
},
|
||||||
|
"description": "Aktive Service-Definitionen (Stammdaten)."
|
||||||
|
},
|
||||||
|
"tour": {
|
||||||
|
"$ref": "#/components/schemas/Tour",
|
||||||
|
"description": "Die Tour, zu der die Lieferung geh\u00f6rt."
|
||||||
|
},
|
||||||
|
"warehouses": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/Warehouse"
|
||||||
|
},
|
||||||
|
"description": "Nur die von den Positionen referenzierten Lager."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"DeliveryItem": {
|
"DeliveryItem": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Einzelposition einer Lieferung. Vereint regul\u00e4re Belegzeilen und\nSt\u00fccklisten-Komponenten zu einer flachen Liste \u2014 die St\u00fccklisten-\nHierarchie ist ein ERP-Konstrukt und wird beim Sync aufgel\u00f6st.\n\n\u00dcber die Felder `belegzeilen_nr` und `komponenten_artikel_nr` bleibt\ndie ERP-Herkunft aufl\u00f6sbar.",
|
"description": "Einzelposition einer Lieferung. Vereint regul\u00e4re Belegzeilen und\nSt\u00fccklisten-Komponenten zu einer flachen Liste \u2014 die St\u00fccklisten-\nHierarchie ist ein ERP-Konstrukt und wird beim Sync aufgel\u00f6st.\n\n\u00dcber die Felder `belegzeilen_nr` und `komponenten_artikel_nr` bleibt\ndie ERP-Herkunft aufl\u00f6sbar.",
|
||||||
@ -2579,6 +3045,68 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"DeliveryPayment": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Protokollierte Zahlungsabwicklung (\u201eAbkassieren\") einer Lieferung.\n\nAppend-only: jede Best\u00e4tigung des Fahrers ist ein eigener Eintrag; im\nTour-Aggregat wird pro Lieferung nur der j\u00fcngste mitgeliefert. Der Betrag\nist der server-seitig berechnete offene Betrag zum Zeitpunkt der\nBest\u00e4tigung. Weicht der aktuelle offene Betrag davon ab (z. B. nach einer\nneuen Gutschrift), ist der Eintrag veraltet und muss erneuert werden.",
|
||||||
|
"required": [
|
||||||
|
"id",
|
||||||
|
"deliveryId",
|
||||||
|
"paymentMethodId",
|
||||||
|
"paymentMethodCode",
|
||||||
|
"amountCents",
|
||||||
|
"recordedByPersonalnummer",
|
||||||
|
"recordedAt"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"amountCents": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "Abgewickelter Betrag in Cent (offener Betrag bei Best\u00e4tigung)."
|
||||||
|
},
|
||||||
|
"deliveryId": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"paymentMethodCode": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Snapshot des Methoden-Codes (`cash`, `ec_card`, `invoice`, \u2026)."
|
||||||
|
},
|
||||||
|
"paymentMethodId": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"recordedAt": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"recordedByCarId": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"recordedByPersonalnummer": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DeliveryPaymentResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"payment"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"payment": {
|
||||||
|
"$ref": "#/components/schemas/DeliveryPayment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"DeliveryResponse": {
|
"DeliveryResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -2814,6 +3342,165 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"PendingReviewResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"delivery_id",
|
||||||
|
"erp_belegart_id",
|
||||||
|
"erp_belegnummer",
|
||||||
|
"customer_name",
|
||||||
|
"tour_date",
|
||||||
|
"last_change_at",
|
||||||
|
"credited_items",
|
||||||
|
"money_credit_cents"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"credited_items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/ReviewedItemResponse"
|
||||||
|
},
|
||||||
|
"description": "Entfernte/teil-gutgeschriebene Positionen."
|
||||||
|
},
|
||||||
|
"customer_name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"delivery_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"erp_belegart_id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
|
"erp_belegnummer": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"last_change_at": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Zeitpunkt der letzten beleg-\u00e4ndernden Aktion (RFC 3339)."
|
||||||
|
},
|
||||||
|
"money_credit_cents": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "Geld-Gutschrift in Cent (0 = keine)."
|
||||||
|
},
|
||||||
|
"money_credit_reason": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tour_date": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Tourdatum (ISO `YYYY-MM-DD`)."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PositionsModifiedResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"belegnummer",
|
||||||
|
"positions_modified"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"belegnummer": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "ERP-Belegnummer, nach der gefragt wurde."
|
||||||
|
},
|
||||||
|
"positions_modified": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "`true`, wenn an der Lieferung Positionen ver\u00e4ndert wurden \u2014 eine Zeile\nwurde entfernt oder in der Menge reduziert (St\u00fcck-Gutschrift) **oder** es\nliegt eine aktive Geld-Gutschrift vor."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"RecordDeliveryPaymentRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"clientEventId",
|
||||||
|
"paymentMethodId",
|
||||||
|
"expectedAmountCents"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"authorCarId": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uuid",
|
||||||
|
"description": "Fahrzeug des Akteurs (Audit-Spur). Muss zum Account geh\u00f6ren."
|
||||||
|
},
|
||||||
|
"clientEventId": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"description": "Idempotenz-Schl\u00fcssel \u2014 pro Best\u00e4tigung genau einmal vergeben."
|
||||||
|
},
|
||||||
|
"expectedAmountCents": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "Betrag in Cent, den der Fahrer in der App gesehen und best\u00e4tigt hat.\nDer Server berechnet den offenen Betrag selbst und lehnt ab, wenn er\ndavon abweicht \u2014 so landet nie ein Betrag im Protokoll, den der\nFahrer nicht gesehen hat."
|
||||||
|
},
|
||||||
|
"paymentMethodId": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid",
|
||||||
|
"description": "Gew\u00e4hlte Zahlungsmethode. Muss existieren und aktiv sein."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ResolveReviewRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"resolved_by"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"note": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"description": "Optionale Notiz zur getroffenen Entscheidung."
|
||||||
|
},
|
||||||
|
"resolved_by": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Bearbeiter (Name/K\u00fcrzel), der die Pr\u00fcfung best\u00e4tigt."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ReviewedItemResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"belegzeilen_nr",
|
||||||
|
"artikel_nr",
|
||||||
|
"article_name",
|
||||||
|
"required_quantity",
|
||||||
|
"credited_quantity"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"article_name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"artikel_nr": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"belegzeilen_nr": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"credited_quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"reason": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"required_quantity": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ScanEvent": {
|
"ScanEvent": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
@ -3416,6 +4103,7 @@
|
|||||||
"warehouses",
|
"warehouses",
|
||||||
"notes",
|
"notes",
|
||||||
"credits",
|
"credits",
|
||||||
|
"payments",
|
||||||
"services",
|
"services",
|
||||||
"deliveryServices",
|
"deliveryServices",
|
||||||
"contactSources",
|
"contactSources",
|
||||||
@ -3481,6 +4169,13 @@
|
|||||||
},
|
},
|
||||||
"description": "Alle Notizen aller Lieferungen dieser Tour, in einer Liste.\nDie App joint clientseitig per `delivery_id`. Reihenfolge:\npro Lieferung aufsteigend nach `created_at`."
|
"description": "Alle Notizen aller Lieferungen dieser Tour, in einer Liste.\nDie App joint clientseitig per `delivery_id`. Reihenfolge:\npro Lieferung aufsteigend nach `created_at`."
|
||||||
},
|
},
|
||||||
|
"payments": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/DeliveryPayment"
|
||||||
|
},
|
||||||
|
"description": "J\u00fcngste protokollierte Zahlungsabwicklung pro Lieferung (nur\nLieferungen mit mindestens einem Eintrag). Join per `delivery_id`."
|
||||||
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
|||||||
@ -17,6 +17,8 @@ doc/CarResponse.md
|
|||||||
doc/CarsApi.md
|
doc/CarsApi.md
|
||||||
doc/CarsList.md
|
doc/CarsList.md
|
||||||
doc/CompleteDeliveryAcknowledgements.md
|
doc/CompleteDeliveryAcknowledgements.md
|
||||||
|
doc/CompletedDeliveriesResponse.md
|
||||||
|
doc/CompletedDeliveryItem.md
|
||||||
doc/ContactChannel.md
|
doc/ContactChannel.md
|
||||||
doc/ContactKind.md
|
doc/ContactKind.md
|
||||||
doc/ContactRole.md
|
doc/ContactRole.md
|
||||||
@ -34,10 +36,13 @@ doc/Delivery.md
|
|||||||
doc/DeliveryCredit.md
|
doc/DeliveryCredit.md
|
||||||
doc/DeliveryCreditEventRequest.md
|
doc/DeliveryCreditEventRequest.md
|
||||||
doc/DeliveryCreditResponse.md
|
doc/DeliveryCreditResponse.md
|
||||||
|
doc/DeliveryDetails.md
|
||||||
doc/DeliveryItem.md
|
doc/DeliveryItem.md
|
||||||
doc/DeliveryNote.md
|
doc/DeliveryNote.md
|
||||||
doc/DeliveryNoteResponse.md
|
doc/DeliveryNoteResponse.md
|
||||||
doc/DeliveryOrderEntry.md
|
doc/DeliveryOrderEntry.md
|
||||||
|
doc/DeliveryPayment.md
|
||||||
|
doc/DeliveryPaymentResponse.md
|
||||||
doc/DeliveryResponse.md
|
doc/DeliveryResponse.md
|
||||||
doc/DeliveryServiceResponse.md
|
doc/DeliveryServiceResponse.md
|
||||||
doc/DeliveryServiceValue.md
|
doc/DeliveryServiceValue.md
|
||||||
@ -52,6 +57,11 @@ doc/PaymentMethod.md
|
|||||||
doc/PaymentMethodResponse.md
|
doc/PaymentMethodResponse.md
|
||||||
doc/PaymentMethodsApi.md
|
doc/PaymentMethodsApi.md
|
||||||
doc/PaymentMethodsList.md
|
doc/PaymentMethodsList.md
|
||||||
|
doc/PendingReviewResponse.md
|
||||||
|
doc/PositionsModifiedResponse.md
|
||||||
|
doc/RecordDeliveryPaymentRequest.md
|
||||||
|
doc/ResolveReviewRequest.md
|
||||||
|
doc/ReviewedItemResponse.md
|
||||||
doc/ScanEvent.md
|
doc/ScanEvent.md
|
||||||
doc/ScanResult.md
|
doc/ScanResult.md
|
||||||
doc/ScanResultStatus.md
|
doc/ScanResultStatus.md
|
||||||
@ -115,6 +125,8 @@ lib/src/model/car.dart
|
|||||||
lib/src/model/car_response.dart
|
lib/src/model/car_response.dart
|
||||||
lib/src/model/cars_list.dart
|
lib/src/model/cars_list.dart
|
||||||
lib/src/model/complete_delivery_acknowledgements.dart
|
lib/src/model/complete_delivery_acknowledgements.dart
|
||||||
|
lib/src/model/completed_deliveries_response.dart
|
||||||
|
lib/src/model/completed_delivery_item.dart
|
||||||
lib/src/model/contact_channel.dart
|
lib/src/model/contact_channel.dart
|
||||||
lib/src/model/contact_kind.dart
|
lib/src/model/contact_kind.dart
|
||||||
lib/src/model/contact_role.dart
|
lib/src/model/contact_role.dart
|
||||||
@ -132,10 +144,13 @@ lib/src/model/delivery.dart
|
|||||||
lib/src/model/delivery_credit.dart
|
lib/src/model/delivery_credit.dart
|
||||||
lib/src/model/delivery_credit_event_request.dart
|
lib/src/model/delivery_credit_event_request.dart
|
||||||
lib/src/model/delivery_credit_response.dart
|
lib/src/model/delivery_credit_response.dart
|
||||||
|
lib/src/model/delivery_details.dart
|
||||||
lib/src/model/delivery_item.dart
|
lib/src/model/delivery_item.dart
|
||||||
lib/src/model/delivery_note.dart
|
lib/src/model/delivery_note.dart
|
||||||
lib/src/model/delivery_note_response.dart
|
lib/src/model/delivery_note_response.dart
|
||||||
lib/src/model/delivery_order_entry.dart
|
lib/src/model/delivery_order_entry.dart
|
||||||
|
lib/src/model/delivery_payment.dart
|
||||||
|
lib/src/model/delivery_payment_response.dart
|
||||||
lib/src/model/delivery_response.dart
|
lib/src/model/delivery_response.dart
|
||||||
lib/src/model/delivery_service_response.dart
|
lib/src/model/delivery_service_response.dart
|
||||||
lib/src/model/delivery_service_value.dart
|
lib/src/model/delivery_service_value.dart
|
||||||
@ -148,6 +163,11 @@ lib/src/model/mark_mail_sent_response.dart
|
|||||||
lib/src/model/payment_method.dart
|
lib/src/model/payment_method.dart
|
||||||
lib/src/model/payment_method_response.dart
|
lib/src/model/payment_method_response.dart
|
||||||
lib/src/model/payment_methods_list.dart
|
lib/src/model/payment_methods_list.dart
|
||||||
|
lib/src/model/pending_review_response.dart
|
||||||
|
lib/src/model/positions_modified_response.dart
|
||||||
|
lib/src/model/record_delivery_payment_request.dart
|
||||||
|
lib/src/model/resolve_review_request.dart
|
||||||
|
lib/src/model/reviewed_item_response.dart
|
||||||
lib/src/model/scan_event.dart
|
lib/src/model/scan_event.dart
|
||||||
lib/src/model/scan_result.dart
|
lib/src/model/scan_result.dart
|
||||||
lib/src/model/scan_result_status.dart
|
lib/src/model/scan_result_status.dart
|
||||||
@ -177,12 +197,13 @@ lib/src/model/update_service_request.dart
|
|||||||
lib/src/model/warehouse.dart
|
lib/src/model/warehouse.dart
|
||||||
lib/src/serializers.dart
|
lib/src/serializers.dart
|
||||||
pubspec.yaml
|
pubspec.yaml
|
||||||
test/contact_channel_test.dart
|
test/completed_deliveries_response_test.dart
|
||||||
test/contact_kind_test.dart
|
test/completed_delivery_item_test.dart
|
||||||
test/contact_role_test.dart
|
test/delivery_details_test.dart
|
||||||
test/contact_source_test.dart
|
test/delivery_payment_response_test.dart
|
||||||
test/delivered_belegnummern_response_test.dart
|
test/delivery_payment_test.dart
|
||||||
test/mark_mail_sent_request_test.dart
|
test/pending_review_response_test.dart
|
||||||
test/mark_mail_sent_response_test.dart
|
test/positions_modified_response_test.dart
|
||||||
test/sync_contact_channel_test.dart
|
test/record_delivery_payment_request_test.dart
|
||||||
test/sync_contact_source_test.dart
|
test/resolve_review_request_test.dart
|
||||||
|
test/reviewed_item_response_test.dart
|
||||||
|
|||||||
@ -66,10 +66,15 @@ All URIs are relative to *http://localhost*
|
|||||||
Class | Method | HTTP request | Description
|
Class | Method | HTTP request | Description
|
||||||
------------ | ------------- | ------------- | -------------
|
------------ | ------------- | ------------- | -------------
|
||||||
[*AccountsApi*](doc/AccountsApi.md) | [**getAccount**](doc/AccountsApi.md#getaccount) | **GET** /accounts/{personalnummer} | Liest den Account zu einer Personalnummer.
|
[*AccountsApi*](doc/AccountsApi.md) | [**getAccount**](doc/AccountsApi.md#getaccount) | **GET** /accounts/{personalnummer} | Liest den Account zu einer Personalnummer.
|
||||||
|
[*AdminApi*](doc/AdminApi.md) | [**belegeDetails**](doc/AdminApi.md#belegedetails) | **GET** /admin/belege/{belegnummer} | Liefert das **volle Detail-Paket** zu einer ERP-Belegnummer: die Lieferung mit Positionen (inkl. Scan-Ständen), Kunde + Ansprechpartner, referenzierte Artikel/Lager, Notizen, Geld-Gutschrift, Dienstleistungswerte und Kontakte — destilliert aus dem Tour-Aggregat. Jede Lieferung, unabhängig vom Status. `404`, wenn die Belegnummer unbekannt ist.
|
||||||
|
[*AdminApi*](doc/AdminApi.md) | [**completedDeliveries**](doc/AdminApi.md#completeddeliveries) | **GET** /admin/completed-deliveries | Liefert **alle** abgeschlossenen (ausgelieferten) Lieferungen — optional auf einen Datumsbereich eingegrenzt, unabhängig vom Mail-Versand-Status. Gefiltert wird über den **Berliner** Kalendertag des Abschluss-Zeitpunkts (`completed_at`).
|
||||||
[*AdminApi*](doc/AdminApi.md) | [**deliveredBelegnummern**](doc/AdminApi.md#deliveredbelegnummern) | **GET** /admin/delivered-belegnummern | Liefert die Belegnummern ausgelieferter (abgeschlossener) Lieferungen, **deren Liefermail noch nicht versendet wurde** (`mail_sent_at IS NULL`). „Ausgeliefert\" = es existiert ein Abschluss. Mit `day` (DD-MM-YYYY) nur Abschlüsse dieses Berliner Kalendertages; **ohne `day` alle offenen** (über alle Tage) — so bleiben Belege über Mitternacht nicht hängen.
|
[*AdminApi*](doc/AdminApi.md) | [**deliveredBelegnummern**](doc/AdminApi.md#deliveredbelegnummern) | **GET** /admin/delivered-belegnummern | Liefert die Belegnummern ausgelieferter (abgeschlossener) Lieferungen, **deren Liefermail noch nicht versendet wurde** (`mail_sent_at IS NULL`). „Ausgeliefert\" = es existiert ein Abschluss. Mit `day` (DD-MM-YYYY) nur Abschlüsse dieses Berliner Kalendertages; **ohne `day` alle offenen** (über alle Tage) — so bleiben Belege über Mitternacht nicht hängen.
|
||||||
[*AdminApi*](doc/AdminApi.md) | [**importErp**](doc/AdminApi.md#importerp) | **POST** /admin/import-erp | Stößt den ERP-Import für ein Datum an und liefert die Zusammenfassung.
|
[*AdminApi*](doc/AdminApi.md) | [**importErp**](doc/AdminApi.md#importerp) | **POST** /admin/import-erp | Stößt den ERP-Import für ein Datum an und liefert die Zusammenfassung.
|
||||||
|
[*AdminApi*](doc/AdminApi.md) | [**listReviews**](doc/AdminApi.md#listreviews) | **GET** /admin/reviews | Listet alle geänderten Lieferscheine, die noch auf eine manuelle Bestätigung (Vier-Augen) warten — Entfernungen und/oder Geld-Gutschriften.
|
||||||
[*AdminApi*](doc/AdminApi.md) | [**markMailSent**](doc/AdminApi.md#markmailsent) | **POST** /admin/mark-mail-sent | Markiert die Liefermails der angegebenen Belegnummern als **versendet** (`mail_sent_at = now()`, nur wo noch offen). Vom Mailclient aufzurufen, NACHDEM ERPframe die Mails erfolgreich verschickt hat — danach erscheinen die Belege nicht mehr in `GET /admin/delivered-belegnummern`.
|
[*AdminApi*](doc/AdminApi.md) | [**markMailSent**](doc/AdminApi.md#markmailsent) | **POST** /admin/mark-mail-sent | Markiert die Liefermails der angegebenen Belegnummern als **versendet** (`mail_sent_at = now()`, nur wo noch offen). Vom Mailclient aufzurufen, NACHDEM ERPframe die Mails erfolgreich verschickt hat — danach erscheinen die Belege nicht mehr in `GET /admin/delivered-belegnummern`.
|
||||||
|
[*AdminApi*](doc/AdminApi.md) | [**positionsModified**](doc/AdminApi.md#positionsmodified) | **GET** /admin/belege/{belegnummer}/positions-modified | Liefert zu **einer** ERP-Belegnummer, ob an der Lieferung Positionen verändert wurden (Menge reduziert/Zeile entfernt oder Geld-Gutschrift) — unabhängig vom Zustand der Lieferung. `404`, wenn die Belegnummer unbekannt ist. Gibt es mehrere Lieferungen mit derselben Belegnummer, ist das Flag `true`, sobald **eine** davon verändert ist.
|
||||||
[*AdminApi*](doc/AdminApi.md) | [**pushCompletion**](doc/AdminApi.md#pushcompletion) | **POST** /admin/push-completion | Stößt das ERP-Rückschreiben eines bereits lokal abgeschlossenen Lieferabschlusses erneut an (idempotenter Retry, falls der automatische Push beim Abschluss fehlschlug).
|
[*AdminApi*](doc/AdminApi.md) | [**pushCompletion**](doc/AdminApi.md#pushcompletion) | **POST** /admin/push-completion | Stößt das ERP-Rückschreiben eines bereits lokal abgeschlossenen Lieferabschlusses erneut an (idempotenter Retry, falls der automatische Push beim Abschluss fehlschlug).
|
||||||
|
[*AdminApi*](doc/AdminApi.md) | [**resolveReview**](doc/AdminApi.md#resolvereview) | **POST** /admin/reviews/{delivery_id}/resolve | Bestätigt die Prüfung einer geänderten Lieferung (Vier-Augen) — die Lieferung verschwindet danach aus `GET /admin/reviews` (sofern nicht erneut geändert).
|
||||||
[*AttachmentsApi*](doc/AttachmentsApi.md) | [**getAttachment**](doc/AttachmentsApi.md#getattachment) | **GET** /attachments/{id} | Liefert ein gerendertes Vorschaubild des Attachments (Bytes), geladen aus DOCUframe. Auflösung/Format über Query-Parameter steuerbar (`?w=&h=&q=&ext=&page=`).
|
[*AttachmentsApi*](doc/AttachmentsApi.md) | [**getAttachment**](doc/AttachmentsApi.md#getattachment) | **GET** /attachments/{id} | Liefert ein gerendertes Vorschaubild des Attachments (Bytes), geladen aus DOCUframe. Auflösung/Format über Query-Parameter steuerbar (`?w=&h=&q=&ext=&page=`).
|
||||||
[*CarsApi*](doc/CarsApi.md) | [**createMyCar**](doc/CarsApi.md#createmycar) | **POST** /me/cars | Legt ein neues Fahrzeug für den angemeldeten Fahrer an.
|
[*CarsApi*](doc/CarsApi.md) | [**createMyCar**](doc/CarsApi.md#createmycar) | **POST** /me/cars | Legt ein neues Fahrzeug für den angemeldeten Fahrer an.
|
||||||
[*CarsApi*](doc/CarsApi.md) | [**listMyCars**](doc/CarsApi.md#listmycars) | **GET** /me/cars | Listet die Fahrzeuge des angemeldeten Fahrers.
|
[*CarsApi*](doc/CarsApi.md) | [**listMyCars**](doc/CarsApi.md#listmycars) | **GET** /me/cars | Listet die Fahrzeuge des angemeldeten Fahrers.
|
||||||
@ -82,6 +87,7 @@ Class | Method | HTTP request | Description
|
|||||||
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**deleteNote**](doc/DeliveriesApi.md#deletenote) | **DELETE** /deliveries/{delivery_id}/notes/{note_id} | Löscht eine Notiz. Antwortet mit `204 No Content`.
|
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**deleteNote**](doc/DeliveriesApi.md#deletenote) | **DELETE** /deliveries/{delivery_id}/notes/{note_id} | Löscht eine Notiz. Antwortet mit `204 No Content`.
|
||||||
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**deleteServiceValue**](doc/DeliveriesApi.md#deleteservicevalue) | **DELETE** /deliveries/{delivery_id}/services/{service_id} | Entfernt den Service-Wert einer Lieferung (Service „nicht gesetzt\"). Nur bei aktiver Lieferung. Antwort `204`.
|
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**deleteServiceValue**](doc/DeliveriesApi.md#deleteservicevalue) | **DELETE** /deliveries/{delivery_id}/services/{service_id} | Entfernt den Service-Wert einer Lieferung (Service „nicht gesetzt\"). Nur bei aktiver Lieferung. Antwort `204`.
|
||||||
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**hold**](doc/DeliveriesApi.md#hold) | **POST** /deliveries/{delivery_id}/hold | Setzt die Lieferung auf `held`. Nur aus `active` zulässig.
|
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**hold**](doc/DeliveriesApi.md#hold) | **POST** /deliveries/{delivery_id}/hold | Setzt die Lieferung auf `held`. Nur aus `active` zulässig.
|
||||||
|
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**recordPayment**](doc/DeliveriesApi.md#recordpayment) | **POST** /deliveries/{delivery_id}/payment | Protokolliert die Zahlungsabwicklung („Abkassieren\") einer Lieferung. Append-only, idempotent über `clientEventId`. Der Server berechnet den offenen Betrag selbst; er muss > 0 sein und `expectedAmountCents` entsprechen. Nur bei aktiver Lieferung und aktiver Zahlungsmethode.
|
||||||
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**resume**](doc/DeliveriesApi.md#resume) | **POST** /deliveries/{delivery_id}/resume | Setzt die Lieferung zurück auf `active`. Nur aus `held` zulässig.
|
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**resume**](doc/DeliveriesApi.md#resume) | **POST** /deliveries/{delivery_id}/resume | Setzt die Lieferung zurück auf `active`. Nur aus `held` zulässig.
|
||||||
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**setService**](doc/DeliveriesApi.md#setservice) | **PUT** /deliveries/{delivery_id}/services/{service_id} | Setzt (Upsert) den Wert eines Service für eine Lieferung. Genau das zum Service-Typ passende Feld (`boolValue`/`numericValue`) muss gesetzt sein; numerische Werte werden gegen min/max geprüft. Nur bei aktiver Lieferung.
|
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**setService**](doc/DeliveriesApi.md#setservice) | **PUT** /deliveries/{delivery_id}/services/{service_id} | Setzt (Upsert) den Wert eines Service für eine Lieferung. Genau das zum Service-Typ passende Feld (`boolValue`/`numericValue`) muss gesetzt sein; numerische Werte werden gegen min/max geprüft. Nur bei aktiver Lieferung.
|
||||||
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**updateNote**](doc/DeliveriesApi.md#updatenote) | **PATCH** /deliveries/{delivery_id}/notes/{note_id} | Ändert Text/Bild einer Notiz. Innerhalb des (geteilten) Accounts darf jeder Fahrer Notizen pflegen — kein Autor-Check. `delivery_id` ist Teil des Pfads (REST-Konsistenz), die Notiz wird über `note_id` adressiert.
|
[*DeliveriesApi*](doc/DeliveriesApi.md) | [**updateNote**](doc/DeliveriesApi.md#updatenote) | **PATCH** /deliveries/{delivery_id}/notes/{note_id} | Ändert Text/Bild einer Notiz. Innerhalb des (geteilten) Accounts darf jeder Fahrer Notizen pflegen — kein Autor-Check. `delivery_id` ist Teil des Pfads (REST-Konsistenz), die Notiz wird über `note_id` adressiert.
|
||||||
@ -98,7 +104,7 @@ Class | Method | HTTP request | Description
|
|||||||
[*ServicesApi*](doc/ServicesApi.md) | [**updateService**](doc/ServicesApi.md#updateservice) | **PATCH** /services/{id} | Patcht Name/Grenzen/Aktiv-Flag/Sortierung. `kind` ist nicht änderbar.
|
[*ServicesApi*](doc/ServicesApi.md) | [**updateService**](doc/ServicesApi.md#updateservice) | **PATCH** /services/{id} | Patcht Name/Grenzen/Aktiv-Flag/Sortierung. `kind` ist nicht änderbar.
|
||||||
[*SyncApi*](doc/SyncApi.md) | [**syncTour**](doc/SyncApi.md#synctour) | **POST** /sync/tour | Sync-Endpoint für das ERP: legt eine Tagestour samt Lieferungen und Positionen idempotent an. Identität pro Tour `(driver_personalnummer, tour_date)`, pro Lieferung `(belegart_id, belegnummer)`.
|
[*SyncApi*](doc/SyncApi.md) | [**syncTour**](doc/SyncApi.md#synctour) | **POST** /sync/tour | Sync-Endpoint für das ERP: legt eine Tagestour samt Lieferungen und Positionen idempotent an. Identität pro Tour `(driver_personalnummer, tour_date)`, pro Lieferung `(belegart_id, belegnummer)`.
|
||||||
[*ToursApi*](doc/ToursApi.md) | [**getTour**](doc/ToursApi.md#gettour) | **GET** /tours/{tour_id} | Lädt eine Tour mit allen Lieferungen, Positionen und referenzierten Stammdaten — die App nutzt das als einzigen großen Read.
|
[*ToursApi*](doc/ToursApi.md) | [**getTour**](doc/ToursApi.md#gettour) | **GET** /tours/{tour_id} | Lädt eine Tour mit allen Lieferungen, Positionen und referenzierten Stammdaten — die App nutzt das als einzigen großen Read.
|
||||||
[*ToursApi*](doc/ToursApi.md) | [**listMyToursToday**](doc/ToursApi.md#listmytourstoday) | **GET** /me/tours/today | Listet heutige Touren des angemeldeten Fahrers (Filter aus dem JWT).
|
[*ToursApi*](doc/ToursApi.md) | [**listMyTours**](doc/ToursApi.md#listmytours) | **GET** /me/tours | Listet die Touren des angemeldeten Fahrers (Filter aus dem JWT) für ein Ziel-Datum. Ohne `?date=` gilt „heute\". Der Fahrer wählt das Datum aktiv im Kopf-Kalender der App (z. B. um die Tour von morgen vorab zu sehen).
|
||||||
[*ToursApi*](doc/ToursApi.md) | [**setDeliveryOrder**](doc/ToursApi.md#setdeliveryorder) | **PUT** /tours/{tour_id}/delivery-order | Schreibt die Sortier-Reihenfolge aller Lieferungen einer Tour neu. Der Client schickt die **vollständige** neue Reihenfolge; fehlende oder fremde Lieferungs-Ids werden mit `400 validation` abgelehnt.
|
[*ToursApi*](doc/ToursApi.md) | [**setDeliveryOrder**](doc/ToursApi.md#setdeliveryorder) | **PUT** /tours/{tour_id}/delivery-order | Schreibt die Sortier-Reihenfolge aller Lieferungen einer Tour neu. Der Client schickt die **vollständige** neue Reihenfolge; fehlende oder fremde Lieferungs-Ids werden mit `400 validation` abgelehnt.
|
||||||
|
|
||||||
|
|
||||||
@ -116,6 +122,8 @@ Class | Method | HTTP request | Description
|
|||||||
- [CarResponse](doc/CarResponse.md)
|
- [CarResponse](doc/CarResponse.md)
|
||||||
- [CarsList](doc/CarsList.md)
|
- [CarsList](doc/CarsList.md)
|
||||||
- [CompleteDeliveryAcknowledgements](doc/CompleteDeliveryAcknowledgements.md)
|
- [CompleteDeliveryAcknowledgements](doc/CompleteDeliveryAcknowledgements.md)
|
||||||
|
- [CompletedDeliveriesResponse](doc/CompletedDeliveriesResponse.md)
|
||||||
|
- [CompletedDeliveryItem](doc/CompletedDeliveryItem.md)
|
||||||
- [ContactChannel](doc/ContactChannel.md)
|
- [ContactChannel](doc/ContactChannel.md)
|
||||||
- [ContactKind](doc/ContactKind.md)
|
- [ContactKind](doc/ContactKind.md)
|
||||||
- [ContactRole](doc/ContactRole.md)
|
- [ContactRole](doc/ContactRole.md)
|
||||||
@ -132,10 +140,13 @@ Class | Method | HTTP request | Description
|
|||||||
- [DeliveryCredit](doc/DeliveryCredit.md)
|
- [DeliveryCredit](doc/DeliveryCredit.md)
|
||||||
- [DeliveryCreditEventRequest](doc/DeliveryCreditEventRequest.md)
|
- [DeliveryCreditEventRequest](doc/DeliveryCreditEventRequest.md)
|
||||||
- [DeliveryCreditResponse](doc/DeliveryCreditResponse.md)
|
- [DeliveryCreditResponse](doc/DeliveryCreditResponse.md)
|
||||||
|
- [DeliveryDetails](doc/DeliveryDetails.md)
|
||||||
- [DeliveryItem](doc/DeliveryItem.md)
|
- [DeliveryItem](doc/DeliveryItem.md)
|
||||||
- [DeliveryNote](doc/DeliveryNote.md)
|
- [DeliveryNote](doc/DeliveryNote.md)
|
||||||
- [DeliveryNoteResponse](doc/DeliveryNoteResponse.md)
|
- [DeliveryNoteResponse](doc/DeliveryNoteResponse.md)
|
||||||
- [DeliveryOrderEntry](doc/DeliveryOrderEntry.md)
|
- [DeliveryOrderEntry](doc/DeliveryOrderEntry.md)
|
||||||
|
- [DeliveryPayment](doc/DeliveryPayment.md)
|
||||||
|
- [DeliveryPaymentResponse](doc/DeliveryPaymentResponse.md)
|
||||||
- [DeliveryResponse](doc/DeliveryResponse.md)
|
- [DeliveryResponse](doc/DeliveryResponse.md)
|
||||||
- [DeliveryServiceResponse](doc/DeliveryServiceResponse.md)
|
- [DeliveryServiceResponse](doc/DeliveryServiceResponse.md)
|
||||||
- [DeliveryServiceValue](doc/DeliveryServiceValue.md)
|
- [DeliveryServiceValue](doc/DeliveryServiceValue.md)
|
||||||
@ -148,6 +159,11 @@ Class | Method | HTTP request | Description
|
|||||||
- [PaymentMethod](doc/PaymentMethod.md)
|
- [PaymentMethod](doc/PaymentMethod.md)
|
||||||
- [PaymentMethodResponse](doc/PaymentMethodResponse.md)
|
- [PaymentMethodResponse](doc/PaymentMethodResponse.md)
|
||||||
- [PaymentMethodsList](doc/PaymentMethodsList.md)
|
- [PaymentMethodsList](doc/PaymentMethodsList.md)
|
||||||
|
- [PendingReviewResponse](doc/PendingReviewResponse.md)
|
||||||
|
- [PositionsModifiedResponse](doc/PositionsModifiedResponse.md)
|
||||||
|
- [RecordDeliveryPaymentRequest](doc/RecordDeliveryPaymentRequest.md)
|
||||||
|
- [ResolveReviewRequest](doc/ResolveReviewRequest.md)
|
||||||
|
- [ReviewedItemResponse](doc/ReviewedItemResponse.md)
|
||||||
- [ScanEvent](doc/ScanEvent.md)
|
- [ScanEvent](doc/ScanEvent.md)
|
||||||
- [ScanResult](doc/ScanResult.md)
|
- [ScanResult](doc/ScanResult.md)
|
||||||
- [ScanResultStatus](doc/ScanResultStatus.md)
|
- [ScanResultStatus](doc/ScanResultStatus.md)
|
||||||
|
|||||||
@ -9,12 +9,113 @@ All URIs are relative to *http://localhost*
|
|||||||
|
|
||||||
Method | HTTP request | Description
|
Method | HTTP request | Description
|
||||||
------------- | ------------- | -------------
|
------------- | ------------- | -------------
|
||||||
|
[**belegeDetails**](AdminApi.md#belegedetails) | **GET** /admin/belege/{belegnummer} | Liefert das **volle Detail-Paket** zu einer ERP-Belegnummer: die Lieferung mit Positionen (inkl. Scan-Ständen), Kunde + Ansprechpartner, referenzierte Artikel/Lager, Notizen, Geld-Gutschrift, Dienstleistungswerte und Kontakte — destilliert aus dem Tour-Aggregat. Jede Lieferung, unabhängig vom Status. `404`, wenn die Belegnummer unbekannt ist.
|
||||||
|
[**completedDeliveries**](AdminApi.md#completeddeliveries) | **GET** /admin/completed-deliveries | Liefert **alle** abgeschlossenen (ausgelieferten) Lieferungen — optional auf einen Datumsbereich eingegrenzt, unabhängig vom Mail-Versand-Status. Gefiltert wird über den **Berliner** Kalendertag des Abschluss-Zeitpunkts (`completed_at`).
|
||||||
[**deliveredBelegnummern**](AdminApi.md#deliveredbelegnummern) | **GET** /admin/delivered-belegnummern | Liefert die Belegnummern ausgelieferter (abgeschlossener) Lieferungen, **deren Liefermail noch nicht versendet wurde** (`mail_sent_at IS NULL`). „Ausgeliefert\" = es existiert ein Abschluss. Mit `day` (DD-MM-YYYY) nur Abschlüsse dieses Berliner Kalendertages; **ohne `day` alle offenen** (über alle Tage) — so bleiben Belege über Mitternacht nicht hängen.
|
[**deliveredBelegnummern**](AdminApi.md#deliveredbelegnummern) | **GET** /admin/delivered-belegnummern | Liefert die Belegnummern ausgelieferter (abgeschlossener) Lieferungen, **deren Liefermail noch nicht versendet wurde** (`mail_sent_at IS NULL`). „Ausgeliefert\" = es existiert ein Abschluss. Mit `day` (DD-MM-YYYY) nur Abschlüsse dieses Berliner Kalendertages; **ohne `day` alle offenen** (über alle Tage) — so bleiben Belege über Mitternacht nicht hängen.
|
||||||
[**importErp**](AdminApi.md#importerp) | **POST** /admin/import-erp | Stößt den ERP-Import für ein Datum an und liefert die Zusammenfassung.
|
[**importErp**](AdminApi.md#importerp) | **POST** /admin/import-erp | Stößt den ERP-Import für ein Datum an und liefert die Zusammenfassung.
|
||||||
|
[**listReviews**](AdminApi.md#listreviews) | **GET** /admin/reviews | Listet alle geänderten Lieferscheine, die noch auf eine manuelle Bestätigung (Vier-Augen) warten — Entfernungen und/oder Geld-Gutschriften.
|
||||||
[**markMailSent**](AdminApi.md#markmailsent) | **POST** /admin/mark-mail-sent | Markiert die Liefermails der angegebenen Belegnummern als **versendet** (`mail_sent_at = now()`, nur wo noch offen). Vom Mailclient aufzurufen, NACHDEM ERPframe die Mails erfolgreich verschickt hat — danach erscheinen die Belege nicht mehr in `GET /admin/delivered-belegnummern`.
|
[**markMailSent**](AdminApi.md#markmailsent) | **POST** /admin/mark-mail-sent | Markiert die Liefermails der angegebenen Belegnummern als **versendet** (`mail_sent_at = now()`, nur wo noch offen). Vom Mailclient aufzurufen, NACHDEM ERPframe die Mails erfolgreich verschickt hat — danach erscheinen die Belege nicht mehr in `GET /admin/delivered-belegnummern`.
|
||||||
|
[**positionsModified**](AdminApi.md#positionsmodified) | **GET** /admin/belege/{belegnummer}/positions-modified | Liefert zu **einer** ERP-Belegnummer, ob an der Lieferung Positionen verändert wurden (Menge reduziert/Zeile entfernt oder Geld-Gutschrift) — unabhängig vom Zustand der Lieferung. `404`, wenn die Belegnummer unbekannt ist. Gibt es mehrere Lieferungen mit derselben Belegnummer, ist das Flag `true`, sobald **eine** davon verändert ist.
|
||||||
[**pushCompletion**](AdminApi.md#pushcompletion) | **POST** /admin/push-completion | Stößt das ERP-Rückschreiben eines bereits lokal abgeschlossenen Lieferabschlusses erneut an (idempotenter Retry, falls der automatische Push beim Abschluss fehlschlug).
|
[**pushCompletion**](AdminApi.md#pushcompletion) | **POST** /admin/push-completion | Stößt das ERP-Rückschreiben eines bereits lokal abgeschlossenen Lieferabschlusses erneut an (idempotenter Retry, falls der automatische Push beim Abschluss fehlschlug).
|
||||||
|
[**resolveReview**](AdminApi.md#resolvereview) | **POST** /admin/reviews/{delivery_id}/resolve | Bestätigt die Prüfung einer geänderten Lieferung (Vier-Augen) — die Lieferung verschwindet danach aus `GET /admin/reviews` (sofern nicht erneut geändert).
|
||||||
|
|
||||||
|
|
||||||
|
# **belegeDetails**
|
||||||
|
> DeliveryDetails belegeDetails(belegnummer)
|
||||||
|
|
||||||
|
Liefert das **volle Detail-Paket** zu einer ERP-Belegnummer: die Lieferung mit Positionen (inkl. Scan-Ständen), Kunde + Ansprechpartner, referenzierte Artikel/Lager, Notizen, Geld-Gutschrift, Dienstleistungswerte und Kontakte — destilliert aus dem Tour-Aggregat. Jede Lieferung, unabhängig vom Status. `404`, wenn die Belegnummer unbekannt ist.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
// TODO Configure API key authorization: admin_api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('admin_api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('admin_api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
|
||||||
|
final api = HolzleitnerApi().getAdminApi();
|
||||||
|
final String belegnummer = belegnummer_example; // String | ERP-Belegnummer, z. B. V-30690291
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = api.belegeDetails(belegnummer);
|
||||||
|
print(response);
|
||||||
|
} catch on DioException (e) {
|
||||||
|
print('Exception when calling AdminApi->belegeDetails: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**belegnummer** | **String**| ERP-Belegnummer, z. B. V-30690291 |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**DeliveryDetails**](DeliveryDetails.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[admin_api_key](../README.md#admin_api_key)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **completedDeliveries**
|
||||||
|
> CompletedDeliveriesResponse completedDeliveries(day, from, to)
|
||||||
|
|
||||||
|
Liefert **alle** abgeschlossenen (ausgelieferten) Lieferungen — optional auf einen Datumsbereich eingegrenzt, unabhängig vom Mail-Versand-Status. Gefiltert wird über den **Berliner** Kalendertag des Abschluss-Zeitpunkts (`completed_at`).
|
||||||
|
|
||||||
|
Parameter (alle `DD-MM-YYYY`, alle optional): `day` = Einzeltag (Kurzform `from=to=day`), sonst `from`/`to` als **inklusive** Bereichsgrenzen (je offen). **Ohne jeden Parameter → ALLE ausgelieferten Belege** (kein Datumsfilter). Pro Lieferung: Belegnummer + `positions_modified` (Menge reduziert/Zeile entfernt oder Geld-Gutschrift). Die Halb-Grenzen-Variante ist für Range-Filter gedacht: `?from=…` und `?to=…` liefern je eine Menge, deren SQL-`AND`-Schnitt den Zeitraum ergibt.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
// TODO Configure API key authorization: admin_api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('admin_api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('admin_api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
|
||||||
|
final api = HolzleitnerApi().getAdminApi();
|
||||||
|
final String day = day_example; // String | Einzeltag DD-MM-YYYY (Kurzform from=to)
|
||||||
|
final String from = from_example; // String | Untere Grenze DD-MM-YYYY (inklusive)
|
||||||
|
final String to = to_example; // String | Obere Grenze DD-MM-YYYY (inklusive)
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = api.completedDeliveries(day, from, to);
|
||||||
|
print(response);
|
||||||
|
} catch on DioException (e) {
|
||||||
|
print('Exception when calling AdminApi->completedDeliveries: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**day** | **String**| Einzeltag DD-MM-YYYY (Kurzform from=to) | [optional]
|
||||||
|
**from** | **String**| Untere Grenze DD-MM-YYYY (inklusive) | [optional]
|
||||||
|
**to** | **String**| Obere Grenze DD-MM-YYYY (inklusive) | [optional]
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**CompletedDeliveriesResponse**](CompletedDeliveriesResponse.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[admin_api_key](../README.md#admin_api_key)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **deliveredBelegnummern**
|
# **deliveredBelegnummern**
|
||||||
> DeliveredBelegnummernResponse deliveredBelegnummern(day)
|
> DeliveredBelegnummernResponse deliveredBelegnummern(day)
|
||||||
|
|
||||||
@ -105,6 +206,47 @@ Name | Type | Description | Notes
|
|||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **listReviews**
|
||||||
|
> BuiltList<PendingReviewResponse> listReviews()
|
||||||
|
|
||||||
|
Listet alle geänderten Lieferscheine, die noch auf eine manuelle Bestätigung (Vier-Augen) warten — Entfernungen und/oder Geld-Gutschriften.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
// TODO Configure API key authorization: admin_api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('admin_api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('admin_api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
|
||||||
|
final api = HolzleitnerApi().getAdminApi();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = api.listReviews();
|
||||||
|
print(response);
|
||||||
|
} catch on DioException (e) {
|
||||||
|
print('Exception when calling AdminApi->listReviews: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
This endpoint does not need any parameter.
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**BuiltList<PendingReviewResponse>**](PendingReviewResponse.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[admin_api_key](../README.md#admin_api_key)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **markMailSent**
|
# **markMailSent**
|
||||||
> MarkMailSentResponse markMailSent(markMailSentRequest)
|
> MarkMailSentResponse markMailSent(markMailSentRequest)
|
||||||
|
|
||||||
@ -150,6 +292,51 @@ Name | Type | Description | Notes
|
|||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **positionsModified**
|
||||||
|
> PositionsModifiedResponse positionsModified(belegnummer)
|
||||||
|
|
||||||
|
Liefert zu **einer** ERP-Belegnummer, ob an der Lieferung Positionen verändert wurden (Menge reduziert/Zeile entfernt oder Geld-Gutschrift) — unabhängig vom Zustand der Lieferung. `404`, wenn die Belegnummer unbekannt ist. Gibt es mehrere Lieferungen mit derselben Belegnummer, ist das Flag `true`, sobald **eine** davon verändert ist.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
// TODO Configure API key authorization: admin_api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('admin_api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('admin_api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
|
||||||
|
final api = HolzleitnerApi().getAdminApi();
|
||||||
|
final String belegnummer = belegnummer_example; // String | ERP-Belegnummer, z. B. V-30690291
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = api.positionsModified(belegnummer);
|
||||||
|
print(response);
|
||||||
|
} catch on DioException (e) {
|
||||||
|
print('Exception when calling AdminApi->positionsModified: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**belegnummer** | **String**| ERP-Belegnummer, z. B. V-30690291 |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**PositionsModifiedResponse**](PositionsModifiedResponse.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[admin_api_key](../README.md#admin_api_key)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: Not defined
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **pushCompletion**
|
# **pushCompletion**
|
||||||
> pushCompletion(deliveryId)
|
> pushCompletion(deliveryId)
|
||||||
|
|
||||||
@ -194,3 +381,49 @@ void (empty response body)
|
|||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **resolveReview**
|
||||||
|
> resolveReview(deliveryId, resolveReviewRequest)
|
||||||
|
|
||||||
|
Bestätigt die Prüfung einer geänderten Lieferung (Vier-Augen) — die Lieferung verschwindet danach aus `GET /admin/reviews` (sofern nicht erneut geändert).
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
// TODO Configure API key authorization: admin_api_key
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('admin_api_key').apiKey = 'YOUR_API_KEY';
|
||||||
|
// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||||
|
//defaultApiClient.getAuthentication<ApiKeyAuth>('admin_api_key').apiKeyPrefix = 'Bearer';
|
||||||
|
|
||||||
|
final api = HolzleitnerApi().getAdminApi();
|
||||||
|
final String deliveryId = deliveryId_example; // String | UUID der Lieferung
|
||||||
|
final ResolveReviewRequest resolveReviewRequest = ; // ResolveReviewRequest |
|
||||||
|
|
||||||
|
try {
|
||||||
|
api.resolveReview(deliveryId, resolveReviewRequest);
|
||||||
|
} catch on DioException (e) {
|
||||||
|
print('Exception when calling AdminApi->resolveReview: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**deliveryId** | **String**| UUID der Lieferung |
|
||||||
|
**resolveReviewRequest** | [**ResolveReviewRequest**](ResolveReviewRequest.md)| |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
void (empty response body)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[admin_api_key](../README.md#admin_api_key)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: Not defined
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|||||||
18
packages/holzleitner_api/doc/CompletedDeliveriesResponse.md
Normal file
18
packages/holzleitner_api/doc/CompletedDeliveriesResponse.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# holzleitner_api.model.CompletedDeliveriesResponse
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**count** | **int** | Anzahl der abgeschlossenen Lieferungen im Bereich. |
|
||||||
|
**deliveries** | [**BuiltList<CompletedDeliveryItem>**](CompletedDeliveryItem.md) | Die abgeschlossenen Lieferungen, aufsteigend nach Abschluss-Zeitpunkt. |
|
||||||
|
**from** | **String** | Wirksame untere Grenze (ISO `YYYY-MM-DD`) oder `null` (offen). | [optional]
|
||||||
|
**to** | **String** | Wirksame obere Grenze (ISO `YYYY-MM-DD`) oder `null` (offen). | [optional]
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
16
packages/holzleitner_api/doc/CompletedDeliveryItem.md
Normal file
16
packages/holzleitner_api/doc/CompletedDeliveryItem.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# holzleitner_api.model.CompletedDeliveryItem
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**belegnummer** | **String** | ERP-Belegnummer der Lieferung. |
|
||||||
|
**positionsModified** | **bool** | `true`, wenn an der Lieferung Positionen verändert wurden — eine Zeile wurde entfernt oder in der Menge reduziert (Stück-Gutschrift) **oder** es liegt eine aktive Geld-Gutschrift vor. |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
@ -17,6 +17,7 @@ Method | HTTP request | Description
|
|||||||
[**deleteNote**](DeliveriesApi.md#deletenote) | **DELETE** /deliveries/{delivery_id}/notes/{note_id} | Löscht eine Notiz. Antwortet mit `204 No Content`.
|
[**deleteNote**](DeliveriesApi.md#deletenote) | **DELETE** /deliveries/{delivery_id}/notes/{note_id} | Löscht eine Notiz. Antwortet mit `204 No Content`.
|
||||||
[**deleteServiceValue**](DeliveriesApi.md#deleteservicevalue) | **DELETE** /deliveries/{delivery_id}/services/{service_id} | Entfernt den Service-Wert einer Lieferung (Service „nicht gesetzt\"). Nur bei aktiver Lieferung. Antwort `204`.
|
[**deleteServiceValue**](DeliveriesApi.md#deleteservicevalue) | **DELETE** /deliveries/{delivery_id}/services/{service_id} | Entfernt den Service-Wert einer Lieferung (Service „nicht gesetzt\"). Nur bei aktiver Lieferung. Antwort `204`.
|
||||||
[**hold**](DeliveriesApi.md#hold) | **POST** /deliveries/{delivery_id}/hold | Setzt die Lieferung auf `held`. Nur aus `active` zulässig.
|
[**hold**](DeliveriesApi.md#hold) | **POST** /deliveries/{delivery_id}/hold | Setzt die Lieferung auf `held`. Nur aus `active` zulässig.
|
||||||
|
[**recordPayment**](DeliveriesApi.md#recordpayment) | **POST** /deliveries/{delivery_id}/payment | Protokolliert die Zahlungsabwicklung („Abkassieren\") einer Lieferung. Append-only, idempotent über `clientEventId`. Der Server berechnet den offenen Betrag selbst; er muss > 0 sein und `expectedAmountCents` entsprechen. Nur bei aktiver Lieferung und aktiver Zahlungsmethode.
|
||||||
[**resume**](DeliveriesApi.md#resume) | **POST** /deliveries/{delivery_id}/resume | Setzt die Lieferung zurück auf `active`. Nur aus `held` zulässig.
|
[**resume**](DeliveriesApi.md#resume) | **POST** /deliveries/{delivery_id}/resume | Setzt die Lieferung zurück auf `active`. Nur aus `held` zulässig.
|
||||||
[**setService**](DeliveriesApi.md#setservice) | **PUT** /deliveries/{delivery_id}/services/{service_id} | Setzt (Upsert) den Wert eines Service für eine Lieferung. Genau das zum Service-Typ passende Feld (`boolValue`/`numericValue`) muss gesetzt sein; numerische Werte werden gegen min/max geprüft. Nur bei aktiver Lieferung.
|
[**setService**](DeliveriesApi.md#setservice) | **PUT** /deliveries/{delivery_id}/services/{service_id} | Setzt (Upsert) den Wert eines Service für eine Lieferung. Genau das zum Service-Typ passende Feld (`boolValue`/`numericValue`) muss gesetzt sein; numerische Werte werden gegen min/max geprüft. Nur bei aktiver Lieferung.
|
||||||
[**updateNote**](DeliveriesApi.md#updatenote) | **PATCH** /deliveries/{delivery_id}/notes/{note_id} | Ändert Text/Bild einer Notiz. Innerhalb des (geteilten) Accounts darf jeder Fahrer Notizen pflegen — kein Autor-Check. `delivery_id` ist Teil des Pfads (REST-Konsistenz), die Notiz wird über `note_id` adressiert.
|
[**updateNote**](DeliveriesApi.md#updatenote) | **PATCH** /deliveries/{delivery_id}/notes/{note_id} | Ändert Text/Bild einer Notiz. Innerhalb des (geteilten) Accounts darf jeder Fahrer Notizen pflegen — kein Autor-Check. `delivery_id` ist Teil des Pfads (REST-Konsistenz), die Notiz wird über `note_id` adressiert.
|
||||||
@ -365,6 +366,49 @@ Name | Type | Description | Notes
|
|||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
# **recordPayment**
|
||||||
|
> DeliveryPaymentResponse recordPayment(deliveryId, recordDeliveryPaymentRequest)
|
||||||
|
|
||||||
|
Protokolliert die Zahlungsabwicklung („Abkassieren\") einer Lieferung. Append-only, idempotent über `clientEventId`. Der Server berechnet den offenen Betrag selbst; er muss > 0 sein und `expectedAmountCents` entsprechen. Nur bei aktiver Lieferung und aktiver Zahlungsmethode.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
|
||||||
|
final api = HolzleitnerApi().getDeliveriesApi();
|
||||||
|
final String deliveryId = 38400000-8cf0-11bd-b23e-10b96e4ef00d; // String |
|
||||||
|
final RecordDeliveryPaymentRequest recordDeliveryPaymentRequest = ; // RecordDeliveryPaymentRequest |
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = api.recordPayment(deliveryId, recordDeliveryPaymentRequest);
|
||||||
|
print(response);
|
||||||
|
} catch on DioException (e) {
|
||||||
|
print('Exception when calling DeliveriesApi->recordPayment: $e\n');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**deliveryId** | **String**| |
|
||||||
|
**recordDeliveryPaymentRequest** | [**RecordDeliveryPaymentRequest**](RecordDeliveryPaymentRequest.md)| |
|
||||||
|
|
||||||
|
### Return type
|
||||||
|
|
||||||
|
[**DeliveryPaymentResponse**](DeliveryPaymentResponse.md)
|
||||||
|
|
||||||
|
### Authorization
|
||||||
|
|
||||||
|
[bearer_auth](../README.md#bearer_auth)
|
||||||
|
|
||||||
|
### HTTP request headers
|
||||||
|
|
||||||
|
- **Content-Type**: application/json
|
||||||
|
- **Accept**: application/json
|
||||||
|
|
||||||
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **resume**
|
# **resume**
|
||||||
> DeliveryResponse resume(deliveryId)
|
> DeliveryResponse resume(deliveryId)
|
||||||
|
|
||||||
|
|||||||
27
packages/holzleitner_api/doc/DeliveryDetails.md
Normal file
27
packages/holzleitner_api/doc/DeliveryDetails.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# holzleitner_api.model.DeliveryDetails
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**articles** | [**BuiltList<Article>**](Article.md) | Nur die von den Positionen referenzierten Artikel. |
|
||||||
|
**contactChannels** | [**BuiltList<ContactChannel>**](ContactChannel.md) | Die zu `contactSources` gehörenden Einzel-Kanäle. Join per `sourceId`. |
|
||||||
|
**contactSources** | [**BuiltList<ContactSource>**](ContactSource.md) | Kontaktquellen der Lieferung (Liefer-/Rechnungsadresse, Ansprechpartner …). |
|
||||||
|
**credit** | [**DeliveryCredit**](DeliveryCredit.md) | Aktuelle Betrags-Gutschrift (`null`, wenn keine aktiv). | [optional]
|
||||||
|
**customer** | [**Customer**](Customer.md) | Der Kunde der Lieferung (`null`, falls unauffindbar — sollte nicht vorkommen). | [optional]
|
||||||
|
**customerContacts** | [**BuiltList<CustomerContact>**](CustomerContact.md) | Ansprechpartner des Kunden. |
|
||||||
|
**delivery** | [**DeliveryWithItems**](DeliveryWithItems.md) | Die Lieferung selbst inkl. Positionen (mit Scan-Ständen) und `sortOrder`. |
|
||||||
|
**deliveryServices** | [**BuiltList<DeliveryServiceValue>**](DeliveryServiceValue.md) | Für diese Lieferung gesetzte Service-Werte. |
|
||||||
|
**notes** | [**BuiltList<DeliveryNote>**](DeliveryNote.md) | Notizen der Lieferung, aufsteigend nach `createdAt`. |
|
||||||
|
**payment** | [**DeliveryPayment**](DeliveryPayment.md) | Jüngste protokollierte Zahlungsabwicklung (`None` = keine). | [optional]
|
||||||
|
**services** | [**BuiltList<Service>**](Service.md) | Aktive Service-Definitionen (Stammdaten). |
|
||||||
|
**tour** | [**Tour**](Tour.md) | Die Tour, zu der die Lieferung gehört. |
|
||||||
|
**warehouses** | [**BuiltList<Warehouse>**](Warehouse.md) | Nur die von den Positionen referenzierten Lager. |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
22
packages/holzleitner_api/doc/DeliveryPayment.md
Normal file
22
packages/holzleitner_api/doc/DeliveryPayment.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# holzleitner_api.model.DeliveryPayment
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**amountCents** | **int** | Abgewickelter Betrag in Cent (offener Betrag bei Bestätigung). |
|
||||||
|
**deliveryId** | **String** | |
|
||||||
|
**id** | **String** | |
|
||||||
|
**paymentMethodCode** | **String** | Snapshot des Methoden-Codes (`cash`, `ec_card`, `invoice`, …). |
|
||||||
|
**paymentMethodId** | **String** | |
|
||||||
|
**recordedAt** | [**DateTime**](DateTime.md) | |
|
||||||
|
**recordedByCarId** | **String** | | [optional]
|
||||||
|
**recordedByPersonalnummer** | **int** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
15
packages/holzleitner_api/doc/DeliveryPaymentResponse.md
Normal file
15
packages/holzleitner_api/doc/DeliveryPaymentResponse.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# holzleitner_api.model.DeliveryPaymentResponse
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**payment** | [**DeliveryPayment**](DeliveryPayment.md) | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
23
packages/holzleitner_api/doc/PendingReviewResponse.md
Normal file
23
packages/holzleitner_api/doc/PendingReviewResponse.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# holzleitner_api.model.PendingReviewResponse
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**creditedItems** | [**BuiltList<ReviewedItemResponse>**](ReviewedItemResponse.md) | Entfernte/teil-gutgeschriebene Positionen. |
|
||||||
|
**customerName** | **String** | |
|
||||||
|
**deliveryId** | **String** | |
|
||||||
|
**erpBelegartId** | **int** | |
|
||||||
|
**erpBelegnummer** | **String** | |
|
||||||
|
**lastChangeAt** | **String** | Zeitpunkt der letzten beleg-ändernden Aktion (RFC 3339). |
|
||||||
|
**moneyCreditCents** | **int** | Geld-Gutschrift in Cent (0 = keine). |
|
||||||
|
**moneyCreditReason** | **String** | | [optional]
|
||||||
|
**tourDate** | **String** | Tourdatum (ISO `YYYY-MM-DD`). |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
16
packages/holzleitner_api/doc/PositionsModifiedResponse.md
Normal file
16
packages/holzleitner_api/doc/PositionsModifiedResponse.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# holzleitner_api.model.PositionsModifiedResponse
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**belegnummer** | **String** | ERP-Belegnummer, nach der gefragt wurde. |
|
||||||
|
**positionsModified** | **bool** | `true`, wenn an der Lieferung Positionen verändert wurden — eine Zeile wurde entfernt oder in der Menge reduziert (Stück-Gutschrift) **oder** es liegt eine aktive Geld-Gutschrift vor. |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
18
packages/holzleitner_api/doc/RecordDeliveryPaymentRequest.md
Normal file
18
packages/holzleitner_api/doc/RecordDeliveryPaymentRequest.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# holzleitner_api.model.RecordDeliveryPaymentRequest
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**authorCarId** | **String** | Fahrzeug des Akteurs (Audit-Spur). Muss zum Account gehören. | [optional]
|
||||||
|
**clientEventId** | **String** | Idempotenz-Schlüssel — pro Bestätigung genau einmal vergeben. |
|
||||||
|
**expectedAmountCents** | **int** | Betrag in Cent, den der Fahrer in der App gesehen und bestätigt hat. Der Server berechnet den offenen Betrag selbst und lehnt ab, wenn er davon abweicht — so landet nie ein Betrag im Protokoll, den der Fahrer nicht gesehen hat. |
|
||||||
|
**paymentMethodId** | **String** | Gewählte Zahlungsmethode. Muss existieren und aktiv sein. |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
16
packages/holzleitner_api/doc/ResolveReviewRequest.md
Normal file
16
packages/holzleitner_api/doc/ResolveReviewRequest.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# holzleitner_api.model.ResolveReviewRequest
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**note** | **String** | Optionale Notiz zur getroffenen Entscheidung. | [optional]
|
||||||
|
**resolvedBy** | **String** | Bearbeiter (Name/Kürzel), der die Prüfung bestätigt. |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
20
packages/holzleitner_api/doc/ReviewedItemResponse.md
Normal file
20
packages/holzleitner_api/doc/ReviewedItemResponse.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# holzleitner_api.model.ReviewedItemResponse
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
**articleName** | **String** | |
|
||||||
|
**artikelNr** | **String** | |
|
||||||
|
**belegzeilenNr** | **int** | |
|
||||||
|
**creditedQuantity** | **int** | |
|
||||||
|
**reason** | **String** | | [optional]
|
||||||
|
**requiredQuantity** | **int** | |
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
@ -17,6 +17,7 @@ Name | Type | Description | Notes
|
|||||||
**deliveries** | [**BuiltList<DeliveryWithItems>**](DeliveryWithItems.md) | |
|
**deliveries** | [**BuiltList<DeliveryWithItems>**](DeliveryWithItems.md) | |
|
||||||
**deliveryServices** | [**BuiltList<DeliveryServiceValue>**](DeliveryServiceValue.md) | Pro-Lieferung gesetzte Service-Werte. Join per `delivery_id` + `service_id`. |
|
**deliveryServices** | [**BuiltList<DeliveryServiceValue>**](DeliveryServiceValue.md) | Pro-Lieferung gesetzte Service-Werte. Join per `delivery_id` + `service_id`. |
|
||||||
**notes** | [**BuiltList<DeliveryNote>**](DeliveryNote.md) | Alle Notizen aller Lieferungen dieser Tour, in einer Liste. Die App joint clientseitig per `delivery_id`. Reihenfolge: pro Lieferung aufsteigend nach `created_at`. |
|
**notes** | [**BuiltList<DeliveryNote>**](DeliveryNote.md) | Alle Notizen aller Lieferungen dieser Tour, in einer Liste. Die App joint clientseitig per `delivery_id`. Reihenfolge: pro Lieferung aufsteigend nach `created_at`. |
|
||||||
|
**payments** | [**BuiltList<DeliveryPayment>**](DeliveryPayment.md) | Jüngste protokollierte Zahlungsabwicklung pro Lieferung (nur Lieferungen mit mindestens einem Eintrag). Join per `delivery_id`. |
|
||||||
**services** | [**BuiltList<Service>**](Service.md) | Aktive Service-Definitionen (Stammdaten) — die App rendert daraus Phase 4. Bewusst hier mitgeliefert, damit die Detailseite alles aus dem Tour-Aggregat hat. |
|
**services** | [**BuiltList<Service>**](Service.md) | Aktive Service-Definitionen (Stammdaten) — die App rendert daraus Phase 4. Bewusst hier mitgeliefert, damit die Detailseite alles aus dem Tour-Aggregat hat. |
|
||||||
**tour** | [**Tour**](Tour.md) | |
|
**tour** | [**Tour**](Tour.md) | |
|
||||||
**warehouses** | [**BuiltList<Warehouse>**](Warehouse.md) | |
|
**warehouses** | [**BuiltList<Warehouse>**](Warehouse.md) | |
|
||||||
|
|||||||
@ -10,7 +10,7 @@ All URIs are relative to *http://localhost*
|
|||||||
Method | HTTP request | Description
|
Method | HTTP request | Description
|
||||||
------------- | ------------- | -------------
|
------------- | ------------- | -------------
|
||||||
[**getTour**](ToursApi.md#gettour) | **GET** /tours/{tour_id} | Lädt eine Tour mit allen Lieferungen, Positionen und referenzierten Stammdaten — die App nutzt das als einzigen großen Read.
|
[**getTour**](ToursApi.md#gettour) | **GET** /tours/{tour_id} | Lädt eine Tour mit allen Lieferungen, Positionen und referenzierten Stammdaten — die App nutzt das als einzigen großen Read.
|
||||||
[**listMyToursToday**](ToursApi.md#listmytourstoday) | **GET** /me/tours/today | Listet heutige Touren des angemeldeten Fahrers (Filter aus dem JWT).
|
[**listMyTours**](ToursApi.md#listmytours) | **GET** /me/tours | Listet die Touren des angemeldeten Fahrers (Filter aus dem JWT) für ein Ziel-Datum. Ohne `?date=` gilt „heute\". Der Fahrer wählt das Datum aktiv im Kopf-Kalender der App (z. B. um die Tour von morgen vorab zu sehen).
|
||||||
[**setDeliveryOrder**](ToursApi.md#setdeliveryorder) | **PUT** /tours/{tour_id}/delivery-order | Schreibt die Sortier-Reihenfolge aller Lieferungen einer Tour neu. Der Client schickt die **vollständige** neue Reihenfolge; fehlende oder fremde Lieferungs-Ids werden mit `400 validation` abgelehnt.
|
[**setDeliveryOrder**](ToursApi.md#setdeliveryorder) | **PUT** /tours/{tour_id}/delivery-order | Schreibt die Sortier-Reihenfolge aller Lieferungen einer Tour neu. Der Client schickt die **vollständige** neue Reihenfolge; fehlende oder fremde Lieferungs-Ids werden mit `400 validation` abgelehnt.
|
||||||
|
|
||||||
|
|
||||||
@ -55,27 +55,31 @@ Name | Type | Description | Notes
|
|||||||
|
|
||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||||
|
|
||||||
# **listMyToursToday**
|
# **listMyTours**
|
||||||
> TourSummaryList listMyToursToday()
|
> TourSummaryList listMyTours(date)
|
||||||
|
|
||||||
Listet heutige Touren des angemeldeten Fahrers (Filter aus dem JWT).
|
Listet die Touren des angemeldeten Fahrers (Filter aus dem JWT) für ein Ziel-Datum. Ohne `?date=` gilt „heute\". Der Fahrer wählt das Datum aktiv im Kopf-Kalender der App (z. B. um die Tour von morgen vorab zu sehen).
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
```dart
|
```dart
|
||||||
import 'package:holzleitner_api/api.dart';
|
import 'package:holzleitner_api/api.dart';
|
||||||
|
|
||||||
final api = HolzleitnerApi().getToursApi();
|
final api = HolzleitnerApi().getToursApi();
|
||||||
|
final String date = date_example; // String | Ziel-Tourdatum YYYY-MM-DD (Default: heute)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final response = api.listMyToursToday();
|
final response = api.listMyTours(date);
|
||||||
print(response);
|
print(response);
|
||||||
} catch on DioException (e) {
|
} catch on DioException (e) {
|
||||||
print('Exception when calling ToursApi->listMyToursToday: $e\n');
|
print('Exception when calling ToursApi->listMyTours: $e\n');
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Parameters
|
### Parameters
|
||||||
This endpoint does not need any parameter.
|
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------- | ------------- | ------------- | -------------
|
||||||
|
**date** | **String**| Ziel-Tourdatum YYYY-MM-DD (Default: heute) | [optional]
|
||||||
|
|
||||||
### Return type
|
### Return type
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,8 @@ export 'package:holzleitner_api/src/model/car.dart';
|
|||||||
export 'package:holzleitner_api/src/model/car_response.dart';
|
export 'package:holzleitner_api/src/model/car_response.dart';
|
||||||
export 'package:holzleitner_api/src/model/cars_list.dart';
|
export 'package:holzleitner_api/src/model/cars_list.dart';
|
||||||
export 'package:holzleitner_api/src/model/complete_delivery_acknowledgements.dart';
|
export 'package:holzleitner_api/src/model/complete_delivery_acknowledgements.dart';
|
||||||
|
export 'package:holzleitner_api/src/model/completed_deliveries_response.dart';
|
||||||
|
export 'package:holzleitner_api/src/model/completed_delivery_item.dart';
|
||||||
export 'package:holzleitner_api/src/model/contact_channel.dart';
|
export 'package:holzleitner_api/src/model/contact_channel.dart';
|
||||||
export 'package:holzleitner_api/src/model/contact_kind.dart';
|
export 'package:holzleitner_api/src/model/contact_kind.dart';
|
||||||
export 'package:holzleitner_api/src/model/contact_role.dart';
|
export 'package:holzleitner_api/src/model/contact_role.dart';
|
||||||
@ -50,10 +52,13 @@ export 'package:holzleitner_api/src/model/delivery.dart';
|
|||||||
export 'package:holzleitner_api/src/model/delivery_credit.dart';
|
export 'package:holzleitner_api/src/model/delivery_credit.dart';
|
||||||
export 'package:holzleitner_api/src/model/delivery_credit_event_request.dart';
|
export 'package:holzleitner_api/src/model/delivery_credit_event_request.dart';
|
||||||
export 'package:holzleitner_api/src/model/delivery_credit_response.dart';
|
export 'package:holzleitner_api/src/model/delivery_credit_response.dart';
|
||||||
|
export 'package:holzleitner_api/src/model/delivery_details.dart';
|
||||||
export 'package:holzleitner_api/src/model/delivery_item.dart';
|
export 'package:holzleitner_api/src/model/delivery_item.dart';
|
||||||
export 'package:holzleitner_api/src/model/delivery_note.dart';
|
export 'package:holzleitner_api/src/model/delivery_note.dart';
|
||||||
export 'package:holzleitner_api/src/model/delivery_note_response.dart';
|
export 'package:holzleitner_api/src/model/delivery_note_response.dart';
|
||||||
export 'package:holzleitner_api/src/model/delivery_order_entry.dart';
|
export 'package:holzleitner_api/src/model/delivery_order_entry.dart';
|
||||||
|
export 'package:holzleitner_api/src/model/delivery_payment.dart';
|
||||||
|
export 'package:holzleitner_api/src/model/delivery_payment_response.dart';
|
||||||
export 'package:holzleitner_api/src/model/delivery_response.dart';
|
export 'package:holzleitner_api/src/model/delivery_response.dart';
|
||||||
export 'package:holzleitner_api/src/model/delivery_service_response.dart';
|
export 'package:holzleitner_api/src/model/delivery_service_response.dart';
|
||||||
export 'package:holzleitner_api/src/model/delivery_service_value.dart';
|
export 'package:holzleitner_api/src/model/delivery_service_value.dart';
|
||||||
@ -66,6 +71,11 @@ export 'package:holzleitner_api/src/model/mark_mail_sent_response.dart';
|
|||||||
export 'package:holzleitner_api/src/model/payment_method.dart';
|
export 'package:holzleitner_api/src/model/payment_method.dart';
|
||||||
export 'package:holzleitner_api/src/model/payment_method_response.dart';
|
export 'package:holzleitner_api/src/model/payment_method_response.dart';
|
||||||
export 'package:holzleitner_api/src/model/payment_methods_list.dart';
|
export 'package:holzleitner_api/src/model/payment_methods_list.dart';
|
||||||
|
export 'package:holzleitner_api/src/model/pending_review_response.dart';
|
||||||
|
export 'package:holzleitner_api/src/model/positions_modified_response.dart';
|
||||||
|
export 'package:holzleitner_api/src/model/record_delivery_payment_request.dart';
|
||||||
|
export 'package:holzleitner_api/src/model/resolve_review_request.dart';
|
||||||
|
export 'package:holzleitner_api/src/model/reviewed_item_response.dart';
|
||||||
export 'package:holzleitner_api/src/model/scan_event.dart';
|
export 'package:holzleitner_api/src/model/scan_event.dart';
|
||||||
export 'package:holzleitner_api/src/model/scan_result.dart';
|
export 'package:holzleitner_api/src/model/scan_result.dart';
|
||||||
export 'package:holzleitner_api/src/model/scan_result_status.dart';
|
export 'package:holzleitner_api/src/model/scan_result_status.dart';
|
||||||
|
|||||||
@ -8,11 +8,17 @@ import 'package:built_value/json_object.dart';
|
|||||||
import 'package:built_value/serializer.dart';
|
import 'package:built_value/serializer.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
|
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
import 'package:holzleitner_api/src/api_util.dart';
|
import 'package:holzleitner_api/src/api_util.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/completed_deliveries_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivered_belegnummern_response.dart';
|
import 'package:holzleitner_api/src/model/delivered_belegnummern_response.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_details.dart';
|
||||||
import 'package:holzleitner_api/src/model/import_summary.dart';
|
import 'package:holzleitner_api/src/model/import_summary.dart';
|
||||||
import 'package:holzleitner_api/src/model/mark_mail_sent_request.dart';
|
import 'package:holzleitner_api/src/model/mark_mail_sent_request.dart';
|
||||||
import 'package:holzleitner_api/src/model/mark_mail_sent_response.dart';
|
import 'package:holzleitner_api/src/model/mark_mail_sent_response.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/pending_review_response.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/positions_modified_response.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/resolve_review_request.dart';
|
||||||
|
|
||||||
class AdminApi {
|
class AdminApi {
|
||||||
|
|
||||||
@ -22,6 +28,181 @@ class AdminApi {
|
|||||||
|
|
||||||
const AdminApi(this._dio, this._serializers);
|
const AdminApi(this._dio, this._serializers);
|
||||||
|
|
||||||
|
/// Liefert das **volle Detail-Paket** zu einer ERP-Belegnummer: die Lieferung mit Positionen (inkl. Scan-Ständen), Kunde + Ansprechpartner, referenzierte Artikel/Lager, Notizen, Geld-Gutschrift, Dienstleistungswerte und Kontakte — destilliert aus dem Tour-Aggregat. Jede Lieferung, unabhängig vom Status. `404`, wenn die Belegnummer unbekannt ist.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
/// * [belegnummer] - ERP-Belegnummer, z. B. V-30690291
|
||||||
|
/// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
|
||||||
|
/// * [headers] - Can be used to add additional headers to the request
|
||||||
|
/// * [extras] - Can be used to add flags to the request
|
||||||
|
/// * [validateStatus] - A [ValidateStatus] callback that can be used to determine request success based on the HTTP status of the response
|
||||||
|
/// * [onSendProgress] - A [ProgressCallback] that can be used to get the send progress
|
||||||
|
/// * [onReceiveProgress] - A [ProgressCallback] that can be used to get the receive progress
|
||||||
|
///
|
||||||
|
/// Returns a [Future] containing a [Response] with a [DeliveryDetails] as data
|
||||||
|
/// Throws [DioException] if API call or serialization fails
|
||||||
|
Future<Response<DeliveryDetails>> belegeDetails({
|
||||||
|
required String belegnummer,
|
||||||
|
CancelToken? cancelToken,
|
||||||
|
Map<String, dynamic>? headers,
|
||||||
|
Map<String, dynamic>? extra,
|
||||||
|
ValidateStatus? validateStatus,
|
||||||
|
ProgressCallback? onSendProgress,
|
||||||
|
ProgressCallback? onReceiveProgress,
|
||||||
|
}) async {
|
||||||
|
final _path = r'/admin/belege/{belegnummer}'.replaceAll('{' r'belegnummer' '}', encodeQueryParameter(_serializers, belegnummer, const FullType(String)).toString());
|
||||||
|
final _options = Options(
|
||||||
|
method: r'GET',
|
||||||
|
headers: <String, dynamic>{
|
||||||
|
...?headers,
|
||||||
|
},
|
||||||
|
extra: <String, dynamic>{
|
||||||
|
'secure': <Map<String, String>>[
|
||||||
|
{
|
||||||
|
'type': 'apiKey',
|
||||||
|
'name': 'admin_api_key',
|
||||||
|
'keyName': 'X-Admin-Api-Key',
|
||||||
|
'where': 'header',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
...?extra,
|
||||||
|
},
|
||||||
|
validateStatus: validateStatus,
|
||||||
|
);
|
||||||
|
|
||||||
|
final _response = await _dio.request<Object>(
|
||||||
|
_path,
|
||||||
|
options: _options,
|
||||||
|
cancelToken: cancelToken,
|
||||||
|
onSendProgress: onSendProgress,
|
||||||
|
onReceiveProgress: onReceiveProgress,
|
||||||
|
);
|
||||||
|
|
||||||
|
DeliveryDetails? _responseData;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final rawResponse = _response.data;
|
||||||
|
_responseData = rawResponse == null ? null : _serializers.deserialize(
|
||||||
|
rawResponse,
|
||||||
|
specifiedType: const FullType(DeliveryDetails),
|
||||||
|
) as DeliveryDetails;
|
||||||
|
|
||||||
|
} catch (error, stackTrace) {
|
||||||
|
throw DioException(
|
||||||
|
requestOptions: _response.requestOptions,
|
||||||
|
response: _response,
|
||||||
|
type: DioExceptionType.unknown,
|
||||||
|
error: error,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response<DeliveryDetails>(
|
||||||
|
data: _responseData,
|
||||||
|
headers: _response.headers,
|
||||||
|
isRedirect: _response.isRedirect,
|
||||||
|
requestOptions: _response.requestOptions,
|
||||||
|
redirects: _response.redirects,
|
||||||
|
statusCode: _response.statusCode,
|
||||||
|
statusMessage: _response.statusMessage,
|
||||||
|
extra: _response.extra,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Liefert **alle** abgeschlossenen (ausgelieferten) Lieferungen — optional auf einen Datumsbereich eingegrenzt, unabhängig vom Mail-Versand-Status. Gefiltert wird über den **Berliner** Kalendertag des Abschluss-Zeitpunkts (`completed_at`).
|
||||||
|
/// Parameter (alle `DD-MM-YYYY`, alle optional): `day` = Einzeltag (Kurzform `from=to=day`), sonst `from`/`to` als **inklusive** Bereichsgrenzen (je offen). **Ohne jeden Parameter → ALLE ausgelieferten Belege** (kein Datumsfilter). Pro Lieferung: Belegnummer + `positions_modified` (Menge reduziert/Zeile entfernt oder Geld-Gutschrift). Die Halb-Grenzen-Variante ist für Range-Filter gedacht: `?from=…` und `?to=…` liefern je eine Menge, deren SQL-`AND`-Schnitt den Zeitraum ergibt.
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
/// * [day] - Einzeltag DD-MM-YYYY (Kurzform from=to)
|
||||||
|
/// * [from] - Untere Grenze DD-MM-YYYY (inklusive)
|
||||||
|
/// * [to] - Obere Grenze DD-MM-YYYY (inklusive)
|
||||||
|
/// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
|
||||||
|
/// * [headers] - Can be used to add additional headers to the request
|
||||||
|
/// * [extras] - Can be used to add flags to the request
|
||||||
|
/// * [validateStatus] - A [ValidateStatus] callback that can be used to determine request success based on the HTTP status of the response
|
||||||
|
/// * [onSendProgress] - A [ProgressCallback] that can be used to get the send progress
|
||||||
|
/// * [onReceiveProgress] - A [ProgressCallback] that can be used to get the receive progress
|
||||||
|
///
|
||||||
|
/// Returns a [Future] containing a [Response] with a [CompletedDeliveriesResponse] as data
|
||||||
|
/// Throws [DioException] if API call or serialization fails
|
||||||
|
Future<Response<CompletedDeliveriesResponse>> completedDeliveries({
|
||||||
|
String? day,
|
||||||
|
String? from,
|
||||||
|
String? to,
|
||||||
|
CancelToken? cancelToken,
|
||||||
|
Map<String, dynamic>? headers,
|
||||||
|
Map<String, dynamic>? extra,
|
||||||
|
ValidateStatus? validateStatus,
|
||||||
|
ProgressCallback? onSendProgress,
|
||||||
|
ProgressCallback? onReceiveProgress,
|
||||||
|
}) async {
|
||||||
|
final _path = r'/admin/completed-deliveries';
|
||||||
|
final _options = Options(
|
||||||
|
method: r'GET',
|
||||||
|
headers: <String, dynamic>{
|
||||||
|
...?headers,
|
||||||
|
},
|
||||||
|
extra: <String, dynamic>{
|
||||||
|
'secure': <Map<String, String>>[
|
||||||
|
{
|
||||||
|
'type': 'apiKey',
|
||||||
|
'name': 'admin_api_key',
|
||||||
|
'keyName': 'X-Admin-Api-Key',
|
||||||
|
'where': 'header',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
...?extra,
|
||||||
|
},
|
||||||
|
validateStatus: validateStatus,
|
||||||
|
);
|
||||||
|
|
||||||
|
final _queryParameters = <String, dynamic>{
|
||||||
|
if (day != null) r'day': encodeQueryParameter(_serializers, day, const FullType(String)),
|
||||||
|
if (from != null) r'from': encodeQueryParameter(_serializers, from, const FullType(String)),
|
||||||
|
if (to != null) r'to': encodeQueryParameter(_serializers, to, const FullType(String)),
|
||||||
|
};
|
||||||
|
|
||||||
|
final _response = await _dio.request<Object>(
|
||||||
|
_path,
|
||||||
|
options: _options,
|
||||||
|
queryParameters: _queryParameters,
|
||||||
|
cancelToken: cancelToken,
|
||||||
|
onSendProgress: onSendProgress,
|
||||||
|
onReceiveProgress: onReceiveProgress,
|
||||||
|
);
|
||||||
|
|
||||||
|
CompletedDeliveriesResponse? _responseData;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final rawResponse = _response.data;
|
||||||
|
_responseData = rawResponse == null ? null : _serializers.deserialize(
|
||||||
|
rawResponse,
|
||||||
|
specifiedType: const FullType(CompletedDeliveriesResponse),
|
||||||
|
) as CompletedDeliveriesResponse;
|
||||||
|
|
||||||
|
} catch (error, stackTrace) {
|
||||||
|
throw DioException(
|
||||||
|
requestOptions: _response.requestOptions,
|
||||||
|
response: _response,
|
||||||
|
type: DioExceptionType.unknown,
|
||||||
|
error: error,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response<CompletedDeliveriesResponse>(
|
||||||
|
data: _responseData,
|
||||||
|
headers: _response.headers,
|
||||||
|
isRedirect: _response.isRedirect,
|
||||||
|
requestOptions: _response.requestOptions,
|
||||||
|
redirects: _response.redirects,
|
||||||
|
statusCode: _response.statusCode,
|
||||||
|
statusMessage: _response.statusMessage,
|
||||||
|
extra: _response.extra,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Liefert die Belegnummern ausgelieferter (abgeschlossener) Lieferungen, **deren Liefermail noch nicht versendet wurde** (`mail_sent_at IS NULL`). „Ausgeliefert\" = es existiert ein Abschluss. Mit `day` (DD-MM-YYYY) nur Abschlüsse dieses Berliner Kalendertages; **ohne `day` alle offenen** (über alle Tage) — so bleiben Belege über Mitternacht nicht hängen.
|
/// Liefert die Belegnummern ausgelieferter (abgeschlossener) Lieferungen, **deren Liefermail noch nicht versendet wurde** (`mail_sent_at IS NULL`). „Ausgeliefert\" = es existiert ein Abschluss. Mit `day` (DD-MM-YYYY) nur Abschlüsse dieses Berliner Kalendertages; **ohne `day` alle offenen** (über alle Tage) — so bleiben Belege über Mitternacht nicht hängen.
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@ -196,6 +377,86 @@ class AdminApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Listet alle geänderten Lieferscheine, die noch auf eine manuelle Bestätigung (Vier-Augen) warten — Entfernungen und/oder Geld-Gutschriften.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
/// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
|
||||||
|
/// * [headers] - Can be used to add additional headers to the request
|
||||||
|
/// * [extras] - Can be used to add flags to the request
|
||||||
|
/// * [validateStatus] - A [ValidateStatus] callback that can be used to determine request success based on the HTTP status of the response
|
||||||
|
/// * [onSendProgress] - A [ProgressCallback] that can be used to get the send progress
|
||||||
|
/// * [onReceiveProgress] - A [ProgressCallback] that can be used to get the receive progress
|
||||||
|
///
|
||||||
|
/// Returns a [Future] containing a [Response] with a [BuiltList<PendingReviewResponse>] as data
|
||||||
|
/// Throws [DioException] if API call or serialization fails
|
||||||
|
Future<Response<BuiltList<PendingReviewResponse>>> listReviews({
|
||||||
|
CancelToken? cancelToken,
|
||||||
|
Map<String, dynamic>? headers,
|
||||||
|
Map<String, dynamic>? extra,
|
||||||
|
ValidateStatus? validateStatus,
|
||||||
|
ProgressCallback? onSendProgress,
|
||||||
|
ProgressCallback? onReceiveProgress,
|
||||||
|
}) async {
|
||||||
|
final _path = r'/admin/reviews';
|
||||||
|
final _options = Options(
|
||||||
|
method: r'GET',
|
||||||
|
headers: <String, dynamic>{
|
||||||
|
...?headers,
|
||||||
|
},
|
||||||
|
extra: <String, dynamic>{
|
||||||
|
'secure': <Map<String, String>>[
|
||||||
|
{
|
||||||
|
'type': 'apiKey',
|
||||||
|
'name': 'admin_api_key',
|
||||||
|
'keyName': 'X-Admin-Api-Key',
|
||||||
|
'where': 'header',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
...?extra,
|
||||||
|
},
|
||||||
|
validateStatus: validateStatus,
|
||||||
|
);
|
||||||
|
|
||||||
|
final _response = await _dio.request<Object>(
|
||||||
|
_path,
|
||||||
|
options: _options,
|
||||||
|
cancelToken: cancelToken,
|
||||||
|
onSendProgress: onSendProgress,
|
||||||
|
onReceiveProgress: onReceiveProgress,
|
||||||
|
);
|
||||||
|
|
||||||
|
BuiltList<PendingReviewResponse>? _responseData;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final rawResponse = _response.data;
|
||||||
|
_responseData = rawResponse == null ? null : _serializers.deserialize(
|
||||||
|
rawResponse,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(PendingReviewResponse)]),
|
||||||
|
) as BuiltList<PendingReviewResponse>;
|
||||||
|
|
||||||
|
} catch (error, stackTrace) {
|
||||||
|
throw DioException(
|
||||||
|
requestOptions: _response.requestOptions,
|
||||||
|
response: _response,
|
||||||
|
type: DioExceptionType.unknown,
|
||||||
|
error: error,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response<BuiltList<PendingReviewResponse>>(
|
||||||
|
data: _responseData,
|
||||||
|
headers: _response.headers,
|
||||||
|
isRedirect: _response.isRedirect,
|
||||||
|
requestOptions: _response.requestOptions,
|
||||||
|
redirects: _response.redirects,
|
||||||
|
statusCode: _response.statusCode,
|
||||||
|
statusMessage: _response.statusMessage,
|
||||||
|
extra: _response.extra,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Markiert die Liefermails der angegebenen Belegnummern als **versendet** (`mail_sent_at = now()`, nur wo noch offen). Vom Mailclient aufzurufen, NACHDEM ERPframe die Mails erfolgreich verschickt hat — danach erscheinen die Belege nicht mehr in `GET /admin/delivered-belegnummern`.
|
/// Markiert die Liefermails der angegebenen Belegnummern als **versendet** (`mail_sent_at = now()`, nur wo noch offen). Vom Mailclient aufzurufen, NACHDEM ERPframe die Mails erfolgreich verschickt hat — danach erscheinen die Belege nicht mehr in `GET /admin/delivered-belegnummern`.
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@ -298,6 +559,88 @@ class AdminApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Liefert zu **einer** ERP-Belegnummer, ob an der Lieferung Positionen verändert wurden (Menge reduziert/Zeile entfernt oder Geld-Gutschrift) — unabhängig vom Zustand der Lieferung. `404`, wenn die Belegnummer unbekannt ist. Gibt es mehrere Lieferungen mit derselben Belegnummer, ist das Flag `true`, sobald **eine** davon verändert ist.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
/// * [belegnummer] - ERP-Belegnummer, z. B. V-30690291
|
||||||
|
/// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
|
||||||
|
/// * [headers] - Can be used to add additional headers to the request
|
||||||
|
/// * [extras] - Can be used to add flags to the request
|
||||||
|
/// * [validateStatus] - A [ValidateStatus] callback that can be used to determine request success based on the HTTP status of the response
|
||||||
|
/// * [onSendProgress] - A [ProgressCallback] that can be used to get the send progress
|
||||||
|
/// * [onReceiveProgress] - A [ProgressCallback] that can be used to get the receive progress
|
||||||
|
///
|
||||||
|
/// Returns a [Future] containing a [Response] with a [PositionsModifiedResponse] as data
|
||||||
|
/// Throws [DioException] if API call or serialization fails
|
||||||
|
Future<Response<PositionsModifiedResponse>> positionsModified({
|
||||||
|
required String belegnummer,
|
||||||
|
CancelToken? cancelToken,
|
||||||
|
Map<String, dynamic>? headers,
|
||||||
|
Map<String, dynamic>? extra,
|
||||||
|
ValidateStatus? validateStatus,
|
||||||
|
ProgressCallback? onSendProgress,
|
||||||
|
ProgressCallback? onReceiveProgress,
|
||||||
|
}) async {
|
||||||
|
final _path = r'/admin/belege/{belegnummer}/positions-modified'.replaceAll('{' r'belegnummer' '}', encodeQueryParameter(_serializers, belegnummer, const FullType(String)).toString());
|
||||||
|
final _options = Options(
|
||||||
|
method: r'GET',
|
||||||
|
headers: <String, dynamic>{
|
||||||
|
...?headers,
|
||||||
|
},
|
||||||
|
extra: <String, dynamic>{
|
||||||
|
'secure': <Map<String, String>>[
|
||||||
|
{
|
||||||
|
'type': 'apiKey',
|
||||||
|
'name': 'admin_api_key',
|
||||||
|
'keyName': 'X-Admin-Api-Key',
|
||||||
|
'where': 'header',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
...?extra,
|
||||||
|
},
|
||||||
|
validateStatus: validateStatus,
|
||||||
|
);
|
||||||
|
|
||||||
|
final _response = await _dio.request<Object>(
|
||||||
|
_path,
|
||||||
|
options: _options,
|
||||||
|
cancelToken: cancelToken,
|
||||||
|
onSendProgress: onSendProgress,
|
||||||
|
onReceiveProgress: onReceiveProgress,
|
||||||
|
);
|
||||||
|
|
||||||
|
PositionsModifiedResponse? _responseData;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final rawResponse = _response.data;
|
||||||
|
_responseData = rawResponse == null ? null : _serializers.deserialize(
|
||||||
|
rawResponse,
|
||||||
|
specifiedType: const FullType(PositionsModifiedResponse),
|
||||||
|
) as PositionsModifiedResponse;
|
||||||
|
|
||||||
|
} catch (error, stackTrace) {
|
||||||
|
throw DioException(
|
||||||
|
requestOptions: _response.requestOptions,
|
||||||
|
response: _response,
|
||||||
|
type: DioExceptionType.unknown,
|
||||||
|
error: error,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response<PositionsModifiedResponse>(
|
||||||
|
data: _responseData,
|
||||||
|
headers: _response.headers,
|
||||||
|
isRedirect: _response.isRedirect,
|
||||||
|
requestOptions: _response.requestOptions,
|
||||||
|
redirects: _response.redirects,
|
||||||
|
statusCode: _response.statusCode,
|
||||||
|
statusMessage: _response.statusMessage,
|
||||||
|
extra: _response.extra,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Stößt das ERP-Rückschreiben eines bereits lokal abgeschlossenen Lieferabschlusses erneut an (idempotenter Retry, falls der automatische Push beim Abschluss fehlschlug).
|
/// Stößt das ERP-Rückschreiben eines bereits lokal abgeschlossenen Lieferabschlusses erneut an (idempotenter Retry, falls der automatische Push beim Abschluss fehlschlug).
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@ -357,4 +700,80 @@ class AdminApi {
|
|||||||
return _response;
|
return _response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Bestätigt die Prüfung einer geänderten Lieferung (Vier-Augen) — die Lieferung verschwindet danach aus `GET /admin/reviews` (sofern nicht erneut geändert).
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
/// * [deliveryId] - UUID der Lieferung
|
||||||
|
/// * [resolveReviewRequest]
|
||||||
|
/// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
|
||||||
|
/// * [headers] - Can be used to add additional headers to the request
|
||||||
|
/// * [extras] - Can be used to add flags to the request
|
||||||
|
/// * [validateStatus] - A [ValidateStatus] callback that can be used to determine request success based on the HTTP status of the response
|
||||||
|
/// * [onSendProgress] - A [ProgressCallback] that can be used to get the send progress
|
||||||
|
/// * [onReceiveProgress] - A [ProgressCallback] that can be used to get the receive progress
|
||||||
|
///
|
||||||
|
/// Returns a [Future]
|
||||||
|
/// Throws [DioException] if API call or serialization fails
|
||||||
|
Future<Response<void>> resolveReview({
|
||||||
|
required String deliveryId,
|
||||||
|
required ResolveReviewRequest resolveReviewRequest,
|
||||||
|
CancelToken? cancelToken,
|
||||||
|
Map<String, dynamic>? headers,
|
||||||
|
Map<String, dynamic>? extra,
|
||||||
|
ValidateStatus? validateStatus,
|
||||||
|
ProgressCallback? onSendProgress,
|
||||||
|
ProgressCallback? onReceiveProgress,
|
||||||
|
}) async {
|
||||||
|
final _path = r'/admin/reviews/{delivery_id}/resolve'.replaceAll('{' r'delivery_id' '}', encodeQueryParameter(_serializers, deliveryId, const FullType(String)).toString());
|
||||||
|
final _options = Options(
|
||||||
|
method: r'POST',
|
||||||
|
headers: <String, dynamic>{
|
||||||
|
...?headers,
|
||||||
|
},
|
||||||
|
extra: <String, dynamic>{
|
||||||
|
'secure': <Map<String, String>>[
|
||||||
|
{
|
||||||
|
'type': 'apiKey',
|
||||||
|
'name': 'admin_api_key',
|
||||||
|
'keyName': 'X-Admin-Api-Key',
|
||||||
|
'where': 'header',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
...?extra,
|
||||||
|
},
|
||||||
|
contentType: 'application/json',
|
||||||
|
validateStatus: validateStatus,
|
||||||
|
);
|
||||||
|
|
||||||
|
dynamic _bodyData;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const _type = FullType(ResolveReviewRequest);
|
||||||
|
_bodyData = _serializers.serialize(resolveReviewRequest, specifiedType: _type);
|
||||||
|
|
||||||
|
} catch(error, stackTrace) {
|
||||||
|
throw DioException(
|
||||||
|
requestOptions: _options.compose(
|
||||||
|
_dio.options,
|
||||||
|
_path,
|
||||||
|
),
|
||||||
|
type: DioExceptionType.unknown,
|
||||||
|
error: error,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final _response = await _dio.request<Object>(
|
||||||
|
_path,
|
||||||
|
data: _bodyData,
|
||||||
|
options: _options,
|
||||||
|
cancelToken: cancelToken,
|
||||||
|
onSendProgress: onSendProgress,
|
||||||
|
onReceiveProgress: onReceiveProgress,
|
||||||
|
);
|
||||||
|
|
||||||
|
return _response;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,9 +15,11 @@ import 'package:holzleitner_api/src/model/create_delivery_note_request.dart';
|
|||||||
import 'package:holzleitner_api/src/model/delivery_credit_event_request.dart';
|
import 'package:holzleitner_api/src/model/delivery_credit_event_request.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_credit_response.dart';
|
import 'package:holzleitner_api/src/model/delivery_credit_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_note_response.dart';
|
import 'package:holzleitner_api/src/model/delivery_note_response.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_payment_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_response.dart';
|
import 'package:holzleitner_api/src/model/delivery_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_service_response.dart';
|
import 'package:holzleitner_api/src/model/delivery_service_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/hold_delivery_request.dart';
|
import 'package:holzleitner_api/src/model/hold_delivery_request.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/record_delivery_payment_request.dart';
|
||||||
import 'package:holzleitner_api/src/model/set_delivery_service_request.dart';
|
import 'package:holzleitner_api/src/model/set_delivery_service_request.dart';
|
||||||
import 'package:holzleitner_api/src/model/update_delivery_note_request.dart';
|
import 'package:holzleitner_api/src/model/update_delivery_note_request.dart';
|
||||||
|
|
||||||
@ -736,6 +738,109 @@ class DeliveriesApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Protokolliert die Zahlungsabwicklung („Abkassieren\") einer Lieferung. Append-only, idempotent über `clientEventId`. Der Server berechnet den offenen Betrag selbst; er muss > 0 sein und `expectedAmountCents` entsprechen. Nur bei aktiver Lieferung und aktiver Zahlungsmethode.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
/// * [deliveryId]
|
||||||
|
/// * [recordDeliveryPaymentRequest]
|
||||||
|
/// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
|
||||||
|
/// * [headers] - Can be used to add additional headers to the request
|
||||||
|
/// * [extras] - Can be used to add flags to the request
|
||||||
|
/// * [validateStatus] - A [ValidateStatus] callback that can be used to determine request success based on the HTTP status of the response
|
||||||
|
/// * [onSendProgress] - A [ProgressCallback] that can be used to get the send progress
|
||||||
|
/// * [onReceiveProgress] - A [ProgressCallback] that can be used to get the receive progress
|
||||||
|
///
|
||||||
|
/// Returns a [Future] containing a [Response] with a [DeliveryPaymentResponse] as data
|
||||||
|
/// Throws [DioException] if API call or serialization fails
|
||||||
|
Future<Response<DeliveryPaymentResponse>> recordPayment({
|
||||||
|
required String deliveryId,
|
||||||
|
required RecordDeliveryPaymentRequest recordDeliveryPaymentRequest,
|
||||||
|
CancelToken? cancelToken,
|
||||||
|
Map<String, dynamic>? headers,
|
||||||
|
Map<String, dynamic>? extra,
|
||||||
|
ValidateStatus? validateStatus,
|
||||||
|
ProgressCallback? onSendProgress,
|
||||||
|
ProgressCallback? onReceiveProgress,
|
||||||
|
}) async {
|
||||||
|
final _path = r'/deliveries/{delivery_id}/payment'.replaceAll('{' r'delivery_id' '}', encodeQueryParameter(_serializers, deliveryId, const FullType(String)).toString());
|
||||||
|
final _options = Options(
|
||||||
|
method: r'POST',
|
||||||
|
headers: <String, dynamic>{
|
||||||
|
...?headers,
|
||||||
|
},
|
||||||
|
extra: <String, dynamic>{
|
||||||
|
'secure': <Map<String, String>>[
|
||||||
|
{
|
||||||
|
'type': 'http',
|
||||||
|
'scheme': 'bearer',
|
||||||
|
'name': 'bearer_auth',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
...?extra,
|
||||||
|
},
|
||||||
|
contentType: 'application/json',
|
||||||
|
validateStatus: validateStatus,
|
||||||
|
);
|
||||||
|
|
||||||
|
dynamic _bodyData;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const _type = FullType(RecordDeliveryPaymentRequest);
|
||||||
|
_bodyData = _serializers.serialize(recordDeliveryPaymentRequest, specifiedType: _type);
|
||||||
|
|
||||||
|
} catch(error, stackTrace) {
|
||||||
|
throw DioException(
|
||||||
|
requestOptions: _options.compose(
|
||||||
|
_dio.options,
|
||||||
|
_path,
|
||||||
|
),
|
||||||
|
type: DioExceptionType.unknown,
|
||||||
|
error: error,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final _response = await _dio.request<Object>(
|
||||||
|
_path,
|
||||||
|
data: _bodyData,
|
||||||
|
options: _options,
|
||||||
|
cancelToken: cancelToken,
|
||||||
|
onSendProgress: onSendProgress,
|
||||||
|
onReceiveProgress: onReceiveProgress,
|
||||||
|
);
|
||||||
|
|
||||||
|
DeliveryPaymentResponse? _responseData;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final rawResponse = _response.data;
|
||||||
|
_responseData = rawResponse == null ? null : _serializers.deserialize(
|
||||||
|
rawResponse,
|
||||||
|
specifiedType: const FullType(DeliveryPaymentResponse),
|
||||||
|
) as DeliveryPaymentResponse;
|
||||||
|
|
||||||
|
} catch (error, stackTrace) {
|
||||||
|
throw DioException(
|
||||||
|
requestOptions: _response.requestOptions,
|
||||||
|
response: _response,
|
||||||
|
type: DioExceptionType.unknown,
|
||||||
|
error: error,
|
||||||
|
stackTrace: stackTrace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response<DeliveryPaymentResponse>(
|
||||||
|
data: _responseData,
|
||||||
|
headers: _response.headers,
|
||||||
|
isRedirect: _response.isRedirect,
|
||||||
|
requestOptions: _response.requestOptions,
|
||||||
|
redirects: _response.redirects,
|
||||||
|
statusCode: _response.statusCode,
|
||||||
|
statusMessage: _response.statusMessage,
|
||||||
|
extra: _response.extra,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Setzt die Lieferung zurück auf `active`. Nur aus `held` zulässig.
|
/// Setzt die Lieferung zurück auf `active`. Nur aus `held` zulässig.
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|||||||
@ -103,11 +103,11 @@ class ToursApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Listet die Touren des angemeldeten Fahrers (Filter aus dem JWT) für ein
|
/// Listet die Touren des angemeldeten Fahrers (Filter aus dem JWT) für ein Ziel-Datum. Ohne `?date=` gilt „heute\". Der Fahrer wählt das Datum aktiv im Kopf-Kalender der App (z. B. um die Tour von morgen vorab zu sehen).
|
||||||
/// Ziel-Datum. Ohne [date] gilt serverseitig „heute".
|
///
|
||||||
///
|
///
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
/// * [date] - Ziel-Tourdatum im Format YYYY-MM-DD (Default: heute)
|
/// * [date] - Ziel-Tourdatum YYYY-MM-DD (Default: heute)
|
||||||
/// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
|
/// * [cancelToken] - A [CancelToken] that can be used to cancel the operation
|
||||||
/// * [headers] - Can be used to add additional headers to the request
|
/// * [headers] - Can be used to add additional headers to the request
|
||||||
/// * [extras] - Can be used to add flags to the request
|
/// * [extras] - Can be used to add flags to the request
|
||||||
@ -146,7 +146,7 @@ class ToursApi {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final _queryParameters = <String, dynamic>{
|
final _queryParameters = <String, dynamic>{
|
||||||
if (date != null) r'date': date,
|
if (date != null) r'date': encodeQueryParameter(_serializers, date, const FullType(String)),
|
||||||
};
|
};
|
||||||
|
|
||||||
final _response = await _dio.request<Object>(
|
final _response = await _dio.request<Object>(
|
||||||
|
|||||||
@ -0,0 +1,166 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element
|
||||||
|
import 'package:holzleitner_api/src/model/completed_delivery_item.dart';
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
|
||||||
|
part 'completed_deliveries_response.g.dart';
|
||||||
|
|
||||||
|
/// CompletedDeliveriesResponse
|
||||||
|
///
|
||||||
|
/// Properties:
|
||||||
|
/// * [count] - Anzahl der abgeschlossenen Lieferungen im Bereich.
|
||||||
|
/// * [deliveries] - Die abgeschlossenen Lieferungen, aufsteigend nach Abschluss-Zeitpunkt.
|
||||||
|
/// * [from] - Wirksame untere Grenze (ISO `YYYY-MM-DD`) oder `null` (offen).
|
||||||
|
/// * [to] - Wirksame obere Grenze (ISO `YYYY-MM-DD`) oder `null` (offen).
|
||||||
|
@BuiltValue()
|
||||||
|
abstract class CompletedDeliveriesResponse implements Built<CompletedDeliveriesResponse, CompletedDeliveriesResponseBuilder> {
|
||||||
|
/// Anzahl der abgeschlossenen Lieferungen im Bereich.
|
||||||
|
@BuiltValueField(wireName: r'count')
|
||||||
|
int get count;
|
||||||
|
|
||||||
|
/// Die abgeschlossenen Lieferungen, aufsteigend nach Abschluss-Zeitpunkt.
|
||||||
|
@BuiltValueField(wireName: r'deliveries')
|
||||||
|
BuiltList<CompletedDeliveryItem> get deliveries;
|
||||||
|
|
||||||
|
/// Wirksame untere Grenze (ISO `YYYY-MM-DD`) oder `null` (offen).
|
||||||
|
@BuiltValueField(wireName: r'from')
|
||||||
|
String? get from;
|
||||||
|
|
||||||
|
/// Wirksame obere Grenze (ISO `YYYY-MM-DD`) oder `null` (offen).
|
||||||
|
@BuiltValueField(wireName: r'to')
|
||||||
|
String? get to;
|
||||||
|
|
||||||
|
CompletedDeliveriesResponse._();
|
||||||
|
|
||||||
|
factory CompletedDeliveriesResponse([void updates(CompletedDeliveriesResponseBuilder b)]) = _$CompletedDeliveriesResponse;
|
||||||
|
|
||||||
|
@BuiltValueHook(initializeBuilder: true)
|
||||||
|
static void _defaults(CompletedDeliveriesResponseBuilder b) => b;
|
||||||
|
|
||||||
|
@BuiltValueSerializer(custom: true)
|
||||||
|
static Serializer<CompletedDeliveriesResponse> get serializer => _$CompletedDeliveriesResponseSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$CompletedDeliveriesResponseSerializer implements PrimitiveSerializer<CompletedDeliveriesResponse> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [CompletedDeliveriesResponse, _$CompletedDeliveriesResponse];
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String wireName = r'CompletedDeliveriesResponse';
|
||||||
|
|
||||||
|
Iterable<Object?> _serializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
CompletedDeliveriesResponse object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) sync* {
|
||||||
|
yield r'count';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.count,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
);
|
||||||
|
yield r'deliveries';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.deliveries,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(CompletedDeliveryItem)]),
|
||||||
|
);
|
||||||
|
if (object.from != null) {
|
||||||
|
yield r'from';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.from,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (object.to != null) {
|
||||||
|
yield r'to';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.to,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object serialize(
|
||||||
|
Serializers serializers,
|
||||||
|
CompletedDeliveriesResponse object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
return _serializeProperties(serializers, object, specifiedType: specifiedType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deserializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
required List<Object?> serializedList,
|
||||||
|
required CompletedDeliveriesResponseBuilder result,
|
||||||
|
required List<Object?> unhandled,
|
||||||
|
}) {
|
||||||
|
for (var i = 0; i < serializedList.length; i += 2) {
|
||||||
|
final key = serializedList[i] as String;
|
||||||
|
final value = serializedList[i + 1];
|
||||||
|
switch (key) {
|
||||||
|
case r'count':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
) as int;
|
||||||
|
result.count = valueDes;
|
||||||
|
break;
|
||||||
|
case r'deliveries':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(CompletedDeliveryItem)]),
|
||||||
|
) as BuiltList<CompletedDeliveryItem>;
|
||||||
|
result.deliveries.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'from':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
) as String?;
|
||||||
|
if (valueDes == null) continue;
|
||||||
|
result.from = valueDes;
|
||||||
|
break;
|
||||||
|
case r'to':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
) as String?;
|
||||||
|
if (valueDes == null) continue;
|
||||||
|
result.to = valueDes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unhandled.add(key);
|
||||||
|
unhandled.add(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
CompletedDeliveriesResponse deserialize(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
final result = CompletedDeliveriesResponseBuilder();
|
||||||
|
final serializedList = (serialized as Iterable<Object?>).toList();
|
||||||
|
final unhandled = <Object?>[];
|
||||||
|
_deserializeProperties(
|
||||||
|
serializers,
|
||||||
|
serialized,
|
||||||
|
specifiedType: specifiedType,
|
||||||
|
serializedList: serializedList,
|
||||||
|
unhandled: unhandled,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,147 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'completed_deliveries_response.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class _$CompletedDeliveriesResponse extends CompletedDeliveriesResponse {
|
||||||
|
@override
|
||||||
|
final int count;
|
||||||
|
@override
|
||||||
|
final BuiltList<CompletedDeliveryItem> deliveries;
|
||||||
|
@override
|
||||||
|
final String? from;
|
||||||
|
@override
|
||||||
|
final String? to;
|
||||||
|
|
||||||
|
factory _$CompletedDeliveriesResponse(
|
||||||
|
[void Function(CompletedDeliveriesResponseBuilder)? updates]) =>
|
||||||
|
(CompletedDeliveriesResponseBuilder()..update(updates))._build();
|
||||||
|
|
||||||
|
_$CompletedDeliveriesResponse._(
|
||||||
|
{required this.count, required this.deliveries, this.from, this.to})
|
||||||
|
: super._();
|
||||||
|
@override
|
||||||
|
CompletedDeliveriesResponse rebuild(
|
||||||
|
void Function(CompletedDeliveriesResponseBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
CompletedDeliveriesResponseBuilder toBuilder() =>
|
||||||
|
CompletedDeliveriesResponseBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is CompletedDeliveriesResponse &&
|
||||||
|
count == other.count &&
|
||||||
|
deliveries == other.deliveries &&
|
||||||
|
from == other.from &&
|
||||||
|
to == other.to;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var _$hash = 0;
|
||||||
|
_$hash = $jc(_$hash, count.hashCode);
|
||||||
|
_$hash = $jc(_$hash, deliveries.hashCode);
|
||||||
|
_$hash = $jc(_$hash, from.hashCode);
|
||||||
|
_$hash = $jc(_$hash, to.hashCode);
|
||||||
|
_$hash = $jf(_$hash);
|
||||||
|
return _$hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper(r'CompletedDeliveriesResponse')
|
||||||
|
..add('count', count)
|
||||||
|
..add('deliveries', deliveries)
|
||||||
|
..add('from', from)
|
||||||
|
..add('to', to))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CompletedDeliveriesResponseBuilder
|
||||||
|
implements
|
||||||
|
Builder<CompletedDeliveriesResponse,
|
||||||
|
CompletedDeliveriesResponseBuilder> {
|
||||||
|
_$CompletedDeliveriesResponse? _$v;
|
||||||
|
|
||||||
|
int? _count;
|
||||||
|
int? get count => _$this._count;
|
||||||
|
set count(int? count) => _$this._count = count;
|
||||||
|
|
||||||
|
ListBuilder<CompletedDeliveryItem>? _deliveries;
|
||||||
|
ListBuilder<CompletedDeliveryItem> get deliveries =>
|
||||||
|
_$this._deliveries ??= ListBuilder<CompletedDeliveryItem>();
|
||||||
|
set deliveries(ListBuilder<CompletedDeliveryItem>? deliveries) =>
|
||||||
|
_$this._deliveries = deliveries;
|
||||||
|
|
||||||
|
String? _from;
|
||||||
|
String? get from => _$this._from;
|
||||||
|
set from(String? from) => _$this._from = from;
|
||||||
|
|
||||||
|
String? _to;
|
||||||
|
String? get to => _$this._to;
|
||||||
|
set to(String? to) => _$this._to = to;
|
||||||
|
|
||||||
|
CompletedDeliveriesResponseBuilder() {
|
||||||
|
CompletedDeliveriesResponse._defaults(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompletedDeliveriesResponseBuilder get _$this {
|
||||||
|
final $v = _$v;
|
||||||
|
if ($v != null) {
|
||||||
|
_count = $v.count;
|
||||||
|
_deliveries = $v.deliveries.toBuilder();
|
||||||
|
_from = $v.from;
|
||||||
|
_to = $v.to;
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(CompletedDeliveriesResponse other) {
|
||||||
|
_$v = other as _$CompletedDeliveriesResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(CompletedDeliveriesResponseBuilder)? updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
CompletedDeliveriesResponse build() => _build();
|
||||||
|
|
||||||
|
_$CompletedDeliveriesResponse _build() {
|
||||||
|
_$CompletedDeliveriesResponse _$result;
|
||||||
|
try {
|
||||||
|
_$result = _$v ??
|
||||||
|
_$CompletedDeliveriesResponse._(
|
||||||
|
count: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
count, r'CompletedDeliveriesResponse', 'count'),
|
||||||
|
deliveries: deliveries.build(),
|
||||||
|
from: from,
|
||||||
|
to: to,
|
||||||
|
);
|
||||||
|
} catch (_) {
|
||||||
|
late String _$failedField;
|
||||||
|
try {
|
||||||
|
_$failedField = 'deliveries';
|
||||||
|
deliveries.build();
|
||||||
|
} catch (e) {
|
||||||
|
throw BuiltValueNestedFieldError(
|
||||||
|
r'CompletedDeliveriesResponse', _$failedField, e.toString());
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package,type=lint
|
||||||
@ -0,0 +1,124 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
|
||||||
|
part 'completed_delivery_item.g.dart';
|
||||||
|
|
||||||
|
/// Eine abgeschlossene Lieferung im Tagesabruf.
|
||||||
|
///
|
||||||
|
/// Properties:
|
||||||
|
/// * [belegnummer] - ERP-Belegnummer der Lieferung.
|
||||||
|
/// * [positionsModified] - `true`, wenn an der Lieferung Positionen verändert wurden — eine Zeile wurde entfernt oder in der Menge reduziert (Stück-Gutschrift) **oder** es liegt eine aktive Geld-Gutschrift vor.
|
||||||
|
@BuiltValue()
|
||||||
|
abstract class CompletedDeliveryItem implements Built<CompletedDeliveryItem, CompletedDeliveryItemBuilder> {
|
||||||
|
/// ERP-Belegnummer der Lieferung.
|
||||||
|
@BuiltValueField(wireName: r'belegnummer')
|
||||||
|
String get belegnummer;
|
||||||
|
|
||||||
|
/// `true`, wenn an der Lieferung Positionen verändert wurden — eine Zeile wurde entfernt oder in der Menge reduziert (Stück-Gutschrift) **oder** es liegt eine aktive Geld-Gutschrift vor.
|
||||||
|
@BuiltValueField(wireName: r'positions_modified')
|
||||||
|
bool get positionsModified;
|
||||||
|
|
||||||
|
CompletedDeliveryItem._();
|
||||||
|
|
||||||
|
factory CompletedDeliveryItem([void updates(CompletedDeliveryItemBuilder b)]) = _$CompletedDeliveryItem;
|
||||||
|
|
||||||
|
@BuiltValueHook(initializeBuilder: true)
|
||||||
|
static void _defaults(CompletedDeliveryItemBuilder b) => b;
|
||||||
|
|
||||||
|
@BuiltValueSerializer(custom: true)
|
||||||
|
static Serializer<CompletedDeliveryItem> get serializer => _$CompletedDeliveryItemSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$CompletedDeliveryItemSerializer implements PrimitiveSerializer<CompletedDeliveryItem> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [CompletedDeliveryItem, _$CompletedDeliveryItem];
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String wireName = r'CompletedDeliveryItem';
|
||||||
|
|
||||||
|
Iterable<Object?> _serializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
CompletedDeliveryItem object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) sync* {
|
||||||
|
yield r'belegnummer';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.belegnummer,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'positions_modified';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.positionsModified,
|
||||||
|
specifiedType: const FullType(bool),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object serialize(
|
||||||
|
Serializers serializers,
|
||||||
|
CompletedDeliveryItem object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
return _serializeProperties(serializers, object, specifiedType: specifiedType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deserializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
required List<Object?> serializedList,
|
||||||
|
required CompletedDeliveryItemBuilder result,
|
||||||
|
required List<Object?> unhandled,
|
||||||
|
}) {
|
||||||
|
for (var i = 0; i < serializedList.length; i += 2) {
|
||||||
|
final key = serializedList[i] as String;
|
||||||
|
final value = serializedList[i + 1];
|
||||||
|
switch (key) {
|
||||||
|
case r'belegnummer':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.belegnummer = valueDes;
|
||||||
|
break;
|
||||||
|
case r'positions_modified':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(bool),
|
||||||
|
) as bool;
|
||||||
|
result.positionsModified = valueDes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unhandled.add(key);
|
||||||
|
unhandled.add(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
CompletedDeliveryItem deserialize(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
final result = CompletedDeliveryItemBuilder();
|
||||||
|
final serializedList = (serialized as Iterable<Object?>).toList();
|
||||||
|
final unhandled = <Object?>[];
|
||||||
|
_deserializeProperties(
|
||||||
|
serializers,
|
||||||
|
serialized,
|
||||||
|
specifiedType: specifiedType,
|
||||||
|
serializedList: serializedList,
|
||||||
|
unhandled: unhandled,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,110 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'completed_delivery_item.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class _$CompletedDeliveryItem extends CompletedDeliveryItem {
|
||||||
|
@override
|
||||||
|
final String belegnummer;
|
||||||
|
@override
|
||||||
|
final bool positionsModified;
|
||||||
|
|
||||||
|
factory _$CompletedDeliveryItem(
|
||||||
|
[void Function(CompletedDeliveryItemBuilder)? updates]) =>
|
||||||
|
(CompletedDeliveryItemBuilder()..update(updates))._build();
|
||||||
|
|
||||||
|
_$CompletedDeliveryItem._(
|
||||||
|
{required this.belegnummer, required this.positionsModified})
|
||||||
|
: super._();
|
||||||
|
@override
|
||||||
|
CompletedDeliveryItem rebuild(
|
||||||
|
void Function(CompletedDeliveryItemBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
CompletedDeliveryItemBuilder toBuilder() =>
|
||||||
|
CompletedDeliveryItemBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is CompletedDeliveryItem &&
|
||||||
|
belegnummer == other.belegnummer &&
|
||||||
|
positionsModified == other.positionsModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var _$hash = 0;
|
||||||
|
_$hash = $jc(_$hash, belegnummer.hashCode);
|
||||||
|
_$hash = $jc(_$hash, positionsModified.hashCode);
|
||||||
|
_$hash = $jf(_$hash);
|
||||||
|
return _$hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper(r'CompletedDeliveryItem')
|
||||||
|
..add('belegnummer', belegnummer)
|
||||||
|
..add('positionsModified', positionsModified))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CompletedDeliveryItemBuilder
|
||||||
|
implements Builder<CompletedDeliveryItem, CompletedDeliveryItemBuilder> {
|
||||||
|
_$CompletedDeliveryItem? _$v;
|
||||||
|
|
||||||
|
String? _belegnummer;
|
||||||
|
String? get belegnummer => _$this._belegnummer;
|
||||||
|
set belegnummer(String? belegnummer) => _$this._belegnummer = belegnummer;
|
||||||
|
|
||||||
|
bool? _positionsModified;
|
||||||
|
bool? get positionsModified => _$this._positionsModified;
|
||||||
|
set positionsModified(bool? positionsModified) =>
|
||||||
|
_$this._positionsModified = positionsModified;
|
||||||
|
|
||||||
|
CompletedDeliveryItemBuilder() {
|
||||||
|
CompletedDeliveryItem._defaults(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompletedDeliveryItemBuilder get _$this {
|
||||||
|
final $v = _$v;
|
||||||
|
if ($v != null) {
|
||||||
|
_belegnummer = $v.belegnummer;
|
||||||
|
_positionsModified = $v.positionsModified;
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(CompletedDeliveryItem other) {
|
||||||
|
_$v = other as _$CompletedDeliveryItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(CompletedDeliveryItemBuilder)? updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
CompletedDeliveryItem build() => _build();
|
||||||
|
|
||||||
|
_$CompletedDeliveryItem _build() {
|
||||||
|
final _$result = _$v ??
|
||||||
|
_$CompletedDeliveryItem._(
|
||||||
|
belegnummer: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
belegnummer, r'CompletedDeliveryItem', 'belegnummer'),
|
||||||
|
positionsModified: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
positionsModified, r'CompletedDeliveryItem', 'positionsModified'),
|
||||||
|
);
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package,type=lint
|
||||||
334
packages/holzleitner_api/lib/src/model/delivery_details.dart
Normal file
334
packages/holzleitner_api/lib/src/model/delivery_details.dart
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_credit.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_note.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_with_items.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_payment.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/article.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/contact_channel.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/customer.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/contact_source.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/tour.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/warehouse.dart';
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/customer_contact.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/service.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_service_value.dart';
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
|
||||||
|
part 'delivery_details.g.dart';
|
||||||
|
|
||||||
|
/// DeliveryDetails
|
||||||
|
///
|
||||||
|
/// Properties:
|
||||||
|
/// * [articles] - Nur die von den Positionen referenzierten Artikel.
|
||||||
|
/// * [contactChannels] - Die zu `contactSources` gehörenden Einzel-Kanäle. Join per `sourceId`.
|
||||||
|
/// * [contactSources] - Kontaktquellen der Lieferung (Liefer-/Rechnungsadresse, Ansprechpartner …).
|
||||||
|
/// * [credit] - Aktuelle Betrags-Gutschrift (`null`, wenn keine aktiv).
|
||||||
|
/// * [customer] - Der Kunde der Lieferung (`null`, falls unauffindbar — sollte nicht vorkommen).
|
||||||
|
/// * [customerContacts] - Ansprechpartner des Kunden.
|
||||||
|
/// * [delivery] - Die Lieferung selbst inkl. Positionen (mit Scan-Ständen) und `sortOrder`.
|
||||||
|
/// * [deliveryServices] - Für diese Lieferung gesetzte Service-Werte.
|
||||||
|
/// * [notes] - Notizen der Lieferung, aufsteigend nach `createdAt`.
|
||||||
|
/// * [payment] - Jüngste protokollierte Zahlungsabwicklung (`None` = keine).
|
||||||
|
/// * [services] - Aktive Service-Definitionen (Stammdaten).
|
||||||
|
/// * [tour] - Die Tour, zu der die Lieferung gehört.
|
||||||
|
/// * [warehouses] - Nur die von den Positionen referenzierten Lager.
|
||||||
|
@BuiltValue()
|
||||||
|
abstract class DeliveryDetails implements Built<DeliveryDetails, DeliveryDetailsBuilder> {
|
||||||
|
/// Nur die von den Positionen referenzierten Artikel.
|
||||||
|
@BuiltValueField(wireName: r'articles')
|
||||||
|
BuiltList<Article> get articles;
|
||||||
|
|
||||||
|
/// Die zu `contactSources` gehörenden Einzel-Kanäle. Join per `sourceId`.
|
||||||
|
@BuiltValueField(wireName: r'contactChannels')
|
||||||
|
BuiltList<ContactChannel> get contactChannels;
|
||||||
|
|
||||||
|
/// Kontaktquellen der Lieferung (Liefer-/Rechnungsadresse, Ansprechpartner …).
|
||||||
|
@BuiltValueField(wireName: r'contactSources')
|
||||||
|
BuiltList<ContactSource> get contactSources;
|
||||||
|
|
||||||
|
/// Aktuelle Betrags-Gutschrift (`null`, wenn keine aktiv).
|
||||||
|
@BuiltValueField(wireName: r'credit')
|
||||||
|
DeliveryCredit? get credit;
|
||||||
|
|
||||||
|
/// Der Kunde der Lieferung (`null`, falls unauffindbar — sollte nicht vorkommen).
|
||||||
|
@BuiltValueField(wireName: r'customer')
|
||||||
|
Customer? get customer;
|
||||||
|
|
||||||
|
/// Ansprechpartner des Kunden.
|
||||||
|
@BuiltValueField(wireName: r'customerContacts')
|
||||||
|
BuiltList<CustomerContact> get customerContacts;
|
||||||
|
|
||||||
|
/// Die Lieferung selbst inkl. Positionen (mit Scan-Ständen) und `sortOrder`.
|
||||||
|
@BuiltValueField(wireName: r'delivery')
|
||||||
|
DeliveryWithItems get delivery;
|
||||||
|
|
||||||
|
/// Für diese Lieferung gesetzte Service-Werte.
|
||||||
|
@BuiltValueField(wireName: r'deliveryServices')
|
||||||
|
BuiltList<DeliveryServiceValue> get deliveryServices;
|
||||||
|
|
||||||
|
/// Notizen der Lieferung, aufsteigend nach `createdAt`.
|
||||||
|
@BuiltValueField(wireName: r'notes')
|
||||||
|
BuiltList<DeliveryNote> get notes;
|
||||||
|
|
||||||
|
/// Jüngste protokollierte Zahlungsabwicklung (`None` = keine).
|
||||||
|
@BuiltValueField(wireName: r'payment')
|
||||||
|
DeliveryPayment? get payment;
|
||||||
|
|
||||||
|
/// Aktive Service-Definitionen (Stammdaten).
|
||||||
|
@BuiltValueField(wireName: r'services')
|
||||||
|
BuiltList<Service> get services;
|
||||||
|
|
||||||
|
/// Die Tour, zu der die Lieferung gehört.
|
||||||
|
@BuiltValueField(wireName: r'tour')
|
||||||
|
Tour get tour;
|
||||||
|
|
||||||
|
/// Nur die von den Positionen referenzierten Lager.
|
||||||
|
@BuiltValueField(wireName: r'warehouses')
|
||||||
|
BuiltList<Warehouse> get warehouses;
|
||||||
|
|
||||||
|
DeliveryDetails._();
|
||||||
|
|
||||||
|
factory DeliveryDetails([void updates(DeliveryDetailsBuilder b)]) = _$DeliveryDetails;
|
||||||
|
|
||||||
|
@BuiltValueHook(initializeBuilder: true)
|
||||||
|
static void _defaults(DeliveryDetailsBuilder b) => b;
|
||||||
|
|
||||||
|
@BuiltValueSerializer(custom: true)
|
||||||
|
static Serializer<DeliveryDetails> get serializer => _$DeliveryDetailsSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DeliveryDetailsSerializer implements PrimitiveSerializer<DeliveryDetails> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [DeliveryDetails, _$DeliveryDetails];
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String wireName = r'DeliveryDetails';
|
||||||
|
|
||||||
|
Iterable<Object?> _serializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
DeliveryDetails object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) sync* {
|
||||||
|
yield r'articles';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.articles,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(Article)]),
|
||||||
|
);
|
||||||
|
yield r'contactChannels';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.contactChannels,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(ContactChannel)]),
|
||||||
|
);
|
||||||
|
yield r'contactSources';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.contactSources,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(ContactSource)]),
|
||||||
|
);
|
||||||
|
if (object.credit != null) {
|
||||||
|
yield r'credit';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.credit,
|
||||||
|
specifiedType: const FullType.nullable(DeliveryCredit),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (object.customer != null) {
|
||||||
|
yield r'customer';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.customer,
|
||||||
|
specifiedType: const FullType.nullable(Customer),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
yield r'customerContacts';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.customerContacts,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(CustomerContact)]),
|
||||||
|
);
|
||||||
|
yield r'delivery';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.delivery,
|
||||||
|
specifiedType: const FullType(DeliveryWithItems),
|
||||||
|
);
|
||||||
|
yield r'deliveryServices';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.deliveryServices,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(DeliveryServiceValue)]),
|
||||||
|
);
|
||||||
|
yield r'notes';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.notes,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(DeliveryNote)]),
|
||||||
|
);
|
||||||
|
if (object.payment != null) {
|
||||||
|
yield r'payment';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.payment,
|
||||||
|
specifiedType: const FullType.nullable(DeliveryPayment),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
yield r'services';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.services,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(Service)]),
|
||||||
|
);
|
||||||
|
yield r'tour';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.tour,
|
||||||
|
specifiedType: const FullType(Tour),
|
||||||
|
);
|
||||||
|
yield r'warehouses';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.warehouses,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(Warehouse)]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object serialize(
|
||||||
|
Serializers serializers,
|
||||||
|
DeliveryDetails object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
return _serializeProperties(serializers, object, specifiedType: specifiedType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deserializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
required List<Object?> serializedList,
|
||||||
|
required DeliveryDetailsBuilder result,
|
||||||
|
required List<Object?> unhandled,
|
||||||
|
}) {
|
||||||
|
for (var i = 0; i < serializedList.length; i += 2) {
|
||||||
|
final key = serializedList[i] as String;
|
||||||
|
final value = serializedList[i + 1];
|
||||||
|
switch (key) {
|
||||||
|
case r'articles':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(Article)]),
|
||||||
|
) as BuiltList<Article>;
|
||||||
|
result.articles.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'contactChannels':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(ContactChannel)]),
|
||||||
|
) as BuiltList<ContactChannel>;
|
||||||
|
result.contactChannels.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'contactSources':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(ContactSource)]),
|
||||||
|
) as BuiltList<ContactSource>;
|
||||||
|
result.contactSources.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'credit':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType.nullable(DeliveryCredit),
|
||||||
|
) as DeliveryCredit?;
|
||||||
|
if (valueDes == null) continue;
|
||||||
|
result.credit.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'customer':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType.nullable(Customer),
|
||||||
|
) as Customer?;
|
||||||
|
if (valueDes == null) continue;
|
||||||
|
result.customer.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'customerContacts':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(CustomerContact)]),
|
||||||
|
) as BuiltList<CustomerContact>;
|
||||||
|
result.customerContacts.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'delivery':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(DeliveryWithItems),
|
||||||
|
) as DeliveryWithItems;
|
||||||
|
result.delivery.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'deliveryServices':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(DeliveryServiceValue)]),
|
||||||
|
) as BuiltList<DeliveryServiceValue>;
|
||||||
|
result.deliveryServices.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'notes':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(DeliveryNote)]),
|
||||||
|
) as BuiltList<DeliveryNote>;
|
||||||
|
result.notes.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'payment':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType.nullable(DeliveryPayment),
|
||||||
|
) as DeliveryPayment?;
|
||||||
|
if (valueDes == null) continue;
|
||||||
|
result.payment.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'services':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(Service)]),
|
||||||
|
) as BuiltList<Service>;
|
||||||
|
result.services.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'tour':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(Tour),
|
||||||
|
) as Tour;
|
||||||
|
result.tour.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'warehouses':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(Warehouse)]),
|
||||||
|
) as BuiltList<Warehouse>;
|
||||||
|
result.warehouses.replace(valueDes);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unhandled.add(key);
|
||||||
|
unhandled.add(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeliveryDetails deserialize(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
final result = DeliveryDetailsBuilder();
|
||||||
|
final serializedList = (serialized as Iterable<Object?>).toList();
|
||||||
|
final unhandled = <Object?>[];
|
||||||
|
_deserializeProperties(
|
||||||
|
serializers,
|
||||||
|
serialized,
|
||||||
|
specifiedType: specifiedType,
|
||||||
|
serializedList: serializedList,
|
||||||
|
unhandled: unhandled,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
291
packages/holzleitner_api/lib/src/model/delivery_details.g.dart
Normal file
291
packages/holzleitner_api/lib/src/model/delivery_details.g.dart
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'delivery_details.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class _$DeliveryDetails extends DeliveryDetails {
|
||||||
|
@override
|
||||||
|
final BuiltList<Article> articles;
|
||||||
|
@override
|
||||||
|
final BuiltList<ContactChannel> contactChannels;
|
||||||
|
@override
|
||||||
|
final BuiltList<ContactSource> contactSources;
|
||||||
|
@override
|
||||||
|
final DeliveryCredit? credit;
|
||||||
|
@override
|
||||||
|
final Customer? customer;
|
||||||
|
@override
|
||||||
|
final BuiltList<CustomerContact> customerContacts;
|
||||||
|
@override
|
||||||
|
final DeliveryWithItems delivery;
|
||||||
|
@override
|
||||||
|
final BuiltList<DeliveryServiceValue> deliveryServices;
|
||||||
|
@override
|
||||||
|
final BuiltList<DeliveryNote> notes;
|
||||||
|
@override
|
||||||
|
final DeliveryPayment? payment;
|
||||||
|
@override
|
||||||
|
final BuiltList<Service> services;
|
||||||
|
@override
|
||||||
|
final Tour tour;
|
||||||
|
@override
|
||||||
|
final BuiltList<Warehouse> warehouses;
|
||||||
|
|
||||||
|
factory _$DeliveryDetails([void Function(DeliveryDetailsBuilder)? updates]) =>
|
||||||
|
(DeliveryDetailsBuilder()..update(updates))._build();
|
||||||
|
|
||||||
|
_$DeliveryDetails._(
|
||||||
|
{required this.articles,
|
||||||
|
required this.contactChannels,
|
||||||
|
required this.contactSources,
|
||||||
|
this.credit,
|
||||||
|
this.customer,
|
||||||
|
required this.customerContacts,
|
||||||
|
required this.delivery,
|
||||||
|
required this.deliveryServices,
|
||||||
|
required this.notes,
|
||||||
|
this.payment,
|
||||||
|
required this.services,
|
||||||
|
required this.tour,
|
||||||
|
required this.warehouses})
|
||||||
|
: super._();
|
||||||
|
@override
|
||||||
|
DeliveryDetails rebuild(void Function(DeliveryDetailsBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeliveryDetailsBuilder toBuilder() => DeliveryDetailsBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is DeliveryDetails &&
|
||||||
|
articles == other.articles &&
|
||||||
|
contactChannels == other.contactChannels &&
|
||||||
|
contactSources == other.contactSources &&
|
||||||
|
credit == other.credit &&
|
||||||
|
customer == other.customer &&
|
||||||
|
customerContacts == other.customerContacts &&
|
||||||
|
delivery == other.delivery &&
|
||||||
|
deliveryServices == other.deliveryServices &&
|
||||||
|
notes == other.notes &&
|
||||||
|
payment == other.payment &&
|
||||||
|
services == other.services &&
|
||||||
|
tour == other.tour &&
|
||||||
|
warehouses == other.warehouses;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var _$hash = 0;
|
||||||
|
_$hash = $jc(_$hash, articles.hashCode);
|
||||||
|
_$hash = $jc(_$hash, contactChannels.hashCode);
|
||||||
|
_$hash = $jc(_$hash, contactSources.hashCode);
|
||||||
|
_$hash = $jc(_$hash, credit.hashCode);
|
||||||
|
_$hash = $jc(_$hash, customer.hashCode);
|
||||||
|
_$hash = $jc(_$hash, customerContacts.hashCode);
|
||||||
|
_$hash = $jc(_$hash, delivery.hashCode);
|
||||||
|
_$hash = $jc(_$hash, deliveryServices.hashCode);
|
||||||
|
_$hash = $jc(_$hash, notes.hashCode);
|
||||||
|
_$hash = $jc(_$hash, payment.hashCode);
|
||||||
|
_$hash = $jc(_$hash, services.hashCode);
|
||||||
|
_$hash = $jc(_$hash, tour.hashCode);
|
||||||
|
_$hash = $jc(_$hash, warehouses.hashCode);
|
||||||
|
_$hash = $jf(_$hash);
|
||||||
|
return _$hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper(r'DeliveryDetails')
|
||||||
|
..add('articles', articles)
|
||||||
|
..add('contactChannels', contactChannels)
|
||||||
|
..add('contactSources', contactSources)
|
||||||
|
..add('credit', credit)
|
||||||
|
..add('customer', customer)
|
||||||
|
..add('customerContacts', customerContacts)
|
||||||
|
..add('delivery', delivery)
|
||||||
|
..add('deliveryServices', deliveryServices)
|
||||||
|
..add('notes', notes)
|
||||||
|
..add('payment', payment)
|
||||||
|
..add('services', services)
|
||||||
|
..add('tour', tour)
|
||||||
|
..add('warehouses', warehouses))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeliveryDetailsBuilder
|
||||||
|
implements Builder<DeliveryDetails, DeliveryDetailsBuilder> {
|
||||||
|
_$DeliveryDetails? _$v;
|
||||||
|
|
||||||
|
ListBuilder<Article>? _articles;
|
||||||
|
ListBuilder<Article> get articles =>
|
||||||
|
_$this._articles ??= ListBuilder<Article>();
|
||||||
|
set articles(ListBuilder<Article>? articles) => _$this._articles = articles;
|
||||||
|
|
||||||
|
ListBuilder<ContactChannel>? _contactChannels;
|
||||||
|
ListBuilder<ContactChannel> get contactChannels =>
|
||||||
|
_$this._contactChannels ??= ListBuilder<ContactChannel>();
|
||||||
|
set contactChannels(ListBuilder<ContactChannel>? contactChannels) =>
|
||||||
|
_$this._contactChannels = contactChannels;
|
||||||
|
|
||||||
|
ListBuilder<ContactSource>? _contactSources;
|
||||||
|
ListBuilder<ContactSource> get contactSources =>
|
||||||
|
_$this._contactSources ??= ListBuilder<ContactSource>();
|
||||||
|
set contactSources(ListBuilder<ContactSource>? contactSources) =>
|
||||||
|
_$this._contactSources = contactSources;
|
||||||
|
|
||||||
|
DeliveryCreditBuilder? _credit;
|
||||||
|
DeliveryCreditBuilder get credit =>
|
||||||
|
_$this._credit ??= DeliveryCreditBuilder();
|
||||||
|
set credit(DeliveryCreditBuilder? credit) => _$this._credit = credit;
|
||||||
|
|
||||||
|
CustomerBuilder? _customer;
|
||||||
|
CustomerBuilder get customer => _$this._customer ??= CustomerBuilder();
|
||||||
|
set customer(CustomerBuilder? customer) => _$this._customer = customer;
|
||||||
|
|
||||||
|
ListBuilder<CustomerContact>? _customerContacts;
|
||||||
|
ListBuilder<CustomerContact> get customerContacts =>
|
||||||
|
_$this._customerContacts ??= ListBuilder<CustomerContact>();
|
||||||
|
set customerContacts(ListBuilder<CustomerContact>? customerContacts) =>
|
||||||
|
_$this._customerContacts = customerContacts;
|
||||||
|
|
||||||
|
DeliveryWithItemsBuilder? _delivery;
|
||||||
|
DeliveryWithItemsBuilder get delivery =>
|
||||||
|
_$this._delivery ??= DeliveryWithItemsBuilder();
|
||||||
|
set delivery(DeliveryWithItemsBuilder? delivery) =>
|
||||||
|
_$this._delivery = delivery;
|
||||||
|
|
||||||
|
ListBuilder<DeliveryServiceValue>? _deliveryServices;
|
||||||
|
ListBuilder<DeliveryServiceValue> get deliveryServices =>
|
||||||
|
_$this._deliveryServices ??= ListBuilder<DeliveryServiceValue>();
|
||||||
|
set deliveryServices(ListBuilder<DeliveryServiceValue>? deliveryServices) =>
|
||||||
|
_$this._deliveryServices = deliveryServices;
|
||||||
|
|
||||||
|
ListBuilder<DeliveryNote>? _notes;
|
||||||
|
ListBuilder<DeliveryNote> get notes =>
|
||||||
|
_$this._notes ??= ListBuilder<DeliveryNote>();
|
||||||
|
set notes(ListBuilder<DeliveryNote>? notes) => _$this._notes = notes;
|
||||||
|
|
||||||
|
DeliveryPaymentBuilder? _payment;
|
||||||
|
DeliveryPaymentBuilder get payment =>
|
||||||
|
_$this._payment ??= DeliveryPaymentBuilder();
|
||||||
|
set payment(DeliveryPaymentBuilder? payment) => _$this._payment = payment;
|
||||||
|
|
||||||
|
ListBuilder<Service>? _services;
|
||||||
|
ListBuilder<Service> get services =>
|
||||||
|
_$this._services ??= ListBuilder<Service>();
|
||||||
|
set services(ListBuilder<Service>? services) => _$this._services = services;
|
||||||
|
|
||||||
|
TourBuilder? _tour;
|
||||||
|
TourBuilder get tour => _$this._tour ??= TourBuilder();
|
||||||
|
set tour(TourBuilder? tour) => _$this._tour = tour;
|
||||||
|
|
||||||
|
ListBuilder<Warehouse>? _warehouses;
|
||||||
|
ListBuilder<Warehouse> get warehouses =>
|
||||||
|
_$this._warehouses ??= ListBuilder<Warehouse>();
|
||||||
|
set warehouses(ListBuilder<Warehouse>? warehouses) =>
|
||||||
|
_$this._warehouses = warehouses;
|
||||||
|
|
||||||
|
DeliveryDetailsBuilder() {
|
||||||
|
DeliveryDetails._defaults(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeliveryDetailsBuilder get _$this {
|
||||||
|
final $v = _$v;
|
||||||
|
if ($v != null) {
|
||||||
|
_articles = $v.articles.toBuilder();
|
||||||
|
_contactChannels = $v.contactChannels.toBuilder();
|
||||||
|
_contactSources = $v.contactSources.toBuilder();
|
||||||
|
_credit = $v.credit?.toBuilder();
|
||||||
|
_customer = $v.customer?.toBuilder();
|
||||||
|
_customerContacts = $v.customerContacts.toBuilder();
|
||||||
|
_delivery = $v.delivery.toBuilder();
|
||||||
|
_deliveryServices = $v.deliveryServices.toBuilder();
|
||||||
|
_notes = $v.notes.toBuilder();
|
||||||
|
_payment = $v.payment?.toBuilder();
|
||||||
|
_services = $v.services.toBuilder();
|
||||||
|
_tour = $v.tour.toBuilder();
|
||||||
|
_warehouses = $v.warehouses.toBuilder();
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(DeliveryDetails other) {
|
||||||
|
_$v = other as _$DeliveryDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(DeliveryDetailsBuilder)? updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeliveryDetails build() => _build();
|
||||||
|
|
||||||
|
_$DeliveryDetails _build() {
|
||||||
|
_$DeliveryDetails _$result;
|
||||||
|
try {
|
||||||
|
_$result = _$v ??
|
||||||
|
_$DeliveryDetails._(
|
||||||
|
articles: articles.build(),
|
||||||
|
contactChannels: contactChannels.build(),
|
||||||
|
contactSources: contactSources.build(),
|
||||||
|
credit: _credit?.build(),
|
||||||
|
customer: _customer?.build(),
|
||||||
|
customerContacts: customerContacts.build(),
|
||||||
|
delivery: delivery.build(),
|
||||||
|
deliveryServices: deliveryServices.build(),
|
||||||
|
notes: notes.build(),
|
||||||
|
payment: _payment?.build(),
|
||||||
|
services: services.build(),
|
||||||
|
tour: tour.build(),
|
||||||
|
warehouses: warehouses.build(),
|
||||||
|
);
|
||||||
|
} catch (_) {
|
||||||
|
late String _$failedField;
|
||||||
|
try {
|
||||||
|
_$failedField = 'articles';
|
||||||
|
articles.build();
|
||||||
|
_$failedField = 'contactChannels';
|
||||||
|
contactChannels.build();
|
||||||
|
_$failedField = 'contactSources';
|
||||||
|
contactSources.build();
|
||||||
|
_$failedField = 'credit';
|
||||||
|
_credit?.build();
|
||||||
|
_$failedField = 'customer';
|
||||||
|
_customer?.build();
|
||||||
|
_$failedField = 'customerContacts';
|
||||||
|
customerContacts.build();
|
||||||
|
_$failedField = 'delivery';
|
||||||
|
delivery.build();
|
||||||
|
_$failedField = 'deliveryServices';
|
||||||
|
deliveryServices.build();
|
||||||
|
_$failedField = 'notes';
|
||||||
|
notes.build();
|
||||||
|
_$failedField = 'payment';
|
||||||
|
_payment?.build();
|
||||||
|
_$failedField = 'services';
|
||||||
|
services.build();
|
||||||
|
_$failedField = 'tour';
|
||||||
|
tour.build();
|
||||||
|
_$failedField = 'warehouses';
|
||||||
|
warehouses.build();
|
||||||
|
} catch (e) {
|
||||||
|
throw BuiltValueNestedFieldError(
|
||||||
|
r'DeliveryDetails', _$failedField, e.toString());
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package,type=lint
|
||||||
223
packages/holzleitner_api/lib/src/model/delivery_payment.dart
Normal file
223
packages/holzleitner_api/lib/src/model/delivery_payment.dart
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
|
||||||
|
part 'delivery_payment.g.dart';
|
||||||
|
|
||||||
|
/// Protokollierte Zahlungsabwicklung („Abkassieren\") einer Lieferung. Append-only: jede Bestätigung des Fahrers ist ein eigener Eintrag; im Tour-Aggregat wird pro Lieferung nur der jüngste mitgeliefert. Der Betrag ist der server-seitig berechnete offene Betrag zum Zeitpunkt der Bestätigung. Weicht der aktuelle offene Betrag davon ab (z. B. nach einer neuen Gutschrift), ist der Eintrag veraltet und muss erneuert werden.
|
||||||
|
///
|
||||||
|
/// Properties:
|
||||||
|
/// * [amountCents] - Abgewickelter Betrag in Cent (offener Betrag bei Bestätigung).
|
||||||
|
/// * [deliveryId]
|
||||||
|
/// * [id]
|
||||||
|
/// * [paymentMethodCode] - Snapshot des Methoden-Codes (`cash`, `ec_card`, `invoice`, …).
|
||||||
|
/// * [paymentMethodId]
|
||||||
|
/// * [recordedAt]
|
||||||
|
/// * [recordedByCarId]
|
||||||
|
/// * [recordedByPersonalnummer]
|
||||||
|
@BuiltValue()
|
||||||
|
abstract class DeliveryPayment implements Built<DeliveryPayment, DeliveryPaymentBuilder> {
|
||||||
|
/// Abgewickelter Betrag in Cent (offener Betrag bei Bestätigung).
|
||||||
|
@BuiltValueField(wireName: r'amountCents')
|
||||||
|
int get amountCents;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'deliveryId')
|
||||||
|
String get deliveryId;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'id')
|
||||||
|
String get id;
|
||||||
|
|
||||||
|
/// Snapshot des Methoden-Codes (`cash`, `ec_card`, `invoice`, …).
|
||||||
|
@BuiltValueField(wireName: r'paymentMethodCode')
|
||||||
|
String get paymentMethodCode;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'paymentMethodId')
|
||||||
|
String get paymentMethodId;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'recordedAt')
|
||||||
|
DateTime get recordedAt;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'recordedByCarId')
|
||||||
|
String? get recordedByCarId;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'recordedByPersonalnummer')
|
||||||
|
int get recordedByPersonalnummer;
|
||||||
|
|
||||||
|
DeliveryPayment._();
|
||||||
|
|
||||||
|
factory DeliveryPayment([void updates(DeliveryPaymentBuilder b)]) = _$DeliveryPayment;
|
||||||
|
|
||||||
|
@BuiltValueHook(initializeBuilder: true)
|
||||||
|
static void _defaults(DeliveryPaymentBuilder b) => b;
|
||||||
|
|
||||||
|
@BuiltValueSerializer(custom: true)
|
||||||
|
static Serializer<DeliveryPayment> get serializer => _$DeliveryPaymentSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DeliveryPaymentSerializer implements PrimitiveSerializer<DeliveryPayment> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [DeliveryPayment, _$DeliveryPayment];
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String wireName = r'DeliveryPayment';
|
||||||
|
|
||||||
|
Iterable<Object?> _serializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
DeliveryPayment object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) sync* {
|
||||||
|
yield r'amountCents';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.amountCents,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
);
|
||||||
|
yield r'deliveryId';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.deliveryId,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'id';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.id,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'paymentMethodCode';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.paymentMethodCode,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'paymentMethodId';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.paymentMethodId,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'recordedAt';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.recordedAt,
|
||||||
|
specifiedType: const FullType(DateTime),
|
||||||
|
);
|
||||||
|
if (object.recordedByCarId != null) {
|
||||||
|
yield r'recordedByCarId';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.recordedByCarId,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
yield r'recordedByPersonalnummer';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.recordedByPersonalnummer,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object serialize(
|
||||||
|
Serializers serializers,
|
||||||
|
DeliveryPayment object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
return _serializeProperties(serializers, object, specifiedType: specifiedType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deserializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
required List<Object?> serializedList,
|
||||||
|
required DeliveryPaymentBuilder result,
|
||||||
|
required List<Object?> unhandled,
|
||||||
|
}) {
|
||||||
|
for (var i = 0; i < serializedList.length; i += 2) {
|
||||||
|
final key = serializedList[i] as String;
|
||||||
|
final value = serializedList[i + 1];
|
||||||
|
switch (key) {
|
||||||
|
case r'amountCents':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
) as int;
|
||||||
|
result.amountCents = valueDes;
|
||||||
|
break;
|
||||||
|
case r'deliveryId':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.deliveryId = valueDes;
|
||||||
|
break;
|
||||||
|
case r'id':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.id = valueDes;
|
||||||
|
break;
|
||||||
|
case r'paymentMethodCode':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.paymentMethodCode = valueDes;
|
||||||
|
break;
|
||||||
|
case r'paymentMethodId':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.paymentMethodId = valueDes;
|
||||||
|
break;
|
||||||
|
case r'recordedAt':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(DateTime),
|
||||||
|
) as DateTime;
|
||||||
|
result.recordedAt = valueDes;
|
||||||
|
break;
|
||||||
|
case r'recordedByCarId':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
) as String?;
|
||||||
|
if (valueDes == null) continue;
|
||||||
|
result.recordedByCarId = valueDes;
|
||||||
|
break;
|
||||||
|
case r'recordedByPersonalnummer':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
) as int;
|
||||||
|
result.recordedByPersonalnummer = valueDes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unhandled.add(key);
|
||||||
|
unhandled.add(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeliveryPayment deserialize(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
final result = DeliveryPaymentBuilder();
|
||||||
|
final serializedList = (serialized as Iterable<Object?>).toList();
|
||||||
|
final unhandled = <Object?>[];
|
||||||
|
_deserializeProperties(
|
||||||
|
serializers,
|
||||||
|
serialized,
|
||||||
|
specifiedType: specifiedType,
|
||||||
|
serializedList: serializedList,
|
||||||
|
unhandled: unhandled,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
190
packages/holzleitner_api/lib/src/model/delivery_payment.g.dart
Normal file
190
packages/holzleitner_api/lib/src/model/delivery_payment.g.dart
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'delivery_payment.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class _$DeliveryPayment extends DeliveryPayment {
|
||||||
|
@override
|
||||||
|
final int amountCents;
|
||||||
|
@override
|
||||||
|
final String deliveryId;
|
||||||
|
@override
|
||||||
|
final String id;
|
||||||
|
@override
|
||||||
|
final String paymentMethodCode;
|
||||||
|
@override
|
||||||
|
final String paymentMethodId;
|
||||||
|
@override
|
||||||
|
final DateTime recordedAt;
|
||||||
|
@override
|
||||||
|
final String? recordedByCarId;
|
||||||
|
@override
|
||||||
|
final int recordedByPersonalnummer;
|
||||||
|
|
||||||
|
factory _$DeliveryPayment([void Function(DeliveryPaymentBuilder)? updates]) =>
|
||||||
|
(DeliveryPaymentBuilder()..update(updates))._build();
|
||||||
|
|
||||||
|
_$DeliveryPayment._(
|
||||||
|
{required this.amountCents,
|
||||||
|
required this.deliveryId,
|
||||||
|
required this.id,
|
||||||
|
required this.paymentMethodCode,
|
||||||
|
required this.paymentMethodId,
|
||||||
|
required this.recordedAt,
|
||||||
|
this.recordedByCarId,
|
||||||
|
required this.recordedByPersonalnummer})
|
||||||
|
: super._();
|
||||||
|
@override
|
||||||
|
DeliveryPayment rebuild(void Function(DeliveryPaymentBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeliveryPaymentBuilder toBuilder() => DeliveryPaymentBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is DeliveryPayment &&
|
||||||
|
amountCents == other.amountCents &&
|
||||||
|
deliveryId == other.deliveryId &&
|
||||||
|
id == other.id &&
|
||||||
|
paymentMethodCode == other.paymentMethodCode &&
|
||||||
|
paymentMethodId == other.paymentMethodId &&
|
||||||
|
recordedAt == other.recordedAt &&
|
||||||
|
recordedByCarId == other.recordedByCarId &&
|
||||||
|
recordedByPersonalnummer == other.recordedByPersonalnummer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var _$hash = 0;
|
||||||
|
_$hash = $jc(_$hash, amountCents.hashCode);
|
||||||
|
_$hash = $jc(_$hash, deliveryId.hashCode);
|
||||||
|
_$hash = $jc(_$hash, id.hashCode);
|
||||||
|
_$hash = $jc(_$hash, paymentMethodCode.hashCode);
|
||||||
|
_$hash = $jc(_$hash, paymentMethodId.hashCode);
|
||||||
|
_$hash = $jc(_$hash, recordedAt.hashCode);
|
||||||
|
_$hash = $jc(_$hash, recordedByCarId.hashCode);
|
||||||
|
_$hash = $jc(_$hash, recordedByPersonalnummer.hashCode);
|
||||||
|
_$hash = $jf(_$hash);
|
||||||
|
return _$hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper(r'DeliveryPayment')
|
||||||
|
..add('amountCents', amountCents)
|
||||||
|
..add('deliveryId', deliveryId)
|
||||||
|
..add('id', id)
|
||||||
|
..add('paymentMethodCode', paymentMethodCode)
|
||||||
|
..add('paymentMethodId', paymentMethodId)
|
||||||
|
..add('recordedAt', recordedAt)
|
||||||
|
..add('recordedByCarId', recordedByCarId)
|
||||||
|
..add('recordedByPersonalnummer', recordedByPersonalnummer))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeliveryPaymentBuilder
|
||||||
|
implements Builder<DeliveryPayment, DeliveryPaymentBuilder> {
|
||||||
|
_$DeliveryPayment? _$v;
|
||||||
|
|
||||||
|
int? _amountCents;
|
||||||
|
int? get amountCents => _$this._amountCents;
|
||||||
|
set amountCents(int? amountCents) => _$this._amountCents = amountCents;
|
||||||
|
|
||||||
|
String? _deliveryId;
|
||||||
|
String? get deliveryId => _$this._deliveryId;
|
||||||
|
set deliveryId(String? deliveryId) => _$this._deliveryId = deliveryId;
|
||||||
|
|
||||||
|
String? _id;
|
||||||
|
String? get id => _$this._id;
|
||||||
|
set id(String? id) => _$this._id = id;
|
||||||
|
|
||||||
|
String? _paymentMethodCode;
|
||||||
|
String? get paymentMethodCode => _$this._paymentMethodCode;
|
||||||
|
set paymentMethodCode(String? paymentMethodCode) =>
|
||||||
|
_$this._paymentMethodCode = paymentMethodCode;
|
||||||
|
|
||||||
|
String? _paymentMethodId;
|
||||||
|
String? get paymentMethodId => _$this._paymentMethodId;
|
||||||
|
set paymentMethodId(String? paymentMethodId) =>
|
||||||
|
_$this._paymentMethodId = paymentMethodId;
|
||||||
|
|
||||||
|
DateTime? _recordedAt;
|
||||||
|
DateTime? get recordedAt => _$this._recordedAt;
|
||||||
|
set recordedAt(DateTime? recordedAt) => _$this._recordedAt = recordedAt;
|
||||||
|
|
||||||
|
String? _recordedByCarId;
|
||||||
|
String? get recordedByCarId => _$this._recordedByCarId;
|
||||||
|
set recordedByCarId(String? recordedByCarId) =>
|
||||||
|
_$this._recordedByCarId = recordedByCarId;
|
||||||
|
|
||||||
|
int? _recordedByPersonalnummer;
|
||||||
|
int? get recordedByPersonalnummer => _$this._recordedByPersonalnummer;
|
||||||
|
set recordedByPersonalnummer(int? recordedByPersonalnummer) =>
|
||||||
|
_$this._recordedByPersonalnummer = recordedByPersonalnummer;
|
||||||
|
|
||||||
|
DeliveryPaymentBuilder() {
|
||||||
|
DeliveryPayment._defaults(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeliveryPaymentBuilder get _$this {
|
||||||
|
final $v = _$v;
|
||||||
|
if ($v != null) {
|
||||||
|
_amountCents = $v.amountCents;
|
||||||
|
_deliveryId = $v.deliveryId;
|
||||||
|
_id = $v.id;
|
||||||
|
_paymentMethodCode = $v.paymentMethodCode;
|
||||||
|
_paymentMethodId = $v.paymentMethodId;
|
||||||
|
_recordedAt = $v.recordedAt;
|
||||||
|
_recordedByCarId = $v.recordedByCarId;
|
||||||
|
_recordedByPersonalnummer = $v.recordedByPersonalnummer;
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(DeliveryPayment other) {
|
||||||
|
_$v = other as _$DeliveryPayment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(DeliveryPaymentBuilder)? updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeliveryPayment build() => _build();
|
||||||
|
|
||||||
|
_$DeliveryPayment _build() {
|
||||||
|
final _$result = _$v ??
|
||||||
|
_$DeliveryPayment._(
|
||||||
|
amountCents: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
amountCents, r'DeliveryPayment', 'amountCents'),
|
||||||
|
deliveryId: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
deliveryId, r'DeliveryPayment', 'deliveryId'),
|
||||||
|
id: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
id, r'DeliveryPayment', 'id'),
|
||||||
|
paymentMethodCode: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
paymentMethodCode, r'DeliveryPayment', 'paymentMethodCode'),
|
||||||
|
paymentMethodId: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
paymentMethodId, r'DeliveryPayment', 'paymentMethodId'),
|
||||||
|
recordedAt: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
recordedAt, r'DeliveryPayment', 'recordedAt'),
|
||||||
|
recordedByCarId: recordedByCarId,
|
||||||
|
recordedByPersonalnummer: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
recordedByPersonalnummer,
|
||||||
|
r'DeliveryPayment',
|
||||||
|
'recordedByPersonalnummer'),
|
||||||
|
);
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package,type=lint
|
||||||
@ -0,0 +1,107 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_payment.dart';
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
|
||||||
|
part 'delivery_payment_response.g.dart';
|
||||||
|
|
||||||
|
/// DeliveryPaymentResponse
|
||||||
|
///
|
||||||
|
/// Properties:
|
||||||
|
/// * [payment]
|
||||||
|
@BuiltValue()
|
||||||
|
abstract class DeliveryPaymentResponse implements Built<DeliveryPaymentResponse, DeliveryPaymentResponseBuilder> {
|
||||||
|
@BuiltValueField(wireName: r'payment')
|
||||||
|
DeliveryPayment get payment;
|
||||||
|
|
||||||
|
DeliveryPaymentResponse._();
|
||||||
|
|
||||||
|
factory DeliveryPaymentResponse([void updates(DeliveryPaymentResponseBuilder b)]) = _$DeliveryPaymentResponse;
|
||||||
|
|
||||||
|
@BuiltValueHook(initializeBuilder: true)
|
||||||
|
static void _defaults(DeliveryPaymentResponseBuilder b) => b;
|
||||||
|
|
||||||
|
@BuiltValueSerializer(custom: true)
|
||||||
|
static Serializer<DeliveryPaymentResponse> get serializer => _$DeliveryPaymentResponseSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$DeliveryPaymentResponseSerializer implements PrimitiveSerializer<DeliveryPaymentResponse> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [DeliveryPaymentResponse, _$DeliveryPaymentResponse];
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String wireName = r'DeliveryPaymentResponse';
|
||||||
|
|
||||||
|
Iterable<Object?> _serializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
DeliveryPaymentResponse object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) sync* {
|
||||||
|
yield r'payment';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.payment,
|
||||||
|
specifiedType: const FullType(DeliveryPayment),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object serialize(
|
||||||
|
Serializers serializers,
|
||||||
|
DeliveryPaymentResponse object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
return _serializeProperties(serializers, object, specifiedType: specifiedType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deserializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
required List<Object?> serializedList,
|
||||||
|
required DeliveryPaymentResponseBuilder result,
|
||||||
|
required List<Object?> unhandled,
|
||||||
|
}) {
|
||||||
|
for (var i = 0; i < serializedList.length; i += 2) {
|
||||||
|
final key = serializedList[i] as String;
|
||||||
|
final value = serializedList[i + 1];
|
||||||
|
switch (key) {
|
||||||
|
case r'payment':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(DeliveryPayment),
|
||||||
|
) as DeliveryPayment;
|
||||||
|
result.payment.replace(valueDes);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unhandled.add(key);
|
||||||
|
unhandled.add(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeliveryPaymentResponse deserialize(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
final result = DeliveryPaymentResponseBuilder();
|
||||||
|
final serializedList = (serialized as Iterable<Object?>).toList();
|
||||||
|
final unhandled = <Object?>[];
|
||||||
|
_deserializeProperties(
|
||||||
|
serializers,
|
||||||
|
serialized,
|
||||||
|
specifiedType: specifiedType,
|
||||||
|
serializedList: serializedList,
|
||||||
|
unhandled: unhandled,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'delivery_payment_response.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class _$DeliveryPaymentResponse extends DeliveryPaymentResponse {
|
||||||
|
@override
|
||||||
|
final DeliveryPayment payment;
|
||||||
|
|
||||||
|
factory _$DeliveryPaymentResponse(
|
||||||
|
[void Function(DeliveryPaymentResponseBuilder)? updates]) =>
|
||||||
|
(DeliveryPaymentResponseBuilder()..update(updates))._build();
|
||||||
|
|
||||||
|
_$DeliveryPaymentResponse._({required this.payment}) : super._();
|
||||||
|
@override
|
||||||
|
DeliveryPaymentResponse rebuild(
|
||||||
|
void Function(DeliveryPaymentResponseBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeliveryPaymentResponseBuilder toBuilder() =>
|
||||||
|
DeliveryPaymentResponseBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is DeliveryPaymentResponse && payment == other.payment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var _$hash = 0;
|
||||||
|
_$hash = $jc(_$hash, payment.hashCode);
|
||||||
|
_$hash = $jf(_$hash);
|
||||||
|
return _$hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper(r'DeliveryPaymentResponse')
|
||||||
|
..add('payment', payment))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeliveryPaymentResponseBuilder
|
||||||
|
implements
|
||||||
|
Builder<DeliveryPaymentResponse, DeliveryPaymentResponseBuilder> {
|
||||||
|
_$DeliveryPaymentResponse? _$v;
|
||||||
|
|
||||||
|
DeliveryPaymentBuilder? _payment;
|
||||||
|
DeliveryPaymentBuilder get payment =>
|
||||||
|
_$this._payment ??= DeliveryPaymentBuilder();
|
||||||
|
set payment(DeliveryPaymentBuilder? payment) => _$this._payment = payment;
|
||||||
|
|
||||||
|
DeliveryPaymentResponseBuilder() {
|
||||||
|
DeliveryPaymentResponse._defaults(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeliveryPaymentResponseBuilder get _$this {
|
||||||
|
final $v = _$v;
|
||||||
|
if ($v != null) {
|
||||||
|
_payment = $v.payment.toBuilder();
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(DeliveryPaymentResponse other) {
|
||||||
|
_$v = other as _$DeliveryPaymentResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(DeliveryPaymentResponseBuilder)? updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeliveryPaymentResponse build() => _build();
|
||||||
|
|
||||||
|
_$DeliveryPaymentResponse _build() {
|
||||||
|
_$DeliveryPaymentResponse _$result;
|
||||||
|
try {
|
||||||
|
_$result = _$v ??
|
||||||
|
_$DeliveryPaymentResponse._(
|
||||||
|
payment: payment.build(),
|
||||||
|
);
|
||||||
|
} catch (_) {
|
||||||
|
late String _$failedField;
|
||||||
|
try {
|
||||||
|
_$failedField = 'payment';
|
||||||
|
payment.build();
|
||||||
|
} catch (e) {
|
||||||
|
throw BuiltValueNestedFieldError(
|
||||||
|
r'DeliveryPaymentResponse', _$failedField, e.toString());
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package,type=lint
|
||||||
@ -0,0 +1,243 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element
|
||||||
|
import 'package:holzleitner_api/src/model/reviewed_item_response.dart';
|
||||||
|
import 'package:built_collection/built_collection.dart';
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
|
||||||
|
part 'pending_review_response.g.dart';
|
||||||
|
|
||||||
|
/// PendingReviewResponse
|
||||||
|
///
|
||||||
|
/// Properties:
|
||||||
|
/// * [creditedItems] - Entfernte/teil-gutgeschriebene Positionen.
|
||||||
|
/// * [customerName]
|
||||||
|
/// * [deliveryId]
|
||||||
|
/// * [erpBelegartId]
|
||||||
|
/// * [erpBelegnummer]
|
||||||
|
/// * [lastChangeAt] - Zeitpunkt der letzten beleg-ändernden Aktion (RFC 3339).
|
||||||
|
/// * [moneyCreditCents] - Geld-Gutschrift in Cent (0 = keine).
|
||||||
|
/// * [moneyCreditReason]
|
||||||
|
/// * [tourDate] - Tourdatum (ISO `YYYY-MM-DD`).
|
||||||
|
@BuiltValue()
|
||||||
|
abstract class PendingReviewResponse implements Built<PendingReviewResponse, PendingReviewResponseBuilder> {
|
||||||
|
/// Entfernte/teil-gutgeschriebene Positionen.
|
||||||
|
@BuiltValueField(wireName: r'credited_items')
|
||||||
|
BuiltList<ReviewedItemResponse> get creditedItems;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'customer_name')
|
||||||
|
String get customerName;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'delivery_id')
|
||||||
|
String get deliveryId;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'erp_belegart_id')
|
||||||
|
int get erpBelegartId;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'erp_belegnummer')
|
||||||
|
String get erpBelegnummer;
|
||||||
|
|
||||||
|
/// Zeitpunkt der letzten beleg-ändernden Aktion (RFC 3339).
|
||||||
|
@BuiltValueField(wireName: r'last_change_at')
|
||||||
|
String get lastChangeAt;
|
||||||
|
|
||||||
|
/// Geld-Gutschrift in Cent (0 = keine).
|
||||||
|
@BuiltValueField(wireName: r'money_credit_cents')
|
||||||
|
int get moneyCreditCents;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'money_credit_reason')
|
||||||
|
String? get moneyCreditReason;
|
||||||
|
|
||||||
|
/// Tourdatum (ISO `YYYY-MM-DD`).
|
||||||
|
@BuiltValueField(wireName: r'tour_date')
|
||||||
|
String get tourDate;
|
||||||
|
|
||||||
|
PendingReviewResponse._();
|
||||||
|
|
||||||
|
factory PendingReviewResponse([void updates(PendingReviewResponseBuilder b)]) = _$PendingReviewResponse;
|
||||||
|
|
||||||
|
@BuiltValueHook(initializeBuilder: true)
|
||||||
|
static void _defaults(PendingReviewResponseBuilder b) => b;
|
||||||
|
|
||||||
|
@BuiltValueSerializer(custom: true)
|
||||||
|
static Serializer<PendingReviewResponse> get serializer => _$PendingReviewResponseSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$PendingReviewResponseSerializer implements PrimitiveSerializer<PendingReviewResponse> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [PendingReviewResponse, _$PendingReviewResponse];
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String wireName = r'PendingReviewResponse';
|
||||||
|
|
||||||
|
Iterable<Object?> _serializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
PendingReviewResponse object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) sync* {
|
||||||
|
yield r'credited_items';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.creditedItems,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(ReviewedItemResponse)]),
|
||||||
|
);
|
||||||
|
yield r'customer_name';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.customerName,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'delivery_id';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.deliveryId,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'erp_belegart_id';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.erpBelegartId,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
);
|
||||||
|
yield r'erp_belegnummer';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.erpBelegnummer,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'last_change_at';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.lastChangeAt,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'money_credit_cents';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.moneyCreditCents,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
);
|
||||||
|
if (object.moneyCreditReason != null) {
|
||||||
|
yield r'money_credit_reason';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.moneyCreditReason,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
yield r'tour_date';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.tourDate,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object serialize(
|
||||||
|
Serializers serializers,
|
||||||
|
PendingReviewResponse object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
return _serializeProperties(serializers, object, specifiedType: specifiedType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deserializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
required List<Object?> serializedList,
|
||||||
|
required PendingReviewResponseBuilder result,
|
||||||
|
required List<Object?> unhandled,
|
||||||
|
}) {
|
||||||
|
for (var i = 0; i < serializedList.length; i += 2) {
|
||||||
|
final key = serializedList[i] as String;
|
||||||
|
final value = serializedList[i + 1];
|
||||||
|
switch (key) {
|
||||||
|
case r'credited_items':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(ReviewedItemResponse)]),
|
||||||
|
) as BuiltList<ReviewedItemResponse>;
|
||||||
|
result.creditedItems.replace(valueDes);
|
||||||
|
break;
|
||||||
|
case r'customer_name':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.customerName = valueDes;
|
||||||
|
break;
|
||||||
|
case r'delivery_id':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.deliveryId = valueDes;
|
||||||
|
break;
|
||||||
|
case r'erp_belegart_id':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
) as int;
|
||||||
|
result.erpBelegartId = valueDes;
|
||||||
|
break;
|
||||||
|
case r'erp_belegnummer':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.erpBelegnummer = valueDes;
|
||||||
|
break;
|
||||||
|
case r'last_change_at':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.lastChangeAt = valueDes;
|
||||||
|
break;
|
||||||
|
case r'money_credit_cents':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
) as int;
|
||||||
|
result.moneyCreditCents = valueDes;
|
||||||
|
break;
|
||||||
|
case r'money_credit_reason':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
) as String?;
|
||||||
|
if (valueDes == null) continue;
|
||||||
|
result.moneyCreditReason = valueDes;
|
||||||
|
break;
|
||||||
|
case r'tour_date':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.tourDate = valueDes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unhandled.add(key);
|
||||||
|
unhandled.add(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PendingReviewResponse deserialize(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
final result = PendingReviewResponseBuilder();
|
||||||
|
final serializedList = (serialized as Iterable<Object?>).toList();
|
||||||
|
final unhandled = <Object?>[];
|
||||||
|
_deserializeProperties(
|
||||||
|
serializers,
|
||||||
|
serialized,
|
||||||
|
specifiedType: specifiedType,
|
||||||
|
serializedList: serializedList,
|
||||||
|
unhandled: unhandled,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,218 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'pending_review_response.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class _$PendingReviewResponse extends PendingReviewResponse {
|
||||||
|
@override
|
||||||
|
final BuiltList<ReviewedItemResponse> creditedItems;
|
||||||
|
@override
|
||||||
|
final String customerName;
|
||||||
|
@override
|
||||||
|
final String deliveryId;
|
||||||
|
@override
|
||||||
|
final int erpBelegartId;
|
||||||
|
@override
|
||||||
|
final String erpBelegnummer;
|
||||||
|
@override
|
||||||
|
final String lastChangeAt;
|
||||||
|
@override
|
||||||
|
final int moneyCreditCents;
|
||||||
|
@override
|
||||||
|
final String? moneyCreditReason;
|
||||||
|
@override
|
||||||
|
final String tourDate;
|
||||||
|
|
||||||
|
factory _$PendingReviewResponse(
|
||||||
|
[void Function(PendingReviewResponseBuilder)? updates]) =>
|
||||||
|
(PendingReviewResponseBuilder()..update(updates))._build();
|
||||||
|
|
||||||
|
_$PendingReviewResponse._(
|
||||||
|
{required this.creditedItems,
|
||||||
|
required this.customerName,
|
||||||
|
required this.deliveryId,
|
||||||
|
required this.erpBelegartId,
|
||||||
|
required this.erpBelegnummer,
|
||||||
|
required this.lastChangeAt,
|
||||||
|
required this.moneyCreditCents,
|
||||||
|
this.moneyCreditReason,
|
||||||
|
required this.tourDate})
|
||||||
|
: super._();
|
||||||
|
@override
|
||||||
|
PendingReviewResponse rebuild(
|
||||||
|
void Function(PendingReviewResponseBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
PendingReviewResponseBuilder toBuilder() =>
|
||||||
|
PendingReviewResponseBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is PendingReviewResponse &&
|
||||||
|
creditedItems == other.creditedItems &&
|
||||||
|
customerName == other.customerName &&
|
||||||
|
deliveryId == other.deliveryId &&
|
||||||
|
erpBelegartId == other.erpBelegartId &&
|
||||||
|
erpBelegnummer == other.erpBelegnummer &&
|
||||||
|
lastChangeAt == other.lastChangeAt &&
|
||||||
|
moneyCreditCents == other.moneyCreditCents &&
|
||||||
|
moneyCreditReason == other.moneyCreditReason &&
|
||||||
|
tourDate == other.tourDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var _$hash = 0;
|
||||||
|
_$hash = $jc(_$hash, creditedItems.hashCode);
|
||||||
|
_$hash = $jc(_$hash, customerName.hashCode);
|
||||||
|
_$hash = $jc(_$hash, deliveryId.hashCode);
|
||||||
|
_$hash = $jc(_$hash, erpBelegartId.hashCode);
|
||||||
|
_$hash = $jc(_$hash, erpBelegnummer.hashCode);
|
||||||
|
_$hash = $jc(_$hash, lastChangeAt.hashCode);
|
||||||
|
_$hash = $jc(_$hash, moneyCreditCents.hashCode);
|
||||||
|
_$hash = $jc(_$hash, moneyCreditReason.hashCode);
|
||||||
|
_$hash = $jc(_$hash, tourDate.hashCode);
|
||||||
|
_$hash = $jf(_$hash);
|
||||||
|
return _$hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper(r'PendingReviewResponse')
|
||||||
|
..add('creditedItems', creditedItems)
|
||||||
|
..add('customerName', customerName)
|
||||||
|
..add('deliveryId', deliveryId)
|
||||||
|
..add('erpBelegartId', erpBelegartId)
|
||||||
|
..add('erpBelegnummer', erpBelegnummer)
|
||||||
|
..add('lastChangeAt', lastChangeAt)
|
||||||
|
..add('moneyCreditCents', moneyCreditCents)
|
||||||
|
..add('moneyCreditReason', moneyCreditReason)
|
||||||
|
..add('tourDate', tourDate))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PendingReviewResponseBuilder
|
||||||
|
implements Builder<PendingReviewResponse, PendingReviewResponseBuilder> {
|
||||||
|
_$PendingReviewResponse? _$v;
|
||||||
|
|
||||||
|
ListBuilder<ReviewedItemResponse>? _creditedItems;
|
||||||
|
ListBuilder<ReviewedItemResponse> get creditedItems =>
|
||||||
|
_$this._creditedItems ??= ListBuilder<ReviewedItemResponse>();
|
||||||
|
set creditedItems(ListBuilder<ReviewedItemResponse>? creditedItems) =>
|
||||||
|
_$this._creditedItems = creditedItems;
|
||||||
|
|
||||||
|
String? _customerName;
|
||||||
|
String? get customerName => _$this._customerName;
|
||||||
|
set customerName(String? customerName) => _$this._customerName = customerName;
|
||||||
|
|
||||||
|
String? _deliveryId;
|
||||||
|
String? get deliveryId => _$this._deliveryId;
|
||||||
|
set deliveryId(String? deliveryId) => _$this._deliveryId = deliveryId;
|
||||||
|
|
||||||
|
int? _erpBelegartId;
|
||||||
|
int? get erpBelegartId => _$this._erpBelegartId;
|
||||||
|
set erpBelegartId(int? erpBelegartId) =>
|
||||||
|
_$this._erpBelegartId = erpBelegartId;
|
||||||
|
|
||||||
|
String? _erpBelegnummer;
|
||||||
|
String? get erpBelegnummer => _$this._erpBelegnummer;
|
||||||
|
set erpBelegnummer(String? erpBelegnummer) =>
|
||||||
|
_$this._erpBelegnummer = erpBelegnummer;
|
||||||
|
|
||||||
|
String? _lastChangeAt;
|
||||||
|
String? get lastChangeAt => _$this._lastChangeAt;
|
||||||
|
set lastChangeAt(String? lastChangeAt) => _$this._lastChangeAt = lastChangeAt;
|
||||||
|
|
||||||
|
int? _moneyCreditCents;
|
||||||
|
int? get moneyCreditCents => _$this._moneyCreditCents;
|
||||||
|
set moneyCreditCents(int? moneyCreditCents) =>
|
||||||
|
_$this._moneyCreditCents = moneyCreditCents;
|
||||||
|
|
||||||
|
String? _moneyCreditReason;
|
||||||
|
String? get moneyCreditReason => _$this._moneyCreditReason;
|
||||||
|
set moneyCreditReason(String? moneyCreditReason) =>
|
||||||
|
_$this._moneyCreditReason = moneyCreditReason;
|
||||||
|
|
||||||
|
String? _tourDate;
|
||||||
|
String? get tourDate => _$this._tourDate;
|
||||||
|
set tourDate(String? tourDate) => _$this._tourDate = tourDate;
|
||||||
|
|
||||||
|
PendingReviewResponseBuilder() {
|
||||||
|
PendingReviewResponse._defaults(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PendingReviewResponseBuilder get _$this {
|
||||||
|
final $v = _$v;
|
||||||
|
if ($v != null) {
|
||||||
|
_creditedItems = $v.creditedItems.toBuilder();
|
||||||
|
_customerName = $v.customerName;
|
||||||
|
_deliveryId = $v.deliveryId;
|
||||||
|
_erpBelegartId = $v.erpBelegartId;
|
||||||
|
_erpBelegnummer = $v.erpBelegnummer;
|
||||||
|
_lastChangeAt = $v.lastChangeAt;
|
||||||
|
_moneyCreditCents = $v.moneyCreditCents;
|
||||||
|
_moneyCreditReason = $v.moneyCreditReason;
|
||||||
|
_tourDate = $v.tourDate;
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(PendingReviewResponse other) {
|
||||||
|
_$v = other as _$PendingReviewResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(PendingReviewResponseBuilder)? updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PendingReviewResponse build() => _build();
|
||||||
|
|
||||||
|
_$PendingReviewResponse _build() {
|
||||||
|
_$PendingReviewResponse _$result;
|
||||||
|
try {
|
||||||
|
_$result = _$v ??
|
||||||
|
_$PendingReviewResponse._(
|
||||||
|
creditedItems: creditedItems.build(),
|
||||||
|
customerName: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
customerName, r'PendingReviewResponse', 'customerName'),
|
||||||
|
deliveryId: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
deliveryId, r'PendingReviewResponse', 'deliveryId'),
|
||||||
|
erpBelegartId: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
erpBelegartId, r'PendingReviewResponse', 'erpBelegartId'),
|
||||||
|
erpBelegnummer: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
erpBelegnummer, r'PendingReviewResponse', 'erpBelegnummer'),
|
||||||
|
lastChangeAt: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
lastChangeAt, r'PendingReviewResponse', 'lastChangeAt'),
|
||||||
|
moneyCreditCents: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
moneyCreditCents, r'PendingReviewResponse', 'moneyCreditCents'),
|
||||||
|
moneyCreditReason: moneyCreditReason,
|
||||||
|
tourDate: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
tourDate, r'PendingReviewResponse', 'tourDate'),
|
||||||
|
);
|
||||||
|
} catch (_) {
|
||||||
|
late String _$failedField;
|
||||||
|
try {
|
||||||
|
_$failedField = 'creditedItems';
|
||||||
|
creditedItems.build();
|
||||||
|
} catch (e) {
|
||||||
|
throw BuiltValueNestedFieldError(
|
||||||
|
r'PendingReviewResponse', _$failedField, e.toString());
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package,type=lint
|
||||||
@ -0,0 +1,124 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
|
||||||
|
part 'positions_modified_response.g.dart';
|
||||||
|
|
||||||
|
/// PositionsModifiedResponse
|
||||||
|
///
|
||||||
|
/// Properties:
|
||||||
|
/// * [belegnummer] - ERP-Belegnummer, nach der gefragt wurde.
|
||||||
|
/// * [positionsModified] - `true`, wenn an der Lieferung Positionen verändert wurden — eine Zeile wurde entfernt oder in der Menge reduziert (Stück-Gutschrift) **oder** es liegt eine aktive Geld-Gutschrift vor.
|
||||||
|
@BuiltValue()
|
||||||
|
abstract class PositionsModifiedResponse implements Built<PositionsModifiedResponse, PositionsModifiedResponseBuilder> {
|
||||||
|
/// ERP-Belegnummer, nach der gefragt wurde.
|
||||||
|
@BuiltValueField(wireName: r'belegnummer')
|
||||||
|
String get belegnummer;
|
||||||
|
|
||||||
|
/// `true`, wenn an der Lieferung Positionen verändert wurden — eine Zeile wurde entfernt oder in der Menge reduziert (Stück-Gutschrift) **oder** es liegt eine aktive Geld-Gutschrift vor.
|
||||||
|
@BuiltValueField(wireName: r'positions_modified')
|
||||||
|
bool get positionsModified;
|
||||||
|
|
||||||
|
PositionsModifiedResponse._();
|
||||||
|
|
||||||
|
factory PositionsModifiedResponse([void updates(PositionsModifiedResponseBuilder b)]) = _$PositionsModifiedResponse;
|
||||||
|
|
||||||
|
@BuiltValueHook(initializeBuilder: true)
|
||||||
|
static void _defaults(PositionsModifiedResponseBuilder b) => b;
|
||||||
|
|
||||||
|
@BuiltValueSerializer(custom: true)
|
||||||
|
static Serializer<PositionsModifiedResponse> get serializer => _$PositionsModifiedResponseSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$PositionsModifiedResponseSerializer implements PrimitiveSerializer<PositionsModifiedResponse> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [PositionsModifiedResponse, _$PositionsModifiedResponse];
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String wireName = r'PositionsModifiedResponse';
|
||||||
|
|
||||||
|
Iterable<Object?> _serializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
PositionsModifiedResponse object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) sync* {
|
||||||
|
yield r'belegnummer';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.belegnummer,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'positions_modified';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.positionsModified,
|
||||||
|
specifiedType: const FullType(bool),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object serialize(
|
||||||
|
Serializers serializers,
|
||||||
|
PositionsModifiedResponse object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
return _serializeProperties(serializers, object, specifiedType: specifiedType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deserializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
required List<Object?> serializedList,
|
||||||
|
required PositionsModifiedResponseBuilder result,
|
||||||
|
required List<Object?> unhandled,
|
||||||
|
}) {
|
||||||
|
for (var i = 0; i < serializedList.length; i += 2) {
|
||||||
|
final key = serializedList[i] as String;
|
||||||
|
final value = serializedList[i + 1];
|
||||||
|
switch (key) {
|
||||||
|
case r'belegnummer':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.belegnummer = valueDes;
|
||||||
|
break;
|
||||||
|
case r'positions_modified':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(bool),
|
||||||
|
) as bool;
|
||||||
|
result.positionsModified = valueDes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unhandled.add(key);
|
||||||
|
unhandled.add(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PositionsModifiedResponse deserialize(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
final result = PositionsModifiedResponseBuilder();
|
||||||
|
final serializedList = (serialized as Iterable<Object?>).toList();
|
||||||
|
final unhandled = <Object?>[];
|
||||||
|
_deserializeProperties(
|
||||||
|
serializers,
|
||||||
|
serialized,
|
||||||
|
specifiedType: specifiedType,
|
||||||
|
serializedList: serializedList,
|
||||||
|
unhandled: unhandled,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'positions_modified_response.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class _$PositionsModifiedResponse extends PositionsModifiedResponse {
|
||||||
|
@override
|
||||||
|
final String belegnummer;
|
||||||
|
@override
|
||||||
|
final bool positionsModified;
|
||||||
|
|
||||||
|
factory _$PositionsModifiedResponse(
|
||||||
|
[void Function(PositionsModifiedResponseBuilder)? updates]) =>
|
||||||
|
(PositionsModifiedResponseBuilder()..update(updates))._build();
|
||||||
|
|
||||||
|
_$PositionsModifiedResponse._(
|
||||||
|
{required this.belegnummer, required this.positionsModified})
|
||||||
|
: super._();
|
||||||
|
@override
|
||||||
|
PositionsModifiedResponse rebuild(
|
||||||
|
void Function(PositionsModifiedResponseBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
PositionsModifiedResponseBuilder toBuilder() =>
|
||||||
|
PositionsModifiedResponseBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is PositionsModifiedResponse &&
|
||||||
|
belegnummer == other.belegnummer &&
|
||||||
|
positionsModified == other.positionsModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var _$hash = 0;
|
||||||
|
_$hash = $jc(_$hash, belegnummer.hashCode);
|
||||||
|
_$hash = $jc(_$hash, positionsModified.hashCode);
|
||||||
|
_$hash = $jf(_$hash);
|
||||||
|
return _$hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper(r'PositionsModifiedResponse')
|
||||||
|
..add('belegnummer', belegnummer)
|
||||||
|
..add('positionsModified', positionsModified))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PositionsModifiedResponseBuilder
|
||||||
|
implements
|
||||||
|
Builder<PositionsModifiedResponse, PositionsModifiedResponseBuilder> {
|
||||||
|
_$PositionsModifiedResponse? _$v;
|
||||||
|
|
||||||
|
String? _belegnummer;
|
||||||
|
String? get belegnummer => _$this._belegnummer;
|
||||||
|
set belegnummer(String? belegnummer) => _$this._belegnummer = belegnummer;
|
||||||
|
|
||||||
|
bool? _positionsModified;
|
||||||
|
bool? get positionsModified => _$this._positionsModified;
|
||||||
|
set positionsModified(bool? positionsModified) =>
|
||||||
|
_$this._positionsModified = positionsModified;
|
||||||
|
|
||||||
|
PositionsModifiedResponseBuilder() {
|
||||||
|
PositionsModifiedResponse._defaults(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PositionsModifiedResponseBuilder get _$this {
|
||||||
|
final $v = _$v;
|
||||||
|
if ($v != null) {
|
||||||
|
_belegnummer = $v.belegnummer;
|
||||||
|
_positionsModified = $v.positionsModified;
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(PositionsModifiedResponse other) {
|
||||||
|
_$v = other as _$PositionsModifiedResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(PositionsModifiedResponseBuilder)? updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PositionsModifiedResponse build() => _build();
|
||||||
|
|
||||||
|
_$PositionsModifiedResponse _build() {
|
||||||
|
final _$result = _$v ??
|
||||||
|
_$PositionsModifiedResponse._(
|
||||||
|
belegnummer: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
belegnummer, r'PositionsModifiedResponse', 'belegnummer'),
|
||||||
|
positionsModified: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
positionsModified,
|
||||||
|
r'PositionsModifiedResponse',
|
||||||
|
'positionsModified'),
|
||||||
|
);
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package,type=lint
|
||||||
@ -0,0 +1,161 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
|
||||||
|
part 'record_delivery_payment_request.g.dart';
|
||||||
|
|
||||||
|
/// RecordDeliveryPaymentRequest
|
||||||
|
///
|
||||||
|
/// Properties:
|
||||||
|
/// * [authorCarId] - Fahrzeug des Akteurs (Audit-Spur). Muss zum Account gehören.
|
||||||
|
/// * [clientEventId] - Idempotenz-Schlüssel — pro Bestätigung genau einmal vergeben.
|
||||||
|
/// * [expectedAmountCents] - Betrag in Cent, den der Fahrer in der App gesehen und bestätigt hat. Der Server berechnet den offenen Betrag selbst und lehnt ab, wenn er davon abweicht — so landet nie ein Betrag im Protokoll, den der Fahrer nicht gesehen hat.
|
||||||
|
/// * [paymentMethodId] - Gewählte Zahlungsmethode. Muss existieren und aktiv sein.
|
||||||
|
@BuiltValue()
|
||||||
|
abstract class RecordDeliveryPaymentRequest implements Built<RecordDeliveryPaymentRequest, RecordDeliveryPaymentRequestBuilder> {
|
||||||
|
/// Fahrzeug des Akteurs (Audit-Spur). Muss zum Account gehören.
|
||||||
|
@BuiltValueField(wireName: r'authorCarId')
|
||||||
|
String? get authorCarId;
|
||||||
|
|
||||||
|
/// Idempotenz-Schlüssel — pro Bestätigung genau einmal vergeben.
|
||||||
|
@BuiltValueField(wireName: r'clientEventId')
|
||||||
|
String get clientEventId;
|
||||||
|
|
||||||
|
/// Betrag in Cent, den der Fahrer in der App gesehen und bestätigt hat. Der Server berechnet den offenen Betrag selbst und lehnt ab, wenn er davon abweicht — so landet nie ein Betrag im Protokoll, den der Fahrer nicht gesehen hat.
|
||||||
|
@BuiltValueField(wireName: r'expectedAmountCents')
|
||||||
|
int get expectedAmountCents;
|
||||||
|
|
||||||
|
/// Gewählte Zahlungsmethode. Muss existieren und aktiv sein.
|
||||||
|
@BuiltValueField(wireName: r'paymentMethodId')
|
||||||
|
String get paymentMethodId;
|
||||||
|
|
||||||
|
RecordDeliveryPaymentRequest._();
|
||||||
|
|
||||||
|
factory RecordDeliveryPaymentRequest([void updates(RecordDeliveryPaymentRequestBuilder b)]) = _$RecordDeliveryPaymentRequest;
|
||||||
|
|
||||||
|
@BuiltValueHook(initializeBuilder: true)
|
||||||
|
static void _defaults(RecordDeliveryPaymentRequestBuilder b) => b;
|
||||||
|
|
||||||
|
@BuiltValueSerializer(custom: true)
|
||||||
|
static Serializer<RecordDeliveryPaymentRequest> get serializer => _$RecordDeliveryPaymentRequestSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$RecordDeliveryPaymentRequestSerializer implements PrimitiveSerializer<RecordDeliveryPaymentRequest> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [RecordDeliveryPaymentRequest, _$RecordDeliveryPaymentRequest];
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String wireName = r'RecordDeliveryPaymentRequest';
|
||||||
|
|
||||||
|
Iterable<Object?> _serializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
RecordDeliveryPaymentRequest object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) sync* {
|
||||||
|
if (object.authorCarId != null) {
|
||||||
|
yield r'authorCarId';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.authorCarId,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
yield r'clientEventId';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.clientEventId,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'expectedAmountCents';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.expectedAmountCents,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
);
|
||||||
|
yield r'paymentMethodId';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.paymentMethodId,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object serialize(
|
||||||
|
Serializers serializers,
|
||||||
|
RecordDeliveryPaymentRequest object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
return _serializeProperties(serializers, object, specifiedType: specifiedType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deserializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
required List<Object?> serializedList,
|
||||||
|
required RecordDeliveryPaymentRequestBuilder result,
|
||||||
|
required List<Object?> unhandled,
|
||||||
|
}) {
|
||||||
|
for (var i = 0; i < serializedList.length; i += 2) {
|
||||||
|
final key = serializedList[i] as String;
|
||||||
|
final value = serializedList[i + 1];
|
||||||
|
switch (key) {
|
||||||
|
case r'authorCarId':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
) as String?;
|
||||||
|
if (valueDes == null) continue;
|
||||||
|
result.authorCarId = valueDes;
|
||||||
|
break;
|
||||||
|
case r'clientEventId':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.clientEventId = valueDes;
|
||||||
|
break;
|
||||||
|
case r'expectedAmountCents':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
) as int;
|
||||||
|
result.expectedAmountCents = valueDes;
|
||||||
|
break;
|
||||||
|
case r'paymentMethodId':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.paymentMethodId = valueDes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unhandled.add(key);
|
||||||
|
unhandled.add(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
RecordDeliveryPaymentRequest deserialize(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
final result = RecordDeliveryPaymentRequestBuilder();
|
||||||
|
final serializedList = (serialized as Iterable<Object?>).toList();
|
||||||
|
final unhandled = <Object?>[];
|
||||||
|
_deserializeProperties(
|
||||||
|
serializers,
|
||||||
|
serialized,
|
||||||
|
specifiedType: specifiedType,
|
||||||
|
serializedList: serializedList,
|
||||||
|
unhandled: unhandled,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,144 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'record_delivery_payment_request.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class _$RecordDeliveryPaymentRequest extends RecordDeliveryPaymentRequest {
|
||||||
|
@override
|
||||||
|
final String? authorCarId;
|
||||||
|
@override
|
||||||
|
final String clientEventId;
|
||||||
|
@override
|
||||||
|
final int expectedAmountCents;
|
||||||
|
@override
|
||||||
|
final String paymentMethodId;
|
||||||
|
|
||||||
|
factory _$RecordDeliveryPaymentRequest(
|
||||||
|
[void Function(RecordDeliveryPaymentRequestBuilder)? updates]) =>
|
||||||
|
(RecordDeliveryPaymentRequestBuilder()..update(updates))._build();
|
||||||
|
|
||||||
|
_$RecordDeliveryPaymentRequest._(
|
||||||
|
{this.authorCarId,
|
||||||
|
required this.clientEventId,
|
||||||
|
required this.expectedAmountCents,
|
||||||
|
required this.paymentMethodId})
|
||||||
|
: super._();
|
||||||
|
@override
|
||||||
|
RecordDeliveryPaymentRequest rebuild(
|
||||||
|
void Function(RecordDeliveryPaymentRequestBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
RecordDeliveryPaymentRequestBuilder toBuilder() =>
|
||||||
|
RecordDeliveryPaymentRequestBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is RecordDeliveryPaymentRequest &&
|
||||||
|
authorCarId == other.authorCarId &&
|
||||||
|
clientEventId == other.clientEventId &&
|
||||||
|
expectedAmountCents == other.expectedAmountCents &&
|
||||||
|
paymentMethodId == other.paymentMethodId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var _$hash = 0;
|
||||||
|
_$hash = $jc(_$hash, authorCarId.hashCode);
|
||||||
|
_$hash = $jc(_$hash, clientEventId.hashCode);
|
||||||
|
_$hash = $jc(_$hash, expectedAmountCents.hashCode);
|
||||||
|
_$hash = $jc(_$hash, paymentMethodId.hashCode);
|
||||||
|
_$hash = $jf(_$hash);
|
||||||
|
return _$hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper(r'RecordDeliveryPaymentRequest')
|
||||||
|
..add('authorCarId', authorCarId)
|
||||||
|
..add('clientEventId', clientEventId)
|
||||||
|
..add('expectedAmountCents', expectedAmountCents)
|
||||||
|
..add('paymentMethodId', paymentMethodId))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordDeliveryPaymentRequestBuilder
|
||||||
|
implements
|
||||||
|
Builder<RecordDeliveryPaymentRequest,
|
||||||
|
RecordDeliveryPaymentRequestBuilder> {
|
||||||
|
_$RecordDeliveryPaymentRequest? _$v;
|
||||||
|
|
||||||
|
String? _authorCarId;
|
||||||
|
String? get authorCarId => _$this._authorCarId;
|
||||||
|
set authorCarId(String? authorCarId) => _$this._authorCarId = authorCarId;
|
||||||
|
|
||||||
|
String? _clientEventId;
|
||||||
|
String? get clientEventId => _$this._clientEventId;
|
||||||
|
set clientEventId(String? clientEventId) =>
|
||||||
|
_$this._clientEventId = clientEventId;
|
||||||
|
|
||||||
|
int? _expectedAmountCents;
|
||||||
|
int? get expectedAmountCents => _$this._expectedAmountCents;
|
||||||
|
set expectedAmountCents(int? expectedAmountCents) =>
|
||||||
|
_$this._expectedAmountCents = expectedAmountCents;
|
||||||
|
|
||||||
|
String? _paymentMethodId;
|
||||||
|
String? get paymentMethodId => _$this._paymentMethodId;
|
||||||
|
set paymentMethodId(String? paymentMethodId) =>
|
||||||
|
_$this._paymentMethodId = paymentMethodId;
|
||||||
|
|
||||||
|
RecordDeliveryPaymentRequestBuilder() {
|
||||||
|
RecordDeliveryPaymentRequest._defaults(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecordDeliveryPaymentRequestBuilder get _$this {
|
||||||
|
final $v = _$v;
|
||||||
|
if ($v != null) {
|
||||||
|
_authorCarId = $v.authorCarId;
|
||||||
|
_clientEventId = $v.clientEventId;
|
||||||
|
_expectedAmountCents = $v.expectedAmountCents;
|
||||||
|
_paymentMethodId = $v.paymentMethodId;
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(RecordDeliveryPaymentRequest other) {
|
||||||
|
_$v = other as _$RecordDeliveryPaymentRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(RecordDeliveryPaymentRequestBuilder)? updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
RecordDeliveryPaymentRequest build() => _build();
|
||||||
|
|
||||||
|
_$RecordDeliveryPaymentRequest _build() {
|
||||||
|
final _$result = _$v ??
|
||||||
|
_$RecordDeliveryPaymentRequest._(
|
||||||
|
authorCarId: authorCarId,
|
||||||
|
clientEventId: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
clientEventId, r'RecordDeliveryPaymentRequest', 'clientEventId'),
|
||||||
|
expectedAmountCents: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
expectedAmountCents,
|
||||||
|
r'RecordDeliveryPaymentRequest',
|
||||||
|
'expectedAmountCents'),
|
||||||
|
paymentMethodId: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
paymentMethodId,
|
||||||
|
r'RecordDeliveryPaymentRequest',
|
||||||
|
'paymentMethodId'),
|
||||||
|
);
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package,type=lint
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
|
||||||
|
part 'resolve_review_request.g.dart';
|
||||||
|
|
||||||
|
/// ResolveReviewRequest
|
||||||
|
///
|
||||||
|
/// Properties:
|
||||||
|
/// * [note] - Optionale Notiz zur getroffenen Entscheidung.
|
||||||
|
/// * [resolvedBy] - Bearbeiter (Name/Kürzel), der die Prüfung bestätigt.
|
||||||
|
@BuiltValue()
|
||||||
|
abstract class ResolveReviewRequest implements Built<ResolveReviewRequest, ResolveReviewRequestBuilder> {
|
||||||
|
/// Optionale Notiz zur getroffenen Entscheidung.
|
||||||
|
@BuiltValueField(wireName: r'note')
|
||||||
|
String? get note;
|
||||||
|
|
||||||
|
/// Bearbeiter (Name/Kürzel), der die Prüfung bestätigt.
|
||||||
|
@BuiltValueField(wireName: r'resolved_by')
|
||||||
|
String get resolvedBy;
|
||||||
|
|
||||||
|
ResolveReviewRequest._();
|
||||||
|
|
||||||
|
factory ResolveReviewRequest([void updates(ResolveReviewRequestBuilder b)]) = _$ResolveReviewRequest;
|
||||||
|
|
||||||
|
@BuiltValueHook(initializeBuilder: true)
|
||||||
|
static void _defaults(ResolveReviewRequestBuilder b) => b;
|
||||||
|
|
||||||
|
@BuiltValueSerializer(custom: true)
|
||||||
|
static Serializer<ResolveReviewRequest> get serializer => _$ResolveReviewRequestSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$ResolveReviewRequestSerializer implements PrimitiveSerializer<ResolveReviewRequest> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [ResolveReviewRequest, _$ResolveReviewRequest];
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String wireName = r'ResolveReviewRequest';
|
||||||
|
|
||||||
|
Iterable<Object?> _serializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
ResolveReviewRequest object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) sync* {
|
||||||
|
if (object.note != null) {
|
||||||
|
yield r'note';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.note,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
yield r'resolved_by';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.resolvedBy,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object serialize(
|
||||||
|
Serializers serializers,
|
||||||
|
ResolveReviewRequest object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
return _serializeProperties(serializers, object, specifiedType: specifiedType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deserializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
required List<Object?> serializedList,
|
||||||
|
required ResolveReviewRequestBuilder result,
|
||||||
|
required List<Object?> unhandled,
|
||||||
|
}) {
|
||||||
|
for (var i = 0; i < serializedList.length; i += 2) {
|
||||||
|
final key = serializedList[i] as String;
|
||||||
|
final value = serializedList[i + 1];
|
||||||
|
switch (key) {
|
||||||
|
case r'note':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
) as String?;
|
||||||
|
if (valueDes == null) continue;
|
||||||
|
result.note = valueDes;
|
||||||
|
break;
|
||||||
|
case r'resolved_by':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.resolvedBy = valueDes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unhandled.add(key);
|
||||||
|
unhandled.add(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ResolveReviewRequest deserialize(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
final result = ResolveReviewRequestBuilder();
|
||||||
|
final serializedList = (serialized as Iterable<Object?>).toList();
|
||||||
|
final unhandled = <Object?>[];
|
||||||
|
_deserializeProperties(
|
||||||
|
serializers,
|
||||||
|
serialized,
|
||||||
|
specifiedType: specifiedType,
|
||||||
|
serializedList: serializedList,
|
||||||
|
unhandled: unhandled,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'resolve_review_request.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class _$ResolveReviewRequest extends ResolveReviewRequest {
|
||||||
|
@override
|
||||||
|
final String? note;
|
||||||
|
@override
|
||||||
|
final String resolvedBy;
|
||||||
|
|
||||||
|
factory _$ResolveReviewRequest(
|
||||||
|
[void Function(ResolveReviewRequestBuilder)? updates]) =>
|
||||||
|
(ResolveReviewRequestBuilder()..update(updates))._build();
|
||||||
|
|
||||||
|
_$ResolveReviewRequest._({this.note, required this.resolvedBy}) : super._();
|
||||||
|
@override
|
||||||
|
ResolveReviewRequest rebuild(
|
||||||
|
void Function(ResolveReviewRequestBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
ResolveReviewRequestBuilder toBuilder() =>
|
||||||
|
ResolveReviewRequestBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is ResolveReviewRequest &&
|
||||||
|
note == other.note &&
|
||||||
|
resolvedBy == other.resolvedBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var _$hash = 0;
|
||||||
|
_$hash = $jc(_$hash, note.hashCode);
|
||||||
|
_$hash = $jc(_$hash, resolvedBy.hashCode);
|
||||||
|
_$hash = $jf(_$hash);
|
||||||
|
return _$hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper(r'ResolveReviewRequest')
|
||||||
|
..add('note', note)
|
||||||
|
..add('resolvedBy', resolvedBy))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResolveReviewRequestBuilder
|
||||||
|
implements Builder<ResolveReviewRequest, ResolveReviewRequestBuilder> {
|
||||||
|
_$ResolveReviewRequest? _$v;
|
||||||
|
|
||||||
|
String? _note;
|
||||||
|
String? get note => _$this._note;
|
||||||
|
set note(String? note) => _$this._note = note;
|
||||||
|
|
||||||
|
String? _resolvedBy;
|
||||||
|
String? get resolvedBy => _$this._resolvedBy;
|
||||||
|
set resolvedBy(String? resolvedBy) => _$this._resolvedBy = resolvedBy;
|
||||||
|
|
||||||
|
ResolveReviewRequestBuilder() {
|
||||||
|
ResolveReviewRequest._defaults(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolveReviewRequestBuilder get _$this {
|
||||||
|
final $v = _$v;
|
||||||
|
if ($v != null) {
|
||||||
|
_note = $v.note;
|
||||||
|
_resolvedBy = $v.resolvedBy;
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(ResolveReviewRequest other) {
|
||||||
|
_$v = other as _$ResolveReviewRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(ResolveReviewRequestBuilder)? updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ResolveReviewRequest build() => _build();
|
||||||
|
|
||||||
|
_$ResolveReviewRequest _build() {
|
||||||
|
final _$result = _$v ??
|
||||||
|
_$ResolveReviewRequest._(
|
||||||
|
note: note,
|
||||||
|
resolvedBy: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
resolvedBy, r'ResolveReviewRequest', 'resolvedBy'),
|
||||||
|
);
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package,type=lint
|
||||||
@ -0,0 +1,189 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element
|
||||||
|
import 'package:built_value/built_value.dart';
|
||||||
|
import 'package:built_value/serializer.dart';
|
||||||
|
|
||||||
|
part 'reviewed_item_response.g.dart';
|
||||||
|
|
||||||
|
/// ReviewedItemResponse
|
||||||
|
///
|
||||||
|
/// Properties:
|
||||||
|
/// * [articleName]
|
||||||
|
/// * [artikelNr]
|
||||||
|
/// * [belegzeilenNr]
|
||||||
|
/// * [creditedQuantity]
|
||||||
|
/// * [reason]
|
||||||
|
/// * [requiredQuantity]
|
||||||
|
@BuiltValue()
|
||||||
|
abstract class ReviewedItemResponse implements Built<ReviewedItemResponse, ReviewedItemResponseBuilder> {
|
||||||
|
@BuiltValueField(wireName: r'article_name')
|
||||||
|
String get articleName;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'artikel_nr')
|
||||||
|
String get artikelNr;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'belegzeilen_nr')
|
||||||
|
int get belegzeilenNr;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'credited_quantity')
|
||||||
|
int get creditedQuantity;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'reason')
|
||||||
|
String? get reason;
|
||||||
|
|
||||||
|
@BuiltValueField(wireName: r'required_quantity')
|
||||||
|
int get requiredQuantity;
|
||||||
|
|
||||||
|
ReviewedItemResponse._();
|
||||||
|
|
||||||
|
factory ReviewedItemResponse([void updates(ReviewedItemResponseBuilder b)]) = _$ReviewedItemResponse;
|
||||||
|
|
||||||
|
@BuiltValueHook(initializeBuilder: true)
|
||||||
|
static void _defaults(ReviewedItemResponseBuilder b) => b;
|
||||||
|
|
||||||
|
@BuiltValueSerializer(custom: true)
|
||||||
|
static Serializer<ReviewedItemResponse> get serializer => _$ReviewedItemResponseSerializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _$ReviewedItemResponseSerializer implements PrimitiveSerializer<ReviewedItemResponse> {
|
||||||
|
@override
|
||||||
|
final Iterable<Type> types = const [ReviewedItemResponse, _$ReviewedItemResponse];
|
||||||
|
|
||||||
|
@override
|
||||||
|
final String wireName = r'ReviewedItemResponse';
|
||||||
|
|
||||||
|
Iterable<Object?> _serializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
ReviewedItemResponse object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) sync* {
|
||||||
|
yield r'article_name';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.articleName,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'artikel_nr';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.artikelNr,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
);
|
||||||
|
yield r'belegzeilen_nr';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.belegzeilenNr,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
);
|
||||||
|
yield r'credited_quantity';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.creditedQuantity,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
);
|
||||||
|
if (object.reason != null) {
|
||||||
|
yield r'reason';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.reason,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
yield r'required_quantity';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.requiredQuantity,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Object serialize(
|
||||||
|
Serializers serializers,
|
||||||
|
ReviewedItemResponse object, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
return _serializeProperties(serializers, object, specifiedType: specifiedType).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _deserializeProperties(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
required List<Object?> serializedList,
|
||||||
|
required ReviewedItemResponseBuilder result,
|
||||||
|
required List<Object?> unhandled,
|
||||||
|
}) {
|
||||||
|
for (var i = 0; i < serializedList.length; i += 2) {
|
||||||
|
final key = serializedList[i] as String;
|
||||||
|
final value = serializedList[i + 1];
|
||||||
|
switch (key) {
|
||||||
|
case r'article_name':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.articleName = valueDes;
|
||||||
|
break;
|
||||||
|
case r'artikel_nr':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(String),
|
||||||
|
) as String;
|
||||||
|
result.artikelNr = valueDes;
|
||||||
|
break;
|
||||||
|
case r'belegzeilen_nr':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
) as int;
|
||||||
|
result.belegzeilenNr = valueDes;
|
||||||
|
break;
|
||||||
|
case r'credited_quantity':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
) as int;
|
||||||
|
result.creditedQuantity = valueDes;
|
||||||
|
break;
|
||||||
|
case r'reason':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType.nullable(String),
|
||||||
|
) as String?;
|
||||||
|
if (valueDes == null) continue;
|
||||||
|
result.reason = valueDes;
|
||||||
|
break;
|
||||||
|
case r'required_quantity':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(int),
|
||||||
|
) as int;
|
||||||
|
result.requiredQuantity = valueDes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unhandled.add(key);
|
||||||
|
unhandled.add(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReviewedItemResponse deserialize(
|
||||||
|
Serializers serializers,
|
||||||
|
Object serialized, {
|
||||||
|
FullType specifiedType = FullType.unspecified,
|
||||||
|
}) {
|
||||||
|
final result = ReviewedItemResponseBuilder();
|
||||||
|
final serializedList = (serialized as Iterable<Object?>).toList();
|
||||||
|
final unhandled = <Object?>[];
|
||||||
|
_deserializeProperties(
|
||||||
|
serializers,
|
||||||
|
serialized,
|
||||||
|
specifiedType: specifiedType,
|
||||||
|
serializedList: serializedList,
|
||||||
|
unhandled: unhandled,
|
||||||
|
result: result,
|
||||||
|
);
|
||||||
|
return result.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,164 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'reviewed_item_response.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// BuiltValueGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class _$ReviewedItemResponse extends ReviewedItemResponse {
|
||||||
|
@override
|
||||||
|
final String articleName;
|
||||||
|
@override
|
||||||
|
final String artikelNr;
|
||||||
|
@override
|
||||||
|
final int belegzeilenNr;
|
||||||
|
@override
|
||||||
|
final int creditedQuantity;
|
||||||
|
@override
|
||||||
|
final String? reason;
|
||||||
|
@override
|
||||||
|
final int requiredQuantity;
|
||||||
|
|
||||||
|
factory _$ReviewedItemResponse(
|
||||||
|
[void Function(ReviewedItemResponseBuilder)? updates]) =>
|
||||||
|
(ReviewedItemResponseBuilder()..update(updates))._build();
|
||||||
|
|
||||||
|
_$ReviewedItemResponse._(
|
||||||
|
{required this.articleName,
|
||||||
|
required this.artikelNr,
|
||||||
|
required this.belegzeilenNr,
|
||||||
|
required this.creditedQuantity,
|
||||||
|
this.reason,
|
||||||
|
required this.requiredQuantity})
|
||||||
|
: super._();
|
||||||
|
@override
|
||||||
|
ReviewedItemResponse rebuild(
|
||||||
|
void Function(ReviewedItemResponseBuilder) updates) =>
|
||||||
|
(toBuilder()..update(updates)).build();
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReviewedItemResponseBuilder toBuilder() =>
|
||||||
|
ReviewedItemResponseBuilder()..replace(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(other, this)) return true;
|
||||||
|
return other is ReviewedItemResponse &&
|
||||||
|
articleName == other.articleName &&
|
||||||
|
artikelNr == other.artikelNr &&
|
||||||
|
belegzeilenNr == other.belegzeilenNr &&
|
||||||
|
creditedQuantity == other.creditedQuantity &&
|
||||||
|
reason == other.reason &&
|
||||||
|
requiredQuantity == other.requiredQuantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var _$hash = 0;
|
||||||
|
_$hash = $jc(_$hash, articleName.hashCode);
|
||||||
|
_$hash = $jc(_$hash, artikelNr.hashCode);
|
||||||
|
_$hash = $jc(_$hash, belegzeilenNr.hashCode);
|
||||||
|
_$hash = $jc(_$hash, creditedQuantity.hashCode);
|
||||||
|
_$hash = $jc(_$hash, reason.hashCode);
|
||||||
|
_$hash = $jc(_$hash, requiredQuantity.hashCode);
|
||||||
|
_$hash = $jf(_$hash);
|
||||||
|
return _$hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (newBuiltValueToStringHelper(r'ReviewedItemResponse')
|
||||||
|
..add('articleName', articleName)
|
||||||
|
..add('artikelNr', artikelNr)
|
||||||
|
..add('belegzeilenNr', belegzeilenNr)
|
||||||
|
..add('creditedQuantity', creditedQuantity)
|
||||||
|
..add('reason', reason)
|
||||||
|
..add('requiredQuantity', requiredQuantity))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReviewedItemResponseBuilder
|
||||||
|
implements Builder<ReviewedItemResponse, ReviewedItemResponseBuilder> {
|
||||||
|
_$ReviewedItemResponse? _$v;
|
||||||
|
|
||||||
|
String? _articleName;
|
||||||
|
String? get articleName => _$this._articleName;
|
||||||
|
set articleName(String? articleName) => _$this._articleName = articleName;
|
||||||
|
|
||||||
|
String? _artikelNr;
|
||||||
|
String? get artikelNr => _$this._artikelNr;
|
||||||
|
set artikelNr(String? artikelNr) => _$this._artikelNr = artikelNr;
|
||||||
|
|
||||||
|
int? _belegzeilenNr;
|
||||||
|
int? get belegzeilenNr => _$this._belegzeilenNr;
|
||||||
|
set belegzeilenNr(int? belegzeilenNr) =>
|
||||||
|
_$this._belegzeilenNr = belegzeilenNr;
|
||||||
|
|
||||||
|
int? _creditedQuantity;
|
||||||
|
int? get creditedQuantity => _$this._creditedQuantity;
|
||||||
|
set creditedQuantity(int? creditedQuantity) =>
|
||||||
|
_$this._creditedQuantity = creditedQuantity;
|
||||||
|
|
||||||
|
String? _reason;
|
||||||
|
String? get reason => _$this._reason;
|
||||||
|
set reason(String? reason) => _$this._reason = reason;
|
||||||
|
|
||||||
|
int? _requiredQuantity;
|
||||||
|
int? get requiredQuantity => _$this._requiredQuantity;
|
||||||
|
set requiredQuantity(int? requiredQuantity) =>
|
||||||
|
_$this._requiredQuantity = requiredQuantity;
|
||||||
|
|
||||||
|
ReviewedItemResponseBuilder() {
|
||||||
|
ReviewedItemResponse._defaults(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReviewedItemResponseBuilder get _$this {
|
||||||
|
final $v = _$v;
|
||||||
|
if ($v != null) {
|
||||||
|
_articleName = $v.articleName;
|
||||||
|
_artikelNr = $v.artikelNr;
|
||||||
|
_belegzeilenNr = $v.belegzeilenNr;
|
||||||
|
_creditedQuantity = $v.creditedQuantity;
|
||||||
|
_reason = $v.reason;
|
||||||
|
_requiredQuantity = $v.requiredQuantity;
|
||||||
|
_$v = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(ReviewedItemResponse other) {
|
||||||
|
_$v = other as _$ReviewedItemResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void update(void Function(ReviewedItemResponseBuilder)? updates) {
|
||||||
|
if (updates != null) updates(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ReviewedItemResponse build() => _build();
|
||||||
|
|
||||||
|
_$ReviewedItemResponse _build() {
|
||||||
|
final _$result = _$v ??
|
||||||
|
_$ReviewedItemResponse._(
|
||||||
|
articleName: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
articleName, r'ReviewedItemResponse', 'articleName'),
|
||||||
|
artikelNr: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
artikelNr, r'ReviewedItemResponse', 'artikelNr'),
|
||||||
|
belegzeilenNr: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
belegzeilenNr, r'ReviewedItemResponse', 'belegzeilenNr'),
|
||||||
|
creditedQuantity: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
creditedQuantity, r'ReviewedItemResponse', 'creditedQuantity'),
|
||||||
|
reason: reason,
|
||||||
|
requiredQuantity: BuiltValueNullFieldError.checkNotNull(
|
||||||
|
requiredQuantity, r'ReviewedItemResponse', 'requiredQuantity'),
|
||||||
|
);
|
||||||
|
replace(_$result);
|
||||||
|
return _$result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: deprecated_member_use_from_same_package,type=lint
|
||||||
@ -6,6 +6,7 @@
|
|||||||
import 'package:holzleitner_api/src/model/delivery_credit.dart';
|
import 'package:holzleitner_api/src/model/delivery_credit.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_note.dart';
|
import 'package:holzleitner_api/src/model/delivery_note.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_with_items.dart';
|
import 'package:holzleitner_api/src/model/delivery_with_items.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_payment.dart';
|
||||||
import 'package:holzleitner_api/src/model/article.dart';
|
import 'package:holzleitner_api/src/model/article.dart';
|
||||||
import 'package:holzleitner_api/src/model/contact_channel.dart';
|
import 'package:holzleitner_api/src/model/contact_channel.dart';
|
||||||
import 'package:holzleitner_api/src/model/customer.dart';
|
import 'package:holzleitner_api/src/model/customer.dart';
|
||||||
@ -33,6 +34,7 @@ part 'tour_details.g.dart';
|
|||||||
/// * [deliveries]
|
/// * [deliveries]
|
||||||
/// * [deliveryServices] - Pro-Lieferung gesetzte Service-Werte. Join per `delivery_id` + `service_id`.
|
/// * [deliveryServices] - Pro-Lieferung gesetzte Service-Werte. Join per `delivery_id` + `service_id`.
|
||||||
/// * [notes] - Alle Notizen aller Lieferungen dieser Tour, in einer Liste. Die App joint clientseitig per `delivery_id`. Reihenfolge: pro Lieferung aufsteigend nach `created_at`.
|
/// * [notes] - Alle Notizen aller Lieferungen dieser Tour, in einer Liste. Die App joint clientseitig per `delivery_id`. Reihenfolge: pro Lieferung aufsteigend nach `created_at`.
|
||||||
|
/// * [payments] - Jüngste protokollierte Zahlungsabwicklung pro Lieferung (nur Lieferungen mit mindestens einem Eintrag). Join per `delivery_id`.
|
||||||
/// * [services] - Aktive Service-Definitionen (Stammdaten) — die App rendert daraus Phase 4. Bewusst hier mitgeliefert, damit die Detailseite alles aus dem Tour-Aggregat hat.
|
/// * [services] - Aktive Service-Definitionen (Stammdaten) — die App rendert daraus Phase 4. Bewusst hier mitgeliefert, damit die Detailseite alles aus dem Tour-Aggregat hat.
|
||||||
/// * [tour]
|
/// * [tour]
|
||||||
/// * [warehouses]
|
/// * [warehouses]
|
||||||
@ -70,6 +72,10 @@ abstract class TourDetails implements Built<TourDetails, TourDetailsBuilder> {
|
|||||||
@BuiltValueField(wireName: r'notes')
|
@BuiltValueField(wireName: r'notes')
|
||||||
BuiltList<DeliveryNote> get notes;
|
BuiltList<DeliveryNote> get notes;
|
||||||
|
|
||||||
|
/// Jüngste protokollierte Zahlungsabwicklung pro Lieferung (nur Lieferungen mit mindestens einem Eintrag). Join per `delivery_id`.
|
||||||
|
@BuiltValueField(wireName: r'payments')
|
||||||
|
BuiltList<DeliveryPayment> get payments;
|
||||||
|
|
||||||
/// Aktive Service-Definitionen (Stammdaten) — die App rendert daraus Phase 4. Bewusst hier mitgeliefert, damit die Detailseite alles aus dem Tour-Aggregat hat.
|
/// Aktive Service-Definitionen (Stammdaten) — die App rendert daraus Phase 4. Bewusst hier mitgeliefert, damit die Detailseite alles aus dem Tour-Aggregat hat.
|
||||||
@BuiltValueField(wireName: r'services')
|
@BuiltValueField(wireName: r'services')
|
||||||
BuiltList<Service> get services;
|
BuiltList<Service> get services;
|
||||||
@ -148,6 +154,11 @@ class _$TourDetailsSerializer implements PrimitiveSerializer<TourDetails> {
|
|||||||
object.notes,
|
object.notes,
|
||||||
specifiedType: const FullType(BuiltList, [FullType(DeliveryNote)]),
|
specifiedType: const FullType(BuiltList, [FullType(DeliveryNote)]),
|
||||||
);
|
);
|
||||||
|
yield r'payments';
|
||||||
|
yield serializers.serialize(
|
||||||
|
object.payments,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(DeliveryPayment)]),
|
||||||
|
);
|
||||||
yield r'services';
|
yield r'services';
|
||||||
yield serializers.serialize(
|
yield serializers.serialize(
|
||||||
object.services,
|
object.services,
|
||||||
@ -249,6 +260,13 @@ class _$TourDetailsSerializer implements PrimitiveSerializer<TourDetails> {
|
|||||||
) as BuiltList<DeliveryNote>;
|
) as BuiltList<DeliveryNote>;
|
||||||
result.notes.replace(valueDes);
|
result.notes.replace(valueDes);
|
||||||
break;
|
break;
|
||||||
|
case r'payments':
|
||||||
|
final valueDes = serializers.deserialize(
|
||||||
|
value,
|
||||||
|
specifiedType: const FullType(BuiltList, [FullType(DeliveryPayment)]),
|
||||||
|
) as BuiltList<DeliveryPayment>;
|
||||||
|
result.payments.replace(valueDes);
|
||||||
|
break;
|
||||||
case r'services':
|
case r'services':
|
||||||
final valueDes = serializers.deserialize(
|
final valueDes = serializers.deserialize(
|
||||||
value,
|
value,
|
||||||
|
|||||||
@ -26,6 +26,8 @@ class _$TourDetails extends TourDetails {
|
|||||||
@override
|
@override
|
||||||
final BuiltList<DeliveryNote> notes;
|
final BuiltList<DeliveryNote> notes;
|
||||||
@override
|
@override
|
||||||
|
final BuiltList<DeliveryPayment> payments;
|
||||||
|
@override
|
||||||
final BuiltList<Service> services;
|
final BuiltList<Service> services;
|
||||||
@override
|
@override
|
||||||
final Tour tour;
|
final Tour tour;
|
||||||
@ -45,6 +47,7 @@ class _$TourDetails extends TourDetails {
|
|||||||
required this.deliveries,
|
required this.deliveries,
|
||||||
required this.deliveryServices,
|
required this.deliveryServices,
|
||||||
required this.notes,
|
required this.notes,
|
||||||
|
required this.payments,
|
||||||
required this.services,
|
required this.services,
|
||||||
required this.tour,
|
required this.tour,
|
||||||
required this.warehouses})
|
required this.warehouses})
|
||||||
@ -69,6 +72,7 @@ class _$TourDetails extends TourDetails {
|
|||||||
deliveries == other.deliveries &&
|
deliveries == other.deliveries &&
|
||||||
deliveryServices == other.deliveryServices &&
|
deliveryServices == other.deliveryServices &&
|
||||||
notes == other.notes &&
|
notes == other.notes &&
|
||||||
|
payments == other.payments &&
|
||||||
services == other.services &&
|
services == other.services &&
|
||||||
tour == other.tour &&
|
tour == other.tour &&
|
||||||
warehouses == other.warehouses;
|
warehouses == other.warehouses;
|
||||||
@ -86,6 +90,7 @@ class _$TourDetails extends TourDetails {
|
|||||||
_$hash = $jc(_$hash, deliveries.hashCode);
|
_$hash = $jc(_$hash, deliveries.hashCode);
|
||||||
_$hash = $jc(_$hash, deliveryServices.hashCode);
|
_$hash = $jc(_$hash, deliveryServices.hashCode);
|
||||||
_$hash = $jc(_$hash, notes.hashCode);
|
_$hash = $jc(_$hash, notes.hashCode);
|
||||||
|
_$hash = $jc(_$hash, payments.hashCode);
|
||||||
_$hash = $jc(_$hash, services.hashCode);
|
_$hash = $jc(_$hash, services.hashCode);
|
||||||
_$hash = $jc(_$hash, tour.hashCode);
|
_$hash = $jc(_$hash, tour.hashCode);
|
||||||
_$hash = $jc(_$hash, warehouses.hashCode);
|
_$hash = $jc(_$hash, warehouses.hashCode);
|
||||||
@ -105,6 +110,7 @@ class _$TourDetails extends TourDetails {
|
|||||||
..add('deliveries', deliveries)
|
..add('deliveries', deliveries)
|
||||||
..add('deliveryServices', deliveryServices)
|
..add('deliveryServices', deliveryServices)
|
||||||
..add('notes', notes)
|
..add('notes', notes)
|
||||||
|
..add('payments', payments)
|
||||||
..add('services', services)
|
..add('services', services)
|
||||||
..add('tour', tour)
|
..add('tour', tour)
|
||||||
..add('warehouses', warehouses))
|
..add('warehouses', warehouses))
|
||||||
@ -167,6 +173,12 @@ class TourDetailsBuilder implements Builder<TourDetails, TourDetailsBuilder> {
|
|||||||
_$this._notes ??= ListBuilder<DeliveryNote>();
|
_$this._notes ??= ListBuilder<DeliveryNote>();
|
||||||
set notes(ListBuilder<DeliveryNote>? notes) => _$this._notes = notes;
|
set notes(ListBuilder<DeliveryNote>? notes) => _$this._notes = notes;
|
||||||
|
|
||||||
|
ListBuilder<DeliveryPayment>? _payments;
|
||||||
|
ListBuilder<DeliveryPayment> get payments =>
|
||||||
|
_$this._payments ??= ListBuilder<DeliveryPayment>();
|
||||||
|
set payments(ListBuilder<DeliveryPayment>? payments) =>
|
||||||
|
_$this._payments = payments;
|
||||||
|
|
||||||
ListBuilder<Service>? _services;
|
ListBuilder<Service>? _services;
|
||||||
ListBuilder<Service> get services =>
|
ListBuilder<Service> get services =>
|
||||||
_$this._services ??= ListBuilder<Service>();
|
_$this._services ??= ListBuilder<Service>();
|
||||||
@ -198,6 +210,7 @@ class TourDetailsBuilder implements Builder<TourDetails, TourDetailsBuilder> {
|
|||||||
_deliveries = $v.deliveries.toBuilder();
|
_deliveries = $v.deliveries.toBuilder();
|
||||||
_deliveryServices = $v.deliveryServices.toBuilder();
|
_deliveryServices = $v.deliveryServices.toBuilder();
|
||||||
_notes = $v.notes.toBuilder();
|
_notes = $v.notes.toBuilder();
|
||||||
|
_payments = $v.payments.toBuilder();
|
||||||
_services = $v.services.toBuilder();
|
_services = $v.services.toBuilder();
|
||||||
_tour = $v.tour.toBuilder();
|
_tour = $v.tour.toBuilder();
|
||||||
_warehouses = $v.warehouses.toBuilder();
|
_warehouses = $v.warehouses.toBuilder();
|
||||||
@ -233,6 +246,7 @@ class TourDetailsBuilder implements Builder<TourDetails, TourDetailsBuilder> {
|
|||||||
deliveries: deliveries.build(),
|
deliveries: deliveries.build(),
|
||||||
deliveryServices: deliveryServices.build(),
|
deliveryServices: deliveryServices.build(),
|
||||||
notes: notes.build(),
|
notes: notes.build(),
|
||||||
|
payments: payments.build(),
|
||||||
services: services.build(),
|
services: services.build(),
|
||||||
tour: tour.build(),
|
tour: tour.build(),
|
||||||
warehouses: warehouses.build(),
|
warehouses: warehouses.build(),
|
||||||
@ -258,6 +272,8 @@ class TourDetailsBuilder implements Builder<TourDetails, TourDetailsBuilder> {
|
|||||||
deliveryServices.build();
|
deliveryServices.build();
|
||||||
_$failedField = 'notes';
|
_$failedField = 'notes';
|
||||||
notes.build();
|
notes.build();
|
||||||
|
_$failedField = 'payments';
|
||||||
|
payments.build();
|
||||||
_$failedField = 'services';
|
_$failedField = 'services';
|
||||||
services.build();
|
services.build();
|
||||||
_$failedField = 'tour';
|
_$failedField = 'tour';
|
||||||
|
|||||||
@ -26,6 +26,8 @@ import 'package:holzleitner_api/src/model/car.dart';
|
|||||||
import 'package:holzleitner_api/src/model/car_response.dart';
|
import 'package:holzleitner_api/src/model/car_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/cars_list.dart';
|
import 'package:holzleitner_api/src/model/cars_list.dart';
|
||||||
import 'package:holzleitner_api/src/model/complete_delivery_acknowledgements.dart';
|
import 'package:holzleitner_api/src/model/complete_delivery_acknowledgements.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/completed_deliveries_response.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/completed_delivery_item.dart';
|
||||||
import 'package:holzleitner_api/src/model/contact_channel.dart';
|
import 'package:holzleitner_api/src/model/contact_channel.dart';
|
||||||
import 'package:holzleitner_api/src/model/contact_kind.dart';
|
import 'package:holzleitner_api/src/model/contact_kind.dart';
|
||||||
import 'package:holzleitner_api/src/model/contact_role.dart';
|
import 'package:holzleitner_api/src/model/contact_role.dart';
|
||||||
@ -42,10 +44,13 @@ import 'package:holzleitner_api/src/model/delivery.dart';
|
|||||||
import 'package:holzleitner_api/src/model/delivery_credit.dart';
|
import 'package:holzleitner_api/src/model/delivery_credit.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_credit_event_request.dart';
|
import 'package:holzleitner_api/src/model/delivery_credit_event_request.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_credit_response.dart';
|
import 'package:holzleitner_api/src/model/delivery_credit_response.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_details.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_item.dart';
|
import 'package:holzleitner_api/src/model/delivery_item.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_note.dart';
|
import 'package:holzleitner_api/src/model/delivery_note.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_note_response.dart';
|
import 'package:holzleitner_api/src/model/delivery_note_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_order_entry.dart';
|
import 'package:holzleitner_api/src/model/delivery_order_entry.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_payment.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/delivery_payment_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_response.dart';
|
import 'package:holzleitner_api/src/model/delivery_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_service_response.dart';
|
import 'package:holzleitner_api/src/model/delivery_service_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/delivery_service_value.dart';
|
import 'package:holzleitner_api/src/model/delivery_service_value.dart';
|
||||||
@ -58,6 +63,11 @@ import 'package:holzleitner_api/src/model/mark_mail_sent_response.dart';
|
|||||||
import 'package:holzleitner_api/src/model/payment_method.dart';
|
import 'package:holzleitner_api/src/model/payment_method.dart';
|
||||||
import 'package:holzleitner_api/src/model/payment_method_response.dart';
|
import 'package:holzleitner_api/src/model/payment_method_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/payment_methods_list.dart';
|
import 'package:holzleitner_api/src/model/payment_methods_list.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/pending_review_response.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/positions_modified_response.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/record_delivery_payment_request.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/resolve_review_request.dart';
|
||||||
|
import 'package:holzleitner_api/src/model/reviewed_item_response.dart';
|
||||||
import 'package:holzleitner_api/src/model/scan_event.dart';
|
import 'package:holzleitner_api/src/model/scan_event.dart';
|
||||||
import 'package:holzleitner_api/src/model/scan_result.dart';
|
import 'package:holzleitner_api/src/model/scan_result.dart';
|
||||||
import 'package:holzleitner_api/src/model/scan_result_status.dart';
|
import 'package:holzleitner_api/src/model/scan_result_status.dart';
|
||||||
@ -101,6 +111,8 @@ part 'serializers.g.dart';
|
|||||||
CarResponse,
|
CarResponse,
|
||||||
CarsList,
|
CarsList,
|
||||||
CompleteDeliveryAcknowledgements,
|
CompleteDeliveryAcknowledgements,
|
||||||
|
CompletedDeliveriesResponse,
|
||||||
|
CompletedDeliveryItem,
|
||||||
ContactChannel,
|
ContactChannel,
|
||||||
ContactKind,
|
ContactKind,
|
||||||
ContactRole,
|
ContactRole,
|
||||||
@ -117,10 +129,13 @@ part 'serializers.g.dart';
|
|||||||
DeliveryCredit,
|
DeliveryCredit,
|
||||||
DeliveryCreditEventRequest,
|
DeliveryCreditEventRequest,
|
||||||
DeliveryCreditResponse,
|
DeliveryCreditResponse,
|
||||||
|
DeliveryDetails,
|
||||||
DeliveryItem,
|
DeliveryItem,
|
||||||
DeliveryNote,
|
DeliveryNote,
|
||||||
DeliveryNoteResponse,
|
DeliveryNoteResponse,
|
||||||
DeliveryOrderEntry,
|
DeliveryOrderEntry,
|
||||||
|
DeliveryPayment,
|
||||||
|
DeliveryPaymentResponse,
|
||||||
DeliveryResponse,
|
DeliveryResponse,
|
||||||
DeliveryServiceResponse,
|
DeliveryServiceResponse,
|
||||||
DeliveryServiceValue,
|
DeliveryServiceValue,
|
||||||
@ -133,6 +148,11 @@ part 'serializers.g.dart';
|
|||||||
PaymentMethod,
|
PaymentMethod,
|
||||||
PaymentMethodResponse,
|
PaymentMethodResponse,
|
||||||
PaymentMethodsList,
|
PaymentMethodsList,
|
||||||
|
PendingReviewResponse,
|
||||||
|
PositionsModifiedResponse,
|
||||||
|
RecordDeliveryPaymentRequest,
|
||||||
|
ResolveReviewRequest,
|
||||||
|
ReviewedItemResponse,
|
||||||
ScanEvent,
|
ScanEvent,
|
||||||
ScanResult,
|
ScanResult,
|
||||||
ScanResultStatus,
|
ScanResultStatus,
|
||||||
@ -162,6 +182,10 @@ part 'serializers.g.dart';
|
|||||||
Warehouse,
|
Warehouse,
|
||||||
])
|
])
|
||||||
Serializers serializers = (_$serializers.toBuilder()
|
Serializers serializers = (_$serializers.toBuilder()
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(BuiltList, [FullType(PendingReviewResponse)]),
|
||||||
|
() => ListBuilder<PendingReviewResponse>(),
|
||||||
|
)
|
||||||
..add(Delivery.serializer)
|
..add(Delivery.serializer)
|
||||||
..add(const OneOfSerializer())
|
..add(const OneOfSerializer())
|
||||||
..add(const AnyOfSerializer())
|
..add(const AnyOfSerializer())
|
||||||
|
|||||||
@ -20,6 +20,8 @@ Serializers _$serializers = (Serializers().toBuilder()
|
|||||||
..add(CarResponse.serializer)
|
..add(CarResponse.serializer)
|
||||||
..add(CarsList.serializer)
|
..add(CarsList.serializer)
|
||||||
..add(CompleteDeliveryAcknowledgements.serializer)
|
..add(CompleteDeliveryAcknowledgements.serializer)
|
||||||
|
..add(CompletedDeliveriesResponse.serializer)
|
||||||
|
..add(CompletedDeliveryItem.serializer)
|
||||||
..add(ContactChannel.serializer)
|
..add(ContactChannel.serializer)
|
||||||
..add(ContactKind.serializer)
|
..add(ContactKind.serializer)
|
||||||
..add(ContactRole.serializer)
|
..add(ContactRole.serializer)
|
||||||
@ -35,10 +37,13 @@ Serializers _$serializers = (Serializers().toBuilder()
|
|||||||
..add(DeliveryCredit.serializer)
|
..add(DeliveryCredit.serializer)
|
||||||
..add(DeliveryCreditEventRequest.serializer)
|
..add(DeliveryCreditEventRequest.serializer)
|
||||||
..add(DeliveryCreditResponse.serializer)
|
..add(DeliveryCreditResponse.serializer)
|
||||||
|
..add(DeliveryDetails.serializer)
|
||||||
..add(DeliveryItem.serializer)
|
..add(DeliveryItem.serializer)
|
||||||
..add(DeliveryNote.serializer)
|
..add(DeliveryNote.serializer)
|
||||||
..add(DeliveryNoteResponse.serializer)
|
..add(DeliveryNoteResponse.serializer)
|
||||||
..add(DeliveryOrderEntry.serializer)
|
..add(DeliveryOrderEntry.serializer)
|
||||||
|
..add(DeliveryPayment.serializer)
|
||||||
|
..add(DeliveryPaymentResponse.serializer)
|
||||||
..add(DeliveryResponse.serializer)
|
..add(DeliveryResponse.serializer)
|
||||||
..add(DeliveryServiceResponse.serializer)
|
..add(DeliveryServiceResponse.serializer)
|
||||||
..add(DeliveryServiceValue.serializer)
|
..add(DeliveryServiceValue.serializer)
|
||||||
@ -51,6 +56,11 @@ Serializers _$serializers = (Serializers().toBuilder()
|
|||||||
..add(PaymentMethod.serializer)
|
..add(PaymentMethod.serializer)
|
||||||
..add(PaymentMethodResponse.serializer)
|
..add(PaymentMethodResponse.serializer)
|
||||||
..add(PaymentMethodsList.serializer)
|
..add(PaymentMethodsList.serializer)
|
||||||
|
..add(PendingReviewResponse.serializer)
|
||||||
|
..add(PositionsModifiedResponse.serializer)
|
||||||
|
..add(RecordDeliveryPaymentRequest.serializer)
|
||||||
|
..add(ResolveReviewRequest.serializer)
|
||||||
|
..add(ReviewedItemResponse.serializer)
|
||||||
..add(ScanEvent.serializer)
|
..add(ScanEvent.serializer)
|
||||||
..add(ScanResult.serializer)
|
..add(ScanResult.serializer)
|
||||||
..add(ScanResultStatus.serializer)
|
..add(ScanResultStatus.serializer)
|
||||||
@ -78,6 +88,31 @@ Serializers _$serializers = (Serializers().toBuilder()
|
|||||||
..add(UpdatePaymentMethodRequest.serializer)
|
..add(UpdatePaymentMethodRequest.serializer)
|
||||||
..add(UpdateServiceRequest.serializer)
|
..add(UpdateServiceRequest.serializer)
|
||||||
..add(Warehouse.serializer)
|
..add(Warehouse.serializer)
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(BuiltList, const [const FullType(Article)]),
|
||||||
|
() => ListBuilder<Article>())
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(BuiltList, const [const FullType(ContactChannel)]),
|
||||||
|
() => ListBuilder<ContactChannel>())
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(BuiltList, const [const FullType(ContactSource)]),
|
||||||
|
() => ListBuilder<ContactSource>())
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(BuiltList, const [const FullType(CustomerContact)]),
|
||||||
|
() => ListBuilder<CustomerContact>())
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(
|
||||||
|
BuiltList, const [const FullType(DeliveryServiceValue)]),
|
||||||
|
() => ListBuilder<DeliveryServiceValue>())
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(BuiltList, const [const FullType(DeliveryNote)]),
|
||||||
|
() => ListBuilder<DeliveryNote>())
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(BuiltList, const [const FullType(Service)]),
|
||||||
|
() => ListBuilder<Service>())
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(BuiltList, const [const FullType(Warehouse)]),
|
||||||
|
() => ListBuilder<Warehouse>())
|
||||||
..addBuilderFactory(
|
..addBuilderFactory(
|
||||||
const FullType(BuiltList, const [const FullType(Article)]),
|
const FullType(BuiltList, const [const FullType(Article)]),
|
||||||
() => ListBuilder<Article>())
|
() => ListBuilder<Article>())
|
||||||
@ -106,6 +141,9 @@ Serializers _$serializers = (Serializers().toBuilder()
|
|||||||
..addBuilderFactory(
|
..addBuilderFactory(
|
||||||
const FullType(BuiltList, const [const FullType(DeliveryNote)]),
|
const FullType(BuiltList, const [const FullType(DeliveryNote)]),
|
||||||
() => ListBuilder<DeliveryNote>())
|
() => ListBuilder<DeliveryNote>())
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(BuiltList, const [const FullType(DeliveryPayment)]),
|
||||||
|
() => ListBuilder<DeliveryPayment>())
|
||||||
..addBuilderFactory(
|
..addBuilderFactory(
|
||||||
const FullType(BuiltList, const [const FullType(Service)]),
|
const FullType(BuiltList, const [const FullType(Service)]),
|
||||||
() => ListBuilder<Service>())
|
() => ListBuilder<Service>())
|
||||||
@ -115,6 +153,10 @@ Serializers _$serializers = (Serializers().toBuilder()
|
|||||||
..addBuilderFactory(
|
..addBuilderFactory(
|
||||||
const FullType(BuiltList, const [const FullType(Car)]),
|
const FullType(BuiltList, const [const FullType(Car)]),
|
||||||
() => ListBuilder<Car>())
|
() => ListBuilder<Car>())
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(
|
||||||
|
BuiltList, const [const FullType(CompletedDeliveryItem)]),
|
||||||
|
() => ListBuilder<CompletedDeliveryItem>())
|
||||||
..addBuilderFactory(
|
..addBuilderFactory(
|
||||||
const FullType(BuiltList, const [const FullType(DeliveryItem)]),
|
const FullType(BuiltList, const [const FullType(DeliveryItem)]),
|
||||||
() => ListBuilder<DeliveryItem>())
|
() => ListBuilder<DeliveryItem>())
|
||||||
@ -127,6 +169,10 @@ Serializers _$serializers = (Serializers().toBuilder()
|
|||||||
..addBuilderFactory(
|
..addBuilderFactory(
|
||||||
const FullType(BuiltList, const [const FullType(PaymentMethod)]),
|
const FullType(BuiltList, const [const FullType(PaymentMethod)]),
|
||||||
() => ListBuilder<PaymentMethod>())
|
() => ListBuilder<PaymentMethod>())
|
||||||
|
..addBuilderFactory(
|
||||||
|
const FullType(
|
||||||
|
BuiltList, const [const FullType(ReviewedItemResponse)]),
|
||||||
|
() => ListBuilder<ReviewedItemResponse>())
|
||||||
..addBuilderFactory(
|
..addBuilderFactory(
|
||||||
const FullType(BuiltList, const [const FullType(ScanEvent)]),
|
const FullType(BuiltList, const [const FullType(ScanEvent)]),
|
||||||
() => ListBuilder<ScanEvent>())
|
() => ListBuilder<ScanEvent>())
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:holzleitner_api/holzleitner_api.dart';
|
||||||
|
|
||||||
|
// tests for CompletedDeliveriesResponse
|
||||||
|
void main() {
|
||||||
|
final instance = CompletedDeliveriesResponseBuilder();
|
||||||
|
// TODO add properties to the builder and call build()
|
||||||
|
|
||||||
|
group(CompletedDeliveriesResponse, () {
|
||||||
|
// Anzahl der abgeschlossenen Lieferungen im Bereich.
|
||||||
|
// int count
|
||||||
|
test('to test the property `count`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Die abgeschlossenen Lieferungen, aufsteigend nach Abschluss-Zeitpunkt.
|
||||||
|
// BuiltList<CompletedDeliveryItem> deliveries
|
||||||
|
test('to test the property `deliveries`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wirksame untere Grenze (ISO `YYYY-MM-DD`) oder `null` (offen).
|
||||||
|
// String from
|
||||||
|
test('to test the property `from`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wirksame obere Grenze (ISO `YYYY-MM-DD`) oder `null` (offen).
|
||||||
|
// String to
|
||||||
|
test('to test the property `to`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:holzleitner_api/holzleitner_api.dart';
|
||||||
|
|
||||||
|
// tests for CompletedDeliveryItem
|
||||||
|
void main() {
|
||||||
|
final instance = CompletedDeliveryItemBuilder();
|
||||||
|
// TODO add properties to the builder and call build()
|
||||||
|
|
||||||
|
group(CompletedDeliveryItem, () {
|
||||||
|
// ERP-Belegnummer der Lieferung.
|
||||||
|
// String belegnummer
|
||||||
|
test('to test the property `belegnummer`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// `true`, wenn an der Lieferung Positionen verändert wurden — eine Zeile wurde entfernt oder in der Menge reduziert (Stück-Gutschrift) **oder** es liegt eine aktive Geld-Gutschrift vor.
|
||||||
|
// bool positionsModified
|
||||||
|
test('to test the property `positionsModified`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
89
packages/holzleitner_api/test/delivery_details_test.dart
Normal file
89
packages/holzleitner_api/test/delivery_details_test.dart
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:holzleitner_api/holzleitner_api.dart';
|
||||||
|
|
||||||
|
// tests for DeliveryDetails
|
||||||
|
void main() {
|
||||||
|
final instance = DeliveryDetailsBuilder();
|
||||||
|
// TODO add properties to the builder and call build()
|
||||||
|
|
||||||
|
group(DeliveryDetails, () {
|
||||||
|
// Nur die von den Positionen referenzierten Artikel.
|
||||||
|
// BuiltList<Article> articles
|
||||||
|
test('to test the property `articles`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Die zu `contactSources` gehörenden Einzel-Kanäle. Join per `sourceId`.
|
||||||
|
// BuiltList<ContactChannel> contactChannels
|
||||||
|
test('to test the property `contactChannels`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Kontaktquellen der Lieferung (Liefer-/Rechnungsadresse, Ansprechpartner …).
|
||||||
|
// BuiltList<ContactSource> contactSources
|
||||||
|
test('to test the property `contactSources`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Aktuelle Betrags-Gutschrift (`null`, wenn keine aktiv).
|
||||||
|
// DeliveryCredit credit
|
||||||
|
test('to test the property `credit`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Der Kunde der Lieferung (`null`, falls unauffindbar — sollte nicht vorkommen).
|
||||||
|
// Customer customer
|
||||||
|
test('to test the property `customer`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ansprechpartner des Kunden.
|
||||||
|
// BuiltList<CustomerContact> customerContacts
|
||||||
|
test('to test the property `customerContacts`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Die Lieferung selbst inkl. Positionen (mit Scan-Ständen) und `sortOrder`.
|
||||||
|
// DeliveryWithItems delivery
|
||||||
|
test('to test the property `delivery`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Für diese Lieferung gesetzte Service-Werte.
|
||||||
|
// BuiltList<DeliveryServiceValue> deliveryServices
|
||||||
|
test('to test the property `deliveryServices`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Notizen der Lieferung, aufsteigend nach `createdAt`.
|
||||||
|
// BuiltList<DeliveryNote> notes
|
||||||
|
test('to test the property `notes`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Jüngste protokollierte Zahlungsabwicklung (`None` = keine).
|
||||||
|
// DeliveryPayment payment
|
||||||
|
test('to test the property `payment`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Aktive Service-Definitionen (Stammdaten).
|
||||||
|
// BuiltList<Service> services
|
||||||
|
test('to test the property `services`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Die Tour, zu der die Lieferung gehört.
|
||||||
|
// Tour tour
|
||||||
|
test('to test the property `tour`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Nur die von den Positionen referenzierten Lager.
|
||||||
|
// BuiltList<Warehouse> warehouses
|
||||||
|
test('to test the property `warehouses`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:holzleitner_api/holzleitner_api.dart';
|
||||||
|
|
||||||
|
// tests for DeliveryPaymentResponse
|
||||||
|
void main() {
|
||||||
|
final instance = DeliveryPaymentResponseBuilder();
|
||||||
|
// TODO add properties to the builder and call build()
|
||||||
|
|
||||||
|
group(DeliveryPaymentResponse, () {
|
||||||
|
// DeliveryPayment payment
|
||||||
|
test('to test the property `payment`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
53
packages/holzleitner_api/test/delivery_payment_test.dart
Normal file
53
packages/holzleitner_api/test/delivery_payment_test.dart
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:holzleitner_api/holzleitner_api.dart';
|
||||||
|
|
||||||
|
// tests for DeliveryPayment
|
||||||
|
void main() {
|
||||||
|
final instance = DeliveryPaymentBuilder();
|
||||||
|
// TODO add properties to the builder and call build()
|
||||||
|
|
||||||
|
group(DeliveryPayment, () {
|
||||||
|
// Abgewickelter Betrag in Cent (offener Betrag bei Bestätigung).
|
||||||
|
// int amountCents
|
||||||
|
test('to test the property `amountCents`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String deliveryId
|
||||||
|
test('to test the property `deliveryId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String id
|
||||||
|
test('to test the property `id`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Snapshot des Methoden-Codes (`cash`, `ec_card`, `invoice`, …).
|
||||||
|
// String paymentMethodCode
|
||||||
|
test('to test the property `paymentMethodCode`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String paymentMethodId
|
||||||
|
test('to test the property `paymentMethodId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// DateTime recordedAt
|
||||||
|
test('to test the property `recordedAt`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String recordedByCarId
|
||||||
|
test('to test the property `recordedByCarId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int recordedByPersonalnummer
|
||||||
|
test('to test the property `recordedByPersonalnummer`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:holzleitner_api/holzleitner_api.dart';
|
||||||
|
|
||||||
|
// tests for PendingReviewResponse
|
||||||
|
void main() {
|
||||||
|
final instance = PendingReviewResponseBuilder();
|
||||||
|
// TODO add properties to the builder and call build()
|
||||||
|
|
||||||
|
group(PendingReviewResponse, () {
|
||||||
|
// Entfernte/teil-gutgeschriebene Positionen.
|
||||||
|
// BuiltList<ReviewedItemResponse> creditedItems
|
||||||
|
test('to test the property `creditedItems`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String customerName
|
||||||
|
test('to test the property `customerName`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String deliveryId
|
||||||
|
test('to test the property `deliveryId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int erpBelegartId
|
||||||
|
test('to test the property `erpBelegartId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String erpBelegnummer
|
||||||
|
test('to test the property `erpBelegnummer`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Zeitpunkt der letzten beleg-ändernden Aktion (RFC 3339).
|
||||||
|
// String lastChangeAt
|
||||||
|
test('to test the property `lastChangeAt`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Geld-Gutschrift in Cent (0 = keine).
|
||||||
|
// int moneyCreditCents
|
||||||
|
test('to test the property `moneyCreditCents`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String moneyCreditReason
|
||||||
|
test('to test the property `moneyCreditReason`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tourdatum (ISO `YYYY-MM-DD`).
|
||||||
|
// String tourDate
|
||||||
|
test('to test the property `tourDate`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:holzleitner_api/holzleitner_api.dart';
|
||||||
|
|
||||||
|
// tests for PositionsModifiedResponse
|
||||||
|
void main() {
|
||||||
|
final instance = PositionsModifiedResponseBuilder();
|
||||||
|
// TODO add properties to the builder and call build()
|
||||||
|
|
||||||
|
group(PositionsModifiedResponse, () {
|
||||||
|
// ERP-Belegnummer, nach der gefragt wurde.
|
||||||
|
// String belegnummer
|
||||||
|
test('to test the property `belegnummer`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// `true`, wenn an der Lieferung Positionen verändert wurden — eine Zeile wurde entfernt oder in der Menge reduziert (Stück-Gutschrift) **oder** es liegt eine aktive Geld-Gutschrift vor.
|
||||||
|
// bool positionsModified
|
||||||
|
test('to test the property `positionsModified`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:holzleitner_api/holzleitner_api.dart';
|
||||||
|
|
||||||
|
// tests for RecordDeliveryPaymentRequest
|
||||||
|
void main() {
|
||||||
|
final instance = RecordDeliveryPaymentRequestBuilder();
|
||||||
|
// TODO add properties to the builder and call build()
|
||||||
|
|
||||||
|
group(RecordDeliveryPaymentRequest, () {
|
||||||
|
// Fahrzeug des Akteurs (Audit-Spur). Muss zum Account gehören.
|
||||||
|
// String authorCarId
|
||||||
|
test('to test the property `authorCarId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Idempotenz-Schlüssel — pro Bestätigung genau einmal vergeben.
|
||||||
|
// String clientEventId
|
||||||
|
test('to test the property `clientEventId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Betrag in Cent, den der Fahrer in der App gesehen und bestätigt hat. Der Server berechnet den offenen Betrag selbst und lehnt ab, wenn er davon abweicht — so landet nie ein Betrag im Protokoll, den der Fahrer nicht gesehen hat.
|
||||||
|
// int expectedAmountCents
|
||||||
|
test('to test the property `expectedAmountCents`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Gewählte Zahlungsmethode. Muss existieren und aktiv sein.
|
||||||
|
// String paymentMethodId
|
||||||
|
test('to test the property `paymentMethodId`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:holzleitner_api/holzleitner_api.dart';
|
||||||
|
|
||||||
|
// tests for ResolveReviewRequest
|
||||||
|
void main() {
|
||||||
|
final instance = ResolveReviewRequestBuilder();
|
||||||
|
// TODO add properties to the builder and call build()
|
||||||
|
|
||||||
|
group(ResolveReviewRequest, () {
|
||||||
|
// Optionale Notiz zur getroffenen Entscheidung.
|
||||||
|
// String note
|
||||||
|
test('to test the property `note`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bearbeiter (Name/Kürzel), der die Prüfung bestätigt.
|
||||||
|
// String resolvedBy
|
||||||
|
test('to test the property `resolvedBy`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:holzleitner_api/holzleitner_api.dart';
|
||||||
|
|
||||||
|
// tests for ReviewedItemResponse
|
||||||
|
void main() {
|
||||||
|
final instance = ReviewedItemResponseBuilder();
|
||||||
|
// TODO add properties to the builder and call build()
|
||||||
|
|
||||||
|
group(ReviewedItemResponse, () {
|
||||||
|
// String articleName
|
||||||
|
test('to test the property `articleName`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String artikelNr
|
||||||
|
test('to test the property `artikelNr`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int belegzeilenNr
|
||||||
|
test('to test the property `belegzeilenNr`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int creditedQuantity
|
||||||
|
test('to test the property `creditedQuantity`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// String reason
|
||||||
|
test('to test the property `reason`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
// int requiredQuantity
|
||||||
|
test('to test the property `requiredQuantity`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
278
test/payment_step_test.dart
Normal file
278
test/payment_step_test.dart
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import 'package:hl_lieferservice/domain/entity/address.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/customer.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_credit.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_item.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/delivery_payment.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/payment_method.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/scan_progress.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/tour.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/entity/tour_details.dart';
|
||||||
|
import 'package:hl_lieferservice/domain/repository/payment_methods_repository.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/model/delivery_payment_status.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/delivery/detail/presentation/widget/payment_sheet.dart';
|
||||||
|
import 'package:hl_lieferservice/feature/payment_methods/bloc/payment_methods_cubit.dart';
|
||||||
|
|
||||||
|
const _address = Address(
|
||||||
|
street: 'Konstantinplatz',
|
||||||
|
houseNumber: '3',
|
||||||
|
postalCode: '41849',
|
||||||
|
city: 'Wassenberg',
|
||||||
|
country: 'DE',
|
||||||
|
);
|
||||||
|
|
||||||
|
final _methods = [
|
||||||
|
PaymentMethod(
|
||||||
|
id: 'm-cash',
|
||||||
|
code: 'cash',
|
||||||
|
name: 'Bar',
|
||||||
|
active: true,
|
||||||
|
createdAt: DateTime(2026),
|
||||||
|
),
|
||||||
|
PaymentMethod(
|
||||||
|
id: 'm-ec',
|
||||||
|
code: 'ec_card',
|
||||||
|
name: 'EC-Karte',
|
||||||
|
active: true,
|
||||||
|
createdAt: DateTime(2026),
|
||||||
|
),
|
||||||
|
PaymentMethod(
|
||||||
|
id: 'm-inv',
|
||||||
|
code: 'invoice',
|
||||||
|
name: 'Rechnung',
|
||||||
|
active: true,
|
||||||
|
createdAt: DateTime(2026),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Lieferung: 2 × 50 € Warenwert, 20 € angezahlt ⇒ 80 € offen.
|
||||||
|
Delivery _delivery({double prepaid = 20}) => Delivery(
|
||||||
|
id: 'd1',
|
||||||
|
tourId: 't1',
|
||||||
|
customerId: 'c1',
|
||||||
|
contactPersonIds: const [],
|
||||||
|
deliveryAddressSnapshot: _address,
|
||||||
|
erpBelegartId: 24,
|
||||||
|
erpBelegnummer: 'V-1',
|
||||||
|
state: DeliveryState.active,
|
||||||
|
sortOrder: 1,
|
||||||
|
prepaidAmount: prepaid,
|
||||||
|
paymentMethodId: 'm-cash',
|
||||||
|
items: [
|
||||||
|
DeliveryItem(
|
||||||
|
id: 'i1',
|
||||||
|
deliveryId: 'd1',
|
||||||
|
articleId: 'a1',
|
||||||
|
warehouseId: 'w1',
|
||||||
|
belegzeilenNr: 1,
|
||||||
|
requiredQuantity: 2,
|
||||||
|
unitPrice: 50,
|
||||||
|
scanProgress: ScanProgress(
|
||||||
|
status: ScanStatus.done,
|
||||||
|
scannedQuantity: 2,
|
||||||
|
lastUpdatedAt: DateTime(2026),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
TourDetails _details(
|
||||||
|
Delivery delivery, {
|
||||||
|
DeliveryPayment? payment,
|
||||||
|
DeliveryCredit? credit,
|
||||||
|
}) => TourDetails(
|
||||||
|
tour: Tour(
|
||||||
|
id: 't1',
|
||||||
|
accountId: 414,
|
||||||
|
date: DateTime(2026, 9, 25),
|
||||||
|
syncedAt: DateTime(2026),
|
||||||
|
),
|
||||||
|
deliveries: [delivery],
|
||||||
|
customers: const {
|
||||||
|
'c1': Customer(
|
||||||
|
id: 'c1',
|
||||||
|
name: 'Cremer',
|
||||||
|
erpCustomerId: 7843068,
|
||||||
|
address: _address,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
contacts: const {},
|
||||||
|
articles: const {},
|
||||||
|
warehouses: const {},
|
||||||
|
notesByDeliveryId: const {},
|
||||||
|
creditsByDeliveryId: {if (credit != null) 'd1': credit},
|
||||||
|
paymentsByDeliveryId: {if (payment != null) 'd1': payment},
|
||||||
|
services: const [],
|
||||||
|
serviceValuesByDeliveryId: const {},
|
||||||
|
contactSourcesByDeliveryId: const {},
|
||||||
|
contactChannelsBySourceId: const {},
|
||||||
|
);
|
||||||
|
|
||||||
|
DeliveryPayment _payment(int cents, {String code = 'ec_card'}) =>
|
||||||
|
DeliveryPayment(
|
||||||
|
id: 'p1',
|
||||||
|
deliveryId: 'd1',
|
||||||
|
paymentMethodId: code == 'ec_card' ? 'm-ec' : 'm-cash',
|
||||||
|
paymentMethodCode: code,
|
||||||
|
amountCents: cents,
|
||||||
|
recordedAt: DateTime(2026, 9, 25, 13, 5),
|
||||||
|
);
|
||||||
|
|
||||||
|
class _FakePaymentMethods implements PaymentMethodsRepository {
|
||||||
|
@override
|
||||||
|
Future<List<PaymentMethod>> list({bool includeInactive = false}) async =>
|
||||||
|
_methods;
|
||||||
|
|
||||||
|
@override
|
||||||
|
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group('DeliveryPaymentStatus', () {
|
||||||
|
test('offener Betrag ohne Zahlung ist nicht erledigt', () {
|
||||||
|
final d = _delivery();
|
||||||
|
final s = DeliveryPaymentStatus.of(d, _details(d));
|
||||||
|
expect(s.openCents, 8000);
|
||||||
|
expect(s.isSettled, isFalse);
|
||||||
|
expect(s.isStale, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('passende Zahlung erledigt den Step', () {
|
||||||
|
final d = _delivery();
|
||||||
|
final s = DeliveryPaymentStatus.of(
|
||||||
|
d,
|
||||||
|
_details(d, payment: _payment(8000)),
|
||||||
|
);
|
||||||
|
expect(s.validPayment?.id, 'p1');
|
||||||
|
expect(s.isSettled, isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Gutschrift nach Zahlung macht sie veraltet', () {
|
||||||
|
final d = _delivery();
|
||||||
|
final s = DeliveryPaymentStatus.of(
|
||||||
|
d,
|
||||||
|
_details(
|
||||||
|
d,
|
||||||
|
payment: _payment(8000),
|
||||||
|
credit: const DeliveryCredit(
|
||||||
|
deliveryId: 'd1',
|
||||||
|
amountCents: 1000,
|
||||||
|
reason: 'Kratzer',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(s.openCents, 7000);
|
||||||
|
expect(s.isStale, isTrue);
|
||||||
|
expect(s.isSettled, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('bereits bezahlt: nichts offen, Step überspringbar', () {
|
||||||
|
final d = _delivery(prepaid: 100);
|
||||||
|
final s = DeliveryPaymentStatus.of(d, _details(d));
|
||||||
|
expect(s.hasOpenAmount, isFalse);
|
||||||
|
expect(s.isSettled, isTrue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
group('Zahlungs-Modal', () {
|
||||||
|
late PaymentSheetResult? result;
|
||||||
|
|
||||||
|
Future<void> openSheet(WidgetTester tester) async {
|
||||||
|
result = null;
|
||||||
|
final cubit = PaymentMethodsCubit(repository: _FakePaymentMethods());
|
||||||
|
await cubit.load();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
BlocProvider.value(
|
||||||
|
value: cubit,
|
||||||
|
child: MaterialApp(
|
||||||
|
home: Builder(
|
||||||
|
builder:
|
||||||
|
(context) => Scaffold(
|
||||||
|
body: TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
result = await showPaymentSheet(
|
||||||
|
context,
|
||||||
|
openCents: 8000,
|
||||||
|
customerNumber: 7843068,
|
||||||
|
preselectedMethodId: 'm-cash',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('open'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.tap(find.text('open'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
}
|
||||||
|
|
||||||
|
testWidgets('zeigt Betrag, bei EC die Kundennummer, bestätigt Methode', (
|
||||||
|
tester,
|
||||||
|
) async {
|
||||||
|
tester.view.physicalSize = const Size(1080, 2400);
|
||||||
|
tester.view.devicePixelRatio = 2.75;
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
|
await openSheet(tester);
|
||||||
|
|
||||||
|
expect(find.textContaining('80,00'), findsOneWidget);
|
||||||
|
expect(find.text('Bar'), findsOneWidget);
|
||||||
|
expect(find.text('EC-Karte'), findsOneWidget);
|
||||||
|
expect(find.text('Rechnung'), findsOneWidget);
|
||||||
|
expect(find.text('7843068'), findsNothing);
|
||||||
|
|
||||||
|
await tester.tap(find.text('EC-Karte'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(find.text('7843068'), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tap(find.text('Zahlung erhalten'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(result, isA<PaymentConfirmed>());
|
||||||
|
expect((result as PaymentConfirmed).method.code, 'ec_card');
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Rechnung ändert den Bestätigungs-Text', (tester) async {
|
||||||
|
tester.view.physicalSize = const Size(1080, 2400);
|
||||||
|
tester.view.devicePixelRatio = 2.75;
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
|
await openSheet(tester);
|
||||||
|
|
||||||
|
await tester.tap(find.text('Rechnung'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(find.text('Auf Rechnung bestätigen'), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Abbrechen schließt ohne Ergebnis', (tester) async {
|
||||||
|
tester.view.physicalSize = const Size(1080, 2400);
|
||||||
|
tester.view.devicePixelRatio = 2.75;
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
|
await openSheet(tester);
|
||||||
|
|
||||||
|
await tester.tap(find.text('Abbrechen'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(result, isNull);
|
||||||
|
expect(find.text('Zahlung abwickeln'), findsNothing);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Lieferung abbrechen fragt Grund ab', (tester) async {
|
||||||
|
tester.view.physicalSize = const Size(1080, 2400);
|
||||||
|
tester.view.devicePixelRatio = 2.75;
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
|
await openSheet(tester);
|
||||||
|
|
||||||
|
await tester.tap(find.text('Lieferung abbrechen'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.enterText(find.byType(TextField), 'Kunde zahlt nicht');
|
||||||
|
await tester.tap(find.text('Bestätigen'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(result, isA<DeliveryCancelRequested>());
|
||||||
|
expect((result as DeliveryCancelRequested).reason, 'Kunde zahlt nicht');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user