mivita/tests/Feature/Incentive/IncentiveIncludeAbosToggleTest.php
Kevin 11afdb11d1 Incentive: Schalter "Abos beruecksichtigen", Recruiting Challenge ohne Abos
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>
2026-09-24 11:37:32 +00:00

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);
});