mivita/dev/code/TreeCalcBot_Berechnungslogik.md
2025-08-12 18:01:59 +02:00

12 KiB
Raw Blame History

TreeCalcBot - Berechnungslogik Dokumentation

Überblick des MLM-Berechnungssystems

Das Mivita MLM-System implementiert ein mehrstufiges Provisionsberechnungssystem basierend auf:

  • KP (Kundenpoints) - Direkte Verkaufspunkte
  • TP (Teampoints) - Punkte aus der Downline-Hierarchie
  • Shop Points - E-Commerce-Verkäufe
  • Payline-System - Ebenen-basierte Provisionsberechnung
  • Growth Bonus - Zusätzliche Provisionen ab bestimmten Ebenen

1. PUNKTE-SAMMLUNG UND -AGGREGATION

1.1 Grundlegende Punktetypen

// In BusinessUserItem->makeUser()
'sales_volume_KP_points' => $user->getUserSalesVolumeBy($month, $year, 'sales_volume_KP_points'),     // Direkte Kundenpunkte
'sales_volume_TP_points' => $user->getUserSalesVolumeBy($month, $year, 'sales_volume_TP_points'),     // Teampunkte  
'sales_volume_points_shop' => $user->getUserSalesVolumeBy($month, $year, 'sales_volume_points_shop'), // Shop-Punkte

// Berechnete Summen
'sales_volume_points_KP_sum' => KP_points + points_shop,  // KP + Shop kombiniert
'sales_volume_points_TP_sum' => TP_points + points_shop,  // TP + Shop kombiniert

🔍 POTENZIELLE BERECHNUNGSFEHLER:

  • Doppelzählung von points_shop in beiden Summen-Feldern
  • Fehlende Validierung ob Shop-Punkte bereits in KP/TP enthalten sind

1.2 Hierarchische Punkteaggregation

// TreeCalcBot->calcUserPoints() - Zeile 104-119
private function calcUserPoints($businessUserItems, $line) {
    // Für jede Hierarchie-Ebene
    foreach($businessUserItems as $business_user_item) {
        
        // 1. REKURSION: Tiefere Ebenen erst berechnen
        if(count($business_user_item->businessUserItems) > 0) {
            $this->calcUserPoints($business_user_item->businessUserItems, $line+1);
        }
        
        // 2. PUNKTE ADDIEREN: TP_sum (TP + Shop) wird verwendet
        $this->business_user->addBusinessLinePoints($line, $business_user_item->sales_volume_points_TP_sum);
        $this->business_user->addTotal TP($business_user_item->sales_volume_points_TP_sum);
    }
}

📊 BERECHNUNGSABLAUF:

Ebene 1: User A (100 TP) + User B (200 TP) = 300 Punkte
Ebene 2: User C (50 TP) + User D (75 TP)   = 125 Punkte  
Ebene 3: User E (25 TP)                    = 25 Punkte

Total Points: 300 + 125 + 25 = 450 Punkte

🚨 KRITISCHE BERECHNUNGSFEHLER:

  1. Inkonsistente Punktetypen: Es wird sales_volume_points_TP_sum verwendet, aber eigentlich sollten nur Team-Punkte ohne eigene Verkäufe aggregiert werden
  2. Doppelzählung Risk: Eigene Punkte des Users werden möglicherweise sowohl in KP als auch in der Hierarchie gezählt

2. QUALIFIKATIONS-BERECHNUNGSSYSTEM

2.1 Qualifikations-Voraussetzungen

// BusinessUserItem->calcuQualLevel() - Zeile 215-231
public function calcuQualLevel() {
    // 1. FILTER: Alle Level wo KP-Mindestanforderung erfüllt ist
    $qualUserLevels = UserLevel::where('qual_kp', '<=', $this->sales_volume_points_KP_sum)
                               ->where('pos', '<=', $this->user_level_active_pos)  
                               ->orderBy('qual_pp', 'desc')
                               ->get();
    
    // 2. PRÜFUNG: Für jeden möglichen Level
    foreach($qualUserLevels as $qualUserLevel) {
        $payline_points = $this->getPointsforPayline($qualUserLevel->paylines);
        $payline_points_qual_kp = $payline_points + $this->getRestQualKP();
        
        // 3. QUALIFIKATION: Wenn PP-Anforderung erfüllt
        if($payline_points_qual_kp >= $qualUserLevel->qual_pp) {
            return $qualUserLevel; // Höchster erreichter Level
        }
    }
    return NULL; // Keine Qualifikation erreicht
}

2.2 Payline-Punkte Berechnung

