# phupa26/personal-expense-management architecture

> Architecture diagram of the GitHub repository phupa26/personal-expense-management, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-18). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/phupa26/personal-expense-management
- Repository: https://github.com/phupa26/personal-expense-management

## Overview

1. **Overall shape**
   This repository is a **single-process Python CLI application** for personal finance tracking. The architecture is layered: **core data structures and domain models** at the bottom, **persistence and indexing** in the middle, **business services** above that, and a **CLI entrypoint** in `main.py` on top.

2. **Entry point and interaction loop**
   `main.py` is the orchestration layer. It drives the terminal menu, collects user input, invokes service methods, and displays summaries/reports. The CLI is also the natural boundary where user actions become domain operations such as add/update/delete transaction, category maintenance, budget setting, and report generation.

3. **Domain model layer**
   `core/models.py` contains the main business entities: `Transaction`, `Category`, and monthly state objects such as `CategoryState`, `IncomeState`, `ExpenseState`, plus `MonthData`. This layer holds the system’s financial meaning: transaction amount, date, category, type, notes, category activation status, and monthly budget/expense accumulation.

4. **Custom data structures**
   `core/data_structure.py` implements a custom **HashMap/HashNode** rather than using Python dict as the primary storage abstraction. This is an important architectural choice because other modules depend on it for fast lookups, collision handling, and month/category indexing. The repo also claims binary search support for date-based lookup, so search performance is explicitly part of the design, not incidental.

5. **Persistence boundary**
   `data/file_io.py` is the persistence layer. It serializes and restores the application state to the custom text file in `storage/data.txt`, so the app does not depend on an external database. This layer is also where the system likely centralizes reading/writing of the full object graph: categories, monthly state, and transactions.

6. **Indexing and lookup services**
   `data/index_services.py` provides the internal indices that make the CLI responsive: `MonthIndex`, `TransactionIndex`, `TransactionMap`, and `CategoryIndex`. These are not just storage helpers; they are the mechanism that ties transaction IDs to months, categories to monthly states, and date/category queries to the right subset of data.

7. **Business services**
   The `services/` package contains the application logic:
   - `category_manager.py` handles category CRUD-like behavior and filtering by name/type/ID.
   - `transaction_manager.py` manages transaction creation, update, deletion, budget checks, and category suggestions based on note history.
   - `report_manager.py` assembles daily, monthly, yearly, and rolling K-month reports.
   These services sit between CLI input and the underlying indexed data structures.

8. **Data flow for transaction writes**
   A new transaction typically flows from `main.py` into `transaction_manager.py`, which validates the input, resolves the category, updates the relevant monthly state in `MonthIndex`, and records the transaction in the transaction index/map. If budgets are exceeded, the service layer is responsible for detecting and surfacing that condition. The state then persists through `file_io.py`.

9. **Data flow for reads and reports**
   Reporting reads from the same monthly indices rather than recomputing everything from scratch. `report_manager.py` pulls the relevant `MonthData` and aggregates by time window: day, month, year, or last K months. The report layer also renders ASCII-style visual output, so it transforms internal financial state into human-readable terminal output.

10. **Category and budget model**
   Categories are soft-deleted rather than removed outright, preserving historical transaction integrity. Budgeting is month-scoped: category limits are represented through per-month `CategoryState` objects, not only on the base `Category` record. This separation is a key architectural boundary because it keeps current configuration distinct from historical financial state.

11. **Import and external file inputs**
   `import.csv` is an ingest path for bulk transaction loading. The system uses Python’s built-in `csv` module, so imported data enters the same transaction pipeline as manually entered records. That means CSV import is not a separate subsystem; it is an alternate input source feeding the same domain services.

12. **Storage and operational artifacts**
   `storage/data.txt` is the main persistent state file, while `storage/inputoutput.txt` is an execution log of prompts and user actions. Those two files reflect the app’s operating model: one file captures durable financial state, and the other captures interaction history for debugging/auditing.

13. **Important architectural boundary**
   There are no external databases, web services, or third-party frameworks. The repo’s architecture is intentionally self-contained: standard Python only, custom data structures, custom serialization, and CLI rendering. For an architecture diagram, the main arrows should be from **CLI → services → indices/models → file I/O**, with `core` underpinning everything and `storage` serving as the persistence boundary.

