// payment-modal.js — ES Module für das Payment Recording Modal // Ermöglicht: Auswahl mehrerer Rechnungen, Check/ACH, Deposit To Konto // ============================================================ // State // ============================================================ let bankAccounts = []; let paymentMethods = []; let selectedInvoices = []; // Array of invoice objects let isOpen = false; // Cache QBO reference data (nur einmal laden) let dataLoaded = false; // ============================================================ // Load QBO Reference Data // ============================================================ async function loadQboData() { if (dataLoaded) return; try { const [accRes, pmRes] = await Promise.all([ fetch('/api/qbo/accounts'), fetch('/api/qbo/payment-methods') ]); if (accRes.ok) bankAccounts = await accRes.json(); if (pmRes.ok) paymentMethods = await pmRes.json(); dataLoaded = true; } catch (error) { console.error('Error loading QBO reference data:', error); } } // ============================================================ // Open / Close Modal // ============================================================ export async function openPaymentModal(invoiceIds = []) { // Lade QBO-Daten falls noch nicht geschehen await loadQboData(); // Lade die ausgewählten Rechnungen if (invoiceIds.length > 0) { selectedInvoices = []; for (const id of invoiceIds) { try { const res = await fetch(`/api/invoices/${id}`); const data = await res.json(); if (data.invoice) { selectedInvoices.push(data.invoice); } } catch (e) { console.error('Error loading invoice:', id, e); } } } renderModal(); document.getElementById('payment-modal').classList.add('active'); isOpen = true; } export function closePaymentModal() { const modal = document.getElementById('payment-modal'); if (modal) modal.classList.remove('active'); isOpen = false; selectedInvoices = []; } // ============================================================ // Add/Remove Invoices from selection // ============================================================ export async function addInvoiceToPayment(invoiceId) { if (selectedInvoices.find(inv => inv.id === invoiceId)) return; // already selected try { const res = await fetch(`/api/invoices/${invoiceId}`); const data = await res.json(); if (data.invoice) { // Validierung: Muss QBO-verknüpft sein if (!data.invoice.qbo_id) { alert('Diese Rechnung ist noch nicht in QBO. Bitte erst exportieren.'); return; } // Validierung: Alle müssen zum selben Kunden gehören if (selectedInvoices.length > 0 && data.invoice.customer_id !== selectedInvoices[0].customer_id) { alert('Alle Rechnungen eines Payments müssen zum selben Kunden gehören.'); return; } selectedInvoices.push(data.invoice); renderInvoiceList(); updateTotal(); } } catch (e) { console.error('Error adding invoice:', e); } } function removeInvoiceFromPayment(invoiceId) { selectedInvoices = selectedInvoices.filter(inv => inv.id !== invoiceId); renderInvoiceList(); updateTotal(); } // ============================================================ // Rendering // ============================================================ function renderModal() { let modal = document.getElementById('payment-modal'); if (!modal) { modal = document.createElement('div'); modal.id = 'payment-modal'; modal.className = 'modal-overlay'; document.body.appendChild(modal); } const accountOptions = bankAccounts.map(acc => `` ).join(''); const methodOptions = paymentMethods .filter(pm => ['Check', 'ACH'].includes(pm.name) || pm.name.toLowerCase().includes('check') || pm.name.toLowerCase().includes('ach')) .map(pm => ``) .join(''); // Falls keine Filter-Treffer, alle anzeigen const allMethodOptions = paymentMethods.map(pm => `` ).join(''); const today = new Date().toISOString().split('T')[0]; modal.innerHTML = `
`; renderInvoiceList(); updateTotal(); } function renderInvoiceList() { const container = document.getElementById('payment-invoice-list'); if (!container) return; if (selectedInvoices.length === 0) { container.innerHTML = `