diff --git a/src/main/bundles/dev.bundle b/src/main/bundles/dev.bundle
index fbb4a31..f28ff6a 100644
Binary files a/src/main/bundles/dev.bundle and b/src/main/bundles/dev.bundle differ
diff --git a/src/main/frontend/invoice-generator/invoice-generator.js b/src/main/frontend/invoice-generator/invoice-generator.js
index bb65bd3..246a0b6 100644
--- a/src/main/frontend/invoice-generator/invoice-generator.js
+++ b/src/main/frontend/invoice-generator/invoice-generator.js
@@ -449,6 +449,15 @@
ctx.lineTo(el.x + (el.width || 200), el.y);
ctx.stroke();
break;
+
+ case 'vline':
+ ctx.strokeStyle = el.color || '#333333';
+ ctx.lineWidth = el.strokeWidth || 1;
+ ctx.beginPath();
+ ctx.moveTo(el.x, el.y);
+ ctx.lineTo(el.x, el.y + (el.height || 200));
+ ctx.stroke();
+ break;
case 'image':
if (el.imageData) {
@@ -699,6 +708,11 @@
el.width = 200;
el.height = 2;
break;
+ case 'vline':
+ el.text = '';
+ el.width = 2;
+ el.height = 200;
+ break;
case 'image':
el.text = 'Bild';
el.width = 100;
diff --git a/src/main/frontend/invoice-generator/profile-invoice-generator.js b/src/main/frontend/invoice-generator/profile-invoice-generator.js
index d80570f..da92ec6 100644
--- a/src/main/frontend/invoice-generator/profile-invoice-generator.js
+++ b/src/main/frontend/invoice-generator/profile-invoice-generator.js
@@ -265,7 +265,9 @@ window.initProfileInvoiceGenerator = function() {
// Always use black text for static elements, otherwise use element color
ctx.fillStyle = el.isStatic ? '#000000' : (el.color || '#333333');
- ctx.font = (el.fontStyle || '') + ' ' + fontSize + 'px Arial';
+ // Masterdata elements are never bold; other elements respect their fontStyle
+ var fontWeight = (el.isStatic && !el.isCustomer) ? '' : (el.fontStyle || '');
+ ctx.font = (fontWeight ? fontWeight + ' ' : '') + fontSize + 'px Arial';
ctx.textBaseline = 'top';
lines.forEach(function(line) {
@@ -1108,6 +1110,17 @@ window.initProfileInvoiceGenerator = function() {
};
};
+ window.updateProfileMasterdataValue = function(key, value) {
+ if (!window.masterdataValues) window.masterdataValues = {};
+ window.masterdataValues[key] = value;
+ elements.forEach(function(el) {
+ if (el.variable === key) {
+ el.text = value;
+ }
+ });
+ draw();
+ };
+
draw();
window.profileInvoiceState.initialized = true;
console.log('Profile canvas initialized with ' + elements.length + ' elements');
diff --git a/src/main/java/de/assecutor/votianlt/pages/view/EditProfileView.java b/src/main/java/de/assecutor/votianlt/pages/view/EditProfileView.java
index d52df74..6ae9c57 100644
--- a/src/main/java/de/assecutor/votianlt/pages/view/EditProfileView.java
+++ b/src/main/java/de/assecutor/votianlt/pages/view/EditProfileView.java
@@ -327,6 +327,20 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
billingEnabled.setValue(true); // Standardmäßig aktiviert
billingTab.add(billingEnabled);
+ prefixField.setLabel(getTranslation("profile.billing.prefix"));
+ prefixField.setPlaceholder("z.B. RE-2024-");
+ prefixField.setMaxWidth("300px");
+ prefixField.setVisible(true);
+ prefixField.addBlurListener(e -> {
+ saveInvoiceData();
+ String p = prefixField.getValue();
+ String invNr = (p != null && !p.isBlank() ? p : "") + "12345";
+ getElement().executeJs(
+ "if (window.updateProfileMasterdataValue) { window.updateProfileMasterdataValue('masterdata.invoice_number', '"
+ + invNr.replace("'", "\\'") + "'); }");
+ });
+ billingTab.add(prefixField);
+
// Hauptlayout: Links (Templates) | Mitte (Canvas) | Rechts (Eigenschaften)
final HorizontalLayout mainLayout = new HorizontalLayout();
mainLayout.setWidthFull();
@@ -384,13 +398,6 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
actionLayout.setSpacing(true);
actionLayout.getStyle().set("margin-top", "var(--lumo-space-s)");
- Button clearButton = new Button(getTranslation("button.clear"), new Icon(VaadinIcon.TRASH));
- clearButton.addThemeVariants(ButtonVariant.LUMO_ERROR, ButtonVariant.LUMO_TERTIARY);
- clearButton.addClickListener(e -> {
- getElement().executeJs("if (window.clearProfileCanvas) { window.clearProfileCanvas(); }");
- Notification.show(getTranslation("profile.canvas.cleared"), 2000, Notification.Position.BOTTOM_CENTER);
- });
-
Button previewPdfButton = new Button(getTranslation("button.preview"), new Icon(VaadinIcon.EYE));
previewPdfButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
previewPdfButton.addClickListener(e -> generatePreviewPdfFromProfile());
@@ -424,7 +431,7 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
});
});
- actionLayout.add(clearButton, previewPdfButton, saveTemplateButton);
+ actionLayout.add(previewPdfButton, saveTemplateButton);
billingTab.add(actionLayout);
// Initialen Zustand setzen (sichtbar da checkbox standardmäßig true)
@@ -435,6 +442,7 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
// Sichtbarkeit des Invoice Generators an Checkbox binden
billingEnabled.addValueChangeListener(e -> {
boolean visible = e.getValue();
+ prefixField.setVisible(visible);
mainLayout.setVisible(visible);
actionLayout.setVisible(visible);
});
@@ -866,7 +874,7 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
templateData = result.toString();
}
byte[] pdfBytes = customerInvoiceService.generatePdfFromCanvasTemplate(templateData,
- currentUser);
+ currentUser, prefixField.getValue());
showPdfInDialog(pdfBytes);
} catch (Exception ex) {
Notification.show(getTranslation("profile.pdf.preview.error", ex.getMessage()), 3000,
@@ -958,6 +966,8 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
"masterdata.email", email.isEmpty() ? getTranslation("profile.invoice.placeholder.email") : email);
Div senderPhone = createVariableTemplate(getTranslation("profile.invoice.phone"), VaadinIcon.PHONE,
"masterdata.phone", phone.isEmpty() ? getTranslation("profile.invoice.placeholder.phone") : phone);
+ Div invoiceNumber = createVariableTemplate(getTranslation("profile.invoice.element.invoicenumber"),
+ VaadinIcon.HASH, "masterdata.invoice_number", "RE-2024-0001");
// Bereich 2: Leistungen
Span servicesHeader = new Span(getTranslation("profile.services.label"));
@@ -1017,7 +1027,7 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
"image");
panel.add(invoiceHeader, senderCompany, senderName, senderAddress, senderCity, senderEmail, senderPhone,
- servicesHeader, servicesListBlock, servicesNetBlock, servicesVatBlock, servicesGrossBlock,
+ invoiceNumber, servicesHeader, servicesListBlock, servicesNetBlock, servicesVatBlock, servicesGrossBlock,
customerHeader, customerCompany, customerName, customerAddress, customerCity, customerEmail,
customerPhone, freeHeader, textBlock, headerBlock, dateBlock, customerBlock, companyBlock, amountBlock,
lineBlock, imageBlock);
@@ -1422,11 +1432,14 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
String city = safe(currentUser.getZip()) + " " + safe(currentUser.getCity());
String email = safe(currentUser.getEmail());
String phone = safe(currentUser.getPhone());
+ String prefix = prefixField.getValue();
+ String invoiceNumber = (prefix != null && !prefix.isBlank() ? prefix : "") + "12345";
String masterdataJson = "{" + "'masterdata.company_name': '" + company.replace("'", "\\'") + "',"
+ "'masterdata.contact_name': '" + fullName.replace("'", "\\'") + "',"
+ "'masterdata.street': '" + street.replace("'", "\\'") + "'," + "'masterdata.city': '"
+ city.replace("'", "\\'") + "'," + "'masterdata.email': '" + email.replace("'", "\\'")
- + "'," + "'masterdata.phone': '" + phone.replace("'", "\\'") + "'" + "}";
+ + "'," + "'masterdata.phone': '" + phone.replace("'", "\\'") + "',"
+ + "'masterdata.invoice_number': '" + invoiceNumber.replace("'", "\\'") + "'" + "}";
getElement().executeJs("setTimeout(function() { "
+ " if (window.loadProfileTemplate && document.getElementById('invoice-canvas-container-profile')) { "
+ " console.log('Loading template into canvas...'); " + " window.masterdataValues = "
diff --git a/src/main/java/de/assecutor/votianlt/pages/view/InvoiceGeneratorView.java b/src/main/java/de/assecutor/votianlt/pages/view/InvoiceGeneratorView.java
index dc85d32..0d4ed94 100644
--- a/src/main/java/de/assecutor/votianlt/pages/view/InvoiceGeneratorView.java
+++ b/src/main/java/de/assecutor/votianlt/pages/view/InvoiceGeneratorView.java
@@ -123,11 +123,13 @@ public class InvoiceGeneratorView extends VerticalLayout implements HasDynamicTi
VaadinIcon.COIN_PILES, "amount");
Div lineBlock = createDraggableTemplate(getTranslation("invoicegenerator.template.line"), VaadinIcon.LINE_V,
"line");
+ Div vlineBlock = createDraggableTemplate(getTranslation("invoicegenerator.template.vline"),
+ VaadinIcon.LINE_BAR_CHART, "vline");
Div imageBlock = createDraggableTemplate(getTranslation("invoicegenerator.template.image"), VaadinIcon.PICTURE,
"image");
panel.add(header, textBlock, headerBlock, dateBlock, customerBlock, companyBlock, amountBlock, lineBlock,
- imageBlock);
+ vlineBlock, imageBlock);
return panel;
}
@@ -409,7 +411,7 @@ public class InvoiceGeneratorView extends VerticalLayout implements HasDynamicTi
}
// Text Feld (nur für Text-Elemente)
- if (!"line".equals(elementType) && !"image".equals(elementType)) {
+ if (!"line".equals(elementType) && !"vline".equals(elementType) && !"image".equals(elementType)) {
TextField textField = new TextField("Text");
textField.setValue(text != null ? text : "");
textField.setWidthFull();
@@ -451,7 +453,7 @@ public class InvoiceGeneratorView extends VerticalLayout implements HasDynamicTi
propertiesPanel.add(yField);
// Font Size (nur für Text-Elemente)
- if (!"line".equals(elementType) && !"image".equals(elementType)) {
+ if (!"line".equals(elementType) && !"vline".equals(elementType) && !"image".equals(elementType)) {
TextField fontSizeField = new TextField(getTranslation("invoicegenerator.fontsize.label"));
fontSizeField.setValue(fontSize != null ? String.valueOf(fontSize) : "16");
fontSizeField.setWidthFull();
diff --git a/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java b/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java
index 076c219..466153b 100644
--- a/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java
+++ b/src/main/java/de/assecutor/votianlt/service/CustomerInvoiceService.java
@@ -248,11 +248,17 @@ public class CustomerInvoiceService {
* representation of the canvas elements and converts it to PDF.
*/
public byte[] generatePdfFromCanvasTemplate(String jsonTemplateData) throws Exception {
- return generatePdfFromCanvasTemplate(jsonTemplateData, null);
+ return generatePdfFromCanvasTemplate(jsonTemplateData, null, null);
}
public byte[] generatePdfFromCanvasTemplate(String jsonTemplateData, de.assecutor.votianlt.model.User user)
throws Exception {
+ return generatePdfFromCanvasTemplate(jsonTemplateData, user, null);
+ }
+
+ public byte[] generatePdfFromCanvasTemplate(String jsonTemplateData, de.assecutor.votianlt.model.User user,
+ String invoicePrefix)
+ throws Exception {
// Parse the JSON template data
com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
com.fasterxml.jackson.databind.JsonNode rootNode = mapper.readTree(jsonTemplateData);
@@ -287,6 +293,8 @@ public class CustomerInvoiceService {
variables.put("masterdata.city", safe(user.getZip()) + " " + safe(user.getCity()));
variables.put("masterdata.email", safe(user.getEmail()));
variables.put("masterdata.phone", safe(user.getPhone()));
+ variables.put("masterdata.invoice_number",
+ (invoicePrefix != null && !invoicePrefix.isBlank() ? invoicePrefix : "") + "12345");
} else {
// Default values for preview without user
variables.put("masterdata.company_name", "Meine Firma GmbH");
@@ -295,6 +303,8 @@ public class CustomerInvoiceService {
variables.put("masterdata.city", "12345 Musterstadt");
variables.put("masterdata.email", "kontakt@firma.de");
variables.put("masterdata.phone", "0123 456789");
+ variables.put("masterdata.invoice_number",
+ (invoicePrefix != null && !invoicePrefix.isBlank() ? invoicePrefix : "") + "12345");
}
// Customer data (placeholder for now - would come from job/customer selection)
@@ -348,7 +358,6 @@ public class CustomerInvoiceService {
}
int fontSize = element.has("fontSize") ? element.get("fontSize").asInt(14) : 14;
- String fontStyle = element.has("fontStyle") ? element.get("fontStyle").asText("") : "";
String color = element.has("color") ? element.get("color").asText("#333333") : "#333333";
// Convert percentages to mm (A4 is 210mm x 297mm)
@@ -361,23 +370,27 @@ public class CustomerInvoiceService {
htmlBuilder.append("style='");
htmlBuilder.append("left:").append(String.format(java.util.Locale.US, "%.2f", mmX)).append("mm;");
htmlBuilder.append("top:").append(String.format(java.util.Locale.US, "%.2f", mmY)).append("mm;");
- htmlBuilder.append("width:").append(String.format(java.util.Locale.US, "%.2f", mmWidth)).append("mm;");
- htmlBuilder.append("height:").append(String.format(java.util.Locale.US, "%.2f", mmHeight))
- .append("mm;");
- htmlBuilder.append("font-size:").append(fontSize).append("pt;");
- htmlBuilder.append("line-height:").append(String.format(java.util.Locale.US, "%.2f", fontSize * 1.2))
- .append("pt;");
- htmlBuilder.append("color:").append(color).append(";");
- if (!fontStyle.isEmpty()) {
- if (fontStyle.contains("bold"))
- htmlBuilder.append("font-weight:bold;");
- }
- // For services.list use block display to allow table to fill width
- if ("services.list".equals(variable)) {
- htmlBuilder.append("display:block;overflow:visible;padding:0;");
+ if ("line".equals(type)) {
+ htmlBuilder.append("width:").append(String.format(java.util.Locale.US, "%.2f", mmWidth)).append("mm;");
+ htmlBuilder.append("height:0;border-top:1px solid #333;");
+ } else if ("vline".equals(type)) {
+ htmlBuilder.append("width:0;border-left:1px solid #333;");
+ htmlBuilder.append("height:").append(String.format(java.util.Locale.US, "%.2f", mmHeight)).append("mm;");
} else {
- // Vertically center content for other elements
- htmlBuilder.append("display:flex;align-items:center;");
+ htmlBuilder.append("width:").append(String.format(java.util.Locale.US, "%.2f", mmWidth)).append("mm;");
+ htmlBuilder.append("height:").append(String.format(java.util.Locale.US, "%.2f", mmHeight))
+ .append("mm;");
+ htmlBuilder.append("font-size:").append(fontSize).append("pt;");
+ htmlBuilder.append("line-height:").append(String.format(java.util.Locale.US, "%.2f", fontSize * 1.2))
+ .append("pt;");
+ htmlBuilder.append("color:").append(color).append(";");
+ // For services.list use block display to allow table to fill width
+ if ("services.list".equals(variable)) {
+ htmlBuilder.append("display:block;overflow:visible;padding:0;");
+ } else {
+ // Vertically center content for other elements
+ htmlBuilder.append("display:flex;align-items:center;");
+ }
}
htmlBuilder.append("'");
htmlBuilder.append(">");
@@ -406,14 +419,13 @@ public class CustomerInvoiceService {
if (text != null) {
text = text.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """)
.replace("'", "'");
+ // Convert newlines to
for multi-line elements (e.g. customer address)
+ text = text.replace("\n", "
");
} else {
text = "";
}
- if ("line".equals(type)) {
- htmlBuilder.append(
- "
");
- } else if ("image".equals(type)) {
+ if ("image".equals(type)) {
if (element.has("imageData") && !element.get("imageData").asText().isEmpty()) {
String imageData = element.get("imageData").asText();
// Ensure proper data URL format
@@ -433,6 +445,9 @@ public class CustomerInvoiceService {
} else if ("services.list".equals(variable)) {
// Render services list as a table
htmlBuilder.append(generateServicesTableHtml(mmWidth));
+ } else if (text.contains("
")) {
+ // Multi-line text: render without nowrap so
tags work
+ htmlBuilder.append("").append(text).append("");
} else {
// Wrap text in a span to prevent flexbox issues
htmlBuilder.append("").append(text).append("");
@@ -640,7 +655,6 @@ public class CustomerInvoiceService {
}
int fontSize = element.has("fontSize") ? element.get("fontSize").asInt(14) : 14;
- String fontStyle = element.has("fontStyle") ? element.get("fontStyle").asText("") : "";
String color = element.has("color") ? element.get("color").asText("#333333") : "#333333";
// Convert percentages to mm (A4 is 210mm x 297mm)
@@ -653,22 +667,26 @@ public class CustomerInvoiceService {
htmlBuilder.append("style='");
htmlBuilder.append("left:").append(String.format(java.util.Locale.US, "%.2f", mmX)).append("mm;");
htmlBuilder.append("top:").append(String.format(java.util.Locale.US, "%.2f", mmY)).append("mm;");
- htmlBuilder.append("width:").append(String.format(java.util.Locale.US, "%.2f", mmWidth)).append("mm;");
- htmlBuilder.append("height:").append(String.format(java.util.Locale.US, "%.2f", mmHeight))
- .append("mm;");
- htmlBuilder.append("font-size:").append(fontSize).append("pt;");
- htmlBuilder.append("line-height:").append(String.format(java.util.Locale.US, "%.2f", fontSize * 1.2))
- .append("pt;");
- htmlBuilder.append("color:").append(color).append(";");
- if (!fontStyle.isEmpty()) {
- if (fontStyle.contains("bold"))
- htmlBuilder.append("font-weight:bold;");
- }
- // For services.list use block display
- if ("services.list".equals(variable)) {
- htmlBuilder.append("display:block;overflow:visible;padding:0;");
+ if ("line".equals(type)) {
+ htmlBuilder.append("width:").append(String.format(java.util.Locale.US, "%.2f", mmWidth)).append("mm;");
+ htmlBuilder.append("height:0;border-top:1px solid #333;");
+ } else if ("vline".equals(type)) {
+ htmlBuilder.append("width:0;border-left:1px solid #333;");
+ htmlBuilder.append("height:").append(String.format(java.util.Locale.US, "%.2f", mmHeight)).append("mm;");
} else {
- htmlBuilder.append("display:flex;align-items:center;");
+ htmlBuilder.append("width:").append(String.format(java.util.Locale.US, "%.2f", mmWidth)).append("mm;");
+ htmlBuilder.append("height:").append(String.format(java.util.Locale.US, "%.2f", mmHeight))
+ .append("mm;");
+ htmlBuilder.append("font-size:").append(fontSize).append("pt;");
+ htmlBuilder.append("line-height:").append(String.format(java.util.Locale.US, "%.2f", fontSize * 1.2))
+ .append("pt;");
+ htmlBuilder.append("color:").append(color).append(";");
+ // For services.list use block display
+ if ("services.list".equals(variable)) {
+ htmlBuilder.append("display:block;overflow:visible;padding:0;");
+ } else {
+ htmlBuilder.append("display:flex;align-items:center;");
+ }
}
htmlBuilder.append("'");
htmlBuilder.append(">");
@@ -695,14 +713,13 @@ public class CustomerInvoiceService {
if (text != null) {
text = text.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """)
.replace("'", "'");
+ // Convert newlines to
for multi-line elements (e.g. customer address)
+ text = text.replace("\n", "
");
} else {
text = "";
}
- if ("line".equals(type)) {
- htmlBuilder.append(
- "
");
- } else if ("image".equals(type)) {
+ if ("image".equals(type)) {
if (element.has("imageData") && !element.get("imageData").asText().isEmpty()) {
String imageData = element.get("imageData").asText();
if (!imageData.startsWith("data:")) {
@@ -720,6 +737,9 @@ public class CustomerInvoiceService {
} else if ("services.list".equals(variable)) {
// Render services list as a table with actual data
htmlBuilder.append(generateServicesTableHtmlWithData(mmWidth, variables));
+ } else if (text.contains("
")) {
+ // Multi-line text: render without nowrap so
tags work
+ htmlBuilder.append("").append(text).append("");
} else {
htmlBuilder.append("").append(text).append("");
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 3b9d1d9..1874462 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -6,6 +6,7 @@ spring.profiles.active=dev
# Logging configuration
logging.level.org.atmosphere=warn
+logging.level.com.vaadin.flow.server.communication.PushAtmosphereHandler=off
logging.level.de.assecutor.votianlt=INFO
logging.level.de.assecutor.votianlt.controller.MessageController=DEBUG
logging.level.de.assecutor.votianlt.config.MongoConfig=DEBUG
diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties
index 7615ff3..309bff2 100644
--- a/src/main/resources/messages.properties
+++ b/src/main/resources/messages.properties
@@ -36,8 +36,14 @@ profile.basicdata=Stammdaten
profile.map=Karte
profile.invoicecreation=Rechnungserstellung
profile.settings=Einstellungen
+profile.settings.digitalprocess=Digitale Abwicklung
+profile.settings.digitalprocess.info=Aufträge werden digital über die App abgewickelt
+profile.settings.locateappuser=App-Nutzer orten
+profile.settings.locateappuser.info=Standort der App-Nutzer wird regelmäßig übertragen
profile.account=Konto
profile.security=Sicherheit
+profile.security.twofactor=Zwei-Faktor-Authentifizierung
+profile.security.twofactor.info=Beim Anmelden wird ein zusätzlicher Code per E-Mail versendet
profile.services=Leistungskatalog
profile.saved=Profil gespeichert
profile.save.error=Fehler beim Speichern: {0}
@@ -53,6 +59,7 @@ settings.twofactorinfo=Bei Aktivierung wird bei jeder Anmeldung ein Code per E-M
# Profile Billing
profile.billing.enabled=Rechnungslegung über votianLT
+profile.billing.prefix=Rechnungspräfix
# Profile Validation
profile.validation.company=Firma ist ein Pflichtfeld
@@ -106,6 +113,7 @@ profile.invoice.element.company=Firmeninfo
profile.invoice.element.amount=Betrag
profile.invoice.element.line=Linie
profile.invoice.element.image=Bild
+profile.invoice.element.invoicenumber=Rechnungsnummer
profile.invoice.properties=Eigenschaften
profile.invoice.properties.info=Klicken Sie auf ein Element im Canvas, um dessen Eigenschaften zu bearbeiten.
profile.invoice.type=Typ
@@ -655,6 +663,21 @@ myinvoices.bank.iban=IBAN
myinvoices.recipient.name=Kunde
myinvoices.recipient.department=
myinvoices.item.description=Position: {0}
+myinvoices.card.open=Offene Rechnungen
+myinvoices.card.bank=Bankverbindung
+myinvoices.bank.reference=Verwendungszweck
+myinvoices.section.title=Alle Rechnungen
+myinvoices.filter.pagesize=Einträge pro Seite
+myinvoices.filter.search=Suche
+myinvoices.filter.search.placeholder=Rechnungsnummer suchen...
+myinvoices.column.status=Status
+myinvoices.column.number=Nummer
+myinvoices.column.date=Datum
+myinvoices.column.amount=Betrag
+myinvoices.empty.title=Keine Rechnungen
+myinvoices.empty.desc=Es wurden keine Rechnungen gefunden.
+myinvoices.button.prev=Zurück
+myinvoices.button.next=Weiter
# App User
appuser.title=App-Nutzer
@@ -811,6 +834,7 @@ invoicegenerator.upload.success=Bild erfolgreich hochgeladen
invoicegenerator.upload.error=Fehler beim Hochladen: {0}
invoicegenerator.file.rejected=Datei abgelehnt: {0}
invoicegenerator.properties.select.info=Klicken Sie auf ein Element im Canvas, um dessen Eigenschaften zu bearbeiten.
+invoicegenerator.template.vline=Vertikale Linie
# CSV Export
csv.header.customer=Auftraggeber
diff --git a/src/main/resources/messages_ee.properties b/src/main/resources/messages_ee.properties
index 26725d1..2530779 100644
--- a/src/main/resources/messages_ee.properties
+++ b/src/main/resources/messages_ee.properties
@@ -36,8 +36,14 @@ profile.basicdata=Põhiandmed
profile.map=Kaart
profile.invoicecreation=Arve loomine
profile.settings=Seaded
+profile.settings.digitalprocess=Digitaalne töötlus
+profile.settings.digitalprocess.info=Tellimused töödeldakse rakenduse kaudu digitaalselt
+profile.settings.locateappuser=Leia rakenduse kasutaja
+profile.settings.locateappuser.info=Rakenduse kasutajate asukoht edastatakse regulaarselt
profile.account=Konto
profile.security=Turvalisus
+profile.security.twofactor=Kahefaktoriline autentimine
+profile.security.twofactor.info=Sisselogimisel saadetakse e-postiga täiendav kood
profile.services=Teenuste kataloog
profile.saved=Profiil salvestatud
profile.save.error=Viga salvestamisel: {0}
@@ -189,6 +195,32 @@ register.notification.failed=Registreerimine ebaõnnestus: {0}
# CTA Button
cta.freetest=Proovi tasuta
+
+# Profile Billing
+profile.billing.prefix=Arve eesliide
+profile.invoice.element.invoicenumber=Arve number
+
+# My Invoices
+myinvoices.title=Minu arved
+myinvoices.hint.noopen=Teil ei ole avatud arveid. Kõik arved on tasutud.
+myinvoices.bank.institute=Pank
+myinvoices.bank.beneficiary=Saaja
+myinvoices.bank.iban=IBAN
+myinvoices.card.open=Avatud arved
+myinvoices.card.bank=Pangaandmed
+myinvoices.bank.reference=Selgitus
+myinvoices.section.title=Kõik arved
+myinvoices.filter.pagesize=Kirjeid lehel
+myinvoices.filter.search=Otsing
+myinvoices.filter.search.placeholder=Otsi arve numbrit...
+myinvoices.column.status=Staatus
+myinvoices.column.number=Number
+myinvoices.column.date=Kuupäev
+myinvoices.column.amount=Summa
+myinvoices.empty.title=Arveid pole
+myinvoices.empty.desc=Arveid ei leitud.
+myinvoices.button.prev=Eelmine
+myinvoices.button.next=Järgmine
src/main/resources/messages_lv.properties
diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties
index cea1b6b..50e8c3f 100644
--- a/src/main/resources/messages_en.properties
+++ b/src/main/resources/messages_en.properties
@@ -36,8 +36,14 @@ profile.basicdata=Basic Data
profile.map=Map
profile.invoicecreation=Invoice Creation
profile.settings=Settings
+profile.settings.digitalprocess=Digital Processing
+profile.settings.digitalprocess.info=Jobs are processed digitally via the app
+profile.settings.locateappuser=Locate App User
+profile.settings.locateappuser.info=Location of app users is regularly transmitted
profile.account=Account
profile.security=Security
+profile.security.twofactor=Two-Factor Authentication
+profile.security.twofactor.info=An additional code is sent by email when logging in
profile.services=Service Catalog
profile.saved=Profile saved
profile.save.error=Error saving: {0}
@@ -53,6 +59,7 @@ settings.twofactorinfo=When enabled, a code will be sent via email for each logi
# Profile Billing
profile.billing.enabled=Billing via votianLT
+profile.billing.prefix=Invoice Prefix
# Profile Validation
profile.validation.company=Company is a required field
@@ -106,6 +113,7 @@ profile.invoice.element.company=Company Info
profile.invoice.element.amount=Amount
profile.invoice.element.line=Line
profile.invoice.element.image=Image
+profile.invoice.element.invoicenumber=Invoice Number
profile.invoice.properties=Properties
profile.invoice.properties.info=Click on an element in the canvas to edit its properties
profile.invoice.type=Type
@@ -655,6 +663,21 @@ myinvoices.bank.iban=IBAN
myinvoices.recipient.name=Customer
myinvoices.recipient.department=
myinvoices.item.description=Item: {0}
+myinvoices.card.open=Open Invoices
+myinvoices.card.bank=Bank Account
+myinvoices.bank.reference=Reference
+myinvoices.section.title=All Invoices
+myinvoices.filter.pagesize=Entries per page
+myinvoices.filter.search=Search
+myinvoices.filter.search.placeholder=Search invoice number...
+myinvoices.column.status=Status
+myinvoices.column.number=Number
+myinvoices.column.date=Date
+myinvoices.column.amount=Amount
+myinvoices.empty.title=No Invoices
+myinvoices.empty.desc=No invoices were found.
+myinvoices.button.prev=Previous
+myinvoices.button.next=Next
# App User
appuser.title=App Users
diff --git a/src/main/resources/messages_es.properties b/src/main/resources/messages_es.properties
index b9752f4..bf8cafb 100644
--- a/src/main/resources/messages_es.properties
+++ b/src/main/resources/messages_es.properties
@@ -36,8 +36,14 @@ profile.basicdata=Datos Básicos
profile.map=Mapa
profile.invoicecreation=Creación de Factura
profile.settings=Configuración
+profile.settings.digitalprocess=Procesamiento digital
+profile.settings.digitalprocess.info=Los pedidos se procesan digitalmente a través de la aplicación
+profile.settings.locateappuser=Localizar usuario de la aplicación
+profile.settings.locateappuser.info=La ubicación de los usuarios se transmite regularmente
profile.account=Cuenta
profile.security=Seguridad
+profile.security.twofactor=Autenticación de dos factores
+profile.security.twofactor.info=Se envía un código adicional por correo al iniciar sesión
profile.services=Catálogo de Servicios
profile.saved=Perfil guardado
profile.save.error=Error al guardar: {0}
@@ -53,6 +59,7 @@ settings.twofactorinfo=Cuando está activado, se enviará un código por correo
# Profile Billing
profile.billing.enabled=Facturación a través de votianLT
+profile.billing.prefix=Prefijo de factura
# Profile Validation
profile.validation.company=La empresa es un campo obligatorio
@@ -106,6 +113,7 @@ profile.invoice.element.company=Información de la Empresa
profile.invoice.element.amount=Cantidad
profile.invoice.element.line=Línea
profile.invoice.element.image=Imagen
+profile.invoice.element.invoicenumber=Número de factura
profile.invoice.properties=Propiedades
profile.invoice.properties.info=Haga clic en un elemento del lienzo para editar sus propiedades
profile.invoice.type=Tipo
@@ -655,6 +663,21 @@ myinvoices.bank.iban=IBAN
myinvoices.recipient.name=Cliente
myinvoices.recipient.department=
myinvoices.item.description=Artículo: {0}
+myinvoices.card.open=Facturas abiertas
+myinvoices.card.bank=Datos bancarios
+myinvoices.bank.reference=Referencia
+myinvoices.section.title=Todas las facturas
+myinvoices.filter.pagesize=Entradas por página
+myinvoices.filter.search=Búsqueda
+myinvoices.filter.search.placeholder=Buscar número de factura...
+myinvoices.column.status=Estado
+myinvoices.column.number=Número
+myinvoices.column.date=Fecha
+myinvoices.column.amount=Importe
+myinvoices.empty.title=Sin facturas
+myinvoices.empty.desc=No se encontraron facturas.
+myinvoices.button.prev=Anterior
+myinvoices.button.next=Siguiente
# App User
appuser.title=Usuarios de App
diff --git a/src/main/resources/messages_fr.properties b/src/main/resources/messages_fr.properties
index a7e0fd9..4f2b037 100644
--- a/src/main/resources/messages_fr.properties
+++ b/src/main/resources/messages_fr.properties
@@ -36,8 +36,14 @@ profile.basicdata=Données de Base
profile.map=Carte
profile.invoicecreation=Création de Facture
profile.settings=Paramètres
+profile.settings.digitalprocess=Traitement numérique
+profile.settings.digitalprocess.info=Les commandes sont traitées numériquement via l'application
+profile.settings.locateappuser=Localiser l'utilisateur de l'application
+profile.settings.locateappuser.info=La localisation des utilisateurs est transmise régulièrement
profile.account=Compte
profile.security=Sécurité
+profile.security.twofactor=Authentification à deux facteurs
+profile.security.twofactor.info=Un code supplémentaire est envoyé par e-mail lors de la connexion
profile.services=Catalogue de Services
profile.saved=Profil enregistré
profile.save.error=Erreur lors de l'enregistrement : {0}
@@ -53,6 +59,7 @@ settings.twofactorinfo=Une fois activé, un code sera envoyé par email à chaqu
# Profile Billing
profile.billing.enabled=Facturation via votianLT
+profile.billing.prefix=Préfixe de facture
# Profile Validation
profile.validation.company=L'entreprise est un champ obligatoire
@@ -106,6 +113,7 @@ profile.invoice.element.company=Infos Entreprise
profile.invoice.element.amount=Montant
profile.invoice.element.line=Ligne
profile.invoice.element.image=Image
+profile.invoice.element.invoicenumber=Numéro de facture
profile.invoice.properties=Propriétés
profile.invoice.properties.info=Cliquez sur un élément dans le canevas pour modifier ses propriétés
profile.invoice.type=Type
@@ -655,6 +663,21 @@ myinvoices.bank.iban=IBAN
myinvoices.recipient.name=Client
myinvoices.recipient.department=
myinvoices.item.description=Article : {0}
+myinvoices.card.open=Factures ouvertes
+myinvoices.card.bank=Coordonnées bancaires
+myinvoices.bank.reference=Référence
+myinvoices.section.title=Toutes les factures
+myinvoices.filter.pagesize=Entrées par page
+myinvoices.filter.search=Recherche
+myinvoices.filter.search.placeholder=Rechercher un numéro de facture...
+myinvoices.column.status=Statut
+myinvoices.column.number=Numéro
+myinvoices.column.date=Date
+myinvoices.column.amount=Montant
+myinvoices.empty.title=Aucune facture
+myinvoices.empty.desc=Aucune facture trouvée.
+myinvoices.button.prev=Précédent
+myinvoices.button.next=Suivant
# App User
appuser.title=Utilisateurs d'App
diff --git a/src/main/resources/messages_lt.properties b/src/main/resources/messages_lt.properties
index 3819ec9..6118132 100644
--- a/src/main/resources/messages_lt.properties
+++ b/src/main/resources/messages_lt.properties
@@ -36,8 +36,14 @@ profile.basicdata=Pagrindiniai duomenys
profile.map=Žemėlapis
profile.invoicecreation=Sąskaitos kūrimas
profile.settings=Nustatymai
+profile.settings.digitalprocess=Skaitmeninis apdorojimas
+profile.settings.digitalprocess.info=Užsakymai apdorojami skaitmeniškai per programėlę
+profile.settings.locateappuser=Rasti programėlės naudotoją
+profile.settings.locateappuser.info=Programėlės naudotojų vieta reguliariai perduodama
profile.account=Paskyra
profile.security=Saugumas
+profile.security.twofactor=Dviejų veiksnių autentifikavimas
+profile.security.twofactor.info=Prisijungiant el. paštu siunčiamas papildomas kodas
profile.services=Paslaugų katalogas
profile.saved=Profilis išsaugotas
profile.save.error=Klaida išsaugant: {0}
@@ -188,4 +194,30 @@ register.notification.success=Registracija sėkminga. Prašome prisijungti.
register.notification.failed=Registracijos klaida: {0}
# CTA Button
-cta.freetest=Išbandykite nemokamai
\ No newline at end of file
+cta.freetest=Išbandykite nemokamai
+
+# Profile Billing
+profile.billing.prefix=Sąskaitos prefiksas
+profile.invoice.element.invoicenumber=Sąskaitos numeris
+
+# My Invoices
+myinvoices.title=Mano sąskaitos
+myinvoices.hint.noopen=Neturite atvirų sąskaitų. Visos sąskaitos apmokėtos.
+myinvoices.bank.institute=Bankas
+myinvoices.bank.beneficiary=Gavėjas
+myinvoices.bank.iban=IBAN
+myinvoices.card.open=Atidarytos sąskaitos
+myinvoices.card.bank=Banko duomenys
+myinvoices.bank.reference=Mokėjimo paskirtis
+myinvoices.section.title=Visos sąskaitos
+myinvoices.filter.pagesize=Įrašų per puslapį
+myinvoices.filter.search=Paieška
+myinvoices.filter.search.placeholder=Ieškoti sąskaitos numerio...
+myinvoices.column.status=Statusas
+myinvoices.column.number=Numeris
+myinvoices.column.date=Data
+myinvoices.column.amount=Suma
+myinvoices.empty.title=Sąskaitų nėra
+myinvoices.empty.desc=Sąskaitų nerasta.
+myinvoices.button.prev=Ankstesnis
+myinvoices.button.next=Kitas
\ No newline at end of file
diff --git a/src/main/resources/messages_lv.properties b/src/main/resources/messages_lv.properties
index d76311e..76d5850 100644
--- a/src/main/resources/messages_lv.properties
+++ b/src/main/resources/messages_lv.properties
@@ -36,8 +36,14 @@ profile.basicdata=Pamatdati
profile.map=Karte
profile.invoicecreation=Rēķina izveide
profile.settings=Iestatījumi
+profile.settings.digitalprocess=Digitālā apstrāde
+profile.settings.digitalprocess.info=Pasūtījumi tiek apstrādāti digitāli, izmantojot lietotni
+profile.settings.locateappuser=Atrast lietotnes lietotāju
+profile.settings.locateappuser.info=Lietotnes lietotāju atrašanās vieta tiek regulāri pārsūtīta
profile.account=Konts
profile.security=Drošība
+profile.security.twofactor=Divu faktoru autentifikācija
+profile.security.twofactor.info=Pierakstoties tiek nosūtīts papildu kods uz e-pastu
profile.services=Pakalpojumu katalogs
profile.saved=Profils saglabāts
profile.save.error=Kļūda saglabājot: {0}
@@ -188,4 +194,30 @@ register.notification.success=Reģistrācija veiksmīga. Lūdzu, pieteikties.
register.notification.failed=Reģistrācijas kļūda: {0}
# CTA Button
-cta.freetest=Izmēģiniet bez maksas
\ No newline at end of file
+cta.freetest=Izmēģiniet bez maksas
+
+# Profile Billing
+profile.billing.prefix=Rēķina prefikss
+profile.invoice.element.invoicenumber=Rēķina numurs
+
+# My Invoices
+myinvoices.title=Mani rēķini
+myinvoices.hint.noopen=Jums nav atvērtu rēķinu. Visi rēķini ir apmaksāti.
+myinvoices.bank.institute=Banka
+myinvoices.bank.beneficiary=Saņēmējs
+myinvoices.bank.iban=IBAN
+myinvoices.card.open=Atvērtie rēķini
+myinvoices.card.bank=Bankas dati
+myinvoices.bank.reference=Maksājuma mērķis
+myinvoices.section.title=Visi rēķini
+myinvoices.filter.pagesize=Ieraksti lapā
+myinvoices.filter.search=Meklēt
+myinvoices.filter.search.placeholder=Meklēt rēķina numuru...
+myinvoices.column.status=Statuss
+myinvoices.column.number=Numurs
+myinvoices.column.date=Datums
+myinvoices.column.amount=Summa
+myinvoices.empty.title=Nav rēķinu
+myinvoices.empty.desc=Rēķini nav atrasti.
+myinvoices.button.prev=Iepriekšējais
+myinvoices.button.next=Nākamais
\ No newline at end of file
diff --git a/src/main/resources/messages_pl.properties b/src/main/resources/messages_pl.properties
index 3ff638b..6ecb9be 100644
--- a/src/main/resources/messages_pl.properties
+++ b/src/main/resources/messages_pl.properties
@@ -36,8 +36,14 @@ profile.basicdata=Dane podstawowe
profile.map=Mapa
profile.invoicecreation=Tworzenie faktury
profile.settings=Ustawienia
+profile.settings.digitalprocess=Przetwarzanie cyfrowe
+profile.settings.digitalprocess.info=Zlecenia są przetwarzane cyfrowo przez aplikację
+profile.settings.locateappuser=Lokalizuj użytkownika aplikacji
+profile.settings.locateappuser.info=Lokalizacja użytkowników jest regularnie przesyłana
profile.account=Konto
profile.security=Bezpieczeństwo
+profile.security.twofactor=Uwierzytelnianie dwuskładnikowe
+profile.security.twofactor.info=Dodatkowy kod jest wysyłany e-mailem przy logowaniu
profile.services=Katalog usług
profile.saved=Profil zapisany
profile.save.error=Błąd podczas zapisywania: {0}
@@ -191,4 +197,30 @@ register.notification.success=Rejestracja zakończona sukcesem. Zaloguj się.
register.notification.failed=Rejestracja nie powiodła się: {0}
# CTA Button
-cta.freetest=Wypróbuj teraz za darmo
\ No newline at end of file
+cta.freetest=Wypróbuj teraz za darmo
+
+# Profile Billing
+profile.billing.prefix=Prefiks faktury
+profile.invoice.element.invoicenumber=Numer faktury
+
+# My Invoices
+myinvoices.title=Moje faktury
+myinvoices.hint.noopen=Nie masz otwartych faktur. Wszystkie faktury są uregulowane.
+myinvoices.bank.institute=Bank
+myinvoices.bank.beneficiary=Odbiorca
+myinvoices.bank.iban=IBAN
+myinvoices.card.open=Otwarte faktury
+myinvoices.card.bank=Dane bankowe
+myinvoices.bank.reference=Tytuł przelewu
+myinvoices.section.title=Wszystkie faktury
+myinvoices.filter.pagesize=Wpisów na stronie
+myinvoices.filter.search=Szukaj
+myinvoices.filter.search.placeholder=Szukaj numeru faktury...
+myinvoices.column.status=Status
+myinvoices.column.number=Numer
+myinvoices.column.date=Data
+myinvoices.column.amount=Kwota
+myinvoices.empty.title=Brak faktur
+myinvoices.empty.desc=Nie znaleziono faktur.
+myinvoices.button.prev=Poprzedni
+myinvoices.button.next=Następny
\ No newline at end of file
diff --git a/src/main/resources/messages_ru.properties b/src/main/resources/messages_ru.properties
index 5e85e4e..16aef01 100644
--- a/src/main/resources/messages_ru.properties
+++ b/src/main/resources/messages_ru.properties
@@ -36,8 +36,14 @@ profile.basicdata=Основные данные
profile.map=Карта
profile.invoicecreation=Создание счета
profile.settings=Настройки
+profile.settings.digitalprocess=Цифровая обработка
+profile.settings.digitalprocess.info=Заказы обрабатываются в цифровом формате через приложение
+profile.settings.locateappuser=Определить местоположение пользователя
+profile.settings.locateappuser.info=Местоположение пользователей приложения регулярно передаётся
profile.account=Аккаунт
profile.security=Безопасность
+profile.security.twofactor=Двухфакторная аутентификация
+profile.security.twofactor.info=При входе на электронную почту отправляется дополнительный код
profile.services=Каталог услуг
profile.saved=Профиль сохранен
profile.save.error=Ошибка сохранения: {0}
@@ -211,4 +217,30 @@ register.notification.success=Регистрация прошла успешно
register.notification.failed=Ошибка регистрации: {0}
# CTA Button
-cta.freetest=Попробуйте бесплатно
\ No newline at end of file
+cta.freetest=Попробуйте бесплатно
+
+# Profile Billing
+profile.billing.prefix=Префикс счёта
+profile.invoice.element.invoicenumber=Номер счёта
+
+# My Invoices
+myinvoices.title=Мои счета
+myinvoices.hint.noopen=У вас нет открытых счетов. Все счета оплачены.
+myinvoices.bank.institute=Банк
+myinvoices.bank.beneficiary=Получатель
+myinvoices.bank.iban=IBAN
+myinvoices.card.open=Открытые счета
+myinvoices.card.bank=Банковские реквизиты
+myinvoices.bank.reference=Назначение платежа
+myinvoices.section.title=Все счета
+myinvoices.filter.pagesize=Записей на странице
+myinvoices.filter.search=Поиск
+myinvoices.filter.search.placeholder=Поиск по номеру счёта...
+myinvoices.column.status=Статус
+myinvoices.column.number=Номер
+myinvoices.column.date=Дата
+myinvoices.column.amount=Сумма
+myinvoices.empty.title=Нет счетов
+myinvoices.empty.desc=Счета не найдены.
+myinvoices.button.prev=Назад
+myinvoices.button.next=Далее
\ No newline at end of file
diff --git a/src/main/resources/messages_tr.properties b/src/main/resources/messages_tr.properties
index d84df0a..8da81ae 100644
--- a/src/main/resources/messages_tr.properties
+++ b/src/main/resources/messages_tr.properties
@@ -36,8 +36,14 @@ profile.basicdata=Temel Veriler
profile.map=Harita
profile.invoicecreation=Fatura Oluşturma
profile.settings=Ayarlar
+profile.settings.digitalprocess=Dijital İşlem
+profile.settings.digitalprocess.info=Siparişler uygulama üzerinden dijital olarak işlenir
+profile.settings.locateappuser=Uygulama Kullanıcısını Konumla
+profile.settings.locateappuser.info=Uygulama kullanıcılarının konumu düzenli olarak iletilir
profile.account=Hesap
profile.security=Güvenlik
+profile.security.twofactor=İki Faktörlü Kimlik Doğrulama
+profile.security.twofactor.info=Giriş yaparken e-posta ile ek bir kod gönderilir
profile.services=Hizmet Kataloğu
profile.saved=Profil kaydedildi
profile.save.error=Kaydetme hatası: {0}
@@ -185,4 +191,30 @@ register.notification.success=Kayıt başarılı. Lütfen giriş yapın.
register.notification.failed=Kayıt başarısız: {0}
# CTA Button
-cta.freetest=Şimdi ücretsiz dene
\ No newline at end of file
+cta.freetest=Şimdi ücretsiz dene
+
+# Profile Billing
+profile.billing.prefix=Fatura ön eki
+profile.invoice.element.invoicenumber=Fatura numarası
+
+# My Invoices
+myinvoices.title=Faturalarım
+myinvoices.hint.noopen=Açık faturanız yok. Tüm faturalar ödendi.
+myinvoices.bank.institute=Banka
+myinvoices.bank.beneficiary=Alıcı
+myinvoices.bank.iban=IBAN
+myinvoices.card.open=Açık Faturalar
+myinvoices.card.bank=Banka Bilgileri
+myinvoices.bank.reference=Referans
+myinvoices.section.title=Tüm Faturalar
+myinvoices.filter.pagesize=Sayfa başına giriş
+myinvoices.filter.search=Ara
+myinvoices.filter.search.placeholder=Fatura numarası ara...
+myinvoices.column.status=Durum
+myinvoices.column.number=Numara
+myinvoices.column.date=Tarih
+myinvoices.column.amount=Tutar
+myinvoices.empty.title=Fatura Yok
+myinvoices.empty.desc=Hiçbir fatura bulunamadı.
+myinvoices.button.prev=Önceki
+myinvoices.button.next=Sonraki
\ No newline at end of file