Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/balance-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,12 @@ export type DailyAccountBalanceChangeMap = Map<string, Map<string, number>>;
* If an account has no balance change on a date, that key will not be included
* in the inner map. If a date has no transactions, that key will not be
* included in the outer map.
*
* Only transactions matching the passed currencySymbol will be included.
*/
export const makeDailyAccountBalanceChangeMap = (
transactions: EnhancedTransaction[],
currencySymbol: string,
): DailyAccountBalanceChangeMap => {
// This map contains a mapping from every day (YYYY-MM-DD) to account names to
// a list of all balance changes.
Expand All @@ -191,6 +194,10 @@ export const makeDailyAccountBalanceChangeMap = (
return; // Must be a comment line
}

if (line.currency != currencySymbol) {
return;
}

getWithDefault(
accounts,
line.dealiasedAccount,
Expand Down
40 changes: 25 additions & 15 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,8 @@ export const fillMissingAmount = (
): Result<null, TxError> => {
const lines = tx.value.expenselines;
let missingLine: Expenseline | undefined;
let missingIndex = -1;
let currency = '';

let totals: Map<string, number> = new Map<string, number>();

for (let i = 0; i < lines.length; i++) {
const line = lines[i];
Expand All @@ -435,28 +435,38 @@ export const fillMissingAmount = (
});
}
missingLine = line;
missingIndex = i;
} else if (line.currency) {
currency = line.currency;
// Calculate running total for each currency
if (!totals.has(line.currency)) {
totals.set(line.currency, 0);
}

totals.set(line.currency!, totals.get(line.currency)! + line.amount!);
}
}

if (!missingLine) {
return ok(null);
}

if (currency) {
missingLine.currency = currency;
}
missingLine.amount =
-1 *
lines.reduce((prev, line, i): number => {
if (i === missingIndex || !('account' in line)) {
return prev;
}
let account = missingLine.account;

// Remove initial missing line and repopulate with lines for each currency
tx.value.expenselines.remove(missingLine);

return line.amount !== undefined ? prev + line.amount : prev;
}, 0);
Array.from(totals.entries()).forEach(([currency, total]) => {
if (total === 0) {
return;
}
tx.value.expenselines.push(
{
account,
amount: -1 * total,
currency,
comment: '',
},
);
});

return ok(null);
};
38 changes: 38 additions & 0 deletions src/transaction-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,44 @@ export const getTotal = (
return currency + total.toFixed(2);
};

/**
* getCurrencyTotals returns the total values of the transaction. It returns a
* string separated by newlines, with a line for each currency.
*/
export const getCurrencyTotals = (
tx: EnhancedTransaction
): string => {
let totals: Map<string, number> = new Map<string, number>();

console.log(tx.value.expenselines);

let currentSignPositive = null;

for (let i = 0; i < tx.value.expenselines.length; i++) {
const line = tx.value.expenselines[i];

if ('currency' in line && line.currency) {
// Track the sign of the first value and skip lines that differ.
// We continue instead of breaking in case the transactions flip-flop
// between positive and negative, as unlikely as that is.
if (currentSignPositive === null) {
currentSignPositive = line.amount >= 0;
} else if (currentSignPositive === (line.amount < 0)) {
continue;
}

if (!totals.has(line.currency)) {
totals.set(line.currency, 0);
}

totals.set(line.currency, totals.get(line.currency)! + line.amount);
}
}

return Array.from(totals).map(([key, value]) => key + value.toFixed(2)).join("\n");
};


export const getTotalAsNum = (tx: EnhancedTransaction): number => {
// The total of an EnhancedTransaction is -1 * the last line that is not a comment
for (let i = tx.value.expenselines.length - 1; i >= 0; i--) {
Expand Down
1 change: 1 addition & 0 deletions src/ui/LedgerDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ const DesktopDashboard: React.FC<{

const changeMap = makeDailyAccountBalanceChangeMap(
props.txCache.transactions,
props.settings.currencySymbol,
);
const balanceMap = makeDailyBalanceMap(
props.txCache.accounts,
Expand Down
11 changes: 7 additions & 4 deletions src/ui/TransactionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
filterByStartDate,
filterTransactions,
getTotal,
getCurrencyTotals,
} from '../transaction-utils';
import { Moment } from 'moment';
import React from 'react';
Expand Down Expand Up @@ -178,7 +179,7 @@ const buildTableRows = (
return {
date: tx.value.date,
payee: tx.value.payee,
total: getTotal(tx, currencySymbol),
total: getCurrencyTotals(tx),
from: nonCommentLines[1].account,
to: nonCommentLines[0].account,
actions: makeClone(tx),
Expand All @@ -188,7 +189,7 @@ const buildTableRows = (
return {
date: tx.value.date,
payee: tx.value.payee,
total: getTotal(tx, currencySymbol),
total: getCurrencyTotals(tx),
from: nonCommentLines[nonCommentLines.length - 1].account,
to: <i>Multiple</i>,
actions: makeClone(tx),
Expand All @@ -200,7 +201,7 @@ const buildTableRows = (
const aDate = window.moment(a.date);
const bDate = window.moment(b.date);
if (aDate.isSame(bDate)) {
return 0;
return -1;
}
return aDate.isBefore(bDate) ? 1 : -1;
});
Expand Down Expand Up @@ -342,7 +343,9 @@ const TransactionTable: React.FC<{
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell) => (
<td {...cell.getCellProps()}>{cell.render('Cell')}</td>
// Whitespace styling to support Total column newlines
// There's definitely a better way to style this.
<td style={{ whiteSpace: "pre" }} {...cell.getCellProps()}>{cell.render('Cell')}</td>
))}
</tr>
);
Expand Down
2 changes: 1 addition & 1 deletion tests/balance-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ describe('Balance maps', () => {
describe('makeDailyAccountBalanceChangeMap()', () => {
test('simple test', () => {
const input = [tx4, tx5, tx6];
const result = makeDailyAccountBalanceChangeMap(input);
const result = makeDailyAccountBalanceChangeMap(input, "");
expect(result).toEqual(expectedDailyAccountBalanceChangeMap);
});
});
Expand Down