HEX
Server: LiteSpeed
System: Linux cp01.bhostbrasil.com.br 5.14.0-611.16.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Dec 22 03:40:39 EST 2025 x86_64
User: onlyfibr (1083)
PHP: 8.2.31
Disabled: NONE
Upload Files
File: /home/onlyfibr/public_html/assinar/admin/cadastros_pendentes.php
<?php
// HABILITAR ERROS PARA DEBUG - REMOVER/COMENTAR EM PRODUÇÃO!
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// ---------------------------------------------------------
// 1. Verifica se o admin está logado
require_once 'includes/auth_check.php';

// Define o título desta página ANTES de incluir o header
$pageTitle = 'Cadastros Pendentes';

require_once '../includes/config/config.php'; // Necessário para $pdo e constantes
require_once '../includes/functions/functions.php'; // Pode ser necessário para alguma função auxiliar

// --- Processamento de Ações (POST Requests) ---
$mensagem_erro = $_SESSION['erro_dashboard'] ?? null;
$mensagem_sucesso = $_SESSION['sucesso_dashboard'] ?? null;
$erro_busca_db = ''; // Inicializa como string vazia
unset($_SESSION['erro_dashboard'], $_SESSION['sucesso_dashboard']);

// Geração de token CSRF
if (!isset($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
$csrf_token = $_SESSION['csrf_token'];

// --- Ação: Processar API Manualmente ---
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'process_api') {
    // Verificação do token CSRF
    if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
        $_SESSION['erro_dashboard'] = "Erro de validação do formulário. Por favor, tente novamente.";
        header('Location: ' . htmlspecialchars($_SERVER['PHP_SELF']));
        exit;
    }
    
    $id_para_processar = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);

    if ($id_para_processar && $pdo) {
        try {
            // 1. Buscar todos os dados necessários do pré-cadastro
            //    Certifique-se de incluir TODOS os campos que a API espera.
            $sqlFetch = "SELECT * FROM precadastros WHERE id = :id AND p_processar = TRUE LIMIT 1";
            $stmtFetch = $pdo->prepare($sqlFetch);
            $stmtFetch->bindParam(':id', $id_para_processar, PDO::PARAM_INT);
            $stmtFetch->execute();
            $data = $stmtFetch->fetch(PDO::FETCH_ASSOC);

            if ($data) {
                // 2. Determinar o endpoint correto
                $endpointApi = ($data['tipo_pessoa'] === 'PF') ? '/api/precadastro/F' : '/api/precadastro/J';

                // 3. Montar o Payload da API (similar ao assinar.php)
                //    Adapte os nomes dos campos conforme a API espera e os dados do seu DB.
                $payloadApi = [
                    'app' => APP_NAME,
                    'token' => APP_TOKEN,
                    'nome' => $data['nome'],
                    'cpfcnpj' => $data['cpf_cnpj'],
                    'email' => $data['email'],
                    'celular' => $data['celular'],
                    'logradouro' => $data['logradouro'],
                    'numero' => (int)$data['numero'], // Garante que seja inteiro
                    'complemento' => $data['complemento'] ?: null,
                    'bairro' => $data['bairro'],
                    'cidade' => $data['cidade'],
                    'cep' => $data['cep'], // Certifique-se que está sem máscara
                    'uf' => $data['estado'], // Ajuste se o nome da coluna for diferente
                    'pais' => 'BR', // Ou buscar do DB se necessário
                    'pontoreferencia' => $data['ponto_referencia'] ?: null, // Ajuste nome da coluna
                    'observacao' => $data['observacao'] ?: null,
                    'plano_id' => $data['plano_id_selecionado'], // Ajuste nome da coluna
                    'vencimento_id' => $data['vencimento_id_selecionado'], // Ajuste nome da coluna
                    'vendedor_id' => $data['vendedor_id'] ?: null, // Ajuste nome da coluna
                    // Campos específicos PF/PJ
                    // Adicione aqui os campos RG, Data Nasc, Nome Fantasia, IE, etc., se existirem na sua tabela e forem necessários pela API
                ];
                if ($data['tipo_pessoa'] === 'PF') {
                    $payloadApi['rg'] = $data['rg'] ?? null; // Ajuste nome da coluna
                    $payloadApi['rg_emissor'] = $data['rg_emissor'] ?? null; // Ajuste nome da coluna
                    $payloadApi['datanasc'] = $data['data_nascimento'] ?? null; // Ajuste nome da coluna e formato se necessário
                }
                if ($data['tipo_pessoa'] === 'PJ') {
                    $payloadApi['nomefantasia'] = $data['nome_fantasia'] ?? null; // Ajuste nome da coluna
                    $payloadApi['insc_estadual'] = $data['insc_estadual'] ?? null; // Ajuste nome da coluna
                }

                // Remover chaves com valor null, se a API não os aceitar
                $payloadApi = array_filter($payloadApi, function ($value) {
                    return $value !== null;
                });

                // 4. Chamar a API
                $responseApi = postApiJson(BASE_URL, $endpointApi, $payloadApi);
                $resultadoApi = json_decode($responseApi, true);
                $api_response_msg = $responseApi; // Salva a resposta crua

                // 5. Verificar o resultado e atualizar o banco
                //    A condição de sucesso pode variar dependendo da resposta da sua API
                if (json_last_error() === JSON_ERROR_NONE && isset($resultadoApi['message']) && stripos($resultadoApi['message'], 'criado com sucesso') !== false) {
                    // Sucesso! Atualiza p_processar para FALSE e status_processamento
                    $sqlUpdate = "UPDATE precadastros SET p_processar = :p_proc, status_processamento = 'aprovado', resposta_api = :resp WHERE id = :id";
                    $stmtUpdate = $pdo->prepare($sqlUpdate);
                    // Define explicitamente o valor como booleano e usa PDO::PARAM_BOOL
                    $stmtUpdate->bindValue(':p_proc', false, PDO::PARAM_BOOL);
                    $stmtUpdate->bindValue(':resp', "Processado manualmente com sucesso: " . $api_response_msg);
                    $stmtUpdate->bindParam(':id', $id_para_processar, PDO::PARAM_INT);
                    $stmtUpdate->execute(); // Esta linha agora usa o valor booleano corretamente vinculado
                    $_SESSION['sucesso_dashboard'] = "Registro ID {$id_para_processar} processado e enviado para a API com sucesso.";
                } else {
                    // Falha na API
                    $erro_api_msg = $resultadoApi['message'] ?? ($resultadoApi['msg'] ?? 'Erro desconhecido retornado pela API.');
                    // Atualiza apenas a resposta da API, mas mantém p_processar = TRUE
                    $sqlUpdate = "UPDATE precadastros SET resposta_api = :resp WHERE id = :id";
                    $stmtUpdate = $pdo->prepare($sqlUpdate);
                    $stmtUpdate->bindValue(':resp', "Falha no processamento manual: " . $api_response_msg);
                    $stmtUpdate->bindParam(':id', $id_para_processar, PDO::PARAM_INT);
                    $stmtUpdate->execute();
                    $_SESSION['erro_dashboard'] = "Erro ao processar API para ID {$id_para_processar}: " . htmlspecialchars($erro_api_msg);
                    error_log("Erro API processamento manual $id_para_processar ($endpointApi) (PGSQL). Payload: " . json_encode($payloadApi) . ". Resp: " . $responseApi);
                }
            } else {
                $_SESSION['erro_dashboard'] = "Registro ID {$id_para_processar} não encontrado ou já processado.";
            }
        } catch (\PDOException $e) {
            $failing_sql = $stmtUpdate->queryString ?? ($stmtFetch->queryString ?? 'Query Desconhecida');
            error_log("PDOException ao processar API ID {$id_para_processar}. SQLState: " . $e->getCode() . ". Mensagem PDO: " . $e->getMessage() . ". Query Provável: " . $failing_sql);
            $_SESSION['erro_dashboard'] = "Erro de banco de dados [Ref:" . $e->getCode() . "] ao atualizar registro. Verifique os logs.";
        } catch (\Exception $e) { // Captura erros gerais (ex: falha na função postApiJson)
            error_log("Erro GERAL ao processar API manualmente para ID {$id_para_processar}: " . $e->getMessage());
            $_SESSION['erro_dashboard'] = "Erro inesperado ao processar API para ID {$id_para_processar}. Verifique os logs.";
        }
    } else {
        $_SESSION['erro_dashboard'] = "ID inválido para processamento.";
    }
    // Redireciona para limpar POST e atualizar a tabela
    header('Location: ' . htmlspecialchars($_SERVER['PHP_SELF']));
    exit;
}

