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:
1 parent
312705efc4
commit
e1c9b57249
2 files changed
+82
-1
No files matched your search
@@ -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.' }
|
||||
}
|
||||
@@ -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.' })
|
||||
})
|
||||
Reference in new issue
Block a user