Symphonious

Living in a state of accord.

Moolah Diaries – Upgrading to Hapi 17

Hapi 17 was released a while back with quite a few nice improvement – mostly centered around using promises instead of callbacks and thus fitting in with async/await well.  However, it’s a very significant change right across it’s APIs so it took quite a while for the various plugins that Moolah uses to be updated.

Eventually though they were all ready and then the actual upgrade of Moolah code was pretty straight forward.  Moolah had been using async handlers via a plugin all along so there were minor changes to how they were specified but very few changes to the control flow they then used.

In the end it only took an evening’s work to get it all upgraded and I haven’t encountered any bugs since. That’s a pretty good vote of confidence in the effectiveness of it’s tests.

The next big upgrade will be to move the front-end over to WebPack v4. The improvements there look excellent, removing a lot of the previously required config and simplifying things but that also means it’s a pretty complex migration.

Moolah Diaries – Earmarked Funds

I dropped out of the habit of writing about Moolah but it’s been ticking along doing what I need it to for a fair while with a few additions here and there. Recently I spent a chunk of time adding the ability to ‘earmark’ money for a particular use.

My main motivation is that we’re planning a family trip to Germany at the end of the year and I want to be able to set aside money through the year as we save for it. Various things will need to be paid upfront and those expense need to come out of the earmarked funds. I could track that with a new account for the savings, but since I’m not setting up a new bank account the balances wouldn’t match up and I’d spend a lot of time transferring money in and out of the holiday account.

So I’ve introduced ‘Earmark’ as a new type of entity. In many ways they’re similar to accounts, but a single transaction can have both an account and an earmark, affecting the balance of both. So the transaction recording paying for our flights has the credit card as it’s account and the earmark set to the Germany holiday. It acts as an expense reducing the balance of both the account and the earmark.

Similarly, my wife’s income goes into our bank account and for this year I’m also earmarking it for Germany so it increases the bank balance (we did actually get the cash) and also increases the balance of the earmark.

This sounds like double counting, but the earmark balance is not included in the net worth which is still just the sum of account balances. The UI also displays “available funds” which is the sum of account balances less the sum of earmark balances.

The result of this is that an expense with an account and earmark reduces the balance of the account (we now have less money in total) but also reduces the balance of the earmark so there is less money set aside for that purpose. As a result the net worth is reduced but the available funds remains the same because the cost came out of our reserved funds.

Income with an account and an earmark increases the balance of both, so net worth goes up but available funds stays the same – those funds have been earmarked for that purpose and aren’t available for general use.

But what if we want to earmark a fixed amount per month separately to any actual income? To support that, Moolah allows creating transactions with an earmark but no account. In that case we’re recording the allocation of funds but with no actual cash movement.

The feature set is rounded out by tracking how much has been saved (total of income) and how much has been spent (total of expenses), a savings target and target date and providing some visualisations to show savings progress vs time and expense breakdowns.

Moolah Diaries – Finding Transaction in the Past Month in MySQL

Ultimately the point of Moolah isn’t just to record a bunch of transactions, it’s to provide some insight into how your finances are going. The key question being how much more or less are we spending than we earn? I use a few simple bits of analysis to answer that question in Moolah, the first of which is income vs expenses over the past x months.

The simple way to do that is to show totals based on calendar month (month to date for the current month), but since my salary is paid monthly that doesn’t provide a very useful view of the current month since no income has arrived yet.

I really want to see data for the previous month as a sliding window.  So on the 3rd July the last month would be 4 June to 3 July (inclusive) and on the 25th of July it would be 26 June to 25 July. Given the way salary and bills are paid each month that provides a fairly stable view of income vs expense without fluctuating too much due to the time of the month.

Previously that was easy enough because all the transactions were in memory and we were iterating in JavaScript – flexible but doesn’t scale particularly well. With Moolah 2 we really want to do that in the database and avoid loading all the transactions.

The key bit of sql that makes it possible to achieve this sliding window for previous month is the group by clause:

GROUP BY IF(DAYOFMONTH(date) > DAYOFMONTH(NOW()), 
EXTRACT(YEAR_MONTH FROM DATE_ADD(date, INTERVAL 1 MONTH)),
EXTRACT(YEAR_MONTH FROM date))

There’s nothing particularly magic here – we just decide whether to push a transaction date into the next month based on whether it’s day of month is past the current day of month. The full transaction is in analysisDao.js.

Initially I limited the query to just the last 12 months worth but MySQL can iterate so much faster than JavaScript it can easily run through the full data set covering about 6 years. I probably should put some limit on it but I’m interested in how long it will last.

Moolah Diaries – Data Parity

Moolah just reached it’s first key milestone – it’s reached “data parity” with the old version. Basically it has enough functionality that it’s viable to import the data from the old version and get the same balances and totals. Using real data that’s been generated over the last 5 years has revealed a few important things.

The good:

  • The balances add up so things really are working
  • It really does load way faster
  • The old version allowed some data inconsistencies that the new version will prevent

The bad:

  • There’s quite a few features still missing from the display – more than I’d realised
  • There’s a few places that are much slower than expected because of some rather careless algorithm/data structure choices. Fortunately there’s some trivial changes that should give pretty dramatic improvements.

The next major milestone will be when I can actually switch over from the old system. Hopefully that’s not too far off.

Moolah Diaries – Tracking Account Balances

Moolah has two separate Vuex modules, transactions and accounts. That’s a fairly reasonably logical separation, but in the new Moolah, it’s not a complete separation. Moolah only ever loads a subset of transactions – typically the most recent transactions from the currently selected account.  As a result, accounts have their own current balance property because they can’t always calculate it off of their transactions.

That means that sometimes the transaction Vuex module needs to make changes to state owned by the account module which is a rather unpleasant breach of module separation. While we ensured transaction balances remained consistent inside each mutation, we can’t do that for account balances because Vuex (presumably deliberately) makes it impossible for a mutation to access or change state outside of the module itself. Instead, I’ve used a simple Vuex plugin that watches the balance on the most recent transaction and notifies the account module when it changes:

import {mutations as accountsMutations} from './accountsStore';
export default store => store.watch(
    (state) => {
        return state.transactions.transactions.length > 0 
? state.transactions.transactions[0].balance
: undefined; }, (newValue, oldValue) => { if (store.getters["accounts/selectedAccount"] !== undefined &&
newValue !== undefined) { store.commit('accounts/' + accountsMutations.updateAccount, { id: store.state.selectedAccountId,
patch: {balance: newValue} }); } });

Most of the complexity there is dealing with the case where we don’t yet have transaction or don’t have a selected account. This essentially makes the syncing between transaction balances and account balances a separate responsibility that belongs to this plugin.

The plugin doesn’t completely handle transfers between accounts. The balance for the account currently being edited updates correctly, but the balance for the account on the other side of the transfer doesn’t update. I’m not particularly happy with the solution, but at least for now the responsibility of reacting to transfer changes is in the transaction module’s actions. The action can easily calculate the effects of transaction changes on the balances of other accounts and use Vuex’s dispatch to send a notification over to the account module to perform the update. Mutations can’t dispatch events so it has to be the action that does it.

This leaves responsibility for updating the current account’s balance with the plugin and the responsibility for updating other account’s balances with the transaction module which is ugly. Perhaps the transaction module actions should be responsible for all account balances. Probably the right answer is to extract a separate class/function that the transaction module notifies at the end of each action with the state of the transaction before and after. Then that new class/function is responsible for updating account balances. Will need to prod the code a bit to see if that really can be done…