mivita/resources/views/pdf/delivery-detail.blade.php
Kevin 65b867f8ee 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>
2026-06-23 13:38:11 +00:00

66 lines
No EOL
2.9 KiB
PHP

<div id="invoice_box">
<table>
<thead>
<tr>
<th class="text-left" style="width: 10%">
<span class="no-line-break">{{__('tables.article_no')}}</span>
</th>
<th class="text-left" style="width: 40%">{{__('tables.label')}}</th>
<th class="text-right" style="width: 10%">{{__('tables.quantity')}}</th>
</tr>
</thead>
<tbody>
@php
$deliveryItems = $shopping_order->shopping_order_items->sortBy(fn ($item) => $item->is_abo_addon ? 1 : 0)->values();
$hasAddonItems = $deliveryItems->contains(fn ($item) => $item->is_abo_addon);
$addonHeadingShown = false;
$aboHeadingShown = false;
@endphp
@foreach($deliveryItems as $shopping_order_item)
@if($hasAddonItems && ! $shopping_order_item->is_abo_addon && ! $aboHeadingShown)
@php($aboHeadingShown = true)
<tr class="item">
<td class="small text-left" colspan="3" style="background-color: #f2f2f2;">
<b>{{ __('pdf.abo_items_heading') }}</b>
</td>
</tr>
@endif
@if($hasAddonItems && $shopping_order_item->is_abo_addon && ! $addonHeadingShown)
@php($addonHeadingShown = true)
<tr class="item">
<td class="small text-left" colspan="3" style="background-color: #f2f2f2;">
<b>{{ __('pdf.abo_addon_items_heading') }}</b>
</td>
</tr>
@endif
<tr class="item">
<td class="small text-left">
{{ $shopping_order_item->product->number }}
</td>
<td class="small text-left">
{{ maxStrLength($shopping_order_item->product->getLang('name'), 35) }}
</td>
<td class="text-right small">
{{ cleanIntegerFromString($shopping_order_item->qty) }}
</td>
</tr>
{{-- Bundle-Items: Enthaltene Produkte im Set/Kit auflisten --}}
@if($shopping_order_item->product->bundleItems && $shopping_order_item->product->bundleItems->count() > 0)
@foreach($shopping_order_item->product->bundleItems as $bundleItem)
<tr class="item" style="background-color: #f9f9f9;">
<td class="small text-left" style="padding-left: 5mm; color: #666;">
{{ $bundleItem->number }}
</td>
<td class="small text-left" style="color: #666;">
<span style="font-size: 0.9em;">↳ {{ $bundleItem->pivot->quantity }}x {{ maxStrLength($bundleItem->getLang('name'), 30) }}</span>
</td>
<td class="text-right small" style="color: #999;">
-
</td>
</tr>
@endforeach
@endif
@endforeach
</tbody>
</table>
</div>