Files
Holzleitner-Lieferservice-App/lib/feature/loading/util/loading_order.dart
Dennis Nemec 456fb59668 Phasenbasierte Lieferübersicht + Beladen-Flow, plus Migrationsplan für Rust-Backend
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)
2026-05-14 22:27:56 +02:00

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);
}
}