Domain Model¶
Understanding Maxwell's Wallet's data model and business concepts.
Core Entities¶
Transaction¶
The central entity representing a financial transaction.
| Field | Type | Description |
|---|---|---|
id |
int | Primary key |
date |
date | Transaction date |
amount |
float | Negative = expense, positive = income |
merchant |
string | Normalized merchant name |
description |
string | Original bank description |
account_source |
string | Source account identifier |
account_tag_id |
int | FK to account Tag |
reconciliation_status |
enum | unreconciled, matched, ignored, manually_entered |
is_transfer |
bool | Internal transfer flag |
content_hash |
string | SHA256 with account for same-account dedup |
content_hash_no_account |
string | SHA256 without account for cross-account detection |
TransactionSplit¶
Allows splitting a single transaction across multiple buckets.
| Field | Type | Description |
|---|---|---|
id |
int | Primary key |
transaction_id |
int | FK to Transaction |
tag_id |
int | FK to Tag (bucket) |
amount |
float | Portion allocated to this bucket |
notes |
string | Optional description |
When a transaction has splits, the original bucket tag is ignored and splits determine categorization.
Tag¶
Flexible categorization system with namespaces.
| Namespace | Purpose | Cardinality |
|---|---|---|
bucket |
Spending category | One per transaction (or splits) |
occasion |
Events/trips | Many per transaction |
account |
Source account | One per transaction |
Budget¶
Spending limits with tracking.
| Field | Description |
|---|---|
tag_namespace |
Which namespace to track (bucket, occasion, account) |
tag_value |
Which tag value |
amount |
Spending limit |
period |
monthly or yearly |
Dashboard¶
Named dashboard configuration with shared settings.
| Field | Type | Description |
|---|---|---|
id |
int | Primary key |
name |
string | Display name |
description |
string | Optional description |
view_mode |
string | "month" or "year" |
pinned_year |
int | Optional fixed year |
pinned_month |
int | Optional fixed month |
filter_buckets |
JSON | Dashboard-level bucket filter |
filter_accounts |
JSON | Dashboard-level account filter |
filter_merchants |
JSON | Dashboard-level merchant filter |
is_default |
bool | Loads on homepage |
position |
int | Sidebar order |
DashboardWidget¶
Individual widget within a dashboard.
| Field | Type | Description |
|---|---|---|
id |
int | Primary key |
dashboard_id |
int | FK to Dashboard |
widget_type |
string | Type of visualization |
title |
string | Display title |
position |
int | Order in dashboard |
width |
string | Layout width |
is_visible |
bool | Show/hide toggle |
config |
JSON | Widget-specific settings |
filter_buckets |
JSON | Widget-level bucket filter (overrides dashboard) |
filter_accounts |
JSON | Widget-level account filter |
filter_merchants |
JSON | Widget-level merchant filter |
Widget Types:
summary, velocity, spending_chart, budget_progress, top_merchants, recent_transactions, month_over_month, anomalies, recurring, credit_cards, insights, sankey_chart, treemap_chart, calendar_heatmap
Bounded Contexts¶
Import Context¶
Responsible for parsing external files and creating transactions.
- File format detection (AMEX, BofA, Venmo, Inspira HSA, QIF/QFX/OFX)
- Dual-hash duplicate detection (same-account and cross-account)
- Merchant alias application
- Bucket tag inference
- Required account selection
Dashboard Context¶
Manages multi-dashboard configuration and widgets.
- Dashboard CRUD with clone/set-default
- Widget layout and visibility
- Per-widget and per-dashboard filtering
- View mode (month/year) switching
Analytics Context¶
Generates insights from transaction data.
- Monthly/yearly summaries
- Advanced visualizations (Sankey, Treemap, Heatmap)
- Trend analysis
- Anomaly detection
- Budget status calculation
Organization Context¶
Manages categorization and tagging.
- Tag CRUD
- Category rules (pattern-based auto-categorization)
- Merchant aliases
- Transfer detection
- Split transactions
Business Rules¶
Duplicate Detection¶
Dual-hash approach for reliable deduplication:
content_hash = SHA256(date + amount + description + account)
content_hash_no_account = SHA256(date + amount + description)
- Same-account duplicates: Rejected using
content_hash - Cross-account matches: Warning using
content_hash_no_account
Split Transaction Allocation¶
When a transaction is split:
- Original bucket tag is ignored
- Each split allocates a portion to a bucket
- Split amounts must sum to transaction amount
- Budget calculations use split amounts
Transfer Identification¶
A transaction is marked as transfer if:
- Merchant matches transfer patterns (AUTOPAY, ACH, WIRE, etc.)
- OR manually marked by user
Transfers are excluded from spending calculations.
Budget Status¶
if spent < limit * 0.8:
status = "on_track"
elif spent < limit:
status = "warning"
else:
status = "exceeded"
Widget Filter Inheritance¶
Filters cascade from dashboard to widget:
- Dashboard filters apply to all widgets as defaults
- Widget filters override dashboard filters when set
- Empty widget filter = use dashboard filter
Large Transaction Threshold¶
Calculated from 3-month expense baseline:
This captures approximately the 95th percentile of spending.