Files
budget/src/lib/db.js

310 lines
10 KiB
JavaScript

// 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