update sync endpoint

This commit is contained in:
Andreas Knuth 2026-02-20 12:16:34 -06:00
parent 4e6429e9ac
commit c44fc7f63e
1 changed files with 34 additions and 32 deletions

View File

@ -2062,13 +2062,13 @@ app.get('/api/qbo/labor-rate', async (req, res) => {
app.post('/api/qbo/sync-payments', async (req, res) => { app.post('/api/qbo/sync-payments', async (req, res) => {
const dbClient = await pool.connect(); const dbClient = await pool.connect();
try { 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(` const openResult = await dbClient.query(`
SELECT i.id, i.qbo_id, i.invoice_number, i.total, i.paid_date, i.payment_status, 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 COALESCE((SELECT SUM(pi.amount) FROM payment_invoices pi WHERE pi.invoice_id = i.id), 0) as local_paid
FROM invoices i FROM invoices i
WHERE i.qbo_id IS NOT NULL 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; 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 // Prüfe ob in QBO bezahlt/teilweise bezahlt
if (qboBalance === 0 && qboTotal > 0) { if (qboBalance === 0 && qboTotal > 0) {
// Voll bezahlt in QBO // Voll bezahlt in QBO
// Prüfe ob "Deposited" — DepositToAccountRef != Undeposited Funds (221)
let status = 'Paid';
const UNDEPOSITED_FUNDS_ID = '221'; const UNDEPOSITED_FUNDS_ID = '221';
let status = 'Paid';
if (qboInv.LinkedTxn) { if (qboInv.LinkedTxn) {
for (const txn of 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 // Update wenn sich etwas geändert hat
if (!localInv.paid_date) { const needsUpdate = !localInv.paid_date || localInv.payment_status !== status;
if (needsUpdate) {
await dbClient.query( await dbClient.query(
'UPDATE invoices SET paid_date = CURRENT_DATE, payment_status = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2', `UPDATE invoices SET
[status, localInv.id] paid_date = COALESCE(paid_date, CURRENT_DATE),
); payment_status = $1,
} else { updated_at = CURRENT_TIMESTAMP
await dbClient.query( WHERE id = $2`,
'UPDATE invoices SET payment_status = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2',
[status, localInv.id] [status, localInv.id]
); );
updated++;
console.log(` ✅ #${localInv.invoice_number}: ${status}`);
} }
// Fehlenden lokalen Payment-Eintrag erstellen wenn nötig // Fehlenden Payment-Eintrag NUR erstellen wenn Differenz > $0.01
const qboPaid = qboTotal; const diff = qboTotal - localPaid;
if (qboPaid > localPaid) { if (diff > 0.01) {
const diff = qboPaid - localPaid;
// Einen generischen Payment-Eintrag für den Differenzbetrag
const payResult = await dbClient.query( const payResult = await dbClient.query(
`INSERT INTO payments (payment_date, payment_method, total_amount, customer_id, notes, created_at) `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`, RETURNING id`,
[diff, localInv.id] [diff, localInv.id]
); );
@ -2171,19 +2170,28 @@ app.post('/api/qbo/sync-payments', async (req, res) => {
[payResult.rows[0].id, localInv.id, diff] [payResult.rows[0].id, localInv.id, diff]
); );
newPayments++; 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) { } else if (qboBalance > 0 && qboBalance < qboTotal) {
// Teilweise bezahlt in QBO // Teilweise bezahlt in QBO
const qboPaid = qboTotal - qboBalance; 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( const payResult = await dbClient.query(
`INSERT INTO payments (payment_date, payment_method, total_amount, customer_id, notes, created_at) `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`, RETURNING id`,
[diff, localInv.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)', 'INSERT INTO payment_invoices (payment_id, invoice_id, amount) VALUES ($1, $2, $3)',
[payResult.rows[0].id, localInv.id, diff] [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++; 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 // Start server and browser
async function startServer() { async function startServer() {
await initBrowser(); await initBrowser();