diff --git a/public/js/modals/expense-modal.js b/public/js/modals/expense-modal.js index a703853..450ebfc 100644 --- a/public/js/modals/expense-modal.js +++ b/public/js/modals/expense-modal.js @@ -33,6 +33,7 @@ let isSaving = false; let selectedFile = null; // File object aus let attachmentLimits = null; // { maxBytes, maxMb, allowedMimeTypes, allowedExtensions } +let editingExpenseId = null; // null = Create-Modus, sonst = Purchase-ID im Edit-Modus // ──────────────────────────────────────────────────────────────────── // Helpers // ──────────────────────────────────────────────────────────────────── @@ -138,14 +139,14 @@ function renderFilePreview() { // Public Entry // ──────────────────────────────────────────────────────────────────── -export async function openExpenseModal({ onSaved } = {}) { +export async function openExpenseModal({ onSaved, expense = null } = {}) { onSavedCb = onSaved || null; selectedVendorId = null; selectedVendorName = ''; lineCount = 0; isSaving = false; + editingExpenseId = expense ? expense.id : null; - // Lade Stammdaten parallel (alles aus dem Cache → schnell) try { [vendors, expenseAccounts, paymentAccounts, paymentMethods, attachmentLimits] = await Promise.all([ window.API.accounting.getVendors('', 1000), @@ -155,7 +156,6 @@ export async function openExpenseModal({ onSaved } = {}) { window.API.accounting.getAttachmentLimits() ]); - // Errors aus dem Backend abfangen for (const [name, data] of [['vendors', vendors], ['expenseAccounts', expenseAccounts], ['paymentAccounts', paymentAccounts], ['paymentMethods', paymentMethods]]) { if (data && data.error) { alert(`Failed to load ${name}: ${data.error}\n\nTry "Sync from QBO" first.`); @@ -168,6 +168,11 @@ export async function openExpenseModal({ onSaved } = {}) { } renderModal(); + + // Im Edit-Modus: Formular mit bestehenden Daten befüllen + if (expense) { + prefillForm(expense); + } } function closeModal() { @@ -192,6 +197,43 @@ function resetForm() { updateTotal(); } +function prefillForm(expense) { + // Vendor + if (expense.vendorId) { + selectVendor(expense.vendorId, expense.vendorName || expense.vendorId); + } + // Payment Account + if (expense.accountId) { + const pa = document.getElementById('exp-payment-account'); + if (pa) pa.value = expense.accountId; + } + // Datum + if (expense.txnDate) { + document.getElementById('exp-date').value = expense.txnDate; + } + // Payment Method + if (expense.paymentMethodId) { + const pm = document.getElementById('exp-payment-method'); + if (pm) pm.value = expense.paymentMethodId; + } + // Ref / Memo + if (expense.refNo) document.getElementById('exp-ref-no').value = expense.refNo; + if (expense.memo) document.getElementById('exp-memo').value = expense.memo; + + // Lines — bestehende Zeilen ersetzen + document.getElementById('exp-lines-tbody').innerHTML = ''; + lineCount = 0; + const lines = expense.lines && expense.lines.length ? expense.lines : [{}]; + lines.forEach(l => { + addLine(); + const rows = document.querySelectorAll('#exp-lines-tbody tr'); + const tr = rows[rows.length - 1]; + if (l.accountId) tr.querySelector('.exp-line-account').value = l.accountId; + if (l.description) tr.querySelector('.exp-line-desc').value = l.description; + if (l.amount != null) tr.querySelector('.exp-line-amount').value = l.amount; + }); + updateTotal(); +} // ──────────────────────────────────────────────────────────────────── // Render // ──────────────────────────────────────────────────────────────────── @@ -203,7 +245,7 @@ function renderModal() {