Processando...
Resumo Executivo
Total 2025
Faturamento acumulado
Total 2026
Crescimento 26/25
Meta 2026 (+10%)
sobre 2025
Atingimento da Meta
da meta anual
Gap para Meta
para atingir a meta
Clientes Ativos
Alertas e Oportunidades
clique para detalhar
Análise da Base (Geral)
Mês a Mês e Trimestre (2025 x 2026)
Comparativo de Faturamento
Período selecionado: —
Faturamento Mês a Mês — 2025 x 2026
R$ (Milhões)
Acima da meta Até 5% abaixo da meta Mais de 5% abaixo da meta
Média Mensal 2025
Média Mensal 2026
Diferença Média
Acumulado (Jan–Mai)
ⓘ Meta 2026: 10% acima de 2025 (mês a mês)
Faturamento Trimestral — 2025 x 2026
R$ (Milhões)
Acumulado Trimestres (Jan–Mai)
Projeção 2026
Meta Anual 2026
Gap Projetado
ⓘ Meta trimestral: 10% acima do mesmo período de 2025
Destaques Positivos
Atenção
Tendência (últimos 3 meses)
Resumo Rápido
Valores em Reais (R$) · Dados atualizados até · Fonte: Sistema Comercial
Top 15 Clientes
#CódClienteTotalVar %
Menores 15 Clientes
#CódClienteTotalVar %
`); w.document.close(); w.focus(); setTimeout(()=>{ try{ w.print(); }catch(_){ } }, 350); }catch(_){ } }); } // ── Sidebar recolher/expandir ── function initSidebarToggle(){ const shell = document.getElementById('appShell'); const btn = document.getElementById('sidebarToggleBtn'); if (!shell || !btn || btn.dataset.bound) return; btn.dataset.bound = '1'; const KEY = 'haskell_sidebar_collapsed'; const apply = (collapsed)=>{ shell.classList.toggle('sidebar-collapsed', collapsed); btn.setAttribute('aria-expanded', collapsed ? 'false' : 'true'); }; let collapsed = false; try{ collapsed = localStorage.getItem(KEY) === '1'; }catch(_){ } apply(collapsed); btn.addEventListener('click', ()=>{ collapsed = !shell.classList.contains('sidebar-collapsed'); apply(collapsed); try{ localStorage.setItem(KEY, collapsed ? '1' : '0'); }catch(_){ } }); } // bootstrap document.addEventListener('DOMContentLoaded', ()=>{ initSidebarToggle(); initDensity(); fixStatusOptions(); enhanceActiveFilters(); injectExecUI(); patchCharts(); patchAdvanced(); // Meta configurável + preferências initMetaPersistence(); bindExportSummary(); bindTabPersistence(); bindFilterPersistence(); // restaura aba salva (se houver) const savedTab = lsGet(LS_KEYS.tab, 'rep'); if (savedTab) setActiveTabKey(savedTab); // aplica filtros salvos assim que o Excel for carregado applySavedWhenReady(); const metaInp = $('metaPct'); if (metaInp){ // valor inicial depende do contexto (global ou rep) try{ window.syncMetaInputToContext?.(); }catch(_){ } metaInp.addEventListener('change', ()=>{ const v = parseFloat(String(metaInp.value).replace(',','.')); const pctVal = isFinite(v) ? Math.max(0, Math.min(300, v))/100 : 0.30; const rep = $('repSelect')?.value || '__ALL_REPS__'; if (window.state.metaPerRep && rep && rep !== '__ALL_REPS__'){ window.state.metaPctMap = window.state.metaPctMap || {}; window.state.metaPctMap[rep] = pctVal; lsSetJSON(LS_KEYS.meta_map, window.state.metaPctMap); }else{ window.state.metaPctGlobal = pctVal; lsSet(LS_KEYS.meta_global, (pctVal*100).toFixed(2)); } // mantém input consistente com o contexto try{ window.syncMetaInputToContext?.(); }catch(_){ } try{ window.renderCharts?.(); }catch(_){ } try{ const ag = window.buildAggregates?.(); window.renderAdvanced?.(ag); }catch(_){ } }); } // quando muda de representante, se meta por rep estiver ativa, troca a meta automaticamente const repSel = $('repSelect'); if (repSel && !repSel.dataset.metaBound){ repSel.dataset.metaBound='1'; repSel.addEventListener('change', ()=>{ try{ window.syncMetaInputToContext?.(); }catch(_){ } try{ window.renderCharts?.(); }catch(_){ } try{ const ag = window.buildAggregates?.(); window.renderAdvanced?.(ag); }catch(_){ } }); } }); })();