Tracking My Expenses

08/08/23

In tackling any task with reasonable complexity, I find that it is incredibly helpful to focus on the safest assumptions and strip away everything else.

In applying this approach to the question of whether I should pursue freelance, I found that the safest assumption was the following:

The only hard requirement that I must satisfy is that I need to make only as much money as I need.

If I spend $X a year, then I need to make $X a year (preferably with some padding). Of course, life is full of surprises, and it's not reasonable (or pragmatic) to assume that your current output will remain unchanged over the course of the next year. That's true, but it's also a good start.

So, the question becomes, "What is my current output?"

Which is why I created an app for myself to track my output, or, my expenses.

Why

Q: Why didn't you just use MINT or another expense tracking app? There are so many out there.
A: This is true. There are SO MANY out there. There are a few reasons why:

  1. By importing my expenses from my bank accounts directly into a local database that I manage, I'm able to query that database in as many ways as I'd like. I can ask my database questions about my expenses in ways that available apps simply do not support.
  2. My experience with these apps is that I'm not generally happy with the categories/tags they assign to my expenses. Sure, some will allow me to modify them individually..but because my expenses typically follow patterns that I'm more attuned to, I am better able to manage these categories programmatically on import, allowing me to segment them in ways that are interesting to me.
  3. Building my own SwiftUI app is just good practice. Also, I'm able to integrate features that I find valuable as I progress. For example, I've found that I spend more on FOOD than I had guessed prior to building this. So, it might be helpful for me to dig into that category -- further separate by food delivery, restaurants, alcohol, grocery. How are each of these segments contributing, and how can I visualize that progress over time.
  4. Data. Your financial data is extremely powerful in dissecting the patterns of your daily life. Aside from the aforementioned points, being able to access and manipulate my data locally provides me with a significant peace of mind.

How

The following steps provide a rough overview of the steps I took to implement this:

  1. Download CSV files from bank and credit cards of all transactions YTD.
  2. Design and implement MySQL table structure for each provider. A note on this: I had debated whether to create a unique table for each provider, or whether to consolidate columns for all providers into a single source. I decided to create a unique table for each. This would later prove advantageous as each provider has its own set of quirks and differences. Having distinct tables allows me to manage these differences in isolation.
  3. Write a script to handle CSV data upload. At this stage, determine best-fit category based on specified attributes. As a safety check, add appropriate UNIQUE indices to tables to ensure that rows are not duplicated if file is uploaded multiple times.
  4. Create an API in Node + Express. The only endpoint I need (currently) is GET /expenses. All filtering (month, category) is done on the client.
  5. Create a multi-platform client in Xcode. A multi-platform app is written in SwiftUI and will run natively on MacOS, iOS, and iPadOS. Charts are drawn natively using Swift Charts.

A Note on Design Decisions

Throughout the project, I had to remind myself not to over-engineer this. As developers, we are in the habit of reminding ourselves to build for scale; to build generically. But I have no plans to distribute this. I have no plans to build this in a way that allows for any bank to be supported. I have no plans to build an app interface that supports a mass adoption set of use cases. I intend only to use it as a personal tool, and I should build it with that in mind. This doesn't mean it won't be designed and built intelligently -- but an app made for one and an app made for a million inherently have unique design constraints.