From d732aabe534bd4ced1c8d5aaa937de2661e49741 Mon Sep 17 00:00:00 2001 From: tkinaba Date: Thu, 14 May 2026 17:04:02 -0300 Subject: [PATCH] feat(ai): adicionar nome do parametro aos filtros --- src/flash/flash.module.ts | 535 +++++++++++++++++++------------------- 1 file changed, 271 insertions(+), 264 deletions(-) diff --git a/src/flash/flash.module.ts b/src/flash/flash.module.ts index 2730238..9b9fa3d 100644 --- a/src/flash/flash.module.ts +++ b/src/flash/flash.module.ts @@ -3,201 +3,202 @@ import { createModuleFactory } from "@davinti/jeff"; const moduleFactory = createModuleFactory(["C5", "C5_big", "C5_mambo"]); export default moduleFactory - .createModule({ - id: "flash-de-vendas", - description: "Flash de Vendas", - label: "Flash de Vendas", - icon: "bar-chart", - ai : { - topics : { - flash_vendas_big : { - descricao: "Consulta e análise do relatório Flash de Vendas. Permite visualizar metas do mês, vendas do mês atual, variações e projeções, além de comparativos com o mês anterior e ano anterior. Útil para projeção de batimento de meta, ranking de lojas e comparativos de performance.", - prompt: { - prompt_persona: "Você é um Especialista em Dados e Extrator de Filtros de alto nível. Sua única tarefa é analisar a solicitação do usuário sobre desempenho de vendas (Flash de Vendas), identificar quais informações ele deseja buscar (como data de referência ou loja) e como deseja visualizar esses dados (agrupamento), preparando as variáveis exatas para o sistema de relatórios.", - prompt_tarefa: "1. Identificação de Filtros: Extraia a data de referência (geralmente hoje) e identifique se o usuário quer ver dados de uma loja específica. A fonte de dados apenas suporta filtro de 'data' e 'loja'.\n2. Identificação de Agrupamento: Verifique se o usuário deseja visualizar o total geral (agrupamento vazio) ou agrupar por loja (ex: 'Qual loja está mais distante da meta?'). A query não suporta agrupamentos por divisão, segmento ou categoria.\n3. Identificação do Propósito Analítico:\n - Se perguntar 'Vou bater a meta do mês?', a IA final deverá calcular a média de venda diária (realizado / dias corridos), projetar o fechamento (média * dias do mês), comparar com a meta e exibir o gap.\n - Se perguntar 'Qual loja está mais distante da meta?', a IA final deverá criar um ranking ordenando as lojas pelo percentual de atingimento.\n - Se perguntar comparativos temporais ('mês passado' ou 'ano passado'), a IA final fará o comparativo direto em valor e percentual.", - prompt_regras_gerais: "- Extraia listas de lojas se múltiplas forem solicitadas (ex: 'loja A e loja B').\n- Se não houver solicitação explícita ou implícita de agrupamento por loja, não preencha a chave de agrupamento, mantendo-a vazia.\n- Não invente filtros ou agrupamentos (como divisão, segmento) que não existem na configuração.", - prompt_regras_contexto: "- Nunca analise a mensagem de forma isolada se ela for um refinamento (ex: 'E como foi o ano passado?'). Use o histórico para resgatar os filtros anteriores.\n- Não invente valores para os filtros se não forem fornecidos na conversa.", - prompt_exemplos: "*Exemplo 1:*\n- Usuário: 'Vou bater a meta do mês?'\n- Raciocínio: Não há filtro de loja explícito (visão global). Nenhum agrupamento solicitado. A IA apenas extrairá os totais para calcular a projeção e gap com a meta.\n\n*Exemplo 2:*\n- Usuário: 'Qual loja está mais distante da meta?'\n- Raciocínio: Há um pedido implícito de agrupamento por 'loja'. O sistema irá consolidar os dados de todas as lojas para montar o ranking das mais distantes (menor atingimento percentual).\n\n*Exemplo 3:*\n- Usuário: 'Como estamos em relação ao mês passado?'\n- Raciocínio: Nenhuma quebra solicitada, exceto se for contexto anterior. O foco é a comparação de mes_atual vs mes_anterior em valor e percentual.", - prompt_outras_infos: "Atenção: A query subjacente fornece apenas totalizações gerais ou por loja. Qualquer pedido de quebra por divisão, regional ou segmento não pode ser atendido. A lógica de projeção (diária * total dias), gap de valor e ranking de percentual ficam a cargo do processamento final baseado nas colunas mes_atual, meta_mes, mes_anterior e ano_anterior retornadas.", - prompt_saida: "Sua resposta deve ser uma análise detalhada e objetiva dos dados recebidos, apresentando os principais insights de forma clara e concisa." - }, - json_params_saida: { - agrupamentos: [ - { - "nome_parametro": "loja", - coluna_vtr: "x.codigo" - } - ], - filtros: { - data_venda: { - descricao_agente: "A data base para a consulta das vendas. Caso não informada explicitamente, usar a data de hoje no formato YYYY-MM-DD.", - coluna_vtr: "args.data_venda", - }, - loja: { - descricao_agente: "Lista de nomes ou códigos de lojas mencionados para filtragem.", - coluna_vtr: "x.nomeempresaapp", - tabela_rag: "tb_flash_nodo" - } - } - }, - query_base : "flash_vendas_ai" - }, - } - }, - queries: { - flash: { - name: "Flash de Vendas", - display: { - type: "flash", - settings: { - group_column: "canalapp", - total_indicator_column: "is_total", - null_label_key: "Geral", - }, - header: { - title_column: "canalapp", - value_column: "venda_dia", - value_format: "currency", - }, - rows: [ - { - label: "Meta Mês", - column: "meta_mes", - format: "currency_short", - }, - { - label: "Mês Atual", - column: "mes_atual", - format: "currency_short", - }, - { - label: "Dif ($)", - column: "dif_mes_atual", - format: "currency_short", - }, - { - label: "% Variação", - column: "variacao_atual", - format: "percentage", - }, - { - label: "Mês Anterior", - column: "mes_anterior", - format: "currency_short", - }, - { - label: "Dif ($)", - column: "dif_mes_anterior", - format: "currency_short", - }, - { - label: "% Variação", - column: "variacao_mes_anterior", - format: "percentage", - }, - { - label: "Ano Anterior", - column: "ano_anterior", - format: "currency_short", - }, - { - label: "Dif ($)", - column: "dif_ano_anterior", - format: "currency_short", - }, - { - label: "% Variação", - column: "variacao_ano_anterior", - format: "percentage", - }, - ], - }, - params: ["data_venda"], - }, - flash_categorias: { - name: "Flash de Vendas por Categorias", - display: { - type: "flash", - settings: { - group_column: "categoriaapp", - total_indicator_column: "is_total", - null_label_key: "Geral", - }, - header: { - title_column: "categoriaapp", - value_column: "venda_dia", - value_format: "currency", - }, - rows: [ - { - label: "Meta Mês", - column: "meta_mes", - format: "currency_short", - }, - { - label: "Mês Atual", - column: "mes_atual", - format: "currency_short", - }, - { - label: "Dif ($)", - column: "dif_mes_atual", - format: "currency_short", - }, - { - label: "% Variação", - column: "variacao_atual", - format: "percentage", - }, - { - label: "Mês Anterior", - column: "mes_anterior", - format: "currency_short", - }, - { - label: "Dif ($)", - column: "dif_mes_anterior", - format: "currency_short", - }, - { - label: "% Variação", - column: "variacao_mes_anterior", - format: "percentage", - }, - { - label: "Ano Anterior", - column: "ano_anterior", - format: "currency_short", - }, - { - label: "Dif ($)", - column: "dif_ano_anterior", - format: "currency_short", - }, - { - label: "% Variação", - column: "variacao_ano_anterior", - format: "percentage", - }, - ], - }, - params: ["data_venda", "codigo_categoria_pai", "cod_empresa"], - }, - flash_vendas_ai : { - name : " Flash de vendas AI", - display: { - type: "none" - }, - params: ["data_venda", "agrupamento"] - } - }, - entrypoint: "flash" as "flash" | "flash_categorias", - }) - .withImplementations({ - C5: { - flash: (args) => { - return { - sql: /*sql*/ ` + .createModule({ + id: "flash-de-vendas", + description: "Flash de Vendas", + label: "Flash de Vendas", + icon: "bar-chart", + ai: { + topics: { + flash_vendas_big: { + descricao: "Consulta e análise do relatório Flash de Vendas. Permite visualizar metas do mês, vendas do mês atual, variações e projeções, além de comparativos com o mês anterior e ano anterior. Útil para projeção de batimento de meta, ranking de lojas e comparativos de performance.", + prompt: { + prompt_persona: "Você é um Especialista em Dados e Extrator de Filtros de alto nível. Sua única tarefa é analisar a solicitação do usuário sobre desempenho de vendas (Flash de Vendas), identificar quais informações ele deseja buscar (como data de referência ou loja) e como deseja visualizar esses dados (agrupamento), preparando as variáveis exatas para o sistema de relatórios.", + prompt_tarefa: "1. Identificação de Filtros: Extraia a data de referência (geralmente hoje) e identifique se o usuário quer ver dados de uma loja específica. A fonte de dados apenas suporta filtro de 'data' e 'loja'.\n2. Identificação de Agrupamento: Verifique se o usuário deseja visualizar o total geral (agrupamento vazio) ou agrupar por loja (ex: 'Qual loja está mais distante da meta?'). A query não suporta agrupamentos por divisão, segmento ou categoria.\n3. Identificação do Propósito Analítico:\n - Se perguntar 'Vou bater a meta do mês?', a IA final deverá calcular a média de venda diária (realizado / dias corridos), projetar o fechamento (média * dias do mês), comparar com a meta e exibir o gap.\n - Se perguntar 'Qual loja está mais distante da meta?', a IA final deverá criar um ranking ordenando as lojas pelo percentual de atingimento.\n - Se perguntar comparativos temporais ('mês passado' ou 'ano passado'), a IA final fará o comparativo direto em valor e percentual.", + prompt_regras_gerais: "- Extraia listas de lojas se múltiplas forem solicitadas (ex: 'loja A e loja B').\n- Se não houver solicitação explícita ou implícita de agrupamento por loja, não preencha a chave de agrupamento, mantendo-a vazia.\n- Não invente filtros ou agrupamentos (como divisão, segmento) que não existem na configuração.", + prompt_regras_contexto: "- Nunca analise a mensagem de forma isolada se ela for um refinamento (ex: 'E como foi o ano passado?'). Use o histórico para resgatar os filtros anteriores.\n- Não invente valores para os filtros se não forem fornecidos na conversa.", + prompt_exemplos: "*Exemplo 1:*\n- Usuário: 'Vou bater a meta do mês?'\n- Raciocínio: Não há filtro de loja explícito (visão global). Nenhum agrupamento solicitado. A IA apenas extrairá os totais para calcular a projeção e gap com a meta.\n\n*Exemplo 2:*\n- Usuário: 'Qual loja está mais distante da meta?'\n- Raciocínio: Há um pedido implícito de agrupamento por 'loja'. O sistema irá consolidar os dados de todas as lojas para montar o ranking das mais distantes (menor atingimento percentual).\n\n*Exemplo 3:*\n- Usuário: 'Como estamos em relação ao mês passado?'\n- Raciocínio: Nenhuma quebra solicitada, exceto se for contexto anterior. O foco é a comparação de mes_atual vs mes_anterior em valor e percentual.", + prompt_outras_infos: "Atenção: A query subjacente fornece apenas totalizações gerais ou por loja. Qualquer pedido de quebra por divisão, regional ou segmento não pode ser atendido. A lógica de projeção (diária * total dias), gap de valor e ranking de percentual ficam a cargo do processamento final baseado nas colunas mes_atual, meta_mes, mes_anterior e ano_anterior retornadas.", + prompt_saida: "Sua resposta deve ser uma análise detalhada e objetiva dos dados recebidos, apresentando os principais insights de forma clara e concisa." + }, + json_params_saida: { + agrupamentos: [ + { + "nome_parametro": "loja", + coluna_vtr: "x.codigo" + } + ], + filtros: { + data_venda: { + descricao_agente: "A data base para a consulta das vendas. Caso não informada explicitamente, usar a data de hoje no formato YYYY-MM-DD.", + coluna_vtr: "data_referencia", + nome_parametro: "data_venda", + }, + loja: { + descricao_agente: "Lista de nomes ou códigos de lojas mencionados para filtragem.", + coluna_vtr: "x.nomeempresaapp", + tabela_rag: "tb_flash_nodo" + } + } + }, + query_base: "flash_vendas_ai" + }, + } + }, + queries: { + flash: { + name: "Flash de Vendas", + display: { + type: "flash", + settings: { + group_column: "canalapp", + total_indicator_column: "is_total", + null_label_key: "Geral", + }, + header: { + title_column: "canalapp", + value_column: "venda_dia", + value_format: "currency", + }, + rows: [ + { + label: "Meta Mês", + column: "meta_mes", + format: "currency_short", + }, + { + label: "Mês Atual", + column: "mes_atual", + format: "currency_short", + }, + { + label: "Dif ($)", + column: "dif_mes_atual", + format: "currency_short", + }, + { + label: "% Variação", + column: "variacao_atual", + format: "percentage", + }, + { + label: "Mês Anterior", + column: "mes_anterior", + format: "currency_short", + }, + { + label: "Dif ($)", + column: "dif_mes_anterior", + format: "currency_short", + }, + { + label: "% Variação", + column: "variacao_mes_anterior", + format: "percentage", + }, + { + label: "Ano Anterior", + column: "ano_anterior", + format: "currency_short", + }, + { + label: "Dif ($)", + column: "dif_ano_anterior", + format: "currency_short", + }, + { + label: "% Variação", + column: "variacao_ano_anterior", + format: "percentage", + }, + ], + }, + params: ["data_venda"], + }, + flash_categorias: { + name: "Flash de Vendas por Categorias", + display: { + type: "flash", + settings: { + group_column: "categoriaapp", + total_indicator_column: "is_total", + null_label_key: "Geral", + }, + header: { + title_column: "categoriaapp", + value_column: "venda_dia", + value_format: "currency", + }, + rows: [ + { + label: "Meta Mês", + column: "meta_mes", + format: "currency_short", + }, + { + label: "Mês Atual", + column: "mes_atual", + format: "currency_short", + }, + { + label: "Dif ($)", + column: "dif_mes_atual", + format: "currency_short", + }, + { + label: "% Variação", + column: "variacao_atual", + format: "percentage", + }, + { + label: "Mês Anterior", + column: "mes_anterior", + format: "currency_short", + }, + { + label: "Dif ($)", + column: "dif_mes_anterior", + format: "currency_short", + }, + { + label: "% Variação", + column: "variacao_mes_anterior", + format: "percentage", + }, + { + label: "Ano Anterior", + column: "ano_anterior", + format: "currency_short", + }, + { + label: "Dif ($)", + column: "dif_ano_anterior", + format: "currency_short", + }, + { + label: "% Variação", + column: "variacao_ano_anterior", + format: "percentage", + }, + ], + }, + params: ["data_venda", "codigo_categoria_pai", "cod_empresa"], + }, + flash_vendas_ai: { + name: " Flash de vendas AI", + display: { + type: "none" + }, + params: ["data_venda", "agrupamento"] + } + }, + entrypoint: "flash" as "flash" | "flash_categorias", + }) + .withImplementations({ + C5: { + flash: (args) => { + return { + sql: /*sql*/ ` select tes.canalapp, tes.nomeempresaapp, @@ -223,11 +224,11 @@ where 1=1 and (tvf.nroempresa in (${args.ctx_user_companies_for_module})) group by rollup(canalapp, nomeempresaapp) order by grouping(canalapp) desc, grouping(nomeempresaapp) desc`, - }; - }, - flash_categorias: (args) => { - return { - sql: /*sql*/ ` + }; + }, + flash_categorias: (args) => { + return { + sql: /*sql*/ ` select 'Categorias' as categoriaapp, 1 as is_total, @@ -244,19 +245,20 @@ select 0 as variacao_ano_anterior from dual where 1 = 0`, - }; - }, - flash_vendas_ai: (args) => { - return { - sql: /*sql*/ ` + }; + }, + flash_vendas_ai: (args) => { + return { + sql: /*sql*/ ` ` - } - } - }, - C5_big: {flash: (args) => { - return { - sql: /*sql*/ ` + } + } + }, + C5_big: { + flash: (args) => { + return { + sql: /*sql*/ ` SELECT 'Lojas' AS canalapp, x.codigo AS cod_empresa, @@ -335,11 +337,12 @@ where 1 = 0`, (x.codigo, x.nomeempresaapp), () ) - `,}; - }, - flash_categorias: (args) => { - return { - sql: /*sql*/ ` + `, + }; + }, + flash_categorias: (args) => { + return { + sql: /*sql*/ ` WITH params AS ( SELECT TO_DATE(${args.data_venda}, 'YYYY-MM-DD') AS data_venda, @@ -511,11 +514,12 @@ where 1 = 0`, ORDER BY is_total, nomeempresaapp - `,}; - }, - flash_vendas_ai: (args) => { - return { - sql: /*sql*/ ` + `, + }; + }, + flash_vendas_ai: (args) => { + return { + sql: /*sql*/ ` SELECT ${args.agrupamento} AS KEY_FIELD, SUM(CASE WHEN x.periodo = 'ATUAL' THEN x.valor_meta_efetiva ELSE 0 END) AS meta_mes, @@ -577,39 +581,42 @@ where 1 = 0`, GROUP BY ${args.agrupamento} ORDER BY mes_atual DESC ` - } - } - }, - C5_mambo: {flash: (args) => { - return { - sql: /*sql*/ ``,}; - }, - flash_categorias: (args) => { - return { - sql: /*sql*/ ``,}; - }, - flash_vendas_ai: (args) => { - return { - sql: /*sql*/ ` + } + } + }, + C5_mambo: { + flash: (args) => { + return { + sql: /*sql*/ ``, + }; + }, + flash_categorias: (args) => { + return { + sql: /*sql*/ ``, + }; + }, + flash_vendas_ai: (args) => { + return { + sql: /*sql*/ ` ` - } - } - }, - }).withSchedules({ - C5: [ - { - name: "Procedure que atualiza os dados do flash", - command: /*sql*/ `BEGIN + } + } + }, + }).withSchedules({ + C5: [ + { + name: "Procedure que atualiza os dados do flash", + command: /*sql*/ `BEGIN END`, - cron: "0 * * * *", - timeout_seconds: 2400, - }, - ], - C5_big: [ - { - name: "Procedure que atualiza os dados do flash", - command: /*sql*/ `BEGIN + cron: "0 * * * *", + timeout_seconds: 2400, + }, + ], + C5_big: [ + { + name: "Procedure que atualiza os dados do flash", + command: /*sql*/ `BEGIN PRC_FLASH_ATUALIZA_VENDA_DONO( p_data_inicial => TRUNC(SYSDATE) - 30, p_data_final => TRUNC(SYSDATE), @@ -617,17 +624,17 @@ where 1 = 0`, p_empresa_fim => 10 ); END;`, - cron: "0 * * * *", - timeout_seconds: 2400, - }, - ], - C5_mambo: [ - { - name: "Procedure que atualiza os dados do flash", - command: /*sql*/ `BEGIN + cron: "0 * * * *", + timeout_seconds: 2400, + }, + ], + C5_mambo: [ + { + name: "Procedure que atualiza os dados do flash", + command: /*sql*/ `BEGIN END`, - cron: "0 * * * *", - timeout_seconds: 2400, - }, - ], - }); + cron: "0 * * * *", + timeout_seconds: 2400, + }, + ], + });