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>
186 lines
6.8 KiB
PHP
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);
|
|
});
|