Personal Finance Tracker

 import tkinter as tk

from tkinter import ttk, messagebox

import sqlite3

import matplotlib.pyplot as plt


# Database Setup

conn = sqlite3.connect("finance_tracker.db")

cursor = conn.cursor()

cursor.execute("""

    CREATE TABLE IF NOT EXISTS transactions (

        id INTEGER PRIMARY KEY AUTOINCREMENT,

        date TEXT,

        category TEXT,

        amount REAL,

        type TEXT

    )

""")

conn.commit()


class FinanceTracker:

    def __init__(self, root):

        self.root = root

        self.root.title("Personal Finance Tracker 💰")

        self.root.geometry("600x500")


        # UI Components

        tk.Label(root, text="Date (YYYY-MM-DD):").grid(row=0, column=0, padx=10, pady=5, sticky="w")

        self.date_entry = tk.Entry(root, width=30)

        self.date_entry.grid(row=0, column=1, padx=10, pady=5)


        tk.Label(root, text="Category:").grid(row=1, column=0, padx=10, pady=5, sticky="w")

        self.category_entry = tk.Entry(root, width=30)

        self.category_entry.grid(row=1, column=1, padx=10, pady=5)


        tk.Label(root, text="Amount:").grid(row=2, column=0, padx=10, pady=5, sticky="w")

        self.amount_entry = tk.Entry(root, width=30)

        self.amount_entry.grid(row=2, column=1, padx=10, pady=5)


        tk.Label(root, text="Transaction Type:").grid(row=3, column=0, padx=10, pady=5, sticky="w")

        self.type_var = tk.StringVar(value="Expense")  

        self.type_dropdown = ttk.Combobox(root, textvariable=self.type_var, values=["Expense", "Income"], width=28)

        self.type_dropdown.grid(row=3, column=1, padx=10, pady=5)

        self.type_dropdown.current(0)


        # Buttons - Expanded Width

        tk.Button(root, text="Add Transaction", command=self.add_transaction, width=20).grid(row=4, column=0, columnspan=2, pady=10)

        tk.Button(root, text="Show Transactions", command=self.show_transactions, width=20).grid(row=5, column=0, columnspan=2, pady=5)

        tk.Button(root, text="View Report", command=self.view_report, width=20).grid(row=6, column=0, columnspan=2, pady=5)


        # Transaction List Display

        self.tree = ttk.Treeview(root, columns=("ID", "Date", "Category", "Amount", "Type"), show="headings")

        self.tree.heading("ID", text="ID")

        self.tree.heading("Date", text="Date")

        self.tree.heading("Category", text="Category")

        self.tree.heading("Amount", text="Amount")

        self.tree.heading("Type", text="Type")

        self.tree.column("ID", width=30)

        self.tree.column("Date", width=100)

        self.tree.column("Category", width=100)

        self.tree.column("Amount", width=80)

        self.tree.column("Type", width=80)

        self.tree.grid(row=7, column=0, columnspan=2, padx=10, pady=10)


    def add_transaction(self):

        date = self.date_entry.get()

        category = self.category_entry.get()

        amount = self.amount_entry.get()

        trans_type = self.type_var.get()


        if not date or not category or not amount or not trans_type:

            messagebox.showerror("Error", "All fields are required!")

            return

        

        try:

            amount = float(amount)

            cursor.execute("INSERT INTO transactions (date, category, amount, type) VALUES (?, ?, ?, ?)", 

                           (date, category, amount, trans_type))

            conn.commit()

            messagebox.showinfo("Success", "Transaction added successfully!")

            self.clear_entries()

        except ValueError:

            messagebox.showerror("Error", "Amount must be a number!")


    def show_transactions(self):

        for item in self.tree.get_children():

            self.tree.delete(item)


        cursor.execute("SELECT * FROM transactions")

        for row in cursor.fetchall():

            self.tree.insert("", "end", values=row)


    def view_report(self):

        cursor.execute("SELECT category, SUM(amount) FROM transactions WHERE type='Expense' GROUP BY category")

        data = cursor.fetchall()


        if not data:

            messagebox.showinfo("Report", "No expenses recorded.")

            return


        categories, amounts = zip(*data)

        plt.figure(figsize=(6, 6))

        plt.pie(amounts, labels=categories, autopct="%1.1f%%", startangle=140)

        plt.title("Expense Breakdown")

        plt.show()


    def clear_entries(self):

        self.date_entry.delete(0, tk.END)

        self.category_entry.delete(0, tk.END)

        self.amount_entry.delete(0, tk.END)

        self.type_var.set("Expense")


# Run the application

if __name__ == "__main__":

    root = tk.Tk()

    app = FinanceTracker(root)

    root.mainloop()

No comments: