Zum Inhalt

Firebase Konfiguration & Dokumentation

Dieses Verzeichnis enthält Dokumentation und Deployment-Tools für Firebase.

⚠️ Wichtig

Die aktiven Firebase-Konfigurationsdateien liegen im Projekt-Root: - /firestore.rules - Firestore Security Rules - /storage.rules - Storage Security Rules - /firestore.indexes.json - Composite Indexes - /firebase.json - Projekt-Konfiguration - /cors.json - Storage CORS-Konfiguration

Diese Dateien werden von Git getrackt und bei git clone automatisch heruntergeladen.

Dateien in diesem Verzeichnis

  • README.md - Diese Datei
  • deploy_rules.sh - Interaktives Deployment Script
  • ROLES_AND_PERMISSIONS.md - User-Rollen Dokumentation
  • CLOUD_FUNCTIONS_AND_RULES.md - Cloud Functions & Security Rules
  • QUICK_REFERENCE.md - Schnellreferenz für häufige Aufgaben

Neues Projekt Setup

1. Repository klonen

git clone https://github.com/Tech-Schuppen/easy_sale_erp.git
cd easy_sale_erp

Die Firebase-Konfigurationsdateien sind bereits im Root vorhanden!

2. Firebase CLI installieren

npm install -g firebase-tools

3. Firebase Login

firebase login

4. Firebase Projekt hinzufügen

firebase use --add
# Wähle dein Projekt aus der Liste

5. Rules deployen

./firebase_config/deploy_rules.sh
# oder direkt:
firebase deploy --only firestore:rules,storage:rules,firestore:indexes

Workflow

Änderungen an Rules

  1. Bearbeite die Dateien im Root:

    vim firestore.rules
    vim storage.rules
    

  2. Teste lokal (optional):

    firebase emulators:start
    

  3. Deploye:

    ./firebase_config/deploy_rules.sh
    

  4. Commit:

    git add firestore.rules storage.rules
    git commit -m "Updated firestore rules"
    git push
    

Production Deployment

# Wähle Production Projekt
firebase use production

# Deploye Rules
firebase deploy --only firestore:rules,storage:rules

# Zurück zu Dev
firebase use dev

Wichtige Hinweise

⚠️ Firestore Rules - Sicherheit

Aktuelle Rules erfordern Authentifizierung für alle Collections:

match /{document=**} {
  allow read, write: if request.auth != null;
}

Ausnahme - System Settings (nur SuperAdmin):

match /system_settings/{settingId} {
  allow read: if isAuthenticated();
  allow write: if isSuperAdmin(); // userRole == 2
}

Details siehe: ROLES_AND_PERMISSIONS.md

Storage Rules

Die Storage Rules erlauben: - Artikel-Bilder: Öffentlich lesbar, schreiben nur für authentifizierte User - Alle anderen Dateien: Nur für authentifizierte User

Storage CORS

Die /cors.json konfiguriert Cross-Origin Resource Sharing:

# CORS auf Storage anwenden
gsutil cors set cors.json gs://YOUR-PROJECT.appspot.com

# Aktuelle Konfiguration prüfen
gsutil cors get gs://YOUR-PROJECT.appspot.com

Multi-Projekt Setup

Für mehrere Firebase-Projekte (dev, staging, prod):

# Projekte hinzufügen
firebase use --add

# Zwischen Projekten wechseln
firebase use dev
firebase use staging
firebase use prod

# Aktuelles Projekt anzeigen
firebase use

# Auf spezifisches Projekt deployen
firebase deploy --only firestore:rules --project dev
firebase deploy --only firestore:rules --project prod

Firestore Indexes

Die Indexes werden automatisch aus firestore.indexes.json deployed.

Neue Indexes hinzufügen: 1. Firebase Console → Firestore → Indexes 2. Klicke auf den Link in der Fehlermeldung der Query 3. Oder exportiere bestehende Indexes:

firebase firestore:indexes > firestore.indexes.json

Rules Testen

Emulator

# Emulator starten
firebase emulators:start --only firestore

# Rules Unit Tests (optional)
firebase emulators:exec --only firestore "npm test"

Rules Playground

  • Firebase Console → Firestore → Rules
  • Tab "Rules Playground" für manuelle Tests

Firebase Config - Quick Reference

🤔 Welches Script verwenden?

┌─────────────────────────────────────────────────────────────┐
│ Was möchtest du tun?                                        │
└─────────────────────────────────────────────────────────────┘

