Kundenansicht P5: Setup-Skript für Kundenart und Einrichtungs-Marker
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c2b7073d99
commit
c5b1333953
4 files changed
+171
-4
No files matched your search
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Kundenansicht neu (Paket P5, Abo-Modell Kern): legt die neuen Attribute an. Der Code schreibt sie nur, wenn ein
|
||||
* Aufrufer die zugehoerigen Parameter uebergibt; ohne dieses Skript bleibt die alte Ansicht unberuehrt.
|
||||
* - featureConsents.kundenart: Kundenart zum Klickzeitpunkt im Nachweis ('privat' | 'unternehmen')
|
||||
* - workorders.einrichtungFuer: Schluessel der Funktion, die das Einrichtungs-Ticket betrifft (laengster: 'unterkunft')
|
||||
* - workorders.einrichtungAbrechnung: 'abo' | 'projekt' | '' (Abrechnung der Einrichtung am Ticket)
|
||||
* - portalFeatures.einrichtungAbrechnung: dieselbe Abrechnung am Funktionsdokument (Nachlegen und Heilen setzen
|
||||
* den Marker am Ticket erneut)
|
||||
* - portalFeatures.unlockedBy: 'kauf' | 'abo' | 'team' | 'projekt' (steht schon im Zeiten-Schema; fehlt es, legt
|
||||
* dieses Skript es an)
|
||||
* Idempotent: Vorhandenes wird uebersprungen. Das Skript loescht nichts und laeuft in Entwicklung und Tests nie
|
||||
* gegen Produktion; dort nur auf Anweisung des Controllers nach OK des Inhabers, vorher immer mit --pruefen.
|
||||
* scripts/setup-abo-collections.mjs, feature-setup.mjs und zeiten-setup.mjs bleiben unveraendert.
|
||||
* Usage:
|
||||
* node scripts/kundenansicht-setup.mjs --pruefen (Alias --check; nur melden, nichts anlegen; Exit 1 bei Luecken)
|
||||
* node scripts/kundenansicht-setup.mjs (Fehlendes anlegen)
|
||||
*
|
||||
* config.js und der Appwrite-Client werden erst in main() geladen: test/support/schema.js importiert die
|
||||
* Attributlisten, bevor die Tests ihre Umgebung (useTestEnv) setzen koennen.
|
||||
*/
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { ZEITEN_FEATURE_ATTRIBUTES } from '../server/services/zeiten/schema.js'
|
||||
|
||||
const str = (key, size) => ({ key, type: 'string', size, required: false })
|
||||
const unlockedBy = ZEITEN_FEATURE_ATTRIBUTES.find((a) => a.key === 'unlockedBy')
|
||||
|
||||
export const KUNDENANSICHT_ATTRIBUTE = {
|
||||
featureConsents: [str('kundenart', 12)],
|
||||
workorders: [str('einrichtungFuer', 16), str('einrichtungAbrechnung', 8)],
|
||||
portalFeatures: [unlockedBy, str('einrichtungAbrechnung', 8)],
|
||||
}
|
||||
|
||||
export async function main({ pruefen = 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 missing = []
|
||||
const plan = []
|
||||
|
||||
// Erst alles pruefen, dann (ohne --pruefen) anlegen, damit --pruefen garantiert nichts veraendert
|
||||
for (const [name, attributes] of Object.entries(KUNDENANSICHT_ATTRIBUTE)) {
|
||||
const id = config.collections[name]
|
||||
const exists = await api.collectionExists(id)
|
||||
if (!exists && !pruefen) throw new Error(`Collection ${id} fehlt – zuerst das jeweilige Setup-Skript ausfuehren`)
|
||||
if (!exists) log(`- ${id} FEHLT`)
|
||||
const have = exists ? new Set((await api.listAttributes(id)).map((a) => a.key)) : new Set()
|
||||
for (const attr of attributes) {
|
||||
if (have.has(attr.key)) log(`= ${id}.${attr.key} (existiert)`)
|
||||
else if (pruefen) log(`- ${id}.${attr.key} FEHLT`)
|
||||
}
|
||||
const absent = attributes.filter((a) => !have.has(a.key))
|
||||
absent.forEach((a) => missing.push({ ...a, collection: id }))
|
||||
plan.push({ id, absent })
|
||||
}
|
||||
|
||||
const result = { missing }
|
||||
if (pruefen) {
|
||||
log(missing.length ? `${missing.length} Eintrag/Eintraege fehlen.` : 'Alles vorhanden.')
|
||||
return result
|
||||
}
|
||||
|
||||
for (const { id, absent } of plan) {
|
||||
for (const attr of absent) {
|
||||
await api.createAttribute(id, attr)
|
||||
log(`+ Attribut ${id}.${attr.key}`)
|
||||
}
|
||||
}
|
||||
for (const { id, absent } of plan) {
|
||||
for (const attr of absent) await api.waitForAttribute(id, attr.key)
|
||||
}
|
||||
log('Fertig.')
|
||||
return result
|
||||
}
|
||||
|
||||
const invokedDirectly = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href
|
||||
if (invokedDirectly) {
|
||||
const pruefen = process.argv.includes('--pruefen') || process.argv.includes('--check')
|
||||
main({ pruefen })
|
||||
.then(({ missing }) => process.exit(pruefen && missing.length ? 1 : 0))
|
||||
.catch((e) => {
|
||||
console.error(e.message)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user