- Login: Appwrite-User mit Label 'admin' (Ticketsystem-Mitarbeiter) bekommen eine Admin-Session und landen auf /admin.html - Admin-Dashboard: Statistik-Uebersicht, Projektsuche ueber alle Projekte (inkl. Preview-/Gitea-Links, Vorschau ohne Kunden-Login), Kundenliste mit Portal-Status, letztem Login und Projektanzahl - Kundennummer (code) direkt im Admin-Bereich pflegbar - 'Als Kunde ansehen': Admin sieht das Portal exakt wie der Kunde (Banner mit Rueckweg zur Admin-Uebersicht) - Kunden-Dashboard: neue Bereiche 'Meine Rechnungen' (InvoiceNinja inkl. Link ins Rechnungsportal) und 'Was wurde gemacht' (Tickets + Worksheets aus dem Ticketsystem, ohne interne Akquise-Tickets); Kundennummer im Header - Admin-API /api/portal-admin/* (Session-basiert), Kunden-API /api/invoices und /api/activity - appwriteClient: uebrig gebliebene Debug-Instrumentierung entfernt Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
58 lines
1.8 KiB
JavaScript
58 lines
1.8 KiB
JavaScript
import { config } from '../config.js'
|
|
import { listDocuments, Query } from './appwriteAdmin.js'
|
|
|
|
/**
|
|
* Tickets + zugehoerige Worksheets eines Kunden ("was wurde gemacht").
|
|
* excludeTypes: Ticket-Typen, die der Kunde nicht sehen soll (z. B. Akquise).
|
|
*/
|
|
export async function getCustomerActivity(customerId, { ticketLimit = 25, excludeTypes = [] } = {}) {
|
|
if (!customerId) return []
|
|
|
|
let workorders = await listDocuments(config.collections.workorders, [
|
|
Query.equal('customerId', customerId),
|
|
Query.orderDesc('$createdAt'),
|
|
Query.limit(ticketLimit),
|
|
])
|
|
|
|
if (excludeTypes.length) {
|
|
const blocked = new Set(excludeTypes.map((t) => t.toLowerCase()))
|
|
workorders = workorders.filter((w) => !blocked.has(String(w.type || '').toLowerCase()))
|
|
}
|
|
|
|
const ids = workorders.map((w) => w.$id)
|
|
let worksheets = []
|
|
if (ids.length) {
|
|
worksheets = await listDocuments(config.collections.worksheets, [
|
|
Query.equal('workorderId', ids),
|
|
Query.orderDesc('$createdAt'),
|
|
Query.limit(300),
|
|
]).catch(() => [])
|
|
}
|
|
|
|
const sheetsByWorkorder = {}
|
|
for (const ws of worksheets) {
|
|
if (ws.isComment) continue
|
|
const list = (sheetsByWorkorder[ws.workorderId] ||= [])
|
|
list.push({
|
|
wsid: ws.wsid || '',
|
|
employeeName: ws.employeeName || ws.employeeShort || '',
|
|
serviceType: ws.serviceType || '',
|
|
newStatus: ws.newStatus || '',
|
|
totalTime: ws.totalTime || '',
|
|
date: ws.endDate || ws.startDate || '',
|
|
details: ws.details || '',
|
|
createdAt: ws.createdAt || ws.$createdAt || '',
|
|
})
|
|
}
|
|
|
|
return workorders.map((w) => ({
|
|
id: w.$id,
|
|
woid: w.woid || '',
|
|
topic: w.topic || w.title || '',
|
|
status: w.status || '',
|
|
type: w.type || '',
|
|
createdAt: w.createdAt || w.$createdAt || '',
|
|
worksheets: (sheetsByWorkorder[w.$id] || []).slice(0, 20),
|
|
}))
|
|
}
|