// db.js import postgres from 'postgres' const db = postgres({ host:'192.168.1.126', username:'budget', password:'budget', database:'budget'}) // will use psql environment variables export async function setAccountInTotal(accountId, total) { return await db` update account set in_total = ${total} where id = ${accountId} ` } export async function setAccountHide(accountId, hide) { return await db` update account set hide = ${hide} where id = ${accountId} ` } export async function deleteBudget(id) { return await db` UPDATE budget SET delete = true WHERE id = ${id} ` } export async function createBudgetTable() { return await db` create table if not exists budget ( id serial primary key, name text not null, amount numeric(10,2) not null, notes text, delete boolean default false ) ` } export async function createBudgetTransactionTable() { return await db` create table if not exists budget_transaction ( id serial primary key, budget_id integer not null references budget(id), transaction_id text not null references transaction(id), amount numeric(10,2) not null )` } export async function addBudget(name, amount, notes) { const result = await db` insert into budget (name, amount, notes) values (${name}, ${amount}, ${notes}) returning id ` // result = Result [{ id: 1 }] return result[0].id } export async function deleteBudget(id) { const result = await db` delete from budget where id = ${id} ` // result = Result [{ id: 1 }] return result } export async function updateBudget(id, name, amount, notes) { const result = await db` update budget set name = ${name}, amount = ${amount}, notes = ${notes} where id = ${id} ` // result = Result [{ id: 1 }] return result } export async function getBudgetTransactions(id) { // Fetch all transactions associated with a specific budget try { const transactions = await db` select transaction.id as id, transaction.posted as posted, transaction.amount as amount, transaction.description as description, transaction.pending as pending, transaction.notes as notes, budget_transaction.amount as budget_amount, budget_transaction.id as budget_transaction_id from budget_transaction join transaction on budget_transaction.transaction_id = transaction.id where budget_transaction.budget_id = ${id} order by transaction.posted desc ` // transactions = Result [{ id: 1, posted: 1633036800, amount: 50.00, description: "Grocery Store", pending: false, notes: "Weekly groceries" }, ...] return { transactions } } catch { await createBudgetTransactionTable(); return [] } } export async function deleteBudgetTransaction(budgetId, transactionId) { // Delete a transaction from a budget const result = await db` delete from budget_transaction where budget_id = ${budgetId} and transaction_id = ${transactionId} ` // result = Result [{ id: 1 }] return result } export async function addBudgetTransaction(budgetId, transactionId, amount) { // Add a transaction to a budget const result = await db` insert into budget_transaction (budget_id, transaction_id, amount) values (${budgetId}, ${transactionId}, ${amount}) returning id ` // result = Result [{ id: 1 }] return result[0].id } export async function getBudgets() { const budgets = await db` select budget.id as id, budget.name as name, budget.amount as amount, budget.notes as notes from budget WHERE budget.delete is false ` if (!budgets) { await createBudgetTable(); return await getBudgets() } // budgets = Result [{ name: "Walter", age: 80 }, { name: 'Murray', age: 68 }, ...] return budgets } export async function getAccounts(age) { const accounts = await db` select account.id as id, account.name as name, org.name as org_name, balance, available_balance, balance_date, hide, in_total from account left join org on org.id = account.org_id where account.hide is false ` // users = Result [{ name: "Walter", age: 80 }, { name: 'Murray', age: 68 }, ...] return accounts } export async function getHiddenAccounts(age) { const accounts = await db` select account.id as id, account.name as name, org.name as org_name, balance, available_balance, balance_date, hide, in_total from account left join org on org.id = account.org_id where account.hide is true ` // users = Result [{ name: "Walter", age: 80 }, { name: 'Murray', age: 68 }, ...] return accounts } export async function getTransactions(accountId) { let transactions = await db` select transaction.id as id, transaction.posted as posted, transaction.amount as amount, transaction.description as description, transaction.pending as pending, transaction.notes as notes from transaction where account_id = ${accountId} order by posted desc ` transactions = transactions.map((t) => ({ ...t, date: new Date(t.posted * 1000) })); return transactions } export async function setTransactionNote(transactionId, note) { const result = await db` update transaction set notes = ${note} where id = ${transactionId} ` return result } export async function updateAccounts(data) { try { console.log('Updating accounts with data:', data); for (const account of data.accounts) { // Upsert Org console.log(`Upserting org for account: ${account.id}`, account.org); await db` insert into org (id, domain, name, sfin_url, url) values (${account.org.id}, ${account.org.domain ?? null}, ${account.org.name ?? null}, ${account.org.sfin_url ?? null}, ${account.org.url ?? null}) on conflict (id) do update set domain = excluded.domain, name = excluded.name, sfin_url = excluded.sfin_url, url = excluded.url `; console.log(`Upserting account: ${account.id} (${account.name})`); // Upsert Account await db` insert into account (id, org_id, name, currency, balance, available_balance, balance_date) values ( ${account.id}, ${account.org.id}, ${account.name ?? null}, ${account.currency ?? null}, ${account.balance ?? null}, ${account.available_balance ?? null}, ${account.balance_date ?? null} ) on conflict (id) do update set org_id = excluded.org_id, name = excluded.name, currency = excluded.currency, balance = excluded.balance, available_balance = excluded.available_balance, balance_date = excluded.balance_date `; // Upsert Transactions if (account.transactions && account.transactions.length > 0) { for (const txn of account.transactions) { let extraId = null; console.log(`Upserting transaction: ${txn.id} for account: ${account.id}`); if (txn.extra) { // Upsert TransactionExtra (insert only, update not needed for category) const extraResult = await db` insert into transaction_extra (category) values (${txn.extra.category ?? null}) on conflict (category) do nothing returning id `; if (extraResult.length > 0) { extraId = extraResult[0].id; } else { // If already exists, fetch id const existing = await db` select id from transaction_extra where category = ${txn.extra.category ?? null} `; if (existing.length > 0) { extraId = existing[0].id; } } } console.log(`Preparing to upsert transaction: ${txn.id} with data:`, txn); await db` insert into transaction (id, account_id, posted, amount, description, pending, transacted_at) values ( ${txn.id}, ${account.id}, ${txn.posted}, ${txn.amount ?? null}, ${txn.description ?? null}, ${txn.pending ?? false}, ${txn.transacted_at ?? 0} ) on conflict (id) do update set account_id = excluded.account_id, posted = excluded.posted, amount = excluded.amount, description = excluded.description, pending = excluded.pending, transacted_at = excluded.transacted_at `; } } } return true; } catch (error) { console.error('updateAccounts error:', error); return false; } } export default db