Added code to EnterTime.py to accept arguments. This can be used at the command line and allows shortcuts collect the data and pass those in to the script.

This commit is contained in:
2026-05-24 11:01:05 -05:00
parent 602ecffa23
commit cf88d603e9
5 changed files with 119 additions and 17 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
{
"DataDirectory": "~/HourStack",
"PDFOutputDirectory": "~/Invoices"
}
"DataDirectory": "/Users/mattspeer/time-tracking/test-data",
"PDFOutputDirectory": "/Users/mattspeer/time-tracking/test-invoices"
}
+29 -14
View File
@@ -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": []})
+35
View File
@@ -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": ""
}
]
}
+34
View File
@@ -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
}
]
}
+18
View File
@@ -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
}
]
}