192 lines
6.3 KiB
JavaScript
192 lines
6.3 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 baseDir = process.pkg ? path.dirname(process.execPath) : __dirname;
|
|
const DB_PATH = path.join(baseDir, '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,
|
|
bypass_state_filter 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 {
|
|
db.exec(`ALTER TABLE dashboard_chart_lines ADD COLUMN bypass_state_filter INTEGER NOT NULL DEFAULT 0`);
|
|
} 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, bypass_state_filter)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, 1, 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, bypass_state_filter)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, 1, 1, 0)
|
|
`).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();
|
|
|
|
// Set default Ticket aperti to bypass state filter
|
|
db.prepare(`UPDATE dashboard_chart_lines SET bypass_state_filter = 1 WHERE name = 'Ticket aperti'`).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 };
|