Zum Hauptinhalt springen

Operative Durchgängigkeit & Werker-Sicht (OP-UX-1)

Status: gebaut — OP-UX-1 (U1–U7, ✅ Stand 06-28; U9 ✅ v0.58.0) · OP-UX-2 (U8 Klärfälle-Workspace) · OP-UX-3 (Nacharbeit live im Gantt) · OP-QS-GATE · OP-QS-4/-5 (✅ v0.46.0); E-UX-1…3 entschieden · Bezug: OP-UX-1 (Owning-OP) · OP-UX-2/-3 · OP-QS-GATE · OP-QS-4/-5 · Zielgruppe: IT-Dev/Architektur (Slices + Datenfluss) · Anwender · Business/Management (§2 „warum das den Alltag trägt") · True North: direkt — die durchgängige Auftragszeile (U1) ist die direkteste Antwort auf Frage 2 (Wo stehen die Fahrzeuge?); §2 belegt den Bezug zu allen drei Leitfragen.

Kernaussage. Den operativen Flow — „ein Auto kommt, was passiert dann?" — durchgängig und intuitiv machen. Der Flow-Audit (06-27) ergab: das Cockpit ist auf hohem Niveau, aber der Alltag bricht an drei Stellen — es fehlt eine durchgängige Auftragszeile (Status · Mitarbeiter · Bucht · Standort · Fortschritt verteilt auf vier Seiten), eine Werker-Sicht (der Mitarbeiter sieht „seine" Schritte nicht) und eine echte Annahme-Maske (Auftrag anlegen geht heute nur per Demo-Button). Dieses Dokument zurrt die Politik fest und schneidet die Umsetzung in Slices — inzwischen gebaut (s. Status): der Flow ist von der Vordertür (Annahme) über Tafel + Meine Arbeit bis zur Abholung durchgängig.

1. Ausgangsbefund & Lösungsschnitt (Flow-Audit 06-27)

