- Laravel 11, Blade, Alpine.js, Tailwind CSS - Produkt- & Kategorieverwaltung mit Varianten - Checkout (Vorkasse + Rechnung), Session-Warenkorb - Admin-Backend (Dashboard, Bestellungen, Kunden, CMS) - DSGVO-konform: Cookie-Consent, Impressum, Widerruf, AGB - PDF-Rechnung via dompdf, SMTP-Mailversand - Kundenverwaltung mit manueller Freischaltung Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
135 lines
5.5 KiB
PHP
135 lines
5.5 KiB
PHP
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: DejaVu Sans, Arial, sans-serif; font-size: 11px; color: #222; }
|
|
.header { display: flex; justify-content: space-between; margin-bottom: 30px; }
|
|
.logo { font-size: 20px; font-weight: bold; color: #1d4ed8; }
|
|
.shop-info { text-align: right; font-size: 10px; color: #555; }
|
|
.address-block { margin-bottom: 30px; }
|
|
.address-block .to { font-size: 9px; color: #888; margin-bottom: 4px; }
|
|
.meta { float: right; width: 200px; }
|
|
.meta table { width: 100%; }
|
|
.meta td { padding: 3px 6px; }
|
|
.meta td:first-child { color: #555; }
|
|
.meta td:last-child { text-align: right; font-weight: bold; }
|
|
h2 { font-size: 16px; margin-bottom: 20px; clear: both; }
|
|
table.items { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
|
|
table.items th { background: #f1f5f9; padding: 7px 8px; text-align: left; font-size: 10px; border-bottom: 2px solid #cbd5e1; }
|
|
table.items td { padding: 6px 8px; border-bottom: 1px solid #e2e8f0; }
|
|
.text-right { text-align: right; }
|
|
.totals { width: 260px; margin-left: auto; }
|
|
.totals td { padding: 4px 8px; }
|
|
.totals td:last-child { text-align: right; }
|
|
.totals .grand-total td { font-weight: bold; font-size: 13px; border-top: 2px solid #1d4ed8; padding-top: 6px; }
|
|
.footer { margin-top: 40px; padding-top: 12px; border-top: 1px solid #e2e8f0; font-size: 9px; color: #888; }
|
|
.payment-box { background: #f0fdf4; border: 1px solid #86efac; padding: 12px; margin: 20px 0; border-radius: 4px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
@php
|
|
$shop = [
|
|
'name' => \App\Models\Setting::get('shop_name'),
|
|
'owner' => \App\Models\Setting::get('shop_owner'),
|
|
'address' => \App\Models\Setting::get('shop_address'),
|
|
'email' => \App\Models\Setting::get('shop_email'),
|
|
'phone' => \App\Models\Setting::get('shop_phone'),
|
|
'vat_id' => \App\Models\Setting::get('shop_vat_id'),
|
|
'bank' => \App\Models\Setting::get('bank_name'),
|
|
'iban' => \App\Models\Setting::get('bank_iban'),
|
|
'bic' => \App\Models\Setting::get('bank_bic'),
|
|
'days' => \App\Models\Setting::get('invoice_payment_days', 14),
|
|
];
|
|
$billing = $order->billingAddress();
|
|
$due = $order->paid_at?->addDays((int)$shop['days']);
|
|
@endphp
|
|
|
|
<div class="header">
|
|
<div class="logo">{{ $shop['name'] }}</div>
|
|
<div class="shop-info">
|
|
{{ $shop['owner'] }}<br>
|
|
{!! nl2br(e($shop['address'])) !!}<br>
|
|
{{ $shop['email'] }}<br>
|
|
@if($shop['vat_id']) USt-IdNr.: {{ $shop['vat_id'] }} @endif
|
|
</div>
|
|
</div>
|
|
|
|
<div class="address-block">
|
|
<div class="meta">
|
|
<table>
|
|
<tr><td>Rechnungsnr.</td><td>{{ $order->order_number }}</td></tr>
|
|
<tr><td>Datum</td><td>{{ ($order->paid_at ?? $order->created_at)->format('d.m.Y') }}</td></tr>
|
|
@if($due)<tr><td>Zahlungsziel</td><td>{{ $due->format('d.m.Y') }}</td></tr>@endif
|
|
<tr><td>Zahlungsart</td><td>{{ $order->payment_label }}</td></tr>
|
|
</table>
|
|
</div>
|
|
<div class="to">Rechnungsadresse</div>
|
|
@if($billing)
|
|
{{ $billing->full_name }}<br>
|
|
@if($billing->company) {{ $billing->company }}<br> @endif
|
|
{{ $billing->street }}<br>
|
|
@if($billing->street2) {{ $billing->street2 }}<br> @endif
|
|
{{ $billing->zip }} {{ $billing->city }}<br>
|
|
{{ $billing->country }}
|
|
@endif
|
|
</div>
|
|
|
|
<h2>Rechnung {{ $order->order_number }}</h2>
|
|
|
|
<table class="items">
|
|
<thead>
|
|
<tr>
|
|
<th>Artikel</th>
|
|
<th class="text-right">Menge</th>
|
|
<th class="text-right">Einzelpreis</th>
|
|
<th class="text-right">MwSt.</th>
|
|
<th class="text-right">Gesamt</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach($order->items as $item)
|
|
<tr>
|
|
<td>
|
|
{{ $item->product_name }}
|
|
@if($item->variant_label)<br><span style="color:#666;font-size:9px">{{ $item->variant_label }}</span>@endif
|
|
</td>
|
|
<td class="text-right">{{ $item->quantity }}</td>
|
|
<td class="text-right">{{ number_format($item->unit_price, 2, ',', '.') }} €</td>
|
|
<td class="text-right">{{ number_format($item->tax_rate, 0) }} %</td>
|
|
<td class="text-right">{{ number_format($item->line_total, 2, ',', '.') }} €</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
|
|
@php
|
|
$taxGroups = $order->items->groupBy('tax_rate')->map(fn($g) => $g->sum('tax_amount'));
|
|
@endphp
|
|
|
|
<table class="totals">
|
|
<tr><td>Nettobetrag</td><td>{{ number_format($order->subtotal - $order->tax_total, 2, ',', '.') }} €</td></tr>
|
|
@foreach($taxGroups as $rate => $amount)
|
|
<tr><td>MwSt. {{ number_format($rate, 0) }} %</td><td>{{ number_format($amount, 2, ',', '.') }} €</td></tr>
|
|
@endforeach
|
|
<tr><td>Versand</td><td>{{ number_format($order->shipping_cost, 2, ',', '.') }} €</td></tr>
|
|
<tr class="grand-total"><td>Gesamtbetrag</td><td>{{ number_format($order->total, 2, ',', '.') }} €</td></tr>
|
|
</table>
|
|
|
|
@if($order->payment_method === 'invoice')
|
|
<div class="payment-box">
|
|
<strong>Bitte überweisen Sie den Betrag bis {{ $due?->format('d.m.Y') ?? 'baldmöglichst' }} auf:</strong><br>
|
|
Bank: {{ $shop['bank'] }} | IBAN: {{ $shop['iban'] }} | BIC: {{ $shop['bic'] }}<br>
|
|
Verwendungszweck: {{ $order->order_number }}
|
|
</div>
|
|
@endif
|
|
|
|
<div class="footer">
|
|
{{ $shop['name'] }} · {{ $shop['owner'] }} · {{ $shop['address'] }} · {{ $shop['email'] }}
|
|
@if($shop['vat_id']) · USt-IdNr.: {{ $shop['vat_id'] }} @endif
|
|
@if($shop['iban']) · IBAN: {{ $shop['iban'] }} @endif
|
|
</div>
|
|
</body>
|
|
</html>
|