Project Cs
Project Cs
pip install
mysql-connector-python
matplotlib
"""
Smart Daily Expense Tracker
Single-file example with:
- Tkinter GUI
- MySQL connectivity (creates DB & table if not exists)
- File handling (generates text report in ./reports/)
- Matplotlib graphs embedded in Tkinter
Author: Example for Class 12 project
"""
import os
import [Link]
from [Link] import errorcode
import tkinter as tk
from tkinter import ttk, messagebox
from tkinter import simpledialog
from datetime import datetime, date
import matplotlib
[Link]("TkAgg")
from [Link] import Figure
from [Link].backend_tkagg import FigureCanvasTkAgg
# ---------------------------
# ====== CONFIGURE DB =======
# ---------------------------
DB_CONFIG = {
"host": "localhost",
"user": "root",
"password": "", # <- set your MySQL root password here
"database": "expense_tracker_db"
}
# ---------------------------
# ====== DB & TABLE SETUP ===
# ---------------------------
def get_db_connection(create_db_if_missing=True):
"""Establish connection. If DB doesn't exist, optionally create it."""
try:
conn = [Link](
host=DB_CONFIG["host"],
user=DB_CONFIG["user"],
password=DB_CONFIG["password"],
)
cursor = [Link]()
# create database if not exists
if create_db_if_missing:
[Link](f"CREATE DATABASE IF NOT EXISTS
{DB_CONFIG['database']}")
[Link] = DB_CONFIG['database']
return conn
except [Link] as err:
[Link]("DB Error", f"Database connection failed:\n{err}")
raise
def setup_table():
conn = get_db_connection()
cursor = [Link]()
create_table = (
"CREATE TABLE IF NOT EXISTS expenses ("
" id INT AUTO_INCREMENT PRIMARY KEY,"
" date DATE NOT NULL,"
" category VARCHAR(50) NOT NULL,"
" amount DECIMAL(10,2) NOT NULL,"
" note VARCHAR(255)"
");"
)
[Link](create_table)
[Link]()
[Link]()
[Link]()
# ---------------------------
# ====== DB FUNCTIONS =======
# ---------------------------
def add_expense_to_db(tx_date, category, amount, note):
conn = get_db_connection()
cursor = [Link]()
insert_q = "INSERT INTO expenses (date, category, amount, note) VALUES (%s, %s,
%s, %s)"
[Link](insert_q, (tx_date, category, amount, note))
[Link]()
[Link]()
[Link]()
def delete_expense(expense_id):
conn = get_db_connection()
cursor = [Link]()
[Link]("DELETE FROM expenses WHERE id = %s", (expense_id,))
[Link]()
[Link]()
[Link]()
# ---------------------------
# ====== GUI FUNCTIONS ======
# ---------------------------
class ExpenseTrackerApp:
def __init__(self, root):
[Link] = root
[Link]("Smart Daily Expense Tracker")
[Link]("780x520")
def add_expense(self):
dt = self.date_var.get().strip()
cat = self.category_var.get().strip()
amt = self.amount_var.get().strip()
note = self.note_var.get().strip()
if not dt or not cat or not amt:
[Link]("Missing data", "Please fill Date, Category and
Amount.")
return
try:
# validate date and amount
dt_obj = [Link](dt, "%Y-%m-%d").date()
amt_f = float(amt)
except Exception as e:
[Link]("Invalid input", f"Date or amount invalid:\n{e}")
return
add_expense_to_db(dt_obj, cat, amt_f, note)
[Link]("Success", "Expense added.")
# clear amount and note
self.amount_var.set("")
self.note_var.set("")
self.refresh_today_summary()
def refresh_today_summary(self):
today = [Link]()
rows = fetch_expenses(from_date=str(today), to_date=str(today))
total = sum([float(r['amount']) for r in rows])
self.summary_text.delete("1.0", [Link])
self.summary_text.insert([Link], f"Date: {today}\nTotal expenses today: ₹
{total:.2f}\n\nDetails:\n")
if not rows:
self.summary_text.insert([Link], "No expenses today.\n")
else:
for r in rows:
self.summary_text.insert([Link], f"- [{r['id']}] {r['category']}: ₹
{r['amount']} ({r['note']})\n")
def show_expenses_window(self):
win = [Link]([Link])
[Link]("All Expenses")
[Link]("700x420")
# Filter frame
fframe = [Link](win)
[Link](fill="x", padx=6, pady=6)
[Link](fframe, text="From (YYYY-MM-DD)").grid(row=0, column=0, padx=4)
from_var = [Link]()
[Link](fframe, textvariable=from_var, width=12).grid(row=0, column=1,
padx=4)
[Link](fframe, text="To (YYYY-MM-DD)").grid(row=0, column=2, padx=4)
to_var = [Link]()
[Link](fframe, textvariable=to_var, width=12).grid(row=0, column=3,
padx=4)
[Link](fframe, text="Category").grid(row=0, column=4, padx=4)
cat_var = [Link]()
[Link](fframe, textvariable=cat_var, width=15).grid(row=0, column=5,
padx=4)
def apply_filter():
rows = fetch_expenses(from_date=from_var.get() or None,
to_date=to_var.get() or None, category=cat_var.get() or None)
fill_tree(rows)
[Link](fframe, text="Apply Filter", command=apply_filter).grid(row=0,
column=6, padx=4)
# populate initial
def fill_tree(rows):
for i in tree.get_children():
[Link](i)
for r in rows:
[Link]("", [Link], values=(r['id'], r['date'], r['category'],
float(r['amount']), r['note'] or ""))
rows = fetch_expenses()
fill_tree(rows)
# delete button
def delete_selected():
sel = [Link]()
if not sel:
[Link]("Select", "Select a row to delete.")
return
item = [Link](sel[0])
expense_id = item['values'][0]
if [Link]("Confirm", f"Delete expense id {expense_id}?"):
delete_expense(expense_id)
[Link](sel[0])
self.refresh_today_summary()
[Link](win, text="Delete Selected",
command=delete_selected).pack(pady=4)
def show_graphs_dialog(self):
# get month / date range from user
win = [Link]([Link])
[Link]("Graphs - choose range")
[Link]("420x140")
[Link](win, text="From (YYYY-MM-DD):").grid(row=0, column=0, padx=6,
pady=6)
fvar = [Link]()
[Link](win, textvariable=fvar).grid(row=0, column=1)
[Link](win, text="To (YYYY-MM-DD):").grid(row=1, column=0, padx=6,
pady=6)
tvar = [Link]()
[Link](win, textvariable=tvar).grid(row=1, column=1)
def open_graphs():
fd = [Link]() or None
td = [Link]() or None
[Link]()
self.show_graphs_window(fd, td)
[Link](win, text="Show", command=open_graphs).grid(row=2, column=0,
columnspan=2, pady=8)
gwin = [Link]([Link])
[Link]("Expense Graphs")
[Link]("900x420")
# ---------------------------
# ====== RUN APP ============
# ---------------------------
if __name__ == "__main__":
root = [Link]()
app = ExpenseTrackerApp(root)
[Link]()