diff options
| author | Danilo M. <danix@danix.xyz> | 2026-07-05 19:17:04 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-07-05 19:17:04 +0200 |
| commit | 50cb852130986249cacec411e23392a8610e12f1 (patch) | |
| tree | d49c544811f3f088b966046c859412f1b1015162 /firefly_cli/commands | |
| parent | 2f768bb3373105e96d0cbc6fb4ba37c777bbca25 (diff) | |
| download | firefly-cli-50cb852130986249cacec411e23392a8610e12f1.tar.gz firefly-cli-50cb852130986249cacec411e23392a8610e12f1.zip | |
Add two deferred budget follow-ups:
- tx edit --budget: re-assign a budget on an existing transaction,
mirroring the existing tx add --budget flag (name/id resolved, hard
error on miss). Resolves the ISSUES.md backfill wish.
- budget update: rename a budget and/or edit its auto-budget fields via
PUT /budgets/{id}; only fields passed are sent, empty is a hard error.
New command adds to the CLI surface without breaking callers, so this is
a MINOR bump (0.4.1 -> 0.5.0). Docs (README, SKILL.md), completion, and
TODO synced. The tx add --budget-id item stays open (still YAGNI).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'firefly_cli/commands')
| -rw-r--r-- | firefly_cli/commands/budget.py | 32 | ||||
| -rw-r--r-- | firefly_cli/commands/transaction.py | 5 |
2 files changed, 37 insertions, 0 deletions
diff --git a/firefly_cli/commands/budget.py b/firefly_cli/commands/budget.py index 86317fa..8e35a16 100644 --- a/firefly_cli/commands/budget.py +++ b/firefly_cli/commands/budget.py @@ -99,6 +99,38 @@ def _set_active(ctx, ref, active): output.emit(output.unwrap(resp), human=ctx.human) return 0 +def _update_args(p): + _ref_arg(p) + p.add_argument("--name", default=None, help="new budget name") + p.add_argument("--currency", default=None, help="auto-budget currency code, e.g. EUR") + p.add_argument("--auto-budget-amount", dest="auto_budget_amount", default=None, + help="recurring auto-budget amount") + p.add_argument("--auto-budget-period", dest="auto_budget_period", default=None, + help="daily|weekly|monthly|quarterly|half_year|yearly") + p.add_argument("--auto-budget-type", dest="auto_budget_type", default=None, + help="reset|rollover|adjusted|none") + +@registry.command("budget update", help="rename a budget and/or edit its auto-budget fields (name or id)", args=_update_args) +def cmd_update(args, ctx): + b = ctx.resolver.budget(args.ref) + body = {} + if args.name is not None: + body["name"] = args.name + if args.auto_budget_amount is not None: + body["auto_budget_amount"] = str(args.auto_budget_amount) + if args.auto_budget_period is not None: + body["auto_budget_period"] = args.auto_budget_period + if args.auto_budget_type is not None: + body["auto_budget_type"] = args.auto_budget_type + if args.currency: + body["currency_code"] = args.currency + if not body: + raise FireflyError("budget update: nothing to change; pass at least one field") + resp = ctx.client.request("PUT", f"/api/v1/budgets/{b['id']}", body=body) + output.emit(output.unwrap(resp), human=ctx.human) + return 0 + + @registry.command("budget enable", help="mark a budget active", args=_ref_arg) def cmd_enable(args, ctx): return _set_active(ctx, args.ref, True) diff --git a/firefly_cli/commands/transaction.py b/firefly_cli/commands/transaction.py index 9f8e130..1772d87 100644 --- a/firefly_cli/commands/transaction.py +++ b/firefly_cli/commands/transaction.py @@ -109,6 +109,8 @@ def _edit_args(p): p.add_argument("--to", dest="dest", default=None, help="destination account") 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 (re)assign (must already exist)") p.add_argument("--type", default=None, help="withdrawal|deposit|transfer") # ponytail: single-split journals only; multi-split edits need transaction_journal_id per row. @@ -129,6 +131,9 @@ def cmd_edit(args, ctx): split["category_name"] = args.category if args.tags is not None: split["tags"] = [t.strip() for t in args.tags.split(",") if t.strip()] + if args.budget is not None: + # Budgets must pre-exist; resolve name/id -> id (hard error on miss). + split["budget_id"] = ctx.resolver.budget(args.budget)["id"] if args.type is not None: split["type"] = args.type if not split: |
