refactor: Projektstruktur in app/ und backend/ aufgeteilt

This commit is contained in:
2026-03-24 15:06:44 +01:00
parent 5f5d5995c5
commit 2673ef658d
449 changed files with 28551 additions and 167 deletions

View File

@@ -0,0 +1,464 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rechnung ${invoiceData.invoiceNumber}</title>
<style>
@page {
size: A4;
margin: 2cm 1.5cm 2cm 1.5cm;
}
* {
box-sizing: border-box;
}
body {
font-family: 'Arial', 'Helvetica', sans-serif;
font-size: 11pt;
line-height: 1.4;
color: #333;
margin: 0;
padding: 0;
background: white;
}
.invoice-container {
max-width: 21cm;
margin: 0 auto;
background: white;
padding: 0;
}
/* Header Section */
.header {
display: table;
width: 100%;
margin-bottom: 3em;
border-bottom: 2px solid #2c5aa0;
padding-bottom: 1em;
}
.header-left {
display: table-cell;
width: 60%;
vertical-align: top;
}
.header-right {
display: table-cell;
width: 40%;
vertical-align: top;
text-align: right;
}
.company-logo {
font-size: 24pt;
font-weight: bold;
color: #2c5aa0;
margin-bottom: 0.5em;
}
.company-details {
font-size: 9pt;
color: #666;
line-height: 1.3;
}
.invoice-title {
font-size: 18pt;
font-weight: bold;
color: #2c5aa0;
margin-bottom: 0.3em;
}
.invoice-meta {
font-size: 10pt;
line-height: 1.4;
}
/* Recipient Section */
.recipient-section {
margin-bottom: 2.5em;
}
.sender-short {
font-size: 8pt;
color: #666;
border-bottom: 1px solid #ccc;
padding-bottom: 2pt;
margin-bottom: 1em;
}
.recipient-address {
font-size: 11pt;
line-height: 1.4;
}
.recipient-address .company {
font-weight: bold;
}
/* Invoice Details */
.invoice-details {
display: table;
width: 100%;
margin-bottom: 2em;
font-size: 10pt;
}
.invoice-details-left {
display: table-cell;
width: 50%;
vertical-align: top;
}
.invoice-details-right {
display: table-cell;
width: 50%;
vertical-align: top;
text-align: right;
}
.detail-row {
margin-bottom: 0.3em;
}
.detail-label {
font-weight: bold;
display: inline-block;
width: 120px;
}
/* Items Table */
.items-section {
margin-bottom: 2em;
}
.items-table {
width: 100%;
border-collapse: collapse;
font-size: 10pt;
margin-bottom: 1em;
}
.items-table th {
background-color: #f8f9fa;
border: 1px solid #dee2e6;
padding: 8pt;
text-align: left;
font-weight: bold;
color: #2c5aa0;
}
.items-table td {
border: 1px solid #dee2e6;
padding: 6pt 8pt;
vertical-align: top;
}
.items-table tbody tr:nth-child(even) {
background-color: #f8f9fa;
}
.items-table .qty-col {
width: 10%;
text-align: center;
}
.items-table .desc-col {
width: 50%;
}
.items-table .price-col {
width: 20%;
text-align: right;
}
.items-table .total-col {
width: 20%;
text-align: right;
}
/* Totals Section */
.totals-section {
display: table;
width: 100%;
margin-bottom: 2em;
}
.totals-left {
display: table-cell;
width: 60%;
vertical-align: top;
}
.totals-right {
display: table-cell;
width: 40%;
vertical-align: top;
}
.totals-table {
width: 100%;
font-size: 11pt;
}
.totals-table td {
padding: 4pt 8pt;
border: none;
}
.totals-table .label-col {
text-align: right;
width: 70%;
border-bottom: 1px solid #eee;
}
.totals-table .amount-col {
text-align: right;
width: 30%;
font-weight: bold;
border-bottom: 1px solid #eee;
}
.totals-table .total-row .label-col,
.totals-table .total-row .amount-col {
background-color: #2c5aa0;
color: white;
font-weight: bold;
border: none;
}
/* Payment Section */
.payment-section {
margin-bottom: 2em;
font-size: 10pt;
}
.payment-terms {
background-color: #f8f9fa;
padding: 1em;
border-left: 4px solid #2c5aa0;
margin-bottom: 1em;
}
.bank-details {
display: table;
width: 100%;
}
.bank-details-left {
display: table-cell;
width: 50%;
vertical-align: top;
}
.bank-details-right {
display: table-cell;
width: 50%;
vertical-align: top;
}
/* Legal Footer */
.legal-footer {
border-top: 1px solid #dee2e6;
padding-top: 1em;
font-size: 8pt;
color: #666;
text-align: center;
line-height: 1.3;
}
/* Utility Classes */
.text-right {
text-align: right;
}
.text-center {
text-align: center;
}
.font-bold {
font-weight: bold;
}
.mb-1 {
margin-bottom: 0.5em;
}
.mb-2 {
margin-bottom: 1em;
}
/* Print Styles */
@media print {
body {
font-size: 10pt;
}
.invoice-container {
max-width: none;
margin: 0;
padding: 0;
}
.header {
page-break-after: avoid;
}
.items-table {
page-break-inside: avoid;
}
.totals-section {
page-break-inside: avoid;
}
}
</style>
</head>
<body>
<div class="invoice-container">
<!-- Header Section -->
<div class="header">
<div class="header-left">
<div class="company-logo">${invoiceData.senderName}</div>
<div class="company-details">
${invoiceData.senderAddress}<br>
${invoiceData.senderPostcode} ${invoiceData.senderCity}<br>
${invoiceData.senderCountry}<br>
<br>
Tel: ${invoiceData.senderPhone}<br>
E-Mail: ${invoiceData.senderEmail}<br>
Web: ${invoiceData.senderWebsite}<br>
<br>
Steuernr.: ${invoiceData.senderTaxNumber}<br>
USt-IdNr.: ${invoiceData.senderVatId}
</div>
</div>
<div class="header-right">
<div class="invoice-title">RECHNUNG</div>
<div class="invoice-meta">
<strong>Nr. ${invoiceData.invoiceNumber}</strong><br>
vom ${invoiceData.invoiceDate}
</div>
</div>
</div>
<!-- Recipient Section -->
<div class="recipient-section">
<div class="sender-short">
${invoiceData.senderName} · ${invoiceData.senderAddress} · ${invoiceData.senderPostcode} ${invoiceData.senderCity}
</div>
<div class="recipient-address">
<div class="company">${invoiceData.recipientCompany}</div>
<div>${invoiceData.recipientName}</div>
<div>${invoiceData.recipientAddress}</div>
<div>${invoiceData.recipientPostcode} ${invoiceData.recipientCity}</div>
<div>${invoiceData.recipientCountry}</div>
</div>
</div>
<!-- Invoice Details -->
<div class="invoice-details">
<div class="invoice-details-left">
<div class="detail-row">
<span class="detail-label">Rechnungsdatum:</span>
${invoiceData.invoiceDate}
</div>
<div class="detail-row">
<span class="detail-label">Leistungsdatum:</span>
${invoiceData.deliveryDate}
</div>
<div class="detail-row">
<span class="detail-label">Kundennummer:</span>
${invoiceData.recipientVatId}
</div>
</div>
<div class="invoice-details-right">
<div class="detail-row">
<span class="detail-label">Fälligkeitsdatum:</span>
${invoiceData.paymentDueDate}
</div>
<div class="detail-row">
<span class="detail-label">Zahlungsziel:</span>
14 Tage netto
</div>
</div>
</div>
<!-- Description -->
<div class="mb-2">
<strong>Leistungsbeschreibung:</strong><br>
${invoiceData.description}
</div>
<!-- Items Table -->
<div class="items-section">
<table class="items-table">
<thead>
<tr>
<th class="qty-col">Menge</th>
<th class="desc-col">Beschreibung</th>
<th class="price-col">Einzelpreis<br>(netto)</th>
<th class="total-col">Gesamtpreis<br>(netto)</th>
</tr>
</thead>
<tbody>
<!-- ITEM_ROWS -->
</tbody>
</table>
</div>
<!-- Totals Section -->
<div class="totals-section">
<div class="totals-left">
<!-- Space for additional notes if needed -->
</div>
<div class="totals-right">
<table class="totals-table">
<tr>
<td class="label-col">Nettobetrag:</td>
<td class="amount-col">${invoiceData.netAmount}</td>
</tr>
<tr class="total-row">
<td class="label-col">Rechnungsbetrag:</td>
<td class="amount-col">${invoiceData.totalAmount}</td>
</tr>
</table>
</div>
</div>
<!-- Payment Section -->
<div class="payment-section">
<div class="payment-terms">
<strong>Zahlungsbedingungen:</strong><br>
${invoiceData.paymentTerms}
Fälligkeitsdatum: ${invoiceData.paymentDueDate}
</div>
<div class="bank-details">
<div class="bank-details-left">
<strong>Bankverbindung:</strong><br>
${invoiceData.bankAccount}<br>
IBAN: ${invoiceData.iban}<br>
BIC: ${invoiceData.bic}
</div>
<div class="bank-details-right">
<strong>Verwendungszweck:</strong><br>
Rechnung ${invoiceData.invoiceNumber}
</div>
</div>
</div>
<!-- Legal Footer -->
<div class="legal-footer">
${invoiceData.legalNotes}<br>
<br>
Vielen Dank für Ihr Vertrauen!<br>
Bei Fragen zu dieser Rechnung wenden Sie sich bitte an: ${invoiceData.senderEmail}
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,187 @@
{
"elements": [
{
"id": "demo-title",
"type": "header",
"text": "Rechnung",
"xPercent": "7.56",
"yPercent": "6.53",
"widthPercent": "28.07",
"heightPercent": "4.04",
"fontSize": 24,
"fontStyle": "bold",
"color": "#111111"
},
{
"id": "demo-number-label",
"type": "text",
"text": "Rechnungsnr.",
"xPercent": "67.06",
"yPercent": "7.48",
"widthPercent": "17.98",
"heightPercent": "2.97",
"fontSize": 11,
"fontStyle": "bold",
"color": "#111111"
},
{
"id": "demo-number-value",
"type": "text",
"text": "000000",
"xPercent": "84.03",
"yPercent": "7.48",
"widthPercent": "10.08",
"heightPercent": "2.97",
"fontSize": 11,
"fontStyle": "normal",
"color": "#111111",
"isStatic": true,
"variable": "invoice.number"
},
{
"id": "demo-date-label",
"type": "text",
"text": "Datum",
"xPercent": "67.06",
"yPercent": "11.52",
"widthPercent": "17.98",
"heightPercent": "2.97",
"fontSize": 11,
"fontStyle": "bold",
"color": "#111111"
},
{
"id": "demo-date-value",
"type": "text",
"text": "2026-01-01",
"xPercent": "84.03",
"yPercent": "11.52",
"widthPercent": "10.08",
"heightPercent": "2.97",
"fontSize": 11,
"fontStyle": "normal",
"color": "#111111",
"isStatic": true,
"variable": "invoice.date"
},
{
"id": "demo-sender",
"type": "text",
"text": null,
"xPercent": "7.56",
"yPercent": "16.51",
"widthPercent": "30.08",
"heightPercent": "2.97",
"fontSize": 12,
"fontStyle": "bold",
"color": "#111111",
"isStatic": true,
"variable": "masterdata.contact_name"
},
{
"id": "demo-customer",
"type": "customer",
"text": "Kundenname\nStraße Nr.\nPLZ Ort",
"xPercent": "7.56",
"yPercent": "25.06",
"widthPercent": "33.95",
"heightPercent": "12.00",
"fontSize": 12,
"fontStyle": "normal",
"color": "#111111"
},
{
"id": "demo-services",
"type": "text",
"text": "Leistungen",
"xPercent": "7.56",
"yPercent": "42.04",
"widthPercent": "85.04",
"heightPercent": "28.03",
"fontSize": 11,
"fontStyle": "normal",
"color": "#111111",
"isStatic": true,
"variable": "services.list"
},
{
"id": "demo-net-label",
"type": "text",
"text": "Netto",
"xPercent": "67.06",
"yPercent": "73.99",
"widthPercent": "11.93",
"heightPercent": "2.97",
"fontSize": 11,
"fontStyle": "bold",
"color": "#111111"
},
{
"id": "demo-net-value",
"type": "text",
"text": "0,00 €",
"xPercent": "80.00",
"yPercent": "73.99",
"widthPercent": "13.95",
"heightPercent": "2.97",
"fontSize": 11,
"fontStyle": "normal",
"color": "#111111",
"isStatic": true,
"variable": "invoice.net_total"
},
{
"id": "demo-total-label",
"type": "text",
"text": "Gesamt",
"xPercent": "67.06",
"yPercent": "78.98",
"widthPercent": "11.93",
"heightPercent": "3.44",
"fontSize": 13,
"fontStyle": "bold",
"color": "#111111"
},
{
"id": "demo-total-value",
"type": "text",
"text": "0,00 €",
"xPercent": "80.00",
"yPercent": "78.98",
"widthPercent": "13.95",
"heightPercent": "3.44",
"fontSize": 13,
"fontStyle": "bold",
"color": "#111111",
"isStatic": true,
"variable": "invoice.gross_total"
},
{
"id": "demo-template-note",
"type": "text",
"text": "Hinweis: Dieses Rechnungstemplate kann vom Benutzer ",
"xPercent": "0.00",
"yPercent": "20.78",
"widthPercent": "100.00",
"heightPercent": "4.51",
"fontSize": 20,
"fontStyle": "normal",
"textAlign": "center",
"color": "#555555"
},
{
"id": "element-1",
"type": "text",
"text": "frei angepasst werden.",
"xPercent": "31.93",
"yPercent": "24.94",
"widthPercent": "25.21",
"heightPercent": "3.56",
"fontSize": 20,
"color": "#333333",
"isStatic": false,
"isCustomer": false,
"variable": null
}
]
}

