From d44d62f5944c2765ba009197cc3ac5bb50d073e2 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 3 Jul 2026 18:07:47 +0200 Subject: fix(budget): group help blurb, exact Decimal spent, resolver comment (v0.4.1) Follow-ups from the v0.4.0 review: - add the missing _GROUP_HELP blurb for the budget group (every other group shows one) + a regression test asserting all groups have one. - _spent_scalar sums with decimal.Decimal instead of float (exact money). - note the numeric-name sniffing tradeoff in resolver.budget(). Co-Authored-By: Claude Opus 4.8 --- firefly_cli/__init__.py | 2 +- firefly_cli/cli.py | 1 + firefly_cli/commands/budget.py | 7 ++++--- firefly_cli/resolver.py | 4 ++++ pyproject.toml | 2 +- tests/unit/test_cli.py | 9 +++++++++ 6 files changed, 20 insertions(+), 5 deletions(-) diff --git a/firefly_cli/__init__.py b/firefly_cli/__init__.py index f2c1864..1d2fe01 100644 --- a/firefly_cli/__init__.py +++ b/firefly_cli/__init__.py @@ -2,4 +2,4 @@ # Copyright (C) 2026 Danilo M. # Licensed under the GNU General Public License v2.0 only. -__version__ = "0.4.0" +__version__ = "0.4.1" diff --git a/firefly_cli/cli.py b/firefly_cli/cli.py index ad54504..712d52d 100644 --- a/firefly_cli/cli.py +++ b/firefly_cli/cli.py @@ -19,6 +19,7 @@ _GROUP_HELP = { "category": "list categories (categories auto-create when used on a tx)", "tag": "list tags (tags auto-create when attached to a tx)", "tx": "record, list, and search transactions", + "budget": "manage budgets and per-period spending limits", } def _build_parser(): diff --git a/firefly_cli/commands/budget.py b/firefly_cli/commands/budget.py index f9999a5..86317fa 100644 --- a/firefly_cli/commands/budget.py +++ b/firefly_cli/commands/budget.py @@ -1,6 +1,7 @@ # Copyright (C) 2026 Danilo M. GPL-2.0-only import calendar from datetime import date +from decimal import Decimal, InvalidOperation from firefly_cli import registry, output from firefly_cli.errors import FireflyError @@ -18,11 +19,11 @@ def _spent_scalar(budget_obj): """Sum a budget's nested `spent` array into a single number (for --human). Firefly sends spent as a per-currency list of {sum: "-12.34", ...}; we sum the sums. JSON output is untouched; this only feeds the table view.""" - total = 0.0 + total = Decimal(0) for entry in budget_obj.get("spent") or []: try: - total += float(entry.get("sum", 0)) - except (TypeError, ValueError): + total += Decimal(str(entry.get("sum", 0))) + except (TypeError, InvalidOperation): pass return f"{total:.2f}" diff --git a/firefly_cli/resolver.py b/firefly_cli/resolver.py index 53144e1..cb7e9a8 100644 --- a/firefly_cli/resolver.py +++ b/firefly_cli/resolver.py @@ -48,6 +48,10 @@ class Resolver: # transaction), so we resolve to an id. A numeric-looking ref goes # straight to the show endpoint (lets same-name-safe callers pin an id); # otherwise match by name against the list. + # ponytail: sniffing digits makes a budget literally named "7" + # unreachable by name (same lossy tradeoff ISSUES.md #2 hit for + # accounts). All-digit budget names are rare; add a --budget-id flag to + # tx add if this ever bites, mirroring --from-id/--to-id. if str(name_or_id).isdigit(): return self.budget_by_id(name_or_id) return self._match("budget", self._list("/api/v1/budgets"), name_or_id) diff --git a/pyproject.toml b/pyproject.toml index 0d1f7e6..27034f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "firefly-iii-agent" -version = "0.4.0" +version = "0.4.1" description = "CLI tool for agent interaction with Firefly III" readme = "README.md" requires-python = ">=3.11" diff --git a/tests/unit/test_cli.py b/tests/unit/test_cli.py index 883f200..47e01cc 100644 --- a/tests/unit/test_cli.py +++ b/tests/unit/test_cli.py @@ -24,3 +24,12 @@ class TestCli(unittest.TestCase): w.return_value = "/tmp/x" rc = cli.main(["auth", "set", "--url", "https://f", "--token", "t"]) self.assertEqual(rc, 0) + + def test_every_command_group_has_a_help_blurb(self): + # Every group shown in `firefly --help` should carry a _GROUP_HELP + # blurb; a new group added without one is easy to miss (budget did). + from firefly_cli import registry + import firefly_cli.commands # noqa: F401 ensure registration + groups = {c.name.split(" ", 1)[0] for c in registry.all_commands()} + missing = groups - set(cli._GROUP_HELP) + self.assertFalse(missing, f"groups without _GROUP_HELP: {missing}") -- cgit v1.2.3