== Документација за функцијата за извештаи од админ панелот Опис на функцијата Оваа функција, означена како getDashboardStats, се користи за собирање и враќање на различни статистики и метрики од базата на податоци за административниот панел на апликацијата. Функцијата е асинхрона и повикува повеќе SQL прашања за да ги добие потребните податоци. **Податоци што ги враќа** Функцијата враќа објект со следниве податоци: * employeeSales: Листа на вработени со број на продажби и вкупна вредност на продажбите. * maintenanceStats: Листа на вработени (техничари) со број на завршени одржувања. * customerTotals: Листа на купувачи со број на нарачки и вкупна потрошена сума * averageMaintenanceTime: Просечно време (во минути) потребно за завршување на одржување * totalProcurements: Вкупен број на барања за набавка * avgProcurementValue: Просечна вредност на набавка * totalRevenue: Вкупен приход од сите трансакции * revenueSplit: Распределба на приход по тип на трансакција ** Детали за SQL прашањата ** * Продажби по вработен: Групира по вработен и дава број на продажби и вкупна вредност на продажбите * Завршени одржувања по техничар: Групира по вработен и дава број на завршени одржувања, филтрирани само за оние со статус „Completed“ * Купувачи и нивните нарачки: Групира по купувач и дава број на нарачки и вкупна потрошена сума * Просечно време на одржување: Го пресметува просечното време (во минути) помеѓу почетокот и крајот на завршените одржувања * Вкупен број на барања за набавка: Брои колку барања за набавка има во базата * Просечна вредност на набавка: Го пресметува просекот на вредноста на сите набавки * Вкупен приход: Ги собира вредностите на сите трансакции * Распределба на приход по тип: Групира по тип на трансакција и ги дава вредностите ** Ракување со грешки ** Доколку дојде до грешка при извр2шување на SQL прашањата, функцијата враќа HTTP статус 500 и порака за грешка. Исто така, во случај на празни резултати, се користат стандардни вредности (0) за да се избегнат грешки. Предлози за подобрување * Индексирање: Препорачливо е да се индексираат клучните колони како TransactionID, Status, EmployeeID и слично. * Кеширање: За чести повици, може да се користи кеширање на податоците. * Филтрирање по датум: Во иднина може да се додадат филтри за изве2стување по временски период. {{{ const pool = require('../models/db'); exports.getDashboardStats = async (req, res) => { try { const [employeeSales] = await pool.query(` SELECT e.EmployeeID, e.EmployeeName AS Name, e.EmployeeSurName AS Surname, COUNT(*) AS SalesCount, SUM(t.TotalPrice) AS TotalSales FROM procurement p JOIN t_type t ON t.TransactionID = p.TransactionID JOIN employee e ON e.EmployeeID = p.EmployeeID GROUP BY e.EmployeeID `); const [maintenanceStats] = await pool.query(` SELECT e.EmployeeID, e.EmployeeName AS Name, e.EmployeeSurName AS Surname, COUNT(*) AS MaintenanceDone FROM maintenance m JOIN employee e ON e.EmployeeID = m.EmployeeID WHERE m.Status = 'Completed' GROUP BY e.EmployeeID `); const [customerTotals] = await pool.query(` SELECT c.CustomerID, c.CustomerName, c.CustomerSurName, COUNT(*) AS Purchases, SUM(t.TotalPrice) AS TotalSpent FROM procurement p JOIN customer c ON c.CustomerID = p.CustomerID JOIN t_type t ON t.TransactionID = p.TransactionID GROUP BY c.CustomerID `); const [averageMaintenanceTime] = await pool.query(` SELECT AVG(TIMESTAMPDIFF(MINUTE, StartTime, EndTime)) AS AvgMinutes FROM maintenance WHERE Status = 'Completed' AND StartTime IS NOT NULL AND EndTime IS NOT NULL `); const [totalProcurements] = await pool.query(` SELECT COUNT(*) AS TotalProcurements FROM procurement_request `); const [avgProcurementValue] = await pool.query(` SELECT AVG(TotalPrice) AS AvgProcurementValue FROM t_type `); const [totalRevenue] = await pool.query(` SELECT SUM(TotalPrice) AS TotalRevenue FROM t_type `); const [revenueSplit] = await pool.query(` SELECT Type, SUM(TotalPrice) AS Revenue FROM t_type GROUP BY Type `); res.json({ employeeSales, maintenanceStats, customerTotals, averageMaintenanceTime: averageMaintenanceTime[0]?.AvgMinutes || 0, totalProcurements: totalProcurements[0]?.TotalProcurements || 0, avgProcurementValue: avgProcurementValue[0]?.AvgProcurementValue || 0, totalRevenue: totalRevenue[0]?.TotalRevenue || 0, revenueSplit }); } catch (err) { console.error("Dashboard metrics fetch error:", err); res.status(500).json({ error: "Failed to fetch admin stats" }); } }; }}}