Erweiterungen

This commit is contained in:
2026-02-23 17:26:27 +01:00
parent 1c7652bb28
commit 0531c96cc8
17 changed files with 410 additions and 62 deletions

Binary file not shown.

View File

@@ -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;

View File

@@ -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');

View File

@@ -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 = "

View File

@@ -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();

View File

@@ -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("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;")
.replace("'", "&#x27;");
// Convert newlines to <br> for multi-line elements (e.g. customer address)
text = text.replace("\n", "<br>");
} else {
text = "";
}
if ("line".equals(type)) {
htmlBuilder.append(
"<hr style='margin:0;border:none;border-top:1px solid #333;height:0;width:100%;'/>");
} 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("<br>")) {
// Multi-line text: render without nowrap so <br> tags work
htmlBuilder.append("<span>").append(text).append("</span>");
} else {
// Wrap text in a span to prevent flexbox issues
htmlBuilder.append("<span style='white-space:nowrap;'>").append(text).append("</span>");
@@ -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("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("\"", "&quot;")
.replace("'", "&#x27;");
// Convert newlines to <br> for multi-line elements (e.g. customer address)
text = text.replace("\n", "<br>");
} else {
text = "";
}
if ("line".equals(type)) {
htmlBuilder.append(
"<hr style='margin:0;border:none;border-top:1px solid #333;height:0;width:100%;'/>");
} 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("<br>")) {
// Multi-line text: render without nowrap so <br> tags work
htmlBuilder.append("<span>").append(text).append("</span>");
} else {
htmlBuilder.append("<span style='white-space:nowrap;'>").append(text).append("</span>");
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
</content>
<write_to_file>
<path>src/main/resources/messages_lv.properties</path>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
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

View File

@@ -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
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

View File

@@ -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
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

View File

@@ -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=Попробуйте бесплатно
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=Далее

View File

@@ -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
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=ık faturanız yok. Tüm faturalar ödendi.
myinvoices.bank.institute=Banka
myinvoices.bank.beneficiary=Alıcı
myinvoices.bank.iban=IBAN
myinvoices.card.open=ı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