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

375 lines
20 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 } from 'node:test'
import assert from 'node:assert/strict'
import { startAppwriteMock } from './support/appwriteMock.js'
import { useTestEnv } from './support/testEnv.js'
import { schemaKeys } from './support/schema.js'
// Buchungskalender Task 10: Aufbewahrung, Fristen, Loeschen (aufbewahrung.js, Tagesjob, Kundenloeschung). Die Uhr ist immer ein fester Zeitpunkt.
const NAMEN = ['ukUnterkuenfte', 'ukPreise', 'ukSperren', 'ukAnfragen', 'ukRechnungen', 'ukEinstellungen']
const aw = await startAppwriteMock({
schema: { ...Object.fromEntries(NAMEN.map((n) => [n, schemaKeys(n)])), portalFeatures: schemaKeys('portalFeatures'), termineOutbox: schemaKeys('termineOutbox') },
datetimes: { ukAnfragen: ['fristAt', 'freigegebenAt', 'gebuchtAt', 'abgelehntAt', 'abgelaufenAt', 'storniertAt', 'bezahltAt', 'anonymisiertAt'], termineOutbox: ['naechsterVersuch', 'versendetAt'] },
defaultLimit: 25,
})
after(() => aw.close())
useTestEnv({ appwriteUrl: aw.url, stripeUrl: 'http://127.0.0.1:1/v1' })
const { config } = await import('../server/config.js')
const { deleteDocument, updateDocument } = await import('../server/services/appwriteAdmin.js')
const { anonymisiere, loescheAbgeschaltete, loescheUkDaten, schliesseUkVonKunde } = await import('../server/services/unterkunft/aufbewahrung.js')
const jobs = await import('../server/services/unterkunft/jobs.js')
const mails = await import('../server/services/unterkunft/mails.js')
const { deleteCustomerWithPortalAccess } = await import('../server/services/customerAdmin.js')
const { withLocks } = await import('../server/services/keyedLock.js')
const { raeumeAuf } = await import('../server/services/termine/outbox.js')
const { sendeHinweiseVorLoeschung } = await import('../server/services/unterkunft/abschaltHinweis.js')
const { setMailTransportForTests } = await import('../server/services/mailer.js')
const { mailSink } = await import('./support/mailSink.js')
const TAG = 24 * 3600 * 1000
const JETZT = new Date('2026-10-07T10:00:00.000Z')
const vor = (tage, von = JETZT) => new Date(von.getTime() - tage * TAG).toISOString()
const GAST = { name: 'Eva Gast', firma: '', email: 'eva@example.com', telefon: '0123', nachricht: 'Hallo' }
const ADRESSE = { name: 'Eva Gast', strasse: 'Weg 1', plz: '12345', ort: 'Berlin', land: 'DE' }
let n = 0
const anfrage = (over = {}) => {
const $id = over.$id ?? `a${++n}`
aw.seed('ukAnfragen', { $id, featureId: 'f1', customerId: 'c1', projectId: 'p1', unterkunftId: 'u1', nummer: 'A-' + $id, von: '2026-09-01', bis: '2026-09-05', personen: 2, status: 'neu', gast: JSON.stringify(GAST), nachrichtVermieter: 'Willkommen', ipHash: 'abcd', erstattetCent: 0, ...over })
return $id
}
const holen = (id) => aw.docs('ukAnfragen').get(id)
const gast = (id) => JSON.parse(holen(id).gast)
beforeEach(async () => {
for (const c of [...NAMEN, 'termineOutbox', 'portalFeatures', 'customers', 'websiteProjects']) for (const id of aw.docs(c).keys()) await deleteDocument(c, id)
mails._aufrufe.length = 0
})
test('ipHash: nach 29 Tagen noch da, nach 31 Tagen leer; idempotent', async () => {
const jung = anfrage({ $createdAt: vor(29) })
const alt = anfrage({ $createdAt: vor(31) })
const r = await anonymisiere(JETZT)
assert.equal(r.ipHashes, 1)
assert.equal(holen(jung).ipHash, 'abcd')
assert.equal(holen(alt).ipHash, '')
assert.equal((await anonymisiere(JETZT)).ipHashes, 0)
})
test('neu: nach 59 Tagen bleibt neu, nach 61 Tagen abgelaufen ohne Mail', async () => {
const jung = anfrage({ $createdAt: vor(59) })
const alt = anfrage({ $createdAt: vor(61) })
const entschieden = anfrage({ $createdAt: vor(61), status: 'freigegeben' })
const r = await anonymisiere(JETZT)
assert.equal(r.abgelaufen, 1)
assert.equal(holen(jung).status, 'neu')
assert.equal(holen(alt).status, 'abgelaufen')
assert.ok(Math.abs(Date.parse(holen(alt).abgelaufenAt) - JETZT.getTime()) < 1000)
assert.equal(holen(entschieden).status, 'freigegeben')
assert.equal(mails._aufrufe.length, 0)
})
test('Unverbindliche Anfragen: nach 6 Monaten anonymisiert, knapp davor nicht; storniert ohne Rechnung auch, mit Rechnung nicht', async () => {
const sechs = new Date('2026-04-07T10:00:00.000Z')
const davor = anfrage({ status: 'abgelehnt', $createdAt: new Date(sechs.getTime() + 3600e3).toISOString(), rechnungsadresse: JSON.stringify(ADRESSE) })
const danach = anfrage({ status: 'abgelehnt', $createdAt: new Date(sechs.getTime() - 3600e3).toISOString(), rechnungsadresse: JSON.stringify(ADRESSE) })
const verfallen = anfrage({ status: 'abgelaufen', $createdAt: vor(200) })
const stornoOhne = anfrage({ status: 'storniert', $createdAt: vor(200) })
const stornoMit = anfrage({ status: 'storniert', $createdAt: vor(200), rechnungId: 'r1', rechnungsadresse: JSON.stringify(ADRESSE), bis: '2026-09-05' })
aw.seed('ukRechnungen', { $id: 'r1', featureId: 'f1', anfrageId: stornoMit, art: 'rechnung', nummer: 'R-1', datum: '2026-09-01', bruttoCent: 100, inhalt: '{"x":1}' })
const r = await anonymisiere(JETZT)
assert.equal(r.anfragen, 3)
assert.equal(r.gaeste, 0)
assert.deepEqual(gast(davor), GAST)
for (const id of [danach, verfallen, stornoOhne]) {
const d = holen(id)
assert.deepEqual(JSON.parse(d.gast), {})
assert.equal(d.nachrichtVermieter, '')
assert.equal(d.rechnungsadresse, null)
assert.equal(d.ipHash, '')
assert.ok(d.anonymisiertAt)
}
assert.deepEqual(gast(stornoMit), GAST)
assert.deepEqual(JSON.parse(holen(stornoMit).rechnungsadresse), ADRESSE)
assert.equal((await anonymisiere(JETZT)).anfragen, 0)
})
test('Gebuchte Aufenthalte: Gast weg 3 Jahre nach Jahresende der Abreise (Berlin); Rechnungsadresse und Rechnung bleiben unveraendert', async () => {
const inhalt = JSON.stringify({ gast: ADRESSE, summe: 12345 })
const a = anfrage({ status: 'bezahlt', bis: '2022-12-31', von: '2022-12-28', $createdAt: vor(1500), rechnungsadresse: JSON.stringify(ADRESSE), rechnungId: 'r1', tokenHash: 'abc123' })
const b = anfrage({ status: 'gebucht', bis: '2023-01-02', von: '2022-12-30', $createdAt: vor(1500), rechnungsadresse: JSON.stringify(ADRESSE) })
aw.seed('ukRechnungen', { $id: 'r1', featureId: 'f1', anfrageId: a, art: 'rechnung', nummer: 'R-1', datum: '2022-12-20', bruttoCent: 12345, inhalt })
// 31.12.2025 23:30 Berlin: noch Jahr 2025 -> nichts
assert.equal((await anonymisiere(new Date('2025-12-31T22:30:00Z'))).gaeste, 0)
assert.deepEqual(gast(a), GAST)
// 01.01.2026 00:30 Berlin -> a (Abreise 2022), b (Abreise 2023) noch nicht
const r = await anonymisiere(new Date('2025-12-31T23:30:00Z'))
assert.equal(r.gaeste, 1)
assert.deepEqual(gast(a), {})
assert.ok(holen(a).anonymisiertAt)
assert.equal(holen(a).tokenHash, '', 'Buchungslink tot')
assert.deepEqual(JSON.parse(holen(a).rechnungsadresse), ADRESSE)
assert.deepEqual(gast(b), GAST)
const re = aw.docs('ukRechnungen').get('r1')
assert.equal(re.inhalt, inhalt, 'PDF-Schnappschuss unveraendert')
assert.equal(re.nummer, 'R-1')
assert.equal((await anonymisiere(new Date('2025-12-31T23:30:00Z'))).gaeste, 0)
})
test('Rechnungen: 8 Jahre nach Ende des Rechnungsjahres geloescht, zugleich Rechnungsadresse der Anfrage weg', async () => {
const a = anfrage({ status: 'bezahlt', bis: '2018-05-05', anonymisiertAt: vor(1000), gast: '{}', rechnungsadresse: JSON.stringify(ADRESSE), rechnungId: 'r1' })
aw.seed('ukRechnungen', { $id: 'r1', featureId: 'f1', anfrageId: a, art: 'rechnung', nummer: 'R-1', datum: '2018-05-01', bruttoCent: 1, inhalt: '{}' })
aw.seed('ukRechnungen', { $id: 'r2', featureId: 'f1', anfrageId: a, art: 'storno', nummer: 'S-1', datum: '2019-01-10', bruttoCent: -1, inhalt: '{}' })
// Ende 2026 -> r1 faellig am 01.01.2027; r2 (2019) erst 01.01.2028
assert.equal((await anonymisiere(new Date('2026-12-31T22:30:00Z'))).rechnungen, 0)
const r = await anonymisiere(new Date('2026-12-31T23:30:00Z'))
assert.equal(r.rechnungen, 1)
assert.equal(aw.docs('ukRechnungen').has('r1'), false)
assert.equal(aw.docs('ukRechnungen').has('r2'), true)
assert.deepEqual(JSON.parse(holen(a).rechnungsadresse), ADRESSE, 'noch eine Rechnung der Anfrage uebrig')
const r2 = await anonymisiere(new Date('2027-12-31T23:30:00Z'))
assert.equal(r2.rechnungen, 1)
assert.equal(r2.adressen, 1)
assert.equal(aw.docs('ukRechnungen').size, 0)
assert.equal(holen(a).rechnungsadresse, null)
})
test('Deckel begrenzt die Zahl je Lauf, der Rest folgt am naechsten', async () => {
for (let i = 0; i < 5; i++) anfrage({ $createdAt: vor(40) })
const r1 = await anonymisiere(JETZT, { deckel: 2 })
assert.equal(r1.ipHashes, 2)
assert.equal(r1.gedeckelt, true)
assert.equal((await anonymisiere(JETZT, { deckel: 2 })).ipHashes, 2)
const r3 = await anonymisiere(JETZT, { deckel: 2 })
assert.equal(r3.ipHashes, 1)
assert.equal(r3.gedeckelt, false)
})
test('Logs ohne Personendaten: ein Fehler wird gezaehlt, der Lauf macht weiter', async (t) => {
const log = t.mock.method(console, 'warn', () => {})
const a = anfrage({ $createdAt: vor(40) })
const b = anfrage({ $createdAt: vor(40) })
aw.failNext({ collection: 'ukAnfragen', method: 'PATCH', status: 500, message: 'kaputt eva@example.com' })
const r = await anonymisiere(JETZT)
assert.equal(r.fehler, 1)
assert.equal(r.ipHashes, 1)
assert.deepEqual([holen(a).ipHash, holen(b).ipHash].sort(), ['', 'abcd'])
assert.ok(log.mock.calls.length >= 1)
assert.ok(!JSON.stringify(log.mock.calls.map((c) => c.arguments)).includes('eva@example.com'), 'keine Personendaten im Log')
})
const funktion = (over = {}) => aw.seed('portalFeatures', { $id: 'f1', customerId: 'c1', projectId: 'p1', featureKey: 'unterkunft', siteKey: 'abcdefghijklmnop', state: 'active', enabled: true, ...over })
const datenFuer = (f) => {
aw.seed('ukEinstellungen', { $id: f, featureId: f, firma: 'Haus' })
aw.seed('ukUnterkuenfte', { $id: 'u_' + f, featureId: f, customerId: 'c1', name: 'W', aktiv: true })
aw.seed('ukPreise', { $id: 'p_' + f, unterkunftId: 'u_' + f, featureId: f })
aw.seed('ukSperren', { $id: 's_' + f, unterkunftId: 'u_' + f, featureId: f, von: '2026-12-01', bis: '2026-12-02' })
anfrage({ $id: 'an_' + f, featureId: f })
aw.seed('ukRechnungen', { $id: 're_' + f, featureId: f, anfrageId: 'an_' + f, art: 'rechnung', nummer: 'R', datum: '2026-09-01', bruttoCent: 1, inhalt: '{}' })
}
const anzahl = (f) => NAMEN.reduce((s, c) => s + [...aw.docs(c).values()].filter((d) => d.featureId === f).length, 0)
test('Abgeschaltete Funktion: nach 89 Tagen alles da, nach 91 Tagen alle uk*-Daten weg, Marker gesetzt, Rest unberuehrt, idempotent', async () => {
funktion({ state: 'disabled', enabled: false, disabledAt: vor(89) })
funktion({ $id: 'f2', state: 'disabled', enabled: false, disabledAt: vor(100), siteKey: 'bcdefghijklmnopq' })
funktion({ $id: 'f3', state: 'active' })
for (const f of ['f1', 'f2', 'f3']) datenFuer(f)
let r = await loescheAbgeschaltete(JETZT)
assert.equal(r.funktionen, 1)
assert.equal(anzahl('f1'), 6)
assert.equal(anzahl('f2'), 0)
assert.equal(anzahl('f3'), 6)
assert.match(aw.docs('portalFeatures').get('f2').adminNote, /^Buchungsdaten gelöscht am 2026-10-07/)
r = await loescheAbgeschaltete(JETZT)
assert.equal(r.funktionen, 0)
r = await loescheAbgeschaltete(new Date(JETZT.getTime() + 3 * TAG))
assert.equal(r.funktionen, 1)
assert.equal(anzahl('f1'), 0)
assert.equal(anzahl('f3'), 6)
})
test('K35: einmal pro Abschaltung, mit Loeschdatum, nur mit Daten; Marker; ohne Adresse nur Marker; Fehler wird wiederholt; Tagesjob sendet vor der Loeschung', async () => {
const senke = mailSink()
setMailTransportForTests(senke)
try {
aw.seed('customers', { $id: 'c1', name: 'Mimi', email: 'mimi@example.com' })
aw.seed('websiteProjects', { $id: 'p1', customerId: 'c1', projectName: 'Donau Home' })
funktion({ state: 'disabled', enabled: false, disabledAt: vor(1) })
funktion({ $id: 'f2', state: 'disabled', enabled: false, disabledAt: vor(1), customerId: 'c9' }) // Kunde fehlt
funktion({ $id: 'f3', state: 'disabled', enabled: false, disabledAt: vor(1) }) // ohne Daten
funktion({ $id: 'f4', state: 'active' })
for (const f of ['f1', 'f2', 'f4']) datenFuer(f)
const r = await sendeHinweiseVorLoeschung(JETZT)
assert.deepEqual([r.gesendet, r.ohneAdresse, r.fehler], [1, 1, 0])
assert.equal(senke.sent.length, 1)
const m = senke.sent[0]
assert.equal(m.to[0].address, 'mimi@example.com')
assert.match(m.subject, /Buchungskalender abgeschaltet/)
assert.match(m.text, /Donau Home/)
assert.match(m.text, /04.01.2027/, 'disabledAt + 90 Tage')
assert.match(aw.docs('portalFeatures').get('f1').adminNote, /K35 am 2026-10-07/)
assert.match(aw.docs('portalFeatures').get('f2').adminNote, /K35 am 2026-10-07/)
assert.ok(!aw.docs('portalFeatures').get('f3').adminNote)
assert.ok(!aw.docs('portalFeatures').get('f4').adminNote)
// zweiter Lauf: nichts mehr
assert.equal((await sendeHinweiseVorLoeschung(new Date(JETZT.getTime() + TAG))).gesendet, 0)
assert.equal(senke.sent.length, 1)
// erneut abgeschaltet (alter Marker liegt vor disabledAt): wieder ein Hinweis
await updateDocument(config.collections.portalFeatures, 'f1', { disabledAt: vor(-5) })
assert.equal((await sendeHinweiseVorLoeschung(new Date(JETZT.getTime() + 6 * TAG))).gesendet, 1)
// Versandfehler: kein Marker, naechster Lauf wiederholt
aw.seed('portalFeatures', { ...aw.docs('portalFeatures').get('f3'), adminNote: '' })
datenFuer('f3')
setMailTransportForTests({ async sendMail() { throw new Error('smtp down') } })
const log = console.warn
console.warn = () => {}
const f = await sendeHinweiseVorLoeschung(JETZT)
console.warn = log
assert.equal(f.fehler, 1)
assert.ok(!aw.docs('portalFeatures').get('f3').adminNote)
setMailTransportForTests(senke)
assert.equal((await sendeHinweiseVorLoeschung(JETZT)).gesendet, 1)
} finally {
setMailTransportForTests(null)
}
})
test('K35: Tagesjob schickt den Hinweis und loescht erst nach 90 Tagen', async () => {
const senke = mailSink()
setMailTransportForTests(senke)
try {
aw.seed('customers', { $id: 'c1', name: 'Mimi', email: 'mimi@example.com' })
funktion({ state: 'disabled', enabled: false, disabledAt: vor(3) })
datenFuer('f1')
await jobs.taeglicherJob(JETZT)
assert.equal(senke.sent.length, 1)
assert.equal(anzahl('f1'), 6)
await jobs.taeglicherJob(new Date(JETZT.getTime() + 88 * TAG))
assert.equal(senke.sent.length, 1)
assert.equal(anzahl('f1'), 0)
} finally {
setMailTransportForTests(null)
}
})
test('loescheUkDaten mit Deckel: unvollstaendig, Fortsetzung loescht den Rest', async () => {
datenFuer('f1')
const a = await loescheUkDaten({ featureId: 'f1', deckel: 2 })
assert.equal(a.vollstaendig, false)
assert.equal(a.geloescht, 2)
const b = await loescheUkDaten({ featureId: 'f1', deckel: 100 })
assert.equal(b.vollstaendig, true)
assert.equal(anzahl('f1'), 0)
})
test('Tagesjob: off ohne Daten = aus, mit Daten laeuft er; on fuehrt Aufbewahrung und Loeschung aus', async () => {
const modus = config.unterkunft.mode
try {
config.unterkunft.mode = 'off'
assert.deepEqual(await jobs.taeglicherJob(JETZT), { aus: true })
anfrage({ $createdAt: vor(40) })
const r = await jobs.taeglicherJob(JETZT)
assert.equal(r.aufbewahrung.ipHashes, 1, 'die Fristen gelten auch bei off')
config.unterkunft.mode = 'on'
funktion({ state: 'disabled', enabled: false, disabledAt: vor(120) })
datenFuer('f1')
const r2 = await jobs.taeglicherJob(JETZT)
assert.equal(r2.abgeschaltet.funktionen, 1)
assert.equal(anzahl('f1'), 0)
} finally {
config.unterkunft.mode = modus
}
})
test('Warteschlange: raeumeAuf loescht Eintraege jeder art (auch uk-*) 7 Tage nach Versand bzw. 48 Stunden nach Fehler', async () => {
const eintrag = (id, status, wann) => aw.seed('termineOutbox', { $id: id, featureId: 'f1', art: 'G16', bookingId: 'x', status, naechsterVersuch: wann })
eintrag('o1', 'gesendet', vor(8))
eintrag('o2', 'gesendet', vor(-6))
eintrag('o3', 'fehler', vor(3))
eintrag('o4', 'wartet', vor(10))
assert.equal(await raeumeAuf(JETZT), 2)
assert.deepEqual([...aw.docs('termineOutbox').keys()].sort(), ['o2', 'o4'])
})
test('Kundenloeschung schaltet die Funktion ab, schliesst die Unterkuenfte, Daten bleiben bis zur Frist', async () => {
aw.seed('customers', { $id: 'c1', name: 'Weg', email: 'weg@example.invalid' })
aw.seed('websiteProjects', { $id: 'p1', customerId: 'c1', projectName: 'Haus' })
funktion()
datenFuer('f1')
aw.seed('ukUnterkuenfte', { $id: 'u_fremd', featureId: 'f9', customerId: 'c9', name: 'X', aktiv: true })
await deleteCustomerWithPortalAccess('c1')
const f = aw.docs('portalFeatures').get('f1')
assert.deepEqual([f.state, f.enabled, f.adminNote, f.disabledReason], ['disabled', false, 'Kunde gelöscht', 'kunde_geloescht'])
assert.equal(aw.docs('ukUnterkuenfte').get('u_f1').aktiv, false)
assert.equal(aw.docs('ukUnterkuenfte').get('u_fremd').aktiv, true)
assert.equal(anzahl('f1'), 6)
assert.equal((await loescheAbgeschaltete(new Date(Date.parse(f.disabledAt) + 91 * TAG))).funktionen, 1)
assert.equal(anzahl('f1'), 0)
assert.equal(await schliesseUkVonKunde('c1'), 0)
})
test('Sperre wie ablauf.js: ein Wechsel auf freigegeben unter der Unterkunfts-Sperre wird nicht ueberschrieben', async () => {
const id = anfrage({ $createdAt: vor(61), unterkunftId: 'u1' })
let lauf
await withLocks(['unterkunft:u1'], async () => {
// der Job laeuft an und wartet auf die Sperre; waehrenddessen gibt der Vermieter frei
lauf = anonymisiere(JETZT)
await new Promise((r) => setTimeout(r, 150))
await (await import('../server/services/appwriteAdmin.js')).updateDocument(config.collections.ukAnfragen, id, { status: 'freigegeben' })
})
const r = await lauf
assert.equal(r.abgelaufen, 0)
assert.equal(holen(id).status, 'freigegeben')
})
test('Gebucht ohne jede Rechnung: Rechnungsadresse geht mit den Gastdaten', async () => {
const a = anfrage({ status: 'gebucht', bis: '2022-06-01', rechnungsadresse: JSON.stringify(ADRESSE) })
const r = await anonymisiere(new Date('2026-01-02T10:00:00Z'))
assert.equal(r.gaeste, 1)
assert.deepEqual(gast(a), {})
assert.equal(holen(a).rechnungsadresse, null)
})
test('adminNote: bisheriger Text bleibt vor dem Marker; Wiedereinschalten bricht ab; erneutes Abschalten loescht nach neuen 90 Tagen; aktive Funktion mit altem Marker unberuehrt', async () => {
const sp = await import('../server/services/appwriteAdmin.js')
funktion({ state: 'disabled', enabled: false, disabledAt: vor(100), adminNote: 'Kunde gelöscht' })
datenFuer('f1')
assert.equal((await loescheAbgeschaltete(JETZT)).funktionen, 1)
assert.equal(aw.docs('portalFeatures').get('f1').adminNote, 'Kunde gelöscht – Buchungsdaten gelöscht am 2026-10-07')
// wieder eingeschaltet: nichts wird geloescht
funktion({ $id: 'f4', state: 'disabled', enabled: false, disabledAt: vor(91) })
datenFuer('f4')
await sp.updateDocument(config.collections.portalFeatures, 'f4', { state: 'active', enabled: true })
assert.equal((await loescheAbgeschaltete(JETZT)).funktionen, 0)
assert.equal(anzahl('f4'), 6)
// erneut abgeschaltet (alter Marker steht noch): erst nach neuen 90 Tagen
await sp.updateDocument(config.collections.portalFeatures, 'f4', { adminNote: 'Buchungsdaten gelöscht am 2026-01-01', state: 'disabled', enabled: false, disabledAt: vor(10) })
assert.equal((await loescheAbgeschaltete(JETZT)).funktionen, 0)
assert.equal(anzahl('f4'), 6)
assert.equal((await loescheAbgeschaltete(new Date(JETZT.getTime() + 81 * TAG))).funktionen, 1)
assert.equal(anzahl('f4'), 0)
// aktive Funktion mit altem Marker: unberuehrt
funktion({ $id: 'f5', state: 'active', adminNote: 'Buchungsdaten gelöscht am 2026-01-01' })
datenFuer('f5')
await loescheAbgeschaltete(new Date(JETZT.getTime() + 500 * TAG))
assert.equal(anzahl('f5'), 6)
})
test('Gemeinsamer Deckel: der Tagesjob gibt der Loeschung nur den Rest', async () => {
const modus = config.unterkunft.mode
const alt = config.unterkunft.aufbewahrungDeckel
try {
config.unterkunft.mode = 'on'
config.unterkunft.aufbewahrungDeckel = 3
for (let i = 0; i < 3; i++) anfrage({ $createdAt: vor(40) })
funktion({ state: 'disabled', enabled: false, disabledAt: vor(120) })
datenFuer('f1')
const r = await jobs.taeglicherJob(JETZT)
assert.equal(r.aufbewahrung.verbraucht, 3)
assert.equal(r.abgeschaltet.dokumente, 0)
assert.equal(r.abgeschaltet.gedeckelt, true)
} finally {
config.unterkunft.mode = modus
config.unterkunft.aufbewahrungDeckel = alt
}
})