Update running balance only if required

This commit is contained in:
RunasSudo 2024-11-17 01:53:19 +11:00
parent 4bbfad335e
commit 48211b2176
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A

View File

@ -74,6 +74,8 @@ export async function totalBalances(session: Database): Promise<{account: string
} }
export async function updateRunningBalances() { export async function updateRunningBalances() {
// TODO: This is very slow - it would be faster to do this in Rust
// Recompute any required running balances // Recompute any required running balances
const session = await db.load(); const session = await db.load();
const staleAccountsRaw: {account: string}[] = await session.select('SELECT DISTINCT account FROM postings WHERE running_balance IS NULL'); const staleAccountsRaw: {account: string}[] = await session.select('SELECT DISTINCT account FROM postings WHERE running_balance IS NULL');
@ -87,7 +89,7 @@ export async function updateRunningBalances() {
// FIXME: Recompute balances only from the last non-stale balance to be more efficient // FIXME: Recompute balances only from the last non-stale balance to be more efficient
const arraySQL = '(?' + ', ?'.repeat(staleAccounts.length - 1) + ')'; const arraySQL = '(?' + ', ?'.repeat(staleAccounts.length - 1) + ')';
const joinedTransactionPostings: JoinedTransactionPosting[] = await session.select( const joinedTransactionPostings: JoinedTransactionPosting[] = await session.select(
`SELECT postings.id, account, quantity, commodity `SELECT postings.id, account, quantity, commodity, running_balance
FROM transactions FROM transactions
JOIN postings ON transactions.id = postings.transaction_id JOIN postings ON transactions.id = postings.transaction_id
WHERE postings.account IN ${arraySQL} WHERE postings.account IN ${arraySQL}
@ -99,16 +101,21 @@ export async function updateRunningBalances() {
for (const posting of joinedTransactionPostings) { for (const posting of joinedTransactionPostings) {
const openingBalance = runningBalances.get(posting.account) ?? 0; const openingBalance = runningBalances.get(posting.account) ?? 0;
const quantityCost = asCost(posting.quantity, posting.commodity); const quantityCost = asCost(posting.quantity, posting.commodity);
runningBalances.set(posting.account, openingBalance + quantityCost); const runningBalance = openingBalance + quantityCost;
runningBalances.set(posting.account, runningBalance);
// Update running balance of posting // Update running balance of posting
// Only perform this update if required, to avoid expensive call to DB
if (posting.running_balance !== runningBalance) {
await session.execute( await session.execute(
`UPDATE postings `UPDATE postings
SET running_balance = $1 SET running_balance = $1
WHERE id = $2`, WHERE id = $2`,
[openingBalance + quantityCost, posting.id] [runningBalance, posting.id]
); );
} }
}
} }
export function joinedToTransactions(joinedTransactionPostings: JoinedTransactionPosting[]): Transaction[] { export function joinedToTransactions(joinedTransactionPostings: JoinedTransactionPosting[]): Transaction[] {