// --- Ação: Processar Todos os Registros Pendentes ---
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'process_all') {
    // Verificação do token CSRF
    if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
        $_SESSION['erro_dashboard'] = "Erro de validação do formulário. Por favor, tente novamente.";
        header('Location: ' . htmlspecialchars($_SERVER['PHP_SELF']));
        exit;
    }
    
    $registros_processados = 0;
    $registros_com_erro = 0;

    if ($pdo) {
        try {
            // 1. Buscar todos os registros pendentes
            $sqlFetchAll = "SELECT id FROM precadastros WHERE p_processar = TRUE ORDER BY id";
            $stmtFetchAll = $pdo->query($sqlFetchAll);
            $pendentes = $stmtFetchAll->fetchAll(PDO::FETCH_COLUMN);

            if (!empty($pendentes)) {
                foreach ($pendentes as $id_registro) {
                    // Para cada registro pendente, executamos o processamento individual
                    try {
                        // Buscar dados do registro
                        $sqlFetch = "SELECT * FROM precadastros WHERE id = :id AND p_processar = TRUE LIMIT 1";
                        $stmtFetch = $pdo->prepare($sqlFetch);
                        $stmtFetch->bindParam(':id', $id_registro, PDO::PARAM_INT);
                        $stmtFetch->execute();
                        $data = $stmtFetch->fetch(PDO::FETCH_ASSOC);
                        
                        if (!$data) {
                            $registros_com_erro++;
                            continue; // Pula para o próximo registro
                        }
                        
                        // Determinar o endpoint correto
                        $endpointApi = ($data['tipo_pessoa'] === 'PF') ? '/api/precadastro/F' : '/api/precadastro/J';
                        
                        // Construir o payload
                        $payloadApi = [
                            'app' => APP_NAME,
                            'token' => APP_TOKEN,
                            'nome' => $data['nome'],
                            'cpfcnpj' => $data['cpf_cnpj'],
                            'email' => $data['email'],
                            'celular' => $data['celular'],
                            'logradouro' => $data['logradouro'],
                            'numero' => (int)$data['numero'],
                            'complemento' => $data['complemento'] ?: null,
                            'bairro' => $data['bairro'],
                            'cidade' => $data['cidade'],
                            'cep' => $data['cep'],
                            'uf' => $data['estado'],
                            'pais' => 'BR',
                            'pontoreferencia' => $data['ponto_referencia'] ?: null,
                            'observacao' => $data['observacao'] ?: null,
                            'plano_id' => $data['plano_id_selecionado'],
                            'vencimento_id' => $data['vencimento_id_selecionado'],
                            'vendedor_id' => $data['vendedor_id'] ?: null,
                        ];
                        
                        // Adicionar campos específicos para PF ou PJ
                        if ($data['tipo_pessoa'] === 'PF') {
                            $payloadApi['rg'] = $data['rg'] ?? null;
                            $payloadApi['rg_emissor'] = $data['rg_emissor'] ?? null;
                            $payloadApi['datanasc'] = $data['data_nascimento'] ?? null;
                        }
                        if ($data['tipo_pessoa'] === 'PJ') {
                            $payloadApi['nomefantasia'] = $data['nome_fantasia'] ?? null;
                            $payloadApi['insc_estadual'] = $data['insc_estadual'] ?? null;
                        }
                        
                        // Remover valores nulos
                        $payloadApi = array_filter($payloadApi, function ($value) {
                            return $value !== null;
                        });
                        
                        // Chamar API
                        $responseApi = postApiJson(BASE_URL, $endpointApi, $payloadApi);
                        $resultadoApi = json_decode($responseApi, true);
                        
                        // Verificar resultado e atualizar banco
                        if (json_last_error() === JSON_ERROR_NONE && isset($resultadoApi['message']) && stripos($resultadoApi['message'], 'criado com sucesso') !== false) {
                            // Sucesso
                            $sqlUpdate = "UPDATE precadastros SET p_processar = :p_proc, status_processamento = 'aprovado', resposta_api = :resp WHERE id = :id";
                            $stmtUpdate = $pdo->prepare($sqlUpdate);
                            $stmtUpdate->bindValue(':p_proc', false, PDO::PARAM_BOOL);
                            $stmtUpdate->bindValue(':resp', "Processado em lote com sucesso: " . $responseApi);
                            $stmtUpdate->bindParam(':id', $id_registro, PDO::PARAM_INT);
                            $stmtUpdate->execute();
                            $registros_processados++;
                        } else {
                            // Falha
                            $erro_api_msg = $resultadoApi['message'] ?? ($resultadoApi['msg'] ?? 'Erro desconhecido retornado pela API.');
                            $sqlUpdate = "UPDATE precadastros SET resposta_api = :resp WHERE id = :id";
                            $stmtUpdate = $pdo->prepare($sqlUpdate);
                            $stmtUpdate->bindValue(':resp', "Falha no processamento em lote: " . $responseApi);
                            $stmtUpdate->bindParam(':id', $id_registro, PDO::PARAM_INT);
                            $stmtUpdate->execute();
                            $registros_com_erro++;
                            error_log("Erro API processamento em lote $id_registro ($endpointApi). Payload: " . json_encode($payloadApi) . ". Resp: " . $responseApi);
                        }
                    } catch (\Exception $e) {
                        $registros_com_erro++;
                        error_log("Erro ao processar ID $id_registro em lote: " . $e->getMessage());
                    }
                }

                // Feedback final
                if ($registros_processados > 0) {
                    $_SESSION['sucesso_dashboard'] = "Processamento em lote concluído. $registros_processados registros processados com sucesso" . 
                                                   ($registros_com_erro > 0 ? " e $registros_com_erro com erro." : ".");
                } else {
                    $_SESSION['erro_dashboard'] = "Nenhum registro processado com sucesso. $registros_com_erro registros com erro.";
                }
            } else {
                $_SESSION['mensagem_dashboard'] = "Não foram encontrados registros pendentes de processamento.";
            }
        } catch (\PDOException $e) {
            error_log("Erro DB ao processar todos os registros: " . $e->getMessage());
            $_SESSION['erro_dashboard'] = "Erro de banco de dados ao processar registros em lote. Verifique os logs.";
        } catch (\Exception $e) {
            error_log("Erro geral ao processar todos os registros: " . $e->getMessage());
            $_SESSION['erro_dashboard'] = "Erro inesperado ao processar registros em lote. Verifique os logs.";
        }
    }
    
    // Redireciona para limpar POST e atualizar a tabela
    header('Location: ' . htmlspecialchars($_SERVER['PHP_SELF']));
    exit;
}

