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:
+3
-3
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"DataDirectory": "~/HourStack",
|
||||
"PDFOutputDirectory": "~/Invoices"
|
||||
}
|
||||
"DataDirectory": "/Users/mattspeer/time-tracking/test-data",
|
||||
"PDFOutputDirectory": "/Users/mattspeer/time-tracking/test-invoices"
|
||||
}
|
||||
|
||||
+29
-14
@@ -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": []})
|
||||
|
||||
@@ -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": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user