import os from utils import load_config, load_json def main(): config = load_config() data_dir = config["DataDirectory"] # Load supporting 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": []}) # Map IDs for quick lookup client_map = {c["ClientID"]: c["Name"] for c in clients_data["Clients"]} project_map = {p["ProjectID"]: p["Name"] for p in projects_data["Projects"]} project_rates = {p["ProjectID"]: p.get("BillingRate", 0) for p in projects_data["Projects"]} client_rates = {c["ClientID"]: c["DefaultRate"] for c in clients_data["Clients"]} log_files = [f for f in os.listdir(data_dir) if f.endswith("_Time_Log.json")] # Structure: { ClientName: { ProjectName: { hours: 0, amount: 0 } } } report = {} for file_name in log_files: logs = load_json(os.path.join(data_dir, file_name), {"Entries": []}) for entry in logs.get("Entries", []): if not entry.get("Invoiced", False): c_id = entry["ClientID"] p_id = entry["ProjectID"] c_name = client_map.get(c_id, f"Unknown ({c_id})") p_name = project_map.get(p_id, "No Project") # Determine rate rate = project_rates.get(p_id, 0) if rate == 0: rate = client_rates.get(c_id, 0) hours = float(entry.get("Duration", 0)) amount = hours * rate if c_name not in report: report[c_name] = {} if p_name not in report[c_name]: report[c_name][p_name] = {"hours": 0.0, "amount": 0.0} report[c_name][p_name]["hours"] += hours report[c_name][p_name]["amount"] += amount # Print Report print("\n" + "="*50) print("UNBILLED TIME REPORT") print("="*50) if not report: print("No unbilled entries found.") return grand_total_amount = 0 for client, projects in sorted(report.items()): print(f"\nCLIENT: {client}") print("-" * 30) client_total_h = 0 client_total_a = 0 for project, stats in projects.items(): print(f" {project:<20} {stats['hours']:>6.2f} hrs ${stats['amount']:>8.2f}") client_total_h += stats['hours'] client_total_a += stats['amount'] print(f" {'Total:':<20} {client_total_h:>6.2f} hrs ${client_total_a:>8.2f}") grand_total_amount += client_total_a print("\n" + "="*50) print(f"GRAND TOTAL UNBILLED: ${grand_total_amount:,.2f}") print("="*50 + "\n") if __name__ == "__main__": main()