Die Rechnung auf eine Regel bringen, plus Knopf zum Nachrechnen

Die Regel lautet: so viele CC-Pakete wie Ketten, so viele Redesigns wie
Eintraege minus Ketten. Anders gesagt - wer keinen Vorgaenger hat, ist der
Anfang einer Kette und damit ein gekaufter CC; wer einen hat, ist dessen
Redesign. In welcher Linie ein Eintrag gefuehrt wird, spielt keine Rolle.

Ich hatte das mit einer Sonderbehandlung fuer "Herkunft ausserhalb der Linie"
gebaut. Die faellt weg: Sie war ein Umweg um dieselbe Regel und hat sie an
einer Stelle verfehlt. Jetzt steht sie direkt im Code, und der Fall mit dem
fremden Gruppen-CC folgt von selbst daraus - dessen eigener Strang hat einen
Vorgaenger, ist also kein Kauf.

Fuer Bestaende, die aus einer Zeit stammen, in der eine Buchung blieb, wo sie
beim Anlegen entstand, gibt es "Buchungen nachrechnen" auf der Spielerseite.
Es richtet alle Buchungen eines Spielers nach dieser Regel aus, fasst nur an,
was nicht passt, bucht ueber Gegenbuchungen um und laesst Kulanz-
Entscheidungen stehen.

Vier Tests halten die Rechnung fest, einer davon genau in der Form, in der
sie formuliert wurde: Ketten zaehlen, Eintraege zaehlen, Buchungen zaehlen,
vergleichen.
This commit is contained in:
2026-09-21 19:26:00 +02:00
parent 46e339fdc4
commit f0213fe4bc
5 changed files with 273 additions and 27 deletions
+45
View File
@@ -101,6 +101,42 @@ export default function PlayerDetail() {
}
};
/**
* Richtet die Buchungen nach den Ketten aus.
*
* Die Regel steckt in der Anzeige: so viele CC-Pakete wie Plätze, alles
* Weitere sind Redesigns. Für Bestände, die aus einer Zeit stammen, in der
* eine Buchung blieb, wo sie beim Anlegen entstand.
*/
const buchungenNachrechnen = async () => {
if (
!window.confirm(
'Buchungen nach den Ketten ausrichten?\n\nJede Kette beginnt mit einem gekauften CC, alles Weitere sind Redesigns. Was nicht passt, wird umgebucht - über eine Gegenbuchung, nichts geht verloren.',
)
) {
return;
}
setBusy(true);
setError(null);
try {
const ergebnis = await api<{ geprueft: number; umgebucht: number }>(
`/api/players/${playerId}/credits/rebuild`,
{ method: 'POST', body: {} },
);
await load();
melden(
ergebnis.umgebucht > 0
? `${ergebnis.umgebucht} von ${ergebnis.geprueft} Buchungen umgestellt.`
: `Alles passt - ${ergebnis.geprueft} Buchungen geprüft, nichts zu ändern.`,
);
} catch (err) {
setError(err instanceof ApiError ? err.message : 'Nachrechnen fehlgeschlagen');
} finally {
setBusy(false);
}
};
/**
* Nimmt die zuletzt von Hand eingetragene Zugabe zurück.
*
@@ -345,6 +381,15 @@ export default function PlayerDetail() {
>
Neuer CC
</button>
<button
type="button"
className="btn"
disabled={busy}
title="Jede Kette beginnt mit einem gekauften CC, alles Weitere sind Redesigns - danach die Buchungen richten"
onClick={() => void buchungenNachrechnen()}
>
Buchungen nachrechnen
</button>
{can('EDITOR') && detail.player.steamId && (
<button
type="button"