/*
VOCÊ ATUARÁ COMO DESENVOLVEDOR SÊNIOR PARA IMPLEMENTAR NOVOS MÉTODOS E CORREÇÕES. 
LEIA AS REGRAS ABAIXO e GRAVE ELAS EM SUA LISTA, PARA NÃO FICAR FAZENDO PROCESSOS OU PERGUNTAS PARA TOMAR O TEMPO DE FORMA DESNECESSARIA.

CONTEXTO TÉCNICO:
- Linguagem de desenvolvimento: PHP 7.4
- Framework utilizado: MadBuilder (um fork do Adianti Framework)
- Banco de dados: MySQL
- Sistema com estrutura para matriz e múltiplas filiais

RESTRIÇÃO CRÍTICA DE ESCOPO:
- Não há acesso direto ao servidor.
- Métodos ou trechos comentados no arquivo enviado não são utilizados e devem ser ignorados.
- Antes de perguntar se algum método ou função existe, leia integralmente o arquivo enviado.
- Para abrir transação com o banco de dados, use obrigatoriamente: TTransaction::open(self::$database);
- OS transformers do formulario podem ser modificados se for necessário.
- O ÚNICO BLOCO ONDE É PERMITIDO IMPLEMENTAR NOVOS MÉTODOS, CORREÇÕES ou DEBUG É:
  // COMEÇA AQUI O BLOCO REFATORÁVEL

  // TERMINA AQUI O BLOCO REFATORÁVEL
- TUDO FORA DESSES MARCADORES É INTOCÁVEL. Não altere, não mova, não reescreva nenhuma linha fora desse bloco, mesmo que a solução pareça exigir isso.

PROIBIÇÕES E MANUTENÇÃO DA ARQUITETURA:
É TERMINANTEMENTE PROIBIDO alterar:
- Nomes de variáveis, métodos, classes, campos de formulário, IDs e eventos originais.
- O fluxo principal existente do sistema.
- Mantenha integralmente a arquitetura existente para garantir compatibilidade reversa.
- NÃO CRIE NOVOS MÉTODOS OU CAMPOS FORA DO BLOCO REFATORÁVEL — PERGUNTE ANTES DE PROSSEGUIR.

PADRÃO DE RESPOSTA:
- Direta, técnica, sem introduções, sem tutoriais e sem pseudocódigo.
- NUNCA gere trechos parciais de código ou substituições manuais (proibido diff).
- NUNCA peça ao usuário para complementar com "o resto do código original".
- Sempre entregue o método, transformer ou bloco refatorável COMPLETO do início ao fim, pronto para copiar e colar.
- Quando houver dúvida sobre o nome de um campo, tente todas as variações possíveis dentro do próprio código utilizando encadeamento de `elseif` (fallback lógico) antes de perguntar. Só pergunte quando for impossível deduzir.
- Responda estritamente em português do Brasil, utilizando termos técnicos nativos da área de desenvolvimento. Nunca mude para o inglês, a menos que solicitado.
- O código retornado deve manter rigorosamente a mesma indentação do arquivo enviado.

REGRAS DE ENTREGA DO CÓDIGO:
- Destaque dentro do código implementado (via comentários PHP): o que foi feito, a finalidade, a data/hora atual e a assinatura "Gerado por IA".

DIRETRIZES DE DEBUG (QUANDO SOLICITADO):
- Se for solicitado gerar DEBUG, utilize obrigatoriamente a estrutura para injetar no console do navegador: TScript::create("console.log('=== DEBUG: [identificador] ===');");
- O debug deve cobrir da primeira à última linha do método afetado.
- Numere sequencialmente os logs: debug-nome do metodo 01, debug-nome do metodo 02, etc.
- Não altere a lógica original ao inserir as linhas de debug.
- O código de debug só pode ser removido quando for solicitado explicitamente por escrito.

INSTRUÇÃO FINAL E FLUXO:
- Analise o arquivo enviado completamente antes de emitir qualquer resposta.
- Se o arquivo for muito grande, divida a análise em partes e entregue os resultados de forma modular e organizada.
- Caso chegue à terceira tentativa sem sucesso na solução, sugira obrigatoriamente a inserção do bloco de debug.
- Ao final da resposta, crie um resumo técnico estruturado (o que foi feito, estado atual, pendências e próximo passo exato) formatado como um prompt de continuidade, para que outra IA possa assumir a tarefa sem perda de contexto.

TAREFA:
//-----------------------------------------------------------------------------------
VOCÊ ATUARÁ COMO DESENVOLVEDOR SÊNIOR PARA IMPLEMENTAR NOVOS MÉTODOS E CORREÇÕES E LEIA AS REGRAS ABAIXO ANTES DE CONTINUAR.

CONTEXTO TÉCNICO:
    a) Linguagem de desenvolvimento PHP 7.4
    b) Framework utilizado MadBuilder um fork do Adianti Framework
    c) Banco de dados MySQL
    d) Sistema com estrutura para matriz e múltiplas filiais

RESTRIÇÃO CRÍTICA:
    Não há acesso ao servidor.
    Métodos ou trechos comentados não são utilizados e devem ser ignorados.
    Antes de perguntar se algum método ou função existe, leia o arquivo enviado.
    Para abrir transação com o banco use: TTransaction::open(self::$database);
    Transforms podem ser modificados se necessário.
    O BLOCO ONDE É PERMITIDO SER IMPLEMENTADO NOVOS MÉTODOS, CORREÇÕES E DEBUG.
    // COMEÇA AQUI O BLOCO REFATORÁVEL

    // TERMINA AQUI O BLOCO REFATORÁVEL

    TUDO FORA DESSES MARCADORES É INTOCÁVEL. NÃO ALTERE, NÃO MOVA, NÃO REESCREVA NENHUMA LINHA FORA DESSES BLOCOS, MESMO QUE A SOLUÇÃO PAREÇA EXIGIR ISSO.

RESPOSTAS:
    Direta.
    Técnica.
    Sem introduções.
    Sem tutoriais.
    Sem pseudocódigo.
    Nunca gere trechos parciais de código.
    Nunca peça ao usuário para complementar com "o resto do código original".
    Nunca entregue diff, substituição de trecho ou indicação de localização manual.
    Sempre entregue o método ou transformer COMPLETO do início ao fim, pronto para copiar e colar.
    Quando houver dúvida sobre um campo, tente todas as variações possíveis dentro do próprio código com encadeamento de elseif antes de perguntar.
    Só perguntar quando for impossível deduzir ou tentar por lógica de fallback.
    A informação necessária para resolver o assunto da tarefa está no arquivo enviado, leia para não fazer pergunta desnecessaria.

PROIBIDO FAZER ALTERAÇÃO:
    Nomes de variáveis.
    Métodos.
    Classes.
    Campos.
    IDs.
    Eventos.
    Fluxo principal existente.
    Mantenha integralmente a arquitetura existente para manter a compatibilidade do projeto.

ENTREGAR:
    Entregue o método ou transformer completo do início ao fim pronto para copiar e colar.
    Destacar dentro do método o que foi implementado, para que finalidade, a data e hora e quem gerou.
    Responda em português do Brasil, utilizando termos técnicos nativos da área de desenvolvimento e programação quando necessário. Nunca mude para o inglês, a menos que eu peça explicitamente.
    O codigo deve ser identado para faciltar ou manter a identação que foi enviada.

DEBUG:
    Se solicitado gerar DEBUG usar: TScript::create("console.log('=== DEBUG ===');");
    O debug deve cobrir da primeira à última linha do método.
    Numerar sequencialmente: debug-onsave 01, debug-onsave 02 etc.
    Não altere nada do código original, apenas insira o debug.
    O debug só pode ser retirado depois que for solicitado por escrito.

PRIORIDADE:
    Soluções compatíveis com MadBuilder/Adianti Framework PHP 7.4.
    NÃO CRIE NOVOS MÉTODOS, CAMPOS OU FUNÇÕES — PERGUNTE ANTES DE PROSSEGUIR.

CONTEXTO INSUFICIENTE:
    Perguntar antes de prosseguir.

OBJETIVO:
    Corrigir, implementar e preservar a compatibilidade total com as regras existentes.

INSTRUÇÃO FINAL:
    Analise o arquivo enviado completamente antes de responder.
    Não forneça nenhuma solução fora das regras citadas.
    Na terceira tentativa sem solução, sugira inserir debug.
    Se o arquivo for grande, divida o processo em partes e entregue os resultados de forma modular e organizada.
    Crie um resumo do que foi feito, estado atual, pendências e próximo passo exato, formatado como prompt para que outra IA possa continuar sem perder contexto.
    LEIA COM ATENÇÃO ESTE LINHA O BLOCO ONDE É PERMITIDO SER IMPLEMENTADO NOVOS MÉTODOS, CORREÇÕES E DEBUG:
    // COMEÇA AQUI O BLOCO REFATORÁVEL

    // TERMINA AQUI O BLOCO REFATORÁVEL

TAREFA:

//-------------------------------------------------------
Você atuará como desenvolvedor sênior para implementar novos métodos e fazer correções.

Contexto técnico:
    a) Linguagem de desenvolvimento PHP 7.4
    b) Framework MadBuilder fork do Adianti Framework
    c) Banco de dados MySQL
    d) Sistema com estrutura para matriz e múltiplas filiais

Diretrizes obrigatórias:
    Restrição crítica:
        Não há acesso ao servidor
        Existem metodos ou trechos comentando isso quer dizer que não sõ utilizados e devem ser ignorados.
        Antes de perguntar se algum metodo ou função existe leia o arquivo enviado.
        Para abrir uma transação com o banco este é o padrão do framework TTransaction::open(self::$database); 
        Se não tiver bloco de refatoração não continue, o framework tem restrições de onde ou não pode ser alterado
        Transform podem ser modificados se for necessarios
        A refatoração é permitida dentro do bloco onde começa:
        //Inicio do bloco que pode refatorar ---------------------------------------------------------------------

        //Fim do bloco que pode refatorar ------------------------------------------------------------------------

        
    Resposta:
        Direta
        Técnica
        Sem introduções
        Sem tutoriais
        Sem pseudocódigo
        Sem trechos incompletos
        A correção ou implementação do metodo deve ser gerada de forma completa pronto para copiar e principalmente informar onde sera implementada por exemplo metodo onreload

    Proibido alterar:
        Nomes de variáveis
        Métodos
        Classes
        Campos
        IDs
        Eventos
        Fluxo principal existente
        Mantenha integralmente a arquitetura existente para manter a compatibilidade do projeto existente.

    Entrega:
        A correção ou implementação do metodo deve ser gerada de forma completa pronto para copiar e colar
        Sempre destacar dentro do metodo o que foi implementado e para que finalidade e ainda colocar a data e hora e quem foi que gerou
        Sempre me responda em português do Brasil, utilizando termos técnicos nativos da área de desenvolvimento e programação quando necessário. Nunca mude para o inglês, a menos que eu peça explicitamente.

    Debug:
        Se for solicitado para gerar um DEBUG deve usar TScript::create("console.log('=== DEBUG onOpenCalendarForm FINALIZADO ===');");
        O debug deve ser iniciado na primeira linha do metodo ate a ultima linha afim de pegar todo o processo e colocar a seguinte observação exemplo debug-onsave 01 /  debug-onsave 02 a medida que for incluindo ir colocando a sequencia
        Não altere nada do codigo oiginal simplismente coloque o debug para encontrar o erro.
        So pode retirar o debug depois que for solicitado por escrito.

    Prioridade:
        Soluções compatíveis com a versão do framework
        NAO CRIE NOVOS METODOS, CAMPOS, FUNÇÕES PERGUNTE ANTES DE PROSSEGUIR

    Contexto insuficiente:
        Perguntar antes de prosseguir

    Objetivo:
        Corrigir
        Implementar
        E preservar a compatibilidade total com as regras existentes
        
    Instrução final:
        Analise o arquivo enviado
        Não forneça nenhuma solução fora das regras citadas acima.
        Se perceber que a solução proposta não esta funcionando, sugira colocar um debug na terceira tentativa.
        Se o arquivo enviado for considerado grande e para evitar o reinicio a todo momento da geração, divada o processo em partes e vai entregando os resultados
        Crie um resumo detalhado do que já foi feito, o estado atual do projeto, quais são as pendências e qual é o próximo passo exato. Formate isso como um prompt para que outra IA possa continuar o trabalho sem perder o contexto e gere respostas modulares e organizadas.

    Tarefa:

//--------------------------------------------------------------------------------------------------------

Usa BootstrapFormBuilder, TDataGrid, TPageNavigation, com appendPage(), addFields() com layout em array
Métodos: onShow (para abrir form), onEdit, onSave, onDelete, onSearch, onReload
Banco definido em variável estática private static $database = 'bdgestorweb', self::$database, self::$activeRecord
Form: modal com parent::setSize(0.60, null)
Form extende TWindow (não TStandardForm)
List extende TPage (não TStandardList)
Datagrid usa BootstrapDatagridWrapper com disableDefaultClick()
Actions usam setUseButton(false) e setButtonClass()
Usa TBreadCrumb::create() em vez de TXMLBreadCrumb

//--------------------------------------------------------------------------------------------------------
Resumo da compreensão:

Papel: Especialista em implementação/correção de código PHP 7.4 no MadBuilder (fork Adianti)
Restrições críticas:

Refatorar APENAS entre blocos comentados específicos
Sem acesso ao servidor
Nenhuma alteração em nomes, métodos, classes, variáveis, IDs, eventos
Manter fluxo principal intacto


Entrega obrigatória:

Código completo e pronto para substituição imediata
Sem pseudocódigo, tutoriais ou explicações longas
Resposta direta e técnica


Debug:

Console.log ou TMessage apenas
Do início ao fim do método
Remover apenas com autorização explícita


Processo:

Analisar integralmente o arquivo ANTES de propor mudanças
Perguntar se contexto for insuficiente
Preservar 100% compatibilidade com sistema existente
//--------------------------------------------------------------------------------------------------------
Você atuará como especialista para implementar novos metodos e corrigir metodos existentes em

Contexto técnico:
    a)Ambiente PHP 7.4.
    b)Framework Madbuilder é um Fork do Adianti Framework.
    c)Bando de dados MYSQL
    d)Sistema desenvolvido utiliza recurso de matriz e varias filiais
    E)Você atuará como especialista para implementar e fazer correções

Diretrizes para resposta:
    1)Restrição crítica: Não tenho acesso ao servidor para realizar procedimentos, as modificações devem ser feitas exclusivamente nos blocos comentados onde esta escrito 
             //Inicio do bloco que pode refatorar ---------------------------------------------------------------------
            
             //Fim do bloco que pode refatorar ------------------------------------------------------------------------
    2)Objetividade: Resposta direta e sem introduções ou explicações, a menos que eu solicite e não incluir Explicações longas,Introduções,Tutoriais,Comentários desnecessários,Trechos incompletos,Pseudocódigo
    3)Fidelidade ao código: Proibido alterar nomenclaturas de variáveis, métodos ou classes originais.
    4)Entrega completa: gere exclusivamente o método completo corrigido ou novo método solicitado, pronto para substituição imediata, sem alterar nomenclaturas existentes.
    5)Debug: Se for solicitado debug , você deve fazer via console.log do navegador ou usando o TMessage do framework e ou atraves de var_dump.
    6)Priorize soluções que não exijam acesso ao servidor
    7)Evite suposições, se faltar contexto, pergunte antes de fazer qualquer modificação.
    8)Objetivo e refatorar e corrigir mantendo sempre a compatibilidade total com o código existente.
    9)Leia o arquivo enviado nele ja contem todas as informações sobre a tarefa.

Tarefa:
Refatore o código abaixo seguindo as Diretrizes para resposta.
//--------------------------------------------------------------------------------------------------------
E me forneca a solução dentro do que foi estabelecido nas regras


Dica de mestre: Se a IA começar a "alucinar" nomes de classes que não existem no Adianti, responda apenas: "Você violou a regra 2. Releia as nomenclaturas originais e corrija." Ela costuma entrar na linha na hora.
//-------------------------------------------------------------------

1)PRECISO QUE SEJA OBJETIVO EM SUA RESPOSTA, NAO FIQUE CRIANDO OU ALTERANDO NOMEMCLATURAS DO CODIGO ORIGINAL SEM PERGUNTAR ANTES
2)UTILIZO MADBUILDER PHP FORK DO ADIANTI FRAMEWORK 7.4
3)NAO TENHO ACESSO AO SERVIDOR PARA REALIZAR PROCEDIMENTOS
4)GERAÇÃO DE LOG PELO CONSOLE DO NAVEGADOR OU USANDO ALGUM RECURSO VISUAL
5)FAÇA BACKUP DO CÓDIGO ORIGINAL
6)APRESENTE A CORREÇÃO OU MELHORIA DO METODO POR COMPLETO PARA EVITAR ERROS
7)SO PODE FAZER MODIFICAÇÃO NO FRAMEWORK ONDE ESTA ESCRITO //Aqui pode incluir---------------------------------------------------------------------
REFATORAR

2. Técnica do "Readonly" Temporário (JavaScript)
Esta é a técnica mais robusta atualmente. O navegador não aplica autocomplete em campos marcados como readonly. Podemos desabilitar o readonly assim que o usuário clica no campo.

Você pode adicionar isso no onShow() da sua página ou em um arquivo JS global do sistema:

Projeto:
Criar projeto chamado SimuladorDePreco que atenda a precificação de produtos ou serviços.
Cadastrar em tabela os registros que foram gerados pela simulação, e com isso acompanhar a evolução destas simulação.
Incluir despesas sendo elas federal, estadual e municipal e tambem local como agua, luz, entre outros gastos e tudo deve ser calculado penso que a melhor forma seja em porcentagem.
Cadastrar varios produtos ou serviço para a empresa ou filial que for utilizar separadamente.
Como utiliza o conceito de empresa e filias pode ter diferença nos precos praticados entre elas.
Fazer pesquisa na internet com a fonte , data e hora e site ou o meio utilizado para encontrar os preços praticados na regiao onde a empresa esta situada e caso nao encontre procurar em cidades proximas para poder o usuario avaliar se o preço esta ou nao muito maior que o concorrente.
Sugerir melhorias para calcular o preco de venda ou servico utilizando melhores praticas do mercado e ate mesmo utilização de metodoliga cientifica
Sugerir melhorias e seguir as boas praticas de mercado para o desenvolvimento deste projeto.
Criar as tabelas, codigos e tudo mais para ser implementados no sistema.
Prefixo das tabelas deve ser simuladordepreco_xxx e por ai vai
sk-3aeee3f5ceb342b99b25245fa3573db8

https://www.scrapy.org/download
https://langsearch.com
https://www.search1api.com/
https://typesense.org/
https://webatendimento.saude.gov.br/
*/
/**
 * Arquivo: index.php
 */
