Skip to content

fix(time_entries): list_time_entries fails — invalid work-package filter + non-numeric hours sum #12

Description

@AndreaV-Lsi

Problem / motivation

list_time_entries cannot read back time entries. Two independent bugs, both
surfaced while verifying a real entry against a live OpenProject instance:

Bug A — work-package filter rejected.
list_time_entries(work_package_id=…) builds
filters=[{"work_package": {"operator": "=", "values": [id]}}].
OpenProject's /time_entries endpoint rejects this:

API Error 400: {"_type":"Error",
"errorIdentifier":"urn:openproject-org:api:v3:errors:InvalidQuery",
"message":"Filters Work package filter does not exist."}

The filter identifier is wrong for the time-entries query (its filter set differs
from the work-packages query). The correct identifier must be verified against the
instance's time-entries query schema.

Bug B — hours sum crashes.
The tool does total_hours = 0 then total_hours += entry.get('hours', 0), but the
API returns hours as an ISO-8601 duration string (e.g. "PT4H"). So as soon as
any entry is present:

TypeError: unsupported operand type(s) for +=: 'int' and 'str'

The per-entry line also prints the raw PT4H instead of a number.

Net effect: list_time_entries is unusable whenever entries exist — it either 400s
(work-package filter) or raises TypeError (hours sum).

Scope / proposed approach

  • Bug A: replace the work_package filter identifier with the correct
    time-entries filter name, verified against the instance's query schema. Audit the
    user filter name in the same tool while at it (same filter set).
  • Bug B: parse the ISO-8601 duration to float hours for both the per-entry
    display and the running total; guard None/non-numeric so a malformed value can't
    crash the whole listing.
  • Keep the diff single-purpose — no unrelated reformatting.

Files: src/tools/time_entries.py (list_time_entries); possibly src/client.py
(get_time_entries).

Acceptance criteria

  • list_time_entries(work_package_id=X) and list_time_entries(user_id=Y) both
    return entries with a correct numeric total — no InvalidQuery, no TypeError.
  • Per-entry hours render as a number (e.g. 4.0), not PT4H.
  • Network-free unit test in the existing style: a mocked entry with hours="PT4H"
    → total 4.0, no crash; and the built filter uses the corrected identifier.
  • Filter-name change verified against a running instance (gated live test /
    ephemeral Docker).

Out of scope

  • No unrelated reformatting or refactoring.
  • No new filters/features beyond fixing the two bugs.

Notes

Independent of the input-serialization work (PR AndyEverything#22) — a pre-existing bug on main,
so it branches off main as a clean standalone fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions