From b83e80466c0e115f5a5b7230591edbd2b6c108fd Mon Sep 17 00:00:00 2001 From: Roger Oriol Date: Sun, 28 Dec 2025 18:29:38 +0100 Subject: [PATCH] budget for 2026 --- commands/budget | 71 +++++++++++++++++++++++------------------ ledger/budget.beancount | 31 ++++++++++++++++++ 2 files changed, 71 insertions(+), 31 deletions(-) diff --git a/commands/budget b/commands/budget index 6c51f57..cef7c50 100755 --- a/commands/budget +++ b/commands/budget @@ -26,19 +26,26 @@ class bcolors: def get_budget_entries(entries, period, start_date): budgets = [] - seen_accounts = set() + seen_accounts = {} for entry in entries: if isinstance(entry, Custom) and entry.values[1].value == period \ and entry.date <= date.fromisoformat(start_date): account = entry.values[0].value if account not in seen_accounts: - seen_accounts.add(account) + seen_accounts[account] = len(budgets) budgets.append({ "date": entry.date, "account": account, "period": entry.values[1].value, "budget": entry.values[2].value }) + else: + budgets[seen_accounts[account]] = { + "date": entry.date, + "account": account, + "period": entry.values[1].value, + "budget": entry.values[2].value + } return budgets @@ -82,25 +89,26 @@ def build_budget(budget_entries, expenses, equity_amounts, total_positive_expens total_perc = 0 remaining = entry["budget"] if entry["account"] in expenses: - expense = expenses[entry["account"]].get_only_position().units + if expenses[entry["account"]].get_only_position() is not None: + expense = expenses[entry["account"]].get_only_position().units - # Apply equity deductions for specific accounts - if entry["account"] == "Expenses:Lloguer" and "Equity:LloguerMiquel" in equity_amounts: - equity_amount = equity_amounts["Equity:LloguerMiquel"].get_only_position( - ) - expense = sub(expense, equity_amount.units) - elif entry["account"] == "Expenses:FacturesUtilitats" and "Equity:FacturesUtilitatsMiquel" in equity_amounts: - equity_amount = equity_amounts["Equity:FacturesUtilitatsMiquel"].get_only_position( - ) - expense = sub(expense, equity_amount.units) + # Apply equity deductions for specific accounts + # if entry["account"] == "Expenses:Lloguer" and "Equity:LloguerMiquel" in equity_amounts: + # equity_amount = equity_amounts["Equity:LloguerMiquel"].get_only_position( + # ) + # expense = sub(expense, equity_amount.units) + # elif entry["account"] == "Expenses:FacturesUtilitats" and "Equity:FacturesUtilitatsMiquel" in equity_amounts: + # equity_amount = equity_amounts["Equity:FacturesUtilitatsMiquel"].get_only_position( + # ) + # expense = sub(expense, equity_amount.units) - expense_perc = (expense.number / - entry["budget"].number) * 100 - # Calculate percentage of total positive expenses only - if total_positive_expenses.number > 0 and expense.number > 0: - total_perc = (expense.number / - total_positive_expenses.number) * 100 - remaining = sub(remaining, expense) + expense_perc = (expense.number / + entry["budget"].number) * 100 + # Calculate percentage of total positive expenses only + if total_positive_expenses.number > 0 and expense.number > 0: + total_perc = (expense.number / + total_positive_expenses.number) * 100 + remaining = sub(remaining, expense) result.append({ "Account": entry["account"], "Budget": entry["budget"].to_string(), @@ -161,20 +169,21 @@ def main(): Decimal(0), budget_entries[0]["budget"].currency) for entry in budget_entries: if entry["account"] in expenses: - expense = expenses[entry["account"]].get_only_position().units + if expenses[entry["account"]].get_only_position() is not None: + expense = expenses[entry["account"]].get_only_position().units - # Apply equity deductions for specific accounts (same logic as in build_budget) - if entry["account"] == "Expenses:Lloguer" and "Equity:LloguerMiquel" in equity_amounts: - equity_amount = equity_amounts["Equity:LloguerMiquel"].get_only_position( - ) - expense = sub(expense, equity_amount.units) - elif entry["account"] == "Expenses:FacturesUtilitats" and "Equity:FacturesUtilitatsMiquel" in equity_amounts: - equity_amount = equity_amounts["Equity:FacturesUtilitatsMiquel"].get_only_position( - ) - expense = sub(expense, equity_amount.units) + # Apply equity deductions for specific accounts (same logic as in build_budget) + if entry["account"] == "Expenses:Lloguer" and "Equity:LloguerMiquel" in equity_amounts: + equity_amount = equity_amounts["Equity:LloguerMiquel"].get_only_position( + ) + expense = sub(expense, equity_amount.units) + elif entry["account"] == "Expenses:FacturesUtilitats" and "Equity:FacturesUtilitatsMiquel" in equity_amounts: + equity_amount = equity_amounts["Equity:FacturesUtilitatsMiquel"].get_only_position( + ) + expense = sub(expense, equity_amount.units) - if expense.number > 0: - positive_expenses_sum = add(positive_expenses_sum, expense) + if expense.number > 0: + positive_expenses_sum = add(positive_expenses_sum, expense) budget_report = build_budget( budget_entries, expenses, equity_amounts, positive_expenses_sum) diff --git a/ledger/budget.beancount b/ledger/budget.beancount index 758fb84..080a135 100644 --- a/ledger/budget.beancount +++ b/ledger/budget.beancount @@ -1,3 +1,34 @@ +;; BUDGET 2026 +;; Monthly: 3097.00 EUR +;; Yearly: 7699.65 EUR +;; Total Yearly Run: 44863.65 EUR +;; Total Yearly Net Income: 44868 EUR +2026-01-01 custom "budget" Expenses:Lloguer "monthly" 625.00 EUR +2026-01-01 custom "budget" Expenses:FacturesUtilitats "monthly" 90.00 EUR +2026-01-01 custom "budget" Expenses:Internet "monthly" 50.00 EUR +2026-01-01 custom "budget" Expenses:Gasolina "monthly" 50.00 EUR +2026-01-01 custom "budget" Expenses:Perruqueria "monthly" 17.00 EUR +2026-01-01 custom "budget" Expenses:Supermercat "monthly" 185.00 EUR +2026-01-01 custom "budget" Expenses:Parking "monthly" 100.00 EUR +2026-01-01 custom "budget" Expenses:Mobilitat "monthly" 170.00 EUR +2026-01-01 custom "budget" Expenses:Entreteniment "monthly" 60.00 EUR +2026-01-01 custom "budget" Expenses:MenjarFora "monthly" 300.00 EUR +2026-01-01 custom "budget" Expenses:Altres "monthly" 200.00 EUR +2026-01-01 custom "budget" Liabilities:Credit:Renta4:PolissaCredit "monthly" 1300 EUR + +2026-01-01 custom "budget" Expenses:Roba "yearly" 1000 EUR +2026-01-01 custom "budget" Expenses:MantenimentCotxe "yearly" 1200.00 EUR +2026-01-01 custom "budget" Expenses:Educació "yearly" 180.00 EUR +2026-01-01 custom "budget" Expenses:Medic "yearly" 540.00 EUR +2026-01-01 custom "budget" Expenses:Vacances "yearly" 3000.00 EUR +2026-01-01 custom "budget" Expenses:Taxes:ImpostCirculacio "yearly" 66.00 EUR +2026-01-01 custom "budget" Expenses:NintendoOnline "yearly" 35.00 EUR +2026-01-01 custom "budget" Expenses:AmazonPrime "yearly" 50.00 EUR +2026-01-01 custom "budget" Expenses:Insurance:Cotxe "yearly" 660.00 EUR +2026-01-01 custom "budget" Expenses:CarnetJove "yearly" 8.65 EUR +2026-01-01 custom "budget" Expenses:Gimnàs "yearly" 720.00 EUR +2026-01-01 custom "budget" Expenses:MarcaPersonal "yearly" 240.00 EUR + ;; BUDGET 2025 ;; TOTAL: ;; Monthly: 3027.00 EUR