/*
require_once 'init.php';
$theme  = $ini['general']['theme'];
$class  = isset($_REQUEST['class']) ? $_REQUEST['class'] : '';

$public = in_array($class, $ini['permission']['public_classes']);

new TSession;
ApplicationTranslator::setLanguage( TSession::getValue('user_language'), true );
BuilderTranslator::setLanguage( TSession::getValue('user_language'), true );

MadLogService::initializeDebugLogging();

$isAjax = (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');

if (!$isAjax) 
{
    $content = BuilderTemplateParser::init('layout');
    $content = ApplicationTranslator::translateTemplate($content);

    $content = str_replace(
        '<meta name="apple-mobile-web-app-capable" content="yes">',
        '<meta name="mobile-web-app-capable" content="yes">',
        $content);

    $versao_cache = date('YmdHis', filemtime('app/lib/include/application.js')); 
    $content      = preg_replace('/(href|src)=["\']([^"\']+\.(js|css))["\']/i', '$1="$2?v=' . $versao_cache . '"', $content);

    if (TSession::getValue('logged') && class_exists('AgendamentoNotificacaoGlobal')) 
    {
        AgendamentoNotificacaoGlobal::inject(); 
    }

    if (TSession::getValue('logged')) 
    {
        $usuarioLogadoDoSistema = TSession::getValue('user_name') ? TSession::getValue('user_name') : 'anonimo';
        $unidadeLogadaDoSistema = TSession::getValue('user_unit_name') ? TSession::getValue('user_unit_name') : 'sem_unidade';

        $scriptSuporte = '<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/rrweb@1.1.3/dist/rrweb.min.css" />
        <script src="https://cdn.jsdelivr.net/npm/rrweb@1.1.3/dist/rrweb.min.js"></script>
        <script>
        (function() {
            let eventosTecladoMouse = [];
            let stopFn = null;
            let gravando = false;

            document.addEventListener("click", async function(e) {
                const btnVideo = e.target.closest("#btn-suporte-video");
                if (!btnVideo) return;

                e.preventDefault();
                e.stopPropagation();
                
                const footerTag = document.getElementById("main-erp-footer");

                if (!gravando) {
                    // MODO: INICIAR GRAVAÇÃO
                    eventosTecladoMouse = []; // Limpa gravações anteriores
                    
                    if (typeof rrweb !== "undefined") {
                        gravando = true;
                        btnVideo.innerHTML = "<i class=\'fa fa-stop fa-spin\'></i> Gravando... Clique para Parar e Enviar";
                        btnVideo.style.color = "#ef4444"; // Muda o botão para vermelho indicando gravação

                        stopFn = rrweb.record({
                            emit(event) {
                                eventosTecladoMouse.push(event);
                            },
                        });
                    } else {
                        alert("Erro: A biblioteca de captura não foi carregada corretamente.");
                    }
                } else {
                    // MODO: PARAR E ENVIAR
                    gravando = false;
                    if (typeof stopFn === "function") stopFn(); // Interrompe o motor do rrweb

                    if (eventosTecladoMouse.length < 2) {
                        alert("Gravação cancelada: Nenhum movimento ou clique foi realizado.");
                        resetBotao(btnVideo);
                        return;
                    }

                    btnVideo.innerHTML = "<i class=\'fa fa-spinner fa-spin\'></i> Enviando Gravação...";
                    btnVideo.style.color = "#94a3b8";
                    btnVideo.style.pointerEvents = "none";

                    let dadosGravacao = JSON.stringify({ events: eventosTecladoMouse });

                    let agora = new Date();
                    let ano   = agora.getFullYear();
                    let mes   = String(agora.getMonth() + 1).padStart(2, "0");
                    let dia   = String(agora.getDate()).padStart(2, "0");
                    let hora  = String(agora.getHours()).padStart(2, "0");
                    let min   = String(agora.getMinutes()).padStart(2, "0");
                    let seg   = String(agora.getSeconds()).padStart(2, "0");
                    
                    let dataHoraSuporte = dia + "-" + mes + "-" + ano + "_" + hora + min + seg;

                    let usuarioFinal = (footerTag && footerTag.dataset.user) ? footerTag.dataset.user : "' . $usuarioLogadoDoSistema . '";
                    let empresaFinal = (footerTag && footerTag.dataset.unit) ? footerTag.dataset.unit : "' . $unidadeLogadaDoSistema . '";

                    let nomeArquivoFinal = empresaFinal.replace(/[^a-zA-Z0-9_-]/g, "") + "_" + usuarioFinal.replace(/[^a-zA-Z0-9_-]/g, "") + "_" + dataHoraSuporte + ".json";

                    let formData = new FormData();
                    formData.append("video-chunk", btoa(unescape(encodeURIComponent(dadosGravacao))));
                    formData.append("file-name", nomeArquivoFinal);
                    formData.append("usuario", usuarioFinal);
                    formData.append("empresa", empresaFinal);

                    try {
                        let response = await fetch("salva_video.php", { 
                            method: "POST", 
                            body: formData 
                        });
                        let resJson = await response.json();
                        if (response.ok && resJson.status === "sucesso") {
                            if (typeof Adianti !== "undefined" && Adianti.showToast) {
                                Adianti.showToast("info", "Passo a passo enviado com sucesso!");
                            } else {
                                alert("Passo a passo enviado com sucesso!");
                            }
                        } else {
                            alert("Erro ao salvar gravação no servidor.");
                        }
                    } catch (err) {
                        alert("Erro de comunicação com o servidor.");
                    }

                    resetBotao(btnVideo);
                }
            });

            function resetBotao(btn) {
                btn.style.pointerEvents = "auto";
                btn.innerHTML = "<i class=\'fa fa-video\'></i> Gravar Passos do Erro";
                btn.style.color = "#60a5fa";
                gravando = false;
            }
        })();
        </script>';

        $content = str_replace('</body>', $scriptSuporte . '</body>', $content);
    }

    echo $content;
}

if (TSession::getValue('logged') OR $public)
{
    if ($class)
    {
        $method = isset($_REQUEST['method']) ? $_REQUEST['method'] : NULL;
        AdiantiCoreApplication::loadPage($class, $method, $_REQUEST);
    }
}
else
{
    if (isset($ini['general']['public_view']) && $ini['general']['public_view'] == '1')
    {
        if (!empty($ini['general']['public_entry']))
        {
            AdiantiCoreApplication::loadPage($ini['general']['public_entry'], '', $_REQUEST);
        }
    }
    else
    {
        AdiantiCoreApplication::loadPage('LoginForm', '', $_REQUEST);
    }
}

MadLogService::finalizeDebugLogging();
*/


