From c44fc7f63e0b18acad4de66bc340d53ed2046e72 Mon Sep 17 00:00:00 2001 From: Andreas Knuth Date: Fri, 20 Feb 2026 12:16:34 -0600 Subject: [PATCH] update sync endpoint --- server.js | 66 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/server.js b/server.js index bb71b02..a946d7c 100644 --- a/server.js +++ b/server.js @@ -2062,13 +2062,13 @@ app.get('/api/qbo/labor-rate', async (req, res) => { app.post('/api/qbo/sync-payments', async (req, res) => { const dbClient = await pool.connect(); try { - // Alle lokalen Invoices die in QBO sind aber noch nicht voll bezahlt + // Alle lokalen Invoices die in QBO sind und noch aktualisiert werden könnten + // Auch bereits bezahlte prüfen um payment_status zu korrigieren (Paid↔Deposited) const openResult = await dbClient.query(` SELECT i.id, i.qbo_id, i.invoice_number, i.total, i.paid_date, i.payment_status, COALESCE((SELECT SUM(pi.amount) FROM payment_invoices pi WHERE pi.invoice_id = i.id), 0) as local_paid FROM invoices i WHERE i.qbo_id IS NOT NULL - AND (i.paid_date IS NULL OR i.payment_status IS NULL OR i.payment_status != 'Deposited') `); const openInvoices = openResult.rows; @@ -2119,9 +2119,8 @@ app.post('/api/qbo/sync-payments', async (req, res) => { // Prüfe ob in QBO bezahlt/teilweise bezahlt if (qboBalance === 0 && qboTotal > 0) { // Voll bezahlt in QBO - // Prüfe ob "Deposited" — DepositToAccountRef != Undeposited Funds (221) - let status = 'Paid'; const UNDEPOSITED_FUNDS_ID = '221'; + let status = 'Paid'; if (qboInv.LinkedTxn) { for (const txn of qboInv.LinkedTxn) { @@ -2142,27 +2141,27 @@ app.post('/api/qbo/sync-payments', async (req, res) => { } } - // paid_date setzen falls noch nicht - if (!localInv.paid_date) { + // Update wenn sich etwas geändert hat + const needsUpdate = !localInv.paid_date || localInv.payment_status !== status; + if (needsUpdate) { await dbClient.query( - 'UPDATE invoices SET paid_date = CURRENT_DATE, payment_status = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2', - [status, localInv.id] - ); - } else { - await dbClient.query( - 'UPDATE invoices SET payment_status = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2', + `UPDATE invoices SET + paid_date = COALESCE(paid_date, CURRENT_DATE), + payment_status = $1, + updated_at = CURRENT_TIMESTAMP + WHERE id = $2`, [status, localInv.id] ); + updated++; + console.log(` ✅ #${localInv.invoice_number}: ${status}`); } - // Fehlenden lokalen Payment-Eintrag erstellen wenn nötig - const qboPaid = qboTotal; - if (qboPaid > localPaid) { - const diff = qboPaid - localPaid; - // Einen generischen Payment-Eintrag für den Differenzbetrag + // Fehlenden Payment-Eintrag NUR erstellen wenn Differenz > $0.01 + const diff = qboTotal - localPaid; + if (diff > 0.01) { const payResult = await dbClient.query( `INSERT INTO payments (payment_date, payment_method, total_amount, customer_id, notes, created_at) - VALUES (CURRENT_DATE, 'Synced from QBO', $1, (SELECT customer_id FROM invoices WHERE id = $2), 'Auto-synced from QBO', CURRENT_TIMESTAMP) + VALUES (CURRENT_DATE, 'Synced from QBO', $1, (SELECT customer_id FROM invoices WHERE id = $2), 'Synced from QBO', CURRENT_TIMESTAMP) RETURNING id`, [diff, localInv.id] ); @@ -2171,19 +2170,28 @@ app.post('/api/qbo/sync-payments', async (req, res) => { [payResult.rows[0].id, localInv.id, diff] ); newPayments++; + console.log(` 💰 #${localInv.invoice_number}: +$${diff.toFixed(2)} payment synced`); } - console.log(` ✅ #${localInv.invoice_number}: ${status} (QBO Balance: $${qboBalance})`); - updated++; - } else if (qboBalance > 0 && qboBalance < qboTotal) { // Teilweise bezahlt in QBO const qboPaid = qboTotal - qboBalance; - if (qboPaid > localPaid) { - const diff = qboPaid - localPaid; + const diff = qboPaid - localPaid; + + const needsUpdate = localInv.payment_status !== 'Partial'; + if (needsUpdate) { + await dbClient.query( + 'UPDATE invoices SET payment_status = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2', + ['Partial', localInv.id] + ); + updated++; + } + + // Payment nur erstellen wenn echte Differenz > $0.01 + if (diff > 0.01) { const payResult = await dbClient.query( `INSERT INTO payments (payment_date, payment_method, total_amount, customer_id, notes, created_at) - VALUES (CURRENT_DATE, 'Synced from QBO', $1, (SELECT customer_id FROM invoices WHERE id = $2), 'Auto-synced partial from QBO', CURRENT_TIMESTAMP) + VALUES (CURRENT_DATE, 'Synced from QBO', $1, (SELECT customer_id FROM invoices WHERE id = $2), 'Synced from QBO', CURRENT_TIMESTAMP) RETURNING id`, [diff, localInv.id] ); @@ -2191,15 +2199,8 @@ app.post('/api/qbo/sync-payments', async (req, res) => { 'INSERT INTO payment_invoices (payment_id, invoice_id, amount) VALUES ($1, $2, $3)', [payResult.rows[0].id, localInv.id, diff] ); - - await dbClient.query( - 'UPDATE invoices SET payment_status = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2', - ['Partial', localInv.id] - ); - - console.log(` 📎 #${localInv.invoice_number}: Partial ($${qboPaid.toFixed(2)} of $${qboTotal.toFixed(2)})`); - updated++; newPayments++; + console.log(` 📎 #${localInv.invoice_number}: Partial +$${diff.toFixed(2)} ($${qboPaid.toFixed(2)} of $${qboTotal.toFixed(2)})`); } } } @@ -2241,6 +2242,7 @@ app.get('/api/qbo/last-sync', async (req, res) => { }); + // Start server and browser async function startServer() { await initBrowser();