Files
Holzleitner-Lieferservice-App/lib/domain/entity/delivery_item.dart
Dennis Nemec a9bf8ecdd1 Final commit.
2026-06-01 17:12:28 +02:00

107 lines
3.6 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'scan_progress.dart';
/// Eine Belegzeile innerhalb einer Lieferung.
///
/// Verweist über `articleId` auf den Artikel-Stamm (lookup via
/// `TourDetails.articleById`) und über `warehouseId` auf das Lager. Die
/// Soll-/Ist-Quantitäten leben hier: `requiredQuantity` ist statisch (ERP),
/// `scanProgress.scannedQuantity` wandert mit jedem Scan nach oben.
///
/// `komponentenArtikelNr` markiert Stücklisten-Komponenten. Im neuen
/// Backend gibt es **keine** Parent-/Child-Hierarchie mehr — jedes Item ist
/// gleichrangig; das Feld dient nur noch der Anzeige ("Teil von X") und
/// hat keinerlei Scan-Semantik.
class DeliveryItem {
const DeliveryItem({
required this.id,
required this.deliveryId,
required this.articleId,
required this.warehouseId,
required this.belegzeilenNr,
required this.requiredQuantity,
required this.scanProgress,
this.unitPrice = 0,
this.komponentenArtikelNr,
this.parentArtikelNr,
});
final String id;
final String deliveryId;
final String articleId;
final String warehouseId;
/// ERP-Belegzeilen-Nummer. Bestimmt die Reihenfolge der Items in der
/// Detail-Ansicht (aufsteigend).
final int belegzeilenNr;
final int requiredQuantity;
final ScanProgress scanProgress;
/// Stückpreis (brutto, EUR) aus dem ERP-Sync.
final double unitPrice;
final String? komponentenArtikelNr;
/// Artikelnummer des Oberartikels, zu dem diese Komponente gehört (aus dem
/// Sync). `null` bei Oberartikeln/regulären Zeilen. Die Liste rückt
/// Komponenten unter ihrem Oberartikel ein.
final String? parentArtikelNr;
/// `true`, wenn dieses Item eine Stücklisten-Komponente ist (gehört unter
/// einen Oberartikel).
bool get isComponent => parentArtikelNr != null;
// ─── Abgeleitete Sicht-Eigenschaften ──────────────────────────────────
/// Tatsächlich auszuliefernde Menge = Soll Gutschrift. Nie negativ.
int get deliveredQuantity {
final d = requiredQuantity - scanProgress.creditedQuantity;
return d < 0 ? 0 : d;
}
/// Wert der ausgelieferten Menge dieser Position (brutto, EUR).
double get lineTotal => unitPrice * deliveredQuantity;
/// Vollständig gescannt (Status `done` oder Ist ≥ Soll).
bool get isDone =>
scanProgress.status == ScanStatus.done ||
scanProgress.scannedQuantity >= requiredQuantity;
/// Aktuell pausiert.
bool get isHeld => scanProgress.status == ScanStatus.held;
/// Nach dem Laden wieder entfernt.
bool get isRemoved => scanProgress.status == ScanStatus.removed;
/// Noch offene Restmenge (für Loading-UI). Nicht negativ.
int get remainingQuantity {
final remaining = requiredQuantity - scanProgress.scannedQuantity;
return remaining < 0 ? 0 : remaining;
}
DeliveryItem copyWith({
String? id,
String? deliveryId,
String? articleId,
String? warehouseId,
int? belegzeilenNr,
int? requiredQuantity,
ScanProgress? scanProgress,
double? unitPrice,
String? komponentenArtikelNr,
String? parentArtikelNr,
}) {
return DeliveryItem(
id: id ?? this.id,
deliveryId: deliveryId ?? this.deliveryId,
articleId: articleId ?? this.articleId,
warehouseId: warehouseId ?? this.warehouseId,
belegzeilenNr: belegzeilenNr ?? this.belegzeilenNr,
requiredQuantity: requiredQuantity ?? this.requiredQuantity,
scanProgress: scanProgress ?? this.scanProgress,
unitPrice: unitPrice ?? this.unitPrice,
komponentenArtikelNr: komponentenArtikelNr ?? this.komponentenArtikelNr,
parentArtikelNr: parentArtikelNr ?? this.parentArtikelNr,
);
}
}