📝 Ich habe Rules im Root bearbeitet
   → firebase deploy --only firestore:rules
   → ./firebase_config/sync_from_root.sh  (zum Backup sichern)

🆕 Ich setze ein NEUES Firebase-Projekt auf
   → ./firebase_config/setup_project.sh
   → firebase use --add
   → firebase deploy

📥 Ich habe das Repo geklont
   → Nichts! Die Dateien sind schon im Root
   → Nur: firebase use --add (um dein Projekt zu wählen)

🚀 Ich will deployen
   → ./firebase_config/deploy_rules.sh

🔄 Kollege hat Rules geändert (git pull)
   → Nichts! Root-Dateien sind aktuell durch git
   → Nur deployen wenn nötig

📂 Verzeichnisstruktur

/                              ← Root (aktive Dateien)
├── firestore.rules           ← Firebase CLI liest HIER
├── storage.rules             ← Firebase CLI liest HIER
├── firestore.indexes.json    ← Firebase CLI liest HIER
├── firebase.json             ← Firebase CLI liest HIER
├── cors.json                 ← Für gsutil cors set
└── firebase_config/          ← Backup & Templates
    ├── firestore.rules               (Backup/Template)
    ├── firestore.rules.production    (Production Version)
    ├── storage.rules                 (Backup/Template)
    ├── firestore.indexes.json        (Backup/Template)
    ├── firebase.json                 (Backup/Template)
    ├── cors.json                     (Backup/Template)
    ├── sync_from_root.sh      ← Root → firebase_config
    ├── setup_project.sh       ← firebase_config → Root
    └── deploy_rules.sh        ← Deployment

🔁 Typische Workflows

Workflow 1: Rules ändern

vim firestore.rules                    # Im Root bearbeiten
firebase deploy --only firestore:rules # Deployen
./firebase_config/sync_from_root.sh    # Backup sichern
git add . && git commit -m "..."       # Committen

Workflow 2: Production Rules aktivieren

cp firebase_config/firestore.rules.production firestore.rules
firebase deploy --only firestore:rules
./firebase_config/sync_from_root.sh

Workflow 3: Neues Projekt

git clone ...
./firebase_config/setup_project.sh
firebase login
firebase use --add
firebase deploy --only firestore:rules,storage:rules

⚠️ Wichtig zu verstehen

  1. Git tracked die Root-Dateien UND firebase_config/
  2. Beide Versionen sind im Repo

  3. Firebase CLI liest NUR die Root-Dateien

  4. firebase deploy schaut nur in /firestore.rules usw.

  5. firebase_config/ ist für Menschen

  6. Backup für neues Projekt-Setup
  7. Template für andere Entwickler
  8. Production-Varianten

  9. Nach Änderungen immer sync_from_root.sh

  10. Sonst driften Root und firebase_config/ auseinander
  11. Andere Entwickler haben veraltete Templates

Dashboard Optimierungen

Übersicht der vorgenommenen Optimierungen

1. Frontend Optimierungen (Flutter/Dart)

Firestore Queries

  • Limit hinzugefügt: Top 50 Artikel, Top 50 Kunden, Top 20 Länder
  • Server-side Sortierung: orderBy('salesVolume', descending: true) direkt in Firestore
  • Vorteil: Drastisch reduzierter Datentransfer, schnellere Queries

Vorher:

// Lade ALLE Artikel/Kunden aus Firestore
final snapshot = await _firestore
    .collection('statisticsPeriodSummary')
    .doc(periodKey)
    .collection('articlesByRevenue')
    .get(); // Könnte 1000+ Dokumente sein!

// Sortiere im Client
results.sort((a, b) => b.salesVolume.compareTo(a.salesVolume));

Nachher:

// Lade nur Top 50, bereits sortiert
final snapshot = await _firestore
    .collection('statisticsPeriodSummary')
    .doc(periodKey)
    .collection('articlesByRevenue')
    .orderBy('salesVolume', descending: true)
    .limit(50)
    .get(); // Maximal 50 Dokumente

Widget Performance

  • Entfernte doppelte Sortierung: Widgets sortieren nicht mehr selbst
  • Weniger Speicher: Keine Kopien für Sortierung nötig
  • Schnelleres Rendering: Daten sind bereits sortiert

Vorher:

void showFullArticleListDialog(List<ArticleSalesStatistic> articles) {
  final sortedArticles = [...articles] // Kopie erstellen
    ..sort((a, b) => b.salesVolume.compareTo(a.salesVolume)); // Erneut sortieren
  // ...
}

