diff --git a/reports.py b/reports.py deleted file mode 100644 index 94cace8..0000000 --- a/reports.py +++ /dev/null @@ -1,125 +0,0 @@ -import sqlite3 -import os -from datetime import datetime - -def connect_db(): - """ - Connects to the SQLite database file and returns the connection object. - If the file does not exist, it prints an an error message. - """ - db_file = 'time_tracker.db' - if not os.path.exists(db_file): - print(f"Error: Database file '{db_file}' not found. Please run the database creation script first.") - return None - return sqlite3.connect(db_file) - -def unbilled_time_report(): - """ - Generates a report of unbilled time entries for a selected client. - """ - conn = connect_db() - if not conn: - return - - try: - cursor = conn.cursor() - - # Display active clients for selection - cursor.execute('SELECT client_id, client_name FROM clients WHERE active = 1 ORDER BY client_name') - active_clients = cursor.fetchall() - - if not active_clients: - print("No active clients found to generate a report for.") - return - - print("\n--- Select a Client for Unbilled Time Report ---") - for client_id, client_name in active_clients: - print(f"{client_id}: {client_name}") - print("0: Exit") - print("--------------------------------------------------\n") - - while True: - try: - choice = input("Enter the ID of the client (or 0 to exit): ") - if choice == '0': - print("Exiting report generation.") - return - - client_id = int(choice) - if any(c[0] == client_id for c in active_clients): - break - else: - print("Invalid client ID. Please enter a valid ID from the list.") - except ValueError: - print("Invalid input. Please enter a number.") - - # Fetch client details and billing rate - cursor.execute('SELECT client_name, billing_rate FROM clients WHERE client_id = ?', (client_id,)) - client_name, billing_rate = cursor.fetchone() - - # Fetch unbilled time entries for the selected client, including description - cursor.execute(''' - SELECT date, hours, description, project - FROM time_tracking - WHERE client_id = ? AND invoiced = 0 - ORDER BY date - ''', (client_id,)) - - time_entries = cursor.fetchall() - - if not time_entries: - print(f"\nNo unbilled time entries found for {client_name}.") - return - - # Calculate daily summary, descriptions, and total cost - daily_summary = {} - grand_total_cost = 0.0 - - for entry_date, hours, description, project in time_entries: - if entry_date not in daily_summary: - daily_summary[entry_date] = {'hours': 0.0, 'cost': 0.0, 'entries': []} - - daily_summary[entry_date]['hours'] += hours - daily_summary[entry_date]['cost'] += hours * billing_rate - daily_summary[entry_date]['entries'].append({'description': description, 'project': project}) - grand_total_cost += hours * billing_rate - - # Print the formatted report - print(f"\n--- Unbilled Time Report for {client_name} ---") - print(f"Total Unbilled Cost: ${grand_total_cost:.2f}\n") - - for daily_date, summary in daily_summary.items(): - print(f"Date: {daily_date} | Hours: {summary['hours']:.2f} | Cost: ${summary['cost']:.2f}") - for entry in summary['entries']: - print(f" - Project: {entry['project']}, Description: {entry['description']}") - print("-" * 32) - - print(f"\nReport generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") - - except sqlite3.Error as e: - print(f"An error occurred: {e}") - finally: - if conn: - conn.close() - -def main_menu(): - """ - Displays the main menu and handles user choices. - """ - while True: - print("\n--- Reports Menu ---") - print("1: Unbilled Time") - print("0: Exit") - print("--------------------\n") - choice = input("Enter your choice: ") - - if choice == '1': - unbilled_time_report() - elif choice == '0': - print("Exiting reports script. Goodbye!") - break - else: - print("Invalid choice. Please try again.") - -if __name__ == "__main__": - main_menu()