_blogs
// blogs / 20260823.md
// blogs / 20260823.md
Dev Log: August 23 Wrap-up
Overview
Today was all about rounding out the experience for my expense tracker. I spent a good chunk of time moving past just 'logging things' and into actually 'visualizing the balance.' I also officially bumped the version to 1.3.0 after getting a stable CSV export working.
What I Worked On
Giving users their data back (CSV Export)
I finally got around to implementing a CSV export feature. While I personally prefer JSON for backups because it’s easy to import back into the app, most people just want something they can open in Excel or Google Sheets to send to their accountant.
I wanted to make sure it wasn't just a raw database dump. Instead of showing internal category IDs, I joined the data so the CSV shows actual names like 'Food' or 'Rent'. I also had to be careful with string escaping. If a user has a comma in their transaction note, a naive joinToString(",") would break the entire spreadsheet layout. I went with RFC 4180-style escaping to keep things robust.
/*
* Mapping transactions to a spreadsheet-friendly format.
* We wrap strings in quotes and escape existing quotes to
* ensure the CSV doesn't break on special characters.
*/
val csvRow = listOf(
data.date,
data.categoryLabel,
"\"${data.note.replace("\"", "\"\"")}\"",
data.amount
).joinToString(",")
Seeing the 'Net' Picture
Most of the time, I'm looking at what I spent (the debits), but only seeing the outflow is only half the story. I updated the daily spend trend graph and the category detail screens to show the net amount.
If I spent ₹500 on groceries but a friend paid me back ₹200 for their share, seeing that "Net: -₹300" is much more satisfying (and accurate) than just seeing a flat ₹500 loss. I had to tweak the donut chart logic as well. A single ring can't easily plot two different totals (total credits vs total debits), so I added a toggle mode to switch between them. It keeps the UI clean without trying to cram too much conflicting data into one visual.
Reflecting on 'Ghost' Bugs
While cleaning up my internal docs today, I was thinking back to a weird double-encoding bug I hit earlier this week. It’s funny how some framework utilities try to be helpful by automatically encoding strings, which is great—until you’ve already manually handled the encoding yourself. You end up with a mess of %2520 instead of a simple space. It was a good reminder to always check the 'magic' happening under the hood when a string looks like alphabet soup.
Wrapping Up
With the net totals visible and the CSV export live, the app feels a lot more 'professional' and less like a side-project. Version 1.3.0 is out the door. I think for the next few days, I'll take a break from heavy feature work and just use the app to see where the UI friction points are. Catch you tomorrow.