All Activity
This stream auto-updates
- Yesterday
-
twipeer joined the community
- Last week
-
RUY changed their profile photo
-
resolvido. substr e strlen.
-
Boa tarde, Duvida simples... Quando recupero os dados RSS, para inserir no banco de dados esta salvando corretamento porém no mysql esta com (ponto) . na frente de todos os registros via RSS. Fica com um ponto na frente outro atras... Data/hora: .2024-11-30 10:03:47.
- Earlier
-
PHP+Codeigniter - Adicionar Registro Plano de Contas
Williams Duarte replied to violin101's topic in PHP
-
Caro amigo Williams saudações. Deus o abençoa, deu certo, obrigado, Atenciosamente, Cesar
-
PHP+Codeigniter - Adicionar Registro Plano de Contas
Williams Duarte replied to violin101's topic in PHP
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); } -
Caro amigo, Williams saudações. Deu certo, gravou com as Hierarquias corretamente. Amigo Williams esta linha mostra o tamanho do campo do mysql: ->where('LENGTH(pl_idconta) <=', 4) // Limita a 2 níveis (1 ou 1.01) Alterei para esta e trouxe os níveis: ->where('CHAR_LENGTH(pl_idconta) <=', 4) // Limita a 2 níveis (1 ou 1.01) Observação: apenas curiosidade. se precisar criar mais um nível, como devo fazer, por exemplo: 1 - principal 1.01 - nível_1 1.01.001 - nível_2 1.01.001.0001 - conta_1
-
PHP+Codeigniter - Adicionar Registro Plano de Contas
Williams Duarte replied to violin101's topic in PHP
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! -
Amigo Williams, saudações. POR FAVOR, me PERDOA em recorrer a ajuda do amigo novamente, testando o código que o amigo enviou, continua dando erro de DUPLICIDADE, agora está assim. 1 - TESTE A 1.01 - GRAVA NORMAL 1.01.0001 - GRAVA NORMAL 1.01.0002 ========> AQUI JÁ DÁ ERRO, O SISTEMA NÃO GRAVA .0002 ---- DUPLICA o .0001 novamente 2 - TESTE B 2.01 - GRAVA NORMAL 2.01.0001 - GRAVA NORMAL 2.01.0002 ========> AQUI JÁ DÁ ERRO, O SISTEMA NÃO GRAVA .0002 ---- DUPLICA o .0001 novamente
-
PHP+Codeigniter - Adicionar Registro Plano de Contas
Williams Duarte replied to violin101's topic in PHP
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 -
Caro amigo Williams. Consegui fazer o INSERT. Agora estou com o seguinte problema. Quando salvo os Registro não faz a soma, ou seja, duplica o 1, para todos. Salva assim: 1 - teste 1.01 testeA 1.01.01 testeB 1.01.01.0 testeC Segui todas as suas orientações conforme a MODEL, só não entendo porque não está fazendo o ++. O meu controller ficou assim: function adicionar() { if (!$this->permission->checkPermission($this->session->userdata('permissao'), 'aContas')) { $this->session->set_flashdata('error', 'Você não tem permissão para adicionar plano de contas.'); redirect(base_url()); } $this->load->library('form_validation'); $this->data['custom_error'] = ''; if ($this->form_validation->run('planocontas') == false) { $this->data['custom_error'] = (validation_errors() ? '<div class="form_error">' . validation_errors() . '</div>' : false); } else { $data = [ 'parent_code' => $this->input->post('parent_code'), 'pl_descricao' => $this->input->post('pl_descricao'), 'pl_titulo' => 1, 'pl_status' => 1 ]; /* echo '<pre>'; var_dump($data); echo '</pre>'; exit(); */ $result = $this->planocontas_model->insert($data); if ($result) { $this->session->set_flashdata('success', 'Conta adicionada com sucesso!'); redirect(base_url() . 'faturamento/planocontas/adicionar/'); } else { $this->data['custom_error'] = '<div class="form_error"><p>Ocorreu um erro.</p></div>'; } } $this->novo(); $this->load->view('estilo/header', $this->data); $this->load->view('faturamento/planocontas/adicionarConta'); } public function novo() { // Carrega todos os códigos possíveis de serem pai $this->load->model('planocontas_model'); $data['plcta'] = $this->db ->select('*') ->from('planocontas') ->where('pl_status', 1) ->order_by('pl_idconta') ->get() ->result(); $this->load->view('estilo/header', $this->data); $this->load->view('faturamento/planocontas/adicionarConta', $data); } A MODEL, ficou assim: <?php class Planocontas_model extends CI_Model { function __construct() { parent::__construct(); $this->load->database(); } function get($table, $fields, $where = '', $perpage = 0, $start = 0, $one = false, $array = 'array') { $this->db->select($fields); $this->db->from($table); $this->db->order_by('pl_idconta', 'ASC'); $this->db->limit($perpage, $start); if ($where) { $this->db->where($where); } $query = $this->db->get(); $result = !$one ? $query->result() : $query->row(); return $result; } function getById($id) { $this->db->where('idPlanocontas', $id); $this->db->limit(1); return $this->db->get('planocontas')->row(); } function edit($table, $data, $fieldID, $ID) { $this->db->where($fieldID, $ID); $this->db->update($table, $data); if ($this->db->affected_rows() >= 0) { return true; } return false; } function delete($table, $fieldID, $ID) { $this->db->where($fieldID, $ID); $this->db->delete($table); if ($this->db->affected_rows() == '1') { return true; } return false; } function count($table) { return $this->db->count_all($table); } public function getNextCode($parent_code = null) { if (!$parent_code) { // Busca próximo código raiz (1, 2, 3...) $query = $this->db->select('MAX(SUBSTRING_INDEX(pl_idconta, ".", 1)) as max_code') ->from('planocontas') ->where('LENGTH(pl_idconta) = 1') ->get(); $result = $query->row(); return ($result->max_code ?? 0) + 1; } else { // Busca próximo subcódigo $like_pattern = $parent_code . '.%'; $length = strlen($parent_code) + 3; $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; } } public function insert($data) { if (empty($data['parent_code'])) { $data['pl_idconta'] = $this->getNextCode(); } else { $data['pl_idconta'] = $this->getNextCode($data['parent_code']); } return $this->db->insert('planocontas', [ 'pl_idconta' => $data['pl_idconta'], 'pl_descricao' => $data['pl_descricao'], 'pl_titulo' => $data['pl_titulo'], 'pl_status' => $data['pl_status'] ]); } } A VIEW está assim: <?php defined('BASEPATH') OR exit('No direct script access allowed'); $this->load->view('faturamento/tema/topo'); ?> <!-- Content Wrapper. Contains page content --> <div class="content-wrapper"> <!-- Content Header (Page header) --> <section class="content-header"> <div class="container-fluid"> <div class="row mb-2"> <div class="col-sm-6"> <h1>Condição de Pagamento</h1> </div> <div class="col-sm-6"> <ol class="breadcrumb float-sm-right"> <li class="breadcrumb-item"><a href="<?php echo base_url()?>faturamento/controle">Home</a></li> <li class="breadcrumb-item active">Condição de Pagamento</li> </ol> </div> </div> </div><!-- /.container-fluid --> </section> <section class="content"> <div class="container-fluid"> <!-- Mensagem de Sucesso / Erro --> <?php $this->load->view('estilo/acao'); ?> <div class="row"> <!-- left column --> <div class="col-md-12"> <div class="card card-success"> <div class="card-header"> <h3 class="card-title">Adicionar</h3> </div> <!-- /.card-header --> <!-- form start --> <form action="<?php echo current_url(); ?>" id="frmPlanoconta" method="post" > <div class="card-body"> <div class="form-group"> <label for="parent_code" class="control-label">Conta<span class="required">*</span></label> <select name="parent_code" id="parent_code" style="width:230px" class="form-control"> <option value="">Selecione uma Conta</option> <?php foreach ($plcta as $ct) { echo '<option value="'.$ct->pl_idconta.'">'.$ct->pl_idconta. '-'.$ct->pl_descricao.'</option>'; } ?> </select> </div> <div class="form-group"> <label for="pl_descricao">Descrição<span class="required">*</span></label> <input id="pl_descricao" type="text" name="pl_descricao" style="width:100%" class="form-control" value="<?php echo set_value('pl_descricao'); ?>" /> </div> <div class="card-footer" style="text-align:center;"> <a href="<?php echo base_url() ?>faturamento/planocontas" id="" class="btn btn-danger"><i class="fa fa-undo"></i> Voltar</a> <button type="submit" class="btn btn-primary">Adicionar</button> </div> </div> </form> </div> </div> </div> </section> </div> <?php $this->load->view('estilo/footer'); ?> Grato, Cesar
-
PHP+Codeigniter - Adicionar Registro Plano de Contas
Williams Duarte replied to violin101's topic in PHP
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! -
Amigo Williams, saudações. Desculpa minha dúvida. Qual campo no Formulário POST seria essa linha: $parent_code = null Seguindo sua orientação acima, o sistema salva os campos: Código e Descrição somente com 1. Grato, Cesar
-
PHP+Codeigniter - Adicionar Registro Plano de Contas
Williams Duarte replied to violin101's topic in PHP
Para implementar um sistema de numeração hierárquica automática no CodeIgniter, sugiro a seguinte solução, adapte a sua necessidade: // Model: PlanoContasModel.php class PlanoContasModel extends CI_Model { public function __construct() { parent::__construct(); $this->load->database(); } public function getNextCode($parent_code = null) { if (!$parent_code) { // Busca próximo código raiz (1, 2, 3...) $query = $this->db->select('MAX(SUBSTRING_INDEX(codigo, ".", 1)) as max_code') ->from('plano_contas') ->where('LENGTH(codigo) = 1') ->get(); $result = $query->row(); return ($result->max_code ?? 0) + 1; } else { // Busca próximo subcódigo $like_pattern = $parent_code . '.%'; $length = strlen($parent_code) + 3; $query = $this->db->select('MAX(SUBSTRING_INDEX(codigo, ".", -1)) as max_code') ->from('plano_contas') ->like('codigo', $like_pattern, 'after') ->where('LENGTH(codigo) =', $length) ->get(); $result = $query->row(); $next_number = str_pad(($result->max_code ?? 0) + 1, 2, '0', STR_PAD_LEFT); return $parent_code . '.' . $next_number; } } public function insert($data) { if (empty($data['parent_code'])) { $data['codigo'] = $this->getNextCode(); } else { $data['codigo'] = $this->getNextCode($data['parent_code']); } return $this->db->insert('plano_contas', [ 'codigo' => $data['codigo'], 'descricao' => $data['descricao'] ]); } } // Controller: PlanoContas.php class PlanoContas extends CI_Controller { public function __construct() { parent::__construct(); $this->load->model('PlanoContasModel'); } public function adicionar() { $data = [ 'descricao' => $this->input->post('descricao'), 'parent_code' => $this->input->post('parent_code') ]; $result = $this->PlanoContasModel->insert($data); if ($result) { echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'error' => 'Erro ao inserir']); } } } Esta solução: Gera códigos automaticamente seguindo a hierarquia Suporta múltiplos níveis (1, 1.01, 1.01.01, etc.) Mantém o formato padronizado dos códigos Usa zero à esquerda para subcódigos (01, 02, etc.) Exemplo de uso: CREATE TABLE plano_contas ( id INT PRIMARY KEY AUTO_INCREMENT, codigo VARCHAR(20) UNIQUE, descricao VARCHAR(100) ); Para adicionar um registro, faça uma requisição POST com: descricao: Nome da conta parent_code: Código pai (opcional) -
Caros amigos, saudações. Humildemente peço desculpa por postar uma dúvida que tenho. Preciso salvar no MySql, os seguinte Registro: 1 - Principal ====> minha dúvida começa aqui ==========> como faço para o Sistema Contar Automaticamente o que estiver despois do 1.____? 1.01 - Matriz 1.01.0001 - Estoque 1.01.0002 - Oficina etc 2 - Secundário 2.01 - Loja_1 2.01.0001 - Caixa 2.01.0002 - Recepção etc Resumindo seria como se fosse um Cadastro de PLANO de CONTAS CONTÁBEIL. Grato, Cesar
-
Javascript - Passar Parâmetros para uma Função.
Williams Duarte replied to violin101's topic in Javascript
Para passar parâmetros para uma função JS, você pode utilizar atributos de dados (data attributes) nos elementos HTML e, em seguida, acessar esses atributos no JavaScript para obter os valores desejados. Segue o exemplo de como você pode modificar seu código para passar os parâmetros usando JavaScript Modifique os botões "Visualizar" e "Editar" para incluir atributos de dados com os valores necessários: <button class="btn btn-warning" title="Visualizar" style="margin-left:50%; padding: 1px 3px;" data-id-pedido="<?php echo $r->idPedidos; ?>" data-nr-pedido="<?php echo $r->pd_numero; ?>" onclick="visualizarPedido(this)"><i class="fa fa-search icon-white"></i></button> <button class="btn btn-primary" title="Editar" style="margin-left:50%; padding: 1px 3px;" data-id-pedido="<?php echo $r->idPedidos; ?>" data-nr-pedido="<?php echo $r->pd_numero; ?>" onclick="editarPedido(this)"><i class="fa fa-edit icon-white"></i></button> Remova os formulários que envolvem os botões, pois não serão mais necessários. Adicione as seguintes funções JS no seu arquivo de JavaScript ou dentro de uma tag <script> na sua página: function visualizarPedido(button) { const idPedido = button.getAttribute('data-id-pedido'); const nrPedido = button.getAttribute('data-nr-pedido'); // Faça uma requisição Ajax para a URL desejada, passando os parâmetros const url = '<?= base_url() ?>compras/pedidos/visualizar?idPedido=' + idPedido + '&nrPedido=' + nrPedido; // Exemplo usando fetch: fetch(url) .then(response => response.text()) .then(data => { // Faça algo com a resposta recebida console.log(data); }) .catch(error => { console.error('Erro:', error); }); } function editarPedido(button) { const idPedido = button.getAttribute('data-id-pedido'); const nrPedido = button.getAttribute('data-nr-pedido'); // Faça uma requisição Ajax para a URL desejada, passando os parâmetros const url = '<?= base_url() ?>compras/pedidos/editar?idPedido=' + idPedido + '&nrPedido=' + nrPedido; // Exemplo usando fetch: fetch(url) .then(response => response.text()) .then(data => { // Faça algo com a resposta recebida console.log(data); }) .catch(error => { console.error('Erro:', error); }); } No exemplo, adicionamos atributos de dados aos botões para armazenar os valores necessários. No JavaScript, obtemos esses valores usando `getAttribute` e construímos a URL com os parâmetros. Em seguida, fazemos uma requisição Ajax para a URL usando `fetch` e lidamos com a resposta de acordo com as necessidades. Essa abordagem permite passar os parâmetros sem a necessidade de formulários adicionais. -
ErickCristiano changed their profile photo
-
Caros amigos, saudações. Consegui solucionar a minha SQL desta forma. <?php public function faturaPrazo($diasvcto = null, $ordenar = null){ if ($ordenar != null) { $this->db->order_by($ordenar); } $query = "SELECT faturamento.*, fornecedor.* FROM faturamento INNER JOIN fornecedor ON fornecedor.idfornecedor = faturamento.id_fornecedor WHERE faturamento.dataVencimento <= DATE_ADD(NOW(), INTERVAL $diasvcto DAY) AND faturamento.statusFatur = 1 ORDER BY faturamento.dataVencimento $ordenar "; return $this->db->query($query)->result(); } ?> Observação: - não sei se existe outra rotina parecida ou mais eficiente que a que escrevi. - caso tenha e os amigos puder compartilhar, fico inteiramente grato. Grato, Cesar
-
Caros amigos, saudações. Por favor, me perdoa em recorrer a orientação dos amigos. Preciso fazer um Relatório onde o usuário pode Gerar uma Lista com prazo para vencimento de: 15 / 20/ 30 dias da data atual. Tem como montar uma SQL para o sistema fazer uma busca no MySql por período ou dias próximo ao vencimento ? Tentei fazer assim, mas o SQL me traz tudo: $query = "SELECT faturamento.*, DATE_ADD(faturamento.dataVencimento, INTERVAL 30 DAY), fornecedor.* FROM faturamento INNER JOIN fornecedor ON fornecedor.idfornecedor = faturamento.id_fornecedor WHERE faturamento.statusFatur = 1 ORDER BY faturamento.idFaturamento $ordenar "; Grato, Cesar
-
Caros amigos, saudações. Após pesquisa e conversa com amigos, consegui resolver o meu problema da seguinte forma. Escrevi este código direto no FOREACH da Tabela e resolveu. <?php //Recebe a DataVencimento - MySql $data_inicio = new DateTime($dataVencimento); //Pega a Data Atual $data_atual = new DateTime('now'); //Calcula a Diferença entre a Data Vencimento com data Atual $dateInterval = $data_inicio->diff($data_atual)->days; if($dateInterval <= 20){ $cor = '#FDFEBA'; //Cor: Amarelo } else { $cor = ''; //Cor: Neutro } ?> Grato, Cesar
-
Caro amigo, Felipe. Saudações. Quando salvo a Data de Vencimento no MySql, salvo neste formato = 2024-11-01 ou seja ANO-MÊS-DIA. Após testar o seu código deu erro de Boolean, nesta linha. // Inverter a data para o formato AAAAMMDD e remover as barras $dataInvertida = DateTime::createFromFormat('d/m/Y', $data)->format('Ymd'); Como corrijo esta linha Grato, Cesar
-
Boa tarde Cesar, tudo bem? Vejo que o seu problema está relacionado a uma questão de lógica. Eu recomendo você a usar algo parecido com as funções abaixo: <?php function verificaDiferencaDatas($data) { // Inverter a data para o formato AAAAMMDD e remover as barras $dataInvertida = DateTime::createFromFormat('d/m/Y', $data)->format('Ymd'); // Obter a data atual no formato AAAAMMDD $dataAtual = (new DateTime())->format('Ymd'); // Calcular a diferença em dias $data1 = DateTime::createFromFormat('Ymd', $dataInvertida); $data2 = DateTime::createFromFormat('Ymd', $dataAtual); $diferenca = $data2->diff($data1)->days; // Verificar se a diferença é menor que 30 dias return $diferenca <= 30; } // Exemplo de uso $data = '01/12/2024'; if (verificaDiferencaDatas($data)) { echo "A diferença é menor ou igual a 30 dias."; echo "<font color='orange'><b>Fornecedor_1...........01/12/2024..........R$ 120,00<b></font>" } else { echo "A diferença é maior que 30 dias."; echo "Fornecedor_1...........01/12/2024..........R$ 120,00" } O que você vai precisar fazer é um LOOP para CADA DATA DE VENCIMENTO OBTIDA e validar. Ficaria algo assim: Data do primeiro vencimento: 01/12/2024 // Exemplo de uso $data = '01/12/2024'; // <-- data do vencimento if (verificaDiferencaDatas($data)) { echo "A diferença é menor ou igual a 30 dias."; echo "<font color='orange'><b>Fornecedor_1...........01/12/2024..........R$ 120,00<b></font>" } else { echo "A diferença é maior que 30 dias."; echo "Fornecedor_1...........01/12/2024..........R$ 120,00" } Com isso você apenas repete a lógica, se você precisar de cores diferentes como mencionou, crie um "array" com cores e um contador, para cada vez que você passar no LOOP e entrar na parte onde a diferença é inferior a 30 você pega a posição do array do contador, usa a cor e depois adiciona 1 no contador, no final você verifica se o tamanho do seu array é superior ao tamanho lenth do array, se for maior você ZERA se não você segue. Ficaria algo assim // Declaração do array de cores // Todo array em PHP inicia da posição 0 e não da prosição 1 $arrayCor = ["Green", "Red", "Orange", "Yellow", "Blue"]; // Inicialização do contador $contador = 0; // Exemplo de uso $data = '01/12/2024'; // <-- data do vencimento if (verificaDiferencaDatas($data)) { echo "A diferença é menor ou igual a 30 dias."; echo "<font color='" . $arrayCor[$contador] . "'><b>Fornecedor_1...........01/12/2024..........R$ 120,00<b></font>" } else { echo "A diferença é maior que 30 dias."; echo "Fornecedor_1...........01/12/2024..........R$ 120,00" } // Incrementa o contador $contador++; // Reinicia o contador se ele atingir o tamanho do array if ($contador >= count($arrayCor)) { $contador = 0; }
-
Caros amigos, saudações Por favor, me perdoa em recorrer a orientação dos amigos, tenho uma dúvida. Gostaria de uma rotina onde o Sistema possa acusar para o usuário antes dos 30 dias, grifar na Tabela o aviso de vencimento próximo, por exemplo: Data Atual: 15/11/2024 Vencimento Fornecedor.....................Data.....................Valor Fornecedor_1...........01/12/2024..........R$ 120,00 <== grifar a linha de Laranja Fornecedor_1...........01/01/2025..........R$ 130,00 Fornecedor_2...........15/12/2024..........R$ 200,00 <== grifar a linha de Amarelo Fornecedor_2...........15/01/2025..........R$ 230,00 Fornecedor_3...........20/12/2024..........R$ 150,00 Alguém tem alguma dica ou leitura sobre este assunto ? Grato, Cesar
-
Olá pessoal ! Estou tentando rodar um projeto de um jogo na minha maquina porem o mesmo pede para adicionar o log4cxx 0.10.0, realizei pesquisas na internet a respeito mas até agora nada, Encontre para baixar nesse site https://logging.apache.org/log4cxx/1.0.0/download.html porem não sei se devo instalar ele no windows porque ao exportar ele no projeto as depêndencias que precisam dele ficam informando o erro log4cxx.logger.h no such file or directory. a linguagem que estou usando e C++
-
O erro Class NFePHP\NFe\Make not found acontece por causa de uma configuração incorreta do autoload do Composer. Par resolver isso: modifique seu composer.json para: { "description": "The CodeIgniter framework", "name": "codeigniter/framework", "type": "project", "homepage": "https://codeigniter.com", "license": "MIT", "require": { "php": ">=7.4", "mpdf/mpdf": "^7.1", "nfephp-org/sped-nfe": "^5.0", "nfephp-org/sped-da": "^1.0" }, "autoload": { "psr-4": { "App\\": "application/" } }, "config": { "vendor-dir": "vendor" } } No seu application/config/config.php, coloque: $config['composer_autoload'] = FCPATH . 'vendor/autoload.php'; Depois, no terminal, execute: composer clear-cache composer update composer dump-autoload -o Seu arquivo libraries/NfeService.php deve começar assim: <?php defined('BASEPATH') OR exit('No direct script access allowed'); use NFePHP\NFe\Make; use NFePHP\NFe\Tools; use NFePHP\Common\Certificate; use NFePHP\NFe\Common\Standardize; class NfeService { private $CI; private $config; private $tools; private $certificate; public function __construct() { $this->CI =& get_instance(); $this->CI->config->load('nfe'); $this->config = $this->CI->config->item('nfe'); $this->initialize(); } // ... resto do código Crie o arquivo application/config/nfe.php: <?php defined('BASEPATH') OR exit('No direct script access allowed'); $config['nfe'] = [ 'atualizacao' => date('Y-m-d H:i:s'), 'tpAmb' => 2, // 1-Produção; 2-Homologação 'razaosocial' => 'Sua Empresa', 'siglaUF' => 'SP', // Seu estado 'cnpj' => '00000000000000', // Seu CNPJ 'schemes' => 'PL_009_V4', 'versao' => '4.00', 'pathNFeFiles' => APPPATH . 'nfe_files/', 'pathCertsFiles' => APPPATH . 'certificates/', 'certFile' => 'certificado.pfx', 'certPassword' => 'senha_certificado' ]; Crie as pastas necessárias: application/ ├── nfe_files/ └── certificates/ PHP tem ser 7.4 ou superior Para testar se está funcionando, crie um arquivo test.php na raiz: <?php require 'vendor/autoload.php'; try { $nfe = new NFePHP\NFe\Make(); echo "NFe class loaded successfully!"; } catch (Exception $e) { echo "Error: " . $e->getMessage(); } Um controlador básico para teste: <?php defined('BASEPATH') OR exit('No direct script access allowed'); class Nfe extends CI_Controller { public function __construct() { parent::__construct(); $this->load->library('NfeService'); } public function teste() { try { $nfe = new \NFePHP\NFe\Make(); echo "NFe class loaded successfully!"; } catch (Exception $e) { echo "Error: " . $e->getMessage(); } } } Algumas verificações adicionais se ainda houver problemas: Verifique se a pasta vendor existe e contém os arquivos do NFePHP Confira as permissões das pastas (755 para diretórios, 644 para arquivos) Certifique-se de que o index.php na raiz tem a linha: require_once __DIR__ . '/vendor/autoload.php'; Se ainda persistir o erro, execute: composer show | grep nfephp E verifique se as bibliotecas estão listadas corretamente. O erro geralmente é resolvido seguindo esses passos.
-
Amigo Williams, saudações. Eu já fiz, refiz, voltei a fazer a instalação da NFePHP usando o Composer. Não entendo, não entendo,... acho que eu sou burro. Após fazer a Instalação e Configuração da NFePHP no Codeignter, e seguir sua orientação acima, continua aparecendo esse erro. An uncaught Exception was encountered Type: Error Message: Class 'NFePHP\NFe\Make' not found Filename: C:\xampp\htdocs\ziscom\application\libraries\NfeService.php Line Number: 51 Backtrace: File: C:\xampp\htdocs\ziscom\application\controllers\Estoque\nfe.php Line: 48 Function: emitirNFe File: C:\xampp\htdocs\ziscom\index.php Line: 315 Function: require_once Já fiz isso: Para adicionar as bibliotecas ao seu projeto: composer require nfephp-org/sped-nfe composer require nfephp-org/sped-da Configurar o autoload do Composer no CodeIgniter //$config['composer_autoload'] = true; Linha IGNORADA //$config['composer_autoload'] = FCPATH . 'vendor/autoload.php'; Linha IGNORADA $config['composer_autoload'] = './vendor/autoload.php'; Já fiz assim e continua o erro: $nfe = new \NFePHP\NFe\Make(); O meu INDEX.PHP está assim: define('ENVIRONMENT', 'development'); O Composer.json está assim: { "description": "The CodeIgniter framework", "name": "codeigniter/framework", "type": "project", "homepage": "https://codeigniter.com", "license": "MIT", "support": { "forum": "http://forum.codeigniter.com/", "wiki": "https://github.com/bcit-ci/CodeIgniter/wiki", "irc": "irc://irc.freenode.net/codeigniter", "source": "https://github.com/bcit-ci/CodeIgniter" }, "require": { "php": ">=5.3.7", "mpdf/mpdf": "^7.1", "nfephp-org/sped-nfe": "^5.0", "nfephp-org/sped-da": "^1.0" }, "suggest": { "paragonie/random_compat": "Provides better randomness in PHP 5.x" }, "autoload": { "psr-4": { "Libraries\\": "application/libraries" } } } Caro amigo, não entendo, não entendo. Grato, Cesar
-
Um passo a passo detalhado para implementar a emissão de NFe usando NFePHP no CodeIgniter. // application/config/nfe.php <?php $config['nfe'] = [ 'atualizacao' => date('Y-m-d H:i:s'), 'tpAmb' => 2, // 1-Produção; 2-Homologação 'razaosocial' => 'Empresa Teste', 'siglaUF' => 'SP', 'cnpj' => '00000000000000', 'schemes' => 'PL_009_V4', 'versao' => '4.00', 'pathNFeFiles' => APPPATH . 'nfe_files/', 'pathCertsFiles' => APPPATH . 'certificates/', 'certFile' => 'certificado.pfx', 'certPassword' => 'senha_certificado' ]; // application/libraries/NfeService.php <?php defined('BASEPATH') OR exit('No direct script access allowed'); use NFePHP\NFe\Make; use NFePHP\NFe\Tools; use NFePHP\Common\Certificate; use NFePHP\NFe\Common\Standardize; class NfeService { private $CI; private $config; private $tools; private $certificate; public function __construct() { $this->CI =& get_instance(); $this->CI->config->load('nfe'); $this->config = $this->CI->config->item('nfe'); $this->initialize(); } private function initialize() { try { // Carrega o certificado $certPath = $this->config['pathCertsFiles'] . $this->config['certFile']; $this->certificate = Certificate::readPfx( file_get_contents($certPath), $this->config['certPassword'] ); // Inicializa as ferramentas $this->tools = new Tools( json_encode($this->config), $this->certificate ); // Configura o ambiente $this->tools->setEnvironment($this->config['tpAmb']); } catch (Exception $e) { log_message('error', 'NFe initialization error: ' . $e->getMessage()); throw new Exception('Erro ao inicializar NFe: ' . $e->getMessage()); } } public function emitirNFe($dados) { try { // Cria o XML $nfe = new Make(); // Informações da Nota $std = new \stdClass(); $std->versao = '4.00'; $nfe->taginfNFe($std); // Identificação da Nota $std = new \stdClass(); $std->cUF = 35; // Código do estado (SP = 35) $std->natOp = 'VENDA'; $std->mod = 55; // Modelo da NFe $std->serie = 1; $std->nNF = $dados['numero_nf']; // Número da nota $std->dhEmi = date('Y-m-d\TH:i:sP'); $std->tpNF = 1; // 1=Saída $std->idDest = 1; // 1=Operação interna $std->cMunFG = '3550308'; // Código do município (São Paulo) $std->tpImp = 1; // 1=DANFE retrato $std->tpEmis = 1; // 1=Emissão normal $std->tpAmb = $this->config['tpAmb']; $std->finNFe = 1; // 1=NFe normal $std->indFinal = 1; // 1=Consumidor final $std->indPres = 1; // 1=Operação presencial $std->procEmi = 0; // 0=Emissão de NF-e com aplicativo do contribuinte $std->verProc = '1.0'; $nfe->tagide($std); // Emitente $std = new \stdClass(); $std->xNome = $this->config['razaosocial']; $std->CNPJ = $this->config['cnpj']; $std->IE = '123456789'; $std->CRT = 3; // 3=Regime normal $std->xLgr = 'Rua Teste'; $std->nro = '123'; $std->xBairro = 'Centro'; $std->cMun = '3550308'; // São Paulo $std->xMun = 'Sao Paulo'; $std->UF = 'SP'; $std->CEP = '01001001'; $std->cPais = '1058'; $std->xPais = 'Brasil'; $nfe->tagemit($std); // Destinatário $std = new \stdClass(); $std->xNome = $dados['cliente']['nome']; $std->CNPJ = $dados['cliente']['cnpj']; $std->IE = $dados['cliente']['ie']; $std->xLgr = $dados['cliente']['endereco']; $std->nro = $dados['cliente']['numero']; $std->xBairro = $dados['cliente']['bairro']; $std->cMun = $dados['cliente']['cod_municipio']; $std->xMun = $dados['cliente']['municipio']; $std->UF = $dados['cliente']['uf']; $std->CEP = $dados['cliente']['cep']; $std->cPais = '1058'; $std->xPais = 'Brasil'; $nfe->tagdest($std); // Produtos foreach ($dados['produtos'] as $i => $produto) { $std = new \stdClass(); $std->item = $i + 1; $std->cProd = $produto['codigo']; $std->xProd = $produto['descricao']; $std->NCM = $produto['ncm']; $std->CFOP = $produto['cfop']; $std->uCom = $produto['unidade']; $std->qCom = $produto['quantidade']; $std->vUnCom = $produto['valor_unitario']; $std->vProd = $produto['valor_total']; $nfe->tagprod($std); // Impostos do produto $std = new \stdClass(); $std->item = $i + 1; $std->vTotTrib = 0.00; $nfe->tagimposto($std); } // Totais $std = new \stdClass(); $std->vBC = $dados['total']['base_calculo']; $std->vICMS = $dados['total']['valor_icms']; $std->vProd = $dados['total']['valor_produtos']; $std->vNF = $dados['total']['valor_nota']; $nfe->tagICMSTot($std); // Transporte $std = new \stdClass(); $std->modFrete = 9; // 9=Sem frete $nfe->tagtransp($std); // Gera o XML $xml = $nfe->getXML(); // Assina o XML $xml = $this->tools->signNFe($xml); // Envia para SEFAZ $response = $this->tools->sefazEnviaLote([$xml]); // Processa resposta $stdResponse = new Standardize($response); $arrayResponse = $stdResponse->toArray(); // Consulta recibo if (isset($arrayResponse['infRec']['nRec'])) { $recibo = $arrayResponse['infRec']['nRec']; $protocolo = $this->tools->sefazConsultaRecibo($recibo); // Guarda XML e protocolo $this->salvarXml($xml, $protocolo, $dados['numero_nf']); } return $arrayResponse; } catch (Exception $e) { log_message('error', 'NFe emission error: ' . $e->getMessage()); throw new Exception('Erro ao emitir NFe: ' . $e->getMessage()); } } private function salvarXml($xml, $protocolo, $numero) { $path = $this->config['pathNFeFiles']; $filename = $numero . '_' . date('Y-m-d_H-i-s') . '.xml'; if (!is_dir($path)) { mkdir($path, 0777, true); } file_put_contents($path . $filename, $xml); file_put_contents($path . 'protocolo_' . $filename, $protocolo); } } // application/controllers/Nfe.php <?php defined('BASEPATH') OR exit('No direct script access allowed'); class Nfe extends CI_Controller { public function __construct() { parent::__construct(); $this->load->library('NfeService'); } public function emitir() { try { // Dados de exemplo - você deve adaptar para seus dados reais $dados = [ 'numero_nf' => '1', 'cliente' => [ 'nome' => 'Cliente Teste', 'cnpj' => '00000000000000', 'ie' => '123456789', 'endereco' => 'Rua Teste', 'numero' => '123', 'bairro' => 'Centro', 'cod_municipio' => '3550308', 'municipio' => 'Sao Paulo', 'uf' => 'SP', 'cep' => '01001001' ], 'produtos' => [ [ 'codigo' => '001', 'descricao' => 'Produto Teste', 'ncm' => '84714900', 'cfop' => '5102', 'unidade' => 'UN', 'quantidade' => 1, 'valor_unitario' => 100.00, 'valor_total' => 100.00 ] ], 'total' => [ 'base_calculo' => 100.00, 'valor_icms' => 18.00, 'valor_produtos' => 100.00, 'valor_nota' => 100.00 ] ]; $response = $this->nfeservice->emitirNFe($dados); // Retorna resposta em JSON $this->output ->set_content_type('application/json') ->set_output(json_encode([ 'status' => 'success', 'data' => $response ])); } catch (Exception $e) { $this->output ->set_content_type('application/json') ->set_output(json_encode([ 'status' => 'error', 'message' => $e->getMessage() ])); } } } Para implementar este código, siga estes passos: 1. Primeiro, instale o NFePHP via Composer: composer require nfephp-org/sped-nfe 2. Crie os diretórios necessários: - application/nfe_files/ - para armazenar os XMLs gerados - application/certificates/ - para armazenar o certificado digital 3. Configure o arquivo application/config/nfe.php com seus dados: - Altere os dados da empresa - Configure o ambiente (homologação/produção) - Defina o caminho e senha do certificado 4. Adapte o modelo de dados no controller para sua estrutura de banco de dados. Pontos importantes: 1. Certificado Digital: - Você precisa ter um certificado digital A1 válido - Configure corretamente o caminho e senha no arquivo de configuração 2. Ambiente: - Comece usando o ambiente de homologação (tpAmb = 2) - Teste extensivamente antes de mudar para produção 3. Validações: - Adicione validações para todos os campos obrigatórios - Verifique as regras de negócio específicas do seu estado 4. Tratamento de Erros: - Implemente logs detalhados - Trate adequadamente as exceções - Armazene os retornos da SEFAZ 5. Melhorias Sugeridas: - Implementar fila de processamento para notas - Adicionar sistema de contingência - Criar rotinas de consulta de status - Implementar cancelamento de notas Você pode chamar a emissão assim: $response = $this->nfeservice->emitirNFe($dados); Este é um exemplo básico que você pode adaptar às suas necessidades. Recomendo: 1. Teste primeiro em homologação 2. Implemente gradualmente 3. Documente todas as alterações 4. Mantenha backup dos XMLs 5. Implemente validações rigorosas