fix recurring
This commit is contained in:
@@ -98,9 +98,20 @@ async function loadInvoiceForEdit(invoiceId) {
|
|||||||
const recurringInterval = document.getElementById('invoice-recurring-interval');
|
const recurringInterval = document.getElementById('invoice-recurring-interval');
|
||||||
const recurringGroup = document.getElementById('invoice-recurring-group');
|
const recurringGroup = document.getElementById('invoice-recurring-group');
|
||||||
if (recurringCb) {
|
if (recurringCb) {
|
||||||
recurringCb.checked = data.invoice.is_recurring || false;
|
const isGeneratedRecurringChild = !!data.invoice.recurring_source_id;
|
||||||
if (recurringInterval) recurringInterval.value = data.invoice.recurring_interval || 'monthly';
|
const canBeRecurringMaster = !isGeneratedRecurringChild;
|
||||||
if (recurringGroup) recurringGroup.style.display = data.invoice.is_recurring ? 'block' : 'none';
|
|
||||||
|
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
|
// 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]
|
[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(
|
// Preserve existing next_recurring_date when editing an already-recurring invoice.
|
||||||
'UPDATE invoices SET is_recurring = $1, recurring_interval = $2, next_recurring_date = $3 WHERE id = $4',
|
// Otherwise editing an old invoice can move next_recurring_date backwards and create duplicates.
|
||||||
[is_recurring || false, recurring_interval || null, next_recurring_date, id]
|
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
|
// Delete and re-insert items
|
||||||
await client.query('DELETE FROM invoice_items WHERE invoice_id = $1', [id]);
|
await client.query('DELETE FROM invoice_items WHERE invoice_id = $1', [id]);
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user