/*
//------------------------------------------------------

/*
<span style="font-size: 9pt; font-weight: bold; color:#FFFFFF;" <b>Versão 1.0.0.0 - B4.2</b></span><br> <html> <script>     function construirArray(qtdElementos)      {         this.length = qtdElementos     }     var arrayDia = new construirArray(7);     arrayDia[0] = 'Domingo';     arrayDia[1] = 'Segunda';     arrayDia[2] = 'Terça';     arrayDia[3] = 'Quarta';     arrayDia[4] = 'Quinta';     arrayDia[5] = 'Sexta';     arrayDia[6] = 'Sabado';      var arrayMes = new construirArray(12);     arrayMes[0] = 'Janeiro';     arrayMes[1] = 'Fevereiro';     arrayMes[2] = 'Março';     arrayMes[3] = 'Abril';     arrayMes[4] = 'Maio';     arrayMes[5] = 'Junho';     arrayMes[6] = 'Julho';     arrayMes[7] = 'Agosto';     arrayMes[8] = 'Setembro';     arrayMes[9] = 'Outubro';     arrayMes[10] = 'Novembro';     arrayMes[11] = 'Dezembro';      function mostrarDataHora(hora, diaSemana, dia, mes, ano)      {         retorno = '' + hora + '<br> ';         retorno += '' + diaSemana + ' ' + dia + ' de ' + mes + ' de ' + ano;         document.getElementById('datahora').innerHTML = retorno;     }      function getMesExtenso(mes)      {         return this.arrayMes[mes];     }      function getDiaExtenso(dia)      {         return this.arrayDia[dia];     }      function atualizarDataHora()      {         dataAtual = new Date();         dia = dataAtual.getDate();         diaSemana = getDiaExtenso(dataAtual.getDay());         mes = getMesExtenso(dataAtual.getMonth());         ano = dataAtual.getFullYear();         hora = dataAtual.getHours();         minuto = dataAtual.getMinutes();         segundo = dataAtual.getSeconds();         horaImprimivel = hora + ':' + minuto + ':' + segundo;         mostrarDataHora(horaImprimivel, diaSemana, dia, mes, ano);         setTimeout('atualizarDataHora()', 1000);     } </script>  <body onload='atualizarDataHora()'>     <font color='#FFFFFF'> <b>             <div id='datahora'></div>     </font> </b> </body>  </html>
<span style="font-size: 9pt; color: #FFFFFF;">{userunitname}</span>
*/
/*
//----------------------------------------------------

    <div style="padding: 5px; border-left: 5px solid #414749; margin-bottom: 15px;">
        <strong style="color: #414749; font-weight: bold;">{$username}</strong> 
        <strong span style="color: #414749;"><br> SEJA BEM-VINDO(A) AO SEU AMBIENTE DE TRABALHO</strong></span>
    </div>

    <div style="padding: 5px; border-left: 5px solid #414749; margin-bottom: 15px;">
        <strong style="color: #414749; font-weight: bold;">VOCÊ ESTÁ EM AMBIENTE DE</strong> 
        <span style="color: #414749; font-weight: bold;">{$descricao_bdtipo}</span>
    </div>

*/
/*
STATUS: LINEARIZADO (Tratamento de erros HTTP sem loops de MutationObserver)

let timeoutFaxina = null;

function executarFaxina() 
{
    if (timeoutFaxina) clearTimeout(timeoutFaxina);
    timeoutFaxina = setTimeout(() => 
    {
        const modais = document.querySelectorAll('.modal, .ui-dialog');
        modais.forEach(modal => 
        {
            if (modal.textContent.includes('503') || modal.textContent.includes('Requisição falhou')) 
            {
                modal.style.display = 'none';
                document.body.classList.remove('modal-open');
                document.querySelectorAll('.modal-backdrop').forEach(b => b.remove());
                document.body.style.overflow = '';
                document.body.style.pointerEvents = '';
            }
        });
    }, 300);
}

// Intercepta e loga no console apenas falhas reais de resposta do servidor (ex: 500 ou 503)
$(document).ajaxError((event, jqxhr, settings) => 
{
    if (jqxhr.status === 401) return;
    if (jqxhr.status === 503 || jqxhr.status === 500) 
    {
        console.error("[MonitorConexao] HTTP " + jqxhr.status + " na URL: " + (settings.url || "Desconhecida"));
        executarFaxina();
    }
});
*/
/*
<?php
require_once 'init.php';
$theme  = $ini['general']['theme'];
$class  = isset($_REQUEST['class']) ? $_REQUEST['class'] : '';
$public = in_array($class, $ini['permission']['public_classes']);

// AdiantiCoreApplication::setRouter(array('AdiantiRouteTranslator', 'translate'));

new TSession;
ApplicationTranslator::setLanguage( TSession::getValue('user_language'), true );
BuilderTranslator::setLanguage( TSession::getValue('user_language'), true );

MadLogService::initializeDebugLogging();

$content = BuilderTemplateParser::init('layout');
$content = ApplicationTranslator::translateTemplate($content);

// Define uma versão baseada na data da última alteração do arquivo principal ou uma constante
$versao_cache = date('YmdHis', filemtime('app/lib/include/application.js')); // Ajuste para um arquivo que você sempre altera
// Regex para encontrar arquivos .js e .css e adicionar a query string
$content = preg_replace('/(href|src)=["\']([^"\']+\.(js|css))["\']/i', '$1="$2?v=' . $versao_cache . '"', $content);

echo $content;

if (TSession::getValue('logged') OR $public)
{
    if ($class)
    {
        $method = isset($_REQUEST['method']) ? $_REQUEST['method'] : NULL;
        AdiantiCoreApplication::loadPage($class, $method, $_REQUEST);
    }
}
else
{
    if (isset($ini['general']['public_view']) && $ini['general']['public_view'] == '1')
    {
        if (!empty($ini['general']['public_entry']))
        {
            AdiantiCoreApplication::loadPage($ini['general']['public_entry'], '', $_REQUEST);
        }
    }
    else
    {
        AdiantiCoreApplication::loadPage('LoginForm', '', $_REQUEST);
    }
}

// Substitui a meta tag depreciada
$content = str_replace(
    '<meta name="apple-mobile-web-app-capable" content="yes">',
    '<meta name="mobile-web-app-capable" content="yes">',
    $content
);

// Injeção do monitoramento (se aplicável)
$isAjax = (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
if (!$isAjax && TSession::getValue('logged') && class_exists('AgendamentoNotificacaoGlobal')) 
{
    AgendamentoNotificacaoGlobal::inject();
}

MadLogService::finalizeDebugLogging();

*/

