Skip to content

Commit

Permalink
feat: add option to ignore pending transactions
Browse files Browse the repository at this point in the history
closes #78
  • Loading branch information
leo-benz authored and Xiphe committed Feb 15, 2021
1 parent 38d7e54 commit 5436c41
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 7 deletions.
1 change: 1 addition & 0 deletions cypress/factories/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function createSettings(
fractionDigits: 2,
startDate: 1562450400000,
startBalance: 0,
ignorePendingTransactions: false,
...settings,
};
}
17 changes: 13 additions & 4 deletions src/budget/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@ import {
} from '../moneymoney';
import { isLeft } from 'fp-ts/lib/Either';
import { ThrowReporter } from 'io-ts/lib/ThrowReporter';
import semver from 'semver';

/**
* ## 0.0.1 -> 0.0.2
* now using uuids to reference categories and accounts
*
* ## 0.0.2 -> 0.0.3
* removed setting.numberLocale in favor of always using system
*
* ## 0.0.3 -> 0.0.4
* added setting.ignorePendingTransactions
*/
export const VERSION = '0.0.3';
export const VERSION = '0.0.4';

const categoryShape = t.partial({
amount: t.number,
Expand All @@ -39,6 +43,7 @@ const incomeCategoryShape = t.type(
const settingsShape = t.type(
{
fractionDigits: t.number,
ignorePendingTransactions: t.boolean,
startDate: t.number,
currency: t.string,
startBalance: t.number,
Expand Down Expand Up @@ -76,13 +81,17 @@ export function validateBudgetState(data: unknown): BudgetState {
if (typeof data !== 'object' || data === null) {
throw new Error('Invalid budget file format');
}
const version: unknown = (data as any).version;
if (!version || version === '0.0.1') {
const version: string = (data as any).version as string;
if (!version || !semver.valid(version) || !semver.satisfies(version, '>0.0.1')){
throw new Error(
'File format not supported. Please use an earlier version of BudgetBudget to open this file',
);
}

// Upgrade to 0.0.4 version format
if (semver.lt(version, '0.0.4')) {
(data as any).settings.ignorePendingTransactions = false;
(data as any).version = '0.0.4';
}
const c = budgetStateShape.decode(data);
if (isLeft(c)) {
throw ThrowReporter.report(c);
Expand Down
16 changes: 16 additions & 0 deletions src/budget/budgetReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export const ACTION_SET_NAME = Symbol('SET_NAME');
export const ACTION_SETTINGS_SET_FRACTION_DIGITS = Symbol(
'ACTION_SETTINGS_SET_FRACTION_DIGITS',
);
export const ACTION_SETTINGS_SET_IGNORE_PENDING_TRANSACTIONS = Symbol(
'ACTION_SETTINGS_SET_IGNORE_PENDING_TRANSACTIONS',
);
export const ACTION_SETTINGS_SET_SELECTED_ACCOUNTS = Symbol(
'ACTION_SETTINGS_SET_SELECTED_ACCOUNTS',
);
Expand Down Expand Up @@ -71,6 +74,10 @@ type SetSettingsFractionDigits = {
type: typeof ACTION_SETTINGS_SET_FRACTION_DIGITS;
payload: number;
};
type SetSettingsIgnorePendingTransactions = {
type: typeof ACTION_SETTINGS_SET_IGNORE_PENDING_TRANSACTIONS;
payload: boolean;
};
type SetSettingsSelectedAccounts = {
type: typeof ACTION_SETTINGS_SET_SELECTED_ACCOUNTS;
payload: string[];
Expand Down Expand Up @@ -125,6 +132,7 @@ export type Action =
| SetCategoryRolloverAction
| SetNameAction
| SetSettingsFractionDigits
| SetSettingsIgnorePendingTransactions
| SetSettingsSelectedAccounts
| SetSettingsStartDate
| SetSettingsStartBalance
Expand Down Expand Up @@ -233,6 +241,14 @@ function budgetReducer(state: BudgetState, action: Action): BudgetState {
fractionDigits: action.payload,
},
};
case ACTION_SETTINGS_SET_IGNORE_PENDING_TRANSACTIONS:
return {
...state,
settings: {
...state.settings,
ignorePendingTransactions: action.payload,
},
};
case ACTION_SETTINGS_SET_SELECTED_ACCOUNTS:
return {
...state,
Expand Down
6 changes: 3 additions & 3 deletions src/budget/useBudgets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ export default function useBudgets(
defaultCategories: Category[] = [],
{
budgets,
settings: { incomeCategories, fractionDigits, startBalance, startDate },
settings: { incomeCategories, fractionDigits, startBalance, startDate, ignorePendingTransactions },
}: BudgetState,
): [MonthData[], (add: number) => void] {
const defaultCategoryIds = useMemo(
() => defaultCategories.map(({ uuid }) => uuid),
[defaultCategories],
);
const balances = useMemo(
() => calculateBalances(transactions, defaultCategoryIds),
[transactions, defaultCategoryIds],
() => calculateBalances(transactions, defaultCategoryIds, ignorePendingTransactions),
[transactions, defaultCategoryIds, ignorePendingTransactions],
);
const getInitial = useMemo(() => {
const initial: InterMonthData = {
Expand Down
1 change: 1 addition & 0 deletions src/lib/initialSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const settings: BudgetState['settings'] = {
currency: 'EUR',
incomeCategories: [],
fractionDigits: 2,
ignorePendingTransactions: false,
startDate: startOfMonth(subMonths(getToday(), 1)).getTime(),
startBalance: 0,
};
Expand Down
4 changes: 4 additions & 0 deletions src/moneymoney/calculateBalances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import { formatDateKey } from '../lib';
export default function calculateBalances(
transactions: Transaction[],
defaultCategoryIds: string[],
ignorePendingTransactions: boolean
): Balances {
return transactions.reduce((memo, transaction) => {
if (!transaction.booked && ignorePendingTransactions) {
return memo;
}
const key = formatDateKey(transaction.bookingDate);
let balance = memo[key];
if (!balance) {
Expand Down
3 changes: 3 additions & 0 deletions src/views/Settings/General/General.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import CurrencySetting from './Currency';
import { Props } from './Types';
import { Loading } from '../../../components';
import { NumberFormatter } from '../../../lib/createNumberFormatter';
import IgnorePendingTransactionsSetting from './IgnorePendingTransactions';

export default function Settings(
props: Props & { numberFormatter: NumberFormatter },
Expand All @@ -26,6 +27,8 @@ export default function Settings(
<hr />
<FractionDigitsSetting {...props} />
<hr />
<IgnorePendingTransactionsSetting {...props} />
<hr />
<StartDateSetting {...props} />
<StartBalanceSetting {...props} />
</>
Expand Down
35 changes: 35 additions & 0 deletions src/views/Settings/General/IgnorePendingTransactions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { useCallback } from 'react';
import { ACTION_SETTINGS_SET_IGNORE_PENDING_TRANSACTIONS } from '../../../budget';
import Setting from '../Setting';
import { Props } from './Types';

export default function IgnorePendingTransactionsSetting({
state: {
settings: { ignorePendingTransactions },
},
dispatch,
}: Props) {
const onChange = useCallback(
(ev: React.ChangeEvent<HTMLInputElement>) => {
dispatch({
type: ACTION_SETTINGS_SET_IGNORE_PENDING_TRANSACTIONS,
payload: ev.target.checked,
});
},
[dispatch],
);

return (
<Setting
label="Ignore pending transactions"
id="setting-ignore-pending-transactions"
>
<input
type="checkbox"
id="setting-ignore-pending-transactions"
checked={ignorePendingTransactions}
onChange={onChange}
/>
</Setting>
);
}

0 comments on commit 5436c41

Please sign in to comment.