In „Depotbuchung erfassen“ ergibt sich bei Kauf und Verkauf aus zwei der drei Felder Betrag, Stück und Kurs das dritte (Betrag = Stück × Kurs). Der ausgerechnete Wert ist hervorgehoben und zieht nach, wenn sich die anderen Felder ändern. Serverseitig rechnet Depotbuchung::dritterWert() dieselbe Regel für den Weg ohne JavaScript. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
111 lines
3.5 KiB
JavaScript
111 lines
3.5 KiB
JavaScript
/* Stück, Kurs und Betrag in der Maske „Depotbuchung erfassen“.
|
||
*
|
||
* Bei Kauf und Verkauf gilt Betrag = Stück × Kurs: Sobald zwei der drei Felder
|
||
* eingetragen sind, ergibt sich das dritte. Der ausgerechnete Wert bleibt
|
||
* ausgerechnet – ändert man danach eines der beiden anderen Felder, wird er
|
||
* nachgezogen. Tippt man ihn selbst um, gilt er als eingetragen; leert man eines
|
||
* der beiden anderen Felder, verschwindet er wieder, weil nichts mehr dahinter
|
||
* steht.
|
||
*
|
||
* Der Server rechnet dieselbe Regel noch einmal (Depotbuchung::dritterWert) –
|
||
* für den Weg ohne JavaScript.
|
||
*/
|
||
|
||
(function () {
|
||
'use strict';
|
||
|
||
const formular = document.getElementById('depotbuchungsformular');
|
||
if (!formular || !window.FmBetrag) {
|
||
return;
|
||
}
|
||
|
||
const vorgang = document.getElementById('vorgang');
|
||
const felder = {
|
||
stueck: document.getElementById('stueck'),
|
||
kurs: document.getElementById('kurs'),
|
||
betrag: document.getElementById('betrag')
|
||
};
|
||
if (!vorgang || !felder.stueck || !felder.kurs || !felder.betrag) {
|
||
return;
|
||
}
|
||
|
||
// Welches Feld zuletzt ausgerechnet wurde – null, solange alle eingetragen sind.
|
||
let berechnet = null;
|
||
|
||
function wert(name) {
|
||
return window.FmBetrag.zahl(felder[name].value);
|
||
}
|
||
|
||
function leer(name) {
|
||
return felder[name].value.trim() === '';
|
||
}
|
||
|
||
function formatiere(name, zahl) {
|
||
if (name === 'betrag') {
|
||
return window.FmBetrag.formatiere(zahl);
|
||
}
|
||
// Stück und Kurs führt die Datenbank mit sechs Nachkommastellen.
|
||
return zahl.toLocaleString('de-DE', { minimumFractionDigits: 0, maximumFractionDigits: 6 });
|
||
}
|
||
|
||
function setze(name, zahl) {
|
||
felder[name].value = zahl === null ? '' : formatiere(name, zahl);
|
||
felder[name].classList.toggle('berechnet', zahl !== null);
|
||
berechnet = zahl === null ? null : name;
|
||
}
|
||
|
||
function ausrechnen(name) {
|
||
const stueck = wert('stueck');
|
||
const kurs = wert('kurs');
|
||
const betrag = wert('betrag');
|
||
|
||
switch (name) {
|
||
case 'betrag':
|
||
return stueck > 0 && kurs > 0 ? Math.round(stueck * kurs * 100) / 100 : null;
|
||
case 'kurs':
|
||
return stueck > 0 && betrag > 0 ? Math.round(betrag / stueck * 1e6) / 1e6 : null;
|
||
default:
|
||
return kurs > 0 && betrag > 0 ? Math.round(betrag / kurs * 1e6) / 1e6 : null;
|
||
}
|
||
}
|
||
|
||
function rechne(geaendert) {
|
||
if (geaendert !== null && geaendert === berechnet) {
|
||
felder[geaendert].classList.remove('berechnet');
|
||
berechnet = null;
|
||
}
|
||
if (vorgang.value !== 'kauf' && vorgang.value !== 'verkauf') {
|
||
return;
|
||
}
|
||
|
||
if (geaendert !== null && leer(geaendert) && berechnet !== null) {
|
||
setze(berechnet, null);
|
||
return;
|
||
}
|
||
|
||
let ziel = berechnet;
|
||
if (ziel === null) {
|
||
const offen = Object.keys(felder).filter(leer);
|
||
if (offen.length !== 1) {
|
||
return;
|
||
}
|
||
ziel = offen[0];
|
||
}
|
||
|
||
const ergebnis = ausrechnen(ziel);
|
||
if (ergebnis !== null) {
|
||
setze(ziel, ergebnis);
|
||
} else if (ziel === berechnet) {
|
||
setze(ziel, null);
|
||
}
|
||
}
|
||
|
||
Object.keys(felder).forEach(function (name) {
|
||
felder[name].addEventListener('input', function () {
|
||
rechne(name);
|
||
});
|
||
});
|
||
vorgang.addEventListener('change', function () {
|
||
rechne(null);
|
||
});
|
||
})();
|