papi-projects 0.4.2__tar.gz → 0.4.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {papi_projects-0.4.2 → papi_projects-0.4.3}/PKG-INFO +1 -1
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/wrappers.py +17 -9
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/PKG-INFO +1 -1
- {papi_projects-0.4.2 → papi_projects-0.4.3}/pyproject.toml +1 -1
- {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/collate_toggl_hours.py +2 -1
- {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/generate_timesheet.py +69 -15
- {papi_projects-0.4.2 → papi_projects-0.4.3}/README.md +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/__init__.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/project.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/task.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/user.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/workorder.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/SOURCES.txt +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/dependency_links.txt +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/entry_points.txt +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/requires.txt +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/top_level.txt +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/__init__.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/create_notion_project.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/create_notion_task.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/create_project.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/create_toggl_project.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/test_notion.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/setup.cfg +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/tests/test_project.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/tests/test_task.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/tests/test_user.py +0 -0
- {papi_projects-0.4.2 → papi_projects-0.4.3}/tests/test_wrappers.py +0 -0
|
@@ -176,14 +176,18 @@ class TogglTrackWrapper(Protocol):
|
|
|
176
176
|
if isinstance(times_json, list):
|
|
177
177
|
times = {}
|
|
178
178
|
for t in times_json:
|
|
179
|
-
pid
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
179
|
+
if "pid" in t:
|
|
180
|
+
pid = t["pid"]
|
|
181
|
+
seconds = t["duration"]
|
|
182
|
+
hours = seconds / 60 / 60
|
|
183
|
+
if pid not in times:
|
|
184
|
+
times[pid] = hours
|
|
185
|
+
else:
|
|
186
|
+
times[pid] += hours
|
|
187
|
+
if times:
|
|
188
|
+
return times
|
|
189
|
+
else:
|
|
190
|
+
return None
|
|
187
191
|
else:
|
|
188
192
|
warnings.warn(times_json)
|
|
189
193
|
return None
|
|
@@ -419,7 +423,11 @@ class NotionWrapper(Protocol):
|
|
|
419
423
|
t = b["type"]
|
|
420
424
|
if t not in ALLOWED:
|
|
421
425
|
continue
|
|
422
|
-
|
|
426
|
+
block_data = {
|
|
427
|
+
k: v for k, v in b[t].items()
|
|
428
|
+
if v is not None and not (k == "color" and v == "default")
|
|
429
|
+
}
|
|
430
|
+
minimal = {"type": t, t: block_data}
|
|
423
431
|
if b.get("has_children"):
|
|
424
432
|
child_raw = self._fetch_template_blocks(b["id"])
|
|
425
433
|
minimal["children"] = self._clean_blocks(child_raw)
|
|
@@ -51,6 +51,7 @@ def main():
|
|
|
51
51
|
# Get tracked hours and tracked project IDs/names
|
|
52
52
|
|
|
53
53
|
tracked_hours = toggl.get_user_hours(start_time=start_time, end_time=end_time)
|
|
54
|
+
print(tracked_hours)
|
|
54
55
|
projects = {p["id"]: p["name"] for p in toggl.get_user_projects() if p["id"] in tracked_hours}
|
|
55
56
|
hours_per_project = [(projects[t], tracked_hours[t]) for t in tracked_hours]
|
|
56
57
|
|
|
@@ -69,4 +70,4 @@ def main():
|
|
|
69
70
|
warnings.warn("Start time must not be more than 3 months ago!")
|
|
70
71
|
|
|
71
72
|
if __name__ == "__main__":
|
|
72
|
-
main()
|
|
73
|
+
main()
|
|
@@ -74,7 +74,8 @@ def main():
|
|
|
74
74
|
logger = setup_logger(True, "WARNING", None)
|
|
75
75
|
|
|
76
76
|
start_time = pendulum.parse(args.start).to_rfc3339_string()
|
|
77
|
-
|
|
77
|
+
# Toggl's end_date is exclusive, so add a day to include entries on the end date itself.
|
|
78
|
+
end_time = pendulum.now().to_rfc3339_string() if not args.end else pendulum.parse(args.end).add(days=1).to_rfc3339_string()
|
|
78
79
|
|
|
79
80
|
if pendulum.now() < pendulum.parse(args.start).add(months=3):
|
|
80
81
|
toggl_workspace = config["TOGGL_TRACK_WORKSPACE"]
|
|
@@ -101,8 +102,10 @@ def main():
|
|
|
101
102
|
)
|
|
102
103
|
|
|
103
104
|
for user in toggl_users:
|
|
105
|
+
print(user)
|
|
104
106
|
toggl = initialise_toggl(user["api_key"], toggl_workspace)
|
|
105
107
|
hours_dict = get_toggl_hours(start_time, end_time, toggl)
|
|
108
|
+
print(hours_dict)
|
|
106
109
|
|
|
107
110
|
for project_id, hours in hours_dict.items():
|
|
108
111
|
hours = float(hours)
|
|
@@ -117,18 +120,22 @@ def main():
|
|
|
117
120
|
project_id,
|
|
118
121
|
workorders_db_id=config["NOTION_WORKORDERS_DB"]
|
|
119
122
|
)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
if project is not None:
|
|
124
|
+
project_name = project.name
|
|
125
|
+
workorder_id = project.workorder
|
|
126
|
+
if workorder_id is not None:
|
|
127
|
+
workorder = notion.get_workorder(
|
|
128
|
+
workorders_db_id=config["NOTION_WORKORDERS_DB"],
|
|
129
|
+
workorder_id=workorder_id
|
|
130
|
+
)
|
|
131
|
+
if workorder.is_complete():
|
|
132
|
+
payment_type = workorder.payment_type
|
|
133
|
+
costing_rate = workorder.costing_rate
|
|
134
|
+
hourly_rate = workorder.hourly_rate
|
|
135
|
+
cost = calculate_cost(hours, workorder.hourly_rate)
|
|
136
|
+
else:
|
|
137
|
+
project_name = ""
|
|
138
|
+
workorder_id = ""
|
|
132
139
|
else:
|
|
133
140
|
project_name = project_id
|
|
134
141
|
|
|
@@ -145,8 +152,55 @@ def main():
|
|
|
145
152
|
f"{project_id}: {project_name}",
|
|
146
153
|
]
|
|
147
154
|
|
|
148
|
-
|
|
149
|
-
|
|
155
|
+
output_path = Path(output).expanduser()
|
|
156
|
+
itemised_path = output_path.with_name(f"{output_path.stem}-itemised{output_path.suffix}")
|
|
157
|
+
totals_path = output_path.with_name(f"{output_path.stem}-totals{output_path.suffix}")
|
|
158
|
+
da_path = output_path.with_name(f"{output_path.stem}-DA{output_path.suffix}")
|
|
159
|
+
di_path = output_path.with_name(f"{output_path.stem}-DI{output_path.suffix}")
|
|
160
|
+
|
|
161
|
+
df.to_csv(itemised_path, sep="\t", index=False)
|
|
162
|
+
|
|
163
|
+
totals_df = df.drop(columns=["person"]).groupby("project_id", as_index=False).agg(
|
|
164
|
+
{
|
|
165
|
+
"workorder": "first",
|
|
166
|
+
"payment_type": "first",
|
|
167
|
+
"costing_rate": "first",
|
|
168
|
+
"hourly_rate": "first",
|
|
169
|
+
"hours": "sum",
|
|
170
|
+
"cost": "sum",
|
|
171
|
+
"description": "first",
|
|
172
|
+
"agresso_description": "first",
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
totals_df = totals_df[
|
|
176
|
+
[
|
|
177
|
+
"workorder",
|
|
178
|
+
"project_id",
|
|
179
|
+
"payment_type",
|
|
180
|
+
"costing_rate",
|
|
181
|
+
"hourly_rate",
|
|
182
|
+
"hours",
|
|
183
|
+
"cost",
|
|
184
|
+
"description",
|
|
185
|
+
"agresso_description",
|
|
186
|
+
]
|
|
187
|
+
]
|
|
188
|
+
totals_df.to_csv(totals_path, sep="\t", index=False)
|
|
189
|
+
|
|
190
|
+
da_df = totals_df[totals_df["payment_type"] == "DA"]
|
|
191
|
+
if len(da_df):
|
|
192
|
+
da_df.to_csv(da_path, sep="\t", index=False)
|
|
193
|
+
|
|
194
|
+
di_df = totals_df[totals_df["payment_type"] == "DI"]
|
|
195
|
+
if len(di_df):
|
|
196
|
+
di_df.to_csv(di_path, sep="\t", index=False)
|
|
197
|
+
|
|
198
|
+
logger.warning(f"{len(df)} journal entries successfully written to {itemised_path}")
|
|
199
|
+
logger.warning(f"{len(totals_df)} project totals successfully written to {totals_path}")
|
|
200
|
+
if len(da_df):
|
|
201
|
+
logger.warning(f"{len(da_df)} DA totals successfully written to {da_path}")
|
|
202
|
+
if len(di_df):
|
|
203
|
+
logger.warning(f"{len(di_df)} DI totals successfully written to {di_path}")
|
|
150
204
|
else:
|
|
151
205
|
logger.warning("Start time must not be more than 3 months ago!")
|
|
152
206
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|