Revisão da visualização do Balancete
This commit is contained in:
parent
530e0e85e3
commit
a8db64d949
@ -82,7 +82,11 @@
|
||||
"Bash(\"./.venv/Scripts/python.exe\" manage.py makemigrations --check --dry-run)",
|
||||
"Bash(\"./.venv/Scripts/pip.exe\" install *)",
|
||||
"PowerShell(node --check \"static/js/dashboard-contabil.js\")",
|
||||
"Bash(.venv/Scripts/python.exe -m py_compile portal_api/dashboard_contabil/regras.py)"
|
||||
"Bash(.venv/Scripts/python.exe -m py_compile portal_api/dashboard_contabil/regras.py)",
|
||||
"Bash(node -e \"require\\('vm'\\).Script\\(require\\('fs'\\).readFileSync\\('static/js/dashboard-contabil.js','utf8'\\)\\)\")",
|
||||
"Bash(.venv/Scripts/python.exe \"C:/Users/Depaula/AppData/Local/Temp/claude/c--Users-Depaula-Documents-Portal/cf4a6caf-9798-42a6-bbc8-a8ffbb3debf6/scratchpad/sim_destaque.py\")",
|
||||
"Bash(PYTHONPATH=\"C:\\\\Users\\\\Depaula\\\\Documents\\\\Portal\" .venv/Scripts/python.exe \"C:/Users/Depaula/AppData/Local/Temp/claude/c--Users-Depaula-Documents-Portal/cf4a6caf-9798-42a6-bbc8-a8ffbb3debf6/scratchpad/sim_destaque.py\")",
|
||||
"Bash(PYTHONPATH=\"C:\\\\Users\\\\Depaula\\\\Documents\\\\Portal\" .venv/Scripts/python.exe \"C:/Users/Depaula/AppData/Local/Temp/claude/c--Users-Depaula-Documents-Portal/cf4a6caf-9798-42a6-bbc8-a8ffbb3debf6/scratchpad/sim_expandir_tudo.py\")"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,3 +318,26 @@ Só vale pra achados gerados dali em diante — um achado já persistido mantém
|
||||
Usuário reportou, com print de uma árvore de 3 níveis (Balancete), que uma conta "mãe" (ex. "CAIXA E EQUIVALENTES DE CAIXA") não ficava verde mesmo depois de toda conta-folha dentro dela ("netos", ex. os 4 bancos dentro de "DEPÓSITOS BANCÁRIOS A VISTA") já estarem validadas uma a uma — mesmo a conta "filha" intermediária ("DEPÓSITOS BANCÁRIOS A VISTA") já aparecendo corretamente verde. Causa raiz: `dcEstadoValidacaoGrupo()` (`dashboard-contabil.js`, tri-state do botão "validado" de uma sintética, ver rodada de "Tri-state numa conta/linha sintética") decidia o estado "completo" checando `descendentes.every(d => d.validado)` sobre **todos** os descendentes (filhos, netos, bisnetos), não só os de folha — quando os netos são marcados diretamente (sem clicar na própria "filha" intermediária pra cascatear), o campo `validado` da "filha" no banco continua `False` mesmo que ela já apareça "completa" visualmente (calculada a cada render); a "mãe", ao olhar todos os descendentes, incluía essa "filha" com `validado=False` e nunca fechava o grupo.
|
||||
|
||||
Corrigido restringindo o critério de "completo" só aos descendentes **folha** (sem filhos) — `dcDescendentes()` ganhou um quarto parâmetro opcional (`somenteFolhas`), reaproveitando o mesmo cálculo de "tem filho" já usado por `temFilhos`; `dcEstadoValidacaoGrupo(item, descendentes, descendentesFolhas)` passou a checar `descendentesFolhas.every(d => d.validado)` pro estado "completo", mantendo `descendentes` (todos) pro "parcial" (uma sintética marcada sozinha, sem cascatear, ainda deve sinalizar "em andamento" num ancestral). Os 4 pontos que calculam o estado (`dcValidadoInfo()` + os 3 handlers de clique — Balancete/D.R.E./Análise Vertical) foram atualizados pra passar os dois conjuntos. Puramente lógica de exibição/cálculo no frontend — nenhuma mudança de model/endpoint.
|
||||
|
||||
### 140. Bug real: destaque de um grupo já expandido desaparecia ao expandir outro
|
||||
|
||||
Usuário reportou, com print de uma árvore de 3 níveis (Balancete), que expandir uma segunda conta apagava visualmente o destaque dourado da primeira já expandida — o esperado era as duas ficarem destacadas ao mesmo tempo, pra facilitar a validação em sequência de várias contas abertas de uma vez. Causa: o destaque das linhas recém-reveladas ao expandir (ver rodada "Destaque acompanha o último grupo expandido") era desenhado pra **substituir** a leva anterior por design — cada expandir trocava `dcContasDestaque`/`dcDreDestaque`/`dcAvDestaque` pelos filhos diretos do grupo recém-aberto, empilhando o destaque anterior numa pilha (`dc*DestaqueHistorico`) só restaurada ao recolher o mesmo grupo.
|
||||
|
||||
**Duas tentativas falhas antes de acertar** (as duas reportadas pelo usuário testando em produção — sempre com hard refresh e restart do servidor, então nunca foi cache):
|
||||
|
||||
1. **Somar os filhos revelados ao `Set` de destaque já existente**: não mudou nada visualmente. Causa raiz, só encontrada depois de simular o algoritmo em Python contra as contas reais da apuração do usuário: o destaque inicial (`dcUltimaLevaVisivel`) já marca **praticamente toda conta de nível ≥ 2** — todas nascem recolhidas pelo limiar padrão, então cada uma conta como "fim de ramo visível". Somar os filhos revelados a essa base deixava a tabela inteira destacada, e com tudo destacado nada se destaca. O comportamento original só parecia funcionar porque o "substituir" limpava todo o resto da tabela junto.
|
||||
2. **Destacar a própria conta expandida** em vez dos filhos: o usuário esclareceu que destacar os filhos sempre esteve certo — a única mudança pedida era acumular mais de um grupo.
|
||||
|
||||
**Correção final**: `dcDestaqueGrupos(itens, nivelFn, colapsadas, expandidos)` (nova) passa a derivar o destaque sempre do zero, a partir de um `Set` novo por árvore (`dcContasExpandidos`/`dcDreExpandidos`/`dcAvExpandidos`) com os grupos que o contador expandiu e que continuam abertos: sem nenhum grupo aberto, vale a leva padrão de sempre (`dcUltimaLevaVisivel`); com algum aberto, o destaque é **só** a união dos filhos diretos desses grupos, descartando a leva padrão — é esse descarte que devolve o contraste. Recolher um grupo remove ele **e todos os descendentes** dele do conjunto (um grupo aninhado que estava aberto dentro dele deixa de contar), garantindo que fechar tudo devolva exatamente o estado inicial. As três pilhas de histórico (`dc*DestaqueHistorico`) foram removidas — recolher não precisa mais restaurar nada de uma pilha.
|
||||
|
||||
Validado simulando o algoritmo em Python contra as contas reais da apuração `2021`/`08-2026`, reproduzindo o roteiro exato descrito pelo usuário: expandir "CAIXA E EQUIVALENTES DE CAIXA" destaca só seus 2 filhos (resto da tabela limpo); expandir "CLIENTES" em seguida mantém os 2 e soma "DUPLICATAS A RECEBER"; fechar "CLIENTES" volta aos 2 primeiros; fechar "CAIXA" devolve exatamente o conjunto de destaque inicial (igualdade entre os dois conjuntos conferida). Mesmo ajuste replicado em `pidDcrArvore()` (`dashboard-contabil-relatorio.html`), que reimplementa esta lógica em JS puro pro relatório "Gerar Dashboard" — os dois lados são mantidos manualmente em sincronia, sem fonte única (um é SPA, o outro HTML estático renderizado uma vez). Puramente lógica de exibição no frontend, sem mudança de model/endpoint. Detalhe técnico completo no `CLAUDE.md` desta pasta.
|
||||
|
||||
**Lição registrada na memória do projeto**: nas duas primeiras tentativas a resposta ao "não funcionou" incluiu a hipótese de cache do navegador/JS antigo em memória — o usuário deixou claro que sempre testa com hard refresh e restart do servidor antes de reportar. A causa era sempre bug real, e só apareceu quando o algoritmo foi **simulado com os dados reais** (script Python ad-hoc lendo as contas da apuração pelo ORM) em vez de analisado estaticamente.
|
||||
|
||||
### 141. Botão "+" (expandir tudo) no cabeçalho das tabelas da revisão
|
||||
|
||||
Pedido explícito do usuário: um botão pequeno no canto esquerdo do cabeçalho da primeira coluna que expande todas as contas até o último nível de uma vez. A ideia inicial tinha também um "−" que recolheria um nível por vez, descartada pelo próprio usuário na mesma conversa ("poderia apenas um botão, o de +").
|
||||
|
||||
`.dc-expandir-tudo-btn` (`data-dc-expandir-tudo`) nas 3 tabelas da revisão (Balancete, D.R.E. e Análise Vertical — cada uma com o seu, já que cada árvore tem estado de colapso próprio, mesmo motivo do botão "Restaurar formatação" que já existia), dentro do novo modificador `.dc-th-linha--inicio` (só troca o `justify-content` pra `flex-start`, já que aqui o botão vem antes do rótulo, e não colado na borda direita como o de restaurar). Não é um toggle: o caminho de volta é o próprio "Restaurar formatação padrão", na última coluna da mesma tabela.
|
||||
|
||||
Detalhe não-óbvio da implementação: expandir tudo **zera** o conjunto de grupos expandidos (`dc*Expandidos`) em vez de populá-lo com todos os grupos — com ele vazio, o destaque volta a sair de `dcUltimaLevaVisivel()`, que sem nada recolhido marca exatamente as folhas (as contas analíticas finais). Conferido contra a apuração real `2021`/`08-2026`: 133 contas visíveis e 74 destacadas, exatamente as 74 contas sem filhos. Popular o conjunto com todos os grupos destacaria quase toda linha da tabela, recaindo no mesmo "tudo destacado, nada se destaca" da rodada 140. Só frontend (HTML/CSS/JS), sem mudança de model/endpoint; o relatório "Gerar Dashboard" não ganhou esse botão nesta rodada.
|
||||
|
||||
@ -70,7 +70,23 @@ Diferente de `IndicadorApuracaoViewSet`/`ImportacaoPlanoSaudeViewSet` (onde a ch
|
||||
|
||||
**Nasce recolhida a partir do 3º segmento do código** (pedido explícito do usuário, pra reduzir a poluição visual de uma apuração com muitas contas analíticas — limiar ajustado numa rodada seguinte, ver abaixo): em vez de `renderRevisao()` reiniciar os dois `Set()` vazios (tudo expandido), `dcColapsoPadrao(itens, nivelFn)` os pré-popula com os ids de todo item que tem filhos **e** está no nível `PID_DC_NIVEL_ABERTO_PADRAO` (`2`) ou além — ex. a conta `1.01.01` (3 segmentos, nível 2) aparece aberta, mas seus filhos (`1.01.01.001`, nível 3) ficam ocultos até o contador clicar pra expandir; se expandido, um filho de nível 3 que também tenha netos nasce recolhido de novo pelo mesmo critério, então "nível 3 em diante" precisa sempre de um clique a mais, não só a primeira camada. Mesmo limiar aplicado à DRE, sobre `Math.max(0, linha.nivel)` — decisão confirmada com o usuário (a princípio o pedido citava só o Balancete, mas como a DRE reaproveita o mesmo algoritmo, o mesmo comportamento faz sentido nela também). O relatório "Gerar Dashboard" replica esse mesmo estado inicial (ver abaixo) — não é só a tela de revisão. `PID_DC_NIVEL_ABERTO_PADRAO` (JS) e `_CONTABIL_NIVEL_ABERTO_PADRAO` (`views.py`) são a mesma constante conceitual duplicada nos dois lados (um é SPA, o outro HTML renderizado uma vez) — mudar o limiar exige ajustar os dois.
|
||||
|
||||
**Destaque acompanha o último grupo expandido** (pedido explícito do usuário, mesma rodada do ajuste de limiar acima): ao expandir uma conta/linha, as linhas que acabaram de ficar visíveis (só os filhos **diretos**, não os netos — que continuam recolhidos pelo limiar acima) ganham um realce dourado (`.dc-conta-row--destaque`); se o contador expandir uma dessas linhas em seguida, o realce se move pros filhos dela, e o grupo destacado antes volta pra cor padrão — nunca acumula mais de uma "leva" destacada ao mesmo tempo. `dcContasDestaque`/`dcDreDestaque` (dois `Set()`, um por árvore, resetados em `renderRevisao()`) guardam só a leva mais recente; `dcFilhosDiretos(itens, nivelFn, id)` (função genérica, reaproveitada pelas duas árvores) varre a lista plana a partir do índice do item expandido e para no primeiro item de nível igual ou menor (fim do grupo), coletando só os de nível exatamente `pai+1`. O handler de clique do toggle decide o destino do destaque **antes** de checar se a ação foi expandir ou recolher (`estavaColapsada = colapsadas.has(id)` guardado antes de mutar o `Set`): expandir substitui `dcContasDestaque`/`dcDreDestaque` pelos filhos diretos recém-revelados; recolher só limpa (`new Set()`), já que nada novo foi exposto. Puramente visual, sem persistência — reseta a cada apuração aberta, sem afetar nenhum dado gravado.
|
||||
**Destaque acompanha todo grupo já expandido** (pedido explícito do usuário, mesma rodada do ajuste de limiar acima, com o mecanismo revisado na rodada 140 abaixo): ao expandir uma conta/linha, as linhas que acabaram de ficar visíveis (só os filhos **diretos**, não os netos — que continuam recolhidos pelo limiar acima) ganham um realce dourado (`.dc-conta-row--destaque`), e **mais nada** fica destacado enquanto houver grupo aberto. Dois `Set()` por árvore (os 6 resetados em `renderRevisao()` e no botão "Restaurar formatação"): `dcContasExpandidos`/`dcDreExpandidos`/`dcAvExpandidos` guardam os ids dos grupos que o contador expandiu manualmente e que continuam expandidos, e `dcContasDestaque`/`dcDreDestaque`/`dcAvDestaque` guardam o resultado **derivado** (as linhas de fato destacadas), sempre recalculado por `dcDestaqueGrupos(itens, nivelFn, colapsadas, expandidos)`:
|
||||
|
||||
- `expandidos` vazio (nada aberto ainda) → vale a leva padrão, `dcUltimaLevaVisivel(itens, nivelFn, colapsadas)`, mesma coisa do estado inicial de uma apuração recém-aberta.
|
||||
- `expandidos` com algo → destaque é **só** a união de `dcFilhosDiretos(itens, nivelFn, id)` de cada grupo aberto (função genérica reaproveitada pelas 3 árvores: varre a lista plana a partir do índice do item e para no primeiro item de nível igual ou menor, coletando só os de nível exatamente `pai+1`), descartando a leva padrão por completo.
|
||||
|
||||
O handler de clique do toggle guarda `estavaColapsada = colapsadas.has(id)` **antes** de mutar o `Set` de colapso, e então: expandir adiciona o `id` a `expandidos`; recolher remove o `id` **e todo descendente dele** (`dcDescendentes()`) de `expandidos` — um grupo aninhado que estava aberto dentro do que acabou de fechar deixa de contar pro destaque, senão o destaque apontaria pra linhas agora invisíveis e a árvore nunca voltaria ao estado padrão. Puramente visual, sem persistência — reseta a cada apuração aberta, sem afetar nenhum dado gravado.
|
||||
|
||||
**Bug real, rodada 140 — destaque de um grupo sumia ao expandir outro, e as duas primeiras correções não resolveram**: na versão original, expandir SUBSTITUÍA o `Set` de destaque pelos filhos diretos do grupo recém-aberto (empilhando o anterior numa pilha, restaurada ao recolher) — usuário reportou, com print de uma árvore de 3 níveis, que expandir uma segunda conta "apagava" o destaque da primeira, quando o esperado era as duas conviverem pra facilitar a validação em sequência. Duas tentativas falhas antes da correção final, ambas reportadas pelo usuário testando em produção (sempre com hard refresh + restart do servidor, então nunca foi cache):
|
||||
|
||||
1. **Somar os filhos revelados ao `Set` já existente** (mantendo o que estava): não mudou nada visualmente. Causa, confirmada simulando o algoritmo em Python contra as contas reais da apuração do usuário: o destaque inicial (`dcUltimaLevaVisivel`) já marca **praticamente toda conta de nível ≥ 2** — todas nascem recolhidas pelo limiar padrão, então cada uma é "fim de ramo visível" por si só. Somar os filhos revelados a essa base deixava a tabela inteira destacada, e com tudo destacado nada se destaca. O comportamento original só parecia funcionar porque o "substituir" limpava todo o resto da tabela.
|
||||
2. **Destacar a própria conta expandida** em vez dos filhos: o usuário esclareceu que destacar os filhos estava certo desde o começo — a única mudança pedida era acumular mais de um grupo.
|
||||
|
||||
Correção final é a descrita acima (`dcDestaqueGrupos()` com a base padrão **descartada** enquanto houver grupo aberto). Validada simulando o algoritmo em Python contra as contas reais da apuração `2021`/`08-2026`, reproduzindo o roteiro exato do usuário: expandir "CAIXA E EQUIVALENTES DE CAIXA" destaca só seus 2 filhos (resto da tabela limpo); expandir "CLIENTES" em seguida mantém os 2 primeiros e soma "DUPLICATAS A RECEBER"; fechar "CLIENTES" volta aos 2 primeiros; fechar "CAIXA" devolve exatamente o `Set` de destaque inicial (comparação de igualdade entre os dois conjuntos bateu). Mesmo ajuste replicado em `pidDcrArvore()` (`dashboard-contabil-relatorio.html`, réplica em JS puro desta mesma lógica no relatório "Gerar Dashboard", com `calculaDestaque()`/`expandidos`/`descendentes()` espelhando as funções do JS) — os dois lados são mantidos manualmente em sincronia, ver "Balancete e D.R.E. têm árvore recolhível igual à tela de revisão" abaixo.
|
||||
|
||||
**Botão "+" (expandir tudo) no cabeçalho da primeira coluna** (pedido explícito do usuário, rodada seguinte — a ideia inicial incluía um "−" que recolhesse um nível por vez, descartada pelo próprio usuário na mesma conversa, "poderia apenas um botão"): `.dc-expandir-tudo-btn` (`data-dc-expandir-tudo="balancete|dre|analise-vertical"`), dentro de um `.dc-th-linha.dc-th-linha--inicio` (modificador novo, só troca o `justify-content` pra `flex-start` — o botão vem **antes** do rótulo, ao contrário do "Restaurar formatação", que fica colado na borda direita da última coluna). Abre a árvore inteira de uma vez (`dc*Colapsadas = new Set()`), até a conta analítica mais funda, nas 3 tabelas (cada uma com o seu botão, mesmo motivo do botão de restaurar: estados de colapso independentes). **Não é um toggle** — o caminho de volta é o botão "Restaurar formatação padrão" que já existe na coluna "Observação" da mesma tabela.
|
||||
|
||||
Ponto não-óbvio: expandir tudo **zera** `dc*Expandidos` em vez de populá-lo com todos os grupos. Com o conjunto vazio, `dcDestaqueGrupos()` cai na leva padrão (`dcUltimaLevaVisivel`), que sem nada recolhido marca exatamente as **folhas** — validado contra a apuração real `2021`/`08-2026`: 133 contas visíveis, 74 destacadas, exatamente as 74 contas sem filhos (igualdade de conjuntos conferida). Popular `dc*Expandidos` com todos os grupos destacaria quase toda linha da tabela, que é o mesmo problema de "tudo destacado, nada se destaca" da tentativa falha nº 1 acima. O cabeçalho da Análise Vertical é montado em JS (`renderAnaliseVerticalHead()`, número de colunas varia com os meses), então lá o botão nasce no template string — nos outros dois é HTML fixo em `dashboard-contabil.html`; os listeners são delegados no `<thead>`, então sobrevivem ao `innerHTML` ser refeito a cada render.
|
||||
|
||||
**Card de achado expande a conta usada no apontamento** (`renderAchados()`, pedido explícito do usuário): `achado.conta` (id, já vem no payload de `/api/contabil-apuracoes/{id}/`, junto de `conta_codigo`/`conta_descricao`) é resolvido pra objeto completo procurando em `apuracaoAtual.contas` (`.find((c) => c.id === achado.conta)`) — sem chamada de API extra, já que a apuração inteira (contas + linhas de DRE + achados) já vem de uma vez só nesse endpoint. Só achados vinculados a uma conta específica ganham o botão "Ver conta usada no apontamento" (`.dc-achado-card__toggle-conta`) — as duas regras gerais (`balanceamento_ativo_passivo`/`debito_credito_divergente`, `conta` nulo no model) não têm uma conta única por trás, então não mostram o toggle. Expandido, mostra código/descrição/saldo anterior/débito/crédito/saldo atual da conta (`.dc-achado-card__conta`, um `<dl>` em grid). Estado de expansão (`dcAchadosContaExpandida`, um `Set()` de ids de achado) segue o mesmo padrão de `dcContasColapsadas`/`dcDreColapsadas` — reiniciado em `renderRevisao()`.
|
||||
|
||||
|
||||
@ -1835,9 +1835,17 @@
|
||||
gap: var(--space-2);
|
||||
}
|
||||
|
||||
/* "Expandir tudo" fica na PRIMEIRA coluna, antes do rótulo (o rótulo é que
|
||||
vai pra direita do botão), ao contrário de "Restaurar formatação", que
|
||||
fica na última coluna com o botão empurrado pra borda direita. */
|
||||
.dc-th-linha--inicio {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
/* Menor que o .icon-btn padrão (38px) — vive dentro de uma célula de
|
||||
cabeçalho de tabela, não pode competir em tamanho com o texto da coluna. */
|
||||
.dc-reset-formatacao-btn {
|
||||
.dc-reset-formatacao-btn,
|
||||
.dc-expandir-tudo-btn {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
flex-shrink: 0;
|
||||
|
||||
@ -916,8 +916,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
// do usuário pra não abrir a tela inteira na cor de grupo/total.
|
||||
dcContasDestaque = dcUltimaLevaVisivel(apuracao.contas, dcContaNivel, dcContasColapsadas);
|
||||
dcDreDestaque = dcUltimaLevaVisivel(apuracao.linhas_dre, (linha) => Math.max(0, linha.nivel), dcDreColapsadas);
|
||||
dcContasDestaqueHistorico = [];
|
||||
dcDreDestaqueHistorico = [];
|
||||
dcContasExpandidos = new Set();
|
||||
dcDreExpandidos = new Set();
|
||||
dcObsPainelAberto = { conta: null, dre: null, analise_vertical: null };
|
||||
dcObsEditandoId = null;
|
||||
dcAchadosContaExpandida = new Set();
|
||||
@ -946,7 +946,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
(linha) => Math.max(0, linha.nivel),
|
||||
dcAvColapsadas
|
||||
);
|
||||
dcAvDestaqueHistorico = [];
|
||||
dcAvExpandidos = new Set();
|
||||
|
||||
renderAchados();
|
||||
renderContas();
|
||||
@ -1259,22 +1259,43 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
return destaque;
|
||||
}
|
||||
|
||||
// Ids da última "leva" de linhas recém-reveladas por um clique de
|
||||
// expandir — pedido explícito do usuário: destacar as contas que
|
||||
// aparecem ao expandir um grupo, e mover o destaque (não acumular) pra a
|
||||
// leva mais recente conforme o contador vai expandindo mais fundo. Cada
|
||||
// clique de expandir SUBSTITUI esse conjunto, empilhando o que estava
|
||||
// destacado antes em dc*DestaqueHistorico; um clique de recolher desempilha
|
||||
// e restaura o destaque anterior (pedido explícito do usuário — fechar uma
|
||||
// leva revela de novo o destaque de onde se estava antes de abri-la, em vez
|
||||
// de simplesmente apagar o destaque). Um par conjunto+pilha por árvore, já
|
||||
// que Balancete e DRE são independentes.
|
||||
// Ids das linhas de fato destacadas agora (`.dc-conta-row--destaque`) —
|
||||
// derivado, nunca editado à mão: sai sempre de dcDestaqueGrupos() abaixo.
|
||||
let dcContasDestaque = new Set();
|
||||
let dcDreDestaque = new Set();
|
||||
let dcAvDestaque = new Set();
|
||||
let dcContasDestaqueHistorico = [];
|
||||
let dcDreDestaqueHistorico = [];
|
||||
let dcAvDestaqueHistorico = [];
|
||||
|
||||
// Ids dos grupos que o contador expandiu manualmente e que continuam
|
||||
// expandidos — entram no conjunto ao expandir, saem ao recolher (junto com
|
||||
// qualquer descendente do grupo recolhido, que volta a ficar invisível).
|
||||
// Um conjunto por árvore, já que Balancete/DRE/Análise Vertical são
|
||||
// independentes.
|
||||
let dcContasExpandidos = new Set();
|
||||
let dcDreExpandidos = new Set();
|
||||
let dcAvExpandidos = new Set();
|
||||
|
||||
// Destaque atual de uma árvore. Enquanto o contador não tiver expandido
|
||||
// nada, vale a leva padrão (dcUltimaLevaVisivel — toda linha que esconde
|
||||
// algo ou é folha genuína). A partir do primeiro clique de expandir, o
|
||||
// destaque passa a ser **só** a união dos filhos diretos dos grupos
|
||||
// expandidos manualmente, e mais nada.
|
||||
//
|
||||
// Esse "e mais nada" é o ponto: a leva padrão já marca praticamente toda
|
||||
// conta de nível ≥ 2 (nascem recolhidas, então toda uma é "fim de ramo"),
|
||||
// então somar os filhos revelados a ela deixava a tabela inteira destacada
|
||||
// — com tudo destacado, nada se destaca, que foi exatamente o efeito
|
||||
// reportado pelo usuário ("os filhos não ficaram em destaque"). Limpando o
|
||||
// resto, sobra o contraste de sempre; a diferença pro comportamento antigo
|
||||
// é que agora vários grupos abertos convivem, em vez de o mais recente
|
||||
// substituir o anterior.
|
||||
function dcDestaqueGrupos(itens, nivelFn, colapsadas, expandidos) {
|
||||
if (!expandidos.size) return dcUltimaLevaVisivel(itens, nivelFn, colapsadas);
|
||||
const destaque = new Set();
|
||||
expandidos.forEach((id) => {
|
||||
dcFilhosDiretos(itens, nivelFn, id).forEach((filhoId) => destaque.add(filhoId));
|
||||
});
|
||||
return destaque;
|
||||
}
|
||||
|
||||
// Filhos DIRETOS de um item (mesmo próximo nível, não os netos) — usado
|
||||
// pra saber quais linhas acabaram de ficar visíveis ao expandir `id`.
|
||||
@ -2132,16 +2153,17 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
if (toggleBtn) {
|
||||
const id = Number(toggleBtn.getAttribute("data-dc-conta-toggle"));
|
||||
const estavaColapsada = dcContasColapsadas.has(id);
|
||||
if (estavaColapsada) dcContasColapsadas.delete(id);
|
||||
else dcContasColapsadas.add(id);
|
||||
// Expandir empilha o destaque atual e troca pros filhos recém-revelados;
|
||||
// recolher desempilha e restaura o destaque de antes — ver dcContasDestaque acima.
|
||||
if (estavaColapsada) {
|
||||
dcContasDestaqueHistorico.push(dcContasDestaque);
|
||||
dcContasDestaque = dcFilhosDiretos(apuracaoAtual.contas, dcContaNivel, id);
|
||||
dcContasColapsadas.delete(id);
|
||||
dcContasExpandidos.add(id);
|
||||
} else {
|
||||
dcContasDestaque = dcContasDestaqueHistorico.pop() || new Set();
|
||||
dcContasColapsadas.add(id);
|
||||
dcContasExpandidos.delete(id);
|
||||
// Um grupo aninhado que estava aberto dentro deste some junto —
|
||||
// deixa de valer pro destaque enquanto o pai estiver recolhido.
|
||||
dcDescendentes(apuracaoAtual.contas, dcContaNivel, id).forEach((d) => dcContasExpandidos.delete(d.id));
|
||||
}
|
||||
dcContasDestaque = dcDestaqueGrupos(apuracaoAtual.contas, dcContaNivel, dcContasColapsadas, dcContasExpandidos);
|
||||
renderContas();
|
||||
return;
|
||||
}
|
||||
@ -2242,15 +2264,16 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
if (toggleBtn) {
|
||||
const id = Number(toggleBtn.getAttribute("data-dc-dre-toggle"));
|
||||
const estavaColapsada = dcDreColapsadas.has(id);
|
||||
if (estavaColapsada) dcDreColapsadas.delete(id);
|
||||
else dcDreColapsadas.add(id);
|
||||
const nivelFn = (linha) => Math.max(0, linha.nivel);
|
||||
if (estavaColapsada) {
|
||||
dcDreDestaqueHistorico.push(dcDreDestaque);
|
||||
dcDreDestaque = dcFilhosDiretos(apuracaoAtual.linhas_dre, nivelFn, id);
|
||||
dcDreColapsadas.delete(id);
|
||||
dcDreExpandidos.add(id);
|
||||
} else {
|
||||
dcDreDestaque = dcDreDestaqueHistorico.pop() || new Set();
|
||||
dcDreColapsadas.add(id);
|
||||
dcDreExpandidos.delete(id);
|
||||
dcDescendentes(apuracaoAtual.linhas_dre, nivelFn, id).forEach((d) => dcDreExpandidos.delete(d.id));
|
||||
}
|
||||
dcDreDestaque = dcDestaqueGrupos(apuracaoAtual.linhas_dre, nivelFn, dcDreColapsadas, dcDreExpandidos);
|
||||
renderDre();
|
||||
return;
|
||||
}
|
||||
@ -2281,7 +2304,14 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
const meses = apuracaoAtual.analise_vertical_meses || [];
|
||||
const row = document.getElementById("dc-av-head-row");
|
||||
row.innerHTML = `
|
||||
<th>Descrição</th>
|
||||
<th>
|
||||
<span class="dc-th-linha dc-th-linha--inicio">
|
||||
<button type="button" class="icon-btn dc-expandir-tudo-btn" data-dc-expandir-tudo="analise-vertical" aria-label="Expandir todas as linhas da Análise Vertical" title="Expandir todas as linhas até o último nível">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 5v14"/><path d="M5 12h14"/></svg>
|
||||
</button>
|
||||
Descrição
|
||||
</span>
|
||||
</th>
|
||||
${meses
|
||||
.map((mes) => {
|
||||
const label = pidDcEscapeHtml(pidDcFormatMesAnaliseVertical(mes));
|
||||
@ -2379,15 +2409,21 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
if (toggleBtn) {
|
||||
const id = Number(toggleBtn.getAttribute("data-dc-av-toggle"));
|
||||
const estavaColapsada = dcAvColapsadas.has(id);
|
||||
if (estavaColapsada) dcAvColapsadas.delete(id);
|
||||
else dcAvColapsadas.add(id);
|
||||
const nivelFn = (linha) => Math.max(0, linha.nivel);
|
||||
if (estavaColapsada) {
|
||||
dcAvDestaqueHistorico.push(dcAvDestaque);
|
||||
dcAvDestaque = dcFilhosDiretos(apuracaoAtual.linhas_analise_vertical, nivelFn, id);
|
||||
dcAvColapsadas.delete(id);
|
||||
dcAvExpandidos.add(id);
|
||||
} else {
|
||||
dcAvDestaque = dcAvDestaqueHistorico.pop() || new Set();
|
||||
dcAvColapsadas.add(id);
|
||||
dcAvExpandidos.delete(id);
|
||||
dcDescendentes(apuracaoAtual.linhas_analise_vertical, nivelFn, id).forEach((d) => dcAvExpandidos.delete(d.id));
|
||||
}
|
||||
dcAvDestaque = dcDestaqueGrupos(
|
||||
apuracaoAtual.linhas_analise_vertical,
|
||||
nivelFn,
|
||||
dcAvColapsadas,
|
||||
dcAvExpandidos
|
||||
);
|
||||
renderAnaliseVertical();
|
||||
return;
|
||||
}
|
||||
@ -2423,36 +2459,67 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
if (tab === "dashboard") await renderDashboardTab();
|
||||
});
|
||||
|
||||
// ---- Restaurar formatação padrão (Balancete/DRE/Análise Vertical) ----
|
||||
// Botão no canto direito da linha de cabeçalho de cada tabela — descarta
|
||||
// todo expandir/recolher manual feito pelo contador e recalcula o mesmo
|
||||
// estado inicial de dcColapsoPadrao()/dcUltimaLevaVisivel() usado quando a
|
||||
// apuração é aberta (ver renderRevisao). Cada árvore (Balancete/DRE/Análise
|
||||
// Vertical) tem seu próprio botão porque cada uma tem seu próprio estado de
|
||||
// colapso/destaque, independente das demais.
|
||||
// ---- Cabeçalho: "Expandir tudo" e "Restaurar formatação padrão" ----
|
||||
// Dois botões por tabela, em pontas opostas da linha de cabeçalho: "+" na
|
||||
// primeira coluna abre a árvore inteira (nada recolhido, até a conta
|
||||
// analítica mais funda), e o de restaurar, na coluna "Observação", descarta
|
||||
// todo expandir/recolher manual e recalcula o mesmo estado inicial de
|
||||
// dcColapsoPadrao()/dcUltimaLevaVisivel() usado quando a apuração é aberta
|
||||
// (ver renderRevisao) — é o caminho de volta do "+", já que ele não é um
|
||||
// toggle. Cada árvore (Balancete/DRE/Análise Vertical) tem o seu par,
|
||||
// porque cada uma tem seu próprio estado de colapso/destaque.
|
||||
//
|
||||
// Expandir tudo zera `dc*Expandidos` junto (não popula com todos os grupos):
|
||||
// com o conjunto vazio o destaque volta a sair de dcUltimaLevaVisivel(), que
|
||||
// sem nada recolhido marca exatamente as folhas — as contas analíticas do
|
||||
// último nível, que é o que interessa destacar com a árvore toda aberta.
|
||||
// Popular `dc*Expandidos` com todos os grupos destacaria quase toda linha da
|
||||
// tabela, o que na prática é o mesmo que não destacar nada (ver
|
||||
// dcDestaqueGrupos acima).
|
||||
document.getElementById("dc-contas-thead").addEventListener("click", (event) => {
|
||||
if (event.target.closest("[data-dc-expandir-tudo]")) {
|
||||
dcContasColapsadas = new Set();
|
||||
dcContasExpandidos = new Set();
|
||||
dcContasDestaque = dcUltimaLevaVisivel(apuracaoAtual.contas, dcContaNivel, dcContasColapsadas);
|
||||
renderContas();
|
||||
return;
|
||||
}
|
||||
if (!event.target.closest("[data-dc-reset-formatacao]")) return;
|
||||
dcContasColapsadas = dcColapsoPadrao(apuracaoAtual.contas, dcContaNivel);
|
||||
dcContasExpandidos = new Set();
|
||||
dcContasDestaque = dcUltimaLevaVisivel(apuracaoAtual.contas, dcContaNivel, dcContasColapsadas);
|
||||
dcContasDestaqueHistorico = [];
|
||||
renderContas();
|
||||
});
|
||||
|
||||
document.getElementById("dc-dre-thead").addEventListener("click", (event) => {
|
||||
if (!event.target.closest("[data-dc-reset-formatacao]")) return;
|
||||
const nivelFn = (linha) => Math.max(0, linha.nivel);
|
||||
if (event.target.closest("[data-dc-expandir-tudo]")) {
|
||||
dcDreColapsadas = new Set();
|
||||
dcDreExpandidos = new Set();
|
||||
dcDreDestaque = dcUltimaLevaVisivel(apuracaoAtual.linhas_dre, nivelFn, dcDreColapsadas);
|
||||
renderDre();
|
||||
return;
|
||||
}
|
||||
if (!event.target.closest("[data-dc-reset-formatacao]")) return;
|
||||
dcDreColapsadas = dcColapsoPadrao(apuracaoAtual.linhas_dre, nivelFn);
|
||||
dcDreExpandidos = new Set();
|
||||
dcDreDestaque = dcUltimaLevaVisivel(apuracaoAtual.linhas_dre, nivelFn, dcDreColapsadas);
|
||||
dcDreDestaqueHistorico = [];
|
||||
renderDre();
|
||||
});
|
||||
|
||||
document.getElementById("dc-av-thead").addEventListener("click", (event) => {
|
||||
if (!event.target.closest("[data-dc-reset-formatacao]")) return;
|
||||
const nivelFn = (linha) => Math.max(0, linha.nivel);
|
||||
if (event.target.closest("[data-dc-expandir-tudo]")) {
|
||||
dcAvColapsadas = new Set();
|
||||
dcAvExpandidos = new Set();
|
||||
dcAvDestaque = dcUltimaLevaVisivel(apuracaoAtual.linhas_analise_vertical, nivelFn, dcAvColapsadas);
|
||||
renderAnaliseVertical();
|
||||
return;
|
||||
}
|
||||
if (!event.target.closest("[data-dc-reset-formatacao]")) return;
|
||||
dcAvColapsadas = dcColapsoPadrao(apuracaoAtual.linhas_analise_vertical, nivelFn);
|
||||
dcAvExpandidos = new Set();
|
||||
dcAvDestaque = dcUltimaLevaVisivel(apuracaoAtual.linhas_analise_vertical, nivelFn, dcAvColapsadas);
|
||||
dcAvDestaqueHistorico = [];
|
||||
renderAnaliseVertical();
|
||||
});
|
||||
|
||||
|
||||
@ -443,11 +443,11 @@
|
||||
tr.dcr-linha-total td { font-weight: 700; }
|
||||
.dcr-row-in { animation: dcrFadeIn 220ms ease; }
|
||||
|
||||
/* Destaque temporário nas linhas recém-reveladas ao expandir um grupo —
|
||||
mesmo mecanismo de dc-conta-row--destaque em dashboard-contabil.js/css
|
||||
do Portal (ver ali o porquê: dá pra acompanhar visualmente o que acabou
|
||||
de aparecer ao expandir, e ao recolher de novo o destaque volta pra
|
||||
leva anterior, ver pidDcrArvore() mais abaixo). Este documento não tem
|
||||
/* Destaque nas linhas recém-reveladas ao expandir um grupo — mesmo
|
||||
mecanismo de dc-conta-row--destaque em dashboard-contabil.js/css do
|
||||
Portal (ver ali o porquê: dá pra acompanhar visualmente o que acabou
|
||||
de aparecer ao expandir; expandir mais de um grupo acumula o destaque
|
||||
de todos, ver pidDcrArvore() mais abaixo). Este documento não tem
|
||||
alternância de tema (é sempre a marca clara do escritório), então só
|
||||
existe a variante "clara": linhas fora do destaque ganham um leve
|
||||
tingimento roxo (substitui o zebra por linha par de antes, que ficava
|
||||
@ -1126,12 +1126,6 @@
|
||||
}
|
||||
});
|
||||
|
||||
// Histórico do destaque — mesmo espírito de dcContasDestaqueHistorico
|
||||
// em dashboard-contabil.js: cada expandir empilha o destaque atual e
|
||||
// troca pros filhos diretos recém-revelados; cada recolher desempilha
|
||||
// e restaura o destaque de antes, em vez de simplesmente apagar.
|
||||
var historico = [];
|
||||
|
||||
function filhosDiretos(id) {
|
||||
var idx = linhas.findIndex(function (tr) {
|
||||
return tr.getAttribute("data-dcr-id") === id;
|
||||
@ -1147,6 +1141,27 @@
|
||||
return filhos;
|
||||
}
|
||||
|
||||
// Todos os descendentes (filhos, netos...) de uma linha — usado pra
|
||||
// tirar do destaque um grupo aninhado que estava aberto dentro de um
|
||||
// grupo que acabou de ser recolhido.
|
||||
function descendentes(id) {
|
||||
var idx = linhas.findIndex(function (tr) {
|
||||
return tr.getAttribute("data-dcr-id") === id;
|
||||
});
|
||||
if (idx === -1) return [];
|
||||
var nivelPai = Number(linhas[idx].getAttribute("data-dcr-nivel"));
|
||||
var resultado = [];
|
||||
for (var j = idx + 1; j < linhas.length; j++) {
|
||||
if (Number(linhas[j].getAttribute("data-dcr-nivel")) <= nivelPai) break;
|
||||
resultado.push(linhas[j].getAttribute("data-dcr-id"));
|
||||
}
|
||||
return resultado;
|
||||
}
|
||||
|
||||
// Ids dos grupos expandidos manualmente e ainda abertos — ver
|
||||
// dcContasExpandidos/dcDestaqueGrupos em dashboard-contabil.js.
|
||||
var expandidos = {};
|
||||
|
||||
// Destaque inicial (antes de qualquer clique) — pedido explícito do
|
||||
// usuário depois de notar que folha genuína (linha sem filho
|
||||
// nenhum, ex. "(-) SIMPLES NACIONAL") ficava de fora do destaque
|
||||
@ -1190,7 +1205,24 @@
|
||||
return resultado;
|
||||
}
|
||||
|
||||
var destaque = calculaDestaqueInicial();
|
||||
// Enquanto nada tiver sido expandido, vale a leva padrão acima; a
|
||||
// partir do primeiro clique de expandir, o destaque é só a união dos
|
||||
// filhos diretos dos grupos abertos (vários convivem) — mesma regra
|
||||
// de dcDestaqueGrupos() em dashboard-contabil.js, inclusive o porquê
|
||||
// de descartar a leva padrão nesse caso (ver comentário lá).
|
||||
function calculaDestaque() {
|
||||
var abertos = Object.keys(expandidos);
|
||||
if (!abertos.length) return calculaDestaqueInicial();
|
||||
var resultado = {};
|
||||
abertos.forEach(function (id) {
|
||||
Object.keys(filhosDiretos(id)).forEach(function (filhoId) {
|
||||
resultado[filhoId] = true;
|
||||
});
|
||||
});
|
||||
return resultado;
|
||||
}
|
||||
|
||||
var destaque = calculaDestaque();
|
||||
|
||||
function aplicaDestaque() {
|
||||
linhas.forEach(function (tr) {
|
||||
@ -1226,11 +1258,15 @@
|
||||
colapsadas[id] = !estavaColapsada;
|
||||
btn.classList.toggle("is-expanded", !colapsadas[id]);
|
||||
if (estavaColapsada) {
|
||||
historico.push(destaque);
|
||||
destaque = filhosDiretos(id);
|
||||
expandidos[id] = true;
|
||||
} else {
|
||||
destaque = historico.pop() || {};
|
||||
delete expandidos[id];
|
||||
// Um grupo aninhado aberto dentro deste some junto do destaque.
|
||||
descendentes(id).forEach(function (descendenteId) {
|
||||
delete expandidos[descendenteId];
|
||||
});
|
||||
}
|
||||
destaque = calculaDestaque();
|
||||
aplicaDestaque();
|
||||
atualiza();
|
||||
});
|
||||
@ -1295,7 +1331,7 @@
|
||||
if (toggleBtn) toggleBtn.classList.toggle("is-expanded", !padrao);
|
||||
tr.classList.remove("dcr-row-flash");
|
||||
});
|
||||
historico = [];
|
||||
expandidos = {};
|
||||
destaque = calculaDestaqueInicial();
|
||||
aplicaDestaque();
|
||||
atualiza();
|
||||
|
||||
@ -460,7 +460,14 @@
|
||||
<table class="pa-table dc-contas-table">
|
||||
<thead id="dc-contas-thead">
|
||||
<tr>
|
||||
<th>Conta</th>
|
||||
<th>
|
||||
<span class="dc-th-linha dc-th-linha--inicio">
|
||||
<button type="button" class="icon-btn dc-expandir-tudo-btn" data-dc-expandir-tudo="balancete" aria-label="Expandir todas as contas do Balancete" title="Expandir todas as contas até o último nível">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 5v14"/><path d="M5 12h14"/></svg>
|
||||
</button>
|
||||
Conta
|
||||
</span>
|
||||
</th>
|
||||
<th>Classificação</th>
|
||||
<th>Descrição</th>
|
||||
<th>Saldo Anterior</th>
|
||||
@ -496,7 +503,14 @@
|
||||
<table class="pa-table dc-dre-table">
|
||||
<thead id="dc-dre-thead">
|
||||
<tr>
|
||||
<th>Descrição</th>
|
||||
<th>
|
||||
<span class="dc-th-linha dc-th-linha--inicio">
|
||||
<button type="button" class="icon-btn dc-expandir-tudo-btn" data-dc-expandir-tudo="dre" aria-label="Expandir todas as linhas da DRE" title="Expandir todas as linhas até o último nível">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><path d="M12 5v14"/><path d="M5 12h14"/></svg>
|
||||
</button>
|
||||
Descrição
|
||||
</span>
|
||||
</th>
|
||||
<th>Valor</th>
|
||||
<th>
|
||||
<span class="dc-th-linha">Observação
|
||||
|
||||
Loading…
Reference in New Issue
Block a user