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.
Files changed (28) hide show
  1. {papi_projects-0.4.2 → papi_projects-0.4.3}/PKG-INFO +1 -1
  2. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/wrappers.py +17 -9
  3. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/PKG-INFO +1 -1
  4. {papi_projects-0.4.2 → papi_projects-0.4.3}/pyproject.toml +1 -1
  5. {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/collate_toggl_hours.py +2 -1
  6. {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/generate_timesheet.py +69 -15
  7. {papi_projects-0.4.2 → papi_projects-0.4.3}/README.md +0 -0
  8. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/__init__.py +0 -0
  9. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/project.py +0 -0
  10. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/task.py +0 -0
  11. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/user.py +0 -0
  12. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi/workorder.py +0 -0
  13. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/SOURCES.txt +0 -0
  14. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/dependency_links.txt +0 -0
  15. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/entry_points.txt +0 -0
  16. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/requires.txt +0 -0
  17. {papi_projects-0.4.2 → papi_projects-0.4.3}/papi_projects.egg-info/top_level.txt +0 -0
  18. {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/__init__.py +0 -0
  19. {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/create_notion_project.py +0 -0
  20. {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/create_notion_task.py +0 -0
  21. {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/create_project.py +0 -0
  22. {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/create_toggl_project.py +0 -0
  23. {papi_projects-0.4.2 → papi_projects-0.4.3}/scripts/test_notion.py +0 -0
  24. {papi_projects-0.4.2 → papi_projects-0.4.3}/setup.cfg +0 -0
  25. {papi_projects-0.4.2 → papi_projects-0.4.3}/tests/test_project.py +0 -0
  26. {papi_projects-0.4.2 → papi_projects-0.4.3}/tests/test_task.py +0 -0
  27. {papi_projects-0.4.2 → papi_projects-0.4.3}/tests/test_user.py +0 -0
  28. {papi_projects-0.4.2 → papi_projects-0.4.3}/tests/test_wrappers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: papi-projects
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: PAPI is an API for managing projects
5
5
  Author-email: sandyjmacdonald <sandyjmacdonald@gmail.com>
6
6
  License-Expression: MIT
@@ -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 = t["pid"]
180
- seconds = t["duration"]
181
- hours = seconds / 60 / 60
182
- if pid not in times:
183
- times[pid] = hours
184
- else:
185
- times[pid] += hours
186
- return times
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
- minimal = { "type": t, t: b[t] }
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: papi-projects
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: PAPI is an API for managing projects
5
5
  Author-email: sandyjmacdonald <sandyjmacdonald@gmail.com>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "papi-projects"
3
- version = "0.4.2"
3
+ version = "0.4.3"
4
4
  description = "PAPI is an API for managing projects"
5
5
  authors = [{ name = "sandyjmacdonald", email = "sandyjmacdonald@gmail.com" }]
6
6
  license = "MIT"
@@ -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
- end_time = pendulum.now().to_rfc3339_string() if not args.end else pendulum.parse(args.end).to_rfc3339_string()
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
- project_name = project.name
121
- workorder_id = project.workorder
122
- if workorder_id is not None:
123
- workorder = notion.get_workorder(
124
- workorders_db_id=config["NOTION_WORKORDERS_DB"],
125
- workorder_id=workorder_id
126
- )
127
- if workorder.is_complete():
128
- payment_type = workorder.payment_type
129
- costing_rate = workorder.costing_rate
130
- hourly_rate = workorder.hourly_rate
131
- cost = calculate_cost(hours, workorder.hourly_rate)
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
- df.to_csv(output, sep="\t", index=False)
149
- logger.warning(f"{len(df)} journal entries successfully written to {output}")
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