it-praxisportal/courses/javascript/13_es_module_und_architektur/musterloesung.js

139 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 🌟 MUSTERLÖSUNG: JS 13 – ES MODULE & ARCHITEKTUR 🌟
* ===================================================
*/
function pruefeZahl(val, name = "Wert") {
if (typeof val !== "number" || isNaN(val)) {
throw new TypeError(`${name} muss eine gültige Zahl sein`);
}
}
const MathModule = {
addieren(a, b) {
pruefeZahl(a, "Parameter a");
pruefeZahl(b, "Parameter b");
return Math.round((a + b) * 1e8) / 1e8;
},
subtrahieren(a, b) {
pruefeZahl(a, "Parameter a");
pruefeZahl(b, "Parameter b");
return Math.round((a - b) * 1e8) / 1e8;
},
multiplizieren(a, b) {
pruefeZahl(a, "Parameter a");
pruefeZahl(b, "Parameter b");
return Math.round((a * b) * 1e8) / 1e8;
},
dividieren(a, b) {
pruefeZahl(a, "Parameter a");
pruefeZahl(b, "Parameter b");
if (b === 0) {
throw new Error("Division durch 0 nicht erlaubt");
}
return Math.round((a / b) * 1e8) / 1e8;
},
runden(betrag, dezimalstellen = 2) {
pruefeZahl(betrag, "Betrag");
pruefeZahl(dezimalstellen, "Dezimalstellen");
const faktor = Math.pow(10, dezimalstellen);
return Math.round((betrag + Number.EPSILON) * faktor) / faktor;
}
};
const FormatterModule = {
formatiereWaehrung(betrag, waehrung = "EUR") {
pruefeZahl(betrag, "Betrag");
if (typeof waehrung !== "string" || waehrung.trim().length === 0) {
throw new TypeError("Währung muss ein nicht-leerer String sein");
}
const gerundet = MathModule.runden(betrag, 2);
const teile = (Math.abs(gerundet)).toFixed(2).split(".");
const vz = gerundet < 0 ? "-" : "";
const ganzzahlFormatiert = teile[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
return `${vz}${ganzzahlFormatiert},${teile[1]} ${waehrung.trim().toUpperCase()}`;
},
formatiereDatumIso(datum) {
let d;
if (datum instanceof Date) {
d = datum;
} else if (typeof datum === "string" || typeof datum === "number") {
d = new Date(datum);
} else {
throw new TypeError("Ungültiges Datumsformat");
}
if (isNaN(d.getTime())) {
throw new TypeError("Ungültiges Datum");
}
const jahr = d.getUTCFullYear();
const monat = String(d.getUTCMonth() + 1).padStart(2, "0");
const tag = String(d.getUTCDate()).padStart(2, "0");
return `${jahr}-${monat}-${tag}`;
}
};
class RechnungsEngine {
constructor(mathMod = MathModule, formatMod = FormatterModule) {
this.math = mathMod;
this.formatter = formatMod;
}
erstellePosition(bezeichnung, menge, einzelpreis) {
if (typeof bezeichnung !== "string" || bezeichnung.trim().length === 0) {
throw new Error("Bezeichnung darf nicht leer sein");
}
if (typeof menge !== "number" || isNaN(menge) || menge <= 0) {
throw new RangeError("Menge muss eine Zahl größer als 0 sein");
}
if (typeof einzelpreis !== "number" || isNaN(einzelpreis) || einzelpreis < 0) {
throw new RangeError("Einzelpreis muss eine Zahl >= 0 sein");
}
const gesamtpreis = this.math.multiplizieren(menge, einzelpreis);
return {
bezeichnung: bezeichnung.trim(),
menge,
einzelpreis,
gesamtpreis
};
}
berechneRechnung(positionen, steuersatzProzent = 19) {
if (!Array.isArray(positionen)) {
throw new TypeError("Positionen müssen als Array übergeben werden");
}
if (typeof steuersatzProzent !== "number" || isNaN(steuersatzProzent) || steuersatzProzent < 0) {
throw new RangeError("Steuersatz muss eine Zahl >= 0 sein");
}
let nettoSumme = 0;
for (const p of positionen) {
const gp = (p && typeof p.gesamtpreis === "number") ? p.gesamtpreis : 0;
nettoSumme = this.math.addieren(nettoSumme, gp);
}
const steuerFaktor = this.math.dividieren(steuersatzProzent, 100);
const steuerUnrund = this.math.multiplizieren(nettoSumme, steuerFaktor);
const steuerBetrag = this.math.runden(steuerUnrund, 2);
const bruttoSumme = this.math.addieren(nettoSumme, steuerBetrag);
return {
positionen: [...positionen],
nettoSumme,
steuersatzProzent,
steuerBetrag,
bruttoSumme,
nettoFormatiert: this.formatter.formatiereWaehrung(nettoSumme),
steuerFormatiert: this.formatter.formatiereWaehrung(steuerBetrag),
bruttoFormatiert: this.formatter.formatiereWaehrung(bruttoSumme)
};
}
}