Funktionen: disable() idempotent, disabledReason, Schema-Skript feature-setup
disable() laeuft unter einer Sperre je Dokument und aendert ein schon
abgeschaltetes Dokument nicht mehr (disabledAt als Beginn der 30-Tage-Frist,
Grund und Notiz bleiben); nur Altbestand ohne disabledAt bekommt dieses Feld.
Neu: DISABLED_REASONS und der Parameter reason (Vorgabe team, unbekannt = 400),
disableCustomerFeatures reicht ihn durch, die Kundenloeschung nutzt
kunde_geloescht. activate() leert zusaetzlich disabledReason und aboEndeMailAt
und laesst zahlungMeldung unberuehrt.
scripts/feature-setup.mjs legt portalFeatures.disabledReason, aboEndeMailAt und
zahlungMeldung idempotent an (--check meldet Luecken mit Exit 1);
schemaKeys('portalFeatures') zieht die Schluessel mit.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
39225594e5
commit
aaed273b62
9 files changed
+472
-18
No files matched your search
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Portal-Funktionen (News, Terminplaner): legt die Attribute an der Collection portalFeatures an, die der
|
||||
* Verkauf des Terminplaners braucht (Abschaltgrund, Marker der Abo-Ende-Mail, Marker der Zahlungsmeldung).
|
||||
* Idempotent: Vorhandenes wird uebersprungen. Vor dem Code-Deploy ausfuehren (activate() schreibt die neuen
|
||||
* Felder; ohne Schema antwortet Appwrite mit "Unknown attribute").
|
||||
* scripts/setup-abo-collections.mjs bleibt unveraendert (Top-Level-Skript ohne Pruefmodus).
|
||||
* Usage:
|
||||
* node scripts/feature-setup.mjs --check (nur melden, nichts anlegen; Exit-Code 1 bei Luecken)
|
||||
* node scripts/feature-setup.mjs (Fehlendes anlegen)
|
||||
*
|
||||
* config.js und der Appwrite-Client werden erst in main() geladen: test/support/schema.js importiert die
|
||||
* Attributliste, bevor die Tests ihre Umgebung (useTestEnv) setzen koennen.
|
||||
*/
|
||||
import { pathToFileURL } from 'node:url'
|
||||
|
||||
/**
|
||||
* Neue Attribute von portalFeatures (alle optional):
|
||||
* - disabledReason: 'team' | 'abo_ende' | 'abo_ende_vor_einrichtung' | 'kunde_geloescht' (laengster Wert 24 Zeichen)
|
||||
* - aboEndeMailAt: Zeitpunkt der versandten Mail "Terminplaner beendet" (Marker, nach dem Versand gesetzt)
|
||||
* - zahlungMeldung: '' | 'bereits_aktiv' | 'abgeschaltet' | 'abo_ende' | 'gemeldet' (Marker einer Zahlung ohne Ticket)
|
||||
*/
|
||||
export const PORTAL_FEATURE_ATTRIBUTES = [
|
||||
{ type: 'string', key: 'disabledReason', size: 32, required: false },
|
||||
{ type: 'datetime', key: 'aboEndeMailAt', required: false },
|
||||
{ type: 'string', key: 'zahlungMeldung', size: 24, required: false },
|
||||
]
|
||||
|
||||
export async function main({ check = false, client, log = console.log } = {}) {
|
||||
const { config } = await import('../server/config.js')
|
||||
let api = client
|
||||
if (!api) {
|
||||
const { createAppwriteClient } = await import('./analyse-setup.mjs')
|
||||
api = createAppwriteClient()
|
||||
}
|
||||
const featuresId = config.collections.portalFeatures
|
||||
const missing = []
|
||||
|
||||
// Attribute einer Collection abgleichen: meldet Vorhandenes bzw. (mit --check) jede Luecke und liefert die fehlenden
|
||||
async function syncAttributes(collectionId, attributes) {
|
||||
const have = new Set((await api.listAttributes(collectionId)).map((a) => a.key))
|
||||
for (const attr of attributes) {
|
||||
if (have.has(attr.key)) log(`= ${collectionId}.${attr.key} (existiert)`)
|
||||
else if (check) log(`- ${collectionId}.${attr.key} FEHLT`)
|
||||
}
|
||||
return attributes.filter((a) => !have.has(a.key))
|
||||
}
|
||||
|
||||
const featureAbsent = await syncAttributes(featuresId, PORTAL_FEATURE_ATTRIBUTES)
|
||||
featureAbsent.forEach((a) => missing.push({ ...a, collection: featuresId }))
|
||||
|
||||
if (check) {
|
||||
log(missing.length ? `${missing.length} Eintrag/Eintraege fehlen.` : 'Alles vorhanden.')
|
||||
return { missing }
|
||||
}
|
||||
|
||||
for (const attr of featureAbsent) {
|
||||
await api.createAttribute(featuresId, attr)
|
||||
log(`+ Attribut ${featuresId}.${attr.key}`)
|
||||
}
|
||||
for (const attr of featureAbsent) await api.waitForAttribute(featuresId, attr.key)
|
||||
log('Fertig.')
|
||||
return { missing }
|
||||
}
|
||||
|
||||
const invokedDirectly = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href
|
||||
if (invokedDirectly) {
|
||||
const check = process.argv.includes('--check')
|
||||
main({ check })
|
||||
.then(({ missing }) => process.exit(check && missing.length ? 1 : 0))
|
||||
.catch((e) => {
|
||||
console.error(e.message)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user