Kunden-Dashboard: - Tab-Navigation: Projekte | Was wurde gemacht | Rechnungen | Chat - Projekt-Details pro Projekt: letzte Git-Commits (Titel+Beschreibung), Projektgroesse, Datei-Uebersicht (Top-Level aggregiert), Ticket-Arbeiten - Rechnungen: gestylte Liste mit Status-Pillen, Ansehen/Zahlen-Link, PDF-Download ueber Server-Proxy (IDOR-geschuetzt) - Chat mit dem Webklar-Team (Polling, Ungelesen-Badge, viewAs blockiert) Admin-Dashboard: - Chat-Tab: Konversationsliste + Thread + Antwortfeld, Ungelesen-Badge Backend: - giteaAdmin: getRepoInfo, listRepoCommits, getRepoTreeSummary - projectInsights: 5-min-Cache, Invalidierung per Gitea-Webhook - /api/projects/:id/git|files|work mit Ownership-Check (404) - /api/chat/* (Kunde) + /api/portal-admin/chats/* (Admin), portalMessages-Collection - mailer: E-Mail-Benachrichtigung an Admins bei Kundennachricht (15-min-Throttle) - gitWorksheet: dd.mm.yyyy, voller Commit-Body, startTime leer (Zeit-Nachtrag), Auto-Webpage-Ticket bei Push auf Projekt ohne Ticket (ensureProjectTicket) - customerActivity: Git-Push-Eintraege fuer Kunden sichtbar Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
51 lines
1.7 KiB
JavaScript
51 lines
1.7 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Konvertiert startDate/endDate von GIT-Worksheets aus YYYYMMDD nach dd.mm.yyyy
|
|
* (Format der Ticketsystem-SPA). Idempotent.
|
|
* Usage: APPWRITE_API_KEY=... node scripts/migrate-git-worksheet-dates.mjs
|
|
*/
|
|
const endpoint = (process.env.APPWRITE_ENDPOINT || 'https://ticket.webklar.com/v1').replace(/\/$/, '')
|
|
const projectId = process.env.APPWRITE_PROJECT_ID || '6a1058610003c5a13a05'
|
|
const apiKey = process.env.APPWRITE_API_KEY
|
|
const databaseId = process.env.APPWRITE_DATABASE_ID || 'woms-database'
|
|
|
|
if (!apiKey) {
|
|
console.error('APPWRITE_API_KEY erforderlich')
|
|
process.exit(1)
|
|
}
|
|
|
|
const headers = {
|
|
'Content-Type': 'application/json',
|
|
'X-Appwrite-Project': projectId,
|
|
'X-Appwrite-Key': apiKey,
|
|
}
|
|
|
|
function convert(value) {
|
|
const m = String(value || '').match(/^(\d{4})(\d{2})(\d{2})$/)
|
|
return m ? `${m[3]}.${m[2]}.${m[1]}` : null
|
|
}
|
|
|
|
const listUrl = `${endpoint}/databases/${databaseId}/collections/worksheets/documents?queries[]=${encodeURIComponent(
|
|
JSON.stringify({ method: 'limit', values: [500] })
|
|
)}`
|
|
const { documents } = await fetch(listUrl, { headers }).then((r) => r.json())
|
|
|
|
let migrated = 0
|
|
for (const doc of documents || []) {
|
|
const data = {}
|
|
const start = convert(doc.startDate)
|
|
const end = convert(doc.endDate)
|
|
if (start) data.startDate = start
|
|
if (end) data.endDate = end
|
|
if (!Object.keys(data).length) continue
|
|
|
|
await fetch(`${endpoint}/databases/${databaseId}/collections/worksheets/documents/${doc.$id}`, {
|
|
method: 'PATCH',
|
|
headers,
|
|
body: JSON.stringify({ data }),
|
|
})
|
|
migrated += 1
|
|
console.log(`migriert: WSID ${doc.wsid} (${doc.$id}) -> ${data.startDate || doc.startDate}`)
|
|
}
|
|
console.log(`Fertig: ${migrated} Worksheet(s) migriert.`)
|