Aufträge und Rechnungen: Laden und Ladezustand des Reiters als reine Funktionen (mit Tests)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-07 14:24:20 +00:00
1 parent e7bd146641
commit 312705efc4
2 files changed
+213

No files matched your search

+69
View File
@@ -0,0 +1,69 @@
// Ansichtslogik des Reiters „Aufträge und Rechnungen“ (rein, ohne React und ohne Appwrite; unter Node testbar).
// Die API-Funktionen kommen als Argument. Der Container (AuftraegeUndRechnungen.jsx) verdrahtet diese Funktionen mit
// useFinanceResource und den Abschnitten des Reiters.
export const KONTEN_FEHLER = 'Die Projektübersicht konnte nicht geladen werden.'
export const AUFTRAEGE_FEHLER = 'Die Aufträge konnten nicht geladen werden.'
const istObjekt = (wert) => wert !== null && typeof wert === 'object' && !Array.isArray(wert)
const ohneProjektLeer = () => ({ berechnetCents: 0, bezahltCents: 0, anzahl: 0 })
/**
* Lädt Projektkonten und, nur bei eingeschaltetem Schalter (`auftraegeAktiv === true`), die Aufträge des Kunden.
* Scheitert getProjektkonten, geht der Fehler weiter (keine Aufträge, sie würden ohne Schalter 404 liefern).
* Scheitert nur listAuftraege, bleiben die Projektkonten und der Fehler steht eigens da.
* -> { konten, auftraege: Liste | null, auftraegeFehler: Text | '' }
*/
export async function ladeAuftraegeAnsicht(kundeId, { getProjektkonten, listAuftraege }) {
const antwort = await getProjektkonten(kundeId)
const konten = istObjekt(antwort) ? antwort : {}
if (konten.auftraegeAktiv !== true) return { konten, auftraege: null, auftraegeFehler: '' }
try {
const liste = await listAuftraege(kundeId)
return { konten, auftraege: Array.isArray(liste?.auftraege) ? liste.auftraege : [], auftraegeFehler: '' }
} catch (err) {
return { konten, auftraege: null, auftraegeFehler: (err && err.message) || AUFTRAEGE_FEHLER }
}
}
/**
* Zustand der Ansicht aus dem Ergebnis von useFinanceResource ({ data, error }).
* -> { projekteStatus: 'laden' | 'fehler' | 'bereit', fehler, nachladeFehler,
* auftraegeAktiv, auftraegeStatus: 'aus' | 'bereit' | 'fehler', auftraegeFehler,
* konten, ohneProjekt, stripeOk, kunde, auftraege }
* Ohne Daten gibt es keinen Aufträge-Abschnitt (der Schalter ist noch unbekannt). Scheitert das Neuladen, nachdem Daten
* da sind, bleiben die alten Daten stehen und die Meldung kommt als `nachladeFehler` daneben.
*/
export function ansichtsZustand({ data, error } = {}) {
if (!data) {
return {
projekteStatus: error ? 'fehler' : 'laden',
fehler: error || '',
nachladeFehler: '',
auftraegeAktiv: false,
auftraegeStatus: 'aus',
auftraegeFehler: '',
konten: [],
ohneProjekt: ohneProjektLeer(),
stripeOk: true,
kunde: null,
auftraege: [],
}
}
const k = istObjekt(data.konten) ? data.konten : {}
const auftraegeAktiv = k.auftraegeAktiv === true
const auftraegeStatus = !auftraegeAktiv ? 'aus' : data.auftraegeFehler ? 'fehler' : 'bereit'
return {
projekteStatus: 'bereit',
fehler: '',
nachladeFehler: error || '',
auftraegeAktiv,
auftraegeStatus,
auftraegeFehler: auftraegeStatus === 'fehler' ? data.auftraegeFehler : '',
konten: Array.isArray(k.konten) ? k.konten : [],
ohneProjekt: istObjekt(k.ohneProjekt) ? k.ohneProjekt : ohneProjektLeer(),
stripeOk: k.stripeOk !== false,
kunde: istObjekt(k.kunde) ? k.kunde : null,
auftraege: auftraegeAktiv && Array.isArray(data.auftraege) ? data.auftraege : [],
}
}