Finetuning Rechnungs-Ansicht + vier Open-Sans-TTF Fonts (free) verwendet.

This commit is contained in:
fds2610-bot 2026-04-28 06:50:46 +02:00
parent 3954e8a4b0
commit c1cfad9dc3
7 changed files with 42 additions and 27 deletions

View file

@ -12,6 +12,8 @@ class PdfInvoiceService
{
$html = $this->buildHtml($invoice, $lines, $settings);
$fontDir = dirname(__DIR__) . '/fonts';
$mpdf = new Mpdf([
'mode' => 'utf-8',
'format' => 'A4',
@ -19,6 +21,16 @@ class PdfInvoiceService
'margin_bottom' => 25,
'margin_left' => 25, // DIN 5008: 25mm links
'margin_right' => 15, // DIN 5008: 15mm rechts
'fontDir' => [$fontDir],
'fontdata' => [
'opensans' => [
'R' => 'OpenSans-Regular.ttf',
'B' => 'OpenSans-Bold.ttf',
'I' => 'OpenSans-Italic.ttf',
'BI' => 'OpenSans-BoldItalic.ttf',
],
],
'default_font' => 'opensans',
]);
$mpdf->SetTitle('Rechnung ' . ($invoice['rechnungs_nr'] ?? 'Entwurf'));
@ -107,11 +119,13 @@ class PdfInvoiceService
<div class="logo-wrap" style="{$logoWrapStyle}">{$logoHtml}</div>
<!-- Adressbereich DIN 5008 Typ A (Anschriftfeld 85mm × 45mm) -->
<div style="height:10mm"></div>
<table class="address-block">
<tr>
<!-- Linke Spalte: Anschriftfeld 85mm (Kuvertfenster) -->
<td class="address-left">
<div class="return-address">{$h($settings['firma'] ?? '')} · {$h($settings['strasse'] ?? '')} · {$h($settings['plz'] ?? '')} {$h($settings['ort'] ?? '')}</div>
<div style="height:2.5mm;font-size:2.5mm;line-height:2.5mm">&nbsp;</div>
<div class="recipient">
{$h($customerName)}<br>
{$h($inv['strasse'])}<br>
@ -119,11 +133,12 @@ class PdfInvoiceService
</div>
</td>
<!-- Rechte Spalte: Dokumententitel -->
<td class="address-right" style="text-align:right;vertical-align:top">RECHNUNG</td>
<td class="address-right" style="text-align:right;vertical-align:top;font-size:14.7pt">Rechnung</td>
</tr>
</table>
<!-- Meta-Felder -->
<div style="height:20mm"></div>
<table class="meta-table">
<thead>
<tr>
@ -190,7 +205,7 @@ HTML;
<tr>
<td>
<strong>{$h($settings['firma'] ?? '')}</strong><br>
{$h($settings['inhaber'] ?? '')}<br>
Inh. {$h($settings['inhaber'] ?? '')}<br>
{$h($settings['strasse'] ?? '')}<br>
{$h($settings['plz'] ?? '')} {$h($settings['ort'] ?? '')}<br>
USt-ID: {$h($settings['ust_id'] ?? '')}
@ -216,7 +231,7 @@ HTML;
private function buildCss(): string
{
return <<<CSS
body { font-family: DejaVu Sans, sans-serif; font-size: 7.8pt; color: #000; }
body { font-family: opensans, sans-serif; font-size: 7.8pt; color: #000; }
.invoice-wrap { width: 100%; }
/* Logo */
@ -230,21 +245,21 @@ body { font-family: DejaVu Sans, sans-serif; font-size: 7.8pt; color: #000; }
.return-address {
font-size: 5.5pt; color: #555;
border-bottom: 0.3pt solid #aaa;
padding-bottom: 1mm; margin-bottom: 2mm;
padding-bottom: 1mm;
}
.recipient { font-size: 7.8pt; line-height: 1.5; min-height: 27.3mm; }
.recipient { font-size: 10pt; line-height: 1.5; min-height: 27.3mm; }
/* Meta-Felder */
.meta-table { width: 100%; table-layout: fixed; border-collapse: collapse; margin-bottom: 8mm; font-size: 7pt; }
.meta-table th { background: #f0f0f0; padding: 2mm; text-align: left; font-size: 6pt; color: #555; border: 0.5pt solid #ccc; }
.meta-table td { padding: 2mm; border: 0.5pt solid #ccc; }
.meta-table th { padding: 2mm 2mm 1mm; text-align: left; font-size: 7pt; color: #000; font-weight: bold; }
.meta-table td { padding: 1mm 2mm 2mm; }
.meta-table th:last-child, .meta-table td:last-child { text-align: right; }
/* Positionen */
.pos-table { width: 100%; table-layout: fixed; border-collapse: collapse; margin-bottom: 5mm; font-size: 7pt; }
.pos-table thead th { background: #f0f0f0; color: #000; padding: 2mm; text-align: right; }
.pos-table thead th.pos-nr, .pos-table thead th.pos-bez, .pos-table thead th.pos-einheit { text-align: left; }
.pos-table tbody tr:nth-child(even) { background: #f8f8f8; }
.pos-table tbody tr:nth-child(even) { background: none; }
.pos-table tbody td { padding: 1.5mm 2mm; border-bottom: 0.3pt solid #e0e0e0; vertical-align: top; }
.pos-heading { font-weight: bold; }
.pos-nr { width: 8%; }
@ -261,7 +276,7 @@ body { font-family: DejaVu Sans, sans-serif; font-size: 7.8pt; color: #000; }
.sum-table .sum-val { text-align: right; padding-right: 0; width: 16%; }
/* Zahlungshinweis */
.payment-note { margin-top: 5mm; font-size: 7pt; padding: 3mm; background: #f8f8f8; border-left: 2pt solid #2563eb; }
.payment-note { margin-top: 5mm; font-size: 7pt; padding: 3mm; background: #f0f4ff; border-left: 2pt solid #2563eb; }
/* Fußzeile */
.footer-table { width: 100%; border-collapse: collapse; font-size: 6pt; border-top: 0.5pt solid #ccc; }

View file

@ -73,39 +73,39 @@ $badgeClass = match($invoice['status']) {
<?php endif; ?>
<!-- Adressbereich (DIN 5008: 50% = 85mm bei vollem A4-Preview) -->
<div class="invoice-address" style="margin-bottom:1.5rem">
<div class="invoice-address" style="margin-top:1cm;margin-bottom:1.5rem">
<div>
<div style="font-size:6pt;color:#666;border-bottom:1px solid #ccc;padding-bottom:2px;margin-bottom:4px">
<div style="font-size:6pt;color:#666;border-bottom:1px solid #ccc;padding-bottom:2px;margin-bottom:12px">
<?= $h($settings['firma'] ?? '') ?> · <?= $h($settings['strasse'] ?? '') ?> · <?= $h(($settings['plz'] ?? '') . ' ' . ($settings['ort'] ?? '')) ?>
</div>
<div style="line-height:1.5">
<div style="line-height:1.5;font-size:10pt">
<?= $h($customerName) ?><br>
<?= $h($invoice['strasse']) ?><br>
<?= $h($invoice['plz']) ?> <?= $h($invoice['ort']) ?>
<?php if ($invoice['land'] !== 'DE'): ?><br><?= $h($invoice['land']) ?><?php endif; ?>
</div>
</div>
<div style="text-align:right">RECHNUNG</div>
<div style="text-align:right;font-size:14pt">Rechnung</div>
</div>
<!-- Meta-Tabelle -->
<table style="width:100%;border-collapse:collapse;margin-bottom:1.5rem;font-size:.7rem">
<table style="width:100%;border-collapse:collapse;margin-top:2cm;margin-bottom:1.5rem;font-size:.7rem">
<thead>
<tr style="background:#f0f0f0">
<th style="padding:.4rem .5rem;text-align:left;border:1px solid #ddd;font-weight:normal;white-space:nowrap">Betreff</th>
<th style="padding:.4rem .5rem;text-align:left;border:1px solid #ddd;font-weight:normal;white-space:nowrap">Rechnungsnummer</th>
<th style="padding:.4rem .5rem;text-align:left;border:1px solid #ddd;font-weight:normal;white-space:nowrap">Kundennummer</th>
<th style="padding:.4rem .5rem;text-align:left;border:1px solid #ddd;font-weight:normal;white-space:nowrap">Leistungszeitraum</th>
<th style="padding:.4rem .5rem;text-align:right;border:1px solid #ddd;font-weight:normal;white-space:nowrap;width:100%">Datum</th>
<tr>
<th style="padding:.4rem .5rem;text-align:left;white-space:nowrap;font-weight:bold">Betreff</th>
<th style="padding:.4rem .5rem;text-align:left;white-space:nowrap;font-weight:bold">Rechnungsnummer</th>
<th style="padding:.4rem .5rem;text-align:left;white-space:nowrap;font-weight:bold">Kundennummer</th>
<th style="padding:.4rem .5rem;text-align:left;white-space:nowrap;font-weight:bold">Leistungszeitraum</th>
<th style="padding:.4rem .5rem;text-align:right;white-space:nowrap;width:100%;font-weight:bold">Datum</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding:.4rem .5rem;border:1px solid #ddd;white-space:nowrap"><?= $h($invoice['betreff']) ?></td>
<td style="padding:.4rem .5rem;border:1px solid #ddd;white-space:nowrap;font-weight:700"><?= $h($invoice['rechnungs_nr'] ?? 'Entwurf') ?></td>
<td style="padding:.4rem .5rem;border:1px solid #ddd;white-space:nowrap"><?= $h($invoice['kundennummer']) ?></td>
<td style="padding:.4rem .5rem;border:1px solid #ddd"><?= $lzHtml ?: '–' ?></td>
<td style="padding:.4rem .5rem;border:1px solid #ddd;white-space:nowrap;text-align:right"><?= $h(View::formatDate($invoice['rechnungs_datum'])) ?></td>
<td style="padding:.4rem .5rem;white-space:nowrap"><?= $h($invoice['betreff']) ?></td>
<td style="padding:.4rem .5rem;white-space:nowrap;font-weight:700"><?= $h($invoice['rechnungs_nr'] ?? 'Entwurf') ?></td>
<td style="padding:.4rem .5rem;white-space:nowrap"><?= $h($invoice['kundennummer']) ?></td>
<td style="padding:.4rem .5rem"><?= $lzHtml ?: '–' ?></td>
<td style="padding:.4rem .5rem;white-space:nowrap;text-align:right"><?= $h(View::formatDate($invoice['rechnungs_datum'])) ?></td>
</tr>
</tbody>
</table>
@ -169,7 +169,7 @@ $badgeClass = match($invoice['status']) {
<div style="border-top:1px solid #ccc;padding-top:.75rem;display:grid;grid-template-columns:1fr 1fr 1fr auto;gap:1rem;font-size:.58rem;color:#555">
<div style="min-width:0">
<strong><?= $h($settings['firma'] ?? '') ?></strong><br>
<?= $h($settings['inhaber'] ?? '') ?><br>
Inh. <?= $h($settings['inhaber'] ?? '') ?><br>
<?= $h($settings['strasse'] ?? '') ?><br>
<?= $h(($settings['plz'] ?? '') . ' ' . ($settings['ort'] ?? '')) ?><br>
USt-ID: <?= $h($settings['ust_id'] ?? '') ?>

BIN
src/fonts/OpenSans-Bold.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1 +1 @@
1-260427
1-260428