aboutsummaryrefslogtreecommitdiffstats
path: root/firefly_cli
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-07-05 19:17:04 +0200
committerDanilo M. <danix@danix.xyz>2026-07-05 19:17:04 +0200
commit50cb852130986249cacec411e23392a8610e12f1 (patch)
treed49c544811f3f088b966046c859412f1b1015162 /firefly_cli
parent2f768bb3373105e96d0cbc6fb4ba37c777bbca25 (diff)
downloadfirefly-cli-master.tar.gz
firefly-cli-master.zip
feat(budget): tx edit --budget and budget update (v0.5.0)HEADv0.5.0master
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')
-rw-r--r--firefly_cli/__init__.py2
-rw-r--r--firefly_cli/commands/budget.py32
-rw-r--r--firefly_cli/commands/transaction.py5
3 files changed, 38 insertions, 1 deletions
diff --git a/firefly_cli/__init__.py b/firefly_cli/__init__.py
index 1d2fe01..d4060af 100644
--- a/firefly_cli/__init__.py
+++ b/firefly_cli/__init__.py
@@ -2,4 +2,4 @@
# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
# Licensed under the GNU General Public License v2.0 only.
-__version__ = "0.4.1"
+__version__ = "0.5.0"
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: