Files
otrs-turbo/activityDb.js
T

181 lines
5.8 KiB
JavaScript

/**
* activityDb.js
* Local SQLite activity log database.
* Opens (or creates) internal.db and provides logAttivita() for logging
* every significant action sent to OTRS.
*/
const Database = require('better-sqlite3');
const path = require('path');
const crypto = require('crypto');
const DB_PATH = path.join(__dirname, 'internal.db');
const db = new Database(DB_PATH);
// Ensure WAL mode for better concurrent access
db.pragma('journal_mode = WAL');
// Create table if it does not exist
db.exec(`
CREATE TABLE IF NOT EXISTS attivita (
id TEXT PRIMARY KEY,
agente_id INTEGER NOT NULL DEFAULT 0,
agente_nome TEXT NOT NULL DEFAULT '',
titolo_azione TEXT NOT NULL,
azione TEXT NOT NULL DEFAULT '{}',
esito TEXT NOT NULL DEFAULT 'successo',
creato_il DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
)
`);
db.exec(`
CREATE TABLE IF NOT EXISTS agent_settings (
agent_id INTEGER PRIMARY KEY,
preview_limit INTEGER NOT NULL DEFAULT 10,
tickets_per_page INTEGER NOT NULL DEFAULT 50
)
`);
db.exec(`
CREATE TABLE IF NOT EXISTS email_signatures (
id INTEGER PRIMARY KEY AUTOINCREMENT,
agent_id INTEGER NOT NULL,
name TEXT NOT NULL,
body_html TEXT NOT NULL DEFAULT '',
is_default INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
)
`);
db.exec(`
CREATE TABLE IF NOT EXISTS ticket_groups (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nome TEXT NOT NULL,
descrizione TEXT,
master_ticket_id INTEGER,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
)
`);
db.exec(`
CREATE TABLE IF NOT EXISTS ticket_group_members (
group_id INTEGER NOT NULL,
ticket_id INTEGER NOT NULL,
PRIMARY KEY (group_id, ticket_id),
FOREIGN KEY (group_id) REFERENCES ticket_groups (id) ON DELETE CASCADE
)
`);
db.exec(`
CREATE TABLE IF NOT EXISTS filter_presets (
id INTEGER PRIMARY KEY AUTOINCREMENT,
agent_id INTEGER NOT NULL,
name TEXT NOT NULL,
page_mode TEXT NOT NULL,
filters_json TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
)
`);
db.exec(`
CREATE TABLE IF NOT EXISTS email_address_groups (
id INTEGER PRIMARY KEY AUTOINCREMENT,
agent_id INTEGER NOT NULL,
name TEXT NOT NULL,
emails TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
)
`);
db.exec(`
CREATE TABLE IF NOT EXISTS dashboard_chart_lines (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
statuses TEXT NOT NULL,
types TEXT NOT NULL,
queues TEXT NOT NULL,
owners TEXT NOT NULL,
responsibles TEXT NOT NULL,
color TEXT,
is_visible INTEGER NOT NULL DEFAULT 1,
is_default INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
)
`);
try {
db.exec(`ALTER TABLE dashboard_chart_lines ADD COLUMN color TEXT`);
} catch (e) {
// Already exists
}
try {
db.exec(`ALTER TABLE dashboard_chart_lines ADD COLUMN is_visible INTEGER NOT NULL DEFAULT 1`);
} catch (e) {
// Already exists
}
try {
const countRow = db.prepare("SELECT COUNT(*) AS count FROM dashboard_chart_lines").get();
if (countRow && countRow.count === 0) {
db.prepare(`
INSERT INTO dashboard_chart_lines (name, statuses, types, queues, owners, responsibles, color, is_visible, is_default)
VALUES (?, ?, ?, ?, ?, ?, ?, 1, 1)
`).run('Ticket aperti', JSON.stringify([1, 4, 6, 7, 8]), '[]', '[]', '[]', '[]', '#4f46e5');
db.prepare(`
INSERT INTO dashboard_chart_lines (name, statuses, types, queues, owners, responsibles, color, is_visible, is_default)
VALUES (?, ?, ?, ?, ?, ?, ?, 1, 1)
`).run('Ticket chiusi', JSON.stringify([2, 3, 10]), '[]', '[]', '[]', '[]', '#10b981');
} else {
// Update default ones color if not set yet
db.prepare(`UPDATE dashboard_chart_lines SET color = '#4f46e5' WHERE name = 'Ticket aperti' AND color IS NULL`).run();
db.prepare(`UPDATE dashboard_chart_lines SET color = '#10b981' WHERE name = 'Ticket chiusi' AND color IS NULL`).run();
}
} catch (e) {
console.error("Error seeding default chart lines:", e.message);
}
try {
db.exec(`ALTER TABLE agent_settings ADD COLUMN tickets_per_page INTEGER NOT NULL DEFAULT 50`);
} catch (e) {
// Column already exists
}
/**
* Generate a UUID v7 (time-ordered).
*/
function uuidV7() {
const tsMs = BigInt(Date.now());
const tsMsHex = tsMs.toString(16).padStart(12, '0');
const rand = crypto.randomBytes(10).toString('hex');
const p1 = tsMsHex.slice(0, 8);
const p2 = tsMsHex.slice(8, 12);
const p3 = '7' + rand.slice(0, 3);
const p4 = ((parseInt(rand.slice(3, 4), 16) & 0x3) | 0x8).toString(16) + rand.slice(4, 7);
const p5 = rand.slice(7, 19);
return `${p1}-${p2}-${p3}-${p4}-${p5}`;
}
const insertStmt = db.prepare(`
INSERT INTO attivita (id, agente_id, agente_nome, titolo_azione, azione, esito)
VALUES (?, ?, ?, ?, ?, ?)
`);
/**
* Log an activity record.
* @param {Object} params
*/
function logAttivita({ agente_id = 0, agente_nome = '', titolo_azione, azione = {}, esito = 'successo' }) {
try {
const id = uuidV7();
const azioneStr = typeof azione === 'string' ? azione : JSON.stringify(azione, null, 2);
insertStmt.run(id, agente_id, agente_nome, titolo_azione, azioneStr, esito);
} catch (err) {
console.error('[activityDb] Failed to log activity:', err.message);
}
}
module.exports = { db, logAttivita };