diff --git a/Config.json b/Config.json index e10d730..3e230b8 100644 --- a/Config.json +++ b/Config.json @@ -1,4 +1,4 @@ { - "DataDirectory": "~/HourStack", - "PDFOutputDirectory": "~/Invoices" -} \ No newline at end of file + "DataDirectory": "/Users/mattspeer/time-tracking/test-data", + "PDFOutputDirectory": "/Users/mattspeer/time-tracking/test-invoices" +} diff --git a/EnterTime.py b/EnterTime.py index 994f8fa..0097d87 100644 --- a/EnterTime.py +++ b/EnterTime.py @@ -1,5 +1,5 @@ import os -import json +import argparse from datetime import datetime from utils import load_config, load_json, save_json @@ -21,7 +21,7 @@ def select_or_create_client(data_dir, clients_data): choice = input("\nSelect a number: ") if choice == str(len(active_clients) + 1): - # Create New Client Flow[cite: 2] + # Create New Client Flow new_name = input("Client Name: ") new_rate = float(input("Default Hourly Rate: ") or 0) new_id = get_next_id(clients_data["Clients"], "CLT", "ClientID") @@ -54,7 +54,7 @@ def select_or_create_project(data_dir, projects_data, client_id): if choice == "0": return "" elif choice == str(len(client_projects) + 1): - # Create New Project Flow[cite: 2] + # Create New Project Flow new_name = input("Project Name: ") new_rate = float(input("Project Billing Rate (0 for client default): ") or 0) new_id = get_next_id(projects_data["Projects"], "PRJ", "ProjectID") @@ -73,23 +73,38 @@ def select_or_create_project(data_dir, projects_data, client_id): return client_projects[int(choice) - 1]["ProjectID"] def main(): + # Setup argument parser to accept data from Apple Shortcuts + parser = argparse.ArgumentParser(description="Log a time entry.") + parser.add_argument("--date", type=str, help="Date in YYYY-MM-DD format") + parser.add_argument("--duration", type=float, help="Duration in hours") + parser.add_argument("--client", type=str, help="Client ID") + parser.add_argument("--project", type=str, help="Project ID (Optional)", default="") + parser.add_argument("--desc", type=str, help="Description of work") + args = parser.parse_args() + config = load_config() data_dir = config["DataDirectory"] - # Load existing data[cite: 2] + # Load existing data clients_data = load_json(os.path.join(data_dir, "Clients.json"), {"Clients": []}) projects_data = load_json(os.path.join(data_dir, "Projects.json"), {"Projects": []}) - # Collect Entry Details[cite: 2] - date_str = input(f"Date (YYYY-MM-DD) [Default: {datetime.now().strftime('%Y-%m-%d')}]: ") or datetime.now().strftime("%Y-%m-%d") - duration = float(input("Duration (e.g., 1.5): ")) - - client_id = select_or_create_client(data_dir, clients_data) - project_id = select_or_create_project(data_dir, projects_data, client_id) - - description = input("Description: ") + # Check if data was passed via parameters (e.g., from Apple Shortcuts) + if args.duration and args.client and args.desc: + date_str = args.date if args.date else datetime.now().strftime("%Y-%m-%d") + duration = args.duration + client_id = args.client + project_id = args.project + description = args.desc + else: + # Fall back to interactive mode if no parameters were passed + date_str = input(f"Date (YYYY-MM-DD) [Default: {datetime.now().strftime('%Y-%m-%d')}]: ") or datetime.now().strftime("%Y-%m-%d") + duration = float(input("Duration (e.g., 1.5): ")) + client_id = select_or_create_client(data_dir, clients_data) + project_id = select_or_create_project(data_dir, projects_data, client_id) + description = input("Description: ") - # Generate Entry[cite: 2] + # Generate Entry entry_id = datetime.now().strftime("%Y%m%d%H%M%S") entry = { "ID": entry_id, @@ -102,7 +117,7 @@ def main(): "InvoiceNumber": "" } - # Save to Annual Log[cite: 2] + # Save to Annual Log year = date_str.split('-')[0] log_path = os.path.join(data_dir, f"{year}_Time_Log.json") log_data = load_json(log_path, {"Year": int(year), "Entries": []}) diff --git a/test-data/2026_Time_Log.json b/test-data/2026_Time_Log.json new file mode 100644 index 0000000..7a9f852 --- /dev/null +++ b/test-data/2026_Time_Log.json @@ -0,0 +1,35 @@ +{ + "Year": 2026, + "Entries": [ + { + "ID": "20260509161557", + "Date": "2026-05-09", + "Duration": 1.0, + "ClientID": "CLT-001", + "ProjectID": "", + "Description": "Test time entry", + "Invoiced": false, + "InvoiceNumber": "" + }, + { + "ID": "20260523222322", + "Date": "2026-05-23", + "Duration": 100.0, + "ClientID": "CLT-001", + "ProjectID": "PRJ-001", + "Description": "Test Work Description", + "Invoiced": false, + "InvoiceNumber": "" + }, + { + "ID": "20260524104443", + "Date": "2026-05-24", + "Duration": 30.5, + "ClientID": "CLT-001", + "ProjectID": "", + "Description": "this is another test with variables", + "Invoiced": false, + "InvoiceNumber": "" + } + ] +} \ No newline at end of file diff --git a/test-data/Clients.json b/test-data/Clients.json new file mode 100644 index 0000000..8cd2992 --- /dev/null +++ b/test-data/Clients.json @@ -0,0 +1,34 @@ +{ + "Clients": [ + { + "ClientID": "CLT-001", + "Name": "Test Client", + "Active": true, + "BillingAddress": { + "Street1": "", + "Street2": "", + "City": "", + "State": "", + "PostalCode": "", + "Country": "" + }, + "BillingEmail": "", + "DefaultRate": 65.0 + }, + { + "ClientID": "CLT-002", + "Name": "Test Client 2", + "Active": true, + "BillingAddress": { + "Street1": "", + "Street2": "", + "City": "", + "State": "", + "PostalCode": "", + "Country": "" + }, + "BillingEmail": "", + "DefaultRate": 65.0 + } + ] +} \ No newline at end of file diff --git a/test-data/Projects.json b/test-data/Projects.json new file mode 100644 index 0000000..d558159 --- /dev/null +++ b/test-data/Projects.json @@ -0,0 +1,18 @@ +{ + "Projects": [ + { + "ProjectID": "PRJ-001", + "ClientID": "CLT-001", + "Name": "Zefiro Methane", + "BillingRate": 90.0, + "Active": true + }, + { + "ProjectID": "PRJ-002", + "ClientID": "CLT-001", + "Name": "Bessemer Electric", + "BillingRate": 0.0, + "Active": true + } + ] +} \ No newline at end of file