Skip to content

Commit bd731eb

Browse files
Merge pull request #127 from NessieCanCode/9i4d5w-fix-pdf-export-not-returning-results
Display invoice export errors in UI
2 parents c43d880 + 000f886 commit bd731eb

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

src/invoice.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,23 @@
1313
import sys
1414
from datetime import datetime
1515

16-
from reportlab.lib import colors
17-
from reportlab.lib.enums import TA_RIGHT
18-
from reportlab.lib.pagesizes import LETTER
19-
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
20-
from reportlab.platypus import (SimpleDocTemplate, Paragraph, Spacer, Table,
21-
TableStyle)
16+
# Reportlab is required for PDF generation. If it's missing, emit a clear
17+
# error message on stderr so callers can surface the failure to users.
18+
try:
19+
from reportlab.lib import colors
20+
from reportlab.lib.enums import TA_RIGHT
21+
from reportlab.lib.pagesizes import LETTER
22+
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
23+
from reportlab.platypus import (
24+
SimpleDocTemplate,
25+
Paragraph,
26+
Spacer,
27+
Table,
28+
TableStyle,
29+
)
30+
except ModuleNotFoundError as exc: # pragma: no cover - exercised via JS
31+
print(str(exc), file=sys.stderr)
32+
sys.exit(1)
2233

2334

2435
def _load_profile(base_dir):
@@ -174,8 +185,10 @@ def main():
174185

175186
buffer = io.BytesIO()
176187
generate_invoice(buffer, invoice_data)
177-
pdf_bytes = buffer.getvalue()
188+
buffer.seek(0)
189+
pdf_bytes = buffer.read()
178190
sys.stdout.write(base64.b64encode(pdf_bytes).decode("ascii"))
191+
sys.stdout.flush()
179192

180193

181194
if __name__ == "__main__":

src/slurmcostmanager.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -905,11 +905,26 @@ function Details({
905905
};
906906
try {
907907
setError(null);
908+
if (!filteredDetails.length) {
909+
setError('No usage data matches current filters');
910+
return;
911+
}
908912
const output = await window.cockpit.spawn(
909913
['python3', `${PLUGIN_BASE}/invoice.py`],
910914
{ input: JSON.stringify(invoiceData), err: 'out' }
911915
);
912-
const byteChars = atob(output.trim());
916+
const trimmed = output.trim();
917+
if (!trimmed) {
918+
setError('Invoice generation returned no data');
919+
return;
920+
}
921+
let byteChars;
922+
try {
923+
byteChars = atob(trimmed);
924+
} catch (decodeErr) {
925+
setError(trimmed || decodeErr.message || String(decodeErr));
926+
return;
927+
}
913928
const byteNumbers = new Array(byteChars.length);
914929
for (let i = 0; i < byteChars.length; i++) {
915930
byteNumbers[i] = byteChars.charCodeAt(i);

0 commit comments

Comments
 (0)