diff --git a/public/js/auth.js b/public/js/auth.js index 5d75cec..b514e4f 100644 --- a/public/js/auth.js +++ b/public/js/auth.js @@ -64,7 +64,7 @@ let missingCommentsFetchInFlight = false; async function init() { await loadInternalStatusesConfig(false, true); - await Promise.all([loadMarks(), loadNotes(), loadMentions(), loadUserList(), loadCommentCounts()]); + await Promise.all([loadMarks(), loadNotes(), loadMentions(), loadUserList(), loadCommentCounts(), loadClientDict()]); await loadTasksFromServer(); if (currentUser.is_admin) { @@ -106,6 +106,7 @@ async function loadMarks() { const d = await apiGet('/api/marks'); if (d) marksC async function loadNotes() { const d = await apiGet('/api/notes'); if (d) notesCache = d; } async function loadUserList() { const d = await apiGet('/api/users/list'); if (d) knownUsers = d.map((u) => u.toLowerCase()); } async function loadCommentCounts() { const d = await apiGet('/api/comments/counts'); if (d && typeof d === 'object') commentCounts = d; } +async function loadClientDict() { const d = await apiGet('/api/clients'); if (Array.isArray(d)) window._allClients = d; } async function loadTasksFromServer(silent = false) { if (!silent && !allData.length) showLoading(); diff --git a/public/js/statistics.js b/public/js/statistics.js index e8be97f..2a33ec8 100644 --- a/public/js/statistics.js +++ b/public/js/statistics.js @@ -840,8 +840,16 @@ function renderClientUsersCard() { if (!wrap) return; // createdby — строка с именем создателя, приходит прямо из API - // Собираем: организация → { total, users: { createdby → count } } + // Базовый список клиентов берём из _allClients (все usergroup из dictionaries), + // чтобы показывать клиентов с нулём заявок тоже. const cMap = {}; + + // Сначала заполняем всех известных клиентов с нулями + (window._allClients || []).forEach((c) => { + cMap[c.name] = { total: 0, users: {} }; + }); + + // Затем считаем реальные заявки allData.forEach((item) => { const t = item.task; const org = t._clientname || t.clientname || 'Неизвестно'; diff --git a/refresh-service.js b/refresh-service.js index 4ac9c4d..4a593c9 100644 --- a/refresh-service.js +++ b/refresh-service.js @@ -97,6 +97,12 @@ function createRefreshService({ db, fetch, getSettings, sseBroadcast, logger = c INSERT OR IGNORE INTO sync_state(id, cache_version, refresh_in_progress) VALUES(1, 0, 0); + CREATE TABLE IF NOT EXISTS client_dict ( + client_id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + updated_at TEXT NOT NULL + ); + CREATE TABLE IF NOT EXISTS tasks_index ( task_id TEXT PRIMARY KEY, task_number TEXT NOT NULL, @@ -143,6 +149,10 @@ function createRefreshService({ db, fetch, getSettings, sseBroadcast, logger = c `), clearIndex: db.prepare('DELETE FROM tasks_index'), insertIndex: db.prepare('INSERT INTO tasks_index(task_id, task_number, updated_at) VALUES(?,?,?)'), + upsertClient: db.prepare(` + INSERT INTO client_dict(client_id, name, updated_at) VALUES(?,?,?) + ON CONFLICT(client_id) DO UPDATE SET name=excluded.name, updated_at=excluded.updated_at + `), upsertIntraStatus: db.prepare(` INSERT INTO intra_status_dict(status_id,name,updated_at) VALUES(?,?,?) ON CONFLICT(status_id) DO UPDATE SET name=excluded.name,updated_at=excluded.updated_at @@ -452,6 +462,14 @@ function createRefreshService({ db, fetch, getSettings, sseBroadcast, logger = c const dictMap = {}; (json.dictionaries || []).forEach((d) => { dictMap[d.id] = d.name; }); + // Сохраняем клиентов (usergroup) в отдельную таблицу + const now = safeIsoNow(); + const clientEntries = (json.dictionaries || []).filter((d) => d.type === 'usergroup' && !d.isarchived); + const upsertClients = db.transaction((entries) => { + for (const d of entries) stmts.upsertClient.run(d.id, d.name, now); + }); + if (clientEntries.length) upsertClients(clientEntries); + tasks.forEach((task) => { if (task.clientid && dictMap[task.clientid]) task._clientname = dictMap[task.clientid]; if (task.executor && dictMap[task.executor]) task._executorname = dictMap[task.executor]; diff --git a/server.js b/server.js index 1249f49..b2fe2b0 100644 --- a/server.js +++ b/server.js @@ -524,6 +524,11 @@ app.get('/api/status', auth, (req, res) => { }); // ── Tasks ───────────────────────────────────────────────────────── +app.get('/api/clients', auth, (req, res) => { + const rows = db.prepare('SELECT client_id, name FROM client_dict ORDER BY name ASC').all(); + res.json(rows); +}); + app.get('/api/tasks', auth, (req, res) => { const cache = db.prepare('SELECT * FROM tasks_cache WHERE id=1').get(); const sync = refreshService.getStatusSnapshot();