UI-Restructuring: - TabBar in scan_page durch dedizierte Phasen ersetzt: Sortieren / Beladen / Ausliefern - PhaseBloc + PhaseService leiten Phase aus Tour-/Item-States ab - DeliverySelectionPage (ab 2 Autos) und DeliverySortPage als eigene Flows - LoadingOverviewPage / LoadingCustomerPage für die Beladephase - PhaseStepper-Widget im Home für Phasen-Anzeige - Lager-Differenzierung (Standardlager 0 vs. Außenlager) via WarehouseBadge Process-Stubs: - ProcessRepository für Hold/Cancel/Sort/Assign-Flows (stub, bereit für Backend-Anbindung) Doku: - docs/BACKEND_MIGRATION.md: Phasenplan für Umstellung auf das neue Rust-Backend (OpenAPI-Generator, Keycloak OIDC, Clean-Arch-Layering)
69 lines
2.6 KiB
Dart
69 lines
2.6 KiB
Dart
import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart';
|
|
import 'package:hl_lieferservice/model/delivery.dart';
|
|
|
|
/// Hilfen rund um die Belade-Reihenfolge.
|
|
///
|
|
/// Die Beladereihenfolge ist die *Umkehrung* der vom Fahrer bestätigten
|
|
/// Auslieferungs-Reihenfolge (Sortier-Phase): wer zuletzt ausgeliefert wird,
|
|
/// kommt zuerst auf den LKW und liegt hinten. Diese Klasse liefert die
|
|
/// gefilterte und gespiegelte ID-Liste — Quelle ist immer
|
|
/// `TourLoaded.sortingInformation[carId]`.
|
|
///
|
|
/// Filterung:
|
|
/// * Bei ≥2 Fahrzeugen im Team: nur Lieferungen mit
|
|
/// `delivery.carId == selectedCarId`.
|
|
/// * Bei genau 1 Fahrzeug: alle Tour-Lieferungen.
|
|
///
|
|
/// Konsistent mit der bestehenden Logik in [DeliverySortPage] und der
|
|
/// alten `scan_page.dart:792`.
|
|
class LoadingOrder {
|
|
const LoadingOrder._();
|
|
|
|
/// Berechnet die Belade-Reihenfolge an Delivery-IDs.
|
|
///
|
|
/// [carIdStr] ist das String-Pendant der gewählten Auto-ID, weil die
|
|
/// `sortingInformation` mit String-Keys arbeitet.
|
|
static List<String> computeForCar({
|
|
required TourLoaded state,
|
|
required String carIdStr,
|
|
}) {
|
|
final cars = state.tour.driver.cars;
|
|
final allowedIds = cars.length >= 2
|
|
? state.tour.deliveries
|
|
.where((d) => d.carId?.toString() == carIdStr)
|
|
.map((d) => d.id)
|
|
.toSet()
|
|
: state.tour.deliveries.map((d) => d.id).toSet();
|
|
|
|
final raw = state.sortingInformation[carIdStr] ?? const <String>[];
|
|
|
|
// Mit reversed nach hinten kommt die zuletzt ausgelieferte Lieferung
|
|
// nach vorne (zuerst beladen).
|
|
final reversed = raw.reversed.where(allowedIds.contains).toList();
|
|
|
|
// Falls die Sortierung leer ist (kann bei frisch geladener Tour
|
|
// vorkommen, bevor `EnsureSortingForCarEvent` durchlief), fallen wir
|
|
// auf die unsortierten Tour-IDs zurück — der Fahrer sieht so wenigstens
|
|
// alle Kunden, ohne dass die Page hängt.
|
|
if (reversed.isEmpty && allowedIds.isNotEmpty) {
|
|
return allowedIds.toList(growable: false);
|
|
}
|
|
return reversed;
|
|
}
|
|
|
|
/// Komfort-Variante, die zusätzlich abgeschlossene Lieferungen rausfiltert
|
|
/// (für Anzeigen, die nur "noch zu beladen" bzw. aktive Einträge möchten).
|
|
static List<String> computeActive({
|
|
required TourLoaded state,
|
|
required String carIdStr,
|
|
}) {
|
|
final order = computeForCar(state: state, carIdStr: carIdStr);
|
|
final byId = {for (final d in state.tour.deliveries) d.id: d};
|
|
return order.where((id) {
|
|
final d = byId[id];
|
|
if (d == null) return false;
|
|
return d.state != DeliveryState.finished;
|
|
}).toList(growable: false);
|
|
}
|
|
}
|