120 lines
4.1 KiB
JavaScript
120 lines
4.1 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const pool = require('../db');
|
|
|
|
// GET /api/dashboard/stats — Dashboard statistics
|
|
router.get('/stats', async (req, res) => {
|
|
const activeAgentId = parseInt(req.headers['x-agent-id'], 10) || 1;
|
|
try {
|
|
// All queries in parallel for speed
|
|
const [
|
|
byState,
|
|
byPriority,
|
|
byQueue,
|
|
todayCount,
|
|
weekCount,
|
|
totalOpen,
|
|
recentTickets,
|
|
escalated,
|
|
myOpenCount,
|
|
] = await Promise.all([
|
|
// Tickets by state (only open-ish states)
|
|
pool.query(
|
|
`SELECT ts.name AS state, tst.name AS state_type, COUNT(*) AS count
|
|
FROM ticket t
|
|
JOIN ticket_state ts ON t.ticket_state_id = ts.id
|
|
JOIN ticket_state_type tst ON ts.type_id = tst.id
|
|
WHERE tst.name IN ('new', 'open', 'pending reminder', 'pending auto')
|
|
GROUP BY ts.name, tst.name
|
|
ORDER BY count DESC`
|
|
),
|
|
// Tickets by priority (open only)
|
|
pool.query(
|
|
`SELECT tp.name AS priority, tp.color, COUNT(*) AS count
|
|
FROM ticket t
|
|
JOIN ticket_priority tp ON t.ticket_priority_id = tp.id
|
|
JOIN ticket_state ts ON t.ticket_state_id = ts.id
|
|
JOIN ticket_state_type tst ON ts.type_id = tst.id
|
|
WHERE tst.name IN ('new', 'open', 'pending reminder', 'pending auto')
|
|
GROUP BY tp.name, tp.color, tp.id
|
|
ORDER BY tp.id`
|
|
),
|
|
// Tickets by queue (open only, top 10)
|
|
pool.query(
|
|
`SELECT q.name AS queue, COUNT(*) AS count
|
|
FROM ticket t
|
|
JOIN queue q ON t.queue_id = q.id
|
|
JOIN ticket_state ts ON t.ticket_state_id = ts.id
|
|
JOIN ticket_state_type tst ON ts.type_id = tst.id
|
|
WHERE tst.name IN ('new', 'open', 'pending reminder', 'pending auto')
|
|
GROUP BY q.name
|
|
ORDER BY count DESC
|
|
LIMIT 10`
|
|
),
|
|
// Created today
|
|
pool.query(
|
|
`SELECT COUNT(*) AS count FROM ticket
|
|
WHERE create_time >= CURRENT_DATE`
|
|
),
|
|
// Created this week
|
|
pool.query(
|
|
`SELECT COUNT(*) AS count FROM ticket
|
|
WHERE create_time >= date_trunc('week', CURRENT_DATE)`
|
|
),
|
|
// Total open
|
|
pool.query(
|
|
`SELECT COUNT(*) AS count
|
|
FROM ticket t
|
|
JOIN ticket_state ts ON t.ticket_state_id = ts.id
|
|
JOIN ticket_state_type tst ON ts.type_id = tst.id
|
|
WHERE tst.name IN ('new', 'open', 'pending reminder', 'pending auto')`
|
|
),
|
|
// 10 most recent tickets
|
|
pool.query(
|
|
`SELECT t.id, t.tn, t.title, ts.name AS state_name,
|
|
tp.name AS priority_name, tp.color AS priority_color,
|
|
q.name AS queue_name, t.create_time
|
|
FROM ticket t
|
|
JOIN ticket_state ts ON t.ticket_state_id = ts.id
|
|
JOIN ticket_priority tp ON t.ticket_priority_id = tp.id
|
|
JOIN queue q ON t.queue_id = q.id
|
|
ORDER BY t.create_time DESC
|
|
LIMIT 10`
|
|
),
|
|
// Escalated tickets
|
|
pool.query(
|
|
`SELECT COUNT(*) AS count FROM ticket
|
|
WHERE escalation_time > 0
|
|
AND escalation_time < EXTRACT(EPOCH FROM NOW())`
|
|
),
|
|
// My open tickets count
|
|
pool.query(
|
|
`SELECT COUNT(*) AS count
|
|
FROM ticket t
|
|
JOIN ticket_state ts ON t.ticket_state_id = ts.id
|
|
JOIN ticket_state_type tst ON ts.type_id = tst.id
|
|
WHERE tst.name IN ('new', 'open', 'pending reminder', 'pending auto')
|
|
AND t.user_id = $1`,
|
|
[activeAgentId]
|
|
),
|
|
]);
|
|
|
|
res.json({
|
|
by_state: byState.rows,
|
|
by_priority: byPriority.rows,
|
|
by_queue: byQueue.rows,
|
|
created_today: parseInt(todayCount.rows[0].count),
|
|
created_this_week: parseInt(weekCount.rows[0].count),
|
|
total_open: parseInt(totalOpen.rows[0].count),
|
|
recent_tickets: recentTickets.rows,
|
|
escalated: parseInt(escalated.rows[0].count),
|
|
total_my_open: parseInt(myOpenCount.rows[0].count),
|
|
});
|
|
} catch (err) {
|
|
console.error('Error fetching dashboard stats:', err);
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|