106 lines
3.4 KiB
JavaScript
106 lines
3.4 KiB
JavaScript
import { randomUUID } from 'crypto';
|
|
import db from '../../db.js';
|
|
import { requireCrmEdit } from '../../middleware/auth.js';
|
|
import { badRequest } from '../../lib/http.js';
|
|
import { mapEvent } from '../../lib/mappers.js';
|
|
import { computeRemoteDurationSeconds } from '../../teamviewer.js';
|
|
|
|
const EVENT_TYPES_USER = new Set(['NOTE', 'CALL', 'REMOTE', 'PART']);
|
|
|
|
export function registerEventRoutes(api) {
|
|
api.post('/events', requireCrmEdit, (req, res) => {
|
|
const b = req.body || {};
|
|
const ticketId = b.ticketId;
|
|
const type = b.type;
|
|
if (!ticketId || !type || !EVENT_TYPES_USER.has(type)) {
|
|
return badRequest(res, 'Pflichtfelder fehlen oder ungültiger Typ.');
|
|
}
|
|
const t = db
|
|
.prepare('SELECT 1 AS ok FROM tickets WHERE id = ?')
|
|
.get(ticketId);
|
|
if (!t) return res.status(404).json({ message: 'Nicht gefunden' });
|
|
|
|
const desc = b.description != null ? String(b.description).trim() : '';
|
|
const callbackNumber =
|
|
b.callbackNumber != null ? String(b.callbackNumber).trim() : '';
|
|
const teamviewerId =
|
|
b.teamviewerId != null ? String(b.teamviewerId).trim() : '';
|
|
const articleNumber =
|
|
b.articleNumber != null ? String(b.articleNumber).trim() : '';
|
|
|
|
let description = desc;
|
|
let cb = callbackNumber || null;
|
|
let tv = teamviewerId || null;
|
|
let art = articleNumber || null;
|
|
|
|
if (type === 'NOTE') {
|
|
if (!description) return badRequest(res, 'Beschreibung fehlt.');
|
|
cb = null;
|
|
tv = null;
|
|
art = null;
|
|
} else if (type === 'CALL') {
|
|
// Rückrufnummer optional; nur Beschreibung ist Pflicht.
|
|
if (!description) return badRequest(res, 'Beschreibung fehlt.');
|
|
tv = null;
|
|
art = null;
|
|
} else if (type === 'REMOTE') {
|
|
if (!description?.trim() && !tv) {
|
|
return badRequest(res, 'Beschreibung oder TeamViewer-Gerät erforderlich.');
|
|
}
|
|
cb = null;
|
|
art = null;
|
|
} else if (type === 'PART') {
|
|
if (!articleNumber) return badRequest(res, 'Artikelnummer fehlt.');
|
|
description = desc;
|
|
cb = null;
|
|
tv = null;
|
|
}
|
|
|
|
let remoteDurationSeconds = null;
|
|
let teamviewerNotes = null;
|
|
if (type === 'REMOTE') {
|
|
remoteDurationSeconds = computeRemoteDurationSeconds(
|
|
b.teamviewerStartDate,
|
|
b.teamviewerEndDate,
|
|
);
|
|
const tn =
|
|
b.teamviewerNotes != null ? String(b.teamviewerNotes).trim() : '';
|
|
teamviewerNotes = tn || null;
|
|
}
|
|
|
|
const eid = randomUUID();
|
|
|
|
db.exec('BEGIN');
|
|
try {
|
|
const row = db
|
|
.prepare(
|
|
`INSERT INTO events (id, ticket_id, type, description, callback_number, teamviewer_id, article_number, remote_duration_seconds, teamviewer_notes)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`,
|
|
)
|
|
.get(
|
|
eid,
|
|
ticketId,
|
|
type,
|
|
description,
|
|
cb,
|
|
tv,
|
|
art,
|
|
remoteDurationSeconds,
|
|
teamviewerNotes,
|
|
);
|
|
|
|
db.prepare(
|
|
`UPDATE tickets SET updated_at = datetime('now'),
|
|
sla_anchor_at = CASE WHEN status IN ('OPEN', 'WAITING') THEN datetime('now') ELSE sla_anchor_at END
|
|
WHERE id = ?`,
|
|
).run(ticketId);
|
|
|
|
db.exec('COMMIT');
|
|
res.status(201).json(mapEvent(row));
|
|
} catch (e) {
|
|
db.exec('ROLLBACK');
|
|
throw e;
|
|
}
|
|
});
|
|
}
|