Nachher:

void showFullArticleListDialog(List<ArticleSalesStatistic> articles) {
  // Artikel sind bereits sortiert - direkt verwenden
  // ...
}

2. Backend Optimierungen (Cloud Functions)

Entfernte redundante Collection

  • Gelöscht: statisticsCustomers Collection
  • Behalten: statisticsCustomerSales Collection (identischer Inhalt)
  • Vorteil: 50% weniger Schreiboperationen für Kundenstatistiken

Firestore Struktur vorher:

statisticsCustomers/{timePeriod}_{customerId}  ← REDUNDANT
statisticsCustomerSales/{timePeriod}_{customerId}

Firestore Struktur nachher:

statisticsCustomerSales/{timePeriod}_{customerId}  ← Einzige Quelle

Memory Optimierungen

  • Map statt Object: Bessere Performance für Country Statistics
  • Top-N Filtering: Nur Top 20 Länder werden gespeichert
  • Explizites Memory Clearing: countryMap.clear() nach Verwendung

Vorher:

const countryMap = {}; // Object - langsamer
for (const order of filteredOrders) {
  // ... verarbeite ALLE Länder
}
// Schreibe ALLE Länder in Firestore (könnte 100+ sein)

Nachher:

const countryMap = new Map(); // Map - schneller
for (const order of filteredOrders) {
  if (!c) continue; // Skip ungültige Daten
  // ...
}
// Sortiere und nimm nur Top 20
const topCountries = Array.from(countryMap.entries())
  .sort((a, b) => b[1].salesVolume - a[1].salesVolume)
  .slice(0, 20);
// Schreibe nur Top 20 Länder
countryMap.clear(); // Gib Speicher frei

Code-Deduplizierung

  • Neue Helper-Funktion: writeCountryStatistics()
  • Wiederverwendung: In beiden Trigger-Funktionen
  • Vorteil: Einfachere Wartung, konsistentes Verhalten

3. Firestore Indexes (erforderlich)

Die neuen Queries benötigen Composite Indexes. Diese werden automatisch erstellt oder können manuell hinzugefügt werden:

{
  "indexes": [
    {
      "collectionGroup": "articlesByRevenue",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "salesVolume", "order": "DESCENDING" }
      ]
    },
    {
      "collectionGroup": "statisticsCustomerSales",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "timePeriod", "order": "ASCENDING" },
        { "fieldPath": "salesVolume", "order": "DESCENDING" }
      ]
    },
    {
      "collectionGroup": "statisticsCountries",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "timePeriod", "order": "ASCENDING" },
        { "fieldPath": "salesVolume", "order": "DESCENDING" }
      ]
    }
  ]
}

Performance-Vergleich

Vorher

  • Artikel laden: ~1000 Dokumente, ~200KB Daten
  • Kunden laden: ~500 Dokumente, ~100KB Daten
  • Länder laden: ~50 Dokumente, ~10KB Daten
  • Client-Sortierung: ~300ms pro Widget
  • Firestore Writes: ~1500 Dokumente pro Berechnung

Gesamt pro Dashboard-Load: ~310KB, ~900ms

Nachher

  • Artikel laden: 50 Dokumente, ~10KB Daten
  • Kunden laden: 50 Dokumente, ~10KB Daten
  • Länder laden: 20 Dokumente, ~4KB Daten
  • Server-Sortierung: Bereits sortiert
  • Firestore Writes: ~1000 Dokumente pro Berechnung

Gesamt pro Dashboard-Load: ~24KB, ~100ms

Verbesserung

  • 92% weniger Daten: 310KB → 24KB
  • 89% schneller: 900ms → 100ms
  • 33% weniger Writes: 1500 → 1000 Dokumente

Kostenrechnung (ca. Werte)

Firestore Reads

Vorher: 1550 Dokumente × 0.06€/100k = 0.00093€ pro Dashboard-Load

Nachher: 120 Dokumente × 0.06€/100k = 0.000072€ pro Dashboard-Load

Einsparung: ~92% weniger Read-Kosten

Firestore Writes (pro Statistik-Berechnung)

Vorher: 1500 Dokumente × 0.18€/100k = 0.0027€

Nachher: 1000 Dokumente × 0.18€/100k = 0.0018€

Einsparung: ~33% weniger Write-Kosten

Bei 1000 Dashboard-Loads pro Tag

Vorher: 0.93€/Tag = 27.90€/Monat

Nachher: 0.072€/Tag = 2.16€/Monat

