mivita/tests/Feature/MembershipRenewalProductTest.php
Kevin 30fb031d12 Mitgliedschaft: Erinnerungen und eigenes Verlaengerungs-Produkt
Die Erinnerungsmails vor Ablauf der Mitgliedschaft beschrieben noch den
abgeschafften SEPA-Einzug und verlinkten auf die Hauptdomain, wo
/user/membership nicht existiert. Das Produkt fuer die Verlaengerung war
zudem dasselbe wie bei der Registrierung und sprach deshalb vom
Neuabschluss.

- Erinnerungen: nur noch Stufen 31/33/34/35, SEPA-Stufen 32/36/37 samt
  :price und :pay_date entfallen; Button verlinkt auf my.mivita.care;
  fehlt ein Text zum Status, wird die Mail geloggt statt roh versendet.
- Alle Erinnerungstexte (de/en/es/fr) erklaeren jetzt, dass ohne Zahlung
  der Account pausiert und offene Provisionen ausgezahlt werden.
- Eigenes Produkt fuer die Verlaengerung (identifier show_renewal) als
  Kopie des Mitgliedschafts-Produkts inkl. Preisen, Kategorien und
  Uebersetzungen fuer en/es/fr; die Mitgliedschaftsseite faellt ohne
  dieses Produkt auf das bisherige zurueck.
- Mitgliedschaftsseite auf ein Paket reduziert: Upgrade-, Wechsel- und
  Abo-Optionen entfernt, Texte auf die manuelle Verlaengerung umgestellt.
- Alte Cron-Weboberflaeche entfernt, der Versand laeuft ueber den
  Scheduler (payments:check-accounts).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 08:24:32 +00:00

186 lines
6.8 KiB
PHP

