Ir para conteúdo

POWERED BY:

Williams Duarte

Members
  • Total de itens

    3974
  • Registro em

  • Última visita

  • Dias vencidos

    47

Reputação

431 Incrível

Sobre Williams Duarte

  • Data de Nascimento 05/17/1989

Informações Pessoais

  • Sexo
    Masculino
  • Interesses
    Tecnologia, Engenharia de Software, PHP, Design Pattern, JavaScript, SQL, NoSQL e Empreendedorismo

Últimos Visitantes

8830702 visualizações
  1. Williams Duarte

    Fixar div até atingir uma certa altura

    Você pode ajustar o comportamento da div para que ela pare de ser fixa ao se aproximar do rodapé, calculando a distância entre a div e o rodapé durante o scroll. Aqui está uma solução que faz isso: <script> $(function(){ var jElement = $('.fixar_banner'); var footer = $('footer'); // Substitua 'footer' pelo seletor do seu rodapé var offsetTop = jElement.offset().top; var footerOffset = footer.offset().top; var elementHeight = jElement.outerHeight(); $(window).scroll(function(){ var scrollTop = $(this).scrollTop(); var distanceToFooter = footerOffset - (scrollTop + elementHeight + 20); // 20 é um espaçamento extra if (scrollTop > offsetTop && distanceToFooter > 0) { jElement.css({ 'position': 'fixed', 'top': '10px' }); } else if (scrollTop > offsetTop && distanceToFooter <= 0) { jElement.css({ 'position': 'absolute', 'top': footerOffset - elementHeight }); } else { jElement.css({ 'position': 'relative', 'top': 'auto' }); } }); }); </script> Explicação: Cálculo das Posições: - offsetTop: É a distância inicial da div em relação ao topo da página. - footerOffset: É a distância do rodapé em relação ao topo da página. - elementHeight: É a altura da div que você quer fixar. Lógica do Scroll: 1. Quando o scroll é maior que a posição inicial da div (offsetTop) e ainda há espaço antes do rodapé (distanceToFooter > 0): - A div é fixada na posição desejada (por exemplo, top: 10px). 2. Quando a div está próxima do rodapé (distanceToFooter <= 0): - A div é posicionada de forma absoluta, alinhando-se ao topo do rodapé. 3. Caso contrário: - A div retorna à posição relativa original. Ajustes: - Certifique-se de substituir 'footer' pelo seletor correto do seu rodapé. - O valor 20 é um espaçamento extra para evitar que a div encoste no rodapé. Ajuste conforme necessário.
  2. Williams Duarte

    Fixar div até atingir uma certa altura

    DeepSeek, a ferramenta de IA, vai tirar suas dúvidas e é gratuita ainda: https://chat.deepseek.com/
  3. Williams Duarte

    Ajuda com Extends e envio para o banco

    DeepSeek, a ferramenta de IA, vai tirar suas dúvidas e é gratuita ainda: https://chat.deepseek.com/
  4. Williams Duarte

    PHP+Codeginiter - Orientação para Impressão

    DeepSeek, a ferramenta de IA, vai tirar suas dúvidas e é gratuita ainda: https://chat.deepseek.com/
  5. Williams Duarte

    PHP+Codeigniter - Dúvida referente a PDV

    Na prática, existem duas abordagens principais, cada uma com seus prós e contras: Baixa após finalização da venda (Recomendado): O estoque só é atualizado quando a venda é efetivamente concluída (pagamento confirmado) Vantagens: Evita inconsistências caso a venda seja cancelada Maior segurança nas operações Histórico mais preciso de transações Desvantagens: Necessidade de verificar disponibilidade real-time durante a venda Baixa durante a inclusão dos itens: O estoque é atualizado conforme os produtos são adicionados ao carrinho Vantagens: Reserva imediata do produto Previne vendas simultâneas do mesmo item Desvantagens: Necessidade de "desfazer" as baixas em caso de cancelamento Maior complexidade no controle de transações Risco de inconsistências em caso de falhas Recomendação: Implementar a baixa após a finalização da venda, mas com um sistema de "reserva temporária" durante o processo de venda. Isso pode ser feito: // No Controller do PDV public function adicionarItem() { // Verifica disponibilidade real-time $disponivel = $this->estoque_model->verificarDisponibilidade($produto_id, $quantidade); if ($disponivel) { // Adiciona à reserva temporária $this->reserva_model->reservarProduto($produto_id, $quantidade, $venda_id); // Adiciona ao carrinho $this->venda_model->adicionarItem($produto_id, $quantidade, $venda_id); } } public function finalizarVenda($venda_id) { // Confirma o pagamento if ($this->pagamento_model->processar($venda_id)) { // Efetua a baixa real no estoque $this->estoque_model->baixarProdutos($venda_id); // Remove as reservas $this->reserva_model->limparReservas($venda_id); return true; } return false; } Esta abordagem oferece: Segurança nas operações Controle preciso do estoque Possibilidade de cancelamento sem inconsistências Prevenção de vendas duplicadas O importante é garantir que o sistema tenha tratamento adequado para: Timeout de reservas não finalizadas Cancelamentos Falhas durante o processo Concorrência de vendas
  6. Williams Duarte

    PHP+Codeigniter - Dúvida em Relação a Teclas

    Normalize a tecla para minúscula const key = evt.key.toLowerCase();
  7. Williams Duarte

    [Resolvido] JavaScript - Exibir logo dentro da Tabela html

    Para exibir um logo quando a tabela estiver vazia, você pode: 1 - Adicionar uma div com o logo abaixo da tabela: <table id="tbventas"> <tbody></tbody> </table> <div id="empty-table-logo" style="text-align:center;"> <img src="caminho/logo.png" alt="Logo empresa"> </div> 2 - Controlar a visibilidade via JavaScript: // Função para verificar se tabela está vazia function checkTableEmpty() { const tbody = document.querySelector("#tbventas tbody"); const logo = document.getElementById("empty-table-logo"); if (tbody.children.length === 0) { logo.style.display = "block"; } else { logo.style.display = "none"; } } // Chamar após remover ou adicionar itens $("#tbventas tbody").append(html); checkTableEmpty(); // Na remoção de item $('.btn-remove-produto').click(function() { $(this).closest('tr').remove(); checkTableEmpty(); }); Chame checkTableEmpty() sempre que manipular a tabela para atualizar a visibilidade do logo.
  8. Williams Duarte

    PHP+Codeigniter - Implementar o Input CÓDIGO ou ID do Produto

    Primeiro, você não está declarando a variável timeoutId <script type="text/javascript"> $(document).ready(function(){ let timeoutId; // Declaração da variável $('#idProdutos').on('input', function() { clearTimeout(timeoutId); const idprd = $(this).val(); timeoutId = setTimeout(function() { if (idprd) { $.ajax({ url: "<?php echo base_url(); ?>vendas/pdvcaixa/buscarID", type: "POST", data: { idProdutos: idprd }, // Corrigido nome do parâmetro dataType: 'json', // Importante adicionar success: function(response) { if (response.success) { // Como o resultado é um array, pegamos o primeiro item if (response.produto.length > 0) { $("#descricao").val(response.produto[0].descricao); } } }, error: function(xhr, status, error) { console.log('Erro:', error); } }); } }, 1500); }); }); </script> No Controller, ajuste para: public function buscarID() { $idprd = $this->input->post('idProdutos'); $produto = $this->pdvcaixa_model->buscarCodigo($idprd); if ($produto) { echo json_encode([ 'success' => true, 'produto' => $produto ]); } else { echo json_encode([ 'success' => false, 'message' => 'Produto não encontrado' ]); } } Se ainda assim não funcionar, você pode adicionar alguns console.log para debug: $('#idProdutos').on('input', function() { console.log('Input detectado'); clearTimeout(timeoutId); const idprd = $(this).val(); console.log('Valor digitado:', idprd); timeoutId = setTimeout(function() { console.log('Timeout executado'); if (idprd) { // ... resto do código
  9. Williams Duarte

    PHP+Codeigniter - Implementar o Input CÓDIGO ou ID do Produto

    Para implementar a busca automática com delay de 1-2 segundos sem precisar do ENTER, você pode usar jQuery junto com CodeIgniter. Segue um exemplo simples: $('#codigo_produto').on('input', function() { clearTimeout(timeoutId); const codigo = $(this).val(); timeoutId = setTimeout(function() { if (codigo) { $.ajax({ url: '<?= base_url("produtos/buscar") ?>', type: 'POST', data: { codigo: codigo }, success: function(response) { // Exibe o resultado if (response.success) { $('#resultado').html(response.produto.descricao); } } }); } }, 1500); // 1.5 segundos de delay }); No seu controller: public function buscar() { $codigo = $this->input->post('codigo'); $produto = $this->produtos_model->buscar_por_codigo($codigo); echo json_encode([ 'success' => true, 'produto' => $produto ]); } O código acima vai esperar 1.5 segundos após o usuário parar de digitar antes de fazer a busca. Você pode ajustar o delay alterando o valor 1500 para qualquer outro valor em milissegundos.
  10. Williams Duarte

    PHP+Codeigniter - Adicionar Registro Plano de Contas

    Neste caso tem que criar uma configuração dos níveis e seus formatos $nivel_config = [ 1 => ['length' => 2, 'format' => '%02d'], // 1.01 2 => ['length' => 3, 'format' => '%03d'], // 1.01.001 3 => ['length' => 4, 'format' => '%04d'], // 1.01.001.0001 4 => ['length' => 5, 'format' => '%05d'] // 1.01.001.0001.00001 (caso precise e por ai vai) ]; public function getNextCode($parent_code = null) { log_message('debug', '=== INÍCIO getNextCode ==='); log_message('debug', 'Parent Code: ' . ($parent_code ?? 'NULL')); // Configuração dos níveis e seus formatos $nivel_config = [ 1 => ['length' => 2, 'format' => '%02d'], // 1.01 2 => ['length' => 3, 'format' => '%03d'], // 1.01.001 3 => ['length' => 4, 'format' => '%04d'], // 1.01.001.0001 4 => ['length' => 5, 'format' => '%05d'] // 1.01.001.0001.00001 (caso precise e por ai vai) ]; if (!$parent_code) { $query = $this->db->select('MAX(CAST(pl_idconta AS UNSIGNED)) as max_code') ->from('planocontas') ->where('pl_idconta NOT LIKE "%.%"') ->get(); $result = $query->row(); $next_code = ($result->max_code ?? 0) + 1; log_message('debug', 'Gerando código raiz: ' . $next_code); return $next_code; } $parent_parts = explode('.', $parent_code); $nivel = count($parent_parts); log_message('debug', 'Nível hierárquico: ' . $nivel); // Verifica se o nível é suportado if (!isset($nivel_config[$nivel])) { log_message('error', 'Nível não suportado: ' . $nivel); return false; } $query = $this->db->select('pl_idconta') ->from('planocontas') ->like('pl_idconta', $parent_code . '.', 'after') ->order_by('pl_idconta', 'DESC') ->limit(1) ->get(); log_message('debug', 'SQL executado: ' . $this->db->last_query()); if ($query->num_rows() == 0) { // Primeiro subcódigo deste nível $new_code = $parent_code . '.' . sprintf($nivel_config[$nivel]['format'], 1); log_message('debug', 'Primeiro subcódigo deste pai: ' . $new_code); return $new_code; } $ultimo_codigo = $query->row()->pl_idconta; $partes = explode('.', $ultimo_codigo); $ultimo_numero = (int)end($partes); log_message('debug', sprintf( 'Último código: %s | Último número: %s', $ultimo_codigo, $ultimo_numero )); // Gera próximo código usando a configuração do nível $proximo = sprintf($nivel_config[$nivel]['format'], $ultimo_numero + 1); $final_code = $parent_code . '.' . $proximo; log_message('debug', 'Código gerado: ' . $final_code); log_message('debug', '=== FIM getNextCode ==='); return $final_code; } No controller, ajuste a função que busca os códigos pais public function novo() { $this->load->model('planocontas_model'); $max_nivel = 4; // Defina aqui o número máximo de níveis desejado $data['plcta'] = $this->db ->select('*') ->from('planocontas') ->where('pl_status', 1) ->where('CHAR_LENGTH(pl_idconta) - CHAR_LENGTH(REPLACE(pl_idconta, ".", "")) <', $max_nivel) ->order_by('pl_idconta') ->get() ->result(); $this->load->view('estilo/header', $this->data); $this->load->view('faturamento/planocontas/adicionarConta', $data); }
  11. Williams Duarte

    PHP+Codeigniter - Adicionar Registro Plano de Contas

    Aplique log e vai debugando public function getNextCode($parent_code = null) { log_message('debug', '=== INÍCIO getNextCode ==='); log_message('debug', 'Parent Code: ' . ($parent_code ?? 'NULL')); if (!$parent_code) { $query = $this->db->select('MAX(CAST(pl_idconta AS UNSIGNED)) as max_code') ->from('planocontas') ->where('pl_idconta NOT LIKE "%.%"') ->get(); $result = $query->row(); $next_code = ($result->max_code ?? 0) + 1; log_message('debug', 'Gerando código raiz: ' . $next_code); return $next_code; } $parent_parts = explode('.', $parent_code); $nivel = count($parent_parts); log_message('debug', 'Nível hierárquico: ' . $nivel); $query = $this->db->select('pl_idconta') ->from('planocontas') ->like('pl_idconta', $parent_code . '.', 'after') ->order_by('pl_idconta', 'DESC') ->limit(1) ->get(); log_message('debug', 'SQL executado: ' . $this->db->last_query()); if ($query->num_rows() == 0) { $new_code = ($nivel == 1) ? $parent_code . '.01' : $parent_code . '.0001'; log_message('debug', 'Primeiro subcódigo deste pai: ' . $new_code); return $new_code; } $ultimo_codigo = $query->row()->pl_idconta; $partes = explode('.', $ultimo_codigo); $ultimo_numero = end($partes); log_message('debug', sprintf( 'Último código: %s | Último número: %s', $ultimo_codigo, $ultimo_numero )); if ($nivel == 1) { $proximo = str_pad((int)$ultimo_numero + 1, 2, '0', STR_PAD_LEFT); } else { $proximo = str_pad((int)$ultimo_numero + 1, 4, '0', STR_PAD_LEFT); } $final_code = $parent_code . '.' . $proximo; log_message('debug', 'Código gerado: ' . $final_code); log_message('debug', '=== FIM getNextCode ==='); return $final_code; } Os logs serão gravados em application/logs/. Para visualizar, ative debug no config.php: $config['log_threshold'] = 2; // Debug Caso não consiga corrigir o código pelo debug, poste os logs aqui! Mas dei mais um ajuste!
  12. Williams Duarte

    PHP+Codeigniter - Adicionar Registro Plano de Contas

    O problema está na lógica do getNextCode(): Fiz uns ajustes, não tenho como testar, só olhei a doc por cima de como monta selects no CI, que é bem parecida com Query Builder do Laravel public function getNextCode($parent_code = null) { if (!$parent_code) { // Busca próximo código raiz $query = $this->db->select('MAX(CAST(pl_idconta AS UNSIGNED)) as max_code') ->from('planocontas') ->where('pl_idconta NOT LIKE "%.%"') ->get(); $result = $query->row(); return ($result->max_code ?? 0) + 1; } // Busca subcódigos do mesmo nível $parent_parts = explode('.', $parent_code); $nivel = count($parent_parts); $like_pattern = $parent_code . '.%'; $query = $this->db->select('pl_idconta') ->from('planocontas') ->like('pl_idconta', $like_pattern, 'after') ->get(); $codigos_mesmo_nivel = []; foreach ($query->result() as $row) { $parts = explode('.', $row->pl_idconta); if (count($parts) == $nivel + 1) { $codigos_mesmo_nivel[] = (int)end($parts); } } $proximo = empty($codigos_mesmo_nivel) ? 1 : max($codigos_mesmo_nivel) + 1; // Formata o número baseado no nível if ($nivel == 1) { // Nível 1.XX return $parent_code . '.' . str_pad($proximo, 2, '0', STR_PAD_LEFT); } else if ($nivel == 2) { // Nível 1.XX.XXXX return $parent_code . '.' . str_pad($proximo, 4, '0', STR_PAD_LEFT); } else { // Demais níveis return $parent_code . '.' . $proximo; } } Principais correções: Separação por níveis hierárquicos Contagem correta do próximo número Formatação específica para cada nível Exemplo de resultado: 1 - Principal 1.01 - Setor A 1.01.0001 - Subsetor A1 1.02 - Setor B 2 - Secundário 2.01 - Filial 1 Para fins de comparação # Plano de Contas - Correção na geração de códigos hierárquicos ## Alterações no método getNextCode() - Corrigida lógica de incremento dos níveis - Melhorada separação hierárquica - Adicionada formatação específica por nível ```diff public function getNextCode($parent_code = null) { - if (!$parent_code) { - $query = $this->db->select('MAX(SUBSTRING_INDEX(pl_idconta, ".", 1)) as max_code') - ->from('planocontas') - ->where('LENGTH(pl_idconta) = 1') - ->get(); + if (!$parent_code) { + // Busca próximo código raiz usando CAST para comparação numérica + $query = $this->db->select('MAX(CAST(pl_idconta AS UNSIGNED)) as max_code') + ->from('planocontas') + ->where('pl_idconta NOT LIKE "%.%"') + ->get(); $result = $query->row(); return ($result->max_code ?? 0) + 1; } - $like_pattern = $parent_code . '.%'; - $length = strlen($parent_code) + 3; + // Identificação do nível hierárquico atual + $parent_parts = explode('.', $parent_code); + $nivel = count($parent_parts); + // Busca subcódigos existentes no mesmo nível + $like_pattern = $parent_code . '.%'; $query = $this->db->select('MAX(SUBSTRING_INDEX(pl_idconta, ".", -1)) as max_code') ->from('planocontas') ->like('pl_idconta', $like_pattern, 'after') - ->where('LENGTH(pl_idconta) =', $length) ->get(); $result = $query->row(); - $next_number = str_pad(($result->max_code ?? 0) + 1, 2, '0', STR_PAD_LEFT); - return $parent_code . '.' . $next_number; + + // Formatação específica por nível + if ($nivel == 1) { + // Nível 1.XX + return $parent_code . '.' . str_pad($proximo, 2, '0', STR_PAD_LEFT); + } else if ($nivel == 2) { + // Nível 1.XX.XXXX + return $parent_code . '.' . str_pad($proximo, 4, '0', STR_PAD_LEFT); + } else { + // Demais níveis sem padding + return $parent_code . '.' . $proximo; + } } Principais mudanças: Código raiz (nível 0) Uso de CAST para comparação numérica correta Filtro aprimorado para códigos sem pontos Subcódigos Identificação do nível através de explode() Formatação específica para cada nível Remoção da restrição de LENGTH fixa Formatação Nível 1: XX (dois dígitos) Nível 2: XXXX (quatro dígitos) Demais níveis: sem padding
  13. Williams Duarte

    PHP+Codeigniter - Adicionar Registro Plano de Contas

    O campo parent_code é fundamental para criar a hierarquia do plano de contas. Vou mostrar um exemplo prático de formulário HTML e como ele funciona: <form method="post" action="<?php echo base_url('plano_contas/adicionar'); ?>"> <!-- Campo para código pai (parent_code) --> <div class="form-group"> <label>Código Pai:</label> <select name="parent_code" class="form-control"> <option value="">-- Selecione o código pai --</option> <?php foreach($codigos_pais as $codigo): ?> <option value="<?php echo $codigo->codigo; ?>"> <?php echo $codigo->codigo . ' - ' . $codigo->descricao; ?> </option> <?php endforeach; ?> </select> </div> <!-- Campo descrição --> <div class="form-group"> <label>Descrição:</label> <input type="text" name="descricao" class="form-control" required> </div> <button type="submit" class="btn btn-primary">Salvar</button> </form> Para exemplificar o funcionamento: Quando parent_code é vazio (null): Sistema gera: "1" (primeiro registro) Próximo será: "2" Quando parent_code é "1": Sistema gera: "1.01" Próximo será: "1.02" Quando parent_code é "1.01": Sistema gera: "1.01.0001" Próximo será: "1.01.0002" Aqui está o código atualizado do controller para buscar os códigos pais: public function novo() { // Carrega todos os códigos possíveis de serem pai $this->load->model('PlanoContasModel'); $data['codigos_pais'] = $this->db ->select('codigo, descricao') ->from('plano_contas') ->where('LENGTH(codigo) <=', 4) // Limita a 2 níveis (1 ou 1.01) ->order_by('codigo') ->get() ->result(); $this->load->view('plano_contas/formulario', $data); } Assim: Se você deixar o "Código Pai" vazio → Cria código raiz (1, 2, 3...) Se selecionar "1" como pai → Cria subcódigo (1.01, 1.02...) Se selecionar "1.01" como pai → Cria subcódigo (1.01.0001, 1.01.0002...) Vou ler depois sua mensagem!
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.