Main entry points: [`services/transaction_manager.py`](https://github.com/phupa26/personal-expense-management/blob/main/services/transaction_manager.py) (Transactions), [`data/index_services.py`](https://github.com/phupa26/personal-expense-management/blob/main/data/index_services.py) (Indices), [`main.py`](https://github.com/phupa26/personal-expense-management/blob/main/main.py) (Main CLI), [`data/file_io.py`](https://github.com/phupa26/personal-expense-management/blob/main/data/file_io.py) (File IO)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_cli["CLI"]
  node_main["Main CLI<br/>entrypoint<br/>[main.py]"]
end

subgraph group_core["Core"]
  node_models["Models<br/>[models.py]"]
  node_structures{{"Hash Map<br/>custom DS<br/>[data_structure.py]"}}
  node_month_data["Month Data<br/>monthly state<br/>[models.py]"]
  node_category_state["Category State<br/>budget state<br/>[models.py]"]
  node_transaction["Transaction<br/>financial record<br/>[models.py]"]
  node_category["Category<br/>domain entity<br/>[models.py]"]
end

subgraph group_data["Data"]
  node_fileio[("File IO<br/>persistence<br/>[file_io.py]")]
  node_indexes{{"Indices<br/>lookup/indexing<br/>[index_services.py]"}}
end

subgraph group_services["Services"]
  node_txn_mgr["Transactions"]
  node_cat_mgr["Categories"]
  node_report_mgr["Reports<br/>[report_manager.py]"]
end

subgraph group_storage["Storage"]
  node_csv_import["CSV Import<br/>bulk input<br/>[import.csv]"]
  node_data_txt[("State File<br/>persistent state<br/>[data.txt]")]
  node_log_txt["Action Log<br/>execution log<br/>[inputoutput.txt]"]
end

node_main -->|"manage"| node_txn_mgr
node_main -->|"maintain"| node_cat_mgr
node_main -->|"report"| node_report_mgr
node_main -->|"load/save"| node_fileio
node_txn_mgr -->|"update"| node_indexes
node_txn_mgr -->|"uses"| node_models
node_txn_mgr -->|"budget check"| node_category_state
node_txn_mgr -->|"resolve"| node_category
node_cat_mgr -->|"manage"| node_category
node_report_mgr -->|"read"| node_indexes
node_report_mgr -->|"aggregate"| node_month_data
node_indexes -->|"backed by"| node_structures
node_indexes -->|"map"| node_transaction
node_indexes -->|"organize"| node_month_data
node_month_data -->|"contains"| node_category_state
node_month_data -->|"contains"| node_transaction
node_fileio -->|"persist"| node_data_txt
node_fileio -->|"serialize"| node_models
node_fileio -->|"restore"| node_indexes
node_csv_import -->|"feed"| node_txn_mgr
node_main -.->|"record"| node_log_txt

click node_main "https://github.com/phupa26/personal-expense-management/blob/main/main.py"
click node_models "https://github.com/phupa26/personal-expense-management/blob/main/core/models.py"
click node_structures "https://github.com/phupa26/personal-expense-management/blob/main/core/data_structure.py"
click node_fileio "https://github.com/phupa26/personal-expense-management/blob/main/data/file_io.py"
click node_indexes "https://github.com/phupa26/personal-expense-management/blob/main/data/index_services.py"
click node_txn_mgr "https://github.com/phupa26/personal-expense-management/blob/main/services/transaction_manager.py"
click node_cat_mgr "https://github.com/phupa26/personal-expense-management/blob/main/services/category_manager.py"
click node_report_mgr "https://github.com/phupa26/personal-expense-management/blob/main/services/report_manager.py"
click node_month_data "https://github.com/phupa26/personal-expense-management/blob/main/core/models.py"
click node_category_state "https://github.com/phupa26/personal-expense-management/blob/main/core/models.py"
click node_transaction "https://github.com/phupa26/personal-expense-management/blob/main/core/models.py"
click node_category "https://github.com/phupa26/personal-expense-management/blob/main/core/models.py"
click node_csv_import "https://github.com/phupa26/personal-expense-management/blob/main/import.csv"
click node_data_txt "https://github.com/phupa26/personal-expense-management/blob/main/storage/data.txt"
click node_log_txt "https://github.com/phupa26/personal-expense-management/blob/main/storage/inputoutput.txt"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main toneBlue
class node_models,node_structures,node_month_data,node_category_state,node_transaction,node_category toneAmber
class node_fileio,node_indexes toneMint
class node_txn_mgr,node_cat_mgr,node_report_mgr toneRose
class node_csv_import,node_data_txt,node_log_txt toneIndigo
```

## Components

### CLI

Terminal entrypoint and user interaction loop

- [Main CLI](https://github.com/phupa26/personal-expense-management/blob/main/main.py): entrypoint · Drives menus, input, and top-level orchestration · `main.py`

### Core

Domain models and custom data structures

- [Models](https://github.com/phupa26/personal-expense-management/blob/main/core/models.py): domain models · Transactions, categories, and monthly financial state · `core/models.py`
- [Hash Map](https://github.com/phupa26/personal-expense-management/blob/main/core/data_structure.py): custom DS · Custom hashmap/node storage for fast lookup and indexing · `core/data_structure.py`
- [Month Data](https://github.com/phupa26/personal-expense-management/blob/main/core/models.py): monthly state · Per-month aggregation of income, expense, budgets, and category state · `core/models.py`
- [Category State](https://github.com/phupa26/personal-expense-management/blob/main/core/models.py): budget state · Month-scoped category budget and activity status · `core/models.py`
- [Transaction](https://github.com/phupa26/personal-expense-management/blob/main/core/models.py): financial record · Single expense or income entry with date, amount, category, and notes · `core/models.py`
- [Category](https://github.com/phupa26/personal-expense-management/blob/main/core/models.py): domain entity · Named financial bucket with type and active status · `core/models.py`

### Data

Persistence and indexing boundary

- [File IO](https://github.com/phupa26/personal-expense-management/blob/main/data/file_io.py): persistence · Serializes and restores application state · `data/file_io.py`
- [Indices](https://github.com/phupa26/personal-expense-management/blob/main/data/index_services.py): lookup/indexing · Month, transaction, and category indexes · `data/index_services.py`

### Services

Business logic and reporting

- [Transactions](https://github.com/phupa26/personal-expense-management/blob/main/services/transaction_manager.py): service · Creates, updates, deletes, and validates transactions · `services/transaction_manager.py`
- [Categories](https://github.com/phupa26/personal-expense-management/blob/main/services/category_manager.py): service · Category CRUD and category-based filtering · `services/category_manager.py`
- [Reports](https://github.com/phupa26/personal-expense-management/blob/main/services/report_manager.py): service · Builds daily, monthly, yearly, and rolling reports · `services/report_manager.py`

### Storage

Durable files and operational artifacts

- [CSV Import](https://github.com/phupa26/personal-expense-management/blob/main/import.csv): bulk input · External CSV ingest path feeding the same transaction pipeline · `import.csv`
- [State File](https://github.com/phupa26/personal-expense-management/blob/main/storage/data.txt): persistent state · Primary saved financial data file · `storage/data.txt`
- [Action Log](https://github.com/phupa26/personal-expense-management/blob/main/storage/inputoutput.txt): execution log · Recorded prompts and user actions · `storage/inputoutput.txt`

## Connections

- Main CLI → Transactions: manage · Menu actions for add, update, delete, and validation
- Main CLI → Categories: maintain · Category management actions
- Main CLI → Reports: report · Requests summaries and reports
- Main CLI → File IO: load/save · Loads persisted state and writes updates
- Transactions → Indices: update · Maintains transaction and month lookup structures
- Transactions → Models: uses · Operates on transactions and monthly state
- Transactions → Category State: budget check · Checks and updates month-scoped category budgets
- Transactions → Category: resolve · Finds or assigns categories for transactions
- Categories → Category: manage · Creates, filters, and soft-deletes categories
- Reports → Indices: read · Reads month and transaction indices for aggregation
- Reports → Month Data: aggregate · Summarizes monthly financial state into reports
- Indices → Hash Map: backed by · Uses custom hashmap-based storage for lookup
- Indices → Transaction: map · Tracks transaction IDs and related lookup keys
- Indices → Month Data: organize · Groups transactions and state by month
- Month Data → Category State: contains · Holds per-category monthly budget state
- Month Data → Transaction: contains · Tracks transactions contributing to the month
- File IO → State File: persist · Reads and writes durable application state
- File IO → Models: serialize · Stores and restores domain objects
- File IO → Indices: restore · Rebuilds index structures from saved state
- CSV Import → Transactions: feed · Bulk imported records enter the transaction pipeline
- Main CLI → Action Log: record · Captures interaction history and prompts
