Files
Webklar-Kundenbereich/server/services/ticketAdmin.js
T
2026-09-30 18:30:53 +00:00

153 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { config } from '../config.js'
import {
createDocument,
deleteDocument,
getDocument,
listDocuments,
updateDocument,
Query,
ID,
} from './appwriteAdmin.js'
const WOID_BASE = 9999
async function generateNextWoid() {
// Numerisches Maximum ueber alle Tickets - orderDesc('woid') sortiert Strings
// und liefert bei gemischt 5-/6-stelligen WOIDs falsche Ergebnisse.
const docs = await listDocuments(config.collections.workorders, [Query.limit(1000)])
const highest = docs.reduce((max, doc) => {
const n = parseInt(doc.woid, 10)
return Number.isNaN(n) ? max : Math.max(max, n)
}, WOID_BASE)
return String(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
}
/**
* Einrichtungs-Ticket fuer eine gekaufte Funktion (z. B. News-Pinnwand) einer Kundenwebsite.
* Wird geschlossen, sobald die Funktion eingebaut ist; danach schaltet das Portal sie frei.
*/
export async function createFeatureTicket({ customerId, project, featureKey, siteKey }) {
const customer = await getDocument(config.collections.customers, customerId).catch(() => null)
const woid = await generateNextWoid()
const projectName = project?.projectName || project?.subdomain || ''
const domain = project?.liveDomain || project?.previewUrl || project?.subdomain || ''
const embed = `<div data-webklar-news="${siteKey}"></div> + https://project.webklar.com/embed/news.js`
const ticket = await createDocument(
config.collections.workorders,
{
topic: `News-Pinnwand einbauen – ${projectName}`.trim(),
type: 'Webpage',
status: 'Open',
priority: 1,
serviceType: 'Remote',
systemType: 'n/a',
customerId,
customerName: customer?.name || '',
customerLocation: customer?.location || '',
woid,
details: [
`Funktion: ${featureKey}`,
`Projekt: ${projectName}`,
`Domain: ${domain}`,
`siteKey: ${siteKey}`,
`Einbau: ${embed}`,
'Anleitung: docs/funktionen/news-einbau.md (Repo Webklar-Kundenbereich)',
].join('\n'),
createdAt: new Date().toISOString(),
},
ID.unique()
)
console.log(`[ticketAdmin] Funktions-Ticket #${woid} (${featureKey}) fuer Projekt ${project?.$id} angelegt`)
return { ticketId: ticket.$id, woid }
}
/**
* Legt ein Ticket fuer ein Projekt an (Zuordnen-Flow, erst beim Abschliessen).
* Unbekannter Kunde => Fehler mit status 400.
*/
export async function createTicketForProject({ customerId, topic, type, requestedBy, startDate, details }) {
const customer = customerId
? await getDocument(config.collections.customers, customerId).catch(() => null)
: null
if (!customer) {
const err = new Error('Kunde nicht gefunden.')
err.status = 400
throw err
}
const woid = await generateNextWoid()
const ticket = await createDocument(
config.collections.workorders,
{
topic,
type,
status: 'Open',
priority: 1,
serviceType: 'Remote',
systemType: 'n/a',
customerId,
customerName: customer.name || '',
customerLocation: customer.location || '',
requestedBy: requestedBy || '',
startDate: startDate || '',
details: details || '',
woid,
createdAt: new Date().toISOString(),
},
ID.unique()
)
console.log(`[ticketAdmin] Ticket #${woid} fuer Kunde ${customerId} angelegt`)
return { $id: ticket.$id, woid }
}
/** Loescht ein Ticket wieder (Rollback, wenn der Zuordnen-Flow scheitert). */
export async function deleteTicket(ticketId) {
await deleteDocument(config.collections.workorders, ticketId)
}