13-05-2026 implementation FR
This commit is contained in:
parent
245c281541
commit
70240d2b6a
61 changed files with 4472 additions and 2 deletions
417
dev/2026-05-13-backoffice/ENTWICKLUNGSKONZEPT-BACKOFFICE.md
Normal file
417
dev/2026-05-13-backoffice/ENTWICKLUNGSKONZEPT-BACKOFFICE.md
Normal file
|
|
@ -0,0 +1,417 @@
|
|||
# Entwicklungskonzept: Backoffice Dashboard & Interaktivität
|
||||
|
||||
Datum: 13.05.2026
|
||||
|
||||
Quelle: `docs/salescenter/Todos Backoffice.md`
|
||||
|
||||
## Zielbild
|
||||
|
||||
Das Partner-Backoffice soll von einer statischen Monats-Kachelansicht zu einer klickbaren, linienbasierten Statistik ausgebaut werden. Führungskräfte sollen von der Gesamtübersicht über Linien und Generationen bis zu einzelnen Kunden, Partnern und Abos navigieren können.
|
||||
|
||||
Kernziel ist eine einheitliche Datenbasis für:
|
||||
|
||||
- Dashboard-Kennzahlen pro Linie 1 bis 8 inklusive Summenzeile
|
||||
- Detailansichten je Linie, Firstline und Kennzahl
|
||||
- Kundenabos, Teamabos, Kundenabos im Team, Umsatz und Punkte
|
||||
- neue Spezial-Kennzahl "1000 Punkte Shop"
|
||||
- saubere Begrifflichkeit und rechtssichere Sichtbarkeit in Incentive-Ranglisten
|
||||
|
||||
## Bestandsaufnahme im System
|
||||
|
||||
### Dashboard
|
||||
|
||||
Aktueller Einstieg:
|
||||
|
||||
- Route: `GET /home`
|
||||
- Controller: `App\Http\Controllers\HomeController@show`
|
||||
- View: `resources/views/home.blade.php`
|
||||
- Statistik-Partial: `resources/views/dashboard/_statistics.blade.php`
|
||||
|
||||
Die aktuelle Statistik wird direkt im Blade-Partial berechnet. Sie nutzt unter anderem:
|
||||
|
||||
- `App\Models\UserBusiness` für gespeicherte Monatswerte und Payline-Punkte
|
||||
- `App\Models\UserSalesVolume` für Kunden-/Shop-Punkte
|
||||
- `App\Models\UserAbo` für eigene Abos, Kundenabos und Teamabos
|
||||
- rekursive Sponsor-Abfragen über `users.m_sponsor`
|
||||
|
||||
Bewertung:
|
||||
|
||||
- Die vorhandene Ansicht ist ein guter Einstieg, aber fachlich zu grob.
|
||||
- Es gibt noch keine Linien 1 bis 8, keine Summenzeile und keine Drill-down-Routen.
|
||||
- Die Kennzahl "Kundenabos" vermischt aktuell eigene Abos und Kundenabos.
|
||||
- "Team-Abos" zählt aktuell Beraterabos im Team, aber nicht die separat geforderten Kundenabos im Team.
|
||||
|
||||
### Team- und Abo-Bereich
|
||||
|
||||
Relevante Routen und Controller:
|
||||
|
||||
- `User\TeamController@structure` für Strukturansicht
|
||||
- `User\TeamController@show` und `datatableOptimized` für Teamliste
|
||||
- `User\TeamController@showAbos` für Team-Beraterabos
|
||||
- `User\TeamController@showTeamCustomerAbos` für Kundenabos im Team
|
||||
- `User\TeamController@detailAbo` für Abo-Details
|
||||
|
||||
Relevante Daten:
|
||||
|
||||
- `UserAbo::is_for = 'me'` bedeutet Berater-/Eigenabo
|
||||
- `UserAbo::is_for = 'ot'` bedeutet Kundenabo
|
||||
- `UserAbo::user_id` ist der Bestell-/Abo-User
|
||||
- `UserAbo::member_id` ist der zugeordnete Berater
|
||||
- `UserAbo::next_date` liefert die nächste Abo-Ausführung
|
||||
- `UserAbo::getTotalPoints()` berechnet Punkte aus Abo-Items und Produkten
|
||||
- `AboHelper::getTeamUserIds()` liefert Downline-User-IDs
|
||||
- `AboHelper::getMonthlyAboCounts()` kennt bereits die Scopes `team_abos` und `team_cust_abos`
|
||||
|
||||
Bewertung:
|
||||
|
||||
- Viele Datenquellen für die geforderten Listen existieren bereits.
|
||||
- Die Logik ist aber auf mehrere Controller, Blades und Helper verteilt.
|
||||
- Für das neue Dashboard sollte die Logik zentralisiert werden, statt weitere Berechnungen in Blade-Dateien zu ergänzen.
|
||||
|
||||
### Business- und Punkteberechnung
|
||||
|
||||
Relevante Bausteine:
|
||||
|
||||
- `App\Services\BusinessPlan\TreeCalcBotOptimized`
|
||||
- `App\Models\UserBusiness`
|
||||
- `App\Models\UserSalesVolume`
|
||||
- `App\Services\BusinessPlan\SalesPointsVolume`
|
||||
|
||||
Bewertung:
|
||||
|
||||
- Für Monats- und Teamwerte sollte bevorzugt auf gespeicherte Businessdaten zurückgegriffen werden.
|
||||
- Live-Berechnung über TreeCalcBot ist als Fallback sinnvoll, darf aber nicht bei jedem Seitenaufruf ungefiltert große Strukturen neu berechnen.
|
||||
- Die neue Drill-down-Logik benötigt klare Regeln, ob sie Live-Daten oder gespeicherte Monats-Snapshots zeigt.
|
||||
|
||||
### Incentives
|
||||
|
||||
Relevante Dateien:
|
||||
|
||||
- `App\Http\Controllers\User\IncentiveController`
|
||||
- `resources/views/user/incentive/show.blade.php`
|
||||
- `App\Models\IncentiveParticipant`
|
||||
- `App\Services\Incentive\IncentiveTracker`
|
||||
|
||||
Status:
|
||||
|
||||
- Teilnahme-Opt-in existiert über `accepted_terms_at`.
|
||||
- Ranking wird aktuell mit `paginate(100)` angezeigt.
|
||||
- Nicht zustimmende Teilnehmer werden für normale User anonymisiert.
|
||||
- VIP-Ansicht sieht zusätzliche Hinweise zur Zustimmung.
|
||||
|
||||
Lücke zum Briefing:
|
||||
|
||||
- Es gibt noch keine separate Zustimmung "Name/Fotos/Land in Rangliste sichtbar".
|
||||
- Foto und Land sind in der aktuellen Rangliste nicht als sichtbare Standardspalten umgesetzt.
|
||||
- Rechtliche Freigabe muss fachlich vor der technischen Umsetzung geklärt werden.
|
||||
|
||||
### Checkout-Herkunft
|
||||
|
||||
Relevante Dateien:
|
||||
|
||||
- `App\Http\Controllers\Web\CheckoutController`
|
||||
- `App\Repositories\CheckoutRepository`
|
||||
- `App\Models\ShoppingUser`
|
||||
|
||||
Status:
|
||||
|
||||
- `CheckoutController::validateCheckoutData()` validiert Basisdaten, aber keine Pflichtfrage "Von wem hast du von Mivita erfahren?"
|
||||
- `ShoppingUser` nutzt `is_from` für den technischen Ursprung wie `shopping`, `homeparty` oder `collection`.
|
||||
- Ein fachliches Herkunfts-/Empfehlungsfeld existiert nicht als sauber getrennte Datenquelle.
|
||||
|
||||
### Storno und Punkterückführung
|
||||
|
||||
Relevante Dateien:
|
||||
|
||||
- `App\Repositories\InvoiceRepository`
|
||||
- `App\Services\BusinessPlan\SalesPointsVolume`
|
||||
- `App\Services\Incentive\IncentiveTracker`
|
||||
|
||||
Status:
|
||||
|
||||
- Beim Erstellen einer Stornorechnung ruft `InvoiceRepository::createCancellation()` die Punktekorrektur auf.
|
||||
- `SalesPointsVolume::cancelSalesPointsVolume()` erstellt einen negativen `UserSalesVolume`-Eintrag mit Status `6`.
|
||||
- Danach wird der Monat neu berechnet und `IncentiveTracker::trackStorno()` informiert.
|
||||
|
||||
Risiken:
|
||||
|
||||
- Wenn zur Originalrechnung kein `UserSalesVolume` existiert, wird nur geloggt und keine Punktekorrektur erstellt.
|
||||
- Der negative Storno-Eintrag wird aktuell dem aktuellen Monat zugeordnet, nicht zwingend dem ursprünglichen Umsatzmonat.
|
||||
- Fachlich muss entschieden werden, ob Stornos im Stornomonat oder im Ursprungsmonat wirken sollen.
|
||||
|
||||
## Fachliche Prüfung der To-dos
|
||||
|
||||
### 1. Überarbeitetes Dashboard & KPI-Übersicht
|
||||
|
||||
Umsetzung sinnvoll, aber nicht als Erweiterung des bestehenden Blade-Partials. Benötigt wird ein dedizierter Service, der die Kennzahlen pro Linie liefert.
|
||||
|
||||
Vorgeschlagene Tabelle Stufe 1:
|
||||
|
||||
- Linie
|
||||
- Anzahl Berater
|
||||
- Umsatz gesamt
|
||||
- Eigen-/Beraterabos im Team
|
||||
- eigene Kundenabos
|
||||
- Kundenabos im Team
|
||||
- Neupartner
|
||||
- 1000 Punkte Shop
|
||||
- Summe
|
||||
|
||||
Wichtig:
|
||||
|
||||
- "Teamkundenabos" sollte als Begriff für Kundenabos der Downline verwendet werden.
|
||||
- "Teamabos" sollte nur für Berater-/Eigenabos im Team verwendet werden.
|
||||
- Eigene Abos dürfen nicht in Kundenabos eingerechnet werden.
|
||||
|
||||
### 2. Interaktivität & Deep Dive
|
||||
|
||||
Umsetzung über eigene Backoffice-Statistik-Routen statt über große Modals im Dashboard.
|
||||
|
||||
Vorgeschlagene Stufen:
|
||||
|
||||
- Stufe 1: Linienübersicht `/user/backoffice/statistics`
|
||||
- Stufe 2: Linien-/Firstline-Detail `/user/backoffice/statistics/line/{line}`
|
||||
- Stufe 3: Kennzahlenliste `/user/backoffice/statistics/details?line=...&metric=...&user=...`
|
||||
|
||||
Jede Zahl erhält einen Link auf eine gefilterte Detailansicht. Die Detailansicht sollte die Query-Parameter sichtbar halten, damit Support und Fachbereich Ergebnisse reproduzieren können.
|
||||
|
||||
### 3. Spezial-Kennzahl "1000 Punkte Shop"
|
||||
|
||||
Definition muss vor Umsetzung final geklärt werden.
|
||||
|
||||
Vorschlag für Version 1:
|
||||
|
||||
- Zeitraum: gewählter Monat/Jahr des Dashboards
|
||||
- Personenkreis: Downline des eingeloggten Users
|
||||
- Schwelle: `UserSalesVolume` Shop-/KP-Summe pro Partner >= 1000 Punkte
|
||||
- Sortierung: Volumen absteigend
|
||||
- Detailspalten: Name, Account, Linie/Generation, Shop-Punkte, Gesamt-KP, Umsatz netto
|
||||
|
||||
Offene Fachfrage:
|
||||
|
||||
- Meint "Kundenumsatz" nur Shop-Umsatz (`month_shop_points`) oder alle Kundenpunkte inklusive Abo-/Beraterkontext?
|
||||
|
||||
### 4. Bestellformular: "Von wem hast du von Mivita erfahren?"
|
||||
|
||||
Technisch sollte ein neues fachliches Feld eingeführt werden, nicht `is_from` zweckentfremdet werden.
|
||||
|
||||
Vorschlag:
|
||||
|
||||
- Migration für `shopping_users.referral_source_name` oder ähnliches Feld
|
||||
- optional zusätzlich auf `shopping_orders`, wenn die Information revisionssicher pro Bestellung eingefroren werden soll
|
||||
- Pflichtvalidierung in `CheckoutController::validateCheckoutData()`
|
||||
- Anzeige im Checkout-Formular und optional im Admin-/Bestelldetail
|
||||
- später exportierbar für Marketingauswertung
|
||||
|
||||
Zu klären:
|
||||
|
||||
- Freitext oder Auswahl plus Freitext?
|
||||
- Pflicht nur im Webshop/Bestelllink oder auch bei Salescenter-, Homeparty- und Collection-Flows?
|
||||
- Soll eine konkrete Beraterzuordnung daraus entstehen oder nur Tracking?
|
||||
|
||||
### 5. Stornoprozess
|
||||
|
||||
Die Grundlogik existiert. Vor einer fachlichen Freigabe braucht es Tests und eine Periodenentscheidung.
|
||||
|
||||
Prüfpunkte:
|
||||
|
||||
- Storno einer Beraterbestellung erzeugt negative Punkte beim richtigen Berater.
|
||||
- Storno einer Kunden-/Shopbestellung erzeugt negative Punkte im richtigen Umsatztyp.
|
||||
- Storno einer Abo-Bestellung wirkt korrekt auf Incentive-Logs.
|
||||
- Storno ohne vorhandenen `UserSalesVolume` ist sichtbar und lösbar, nicht nur ein Log-Eintrag.
|
||||
- Businessdaten nach Storno werden für betroffenen Monat/Jahr aktualisiert oder als neu zu berechnen markiert.
|
||||
|
||||
### 6. Rechtliches & Sichtbarkeit in Incentives
|
||||
|
||||
Die bestehende Teilnahmezustimmung sollte nicht automatisch als Freigabe für öffentliche Namens-/Fotoanzeige interpretiert werden.
|
||||
|
||||
Vorschlag:
|
||||
|
||||
- eigenes Feld auf `incentive_participants`, z. B. `ranking_visibility_accepted_at`
|
||||
- Button/Checkbox in der Incentive-Seite: "Ich stimme zu, dass mein Name, Foto und Land in der Rangliste sichtbar sind"
|
||||
- Anzeige von Name, Foto und Land nur, wenn die Zustimmung vorliegt oder ein Admin/VIP die Ansicht nutzt
|
||||
- nach juristischer Klärung kann die Regel angepasst werden
|
||||
|
||||
Technische Ergänzungen:
|
||||
|
||||
- Ranking um Foto und Land erweitern
|
||||
- Pagination/Limit bewusst definieren: alle Teilnehmer anzeigen, aber paginiert
|
||||
- Übersetzungen in `resources/lang/*/incentive.php` ergänzen
|
||||
|
||||
### 7. Multimedia-Bereich / Event-Archiv
|
||||
|
||||
Es gibt bereits Dashboard-News und ein News-Archiv. Für Events sind zwei Varianten möglich:
|
||||
|
||||
Variante A: `DashboardNews` um Typ "event" erweitern
|
||||
|
||||
- weniger Aufwand
|
||||
- bestehendes Admin-Modul kann wiederverwendet werden
|
||||
- geeignet, wenn Events im gleichen Format wie News funktionieren
|
||||
|
||||
Variante B: eigenes Event-Modul
|
||||
|
||||
- sauberere Trennung
|
||||
- eigene Felder für Galerie, Eventdatum, Call-/Foto-Typ
|
||||
- sinnvoll, wenn Uploads, mehrere Bilder pro Event oder Kategorien benötigt werden
|
||||
|
||||
Empfehlung: Variante A als MVP, falls keine komplexe Galerieverwaltung benötigt wird.
|
||||
|
||||
## Technisches Zielkonzept
|
||||
|
||||
### Neue zentrale Services
|
||||
|
||||
Empfohlen:
|
||||
|
||||
- `App\Services\Backoffice\BackofficeDashboardService`
|
||||
- `App\Services\Backoffice\BackofficeDrilldownService`
|
||||
|
||||
Aufgaben `BackofficeDashboardService`:
|
||||
|
||||
- Zeitraum normalisieren
|
||||
- Downline pro Linie aufbauen
|
||||
- Summen pro Linie berechnen
|
||||
- Daten für Stufe 1 und Stufe 2 liefern
|
||||
- Caching-/Snapshot-Strategie kapseln
|
||||
|
||||
Aufgaben `BackofficeDrilldownService`:
|
||||
|
||||
- Kennzahlenfilter aus Request validieren
|
||||
- Personen-/Abo-/Umsatzlisten erzeugen
|
||||
- Berechtigungen gegen Downline prüfen
|
||||
- einheitliche Summary für Listen liefern
|
||||
|
||||
### Controller und Views
|
||||
|
||||
Empfohlen:
|
||||
|
||||
- `App\Http\Controllers\User\BackofficeStatisticsController`
|
||||
- Views unter `resources/views/user/backoffice/statistics/`
|
||||
|
||||
Geplante Actions:
|
||||
|
||||
- `index()` für Stufe 1
|
||||
- `line(int $line)` für Stufe 2
|
||||
- `details()` für Stufe 3
|
||||
- optional `export()` für CSV/Excel später
|
||||
|
||||
Die vorhandenen Team-Views bleiben bestehen. Das neue Dashboard verweist für Detailseiten aber auf eigene, schlankere Statistik-Views.
|
||||
|
||||
### Datenmodell und Definitionen
|
||||
|
||||
Einheitliche Metriken:
|
||||
|
||||
- `consultants`: aktive Berater in Linie
|
||||
- `own_abos`: eigene Beraterabos des eingeloggten Users
|
||||
- `team_partner_abos`: Beraterabos im Team (`is_for = 'me'`)
|
||||
- `direct_customer_abos`: Kundenabos des betrachteten Beraters (`member_id = user_id`, `is_for = 'ot'`)
|
||||
- `team_customer_abos`: Kundenabos der Downline-Berater (`member_id in teamUserIds`, `is_for = 'ot'`)
|
||||
- `new_partners`: neue aktive Partner im Zeitraum
|
||||
- `turnover_points`: Punkte aus `UserSalesVolume`/`UserBusiness`
|
||||
- `turnover_net`: Netto-Umsatz aus `UserSalesVolume`/`UserBusiness`
|
||||
- `shop_1000`: Partner mit Kunden-/Shop-Punkten >= 1000
|
||||
|
||||
### Berechtigungen
|
||||
|
||||
Jede Detailansicht muss sicherstellen:
|
||||
|
||||
- Der eingeloggte User sieht nur eigene Downline-Daten.
|
||||
- Ein direkt angefragter `user_id` muss per Sponsor-Hierarchie im Team liegen.
|
||||
- Kundenabos werden nur in dem Umfang angezeigt, der fachlich für Berater vorgesehen ist.
|
||||
- Datenschutzrelevante Kundendaten sollten auf das notwendige Minimum reduziert werden.
|
||||
|
||||
## Umsetzungsphasen
|
||||
|
||||
### Phase 1: Begriffe, Datenbasis und MVP Dashboard
|
||||
|
||||
- Fachliche Definitionen finalisieren
|
||||
- `BackofficeDashboardService` erstellen
|
||||
- Stufe-1-Linienübersicht mit Linien 1 bis 8 und Summenzeile bauen
|
||||
- bestehende Dashboard-Kachel durch Link auf neue Statistikseite ergänzen oder neue Seite im Menü aufnehmen
|
||||
- Kennzahlen noch ohne vollständigen Deep Dive, aber bereits sauber berechnet
|
||||
|
||||
### Phase 2: Drill-down Stufe 2 und Stufe 3
|
||||
|
||||
- Linien-Detailansicht pro Firstline bauen
|
||||
- Detailansichten je Kennzahl bauen
|
||||
- Abo-Listen mit Name, Punktewert, nächster Ausführung und Anzahl Lieferungen anzeigen
|
||||
- Links aus jeder Kennzahl setzen
|
||||
- leere Zustände und Summenzeilen ergänzen
|
||||
|
||||
### Phase 3: 1000 Punkte Shop
|
||||
|
||||
- fachliche Definition final bestätigen
|
||||
- Query und Summary implementieren
|
||||
- Widget in Übersicht ergänzen
|
||||
- Detailansicht mit Sortierung nach Volumen absteigend bauen
|
||||
|
||||
### Phase 4: Herkunftsabfrage im Checkout
|
||||
|
||||
- Migration und Model-Fillable ergänzen
|
||||
- Checkout-Formular erweitern
|
||||
- Validierung und Speicherung ergänzen
|
||||
- Admin-/Bestelldetail oder Export um Feld erweitern
|
||||
|
||||
### Phase 5: Storno-Qualitätssicherung
|
||||
|
||||
- Tests für vorhandene Storno-Punktepfade ergänzen
|
||||
- Fachentscheidung zur Periodenlogik dokumentieren
|
||||
- Fehlerfall ohne Original-`UserSalesVolume` sichtbar machen
|
||||
- ggf. Businessdaten-Neuberechnung nach Storno anstoßen
|
||||
|
||||
### Phase 6: Incentive-Sichtbarkeit und Event-Archiv
|
||||
|
||||
- rechtliche Entscheidung einarbeiten
|
||||
- separates Ranking-Sichtbarkeits-Opt-in ergänzen
|
||||
- Foto/Land im Ranking anzeigen
|
||||
- Event-Archiv als `DashboardNews`-Typ oder eigenes Modul umsetzen
|
||||
|
||||
## Teststrategie
|
||||
|
||||
Feature-Tests:
|
||||
|
||||
- Dashboard zeigt nur Daten der eigenen Downline.
|
||||
- Linien 1 bis 8 werden korrekt gruppiert.
|
||||
- Summenzeile entspricht Summe der Linien.
|
||||
- Klick auf Teamabos zeigt nur `is_for = 'me'` in der Downline.
|
||||
- Klick auf Kundenabos im Team zeigt nur `is_for = 'ot'` mit `member_id` in der Downline.
|
||||
- 1000-Punkte-Shop listet nur Partner über Schwelle und sortiert absteigend.
|
||||
- Checkout verlangt die Herkunftsabfrage und speichert sie.
|
||||
- Storno erzeugt negativen `UserSalesVolume`-Eintrag und aktualisiert Monatswerte.
|
||||
- Incentive-Ranking zeigt Name/Foto/Land nur nach passender Zustimmung.
|
||||
|
||||
Unit-Tests:
|
||||
|
||||
- Service aggregiert Linien korrekt.
|
||||
- Service verhindert Zugriff auf fremde Team-User.
|
||||
- Metrikdefinitionen liefern stabile Counts bei aktiven, gekündigten und zukünftigen Abos.
|
||||
|
||||
Regressionsprüfung:
|
||||
|
||||
- bestehende Teamseiten `user.team.*`
|
||||
- bestehende Abo-Seiten
|
||||
- bestehendes Incentive-Ranking
|
||||
- Checkout für Webshop, Bestelllink und Salescenter-Flows
|
||||
|
||||
## Offene Fachfragen
|
||||
|
||||
1. Soll die neue Statistik die aktuelle Monatslogik nutzen oder standardmäßig den letzten abgeschlossenen Monat zeigen?
|
||||
2. Sollen Stornos im Stornomonat oder im ursprünglichen Umsatzmonat gegengerechnet werden?
|
||||
3. Wie genau wird "1000 Punkte Shop" definiert: nur Shop-Punkte, alle Kundenpunkte oder Kundenabos plus Einzelbestellungen?
|
||||
4. Welche Kundendaten dürfen Berater in Deep-Dive-Listen sehen?
|
||||
5. Ist die Herkunftsabfrage Freitext, Auswahlfeld oder Kombination?
|
||||
6. Gilt die Herkunftsabfrage für alle Checkout-Flows oder nur für externe Kundenbestellungen?
|
||||
7. Darf eine Incentive-Teilnahme bereits Name/Foto/Land freigeben oder braucht es ein separates Opt-in?
|
||||
8. Soll das Event-Archiv nur Bilder und Texte enthalten oder eine echte Galerie mit Mehrfachuploads?
|
||||
|
||||
## Empfehlung
|
||||
|
||||
Die Backoffice-Statistik sollte als eigenes kleines Modul im User-Bereich umgesetzt werden, nicht als weitere Logik in `dashboard/_statistics.blade.php`. Die vorhandenen Datenquellen sind ausreichend für ein MVP, aber sie müssen zentral aggregiert, fachlich sauber benannt und über berechtigte Drill-down-Routen zugänglich gemacht werden.
|
||||
|
||||
Priorität für die erste Umsetzung:
|
||||
|
||||
1. Daten- und Begriffsdefinitionen finalisieren
|
||||
2. zentrale Services und Stufe-1-Linienübersicht
|
||||
3. Drill-down für Abos und Neupartner
|
||||
4. 1000-Punkte-Shop
|
||||
5. Checkout-Herkunft und Storno-Tests
|
||||
6. Incentive-Sichtbarkeit und Event-Archiv
|
||||
190
dev/2026-05-13-dhl-modul/ENTWICKLUNGSKONZEPT-DHL-MODUL.md
Normal file
190
dev/2026-05-13-dhl-modul/ENTWICKLUNGSKONZEPT-DHL-MODUL.md
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
# Entwicklungskonzept DHL Modul
|
||||
|
||||
Stand: 13.05.2026
|
||||
|
||||
## Ziel
|
||||
|
||||
Diese Datei ist die aktuelle Arbeitsgrundlage fuer die Weiterentwicklung des DHL Moduls. Die bisherigen Markdown-Dateien in diesem Ordner dokumentieren abgeschlossene oder ueberholte Zwischenstaende, insbesondere den frueheren SDK-Ansatz, Paketinstallation, SSL/cURL-Fixes und einzelne abgeschlossene Entwicklungsschritte.
|
||||
|
||||
Aktuelle Anforderungen kommen aus `docs/dhl/Anpassung DHL Modul.md`:
|
||||
|
||||
- Internationaler Versand ausserhalb Deutschlands, insbesondere Oesterreich und Spanien.
|
||||
- Freies Feld fuer Sendungsreferenz oder interne Hinweise wie "Nachlieferung".
|
||||
- Adressvalidierung vor Labelerstellung, damit fehlerhafte Labels und kostenpflichtige Stornos vermieden werden.
|
||||
- Storno im DHL Cockpit pruefen und stabilisieren.
|
||||
- Gewicht von Kompensationsprodukten in das DHL-Paketgewicht einrechnen.
|
||||
- Tracking-Mails auf Rhythmus, Ausloeser und Mehrfachversand pruefen.
|
||||
- Tracking-Codes in Admin, User-Portal und User-N-Portal sichtbar machen.
|
||||
- Tracking-Mail-Versand nur bei Statusaenderung.
|
||||
- DHL-Umstellung von `V62WP` Warenpost auf `V62KP` DHL Kleinpaket bis spaetestens 31.05.2026.
|
||||
|
||||
## Aktueller technischer Stand
|
||||
|
||||
Das produktive Modul basiert auf dem Paket `packages/acme-laravel-dhl` und verwendet die DHL REST API ueber `Acme\Dhl\Support\DhlClient`. Die zentrale Tabelle ist `dhl_package_shipments`.
|
||||
|
||||
Wichtige produktive Einstiegspunkte:
|
||||
|
||||
- `app/Http/Controllers/DhlShipmentController.php`
|
||||
- `app/Services/DhlShipmentService.php`
|
||||
- `app/Services/DhlModalService.php`
|
||||
- `app/Services/DhlDataHelper.php`
|
||||
- `app/Services/DhlTrackingService.php`
|
||||
- `packages/acme-laravel-dhl/src/Services/ShippingService.php`
|
||||
- `packages/acme-laravel-dhl/src/Services/ReturnsService.php`
|
||||
- `packages/acme-laravel-dhl/src/Models/DhlShipment.php`
|
||||
- `config/dhl.php`
|
||||
|
||||
Historische Dokumente erwaehnen teilweise alte Strukturen wie `App\Models\DhlShipment`, `dhl_shipments` oder einen konsolidierten `DhlApiService`. Diese Angaben sind nicht mehr massgeblich, ausser sie werden explizit in aktuellem Code noch referenziert. Aktuell gibt es genau dort noch Altlasten, die bereinigt werden muessen.
|
||||
|
||||
## Offensichtliche Befunde
|
||||
|
||||
### 1. Produktkuerzel `V62WP` ist veraltet
|
||||
|
||||
`V62WP` ist weiterhin in Konfiguration, Admin-Settings, Validierung, Produktauswahl und Sprachdateien vorhanden. DHL verlangt die Umstellung auf `V62KP`.
|
||||
|
||||
Betroffene Stellen:
|
||||
|
||||
- `config/dhl.php`
|
||||
- `app/Http/Controllers/SettingController.php`
|
||||
- `app/Services/DhlModalService.php`
|
||||
- `packages/acme-laravel-dhl/src/Services/ShippingService.php`
|
||||
- `resources/lang/*/dhl.php`
|
||||
|
||||
Risiko: Kleinpaket/Warenpost-Labels koennen nach der DHL-Frist abgelehnt werden.
|
||||
|
||||
### 2. Async Tracking verwendet veraltetes Model
|
||||
|
||||
`app/Jobs/TrackShipmentJob.php` importiert `App\Models\DhlShipment`, dieses Model existiert im aktuellen System nicht mehr. Die produktive DHL-Integration verwendet `Acme\Dhl\Models\DhlShipment`.
|
||||
|
||||
Risiko: Asynchrones Tracking bricht zur Laufzeit, sobald Queue-Tracking genutzt wird.
|
||||
|
||||
### 3. Statuswerte fuer Storno sind inkonsistent
|
||||
|
||||
Im Paket wird bei erfolgreichem Storno `canceled` gesetzt. Andere Stellen, Uebersetzungen und historische Dokumente verwenden `cancelled`.
|
||||
|
||||
Risiko: Filter, Badges, Terminal-Status, Uebersetzungen und Storno-Buttons verhalten sich uneinheitlich.
|
||||
|
||||
### 4. Storno ist technisch vorhanden, aber nicht robust genug
|
||||
|
||||
Storno laeuft ueber `DELETE /parcel/de/shipping/v2/orders/{shipmentNumber}`. Der Code prueft `canCancel()`, speichert aber Fehler nur begrenzt fachlich verwertbar. Produktspezifische Einschraenkungen wie Warenpost/Kleinpaket sind nicht sauber modelliert.
|
||||
|
||||
Risiko: Anwender sehen generische Fehler und koennen nicht erkennen, ob ein Storno produktbedingt, statusbedingt, API-bedingt oder wegen Sandbox/Production-Mismatch scheitert.
|
||||
|
||||
### 5. Internationaler Versand ist nur teilweise vorbereitet
|
||||
|
||||
`V53PAK` ist als internationales Produkt vorhanden, und einige Laender werden in 3-stellige ISO-Codes konvertiert. Dennoch gibt es keinen zentralen Produktentscheid je Zielland, keine harte Validierung nicht unterstuetzter Laender und einen gefaehrlichen Fallback auf `DEU`.
|
||||
|
||||
Risiko: Sendungen nach Oesterreich, Spanien oder weitere Laender koennen falsche Produktcodes, falsche Abrechnungsnummern oder falsche Laendercodes erhalten.
|
||||
|
||||
### 6. Adressvalidierung ist nur formal
|
||||
|
||||
Aktuell prueft das Modul Pflichtfelder, Hausnummern und einfache PLZ-Regeln. Eine echte Pruefung, ob Strasse, PLZ und Ort postalisch existieren, findet nicht statt.
|
||||
|
||||
Empfohlene Loesung: DHL/Post & DHL `DATAFACTORY AUTOCOMPLETE 2.0` fuer DE/AT/CH pruefen und integrieren. Alternativen fuer breiteren Laenderumfang: Loqate, Google Address Validation oder HERE. Wichtig ist eine harte Sperre bei nicht versandfaehigen Adressen vor Labelerstellung.
|
||||
|
||||
### 7. Referenzfeld ist API-seitig vorhanden, aber nicht im Cockpit nutzbar
|
||||
|
||||
`ShippingService` kann `reference` nach `refNo` mappen. `DhlDataHelper` setzt aktuell automatisch `Order-{id}`.
|
||||
|
||||
Risiko: Admins koennen Hinweise wie "Nachlieferung" nicht strukturiert am Label/API-Auftrag hinterlegen.
|
||||
|
||||
### 8. Gewicht von Kompensationsprodukten fehlt
|
||||
|
||||
Kompensationsprodukte werden im Warenkorb mit Gewicht `0` abgelegt, damit die Kompensationslogik nicht beeinflusst wird. Das DHL-Gewicht kommt aus `ShoppingOrder->weight` und enthaelt dieses Produktgewicht dadurch nicht.
|
||||
|
||||
Risiko: DHL-Label wird mit zu geringem Paketgewicht erstellt.
|
||||
|
||||
### 9. Tracking-Mail-Logik ist grundsaetzlich brauchbar, muss aber abgesichert werden
|
||||
|
||||
Der Scheduler ruft stuendlich `dhl:update-tracking --days=30 --send-emails` auf. Statusabhaengige Intervalle verhindern zu viele API-Calls. Automatische Mails werden nur gesendet, wenn eine Sendung neu auf `in_transit` wechselt und noch keine Mail markiert wurde.
|
||||
|
||||
Risiko: Statusspruenge direkt auf `out_for_delivery` oder besondere DHL-Statuscodes koennen ohne Mail bleiben. Mehrere Sendungen einer Bestellung werden teils zusammengefasst, aber die fachliche Regel muss final bestaetigt werden.
|
||||
|
||||
## Entwicklungskonzept
|
||||
|
||||
### Phase 1: Pflichtkorrekturen vor DHL-Frist
|
||||
|
||||
1. `V62WP` vollstaendig auf `V62KP` migrieren.
|
||||
2. Neue Konfigurationskeys fuer `DHL_ACCOUNT_NUMBER_V62KP`, Admin-Setting `dhl_account_v62kp`, Dimensionen und Uebersetzungen einfuehren.
|
||||
3. `ShippingService` Validierung um `V62KP` erweitern und `V62WP` entfernen oder nur noch als Legacy-Mapping fuer Altdaten anzeigen.
|
||||
4. Bestehende Sendungen mit `V62WP` historisch lesbar lassen, aber neue Labelerstellung blockieren.
|
||||
5. Tests fuer Produktcode-Auswahl, Validierung und Payload-Erstellung schreiben.
|
||||
|
||||
### Phase 2: Stabilisierung von Tracking und Storno
|
||||
|
||||
1. `TrackShipmentJob` auf aktuelles Model und aktuellen `DhlTrackingService` umstellen.
|
||||
2. Statuswerte vereinheitlichen. Empfehlung: intern `canceled` verwenden, Uebersetzung auf Deutsch "Storniert".
|
||||
3. `TERMINAL_STATUSES`, Badges, Filter und Sprachdateien entsprechend angleichen.
|
||||
4. Storno-Fehler strukturiert speichern: HTTP-Status, DHL-Fehlercode, DHL-Detailtext, Zeitpunkt.
|
||||
5. Admin-Feedback verbessern: nicht stornierbar wegen Status, Produkt, API-Antwort oder nicht auffindbarer DHL-Sendung.
|
||||
6. Tests fuer erfolgreiche Stornierung, bereits stornierte Sendung, nicht stornierbare Sendung und API-Fehler.
|
||||
|
||||
### Phase 3: Internationalisierung Versand
|
||||
|
||||
1. Zentralen Service fuer Produkt-/Billing-Entscheidung einfuehren, z. B. `DhlProductResolver`.
|
||||
2. Zielland, Produktcode, Abrechnungsnummer und erlaubte Services dort validieren.
|
||||
3. Regeln initial:
|
||||
- `DE`: `V01PAK` oder `V62KP`
|
||||
- `AT`, `ES` und weitere aktivierte Laender: `V53PAK`
|
||||
4. Fallback auf `DEU` entfernen. Unbekannte Laender muessen mit klarer Fehlermeldung abbrechen.
|
||||
5. Cockpit-Formular: Produkt anhand Zielland vorschlagen, aber Admin-Korrektur erlauben.
|
||||
|
||||
### Phase 4: Adressvalidierung vor Labelerstellung
|
||||
|
||||
1. Neuen serverseitigen Validierungsendpunkt fuer DHL-Adressen schaffen.
|
||||
2. Basisvalidierung behalten: Pflichtfelder, Land, PLZ-Format, Hausnummer, Packstation/Postnummer.
|
||||
3. DHL DATAFACTORY AUTOCOMPLETE 2.0 fuer DE/AT/CH evaluieren.
|
||||
4. Falls DHL fuer alle benoetigten Laender nicht ausreicht, externen Provider evaluieren.
|
||||
5. UI-Status einfuehren:
|
||||
- gueltig: Labelerstellung erlaubt
|
||||
- Warnung: Admin kann bewusst fortfahren
|
||||
- Fehler: Labelerstellung gesperrt
|
||||
6. Validierungsergebnis optional am Shipment/Order protokollieren.
|
||||
|
||||
### Phase 5: Referenzfeld und Admin-UX
|
||||
|
||||
1. Neues Formularfeld `reference` oder `shipment_reference` im DHL Cockpit.
|
||||
2. Wert an `DhlDataHelper::prepareOrderData()` uebergeben.
|
||||
3. `ShippingService` nutzt vorhandenes Mapping nach `refNo`.
|
||||
4. Referenz im Shipment speichern, damit spaeter nachvollziehbar ist, warum eine Sendung erstellt wurde.
|
||||
5. Laengenlimit der DHL API beachten, aktuell maximal 35 Zeichen.
|
||||
|
||||
### Phase 6: DHL-Gewicht korrekt berechnen
|
||||
|
||||
1. Separaten Gewichtsdienst fuer DHL einfuehren, z. B. `DhlShipmentWeightCalculator`.
|
||||
2. Basis: `ShoppingOrder->weight`.
|
||||
3. Fuer `shopping_order_items` mit `comp > 0` das Produktgewicht aus `Product->weight` nachladen und addieren.
|
||||
4. Nur DHL-Gewicht anpassen, nicht die bestehende Warenkorb-/Versandkostenlogik.
|
||||
5. Rundung und DHL-Grenzwerte je Produkt testen.
|
||||
|
||||
### Phase 7: Tracking-Codes und Mails fachlich finalisieren
|
||||
|
||||
1. Bestehende Admin-Anzeige pruefen und bei Bedarf vereinheitlichen.
|
||||
2. Tracking-Code-Anzeige in User-Portal und User-N-Portal ergaenzen.
|
||||
3. Mail-Regel final definieren:
|
||||
- automatisch nur einmal pro Sendung
|
||||
- nur bei relevanter Statusaenderung
|
||||
- mehrere Sendungen einer Bestellung sinnvoll zusammenfassen
|
||||
4. Statusspruenge wie `created` direkt nach `out_for_delivery` abdecken.
|
||||
5. Command `dhl:update-tracking` Tests fuer Mailausloeser und Nicht-Ausloeser ergaenzen.
|
||||
|
||||
## Empfohlene Reihenfolge
|
||||
|
||||
1. `V62WP` -> `V62KP`, Statuswerte und `TrackShipmentJob` korrigieren.
|
||||
2. Storno stabilisieren und bessere Fehlermeldungen im Cockpit anzeigen.
|
||||
3. Internationalen Produktresolver einbauen.
|
||||
4. Referenzfeld und Gewichtskorrektur umsetzen.
|
||||
5. Adressvalidierung integrieren.
|
||||
6. Tracking-Anzeigen und Mailregeln final testen.
|
||||
|
||||
## Teststrategie
|
||||
|
||||
- Feature-Tests fuer Controller-Endpunkte: Label erstellen, Storno, Tracking-Mail, Tracking-Update.
|
||||
- Unit-Tests fuer Produktresolver, Gewichtskalkulation und Adressvalidierung.
|
||||
- HTTP-Fakes fuer DHL API Responses inklusive Fehlerfaelle.
|
||||
- Regression-Test fuer `V62KP` Payload.
|
||||
- Command-Test fuer `dhl:update-tracking --send-emails`.
|
||||
|
||||
## Legacy-Dokumentation
|
||||
|
||||
Die bisherigen Markdown-Dateien wurden nach `dev/dhl-modul/legacy` verschoben. Sie bleiben als Historie erhalten, sind aber nicht mehr die aktuelle Arbeitsgrundlage.
|
||||
86
dev/BusinessUpdateCalculatedFields-Examples.sh
Normal file
86
dev/BusinessUpdateCalculatedFields-Examples.sh
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#!/bin/bash
|
||||
|
||||
# ================================================================================
|
||||
# Business Update Calculated Fields - Verwendungsbeispiele
|
||||
# ================================================================================
|
||||
|
||||
echo "========================================="
|
||||
echo "Business Update Calculated Fields"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# ================================================================================
|
||||
# 1. TESTLAUF - Empfohlen vor der ersten Produktivnutzung
|
||||
# ================================================================================
|
||||
|
||||
echo "1. TESTLAUF - Einzelner Monat (November 2025)"
|
||||
echo " php artisan business:update-calculated-fields 2025 11 --dry-run"
|
||||
echo ""
|
||||
|
||||
echo "2. TESTLAUF - Ganzes Jahr (2025)"
|
||||
echo " php artisan business:update-calculated-fields 2025 --dry-run"
|
||||
echo ""
|
||||
|
||||
# ================================================================================
|
||||
# 2. PRODUKTIV - Einzelne Monate
|
||||
# ================================================================================
|
||||
|
||||
echo "3. PRODUKTIV - Einzelner Monat (November 2025)"
|
||||
echo " php artisan business:update-calculated-fields 2025 11"
|
||||
echo ""
|
||||
|
||||
echo "4. PRODUKTIV - Mehrere Monate nacheinander"
|
||||
echo " php artisan business:update-calculated-fields 2025 10"
|
||||
echo " php artisan business:update-calculated-fields 2025 11"
|
||||
echo ""
|
||||
|
||||
# ================================================================================
|
||||
# 3. PRODUKTIV - Ganzes Jahr
|
||||
# ================================================================================
|
||||
|
||||
echo "5. PRODUKTIV - Ganzes Jahr (alle 12 Monate)"
|
||||
echo " php artisan business:update-calculated-fields 2025"
|
||||
echo ""
|
||||
|
||||
# ================================================================================
|
||||
# 4. MIGRATION
|
||||
# ================================================================================
|
||||
|
||||
echo "6. VOR DER ERSTEN AUSFÜHRUNG - Migration"
|
||||
echo " php artisan migrate"
|
||||
echo ""
|
||||
|
||||
# ================================================================================
|
||||
# Beispiel-Workflow für komplette Aktualisierung
|
||||
# ================================================================================
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "Beispiel: Kompletter Workflow"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
echo "# 1. Migration ausführen (nur einmal nötig)"
|
||||
echo "php artisan migrate"
|
||||
echo ""
|
||||
echo "# 2. Testlauf für das Jahr 2025"
|
||||
echo "php artisan business:update-calculated-fields 2025 --dry-run"
|
||||
echo ""
|
||||
echo "# 3. Produktiv für das Jahr 2025 ausführen"
|
||||
echo "php artisan business:update-calculated-fields 2025"
|
||||
echo ""
|
||||
echo "========================================="
|
||||
|
||||
# ================================================================================
|
||||
# Hinweise
|
||||
# ================================================================================
|
||||
|
||||
echo ""
|
||||
echo "HINWEISE:"
|
||||
echo "---------"
|
||||
echo "• Der Command ist idempotent (kann mehrfach ausgeführt werden)"
|
||||
echo "• Bereits aktualisierte Einträge werden übersprungen"
|
||||
echo "• Bei ganzen Jahren: Monate ohne Daten werden übersprungen"
|
||||
echo "• Fehler bei einzelnen Einträgen brechen den Prozess nicht ab"
|
||||
echo "• Memory-Nutzung wird überwacht"
|
||||
echo ""
|
||||
|
||||
231
dev/BusinessUpdateCalculatedFields.md
Normal file
231
dev/BusinessUpdateCalculatedFields.md
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
# Business Update Calculated Fields Command
|
||||
|
||||
## Übersicht
|
||||
|
||||
Der Command `business:update-calculated-fields` aktualisiert bereits gespeicherte UserBusiness-Einträge mit den neuen berechneten Feldern für Level-Qualifikationen.
|
||||
|
||||
## Zweck
|
||||
|
||||
Nach der Korrektur der Karriere-Level-Berechnung müssen bereits in der Datenbank gespeicherte UserBusiness-Einträge aktualisiert werden, um die neuen berechneten Felder zu erhalten:
|
||||
|
||||
### Neue Felder:
|
||||
|
||||
1. **`calc_qual_kp`** (in UserBusiness)
|
||||
|
||||
- Die berechnete KP-Qualifikation für den erreichten Level
|
||||
- Zeigt an, wie viele KP-Punkte tatsächlich für die Qualifikation verwendet wurden
|
||||
|
||||
2. **`_calculated_qual_kp`** (in Level-Arrays)
|
||||
|
||||
- Für `qual_user_level_next`, `next_qual_user_level`, `next_can_user_level`
|
||||
- Die berechnete KP für jeden spezifischen Level
|
||||
|
||||
3. **`_calculated_payline_points`** (in Level-Arrays)
|
||||
|
||||
- Die Payline-Punkte basierend auf den spezifischen Paylines des Levels
|
||||
|
||||
4. **`_calculated_payline_points_qual_kp`** (in Level-Arrays)
|
||||
- Die Gesamtpunkte (Payline + Rest-KP) für den Level
|
||||
|
||||
## Verwendung
|
||||
|
||||
### Grundlegende Syntax
|
||||
|
||||
```bash
|
||||
# Einzelner Monat
|
||||
php artisan business:update-calculated-fields {year} {month}
|
||||
|
||||
# Ganzes Jahr (alle 12 Monate)
|
||||
php artisan business:update-calculated-fields {year}
|
||||
```
|
||||
|
||||
### Mit Dry-Run (Testlauf)
|
||||
|
||||
```bash
|
||||
# Einzelner Monat
|
||||
php artisan business:update-calculated-fields {year} {month} --dry-run
|
||||
|
||||
# Ganzes Jahr
|
||||
php artisan business:update-calculated-fields {year} --dry-run
|
||||
```
|
||||
|
||||
Im Dry-Run Modus werden keine Änderungen in der Datenbank gespeichert. Der Command zeigt nur an, welche Einträge aktualisiert werden würden.
|
||||
|
||||
## Beispiele
|
||||
|
||||
### Aktualisiere November 2025
|
||||
|
||||
```bash
|
||||
php artisan business:update-calculated-fields 2025 11
|
||||
```
|
||||
|
||||
### Aktualisiere das ganze Jahr 2025
|
||||
|
||||
```bash
|
||||
php artisan business:update-calculated-fields 2025
|
||||
```
|
||||
|
||||
Das wird alle 12 Monate von Januar bis Dezember 2025 aktualisieren.
|
||||
|
||||
### Testlauf für Oktober 2025
|
||||
|
||||
```bash
|
||||
php artisan business:update-calculated-fields 2025 10 --dry-run
|
||||
```
|
||||
|
||||
### Testlauf für das ganze Jahr 2025
|
||||
|
||||
```bash
|
||||
php artisan business:update-calculated-fields 2025 --dry-run
|
||||
```
|
||||
|
||||
## Ablauf
|
||||
|
||||
### Einzelner Monat
|
||||
|
||||
1. **Lade UserBusiness-Einträge**: Alle Einträge für den angegebenen Monat/Jahr
|
||||
2. **Berechne neue Felder**: Für jeden Eintrag werden die berechneten Felder hinzugefügt
|
||||
3. **Speichere Änderungen**: Nur wenn Änderungen vorhanden sind (und nicht im Dry-Run)
|
||||
4. **Zeige Statistik**: Anzahl aktualisierter, übersprungener und fehlerhafter Einträge
|
||||
|
||||
### Ganzes Jahr
|
||||
|
||||
1. **Durchlaufe alle 12 Monate**: Januar (1) bis Dezember (12)
|
||||
2. **Für jeden Monat**:
|
||||
- Lade UserBusiness-Einträge
|
||||
- Berechne neue Felder
|
||||
- Speichere Änderungen
|
||||
- Zeige Monats-Statistik
|
||||
3. **Zeige Jahres-Zusammenfassung**: Gesamtstatistik über alle Monate
|
||||
|
||||
## Was wird berechnet?
|
||||
|
||||
### calc_qual_kp (für aktuellen Level)
|
||||
|
||||
```php
|
||||
$rest_kp = max(0, $sales_volume_points_KP_sum - $qual_kp);
|
||||
$calc_qual_kp = $rest_kp > 0 ? $qual_kp : $sales_volume_points_KP_sum;
|
||||
```
|
||||
|
||||
- Wenn Rest-KP > 0: Nutze die volle qual_kp des Levels
|
||||
- Sonst: Nutze alle verfügbaren KP-Punkte
|
||||
|
||||
### Für Level-Arrays (next_qual_user_level, etc.)
|
||||
|
||||
```php
|
||||
$payline_points = sum($business_lines[1..paylines]['points']);
|
||||
$rest_kp = max(0, $sales_volume_points_KP_sum - $level['qual_kp']);
|
||||
$payline_points_qual_kp = $payline_points + $rest_kp;
|
||||
$calculated_qual_kp = $rest_kp > 0 ? $level['qual_kp'] : $sales_volume_points_KP_sum;
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
### Einzelner Monat
|
||||
|
||||
Der Command zeigt:
|
||||
|
||||
- Progress Bar während der Verarbeitung
|
||||
- Memory-Nutzung alle 100 Einträge
|
||||
- Abschließende Statistik:
|
||||
- Anzahl aktualisierter Einträge
|
||||
- Anzahl übersprungener Einträge (bereits aktualisiert)
|
||||
- Anzahl Fehler
|
||||
- Ausführungszeit
|
||||
|
||||
**Beispiel Output:**
|
||||
|
||||
```
|
||||
Starte Update für Monat: 11 | Jahr: 2025
|
||||
[Command Start] Memory: 12.5 MB / 512 MB (2.44%) | Peak: 12.5 MB
|
||||
Gefunden: 1547 UserBusiness-Einträge
|
||||
1547/1547 [============================] 100%
|
||||
[Nach 100 Einträgen] Memory: 45.3 MB / 512 MB (8.85%) | Peak: 48.2 MB
|
||||
...
|
||||
|
||||
Update abgeschlossen:
|
||||
- Aktualisiert: 1547
|
||||
- Übersprungen: 0
|
||||
- Fehler: 0
|
||||
UPDATE COMPLETED SUCCESSFULLY | Zeit: 12sec :345.6789 ms
|
||||
```
|
||||
|
||||
### Ganzes Jahr
|
||||
|
||||
Der Command zeigt:
|
||||
|
||||
- Für jeden Monat:
|
||||
- Progress Bar
|
||||
- Monats-Statistik
|
||||
- Memory-Nutzung nach dem Monat
|
||||
- Abschließende Jahres-Zusammenfassung
|
||||
|
||||
**Beispiel Output:**
|
||||
|
||||
```
|
||||
Starte Update für ALLE MONATE des Jahres: 2025
|
||||
======================================================================
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Verarbeite Monat: 01/2025 │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
Gefunden: 1245 UserBusiness-Einträge
|
||||
1245/1245 [============================] 100%
|
||||
✓ Monat 1 abgeschlossen: 1245 aktualisiert, 0 übersprungen, 0 Fehler
|
||||
[Nach Monat 1] Memory: 48.2 MB / 512 MB (9.41%) | Peak: 52.1 MB
|
||||
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Verarbeite Monat: 02/2025 │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
Gefunden: 1367 UserBusiness-Einträge
|
||||
1367/1367 [============================] 100%
|
||||
✓ Monat 2 abgeschlossen: 1367 aktualisiert, 0 übersprungen, 0 Fehler
|
||||
[Nach Monat 2] Memory: 51.3 MB / 512 MB (10.02%) | Peak: 55.4 MB
|
||||
|
||||
[... weitere Monate ...]
|
||||
|
||||
======================================================================
|
||||
ZUSAMMENFASSUNG FÜR DAS JAHR 2025:
|
||||
======================================================================
|
||||
Verarbeitete Monate: 12/12
|
||||
Fehlgeschlagene Monate: 0
|
||||
Gesamt aktualisiert: 15432
|
||||
Gesamt übersprungen: 0
|
||||
Gesamt Fehler: 0
|
||||
======================================================================
|
||||
JAHRES-UPDATE ABGESCHLOSSEN | Zeit: 145sec :678.9012 ms
|
||||
[Command End] Memory: 62.8 MB / 512 MB (12.27%) | Peak: 68.2 MB
|
||||
```
|
||||
|
||||
## Migration
|
||||
|
||||
Vor dem ersten Ausführen des Commands muss die Migration ausgeführt werden:
|
||||
|
||||
```bash
|
||||
php artisan migrate
|
||||
```
|
||||
|
||||
Die Migration fügt das neue Feld `calc_qual_kp` zur `user_businesses` Tabelle hinzu.
|
||||
|
||||
## Integration mit BusinessStoreOptimized
|
||||
|
||||
Nach Ausführung von `business:store-optimized` können die berechneten Felder automatisch befüllt werden. Die neue Logik in `BusinessUserItemOptimized.php` sorgt dafür, dass bei neuen Berechnungen die Felder korrekt gesetzt werden.
|
||||
|
||||
## Fehlerbehandlung
|
||||
|
||||
- Fehler bei einzelnen Einträgen führen nicht zum Abbruch
|
||||
- Fehler werden geloggt und in der Statistik angezeigt
|
||||
- Memory-Nutzung wird überwacht (Warnung bei >80%)
|
||||
|
||||
## Performance
|
||||
|
||||
- Verarbeitet ca. 100-150 Einträge pro Sekunde
|
||||
- Memory-Nutzung: ca. 30-50 MB für 1000 Einträge
|
||||
- Kann für mehrere Monate/Jahre nacheinander ausgeführt werden
|
||||
|
||||
## Hinweise
|
||||
|
||||
- Der Command ist idempotent (kann mehrfach ausgeführt werden)
|
||||
- Bereits vorhandene Felder werden nicht überschrieben
|
||||
- Nutze `--dry-run` für Tests vor der Produktionsausführung
|
||||
- Empfohlen: Backup vor der ersten Ausführung
|
||||
Loading…
Add table
Add a link
Reference in a new issue