Die Tagesauswahl liegt lokal pro Fahrer und wurde ungeprüft
wiederhergestellt. Durch den alten Session-Fehler hatte 414 auf dem
Gerät das Fahrzeug von 423 gespeichert — das erschien weiter, obwohl
„Fahrzeug verwalten" (frisch vom Server) leer war.
CarSelectBloc lädt beim Wiederherstellen die Fahrzeuge des Accounts vom
Server und übernimmt die Auswahl nur, wenn das Fahrzeug dazugehört und
aktiv ist; sonst wird sie verworfen und neu abgefragt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Umgebungen (Name, API-URL, Keycloak-Issuer) kommen aus
assets/hl_server_config.json statt hartcodiertem BackendConfig.prod;
Testumgebung 192.168.1.9:3001 ist dort hinterlegt
- AppBloc laedt die Config, aktiviert die gespeicherte Wahl (Fallback
Default) und registriert das Networking; Wechsel persistiert per
SharedPreferences und registriert neu
- Bloc-Baum ist pro Umgebung gekeyt: beim Wechsel entstehen alle Blocs
mit dem neuen API-Client neu
- Login-Screen: Zahnrad oben rechts oeffnet Einstellungen mit Umgebungs-
Cards (Name + IP:Port); Hinweis auf aktive Umgebung unter dem Button
- Fahrzeugauswahl pro Umgebung getrennt (eigene DB = eigene Car-IDs)
- Tests fuer Config-Parsing, Auswahl-Fallback, Card-Wechsel, Re-Registrierung
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clean-Arch-Schichten für Cars:
- lib/domain/entity/car.dart: UUID-id, accountId (Personalnummer),
plate, active. Pendant zum Backend-Schema.
- lib/domain/repository/cars_repository.dart: Port — listMine,
create, update. Keine teamId/personalnummer-Parameter, der
Account fließt serverseitig aus dem JWT.
- lib/data/mapper/car_mapper.dart: API-DTO (built_value) → Domain.
- lib/data/repository/cars_repository_impl.dart: konkrete Impl via
generierter CarsApi (dio), mit DioException → CarsRepositoryException-
Übersetzung.
Feature-Cars-Refactoring:
- CarsBloc nimmt jetzt die Domain-Repository-Schnittstelle. Events:
CarLoad/CarAdd/CarEdit/CarDeactivate (statt CarDelete). Keine
teamId-Parameter mehr. Kein authBloc-Bezug, Session-Expiry läuft
über den globalen Provider-Stream.
- CarsState sealed mit CarsInitial/Loading/LoadingFailed/Loaded.
- Pages: car_management_page, car_management, car_card, car_fail_page,
car_selection_page komplett auf die neue Entity und Event-Signaturen.
- Alte lib/feature/cars/service/cars_service.dart und
lib/feature/cars/repository/cars_repository.dart gelöscht.
CarSelectBloc + Storage:
- CarSelection.selectedCarId von int? auf String? umgestellt.
- CarSelectionRepository persistiert die UUID jetzt als String;
defensive Migration für noch vorhandene int-Werte (alte
Pre-Migration-Installations) verwirft den Wert leise und
erzwingt Neuauswahl.
Konsequenz-Cleanup im Tour-Code (Phase-D-Vorbereitung):
- Delivery.carId String? statt int?.
- Tour.hasUndeliveredLoadedArticles / getFinishedDeliveries auf
String carId.
- _selectedCarId / int? carId / int selectedCarId in DeliveryOverview,
LoadingCustomerPage/OverviewPage, Home, DeliverySelection/SortPage,
DeliveryInfo/List, CustomSortDialog, SortableDeliveryList auf
String umgestellt.
- TourRepository ersetzt int.parse(carId)/int.tryParse-Zuweisungen
direkt durch String.
- lib/model/car.dart wird zum Re-Export der neuen Domain-Entity,
damit Legacy-Imports während Phase-D-Übergang weiter compilieren.
DI:
- app.dart: CarsBloc bekommt CarsRepositoryImpl(locator<HolzleitnerApi>())
statt der alten CarsRepository(service: CarService()).
Build (flutter build apk --debug) durch, flutter analyze ohne
errors.
- BackendConfig.localDev nutzt jetzt die LAN-IP des Dev-Macs
(192.168.0.138) statt localhost. Notwendig zum Testen auf einem
realen Android-Gerät über WLAN. Auf dem iOS-Simulator
zurückwechseln oder per Build-Flag injizieren.
- AuthBloc.on<SessionExpiredEvent> wird zum No-Op (mit Log).
Begründung: die alten ERPframe-Repos rufen das nach jedem 401 auf,
weil ihr Cookie-Login serverseitig weg ist. Solange Phase D diese
Repos nicht ersetzt hat, wäre ein echter Logout daraus fatal —
der erste TourBloc-Load nach Keycloak-Login würde die Session
sofort wieder wegwerfen. Die legitime SessionExpired-Quelle bleibt
der Provider-Stream (Refresh-Failure).
- CarSelectionPage hat jetzt durchgehend eine AppBar (vorher nur
im 'wechseln'-Modus) plus ein Account-Popup oben rechts mit
Personalnummer + roter Abmelden-Aktion. Der Drawer ist sonst
nur an Home, und solange Cars-Loading per 401 blockt, kommt der
User ohne Pre-Home-Logout nicht raus.