Liefertage-Einstellungen¶
Übersicht¶
Die Liefertage-Einstellungen ermöglichen die Konfiguration von: - Wochentage: An welchen Tagen geliefert wird (Mo-So) - Feiertage: Deutsche Feiertage, an denen geliefert wird (automatisch berechnet) - Betriebsurlaub: Zeiträume, in denen das Unternehmen geschlossen ist - Ausnahmetage: Einzelne Tage, die von der normalen Lieferroutine abweichen
Komponenten¶
1. Model: DeliveryDaysSettings¶
Datei: lib/models/system_settings/delivery_days_settings.dart
Enthält:
- deliveryWeekdays: ListpublicHolidays: ListvacationPeriods: ListexceptionDays: List
2. Service: HolidayService¶
Datei: lib/services/holiday_service.dart
Funktionen:
- calculateEasterSunday(int year): Berechnet Ostersonntag mit Gauß-Algorithmus
- calculateHolidays(int year, List
3. UI: DeliveryDaysSettingsPage¶
Datei: lib/pages/settings/delivery_days_settings/delivery_days_settings_page.dart
Features: - Wochentag-Chips: Visuell ansprechende Auswahl der Liefertage - Feiertags-Schalter: Auswahl der Feiertage, an denen geliefert wird (mit Datumsanzeige) - Betriebsurlaub-Management: Hinzufügen und Löschen von Urlaubszeiträumen mit EsDatePicker - Ausnahmetage: Einzelne Tage mit EsDatePicker hinzufügen
4. BLoC Integration¶
Dateien:
- lib/blocs/system_settings_bloc/system_settings_bloc_events.dart
- lib/blocs/system_settings_bloc/system_settings_bloc.dart
Event:
- UpdateDeliveryDaysSettings: Aktualisiert die Liefertage-Einstellungen
State Management:
- _deliveryDaysSettings: Privates Feld im SystemSettingsBloc
- deliveryDaysSettings: Getter für Zugriff
- _onUpdateDeliveryDaysSettings: Handler für Updates
5. Firebase Service¶
Datei: lib/services/firebase_services/system_settings_firebase_service.dart
Methoden:
- getDeliveryDaysSettings(): Lädt Einstellungen aus Firestore
- updateDeliveryDaysSettings(DeliveryDaysSettings settings): Speichert Einstellungen
Dokument: systemSettings/delivery_days_settings
Verwendung¶
Navigation¶
Die Liefertage-Einstellungen sind in den Einstellungen unter "Liefertage" erreichbar (nach "Bestellungen").
Datenstruktur in Firestore¶
{
"deliveryWeekdays": [1, 2, 3, 4, 5],
"publicHolidays": ["neujahr", "karfreitag", "tag_der_arbeit"],
"vacationPeriods": [
{
"startDate": "2024-07-15",
"endDate": "2024-07-31",
"description": "Sommerurlaub"
}
],
"exceptionDays": ["2024-12-24", "2024-12-31"]
}
Feiertagsberechnung¶
Der HolidayService verwendet den Gauß-Algorithmus zur Berechnung des Ostersonntags, der die Basis für alle beweglichen Feiertage ist:
- Karfreitag: Ostersonntag - 2 Tage
- Ostermontag: Ostersonntag + 1 Tag
- Christi Himmelfahrt: Ostersonntag + 39 Tage
- Pfingstmontag: Ostersonntag + 50 Tage
- Fronleichnam: Ostersonntag + 60 Tage
Feste Feiertage werden direkt aus dem Jahr berechnet.
Beispiel-Integration¶
// In einem Widget:
final settings = context.read<SystemSettingsBloc>().deliveryDaysSettings;
// Prüfen, ob heute ein Liefertag ist
final today = DateTime.now();
final isDeliveryDay = settings?.deliveryWeekdays.contains(today.weekday) ?? false;
// Prüfen, ob heute ein Feiertag ist
final holidays = HolidayService.calculateHolidays(
today.year,
settings?.publicHolidays ?? []
);
final isHoliday = HolidayService.isHoliday(today, holidays);
Zukünftige Erweiterungen¶
Mögliche Verbesserungen: - Automatische Feiertags-Updates für neue Jahre - Import/Export von Feiertagen - Lokalisierung der UI-Strings - Kalenderansicht für bessere Übersicht - Automatische Benachrichtigungen bei bevorstehenden Ausnahmetagen
N-Gram Suche für Kunden¶
Übersicht¶
Implementierung einer hochperformanten N-Gram basierten Suchfunktionalität für Kunden. Die Suche ermöglicht schnelle Teil-String Suchen sowohl nach Kundenname als auch Kundennummer.
Funktionsweise¶
N-Gram Generierung¶
Beispiel: Kundenname "Huber"
Beispiel: Kundennummer "123456"
{
"number": {
"3": ["123", "234", "345", "456"],
"4": ["1234", "2345", "3456"],
"5": ["12345", "23456"],
"6": ["123456"]
}
}
Suchlogik¶
- Mindestlänge: Suche startet erst ab 3 eingegebenen Zeichen
- Optimale Array-Auswahl:
- 3 Zeichen eingegeben → Suche in "3"-Arrays
- 4 Zeichen eingegeben → Suche in "4"-Arrays
- usw. bis maximal 6 Zeichen
- Automatische Feld-Erkennung:
- Numerische Eingabe → Suche in
searchNgrams.number.X - Text-Eingabe → Suche in
searchNgrams.name.X
Vorteile¶
Performance¶
- ✅ Schnelle Firestore Queries mit
arrayContainsstattwhere >= ... && where < - ✅ Optimierte Array-Größen durch Längen-basierte Speicherung
- ✅ Reduzierte Datenübertragung da nur relevante Arrays geladen werden
Benutzererfahrung¶
- ✅ Substring-Suche möglich (nicht nur Prefix wie bei Standard-Firestore)
- ✅ Schnelle Reaktionszeit ab 3 Zeichen Eingabe
- ✅ Intelligente Sortierung (Exakt > StartsWith > Contains)
Skalierbarkeit¶
- ✅ Effiziente Indizierung durch Firestore Array-Indizes
- ✅ Geringe Speichernutzung durch optimierte N-Gram Längen
- ✅ Ein Feld für beide Such-Dimensionen (Name + Nummer)
Datenstruktur¶
Customer Model¶
class Customer {
// ... bestehende Felder ...
final Map<String, dynamic>? searchNgrams;
// Struktur:
// {
// "name": { "3": [...], "4": [...], "5": [...] },
// "number": { "3": [...], "4": [...], "5": [...], "6": [...] }
// }
}
Firestore Dokument¶
{
"companyName": "Huber GmbH",
"customerNumber": "123456",
"searchNgrams": {
"name": {
"3": ["hub", "ube", "ber", " gm", "gmb", "mbh"],
"4": ["hube", "uber", "ber ", "er g", "r gm", " gmb", "gmbh"],
"5": ["huber", "uber ", "ber g", "er gm", "r gmb", " gmbh"]
},
"number": {
"3": ["123", "234", "345", "456"],
"4": ["1234", "2345", "3456"],
"5": ["12345", "23456"],
"6": ["123456"]
}
}
}
Firestore Index¶
Wichtig: Folgender Index muss in Firestore angelegt werden:
Collection: customers
Fields:
- searchNgrams.name.3 (Array)
- searchNgrams.name.4 (Array)
- searchNgrams.name.5 (Array)
- searchNgrams.number.3 (Array)
- searchNgrams.number.4 (Array)
- searchNgrams.number.5 (Array)
- searchNgrams.number.6 (Array)
Migration¶
Bestehende Kunden aktualisieren¶
Das Script: - Lädt alle bestehenden Kunden - Generiert N-Grams für Name und Nummer - Aktualisiert die Dokumente in Batches (500er Pakete) - Zeigt Fortschritt und Statistiken
Automatische Generierung¶
Bei neuen/aktualisierten Kunden werden N-Grams automatisch generiert:
- createCustomer() - fügt N-Grams beim Erstellen hinzu
- updateCustomer() - aktualisiert N-Grams beim Ändern
API¶
NgramHelper¶
// Generiere N-Grams für Kundensuche
final ngrams = NgramHelper.generateCustomerSearchNgrams(
companyName: "Huber GmbH",
customerNumber: "123456",
);
// Bestimme Suchlänge
final length = NgramHelper.getSearchNgramLength("hub"); // returns 3
// Generiere Such-N-Gram
final searchNgram = NgramHelper.generateSearchNgram("Hub"); // returns "hub"
CustomerFirebaseService¶
// Suche wird automatisch mit N-Grams durchgeführt
final result = await customerService.getCustomersPaged(
searchText: "hub", // Suche erst ab 3 Zeichen
limit: 20,
);
Performance-Vergleich¶
Alte Methode (Prefix-Suche)¶
- 2 parallele Queries (Name + Nummer)
where >= "search" && where < "search\uf8ff"- Langsam bei großen Datenmengen
- Nur Prefix-Suche möglich
Neue Methode (N-Gram)¶
- 1 Query mit
arrayContains - Optimiert durch Array-Index
- Schnell auch bei großen Datenmengen
- Substring-Suche möglich
Erwartete Verbesserung: 60-80% schneller bei >1000 Kunden
Speicherverbrauch¶
Für einen typischen Kunden: - Name "Huber GmbH" (10 Zeichen) → ~8 N-Grams á 3-5 Zeichen = ~35 Bytes - Nummer "123456" (6 Zeichen) → 10 N-Grams á 3-6 Zeichen = ~45 Bytes - Total: ~80 Bytes zusätzlich pro Kunde
Bei 10.000 Kunden: ~0.8 MB zusätzlicher Speicher
Limitierungen¶
- Mindestlänge: 3 Zeichen (konfigurierbar)
- Max Nummer-Länge: 6 Zeichen für N-Grams (längere Nummern werden gecappt)
- Case-Insensitive: Alle Suchen in Kleinbuchstaben
- Leerzeichen: Werden in N-Grams inkludiert
Zukünftige Erweiterungen¶
Mögliche Optimierungen: - [ ] N-Grams für weitere Felder (Stadt, Straße, etc.) - [ ] Phonetische Suche für Namen - [ ] Fuzzy-Matching bei Tippfehlern - [ ] Multi-Field Suche (Name + Stadt gleichzeitig)