commit 08-2025
This commit is contained in:
parent
9ae662f63e
commit
480fdc65ed
404 changed files with 65310 additions and 2600431 deletions
357
dev/code/TreeCalcBot_Berechnungslogik.md
Normal file
357
dev/code/TreeCalcBot_Berechnungslogik.md
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
# 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
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
// 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
|
||||
|
||||
```php
|
||||
// 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
|
||||
```php
|
||||
// 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
|
||||
```php
|
||||
'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
|
||||
```php
|
||||
// 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
|
||||
```php
|
||||
// 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
|
||||
```php
|
||||
// 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
|
||||
```php
|
||||
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
|
||||
```php
|
||||
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
|
||||
```php
|
||||
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
|
||||
```php
|
||||
// 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
|
||||
```php
|
||||
class CalculationPipeline {
|
||||
public function calculate($user) {
|
||||
$this->validateInput($user);
|
||||
$this->calculateHierarchyPoints($user);
|
||||
$this->calculateQualifications($user);
|
||||
$this->calculateCommissions($user);
|
||||
$this->validateOutput($user);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Audit-Trail
|
||||
```php
|
||||
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.
|
||||
Loading…
Add table
Add a link
Reference in a new issue