Install any skill in seconds. Free to start, no credit card required.
Get Started Free →This skill should be used when the user asks for patterns, best practices, creation, or fixing of Sankhya dashboards using HTML, JSP, Java, and SQL.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 135% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 63% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 125% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 187% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 190% | 0% |
To provide a consolidated guide of patterns and best practices for creating and maintaining dashboards, SQL queries, BI parameterization, and UI/UX within the Sankhya ecosystem (JSP/HTML/Java).
This skill should be used when:
Aplicar padrões de JSP/JSTL e organização server-side para reduzir erros de compilação, falhas de renderização e regressões em dashboards/telas.
Diretrizes de implementação
isELIgnored="false" para habilitar ${...} em tempo de renderização.core_rt para JSTL core no ecossistema Sankhya.c:if, c:choose, c:forEach).localStorage (ordem de colunas e ordenação).c:set para evitar Erro 500 no servidor Java do Sankhya.<script>. Utilizar containers HTML ocultos para passar dados ao JavaScript, mantendo a saúde do editor de código (IDE Linting).> Os nomes de tabelas e campos abaixo são representativos e podem variar conforme a implementação da instância.
jsp<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false" %> <%@ taglib prefix="snk" uri="/WEB-INF/tld/sankhyaUtil.tld" %> <%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <snk:load />
Carregamento de assets em dashboard/gadget
contextPath + BASE_FOLDER.openLevel), manter caminho absoluto para evitar quebra de resolução.html<script src="${pageContext.request.contextPath}/${BASE_FOLDER}/js/app.js"></script> <link rel="stylesheet" href="${pageContext.request.contextPath}/${BASE_FOLDER}/css/style.css" />
Consumo seguro de snk:query
query.rows (não no objeto raiz).empty query.rows.jsp<snk:query var="qDados"> SELECT CAB.NUNOTA, CAB.CODPARC FROM TGFCAB CAB </snk:query> <c:choose> <c:when test="${empty qDados.rows}"> <span>Sem resultados</span> </c:when> <c:otherwise> <c:forEach var="linha" items="${qDados.rows}"> ${linha.NUNOTA} </c:forEach> </c:otherwise> </c:choose>
Sanitização de parâmetros antes da SQL
" e ") antes de injetar em query.jsp<c:set var="raw_codusu" value="${empty param.P_CODUSU ? '0' : param.P_CODUSU}" /> <c:set var="codusu_limpo" value="${fn:replace(raw_codusu, '\"', '')}" /> <c:set var="codusu_limpo" value="${fn:replace(codusu_limpo, '"', '')}" /> <c:set var="codusu_seguro" value="${empty codusu_limpo ? '0' : codusu_limpo}" /> <snk:query var="qAcessos"> SELECT CODUSU, NOMEUSU FROM TSIUSU WHERE CODUSU = :codusu_seguro </snk:query>
Estado de tela e lazy-load em dashboard único
jsvar dadosGlobais = []; var produtoAtual = null; var abaCarregada = {}; function abrirDetalhe(dado) { produtoAtual = dado; abaCarregada = {}; trocarAba("estoque"); } function trocarAba(aba) { if (aba === "estoque" && !abaCarregada.estoque) carregarAbaEstoque(produtoAtual.CODPROD); if (aba === "pedidos" && !abaCarregada.pedidos) carregarAbaPedidos(produtoAtual.CODPROD); if (aba === "parceiros" && !abaCarregada.parceiros) carregarAbaParceiros(produtoAtual.CODPROD); }
Exemplo de Blindagem e Separação de Camadas
jsp<%-- 1. Blindagem no topo do arquivo --%> <c:set var="v_salesagent" value="${empty param.SALESAGENT ? '0' : param.SALESAGENT}" /> <%-- 2. Container oculto para dados (Separação JSP vs JS) --%> <div id="data-container" style="display:none;"> [ <c:forEach var="row" items="${qDados.rows}" varStatus="loop"> { "id": ${row.ID}, "nome": "${fn:replace(row.NOME, '"', '\\"')}" }${!loop.last ? ',' : ''} </c:forEach> ] </div> <script> // 3. JS apenas lê os dados do container const rawData = document.getElementById('data-container').textContent.trim(); const myData = rawData ? JSON.parse(rawData) : []; </script>
Padronizar identidade visual em componentes BI para consistência entre gadgets HTML5, tabelas e indicadores.
Diretrizes de UI/UX
--color-*) para evitar valores espalhados.BKCOLOR, FGCOLOR) quando necessário.> Os nomes de tabelas e campos abaixo são representativos e podem variar conforme a implementação da instância.
html<style> :root { --color-bg: #F5F7FA; --color-surface: #FFFFFF; --color-text: #1F2937; --color-success: #1A7F37; --color-warning: #B26A00; --color-danger: #B42318; --color-accent: #0E5A8A; } .card { background: var(--color-surface); color: var(--color-text); border-radius: 8px; padding: 12px; } </style>
sqlSELECT V.CODMETA, V.VALOR_ATUAL, V.VALOR_META, CASE WHEN V.VALOR_ATUAL >= V.VALOR_META THEN '#1A7F37' ELSE '#B42318' END AS BKCOLOR, '#FFFFFF' AS FGCOLOR FROM AD_DADOS_VENDA V
html<style> #tblDados thead th { position: sticky; top: 0; z-index: 4; } #tblDados .col-fixa-1 { position: sticky; left: 0; z-index: 3; } #tblDados .col-fixa-2 { position: sticky; left: var(--fix-col-1-width); z-index: 2; } .row-aprovacao td { background: #ffe8cc; color: #7a3a00; } .row-parcial td { background: #fff4c4; color: #5e4c00; } </style>
Estruturar exploração de dados com foco em performance, legibilidade e mapeamento correto de entidades Sankhya.
Boas práticas de exploração (DBExplorer)
DBEXPMAXROW) para evitar carga excessiva.SELECT * em tabelas com campos volumosos (BLOB/CLOB).Mapas essenciais do ecossistema
TDDTAB, TDDCAM, TDDOPC, TDDINS, TDDLIG.TGFCAB, TGFITE, TGFTOP, TGFPAR, TGFPRO, TGFEST, TGFVAR.TSIUSU, TSIGRU, TSIACI, TSIIMP.Padrões de SQL recomendados
CODTIPOPER + data de alteração (DHTIPOPER/DHALTER).(... = :P_PARAM OR :P_PARAM IS NULL).> Os nomes de tabelas e campos abaixo são representativos e podem variar conforme a implementação da instância.
sqlSELECT CAB.NUNOTA, CAB.CODPARC, CAB.DTNEG, ITE.SEQUENCIA, ITE.CODPROD, (ITE.VLRTOT - ITE.VLRDESC) AS VLR_LIQUIDO FROM TGFCAB CAB JOIN TGFITE ITE ON ITE.NUNOTA = CAB.NUNOTA JOIN TGFTOP TOP ON TOP.CODTIPOPER = CAB.CODTIPOPER AND TOP.DHALTER = CAB.DHTIPOPER WHERE (CAB.CODPARC = :P_CODPARC OR :P_CODPARC IS NULL) AND (CAB.CODVEND = :P_CODVEND OR :P_CODVEND IS NULL)
sqlSELECT U.CODUSU, U.NOMEUSU, G.NOMEGRUPO, A.CODREL, I.NOME AS DESCRICAO_RECURSO, A.CONS, A.ALTERA FROM TSIUSU U JOIN TSIGRU G ON G.CODGRUPO = U.CODGRUPO JOIN TSIACI A ON A.CODGRUPO = U.CODGRUPO JOIN TSIIMP I ON I.CODREL = A.CODREL WHERE U.CODUSU = :P_CODUSU ORDER BY I.NOME
Aplicar fluxo de desenvolvimento de componentes HTML5 no BI para garantir renderização, reatividade e navegação entre níveis.
Estrutura e publicação
.zip com index.html como entrada principal.assets/ (CSS, JS, libs, imagens).Fluxo de dados e parâmetros
: para bind padrão.:# para substituição literal (avaliar com cautela e validação).:@ para literal textual em cenários como LIKE./*inCollection*/.> Os nomes de tabelas e campos abaixo são representativos e podem variar conforme a implementação da instância.
sqlSELECT C.CODCID, C.NOMECID, C.UF FROM AD_TABELA_EXEMPLO C WHERE /*inCollection*/ C.CODCID IN :P_CODCID /*inCollection*/
Reatividade e ciclo de vida
DOMContentLoaded em conteúdo injetado.html<script> function renderizarComponente(dados) { // Atualizar DOM, gráficos e KPIs com os dados recebidos } function iniciar() { const dadosIniciais = window.snkBIData || []; renderizarComponente(dadosIniciais); } setTimeout(iniciar, 300); </script>
Drill-down e eventos
Navegação multi-nível (openLevel e contrato de contexto)
NIVEL_RESUMO, NIVEL_DETALHE, NIVEL_ITEM) para evitar acoplamento em string solta.openLevel em funções dedicadas por rota de navegação (ex.: abrir detalhe por vendedor, abrir itens por parceiro).ARG_* para chaves e P_* para filtros/período).openLevel e parâmetros obrigatórios antes de navegar.jsvar cfg = window.DASH_CONFIG || {}; var NIVEL_DETALHE = cfg.NIVEL_DETALHE || "NIVEL_B"; var NIVEL_ITEM = cfg.NIVEL_ITEM || "NIVEL_C"; function abrirNivelDetalhe(codigoEntidade) { if (!codigoEntidade || typeof openLevel !== "function") return; openLevel(NIVEL_DETALHE, { ARG_CODENT: parseInt(codigoEntidade, 10), P_PERIODO_INI: cfg.P_PERIODO_INI || "", P_PERIODO_FIN: cfg.P_PERIODO_FIN || "", P_CODMETA: cfg.P_CODMETA || "" }); } function abrirNivelItem(codigoEntidadeFilha) { if (!codigoEntidadeFilha || typeof openLevel !== "function") return; openLevel(NIVEL_ITEM, { ARG_CODENT_FILHA: parseInt(codigoEntidadeFilha, 10), P_PERIODO_INI: cfg.P_PERIODO_INI || "", P_PERIODO_FIN: cfg.P_PERIODO_FIN || "", P_CODMETA: cfg.P_CODMETA || "" }); }
Segurança e bloqueio de acesso por escopo
WHERE para reaproveitamento em KPIs, grids e gráficos.CODUSU_LOG ou função equivalente de usuário logado) para evitar spoof de parâmetro de usuário.> Os nomes de tabelas e campos abaixo são representativos e podem variar conforme a implementação da instância.
sqlSELECT M.CODMETA, M.CODENTIDADE, SUM(M.VLRPREV) AS VLR_PREV, SUM(M.VLRREAL) AS VLR_REAL FROM AD_DADOS_META M WHERE M.CODMETA = :P_CODMETA AND M.DTREF BETWEEN TO_DATE(:P_PERIODO_INI, 'DD/MM/YYYY') AND TO_DATE(:P_PERIODO_FIN, 'DD/MM/YYYY') AND EXISTS ( SELECT 1 FROM AD_META_USUARIO_LIB L WHERE L.CODMETA = M.CODMETA AND L.CODUSU = STP_GET_CODUSULOGADO ) GROUP BY M.CODMETA, M.CODENTIDADE
Grid hierárquica com expansão/colapso
filhosPorPai e estado nosExpandidos para renderização incremental da árvore.jsvar filhosPorPai = {}; var nosExpandidos = {}; function alternarNo(codNo) { var id = String(codNo); nosExpandidos[id] = !nosExpandidos[id]; renderizarGrid(); } function obterVisiveis(raiz) { var lista = []; function visitar(pai) { (filhosPorPai[pai] || []).forEach(function (no) { lista.push(no); if (nosExpandidos[String(no.CODNO)]) visitar(String(no.CODNO)); }); } visitar(String(raiz || "")); return lista; }
Resiliência de carregamento
vazio) sem derrubar o layout inteiro.Navegação intra-nível (single JSP)
jsfunction abrirTelaNativa(resourceIdBase64, pkObj) { var pk = btoa(JSON.stringify(pkObj)); top.location.href = "/mge/system.jsp#app/" + resourceIdBase64 + "/" + pk + "&pk-refresh=" + Date.now(); } function onKpiClick(lista) { abrirModalLista("Itens selecionados", "Navegação por atalho", lista); } function onGraficoClick(grupo) { filtrarTabelaPorGrupo(grupo); }
Feedback operacional de interface
executeQuery.Variáveis internas de segurança
CODUSU_LOG, CODGRU_LOG, CODVEN_LOG).Other measured skills in the registry, with their headline benchmark lift.