/* ============================================================ HISTORY AND MOVEMENTS TRACKING ============================================================ */ let historyData = { dateFrom: null, dateTo: null, typeFilter: null, movements: [] }; function getHistoryDateRange() { const fromInput = document.getElementById('history-date-from'); const toInput = document.getElementById('history-date-to'); const typeFilter = document.getElementById('history-type-filter'); const today = new Date(); const thirtyDaysAgo = new Date(today.getTime() - (30 * 24 * 60 * 60 * 1000)); historyData.dateFrom = fromInput?.value ? new Date(fromInput.value) : thirtyDaysAgo; historyData.dateTo = toInput?.value ? new Date(toInput.value + 'T23:59:59') : today; historyData.typeFilter = typeFilter?.value || null; } const _historyTypeConfig = { factura: { icon: 'fa-receipt', color: 'blue', label: 'FACTURA' }, stock: { icon: 'fa-boxes-stacked', color: 'green', label: 'STOCK' }, precio: { icon: 'fa-tag', color: 'amber', label: 'PRECIO' }, producto: { icon: 'fa-edit', color: 'purple', label: 'PRODUCTO' }, bulk: { icon: 'fa-table', color: 'indigo', label: 'MASIVO' }, unknown: { icon: 'fa-circle', color: 'gray', label: 'OTRO' }, }; function getAllMovements() { const movements = []; // Facturas if (!historyData.typeFilter || historyData.typeFilter === 'factura') { STATE.adminInvoices.forEach(inv => { const invDate = new Date(inv.date); if (invDate >= historyData.dateFrom && invDate <= historyData.dateTo) { movements.push({ date: inv.date, type: 'factura', title: `Factura #${inv.invoiceNumber || inv.id}`, description: `Cliente: ${inv.client}`, amount: fmt(inv.total), details: `${(inv.items || []).length} producto(s)`, oldValue: null, newValue: null, note: null }); } }); } // changeLog entries const logEntries = STATE.changeLog || []; logEntries.forEach(entry => { const entryDate = new Date(entry.date); if (entryDate < historyData.dateFrom || entryDate > historyData.dateTo) return; if (historyData.typeFilter && entry.type !== historyData.typeFilter) return; const cfg = _historyTypeConfig[entry.type] || _historyTypeConfig.unknown; movements.push({ date: entry.date, type: entry.type, title: entry.productName ? `${cfg.label}: ${entry.productName}` : `${cfg.label}`, description: entry.note || (entry.field ? `Campo: ${entry.field}` : ''), amount: entry.newValue ? `→ ${entry.newValue}` : '', details: entry.oldValue ? `Anterior: ${entry.oldValue}` : '', oldValue: entry.oldValue, newValue: entry.newValue, note: entry.note }); }); historyData.movements = movements.sort((a, b) => new Date(b.date) - new Date(a.date)); return historyData.movements; } function generateHistoryReport() { getHistoryDateRange(); const movements = getAllMovements(); const invoiceCount = movements.filter(m => m.type === 'factura').length; const priceChanges = movements.filter(m => m.type === 'precio').length; const productChanges = movements.filter(m => m.type === 'producto' || m.type === 'bulk').length; const stockChanges = movements.filter(m => m.type === 'stock').length; const inv = document.getElementById('history-total-invoices'); const pc = document.getElementById('history-price-changes'); const pd = document.getElementById('history-product-changes'); const sc = document.getElementById('history-stock-changes'); if (inv) inv.textContent = invoiceCount; if (pc) pc.textContent = priceChanges; if (pd) pd.textContent = productChanges; if (sc) sc.textContent = stockChanges; renderHistoryTimeline(movements); renderHistoryTable(movements); } const _colorBg = { blue: '#DBEAFE', green: '#DCFCE7', amber: '#FEF3C7', purple: '#F3E8FF', indigo: '#E0E7FF', gray: '#F3F4F6' }; const _colorText = { blue: '#1E40AF', green: '#166534', amber: '#92400E', purple: '#6B21A8', indigo: '#3730A3', gray: '#374151' }; const _colorDot = { blue: '#3B82F6', green: '#10B981', amber: '#F59E0B', purple: '#8B5CF6', indigo: '#6366F1', gray: '#9CA3AF' }; function renderHistoryTimeline(movements) { const timeline = document.getElementById('history-timeline'); if (!timeline) return; if (movements.length === 0) { timeline.innerHTML = '
${escapeHtml(m.title)}
${escapeHtml(m.description)}
${m.oldValue || m.newValue ? `${m.oldValue ? `◀ ${escapeHtml(m.oldValue)}` : ''} ${m.oldValue && m.newValue ? ' → ' : ''} ${m.newValue ? `${escapeHtml(m.newValue)} ▶` : ''}
` : ''}${escapeHtml(m.details)} ${m.amount ? '• ' + escapeHtml(m.amount) : ''}