feat(leadscraper): Live-Status-Seite, Einträge-Limit, kaskadierende Region-Auswahl #10

Merged
forgejo-admin merged 1 commit from feature/run-status-tracking into main 2026-07-25 22:49:08 +00:00

Zusammenfassung

Antwort auf Issue #9 (Städte-Namensfilter für die UI) und mehrere daraus entstandene Folgefunde:

  • Lead Scraper Run (neuer Doctype, Frappe Desk): Live-Status jedes Suchlaufs — bearbeitete Städte, aktuelle Stadt, Lead-Zähler, Status Queued/Running/Completed/Failed, Google-Places-API-Request-Zähler + geschätzte Kosten (eigener Preis-pro-Request-Schätzwert in den Settings).
  • "Max. Einträge pro Suchlauf" ersetzt "Max. Städte pro Region": begrenzt tatsächlich angelegte Leads statt durchsuchter Städte. Dafür laufen Suche und Import jetzt verschachtelt (Stadt für Stadt, sofortiger Abbruch bei Erreichen des Limits) statt erst die ganze Region zu durchsuchen und danach zu importieren.
  • Jede Exception während eines Laufs markiert ihn sauber als Failed mit Fehlermeldung, statt unbestimmt auf "Running" hängen zu bleiben.
  • Kaskadierende Land → Region → Landkreis/Stadt-Auswahl ersetzt die bisherigen Freitextfelder — Optionen werden live aus den bestehenden regions/*.json-Dateien geladen (kein Import, eine Quelle der Wahrheit). Anlass: Ein Stadt-Filter "KC" (Kfz-Kennzeichen von Kronach) fand lautlos nichts, weil es keine Kennzeichen-Zuordnung gibt. Die Auswahlfelder machen diese Fehlerklasse strukturell unmöglich; eine gewählte Region wird intern immer qualifiziert (DE:BY) übergeben, um Namenskollisionen zwischen Ländern (z. B. SH = Schleswig-Holstein vs. Schaffhausen) auszuschließen.

Verifikation (live, Demo-Umgebung)

  • Einträge-Limit mit Frühabbruch: Suchlauf mit Limit 2 stoppte exakt bei 2 angelegten Leads (3 Orte geprüft)
  • Fehlerfall (kein Stadt-Treffer): Status landet sauber auf Failed statt lautlos Completed
  • Kaskadierende Auswahl end-to-end: DE:BY + Stadt Kronachcities_total: 1, korrekt aufgelöst
  • Kollisionsfall DE:SH vs. CH:SH gegengeprüft: unterschiedliche, korrekte Städtelisten
  • "Suchraum erschöpft, bevor Limit erreicht" Fall real aufgetreten und als erwartetes Verhalten bestätigt (nicht genug echte Google-Treffer in einer kleinen Stadt)

Docs

docs/install.md Abschnitt 7c komplett überarbeitet, Projekt.md Entscheidungstabelle ergänzt.

## Zusammenfassung Antwort auf Issue #9 (Städte-Namensfilter für die UI) und mehrere daraus entstandene Folgefunde: - **`Lead Scraper Run`** (neuer Doctype, Frappe Desk): Live-Status jedes Suchlaufs — bearbeitete Städte, aktuelle Stadt, Lead-Zähler, Status `Queued/Running/Completed/Failed`, Google-Places-API-Request-Zähler + geschätzte Kosten (eigener Preis-pro-Request-Schätzwert in den Settings). - **"Max. Einträge pro Suchlauf"** ersetzt "Max. Städte pro Region": begrenzt tatsächlich **angelegte** Leads statt durchsuchter Städte. Dafür laufen Suche und Import jetzt verschachtelt (Stadt für Stadt, sofortiger Abbruch bei Erreichen des Limits) statt erst die ganze Region zu durchsuchen und danach zu importieren. - Jede Exception während eines Laufs markiert ihn sauber als `Failed` mit Fehlermeldung, statt unbestimmt auf "Running" hängen zu bleiben. - **Kaskadierende Land → Region → Landkreis/Stadt-Auswahl** ersetzt die bisherigen Freitextfelder — Optionen werden live aus den bestehenden `regions/*.json`-Dateien geladen (kein Import, eine Quelle der Wahrheit). Anlass: Ein Stadt-Filter "KC" (Kfz-Kennzeichen von Kronach) fand lautlos nichts, weil es keine Kennzeichen-Zuordnung gibt. Die Auswahlfelder machen diese Fehlerklasse strukturell unmöglich; eine gewählte Region wird intern immer qualifiziert (`DE:BY`) übergeben, um Namenskollisionen zwischen Ländern (z. B. `SH` = Schleswig-Holstein vs. Schaffhausen) auszuschließen. ## Verifikation (live, Demo-Umgebung) - Einträge-Limit mit Frühabbruch: Suchlauf mit Limit 2 stoppte exakt bei 2 angelegten Leads (3 Orte geprüft) - Fehlerfall (kein Stadt-Treffer): Status landet sauber auf `Failed` statt lautlos `Completed` - Kaskadierende Auswahl end-to-end: `DE:BY` + Stadt `Kronach` → `cities_total: 1`, korrekt aufgelöst - Kollisionsfall `DE:SH` vs. `CH:SH` gegengeprüft: unterschiedliche, korrekte Städtelisten - "Suchraum erschöpft, bevor Limit erreicht" Fall real aufgetreten und als erwartetes Verhalten bestätigt (nicht genug echte Google-Treffer in einer kleinen Stadt) ## Docs `docs/install.md` Abschnitt 7c komplett überarbeitet, `Projekt.md` Entscheidungstabelle ergänzt.
Adds a new Lead Scraper Run doctype (Frappe Desk view) tracking every search
started from the CRM UI in real time: cities processed, current city, lead
counts, status (Queued/Running/Completed/Failed), Google Places API request
count and an estimated cost based on a user-maintained price-per-request
setting.

Search and import now run interleaved (city by city, imported immediately)
instead of searching the whole region first - this is what makes the new
"Max. Eintraege pro Suchlauf" field actually stop the run early once that
many leads are *created* (not just found), rather than always exhausting a
whole region regardless of how many leads were requested. Any exception
during a run now marks it "Failed" with a message instead of leaving it
stuck on "Running".

Replaces the free-text "Regionen"/"Stadt" dialog fields with three cascading
selects (Land -> Region -> Landkreis/Stadt), populated live from the existing
regions/*.json files (no separate import/doctype - one source of truth).
Prompted by a real mishap in testing: a free-text city filter "KC" (Kronach's
license plate code) silently matched nothing, since there is no license-
plate-to-city mapping - only literal city names are ever compared. The
cascading pickers make that class of error structurally impossible, and a
selected region is always passed in qualified form (e.g. "DE:BY") to avoid
region-code collisions between countries (e.g. "SH" = Schleswig-Holstein in
Germany vs. Schaffhausen in Switzerland).

Live-tested end-to-end in the demo environment throughout, including the
country-code collision case and the "search space exhausted before reaching
the requested limit" case.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
forgejo-admin deleted branch feature/run-status-tracking 2026-07-25 22:49:08 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Frappe-Projekte/LeadScraper-Google!10
No description provided.