'use strict'; // Canonical writers for a transaction's match state. // // A transaction's match state lives in three columns that must move together: // match_status 'unmatched' | 'matched' | 'ignored' // matched_bill_id the bill when matched, else NULL // ignored 1 when explicitly ignored, else 0 // // These were previously updated by copy-pasted inline UPDATEs across routes and // services, which is exactly how they drift out of sync — e.g. QA-B5-04, where a // bill purge left match_status='matched' with a NULL bill. Routing every // single-transaction transition through these helpers keeps the columns // consistent by construction. All are ownership-scoped (user_id) and return the // number of rows changed. Bulk transitions (auto-match sweep, retention purge) // stay in their own services where the WHERE clause is fundamentally different. /** * Mark a transaction matched to a bill. * @param {boolean} [opts.resetIgnored] also clear the ignored flag (used when * matching a transaction directly, which implicitly un-ignores it). */ function markMatched(db, userId, transactionId, billId, { resetIgnored = false } = {}) { return db.prepare(` UPDATE transactions SET matched_bill_id = ?, match_status = 'matched'${resetIgnored ? ', ignored = 0' : ''}, updated_at = datetime('now') WHERE id = ? AND user_id = ? `).run(billId, transactionId, userId).changes; } /** * Clear a transaction's match — back to 'unmatched' with no bill. * @param {boolean} [opts.resetIgnored] also clear the ignored flag (un-ignore). */ function markUnmatched(db, userId, transactionId, { resetIgnored = false } = {}) { return db.prepare(` UPDATE transactions SET matched_bill_id = NULL, match_status = 'unmatched'${resetIgnored ? ', ignored = 0' : ''}, updated_at = datetime('now') WHERE id = ? AND user_id = ? `).run(transactionId, userId).changes; } /** Mark a transaction ignored — dropped from matching, no bill. */ function markIgnored(db, userId, transactionId) { return db.prepare(` UPDATE transactions SET ignored = 1, match_status = 'ignored', matched_bill_id = NULL, updated_at = datetime('now') WHERE id = ? AND user_id = ? `).run(transactionId, userId).changes; } module.exports = { markMatched, markUnmatched, markIgnored };