Erweiterungen
This commit is contained in:
Binary file not shown.
@@ -450,6 +450,15 @@
|
|||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
break;
|
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':
|
case 'image':
|
||||||
if (el.imageData) {
|
if (el.imageData) {
|
||||||
// Draw actual image
|
// Draw actual image
|
||||||
@@ -699,6 +708,11 @@
|
|||||||
el.width = 200;
|
el.width = 200;
|
||||||
el.height = 2;
|
el.height = 2;
|
||||||
break;
|
break;
|
||||||
|
case 'vline':
|
||||||
|
el.text = '';
|
||||||
|
el.width = 2;
|
||||||
|
el.height = 200;
|
||||||
|
break;
|
||||||
case 'image':
|
case 'image':
|
||||||
el.text = 'Bild';
|
el.text = 'Bild';
|
||||||
el.width = 100;
|
el.width = 100;
|
||||||
|
|||||||
@@ -265,7 +265,9 @@ window.initProfileInvoiceGenerator = function() {
|
|||||||
|
|
||||||
// Always use black text for static elements, otherwise use element color
|
// Always use black text for static elements, otherwise use element color
|
||||||
ctx.fillStyle = el.isStatic ? '#000000' : (el.color || '#333333');
|
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';
|
ctx.textBaseline = 'top';
|
||||||
|
|
||||||
lines.forEach(function(line) {
|
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();
|
draw();
|
||||||
window.profileInvoiceState.initialized = true;
|
window.profileInvoiceState.initialized = true;
|
||||||
console.log('Profile canvas initialized with ' + elements.length + ' elements');
|
console.log('Profile canvas initialized with ' + elements.length + ' elements');
|
||||||
|
|||||||
@@ -327,6 +327,20 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
|
|||||||
billingEnabled.setValue(true); // Standardmäßig aktiviert
|
billingEnabled.setValue(true); // Standardmäßig aktiviert
|
||||||
billingTab.add(billingEnabled);
|
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)
|
// Hauptlayout: Links (Templates) | Mitte (Canvas) | Rechts (Eigenschaften)
|
||||||
final HorizontalLayout mainLayout = new HorizontalLayout();
|
final HorizontalLayout mainLayout = new HorizontalLayout();
|
||||||
mainLayout.setWidthFull();
|
mainLayout.setWidthFull();
|
||||||
@@ -384,13 +398,6 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
|
|||||||
actionLayout.setSpacing(true);
|
actionLayout.setSpacing(true);
|
||||||
actionLayout.getStyle().set("margin-top", "var(--lumo-space-s)");
|
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));
|
Button previewPdfButton = new Button(getTranslation("button.preview"), new Icon(VaadinIcon.EYE));
|
||||||
previewPdfButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
previewPdfButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_SUCCESS);
|
||||||
previewPdfButton.addClickListener(e -> generatePreviewPdfFromProfile());
|
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);
|
billingTab.add(actionLayout);
|
||||||
|
|
||||||
// Initialen Zustand setzen (sichtbar da checkbox standardmäßig true)
|
// 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
|
// Sichtbarkeit des Invoice Generators an Checkbox binden
|
||||||
billingEnabled.addValueChangeListener(e -> {
|
billingEnabled.addValueChangeListener(e -> {
|
||||||
boolean visible = e.getValue();
|
boolean visible = e.getValue();
|
||||||
|
prefixField.setVisible(visible);
|
||||||
mainLayout.setVisible(visible);
|
mainLayout.setVisible(visible);
|
||||||
actionLayout.setVisible(visible);
|
actionLayout.setVisible(visible);
|
||||||
});
|
});
|
||||||
@@ -866,7 +874,7 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
|
|||||||
templateData = result.toString();
|
templateData = result.toString();
|
||||||
}
|
}
|
||||||
byte[] pdfBytes = customerInvoiceService.generatePdfFromCanvasTemplate(templateData,
|
byte[] pdfBytes = customerInvoiceService.generatePdfFromCanvasTemplate(templateData,
|
||||||
currentUser);
|
currentUser, prefixField.getValue());
|
||||||
showPdfInDialog(pdfBytes);
|
showPdfInDialog(pdfBytes);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Notification.show(getTranslation("profile.pdf.preview.error", ex.getMessage()), 3000,
|
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);
|
"masterdata.email", email.isEmpty() ? getTranslation("profile.invoice.placeholder.email") : email);
|
||||||
Div senderPhone = createVariableTemplate(getTranslation("profile.invoice.phone"), VaadinIcon.PHONE,
|
Div senderPhone = createVariableTemplate(getTranslation("profile.invoice.phone"), VaadinIcon.PHONE,
|
||||||
"masterdata.phone", phone.isEmpty() ? getTranslation("profile.invoice.placeholder.phone") : 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
|
// Bereich 2: Leistungen
|
||||||
Span servicesHeader = new Span(getTranslation("profile.services.label"));
|
Span servicesHeader = new Span(getTranslation("profile.services.label"));
|
||||||
@@ -1017,7 +1027,7 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
|
|||||||
"image");
|
"image");
|
||||||
|
|
||||||
panel.add(invoiceHeader, senderCompany, senderName, senderAddress, senderCity, senderEmail, senderPhone,
|
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,
|
customerHeader, customerCompany, customerName, customerAddress, customerCity, customerEmail,
|
||||||
customerPhone, freeHeader, textBlock, headerBlock, dateBlock, customerBlock, companyBlock, amountBlock,
|
customerPhone, freeHeader, textBlock, headerBlock, dateBlock, customerBlock, companyBlock, amountBlock,
|
||||||
lineBlock, imageBlock);
|
lineBlock, imageBlock);
|
||||||
@@ -1422,11 +1432,14 @@ public class EditProfileView extends HorizontalLayout implements HasDynamicTitle
|
|||||||
String city = safe(currentUser.getZip()) + " " + safe(currentUser.getCity());
|
String city = safe(currentUser.getZip()) + " " + safe(currentUser.getCity());
|
||||||
String email = safe(currentUser.getEmail());
|
String email = safe(currentUser.getEmail());
|
||||||
String phone = safe(currentUser.getPhone());
|
String phone = safe(currentUser.getPhone());
|
||||||
|
String prefix = prefixField.getValue();
|
||||||
|
String invoiceNumber = (prefix != null && !prefix.isBlank() ? prefix : "") + "12345";
|
||||||
String masterdataJson = "{" + "'masterdata.company_name': '" + company.replace("'", "\\'") + "',"
|
String masterdataJson = "{" + "'masterdata.company_name': '" + company.replace("'", "\\'") + "',"
|
||||||
+ "'masterdata.contact_name': '" + fullName.replace("'", "\\'") + "',"
|
+ "'masterdata.contact_name': '" + fullName.replace("'", "\\'") + "',"
|
||||||
+ "'masterdata.street': '" + street.replace("'", "\\'") + "'," + "'masterdata.city': '"
|
+ "'masterdata.street': '" + street.replace("'", "\\'") + "'," + "'masterdata.city': '"
|
||||||
+ city.replace("'", "\\'") + "'," + "'masterdata.email': '" + email.replace("'", "\\'")
|
+ city.replace("'", "\\'") + "'," + "'masterdata.email': '" + email.replace("'", "\\'")
|
||||||
+ "'," + "'masterdata.phone': '" + phone.replace("'", "\\'") + "'" + "}";
|
+ "'," + "'masterdata.phone': '" + phone.replace("'", "\\'") + "',"
|
||||||
|
+ "'masterdata.invoice_number': '" + invoiceNumber.replace("'", "\\'") + "'" + "}";
|
||||||
getElement().executeJs("setTimeout(function() { "
|
getElement().executeJs("setTimeout(function() { "
|
||||||
+ " if (window.loadProfileTemplate && document.getElementById('invoice-canvas-container-profile')) { "
|
+ " if (window.loadProfileTemplate && document.getElementById('invoice-canvas-container-profile')) { "
|
||||||
+ " console.log('Loading template into canvas...'); " + " window.masterdataValues = "
|
+ " console.log('Loading template into canvas...'); " + " window.masterdataValues = "
|
||||||
|
|||||||
@@ -123,11 +123,13 @@ public class InvoiceGeneratorView extends VerticalLayout implements HasDynamicTi
|
|||||||
VaadinIcon.COIN_PILES, "amount");
|
VaadinIcon.COIN_PILES, "amount");
|
||||||
Div lineBlock = createDraggableTemplate(getTranslation("invoicegenerator.template.line"), VaadinIcon.LINE_V,
|
Div lineBlock = createDraggableTemplate(getTranslation("invoicegenerator.template.line"), VaadinIcon.LINE_V,
|
||||||
"line");
|
"line");
|
||||||
|
Div vlineBlock = createDraggableTemplate(getTranslation("invoicegenerator.template.vline"),
|
||||||
|
VaadinIcon.LINE_BAR_CHART, "vline");
|
||||||
Div imageBlock = createDraggableTemplate(getTranslation("invoicegenerator.template.image"), VaadinIcon.PICTURE,
|
Div imageBlock = createDraggableTemplate(getTranslation("invoicegenerator.template.image"), VaadinIcon.PICTURE,
|
||||||
"image");
|
"image");
|
||||||
|
|
||||||
panel.add(header, textBlock, headerBlock, dateBlock, customerBlock, companyBlock, amountBlock, lineBlock,
|
panel.add(header, textBlock, headerBlock, dateBlock, customerBlock, companyBlock, amountBlock, lineBlock,
|
||||||
imageBlock);
|
vlineBlock, imageBlock);
|
||||||
|
|
||||||
return panel;
|
return panel;
|
||||||
}
|
}
|
||||||
@@ -409,7 +411,7 @@ public class InvoiceGeneratorView extends VerticalLayout implements HasDynamicTi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Text Feld (nur für Text-Elemente)
|
// 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 textField = new TextField("Text");
|
||||||
textField.setValue(text != null ? text : "");
|
textField.setValue(text != null ? text : "");
|
||||||
textField.setWidthFull();
|
textField.setWidthFull();
|
||||||
@@ -451,7 +453,7 @@ public class InvoiceGeneratorView extends VerticalLayout implements HasDynamicTi
|
|||||||
propertiesPanel.add(yField);
|
propertiesPanel.add(yField);
|
||||||
|
|
||||||
// Font Size (nur für Text-Elemente)
|
// 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"));
|
TextField fontSizeField = new TextField(getTranslation("invoicegenerator.fontsize.label"));
|
||||||
fontSizeField.setValue(fontSize != null ? String.valueOf(fontSize) : "16");
|
fontSizeField.setValue(fontSize != null ? String.valueOf(fontSize) : "16");
|
||||||
fontSizeField.setWidthFull();
|
fontSizeField.setWidthFull();
|
||||||
|
|||||||
@@ -248,11 +248,17 @@ public class CustomerInvoiceService {
|
|||||||
* representation of the canvas elements and converts it to PDF.
|
* representation of the canvas elements and converts it to PDF.
|
||||||
*/
|
*/
|
||||||
public byte[] generatePdfFromCanvasTemplate(String jsonTemplateData) throws Exception {
|
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)
|
public byte[] generatePdfFromCanvasTemplate(String jsonTemplateData, de.assecutor.votianlt.model.User user)
|
||||||
throws Exception {
|
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
|
// Parse the JSON template data
|
||||||
com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
|
com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
|
||||||
com.fasterxml.jackson.databind.JsonNode rootNode = mapper.readTree(jsonTemplateData);
|
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.city", safe(user.getZip()) + " " + safe(user.getCity()));
|
||||||
variables.put("masterdata.email", safe(user.getEmail()));
|
variables.put("masterdata.email", safe(user.getEmail()));
|
||||||
variables.put("masterdata.phone", safe(user.getPhone()));
|
variables.put("masterdata.phone", safe(user.getPhone()));
|
||||||
|
variables.put("masterdata.invoice_number",
|
||||||
|
(invoicePrefix != null && !invoicePrefix.isBlank() ? invoicePrefix : "") + "12345");
|
||||||
} else {
|
} else {
|
||||||
// Default values for preview without user
|
// Default values for preview without user
|
||||||
variables.put("masterdata.company_name", "Meine Firma GmbH");
|
variables.put("masterdata.company_name", "Meine Firma GmbH");
|
||||||
@@ -295,6 +303,8 @@ public class CustomerInvoiceService {
|
|||||||
variables.put("masterdata.city", "12345 Musterstadt");
|
variables.put("masterdata.city", "12345 Musterstadt");
|
||||||
variables.put("masterdata.email", "kontakt@firma.de");
|
variables.put("masterdata.email", "kontakt@firma.de");
|
||||||
variables.put("masterdata.phone", "0123 456789");
|
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)
|
// 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;
|
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";
|
String color = element.has("color") ? element.get("color").asText("#333333") : "#333333";
|
||||||
|
|
||||||
// Convert percentages to mm (A4 is 210mm x 297mm)
|
// Convert percentages to mm (A4 is 210mm x 297mm)
|
||||||
@@ -361,23 +370,27 @@ public class CustomerInvoiceService {
|
|||||||
htmlBuilder.append("style='");
|
htmlBuilder.append("style='");
|
||||||
htmlBuilder.append("left:").append(String.format(java.util.Locale.US, "%.2f", mmX)).append("mm;");
|
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("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;");
|
if ("line".equals(type)) {
|
||||||
htmlBuilder.append("height:").append(String.format(java.util.Locale.US, "%.2f", mmHeight))
|
htmlBuilder.append("width:").append(String.format(java.util.Locale.US, "%.2f", mmWidth)).append("mm;");
|
||||||
.append("mm;");
|
htmlBuilder.append("height:0;border-top:1px solid #333;");
|
||||||
htmlBuilder.append("font-size:").append(fontSize).append("pt;");
|
} else if ("vline".equals(type)) {
|
||||||
htmlBuilder.append("line-height:").append(String.format(java.util.Locale.US, "%.2f", fontSize * 1.2))
|
htmlBuilder.append("width:0;border-left:1px solid #333;");
|
||||||
.append("pt;");
|
htmlBuilder.append("height:").append(String.format(java.util.Locale.US, "%.2f", mmHeight)).append("mm;");
|
||||||
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;");
|
|
||||||
} else {
|
} else {
|
||||||
// Vertically center content for other elements
|
htmlBuilder.append("width:").append(String.format(java.util.Locale.US, "%.2f", mmWidth)).append("mm;");
|
||||||
htmlBuilder.append("display:flex;align-items:center;");
|
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("'");
|
||||||
htmlBuilder.append(">");
|
htmlBuilder.append(">");
|
||||||
@@ -406,14 +419,13 @@ public class CustomerInvoiceService {
|
|||||||
if (text != null) {
|
if (text != null) {
|
||||||
text = text.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """)
|
text = text.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """)
|
||||||
.replace("'", "'");
|
.replace("'", "'");
|
||||||
|
// Convert newlines to <br> for multi-line elements (e.g. customer address)
|
||||||
|
text = text.replace("\n", "<br>");
|
||||||
} else {
|
} else {
|
||||||
text = "";
|
text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("line".equals(type)) {
|
if ("image".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 (element.has("imageData") && !element.get("imageData").asText().isEmpty()) {
|
if (element.has("imageData") && !element.get("imageData").asText().isEmpty()) {
|
||||||
String imageData = element.get("imageData").asText();
|
String imageData = element.get("imageData").asText();
|
||||||
// Ensure proper data URL format
|
// Ensure proper data URL format
|
||||||
@@ -433,6 +445,9 @@ public class CustomerInvoiceService {
|
|||||||
} else if ("services.list".equals(variable)) {
|
} else if ("services.list".equals(variable)) {
|
||||||
// Render services list as a table
|
// Render services list as a table
|
||||||
htmlBuilder.append(generateServicesTableHtml(mmWidth));
|
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 {
|
} else {
|
||||||
// Wrap text in a span to prevent flexbox issues
|
// Wrap text in a span to prevent flexbox issues
|
||||||
htmlBuilder.append("<span style='white-space:nowrap;'>").append(text).append("</span>");
|
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;
|
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";
|
String color = element.has("color") ? element.get("color").asText("#333333") : "#333333";
|
||||||
|
|
||||||
// Convert percentages to mm (A4 is 210mm x 297mm)
|
// Convert percentages to mm (A4 is 210mm x 297mm)
|
||||||
@@ -653,22 +667,26 @@ public class CustomerInvoiceService {
|
|||||||
htmlBuilder.append("style='");
|
htmlBuilder.append("style='");
|
||||||
htmlBuilder.append("left:").append(String.format(java.util.Locale.US, "%.2f", mmX)).append("mm;");
|
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("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;");
|
if ("line".equals(type)) {
|
||||||
htmlBuilder.append("height:").append(String.format(java.util.Locale.US, "%.2f", mmHeight))
|
htmlBuilder.append("width:").append(String.format(java.util.Locale.US, "%.2f", mmWidth)).append("mm;");
|
||||||
.append("mm;");
|
htmlBuilder.append("height:0;border-top:1px solid #333;");
|
||||||
htmlBuilder.append("font-size:").append(fontSize).append("pt;");
|
} else if ("vline".equals(type)) {
|
||||||
htmlBuilder.append("line-height:").append(String.format(java.util.Locale.US, "%.2f", fontSize * 1.2))
|
htmlBuilder.append("width:0;border-left:1px solid #333;");
|
||||||
.append("pt;");
|
htmlBuilder.append("height:").append(String.format(java.util.Locale.US, "%.2f", mmHeight)).append("mm;");
|
||||||
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;");
|
|
||||||
} else {
|
} 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("'");
|
||||||
htmlBuilder.append(">");
|
htmlBuilder.append(">");
|
||||||
@@ -695,14 +713,13 @@ public class CustomerInvoiceService {
|
|||||||
if (text != null) {
|
if (text != null) {
|
||||||
text = text.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """)
|
text = text.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """)
|
||||||
.replace("'", "'");
|
.replace("'", "'");
|
||||||
|
// Convert newlines to <br> for multi-line elements (e.g. customer address)
|
||||||
|
text = text.replace("\n", "<br>");
|
||||||
} else {
|
} else {
|
||||||
text = "";
|
text = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("line".equals(type)) {
|
if ("image".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 (element.has("imageData") && !element.get("imageData").asText().isEmpty()) {
|
if (element.has("imageData") && !element.get("imageData").asText().isEmpty()) {
|
||||||
String imageData = element.get("imageData").asText();
|
String imageData = element.get("imageData").asText();
|
||||||
if (!imageData.startsWith("data:")) {
|
if (!imageData.startsWith("data:")) {
|
||||||
@@ -720,6 +737,9 @@ public class CustomerInvoiceService {
|
|||||||
} else if ("services.list".equals(variable)) {
|
} else if ("services.list".equals(variable)) {
|
||||||
// Render services list as a table with actual data
|
// Render services list as a table with actual data
|
||||||
htmlBuilder.append(generateServicesTableHtmlWithData(mmWidth, variables));
|
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 {
|
} else {
|
||||||
htmlBuilder.append("<span style='white-space:nowrap;'>").append(text).append("</span>");
|
htmlBuilder.append("<span style='white-space:nowrap;'>").append(text).append("</span>");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ spring.profiles.active=dev
|
|||||||
|
|
||||||
# Logging configuration
|
# Logging configuration
|
||||||
logging.level.org.atmosphere=warn
|
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=INFO
|
||||||
logging.level.de.assecutor.votianlt.controller.MessageController=DEBUG
|
logging.level.de.assecutor.votianlt.controller.MessageController=DEBUG
|
||||||
logging.level.de.assecutor.votianlt.config.MongoConfig=DEBUG
|
logging.level.de.assecutor.votianlt.config.MongoConfig=DEBUG
|
||||||
|
|||||||
@@ -36,8 +36,14 @@ profile.basicdata=Stammdaten
|
|||||||
profile.map=Karte
|
profile.map=Karte
|
||||||
profile.invoicecreation=Rechnungserstellung
|
profile.invoicecreation=Rechnungserstellung
|
||||||
profile.settings=Einstellungen
|
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.account=Konto
|
||||||
profile.security=Sicherheit
|
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.services=Leistungskatalog
|
||||||
profile.saved=Profil gespeichert
|
profile.saved=Profil gespeichert
|
||||||
profile.save.error=Fehler beim Speichern: {0}
|
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
|
||||||
profile.billing.enabled=Rechnungslegung über votianLT
|
profile.billing.enabled=Rechnungslegung über votianLT
|
||||||
|
profile.billing.prefix=Rechnungspräfix
|
||||||
|
|
||||||
# Profile Validation
|
# Profile Validation
|
||||||
profile.validation.company=Firma ist ein Pflichtfeld
|
profile.validation.company=Firma ist ein Pflichtfeld
|
||||||
@@ -106,6 +113,7 @@ profile.invoice.element.company=Firmeninfo
|
|||||||
profile.invoice.element.amount=Betrag
|
profile.invoice.element.amount=Betrag
|
||||||
profile.invoice.element.line=Linie
|
profile.invoice.element.line=Linie
|
||||||
profile.invoice.element.image=Bild
|
profile.invoice.element.image=Bild
|
||||||
|
profile.invoice.element.invoicenumber=Rechnungsnummer
|
||||||
profile.invoice.properties=Eigenschaften
|
profile.invoice.properties=Eigenschaften
|
||||||
profile.invoice.properties.info=Klicken Sie auf ein Element im Canvas, um dessen Eigenschaften zu bearbeiten.
|
profile.invoice.properties.info=Klicken Sie auf ein Element im Canvas, um dessen Eigenschaften zu bearbeiten.
|
||||||
profile.invoice.type=Typ
|
profile.invoice.type=Typ
|
||||||
@@ -655,6 +663,21 @@ myinvoices.bank.iban=IBAN
|
|||||||
myinvoices.recipient.name=Kunde
|
myinvoices.recipient.name=Kunde
|
||||||
myinvoices.recipient.department=
|
myinvoices.recipient.department=
|
||||||
myinvoices.item.description=Position: {0}
|
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
|
# App User
|
||||||
appuser.title=App-Nutzer
|
appuser.title=App-Nutzer
|
||||||
@@ -811,6 +834,7 @@ invoicegenerator.upload.success=Bild erfolgreich hochgeladen
|
|||||||
invoicegenerator.upload.error=Fehler beim Hochladen: {0}
|
invoicegenerator.upload.error=Fehler beim Hochladen: {0}
|
||||||
invoicegenerator.file.rejected=Datei abgelehnt: {0}
|
invoicegenerator.file.rejected=Datei abgelehnt: {0}
|
||||||
invoicegenerator.properties.select.info=Klicken Sie auf ein Element im Canvas, um dessen Eigenschaften zu bearbeiten.
|
invoicegenerator.properties.select.info=Klicken Sie auf ein Element im Canvas, um dessen Eigenschaften zu bearbeiten.
|
||||||
|
invoicegenerator.template.vline=Vertikale Linie
|
||||||
|
|
||||||
# CSV Export
|
# CSV Export
|
||||||
csv.header.customer=Auftraggeber
|
csv.header.customer=Auftraggeber
|
||||||
|
|||||||
@@ -36,8 +36,14 @@ profile.basicdata=Põhiandmed
|
|||||||
profile.map=Kaart
|
profile.map=Kaart
|
||||||
profile.invoicecreation=Arve loomine
|
profile.invoicecreation=Arve loomine
|
||||||
profile.settings=Seaded
|
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.account=Konto
|
||||||
profile.security=Turvalisus
|
profile.security=Turvalisus
|
||||||
|
profile.security.twofactor=Kahefaktoriline autentimine
|
||||||
|
profile.security.twofactor.info=Sisselogimisel saadetakse e-postiga täiendav kood
|
||||||
profile.services=Teenuste kataloog
|
profile.services=Teenuste kataloog
|
||||||
profile.saved=Profiil salvestatud
|
profile.saved=Profiil salvestatud
|
||||||
profile.save.error=Viga salvestamisel: {0}
|
profile.save.error=Viga salvestamisel: {0}
|
||||||
@@ -189,6 +195,32 @@ register.notification.failed=Registreerimine ebaõnnestus: {0}
|
|||||||
|
|
||||||
# CTA Button
|
# CTA Button
|
||||||
cta.freetest=Proovi tasuta
|
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>
|
</content>
|
||||||
<write_to_file>
|
<write_to_file>
|
||||||
<path>src/main/resources/messages_lv.properties</path>
|
<path>src/main/resources/messages_lv.properties</path>
|
||||||
|
|||||||
@@ -36,8 +36,14 @@ profile.basicdata=Basic Data
|
|||||||
profile.map=Map
|
profile.map=Map
|
||||||
profile.invoicecreation=Invoice Creation
|
profile.invoicecreation=Invoice Creation
|
||||||
profile.settings=Settings
|
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.account=Account
|
||||||
profile.security=Security
|
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.services=Service Catalog
|
||||||
profile.saved=Profile saved
|
profile.saved=Profile saved
|
||||||
profile.save.error=Error saving: {0}
|
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
|
||||||
profile.billing.enabled=Billing via votianLT
|
profile.billing.enabled=Billing via votianLT
|
||||||
|
profile.billing.prefix=Invoice Prefix
|
||||||
|
|
||||||
# Profile Validation
|
# Profile Validation
|
||||||
profile.validation.company=Company is a required field
|
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.amount=Amount
|
||||||
profile.invoice.element.line=Line
|
profile.invoice.element.line=Line
|
||||||
profile.invoice.element.image=Image
|
profile.invoice.element.image=Image
|
||||||
|
profile.invoice.element.invoicenumber=Invoice Number
|
||||||
profile.invoice.properties=Properties
|
profile.invoice.properties=Properties
|
||||||
profile.invoice.properties.info=Click on an element in the canvas to edit its properties
|
profile.invoice.properties.info=Click on an element in the canvas to edit its properties
|
||||||
profile.invoice.type=Type
|
profile.invoice.type=Type
|
||||||
@@ -655,6 +663,21 @@ myinvoices.bank.iban=IBAN
|
|||||||
myinvoices.recipient.name=Customer
|
myinvoices.recipient.name=Customer
|
||||||
myinvoices.recipient.department=
|
myinvoices.recipient.department=
|
||||||
myinvoices.item.description=Item: {0}
|
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
|
# App User
|
||||||
appuser.title=App Users
|
appuser.title=App Users
|
||||||
|
|||||||
@@ -36,8 +36,14 @@ profile.basicdata=Datos Básicos
|
|||||||
profile.map=Mapa
|
profile.map=Mapa
|
||||||
profile.invoicecreation=Creación de Factura
|
profile.invoicecreation=Creación de Factura
|
||||||
profile.settings=Configuración
|
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.account=Cuenta
|
||||||
profile.security=Seguridad
|
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.services=Catálogo de Servicios
|
||||||
profile.saved=Perfil guardado
|
profile.saved=Perfil guardado
|
||||||
profile.save.error=Error al guardar: {0}
|
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
|
||||||
profile.billing.enabled=Facturación a través de votianLT
|
profile.billing.enabled=Facturación a través de votianLT
|
||||||
|
profile.billing.prefix=Prefijo de factura
|
||||||
|
|
||||||
# Profile Validation
|
# Profile Validation
|
||||||
profile.validation.company=La empresa es un campo obligatorio
|
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.amount=Cantidad
|
||||||
profile.invoice.element.line=Línea
|
profile.invoice.element.line=Línea
|
||||||
profile.invoice.element.image=Imagen
|
profile.invoice.element.image=Imagen
|
||||||
|
profile.invoice.element.invoicenumber=Número de factura
|
||||||
profile.invoice.properties=Propiedades
|
profile.invoice.properties=Propiedades
|
||||||
profile.invoice.properties.info=Haga clic en un elemento del lienzo para editar sus propiedades
|
profile.invoice.properties.info=Haga clic en un elemento del lienzo para editar sus propiedades
|
||||||
profile.invoice.type=Tipo
|
profile.invoice.type=Tipo
|
||||||
@@ -655,6 +663,21 @@ myinvoices.bank.iban=IBAN
|
|||||||
myinvoices.recipient.name=Cliente
|
myinvoices.recipient.name=Cliente
|
||||||
myinvoices.recipient.department=
|
myinvoices.recipient.department=
|
||||||
myinvoices.item.description=Artículo: {0}
|
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
|
# App User
|
||||||
appuser.title=Usuarios de App
|
appuser.title=Usuarios de App
|
||||||
|
|||||||
@@ -36,8 +36,14 @@ profile.basicdata=Données de Base
|
|||||||
profile.map=Carte
|
profile.map=Carte
|
||||||
profile.invoicecreation=Création de Facture
|
profile.invoicecreation=Création de Facture
|
||||||
profile.settings=Paramètres
|
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.account=Compte
|
||||||
profile.security=Sécurité
|
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.services=Catalogue de Services
|
||||||
profile.saved=Profil enregistré
|
profile.saved=Profil enregistré
|
||||||
profile.save.error=Erreur lors de l'enregistrement : {0}
|
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
|
||||||
profile.billing.enabled=Facturation via votianLT
|
profile.billing.enabled=Facturation via votianLT
|
||||||
|
profile.billing.prefix=Préfixe de facture
|
||||||
|
|
||||||
# Profile Validation
|
# Profile Validation
|
||||||
profile.validation.company=L'entreprise est un champ obligatoire
|
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.amount=Montant
|
||||||
profile.invoice.element.line=Ligne
|
profile.invoice.element.line=Ligne
|
||||||
profile.invoice.element.image=Image
|
profile.invoice.element.image=Image
|
||||||
|
profile.invoice.element.invoicenumber=Numéro de facture
|
||||||
profile.invoice.properties=Propriétés
|
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.properties.info=Cliquez sur un élément dans le canevas pour modifier ses propriétés
|
||||||
profile.invoice.type=Type
|
profile.invoice.type=Type
|
||||||
@@ -655,6 +663,21 @@ myinvoices.bank.iban=IBAN
|
|||||||
myinvoices.recipient.name=Client
|
myinvoices.recipient.name=Client
|
||||||
myinvoices.recipient.department=
|
myinvoices.recipient.department=
|
||||||
myinvoices.item.description=Article : {0}
|
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
|
# App User
|
||||||
appuser.title=Utilisateurs d'App
|
appuser.title=Utilisateurs d'App
|
||||||
|
|||||||
@@ -36,8 +36,14 @@ profile.basicdata=Pagrindiniai duomenys
|
|||||||
profile.map=Žemėlapis
|
profile.map=Žemėlapis
|
||||||
profile.invoicecreation=Sąskaitos kūrimas
|
profile.invoicecreation=Sąskaitos kūrimas
|
||||||
profile.settings=Nustatymai
|
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.account=Paskyra
|
||||||
profile.security=Saugumas
|
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.services=Paslaugų katalogas
|
||||||
profile.saved=Profilis išsaugotas
|
profile.saved=Profilis išsaugotas
|
||||||
profile.save.error=Klaida išsaugant: {0}
|
profile.save.error=Klaida išsaugant: {0}
|
||||||
@@ -189,3 +195,29 @@ register.notification.failed=Registracijos klaida: {0}
|
|||||||
|
|
||||||
# CTA Button
|
# 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
|
||||||
@@ -36,8 +36,14 @@ profile.basicdata=Pamatdati
|
|||||||
profile.map=Karte
|
profile.map=Karte
|
||||||
profile.invoicecreation=Rēķina izveide
|
profile.invoicecreation=Rēķina izveide
|
||||||
profile.settings=Iestatījumi
|
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.account=Konts
|
||||||
profile.security=Drošība
|
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.services=Pakalpojumu katalogs
|
||||||
profile.saved=Profils saglabāts
|
profile.saved=Profils saglabāts
|
||||||
profile.save.error=Kļūda saglabājot: {0}
|
profile.save.error=Kļūda saglabājot: {0}
|
||||||
@@ -189,3 +195,29 @@ register.notification.failed=Reģistrācijas kļūda: {0}
|
|||||||
|
|
||||||
# CTA Button
|
# 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
|
||||||
@@ -36,8 +36,14 @@ profile.basicdata=Dane podstawowe
|
|||||||
profile.map=Mapa
|
profile.map=Mapa
|
||||||
profile.invoicecreation=Tworzenie faktury
|
profile.invoicecreation=Tworzenie faktury
|
||||||
profile.settings=Ustawienia
|
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.account=Konto
|
||||||
profile.security=Bezpieczeństwo
|
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.services=Katalog usług
|
||||||
profile.saved=Profil zapisany
|
profile.saved=Profil zapisany
|
||||||
profile.save.error=Błąd podczas zapisywania: {0}
|
profile.save.error=Błąd podczas zapisywania: {0}
|
||||||
@@ -192,3 +198,29 @@ register.notification.failed=Rejestracja nie powiodła się: {0}
|
|||||||
|
|
||||||
# CTA Button
|
# 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
|
||||||
@@ -36,8 +36,14 @@ profile.basicdata=Основные данные
|
|||||||
profile.map=Карта
|
profile.map=Карта
|
||||||
profile.invoicecreation=Создание счета
|
profile.invoicecreation=Создание счета
|
||||||
profile.settings=Настройки
|
profile.settings=Настройки
|
||||||
|
profile.settings.digitalprocess=Цифровая обработка
|
||||||
|
profile.settings.digitalprocess.info=Заказы обрабатываются в цифровом формате через приложение
|
||||||
|
profile.settings.locateappuser=Определить местоположение пользователя
|
||||||
|
profile.settings.locateappuser.info=Местоположение пользователей приложения регулярно передаётся
|
||||||
profile.account=Аккаунт
|
profile.account=Аккаунт
|
||||||
profile.security=Безопасность
|
profile.security=Безопасность
|
||||||
|
profile.security.twofactor=Двухфакторная аутентификация
|
||||||
|
profile.security.twofactor.info=При входе на электронную почту отправляется дополнительный код
|
||||||
profile.services=Каталог услуг
|
profile.services=Каталог услуг
|
||||||
profile.saved=Профиль сохранен
|
profile.saved=Профиль сохранен
|
||||||
profile.save.error=Ошибка сохранения: {0}
|
profile.save.error=Ошибка сохранения: {0}
|
||||||
@@ -212,3 +218,29 @@ register.notification.failed=Ошибка регистрации: {0}
|
|||||||
|
|
||||||
# CTA Button
|
# 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=Далее
|
||||||
@@ -36,8 +36,14 @@ profile.basicdata=Temel Veriler
|
|||||||
profile.map=Harita
|
profile.map=Harita
|
||||||
profile.invoicecreation=Fatura Oluşturma
|
profile.invoicecreation=Fatura Oluşturma
|
||||||
profile.settings=Ayarlar
|
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.account=Hesap
|
||||||
profile.security=Güvenlik
|
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.services=Hizmet Kataloğu
|
||||||
profile.saved=Profil kaydedildi
|
profile.saved=Profil kaydedildi
|
||||||
profile.save.error=Kaydetme hatası: {0}
|
profile.save.error=Kaydetme hatası: {0}
|
||||||
@@ -186,3 +192,29 @@ register.notification.failed=Kayıt başarısız: {0}
|
|||||||
|
|
||||||
# CTA Button
|
# 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=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
|
||||||
Reference in New Issue
Block a user