Kundenansicht neu E-Fix F4: Team-Wiedereinschalten ohne gesendete Abrechnung nimmt die gespeicherte (Aufbauphase)

WOMS fragt nach einer Team-Sperre die Abrechnung nicht mehr ab und sendet keine; der Server setzte dann pauschal 'abo', pruefeAboDeckung warf
409 abo_fehlt, und eine in der Aufbauphase ('projekt', noch kein Abo) eingebaute Funktion liess sich nicht wieder einschalten.
Jetzt gilt bei disabled/team die am Dokument gespeicherte einrichtungAbrechnung, sonst wie bisher 'abo'; eine ausdrücklich gesendete
Abrechnung geht vor. Test in funktionenAdminAbo.test.js (Aufbauphase: ein, aus, ohne Angabe wieder ein = 200 mit warnung; mit abo hart).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-16 21:32:28 +00:00
1 parent 3962074af6
commit 9c04f806eb
2 files changed
+29 -1

No files matched your search

+11 -1
View File
@@ -340,6 +340,16 @@ async function zeitenAbschalten({ customerId, projectId, by, note }) {
const ACTIONS = ['activate', 'disable', 'abnahme', 'ticket']
const TICKET_ACTIONS = ['abnahme', 'ticket']
/**
* Abrechnung, wenn das Team keine sendet: 'abo'. Ausnahme (E-Fix F4): ein vom Team abgeschaltetes Dokument (disabled, disabledReason team) mit gespeicherter
* einrichtungAbrechnung behält sie. WOMS fragt nach einer Team-Sperre nicht mehr nach der Abrechnung (sie steht schon) und sendet keine; ein pauschales 'abo'
* ließe das Wiedereinschalten einer in der Aufbauphase ('projekt', noch kein Abo) eingebauten Funktion an abo_fehlt scheitern.
*/
async function vorgabeAbrechnung(customerId, projectId, key) {
const vorab = await getFeatureDoc(customerId, projectId, key)
return vorab?.state === 'disabled' && vorab.disabledReason === 'team' && ABRECHNUNGEN.includes(vorab.einrichtungAbrechnung) ? vorab.einrichtungAbrechnung : 'abo'
}
funktionenAdminRouter.post('/:customerId/:key', async (req, res) => {
try {
const { customerId, key } = req.params
@@ -362,7 +372,7 @@ funktionenAdminRouter.post('/:customerId/:key', async (req, res) => {
const modell = action === 'activate' && (await aboModellFuerKunde(customerId))
let abrechnung = null
if (modell) {
abrechnung = req.body?.abrechnung === undefined ? 'abo' : req.body.abrechnung
abrechnung = req.body?.abrechnung === undefined ? await vorgabeAbrechnung(customerId, projectId, key) : req.body.abrechnung
if (!ABRECHNUNGEN.includes(abrechnung)) return res.status(400).json({ error: 'Unbekannte Abrechnung' })
}
const rueckmeldung = {} // adminActivate meldet hier die Warnung der Aufbauphase (abo_fehlt)
+18
View File
@@ -104,6 +104,24 @@ test('Bestand und vom Team abgeschaltet: kauf wie heute, disabled/team direkt ak
assert.equal((await go('c1', 'shop')).body.code, 'abo_fehlt'); aw.seed('subscriptions', subscriptionDoc('sub_h', wartungDoc))
assert.equal((await go('c1', 'shop')).status, 200); assert.deepEqual([feat('shop').state, aw.docs('workorders').size], ['active', 0])
})
test('Wiedereinschalten nach Team-Sperre ohne gesendete abrechnung: die am Dokument gespeicherte Abrechnung gilt, nicht pauschal abo (F4)', async () => {
// Aufbauphase: der Kunde hatte nie ein Abo, das Team schaltet den Webshop 'im Projekt enthalten' ein, ab und wieder ein; WOMS fragt nach einer
// Team-Sperre die Abrechnung nicht mehr ab (die Abrechnung steht schon) und sendet keine abrechnung
await leere('subscriptions')
const an = await go('c1', 'shop', { abrechnung: 'projekt' }); assert.deepEqual([an.status, an.body.warnung], [200, 'abo_fehlt'], JSON.stringify(an.body))
const aus = await go('c1', 'shop', { action: 'disable' }); assert.equal(aus.status, 200, JSON.stringify(aus.body))
assert.deepEqual([feat('shop').state, feat('shop').disabledReason, feat('shop').einrichtungAbrechnung], ['disabled', 'team', 'projekt'])
const wieder = await go('c1', 'shop'); assert.equal(wieder.status, 200, JSON.stringify(wieder.body))
assert.deepEqual([wieder.body.warnung, wieder.body.grund, feat('shop').state], ['abo_fehlt', 'kein_abo', 'active'])
// wieder aus; eine ausdrücklich gesendete Abrechnung gilt vor der gespeicherten: abo ohne Abo bleibt hart
assert.equal((await go('c1', 'shop', { action: 'disable' })).status, 200)
const hart = await go('c1', 'shop', { abrechnung: 'abo' }); assert.deepEqual([hart.status, hart.body.code, hart.body.grund], [409, 'abo_fehlt', 'kein_abo']); assert.equal(feat('shop').state, 'disabled')
// gespeichert abo (oder ohne Angabe): ohne gesendete Abrechnung gilt abo wie bisher
await updateDocument('portalFeatures', 'f_p1_shop', { einrichtungAbrechnung: 'abo', unlockedBy: 'abo' })
const abo = await go('c1', 'shop'); assert.deepEqual([abo.status, abo.body.code, abo.body.grund], [409, 'abo_fehlt', 'kein_abo'])
await updateDocument('portalFeatures', 'f_p1_shop', { einrichtungAbrechnung: '' })
assert.equal((await go('c1', 'shop')).body.code, 'abo_fehlt')
})
test('Textform: Nachweis vor dem Zustand, K38 mit PDF-Anhängen, kein K16; Aktion ticket legt das Ticket ohne Stripe nach', async () => {
config.shop.mode = 'on'; config.shop.pilotEmails = []
const text = { textformDate: '2026-10-10', textformChannel: 'whatsapp' }