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

187 lines
6.4 KiB
JavaScript

/**
* 🌐 JS 13: ES MODULE & ARCHITEKTUR (CLEAN CODE & SEPARATION OF CONCERNS) 🌐
* =========================================================================
* In diesem Modul lernst du, wie modularer Code mit klarer Trennung von
* Geschäftslogik (Math), Präsentation (Formatter) und Controller (Engine)
* aufgebaut wird.
*/
// ============================================================================
// 1. MODUL: MathModule (Reine mathematische Geschäftslogik)
// ============================================================================
const MathModule = {
/**
* 🎯 TEILZIEL 1 (TODO 1a): addieren(a, b)
* Addiert zwei Zahlen. Wirft TypeError falls a oder b keine gültige Zahl ist.
* @param {number} a
* @param {number} b
* @returns {number}
*/
addieren(a, b) {
// TODO: Validierung & Addition
return 0;
},
/**
* 🎯 TEILZIEL 1 (TODO 1b): subtrahieren(a, b)
* Subtrahiert b von a. Wirft TypeError falls a oder b keine gültige Zahl ist.
* @param {number} a
* @param {number} b
* @returns {number}
*/
subtrahieren(a, b) {
// TODO: Validierung & Subtraktion
return 0;
},
/**
* 🎯 TEILZIEL 1 (TODO 1c): multiplizieren(a, b)
* Multipliziert zwei Zahlen. Wirft TypeError falls a oder b keine gültige Zahl ist.
* @param {number} a
* @param {number} b
* @returns {number}
*/
multiplizieren(a, b) {
// TODO: Validierung & Multiplikation
return 0;
},
/**
* 🎯 TEILZIEL 1 (TODO 1d): dividieren(a, b)
* Dividiert a durch b. Wirft TypeError bei ungültigen Zahlen und
* Error("Division durch 0 nicht erlaubt") falls b === 0 ist.
* @param {number} a
* @param {number} b
* @returns {number}
*/
dividieren(a, b) {
// TODO: Validierung, 0-Prüfung & Division
return 0;
},
/**
* 🎯 TEILZIEL 1 (TODO 1e): runden(betrag, dezimalstellen = 2)
* Rundet kaufmännisch auf die übergebene Anzahl von Nachkommastellen.
* @param {number} betrag
* @param {number} [dezimalstellen=2]
* @returns {number}
*/
runden(betrag, dezimalstellen = 2) {
// TODO: Kaufmännisches Runden
return 0;
}
};
// ============================================================================
// 2. MODUL: FormatterModule (Präsentations- & Formatierungslogik)
// ============================================================================
const FormatterModule = {
/**
* 🎯 TEILZIEL 2 (TODO 2a): formatiereWaehrung(betrag, waehrung = "EUR")
* Formatiert eine Zahl im deutschen Währungsformat mit 2 Nachkommastellen
* und Tausender-Trennzeichen:
* z.B. 1250.5 -> "1.250,50 EUR", 49.99 -> "49,99 EUR", 0 -> "0,00 EUR"
* Wirft TypeError falls betrag keine Zahl ist oder waehrung ungültig ist.
*
* @param {number} betrag
* @param {string} [waehrung="EUR"]
* @returns {string}
*/
formatiereWaehrung(betrag, waehrung = "EUR") {
// TODO: Betrag runden, deutsches Format mit Komma und Tausender-Punkt erstellen
return "";
},
/**
* 🎯 TEILZIEL 2 (TODO 2b): formatiereDatumIso(datum)
* Wandelt ein Date-Objekt oder einen Datums-String in das ISO-Format "YYYY-MM-DD" um.
* Wirft TypeError falls das Datum ungültig ist.
* z.B. new Date(2026, 7, 30) -> "2026-08-30"
*
* @param {Date | string | number} datum
* @returns {string}
*/
formatiereDatumIso(datum) {
// TODO: Date-Objekt validieren und als YYYY-MM-DD formatieren
return "";
}
};
// ============================================================================
// 3. HAUPT-CONTROLLER: RechnungsEngine (Orchestrator mit Dependency Injection)
// ============================================================================
/**
* @typedef {Object} Rechnungsposition
* @property {string} bezeichnung - Name des Artikels / der Dienstleistung
* @property {number} menge - Anzahl (muss > 0 sein)
* @property {number} einzelpreis - Preis pro Einheit (muss >= 0 sein)
* @property {number} gesamtpreis - menge * einzelpreis
*/
/**
* @typedef {Object} Rechnung
* @property {Rechnungsposition[]} positionen
* @property {number} nettoSumme
* @property {number} steuersatzProzent
* @property {number} steuerBetrag
* @property {number} bruttoSumme
* @property {string} nettoFormatiert
* @property {string} steuerFormatiert
* @property {string} bruttoFormatiert
*/
class RechnungsEngine {
/**
* Konstruktor mit Dependency Injection:
* Erlaubt das Austauschen der Module für Tests oder andere Währungen/Formate.
* @param {typeof MathModule} [mathMod=MathModule]
* @param {typeof FormatterModule} [formatMod=FormatterModule]
*/
constructor(mathMod = MathModule, formatMod = FormatterModule) {
this.math = mathMod;
this.formatter = formatMod;
}
/**
* 🎯 TEILZIEL 3 (TODO 3): erstellePosition(bezeichnung, menge, einzelpreis)
* Erstellt eine validierte Rechnungsposition und berechnet den gesamtpreis.
*
* Anforderungen:
* - bezeichnung: string (nach .trim() nicht leer, sonst Error werfen)
* - menge: number (> 0, sonst RangeError)
* - einzelpreis: number (>= 0, sonst RangeError)
* - gesamtpreis berechnen über this.math.multiplizieren(menge, einzelpreis)
* - Rückgabe: { bezeichnung, menge, einzelpreis, gesamtpreis }
*
* @param {string} bezeichnung
* @param {number} menge
* @param {number} einzelpreis
* @returns {Rechnungsposition}
*/
erstellePosition(bezeichnung, menge, einzelpreis) {
// TODO: Validierung & Erstellung der Position
return null;
}
/**
* 🎯 TEILZIEL 4 (TODO 4): berechneRechnung(positionen, steuersatzProzent = 19)
* Berechnet Gesamtsummen, Steuern und formatierte Ausgaben für eine Liste von Positionen.
*
* Anforderungen:
* - positionen: Array von Rechnungspositionen (falls leer, Summen = 0)
* - steuersatzProzent: number (Standard: 19)
* - nettoSumme: Summe aller p.gesamtpreis (mit this.math.addieren berechnen)
* - steuerBetrag: this.math.runden(this.math.multiplizieren(nettoSumme, steuersatzProzent / 100), 2)
* - bruttoSumme: this.math.addieren(nettoSumme, steuerBetrag)
* - Formatierte Werte über this.formatter.formatiereWaehrung() erzeugen
* - Rückgabe: Das fertige Rechnung-Objekt
*
* @param {Rechnungsposition[]} positionen
* @param {number} [steuersatzProzent=19]
* @returns {Rechnung}
*/
berechneRechnung(positionen, steuersatzProzent = 19) {
// TODO: Netto, Steuer, Brutto und formatierte Werte berechnen
return null;
}
}