Aufträge und Rechnungen: frische Kundenart und Rückmeldungen nach Rechnung und Auftrag (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:47 +00:00
1 parent 312705efc4
commit e1c9b57249
2 files changed
+82 -1

No files matched your search

+38
View File
@@ -1,6 +1,7 @@
// 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.
import { invoiceDoneMessage } from './financeView'
export const KONTEN_FEHLER = 'Die Projektübersicht konnte nicht geladen werden.'
export const AUFTRAEGE_FEHLER = 'Die Aufträge konnten nicht geladen werden.'
@@ -67,3 +68,40 @@ export function ansichtsZustand({ data, error } = {}) {
auftraege: auftraegeAktiv && Array.isArray(data.auftraege) ? data.auftraege : [],
}
}
// Wertebereich von customers.kundenart (V1); bewusst lokal, auftragView.js gehört dem Strang W2
const KUNDENARTEN = ['unternehmen', 'privat']
/**
* Kundendokument mit der frischen Kundenart des Portals (getProjektkonten -> kunde.kundenart). Gilt nur ein gültiger Wert
* („unternehmen“ oder „privat“), kommt eine Kopie mit diesem Wert zurück, das Dokument der Seite bleibt unverändert.
* Sonst dieselbe Referenz (null bleibt null). So fragt der AB-Dialog nicht erneut, wenn die Kundenart eben gespeichert wurde
* und die Kundenseite noch den alten Datensatz hält.
*/
export function kundeMitKundenart(customer, kundeInfo) {
const art = istObjekt(kundeInfo) ? kundeInfo.kundenart : undefined
if (!customer || !KUNDENARTEN.includes(art)) return customer
return { ...customer, kundenart: art }
}
/**
* Rückmeldung nach dem Anlegen einer Rechnung (wie InvoiceTable.handleCreated): `info.notice` (festgeschrieben, aber nicht
* versendet) gewinnt mit seinem Ton, sonst Entwurf oder gesendet. `info` darf fehlen oder null sein. -> { tone, text }
*/
export function erstelltMeldung(rechnung, info) {
const i = istObjekt(info) ? info : {}
if (typeof i.notice === 'string' && i.notice) return { tone: i.tone || 'ok', text: i.notice }
return { tone: 'ok', text: invoiceDoneMessage(i.senden ? 'create-send' : 'create-draft', rechnung) }
}
/** Rückmeldung nach dem Speichern oder Senden einer Auftragsbestätigung (onSaved des AB-Dialogs). -> { tone, text } */
export function auftragMeldung(auftrag) {
const a = istObjekt(auftrag) ? auftrag : {}
const name = a.nummer ? `Auftragsbestätigung ${a.nummer}` : 'Die Auftragsbestätigung'
if (a.status === 'entwurf') return { tone: 'ok', text: 'Der Entwurf wurde gespeichert.' }
if (a.mailStatus === 'fehler') {
return { tone: 'warn', text: `${name} ist versendet, die Mail an den Kunden wurde aber nicht zugestellt. Bitte in der Liste erneut senden.` }
}
if (a.nummer) return { tone: 'ok', text: `${name} wurde${a.gesendetAn ? ` an ${a.gesendetAn}` : ''} gesendet.` }
return { tone: 'ok', text: 'Die Auftragsbestätigung wurde gespeichert.' }
}
+44 -1
View File
@@ -2,7 +2,9 @@ import test from 'node:test'
import assert from 'node:assert/strict'
import { loadModule } from './load.mjs'
const { KONTEN_FEHLER, AUFTRAEGE_FEHLER, ladeAuftraegeAnsicht, ansichtsZustand } = await loadModule('src/lib/auftraegeAnsicht.js')
const {
KONTEN_FEHLER, AUFTRAEGE_FEHLER, ladeAuftraegeAnsicht, ansichtsZustand, kundeMitKundenart, erstelltMeldung, auftragMeldung,
} = await loadModule('src/lib/auftraegeAnsicht.js')
// Antwort von getProjektkonten (V5) mit den Feldern, die die Ansicht braucht
const konten = (extra = {}) => ({
@@ -142,3 +144,44 @@ test('ansichtsZustand: unvollständige Antworten brechen die Ansicht nicht', ()
}
assert.equal(ansichtsZustand({ data: { konten: konten({ stripeOk: false }) }, error: '' }).stripeOk, false)
})
test('kundeMitKundenart: ein gültiger Wert des Portals gewinnt gegen das veraltete Kundendokument', () => {
const doc = { $id: 'k1', name: 'Anelia Wolf', kundenart: '' }
assert.deepEqual(kundeMitKundenart(doc, { id: 'k1', kundenart: 'privat' }), { ...doc, kundenart: 'privat' })
assert.equal(doc.kundenart, '') // das Dokument der Seite wird nicht verändert
assert.equal(kundeMitKundenart({ ...doc, kundenart: 'unternehmen' }, { kundenart: 'privat' }).kundenart, 'privat')
})
test('kundeMitKundenart: ohne gültigen Wert vom Portal bleibt das Dokument (dieselbe Referenz)', () => {
const doc = { $id: 'k1', kundenart: 'unternehmen' }
for (const info of [null, undefined, {}, { kundenart: '' }, { kundenart: 'firma' }, { kundenart: 5 }, 'privat']) {
assert.equal(kundeMitKundenart(doc, info), doc)
}
assert.equal(kundeMitKundenart(null, { kundenart: 'privat' }), null)
})
test('erstelltMeldung: gesendet, Entwurf und die Meldung nach festgeschriebener, nicht gesendeter Rechnung', () => {
assert.deepEqual(
erstelltMeldung({ number: 'WEBKLAR-0009', customerEmail: 'a@b.de' }, { senden: true }),
{ tone: 'ok', text: 'Rechnung WEBKLAR-0009 wurde an a@b.de gesendet.' },
)
assert.deepEqual(erstelltMeldung({ id: 'in_1' }, { senden: false }), { tone: 'ok', text: 'Der Entwurf wurde gespeichert.' })
assert.deepEqual(erstelltMeldung(null, undefined), { tone: 'ok', text: 'Der Entwurf wurde gespeichert.' })
assert.deepEqual(erstelltMeldung(null, null), { tone: 'ok', text: 'Der Entwurf wurde gespeichert.' })
const text = 'Rechnung WEBKLAR-0010 wurde festgeschrieben, aber nicht versendet. Bitte in der Liste erneut senden.'
assert.deepEqual(erstelltMeldung(null, { senden: true, notice: text, tone: 'warn', finalizedFilter: 'offen' }), { tone: 'warn', text })
assert.deepEqual(erstelltMeldung(null, { senden: true, notice: text }), { tone: 'ok', text })
})
test('auftragMeldung: Entwurf, gesendet und gesendet ohne zugestellte Mail', () => {
assert.deepEqual(auftragMeldung({ status: 'entwurf', nummer: '' }), { tone: 'ok', text: 'Der Entwurf wurde gespeichert.' })
assert.deepEqual(
auftragMeldung({ status: 'versendet', nummer: 'AB-2026-0001', gesendetAn: 'k@x.de', mailStatus: 'gesendet' }),
{ tone: 'ok', text: 'Auftragsbestätigung AB-2026-0001 wurde an k@x.de gesendet.' },
)
assert.deepEqual(
auftragMeldung({ status: 'versendet', nummer: 'AB-2026-0001', gesendetAn: 'k@x.de', mailStatus: 'fehler' }),
{ tone: 'warn', text: 'Auftragsbestätigung AB-2026-0001 ist versendet, die Mail an den Kunden wurde aber nicht zugestellt. Bitte in der Liste erneut senden.' },
)
assert.deepEqual(auftragMeldung(null), { tone: 'ok', text: 'Die Auftragsbestätigung wurde gespeichert.' })
})