feat(activity): add --by-activity flag to break down spent time by activity type
- Load time entry activity names from Redmine enumeration. - Aggregate hours per issue and per activity in fetch_issues_with_spent_time. - Add --by-activity CLI flag and propagate it through report builder, summary, and all formatters (console, CSV, HTML, JSON, ODT). - Keep backward-compatible 2-tuple input in build_grouped_report. - Bump version to 1.8.0. Closes #41
This commit is contained in:
@@ -88,6 +88,11 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
"--user-name",
|
||||
help="Redmine user full name for the report (alternative to --user-id; ambiguous names are rejected)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--by-activity",
|
||||
action="store_true",
|
||||
help="Break down spent time by activity type",
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
# Валидация взаимоисключающих флагов пользователя
|
||||
@@ -130,6 +135,7 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
from_date,
|
||||
to_date,
|
||||
user_id=args.user_id or args.user_login or args.user_name,
|
||||
by_activity=args.by_activity,
|
||||
)
|
||||
except RedmineAPIError as e:
|
||||
print(f"❌ {e.message}", file=sys.stderr)
|
||||
@@ -150,15 +156,25 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
|
||||
print(f"✅ Total issues: {len(issue_hours)} [{args.date}]", file=sys.stderr)
|
||||
|
||||
rows = build_grouped_report(issue_hours, fill_time=not args.no_time)
|
||||
rows = build_grouped_report(
|
||||
issue_hours,
|
||||
fill_time=not args.no_time,
|
||||
by_activity=args.by_activity,
|
||||
)
|
||||
|
||||
if args.summary:
|
||||
summary = calculate_summary(rows)
|
||||
summary = calculate_summary(rows, by_activity=args.by_activity)
|
||||
print(f"⏱️ Total time: {summary['total']}h", file=sys.stderr)
|
||||
for key, value in summary.items():
|
||||
project_keys = [k for k in sorted(summary) if k.startswith("project:")]
|
||||
activity_keys = [k for k in sorted(summary) if k.startswith("activity:")]
|
||||
for key in project_keys + activity_keys:
|
||||
value = summary[key]
|
||||
if key.startswith("project:"):
|
||||
project = key.split(":", 1)[1]
|
||||
print(f" {project}: {value}h", file=sys.stderr)
|
||||
elif key.startswith("activity:"):
|
||||
activity = key.split(":", 1)[1]
|
||||
print(f" [{activity}]: {value}h", file=sys.stderr)
|
||||
|
||||
if args.output:
|
||||
output_ext = os.path.splitext(args.output)[1].lower()
|
||||
|
||||
Reference in New Issue
Block a user