-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexport.py
More file actions
162 lines (128 loc) · 4.73 KB
/
Copy pathexport.py
File metadata and controls
162 lines (128 loc) · 4.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# Non-local imports
import pandas as pd
# Local imports
import os
import pathlib
import zipfile
# Project modules
from config import Config
from pdfclass import PDF
from display import _reorder_dicts
from bitly import bitly
def export_tasks(tasks: list[dict], monthyear: str, path: str = "") -> str:
"""
Takes a list of tasks (dicts) and exports them to a CSV.
`monthyear` is in the format 7-2022. This is provided by the user when
invoking the export command from the CLI.
The resulting files are stored in the current working directory of the terminal.
So, the user should be instructed to navigate to the output directory of choice
using cd in their shell, and then execute the command using the CLI.
Output files are automatically zipped together into a .zip archive called
"Work Log 7-2022.zip" if the month is July, 2022. This is a single file
that can be forwarded to anyone. When unzipped, it contains all export files,
including the PDF report and CSV full list of all logged tasks.
"""
# Remove key and convert everything to string and shorten long values
tasks = _reorder_dicts(tasks)
for task in tasks:
del task['key']
# Mark all unfinished tasks as 0 hours
if not task['Hours']:
task['Hours'] = 0
base_name = f"Work Log {monthyear}"
path = path or os.getcwd()
# if not pathlib.Path(path).exists:
# os.mkdir(path)
path = os.path.join(path, base_name)
# Store CSV before changing values
pd.DataFrame(tasks).to_csv(f"{path}.csv")
# Make PDF
create_pdf(tasks, monthyear, f"{path}.pdf")
# Zip resulting files
with zipfile.ZipFile(f"{path}.zip", "w") as archive:
archive.write(f"{path}.csv")
archive.write(f"{path}.pdf")
return path
def create_pdf(tasks: list[dict], monthyear: str, path: str):
"""
Generate a full PDF report, shortening links with Bitly,
and including an appendix.
"""
data = [list(tasks[0].keys())]
appendix_count = 0
appendix = {}
hours_total = 0
for task in tasks:
# Stringify and shorten length items
for key, val in task.items():
if key == 'Hours':
hours_total += val
str_val = str(val)
if len(str_val) > Config.report_char_cutoff:
appendix_count += 1
appendix[appendix_count] = str_val
str_val = f"A{appendix_count}: " + str_val[:Config.report_char_cutoff] + '...'
task[key] = str_val
data.append(list(task.values()))
pdf = PDF(format='letter')
pdf.add_page()
pdf.set_font(Config.report_font, size=16)
# Titles
pdf.cell(200, 10, txt=f"Log of Working Hours {monthyear}", align='C')
pdf.ln()
pdf.ln()
# Body
pdf.set_font("Times", size=11)
pdf.cell(
txt = (
"The following is an automatically generated report of all hours logged "
f"in the month of {monthyear}. "
)
)
pdf.ln()
pdf.cell(
txt = "Any items cut off for lack of space can be seen in full in the appendix."
)
pdf.ln()
pdf.ln()
pdf.create_table(
table_data = data,
title = f"Total Hours Logged: {hours_total:,.2f}",
cell_width = [30, 50, 15, 93]
)
pdf.ln()
# Deliverables appendix
if appendix:
pdf.set_font(Config.report_font, size = 14)
pdf.cell(
txt = "Appendix of Deliverables",
align = 'L'
)
pdf.ln()
pdf.ln()
pdf.set_font(Config.report_font, size = 10)
pdf.cell(txt="Some of the following items have been interpreted as links.")
pdf.cell(txt="They've been shortened below using bit.ly.")
pdf.ln()
pdf.ln()
pdf.ln()
pdf.set_font(Config.report_font, size = 11)
# Links
for idx, deliverable in appendix.items():
pdf.cell(txt=f"Item A{idx}")
if 'http' in deliverable:
pdf.ln()
pdf.cell(txt=bitly(deliverable))
else:
if len(deliverable) < 100:
pdf.ln()
pdf.cell(txt=deliverable)
else:
pdf.set_font(Config.report_font, size = 9)
pdf.cell(txt="(The full deliverable is too long to be displayed. Part of it is shown below.)")
pdf.set_font(Config.report_font, size = 11)
pdf.ln()
pdf.cell(txt=deliverable[:100]+'...')
pdf.ln()
pdf.ln()
pdf.output(path)