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>
66 lines
2.0 KiB
JavaScript
66 lines
2.0 KiB
JavaScript
import { config } from '../config.js'
|
|
import {
|
|
createDocument,
|
|
getDocument,
|
|
listDocuments,
|
|
updateDocument,
|
|
Query,
|
|
ID,
|
|
} from './appwriteAdmin.js'
|
|
|
|
const WOID_BASE = 9999
|
|
|
|
async function generateNextWoid() {
|
|
const docs = await listDocuments(config.collections.workorders, [
|
|
Query.orderDesc('woid'),
|
|
Query.limit(1),
|
|
])
|
|
const highest = docs[0]?.woid ? parseInt(docs[0].woid, 10) : WOID_BASE
|
|
return String(Math.max(WOID_BASE, highest) + 1)
|
|
}
|
|
|
|
/**
|
|
* Stellt sicher, dass ein Website-Projekt ein Ticket hat, damit Git-Pushes
|
|
* als Worksheets (WSIDs) getrackt werden koennen. Legt bei Bedarf automatisch
|
|
* ein 'Webpage'-Ticket fuer den Kunden des Projekts an und verknuepft es.
|
|
* Projekte ohne Kunde bekommen kein automatisches Ticket.
|
|
*/
|
|
export async function ensureProjectTicket(project, { repoFullName } = {}) {
|
|
if (!project) return null
|
|
if (project.ticketId) return project.ticketId
|
|
if (!project.customerId) return null
|
|
|
|
const customer = await getDocument(config.collections.customers, project.customerId).catch(() => null)
|
|
if (!customer) return null
|
|
|
|
const woid = await generateNextWoid()
|
|
const now = new Date().toISOString()
|
|
|
|
const ticket = await createDocument(
|
|
config.collections.workorders,
|
|
{
|
|
topic: `Website ${project.projectName || repoFullName || project.subdomain || ''}`.trim(),
|
|
type: 'Webpage',
|
|
status: 'Open',
|
|
priority: 1,
|
|
serviceType: 'Remote',
|
|
systemType: 'n/a',
|
|
customerId: project.customerId,
|
|
customerName: customer.name || '',
|
|
customerLocation: customer.location || '',
|
|
woid,
|
|
details: `Automatisch angelegt fuer das Repository ${repoFullName || project.repoFullName || ''} (erster Git-Push).`,
|
|
createdAt: now,
|
|
},
|
|
ID.unique()
|
|
)
|
|
|
|
await updateDocument(config.collections.websiteProjects, project.$id, {
|
|
ticketId: ticket.$id,
|
|
updatedAt: now,
|
|
})
|
|
|
|
console.log(`[ticketAdmin] Webpage-Ticket #${woid} fuer Projekt ${project.$id} angelegt`)
|
|
return ticket.$id
|
|
}
|