diff --git a/pos/static/js/dashboard.js b/pos/static/js/dashboard.js index fd42637..c57dcbc 100644 --- a/pos/static/js/dashboard.js +++ b/pos/static/js/dashboard.js @@ -205,6 +205,50 @@ const Dashboard = (() => { return data; } + // ------------------------------------------------------------------------- + // 1b. Historical sales KPIs (imported data) + // ------------------------------------------------------------------------- + async function loadHistoricalSummary() { + try { + const now = new Date(); + const firstDay = new Date(now.getFullYear(), now.getMonth(), 1).toISOString().slice(0, 10); + const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0).toISOString().slice(0, 10); + + // All historical sales + const all = await apiFetch('/pos/api/historical-sales?per_page=1'); + const totalRecords = all.pagination ? all.pagination.total : 0; + + // Current month historical sales + const month = await apiFetch(`/pos/api/historical-sales?date_from=${firstDay}&date_to=${lastDay}&per_page=200`); + const monthRows = month.data || []; + const monthTotal = monthRows.reduce((a, r) => a + (r.total || 0), 0); + + const totalEl = document.getElementById('kpi-historico-total-value'); + const totalMetaEl = document.getElementById('kpi-historico-total-meta'); + if (totalEl) totalEl.textContent = fmt(monthTotal); + if (totalMetaEl) totalMetaEl.innerHTML = ``; + + const mesEl = document.getElementById('kpi-historico-mes-value'); + const mesMetaEl = document.getElementById('kpi-historico-mes-meta'); + if (mesEl) mesEl.textContent = fmt(monthTotal); + if (mesMetaEl) mesMetaEl.innerHTML = ``; + + const countEl = document.getElementById('kpi-historico-count-value'); + const countMetaEl = document.getElementById('kpi-historico-count-meta'); + if (countEl) countEl.textContent = fmtInt(totalRecords); + if (countMetaEl) countMetaEl.innerHTML = ``; + + } catch (err) { + console.error('Error loading historical summary:', err); + const ids = [ + ['kpi-historico-total-value', 'kpi-historico-total-meta'], + ['kpi-historico-mes-value', 'kpi-historico-mes-meta'], + ['kpi-historico-count-value', 'kpi-historico-count-meta'], + ]; + ids.forEach(([v, m]) => setKpiError(v, m)); + } + } + function setKpiError(valueId, metaId) { const v = document.getElementById(valueId); const m = document.getElementById(metaId); @@ -533,6 +577,7 @@ const Dashboard = (() => { // Load all data in parallel loadDailySummary(); + loadHistoricalSummary(); loadAlerts(); loadTopProducts(); loadWeeklyChart(); diff --git a/pos/static/js/reports.js b/pos/static/js/reports.js index 7539c90..7e78c2d 100644 --- a/pos/static/js/reports.js +++ b/pos/static/js/reports.js @@ -54,7 +54,7 @@ const Reports = (() => { } // Track which tabs have been loaded - var loaded = { ventas: false, inventario: false, clientes: false, financieros: false }; + var loaded = { ventas: false, inventario: false, clientes: false, financieros: false, historico: false }; // ------------------------------------------------------------------------- // Theme switcher @@ -85,6 +85,7 @@ const Reports = (() => { else if (id === 'inventario') loadInventario(); else if (id === 'clientes') loadClientes(); else if (id === 'financieros') loadFinancieros(); + else if (id === 'historico') loadHistorico(); } } window.switchTab = switchTab; @@ -289,6 +290,85 @@ const Reports = (() => { } } + // ========================================================================= + // TAB 5: HISTÓRICO + // ========================================================================= + async function loadHistorico() { + loaded.historico = true; + var dateFrom = document.getElementById('historico-date-from').value; + var dateTo = document.getElementById('historico-date-to').value; + var customer = document.getElementById('historico-customer').value.trim(); + + var params = new URLSearchParams(); + if (dateFrom) params.set('date_from', dateFrom); + if (dateTo) params.set('date_to', dateTo); + if (customer) params.set('customer', customer); + params.set('per_page', '200'); + + var kpiEl = document.getElementById('historico-kpis'); + var detalleEl = document.getElementById('historico-detalle'); + kpiEl.innerHTML = spinner(); + detalleEl.innerHTML = spinner(); + + try { + var allRows = []; + var page = 1; + var totalPages = 1; + + while (page <= totalPages) { + params.set('page', page); + var json = await apiFetch('/pos/api/historical-sales?' + params.toString()); + allRows = allRows.concat(json.data || []); + totalPages = json.pagination ? json.pagination.total_pages : 1; + page++; + if (page > 50) break; + } + + var total = allRows.reduce(function(a, r) { return a + r.total; }, 0); + var subtotal = allRows.reduce(function(a, r) { return a + r.subtotal; }, 0); + var balance = allRows.reduce(function(a, r) { return a + r.balance; }, 0); + + kpiEl.innerHTML = + kpiCard('Total Histórico', '$' + fmt(total), allRows.length + ' registros') + + kpiCard('Subtotal', '$' + fmt(subtotal), '') + + kpiCard('Saldo Pendiente', '$' + fmt(balance), '') + + kpiCard('Tickets', fmtInt(allRows.length), ''); + + var html = '
| Fecha | Documento | Cliente | Pago | ' + + 'Subtotal | Total | ' + + 'Pagado | Saldo | ' + + '
|---|---|---|---|---|---|---|---|
| ' + fmtDate(r.sale_date) + ' | ' + + '' + esc(r.document_no || r.external_document_id || '--') + ' | ' + + '' + esc(r.customer_name || '--') + ' | ' + + '' + esc(r.payment_method || '--') + ' | ' + + '$' + fmt(r.subtotal) + ' | ' + + '$' + fmt(r.total) + ' | ' + + '$' + fmt(r.amount_paid) + ' | ' + + '$' + fmt(r.balance) + ' | ' + + '