Abo Einmalprodukte: Phasen 5-7, konfigurierbare Sperrfristen, Lokalisierung & Dashboard
Rechnung/Lieferschein: - PDF-Gruppierung Abo- vs. Einmal-Artikel (is_abo_addon), rueckwaertskompatibel - Vorschau-Command sales:preview-invoice (umgeht Test-System-Gate, ohne Rechnungsnummer) Reminder-Mail (vorbereitet, Cron inaktiv): - MailAboExecutionReminder + Template, abo:send-execution-reminder, Spalte onetime_reminder_sent_for - Berater -> Sales Center, Kunde -> Portal; Vorschau abo:preview-reminder - Datum-Fix: formatDateDB() statt formatDate() (ICU-Format) Sperrfristen konfigurierbar (Admin-Settings): - abo-lock-days-change (Liefertag + Abo-Produkte), abo-lock-days-pause-cancel - Meldungen mit :lock-Platzhalter; Pausieren/Kuendigen vom Change-Lock entkoppelt - Abo-Produkt-Aenderungen im Lock-Fenster server- + clientseitig eingefroren - Selbstbedienung: Add-only/Lock nach $view (kein Admin-Bypass), Stale-Cache-Fix beim Mengen-Update Dashboard: - Einmalprodukte-Card + Team-Abo-KPI-Card, News-Card responsiv (col-xl-6) Lokalisierung: - Sprachdateien en/es/fr vollstaendig mit de synchronisiert (inkl. marketingplan/portal) - LocalizationSyncTest sichert Key-Gleichheit ab Tests: AboOneTimeInvoiceGrouping, AboExecutionReminder, AboLockDaysSetting, AboOnetimeDashboardAndMail, PreviewInvoiceCommand, TeamAboOverview + erweiterte View-Tests Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
9f996a7f1b
commit
65b867f8ee
96 changed files with 4154 additions and 1189 deletions
|
|
@ -238,4 +238,74 @@ describe('Abo Einmal-Produkte Views', function () {
|
|||
]))
|
||||
->and($html)->toContain(__('abo.confirm_add_ok'));
|
||||
});
|
||||
|
||||
it('rendert nach einer Mengenänderung die aktuelle (persistierte) Menge – kein Stale-Cache', function () {
|
||||
$abo = makeMeAbo();
|
||||
$product = makeProduct(['12'], 50, 0);
|
||||
$item = \App\Models\UserAboItem::create([
|
||||
'user_abo_id' => $abo->id, 'product_id' => $product->id, 'comp' => 0, 'qty' => 1, 'status' => 1,
|
||||
]);
|
||||
|
||||
// Relation cachen (wie initYard/makeOrderYard im Controller)
|
||||
$abo->load('user_abo_items');
|
||||
expect($abo->user_abo_items->first()->qty)->toBe(1);
|
||||
|
||||
// Menge über separate Instanz erhöhen (wie der Controller in updateCart/addProduct)
|
||||
\App\Models\UserAboItem::find($item->id)->update(['qty' => 3]);
|
||||
|
||||
// Fix: Relation vor dem Render neu laden → gerenderte Menge = gespeicherter Stand
|
||||
$abo->load('user_abo_items');
|
||||
$html = view('admin.abo._order_abo_show', [
|
||||
'user_abo' => $abo,
|
||||
'split_mode' => true,
|
||||
'summary' => ['abo' => ['gross' => 150], 'total_with_shipping' => 150],
|
||||
])->render();
|
||||
|
||||
expect($html)->toContain('value="3"');
|
||||
});
|
||||
|
||||
it('blendet Minus/Entfernen im Add-only-Modus aus (Mindestlaufzeit nicht erfüllt)', function () {
|
||||
$abo = makeMeAbo();
|
||||
$product = makeProduct(['12'], 50, 0);
|
||||
\App\Models\UserAboItem::create([
|
||||
'user_abo_id' => $abo->id, 'product_id' => $product->id, 'comp' => 0, 'qty' => 2, 'status' => 1,
|
||||
]);
|
||||
$abo->load('user_abo_items');
|
||||
|
||||
$summary = ['abo' => ['gross' => 100], 'total_with_shipping' => 100];
|
||||
|
||||
$addOnly = view('admin.abo._order_abo_show', [
|
||||
'user_abo' => $abo, 'split_mode' => true, 'summary' => $summary, 'add_only_mode' => true,
|
||||
])->render();
|
||||
expect($addOnly)->not->toContain('remove-from-basket')
|
||||
->and($addOnly)->not->toContain('auto-delete-product')
|
||||
->and($addOnly)->toContain('add-from-basket') // Hinzufügen bleibt möglich
|
||||
->and($addOnly)->toContain('readonly');
|
||||
|
||||
$free = view('admin.abo._order_abo_show', [
|
||||
'user_abo' => $abo, 'split_mode' => true, 'summary' => $summary, 'add_only_mode' => false,
|
||||
])->render();
|
||||
expect($free)->toContain('remove-from-basket')
|
||||
->and($free)->toContain('auto-delete-product');
|
||||
});
|
||||
|
||||
it('friert alle Produkt-Steuerungen ein, wenn der Change-Lock greift', function () {
|
||||
$abo = makeMeAbo();
|
||||
$product = makeProduct(['12'], 50, 0);
|
||||
\App\Models\UserAboItem::create([
|
||||
'user_abo_id' => $abo->id, 'product_id' => $product->id, 'comp' => 0, 'qty' => 2, 'status' => 1,
|
||||
]);
|
||||
$abo->load('user_abo_items');
|
||||
|
||||
$html = view('admin.abo._order_abo_show', [
|
||||
'user_abo' => $abo, 'split_mode' => true,
|
||||
'summary' => ['abo' => ['gross' => 100], 'total_with_shipping' => 100],
|
||||
'change_locked' => true,
|
||||
])->render();
|
||||
|
||||
expect($html)->not->toContain('add-from-basket')
|
||||
->and($html)->not->toContain('remove-from-basket')
|
||||
->and($html)->not->toContain('auto-delete-product')
|
||||
->and($html)->toContain('readonly');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue