mivita/tests/Feature/AboCheckOverdueTest.php
Kevin 452d1ac17f Abos: taegliche Warnung fuer ueberfaellige Abos, ohne Nachbuchung
user:make_abo_order nimmt nur Abos mit next_date = heute; faellt ein Lauf
aus, bleibt ein Abo stillschweigend liegen (Abo 39: Termin 25.03.2026).
abo:check-overdue meldet taeglich um 05:30 alle aktiven Abos mit Status
okay und verstrichenem Termin per Mail an mivita (Link ins Admin-Abo) und
ins abo_order-Log. Es wird bewusst nichts nachgebucht; --no-mail nur fuer
die Ausgabe.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 15:44:45 +00:00

76 lines
2.5 KiB
PHP

<?php
use App\Mail\AboOverdueAlertMail;
use App\Models\UserAbo;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
uses(TestCase::class, RefreshDatabase::class);
beforeEach(function () {
Carbon::setTestNow(Carbon::parse('2026-09-23 05:30:00'));
Mail::fake();
});
afterEach(fn () => Carbon::setTestNow());
function overdueAbo(string $nextDate, int $status = 2, bool $active = true): UserAbo
{
return UserAbo::create([
'user_id' => null,
'member_id' => 1,
'shopping_user_id' => 0,
'is_for' => 'ot',
'email' => 'abo-'.uniqid('', true).'@example.com',
'payone_userid' => 1,
'clearingtype' => 'cc',
'active' => $active,
'status' => $status,
'abo_interval' => (int) Carbon::parse($nextDate)->day,
'start_date' => '2026-01-01',
'next_date' => $nextDate,
]);
}
it('meldet laufende Abos mit verstrichenem Termin und bucht nichts nach', function () {
$stuck = overdueAbo('2026-03-25');
overdueAbo('2026-09-23'); // heute faellig: laeuft regulaer
overdueAbo('2026-10-05'); // Zukunft
overdueAbo('2026-08-10', status: 3); // Zahlung fehlgeschlagen: eigener Zustand
overdueAbo('2026-08-10', active: false); // inaktiv
$this->artisan('abo:check-overdue')
->expectsOutputToContain('Überfällige Abos: 1')
->assertSuccessful();
Mail::assertSent(AboOverdueAlertMail::class, function (AboOverdueAlertMail $mail) use ($stuck) {
$html = $mail->render();
return $mail->hasTo(config('app.default_mail'))
&& count($mail->overdueAbos) === 1
&& str_contains($html, '#'.$stuck->id)
&& str_contains($html, '25.03.2026')
&& str_contains($html, '/admin/abos/detail/'.$stuck->id);
});
expect(Carbon::parse($stuck->fresh()->getRawOriginal('next_date'))->toDateString())->toBe('2026-03-25')
->and($stuck->user_abo_orders()->count())->toBe(0);
});
it('schickt ohne ueberfaellige Abos keine Mail', function () {
overdueAbo('2026-10-05');
$this->artisan('abo:check-overdue')->expectsOutputToContain('Keine überfälligen Abos.')->assertSuccessful();
Mail::assertNothingSent();
});
it('schickt mit --no-mail nur die Ausgabe', function () {
overdueAbo('2026-09-01');
$this->artisan('abo:check-overdue', ['--no-mail' => true])->assertSuccessful();
Mail::assertNothingSent();
});