DEV Community

Cover image for # Personal Expense Tracker — V1 Complete: Building the Core Working Stage
Dhanush K
Dhanush K

Posted on

# Personal Expense Tracker — V1 Complete: Building the Core Working Stage

I’ve completed V1 of my Personal Expense Tracker, a small learning project built with Python and SQLite.

This project was created primarily to learn by building rather than following a tutorial step by step.

The goal of V1 was not to build a production-ready expense tracker.

The goal was:

Build the core application flow, understand the responsibilities of each layer, and make the fundamental functionality work end-to-end.

With that goal achieved, I consider V1 complete.

Why I Built This Project

I wanted to strengthen my understanding of:

  • Python OOP
  • Classes and objects
  • Object responsibilities
  • SQL and SQLite
  • CRUD operations
  • Database design
  • Separating application responsibilities
  • How different layers communicate with each other

Instead of learning these concepts separately, I decided to combine them into one small practical project.

That's why I consider this primarily a learning project.

The objective was not to create a feature-rich application immediately, but to understand the fundamentals by actually building something.

What I Built

The application is a command-line Personal Expense Tracker.

The core V1 functionality includes:

  • Adding an expense
  • Viewing expenses
  • Deleting an expense
  • Storing expenses in SQLite
  • Using SQLite-generated IDs
  • Separating the application into different responsibilities

The database currently contains an expenses table:

Column Type
id INTEGER PRIMARY KEY
amount REAL
category TEXT
description TEXT
date TEXT

Application Architecture

One of the main things I wanted to learn was how to organize responsibilities in an application.

I structured the project into three main layers:

main.py
   ↓
ExpenseManager
   ↓
Database
   ↓
SQLite
Enter fullscreen mode Exit fullscreen mode

main.py — UI Layer

main.py is responsible for interacting with the user through the CLI.

Its responsibilities include:

  • Displaying the menu
  • Taking user input
  • Calling the appropriate operation
  • Displaying results

The UI does not directly handle SQL operations.

expense_manager.py — Application Layer

ExpenseManager acts as the middle layer between the UI and storage.

It coordinates application operations and communicates with the database object.

For example:

main.py
   ↓
ExpenseManager.add_expense()
   ↓
Database.insert_expense()
Enter fullscreen mode Exit fullscreen mode

This helped me understand the difference between the application's operation and the actual persistence of data.

storage.py — Persistence Layer

The Database class handles communication with SQLite.

Its responsibilities include:

  • Creating the database connection
  • Initializing the database
  • Creating the table
  • Inserting expenses
  • Retrieving expenses
  • Deleting expenses

This keeps database-related responsibilities separate from the UI.

Understanding Object Relationships

Another important part of this project was understanding how objects can work together.

The application creates a database object and passes it to ExpenseManager.

Conceptually:

main.py
   │
   ├── creates Database
   │
   └── creates ExpenseManager
             │
             └── uses Database
Enter fullscreen mode Exit fullscreen mode

The manager receives the database dependency instead of creating its own database internally.

This was one of the OOP concepts I wanted to understand through practical implementation.

Why V1 Is Complete

There is an important distinction between:

"V1 is complete"

and

"the project is finished."

V1 is complete because its intended scope has been achieved.

The core application flow works:

User
 ↓
CLI
 ↓
ExpenseManager
 ↓
Database
 ↓
SQLite
Enter fullscreen mode Exit fullscreen mode

An expense can be added and stored, stored expenses can be retrieved and displayed, and expenses can be deleted.

The different layers can communicate with each other correctly.

That is the foundation I wanted to establish in V1.

What I Learned From V1

The biggest lesson wasn't simply learning SQLite syntax or Python syntax.

It was understanding responsibility.

I learned to think about the application as separate parts with different jobs:

UI
→ communicates with the user

Manager
→ coordinates application operations

Storage
→ communicates with the database
Enter fullscreen mode Exit fullscreen mode

Along the way, I gained practical experience with:

  • Python classes
  • Constructors and attributes
  • Methods
  • Object relationships
  • Passing dependencies between objects
  • SQLite tables
  • Primary keys
  • CRUD operations
  • SQL queries
  • Multi-module Python projects
  • Debugging
  • Git and GitHub

What I Didn't Focus On in V1

I deliberately didn't try to make V1 handle every possible invalid input or edge case.

Comprehensive validation and robust error handling were not the main goals of this version.

Instead, I decided to make the core functionality work first and move robustness-related improvements into V2.

This gives the project a clearer progression:

V1
Core Working Stage
       ↓
V2
Robustness + Additional Core Operation
Enter fullscreen mode Exit fullscreen mode

What's Coming in V2?

Now that the core working stage is complete, V2 will focus on improving the application's robustness and functionality.

The planned V2 work includes:

Validation

  • Validating user input
  • Validating expense IDs
  • Handling invalid values
  • Handling invalid menu input

Error Handling

  • Handling invalid user input gracefully
  • Handling invalid/non-existent expense IDs
  • Handling database-related errors
  • Providing better user-facing error messages

Edit Expense

V2 will also introduce an Edit Expense operation.

The core expense operations will then become:

Create
Read
Update
Delete
Enter fullscreen mode Exit fullscreen mode

or simply:

CRUD
Enter fullscreen mode Exit fullscreen mode

This will make the expense management functionality more complete.

V1 → V2

The project's progression can be summarized as:

V1
│
├── Add Expense
├── View Expenses
├── Delete Expense
├── SQLite persistence
├── Layered architecture
└── Core application flow
        │
        ▼
V2
│
├── Edit Expense
├── Input validation
├── ID validation
├── Error handling
└── CLI refinement
Enter fullscreen mode Exit fullscreen mode

I intentionally want to keep these stages separate.

V1 proves that the foundation works.

V2 will make that foundation more robust and complete.

Final Thoughts

This project started as a learning exercise to understand Python OOP and SQLite by building something practical.

Completing V1 gave me more than just another project for my GitHub repository.

It helped me understand how a small application can be divided into responsibilities and how those components communicate with each other.

I'm treating V1 as a completed learning milestone, not as the final state of the application.

The core working stage is done.

🔗 Project

📌 GitHub Repository: Personal Expense Tracker

Now it's time to build on that foundation.

V1: Complete.

Core working stage: Achieved.

Next: V2 — Validation, Error Handling & Edit Expense.

Top comments (0)