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:
@@ -171,7 +171,7 @@ func NewDataset() Dataset {
|
||||
return Dataset{Accounts: []Account{}, Categories: []Category{
|
||||
{ID: "cat_expenses", Name: "Expenses", Kind: "expense"}, {ID: ExpenseFallback, Name: "Unclassified", ParentID: "cat_expenses", Kind: "expense"},
|
||||
{ID: "cat_income", Name: "Income", Kind: "income"}, {ID: IncomeFallback, Name: "Unclassified", ParentID: "cat_income", Kind: "income"},
|
||||
}, Tags: []Tag{}, Merchants: []Merchant{}, Instruments: []Instrument{}, Transactions: []Transaction{}}
|
||||
}, Tags: []Tag{}, Merchants: []Merchant{}, Instruments: []Instrument{}, Assets: []Asset{}, Transactions: []Transaction{}}
|
||||
}
|
||||
|
||||
// InstrumentID derives a stable registry ID from an ISIN so re-importing the
|
||||
@@ -181,7 +181,7 @@ func InstrumentID(isin string) string {
|
||||
return "ins_" + hex.EncodeToString(sum[:16])
|
||||
}
|
||||
func Clone(d Dataset) Dataset {
|
||||
c := Dataset{Accounts: append([]Account{}, d.Accounts...), Categories: append([]Category{}, d.Categories...), Tags: append([]Tag{}, d.Tags...), Merchants: append([]Merchant{}, d.Merchants...), Instruments: append([]Instrument{}, d.Instruments...), Transactions: append([]Transaction{}, d.Transactions...)}
|
||||
c := Dataset{Accounts: append([]Account{}, d.Accounts...), Categories: append([]Category{}, d.Categories...), Tags: append([]Tag{}, d.Tags...), Merchants: append([]Merchant{}, d.Merchants...), Instruments: append([]Instrument{}, d.Instruments...), Assets: append([]Asset{}, d.Assets...), Transactions: append([]Transaction{}, d.Transactions...)}
|
||||
for i := range c.Merchants {
|
||||
c.Merchants[i].Aliases = append([]string{}, d.Merchants[i].Aliases...)
|
||||
c.Merchants[i].DefaultTagIDs = append([]string{}, d.Merchants[i].DefaultTagIDs...)
|
||||
@@ -398,6 +398,22 @@ func Validate(d Dataset) error {
|
||||
isins[v.ISIN] = v.ID
|
||||
instruments[v.ID] = v
|
||||
}
|
||||
for _, v := range d.Assets {
|
||||
if err := register(v.ID, "asset"); err != nil {
|
||||
return err
|
||||
}
|
||||
if !nonblank(v.Name) || !currencyPattern.MatchString(v.Currency) || !validText(v.Kind) {
|
||||
return fmt.Errorf("asset %q: valid UTF-8 name and three-letter uppercase currency required", v.ID)
|
||||
}
|
||||
// A hand-stated value without its day cannot be judged stale, so the
|
||||
// two are recorded together, always.
|
||||
if _, err := v.Value.Minor(); err != nil {
|
||||
return fmt.Errorf("asset %q: %w", v.ID, err)
|
||||
}
|
||||
if !validDate(v.ValuedAt) {
|
||||
return fmt.Errorf("asset %q: invalid valuation date %q", v.ID, v.ValuedAt)
|
||||
}
|
||||
}
|
||||
for _, t := range d.Transactions {
|
||||
f := t.Facts
|
||||
if err := register(f.ID, "transaction"); err != nil {
|
||||
|
||||
@@ -116,6 +116,20 @@ type Instrument struct {
|
||||
QuotedAt string `json:"quoted_at,omitempty"`
|
||||
}
|
||||
|
||||
// Asset is a possession valued by hand: a house, a car, anything without a
|
||||
// market feed. Value is what the owner states it is worth and ValuedAt the day
|
||||
// that estimate was made, so a stale figure is visible rather than silently
|
||||
// trusted. A negative value records a liability such as a mortgage.
|
||||
type Asset struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
// Kind is free display text grouping the asset: "Real estate", "Vehicle".
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Currency string `json:"currency"`
|
||||
Value Money `json:"value"`
|
||||
ValuedAt string `json:"valued_at"`
|
||||
}
|
||||
|
||||
type Facts struct {
|
||||
ID string `json:"id"`
|
||||
Source string `json:"source"`
|
||||
@@ -178,6 +192,7 @@ type Dataset struct {
|
||||
Tags []Tag `json:"tags"`
|
||||
Merchants []Merchant `json:"merchants"`
|
||||
Instruments []Instrument `json:"instruments"`
|
||||
Assets []Asset `json:"assets"`
|
||||
Transactions []Transaction `json:"transactions"`
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user