cli.py: drop redundant 'if issue_hours is None' branch before
'if not issue_hours'. The branch is not formally dead (client
returns None when no time entries found, client.py), but it is a
semantic duplicate: both branches print the same message and
return 0, and None is falsy, so a single 'not issue_hours' check
covers None, empty list and keeps behavior identical.
test_cli_returns_zero_on_no_entries stays green unchanged.
xlsx.py: drop unreachable 'if ws is None' fallback. Workbook()
(write_only=False) always creates one worksheet in __init__, so
wb.active is never None; set the title directly.
Closes#63
- #23: add JSONFormatter and XLSXFormatter
- add openpyxl dependency for .xlsx export
- #22: add --summary flag and calculate_summary() in report_builder
- ReportRow now carries raw hours for summary calculations
- update CLI help and README with .json/.xlsx formats and --summary
- add tests for new formatters and summary computation
Closes#22, closes#23