fix recurring
This commit is contained in:
@@ -98,9 +98,20 @@ async function loadInvoiceForEdit(invoiceId) {
|
||||
const recurringInterval = document.getElementById('invoice-recurring-interval');
|
||||
const recurringGroup = document.getElementById('invoice-recurring-group');
|
||||
if (recurringCb) {
|
||||
recurringCb.checked = data.invoice.is_recurring || false;
|
||||
if (recurringInterval) recurringInterval.value = data.invoice.recurring_interval || 'monthly';
|
||||
if (recurringGroup) recurringGroup.style.display = data.invoice.is_recurring ? 'block' : 'none';
|
||||
const isGeneratedRecurringChild = !!data.invoice.recurring_source_id;
|
||||
const canBeRecurringMaster = !isGeneratedRecurringChild;
|
||||
|
||||
recurringCb.checked = canBeRecurringMaster && (data.invoice.is_recurring || false);
|
||||
recurringCb.disabled = !canBeRecurringMaster;
|
||||
|
||||
if (recurringInterval) {
|
||||
recurringInterval.value = data.invoice.recurring_interval || 'monthly';
|
||||
recurringInterval.disabled = !canBeRecurringMaster;
|
||||
}
|
||||
|
||||
if (recurringGroup) {
|
||||
recurringGroup.style.display = recurringCb.checked ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Load items
|
||||
|
||||
@@ -269,11 +269,46 @@ router.put('/:id', async (req, res) => {
|
||||
[customer_id, invoice_date, terms, auth_code, tax_exempt, tax_rate, subtotal, tax_amount, total, scheduled_send_date || null, bill_to_name || null, id]
|
||||
);
|
||||
}
|
||||
const next_recurring_date = is_recurring ? calculateNextRecurringDate(invoice_date, recurring_interval) : null;
|
||||
await client.query(
|
||||
'UPDATE invoices SET is_recurring = $1, recurring_interval = $2, next_recurring_date = $3 WHERE id = $4',
|
||||
[is_recurring || false, recurring_interval || null, next_recurring_date, id]
|
||||
|
||||
// Preserve existing next_recurring_date when editing an already-recurring invoice.
|
||||
// Otherwise editing an old invoice can move next_recurring_date backwards and create duplicates.
|
||||
const existingRecurringResult = await client.query(
|
||||
'SELECT is_recurring, next_recurring_date, recurring_source_id FROM invoices WHERE id = $1',
|
||||
[id]
|
||||
);
|
||||
|
||||
const existingRecurring = existingRecurringResult.rows[0];
|
||||
|
||||
let next_recurring_date = null;
|
||||
|
||||
// Automatically generated child invoices should not become recurring masters.
|
||||
// recurring_source_id != null means: this invoice was created from another recurring invoice.
|
||||
const isGeneratedRecurringChild = !!existingRecurring?.recurring_source_id;
|
||||
|
||||
if (isGeneratedRecurringChild) {
|
||||
next_recurring_date = null;
|
||||
} else if (is_recurring) {
|
||||
next_recurring_date = existingRecurring?.next_recurring_date
|
||||
? existingRecurring.next_recurring_date
|
||||
: calculateNextRecurringDate(invoice_date, recurring_interval);
|
||||
}
|
||||
|
||||
await client.query(
|
||||
`
|
||||
UPDATE invoices
|
||||
SET is_recurring = $1,
|
||||
recurring_interval = $2,
|
||||
next_recurring_date = $3
|
||||
WHERE id = $4
|
||||
`,
|
||||
[
|
||||
isGeneratedRecurringChild ? false : (is_recurring || false),
|
||||
isGeneratedRecurringChild ? null : (recurring_interval || null),
|
||||
next_recurring_date,
|
||||
id
|
||||
]
|
||||
);
|
||||
|
||||
// Delete and re-insert items
|
||||
await client.query('DELETE FROM invoice_items WHERE invoice_id = $1', [id]);
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
|
||||
Reference in New Issue
Block a user