Die Recruiting Challenge erfasste Eigen- und Kundenabos mit 0 Punkten (Live-Kopie: 175 Eigenabos). Sie tauchten in Details und Admin auf und brachten Berater ohne Neupartner in die Rangliste. - incentives.include_abos (Standard an); Migration schaltet Incentives ohne jede Abo-Wertung aus (0 Abo-Punkte, 0 Mindestabos, ohne Umsatzpunkte) - aus: kein Abo-Tracking in Tracker, Neuaufbau und Reparatur; incentive:calculate raeumt vorhandene Abo-Zeilen ab - Admin: Checkbox im Formular, Abo-Punkte/Mindestabos werden dann auf 0 gesetzt; Abo-Spalte und -Bereiche in Admin, Details und Teilnahme-Hinweis entfallen - Seeder der Recruiting Challenge setzt den Schalter aus Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
134 lines
4.7 KiB
PHP
134 lines
4.7 KiB
PHP
<?php
|
|
|
|
use App\Models\Country;
|
|
use App\Models\Incentive;
|
|
use App\Models\IncentiveNewAbo;
|
|
use App\Models\IncentiveParticipant;
|
|
use App\Models\IncentivePointsLog;
|
|
use App\Models\ShoppingUser;
|
|
use App\Models\UserAbo;
|
|
use App\User;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
/**
|
|
* Kundenwunsch 24.09.2026: Bei der Recruiting-Challenge sollen keine Abos auftauchen.
|
|
* Schalter "Abos beruecksichtigen" im Incentive; aus = kein Abo-Tracking.
|
|
*/
|
|
beforeEach(function () {
|
|
Carbon::setTestNow(Carbon::parse('2026-11-15 10:00:00'));
|
|
});
|
|
|
|
afterEach(fn () => Carbon::setTestNow());
|
|
|
|
/**
|
|
* Berater mit Eigenabo, das schon vor dem Qualifikationsstart lief.
|
|
*
|
|
* @return array{0: User, 1: UserAbo}
|
|
*/
|
|
function includeAbosConsultant(): array
|
|
{
|
|
$country = Country::firstOrCreate(['code' => 'DE'], [
|
|
'phone' => '49', 'en' => 'Germany', 'de' => 'Deutschland', 'es' => 'Alemania',
|
|
'fr' => 'Allemagne', 'it' => 'Germania', 'ru' => 'Германия',
|
|
]);
|
|
|
|
$consultant = User::forceCreate([
|
|
'email' => 'inc-abos-'.uniqid('', true).'@example.com',
|
|
'password' => bcrypt('secret'),
|
|
'lang' => 'de',
|
|
]);
|
|
|
|
$shoppingUser = ShoppingUser::create([
|
|
'auth_user_id' => $consultant->id,
|
|
'member_id' => $consultant->id,
|
|
'billing_country_id' => $country->id,
|
|
'shipping_country_id' => $country->id,
|
|
'billing_email' => 'me-'.uniqid('', true).'@example.com',
|
|
'is_from' => 'wizard',
|
|
]);
|
|
|
|
$userAbo = UserAbo::create([
|
|
'user_id' => $consultant->id,
|
|
'member_id' => null,
|
|
'shopping_user_id' => $shoppingUser->id,
|
|
'is_for' => 'me',
|
|
'email' => $shoppingUser->billing_email,
|
|
'payone_userid' => 999003,
|
|
'clearingtype' => 'cc',
|
|
'active' => true,
|
|
'status' => 2,
|
|
'abo_interval' => 1,
|
|
]);
|
|
$userAbo->forceFill(['created_at' => '2026-06-15 12:00:00'])->save();
|
|
|
|
return [$consultant, $userAbo];
|
|
}
|
|
|
|
function includeAbosIncentive(bool $includeAbos): Incentive
|
|
{
|
|
return Incentive::factory()->create([
|
|
'qualification_start' => '2026-10-01',
|
|
'qualification_end' => '2027-01-31',
|
|
'calculation_end' => '2027-01-31',
|
|
'status' => 1,
|
|
'points_partner_onetime' => 1,
|
|
'points_abo_onetime' => 0,
|
|
'min_direct_partners' => 0,
|
|
'min_customer_abos' => 0,
|
|
'include_sales_points' => false,
|
|
'include_abos' => $includeAbos,
|
|
]);
|
|
}
|
|
|
|
it('erfasst bei ausgeschaltetem Schalter keine Abos', function () {
|
|
[$consultant] = includeAbosConsultant();
|
|
$incentive = includeAbosIncentive(false);
|
|
$participant = IncentiveParticipant::factory()->create([
|
|
'incentive_id' => $incentive->id,
|
|
'user_id' => $consultant->id,
|
|
]);
|
|
|
|
Artisan::call('incentive:calculate', ['incentive_id' => (string) $incentive->id]);
|
|
expect(IncentiveNewAbo::where('participant_id', $participant->id)->exists())->toBeFalse();
|
|
|
|
Artisan::call('incentive:calculate', ['incentive_id' => (string) $incentive->id, '--force' => true]);
|
|
expect(IncentiveNewAbo::where('participant_id', $participant->id)->exists())->toBeFalse()
|
|
->and($participant->fresh()->qualified_abos)->toBe(0)
|
|
->and($incentive->usesAbos())->toBeFalse();
|
|
});
|
|
|
|
it('erfasst das Eigenabo weiterhin, solange der Schalter an ist', function () {
|
|
[$consultant, $userAbo] = includeAbosConsultant();
|
|
$incentive = includeAbosIncentive(true);
|
|
$participant = IncentiveParticipant::factory()->create([
|
|
'incentive_id' => $incentive->id,
|
|
'user_id' => $consultant->id,
|
|
]);
|
|
|
|
Artisan::call('incentive:calculate', ['incentive_id' => (string) $incentive->id]);
|
|
|
|
expect(IncentiveNewAbo::where('participant_id', $participant->id)->where('user_abo_id', $userAbo->id)->exists())
|
|
->toBeTrue();
|
|
});
|
|
|
|
it('raeumt bereits erfasste Abos beim naechsten Lauf ab, wenn der Schalter aus ist', function () {
|
|
[$consultant, $userAbo] = includeAbosConsultant();
|
|
$incentive = includeAbosIncentive(true);
|
|
$participant = IncentiveParticipant::factory()->create([
|
|
'incentive_id' => $incentive->id,
|
|
'user_id' => $consultant->id,
|
|
]);
|
|
Artisan::call('incentive:calculate', ['incentive_id' => (string) $incentive->id]);
|
|
expect($participant->fresh()->qualified_abos)->toBe(1);
|
|
|
|
$incentive->update(['include_abos' => false]);
|
|
Artisan::call('incentive:calculate', ['incentive_id' => (string) $incentive->id]);
|
|
|
|
expect(IncentiveNewAbo::where('participant_id', $participant->id)->exists())->toBeFalse()
|
|
->and(IncentivePointsLog::where('participant_id', $participant->id)->where('type', 'abo')->exists())->toBeFalse()
|
|
->and($participant->fresh()->qualified_abos)->toBe(0);
|
|
});
|