Count hand-valued assets into the wealth figure

A wealth figure that ignores the house is not a wealth figure. Assets
without a market feed - a house, a car, a private loan - are now added
by hand on the Wealth page with a stated value, a currency and the day
the estimate was made; a negative value records a liability. They are
registry entities in assets.finance like everything else, join the
per-currency totals immediately, and a currency held only in an asset
earns its own line.
This commit is contained in:
Lars Nolden
2026-09-14 09:29:19 +02:00
parent a1480af74d
commit 77f4ea5655
15 changed files with 564 additions and 29 deletions
+10 -2
View File
@@ -19,7 +19,7 @@ import (
// registryFiles are the non-monthly journal files, in the order they are read
// and written. A block's file is its kind pluralized, so this list and the
// kinds accepted by parseDocument must stay in step.
var registryFiles = []string{"accounts.finance", "categories.finance", "tags.finance", "merchants.finance", "instruments.finance"}
var registryFiles = []string{"accounts.finance", "categories.finance", "tags.finance", "merchants.finance", "instruments.finance", "assets.finance"}
type fieldSpan struct{ start, end int }
type block struct {
@@ -140,7 +140,7 @@ func parseDocument(path string, raw []byte) (*document, error) {
}
header := strings.Fields(trimmed)
if len(header) != 2 || header[1] != "{" {
return fail(i+1, "expected 'account|category|tag|merchant|instrument|transaction {'")
return fail(i+1, "expected 'account|category|tag|merchant|instrument|asset|transaction {'")
}
kind := header[0]
var value any
@@ -155,6 +155,8 @@ func parseDocument(path string, raw []byte) (*document, error) {
value = &domain.Merchant{}
case "instrument":
value = &domain.Instrument{}
case "asset":
value = &domain.Asset{}
case "transaction":
value = &domain.Transaction{}
default:
@@ -237,6 +239,9 @@ func parseDocument(path string, raw []byte) (*document, error) {
case *domain.Instrument:
b.id = v.ID
b.value = *v
case *domain.Asset:
b.id = v.ID
b.value = *v
case *domain.Merchant:
if v.Aliases == nil {
v.Aliases = []string{}
@@ -342,6 +347,9 @@ func datasetFiles(d domain.Dataset) map[string]map[string]piece {
for _, v := range d.Instruments {
add("instruments.finance", "instrument", v.ID, v)
}
for _, v := range d.Assets {
add("assets.finance", "asset", v.ID, v)
}
for _, v := range d.Transactions {
month := v.Facts.BookingDate[:7]
add("journal/"+month[:4]+"/"+month+".finance", "transaction", v.Facts.ID, v)