diff --git a/app/src/app.js b/app/src/app.js
index 0da4b43..a7121cd 100644
--- a/app/src/app.js
+++ b/app/src/app.js
@@ -480,6 +480,20 @@ app.delete('/api/invoices', requireAuth, async (req, res, next) => {
});
const pdfText = (value) => String(value || 'Neuvedeno');
+const formatCzechDate = (value) => {
+ const date = new Date(`${value}T00:00:00`);
+ return Number.isNaN(date.getTime()) ? '' : date.toLocaleDateString('cs-CZ');
+};
+const toDateInputValue = (date) => date.toISOString().slice(0, 10);
+const resolveIssueDate = (issueDate) => issueDate || toDateInputValue(new Date());
+const resolveDueDate = (dueDate, issueDate) => {
+ if (dueDate) {
+ return dueDate;
+ }
+ const due = new Date(`${resolveIssueDate(issueDate)}T00:00:00`);
+ due.setDate(due.getDate() + 14);
+ return toDateInputValue(due);
+};
const formatCzechNumber = (value) => Number(value || 0).toLocaleString('cs-CZ', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
@@ -554,13 +568,25 @@ const renderInvoicePdf = async (document, invoice) => {
const partyWidth = (pageWidth - 24) / 2;
const customerX = document.page.margins.left + partyWidth + 24;
+ const issueDate = resolveIssueDate(data.issueDate);
+ const dueDate = resolveDueDate(data.dueDate, data.issueDate);
+
const headerY = document.y;
document.fillColor(navy).font(boldFont).fontSize(25).text('Faktura', document.page.margins.left, headerY);
document.fillColor(navy).font(boldFont).fontSize(16).text(invoice.invoice_number, customerX, headerY, {
width: partyWidth,
align: 'right'
});
- document.y = headerY + 40;
+ document.fillColor(bodyText).font(regularFont).fontSize(9)
+ .text(`Datum vystavení: ${formatCzechDate(issueDate)}`, customerX, headerY + 22, {
+ width: partyWidth,
+ align: 'right'
+ })
+ .text(`Datum splatnosti: ${formatCzechDate(dueDate)}`, customerX, headerY + 35, {
+ width: partyWidth,
+ align: 'right'
+ });
+ document.y = headerY + 52;
const partyTop = document.y;
const drawParty = (x, title, profile, name) => {
diff --git a/app/src/static/index.html b/app/src/static/index.html
index d7ab60d..7f9c63e 100644
--- a/app/src/static/index.html
+++ b/app/src/static/index.html
@@ -325,13 +325,13 @@
diff --git a/app/src/static/script.js b/app/src/static/script.js
index d45cc68..241f0b3 100644
--- a/app/src/static/script.js
+++ b/app/src/static/script.js
@@ -46,8 +46,8 @@ const invoiceStartingNumberInput = document.getElementById("invoiceStartingNumbe
const saveNumberingSettingsButton = document.getElementById("saveNumberingSettingsButton");
const cancelNumberingSettingsButton = document.getElementById("cancelNumberingSettingsButton");
const numberingSettingsStatus = document.getElementById("numberingSettingsStatus");
-const dueDateOption = document.getElementById("dueDateOption");
-const dueDateDisplay = document.getElementById("dueDateDisplay");
+const issueDateInput = document.getElementById("issueDate");
+const dueDateInput = document.getElementById("dueDate");
const paymentPresetSelect = document.getElementById("paymentPresetSelect");
const paymentPresetName = document.getElementById("paymentPresetName");
const savePaymentPresetButton = document.getElementById("savePaymentPresetButton");
@@ -207,17 +207,17 @@ const getClientLabel = (client) => [
const formatCzechDate = (dateValue) => new Date(`${dateValue}T00:00:00`).toLocaleDateString("cs-CZ");
-const getDueDays = () => Number.parseInt(dueDateOption.value, 10) || 14;
+const toDateInputValue = (date) => date.toISOString().slice(0, 10);
+
+const getIssueDate = () => issueDateInput.value || toDateInputValue(new Date());
const getDueDate = () => {
- const dueDate = new Date();
- dueDate.setHours(0, 0, 0, 0);
- dueDate.setDate(dueDate.getDate() + getDueDays());
- return dueDate.toISOString().slice(0, 10);
-};
-
-const updateDueDate = () => {
- dueDateDisplay.textContent = `Splatnost: ${formatCzechDate(getDueDate())}`;
+ if (dueDateInput.value) {
+ return dueDateInput.value;
+ }
+ const dueDate = new Date(`${getIssueDate()}T00:00:00`);
+ dueDate.setDate(dueDate.getDate() + 14);
+ return toDateInputValue(dueDate);
};
const updateClientTypeFields = () => {
@@ -333,6 +333,8 @@ deletePaymentPresetButton.addEventListener("click", async () => {
});
const readInvoiceData = () => ({
+ issueDate: getIssueDate(),
+ dueDate: getDueDate(),
supplier: {
...readProfileFields("dodavatel"),
typSubjektu: supplierTypeSelect.value
@@ -363,6 +365,8 @@ const clearInvoiceEditor = () => {
currentInvoiceId = null;
invoiceNumberDisplay.textContent = "Nová faktura";
invoiceSaveStatus.textContent = "";
+ issueDateInput.value = "";
+ dueDateInput.value = "";
writeProfileFields("odberatel", {});
clientSelect.value = "";
clientTypeSelect.value = "osoba";
@@ -384,6 +388,8 @@ const loadInvoiceIntoEditor = (invoice) => {
currentInvoiceId = invoice.id;
invoiceNumberDisplay.textContent = invoice.invoiceNumber;
invoiceSaveStatus.textContent = "";
+ issueDateInput.value = invoice.data.issueDate || "";
+ dueDateInput.value = invoice.data.dueDate || "";
writeProfileFields("dodavatel", invoice.data.supplier || {});
supplierTypeSelect.value = invoice.data.supplier?.typSubjektu || "osoba";
updateSupplierTypeFields();