Spaces:
Sleeping
Sleeping
| import json | |
| import os | |
| from datetime import datetime | |
| from typing import List, Dict, Any | |
| DB_PATH = os.path.join(os.path.dirname(__file__), "database.json") | |
| if not os.path.exists(DB_PATH): | |
| with open(DB_PATH, "w") as f: | |
| json.dump({"expenses": [], "reminders": []}, f, indent=4) | |
| def _load_db() -> Dict[str, Any]: | |
| """Safely load JSON database.""" | |
| try: | |
| with open(DB_PATH, "r") as f: | |
| return json.load(f) | |
| except Exception: | |
| return {"expenses": [], "reminders": []} | |
| def _save_db(data: Dict[str, Any]): | |
| """Safely write JSON database.""" | |
| with open(DB_PATH, "w") as f: | |
| json.dump(data, f, indent=4) | |
| def today_iso() -> str: | |
| """Returns today's date in ISO format.""" | |
| return datetime.now().strftime("%Y-%m-%d") | |
| def add_expense(entry: Dict[str, Any]) -> None: | |
| """Add a new expense to database.json.""" | |
| db = _load_db() | |
| if "expenses" not in db: | |
| db["expenses"] = [] | |
| db["expenses"].append(entry) | |
| _save_db(db) | |
| def list_expenses(user_id: str) -> List[Dict[str, Any]]: | |
| """Return all expenses for a user.""" | |
| db = _load_db() | |
| expenses = db.get("expenses", []) | |
| return [e for e in expenses if e.get("user_id") == user_id] | |
| def total_spent(user_id: str) -> float: | |
| """Compute total spent by user.""" | |
| expenses = list_expenses(user_id) | |
| return sum([e.get("amount", 0) for e in expenses]) | |
| def expenses_by_category(user_id: str) -> Dict[str, float]: | |
| """Aggregate total amount per category.""" | |
| result = {} | |
| for e in list_expenses(user_id): | |
| cat = e.get("category", "Uncategorized") | |
| result[cat] = result.get(cat, 0) + e.get("amount", 0) | |
| return result | |
| def recent_expenses(user_id: str, limit: int = 5) -> List[Dict[str, Any]]: | |
| """Return N most recent expenses.""" | |
| items = list_expenses(user_id) | |
| items_sorted = sorted(items, key=lambda x: x.get("date", ""), reverse=True) | |
| return items_sorted[:limit] |