Show negative values as parentheses on Accounts

This commit is contained in:
2026-09-27 13:21:26 +02:00
parent 483bff90cd
commit b82fc0fc80
4 changed files with 45 additions and 19 deletions
+30 -18
View File
@@ -42,7 +42,11 @@ module Hledger
rows, total = parse_json(result.stdout)
sections = [
{ "title" => nil, "rows" => account_rows(Array(rows)), "total" => amounts(Array(total)) },
{
"title" => nil,
"rows" => account_rows(Array(rows)),
"total" => amounts(Array(total), parenthesize: true),
},
]
envelope("accounts", begin_date, end_date, "sections" => sections, "net" => nil)
@@ -176,7 +180,7 @@ module Hledger
[(full || display).to_s, Array(row_amounts).map { |amount| raw_amount(amount) }]
end
tree_rows(entries)
tree_rows(entries, parenthesize: true)
end
def compound_rows(rows)
@@ -204,11 +208,13 @@ module Hledger
end
end
def tree_rows(entries)
def tree_rows(entries, parenthesize: false)
AccountTree
.expand(entries)
.map do |node|
node.merge("amounts" => node["amounts"].map { |part| normalized_amount(part) })
node.merge(
"amounts" => node["amounts"].map { |part| normalized_amount(part, parenthesize:) },
)
end
end
@@ -216,8 +222,8 @@ module Hledger
label.to_s.casecmp?(title.to_s)
end
def amounts(list)
Array(list).map { |amount| normalized_amount(raw_amount(amount)) }
def amounts(list, parenthesize: false)
Array(list).map { |amount| normalized_amount(raw_amount(amount), parenthesize:) }
end
def raw_amount(amount)
@@ -228,7 +234,7 @@ module Hledger
}
end
def normalized_amount(part)
def normalized_amount(part, parenthesize: false)
commodity = part["commodity"].to_s
quantity = part["quantity"]
style = part["style"] || {}
@@ -236,7 +242,7 @@ module Hledger
{
"commodity" => commodity,
"quantity" => quantity.to_s("F"),
"display" => display_amount(quantity, commodity, style),
"display" => display_amount(quantity, commodity, style, parenthesize:),
"side" => style["ascommodityside"] || "R",
"spaced" => style["ascommodityspaced"] ? true : false,
"precision" => style["asprecision"],
@@ -251,25 +257,31 @@ module Hledger
BigDecimal(mantissa) / (10**places)
end
def display_amount(quantity, commodity, style)
def display_amount(quantity, commodity, style, parenthesize: false)
precision = style["asprecision"]
if precision.nil?
rendered = quantity.to_s("F")
rendered = quantity.abs.to_s("F")
precision = rendered.include?(".") ? rendered.split(".").last.length : 0
end
mark = style["asdecimalmark"].presence || "."
number = format("%.#{precision}f", quantity)
magnitude = parenthesize ? quantity.abs : quantity
number = format("%.#{precision}f", magnitude)
number = number.tr(".", mark) if mark != "."
return number if commodity.blank?
text =
if commodity.blank?
number
else
spaced = style["ascommodityspaced"] ? " " : ""
if style["ascommodityside"] == "L"
"#{commodity}#{spaced}#{number}"
else
"#{number}#{spaced}#{commodity}"
end
end
spaced = style["ascommodityspaced"] ? " " : ""
if style["ascommodityside"] == "L"
"#{commodity}#{spaced}#{number}"
else
"#{number}#{spaced}#{commodity}"
end
parenthesize && quantity.negative? ? "(#{text})" : text
end
def balance_flags(begin_date, end_date)
+1
View File
@@ -40,6 +40,7 @@ RSpec.describe "Hledger integration" do
expect(by_account.keys.first(3)).to eq(%w[assets assets:bank assets:bank:checking])
expect(by_account["assets:bank"]["label"]).to eq("Bank")
expect(by_account["assets:bank"]["amounts"].first["display"]).to eq("1029.50 EUR")
expect(by_account["equity:alice"]["amounts"].first["display"]).to eq("(600.00 EUR)")
end
it "renders the balance sheet and income statement as trees" do
+2 -1
View File
@@ -63,7 +63,8 @@ RSpec.describe Hledger::ReportBuilder do
expect(assets["amounts"].first["display"]).to eq("1029.50 EUR")
equity = rows.find { |row| row["account"] == "equity" }
expect(equity["amounts"].first["display"]).to eq("-1000.00 EUR")
expect(equity["amounts"].first["display"]).to eq("(1000.00 EUR)")
expect(equity["amounts"].first["quantity"]).to eq("-1000.0")
checking = rows.find { |row| row["account"] == "assets:bank:checking" }
expect(checking["depth"]).to eq(2)
@@ -40,6 +40,15 @@ const accountsReport = {
{ commodity: "EUR", quantity: "1000.0", display: "1000.00 EUR" },
],
},
{
account: "equity",
label: "Equity",
depth: 0,
root: true,
amounts: [
{ commodity: "EUR", quantity: "-1000.0", display: "(1000.00 EUR)" },
],
},
],
total: [{ commodity: "EUR", quantity: "1000.0", display: "1000.00 EUR" }],
},
@@ -279,6 +288,9 @@ acceptance("Hledger plugin", function (needs) {
assert.dom(".hledger-dashboard__table").includesText("Bank");
assert.dom(".hledger-dashboard__table").includesText("Checking");
assert.dom(".hledger-dashboard__table").includesText("1000.00 EUR");
assert
.dom(".hledger-dashboard__table")
.includesText("(1000.00 EUR)", "shows credit balances in parentheses");
assert.dom(".hledger-dashboard__account.--depth-1").hasText("Bank");
assert.dom(".hledger-dashboard__account.--depth-2").hasText("Checking");
assert