Team-Route für zeiten: Aktivieren läuft über den Gratis-Pfad (einschaltenZeiten, setup, unlockedBy team, Neubau, Einbau-Ticket, keine K24), Abschalten setzt disabled mit Grund team ohne Löschfrist und legt über nachAbschaltung bei geändertem Wochenplan das Ticket "Ersatz-Tabelle aktualisieren" an. PATCH /:customerId/zeiten/team speichert die Team-Einstellungen mit teamVersion. Die Team-Ansicht liefert für zeiten zusätzlich plaene, team, teamVersion und hindernis. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
96 lines
5.0 KiB
JavaScript
96 lines
5.0 KiB
JavaScript
import { config } from '../../config.js'
|
||
import { berlinDateTime } from '../berlinTime.js'
|
||
import { getDocument } from '../appwriteAdmin.js'
|
||
import { createFeatureTicket } from '../ticketAdmin.js'
|
||
import { ersatzHtml, wochenplanHash } from './ersatz.js'
|
||
import { ladeZeiten, setzeErsatzHash } from './speicher.js'
|
||
import { hauptplan } from './zeitlogik.js'
|
||
|
||
/**
|
||
* Nach dem Abschalten von Oeffnungszeiten live (Spec 4.5): steht in den Platzhaltern der Kundenseite noch eine Ersatz-Tabelle, die
|
||
* nicht mehr zum aktuellen Wochenplan passt, bekommt das Team ein WOMS-Ticket "Ersatz-Tabelle aktualisieren - <Projekt>" mit dem
|
||
* aktuellen Ersatz-HTML (gehoert zum enthaltenen Einbau). Ohne Skript zeigt die Seite ab jetzt nur noch diese Tabelle.
|
||
*
|
||
* Aufrufer: die Team-Route (disable) und spaeter der Abo-Abgleich (Abo-Ende). Aufruf NACH dem Speichern des Zustands und ausserhalb
|
||
* jeder Sperre `feature-admin:<projekt>`: das Ticket legt eine Netzwerkanfrage an, und Sperren sind nicht wiederbetretbar.
|
||
*/
|
||
|
||
const THEMA = 'Ersatz-Tabelle aktualisieren'
|
||
|
||
/** Text des Tickets: Kopfzeilen wie bei den Einbau-Tickets, Anlass, Aufgabe und das aktuelle Ersatz-HTML des Hauptplans. */
|
||
function ticketDetails({ doc, project, daten, haupt, now }) {
|
||
const projektName = project?.projectName || project?.subdomain || ''
|
||
const domain = project?.liveDomain || project?.previewUrl || project?.subdomain || ''
|
||
return [
|
||
'Funktion: zeiten',
|
||
`Projekt: ${projektName}`,
|
||
`Domain: ${domain}`,
|
||
`siteKey: ${doc.siteKey ?? ''}`,
|
||
'',
|
||
`Öffnungszeiten live wurde am ${berlinDateTime(now).date} abgeschaltet. Der Wochenplan weicht von der Tabelle ab, die beim Einbau auf die Seite gesetzt wurde (oder der damalige Stand ist nicht bekannt).`,
|
||
'Aufgabe: Auf der Kundenseite in jedem Platzhalter <div data-webklar-zeiten ...> die Tabelle durch die aktuelle ersetzen. Ohne Skript zeigt die Seite nur noch diese Tabelle.',
|
||
'Weitere Pläne: WOMS → Funktionen → Ersatz-HTML kopieren.',
|
||
'',
|
||
haupt.kurz ? `Ersatz-HTML (Hauptplan ${haupt.kurz}):` : 'Ersatz-HTML (Hauptplan):',
|
||
ersatzHtml(daten, haupt),
|
||
].join('\n')
|
||
}
|
||
|
||
/** Das Projekt des Dokuments; ein geloeschtes Projekt (404) ist kein Fehler, der Name fehlt dann im Ticket. */
|
||
async function ladeProjekt(projectId) {
|
||
try {
|
||
return await getDocument(config.collections.websiteProjects, projectId)
|
||
} catch (err) {
|
||
if (err?.status === 404) return null
|
||
throw err
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Pruefen, ob die Ersatz-Tabelle der Seite noch zum Wochenplan passt, und sonst das Ticket anlegen.
|
||
* Ruling R23: ein leerer oder fehlender gemerkter Hash (ersatzHash) gilt als "unbekannt", also wie geaendert, sobald Zeiten da sind
|
||
* (schlimmstenfalls ein unnoetiges Ticket). Nach dem Ticket wird der Hash auf den aktuellen Stand gesetzt: er gehoert dann zur Tabelle,
|
||
* die das Team einsetzt, und ein zweiter Aufruf (Doppelklick, spaeterer Lauf) legt kein zweites Ticket an. Scheitert das Ticket,
|
||
* bleibt der Hash, und der naechste Aufruf versucht es erneut.
|
||
* @param {{ $id: string, customerId?: string, projectId?: string, siteKey?: string }} doc portalFeatures-Dokument der Zeiten
|
||
* (aus disable(): der Stand nach dem Abschalten)
|
||
* @param {{ now?: Date }} [options]
|
||
* @returns {Promise<'angelegt'|'aktuell'|'fehler'>} angelegt: Ticket entstanden; aktuell: nichts zu tun (keine Zeiten oder Hash gleich);
|
||
* fehler: nicht pruefbar oder Ticket nicht angelegt (im Log ohne Kundendaten). Wirft nie.
|
||
*/
|
||
export async function nachAbschaltung(doc, { now = new Date() } = {}) {
|
||
try {
|
||
if (typeof doc?.$id !== 'string' || doc.$id === '') throw new TypeError('Dokument ohne $id')
|
||
const gespeichert = await ladeZeiten(doc.$id)
|
||
const daten = gespeichert?.daten ?? null
|
||
const haupt = hauptplan(daten)
|
||
// ohne Zeiten wurde nie eine Tabelle zum Ersetzen vorbereitet
|
||
if (!haupt) return 'aktuell'
|
||
const hash = wochenplanHash(daten)
|
||
if (gespeichert.ersatzHash !== '' && gespeichert.ersatzHash === hash) return 'aktuell'
|
||
|
||
const project = await ladeProjekt(doc.projectId)
|
||
const projektName = project?.projectName || project?.subdomain || ''
|
||
await createFeatureTicket({
|
||
customerId: doc.customerId,
|
||
project,
|
||
featureKey: 'zeiten',
|
||
siteKey: doc.siteKey,
|
||
topic: projektName ? `${THEMA} – ${projektName}` : THEMA,
|
||
details: ticketDetails({ doc, project, daten, haupt, now }),
|
||
})
|
||
|
||
// Das Ticket steht; scheitert nur das Merken, entsteht beim naechsten Abschalten ein zweites (Log, kein Fehler)
|
||
try {
|
||
await setzeErsatzHash(doc, hash)
|
||
} catch (err) {
|
||
console.error(`[zeiten] Ersatz-Hash für Projekt ${doc.projectId} nach dem Ticket nicht gemerkt: ${err?.name ?? 'Fehler'} ${err?.status ?? ''}`.trim())
|
||
}
|
||
return 'angelegt'
|
||
} catch (err) {
|
||
// nie Kundendaten ins Log: Art und Statuscode, keine Meldung (Appwrite-Meldungen koennen Feldinhalte nennen)
|
||
console.error(`[zeiten] Ersatz-Ticket nach dem Abschalten (Projekt ${doc?.projectId ?? '?'}): ${err?.name ?? 'Fehler'} ${err?.status ?? ''} ${err?.type ?? ''}`.replace(/\s+/g, ' ').trim())
|
||
return 'fehler'
|
||
}
|
||
}
|