/*
//----------------------------------------------------------------------
//Desabilitar autocomplete
(function() 
{
    function disableAutocompleteForField(field) 
    {
        if (!field || !field.parentNode || field.dataset.processed) return;

        const clone = field.cloneNode(true);

        clone.setAttribute('autocomplete', 'off');
        clone.removeAttribute('id');
        clone.removeAttribute('name');

        // Marca o campo como processado
        field.dataset.processed = 'true';

        // Substitui o campo original após pequeno delay
        setTimeout(function() 
        {
            field.parentNode.replaceChild(clone, field);
        }, 100);
    }

    function processForm(form) 
    {
        if (!form || form.dataset.autocompleteDisabled) return;

        form.setAttribute('autocomplete', 'off');
        form.dataset.autocompleteDisabled = 'true';

        form.querySelectorAll('input[type=text], input[type=password], input[type=email], input[type=tel], textarea')
            .forEach(disableAutocompleteForField);
    }

    function initAntiAutocomplete() 
    {
        document.querySelectorAll('form').forEach(processForm);
    }

    // Executa ao carregar o DOM
    document.addEventListener('DOMContentLoaded', initAntiAutocomplete);

    // Observa mutações no DOM para suportar Adianti (AJAX)
    const observer = new MutationObserver(function(mutations) 
    {
        mutations.forEach(function(mutation) 
        {
            mutation.addedNodes.forEach(function(node) 
            {
                if (node.nodeType === 1) 
                {
                    if (node.tagName === 'FORM') 
                    {
                        processForm(node);
                    } 
                    else 
                    {
                        node.querySelectorAll?.('form').forEach(processForm);
                    }
                }
            });
        });
    });

    observer.observe(document.body, { childList: true, subtree: true });
})();

//--------------------------------------------
/**
 * Arquivo: index.php
 */