<?php
use App\Http\Controllers\User\MembershipController;
use App\Models\Product;
use App\Models\TransProduct;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
uses(TestCase::class, RefreshDatabase::class);
/**
* Die Verlängerung braucht ein eigenes Produkt: das Registrierungs-Produkt
* (show_order) beschreibt den Neuabschluss und passt inhaltlich nicht.
*/
function makeMembershipProduct(string $identifier, array $showOn, string $name, int $pos = 20): Product
{
$now = now();
$id = (int) DB::table('products')->insertGetId([
'name' => $name,
'title' => '12 Monate Laufzeit',
'copy' => '<p>Du kannst Dich jetzt mit der Jahresgebühr registrieren.</p>',
'identifier' => $identifier,
'active' => true,
'price' => 69.90,
'tax' => 19,
'weight' => 0,
'points' => 0,
'pos' => $pos,
'is_membership_only' => 1,
'action' => json_encode(['0', '1']),
'show_on' => json_encode($showOn),
'created_at' => $now,
'updated_at' => $now,
]);
return Product::findOrFail($id);
}
function runRenewalProductMigration(): void
{
(require base_path('database/migrations/2026_08_25_120000_create_membership_renewal_product.php'))->up();
}
function renewalProductsOfController(): Collection
{
$method = new ReflectionMethod(MembershipController::class, 'renewalProducts');
$method->setAccessible(true);
return collect($method->invoke(new MembershipController));
}
it('legt das Verlängerungs-Produkt als Kopie des Registrierungs-Produkts an', function () {
$registration = makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
runRenewalProductMigration();
$renewal = Product::where('identifier', 'show_renewal')->firstOrFail();
expect($renewal->id)->not->toBe($registration->id)
->and($renewal->name)->toBe($registration->name)
->and((float) $renewal->price)->toBe((float) $registration->price)
->and($renewal->action)->toBe($registration->action)
->and((bool) $renewal->is_membership_only)->toBeTrue()
->and($renewal->show_on)->toBe(['8'])
->and($renewal->slug)->not->toBe($registration->slug);
});
it('spricht im Verlängerungs-Text von der Verlängerung statt von der Registrierung', function () {
makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
runRenewalProductMigration();
$renewal = Product::where('identifier', 'show_renewal')->firstOrFail();
expect($renewal->copy)->toContain('verlängerst Deine MIVITA Mitgliedschaft')
->and($renewal->copy)->not->toContain('registrieren');
});
it('laesst das Registrierungs-Produkt unveraendert', function () {
$registration = makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
runRenewalProductMigration();
expect($registration->fresh()->show_on)->toBe(['7', '8'])
->and($registration->fresh()->identifier)->toBe('show_order');
});
it('legt kein zweites Verlängerungs-Produkt an', function () {
makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
runRenewalProductMigration();
runRenewalProductMigration();
expect(Product::where('identifier', 'show_renewal')->count())->toBe(1);
});
it('zeigt bei der Verlängerung nur noch das Verlängerungs-Produkt', function () {
makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
runRenewalProductMigration();
$products = renewalProductsOfController();
expect($products)->toHaveCount(1)
->and($products->first()->identifier)->toBe('show_renewal');
});
it('faellt ohne Verlängerungs-Produkt auf das Mitgliedschafts-Produkt zurueck', function () {
makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
$products = renewalProductsOfController();
expect($products)->toHaveCount(1)
->and($products->first()->identifier)->toBe('show_order');
});
it('ignoriert ein inaktives Verlängerungs-Produkt', function () {
makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
runRenewalProductMigration();
Product::where('identifier', 'show_renewal')->update(['active' => false]);
$products = renewalProductsOfController();
expect($products)->toHaveCount(1)
->and($products->first()->identifier)->toBe('show_order');
});
function runRenewalTranslationMigration(): void
{
(require base_path('database/migrations/2026_08_25_130000_translate_membership_renewal_product.php'))->up();
}
function renewalCopyIn(string $locale): string
{
app()->setLocale($locale);
return Product::where('identifier', 'show_renewal')->firstOrFail()->getLang('copy');
}
it('uebersetzt die Verlängerungs-Beschreibung in alle Sprachen', function (string $locale, string $needle) {
makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
runRenewalProductMigration();
runRenewalTranslationMigration();
expect(renewalCopyIn($locale))->toContain($needle)
->and(renewalCopyIn($locale))->not->toContain('verlängerst Deine MIVITA Mitgliedschaft');
})->with([
'en' => ['en', 'renewing your MIVITA membership'],
'es' => ['es', 'Amplías tu afiliación MIVITA'],
'fr' => ['fr', 'Vous renouvelez votre adhésion MIVITA'],
]);
it('behaelt den deutschen Text als Standard', function () {
makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
runRenewalProductMigration();
runRenewalTranslationMigration();
expect(renewalCopyIn('de'))->toContain('verlängerst Deine MIVITA Mitgliedschaft');
});
it('uebernimmt den uebersetzten Produktnamen aus dem Mitgliedschafts-Produkt', function () {
$registration = makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
TransProduct::create(['language' => 'en', 'product_id' => $registration->id, 'key' => 'name', 'value' => 'MIVITA BUSINESS package']);
runRenewalProductMigration();
runRenewalTranslationMigration();
app()->setLocale('en');
expect(Product::where('identifier', 'show_renewal')->firstOrFail()->getLang('name'))->toBe('MIVITA BUSINESS package');
});
it('ueberschreibt nachtraeglich angepasste Uebersetzungen nicht', function () {
makeMembershipProduct('show_order', ['7', '8'], 'MIVITA BUSINESS Paket');
runRenewalProductMigration();
$renewal = Product::where('identifier', 'show_renewal')->firstOrFail();
TransProduct::create(['language' => 'en', 'product_id' => $renewal->id, 'key' => 'copy', 'value' => '<p>Handmade</p>']);
runRenewalTranslationMigration();
runRenewalTranslationMigration();
expect(renewalCopyIn('en'))->toBe('<p>Handmade</p>')
->and(TransProduct::where('product_id', $renewal->id)->where('key', 'copy')->count())->toBe(3);
});