Fix version display, deterministic sort, remove duplicate sort

get_version() now returns version.name instead of str(version), which
returned the numeric ID from redminelib.resources.Version. Falls back
to str() when .name is absent (#14).

Add issue.id as tertiary sort key in build_grouped_report so tasks
within the same project+version group always appear in the same order
regardless of API response ordering (#33).

Remove redundant sort from client.fetch_issues_with_spent_time — the
sort already runs in report_builder.build_grouped_report, so doing it
twice wastes CPU. Also remove the now-unused get_version import (#32).

Closes #14, closes #32, closes #33
This commit is contained in:
Артём Кокос
2026-06-25 23:32:14 +07:00
parent 3a6d1b7ba7
commit dbc4cf960a
5 changed files with 50 additions and 7 deletions

View File

@@ -4,7 +4,6 @@ from redminelib import Redmine
from redminelib.resources import Issue
from .config import Config
from .utils import get_version
def _get_redmine_auth_kwargs() -> Dict[str, Any]:
@@ -54,13 +53,12 @@ def fetch_issues_with_spent_time(
issue_list_str = ",".join(str(i) for i in issue_ids)
issues = redmine.issue.filter(issue_id=issue_list_str, status_id="*", sort="project:asc")
# Сопоставляем задачи с суммарным временем
# Сопоставляем задачи с суммарным временем.
# Сортировка выполняется в report_builder.build_grouped_report,
# здесь оставляем порядок API как есть.
result = []
for issue in issues:
total_hours = spent_time.get(issue.id, 0.0)
result.append((issue, total_hours))
# Сортируем по (проект, версия)
result.sort(key=lambda x: (str(x[0].project), get_version(x[0])))
return result

View File

@@ -35,7 +35,7 @@ def build_grouped_report(
"""
# Защитная сортировка -- гарантирует корректную группировку независимо от порядка на входе
issue_hours = sorted(issue_hours, key=lambda x: (str(x[0].project), get_version(x[0])))
issue_hours = sorted(issue_hours, key=lambda x: (str(x[0].project), get_version(x[0]), x[0].id))
rows: List[ReportRow] = []
prev_project: str = ""

View File

@@ -33,7 +33,8 @@ def get_version(issue) -> str:
version = getattr(issue, "fixed_version", None)
if version is None:
return "<N/A>"
return str(version)
name = getattr(version, "name", None)
return str(name) if name else str(version)
def hours_to_human(hours: float) -> str: