better states
This commit is contained in:
@@ -25,6 +25,98 @@ function getEmailModalTitle(invoice, isOverdue) {
|
||||
if (invoice.email_status === 'sent') return `🔁 Resend Invoice #${invoice.invoice_number || invoice.id}`;
|
||||
return `📤 Send Invoice #${invoice.invoice_number || invoice.id}`;
|
||||
}
|
||||
function parseLocalDate(dateValue) {
|
||||
if (!dateValue) return null;
|
||||
|
||||
if (dateValue instanceof Date) {
|
||||
return new Date(dateValue.getFullYear(), dateValue.getMonth(), dateValue.getDate());
|
||||
}
|
||||
|
||||
const dateStr = String(dateValue).split('T')[0];
|
||||
const parts = dateStr.split('-').map(Number);
|
||||
|
||||
if (parts.length === 3 && parts.every(Number.isFinite)) {
|
||||
return new Date(parts[0], parts[1] - 1, parts[2]);
|
||||
}
|
||||
|
||||
const d = new Date(dateValue);
|
||||
return Number.isNaN(d.getTime()) ? null : d;
|
||||
}
|
||||
|
||||
function getLastSentDate(invoice) {
|
||||
const sentDates = Array.isArray(invoice.sent_dates)
|
||||
? invoice.sent_dates.filter(Boolean)
|
||||
: [];
|
||||
|
||||
if (sentDates.length > 0) {
|
||||
return sentDates[sentDates.length - 1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getTermDays(invoice) {
|
||||
const terms = String(invoice.terms || '').toLowerCase();
|
||||
|
||||
if (terms.includes('due on receipt') || terms.includes('upon receipt')) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const match = terms.match(/net\s*(\d+)/i);
|
||||
if (match) {
|
||||
return parseInt(match[1], 10);
|
||||
}
|
||||
|
||||
return 30;
|
||||
}
|
||||
|
||||
function addDays(dateValue, days) {
|
||||
const d = parseLocalDate(dateValue);
|
||||
if (!d) return null;
|
||||
|
||||
d.setDate(d.getDate() + days);
|
||||
return d;
|
||||
}
|
||||
|
||||
function getEffectiveDueDate(invoice) {
|
||||
const lastSentDate = getLastSentDate(invoice);
|
||||
|
||||
// Nie versendet = kein Reminder/Overdue Text
|
||||
if (!lastSentDate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (invoice.due_date) {
|
||||
return parseLocalDate(invoice.due_date);
|
||||
}
|
||||
|
||||
return addDays(lastSentDate, getTermDays(invoice));
|
||||
}
|
||||
|
||||
function getOverdueDays(invoice) {
|
||||
const dueDate = getEffectiveDueDate(invoice);
|
||||
if (!dueDate) return 0;
|
||||
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
dueDate.setHours(0, 0, 0, 0);
|
||||
|
||||
return Math.max(0, Math.floor((today - dueDate) / 86400000));
|
||||
}
|
||||
|
||||
function isInvoiceOverdue(invoice) {
|
||||
const dueDate = getEffectiveDueDate(invoice);
|
||||
if (!dueDate) return false;
|
||||
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
dueDate.setHours(0, 0, 0, 0);
|
||||
|
||||
return !invoice.paid_date && dueDate < today;
|
||||
}
|
||||
|
||||
function renderModalContent() {
|
||||
const modal = document.getElementById('email-modal');
|
||||
if (!modal) return;
|
||||
@@ -34,13 +126,8 @@ function renderModalContent() {
|
||||
const stripeStatus = currentInvoice.stripe_payment_status || '';
|
||||
|
||||
// Detect overdue: unpaid + older than 30 days
|
||||
const invoiceDateParsed = currentInvoice.invoice_date
|
||||
? new Date(currentInvoice.invoice_date.split('T')[0])
|
||||
: null;
|
||||
const daysSinceInvoice = invoiceDateParsed
|
||||
? Math.floor((new Date() - invoiceDateParsed) / 86400000)
|
||||
: 0;
|
||||
const isOverdue = !currentInvoice.paid_date && daysSinceInvoice > 30;
|
||||
const isOverdue = isInvoiceOverdue(currentInvoice);
|
||||
const daysOverdue = getOverdueDays(currentInvoice);
|
||||
|
||||
const modalTitle = getEmailModalTitle(currentInvoice, isOverdue);
|
||||
|
||||
@@ -159,7 +246,7 @@ function renderModalContent() {
|
||||
defaultHtml = `
|
||||
<p>Dear ${customerName},</p>
|
||||
<p>We hope this message finds you well. Our records indicate that invoice <strong>#${invoiceNum}</strong> in the amount of <strong>$${totalDue}</strong>, dated ${formatDate(currentInvoice.invoice_date)}, remains unpaid.</p>
|
||||
<p>This invoice is now <strong>${daysSinceInvoice} days past the invoice date</strong>. We kindly request prompt payment at your earliest convenience.</p>
|
||||
<p>This invoice is now <strong>${daysOverdue} days overdue</strong>. We kindly request prompt payment at your earliest convenience.</p>
|
||||
<p>For your convenience, you can pay securely online using the payment link included below. We accept both Credit Card and ACH bank transfer.</p>
|
||||
<p>If payment has already been sent, please disregard this notice. Should you have any questions or need to discuss payment arrangements, please do not hesitate to reply to this email.</p>
|
||||
<p>Thank you for your attention to this matter. We value your business and look forward to continuing our partnership.</p>
|
||||
|
||||
Reference in New Issue
Block a user