Recruiting Challenge: Storno nimmt Neupartner raus, Rang und Auszahlung nur mit Bestaetigung
Kundenentscheid 25.09.2026: - Storno: Ist jede bezahlte Starterpaket-Bestellung eines Neupartners storniert (txaction = cancelled), bekommt das Tracking cancelled_at, eine Storno-Logzeile nimmt die Einmalpunkte zurueck. Nachtlauf und Neuaufbau markieren; "Meine Berechnung" zeigt den Partner durchgestrichen mit "Storniert am ..., zaehlt nicht". - Gezaehlt wird fuer alle, einen Rang bekommen nur bestaetigte Teilnehmer; Export und Summen nur fuer sie. Unbestaetigte sehen "Deine Praemie nach Bestaetigung", im Admin "Teilnahme nicht bestaetigt, keine Auszahlung". - Datenschutz: andere Berater sehen Unbestaetigte in der Rangliste nicht mehr (auch nicht anonym), VIP-Konten schon, der eigene Eintrag bleibt. - Teilnahmebedingungen Punkt 2 und 7 und Hinweistexte in de/en/es/fr. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
42d2a9c0ab
commit
c4edbf97e4
23 changed files with 318 additions and 45 deletions
|
|
@ -4,6 +4,8 @@ namespace App\Models;
|
|||
|
||||
use App\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
|
|
@ -14,11 +16,12 @@ use Illuminate\Database\Eloquent\Model;
|
|||
* @property int $participant_id
|
||||
* @property int $user_id
|
||||
* @property Carbon $registered_at
|
||||
* @property Carbon|null $cancelled_at
|
||||
* @property Carbon|null $created_at
|
||||
* @property Carbon|null $updated_at
|
||||
* @property-read IncentiveParticipant $participant
|
||||
* @property-read User $user
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, IncentivePointsLog> $pointsLogs
|
||||
* @property-read Collection<int, IncentivePointsLog> $pointsLogs
|
||||
*
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
|
|
@ -32,14 +35,29 @@ class IncentiveNewPartner extends Model
|
|||
'participant_id' => 'int',
|
||||
'user_id' => 'int',
|
||||
'registered_at' => 'datetime',
|
||||
'cancelled_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'participant_id',
|
||||
'user_id',
|
||||
'registered_at',
|
||||
'cancelled_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* Nur Neupartner, die zaehlen (Starterpaket-Bestellung nicht storniert).
|
||||
*/
|
||||
public function scopeCounting(Builder $query): Builder
|
||||
{
|
||||
return $query->whereNull($query->getModel()->qualifyColumn('cancelled_at'));
|
||||
}
|
||||
|
||||
public function isCancelled(): bool
|
||||
{
|
||||
return $this->cancelled_at !== null;
|
||||
}
|
||||
|
||||
public function participant()
|
||||
{
|
||||
return $this->belongsTo(IncentiveParticipant::class, 'participant_id');
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Services\Incentive\IncentivePointsLogRepairService;
|
||||
use App\Services\Incentive\IncentiveTracker;
|
||||
use App\User;
|
||||
use Carbon\Carbon;
|
||||
|
|
@ -240,7 +241,7 @@ class IncentiveParticipant extends Model
|
|||
*/
|
||||
public function recalculateFromTrackingTables(): self
|
||||
{
|
||||
$this->qualified_partners = $this->newPartners()->count();
|
||||
$this->qualified_partners = $this->newPartners()->counting()->count();
|
||||
$this->qualified_abos = $this->newAbos()->count();
|
||||
|
||||
$this->total_points = (int) $this->pointsLog()
|
||||
|
|
@ -301,6 +302,9 @@ class IncentiveParticipant extends Model
|
|||
]);
|
||||
}
|
||||
|
||||
// Stornierte Starterpakete: Neupartner bleibt sichtbar, zaehlt aber nicht
|
||||
app(IncentivePointsLogRepairService::class)->markCancelledPartners($this);
|
||||
|
||||
// B. Kundenabos (ot) + Berater-Eigenabos (me): status=2
|
||||
[$qualStart, $qualEnd] = $incentive->qualificationWindow();
|
||||
|
||||
|
|
|
|||
|
|
@ -437,6 +437,16 @@ class ShoppingOrder extends Model
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Bestellung nicht storniert (Stornorechnung setzt txaction = cancelled, paid bleibt 1).
|
||||
*/
|
||||
public function scopeWhereNotCancelled(Builder $query): Builder
|
||||
{
|
||||
return $query->where(function (Builder $q) {
|
||||
$q->whereNull('txaction')->orWhere('txaction', '!=', 'cancelled');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Erfüllt diese Bestellung die Voraussetzung für Incentive-Neupartner-Tracking (Starterpaket)?
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue