Initial commit: MyMidas personal finance tracker

Full-stack self-hosted finance app with FastAPI backend and React frontend.

Features:
- Accounts, transactions, budgets, investments with GBP base currency
- CSV import with auto-detection for 10 UK bank formats
- ML predictions: spending forecast, net worth projection, Monte Carlo
- 7 selectable themes (Obsidian, Arctic, Midnight, Vault, Terminal, Synthwave, Ledger)
- Receipt/document attachments on transactions (JPEG, PNG, WebP, PDF)
- AES-256-GCM field encryption, RS256 JWT, TOTP 2FA, RLS, audit log
- Encrypted nightly backups + key rotation script
- Mobile-responsive layout with bottom nav

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-04-21 11:56:10 +00:00
commit 61a7884ee5
127 changed files with 13323 additions and 0 deletions

View file

@ -0,0 +1,109 @@
import { api } from "./client";
export interface CategoryForecast {
category_id: string;
category_name: string;
monthly_avg: number;
actuals: { date: string; amount: number }[];
forecast: { date: string; amount: number; lower: number; upper: number }[];
}
export interface SpendingForecastResponse {
categories: CategoryForecast[];
}
export interface NetWorthProjectionResponse {
history: { date: string; value: number }[];
projections: {
conservative: { date: string; value: number }[];
base: { date: string; value: number }[];
optimistic: { date: string; value: number }[];
};
insufficient_data: boolean;
}
export interface PercentilePath {
date: string;
value: number;
}
export interface MonteCarloResponse {
dates: string[];
percentiles: {
p10: PercentilePath[];
p25: PercentilePath[];
p50: PercentilePath[];
p75: PercentilePath[];
p90: PercentilePath[];
};
current_value: number;
expected_value: number;
probability_of_gain: number;
insufficient_data: boolean;
}
export interface BudgetForecastItem {
category_id: string;
category_name: string;
budget_amount: number;
spent_so_far: number;
forecast_month_total: number;
daily_velocity: number;
probability_overspend: number;
days_remaining: number;
}
export interface BudgetForecastResponse {
forecasts: BudgetForecastItem[];
message?: string;
}
export interface CashFlowDay {
date: string;
balance: number;
avg_inflow: number;
avg_outflow: number;
negative_risk: boolean;
}
export interface CashFlowResponse {
current_balance: number;
avg_daily_inflow: number;
avg_daily_outflow: number;
forecast: CashFlowDay[];
negative_risk_days: string[];
history_days: number;
}
export async function getSpendingForecast(): Promise<SpendingForecastResponse> {
const res = await api.get("/predictions/spending");
return res.data;
}
export async function getNetWorthProjection(years = 5): Promise<NetWorthProjectionResponse> {
const res = await api.get("/predictions/net-worth", { params: { years } });
return res.data;
}
export async function postMonteCarlo(params: {
years?: number;
n_simulations?: number;
annual_contribution?: number;
}): Promise<MonteCarloResponse> {
const res = await api.post("/predictions/monte-carlo", {
years: params.years ?? 5,
n_simulations: params.n_simulations ?? 1000,
annual_contribution: params.annual_contribution ?? 0,
});
return res.data;
}
export async function getBudgetForecast(): Promise<BudgetForecastResponse> {
const res = await api.get("/predictions/budget-forecast");
return res.data;
}
export async function getCashFlowForecast(): Promise<CashFlowResponse> {
const res = await api.get("/predictions/cashflow");
return res.data;
}