310 lines
10 KiB
JavaScript
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 |