Einsparung: 25.74€/Monat = ~310€/Jahr

Migration

Alte statisticsCustomers Collection löschen (optional)

// Script zum Löschen der alten Collection
const admin = require('firebase-admin');
const db = admin.firestore();

async function deleteOldCollection() {
  const snapshot = await db.collection('statisticsCustomers').get();
  console.log(`Deleting ${snapshot.size} documents...`);

  const batches = [];
  let batch = db.batch();
  let count = 0;

  snapshot.docs.forEach(doc => {
    batch.delete(doc.ref);
    count++;
    if (count >= 500) {
      batches.push(batch.commit());
      batch = db.batch();
      count = 0;
    }
  });

  if (count > 0) {
    batches.push(batch.commit());
  }

  await Promise.all(batches);
  console.log('Done!');
}

deleteOldCollection();

Nach Deployment prüfen

# Prüfe ob neue Indexes aktiv sind
firebase firestore:indexes

# Prüfe Logs
firebase functions:log --only scheduledHourlyStatisticsUpdate

# Teste manuell
cd functions
node manual_trigger_statistics.js

Best Practices für zukünftige Entwicklung

  1. Immer Limits verwenden: Bei Listen mit potenziell vielen Einträgen
  2. Server-side Sortierung: orderBy() in Firestore statt Client
  3. Top-N Pattern: Nur die benötigten Daten speichern
  4. Memory Management: Explizites Clearing bei großen Objekten
  5. Code-Deduplizierung: Helper-Funktionen für wiederkehrende Muster

Monitoring

Überwache folgende Metriken: - Dashboard Load-Zeit (sollte <200ms sein) - Firestore Read-Count (sollte ~120 pro Load sein) - Function Execution Time (sollte <30s sein) - Memory Usage der Function (sollte <400MB sein)

# Cloud Function Metrics anzeigen
firebase functions:log --only scheduledHourlyStatisticsUpdate --limit 10

Onboarding Script - Code Review & Fixes

Datum: 2025-11-21

🔴 Kritische Fehler behoben:

1. ✅ Doppelter Code-Block entfernt (Zeile 588-590)

Problem: Der Block zum Speichern der Zusammenfassung war doppelt vorhanden.

# VORHER (doppelt):
} | tee "$SUMMARY_FILE"
  echo "Log-Datei: $LOG_FILE"
  echo "Zusammenfassung: $SUMMARY_FILE"
} | tee "$SUMMARY_FILE"

# NACHHER (einmal):
} | tee "$SUMMARY_FILE"

2. ✅ Fehlerbehandlung verbessert

Problem: set -e mit trap ERR kann zu unerwarteten Abbrüchen führen. Lösung: - Eigene handle_error Funktion implementiert - Nur noch set -o pipefail für bessere Pipe-Fehlerbehandlung - Kritische Befehle haben jetzt explizite Fehlerprüfung

3. ✅ Storage Bucket Name - beide Varianten unterstützt

Problem: Moderne Firebase Projekte können .appspot.com oder .firebasestorage.app verwenden. Lösung: Script prüft beide Bucket-Namen und zeigt an welcher gefunden wurde.

4. ✅ firebase-admin Package-Check

Problem: User-Creation-Script benötigt firebase-admin, wurde aber nicht geprüft. Lösung: - Prüft ob node_modules/firebase-admin existiert - Installiert automatisch Dependencies falls nötig - Fehlerbehandlung wenn npm install fehlschlägt

5. ✅ npm install Fehlerbehandlung

Problem: Wenn npm install fehlschlug, lief das Script trotzdem weiter. Lösung: - Explizite Prüfung ob npm install erfolgreich war - Functions-Deployment wird übersprungen wenn npm install fehlschlägt - Hilfreiche Fehlermeldungen

⚠️ Wichtige Verbesserungen:

6. ✅ gcloud Auth Check

Problem: Nur Installation wurde geprüft, nicht ob eingeloggt. Lösung: Prüft jetzt aktiven gcloud Account mit gcloud auth list

7. ✅ Warnung bei bestehenden Projekten

Problem: Bestehendes Projekt wurde einfach verwendet ohne Warnung. Lösung: - Zeigt deutliche Warnung - Fragt nach Bestätigung - Möglichkeit zum Abbruch

8. ✅ Sicherheitshinweis für sensible Daten

Problem: API Keys wurden ohne Warnung geloggt. Lösung: - Hinweis dass Werte im Log gespeichert werden - Warnung Log-Datei vertraulich zu behandeln - Validierung dass alle Werte eingegeben wurden