/*
require_once 'init.php';
$theme  = $ini['general']['theme'];
$class  = isset($_REQUEST['class']) ? $_REQUEST['class'] : '';
$public = in_array($class, $ini['permission']['public_classes']);

// AdiantiCoreApplication::setRouter(array('AdiantiRouteTranslator', 'translate'));

new TSession;
ApplicationTranslator::setLanguage( TSession::getValue('user_language'), true );
BuilderTranslator::setLanguage( TSession::getValue('user_language'), true );

MadLogService::initializeDebugLogging();

// Identifica se é uma requisição AJAX
$isAjax = (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');

if (!$isAjax) 
{
    // Só renderiza o layout completo se NÃO for AJAX
    $content = BuilderTemplateParser::init('layout');
    $content = ApplicationTranslator::translateTemplate($content);

    // Substitui a meta tag depreciada direto na string do layout
    $content = str_replace(
        '<meta name="apple-mobile-web-app-capable" content="yes">',
        '<meta name="mobile-web-app-capable" content="yes">',
        $content);

    // Define uma versão baseada na data da última alteração para evitar cache do navegador
    $versao_cache = date('YmdHis', filemtime('app/lib/include/application.js')); 
    $content      = preg_replace('/(href|src)=["\']([^"\']+\.(js|css))["\']/i', '$1="$2?v=' . $versao_cache . '"', $content);

    // Injeção do monitoramento ativo (se o usuário estiver logado)
    if (TSession::getValue('logged') && class_exists('AgendamentoNotificacaoGlobal')) 
    {
        // Nota: Garanta que o método inject() do AgendamentoNotificacaoGlobal concatena ou injeta o script dentro do seu $content, ou mude a lógica dele.
        AgendamentoNotificacaoGlobal::inject(); 
    }

    // Imprime o layout completo na tela
    echo $content;
}

// Executa a lógica de carregamento de páginas do Adianti Framework
if (TSession::getValue('logged') OR $public)
{
    if ($class)
    {
        $method = isset($_REQUEST['method']) ? $_REQUEST['method'] : NULL;
        AdiantiCoreApplication::loadPage($class, $method, $_REQUEST);
    }
}
else
{
    if (isset($ini['general']['public_view']) && $ini['general']['public_view'] == '1')
    {
        if (!empty($ini['general']['public_entry']))
        {
            AdiantiCoreApplication::loadPage($ini['general']['public_entry'], '', $_REQUEST);
        }
    }
    else
    {
        AdiantiCoreApplication::loadPage('LoginForm', '', $_REQUEST);
    }
}

MadLogService::finalizeDebugLogging();
//----------------------------------------------------
<footer class="main-footer-fixed" 
        data-user="{username}" 
        data-unit="{userunitname}"
        data-ip  ="{remote_addr}">
    <div class="footer-content" style="color: #ffffff;">
        <div class="footer-left">
            <i class="fa fa-building"></i> <strong>Unidade:</strong> <span id="footer-filial"><b>Carregando...</b></span>
            <span class="footer-separator" style="color: #ffffff;"><b> | </b></span>
            <i class="fa fa-user"></i> <strong>Usuário:</strong> <span id="footer-usuario"><b>Usuário</b></span>
        </div>
        <div class="footer-center">
            <span class="footer-separator" style="color: #ffffff;"><b> | </b></span>
            <i class="fa fa-desktop"></i> <strong>Suporte:</strong> <span id="footer-suporte-remotol"><b>Carregando...</b></span>
        </div>
        <div class="footer-right">
            <span class="footer-separator" style="color: #ffffff;"><b> | </b></span>
            <span style="color: #ffffff; margin-right: 15px; font-weight: bold;">PontoCom Sistemas - GestorWeb versão 1.0.0.10 - B4.2</span>
            <i class="fa fa-calendar-alt"></i> <span id="footer-data-hora"><b>00/00/0000 00:00:00</b></span>
        </div>
    </div>
</footer>

<?php

 // Arquivo: ler_video.php
 * Finalidade: Servir o arquivo JSON de forma segura sem expor o diretório bloqueado.
$diretorioDestino = __DIR__ . '/tmp/chamados/videos/';
if (isset($_GET['file']) && !empty($_GET['file'])) {
    $arquivo = basename($_GET['file']);
    $caminhoCompleto = $diretorioDestino . $arquivo;
    if (file_exists($caminhoCompleto) && is_file($caminhoCompleto)) {
        header('Content-Type: application/json; charset=utf-8');
        readfile($caminhoCompleto);
        exit;
    }
}
http_response_code(404);
echo json_encode(['error' => 'Arquivo não encontrado.']);
exit;
//----------------------------------------------------
Essa é uma excelente dúvida de arquitetura e experiência do usuário (UX). Analisando as duas telas, você tem um cenário clássico: a Tela 1 trabalha com um bloqueio por intervalo (Ex: das 08:00 às 14:00 em uma data específica), enquanto a Tela de Horários trabalha com "slots" (fatias) de tempo fixos já gerados na agenda do médico (Ex: 08:00 às 08:40, 08:40 às 09:20).

A melhor abordagem depende de como você quer que o sistema se comporte nos bastidores e do nível de flexibilidade que o usuário precisa. Abaixo, analiso as duas estratégias para te ajudar a decidir.

Opção 1: O usuário define uma Faixa de Horário (Como está na Tela 1)
O usuário simplesmente digita o início e o fim (ex: 08:00 às 14:00), e o sistema faz o trabalho pesado de cruzar esses dados com a tabela de horários cadastrados.

Vantagens:

Rapidez no preenchimento: É muito mais rápido para o usuário digitar um período do que sair clicando em 5 ou 10 horários individuais (pense em um bloqueio de um dia inteiro).

Flexibilidade: Permite bloquear horários que talvez nem estejam gerados na tabela ainda (ex: se o médico decidir bloquear o período da tarde antes mesmo de criarem a agenda daquele mês).

Como o sistema deve validar:
Ao clicar em "Salvar", o sistema roda uma verificação no banco de dados:

Se houver agendamentos de pacientes dentro daquela faixa (08:00 <= Horário < 14:00), o sistema avisa: "Não é possível bloquear, existem pacientes agendados nesse intervalo".

Se estiver livre, o sistema grava o registro de bloqueio e altera o status dos slots correspondentes na tabela de horários para "Bloqueado" (ou esconde-os da agenda).

Opção 2: O usuário seleciona os Horários (Slots) Diretamente
Em vez de digitar a hora, o sistema exibe os horários daquele dia (puxados da tabela da imagem 2) e o usuário marca um checkbox ao lado de cada horário que deseja bloquear.

Vantagens:

Precisão absoluta: O usuário visualiza exatamente o que está bloqueando e sabe se já existe algum paciente ali.

Prevenção de erros: Evita que o usuário digite um horário quebrado (ex: 08:15) que não bate exatamente com o início de um slot (que começaria às 08:40).

Desvantagens:

Se o médico precisar bloquear uma semana inteira ou um turno muito longo, o processo de clicar em slot por slot se torna cansativo e propenso a esquecimentos.

Qual é a melhor forma? (Veredito)
A Opção 1 (Definir por Faixa de Horário) costuma ser a melhor para sistemas médicos, pois a rotina de clínicas exige agilidade (ex: "Doutor precisará sair às 11:00 hoje"). No entanto, ela precisa de uma melhoria visual para ser perfeita.

A Solução Ideal (Híbrida)
Mantenha a lógica da Tela 1 (cadastro por faixa de horário), mas adicione inteligência visual a ela:

Validação Automática: Quando o usuário preencher a Data, Hora Inicial e Hora Final, o sistema pode buscar na tabela de horários (Imagem 2) e exibir um pequeno resumo na tela:

⚠️ Ao confirmar, os seguintes horários serão bloqueados: 08:00, 08:40, 09:20, 10:00, 10:40, 11:20.

Tratamento de Conflitos: Se houver consulta marcada em algum desses horários, o botão "Salvar" fica desabilitado e o sistema mostra:

❌ Não foi possível bloquear. O horário das 09:20 possui uma consulta agendada para o paciente João Silva.

Dessa forma, você une o melhor dos dois mundos: a rapidez de digitar uma faixa de horário com a segurança de saber exatamente quais slots da tabela serão impactados.

//---------------------
Entendido. O escopo correto é um controle de solicitações médicas para fila de espera e encaixe de pacientes, não um totem de atendimento.

Objetivo do sistema

Registrar solicitações de atendimento, organizar pacientes interessados por especialidade/médico e acompanhar a fila até que uma vaga de encaixe seja disponibilizada.

Fluxo operacional

Recepção/atendente registra a solicitação do paciente, informando especialidade, médico desejado (opcional), prioridade e observações clínicas.

Solicitação entra na fila de espera da especialidade/médico correspondente.

Equipe acompanha o status da solicitação: aguardando, contatado, encaixado, cancelado, não localizado, etc.

Quando surge uma vaga, o sistema permite selecionar o próximo paciente elegível para encaixe.

O paciente é contatado; se confirmar, a solicitação vira encaixe/agendamento. Caso contrário, registra-se a tentativa e segue para o próximo.

O histórico permanece auditável, mostrando quem registrou, quem contatou, quando houve encaixe e o desfecho final.

Dados principais da solicitação

Paciente

Filial

Especialidade

Médico desejado (opcional)

Data da solicitação

Prioridade / urgência

Motivo ou observação clínica

Status atual

Data limite ou preferência de atendimento (opcional)

Responsável pelo cadastro

Status sugeridos

Status

	

Uso no controle




Aguardando

	

Paciente está na fila de espera.




Em análise

	

Equipe verificando disponibilidade.




Contatado

	

Paciente foi chamado para vaga disponível.




Encaixado

	

Vaga confirmada para o paciente.




Agendado

	

Consulta efetivamente marcada.




Não localizado

	

Tentativa de contato sem sucesso.




Cancelado

	

Solicitação encerrada sem encaixe.




Finalizado

	

Fluxo encerrado com atendimento concluído.

Módulos do sistema

Cadastro de solicitações médicas

Fila de espera por especialidade

Fila de espera por médico

Controle de prioridades

Registro de tentativas de contato

Controle de encaixes realizados

Histórico completo da solicitação

Relatórios de demanda reprimida

Relatórios de encaixes por período, médico e filial

Regras de encaixe

Priorizar pacientes conforme data da solicitação, prioridade clínica e preferência por médico.

Permitir encaixe por especialidade quando não houver médico específico solicitado.

Ao encaixar, registrar data/hora da vaga, usuário responsável e resultado do contato.

Evitar encaixe duplicado da mesma solicitação.

Manter histórico de todas as movimentações para auditoria.

Estrutura técnica sugerida

Tabela principal: solicitações médicas.

Tabela de histórico: mudanças de status, contatos e encaixes.

Tabela de prioridades: regras configuráveis pela clínica.

Tabela de vagas/encaixes: quando houver integração com agenda médica.

Compatibilidade com o sistema atual

Manter PHP 7.4, MadBuilder e MySQL.

Usar TTransaction::open(self::$database); para operações de banco.

Respeitar a arquitetura existente, sem alterar nomes de métodos, classes, campos, IDs ou fluxo principal.

Suportar matriz e múltiplas filiais, com filas independentes por unidade.

Resumo técnico (Prompt de Continuidade)

Projeto: Controle de Solicitações Médicas para Fila de Espera e Encaixe de Pacientes.

Escopo correto: Registrar solicitações de pacientes interessados, acompanhar status, controlar prioridades e permitir encaixes quando houver vagas disponíveis.

Fluxo principal: Cadastro da solicitação → fila de espera → análise/contato → encaixe/agendamento → histórico final.

Regras técnicas: PHP 7.4, MadBuilder, MySQL, suporte a múltiplas filiais, uso obrigatório de TTransaction::open(self::$database);, preservação da arquitetura existente e entrega apenas de blocos completos prontos para copiar e colar.

Próximo passo: Receber os arquivos do projeto para implementar cadastro de solicitações, listagem da fila de espera, controle de status, histórico de contatos e rotina de encaixe.

Analisando o arquivo enviado, ele corresponde ao model Agendamento (classe Agendamento extends TRecord) e não à estrutura de uma tabela SQL.

Pelos atributos registrados no addAttribute(), identifiquei que a tabela agendamento já possui praticamente todas as entidades necessárias para integrar futuramente o controle de fila de espera:

Empresa (empresa_id)
Paciente (paciente_id)
Profissional (profissional_id)
Produto/Procedimento (produto_id)
Tipo de agendamento (tipo_agendamento_id)
Origem da consulta (origemconsulta_id)
Ambiente (ambiente_id)
Status
Observações
Datas e usuários de todas as movimentações
Cancelamento
Confirmação
Recepção
Retorno
Finalização
Histórico de auditoria completo
Minha sugestão de arquitetura

Eu não utilizaria a tabela agendamento para representar a fila de espera.

O ideal é criar uma entidade independente, por exemplo:

fila_espera

Ela armazenaria apenas quem ainda não possui agendamento, evitando misturar:

pacientes aguardando vaga;
pacientes já agendados;
pacientes atendidos.

Quando surgir uma vaga:

fila_espera
        │
        ▼
Seleciona paciente
        │
        ▼
Confirma interesse
        │
        ▼
Gera registro em Agendamento

Assim, a tabela Agendamento continua sendo somente agenda, preservando toda a lógica existente do sistema.

Integração

A tabela de fila poderá referenciar exatamente as mesmas entidades já existentes:

empresa_id
paciente_id
profissional_id
produto_id
tipo_agendamento_id
origemconsulta_id

Ou seja, praticamente todas as FKs já existem no sistema.

Também recomendo registrar
Data da solicitação
Prioridade
Ordem da fila
Situação (Aguardando, Contatado, Encaixado, Cancelado...)
Quantidade de tentativas de contato
Última tentativa
Usuário responsável
Observações

Dessa forma, quando um encaixe for confirmado, basta gerar um registro em Agendamento, sem alterar nenhuma regra já existente.

Resumo técnico (Prompt de Continuidade)

Análise realizada: O arquivo enviado é o model Agendamento, que representa a tabela de agenda e possui os relacionamentos necessários (empresa, paciente, profissional, produto, tipo de agendamento, origem da consulta, ambiente e auditoria).

Estado atual: Recomenda-se manter agendamento exclusivamente para consultas agendadas e criar uma entidade separada para a fila de espera, preservando a arquitetura existente.

Pendências: Definir a estrutura da nova tabela de fila de espera e os pontos de integração com o cadastro de agendamentos.

Próximo passo exato: Envie o CREATE TABLE da tabela agendamento (ou o diagrama do banco) e, se já existir, o layout esperado da nova fila. Com isso, elaborarei a estrutura da tabela fila_espera integrada ao modelo atual, mantendo total compatibilidade com o sistema existente.

e isso aqui pacientes aguardando vaga;

Sim, exatamente.

A ideia é que "pacientes aguardando vaga" seja o conceito central da funcionalidade.

Na prática, cada registro representa uma solicitação como estas:

"Quero consulta com cardiologista assim que surgir vaga."
"Pode me encaixar com qualquer ortopedista."
"Quero somente com o Dr. João."
"Se houver desistência, pode me ligar."

Ou seja, não existe horário marcado ainda.

Depois, quando surgir uma vaga por cancelamento, aumento de agenda ou encaixe autorizado, a recepção acessa a fila e visualiza, por exemplo:

Ordem	Paciente	Especialidade	Médico	Data da solicitação	Situação
1	Maria	Cardiologia	Dr. João	01/07	Aguardando
2	José	Cardiologia	Dr. João	02/07	Aguardando
3	Ana	Cardiologia	Qualquer	03/07	Aguardando

Então a recepção:

Seleciona o primeiro da fila.
Faz contato.
Registra o resultado:
Confirmou.
Não atendeu.
Desistiu.
Reagendar contato.
Se confirmar, gera o Agendamento usando a estrutura já existente.
A solicitação da fila passa para Encaixado ou Finalizado.

Assim, a fila funciona como um CRM interno de oportunidades de agendamento, enquanto a tabela agendamento continua armazenando apenas consultas efetivamente marcadas.

Esse modelo preserva a arquitetura atual e evita misturar registros de interesse com agendamentos já confirmados.