from pathlib import Path from flask import Flask, render_template, request import subprocess import sys import json from pathlib import Path from flask import redirect from datetime import datetime app = Flask(__name__) BASE_DIR = Path(__file__).parent CATEGORIES_FILE = BASE_DIR / "Kategorien.json" def get_current_week_data(): year, week, _ = datetime.now().isocalendar() summary_file = ( BASE_DIR / "Transaktionen" / str(year) / "summary" / f"category_summary_{year}_KW{week:02d}.json" ) transactions_file = ( BASE_DIR / "Transaktionen" / str(year) / "categorized_json" / f"categorized_transactions_{year}_KW{week:02d}.json" ) summary = None transactions = [] total_income = 0 total_expenses = 0 total_saldo = 0 if summary_file.exists(): with open( summary_file, encoding="utf-8" ) as f: summary = json.load(f) for values in summary.values(): total_income += values["income"] total_expenses += values["expenses"] total_saldo += values["saldo"] if transactions_file.exists(): with open( transactions_file, encoding="utf-8" ) as f: transactions = json.load(f) return ( year, week, summary, transactions, total_income, total_expenses, total_saldo ) @app.route("/") @app.route("/") def index(): ( year, week, summary, transactions, total_income, total_expenses, total_saldo ) = get_current_week_data() return render_template( "index.html", year=year, week=week, summary=summary, transactions=transactions, total_income=total_income, total_expenses=total_expenses, total_saldo=total_saldo ) @app.route("/run/balance", methods=["POST"]) def run_balance(): result = subprocess.run( [sys.executable, str(BASE_DIR / "balance.py")], capture_output=True, text=True ) return render_template( "result.html", title="balance.py", output=result.stdout + result.stderr ) @app.route("/run/transactions", methods=["POST"]) def run_transactions(): year = request.form.get("year", "").strip() week = request.form.get("week", "").strip() command = [ sys.executable, str(BASE_DIR / "transactions.py") ] if year and week: command.extend([year, week]) result = subprocess.run( command, capture_output=True, text=True ) return render_template( "result.html", title="transactions.py", output=result.stdout + result.stderr ) @app.route("/run/categorize", methods=["POST"]) def run_categorize(): year = request.form.get("year", "").strip() week = request.form.get("week", "").strip() command = [ sys.executable, str(BASE_DIR / "categorize_transactions.py") ] if year and week: command.extend([year, week]) result = subprocess.run( command, capture_output=True, text=True ) return render_template( "result.html", title="categorize_transactions.py", output=result.stdout + result.stderr ) @app.route("/categories") def categories(): with open( CATEGORIES_FILE, encoding="utf-8" ) as f: categories = json.load(f) #print(categories) return render_template( "categories.html", categories=categories ) @app.route("/categories/delete/") def delete_category(category): with open( CATEGORIES_FILE, encoding="utf-8" ) as f: categories = json.load(f) if category in categories: del categories[category] with open( CATEGORIES_FILE, "w", encoding="utf-8" ) as f: json.dump( categories, f, ensure_ascii=False, indent=2 ) return redirect("/categories") @app.route( "/categories/add", methods=["POST"] ) def add_category(): category = request.form["category"].strip() with open( CATEGORIES_FILE, encoding="utf-8" ) as f: categories = json.load(f) if category not in categories: categories[category] = [] with open( CATEGORIES_FILE, "w", encoding="utf-8" ) as f: json.dump( categories, f, ensure_ascii=False, indent=2 ) return redirect("/categories") @app.route("/categories/edit/") def edit_category(category): with open( CATEGORIES_FILE, encoding="utf-8" ) as f: categories = json.load(f) if category not in categories: return redirect("/categories") return render_template( "edit_category.html", category=category, words=sorted(categories[category]) ) @app.route( "/categories/add_word/", methods=["POST"] ) def add_word(category): word = request.form["word"].strip() with open( CATEGORIES_FILE, encoding="utf-8" ) as f: categories = json.load(f) if ( category in categories and word and word not in categories[category] ): categories[category].append(word) with open( CATEGORIES_FILE, "w", encoding="utf-8" ) as f: json.dump( categories, f, ensure_ascii=False, indent=2 ) return redirect( f"/categories/edit/{category}" ) @app.route( "/categories/delete_word//" ) def delete_word(category, word): with open( CATEGORIES_FILE, encoding="utf-8" ) as f: categories = json.load(f) if ( category in categories and word in categories[category] ): categories[category].remove(word) with open( CATEGORIES_FILE, "w", encoding="utf-8" ) as f: json.dump( categories, f, ensure_ascii=False, indent=2 ) return redirect( f"/categories/edit/{category}" ) if __name__ == "__main__": app.run( host="0.0.0.0", port=5000, debug=True )