View File

@@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Rechnung VOTIAN-LT</title>
<style>
@page { size: A4; margin: 0; }
html, body { margin: 0; padding: 0; width: 21cm; height: 29.7cm; }
body {
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 2cm;
border: 2px solid #1b12b9;
font-family: Arial, sans-serif;
font-size: 12pt;
position: relative;
}
main { flex: 1 0 auto; }
h1, h2 { color: #1b12b9; text-align: center; margin: 0; }
table { width: 100%; border-collapse: collapse; margin-top: 1em; }
th, td { padding: 0.3em; text-align: right; border-top: 1px solid #ddd; vertical-align: top; }
th:first-child, td:first-child { text-align: left; }
.total-row { font-weight: bold; background: #e6e6e6; }
/* Footer exakt 5cm über dem unteren Rand */
.footer-section {
position: absolute;
bottom: 0cm; /* Abstand von unten */
left: 2cm; /* gleiche Einrückung wie body-padding */
right: 2cm;
}
.footer { font-size: 10pt; text-align: center; margin-top: 1em; }
</style>
</head>
<body>
<main>
<h1>Assecutor</h1>
<h2>Data Service GmbH1111</h2>
<p><strong>Empfänger:</strong><br>
Hamburger Hochbahasdfasdasn AG<br>
Kreditorenbuchhaltung<br>
Steinstraße 20<br>
20095 Hamburg
</p>
<p><strong>Absender:</strong><br>
Assecutor Data Service GmbH<br>
Gerhart-Hauptmann-Weg 14, 21502 Geesthacht<br>
Tel.: 040-181237710 · www.assecutor.de
</p>
<p><strong>Datum:</strong> 19.07.2021</p>
<h2>Rechnung HHA-2021-07</h2>
<p>Gemäß unserem Nutzungsvertrag zu der Bestellnummer <strong>45519389</strong>
berechnen wir Ihnen für den Monat Juli 2021 wie folgt:</p>
<table>
<tr>
<th>Menge</th><th>Bezeichnung</th><th>Einzelpreis</th><th>Gesamt</th>
</tr>
<tr>
<td>1</td>
<td style="text-align:left">
Mtl. Lizenzgebühr »ILLT«
</td>
<td>5.639,00 €</td>
<td>5.639,00 €</td>
</tr>
<tr class="total-row">
<td></td><td style="text-align:left">Nettobetrag</td><td></td><td>5.639,00 €</td>
</tr>
<tr>
<td></td><td style="text-align:left">+ 19% USt.</td><td></td><td>1.071,41 €</td>
</tr>
<tr class="total-row">
<td></td><td style="text-align:left">Endbetrag</td><td></td><td>6.710,41 €</td>
</tr>
</table>
</main>
<div class="footer-section">
<p><strong>Zahlungsbedingungen:</strong> Gesamtbetrag bis spätestens zum 10. Werktag nach Rechnungserhalt auf unser Konto.</p>
<br>
<p class="footer">
Geschäftsführer: Carsten Annacker, Gunnar Timm · Steuernummer: 22 294 53099 · USt-IdNr.: DE261094748<br>
Sitz: Geesthacht · Handelsregister: Lübeck HRB 8595<br>
Bankverbindung: Hamburger Sparkasse · IBAN DE67200505501217139888 · BIC HASPDEHHXXX
</p>
</div>
</body>
</html>