diff options
| -rw-r--r-- | firefly_cli/commands/transaction.py | 5 | ||||
| -rw-r--r-- | tests/unit/test_commands_transaction.py | 23 |
2 files changed, 28 insertions, 0 deletions
diff --git a/firefly_cli/commands/transaction.py b/firefly_cli/commands/transaction.py index 60af6f4..9f8e130 100644 --- a/firefly_cli/commands/transaction.py +++ b/firefly_cli/commands/transaction.py @@ -32,6 +32,8 @@ def _add_args(p): p.add_argument("--date", default=None, help="YYYY-MM-DD (default today)") p.add_argument("--category", default=None) p.add_argument("--tags", default=None, help="comma-separated") + p.add_argument("--budget", default=None, + help="budget name or id to assign (must already exist)") p.add_argument("--type", default=None, help="withdrawal|deposit|transfer (overrides inference)") p.add_argument("--dry-run", dest="dry_run", action="store_true", @@ -67,6 +69,9 @@ def cmd_add(args, ctx): split["category_name"] = args.category if args.tags: split["tags"] = [t.strip() for t in args.tags.split(",") if t.strip()] + if args.budget: + # Budgets must pre-exist; resolve name/id -> id (hard error on miss). + split["budget_id"] = ctx.resolver.budget(args.budget)["id"] if ttype == "transfer": # Transfer direction is easy to reverse silently (ISSUES.md #5); echo it # to stderr so the user/agent can catch a swapped --from/--to. stdout diff --git a/tests/unit/test_commands_transaction.py b/tests/unit/test_commands_transaction.py index 61a09ab..7366b5c 100644 --- a/tests/unit/test_commands_transaction.py +++ b/tests/unit/test_commands_transaction.py @@ -430,3 +430,26 @@ class TestTxList(unittest.TestCase): rc = tx.cmd_list(args, ctx) self.assertEqual(rc, 0) self.assertEqual(client.request.call_count, 2) + +class TestTxAddBudget(unittest.TestCase): + def test_budget_ref_sets_budget_id_on_split(self): + from types import SimpleNamespace + from unittest.mock import MagicMock + import firefly_cli.commands.transaction as tx + + client = MagicMock() + client.request.return_value = {"data": {"id": "1", "attributes": {}}} + resolver = MagicMock() + resolver.account.side_effect = lambda n: {"id": "1", "name": n, "type": "asset"} + resolver.budget.return_value = {"id": "12", "name": "Groceries"} + ctx = SimpleNamespace(client=client, resolver=resolver, human=False) + + args = SimpleNamespace( + amount="10", source="Checking", dest="Shop", + source_id=None, dest_id=None, desc=None, date="2026-07-03", + category=None, tags=None, type="withdrawal", + dry_run=False, skip_dupes=False, budget="Groceries") + rc = tx.cmd_add(args, ctx) + self.assertEqual(rc, 0) + body = client.request.call_args[1]["body"] + self.assertEqual(body["transactions"][0]["budget_id"], "12") |