9. ✅ Verbesserte Fehlerbehandlung bei User-Creation

Problem: Fehler beim User-Script führten zu Abbruch. Lösung: - Script läuft weiter auch wenn User-Creation fehlschlägt - Öffnet automatisch Auth Console für manuelle Erstellung - Klare Fehlermeldung mit Anleitung

10. ✅ Functions Deployment robuster

Problem: Keine Fehlerbehandlung beim Firebase Deploy. Lösung: - Prüft Erfolg/Fehler - Gibt hilfreiche Hinweise bei Fehler - Script bricht nicht ab

📊 Script-Qualität:

Vorher:

  • ❌ 5 kritische Fehler
  • ⚠️ 5 wichtige Mängel
  • 📝 Keine Warnung bei sensiblen Daten

Nachher:

  • ✅ Alle kritischen Fehler behoben
  • ✅ Alle wichtigen Mängel behoben
  • ✅ Sicherheitshinweise implementiert
  • ✅ Robuste Fehlerbehandlung
  • ✅ Hilfreiche Fehlermeldungen
  • ✅ Benutzerfreundliche Warnungen

🎯 Das Script ist jetzt:

Production-Ready: Kann sicher für echte Kunden verwendet werden ✅ Robust: Behandelt Fehler korrekt ohne abzubrechen ✅ Sicher: Warnt bei sensiblen Daten und validiert Eingaben ✅ Benutzerfreundlich: Klare Meldungen und Hilfetexte ✅ Wartbar: Sauberer Code ohne Duplikate ✅ Zuverlässig: Prüft alle Voraussetzungen und Abhängigkeiten

📋 Test-Empfehlungen:

Vor Production-Einsatz testen:

  1. ✅ Mit komplett neuem Projekt
  2. ✅ Mit bestehendem Projekt (Warnung testen)
  3. ✅ Mit fehlenden npm packages
  4. ✅ Mit fehlgeschlagenem flutter build
  5. ✅ Mit fehlgeschlagenem firebase deploy
  6. ✅ Mit/ohne Custom User
  7. ✅ Mit ungültiger E-Mail-Adresse
  8. ✅ Abbruch bei verschiedenen Eingaben testen

🔒 Sicherheitshinweise:

⚠️ WICHTIG: - Log-Dateien enthalten API Keys und andere sensible Daten - Log-Dateien NICHT in Git committen - Log-Dateien nach Verwendung löschen oder sicher aufbewahren - .gitignore prüfen dass /tmp/onboarding_*.log ausgeschlossen ist

📝 Verwendung:

# Script ausführbar machen
chmod +x deployment/onboard_new_customer.sh

# Script ausführen
./deployment/onboard_new_customer.sh

# Nach erfolgreicher Ausführung:
# - Log-Datei prüfen: /tmp/onboarding_YYYYMMDD_HHMMSS.log
# - Zusammenfassung: deployment/onboarding_summary_PROJEKTNAME.txt

Zusammenfassung:

Das Script wurde gründlich überprüft und alle gefundenen Probleme wurden behoben. Es ist jetzt production-ready und kann sicher für neue Kunden-Onboardings verwendet werden. Die Fehlerbehandlung ist robust, sensible Daten werden mit Warnungen versehen, und das Script gibt hilfreiche Hinweise bei Problemen.

Statistik-Aktualisierung System

Übersicht

Das Dashboard-Statistik-System wurde optimiert und verwendet jetzt folgende Strategie:

Automatische Aktualisierung

  • Stündlich: Cloud Function läuft automatisch jede volle Stunde (z.B. 10:00, 11:00, 12:00...)
  • Täglich um Mitternacht: Zusätzliche Aktualisierung für Datumswechsel

Manuelle Aktualisierung

  • Aktualisieren-Button im Dashboard: Triggert sofort eine komplette Neuberechnung aller Statistiken
  • Wartezeit: Nach dem Klick dauert es 2-3 Sekunden bis die aktualisierten Daten geladen werden

Cloud Functions

1. scheduledHourlyStatisticsUpdate

  • Schedule: Jede volle Stunde (0 * * * *)
  • Funktion: Berechnet alle Statistiken für alle Zeiträume neu
  • Memory: 512MB
  • Timeout: 540 Sekunden

2. triggerStatisticsUpdate (Callable)

  • Trigger: Wird vom Dashboard-Aktualisieren-Button aufgerufen
  • Funktion: Identisch mit der stündlichen Berechnung
  • Memory: 512MB
  • Timeout: 540 Sekunden

