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>
219 lines
No EOL
10 KiB
PHP
219 lines
No EOL
10 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>
|
|
@if($shopping_order->payment_for === 6)
|
|
<th class="text-right" style="width: 15%">
|
|
<span class="no-line-break">{{ __('pdf.eprice') }}</span> @if($shopping_order->tax == 0)*@endif</th>
|
|
<th class="text-right" style="width: 10%">{{__('tables.quantity')}}</th>
|
|
<th class="text-right" style="width: 10%">{{__('tables.VAT')}}</th>
|
|
<th class="text-right" style="width: 15%">{{__('tables.sum')}} @if($shopping_order->tax == 0)*@endif</th>
|
|
@else
|
|
<th class="text-right" style="width: 15%">
|
|
<span class="no-line-break">{{__('tables.vk_price')}}*</span>
|
|
</th>
|
|
<th class="text-right" style="width: 10%">{{__('tables.quantity')}}</th>
|
|
<th class="text-right" style="width: 10%">{{__('tables.points')}}</th>
|
|
<th class="text-right" style="width: 10%">%</th>
|
|
<th class="text-right" style="width: 15%">
|
|
<span class="no-line-break">{{ __('tables.ek_price') }}*</span>
|
|
</th>
|
|
@endif
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@php
|
|
$invoiceItems = $shopping_order->shopping_order_items->sortBy(fn ($item) => $item->is_abo_addon ? 1 : 0)->values();
|
|
$hasAddonItems = $invoiceItems->contains(fn ($item) => $item->is_abo_addon);
|
|
$headingColspan = $shopping_order->payment_for === 6 ? 6 : 7;
|
|
$addonHeadingShown = false;
|
|
$aboHeadingShown = false;
|
|
@endphp
|
|
@foreach($invoiceItems 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="{{ $headingColspan }}" 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="{{ $headingColspan }}" 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>
|
|
@if($shopping_order->payment_for === 6)
|
|
<td class="text-right small">
|
|
{{ $shopping_order_item->getFormattedPrice() }} €
|
|
</td>
|
|
<td class="text-right small">
|
|
{{ cleanIntegerFromString($shopping_order_item->qty) }}
|
|
</td>
|
|
<td class="text-right small">
|
|
{{ $shopping_order_item->getFormattedTaxRate() }}%
|
|
</td>
|
|
<td class="text-right small">
|
|
{{ $shopping_order_item->getFormattedTotalPrice() }} €
|
|
</td>
|
|
@else
|
|
<td class="text-right small">
|
|
{{ $shopping_order_item->getFormattedPriceVkNet() }} €
|
|
</td>
|
|
<td class="text-right small">
|
|
{{ cleanIntegerFromString($shopping_order_item->qty) }}
|
|
</td>
|
|
<td class="text-right small">
|
|
{{ $shopping_order_item->getFormattedPoints() }}
|
|
</td>
|
|
<td class="text-right small">
|
|
@if($shopping_order_item->price > 0)
|
|
{{ cleanNumberFormat($shopping_order_item->discount) }}
|
|
@else
|
|
0
|
|
@endif
|
|
</td>
|
|
<td class="text-right small">
|
|
{{ $shopping_order_item->getFormattedTotalPriceNet() }} €
|
|
</td>
|
|
@endif
|
|
|
|
</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>
|
|
@if($shopping_order->payment_for === 6)
|
|
<td class="text-right small" style="color: #999;">-</td>
|
|
<td class="text-right small" style="color: #999;">-</td>
|
|
<td class="text-right small" style="color: #999;">-</td>
|
|
<td class="text-right small" style="color: #999;">-</td>
|
|
@else
|
|
<td class="text-right small" style="color: #999;">-</td>
|
|
<td class="text-right small" style="color: #999;">-</td>
|
|
<td class="text-right small" style="color: #999;">-</td>
|
|
<td class="text-right small" style="color: #999;">-</td>
|
|
<td class="text-right small" style="color: #999;">-</td>
|
|
@endif
|
|
</tr>
|
|
@endforeach
|
|
@endif
|
|
@endforeach
|
|
</tbody>
|
|
<tfoot>
|
|
@if($shopping_order->payment_for === 6)
|
|
@php($colspan = 4)
|
|
@else
|
|
@php($colspan = 5)
|
|
@endif
|
|
|
|
<tr class="fullline">
|
|
<td class="text-right"> </td>
|
|
<td class="text-left" colspan="{{ $colspan }}">
|
|
{{__('email.checkout_mail_shipping')}}
|
|
</td>
|
|
<td class="text-right">
|
|
@if($shopping_order->tax > 0)
|
|
@if($shopping_order->payment_for === 6)
|
|
{{ $shopping_order->getFormattedShipping() }} €
|
|
@else
|
|
{{ $shopping_order->getFormattedShippingNet() }} €
|
|
@endif
|
|
@else
|
|
{{ $shopping_order->getFormattedShippingNet() }} €
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
<tr class="fullline">
|
|
<td class="text-right"> </td>
|
|
<td class="text-left" colspan="{{ $colspan }}">
|
|
{{__('email.checkout_mail_subtotal_ws')}}
|
|
</td>
|
|
<td class="text-right">
|
|
{{ $shopping_order->getFormattedSubtotalWs() }} €
|
|
</td>
|
|
</tr>
|
|
@if($shopping_order->tax > 0)
|
|
@if($shopping_order->tax_split)
|
|
@foreach ($shopping_order->tax_split as $tax_rate => $tax)
|
|
<tr class="">
|
|
<td class="text-right"> </td>
|
|
<td class="text-left" colspan="{{ $colspan }}">
|
|
{{ __('order.excl') }} {{ $tax_rate }}% {{ __('order.VAT') }}
|
|
@if(isset($shopping_order->net_split[$tax_rate]))
|
|
/ {{ __('pdf.off') }} {{ Util::formatNumber($shopping_order->net_split[$tax_rate]) }} € {{ __('pdf.net') }}
|
|
@endif
|
|
</td>
|
|
<td class="text-right">
|
|
{{ formatNumber($tax) }} €
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
@else
|
|
<tr class="">
|
|
<td class="text-right"> </td>
|
|
<td class="text-left" colspan="{{ $colspan }}">
|
|
{{__('email.checkout_mail_tax')}}
|
|
</td>
|
|
<td class="text-right">
|
|
{{ $shopping_order->getFormattedTax() }} €
|
|
</td>
|
|
</tr>
|
|
@endif
|
|
|
|
<tr class="fullline">
|
|
<td class="text-right"> </td>
|
|
<td class="text-left" colspan="{{ $colspan }}">
|
|
<b>{{ __('pdf.total_incl_VAT') }}</b>
|
|
</td>
|
|
<td class="text-right">
|
|
<span class="no-line-break">
|
|
<b>{{ $shopping_order->getFormattedTotalShipping() }} €</b>
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
@else
|
|
<tr class="">
|
|
<td class="text-right"> </td>
|
|
<td class="text-left" colspan="{{ $colspan }}">
|
|
{{__('email.checkout_mail_tax')}}
|
|
</td>
|
|
<td class="text-right">
|
|
0 €
|
|
</td>
|
|
</tr>
|
|
<tr class="fullline">
|
|
<td class="text-right"> </td>
|
|
<td class="text-left" colspan="{{ $colspan }}">
|
|
<b>{{ __('order.sum') }}</b>
|
|
</td>
|
|
<td class="text-right">
|
|
<span class="no-line-break">
|
|
<b>{{ $shopping_order->getFormattedTotalShipping() }} €</b>
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
@endif
|
|
</tfoot>
|
|
</table>
|
|
</div> |