Architektur-Überblick
Explanation · Stand: 2026-09-22
Worum geht es?
Wenn ein Händler für einen Verschleiß-Servicefall einen Kostenvoranschlag (KVA) einreicht, muss das Benefit-Portal entscheiden: automatisch freigeben oder manuell prüfen? Diese Entscheidung soll nicht pauschal fallen, sondern anhand des bisherigen Verhaltens des Händlers (Händler-KPIs) und der Eigenschaften des konkreten Falls (Servicefall-KPIs).
Der Supplier-Cluster-Service (dieses Repository) ist ein eigenständiger Laravel-Service, der genau diese Bewertung übernimmt. Er kommuniziert mit dem Benefit-Portal (Monolith) ausschließlich über RabbitMQ-Messages und hat keine gemeinsame Datenbank mit dem Portal.
Warum ein eigener Service?
- Datengetriebene Regeln: Grenzwerte und KPI-Zusammensetzung liegen als
Zeilen in der Tabelle
evaluation_rules, nicht im Code. Eine KPI aufnehmen oder einen Grenzwert ändern erfordert kein Portal-Deployment. - Entkoppelte Deploys: Das Portal kann eine neue KPI publizieren, bevor der Service eine Regel dafür hat (der Wert wird gespeichert und ignoriert) — und umgekehrt.
- Klare Ownership: Die Bewertungslogik (Bänder, Cluster, Matrix) hat genau einen Ort. Das Portal kennt nur das Ergebnis.
Die drei Verantwortungen des Service
flowchart LR
subgraph Portal [Benefit-Portal Monolith]
P1[KPI-Berechnung je Händler]
P2[Servicefall im Status KVA-Prüfung]
P3[Auto-Freigabe oder manuelle Prüfung]
end
subgraph Cluster [Supplier-Cluster-Service]
C1[Ingest: kpi_values versioniert speichern]
C2[Evaluation: Bänder, Cluster, Matrix]
C3[UI: Händler-Übersicht + manueller Override]
end
P1 -- "kpi-message" --> C1
P2 -- "evaluation-request" --> C2
C1 --> C2
C2 -- "evaluation-result" --> P3
- Ingest — Das Portal publiziert periodisch je Händler die berechneten
KPI-Werte (
kpi-message). Der Service speichert sie versioniert inkpi_values: Werte einer neueren Messperiode lösen die alten ab (superseded_at), gleiche Perioden werden in place aktualisiert. Ein täglicher Job löscht abgelöste Werte nach 90 Tagen. - Evaluation — Ein
evaluation-requestträgt die Servicefall-KPIs im Payload; die Händler-KPIs kommen aus dem gespeicherten Bestand. Beide Seiten werden zu je einem Ampel-Cluster verdichtet und über eine Matrix zur Prüfungsintensität (0–100 %) gekreuzt. Details: Ampel-Logik. Das Ergebnis geht alsevaluation-resultzurück. - Übersicht & Override — Unter
/suppliers(Basic-Auth) zeigt eine Livewire-Seite alle Händler mit ihren aktuellen KPI-Bändern. Dort kann der Status eines Händlers manuell festgepinnt werden (Override mit Begründung). Der Override soll dabei auch die automatische Bewertung übersteuern — aktuell wirkt er jedoch nur auf die Übersicht (bekannter Bug, CU-123wka4jt6a; Details: Händler-Status übersteuern).
Der Service entscheidet nicht selbst über „automatisch vs. manuell". Er liefert nur die Prüfungsintensität; die Konsequenz daraus zieht der Konsument (das Portal, siehe unten).
Die Portal-Seite der Integration
Die Integration ist auf beiden Seiten produktiv. Im Monolith (Modul
TechnicalServices/Cluster) sieht sie so aus:
- Händler-KPIs monatlich: Der Command
technical-services:publish-cluster-kpisläuft am 1. jedes Monats (03:00) und publiziert pro aktivem Händler einekpi-message(Kostenquote, beide Einreichungsquoten, Korrektur-Quote; 12-Monats-Betrachtungsfenster). - Score-Anfrage je Servicefall:
SupplierScoreServiceberechnet die Servicefall-KPIs aus echten Vertragsdaten (UVP =productListPricedes Vertrags, Verschleißkosten = Brutto-Summe des Falls, gewöhnlicher Verschleiß aus denmax_contract_exchanges-Limits der Verschleißteile), setzt den Fall auf den StatusScoreRequestedund publiziert denevaluation-request— transaktional, damit keine Antwort vor dem Statuswechsel eintreffen kann. - Entscheidung per Stichprobe: Der Handler für
evaluation-resultspeichert das Ergebnis alsClusterEvaluationam Servicefall (Audit-Trail inkl. Cluster und KPI-Bändern) und nutzt die Prüfungsintensität als Stichproben-Wahrscheinlichkeit (Lottery): Bei X % Prüfungsintensität geht der Fall mit X % Wahrscheinlichkeit in die manuelle Prüfung, sonst in die Auto-Freigabe. Einincomplete-Ergebnis geht immer in die manuelle Prüfung.
Details zu Queues und Payloads: Messages und Queues.