feat: Anlass + Endgrund fields for records

Adds two optional free-text fields to describe why a transaction
started ("Anlass") and why it ended ("Endgrund") - chosen names instead
of the technical "Startursache"/"Endesuhrsache". Displayed as own table
columns and editable in the form; legacy records without those fields
render as "-". Payload is encrypted client-side like every other field
(no server change needed, opaque ciphertext).

Verified: node --check, crypto roundtrip incl. new fields, legacy-safe
access (?? ''), pytest 3/3.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
This commit is contained in:
2026-10-11 01:04:46 +02:00
parent c82de902a8
commit 516cb13dcf
2 changed files with 17 additions and 1 deletions
+10
View File
@@ -74,6 +74,8 @@
<th>Person B</th> <th>Person B</th>
<th>Start</th> <th>Start</th>
<th>Ende</th> <th>Ende</th>
<th>Anlass</th>
<th>Endgrund</th>
<th>Aktion</th> <th>Aktion</th>
<th></th> <th></th>
</tr> </tr>
@@ -100,6 +102,14 @@
<input id="f-tsend" type="text" maxlength="120" <input id="f-tsend" type="text" maxlength="120"
placeholder="z. B. laufend, unbekannt, März 2026 …" /> placeholder="z. B. laufend, unbekannt, März 2026 …" />
</label> </label>
<label>Anlass (optional)
<input id="f-startcause" type="text" maxlength="300"
placeholder="womit/warum es begann, z. B. gemeinsam geplante Reise …" />
</label>
<label>Endgrund (optional)
<input id="f-endcause" type="text" maxlength="300"
placeholder="warum es endete, z. B. zurückgezahlt, abgelaufen …" />
</label>
<label>Aktion <label>Aktion
<input id="f-action" type="text" required maxlength="500" /> <input id="f-action" type="text" required maxlength="500" />
</label> </label>
+7 -1
View File
@@ -104,6 +104,8 @@ function renderRow(record, payload) {
payload.personB, payload.personB,
showTs(payload.tsStart), showTs(payload.tsStart),
showTs(payload.tsEnd), showTs(payload.tsEnd),
showTs(payload.startCause),
showTs(payload.endCause),
payload.action, payload.action,
]; ];
for (const text of cells) { for (const text of cells) {
@@ -145,7 +147,7 @@ async function reload() {
failures++; failures++;
tbody.appendChild( tbody.appendChild(
el("tr", { class: "row-error" }, [ el("tr", { class: "row-error" }, [
el("td", { colspan: "6", text: "Datensatz nicht entschlüsselbar (falsche Passphrase oder manipuliert)." }), el("td", { colspan: "8", text: "Datensatz nicht entschlüsselbar (falsche Passphrase oder manipuliert)." }),
]) ])
); );
} }
@@ -164,6 +166,8 @@ function openEditor(record, payload) {
$("#f-personb").value = payload.personB ?? ""; $("#f-personb").value = payload.personB ?? "";
$("#f-tsstart").value = payload.tsStart ?? ""; $("#f-tsstart").value = payload.tsStart ?? "";
$("#f-tsend").value = payload.tsEnd ?? ""; $("#f-tsend").value = payload.tsEnd ?? "";
$("#f-startcause").value = payload.startCause ?? "";
$("#f-endcause").value = payload.endCause ?? "";
$("#f-action").value = payload.action ?? ""; $("#f-action").value = payload.action ?? "";
$("#editor-backdrop").hidden = false; $("#editor-backdrop").hidden = false;
} }
@@ -201,6 +205,8 @@ async function saveRecord(ev) {
personB: $("#f-personb").value.trim(), personB: $("#f-personb").value.trim(),
tsStart: tsOrNull($("#f-tsstart").value), tsStart: tsOrNull($("#f-tsstart").value),
tsEnd: tsOrNull($("#f-tsend").value), tsEnd: tsOrNull($("#f-tsend").value),
startCause: tsOrNull($("#f-startcause").value),
endCause: tsOrNull($("#f-endcause").value),
action: $("#f-action").value.trim(), action: $("#f-action").value.trim(),
}; };
if (!payload.personA || !payload.personB || !payload.action) { if (!payload.personA || !payload.personB || !payload.action) {