// BusinessUserItem->getPointsforPayline() - Zeile 235-243
private function getPointsforPayline($paylines) {
    $payline_points = 0;
    for ($i=1; $i <= $paylines; $i++) { 
        if(isset($this->business_lines[$i])) {
            $payline_points += $this->business_lines[$i]->points;
        }
    }
    return $payline_points;
}

2.3 Rest-KP Berechnung

// BusinessUserItem->getRestQualKP() - Zeile 149-152
public function getRestQualKP() {
    $ret = $this->sales_volume_points_KP_sum - $this->qual_kp;
    return $ret > 0 ? $ret : 0;
}

🔍 QUALIFIKATIONSLOGIK:

Beispiel User Level "Gold":
- qual_kp = 500   (Mindest-Kundenpunkte)
- qual_pp = 1000  (Mindest-Payline-Punkte)  
- paylines = 3    (Berücksichtigte Ebenen)

User hat:
- sales_volume_points_KP_sum = 600 KP  ✅ (600 >= 500)
- Ebene 1: 300 Punkte
- Ebene 2: 400 Punkte  
- Ebene 3: 200 Punkte
- payline_points = 300 + 400 + 200 = 900
- rest_kp = 600 - 500 = 100
- payline_points_qual_kp = 900 + 100 = 1000  ✅ (1000 >= 1000)

RESULTAT: User qualifiziert sich für "Gold" Level

🚨 POTENZIELLE BERECHNUNGSFEHLER:

  1. Doppelte KP-Nutzung: Rest-KP werden sowohl für Qualifikation als auch für Payline-Berechnung verwendet
  2. Ebenen-Logik: Die Sortierung orderBy('qual_pp', 'desc') könnte niedrigere Level überspringen

3. PROVISIONS-BERECHNUNGSSYSTEM

3.1 Payline-Provisionen

// BusinessUserItem->calcQualPP() - Zeile 171-180
for ($i=1; $i <= $qualUserLevel->paylines; $i++) { 
    if(isset($this->business_lines[$i])) {
        $object = $this->business_lines[$i];
        $object->margin = $this->qual_user_level['pr_line_'.$i]; // Provision in %
        $object->commission = round($object->points / 100 * $object->margin, 2);
        $commission_pp_total += $object->commission;
        $this->b_user->business_lines[$i] = $object;         
    }
}

3.2 Growth Bonus Berechnung

// BusinessUserItem->calcQualPP() - Zeile 182-198
if($qualUserLevel->growth_bonus) {
    $payline = (int) $this->qual_user_level['paylines'] + 1;  // Ab Ebene nach Paylines
    $maxlines = count($this->business_lines) + 1;
    $growth_bonus = (float) $this->qual_user_level['growth_bonus'];

    for ($i=$payline; $i <= $maxlines; $i++) { 
        if(isset($this->business_lines[$i])) {
            $object = $this->business_lines[$i];
            $object->margin = $growth_bonus; // Einheitlicher % für alle Ebenen
            $object->commission = round($object->points / 100 * $object->margin, 2);
            $commission_growth_total += $object->commission;
        }
    }
}

3.3 Shop-Provisionen

// BusinessUserItem->makeUser() - Zeile 85
$this->b_user->commission_shop_sales = round(
    $this->b_user->sales_volume_total_shop / 100 * $this->b_user->margin_shop, 
    2
);

3.4 Gesamt-Provisionen

// BusinessUserItem->getCommissionTotal() - Zeile 154-156
public function getCommissionTotal() {
    return round(
        $this->commission_shop_sales +      // Shop-Verkäufe
        $this->commission_pp_total +        // Payline-Provisionen  
        $this->commission_growth_total,     // Growth Bonus
        2
    );
}

📊 PROVISIONS-BEISPIEL:

User "Gold" Level (3 Paylines, 2% Growth Bonus):
- pr_line_1 = 5%    - Ebene 1: 300 Punkte → 15€ Provision
- pr_line_2 = 3%    - Ebene 2: 400 Punkte → 12€ Provision  
- pr_line_3 = 2%    - Ebene 3: 200 Punkte → 4€ Provision
- Growth Bonus 2%   - Ebene 4: 100 Punkte → 2€ Provision
                    - Ebene 5: 50 Punkte  → 1€ Provision

Shop-Provision: 1000€ Umsatz × 10% = 100€

GESAMT: 15 + 12 + 4 + 2 + 1 + 100 = 134€

4. KRITISCHE BERECHNUNGSFEHLER-ANALYSE

🔴 FEHLER 1: Inkonsistente Punktetypen

Problem: Verschiedene Punktetypen werden vermischt ohne klare Trennung

