├── README.md ├── data_entry.py ├── finance_data.csv ├── main.py └── requirements.txt /README.md: -------------------------------------------------------------------------------- 1 | # Personal-Finance-Tracker 2 | 3 | # 💻 Launch Your Software Development Career Today! 4 | 5 | 🎓 **No degree? No problem!** My program equips you with everything you need to break into tech and land an entry-level software development role. 6 | 7 | 🚀 **Why Join?** 8 | - 💼 **$70k+ starting salary potential** 9 | - 🕐 **Self-paced:** Complete on your own time 10 | - 🤑 **Affordable:** Low risk compared to expensive bootcamps or degrees 11 | - 🎯 **45,000+ job openings** in the market 12 | 13 | 👉 **[Start your journey today!](https://techwithtim.net/dev)** 14 | No experience needed—just your determination. Future-proof your career and unlock six-figure potential like many of our students have! 15 | -------------------------------------------------------------------------------- /data_entry.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | date_format = "%d-%m-%Y" 4 | CATEGORIES = {"I": "Income", "E": "Expense"} 5 | 6 | 7 | def get_date(prompt, allow_default=False): 8 | date_str = input(prompt) 9 | if allow_default and not date_str: 10 | return datetime.today().strftime(date_format) 11 | 12 | try: 13 | valid_date = datetime.strptime(date_str, date_format) 14 | return valid_date.strftime(date_format) 15 | except ValueError: 16 | print("Invalid date frmat. Please enter the date in dd-mm-yyyy format") 17 | return get_date(prompt, allow_default) 18 | 19 | 20 | def get_amount(): 21 | try: 22 | amount = float(input("Enter the amount: ")) 23 | if amount <= 0: 24 | raise ValueError("Amount must be a non-negative non-zero value.") 25 | return amount 26 | except ValueError as e: 27 | print(e) 28 | return get_amount() 29 | 30 | 31 | def get_category(): 32 | category = input("Enter the category ('I' for Income or 'E' for Expense): ").upper() 33 | if category in CATEGORIES: 34 | return CATEGORIES[category] 35 | 36 | print("Invalid category. Please enter 'I' for Income or 'E' for Expense.") 37 | return get_category() 38 | 39 | 40 | def get_descriptipn(): 41 | return input("Enter a description (optional): ") 42 | -------------------------------------------------------------------------------- /finance_data.csv: -------------------------------------------------------------------------------- 1 | date,amount,category,description 2 | 01-07-2024,1000,Income,Salary 3 | 02-07-2024,50,Expense,Groceries 4 | 03-07-2024,150,Expense,Utilities 5 | 04-07-2024,200,Income,Freelance Work 6 | 05-07-2024,75,Expense,Restaurant 7 | 06-07-2024,100,Expense,Transport 8 | 07-07-2024,500,Income,Bonus 9 | 08-07-2024,30,Expense,Snacks 10 | 09-07-2024,250,Income,Stock Dividends 11 | 10-07-2024,90,Expense,Entertainment 12 | 11-07-2024,60,Expense,Coffee 13 | 12-07-2024,120,Expense,Gas 14 | 13-07-2024,80,Expense,Books 15 | 14-07-2024,150,Expense,Clothing 16 | 15-07-2024,1100,Income,Salary 17 | 16-07-2024,40,Expense,Stationery 18 | 17-07-2024,180,Expense,Utilities 19 | 18-07-2024,250,Income,Freelance Work 20 | 19-07-2024,70,Expense,Restaurant 21 | 20-07-2024,130,Expense,Transport 22 | 21-07-2024,600,Income,Bonus 23 | 22-07-2024,35,Expense,Snacks 24 | 23-07-2024,300,Income,Stock Dividends 25 | 24-07-2024,100,Expense,Entertainment 26 | 25-07-2024,55,Expense,Coffee 27 | 26-07-2024,140,Expense,Gas 28 | 27-07-2024,90,Expense,Books 29 | 28-07-2024,170,Expense,Clothing 30 | 29-07-2024,1200,Income,Salary 31 | 30-07-2024,45,Expense,Stationery 32 | 31-07-2024,190,Expense,Utilities 33 | 20-07-2023,124.0,Expense,Groceries 34 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import csv 3 | from datetime import datetime 4 | from data_entry import get_amount, get_category, get_date, get_descriptipn 5 | import matplotlib.pyplot as plt 6 | 7 | 8 | class CSV: 9 | CSV_FILE = "finance_data.csv" 10 | COLUMNS = ["date", "amount", "category", "description"] 11 | FORMAT = "%d-%m-%Y" 12 | 13 | @classmethod 14 | def initialize_csv(cls): 15 | try: 16 | pd.read_csv(cls.CSV_FILE) 17 | except FileNotFoundError: 18 | df = pd.DataFrame(columns=cls.COLUMNS) 19 | df.to_csv(cls.CSV_FILE, index=False) 20 | 21 | @classmethod 22 | def add_entry(cls, date, amount, category, description): 23 | new_entry = { 24 | "date": date, 25 | "amount": amount, 26 | "category": category, 27 | "description": description, 28 | } 29 | with open(cls.CSV_FILE, "a", newline="") as csvfile: 30 | writer = csv.DictWriter(csvfile, fieldnames=cls.COLUMNS) 31 | writer.writerow(new_entry) 32 | print("Entry added successfully") 33 | 34 | @classmethod 35 | def get_transactions(cls, start_date, end_date): 36 | df = pd.read_csv(cls.CSV_FILE) 37 | df["date"] = pd.to_datetime(df["date"], format=CSV.FORMAT) 38 | start_date = datetime.strptime(start_date, CSV.FORMAT) 39 | end_date = datetime.strptime(end_date, CSV.FORMAT) 40 | 41 | mask = (df["date"] >= start_date) & (df["date"] <= end_date) 42 | filtered_df = df.loc[mask] 43 | 44 | if filtered_df.empty: 45 | print("No transactions found in the given date range.") 46 | else: 47 | print( 48 | f"Transactions from {start_date.strftime(CSV.FORMAT)} to {end_date.strftime(CSV.FORMAT)}" 49 | ) 50 | print( 51 | filtered_df.to_string( 52 | index=False, formatters={"date": lambda x: x.strftime(CSV.FORMAT)} 53 | ) 54 | ) 55 | 56 | total_income = filtered_df[filtered_df["category"] == "Income"][ 57 | "amount" 58 | ].sum() 59 | total_expense = filtered_df[filtered_df["category"] == "Expense"][ 60 | "amount" 61 | ].sum() 62 | print("\nSummary:") 63 | print(f"Total Income: ${total_income:.2f}") 64 | print(f"Total Expense: ${total_expense:.2f}") 65 | print(f"Net Savings: ${(total_income - total_expense):.2f}") 66 | 67 | return filtered_df 68 | 69 | 70 | def add(): 71 | CSV.initialize_csv() 72 | date = get_date( 73 | "Enter the date of the transaction (dd-mm-yyyy) or enter for today's date: ", 74 | allow_default=True, 75 | ) 76 | amount = get_amount() 77 | category = get_category() 78 | description = get_descriptipn() 79 | CSV.add_entry(date, amount, category, description) 80 | 81 | 82 | def plot_transactions(df): 83 | df.set_index("date", inplace=True) 84 | 85 | income_df = ( 86 | df[df["category"] == "Income"] 87 | .resample("D") 88 | .sum() 89 | .reindex(df.index, fill_value=0) 90 | ) 91 | expense_df = ( 92 | df[df["category"] == "Expense"] 93 | .resample("D") 94 | .sum() 95 | .reindex(df.index, fill_value=0) 96 | ) 97 | 98 | plt.figure(figsize=(10, 5)) 99 | plt.plot(income_df.index, income_df["amount"], label="Income", color="g") 100 | plt.plot(expense_df.index, expense_df["amount"], label="Expense", color="r") 101 | plt.xlabel("Date") 102 | plt.ylabel("Amount") 103 | plt.title("Income and Expenses Over Time") 104 | plt.legend() 105 | plt.grid(True) 106 | plt.show() 107 | 108 | 109 | def main(): 110 | while True: 111 | print("\n1. Add a new transaction") 112 | print("2. View transactions and summary within a date range") 113 | print("3. Exit") 114 | choice = input("Enter your choice (1-3): ") 115 | 116 | if choice == "1": 117 | add() 118 | elif choice == "2": 119 | start_date = get_date("Enter the start date (dd-mm-yyyy): ") 120 | end_date = get_date("Enter the end date (dd-mm-yyyy): ") 121 | df = CSV.get_transactions(start_date, end_date) 122 | if input("Do you want to see a plot? (y/n) ").lower() == "y": 123 | plot_transactions(df) 124 | elif choice == "3": 125 | print("Exiting...") 126 | break 127 | else: 128 | print("Invalid choice. Enter 1, 2 or 3.") 129 | 130 | 131 | if __name__ == "__main__": 132 | main() 133 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pandas 2 | matplotlib --------------------------------------------------------------------------------