3. scheduledDailyStatisticsUpdate

  • Schedule: Täglich um Mitternacht (0 0 * * *)
  • Funktion: Backup-Berechnung für Datumswechsel

Zeiträume

Das System berechnet Statistiken für folgende Zeiträume:

Zeitraum Key Beschreibung
Heute today Aktueller Tag (00:00 - jetzt)
Gestern yesterday Vorheriger Tag
Diese Woche thisWeek Montag - jetzt
Letzte 30 Tage last30Days Rollierendes 30-Tage-Fenster
Letzte 60 Tage last60Days Rollierendes 60-Tage-Fenster
Dieser Monat thisMonth 1. des Monats - jetzt
Letzter Monat lastMonth Vorheriger Monat komplett
Dieses Jahr thisYear 1. Januar - jetzt
Letztes Jahr lastYear Vorheriges Jahr komplett

Die Zeitraumauswahl im Dashboard wurde korrigiert: - Initialer Wert: "Heute" ist vorausgewählt - Automatisches Laden: Beim ersten Öffnen des Dashboards werden automatisch die Statistiken für "Heute" geladen - Wechsel: Bei Auswahl eines anderen Zeitraums werden die entsprechenden Statistiken sofort geladen

Deployment

Cloud Functions deployen

# Im Projekt-Root
cd /Users/andreasschmid/development/easy_sale_erp

# Firebase Projekt auswählen (falls noch nicht geschehen)
firebase use --add

# Functions deployen
cd functions
npm install
cd ..
firebase deploy --only functions

Nur spezifische Functions deployen

# Nur die neuen Statistik-Functions
firebase deploy --only functions:scheduledHourlyStatisticsUpdate,functions:triggerStatisticsUpdate

Firestore Collections

Das System schreibt in folgende Collections:

statisticsPeriodSummary

  • Dokument-ID: Zeitraum-Key (z.B. today, thisWeek)
  • Felder:
  • timePeriod: String-Key
  • orderCount: Anzahl Orders
  • customerCount: Anzahl unique Kunden
  • salesVolume: Gesamtumsatz
  • activeSessionsAndroid: Anzahl aktiver Android-Sessions
  • activeSessionsIos: Anzahl aktiver iOS-Sessions
  • Subcollection: articlesByRevenue (Top-Artikel nach Umsatz)

statisticsCustomerSales

  • Dokument-ID: {timePeriod}_{customerId}
  • Felder: Kunden-Umsatz-Statistiken

statisticsCountries

  • Dokument-ID: {timePeriod}_{country}
  • Felder: Länder-Umsatz-Statistiken

statisticsSalesVolume

  • Dokument-ID: Zeitraum-Key
  • Felder:
  • hourly: Array mit stündlichen Werten (für today/yesterday)
  • daily: Array mit täglichen Werten (für Wochen/Monate)
  • monthly: Array mit monatlichen Werten (für Jahre)

Fehlerbehandlung

Problem: Statistiken werden nicht aktualisiert

  1. Prüfe ob die Cloud Function erfolgreich läuft:

    firebase functions:log --only scheduledHourlyStatisticsUpdate
    

  2. Prüfe ob Orders in Firestore vorhanden sind:

  3. Firebase Console → Firestore → orders Collection

  4. Manuelle Neuberechnung triggern:

  5. Dashboard öffnen
  6. "Aktualisieren" Button klicken
  7. Oder manuell via Node-Script:
    cd functions
    node manual_trigger_statistics.js
    

Problem: Dropdown zeigt keine Daten

  1. Prüfe Browser-Console auf Fehler
  2. Prüfe ob StatisticBloc korrekt initialisiert ist
  3. Prüfe ob Firestore-Daten für den gewählten Zeitraum existieren

Testing

Manuelle Statistik-Berechnung (lokal)

cd functions
node manual_trigger_statistics.js

Statistiken in Firestore prüfen

cd functions
node debug_check_statistics.js

Migration von alter Version

Die alte Version verwendete einen onDocumentWritten Trigger bei jeder Order-Änderung. Dies wurde entfernt wegen: - Performance: Bei vielen Orders führte dies zu sehr häufigen Berechnungen - Kosten: Jede Order-Änderung triggerte eine teure Cloud Function - Latenz: Berechnungen dauerten lange und blockierten Order-Updates

Die neue Version ist effizienter und kostengünstiger.