

Lagotto BI — Architektur und technische Übersicht
Lagotto BI liest aus einem MSSQL-ERP, synchronisiert Daten alle 5–15 Minuten in eine interne MariaDB-Datenbank und stellt sie über drag&drop-konfigurierbare Dashboards ohne Code-Schreiben bereit. Die Zeit zwischen “Ich habe das ERP noch nicht verbunden” und “Ich habe ein Dashboard mit echten Daten” wird in Wizard-Schritten gemessen, nicht in Wochen individueller Entwicklung.
Technischer Stack
| Komponente | Technologie |
|---|---|
| Backend | FastAPI (Python 3.11+), SQLAlchemy 2.x async, MariaDB |
| Quell-Connector | pymssql — nur Lesezugriff, schreibt nie ins ERP |
| Sync | APScheduler — inkrementell 5–15 Min, nächtlicher Full-Sync ohne Downtime |
| Frontend | Vue 3 + Vite + TypeScript, Pinia |
| Diagramme | Apache ECharts (tree-shaken, nur verwendete Module) |
| Tabellen / Pivot | Tabulator 6 / pivottable.js |
| Isolierung | Dediziertes MariaDB-Schema pro Tenant — keine gemeinsamen Daten zwischen Kunden |
Reale Konfigurationszeiten
Jeder Schritt hat einen integrierten Test oder eine Vorschau. Es wird nie blind gespeichert.
| Schritt | Was passiert | Typische Zeit |
|---|---|---|
| 1. ERP-Verbindung | 5-Schritt-Wizard: Host, Port, Anmeldedaten, Schema-Registry, Live-Verbindungstest vor dem Speichern | 3–5 Minuten |
| 2. Schema-Mapping | Mapper Builder: visueller Feld→Feld-Wizard, vordefinierte Transformationen, Test mit 50-Zeilen-Vorschau vor dem Speichern | 10–20 Minuten pro Tabelle erstmalig — sofort bei bereits zertifiziertem Schema |
| 2b. Vollständiger Tabellenimport | 3-Schritt-Wizard: MSSQL-Tabelle → MariaDB-Staging, ohne Feld-für-Feld-Mapping | 2–3 Minuten |
| 3. Erste Synchronisierung | Automatisch — inkrementell alle 5–15 Minuten, pro Datasource konfigurierbar | Daten verfügbar innerhalb von 15 Minuten |
| 4. Erstes Dashboard | Drag&Drop-Raster, jedes Widget mit Live-Vorschau während der Konfiguration | 1–2 Minuten pro Widget |
| 5. Filter und Drill-Through | Filter-Wizard mit automatischer Cross-View-Propagierung | 2–3 Minuten pro Filter |
Von nicht verbundenem ERP bis zum Dashboard mit echten Daten: die Größenordnung ist eine halbe Stunde, nicht der typische Analyse-Angebot-Entwicklung-Test-Zyklus eines individuellen BI-Projekts.
Aggregations-Engine
Der Unterschied, der am wenigsten sichtbar ist, aber am meisten wiegt: die Aggregation findet in der Datenbank statt, nicht im Browser. Ein Diagramm mit Top 10 + “Sonstige” auf einer Ansicht mit Hunderttausenden von Zeilen lädt diese Zeilen nicht in den Browser, um sie dann in JavaScript zu schneiden — das Backend führt GROUP BY + SUM mit bereits angewendeter Sortierung aus und gibt nur die Zeilen zurück, die gerendert werden.
GET /api/data/v_monatsumsatz ?_top_n_x=monat&_top_n_y=gesamt&_top_n=10&_gruppierung=kundenregion-- vom Backend generiert, parametrisiert — nie String-InterpolationSELECT monat, kundenregion, SUM(gesamt) AS gesamtFROM v_monatsumsatzWHERE jahr = :jahrGROUP BY monat, kundenregionORDER BY SUM(gesamt) DESCDas Pivot-Widget (PRO) folgt bei Bedarf der entgegengesetzten Logik: Rohdaten ohne LIMIT, client-seitig von pivottable.js aggregiert. Verifiziert auf 100.576 echten Zeilen mit € 21.142.336 in Echtzeit summiert, während der Benutzer Felder zieht.
Ein In-Memory-Cache (TTL 60 Sekunden, pro Benutzer) verhindert, dass ein Tab-Wechsel oder ein Doppelklick auf einen Filter dieselbe Abfrage zweimal neu generiert.
Widget-Katalog
Sieben Widget-Typen, alle vom Panel konfigurierbar — keiner erfordert handgeschriebenes JSON.
| Widget | Tier | Was es tut | Was es auszeichnet |
|---|---|---|---|
| KPI | FREE | Einzelwert mit Vorperioden-Vergleich und automatischer Formatierung | Periodenvergleich automatisch berechnet |
| Bar / Line | FREE | Balken- und Liniendiagramme, ein- oder mehrseriig | Mehrseriig rückwärtskompatibel |
| Bar — Varianten | FREE | Gestapelte Balken, horizontale Balken, Werte über/neben | Per Checkbox konfigurierbar |
| Pie / Donut | FREE | Absoluter Wert, Prozentsatz oder beides; Top-N mit “Sonstige” | Server-seitige Aggregation |
| Table | FREE | Tabulator mit Paginierung, Sortierung, aggregierten Spalten | Automatische Formatierung pro Spalte |
| Combo | PRO | Gemischte Balken + Linien-Serien, doppelte Y-Achse | Jede Serie wählt Achse, Typ und Farbe unabhängig |
| Pivot | PRO | Interaktive Pivot auf Rohdaten, ziehbare Zeilen × Spalten | Kein Backend-Zeilenlimit; Excel-Export mit einem Klick |
Beispiel: Kombinations-Diagramm-Konfiguration
{ "typ": "combo", "titel": "Umsatz vs Marge", "ansicht": "v_monatliche_marge", "x_achse": "monat", "serien": [ { "feld": "umsatz", "bezeichnung": "Umsatz", "typ": "bar", "y_achse": "links", "farbe": "#4a90d9" }, { "feld": "marge_pct", "bezeichnung": "Marge %", "typ": "line", "y_achse": "rechts", "farbe": "#e85d4a" } ]}Dieser JSON-Block — vom Widget Builder generiert, nie handgeschrieben — ist alles, was für ein Diagramm benötigt wird, das in vielen BI-Tools eine dedizierte SQL-Ansicht plus manuelle Konfiguration der zweiten Achse erfordert.
Aktionen und Drill-Through
Jedes Widget kann auf einen Klick reagieren. Der Drill-Through-Stack ist rekursiv — ein Klick in einem Modal, das durch einen vorherigen Klick geöffnet wurde, öffnet eine dritte Ebene mit Breadcrumbs zur Rückkehr. Vom Panel konfigurierbar, nicht aus Code.
| Aktion | Verhalten |
|---|---|
open_table / open_bar / open_pie / open_line / open_pivot | Öffnet ein Vollbild-Modal mit dem gewählten Widget, gefiltert auf den angeklickten Wert |
open_kunde | Navigiert zu einem bestimmten Dashboard, vorgefiltert auf den ausgewählten Kunden |
filter_dashboard | Wendet einen globalen Filter auf das gesamte aktuelle Dashboard an |
Mapper Builder und Query Manager
Jedes ERP hat eine JSON-Datei, die seine Tabellen auf das Standardschema von Lagotto abbildet:
{ "erp": "custom_erp", "tabellen": { "RECH_KOPF": { "ziel_ansicht": "v_monatsumsatz", "spalten": { "DOK_DATUM": { "ziel": "rechnungsdatum", "typ": "date" }, "KD_CODE": { "ziel": "kundennummer", "typ": "string" }, "DOK_GESAMT": { "ziel": "umsatz", "typ": "decimal", "anzeige": { "typ": "währung", "symbol": "€", "dezimalstellen": 0 } } } } }}Sechs vordefinierte Transformationen decken die Fälle ab, die normalerweise in einem handgeschriebenen Skript enden:
simple— direkte Kopiemap— Wörterbuch-Lookuplookup— externe Tabelle (z.B. Landkreis→Region)coalesce— erster Nicht-Null-Wert unter mehreren Feldernconcat— Verkettungarithmetisch— Summe/Subtraktion zwischen Feldern
Das display-Feld propagiert die Formatierung automatisch bis zum endgültigen Widget, ohne sie ein zweites Mal konfigurieren zu müssen.
Query Manager (View Builder, PRO): SQL-Editor mit dem Panel der für diesen Datasource verfügbaren Staging-Tabellen. Eine hier erstellte Ansicht ist im Widget Builder sofort verfügbar — kein Backend-Neustart, kein Deploy.
-- Marge nach Kategorie, in einer benutzerdefinierten Ansicht berechnetCREATE OR REPLACE VIEW v_kategorie_marge ASSELECT kategorie, SUM(umsatz) AS gesamtumsatz, SUM(kosten) AS gesamtkosten, ROUND((SUM(umsatz) - SUM(kosten)) / NULLIF(SUM(umsatz),0) * 100, 1) AS aufschlag_pctFROM roh_umsatzGROUP BY kategorieSicherheit und Multi-Tenant-Isolierung
- Obligatorische Ansichts-Whitelist: der Daten-Endpoint akzeptiert nur Ansichten in der expliziten Whitelist — keine beliebigen Abfragen vom Frontend
- Immer parametrisierte Abfragen: nie String-Interpolation, auch nicht für Spaltennamen mit Leerzeichen oder Akzentzeichen
- Server-seitig erzwungener Agenten-Filter: ein Benutzer mit der Rolle
agentsieht nur seine eigenen Daten — der Filter wird im Backend angewendet, nicht vom Frontend umgehbar - Schema pro Tenant: jeder Kunde hat sein eigenes MariaDB-Schema (
lagotto_{slug}) — null gemeinsame Daten, null Cross-Tenant-Abfragen möglich per Konstruktion - Granulare Benutzerprofilierung: ein Admin kann einschränken, welche Dashboards, Tabs, Widgets und permanente Filter ein einzelner Benutzer sieht — server-seitig gefiltert
Pläne und Lizenzierung
| Plan | Dashboards | Widget Builder | Pivot / Combo | Datasources | Benutzer | Preis |
|---|---|---|---|---|---|---|
| Starter | 10 Standard | — | — | 1 | 1 | Immer kostenlos |
| Professional | Unbegrenzt | ✓ | ✓ | 3 | 5 | Dynamisch — siehe Preisliste |
| AI | Unbegrenzt | ✓ | ✓ | Unbegrenzt | >100 | Auf Anfrage |
Das Benutzerlimit wird server-seitig bei jeder neuen Benutzererstellung überprüft. Der Plan wird alle 30 Minuten live gegen den License Server re-verifiziert — Widerrufe und Upgrades werden ohne Neustart propagiert. Die dem Benutzer angezeigten Preise werden in Echtzeit vom License Server gelesen, keine feste Zahl im Code.
Leistung — Zahlen, keine Adjektive
| Metrik | Wert |
|---|---|
| Inkrementelles Sync-Intervall | 5–15 Minuten, pro Datasource konfigurierbar |
| Downtime beim nächtlichen Full-Sync | Null — Shadow-Tabelle + atomares RENAME TABLE |
| Datencache pro Widget | 60 Sekunden pro Benutzer, bei Filteränderung invalidiert |
| In Pivot aggregierte Zeilen | 100.576 verifizierte echte Zeilen |
| In Echtzeit summierter Wert | € 21.142.336 |
| Latenz Planänderungs-Propagierung | Maximal 30 Minuten |
Deklarierte Roadmap
Noch nicht in Produktion:
- Erweiterter Query Manager: Abfrageergebnis in einer Staging-Tabelle materialisieren, nicht nur in einer bei jeder Lesung berechneten Ansicht — für schwere Joins auf Millionen von Zeilen
- Zertifizierte Mapper-Bibliothek: ein erprobtes Mapping-Schema zwischen verschiedenen Installationen desselben ERPs exportieren/importieren
- Vollständiger Dashboard-Import/Export: Layout, Widgets und Filter als exportierbare Datei, wiederverwendbar als Ausgangspunkt für einen neuen Kunden
Technisches Dokument — Lagotto BI. Roadmap-Funktionen sind noch nicht in Produktion verfügbar.
Quellen
Autor: Giantommaso Fogli
Veröffentlichungsdatum: 2026-07-09
Rechte und Attributionen
Bilder, Logos und Fotografien sind Eigentum ihrer jeweiligen Inhaber. Verwendet für Kommentarzwecke.
← Back to journal