import json import os from datetime import date DATA_DIR = os.path.join(os.path.dirname(__file__), "data") SINKING_FILE = os.path.join(DATA_DIR, "sinking_funds.json") FUND_COLORS = { "Travel": "#C5BBA0", "Vet & Pets": "#A0B8C5", "Holidays & Gifts": "#D4B8C5", "Renovations": "#C5A8A0", "Studio Build": "#B4A0C5", "Emergency Fund": "#A8C5A0", } DEFAULT_FUNDS = [ {"name": "Travel", "type": "ongoing", "monthly": 0, "balance": 0, "notes": ""}, {"name": "Vet & Pets", "type": "ongoing", "monthly": 0, "balance": 0, "notes": ""}, {"name": "Holidays & Gifts", "type": "ongoing", "monthly": 0, "balance": 0, "notes": ""}, {"name": "Renovations", "type": "ongoing", "monthly": 0, "balance": 0, "notes": "Subcategories coming later"}, {"name": "Studio Build", "type": "ongoing", "monthly": 0, "balance": 0, "notes": "Goal amount TBD"}, {"name": "Emergency Fund", "type": "ongoing", "monthly": 0, "balance": 0, "notes": "Target: 3–6 months expenses"}, ] def load_funds(): if os.path.exists(SINKING_FILE): with open(SINKING_FILE) as f: return json.load(f) # First run — seed with defaults save_funds(DEFAULT_FUNDS) return DEFAULT_FUNDS def save_funds(funds): with open(SINKING_FILE, "w") as f: json.dump(funds, f, indent=2) def months_until(target_date_str): try: target = date.fromisoformat(target_date_str) today = date.today() months = (target.year - today.year) * 12 + (target.month - today.month) return max(months, 1) except Exception: return None def monthly_needed(balance, goal, target_date_str): m = months_until(target_date_str) if not m: return None remaining = max(goal - balance, 0) return round(remaining / m, 2)