Lab · Projekt
Ein Board, eine Frage: Haben wir die vereinbarten Stunden geleistet?
59 Kunden · 10 Mitarbeiter · ein Monatsabschluss
Zehn Mitarbeiter erfassen in Productive Stunden für 59 Kunden. Ob ein Kunde sein vereinbartes Kontingent bekommen hat, stand trotzdem nirgends. Jeden Monat hieß das: Daten von Hand aus Productive ziehen, gegen die Tabelle mit den Kundenbudgets halten und ausrechnen, wie viele Stunden im nächsten Monat noch drin sind. Pro Kunde. Von Hand. Jeden Monat wieder.
Das Board habe ich für genau eine Frage gebaut: Haben wir bei diesem Kunden die vereinbarten Stunden geleistet? Alles andere ist Beiwerk.
Die Karte: eine große Zahl, drei Regeln
Jeder Kunde ist eine Karte, und die Karte trägt eine große Zahl – das Ziel, also Kontingent plus Übertrag, bei null gekappt. Dahinter stehen drei Regeln, die das System ehrlich halten. Der Übertrag rechnet immer vom Kontingent, nie vom Ziel; sonst friert eine Schuld für immer ein. Die Toleranz färbt nur, sie rechnet nicht; ein grüner Monat kann trotzdem einen Übertrag tragen. Und das Ist kommt live aus Productive, bei jedem Aufruf, für zehn Minuten gecacht – gezählt werden ausschließlich die Projekte, die beim Kunden hinterlegt sind. Keine Heuristik über Kundennamen, keine Firmenzuordnung. Steht ein Ads-Projekt nicht in der Liste, zählt es nicht.
Fehlen eingetragene Stunden, ist das ein Datenfehler, kein Status. Er blockiert den Abschluss. Aufheben lässt sich das nur bewusst: Häkchen setzen, Grund mit mindestens zehn Zeichen tippen.
Der Monatsabschluss
Ein Monat wird nach dem Meeting geschlossen, danach ist er eingefroren: Die Zahlen kommen aus dem Snapshot, nicht mehr aus Productive. Der Durchgang läuft in fester Reihenfolge – erst Stunden nicht eingetragen, dann Überzogen, dann Unterauslastung, zuletzt Im Rahmen. Kunden ohne Projekt-ID oder ohne Kontingent kommen nicht vor. Bei Überzogen und Unterauslastung ist eine Begründung Pflicht, denn die Abweichung zu dokumentieren ist der Zweck des Meetings.
Der laufende Monat lässt sich nicht schließen, er ist noch nicht vorbei. Zweimal schließen geht auch nicht: Der zweite Versuch prallt ab, der Snapshot bleibt unverändert. Ein geschlossener Monat lässt sich wieder öffnen, mit Grund – der alte Snapshot wird archiviert, nie gelöscht. Und ändert jemand die Stunden in Productive nachträglich, gewinnt der Snapshot: Das Board zeigt einen Hinweis, die Zahlen bleiben.
Das Protokoll
Ein geschlossener Monat lässt sich als Datei mitnehmen: Markdown, eine Datei, Klartext – kein PDF, kein Excel. Sie heißt Monthly-Check_2026-07.md. Zuerst die Agentur-Summe, dann pro Betreuer ein Abschnitt, darin die Kunden sortiert nach Status, die roten zuerst. Notizen stehen wörtlich drin: Was im Meeting getippt wurde, landet unverändert im Protokoll, auch die Begründung eines Overrides. Kunden ohne Projekt-ID oder ohne Kontingent stehen am Ende unter Nicht erfasst und fließen in keine Summe. Die Zahlen kommen aus dem Snapshot – ein Export von heute und einer von nächstem Jahr sind identisch, auch wenn jemand die Stunden nachträglich ändert.
Architektur
Frontend: React, Vite und TypeScript, Tailwind für die Stile, Recharts für den Verlauf – gebaut als Statik, ausgeliefert vom selben Server. Dahinter Node und Express auf Google Cloud Run. Die Daten leben an zwei Orten: Stunden kommen live aus der Productive-API, Kundenkonfiguration und Snapshots geschlossener Monate liegen als versionierte JSON-Objekte in Google Cloud Storage. Secrets im Secret Manager, Zugriff per Passwort.
Ein Detail für Techniker: Der Rechenkern ist in ein eigenes Paket ausgelagert, ohne einen einzigen Netzwerkaufruf, gerechnet wird in ganzen Minuten, getestet mit 100 % Branch-Coverage. Es ist die einzige Stelle, an der ein Fehler das ganze Board entwertet. Deshalb ist sie von allem anderen isoliert.
Was das Board nicht tut
Es schreibt nichts nach Productive zurück; Stunden werden dort erfasst, nicht hier. Es rechnet nicht ab: kein Billing, keine Rechnungen, keine Prognosen. Es löscht keine Kunden, nur archivieren, weil Snapshots auf die ID verweisen. Und es kennt keine Rollen und keinen Login – der Zugriff endet auf Domain-Ebene.
Am Anfang standen eine Tabelle neben Productive und ein Taschenrechner. Heute beantwortet eine Karte pro Kunde die eine Frage, und der Monatsabschluss ist ein einziges Meeting mit Protokoll. Welche Zahl rechnen Sie jeden Monat von Hand aus? Schreiben Sie mir.