// --- Busca dos Dados para Listagem ---
$lista_pendentes = [];
$erro_busca_db = '';
if ($pdo) {
    try {
        // Busca apenas os registros pendentes (p_processar = TRUE)
        $sql = "SELECT id, nome, email, celular, cpf_cnpj, cidade, estado, tipo_moradia, status_processamento, data_envio, resposta_api, tipo_pessoa
                FROM precadastros 
                WHERE p_processar = TRUE
                ORDER BY data_envio DESC, id DESC"; // Ordena pelos mais recentes
        $stmt = $pdo->query($sql);
        $lista_pendentes = $stmt->fetchAll(PDO::FETCH_ASSOC);
    } catch (\PDOException $e) {
        $erro_busca_db = "Erro ao buscar dados: " . $e->getMessage();
        error_log("Erro DB Pendentes: " . $e->getMessage());
    }
} else {
    $erro_busca_db = "Erro crítico: Conexão com banco de dados falhou.";
}

// Contador total de pendentes
$total_pendentes = count($lista_pendentes);

// Obter os menus dinamicamente do banco de dados
$menus = carregarMenus($pdo, $usuario_permissoes ?? ['admin']);

// Incluir o header
include_once 'includes/header.php';
?>

<div class="container">
    <div class="d-flex justify-content-between align-items-center mb-3">
        <div>
            <h1>Cadastros Pendentes de Processamento</h1>
            <p class="text-muted">Registros que precisam ser enviados para a API SGP</p>
        </div>
        <div>
            <?php if ($total_pendentes > 0): ?>
            <form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>" class="d-inline" id="processarTodosForm">
                <input type="hidden" name="action" value="process_all">
                <input type="hidden" name="csrf_token" value="<?php echo $csrf_token; ?>">
                <button type="submit" class="btn btn-warning" id="btnProcessarTodos">
                    <i class="fas fa-paper-plane"></i> Processar Todos (<?php echo $total_pendentes; ?>)
                </button>
            </form>
            <?php endif; ?>
            <a href="listar_precadastros.php" class="btn btn-outline-secondary ms-2">
                <i class="fas fa-list"></i> Ver Todos os Cadastros
            </a>
        </div>
    </div>

    <?php if ($mensagem_erro): ?>
        <div class="alert alert-danger alert-dismissible fade show" role="alert">
            <?php echo htmlspecialchars($mensagem_erro); ?>
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
        </div>
    <?php endif; ?>
    <?php if ($mensagem_sucesso): ?>
        <div class="alert alert-success alert-dismissible fade show" role="alert">
            <?php echo htmlspecialchars($mensagem_sucesso); ?>
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
        </div>
    <?php endif; ?>
    <?php if ($erro_busca_db): ?>
        <div class="alert alert-danger"><?php echo htmlspecialchars($erro_busca_db); ?></div>
    <?php endif; ?>

    <?php if (empty($lista_pendentes)): ?>
        <div class="alert alert-info">
            <i class="fas fa-info-circle me-2"></i> Não há cadastros pendentes de processamento no momento.
        </div>
    <?php else: ?>
        <div class="table-responsive">
            <table class="table table-striped table-hover">
                <thead class="table-dark">
                    <tr>
                        <th>ID</th>
                        <th>Nome</th>
                        <th>E-mail/WhatsApp</th>
                        <th>CPF/CNPJ</th>
                        <th>Cidade/UF</th>
                        <th>Status</th>
                        <th>Data/Hora</th>
                        <th>Ações</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($lista_pendentes as $cadastro): ?>
                        <tr>
                            <td><?php echo htmlspecialchars($cadastro['id']); ?></td>
                            <td><?php echo htmlspecialchars($cadastro['nome']); ?></td>
                            <td>
                                <small>
                                    <?php echo htmlspecialchars($cadastro['email']); ?><br>
                                    <?php echo htmlspecialchars($cadastro['celular']); ?>
                                </small>
                            </td>
                            <td><?php echo htmlspecialchars($cadastro['cpf_cnpj']); ?></td>
                            <td><?php echo htmlspecialchars($cadastro['cidade'] . '/' . $cadastro['estado']); ?></td>
                            <td>
                                <span class="badge status-<?php echo htmlspecialchars($cadastro['status_processamento']); ?>">
                                    <?php echo ucwords(str_replace('_', ' ', htmlspecialchars($cadastro['status_processamento']))); ?>
                                </span>
                            </td>
                            <td>
                                <small><?php echo date('d/m/Y H:i', strtotime($cadastro['data_envio'])); ?></small>
                            </td>
                            <td>
                                <div class="btn-group">
                                    <form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
                                        <input type="hidden" name="action" value="process_api">
                                        <input type="hidden" name="id" value="<?php echo $cadastro['id']; ?>">
                                        <input type="hidden" name="csrf_token" value="<?php echo $csrf_token; ?>">
                                        <button type="submit" class="btn btn-sm btn-primary" title="Processar API">
                                            <i class="fas fa-paper-plane"></i>
                                        </button>
                                    </form>
                                    <a href="editar_precadastro.php?id=<?php echo $cadastro['id']; ?>" class="btn btn-sm btn-info ms-1" title="Editar">
                                        <i class="fas fa-edit"></i>
                                    </a>
                                    <a href="ver_precadastro.php?id=<?php echo $cadastro['id']; ?>" class="btn btn-sm btn-secondary ms-1" title="Visualizar Detalhes">
                                        <i class="fas fa-eye"></i>
                                    </a>
                                </div>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>
    <?php endif; ?>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
    // Confirmação para processar todos os registros
    const formProcessarTodos = document.getElementById('processarTodosForm');
    if (formProcessarTodos) {
        formProcessarTodos.addEventListener('submit', function(e) {
            if (!confirm('Tem certeza que deseja processar todos os <?php echo $total_pendentes; ?> registros pendentes?')) {
                e.preventDefault();
            }
        });
    }
    
    // Adicionar tooltips do Bootstrap se necessário
    var tooltipTriggerList = [].slice.call(document.querySelectorAll('[title]'))
    var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
      return new bootstrap.Tooltip(tooltipTriggerEl)
    });
});
</script>

<!-- Estilos para os badges de status -->
<style>
.status-pendente {
    background-color: #ffc107;
    color: #212529;
}
.status-aprovado {
    background-color: #198754;
}
.status-rejeitado {
    background-color: #dc3545;
}
.status-processando {
    background-color: #0dcaf0;
    color: #212529;
}
.status-erro {
    background-color: #6c757d;
}
</style>

<?php
// Incluir o footer
include_once 'includes/footer.php';
?>