// Zeile 115: TP_sum wird für Payline-Berechnung verwendet
addBusinessLinePoints($line, $business_user_item->sales_volume_points_TP_sum);

// Aber Zeile 217: KP_sum wird für Qualifikation verwendet  
where('qual_kp', '<=', $this->sales_volume_points_KP_sum)

Fix: Klare Definition welche Punkte für welche Berechnung verwendet werden

🔴 FEHLER 2: Doppelzählung Shop-Punkte

Problem: Shop-Punkte werden sowohl in KP_sum als auch TP_sum eingerechnet

'sales_volume_points_KP_sum' => KP_points + points_shop,  
'sales_volume_points_TP_sum' => TP_points + points_shop,  

Fix: Shop-Punkte nur einmal berücksichtigen oder klar dokumentieren

🔴 FEHLER 3: Rest-KP Doppelnutzung

Problem: Rest-KP werden für Payline-Berechnung addiert, obwohl sie bereits in der Qualifikation verwendet wurden

// Zeile 221: Rest-KP zu Payline-Punkten addiert
$payline_points_qual_kp = $payline_points + $this->getRestQualKP();

Fix: Klären ob Rest-KP zusätzliche "Bonus-Punkte" sind oder Doppelzählung

🟡 FEHLER 4: Fehlende Boundary-Checks

Problem: Keine Validierung für negative Werte oder Overflow

// Zeile 108: Keine Überprüfung ob points negativ sein könnten
$obj->points += $points;

Fix: Input-Validierung und Boundary-Checks implementieren

🟡 FEHLER 5: Rundungsfehler-Akkumulation

Problem: Rundung nach jeder Berechnung kann zu Abweichungen führen

// Zeile 175: Rundung pro Ebene
$object->commission = round($object->points / 100 * $object->margin, 2);

Fix: Erst am Ende der Gesamtberechnung runden


5. VALIDIERUNGSSCHRITTE FÜR BERECHNUNGEN

Validierung 1: Punktesummen prüfen

function validatePointSums($user) {
    $kp_calculated = $user->sales_volume_KP_points + $user->sales_volume_points_shop;
    $tp_calculated = $user->sales_volume_TP_points + $user->sales_volume_points_shop;
    
    assert($kp_calculated == $user->sales_volume_points_KP_sum, "KP sum mismatch");
    assert($tp_calculated == $user->sales_volume_points_TP_sum, "TP sum mismatch");
}

Validierung 2: Hierarchie-Konsistenz

function validateHierarchyPoints($businessUser) {
    $calculated_total = 0;
    foreach($businessUser->business_lines as $line => $data) {
        $calculated_total += $data->points;
    }
    
    assert($calculated_total == $businessUser->total_pp, "Hierarchy total mismatch");
}

Validierung 3: Provisions-Konsistenz

function validateCommissions($businessUser) {
    $calculated_pp = 0;
    $calculated_growth = 0;
    
    foreach($businessUser->business_lines as $line => $data) {
        if(isset($data->payline) && $data->payline) {
            $calculated_pp += $data->commission;
        }
        if(isset($data->growth_bonus) && $data->growth_bonus) {
            $calculated_growth += $data->commission;  
        }
    }
    
    assert($calculated_pp == $businessUser->commission_pp_total, "PP commission mismatch");
    assert($calculated_growth == $businessUser->commission_growth_total, "Growth commission mismatch");
}

6. EMPFOHLENE FIXES UND VERBESSERUNGEN

1. Punkt-Typ Standardisierung

// Klare Trennung der Punktetypen
class PointTypes {
    const CUSTOMER_POINTS = 'KP';    // Nur direkte Verkäufe
    const TEAM_POINTS = 'TP';        // Nur Team-Hierarchie  
    const SHOP_POINTS = 'SP';        // Nur E-Commerce
    const COMBINED_POINTS = 'CP';    // Für Berechnungen
}

2. Berechnungs-Pipeline

class CalculationPipeline {
    public function calculate($user) {
        $this->validateInput($user);
        $this->calculateHierarchyPoints($user);
        $this->calculateQualifications($user);
        $this->calculateCommissions($user);
        $this->validateOutput($user);
    }
}

3. Audit-Trail

class CalculationAudit {
    public function logCalculation($user, $step, $before, $after) {
        Log::info("Calculation Step", [
            'user_id' => $user->id,
            'step' => $step,
            'before' => $before,
            'after' => $after,
            'diff' => $after - $before
        ]);
    }
}

Diese Dokumentation deckt alle kritischen Berechnungsaspekte ab und zeigt konkrete Stellen auf, wo Berechnungsfehler auftreten könnten.