Der Ordner dev/2026-07-22 ist ueber Monate gewachsen; ohne Einstieg findet man darin nichts mehr. Deshalb ein README als Wegweiser, mit dem Hinweis, dass bei Widerspruechen immer die juengere Entscheidung gilt (Beispiel: F7 wurde am 10.09. abgeloest). Die Bewertung traegt oben einen Stand-Block mit erledigten und offenen Befunden samt Sprungmarken. Ueberholte Aussagen der ersten Fassung sind markiert statt geloescht, damit der Weg nachvollziehbar bleibt. Der Monatsabschluss steht als eigenes Dokument, weil es eine dauerhafte Fachregel ist und keine Audit-Antwort: was eingefroren wird, was die Regel nicht leisten kann, und die Betriebsbefehle. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
44 KiB
Audit der Statistik- und Auswertungsmodule — 09.09.2026
Prüfgegenstand: Entwicklungspläne und Rückmeldungen in diesem Ordner einschließlich der zugehörigen Implementierung im aktuellen Arbeitsverzeichnis. Referenz-Commit: 384b2dcff1533168d4a122f4c2e93a5e0336bd75. Der Arbeitsstand enthält bereits zahlreiche nicht eingecheckte Änderungen; diese wurden ausdrücklich mitgeprüft. Der Bericht bewertet daher den Arbeitsstand, nicht ausschließlich diesen Commit und nicht den unbekannten Produktionsstand.
Es wurden ausschließlich neue Audit-Dokumente angelegt. Anwendungscode, vorhandene Dokumente und Konfiguration wurden nicht geändert. Tests und zusätzliche Gegenproben liefen in einer isolierten Kopie mit SQLite im Arbeitsspeicher. Es wurden keine produktiven Datenbankabfragen, Zahlungen, Nachrichten, Migrationen, Cache-Löschungen oder Snapshot-Neuberechnungen ausgeführt.
Die vollständigen synthetischen Gegenproben, Testergebnisse und Prüfgrenzen stehen im Prüfprotokoll.
1. Ergebnis und Prioritäten
Die geplanten Ansichten und Berechnungsbausteine sind überwiegend vorhanden. Die Aussage „alles umgesetzt und Zahlen korrekt“ ist für den geprüften Stand jedoch nicht belastbar. Es bestehen insbesondere Fehler bei Abo-Regeln, Stornos, historischen Auswertungen und dem Abgleich zwischen Übersicht und Detailansicht.
Der Bericht enthält 23 nummerierte Befunde. Darunter sind nachgestellte Fehler, aus dem Code belegte Risiken sowie ausdrücklich gekennzeichnete Robustheits- und Optimierungsthemen. Die Nummerierung ist keine Reihenfolge der Wichtigkeit.
- P1: zuerst beheben bzw. fachlich absichern; betrifft eine verbindliche Geschäftsregel oder die gemeinsame Punktebasis.
- P2: reguläre Fehlerbehebung mit Regressionstest; fehlerhafte Auswertung, Export, Zugriffseigenschaft oder relevante Betriebsstabilität.
- P3: Randfall, kleinere Umsetzungslücke oder Optimierung.
| ID | Priorität | Befund | Nachweis |
|---|---|---|---|
| A01 | P1 | Abo-Mindestlaufzeit und Pausenregeln über Aktiv-Feld umgehbar | Controller-Gegenprobe |
| A02 | P2 | Persönliche Statistik zählt nicht freigegebene Buchungsstatus mit | Service-Gegenprobe |
| A03 | P2 | Negative Salden fehlen in Punkte-Details und deren CSV | Service-Gegenprobe |
| A04 | P2 | Historischer Snapshot wird mit neu berechneten Monatswerten vermischt | Snapshot-Gegenprobe und Code |
| A05 | P2 | Umsatzrangliste zeigt aktuelle statt abgerechnete Abo-Anzahl | Service-Gegenprobe |
| A06 | P2 | Einmal-Zusätze werden bei Storno nicht korrekt zurückgenommen | Service-Gegenprobe |
| A07 | P2 | Zwei Payline-Prognosen verwenden unterschiedliche Mitgliedermengen | Service-Gegenprobe |
| A08 | P2 | Prognose fehlt vor der ersten Monatsqualifikation | Service-Gegenprobe |
| A09 | P2 | Summenzeile im Neupartner-CSV um eine Spalte verschoben | Exportmethoden-Gegenprobe |
| A10 | P3 | Kundenabo-Liste erzeugt zusätzliche Abfrage je Abo | Gemessene SQL-Anzahl |
| A11 | P3 | Top 3 schneidet Gleichstände vor der Namenssortierung ab | Service-Gegenprobe |
| A12 | P2 | Historisches „+N neu“ führt zu aktueller, abweichender Detailliste | Service-Gegenprobe und Linkprüfung |
| A13 | P2 | Noch nicht ausgeführte Abos verschwinden am Liefertag aus der Prognose | Gegenprobe; Robustheitslücke |
| A14 | P2 | Tabellensortierung verarbeitet englische Datums-/Zahlenformate falsch | Ausgeführte Original-JS-Funktion |
| A15 | P1 | Shop-Stornos können doppelt in Gesamtpunkten abgezogen werden | SQL-Gegenprobe und Buchungscode |
| A16 | P2 | Historischer Abo-Bestand ist auch ab Juli nicht durchgehend exakt | Zustands-Gegenprobe und Schreibpfad |
| A17 | P3 | Monatsüberlauf verschiebt Jahresgebühr-Gruppierung | Carbon-/Service-Gegenprobe |
| A18 | P2 | CSV übernimmt potenzielle Tabellenformeln unverändert | Exportmethoden-Gegenprobe und Code |
| A19 | P2 | Gescheiterte Provisionsberechnung wird als Nullbetrag angezeigt | Durchgängige Codeprüfung |
| A20 | P2 | „Teaminternes“ Profilfoto erhält öffentliche Storage-URL | Architektur-/Konfigurationsprüfung |
| A21 | P3 | Mehrsprachigkeit der neuen Ansichten unvollständig | Templates, Services, Sprachtests |
| A22 | P2 | Snapshot-Batch hält alle bereits berechneten Teambäume im Speicher | Lebensdauer-/Referenzanalyse |
| A23 | P2 | Gemischte Cache-Zeitstände können Prognosen verfälschen | Datenflussanalyse; Betriebsrisiko |
Sinnvolle erste Reihenfolge: A01 → A15 → A02/A03/A06 → A04/A12/A16 → A07/A08/A13/A19/A23 → Exporte/Zugriff/weitere Befunde. A15 betrifft bereits die gemeinsame Buchungslogik; eine ausschließlich kosmetische Statistikänderung wäre hier unzureichend.
2. Unterlagen, Sollstand und Abdeckung
Gelesen wurden alle neun vorhandenen Markdown-Dokumente dieses Ordners, alle drei PDFs sowie der Screenshot vom 25.08. Die PDFs wurden einschließlich der Seiten mit Bildinhalten geprüft. Personenbezogene Beispieldaten daraus werden hier nicht wiederholt.
| Unterlage | Rolle im Audit |
|---|---|
| todos.md, entwicklungskonzept.md | Juli-Grundanforderungen A1/A2 und B1–B10 sowie dokumentierte Entscheidungen |
| Statistiken kontrolliert.pdf, feedback-analyse-2026-07-24.md | Korrekturen zu Zählung, Ranglisten, Führungskräften, Incentive, Versand und Darstellung |
| feedback-an-kundin-statistiken.md, neuerungen-fuer-berater.md | Nach außen zugesagte Funktionen und Erklärungen |
| Statistik-Aenderungen-19-08-2026.pdf, entwicklungsplan-2026-08-19.md | August-Pakete N1–N8 und nachträgliche Review-Ergebnisse |
| feedback-an-kundin-2026-08-25.md, Screenshot | Erläuterungen, Abgrenzung Incentive/Bestand, offene Detailfragen |
| mivita_Statistiken_07_09_2026.pdf, entwicklungsplan-2026-09-07.md, feedback-an-kundin-2026-09-07.md | Aktuellster Sollstand K1–K9, ausdrücklich offene K10–K15 |
Bei widersprüchlichen Versionen wurden spätere dokumentierte Entscheidungen berücksichtigt: Führungskräfte umfassen die ganze Downline; im September entfallen die Direkt-Spalten. Kundenabo-Umsatzranglisten richten sich nach abgerechneten Punkten. Home zeigt historische Monatsendbestände; VIP-Abo-Bestände bleiben nach dokumentierter Entscheidung aktuell.
| Paket | Implementierung und Bewertung |
|---|---|
| Juli A1/A2: Pause/Kündigung | Eigene Aktionen, Mindestlieferungen, Sperrfrist, externe Erledigungen, Historie und neues Abo nach Kündigung vorhanden. Kritischer Nebenweg A01; unvollständige Historie A16. |
| B1: Provision Stand heute | Live-Service, gespeicherte Monatsabrechnung, PP/Shop/Wachstum und Cache vorhanden. Fehlerzustand A19; gemeinsame Punktebasis A15. |
| B2: Monatsstatistik/Snapshots | Speicherung und Live-Bestandsüberlagerung vorhanden. Monatswerte/Details nicht konsistent eingefroren: A04, A12. |
| B3: Neupartner | Sponsor, Kunden-/Gesamtpunkte und spätere Telefonergänzung vorhanden. A09, A18; gemeinsame Punktebasis A15. |
| B4: 1000-Punkte-Shop | Eigenberücksichtigung vorhanden; Schwellenfilter grundsätzlich sachgerecht. A15 kann die Basis beeinflussen. |
| B5/B6: Top-10 Kundenabos | Mengen- und Punkterangliste, Eigenberücksichtigung und Ist-Sortierung vorhanden. A05/A06. |
| B7: Führungskräfte | Gesamte Downline und deduplizierte Kopfsummen vorhanden; Direkt-Spalten nach September-Anforderung entfernt. Skalierung siehe O2. |
| B8/B10: Payline-Abos/Terminvorschau | Soll/Ist, Anzahl und vier kumulierte Termine vorhanden. A07/A08/A13/A23. |
| B9: neue Abos öffnen | only_new und Links vorhanden. Historischer Linkkontext A12. |
| Juli-Nachbesserungen | Punkte-/Strukturabgrenzung, Abo-Kennzeichnung im Baum, Incentive-Rangfolge und Versandsteuer im jeweiligen Teil geprüft. Keine zusätzliche bestätigte Abweichung bei Ranking-/Versandkorrektur; kein vollständiger Payment-Audit. |
| August N1: Firstlines/Qualifikation | Kacheln, Liste und monatlicher Fortschritt vorhanden. Nicht mit dauerhaftem Karriere-Level gleichzusetzen; A08 im angrenzenden Prognosepfad. |
| N2: historische Home-Abos | Monatsend-Rückrechnung vorhanden. A12/A16 und heutige Teamzuordnung begrenzen die historische Aussage. |
| N3: Recruiter | Rekursive Neupartner-Kette, Starterpaketpunkte und Details vorhanden; September-Kopfsumme dedupliziert. A15/O2. |
| N4: Level-/Provisionsprognose | Vorhanden und als Schätzung zu behandeln; A07/A08/A13/A23. |
| N5: Checkout-Herkunft | Freitext und serverseitige Pflichtvalidierung vorhanden; sprachliche Lücke A21. |
| N6: Top 3/Profilfoto | Team einschließlich Betrachter, drei Kategorien, Foto/Initialen, Einwilligungsprüfung und Löschpfad vorhanden. A11/A20/A23; Scope-Vorbereitung siehe D3. |
| N7: Steueroptionen | Reihenfolge geändert, zugrunde liegende Werte erhalten. Keine bestätigte funktionale Abweichung in diesem Teil. |
| N8: Jahresgebühr | Eigene Teamliste für Berater, Kontakte und vier Fälligkeitsgruppen vorhanden. A17; angekündigter Export fehlt, siehe D4. |
| September K1 | Drei Punktespalten vorhanden; Stornoaufteilung A06. |
| K2/K3/K4 | Direkt-Spalten entfernt, Prognosebasis beschriftet, Abo-Summe ergänzt. Keine zusätzliche Abweichung in diesen Darstellungsänderungen. |
| K5 | Abo-Bestellungen farblich abgesetzt, einschließlich angrenzender Punkteansichten im Arbeitsstand; vorhandene Tests bestanden. |
| K6 | Telefonnummer mit Mobil-Fallback und verständlichere Punktespalten vorhanden; CSV-Summe A09. |
| K7 | Recruiter-Kopfsumme dedupliziert vorhanden. Überlappende Zeilenvolumina sind fachlich beabsichtigt. |
| K8 | Such-/sortierbare Kundenabo-Tabelle vorhanden. A10/A14. |
| K9 | Persönliche Kundenabo-Vorschau vorhanden; ausdrücklich ohne Eigenabo und mit Basis 0. A13. |
| K10–K15 | Laut jüngstem Plan bewusst offen. Kein Implementierungsfehler wegen Nichterfüllung dieser Pakete angesetzt. |
3. Befunde mit Nachweis und Behebungskriterien
A01 — P1: Abo-Regeln über abo_is_active umgehbar
Stellen: app/Repositories/AboRepository.php:122–151, app/Http/Controllers/User/AboController.php (update), Abo-Einstellungsformular.
Die regulären Pause-/Kündigungsaktionen prüfen Mindestlieferungen und Pausenabstand. Daneben übernimmt updateStatus() das übergebene Aktiv-Feld auch bei Selbstbedienung. Dieser Zweig prüft bei Deaktivierung lediglich die Sperrfrist vor der nächsten Ausführung. Die Tatsache, dass der sichtbare Schalter im Formular nur administrativ angeboten wird, schützt die serverseitige Verarbeitung nicht. Auch ein fehlendes Feld wird als false interpretiert.
Nachgestellt: Eigentümer eines Kundenabos, null bezahlte Lieferungen, nächste Ausführung 20.09., Prüfdatum 09.09.; regulärer User-Controller mit action=abo_update_settings, unverändertem Intervall und abo_is_active=0. Ergebnis: active=false, Status 6. Die Mindestlaufzeit kann so durch dauerhafte Deaktivierung umgangen werden; der separate Ein-Zyklus-Pausenpfad wird nicht benutzt. Fremdzugriff auf ein anderes Konto wurde damit nicht nachgewiesen.
Behebung: Aktiv-Toggle im Selbstbedienungspfad serverseitig zurückweisen oder ignorieren; Zustandswechsel ausschließlich über die dafür zugelassenen Aktionen. Administrative Ausnahme nur aus vertrauenswürdigem Controller-Kontext. Abnahme: Owner-Requests für me, ot, Portal, fehlendes Feld, 0, wiederholte De-/Reaktivierung und legitimen Admin-Pfad; Mindestlieferungen und Pausenabstand müssen unabhängig vom Formular gelten.
A02 — P2: Persönliche Monatsstatistik summiert Status 0 und 3
Stellen: app/Services/Backoffice/PersonalStatisticsService.php:29–57,68–81; Vergleich app/Services/Backoffice/SalesVolumePoints.php:20–34.
Die persönliche Auswertung lädt sämtliche Monatsbuchungen des Benutzers und summiert deren Punkte und Nettowerte. Die gemeinsame Punkteauswertung schließt Status 0/nicht zugeordnet und 3/pending ausdrücklich aus. Bei einem einem Benutzer zugeordneten Pending-/Importdatensatz entstehen unterschiedliche Gesamtwerte.
Nachgestellt: 100 gültige + 50 Pending- + 25 Status-0-Punkte ergeben persönlich 175 statt 100. Stornos landen zudem pauschal in „Sonstige“, statt das zugehörige Abo-/Shop-Segment zu mindern.
Behebung: Gemeinsame Definition für zählbare Buchungen und eine vorzeichengetreue Gruppierung anhand der Ursprungsbuchung. Offene Buchungen gegebenenfalls separat anzeigen. Abnahme: Alle relevanten Status, nicht zugeordnete Zeilen mit/ohne user_id, Teil-/Vollstorno und Summengleichheit zu bereinigter gemeinsamer Punktebasis.
A03 — P2: Negative Salden fehlen im Drilldown
Stelle: app/Services/Backoffice/BackofficeDrilldownService.php:284–321.
Die Detailabfragen verwenden für Punktekennzahlen HAVING ... > 0. Damit verschwinden Berater mit negativem Monatssaldo, obwohl deren Beträge in der Übersicht enthalten sind. Die CSV-Ausgabe übernimmt dieselbe gefilterte Liste.
Nachgestellt: Zwei Teammitglieder mit +100 und −40 Punkten: Übersicht 60, Detail-Summe 100. Ein reiner Stornomonat kann eine leere Liste trotz negativem Übersichtswert erzeugen.
Behebung: Negative, relevante Salden einschließen; nur für echte Qualifikationslisten wie „mindestens 1000 Punkte“ den Schwellenfilter behalten. Auch die Verlinkung negativer Werte in der Übersicht prüfen. Abnahme: Übersicht = Detail = CSV für positive, negative und saldierte Monatswerte.
A04 — P2: Snapshot friert nur einen Teil der Monatsauswertung ein
Stellen: app/Services/Backoffice/BackofficeDashboardService.php:56–70,162–224,447–456; app/Services/Backoffice/BackofficeDrilldownService.php:19–45.
Beim Lesen eines gespeicherten Monats überschreibt overlayCurrentAboStock() die gesamte Kundenabo-Topliste. Diese enthält nicht nur den ausdrücklich aktuellen Bestand, sondern auch abgerechnete Monatswerte und deren Aufteilung. Dadurch wird die fachlich erlaubte Bestandsüberlagerung auf eingefrorene Umsatzwerte ausgedehnt.
Nachgestellt: August-Snapshot mit 100 Punkten speichern, zugrunde liegende Buchung auf 200 korrigieren, August wieder öffnen: _meta.source=snapshot, Hauptsumme 100, abgerechnete Ranglistenpunkte 200.
Zusätzlich lesen Detaillisten Monatsbuchungen und Teamzuordnung grundsätzlich neu; sie verwenden weder den gespeicherten Zahlenstand noch dessen Mitgliedermenge. Nach Korrektur, Sponsorwechsel oder Löschung kann ein historischer Klick andere Ergebnisse liefern. Auch „neue Abos“ werden beim erstmaligen Snapshot-Bau über den heutigen Aktivbestand ermittelt. Eine Kündigung zwischen Monatsende und Speicherung kann den vergangenen Monat bereits beim Einfrieren verfälschen.
Behebung: Aktuelle Bestandsfelder und historische Monatswerte getrennt halten. Für historische Details denselben Auswertungsstand bereitstellen oder ausdrücklich einen getrennten aktuellen Korrekturstand ausweisen. Payload-Version, Berechnungszeitpunkt und Korrekturversion speichern. Abnahme: Snapshot vor/nach Punkteänderung, Kündigung und Sponsorwechsel; nur ausdrücklich aktuelle Bestandsfelder dürfen sich verändern. Keine pauschale erzwungene Neuberechnung historischer Werte als Ersatz für diese Trennung.
A05 — P2: „Abgerechnete“ Kundenabos werden mit aktuellem Bestand gezählt
Stellen: app/Services/Backoffice/BackofficeDashboardService.php:732–779,1052; Umsatzrangliste im Statistik-Template.
Die Umsatzliste sortiert richtig nach points_actual, bezieht abo_count aber aus heute aktiven Kundenabos. Das beantwortet nicht den Kundenwunsch, mit wie vielen abgerechneten Abos die Punkte entstanden sind. Die Filterung lässt außerdem Zeilen mit positivem Soll und null Ist in die Umsatzliste, solange Platz vorhanden ist.
Nachgestellt: Ein inzwischen gekündigtes Kundenabo hat im gewählten Monat 100 Punkte erzeugt. Ranglistenanzeige: 100 abgerechnete Punkte, 0 Abos. Umgekehrt erhöhen neue, noch nicht abgerechnete Abos die angezeigte Anzahl.
Behebung: Abgerechnete, unterschiedliche Abo-IDs aus Monatsbestellungen/Verknüpfungen ermitteln; aktuellen Bestand separat beschriften. Storno-/Teilstorno-Regel für diese Anzahl festlegen. Abnahme: Kündigung nach Abrechnung, Neuabo vor Erstabbuchung, mehrere Ausführungen desselben Abos, vollständig stornierte Ausführung.
A06 — P2: Einmal-Zusätze bleiben nach Vollstorno stehen
Stellen: app/Services/Backoffice/BackofficeDashboardService.php:748–765,851–883.
Für Zusätze werden unterschiedliche Benutzer-/Bestellungs-Paare gesammelt und anschließend die ursprünglichen positiven Positionspunkte addiert. Vorzeichen und Nettowirkung der Monatsbuchungen gehen dabei verloren. Das abschließende Begrenzen auf die Gesamtpunkte garantiert lediglich eine rechnerisch passende Summe, keine fachlich richtige Aufteilung.
Nachgestellt: Bestellung 100 mit 20 Zusatzpunkten, vollständig mit −100 storniert; weitere reine Abo-Bestellung 100. Ausgabe: Gesamt 100, Zusatz 20, wiederkehrend 80. Erwartet: Gesamt 100, Zusatz 0, wiederkehrend 100. Bei negativem Gesamtwert kann die Begrenzung zudem einen negativen Zusatzanteil unabhängig von dessen tatsächlicher Herkunft erzeugen.
Behebung: Vorzeichen und Stornoanteile pro Bestellung berücksichtigen, erst anschließend je Berater summieren. Abnahme: Voll-/Teilstorno, Storno im Folgemonat, mehrere Zuordnungen, Mengen größer 1 und Buchungen ohne rekonstruierbare Positionsdaten; für letztere einen nachvollziehbaren Restposten verwenden.
A07 — P2: Unterschiedliche Teamfilter innerhalb der Payline-Prognosen
Stellen: app/Services/Abo/PaylineForecastService.php:335–376,500–505; Vergleich app/Services/BusinessPlan/BusinessUserItemOptimized.php:1068.
Die Terminvorschau übernimmt alle Mitglieder der ersten N Ebenen aus lineBuckets(). Die Level-/Provisionsvorschau entfernt dagegen System-/Adminkonten, Benutzer ohne Mitgliedsebene/Abrechnungskonto/Aktivierungsdatum und deren Unterbäume entsprechend dem Provisionsbaum.
Nachgestellt: Ein Mitglied ohne m_level, aber mit aktivem 50-Punkte-Kundenabo, liefert 50 offene Punkte in der Terminvorschau und keinen Beitrag zur Level-/Provisionsvorschau. Die unterschiedliche Berücksichtigung liegt im Mitgliederscope, nicht im Provisionsprozentsatz.
Behebung: Einen gemeinsamen, expliziten Provisionsbaum-Kontext für dieselbe Payline-Sicht verwenden. Das ist von der noch offenen generellen Umstellung „Statistik = Struktur“ K11 zu unterscheiden. Abnahme: Ausgeschlossene Zwischenknoten mit aktiver Downline, Admin-/Systemkonto, fehlende Stammdaten, Aktivierung nach Monatsende und identische Mitgliedermenge in allen Payline-Kacheln.
A08 — P2: Nächstes Level wird ohne bestehende Monatsqualifikation nicht prognostiziert
Stellen: app/Services/Abo/PaylineForecastService.php:268–274; app/Services/BusinessPlan/LiveCommissionService.php:162.
buildLevelAndCommissionForecast() beendet die Berechnung, sobald qual_level kein Array ist. Ein vorhandenes nächstes Level und zukünftige persönliche Abo-Punkte reichen nicht aus. Die Fortschrittsanzeige verarbeitet diesen Zustand bereits sinnvoll.
Nachgestellt: Monat ohne qualifiziertes Level, nächstes Level mit 50 persönlichen Punkten als Anforderung, offenes eigenes Kundenabo mit 50 Punkten: Fortschritt vorhanden, Prognose null.
Behebung: „Noch nicht qualifiziert“ als gültigen Ausgangszustand behandeln; tatsächlichen Berechnungsfehler gesondert lassen. Abnahme: Neue Berater und Monatsbeginn ohne Qualifikation, Erreichen der ersten Stufe durch eigene Kundenabos, keinerlei künftige Punkte und echter Fehlerzustand.
A09 — P2: Summenzeile im Neupartner-CSV hat acht statt neun Felder
Stellen: app/Http/Controllers/User/BackofficeStatisticsController.php:241,338.
Nach Ergänzung der Telefonspalte wurde die Summenzeile nicht entsprechend erweitert. 100 Kundenpunkte landen in „Sponsor“, 300 Gesamtpunkte in „Punkte seiner Kunden“; die eigentliche Gesamtpunktespalte bleibt leer.
Nachgestellt: Kopf 9 Spalten, Summe 8; Array ['Summe', '1 Eintraege', '', '', 100, 300, '', ''].
Behebung: Exportspalten zentral definieren und Summen anhand derselben Spaltenzuordnung erzeugen. Abnahme: CSV zurückparsen und Werte anhand der Überschriften prüfen; leere Liste und alle anderen Exportmetriken einschließen.
A10 — P3: N+1-Abfragen in der eigenen Kundenabo-Liste
Stellen: app/Http/Controllers/User/AboController.php:79; resources/views/user/abo/_customer_abo_list.blade.php:87; app/Models/UserAbo.php (getCountPaidOrders).
Der Controller lädt Artikel/Produkte und Kunden vorab, aber nicht die für jede Tabellenzeile ausgewerteten Abo-Aufträge. Der Zugriff auf die Anzahl bezahlter Lieferungen lädt diese pro Abo nach.
Gemessen: Fünf bereits mit den Controller-Relationen geladene Abos verursachen beim Aufruf der Lieferungszahl fünf weitere SQL-Abfragen. Kein Produktions-Latenzwert wurde gemessen.
Optimierung: Passendes withCount mit derselben fachlichen Bezahlt-/Erledigt-Bedingung oder gebündeltes Laden der tatsächlich benötigten Aufträge. Abnahme: Query-Anzahl wächst nicht linear mit der Anzahl dargestellter Abos; externe Erledigungen bleiben korrekt enthalten.
A11 — P3: Top-3-Gleichstände sind von der Eingabereihenfolge abhängig
Stelle: app/Services/Team/TopResultsService.php:219–250.
Vor dem vorgesehenen Namens-Tiebreak werden nur die ersten 25 Kandidaten behalten. Ein alphabetisch vorrangiger gleichwertiger Kandidat außerhalb dieses Fensters kann nicht mehr gewinnen. Viele Kandidaten ohne Account können außerdem das zugesagte Auffüllen verhindern.
Nachgestellt: 26 Kandidaten mit jeweils 100 Punkten; „Alpha“ kommt an Position 26, davor „Zulu00“ bis „Zulu24“. Ergebnis beginnt mit „Zulu00“, „Alpha“ fehlt.
Behebung: Vollständigen Sortierschlüssel vor Begrenzung anwenden oder alle Gleichstände an der Auswahlgrenze nachladen; stabile ID als letzte Tie-Break-Regel. Abnahme: Mehr als 25 Gleichstände, umgekehrte Eingabereihenfolge, fehlende Accounts.
A12 — P2: Historische Neuabo-Kachel und verlinkte Liste passen nicht zusammen
Stellen: app/Services/Abo/TeamAboOverviewService.php:88–96,492; resources/views/dashboard/_statistics.blade.php:16–19; app/Services/Backoffice/BackofficeDrilldownService.php:203–247.
Home rekonstruiert einen vergangenen Monatsendbestand. Der Link des Neu-Badges führt dagegen in den VIP-Drilldown, der nur heute aktive Abos filtert. Der Monatsparameter allein stellt keine identische Zeitlogik her.
Nachgestellt: Im August gestartetes Abo, Kündigung am 08.09.: August-Home zeigt „+1“, verlinkte Detailabfrage 0. Ein identischer Filtername only_new verdeckt die verschiedenen Bestandsdefinitionen.
Behebung: Historische Links mit der gleichen Lebenszyklus- und Teamdefinition auswerten. Normale Berater erhalten derzeit nicht dieselbe VIP-Verlinkung; sollte auch ihnen die entsprechende Home-Aufschlüsselung angeboten werden, braucht sie eine eigene berechtigte Route. Abnahme: Monatswechsel, spätere Kündigung/Löschung, aktuelle VIP-Bestände und Berechtigungen getrennt testen; VIP-Schutz nicht zur Vereinfachung entfernen.
A13 — P2: Ausführungstag ist eine Lücke zwischen Ist und Prognose
Stellen: app/Services/Abo/PaylineForecastService.php:182,573; app/Services/Abo/TeamAboOverviewService.php (Abfrage offener Ausführungen).
Offene Abos müssen next_date > heute 23:59:59 erfüllen. Damit fehlen heute fällige Abos schon ab Mitternacht, selbst wenn der Job noch nicht gelaufen ist oder die Zahlung noch nicht gebucht wurde.
Nachgestellt: 10.09., 00:01 Uhr, aktives Kundenabo mit 50 Punkten und next_date=10.09., keine Buchung. Die persönliche Vorschau bis zum 25. zeigt 0.
Einordnung: Der Code entspricht der vereinfachten Planformel „next_date > heute“. Der Befund ist eine Robustheitslücke dieser Formel im Betriebsablauf, nicht eine heimliche Abweichung vom wörtlichen Datumsfilter. Eine Anzeige „bereits in Ist enthalten“ ist vor der tatsächlichen Buchung unzutreffend.
Behebung: Fällige, tatsächlich noch offene Ausführungen berücksichtigen und Doppelzählung über Ausführungs-/Buchungsreferenzen verhindern. Abnahme: Vor und nach Joblauf, verspäteter Job, offene Zahlung, Wiederholung und exakt am Liefertag erfolgte Buchung.
A14 — P2: Sortierung funktioniert nur mit deutschen Formaten
Stellen: resources/views/components/_sortable_table.blade.php:99–114; app/Services/Util.php:41–47; Kundenabo-Tabelle.
Der Datumsparser akzeptiert ausschließlich dd.mm.yyyy, während die Anwendung bei Englisch Y-m-d ausgibt. Der Zahlenparser entfernt sämtliche Punkte und interpretiert Kommas als Dezimaltrennzeichen.
Mit der unveränderten Originalfunktion ausgeführt: 2026-09-20 und 2026-08-05 ergeben beide 0. 999.00 wird 99900, 1,000.00 wird 1; damit kann sich die numerische Reihenfolge umkehren.
Behebung: Unformatierte Sortierwerte als Attribute ausgeben; lokalisierte Texte nur anzeigen. Abnahme: Datum und Punkte in de/en/es/fr, leere Werte, Tausenderseparatoren, negative Werte und gleiche Werte. Die korrekte Tabellenoptik allein genügt hier nicht.
A15 — P1: Shop-Storno überschneidet sich in Eigen- und Kundenpunkten
Stellen: app/Services/Backoffice/SalesVolumePoints.php:30–34,71–74; app/Services/BusinessPlan/SalesPointsVolume.php:105–110,289–306.
Status 6 gehört ohne weitere Einschränkung zu Eigenpunkten. Status 6 mit status_turnover=2 gehört gleichzeitig zu Kundenpunkten. totalPoints() addiert beide Kategorien. Der zugrunde liegende ältere Neuberechnungspfad enthält dieselbe Überschneidung; dies ist nicht allein ein neu eingeführter UI-Fehler. Der Stornobuchungspfad übernimmt status_turnover aus der Ursprungsbuchung.
Nachgestellt: +100 Shop-Punkte mit Status 2 und −100 Storno mit Status 6/status_turnover=2: Buchungsnetto 0, totalPointsByUser() −100. Damit können Gesamtpunkte, Firstlines, Recruiter-/Top-3-Volumen und weitere darauf aufbauende Werte zu niedrig sein. Der konkrete Einfluss auf reale Auszahlungen wurde nicht mit Produktionsdaten ermittelt.
Behebung: Ursprungsart der Stornobuchung eindeutig abbilden und disjunkte Kategorien verwenden. Gemeinsam mit der zentralen Punkte-/Provisionslogik korrigieren; Auswirkungen auf vorhandene Daten vor einer Nachberechnung quantifizieren. Abnahme: Eigen- und Shop-Bestellung jeweils mit Voll-/Teilstorno, unterschiedliche Monate, status_turnover 1/2/null und alte Importfälle; jede Buchung darf zur Gesamtpunktesumme genau einmal beitragen.
A16 — P2: Reaktivierungshistorie deckt nicht alle Schreibpfade ab
Stellen: app/Services/Abo/TeamAboOverviewService.php:168–193; app/Repositories/AboRepository.php:139,148; app/Services/AboHelper.php:528–556; app/Models/UserAboStatusHistory.php.
Die Rückrechnung verwirft ein Abo, wenn ein historischer Deaktivierungseintrag bis Monatsende nicht durch eine spätere protokollierte Reaktivierung aufgehoben wurde. Das Repository protokolliert solche Änderungen. Die Recovery-Fortschreibung setzt jedoch direkt active=true, Status 2, ohne einen entsprechenden Historieneintrag zu schreiben. Das Modell ergänzt diesen Eintrag nicht automatisch.
Zustand nachgestellt: Start im Juli, protokollierte Deaktivierung Ende Juli, anschließende Reaktivierung ohne Log wie im Recovery-Schreibpfad. September-Livebestand 1, August-Bestand 0 trotz vor August-Ende reaktiviertem Abo. Die Gegenprobe erzeugt diesen Datenzustand; sie löst bewusst keine Recovery-Zahlung aus.
Darüber hinaus verwendet Home die heutige Teamzuordnung. Selbst eine vollständige Abo-Statushistorie bildet frühere Sponsor-/Kundenzuordnungen nicht automatisch ab. Die pauschale Zusage „ab Juli exakt“ ist deshalb zu weitgehend.
Behebung: Statusänderungen in allen Formular-, Job-, Payment- und Recovery-Pfaden zentral und transaktional protokollieren. Historische Mitgliedschaft entweder persistieren oder die Kennzahl ausdrücklich als Rückrechnung über das heutige Team benennen. Abnahme: Mehrfache De-/Reaktivierung einschließlich Ereignissen mit identischem Zeitstempel, Recovery, spätere Kündigung/Löschung, Sponsorwechsel und Altdaten ohne Historie.
A17 — P3: Fälligkeitsgruppen verwenden Monatsaddition mit Überlauf
Stelle: app/Services/Team/AnnualFeeDueService.php:88–95.
addMonth() bildet an Monatsenden nicht automatisch „gleicher Tag, begrenzt auf letzten Tag des Folgemonats“ ab. Nachgestellt: Bezugsdatum 31.01.2026 und Fälligkeit 02.03.2026 werden als „innerhalb eines Monats“ gruppiert, weil der Februar überläuft.
Behebung: Gewünschte Kalendersemantik festlegen und etwa addMonthNoOverflow/entsprechende Mehrmonatsvariante verwenden. Abnahme: 28./29. Februar, 30./31. Monatsende, Jahreswechsel und exakt fälliger Tag. Die Definition „ein Kalendermonat“ gegenüber „30 Tage“ im Hilfetext eindeutig machen.
A18 — P2: CSV-Formelinhalte werden nicht neutralisiert
Stellen: app/Http/Controllers/User/BackofficeStatisticsController.php:110–121,251.
Benutzer-/Kontaktdaten werden unverändert an fputcsv() übergeben. CSV-Quoting schützt die Dateistruktur, kennzeichnet einen mit = beginnenden Inhalt aber nicht zuverlässig als Text für Tabellenprogramme.
Nachgestellt: Der synthetische Name =1+1 bleibt unverändert im Exportdatensatz. Eine tatsächliche Ausführung externer Aktionen oder ein Angriff auf eine Tabellenanwendung wurde nicht durchgeführt. Das Risiko entsteht beim späteren Öffnen entsprechender, von anderen Personen kontrollierbarer Textfelder.
Behebung: Textspalten für die unterstützten Tabellenprogramme sicher als Text exportieren; Formelpräfixe einschließlich führender Steuerzeichen berücksichtigen. Fachliche Zahlenspalten bleiben numerisch. Abnahme: Harmlose Formelstrings, Namen, internationale Telefonnummern mit +, negative Zahlen, Anführungszeichen und mehrzeilige Texte; CSV-Rückimport und vorgesehenen Tabellenclient prüfen.
A19 — P2: „Berechnung fehlgeschlagen“ wird zu „0,00 Euro“
Stellen: app/Services/BusinessPlan/LiveCommissionService.php:63–88,123–126; app/Http/Controllers/HomeController.php:190.
Der Snapshot kennzeichnet einen Live-Berechnungsfehler korrekt mit failed=true. commission() reicht diesen Zustand nicht weiter und berechnet aus den Ersatzwerten einen Nullbetrag. Auch der Home-Payline-Helfer übernimmt nur Punkte und Live-Kennzeichen. Die Oberfläche kann so einen echten Nullstand und eine nicht verfügbare Berechnung nicht unterscheiden.
Behebung: Fehler-/Verfügbarkeitsstatus bis zum Template erhalten, gegebenenfalls letzten erfolgreichen Stand mit Zeitstempel zeigen. Keine Prognose auf einer fehlgeschlagenen Nullbasis als normale Auswertung ausgeben. Abnahme: Erzwungene Berechnungsausnahme gegenüber fachlich korrektem Nullmonat; vorhandene Tests für Null-Fallback um die sichtbare Fehlerkennzeichnung ergänzen.
A20 — P2: Teaminterne Bilder werden auf öffentlichem Datenträger ausgeliefert
Stellen: app/Services/Slim.php:35–57; app/Http/Controllers/ProfileImageController.php:40–53; app/Models/UserAccount.php:376–388; config/filesystems.php:62–66.
Die Ranglisten-Seite begrenzt ihre Personenauswahl auf das Team. Die Bilddatei wird jedoch auf der öffentlichen Disk gespeichert und mit /storage/images/profile/... verlinkt. Dieser Pfad hat in der Anwendung keine Team-/Anmeldeprüfung. Bei der vorgesehenen öffentlichen Storage-Auslieferung reicht die Kenntnis der URL zum Abruf außerhalb der Teamseite.
Einordnung: Belegt ist die fehlende Zugriffskontrolle im Auslieferungsentwurf. Ob die konkrete Produktions-Webserverkonfiguration die URL tatsächlich öffentlich ausliefert, wurde nicht extern getestet. Upload-Eigentümerschaft, JPEG-/PNG-Inhaltsprüfung, erzwungene Dateiendung und Bildlöschung sind positive Schutzmaßnahmen, lösen diese Sichtbarkeitsfrage aber nicht.
Behebung: Für ausdrücklich teaminterne Fotos private Ablage mit berechtigtem Abruf verwenden oder die öffentliche Bildsichtbarkeit ausdrücklich als Produktentscheidung festhalten. Dies ist keine Bewertung der rechtlichen Wirksamkeit des Einwilligungstexts. Abnahme: Eigenes Team, fremdes Team, unangemeldeter Abruf, Teamwechsel und gelöschtes Bild.
A21 — P3: Neue Texte umgehen teilweise die Sprachdateien
Stellen: app/Services/Backoffice/BackofficeDashboardService.php:36; app/Services/Backoffice/PersonalStatisticsService.php:37; app/Http/Controllers/User/BackofficeStatisticsController.php:226; resources/views/user/backoffice/statistics/; resources/views/web/templates/checkout.blade.php:557.
Mehrere Überschriften, Gruppenbezeichnungen, Tooltips und CSV-Spalten werden weiterhin direkt deutsch ausgegeben. Auch das Herkunfts-Freitextfeld enthält deutsche Beschriftungen. Damit wird die in den Plänen genannte Unterstützung de/en/es/fr nicht durchgängig erreicht. Ein Test auf gleiche Sprachschlüssel kann solche hart codierten Texte nicht finden.
Die ausgeführte angrenzende Testsuite meldet zusätzlich zwei bestehende Schlüsselabweichungen: payment.php fehlen in es und fr jeweils 25 deutsche manual_*-Schlüssel. Dies ist ein Befund des vorhandenen Arbeitsstands; eine Verursachung durch die Statistikpakete ist damit nicht belegt.
Behebung: Sichtbare neue Texte/Exportüberschriften in Sprachdateien überführen und Ansichten pro Sprache prüfen. Abnahme: Nicht nur Key-Parität, sondern gerenderte Beschriftungen sowie Zahlen-/Datumsverhalten aus A14.
A22 — P2: Snapshot-Batch gibt bereits berechnete Teambäume nicht frei
Stellen: app/Providers/AppServiceProvider.php:76; app/Services/Backoffice/BackofficeDashboardService.php:81–112,253; app/Console/Commands/BackofficeStoreStatisticsSnapshots.php:46–82.
Der Dashboard-Service ist ein Singleton und hält lineBuckets je Root-ID in einer Instanz-Memoisierung. storeSnapshot() leert nur die Memoisierung des aktuell berechneten Roots. Der Batch iteriert über sämtliche VIPs; die zuvor berechneten anderen Roots bleiben referenziert. gc_collect_cycles() kann diese regulär erreichbaren Arrays/Modelle nicht freigeben. Zusätzlich werden sämtliche zu bearbeitenden Benutzer vorab geladen.
Risiko: Bei vielen VIPs mit überlappenden großen Teams steigt der Speicherbedarf mit der Summe der gehaltenen Teilbäume, nicht nur mit dem gerade bearbeiteten Team. Ein realer Speicherabbruch wurde nicht provoziert und keine Produktionsgröße geschätzt.
Behebung: Memoisierung am Ende eines Root-Durchlaufs vollständig freigeben oder einen begrenzten Berechnungskontext verwenden; Benutzer per ID chunken. Abnahme: Batch mit vielen überlappenden Teams und Memory-Messung nach jedem Root; dauerhaft begrenzter Speicher und gleiche Snapshot-Ergebnisse.
A23 — P2: Sechs-Stunden-Caches sind untereinander und mit Live-Daten nicht konsistent
Stellen: app/Services/BusinessPlan/LiveCommissionService.php:55–65; app/Services/Abo/PaylineForecastService.php (forecastDays, levelAndCommissionForecast, paylineContext); app/Services/Team/TopResultsService.php:48–65,94–116; app/Http/Controllers/HomeController.php:118.
Die vereinbarte sechs Stunden alte Anzeige ist an sich kein Fehler. Problematisch ist das Mischen verschiedener Zeitstände: Bereits berechnete Payline-/Provisionspunkte können im Cache liegen, während offene Abos frisch gelesen werden. Nach Zahlung und Fortschreibung von next_date ist ein Abo nicht mehr offen, seine neuen Punkte fehlen aber noch in der zwischengespeicherten Basis. Die Prognose kann dadurch vorübergehend absinken. Separate Cache-Erzeugungszeiten verschärfen die Abweichung.
Bei Top 3 werden Bilder frisch ergänzt, die zwischengespeicherten Namen/Werte aber nicht gegen Löschung oder geänderte Teamzuordnung gefiltert. Ein verschwundener Benutzer kann bis zum Ablauf weiter als Ranglistenzeile stehen bleiben. Für aktuelle Teamzugriffe ist das eine andere Fragestellung als absichtlich aufbewahrte historische Auswertungen.
Nachweisgrenze: Die beteiligten Datenflüsse wurden gelesen; ein vollständiger nebenläufiger Zahlungs-/Jobablauf wurde nicht ausgelöst. Der jüngste Plan nennt die fehlende Invalidierungsstrategie bereits selbst als offen.
Behebung: Gemeinsamen Auswertungszeitpunkt bzw. Datenversionsschlüssel verwenden; nach relevanten Buchungs-/Abo-/Teamänderungen gezielt invalidieren. Aktuelle Sichtbarkeit unabhängig von Zahlen-Caches prüfen. Abnahme: Auszahlung/Buchung zwischen zwei Requests, Sponsorwechsel, Löschung, gleichzeitige Requests und keine doppelte Berücksichtigung frisch gebuchter Ausführungen.
4. Weitere Optimierungsmöglichkeiten
Diese Punkte ergänzen die konkreten Befunde; Laufzeitgewinne wurden nicht behauptet oder ohne Messung beziffert.
| ID | Ansatz | Betroffene Stellen und sinnvolle Messung |
|---|---|---|
| O1 | Monatswachstum gebündelt berechnen | TeamAboOverviewService::monthlyGrowth() fragt Monate/Arten wiederholt ab. Gemeinsame Datenbasis oder Monatsaggregation mit identischer historischer Zustandslogik verwenden; SQL-Anzahl und Laufzeit für zwölf Monate vergleichen. Nicht pauschal auf heutige Aktiv-Abos vereinfachen. |
| O2 | Wiederholte Baumdurchläufe vermeiden | BackofficeDashboardService::teamIdsPerLeader() und die rekursive Kettenberechnung in recruiterRanking() laufen mehrfach über überlappende Unterbäume. Bottom-up-Zwischenergebnisse und effiziente Queue statt wiederholtem array_shift; lange Kette, breites Team und Zyklen testen. |
| O3 | Monatsaggregate je Benutzer/Linie wiederverwenden | buildLineRow() und weitere Listen berechnen ähnliche Punktesummen separat. Gebündelte Aggregation mit gemeinsamer Statusdefinition reduziert Abfragen und fachliche Drift. Produktionsnahe EXPLAIN-Pläne für Monats-/Benutzerfilter und Abo-Zuordnung prüfen, bevor neue Indizes vorgeschlagen werden. |
| O4 | Snapshot-Schema und Zeitgrenzen ausdrücklich modellieren | JSON-Payloads ohne durchgängige fachliche Schema-/Korrekturversion und manuelle --force-Rebuilds erschweren Reproduzierbarkeit. Speichern von Version, Quelle, Stichtag und Finalisierungsstatus; alte Payloads bewusst lesen/migrieren. Tiefenbegrenzungen bei Bäumen bei Erreichen sichtbar diagnostizieren statt unbemerkt abzuschneiden. |
5. Dokumentationslücken und offene Produktentscheidungen
D1 — Überzogene Abschlussaussagen. Formulierungen wie „alle Zahlen korrekt“ und „ab Juli exakt“ müssen nach A01–A23 eingeschränkt werden. Der August-Plan bezeichnet fehlende historische Deaktivierungen teils als Grund für „zu hohe“ Werte; der aktuelle Query kann solche Abos auch ausschließen und damit zu niedrige Werte liefern. Richtung und Ursache einer Näherung sollten konkret beschrieben sein.
D2 — Falsche Erklärung zu abgelaufenen Mitgliedschaften. September-Plan und Kundenbrief sagen, der Provisionsbaum schließe Berater mit abgelaufener Jahresgebühr aus. Die hier geprüften Filter in BusinessUserItemOptimized::readParentsBusinessUsers() und PaylineForecastService::countsInCommissionTree() prüfen ein gesetztes payment_account, nicht dessen Gültigkeit gegenüber heute. Indirekte Änderungen durch Cleanup-Jobs sind möglich, aber keine gleichwertige Datumsprüfung. Vor der Entscheidung zu K11 die tatsächlichen Baumprädikate erklären und mit passenden Fixtures belegen.
D3 — Scope-Schalter nur vorbereitet. TopResultsService::SCOPE = 'team' existiert, wird von scopedUserIds() aber nicht ausgewertet. Ändern der Konstante schaltet daher nicht auf firmenweit um. Der technische Kommentar sagt zutreffend, dass die Methode später zu erweitern ist; die Darstellung als schon nutzbarer Schalter im August-Plan geht darüber hinaus. Die gegenwärtige teaminterne Auswertung entspricht der dokumentierten Entscheidung. K10 bleibt offen.
D4 — Jahresgebühr-CSV fehlt. N8 nennt im Umsetzungsvorschlag einen CSV-Export analog zu Drilldowns. Die geprüfte Jahresgebühr-Seite und ihre Routen bieten diesen Export nicht. Entweder als noch offenes Teilstück erfassen oder den akzeptierten Lieferumfang ausdrücklich auf die Ansicht begrenzen. Keine automatische Jahresgebühr-Abbuchung daraus ableiten; diese gehört zum offenen K13.
D5 — Offene Pakete konsistent zählen. Der September-Plan benennt K10–K15, also sechs Pakete. Der Kundenbrief spricht wiederholt von vier offenen/großen Themen und stellt sieben Fragen. Gruppierung und Paketzuordnung erläutern, damit eine ausstehende Entscheidung nicht als erledigte Entwicklung erscheint.
Die offenen Themen bleiben:
| Paket | Ausstehende Entscheidung/Planung laut Unterlagen |
|---|---|
| K10 | Firmenweite Ranglisten und finaler Einwilligungstext |
| K11 | Gemeinsame Definition für Statistik-/Provisionsbaum und weitere Sicht auf abgelaufene Konten |
| K12 | Zeitpunkt und Umkehrbarkeit des Kunden-/Teamübergangs bei Deaktivierung |
| K13 | Automatische Jahresgebühr, Reichweite für neue/bestehende Berater und Zahlungsablauf |
| K14 | Kundenabo in Partnerabo umwandeln, bisherige Lieferungen und Kompensationsprodukte |
| K15 | Zusatzprodukte bei Registrierung und fachliche Punktezuordnung |
6. Bewusst nicht als Fehler bewertet
- Incentive-Qualifikationen sind eine andere Größe als der aktuelle Abo-Bestand. Der Vergleich der Kundenscreenshots allein beweist keinen Zählfehler.
- Überlappende Führungskräfte-/Recruiter-Zeilen sind bei vollständigen Downlines/Ketten zu erwarten. Eine deduplizierte Kopfsumme muss nicht der Addition dieser überlappenden Zeilen entsprechen.
- Home-Historie und aktueller VIP-Abo-Bestand entsprechen verschiedenen dokumentierten Perspektiven. Fehlerhaft sind Vermischung und unpassende Verlinkung, nicht diese Entscheidung an sich.
- Die allgemeine Terminvorschau enthält gemäß dokumentierter Annahme eigene Abos und eigene Kundenabos. Die separate persönliche Kundenabo-Vorschau hat bewusst Basis 0 und enthält nur noch kommende eigene Kundenabo-Punkte.
- Eine Level-/Provisionsprognose ist keine garantierte spätere Auszahlung; zukünftige Rang-/Bonusänderungen können die tatsächliche Abrechnung verändern. Die geprüften Fehler betreffen auch innerhalb dieser zulässigen Näherung die Datenbasis und Behandlung gültiger Ausgangszustände.
- Die geprüften Statistik-/Abo-Routen verwenden angemeldeten Benutzer, Rollenprüfung und eigene Teamzuordnung. Ein beliebiger fremder Statistik-Root über einen Requestparameter wurde in den geprüften Pfaden nicht festgestellt. A01 ist eine Umgehung der eigenen Abo-Regeln, kein Nachweis einer allgemeinen Fremdkontoübernahme.
7. Prüfung, Grenzen und nächster Umsetzungsschritt
| Prüfung | Ergebnis |
|---|---|
| Vorhandene Tests der Statistik-Kernmodule | 109 bestanden, 678 Assertions |
| Vorhandene Tests angrenzender Abo-/Profil-/Checkout-/Incentive-/Sprachfunktionen | 105 bestanden, 2 fehlgeschlagen, 553 Assertions; beide Fehler sind Sprachschlüssel-Parität es/fr |
| Zusätzliche isolierte PHP-Gegenproben | 16 bestanden, 30 Assertions; sie bestätigen ausdrücklich das beschriebene fehlerhafte Verhalten, nicht dessen Behebung |
| Unveränderte JavaScript-Sortierfunktion | Vier Eingaben ausgeführt; Fehlinterpretationen aus A14 bestätigt |
| PHPUnit-Konfiguration | Warnung wegen veraltetem XML-Schema; nicht verändert |
| Schutz vorhandener Dateien | SHA-256-Vergleich gegen vorab erfasste 10.385 vorhandene Dateien; Abschlussnachweis im Prüfprotokoll |
Der Audit umfasst die beschriebenen Module einschließlich ihrer fachlichen Datenzuflüsse, Ansichten, Exporte, Berechtigungsanbindung, Persistenz und vorhandenen Tests. Er ist kein vollständiger Audit der gesamten CRM-/Payment-Anwendung. Es wurde kein Gesamt-Testlauf sämtlicher Repository-Tests, kein Browser-End-to-End-Test über alle Hosts, kein Lasttest und kein Abgleich mit realen Monatsabrechnungen durchgeführt. Deshalb werden weder tatsächliche Kundenzahlen noch Produktionsverfügbarkeit oder Fehlerfreiheit außerhalb des Prüfbereichs bestätigt.
Für eine spätere Behebung zuerst A01 und die disjunkte Punkte-/Stornosemantik A15 absichern. Anschließend die oben genannten Regressionen in die regulären Tests übernehmen, historische und aktuelle Berechnungen sauber verbinden und Exporte/Zugriffskanten korrigieren. Vor Nachberechnung bereits abgeschlossener Monate einen nachvollziehbaren Vergleich alter/neuer Ergebnisse erstellen; dieser Audit hat solche Datenänderungen nicht vorgenommen.