Files
Webklar-Kundenbereich/test/auftraegeSenden.test.js
T

117 lines
7.0 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.
import { test, after, beforeEach, mock } from 'node:test'
import assert from 'node:assert/strict'
import fs from 'node:fs'
import path from 'node:path'
import {
starteUmgebung, KUNDE_ID, VON, MELDUNG, festpreisEingabe, kundeDoc, baueDeps, sha256, abgelehnt,
ergebnis, tor, warte, wartebis, dateienIn,
} from './helpers/auftraegeAb.js'
const umg = await starteUmgebung()
const { aw, config, uploadDir } = umg
after(() => umg.schliesse())
beforeEach(umg.zuruecksetzen)
const { deleteDocument } = await import('../server/services/appwriteAdmin.js')
const { getAuftrag, listAuftraege, updateAuftrag } = await import('../server/services/auftraege/auftragStore.js')
const { lesePdf } = await import('../server/services/auftraege/ablage.js')
const { kundeSnapshot } = await import('../server/services/auftraege/auftragSicht.js')
const { TEXTE_FASSUNG } = await import('../server/services/auftraege/texte.js')
const { AGB_FASSUNG, TOKEN_GUELTIG_TAGE } = await import('../server/services/auftraege/konstanten.js')
const { AuftragError } = await import('../server/services/auftraege/fehler.js')
const { legeEntwurfAn, aendereEntwurf, loescheEntwurf, sendeAuftrag } = await import('../server/services/auftraege/auftraege.js')
const JETZT = new Date('2026-10-06T10:00:00Z') // Berlin: 12:00
const neuerEntwurf = (patch) => legeEntwurfAn(festpreisEingabe(patch), { von: VON })
const sende = (id, deps, extra = {}) => sendeAuftrag(id, { von: VON, deps, jetzt: JETZT, ...extra })
const VOR_DER_NUMMER = [
['Interessent', { customerStatus: 'lead' }, 400, MELDUNG.keinFesterKunde],
['verlorener Kunde (Schreibweise egal)', { customerStatus: ' Lost ' }, 400, MELDUNG.keinFesterKunde],
['Kundenart fehlt', { kundenart: '' }, 400, MELDUNG.keineKundenart],
['Kundenart unbekannt', { kundenart: 'firma' }, 400, MELDUNG.keineKundenart],
['E-Mail fehlt', { email: '' }, 400, MELDUNG.keineMail],
['E-Mail nur Leerzeichen', { email: ' ' }, 400, MELDUNG.keineMail],
['Straße fehlt', { street: '' }, 409, MELDUNG.adresse],
['PLZ nur Leerzeichen', { postalCode: ' ' }, 409, MELDUNG.adresse],
['Ort fehlt', { city: '' }, 409, MELDUNG.adresse],
['Interessent hat Vorrang vor allem anderen', { customerStatus: 'lead', kundenart: '', email: '', street: '' }, 400, MELDUNG.keinFesterKunde],
['Kundenart kommt vor E-Mail und Anschrift', { kundenart: '', email: '', street: '' }, 400, MELDUNG.keineKundenart],
['E-Mail kommt vor der Anschrift', { email: '', street: '' }, 400, MELDUNG.keineMail],
]
test('Senden: unvollständige Kundendaten werden vor der Nummer abgelehnt – nichts wird erzeugt, gespeichert oder verbraucht', async () => {
const entwurf = await neuerEntwurf()
const { deps, calls } = baueDeps()
for (const [name, patch, status, meldung] of VOR_DER_NUMMER) {
aw.seed(config.collections.customers, kundeDoc(patch))
await abgelehnt(sende(entwurf.id, deps), status, meldung, name)
}
assert.deepEqual([calls.pdf.length, calls.token.length, calls.mail.length], [0, 0, 0])
assert.deepEqual(dateienIn(uploadDir), [])
const unveraendert = await getAuftrag(entwurf.id)
assert.deepEqual([unveraendert.status, unveraendert.nummer, unveraendert.jahr], ['entwurf', '', null])
aw.seed(config.collections.customers, kundeDoc()) // der Kunde ist wieder vollständig: die erste echte Nummer ist 0001
assert.equal((await sende(entwurf.id, deps)).auftrag.nummer, 'AB-2026-0001')
})
test('Senden: der Entwurf wird vor der Nummer noch einmal geprüft (beschädigte Daten ergeben die Feldmeldung)', async () => {
const entwurf = await neuerEntwurf()
await updateAuftrag(entwurf.id, { positionen: [] })
await abgelehnt(sende(entwurf.id, baueDeps().deps), 400, MELDUNG.positionen)
})
test('Senden: Nummer, eingefrorener Kunde, PDF mit Prüfsumme, Token und Mail', async () => {
aw.seed(config.collections.financeSettings, { $id: 'main', steuernummer: '12/345/67890', bankDetailsText: 'IBAN DE00 0000 0000 0000 0000 00' })
const entwurf = await neuerEntwurf()
const { deps, calls } = baueDeps()
const { auftrag, mailFehler } = await sende(entwurf.id, deps)
assert.equal(mailFehler, false)
assert.deepEqual([auftrag.id, auftrag.status, auftrag.nummer, auftrag.jahr, auftrag.laufnummer], [entwurf.id, 'versendet', 'AB-2026-0001', 2026, 1])
assert.equal(new Date(auftrag.gesendetAm).getTime(), JETZT.getTime())
assert.equal(auftrag.gesendetAn, 'anna@example.invalid')
assert.deepEqual(auftrag.kunde, kundeSnapshot(kundeDoc()))
assert.equal(auftrag.kunde.kundenart, 'unternehmen')
assert.deepEqual([auftrag.texteFassung, auftrag.agbFassung], [TEXTE_FASSUNG, AGB_FASSUNG])
assert.deepEqual([auftrag.mailStatus, auftrag.mailFehler], ['gesendet', ''])
// PDF: einmal mit der Nummer und dem Kunden-Schnappschuss erzeugt, abgelegt, Prüfsumme gespeichert
const pdf = Buffer.from('%PDF-1.4 AB-2026-0001')
assert.equal(calls.pdf.length, 1)
assert.equal(calls.pdf[0].auftrag.nummer, 'AB-2026-0001')
assert.deepEqual(calls.pdf[0].auftrag.kunde, kundeSnapshot(kundeDoc()))
assert.deepEqual(calls.pdf[0].optionen, { settings: { steuernummer: '12/345/67890', bankDetailsText: 'IBAN DE00 0000 0000 0000 0000 00' } })
assert.equal(auftrag.pdfDatei, `${KUNDE_ID}/${entwurf.id}.pdf`)
assert.equal(auftrag.pdfSha256, sha256(pdf))
assert.deepEqual(await lesePdf(auftrag.pdfDatei), pdf)
// Token: im Dokument nur der Hash, 60 Tage gültig ab dem Versand
assert.equal(calls.token.length, 1)
assert.equal(auftrag.tokenHash, sha256(calls.token[0]))
assert.equal(new Date(auftrag.tokenGueltigBis).getTime(), JETZT.getTime() + TOKEN_GUELTIG_TAGE * 86_400_000)
// Mail: einmal, mit dem gespeicherten Dokument, dem PDF und dem Klartext-Token
assert.equal(calls.mail.length, 1)
assert.equal(calls.mail[0].auftrag.nummer, 'AB-2026-0001')
assert.deepEqual(calls.mail[0].pdf, pdf)
assert.deepEqual([calls.mail[0].token, calls.mail[0].erinnerung], [calls.token[0], false])
assert.deepEqual(await getAuftrag(entwurf.id), auftrag)
})
test('Senden: Nummern zählen fortlaufend, im neuen Berliner Jahr beginnt wieder 0001', async () => {
const { deps } = baueDeps()
const nummern = []
for (let i = 0; i < 2; i += 1) nummern.push((await sende((await neuerEntwurf()).id, deps)).auftrag.nummer)
const neujahr = await sende((await neuerEntwurf()).id, deps, { jetzt: new Date('2026-12-31T23:30:00Z') })
assert.deepEqual(nummern, ['AB-2026-0001', 'AB-2026-0002'])
assert.deepEqual([neujahr.auftrag.nummer, neujahr.auftrag.jahr, neujahr.auftrag.laufnummer], ['AB-2027-0001', 2027, 1])
assert.equal(new Date(neujahr.auftrag.gesendetAm).toISOString(), '2026-12-31T23:30:00.000Z')
})
test('Senden: nur Entwürfe (409), unbekannte Aufträge (404) und Kunden (404)', async () => {
const { deps } = baueDeps()
const entwurf = await neuerEntwurf()
await sende(entwurf.id, deps)
await abgelehnt(sende(entwurf.id, deps), 409, MELDUNG.nurEntwurfSenden)
await abgelehnt(sende('a_gibtsnicht', deps), 404, MELDUNG.auftragFehlt)
const zweiter = await neuerEntwurf()
await deleteDocument(config.collections.customers, KUNDE_ID)
await abgelehnt(sende(zweiter.id, deps), 404, MELDUNG.kundeFehlt)
})