Add account balance anchors

This commit is contained in:
Lars Nolden
2026-09-14 13:32:18 +02:00
parent 83bb86bc93
commit 71e95917da
15 changed files with 440 additions and 23 deletions
+42 -6
View File
@@ -1244,9 +1244,16 @@ function AccountEditor({
pattern="[A-Z]{3}"
maxLength={3}
value={value.currency}
onChange={(e) =>
setValue({ ...value, currency: e.target.value.toUpperCase() })
}
onChange={(e) => {
const currency = e.target.value.toUpperCase();
setValue((current) => ({
...current,
currency,
...(currency !== current.currency
? { anchor_balance: "", anchor_date: "" }
: {}),
}));
}}
/>
</Field>
</div>
@@ -1288,11 +1295,40 @@ function AccountEditor({
>
<input
value={value.external_account_id || ""}
onChange={(e) =>
setValue({ ...value, external_account_id: e.target.value })
}
onChange={(e) => {
const external = e.target.value;
setValue((current) => ({
...current,
external_account_id: external,
...(external !== (current.external_account_id || "")
? { anchor_balance: "", anchor_date: "" }
: {}),
}));
}}
/>
</Field>
{value.anchor_date && (
<Field
label="Balance anchor"
hint="The bank's booked balance, captured once after a sync. It fixes this account's start balance on Wealth. Clear it and the next synchronization captures a fresh one."
>
<div className="anchor-row">
<span>
{money(value.anchor_balance ?? "0", value.currency)} on{" "}
{value.anchor_date}
</span>
<button
type="button"
className="button subtle"
onClick={() =>
setValue({ ...value, anchor_balance: "", anchor_date: "" })
}
>
Clear anchor
</button>
</div>
</Field>
)}
<label className="checkbox">
<input
type="checkbox"
+9 -3
View File
@@ -309,8 +309,11 @@ export default function WealthPage({
<dt>Completeness</dt>
<dd>
Cash equals the real balance only when the journal holds
that account's full history: a broker export does, a
date-windowed bank statement does not.
that account&rsquo;s full history: a broker export does, a
date-windowed bank statement does not. A connected bank
account closes that gap with an anchor the bank&rsquo;s
own booked balance, captured once from which the start
balance before the recorded rows is derived.
</dd>
</div>
</dl>
@@ -547,7 +550,10 @@ function AssetsPanel({
</p>
</div>
<div className="row-actions">
<button className="button secondary" onClick={() => setEditing(blank)}>
<button
className="button secondary"
onClick={() => setEditing(blank)}
>
<Plus size={16} />
Add asset
</button>
+5
View File
@@ -11,6 +11,11 @@ export interface Account {
// against: a broker export carries no counterparty, so its deposits and
// withdrawals pair with the funding account through this IBAN.
reference_iban?: string;
// anchor_balance is the bank's booked balance on anchor_date, captured once
// from open banking after a sync. It fixes the start balance of a
// date-windowed history; clearing both lets the next sync re-anchor.
anchor_balance?: string;
anchor_date?: string;
active: boolean;
}
// Instrument is a security held in an investment account. The ISIN is the
+6
View File
@@ -2675,3 +2675,9 @@ footer span:first-child {
font-size: 10px;
}
}
.anchor-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
}