Abschaltgrund und Loeschfrist in der Funktionsansicht (featureView, frist.js)

featureView liefert zusaetzlich disabledReason, disabledAt und loeschungAm (Berliner
Tag, 30 Tage nach disabledAt); alle drei nur im Zustand disabled, sonst null.
Neu termine/frist.js mit LOESCHFRIST_TAGE, loeschzeit und loeschTag (nur zeit.js/util.js).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-04 13:58:06 +00:00
1 parent 144b053851
commit 35c9800856
4 files changed
+183

No files matched your search

+30
View File
@@ -18,6 +18,7 @@ const { customerCookie, seedFixtures } = await import('./support/fixtures.js')
const { default: funktionenRoutes } = await import('../server/routes/funktionen.js')
const { default: teamRoutes } = await import('../server/routes/team/index.js')
const sf = await import('../server/services/siteFeatures.js')
const { loeschTag } = await import('../server/services/termine/frist.js')
const { deleteCustomerWithPortalAccess } = await import('../server/services/customerAdmin.js')
const app = await startTestApp({ '/api/funktionen': funktionenRoutes, '/api/team': teamRoutes })
@@ -173,10 +174,39 @@ test('GET /api/funktionen: Projekte tragen features.termine und News wie bisher'
const pt2 = body.projects.find((p) => p.projectId === 'pt2')
assert.deepEqual([pt2.features.termine.state, pt2.features.news.state], ['off', 'off'])
assert.deepEqual(Object.keys(pt2.features), ['news', 'termine'])
// Abschaltgrund und Loeschfrist (E2): News ist hier vom Team abgeschaltet, der aktive Terminplaner und das leere Projekt haben nichts
const aus = pt1.features.news
assert.equal(aus.disabledReason, 'team')
assert.ok(Math.abs(Date.parse(aus.disabledAt) - Date.now()) < 60000)
assert.equal(aus.loeschungAm, loeschTag(aus.disabledAt))
for (const view of [pt1.features.termine, pt2.features.news, pt2.features.termine]) {
assert.deepEqual([view.disabledReason, view.disabledAt, view.loeschungAm], [null, null, null])
}
// ohne Sitzung wie bisher gesperrt
assert.equal((await rawGet('/api/funktionen')).status, 401)
})
test('GET /api/funktionen: abgeschalteter Terminplaner nennt Grund, Zeitpunkt und Berliner Loeschtag; Altbestand ohne Grund', async () => {
const projekte = [
['pe2_aboende', { state: 'disabled', enabled: false, disabledReason: 'abo_ende', disabledAt: '2026-10-04T23:30:00.000Z' }],
['pe2_team', { state: 'disabled', enabled: false, disabledReason: 'team', disabledAt: '2026-10-01T10:00:00.000Z' }],
['pe2_alt', { state: 'disabled', enabled: false, disabledAt: '2026-10-01T10:00:00.000Z' }],
['pe2_aktiv', { state: 'active', enabled: true }],
]
for (const [id, felder] of projekte) {
aw.seed('websiteProjects', { $id: id, customerId: 'ce2', projectName: id })
aw.seed('portalFeatures', { $id: `f_${id}_termine`, customerId: 'ce2', projectId: id, featureKey: 'termine', siteKey: 'abcdefghijklmnop', ...felder })
}
const body = await get('/api/funktionen', { cookie: customerCookie('ce2') })
const termine = (id) => body.projects.find((p) => p.projectId === id).features.termine
const felder = (id) => ({ disabledReason: termine(id).disabledReason, disabledAt: termine(id).disabledAt, loeschungAm: termine(id).loeschungAm })
assert.deepEqual(felder('pe2_aboende'), { disabledReason: 'abo_ende', disabledAt: '2026-10-04T23:30:00.000Z', loeschungAm: '2026-11-04' }, 'Berliner Tag, nicht der UTC-Tag 2026-11-03')
assert.deepEqual(felder('pe2_team'), { disabledReason: 'team', disabledAt: '2026-10-01T10:00:00.000Z', loeschungAm: '2026-10-31' })
assert.deepEqual(felder('pe2_alt'), { disabledReason: null, disabledAt: '2026-10-01T10:00:00.000Z', loeschungAm: '2026-10-31' }, 'Altbestand ohne Grund')
assert.deepEqual(felder('pe2_aktiv'), { disabledReason: null, disabledAt: null, loeschungAm: null })
assert.equal(termine('pe2_aboende').state, 'disabled')
})
// --------------------------------------------------------- Kunde loeschen ---
test('Kunde loeschen schaltet seine Terminplaner ab (Notiz Kunde geloescht, Grund kunde_geloescht), nur seine', async () => {
aw.seed('customers', { $id: 'kt1', name: 'Weg Salon', email: 'weg@example.invalid' })