139 lines
4.1 KiB
JavaScript
139 lines
4.1 KiB
JavaScript
export function parseJsonField(v) {
|
|
if (v == null) return undefined;
|
|
if (typeof v === 'object') return v;
|
|
return JSON.parse(v);
|
|
}
|
|
|
|
export function mapMachine(r) {
|
|
const o = {
|
|
id: r.id,
|
|
name: r.name,
|
|
typ: r.typ,
|
|
seriennummer: r.seriennummer,
|
|
standort: r.standort,
|
|
listStatus:
|
|
r.list_status != null && String(r.list_status).trim() !== ''
|
|
? String(r.list_status).trim()
|
|
: '',
|
|
createdAt: r.created_at,
|
|
updatedAt: r.updated_at,
|
|
};
|
|
if (r.extras != null && String(r.extras).trim() !== '') {
|
|
try {
|
|
o.extras =
|
|
typeof r.extras === 'string' ? JSON.parse(r.extras) : r.extras;
|
|
} catch {
|
|
o.extras = null;
|
|
}
|
|
}
|
|
return o;
|
|
}
|
|
|
|
export function mapTicket(r) {
|
|
const machine_row = parseJsonField(r.machine_row);
|
|
const t = {
|
|
id: r.id,
|
|
machineId: r.machine_id,
|
|
title: r.title,
|
|
description: r.description,
|
|
status: r.status,
|
|
priority: r.priority,
|
|
slaDays: r.sla_days != null ? r.sla_days : null,
|
|
slaAnchorAt: r.sla_anchor_at ?? null,
|
|
dueAt: r.sla_due_at ?? null,
|
|
isOverdue: Boolean(r.sla_is_overdue),
|
|
createdAt: r.created_at,
|
|
/** Letzte Änderung: neueres aus Ticket-Zeile oder letztem Event (für Anzeige „Aktualisiert“). */
|
|
updatedAt: r.ticket_last_activity_at ?? r.updated_at,
|
|
};
|
|
if (machine_row) {
|
|
t.machine = mapMachine(machine_row);
|
|
}
|
|
return t;
|
|
}
|
|
|
|
function mapAttachmentRow(a, ticketId) {
|
|
return {
|
|
id: a.id,
|
|
originalName: a.original_name,
|
|
mimeType: a.mime_type ?? null,
|
|
sizeBytes: a.size_bytes,
|
|
createdAt: a.created_at,
|
|
url: `/tickets/${ticketId}/attachments/${a.id}/file`,
|
|
};
|
|
}
|
|
|
|
export function mapEvent(r, attachmentRows = []) {
|
|
const list = Array.isArray(attachmentRows) ? attachmentRows : [];
|
|
return {
|
|
id: r.id,
|
|
ticketId: r.ticket_id,
|
|
type: r.type,
|
|
description: r.description,
|
|
createdAt: r.created_at,
|
|
callbackNumber: r.callback_number ?? null,
|
|
teamviewerId: r.teamviewer_id ?? null,
|
|
articleNumber: r.article_number ?? null,
|
|
remoteDurationSeconds:
|
|
r.remote_duration_seconds != null ? r.remote_duration_seconds : null,
|
|
teamviewerNotes:
|
|
r.teamviewer_notes != null && String(r.teamviewer_notes).trim() !== ''
|
|
? String(r.teamviewer_notes).trim()
|
|
: null,
|
|
attachments: list.map((a) => mapAttachmentRow(a, r.ticket_id)),
|
|
};
|
|
}
|
|
|
|
export function mapPublicUser(r) {
|
|
return {
|
|
id: r.id,
|
|
username: r.username,
|
|
role: r.role,
|
|
active: Boolean(r.active),
|
|
source: r.source,
|
|
ldapDn: r.ldap_dn || null,
|
|
createdAt: r.created_at,
|
|
updatedAt: r.updated_at,
|
|
};
|
|
}
|
|
|
|
/** Spätester Start der Bearbeitungszeit: gespeicherter Anker oder letztes Nutzer-Event (ohne SYSTEM). */
|
|
export const ticketSlaActivityAnchorExpr = `MAX(
|
|
datetime(COALESCE(t.sla_anchor_at, t.created_at)),
|
|
COALESCE(
|
|
(SELECT MAX(datetime(e.created_at)) FROM events e
|
|
WHERE e.ticket_id = t.id AND e.type IN ('NOTE','CALL','REMOTE','PART','ATTACHMENT')),
|
|
datetime(COALESCE(t.sla_anchor_at, t.created_at))
|
|
)
|
|
)`;
|
|
|
|
export const ticketSlaDueExpr = `datetime((${ticketSlaActivityAnchorExpr}), '+' || CAST(COALESCE(t.sla_days, 2) AS TEXT) || ' days')`;
|
|
|
|
/** Spätester Zeitpunkt aus Ticket und Historie (alle Event-Typen). */
|
|
export const ticketLastActivityExpr = `MAX(
|
|
datetime(t.updated_at),
|
|
COALESCE(
|
|
(SELECT MAX(datetime(e.created_at)) FROM events e WHERE e.ticket_id = t.id),
|
|
datetime(t.updated_at)
|
|
)
|
|
)`;
|
|
|
|
export const ticketJoinSelect = `
|
|
SELECT t.*,
|
|
${ticketLastActivityExpr} AS ticket_last_activity_at,
|
|
${ticketSlaDueExpr} AS sla_due_at,
|
|
(CASE WHEN t.status IN ('OPEN','WAITING') AND datetime('now') > ${ticketSlaDueExpr} THEN 1 ELSE 0 END) AS sla_is_overdue,
|
|
json_object(
|
|
'id', m.id,
|
|
'name', m.name,
|
|
'typ', m.typ,
|
|
'seriennummer', m.seriennummer,
|
|
'standort', m.standort,
|
|
'list_status', m.list_status,
|
|
'extras', m.extras,
|
|
'created_at', m.created_at,
|
|
'updated_at', m.updated_at
|
|
) AS machine_row
|
|
FROM tickets t
|
|
JOIN machines m ON m.id = t.machine_id`;
|