From e00b748927e1356bd8fab78bd189b52064069388 Mon Sep 17 00:00:00 2001 From: Andreas Knuth Date: Fri, 1 May 2026 17:05:41 -0500 Subject: [PATCH] fix --- public/js/modals/email-modal.js | 23 ++++++++++---------- public/js/views/invoice-view.js | 38 ++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/public/js/modals/email-modal.js b/public/js/modals/email-modal.js index 3a4d92a..3bcfb2b 100644 --- a/public/js/modals/email-modal.js +++ b/public/js/modals/email-modal.js @@ -43,16 +43,20 @@ function parseLocalDate(dateValue) { return Number.isNaN(d.getTime()) ? null : d; } -function getLastSentDate(invoice) { +function getFirstSentDate(invoice) { const sentDates = Array.isArray(invoice.sent_dates) ? invoice.sent_dates.filter(Boolean) : []; - if (sentDates.length > 0) { - return sentDates[sentDates.length - 1]; + if (sentDates.length === 0) { + return null; } - return null; + const sortedDates = sentDates + .map(d => String(d).split('T')[0]) + .sort(); + + return sortedDates[0]; } function getTermDays(invoice) { @@ -79,18 +83,13 @@ function addDays(dateValue, days) { } function getEffectiveDueDate(invoice) { - const lastSentDate = getLastSentDate(invoice); + const firstSentDate = getFirstSentDate(invoice); - // Nie versendet = kein Reminder/Overdue Text - if (!lastSentDate) { + if (!firstSentDate) { return null; } - if (invoice.due_date) { - return parseLocalDate(invoice.due_date); - } - - return addDays(lastSentDate, getTermDays(invoice)); + return addDays(firstSentDate, getTermDays(invoice)); } function getOverdueDays(invoice) { diff --git a/public/js/views/invoice-view.js b/public/js/views/invoice-view.js index 6e53550..af360c8 100644 --- a/public/js/views/invoice-view.js +++ b/public/js/views/invoice-view.js @@ -87,14 +87,22 @@ function isPartiallyPaid(inv) { return !inv.paid_date && amountPaid > 0 && balance > 0; } -function getLastSentDate(inv) { - const sentDates = Array.isArray(inv.sent_dates) ? inv.sent_dates.filter(Boolean) : []; +function getFirstSentDate(inv) { + const sentDates = Array.isArray(inv.sent_dates) + ? inv.sent_dates.filter(Boolean) + : []; - if (sentDates.length > 0) { - return sentDates[sentDates.length - 1]; + if (sentDates.length === 0) { + return null; } - return null; + // Sicherheit: nicht auf Array-Reihenfolge verlassen, + // sondern wirklich das früheste Versanddatum nehmen. + const sortedDates = sentDates + .map(d => String(d).split('T')[0]) + .sort(); + + return sortedDates[0]; } function getTermDays(inv) { @@ -132,22 +140,18 @@ function isBeforeToday(dateObj) { return compare < today; } - function getEffectiveDueDate(inv) { - const lastSentDate = getLastSentDate(inv); + const firstSentDate = getFirstSentDate(inv); - // Wichtig: Nie versendete Rechnungen können nicht overdue sein. - if (!lastSentDate) { + // Nie versendet = nicht overdue + if (!firstSentDate) { return null; } - // Wenn due_date vorhanden ist, darf es genutzt werden, - // aber nur nachdem die Rechnung tatsächlich gesendet wurde. - if (inv.due_date) { - return parseLocalDate(inv.due_date); - } - - return addDays(lastSentDate, getTermDays(inv)); + // WICHTIG: + // Für Overdue zählt der erste tatsächliche Versand. + // Bei Net 30 also first_sent_date + 30 Tage. + return addDays(firstSentDate, getTermDays(inv)); } function getOverdueDays(inv) { @@ -166,7 +170,7 @@ function isOverdue(inv) { return !!inv.qbo_id && !isPaid(inv) && !isPartiallyPaid(inv) - && !!getLastSentDate(inv) + && !!getFirstSentDate(inv) && isBeforeToday(getEffectiveDueDate(inv)); }