Die folgende Problem-Analyse beschreibt den Ausgangsbefund (Flow-Audit 06-27).

  1. Taktano war ein exzellentes Leitstand-Cockpit mit fehlender Vordertür und ohne Hand-Sicht. Die Steuerung eines bereits erfassten Auftrags war nahe am Meisterwerk; die Erfassung selbst und die Werker-Bedienung fehlten (jetzt geschlossen, s. o.).
  2. Drei Lücken, drei Slices (Priorität in dieser Reihenfolge):
    • U1 — Durchgängige Auftragszeile („Werkstatt-Tafel"). Eine Zeile je Auftrag mit allen Alltags-Fakten auf einen Blick: Auftragsnummer · Status · fachliche Phase · aktueller Schritt · wer · welche Bucht · Standort · Fortschritt · Reserve · Warn-Flags. Heute sind diese Fakten über Aufträge · Planung-Gantt · Belegung verstreut.
    • U2 — Werker-/Mitarbeiter-Sicht. Ein Mitarbeiter sieht „meine Schritte", startet/pausiert selbst, dokumentiert (Kommentar/Foto) — heute ist alles eine Leitstand-Sicht, keine Hand-Sicht.
    • U3 — Annahme-Maske. Auftrag regulär anlegen (Kunde · Leistung · Güteklasse · Wunschtermin); der Server-Handler auftrag.create existiert bereits — es fehlt nur die UI.
  3. Kein neues Datenmodell, keine Solver-Änderung für U1. Die Auftragszeile ist eine reine Projektion des Live-States (AuftragDTO + RessourcenDTO) — Derived-State-Prinzip (S-2), nichts wird zusätzlich gespeichert. U2/U3 brauchen UI + bestehende Handler, kein neues Schema.

2. Warum das den Alltag trägt (True-North-Bezug)

Jedes Feature muss ≥1 der drei True-North-Fragen direkter/schneller/genauer beantworten:

FrageHeuteMit OP-UX-1
Wo stehen die Fahrzeuge? (physisch und in Bearbeitung)Standort in Belegung, Bearbeitungs-Status in Aufträge, Mitarbeiter nur im Detail-Panel → drei SeitenEine Zeile zeigt Standort + aktueller Schritt + Mitarbeiter + Bucht (U1)
Wie hoch ist die Auslastung?Cockpit-KPIs (gut)Tafel zeigt die laufende Belegung pro Auftrag in Kontext (U1)
Wann sind die nächsten freien Kapazitäten?nur indirektU2 macht die Auslastung pro Werker greifbar (Folge-Slice)

Die durchgängige Auftragszeile ist damit die direkteste Antwort auf True-North-Frage 2 — sie verdient ihren Platz.

3. Befund aus dem Flow-Audit (06-27)

Walkthrough „ein Auto kommt": geplant → angeliefert → in_arbeit ⇄ pausiert → fertiggestellt → abgeschlossen → (kontrolliert) → archiviert. Stärken und Reibungen, mit Belegstellen:

Stärken (bleiben unangetastet):

  • Gantt (gantt.component.ts) — Zoom-Presets, Heatmap, Ausfall-Schraffur, Bottleneck-Puls, Konflikt-Marker. Hohe Dichte, lesbar.
  • Doku-/Foto-Pflicht-Gate (OP-R4-3, auftrag-detail-panel.component.ts) — „✓ Fertig" bleibt gesperrt bis Kommentar + Pflicht-Fotos da; Server validiert doppelt.
  • Farb-Semantik konsistent (Rot=Warnung, Grün=bestanden, Blau=aktiv, Amber=Achtung), Mono-Font für alle Daten, ARIA + prefers-reduced-motion.

Reibungen → die drei Slices:

  • U1: Status in orders.component.ts, Mitarbeiter nur im Detail-Panel (auftrag-detail-panel.component.ts), Bucht nur im Gantt-Zeilenlabel, Standort nur in occupancy.component.ts. Für „wer macht gerade was, wo?" ⇒ drei Seiten öffnen.
  • U2: Keine Werker-Sicht — der Mitarbeiter kann nicht sehen „das sind meine Schritte". Das ganze System ist Leitstand, nicht Hand.
  • U3: Auftrag anlegen nur über Demo-Buttons (planning.component.ts, „Testdaten"-Schalter); der reale Server-Handler auftrag.create (server/party/leitstand.ts) wird von keiner UI gefüttert.

Kleinere Reibungen (Backlog): inkonsistente Leere-Zustände (✅ app-empty-state) · zwei rote Warnsysteme (Klärfall ⚠ ≠ Termin-Konflikt ⚡) (✅ entwirrt, U7) · Nacharbeit nach QS-Mangel nicht live im Gantt (✅ OP-UX-3) · Administration-Seite zu technisch für Werkstatt-Rollen · kein Onboarding/Tour.

4. Slices

U1 — Durchgängige Auftragszeile / „Werkstatt-Tafel" (dieser PR, Start)

  • Neuer Workspace „Tafel" (Cluster Überblick, Signaturfarbe --tk-ws-tafel, Glyph ).
  • Eine Zeile je aktivem Auftrag, rein abgeleitet (keine Persistenz, S-2): Auftragsnummer (★ Güteklasse) · Status-Pill · Phase-Pill · aktueller Schritt (in_arbeit, sonst nächster geplanter) mit Mitarbeiter-Namen + Bucht-Name · 📍 Standort · Fortschritt (erledigt/gesamt + Balken) · Reserve · Warn-Flags (⚠ Zuweisung nötig, ⏱ verzögert, ⚡ überfällig, ⚠ Klärfall).
  • Sortierung nach operativer Dringlichkeit (in_arbeit → angeliefert → pausiert → geplant → fertig); Klick auf die Zeile öffnet das geteilte Detail-Panel (auftrag-detail-panel).
  • Quelle: aktiveAuftraege() + ressourcen() + employees() — alles vorhanden.
  • ✅ in diesem PR.

U2 — Werker-/Mitarbeiter-Sicht „Meine Arbeit" (✅ gebaut)

  • Eigener Workspace „Meine Arbeit" (Cluster Operativ, Signaturfarbe --tk-ws-werker, Glyph ⬣, Route /meine-arbeit).
  • Schichtterminal-Picker oben (Mitarbeiter wählen — kein Per-Mitarbeiter-Login nötig; R1-QR/Login ist Future) → darunter nur seine offenen/laufenden Schritte über alle aktiven Aufträge (produktiv aus mitarbeiterIds, zusätzlich als 🎓 Helfer aus helferIds), laufend zuerst sortiert, Badge mit Offen-Anzahl je Person.
  • Große, touch-taugliche Aktionen je Schritt: ⏸ Pause / ▶ Weiter (kein Gate, direkt über teilschrittAktion) und ✓ Fertig. Braucht der Abschluss Doku/Foto (OP-R4-3), führt „Fertig" ins geteilte Detail-Panel (dort lebt das Gate + Foto-Upload — kein zweites Gate); sonst wird direkt erledigt. Inline-Hinweis nennt, was zum Abschluss fehlt.
  • Reine Projektion des Live-States (kein neues Schema, keine Server-/Solver-Änderung).
  • ✅ gebaut.

U3 — Annahme / „Auto kommt → Auftrag anlegen" (✅ gebaut)

  • Eigener Workspace „Annahme" (Cluster Operativ, erster Eintrag = Start des Flows, Signaturfarbe --tk-ws-annahme, Glyph ⊕, Route /annahme).
  • Ein Formular (Single-Modal-Geist, S-1): Kunde (Name + CRM-Link, R5-v1) · Leistung (Picker aus dem aktiven Prozess-Katalog) · Güteklasse + Anspruch · Anlieferung + Wunsch-Abholung (datetime-local, UTC) · Termin-Härte → bestehender auftrag.create-Handler. Der Server prüft Machbarkeit (Angebotsmodus) und legt nur einen machbaren Auftrag an; der erscheint live in Tafel + Aufträge.
  • Kunde v1 neu im Modell (war dokumentiert, aber nicht gebaut): Auftrag.kunde = { name, crmLink? } (R5-v1 = nur Name + CRM-Link am Auftrag; Voll-Modell = FR-1). Optionales Feld, keine Migration nötig.
  • ✅ gebaut.

U3b — Machbarkeits-Rückmeldung der Annahme (✅ gebaut)

  • auftrag.create antwortet jetzt der anlegenden Verbindung (neue ServerMsg-Variante auftrag.create.result) — vorher fire-and-forget (bei nicht machbarem Plan kein Feedback).
  • Abgelehnt (ok:false) mit konkretem Grund aus dem fehlgeschlagenen Schritt (ScheduleResult.reason, z. B. kein qualifizierter Mitarbeiter/keine passende Bucht für die Güteklasse) bzw. „Abholung muss nach Anlieferung liegen" / „ungültige Zeitangaben".
  • Angenommen (ok:true) mit Auftragsnummer; Termin-Warnung, wenn der Auftrag planbar ist, aber frühestens nach der Wunsch-Abholung fertig wird (earliest.abholbereit > abholtermin).
  • Client: LeitstandService.auftragCreateResult-Signal → der Annahme-Workspace zeigt einen Spinner („prüft …"), bei Erfolg Toast + Formular-Reset (+ ggf. Termin-Warn-Toast), bei Ablehnung den Grund inline + Toast (Formular bleibt zum Korrigieren stehen). 8-s-Sicherheitsnetz gegen hängenden Spinner.

U4 — Vorschau mit Preis & Reserve + „Wirklich anlegen?"-Bestätigung (✅ gebaut)

  • Weil bei der Annahme ein kostenpflichtiger Auftrag entsteht, ist „annehmen" jetzt zweistufig: „Prüfen & anlegen" ruft erst die neue Dry-Run-Message auftrag.pruefen (Antwort auftrag.pruefen.result, Muster wie U3b) → läuft angebot() (TS-Scheduler), leitet Machbarkeit, Reserve (floor((abholtermin − earliest.completion)/1440)) und Preis ab — ohne anzulegen.
  • Bei Machbarkeit öffnet ein Bestätigungs-Dialog (Kunde · Leistung · Termine · Reserve grün/rot · Preis · ggf. Termin-Warnung) mit „Abbrechen" / „✓ Wirklich anlegen (kostenpflichtig)"; erst die Bestätigung ruft auftrag.create. Nicht machbar → Grund inline (kein Dialog).
  • Preismodell (OP-R7-6, erster Schnitt): Leistung.grundpreisCent (Seed + Picker zeigt „ab X €"), pure Summen-Funktion auftragspreisCent (server/src/operativ/preis.ts, Self-Test test:preis), Preis-Snapshot Auftrag.preisCent bei Anlage. Güteklasse-/Anspruch-Zuschläge bleiben OP-R7-6-Folge (dokumentiert).
  • Solver-Frage beantwortet: die Annahme-Prüfung läuft den TS-Scheduler (angebot, synchron im DO) — schnelle Einzelauftrags-Machbarkeit; der CP-SAT macht die globale Mehrauftrags-Optimierung (separat). U6 stößt nach Anlage zusätzlich eine globale CP-SAT-Reopt an.

U5 — „Zuletzt angenommen"-Panel + Kunde/CRM nachtragen (✅ gebaut)

  • Der Annahme-Workspace ist jetzt zweispaltig (grid lg:grid-cols-[minmax(0,1fr)_340px], stapelt mobil): links das Formular, rechts ein „Zuletzt angenommen"-Panel mit den letzten ~6 aktiven Aufträgen, neueste zuerst (sortiert über die Anlage-Reihenfolge aus der id AU-<seq> — es gibt kein createdAt).
  • Je Zeile Auftragsnummer · Status · Kunde; Inline-„✎ nachtragen" editiert Kunde-Name + CRM-Link → neue Server-Message auftrag.update ({ id, kunde }) — ändert nur die R5-v1-Kunde-Felder eines bestehenden Auftrags (Name bleibt Pflicht), schreibt ein Audit-Event (auftrag.aktualisiert, OP-AUDIT-1) + Chronik-Eintrag und broadcastet. Kein Leistung-/Termine-Edit (bewusst eng gehalten).

U6 — Reopt bei Annahme (✅ gebaut)

  • auftrag.create ist jetzt ein REOPT_EVENT: nach erfolgreichem Anlegen läuft — wie bei den Lifecycle-Events liefern/starten/teilschritt.aktion/verzoegerung — automatisch ein globaler CP-SAT-Reopt (aktualisiereVorschlaegeAuto, TS-Fallback), der den neuen Auftrag optimal unter allen einplant und das Ergebnis als Idee/Vorschlag in den Feed schiebt (Propose-not-execute, §7 — kein stilles Umplanen). Der Dry-Run auftrag.pruefen löst keinen Reopt aus (reine Vorschau).
  • Damit ist die Solver-Frage vollständig beantwortet: TS-Machbarkeit sofort, CP-SAT-Global-Reopt nach Anlage (als Vorschlag).

U7 — Zwei rote Warnsysteme entwirrt (Störung-Achse ⚠ vs. Termin-Achse) (✅ gebaut)

  • Befund (Flow-Audit, §3-Backlog): Auf der Werkstatt-Tafel kollidierten zwei rote Signale mit gleicher Optik (var(--tk-red)/danger-bg), obwohl sie Verschiedenes meinen — eine Zeile konnte −3T über (rote Reserve-Pille) und ⚡ überfällig (rotes Flag) und ⚠ Klärfall (rotes Flag) zeigen: drei rote Pillen, zwei davon für dieselbe Termin-Bedingung.
  • Entwirrt in zwei klar getrennte Achsen:
    • Störung-Achse — Klärfall ⚠ (rot): das einzige rote Flag; bedeutet „Prozess-Störung, Mensch muss eingreifen" (von Hand gesetzt/gelöst, zeit-unabhängig, OP-R3-1).
    • Termin-Achse — Reserve-/Verzug-Pille mit Schweregrad: Puffer/Verzug quantifiziert (+2T Reserve−5T über) statt als zweites rotes Icon. Farbe nach Schweregrad statt binär: ≥0 grün · −1…−3 T amber (Achtung) · ≤−4 T **rot (Warnung). Die 4-Tage-Schwelle spiegelt die **Konflikte-Triage** (conflicts.component`) → eine Termin-Logik über beide Sichten.
  • Effekt: Das redundante ⚡ überfällig-Flag auf der Tafel entfällt (die Reserve-Pille trägt die Termin-Achse, mit Zahl). Rot auf einer Zeile heißt jetzt entweder Klärfall (Eingriff) oder ein ernster Terminverzug (≤−4 T) — nicht mehr jeder kleine Verzug. Achse-Doku als Pattern in design/COMPONENTS.md („Warn-Achsen"). Design-Regel gewahrt: Amber = Achtung, Rot = Warnung.
  • Folge-Idee → umgesetzt als OP-UX-2 (U8): die symmetrische Klärfall-Sicht/-Zähler (Störung-Achse) ist gebaut — siehe unten.

U9 — Termin-Vorschlag (frühestmögliche Abholung) + Sonderwünsche in der Annahme (✅ gebaut, v0.58.0)

  • Termin-Vorschlag (Nutzer-Wunsch 07-03): Die Annahme bietet den frühestmöglichen Abholtermin basierend auf der gewählten Leistung direkt an — statt dass der Erfasser einen Wunschtermin rät und erst beim Prüfen erfährt, ob er machbar ist. Sobald Leistung (+ Anlieferung/Güteklasse) feststeht, fragt das Formular entprellt den neuen Dry-Run auftrag.terminvorschlag an ({ leistungId, anlieferung, gueteklasse }; ohne Anlieferung rechnet der Client ab „jetzt"); der Server antwortet der Verbindung mit auftrag.terminvorschlag.result = fruehesteAbholung aus scheduleLeistung(...).abholbereit (TS-Scheduler, inkl. Standzeit — dieselbe Größe, an der auch auftrag.create/pruefen die Wunschtermin-Warnung messen) bzw. dem konkreten Nicht-machbar-Grund. Kein State-Change/Broadcast (wie auftrag.pruefen, kein Reopt).
  • Direkt angeboten: ein leeres (oder zuvor automatisch befülltes) Wunsch-Abholung-Feld wird mit dem Vorschlag sofort vorbefüllt; ein von Hand gesetzter Termin bleibt unangetastet — dann zeigt eine Zeile unter dem Feld „Frühestmöglich: …" mit „Übernehmen". Nicht machbar ⇒ dezenter Amber-Hinweis mit Grund (das harte Gate bleibt der Prüfen-Schritt).
  • Sonderwünsche (R7-F10, Nutzer-Wunsch 07-03): neues optionales Freitext-Feld im Annahme-Formular → auftrag.create.sonderwuenscheAuftrag.sonderwuensche (additiv, keine Migration) → sichtbar im Bestätigungs-Dialog und im Aufträge-Detail (Fakten-Grid, volle Breite). Abgrenzung: Freitext am Auftrag — Struktur/Häufigkeits-Auswertung bleibt OP-FIND-1, Sonderwünsche als geprüfter QS-Punkt bleibt der vertagte istAbnahmebereit-Erweiterungspunkt (OP-QS-GATE), Kommentar-Verlauf mit Foto/Voice bleibt OP-R7-12.

OP-UX-2 — Klärfälle-Workspace (Störung-Achse bekommt Sicht + Zähler) (✅ gebaut)

U8 — Klärfälle-Workspace

  • Warum: U7 entwirrte die zwei roten Warn-Achsen. Die Termin-Achse hatte mit dem Konflikte-Workspace (/conflicts) + Nav-Badge bereits ein Zuhause; die Störung-Achse (Klärfall) erschien nur inline (Tafel-Flag, Detail-Panel-Badge) — keine Sammelsicht, kein Zähler. Diese Asymmetrie ist jetzt geschlossen: jede Achse hat Liste + Badge.
  • Neuer Workspace „Klärfälle" (Cluster Steuerung, direkt nach Konflikte; Signaturfarbe --tk-ws-klaerfaelle = Amber/Gold #f59e0b, Glyph , Route /klaerfaelle). Rot bleibt der Termin-Achse (Konflikte) vorbehalten — die Workspace-Identität der Störung-Achse ist amber/gold, die inline-Klärfall-Pille bleibt rot (OP-R3-1).
  • Inhalt (reine Projektion, kein Schema/Server): alle Aufträge mit aktivem klaerfall (svc.klaerfaelle()), Dringlichkeits-sortierteskaliert zuerst, dann am längsten ungeklärt (kleinstes klaerfall.seit) zuerst. Je Zeile: Auftragsnummer · ★ Güteklasse · ⚠ eskaliert-Pille (wenn eskaliert) · Grund · „seit … · X offen". Klick öffnet das geteilte auftrag-detail-panel — dort lebt das geroutete „✓ Klärfall lösen …" (nichts dupliziert).
  • Zähler: svc.klaerfaelleCount() als Nav-Badge (analog konflikteCount).
  • Lösen (seit v0.74.0, OP-R3-1-Folge „Klärungs-Engine"): geroutet über das geteilte Formular app-klaerfall-loesen (auftrag.klaerfall {loesen, route, kommentar, ziel…}) — Routen zurueck · qs (Klärungs-Skip offener Nicht-QS-Schritte) · schritt (ab-hier-weiter oder Katalog-Einschub via zusatzSchritt/Einzelplan) · abbruch (Storno); Lösungs-Kommentar Pflicht, Chronik + D1-Audit (klaerfall.gemeldet/klaerfall.geloest), Reopt-Trigger. Das Melden pausiert laufende Schritte (echte Unterbrechung, §5.1) und erfasst den auslösenden Schritt (klaerfall.teilschrittInstanzId, aus „Meine Arbeit" mitgesendet). Melden geschieht weiter kontextuell aus Detail-Panel/„Meine Arbeit". Kapazitätstragende Klärung (v0.75.0): „⏱ Klärung einplanen" (geteiltes app-klaerung-einplanen, Presets 15/30/60 min → auftrag.klaerungEinplanen) plant die Klärungsarbeit als echten Schritt (Katalog-Template ts-klaerung, Skill „Klärung", Migration v19) — Klärzeit zählt als Auslastung, max. eine offene Klärung je Klärfall, Audit klaerung.eingeplant. Pattern in design/COMPONENTS.md („Warn-Achsen": beide Achsen haben Liste + Badge), Screen in design/WORKSPACES.md.

OP-UX-3 — Nacharbeit nach QS-Mangel live im Gantt (✅ gebaut)

Problem (Flow-Audit-Backlog): Ein in der Endkontrolle erfasster Mangel mit Behebungs-Aufwand (nacharbeitAufwandMin) war nur eine Kennzahl — kein geplanter Schritt: keine Kapazität, kein Gantt-Block, keine Verschiebung von geplanteFertigstellung/Reserve. Das Cockpit beantwortete Auslastung & „wann fertig/frei?" falsch, solange Nacharbeit ausstand.

Lösung — Nacharbeit als echter, voll solver-integrierter Schritt:

  • Auslösung (Sign-off „erst bestätigen"): Mangel wird wie bisher erfasst; in der Qualität-Sicht öffnet ein expliziter Button „⚠ Nacharbeit einplanen" (sichtbar bei offenen Aufwands-Mängeln) die neue Aktion auftrag.nacharbeitEinplanen.
  • Server: pro offenem Aufwands-Mangel eine Nacharbeits-TeilschrittInstanz (status:'geplant', nacharbeitMin = Aufwand, teilschrittId = betroffener Schritt → Skill/Bucht-Typ). Auftrag geht über die neue Transition nacharbeiten: fertiggestellt → angeliefert zurück in die Planung; ein Einzel-Plan wird sofort gerechnet (konkrete Bucht/Zeit/Crew → live im Gantt), die globale CP-SAT-Reopt (REOPT_EVENTS) schiebt Optimierungen als Vorschlag nach. Audit nacharbeit.eingeplant.
  • Scheduler-Kern (Sign-off „voll solver-integriert"): dynamische zusatzSchritte im AuftragInput werden in scheduleLeistung (TS) und buildProblem (CP-SAT) nach dem Skip-Filter an den statischen Leistung.prozess angehängt (Wiederverwendung von dauerOverrideMin + abhaengigkeit); applyPlanung bleibt index-stabil (nach Reopen sind die statischen Schritte erledigt/geskippt → einziger planbarer Schritt ist die Nacharbeit).
  • Besetzung (Sign-off „Solver wählt frei"): Skill + Dauer fix (vom Mangel-Schritt), Bucht + Mitarbeiter optimal vom Solver. Reserve/Konflikt aktualisieren sich automatisch über geplanteFertigstellung (kein Client-Extra). Self-Test test:nacharbeit (blockierender CI-Gate).
  • Mangel-Abschluss (Nachzug, 0.33.1): der Nacharbeits-Schritt trägt eine Verknüpfung zum auslösenden Mangel (TeilschrittInstanz.mangelId). Wird der Schritt erledigt, setzt erledige den verknüpften Auftrag.maengel-Eintrag automatisch auf behoben (+ Protokoll + Audit mangel.behoben). Damit schließt sich der QS-Kreis: Mangel → Nacharbeit → behoben.

OP-QS-GATE — QS-Vollständigkeits-Gate vor der Abholung + Nacharbeit als QS-Schritt (✅ gebaut)

Problem: Die QS-Freigabe war ein reines Client-Gate (eine hartcodierte 4-Punkte-Sichtliste, losgelöst von den echten Teilschritten); der Server akzeptierte abholen blind (Transition fertiggestellt → abgeschlossen ohne Prüfung). Ein Fahrzeug konnte übergeben werden, obwohl Prozessschritte unerledigt/undokumentiert waren oder noch ein Mangel offen war.

Lösung — Nacharbeit dokumentiert sich im QS, und das Gate erzwingt Vollständigkeit server-seitig:

  • Nacharbeit = QS-Phasen-Schritt: neues optionales TeilschrittInstanz.phase (Per-Instanz- Override der Template-Phase). nacharbeitInstanz setzt phase: 'qs' → die Nacharbeit erscheint als QS-Schritt und dokumentiert dass Nacharbeit nötig war (statt die Produktions-Phase des Original-Templates zu erben). aktuellePhase und das Teilschritt-DTO bevorzugen die Instanz-Phase. Der bestehende nacharbeitEinplanen-Mechanismus (Solver-Replan, Lifecycle-Rücklauf) bleibt unverändert — kein separater Lifecycle-Status nacharbeit.
  • Server-hartes Gate (abholen): pure istAbnahmebereit(auftrag, dokuPflichtByTs, fotoAnfByTs, fotosByInstanz) → { ok, offen[] }. Bedingung je nicht übersprungenem Teilschritt: erledigt
    • (falls pflichtig) Doku-Kommentar + Foto-Pflicht erfüllt; zusätzlich kein QS-Mangel offen. Der auftrag.aktion-Handler lehnt abholen bei !ok ab (kein Übergang), schickt auftrag.aktion.result (mit offen[]) an die Verbindung + Audit auftrag.abnahme.abgelehnt (OP-AUDIT-1).
  • Client (Qualität-Sicht): Prozess-Vollständigkeits-Tafel aus den echten Teilschritten (erledigt?/Doku?/Foto? + offene Mängel) spiegelt das Server-Gate; „Übergeben" ist daran gebunden; Server-Ablehnung erscheint als Toast. Die manuelle Sicht-Checkliste startet frisch je QS-Runde (Schlüssel inkl. Nacharbeit-Schritt-Anzahl → kein veraltetes „Bestanden" nach Nacharbeit).

Entscheidungen: (a) Nacharbeit als QS-Phasen-Schritt statt neuem Lifecycle-Status; (b) Gate server-seitig hart (auditierbar/manipulationssicher), Client spiegelt nur; (c) Sonderwünsche vertagt (eigener PR) — istAbnahmebereit ist als Erweiterungspunkt vorbereitet.

Bewusst NICHT (Folge-Schritte):

  • transition()fertiggestellt setzt offene Schritte weiterhin auf erledigt; das Gate fängt undokumentierte Schritte ab (erledigt ohne Kommentar ⇒ blockiert), aber das Auto-Erledigen selbst könnte später eingeschränkt werden.
  • Pflichten-Snapshot: istAbnahmebereit liest die Doku-/Foto-Pflichten aus dem lebenden Template-Katalog (state.teilschritte) — wie schon das bestehende Per-Schritt-Gate beim Erledigen (teilschritt.aktion). Eine nachträgliche Template-Änderung wirkt damit rückwirkend auf bereits erledigte Arbeit. Sauberer wäre, die Pflichten zum Abschluss-Zeitpunkt auf der Instanz zu snapshotten (Persistenz-Frage, OP-DATA-1) — bewusst vertagt (betrifft nicht nur das QS-Gate, sondern die ganze Pflicht-Mechanik) und kein Regress dieses PRs.

Verifikation: test:abnahme (7 Fälle, blockierender CI-Gate) · test:do-migrations (v0→v16) · test:nacharbeit · ng build. Migration: SCHEMA_VERSION 15 → 16 (additiv, kein Transform).

OP-QS-4 — QS-Nacharbeit direkt als zuweisbarer Prozessschritt + Leistungs-Schwellwerte (✅ gebaut, v0.46.0)

Kernaussage: Die QS-Nacharbeit wird direkt in der Endkontrolle als Prozessschritt erfasst (statt zweistufig Mangel→Einplanen), lässt sich manuell oder automatisch einem Mitarbeiter zuweisen, und pro Leistung definierte Minuten-Schwellwerte markieren Aufträge mit auffällig viel Nacharbeit. Der Auftrag ist erst abschließbar, wenn alle QS-Schritte erledigt sind — jetzt server-seitig lückenlos.

Was neu ist (baut auf OP-QS-GATE/OP-UX-3 auf):

  • Einstufige Erfassung — Message qs.nacharbeitErfassen (auftragId, teilschrittInstanzId? = Ursprungsschritt, Kategorie/Schwere/Beschreibung, nacharbeitAufwandMin = überschreibbare Zeit, optional mitarbeiterIds). Der Server legt den Mangel automatisch im Hintergrund an (Bezug → teilschrittId/skillId/betroffeneMitarbeiterIds, speist die Qualitätsbewertung unverändert), erzeugt einen Nacharbeits-Schritt (nacharbeitInstanz, phase:'qs'), reopnet (nacharbeiten) und plant sofort ein (einzelplan). Die alten Messages (qs.mangelErfassen/auftrag.nacharbeitEinplanen) bleiben als interne Bausteine; letztere überspringt jetzt Mängel mit bereits vorhandenem Schritt (keine Doppel-Einplanung).
  • Manuelle Zuweisung — Message teilschritt.zuweisen + Feld TeilschrittInstanz.manuellZugewiesen. applyPlanung behält die Hand-Crew (überschreibt sie nicht bei der Re-Optimierung); der Solver plant weiterhin Zeit/Bucht drumherum. Ohne manuelle Zuweisung besetzt der Solver frei (Default).
  • Abschluss-Gate gehärtettransition(→fertiggestellt) erledigt Nacharbeits-Schritte nicht mehr automatisch (nacharbeitMin != null ausgenommen). Damit blockiert ein offener Nacharbeits-Schritt abholen über das bestehende istAbnahmebereit — das in OP-QS-GATE bewusst vertagte Auto-Erledigen ist hiermit geschlossen.
  • Leistungs-Schwellwerte + MarkerLeistung.nacharbeitSchwelleGesteigertMin/ExtremMin (Minuten, optional, admin-editierbar über den Prozess-Katalog, G-1). Reine Fn nacharbeitStufe(summeMin, gesteigertMin, extremMin). AuftragDTO trägt (abgeleitet, D-2) nacharbeitStufe aus dem Maximum von geplanter und tatsächlicher Nacharbeit-Summe gegen die (über die Auftrags-Leistungen summierten) Schwellwerte, plus nacharbeitGeplantMin/nacharbeitIstMin. Client-Badge in den Auftragskarten (normal ⇒ kein Badge · gesteigert amber · extrem rot).

Entscheidungen (Sign-off): (a) Schritt direkt erfassen, Mangel automatisch (Bewertungs-Pipeline unverändert); (b) Schwellwerte absolute Minuten; (c) erfassbar ab fertiggestellt; (d) Gate server-hart. Bewusst NICHT: Nacharbeit während laufender Produktion (vor fertiggestellt) und ein voller Solver-seitiger Crew-Pin (heute Preservation in applyPlanung, Timing bleibt solver-optimiert).

Verifikation: test:qs-nacharbeit (Stufen-Schwellwerte · Auto-Erledigen-Härtung · Abnahme-Gate · fixe Hand-Zuweisung; blockierender CI-Gate) · test:abnahme/test:nacharbeit unverändert grün · ng build. Keine Migration (alle neuen Felder optional/nested → additiv).

OP-QS-5 — Mangel/Nacharbeitsschritt: Schritt = Single Source der Dauer (✅ gebaut, v0.46.0)

Kernaussage: Der Mangel bleibt ein eigenständiges Objekt (Fehler-Fakt + eigener Lifecycle, künftig OP-QS-3-Kette), aber die Nacharbeit-Dauer wird nicht mehr doppelt geführt: maßgeblich ist die Dauer des Nacharbeitsschritts (TeilschrittInstanz.nacharbeitMin); der am Mangel erfasste nacharbeitAufwandMin ist nur noch Ersterfassung/Intent (bis ein Schritt existiert bzw. für den Zwei-Stufen-Altpfad und Fehler ohne Schritt).

Umsetzung (read-authoritativ, kein Feld-Löschen): Beim Aufbau von alleMaengel für Statistik/Bewertung (leitstand.ts) wird pro Mangel mit verknüpftem Schritt (mangelId) der Aufwand mit dessen nacharbeitMin überschrieben (Fallback: erfasster Mangel-Wert, wenn kein Schritt existiert). Damit beziehen statistikFuer/bewertungScore/erfahrungspunkte/niveauVorschlaege (pure, Signatur unverändert) die Schritt-Dauer, und es gibt keine Sync-Pflicht mehr zwischen Mangel und Schritt. Der DTO-Marker (nacharbeitStufe, OP-QS-4) las die Schritte ohnehin.

Warum eigenständig statt ableiten? Ein Fehler kann ohne Nacharbeitsschritt existieren (Sofort-Fix, reine Doku, akzeptierter/gewaiveter Mangel), trägt einen eigenen Lifecycle (offen→behoben; künftig Ersatzteil-Kette OP-QS-3) und ankert die Qualitätsbewertung dauerhaft (überlebt Re-Planung der Schritte). Er ist damit ein primärer Fakt, kein Derivat (D-2 spricht nicht dagegen).

Verifikation: test:qs-nacharbeit (5) — Schritt-Dauer gewinnt über den erfassten Wert; ohne Schritt Fallback. test:leistung unverändert grün. Keine Migration.

5. Entscheidungen

IDFrageStatus
E-UX-1U1 als eigener Workspace „Tafel" (eigene Signaturfarbe, Cluster Überblick) statt Umbau von Aufträge/Überblick(06-27) eigener Workspace — hält die bestehenden Seiten unverändert, gibt der Durchgängigkeit einen klaren Ort
E-UX-2Werker-Sicht als eigener touch-Workspace vs. Filter der Tafel(06-28) eigener Workspace „Meine Arbeit"; Identität via Mitarbeiter-Picker (Schichtterminal) für den ersten Slice — echtes QR/Login (R1) später
E-UX-3Annahme-Maske: „+ Auftrag"-Button vs. eigener Workspace(06-28) eigener Workspace „Annahme" (erster Operativ-Eintrag); Kunde v1 (Name + CRM-Link) neu am Auftrag

6. Bezug

OP-R3-1 (Phasen first-class / Flow) · OP-R4-3 (Doku-/Foto-Pflicht) · OP-KIOSK-1 (Werkstatt-Tablet) · OP-R9-3 (Mitarbeiter-Ansicht-Detail) · R7 (Auftrag/Lifecycle) · R2 (Belegung) · S-1 (Single-Modal) · S-2 (Derived-State) · design/WORKSPACES.md (Workspace-Verhalten).


↩ Zurück zur Doku-Landkarte · Lesepfade · Register (alle OPs)