Ir para conteúdo
Fórum Script Brasil

Frank K Hosaka

Membros
  • Total de itens

    1.590
  • Registro em

  • Última visita

Tudo que Frank K Hosaka postou

  1. Na célula a1 tenho Categoria, na célula b1 tenho Foto, na célula c1 tenho Junção. Na célula a2 tenho 1, na célula b2 tenho 1, na célula c2 tenho a função =TEXTO(A2;"00")&"."&TEXTO(B2;"000"), o que dá 01.001 Eu não entendi a função do formulário e do VBA. Se que copiar a fórmula da célula C2 na célula C3, você usa o comando copiar e colar. Se eu entendi tudo errado, tem jeito mostrar o esquema do formulário (tire uma foto com o comando printScreen) e também uma lista do código que está dando problema? Sem ver o código, fica dificil saber o que está acontecendo.
  2. Hoje o dia foi bem complicado, pedi para o Copilot me ajudar com o operador BETWEEN, e ele introduziu o conceito de depurador, e a partir daí acabei me desentendo com o Copilot. Pensei que o meu problema era a gambiarra que eu fiz no autoload, então decidi tentar introduzir o BETWEEN sem a ajuda do Copilot. O depurador do Copilot é assim: echo $sql. Eu não entendi o que estava acontecendo. Mas mudei o código assim: echo $sql."<br>"; e tudo fez sentido, e foi justamente com a ajuda do depurador é que consegui introduzir o BETWEEN na classe bd. Quanto ao autoload, eu trouxe a versão original. Já a classe das tabelas ficou assim class tbdiario extends bd { }. No meio de tanta confusão, acabei gostando da função getTableName na classe bd, ele é capaz de saber o nome da tabela que foi invocada, e o VS Code não reclama que a classe tabela está ausente. O código seguinte vai executar esse tipo de consulta: $debitos=array_column(tbdiario::groupBy('contad') ->select(['contad','sum(valor) as debito'], [['dia','BETWEEN',[$primeiroDia,$ultimoDia]]]),'debito','contad'); listagem parcial do arquivo config.php spl_autoload_register(function ($class) { $path = str_replace('\\', DIRECTORY_SEPARATOR, strtolower($class)) . '.php'; if (file_exists($path)) { require $path; } else { echo "classe $class não encontrada"; exit; } }); class bd { private static $pdo; private static $initialized = false; private static $orderBy = ''; private static $groupBy = ''; private static $bindings = []; static function initialize() { if (!self::$initialized) { $dsn = 'mysql:host=' . HOST . ';dbname=' . DBNAME; self::$pdo = new PDO($dsn, USER, PASSWORD); self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); self::$initialized = true; } } protected static function getPdo() { self::initialize(); return self::$pdo; } protected static function getTableName() { $reflection = new \ReflectionClass(static::class); return strtolower($reflection->getShortName()); } public static function orderBy($column, $direction = 'ASC') { self::$orderBy = "ORDER BY $column $direction"; return new static; } // Adicionando o método groupBy public static function groupBy($columns) { if (is_array($columns)) { $columns = implode(', ', $columns); } self::$groupBy = "GROUP BY $columns"; return new static; } public static function select($columns = '*', $conditions = []) { self::initialize(); $table = static::getTableName(); if (is_array($columns)) { $columns = implode(', ', $columns); } $whereClause = ''; self::$bindings=[]; if (!empty($conditions)) { foreach ($conditions as $condition) { $field = $condition[0]; $operator = $condition[1]; $value = $condition[2]; if($operator=='BETWEEN' && is_array($value)) { $whereClause .= "$field BETWEEN :{$field}_start AND :{$field}_end AND "; self::$bindings["{$field}_start"] = $value[0]; self::$bindings["{$field}_end"] = $value[1]; } else { $whereClause .= "$field $operator :$field AND "; self::$bindings[$field] = $value; } } $whereClause = 'WHERE ' . rtrim($whereClause, ' AND '); } $sql = "SELECT $columns FROM $table $whereClause"; if (self::$groupBy) { $sql .= ' ' . self::$groupBy; self::$groupBy = ''; // Reset groupBy after use } if (self::$orderBy) { $sql .= ' ' . self::$orderBy; self::$orderBy = ''; // Reset orderBy after use } // echo $sql."<br>"; // depurador $stmt = self::getPdo()->prepare($sql); foreach (self::$bindings as $key => $value) { $stmt->bindValue(":$key", $value); } $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_OBJ); } } class tbconta extends bd { } class tbdiario extends bd { } class tbusuarios extends bd { }
  3. ** estou tentando implantar a condição between, e vejo que a ideia de eliminar a classe tabela está atrapalhando ** O Laravel tem uma pasta chamada Model e dentro dela tem um arquivo para cada tabela na forma de classe. No projeto semiLaravel eu só trabalho no diretório raiz e pensei em eliminar a classe que representa a tabela, passando a tarefa de criar a classe tabela para o autoload, conforme a necessidade do código. Eu não sou capaz de criar um código desse tipo, mas o Copilot sim: ** o grande efeito colateral é a tela do VS Code, ele sempre vai reclamar que a classe tabela não existe ** listagem parcial do config.php <?php spl_autoload_register(function ($class) { $path = str_replace('\\', DIRECTORY_SEPARATOR, strtolower($class)) . '.php'; if (file_exists($path)) { require $path; } else { eval("class $class extends bd {}"); } }); class bd { private static $pdo; private static $initialized = false; private static $orderBy = ''; private static $groupBy = ''; // Adicionando a variável para a cláusula GROUP BY static function initialize() { if (!self::$initialized) { $dsn = 'mysql:host=' . HOST . ';dbname=' . DBNAME; self::$pdo = new PDO($dsn, USER, PASSWORD); self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); self::$initialized = true; } } protected static function getPdo() { self::initialize(); return self::$pdo; } protected static function getTableName() { return strtolower((new \ReflectionClass(static::class))->getShortName()); } public static function orderBy($column, $direction = 'ASC') { self::$orderBy = "ORDER BY $column $direction"; return new static; } // Adicionando o método groupBy public static function groupBy($columns) { if (is_array($columns)) { $columns = implode(', ', $columns); } self::$groupBy = "GROUP BY $columns"; return new static; } public static function select($columns = '*', $conditions = []) { self::initialize(); $table = static::getTableName(); if (is_array($columns)) { $columns = implode(', ', $columns); } $whereClause = ''; if (!empty($conditions)) { foreach ($conditions as $condition) { $field = $condition[0]; $operator = $condition[1]; $value = $condition[2]; $whereClause .= "$field $operator :$field AND "; } $whereClause = 'WHERE ' . rtrim($whereClause, ' AND '); } $sql = "SELECT $columns FROM $table $whereClause"; if (self::$groupBy) { $sql .= ' ' . self::$groupBy; self::$groupBy = ''; // Reset groupBy after use } if (self::$orderBy) { $sql .= ' ' . self::$orderBy; self::$orderBy = ''; // Reset orderBy after use } $stmt = self::getPdo()->prepare($sql); if (!empty($conditions)) { foreach ($conditions as $condition) { $field = $condition[0]; $value = $condition[2]; $stmt->bindValue(":$field", $value); } } $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_OBJ); } }
  4. Para executar esse comando: $debitosAnteriores=array_column(tbdiario::groupBy('contad') ->select(['contad','sum(valor) as debito_anterior'], [['dia','<',$primeiroDia]]),'debito_anterior','contad'); eu precisei alterar a classe bd: listagem parcial de config.php <?php class bd { private static $pdo; private static $initialized = false; private static $orderBy = ''; private static $groupBy = ''; // Adicionando a variável para a cláusula GROUP BY static function initialize() { if (!self::$initialized) { $dsn = 'mysql:host=' . HOST . ';dbname=' . DBNAME; self::$pdo = new PDO($dsn, USER, PASSWORD); self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); self::$initialized = true; } } protected static function getPdo() { self::initialize(); return self::$pdo; } protected static function getTableName() { return ''; // Será implementado na classe filha } public static function orderBy($column, $direction = 'ASC') { self::$orderBy = "ORDER BY $column $direction"; return new static; } // Adicionando o método groupBy public static function groupBy($columns) { if (is_array($columns)) { $columns = implode(', ', $columns); } self::$groupBy = "GROUP BY $columns"; return new static; } public static function select($columns = '*', $conditions = []) { self::initialize(); $table = static::getTableName(); if (is_array($columns)) { $columns = implode(', ', $columns); } $whereClause = ''; if (!empty($conditions)) { foreach ($conditions as $condition) { $field = $condition[0]; $operator = $condition[1]; $value = $condition[2]; $whereClause .= "$field $operator :$field AND "; } $whereClause = 'WHERE ' . rtrim($whereClause, ' AND '); } $sql = "SELECT $columns FROM $table $whereClause"; if (self::$groupBy) { $sql .= ' ' . self::$groupBy; self::$groupBy = ''; // Reset groupBy after use } if (self::$orderBy) { $sql .= ' ' . self::$orderBy; self::$orderBy = ''; // Reset orderBy after use } $stmt = self::getPdo()->prepare($sql); if (!empty($conditions)) { foreach ($conditions as $condition) { $field = $condition[0]; $value = $condition[2]; $stmt->bindValue(":$field", $value); } } $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_OBJ); } } class tbdiario extends bd { protected static function getTableName() { return 'tbdiario'; } } class tbconta extends bd { protected static function getTableName() { return 'tbconta'; } } class tbusuarios extends bd { protected static function getTableName() { return 'tbusuarios';}}
  5. rs é abreviatura de recorset, eu usava isso quando trabalhava com o MS Access dentro do MS Excel, e o código era mais ou menos assim: Sub LerEGravarValoresNoAccess() Dim ws As Worksheet Dim db As Object Dim rs As Object Dim strDBPath As String Dim i As Integer ' Definir a planilha onde os dados estão Set ws = ThisWorkbook.Sheets("NomeDaSuaPlanilha") ' Altere o nome da planilha conforme necessário ' Caminho do banco de dados do Access strDBPath = "C:\Caminho\Para\Seu\BancoDeDados.accdb" ' Altere para o caminho do seu banco de dados ' Abrir conexão com o banco de dados do Access Set db = CreateObject("DAO.DBEngine.120").OpenDatabase(strDBPath) ' Definir o Recordset para a tabela onde os dados serão gravados Set rs = db.OpenRecordset("NomeDaSuaTabela", 2) ' Altere o nome da tabela conforme necessário ' Ler e gravar valores no banco de dados do Access For i = 1 To 3 ' Assumindo que os valores estão nas células A1:A3 e B1:B3 rs.AddNew rs.Fields("Orcamento").Value = ws.Cells(i, 1).Value ' Assumindo que os valores do orçamento estão na coluna A rs.Fields("Valor").Value = ws.Cells(i, 2).Value ' Assumindo que os valores estão na coluna B rs.Update Next i ' Fechar o Recordset e o banco de dados rs.Close db.Close ' Limpar objetos Set rs = Nothing Set db = Nothing End Sub Mas eu não tenho certeza se você está falando do MS Access, pois você só fala em "banco de dados", e assim fica difícil oferecer qualquer tipo de ajuda, eu não sei se você conseguiu conectar o Excel no banco de dados, eu não sei se você sabe usar critério de consulta, e o pior é que também não sei se o formulário tem uma caixa de texto chamado txt_ValorOrcamento, onde qualquer erro de digitação impede que o valor esperado apareça no local esperado.
  6. Estou montando o projeto na base da tentativa e erro, pois eu não entendo nada de lógica. Tenho muita ajuda do Copilot, fico contente quando o código funciona, entender o código, isso sim é uma tarefa difícil. O primeiro problema é do roteador é que eu precisei criar o arquivo .htaccess para mandar todas as solicitações para o arquivo index.php, ele funciona aqui no notebook que usa o Apache. Mas lá no Hostinger, ainda não sei se o código vai funcionar. Eu consegui executar o código do login com a primeira versão do roteador. Mas na hora de testar um novo código que trabalha com datas, o programa travou. O meu roteador foi projetado para executar classe:metodo( ). Tive que mudar tudo, precisei mudar o código para suportar classe:metodo(argumento), ele ficou assim: arquivo index.php <?php require('config.php'); $requestUri = $_SERVER['REQUEST_URI']; $basePath = '/semiLaravel/'; $path = substr($requestUri, strlen($basePath)); if ($path == "") { $path = "loginLogin()"; } // Ajuste a regex para capturar argumentos no formato classeMetodo(arg) if (preg_match('/^([a-z]+)([A-Z][a-zA-Z]*)\((.*)\)$/', $path, $matches)) { $classe = $matches[1]; $metodo = $matches[2]; $argumento = $matches[3]; // Supondo que o método aceita um argumento if (!empty($argumento)) { $classe::$metodo($argumento); } else { $classe::$metodo(); } } else { echo "Formato de URL inválido."; } ?>
  7. O meu código PHP usa um query builder bem simples (PDO->query()), mas na semana passada o Copilot viu o meu código e ele comentou que ele é vulnerável a um ataque do tipo "injeção de SQL", ele sugeriu eu separar a consulta dos parâmetros da consulta. Já que preciso mudar a minha query builder, então que seja mais ou menos no formato do Eloquent, mas hoje o dia foi terrível, eu e o Copilot ficamos o dia todo preso nesse código: if ($lcto) { $btnMenu = "Acrescenta Lançamento"; } else { $lcto = tbdiario::orderBy('lcto', 'DESC')->select('lcto')[0]->lcto+1; } $dia = isset($_SESSION['dia']) ? $_SESSION['dia'] : date('Y-m-d'); $ativo = tbconta::select('*', [['conta', '<', 201]]); O Copilot trabalhou duro, e várias vezes ele reclamou que a minha codificação é uma porcaria; tentei fazer do jeito dele, e não deu certo. Exausto, o Copilot me sugeriu executar uma consulta de cada vez, e para a minha perplexidade, eles funcionam de maneira separada. Eu inverti a ordem da consulta, e o código andou. O Copilot pensou, pensou e pensou e concluiu que o problema era a função orderBy( ). Ele inventou um comando do tipo reset para a função orderBy( ), e agora consigo executar o meu programa do jeito que eu listei. A seguir eu mostro o query builder que eu chamei de semiLaravel. O Laravel coloca todas as classes na pasta Model, no PHP eu não trabalho com nenhuma pasta. No caso do banco de dados, eu joguei tudo dentro do arquivo config.php, assim: listagem parcial do arquivo config.php class bd { private static $pdo; private static $initialized = false; private static $orderBy = ''; static function initialize() { if (!self::$initialized) { $dsn = 'mysql:host=' . HOST . ';dbname=' . DBNAME; self::$pdo = new PDO($dsn, USER, PASSWORD); self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); self::$initialized = true; } } protected static function getPdo() { self::initialize(); return self::$pdo; } protected static function getTableName() { return ''; // Será implementado na classe filha } public static function orderBy($column, $direction = 'ASC') { self::$orderBy = "ORDER BY $column $direction"; return new static; } public static function select($columns = '*', $conditions = []) { self::initialize(); $table = static::getTableName(); if (is_array($columns)) { $columns = implode(', ', $columns); } $whereClause = ''; if (!empty($conditions)) { foreach ($conditions as $condition) { $field = $condition[0]; $operator = $condition[1]; $value = $condition[2]; $whereClause .= "$field $operator :$field AND "; } $whereClause = 'WHERE ' . rtrim($whereClause, ' AND '); } $sql = "SELECT $columns FROM $table $whereClause"; if (self::$orderBy) { $sql .= ' ' . self::$orderBy; self::$orderBy = ''; // Reset orderBy after use } $stmt = self::getPdo()->prepare($sql); if (!empty($conditions)) { foreach ($conditions as $condition) { $field = $condition[0]; $value = $condition[2]; $stmt->bindValue(":$field", $value); } } $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_OBJ); } } class tbdiario extends bd { protected static function getTableName() { return 'tbdiario'; } } class tbconta extends bd { protected static function getTableName() { return 'tbconta'; } } class tbusuarios extends bd { protected static function getTableName() { return 'tbusuarios';}} ?>
  8. Fiz alguns testes, e tive que mudar algumas coisas: arquivo .htaccess RewriteEngine On # Redirecionar tudo para index.php RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^ index.php [L] arquivo appView.php <!DOCTYPE html> <html lang="en"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> </script> <script src="https://cdn.tailwindcss.com"></script> <style> @media (min-width: 768px) { .geral {width: 700px; margin: auto; font-size: 16px; background-color: #f7fafc} } @media (max-width: 767px) { body {width: 630px; margin: auto; font-size: 16px; background-color: #f7fafc} } @media (min-width: 768px) and (max-width:1024px) { body {width:700px;margin: auto; font-size: 16px; background-color: #f7fafc}} input[type="date"]::-webkit-calendar-picker-indicator {display: none} summary { list-style:none } </style> <title>Projeto Classe</title> <body class=geral> arquivo config.php <?php session_start(); error_reporting(E_ALL); ini_set('display_errors', 1); date_default_timezone_set('America/Sao_Paulo'); $baseDir = $_SERVER['SERVER_NAME'] === 'frank.com' ? $_SERVER['DOCUMENT_ROOT'] : $_SERVER['DOCUMENT_ROOT'].'/Frank/'; defined('HOST') || define('HOST', 'localhost'); defined('DBNAME') || define('DBNAME', $baseDir === $_SERVER['DOCUMENT_ROOT'] ? 'Diario' : 'diario'); defined('USER') || define('USER', $baseDir === $_SERVER['DOCUMENT_ROOT'] ? 'Root' : 'root'); defined('PASSWORD') || define('PASSWORD', $baseDir === $_SERVER['DOCUMENT_ROOT'] ? '14061406' : ''); defined('lctoBaixaEstoque') || define('lctoBaixaEstoque',14421); defined('lctoAcertoMais') || define('lctoAcertoMais',14742); defined('lctoAcertoMenos') || define('lctoAcertoMenos',14743); defined('diaAcerto') || define('diaAcerto','2025-01-31'); spl_autoload_register(fn ($class) => require str_replace('\\', DIRECTORY_SEPARATOR, strtolower($class)) . '.php'); function view($arquivo, $array = null){ if (!is_null($array)){ foreach ($array as $var => $value){ ${$var} = $value; } } ob_start(); include $arquivo . ".php"; ob_flush(); } class bd { private static $pdo; private static $initialized = false; public static function initialize() { if (!self::$initialized) { $dsn = 'mysql:host=' . HOST . ';dbname=' . DBNAME; self::$pdo = new PDO($dsn, USER, PASSWORD); self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); self::$initialized = true; } } protected static function getPdo() { self::initialize(); return self::$pdo; } protected static function getTableName() { return ''; // Será implementado na classe filha } public static function select($columns = '*', $conditions = []) { self::initialize(); $table = static::getTableName(); // Construindo a cláusula SELECT if (is_array($columns)) { $columns = implode(', ', $columns); } // Construindo a cláusula WHERE, se houver condições $whereClause = ''; if (!empty($conditions)) { foreach ($conditions as $field => $value) { $whereClause .= "$field = :$field AND "; } $whereClause = 'WHERE ' . rtrim($whereClause, ' AND '); } $sql = "SELECT $columns FROM $table $whereClause"; $stmt = self::getPdo()->prepare($sql); // Vinculando os valores para a cláusula WHERE if (!empty($conditions)) { foreach ($conditions as $field => $value) { $stmt->bindValue(":$field", $value); } } $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_OBJ); } public static function update($conditions, $data) { self::initialize(); $table = static::getTableName(); // Construindo a cláusula SET $setClause = ''; foreach ($data as $field => $value) { $setClause .= "$field = :$field, "; } $setClause = rtrim($setClause, ', '); // Construindo a cláusula WHERE $whereClause = ''; foreach ($conditions as $field => $value) { $whereClause .= "$field = :where_$field AND "; } $whereClause = rtrim($whereClause, ' AND '); $sql = "UPDATE $table SET $setClause WHERE $whereClause"; $stmt = self::getPdo()->prepare($sql); // Vinculando os valores para a cláusula SET foreach ($data as $field => $value) { $stmt->bindValue(":$field", $value); } // Vinculando os valores para a cláusula WHERE foreach ($conditions as $field => $value) { $stmt->bindValue(":where_$field", $value); } $stmt->execute(); } public static function where($field, $operator, $value) { self::initialize(); $table = static::getTableName(); $sql = "SELECT * FROM $table WHERE $field $operator :value"; $stmt = self::getPdo()->prepare($sql); $stmt->bindParam(':value', $value); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_OBJ); } } class tbusuarios extends bd { protected static function getTableName() { return 'tbusuarios'; } } ?> arquivo index.php <?php require('config.php'); $requestUri = $_SERVER['REQUEST_URI']; $basePath = '/astudy/'; $path = substr($requestUri, strlen($basePath)); $path = $path ? $path : "loginLogin"; if (preg_match('/^([a-z]+)([A-Z].*)$/', $path, $matches)) { $classe = $matches[1]; $metodo = $matches[2]; } $classe::$metodo(); arquivo login.php <?php class Login { public static function alterarSenha() { $mensagem=""; $id=$_SESSION['id']; $email=tbusuarios::select('email',['id'=>$id])[0]->email; return view('loginAlterarSenha',['mensagem'=>$mensagem,'email'=>$email]); } public static function login() { $mensagem=""; $email=""; return view('loginView',['mensagem'=>$mensagem,'email'=>$email]); } public static function menu() { $email=$_POST['email']; $senha=$_POST['password']; $usuario=tbusuarios::where('email','=',$email); if(!$usuario) { $_SESSION['mensagem']="Dados inválidos!"; return view('loginView'); } $confirmar=$usuario[0]->senha; $validaSenha=password_verify($senha,$confirmar); if(!$validaSenha) { $_SESSION['mensagem']="Dados inválidos!"; return view('loginView'); } unset($_SESSION['mensagem']); $_SESSION['id']=$usuario[0]->id; $_SESSION['nome']=$usuario[0]->nome; return view('menuView'); } public static function sair() { session_destroy(); view('loginView',['mensagem'=>""]); } public static function senhaAlterada() { $senhaAlterada=$_POST['senhaAlterada']; $hash=password_hash($senhaAlterada,PASSWORD_BCRYPT,['cost'=>12]); $id=$_SESSION['id']; tbusuarios::update(['id'=>$id],['senha'=>$hash]); return self::login(); } } arquivo loginView.php <?php require('appView.php'); ?> <script>document.title="Login"</script> <div class="mt-[150px] flex justify-center items-center"> <div> <div class="text-2xl">Projeto Classe</div> <div class="w-[630px] sm:max-w-md mt-6 px-6 py-4 bg-white shadow-md overflow-hidden sm:rounded-lg"> <!-- Session Status --> <form method="POST" action="loginMenu"> <div> <label class="block font-medium text-sm text-gray-700" for="email"> Email </label> <input class="w-full px-2 py-2 border rounded-md shadow-sm mt-2 focus:outline-blue-700" id="email" type="email" name="email" required="required" autofocus autocomplete="username"> </div> <!-- Password --> <div class="mt-4"> <label class="block font-medium text-sm text-gray-700" for="password"> Senha </label> <input class="px-2 py-2 border rounded-md shadow-sm block mt-1 w-full focus:outline-blue-700" id="password" type="password" name="password" required="required" autocomplete="current-password"> </div> <button type="submit" class="px-2 mt-4 rounded-lg text-gray-500 font-semibold hover:bg-gray-200"> Entrar </button> </form> </div> </div> </div> arquivo menuView.php <?php include('appView.php'); if (!isset($_SESSION['id']) || !isset($_SESSION['nome'])) { header('Location: loginLogin'); exit(); } ?> <script> window.onload = function() { btDiv.addEventListener('click', function() { dropdownMenu.classList.toggle('hidden'); }); btLogin.addEventListener('click', function() { menuLogin.classList.toggle('hidden'); }); document.addEventListener('click', function(event) { if (!btDiv.contains(event.target) && !btDiv.contains(event.target)) { dropdownMenu.classList.add('hidden'); } if (!btLogin.contains(event.target) && !btLogin.contains(event.target)) { menuLogin.classList.add('hidden'); } }); } </script> <header id="cabecalho" class="bg-white shadow-sm flex p-1 items-center justify-between mb-2"> <div class="flex items-center flex-grow"> <div class="w-[170px] font-semibold">Classe</div> <div class="flex-grow flex justify-center"> <button type="button" id="btDiv" class="inline-flex justify-center w-full px-4 py-1 hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 font-semibold rounded text-gray-500"> <div id="btMenu">Menu</div> <svg class="-mr-1 ml-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a 1 1 0 111.414 1.414l-4 4a 1 1 0 01-1.414 0l-4-4a 1 1 0 010-1.414z" clip-rule="evenodd" /> </svg> </button> <div id="dropdownMenu" class="hidden origin-top-left absolute left-0 mt-2 w-auto rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5"> <?php if ($_SESSION['id'] == 1): ?> <div class="py-1" role="menu" aria-orientation="vertical" aria-labelledby="btMenu"> <a class="block text-gray-500 font-semibold px-4 py-2 hover:bg-gray-200" href="diarioInicio">Diário</a> <a class="block text-gray-500 font-semibold px-4 py-2 hover:bg-gray-200" href="balanceteInicio">Balancete</a> <a class="block text-gray-500 font-semibold px-4 py-2 hover:bg-gray-200" href="pagarInicio">Pagar</a> <a class="block text-gray-500 font-semibold px-4 py-2 hover:bg-gray-200" href="outrosInicio">Outros</a> <?php endif; ?> <a class="block text-gray-500 font-semibold px-4 py-2 hover:bg-gray-200" href="orcamentoMenu">Orçamento</a> <a class="block text-gray-500 font-semibold px-4 py-2 hover:bg-gray-200" href="pessoaInicio">Pessoa</a> <a class="block text-gray-500 font-semibold px-4 py-2 hover:bg-gray-200" href="produtoInicio">Produto</a> <a class="block text-gray-500 font-semibold px-4 py-2 hover:bg-gray-200 whitespace-nowrap" href="vendaInicio">Relatório de Venda</a> <a class="block text-gray-500 font-semibold px-4 py-2 hover:bg-gray-200" href="nfVerxml">Ver XML</a> </div> </div> </div> <div class="flex items-center"> <div class="relative"> <button type="button" id="btLogin" class="inline-flex justify-center w-full px-4 py-1 hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 font-semibold rounded text-gray-500"> <div id="teste"><?=$_SESSION['nome']?></div> <svg class="-mr-1 ml-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a 1 1 0 111.414 1.414l-4 4a 1 1 0 01-1.414 0l-4-4a 1 1 0 010-1.414z" clip-rule="evenodd" /> </svg> </button> <div id="menuLogin" class="hidden origin-top-right absolute right-0 mt-2 w-auto rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5"> <a class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-200" href="loginSair">Sair</a> <a class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-200" href="loginAlterSenha">Mudar Senha</a> </div> </div> </div> </header>
  9. O que eu mais gostei no Laravel foi o Eloquent (ele usa a sintaxe tbdiario::where('lcto',12)->get( )) e o roteador. O problema do roteador web.php é que você precisa criar uma nova rota para cada novo comando. O roteador que inventei não trabalha com um monte de rota, mas trabalha com a sintaxe classeMetodo, assim: arquivo .htaccess RewriteEngine On # Redirecionar tudo para index.php RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^ index.php [L] arquivo bd.php <?php class BD { public static $pdo; private static $initialized = false; public static function initialize() { if (!self::$initialized) { $host = 'localhost'; $dbname = 'diario'; $username = 'root'; $password = ''; $dsn = 'mysql:host=' . $host . ';dbname=' . $dbname; self::$pdo = new PDO($dsn, $username, $password); self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); self::$initialized = true; } } } ?> arquivo diario.php <?php class Diario extends BD { public static function getValor($lcto) { self::initialize(); // Certificando que a inicialização está sendo feita $sql = 'SELECT valor FROM tbdiario WHERE lcto = :lcto'; $stmt = self::$pdo->prepare($sql); $stmt->bindParam(':lcto', $lcto); $stmt->execute(); return $stmt->fetchColumn(); } public static function inicio() { self::initialize(); // Certificando que a inicialização está sendo feita echo "olá mundo<br>"; echo self::getValor(12); } } ?> arquivo index.php <?php spl_autoload_register(fn ($class) => require str_replace('\\', DIRECTORY_SEPARATOR, strtolower($class)) . '.php'); $requestUri = $_SERVER['REQUEST_URI']; $basePath = '/astudy/'; $path = substr($requestUri, strlen($basePath)); if($path=="") { header('location:teste.php'); exit; } if (preg_match('/^([a-z]+)([A-Z].*)$/', $path, $matches)) { $classe = $matches[1]; $metodo = $matches[2]; } $classe::$metodo(); arquivo teste.php <a href=diarioInicio>teste</a>
  10. Encontrei um vídeo no YouTube que ensina como conectar o VBA no WhatsApp versão web, ele usa o comando VBA Shell e SendKeys. O chato é ter que trabalhar com o temporizador, muda de laptop para laptop, mas eu consegui chegar até a caixa de contatos: Sub WhatsApp() Shell "C:\Program Files\Google\Chrome\Application\Chrome.exe" Application.Wait Now + TimeValue("00:00:03") SendKeys "https://web.whatsapp.com/" Application.Wait Now + TimeValue("00:00:03") SendKeys "~" Application.Wait Now + TimeValue("00:00:13") For i = 1 To 10 SendKeys "{TAB}" Application.Wait Now + TimeValue("00:00:02") Next End Sub
  11. O Copilot disse que o Power Automate é capaz de enviar documentos para o WhatsApp, mas você precisa ter uma conta no WhatsApp Business Api, desconfio que o Power Automate não faz parte do Office (que cobra R$ 459,00 por ano) e a API do WhatsApp também não é de graça. Se eu fosse você pegaria um morador de rua e pediria para ele encaminhar cada documento pelo WhatsApp do desktop para o número correspondente, prometendo que você garantiria a pinga no final do serviço. Estava pensando em colocar todos os holerites numa página da empresa, cada um pega o seu. O problema é o safado que vai pegar o holerite do outro e vai reclamar com o patrão que ele ganha bem menos. Nesse caso, iria criptografar o pdf com o CPF do colaborador, mas aí a Adobe quer R$ 100,00 por mês. Isso é um problema difícil de resolver. Boa sorte. Ah, lembrei agora, eu fiz o teste com duas Galaxy da Samsung, ele tem a tecnologia NFC e consegue transferir arquivos entre si, sem precisar usar o Bluetooth ou outro canal de comunicação, tudo por aproximação. Já o iPhone é jogo duro, e tem muito colaborador que tem celular, mas não tem Android nem iOs, e desconfio que o WhatsApp não funciona nesses celulares. Seja qual for a solução, por favor, publique a sua solução, muita gente vai querer saber da sua experiência.
  12. Pelo que eu entendi você quer cadastrar um administrador da tabela admin na tabela users. Para simplificar, a tabela admin só tem um campo chamado nome e o users também. O meu modelo ficou assim: app > Models > User.php <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class User extends Authenticatable { use HasFactory, Notifiable; public $timestamps = false; protected $fillable = ['name',]; } app > Models > Admin.php <?php namespace App\Models; class Admin extends User { protected $table="admin"; } app > Http > Controllers > Teste.php <?php namespace App\Http\Controllers; use App\Models\User; use App\Models\Admin; class Teste { function index(){ $admin=Admin::where('id',1)->value('nome'); User::create(['name'=>$admin]); } } Eu gostei do verbo extends no model, eu não preciso mais fazer aquela longa lista de biblioteca que o model precisa usar, mas para pegar uma informação numa tabela e colocar em outra, acho mais fácil jogar o serviço para o Eloquent.
  13. Instalei o selenium, o ChromeDriveManager e o webdriver_manager pelo comando pip install. Eu tive problema com o Service na quarta linha, então o Copilot corrigiu a segunda linha capitalizando a palavra Service. Com outras alterações do Copilot, o código ficou assim: arquivo rascunho.py from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service) driver.get("https://www.exemplo.com") e a mensagem que recebi foi bem diferente do que você apresentou, quando executei o comando python rascunho.py
  14. Todas as notas fiscais são feitas no formato XML. O Excel é um excelente aplicativo que consegue importar o XML no formato CSV e assim você consegue montar a memória de cálculo para diferença de alíquota de ICMS ou ICMS Substituição Tributária no caso das compras fora do estado de São Paulo. Eu já uso o PHP que tem uma boa ferramenta para importar o XML para a memória do computador (eu já uso uma tabela provisória do MySQL), comparo o novo custo do produto com o velho e atualizo, e em seguida uso todas as informações para dar entrada no estoque. Nem sempre o fornecedor manda o arquivo XML, nesse caso eu peço para o meu irmão tirar uma foto da chave do DANFE, e com essa chave eu vou no portal da Nota Fiscal Eletrônica e peço para fazer o download do arquivo (o portal só autoriza a consulta plena ou o download com o certificado digital da empresa que consta na Nota Fiscal Eletrônica). Estamos em 2025, esse é um mundo totalmente diferente. No meu tempo, a gente ajuntava todas as notas para encaminhar para a contabilidade para fazer a escrituração, apuração e imprimir os livros fiscais. Hoje não. A Contabilidade tem um esquema que consegue puxar todos os xml com o CNJP do cliente. Não sei que mágica é essa, tudo o que sei é que existe uma empresa por trás disso, como eles conseguem fazer esse serviço, isso é um mistério para mim. O que eu mando para a contabilidade são os xml que eu criei para vender. Se você tem PHP, aqui está um código parcial que eu fiz (eu criei um query builder baseado no PDO->query()) e roteador bem simples que passa pelo arquivo index com a sintaxe ?classe.método.argumento): arquivo nf.php <?php class NF { function atualiza() { $previa=(new Conn)->select("* from tbnf"); extract($_SESSION['vetor']); return view('nfView',['previa'=>$previa,'nNF' => $nNF,'xNome' => $xNome, 'codp' => $codp,'vNF' => $vNF,'difAliqICMS' => $difAliqICMS, 'soma'=>$soma,'st'=>$st]); } function CFOP() { return view('nfArquivo',['action'=>'?NF.CFOPselecionado']); } function CFOPatualizar() { $cfop = $_POST['cfop']; $codprod = $_POST['codprod']; (new Conn)->update("tbprod set cfop='$cfop' where codprod = $codprod"); } function CFOPselecionado() { (new Conn)->delete("tbnf"); (new Conn)->exec("alter table tbnf auto_increment = 1"); $nfe=simplexml_load_file($_FILES['arquivo']['tmp_name']); $itens=$nfe->NFe->infNFe->det; $nNF = (float)$nfe->NFe->infNFe->ide->nNF; $xNome = (string)$nfe->NFe->infNFe->emit->xNome; $nome = explode(" ", $xNome)[0]; $codp = (new Conn)->select("codp from tbpessoa where pessoa like '%$nome%'")[0]->codp; foreach ($itens as $item){ // no campo codforn uso a primeira letra para identificar o fornecedor $codforn = (string)$item->prod->cProd; $criterio= strtolower($nome[0].$codforn); $consulta = (new Conn)->select("* from tbprod where codforn like '%$criterio%' "); $codprod = 'null'; if (count($consulta) == 1) { $codprod = $consulta[0]->codprod; } if (count($consulta) > 1) { $consulta2 = (new Conn)->select("* from tbprod where codforn like '%$criterio' "); if(count($consulta2) == 1){ $codprod = $consulta2[0]->codprod; $consulta = $consulta2; } else { echo "existem vários produtos com codforn com o critério $criterio"; foreach($consulta as $c) { echo "<br>".$c->codprod." ".$c->prod; } exit; } } if (count($consulta)==0) { echo "nenhum produto encontrado com o critério $criterio"; exit; } $produto = substr((string)$item->prod->xProd,0,79); $cfop = (string)$item->prod->CFOP; if($cfop==6101 || $cfop==6102 || $cfop==5101) { $cfop=5102; } if($cfop==6401 || $cfop==6402 || $cfop==6403 || $cfop==5401) { $cfop=5405; } $class=($cfop == $consulta[0]->cfop) ? "w-[50px] text-right" : "w-[50px] text-red-500 text-right"; $ncm = (string)$item->prod->NCM; $class2=($ncm == $consulta[0]->cf) ? "w-[100px] text-right" : "w-[100px] text-red-500 text-right"; (new Conn)->insert("tbnf (codforn,codprod,prod,cfop,codp,ncm,class,class2) values ($codforn,$codprod,'$produto','$cfop',$codp,'$ncm','$class','$class2')"); } $previa=(new Conn)->select("* from tbnf"); return view('nfCFOPview',['previa'=>$previa,'nNF' => $nNF,'xNome' => $xNome, 'codp' => $codp]); } function custo() { $custoAtual = $_POST['custoAtual']; $codprod = $_POST['codprod']; $margem=(new Conn)->select("marg from tbprod where codprod=$codprod")[0]->marg; $venda=pvenda($custoAtual,$margem); $class="class=text-end"; (new Conn)->update("tbnf set custoanterior=$custoAtual, class='$class' where codprod=$codprod"); (new Conn)->update("tbprod set custo=$custoAtual, venda=$venda where codprod = $codprod"); } function incluir() { $lcto=$_POST['lcto']; $verifica=count((new Conn)->select("* from tbhistprod where lcto=$lcto")); if($verifica){ $mensagem="<h1>Nota já lançada. <a href=?NF.atualiza>Voltar</a></h1>"; return view('mensagemView',['mensagem'=>$mensagem]); } $dia=(new Conn)->select("dia from tbdiario where lcto=$lcto")[0]->dia; $matriz=(new Conn)->select("* from tbnf"); foreach($matriz as $vetor) { (new Conn)->insert("tbhistprod (codprod,dia,qt,custototal,codp,lcto) values ('$vetor->codprod','$dia',$vetor->qt,$vetor->custototal,$vetor->codp,$lcto)"); } return header("location:?Diario.inicio.$dia"); } function inicio() { return view('nfArquivo',['action'=>'?NF.selecionada']); } function qt() { $qt=$_POST['qt']; $id=$_POST['id']; $previa=(new Conn)->select("* from tbnf where id=$id")[0]; $novoClass=$previa->class; $custoAtual=intval($previa->custototal/$qt*100)/100; if($custoAtual!==$previa->custoanterior) { $novoClass="class=\"text-danger text-end\""; } (new Conn)->update("tbnf set class='$novoClass', custoatual=$custoAtual, qt=$qt where id=$id"); return $this->atualiza(); } function selecionada() { (new Conn)->delete("tbnf"); (new Conn)->exec("alter table tbnf auto_increment = 1"); $nfe=simplexml_load_file($_FILES['arquivo']['tmp_name']); $itens=$nfe->NFe->infNFe->det; $difAliqICMS=0; $st=0; $aliquotaInterna=0.18; foreach ($itens as $item) { if ((float)$item->prod->CFOP == 6102 || (float)$item->prod->CFOP ==6101) { $vBC = (float)$item->imposto->ICMS->ICMS10->vBC; $vBC = $vBC ? $vBC : (float)$item->imposto->ICMS->ICMS00->vBC; $vICMS = (float)$item->imposto->ICMS->ICMS10->vICMS; $vICMS = $vICMS ? $vICMS : (float)$item->imposto->ICMS->ICMS00->vICMS; if((float)$item->prod->NCM == 40169300) { $st += round($vBC*(1.4)*$aliquotaInterna-$vICMS+0.00001,2); // anel de vedação } else { $difAliqICMS += round(($vBC * $aliquotaInterna - $vICMS+0.00001),2); } } } $vNF = (float)$nfe->NFe->infNFe->total->ICMSTot->vNF; $nNF = (float)$nfe->NFe->infNFe->ide->nNF; $xNome = (string)$nfe->NFe->infNFe->emit->xNome; $nome = explode(" ", $xNome)[0]; $codp = (new Conn)->select("codp from tbpessoa where pessoa like '%$nome%'")[0]->codp; $soma=0; foreach ($itens as $item){ // no campo codforn uso a primeira letra para identificar o fornecedor $codforn = (string)$item->prod->cProd; $criterio= strtolower($nome[0].$codforn); $consulta = (new Conn)->select("* from tbprod where codforn like '%$criterio%' "); $codprod = 'null'; if (count($consulta) == 1) { $codprod = $consulta[0]->codprod; } if (count($consulta) > 1) { echo "existem vários produtos com codforn com o critério $criterio"; foreach($consulta as $c) { echo "<br>".$c->codprod." ".$c->prod; } exit; } if (count($consulta)==0) { echo "nenhum produto encontrado com o critério $criterio"; exit; } $produto = substr((string)$item->prod->xProd,0,79); $quantidade = (string)$item->prod->qCom; if (is_numeric($codprod)) { $produtoDobrado = [506, 507, 508, 509, 510, 519, 1768, 1770, 1772]; if (in_array($codprod, $produtoDobrado)) { $quantidade = 2 * $quantidade; } $produtox5=[1798]; if (in_array($codprod,$produtox5 )) { $quantidade = 5 * $quantidade; } $produtoX10 = [2192, 2190,1782,2456]; if (in_array($codprod, $produtoX10)) { $quantidade = 10 * $quantidade; } $produtox12 = [2403,2406,2496,2497,2498,2499]; if (in_array($codprod, $produtox12)) { $quantidade = 12 * $quantidade; } $produtox24 = [2493,2405,2494,2495,2409]; if (in_array($codprod, $produtox24)) { $quantidade = 24 * $quantidade; } } $vICMSST1 = ((float)$item->imposto->ICMS->ICMS10->vICMSST) ? (float)$item->imposto->ICMS->ICMS10->vICMSST : null; $vICMSST2 = ((float)$item->imposto->ICMS->ICMSSN202->vICMSST) ? (float)$item->imposto->ICMS->ICMSSN202->vICMSST : null; $vICMSST = $vICMSST1 ? $vICMSST1 : $vICMSST2; $difAliq = 0; if ((float)$item->prod->CFOP == 6102 || (float)$item->prod->CFOP == 6101){ $vBC = (float)$item->imposto->ICMS->ICMS10->vBC; $vBC = $vBC ? $vBC : (float)$item->imposto->ICMS->ICMS00->vBC; $vICMS = (float)$item->imposto->ICMS->ICMS10->vICMS; $vICMS = $vICMS ? $vICMS : (float)$item->imposto->ICMS->ICMS00->vICMS; if((float)$item->prod->NCM == 40169300) { $difAliq = round($vBC * 1.4 * $aliquotaInterna -$vICMS+0.00001,2); // usando variável $difAliq como st } else { $difAliq = round(($vBC * $aliquotaInterna - $vICMS+0.00001),2); } } $vIPI = (float)$item->imposto->IPI->IPITrib->vIPI ? (float)$item->imposto->IPI->IPITrib->vIPI : 0; $vProd = (string)$item->prod->vProd; $valorTotal = $vProd + $vICMSST + $difAliq + $vIPI; $soma += $valorTotal; $class = "class=text-end"; $custoAtual=0; $custoAnterior=0; if (is_numeric($codprod)) { $custoAtual = intval($valorTotal / $quantidade * 100) / 100; $consulta = (new Conn)->select("custo from tbprod where codprod=$codprod"); $custoAnterior = $consulta[0]->custo; if (abs($custoAnterior - $custoAtual) > 0.02) { $class = "class=\"text-end text-danger\""; } } $produto=str_replace("'","''",$produto); (new Conn)->insert("tbnf (codforn,codprod,prod,qt,custoatual, custoanterior,class,custototal,codp,cfop,class2) values ('$codforn',$codprod,'$produto',$quantidade,$custoAtual, $custoAnterior,'$class',$valorTotal,$codp,'5405','text-right')"); } $previa=(new Conn)->select("* from tbnf"); $_SESSION['vetor']=['nNF' => $nNF,'xNome' => $xNome, 'codp' => $codp,'vNF' => $vNF,'difAliqICMS' => $difAliqICMS, 'soma'=>$soma,'st'=>$st]; return view('nfView',['previa'=>$previa,'nNF' => $nNF,'xNome' => $xNome, 'codp' => $codp,'vNF' => $vNF,'difAliqICMS' => $difAliqICMS, 'soma'=>$soma,'st'=>$st]); } function verXML(){ return view('nfArquivo',['action'=>'?NF.xml']); } function xml(){ $nfe=simplexml_load_file($_FILES['arquivo']['tmp_name']); return imprime($nfe); } } arquivo nfArquivo.php <?php require 'menuView.php' ?> <script>btmenu.innerHTML="Nota do Fornecedor";document.title="Nota do Fornecedor"</script> <div class=mb-3> <form method=post enctype="multipart/form-data" action="<?=$action?>"> <label for=arquivo class=form-label>Escolha o arquivo XML</label> <input type=file name=arquivo class=form-control id=formfile required onchange=submit()> </form> </div> arquivo nfCFOPview.php <?php include('menuView.php'); ?> <script> btMenu.innerHTML='NF Fornecedor CFOP';document.title="NF Fornecedor CFOP" function getCsrfToken() { return document.querySelector('meta[name="csrf-token"]').getAttribute('content'); } function atualizar(cfop, codprod) { var xmlhttp = new XMLHttpRequest(); var url = "nfCFOPatualizar"; var formData = new FormData(); formData.append('cfop', cfop); formData.append('codprod', codprod); formData.append('_token', getCsrfToken()); xmlhttp.open("POST", url, true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) { console.log("Estado da requisição: " + xmlhttp.readyState); if (xmlhttp.status == 200) { location.reload(); } else { alert("Erro na requisição: " + xmlhttp.status); } } }; xmlhttp.send(formData); } </script> <div class="flex"> <div class="w-[50px] text-right">Cforn</div> <div class="w-[50px] text-right">Cod</div> <div class="w-[448px] ml-2">Produto</div> <div class="w-[50px] text-right">CFOP</div> <div class="w-[100px] text-right">NCM</div> </div> <?php foreach($previa as $p): ?> <div class="flex odd:bg-gray-200"> <div class="w-[50px] text-right"><?=$p->codforn?></div> <div class="w-[50px] text-right"><?=$p->codprod?></div> <div class="w-[448px] ml-2 truncate"><?=$p->prod?></div> <div class="<?=$p->class?>" onclick="atualizar(<?=$p->cfop?>,<?=$p->codprod?>)"> <?=$p->cfop?> </div> <div class="<?=$p->class2?>"><?=$p->ncm?></div> </div> <?php endforeach; ?> arquivo nfView.php <?php include('menuView.php'); ?> <script> btMenu.innerHTML='NF Fornecedor';document.title="NF Fornecedor" function atualizar(custoAtual, custoAnterior, codprod) { var confirma = confirm("Atualizar?\ncusto atual: " + custoAtual + "\ncusto anterior: " + custoAnterior); if (confirma) { var xmlhttp = new XMLHttpRequest(); var url = "?NF.custo"; var formData = new FormData(); formData.append('custoAtual', custoAtual); formData.append('codprod', codprod); xmlhttp.open("POST", url, true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) { console.log("Estado da requisição: " + xmlhttp.readyState); if (xmlhttp.status == 200) { // console.log("Status da resposta: " + xmlhttp.status); // alert("Resposta do servidor: " + xmlhttp.responseText); location.replace("?NF.atualiza"); } else { alert("Erro na requisição: " + xmlhttp.status); } } }; xmlhttp.send(formData); } } </script> <table class='table table-striped table-sm'> <tr class=fw-semibold><td colspan=3>NF <?=$nNF." ".substr($xNome,0,10)." codp ".$codp?><td><td><td class=text-end><?=dec($vNF)?> <?php if($difAliqICMS!==0 || $st!==0): ?> <tr class=fw-semibold><td><td><td>Diferença de Alíquota de ICMS<td><td><td class=text-end><?=dec($difAliqICMS)?> <tr class=fw-semibold><td><td><td>Substituição Tributária<td><td><td class=text-end><?=dec($st)?> <tr class=fw-semibold><td><td><td>Total a conferir<td><td><td class=text-end><?=dec($difAliqICMS+$vNF+$st)?> <?php endif; ?> </table> <table class="table table-striped table-sm"> <th style="max-width:50px">Cforn <th style="width:50px text-end">Cod <th style="width:330px">Produto <th class=text-end>Qt <th class=text-end>Custo <th class=text-end>Total <?php foreach($previa as $p): ?> <tr><td style="max-width:80px" class=text-end><?=$p->codforn?> <td style="max-width:50px" class=text-end><?=$p->codprod?> <td style="max-width:330px" class="overflow-hidden" ><?=$p->prod?> <td> <form method=post action=?NF.qt> <input name=qt value='<?=$p->qt?>' class="inv text-end" size='1' onchange=submit()> <input type=hidden name=id value='<?=$p->id?>'> </form> <td <?=$p->class?> onclick="atualizar(<?=$p->custoatual?>,<?=$p->custoanterior?>,<?=$p->codprod?>)"><?=dec($p->custoatual)?> <td class=text-end><?=dec($p->custototal)?> <?php endforeach; ?> <tr class=fw-semibold><td><td><td>Total dos itens<td><td></td><td class=text-end><?=dec($soma)?> </table> <div> Enviar tudo para o banco de dados <form action=?NF.incluir method=post> <input name=lcto placeholder="Número do Lançamento" required> <input type=submit> </form> </div>
  15. Tem jeito de compartilhar o código do arquivo para a gente testar aqui?
  16. Eu acho bem difícil dominar o SQL em apenas duas horas, ele exige uma boa base teórica. Eu por exemplo levei vinte anos para entender o que é chave primária de uma tabela, hoje eu não me assusto quando usam o campo id na tabela produtos, id na tabela contatos, id na tabela pedido e assim por diante. Eu ainda não sei usar a chave externa, mas em 2020 conheci o PHP, ele me livrou do problema dos relacionamentos. E finalmente em 2024 conheci o Copilot, comentei com ele que o meu programa balancete levava cinco horas para aparecer na tela. O Copilot leu o meu código, e fez algumas correções, e agora consigo ver o balancete em menos de cinco segundos. Eu aconselho a fazer o curso de SQL só quem souber o que é atomização da informação, sem isso, tudo é dinheiro perdido.
  17. <?php function menorNumero($numero1, $numero2) { if ($numero1 < $numero2) { return $numero1; } else { return $numero2; } } // Exemplo de uso $numero1 = 10; $numero2 = 20; echo "O menor número é: " . menorNumero($numero1, $numero2); ?>
  18. O problema é criar o critério. Não sei o que devo procurar na primeira e na segunda planilhas. Se ambas usassem uma chave tipo CPF+PagamentoMês, aí dá para pintar uma chave presente numa planilha e ausente na outra, ou pintar de cor diferente se for de valores diferentes, ou não pintar se as chaves e valores forem iguais. No seu caso, você repete o CPF várias vezes com valores diferentes, por exemplo Vilma 10, Vilma 10, Vilma 10, e na outra planilha tenho Vilma 15, não dá para fazer nada, não dá saber qual a relação do primeiro dado com o dado na outra planilha. Na teoria do banco de dados, o nome disso é chave primária, sem isso é impossível fazer qualquer tipo de trabalho.
  19. Eu tenho 66 anos, e estudo programação para tentar colocar um pouco de lógica na minha vida, bem como familiarizar com as novas tecnologias. Enfrento vários problemas, mas não sei quem pode me ajudar, eu queria que o serviço de impressão fosse mais rápido pelo celular, eu queria consertar a guilhotina da minha impressora térmica, eu queria consertar o touch pad do meu irmão. Eu tento ensinar o meu irmão a usar o computador com critério, sempre ajuntar a fatura com o comprovante de pagamento num só arquivo, e nomear de forma que seja fácil localizar. Eu queria ter coragem de abrir o Excel no celular de um arquivo hospedado no OneDrive, mas toda vez que eu abro, isso gera um monte de dificuldade na hora de abrir no laptop. Enfim, é só experiência e conhecimento que você ganha ao estudar a programação. O dinheiro só depende de você usar a lógica na sua vida. Por exemplo, o que impede você de pegar R$ 2,00 do seu vizinho, prometendo lavar o banheiro dele? É que você não sabe o nome dele, e ele não sabe o seu nome. Se você conseguir aproveitar o estudo da programação para você se tornar visível, certamente vale a pena estudar. O mais importante é o cliente, você precisa aprender a respeitá-lo, mostrar que você pode ajudá-lo. E quando você conquistar a confiança dele, certamente o dinheiro será o menor dos seus problemas.
  20. O JavaScript é o único programa que eu conheço que é capaz de atualizar a página onde ele está, através do comando location.reload( ), e isso eu consegui no código PHP. O Laravel é outra história, qualquer solicitação que você faz precisa usar a ferramenta @csrf. Mas o @csrf só é usado com o marcador <form>, e não queria sair da página porque isso ia ser um grande desastre. Copiei o código JavaScript do PHP no Laravel, e obtive o erro 419, esse é o famoso erro da ausência do csrf. O Copilot pediu para criar um comando <meta> que gera o crsf e também pedir para o JavaScript encaminhar o crsf adiante. E deu certo. Eu não sou bom com o JavaScript, mas quando consigo fazer o JavaScript trabalhar para mim, eu fico feliz da vida: arquivo resources > views > nfCFOPview.blade.php <meta name="csrf-token" content="{{ csrf_token() }}"> @include('menuView') <script> btMenu.innerHTML='NF Fornecedor CFOP';document.title="NF Fornecedor CFOP" function getCsrfToken() { return document.querySelector('meta[name="csrf-token"]').getAttribute('content'); } function atualizar(cfop, codprod) { var xmlhttp = new XMLHttpRequest(); var url = "nfCFOPatualizar"; var formData = new FormData(); formData.append('cfop', cfop); formData.append('codprod', codprod); formData.append('_token',getCsrfToken()) xmlhttp.open("POST", url, true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) { console.log("Estado da requisição: " + xmlhttp.readyState); if (xmlhttp.status == 200) { location.reload(); } else { alert("Erro na requisição: " + xmlhttp.status); } } }; xmlhttp.send(formData); } </script> <div class="flex"> <div class="w-[50px] text-right">Cforn</div> <div class="w-[50px] text-right">Cod</div> <div class="w-[378px] ml-2">Produto</div> <div class="w-[50px] text-right">CFOP</div> <div class="w-[100px] text-right">NCM</div> </div> <?php foreach($previa as $p): ?> <div class="flex odd:bg-gray-200"> <div class="w-[50px] text-right"><?=$p->codforn?></div> <div class="w-[50px] text-right"><?=$p->codprod?></div> <div class="w-[378px] ml-2 truncate"><?=$p->prod?></div> <div class="<?=$p->class?>" onclick="atualizar(<?=$p->cfop?>,<?=$p->codprod?>)"> <?=$p->cfop?> </div> <div class="<?=$p->class2?>"><?=$p->ncm?></div> </div> <?php endforeach; ?>
  21. Frank K Hosaka

    CFOP

    Semana passada a Bling me orientou que existe no menu de configurações a rotina para Nota Fiscal > Natureza da Operação, onde podem ser definidas as regras de tributação, e assim definir uma CFOP para cada produto de acordo com a NCM. O MySQL me informou que eu tenho atualmente 256 NCM dentro da tbprod, o problema é saber quem tem substituição tributária e quem não tem. A Secretaria da Fazenda tem o regulamento do ICMS bem como planilhas que definem os produtos que tem substituição tributária, mas aquilo é bem difícil de entender e trabalhar. A minha saída é olhar cada nota fiscal do fornecedor e corrigir o banco de dados. Na tbprod eu criei o campo string cfop, e defini para todas elas 5405. A seguir criei uma rotina em PHP para olhar a nota do fornecedor no formato xml, comparar os dados com a tbprod, e assim corrigir o que for necessário: arquivo nf.php <?php class NF { function CFOP() { return view('nfArquivo',['action'=>'?NF.CFOPselecionado']); } function CFOPatualizar() { $cfop = $_POST['cfop']; $codprod = $_POST['codprod']; (new Conn)->update("tbprod set cfop='$cfop' where codprod = $codprod"); } function CFOPselecionado() { (new Conn)->delete("tbnf"); (new Conn)->exec("alter table tbnf auto_increment = 1"); $nfe=simplexml_load_file($_FILES['arquivo']['tmp_name']); $itens=$nfe->NFe->infNFe->det; $nNF = (float)$nfe->NFe->infNFe->ide->nNF; $xNome = (string)$nfe->NFe->infNFe->emit->xNome; $nome = explode(" ", $xNome)[0]; $codp = (new Conn)->select("codp from tbpessoa where pessoa like '%$nome%'")[0]->codp; foreach ($itens as $item){ // no campo codforn uso a primeira letra para identificar o fornecedor $codforn = (string)$item->prod->cProd; $criterio= strtolower($nome[0].$codforn); $consulta = (new Conn)->select("* from tbprod where codforn like '%$criterio%' "); $codprod = 'null'; if (count($consulta) == 1) { $codprod = $consulta[0]->codprod; } if (count($consulta) > 1) { $consulta2 = (new Conn)->select("* from tbprod where codforn like '%$criterio' "); if(count($consulta2) == 1){ $codprod = $consulta2[0]->codprod; } else { echo "existem vários produtos com codforn com o critério $criterio"; foreach($consulta as $c) { echo "<br>".$c->codprod." ".$c->prod; } exit; } } if (count($consulta)==0) { echo "nenhum produto encontrado com o critério $criterio"; exit; } $produto = substr((string)$item->prod->xProd,0,79); $cfop = (string)$item->prod->CFOP; if($cfop==6101 || $cfop==6102 || $cfop==5101) { $cfop=5102; } if($cfop==6401 || $cfop==6402 || $cfop==5401) { $cfop=5405; } $class=($cfop == $consulta[0]->cfop) ? "w-[50px] text-right" : "w-[50px] text-red-500 text-right"; $ncm = (string)$item->prod->NCM; $class2=($ncm == $consulta[0]->cf) ? "w-[100px] text-right" : "w-[100px] text-red-500 text-right"; (new Conn)->insert("tbnf (codforn,codprod,prod,cfop,codp,ncm,class,class2) values ($codforn,$codprod,'$produto','$cfop',$codp,'$ncm','$class','$class2')"); } $previa=(new Conn)->select("* from tbnf"); $_SESSION['vetor']=['nNF' => $nNF,'xNome' => $xNome, 'codp' => $codp]; return view('nfCFOPView',['previa'=>$previa,'nNF' => $nNF,'xNome' => $xNome, 'codp' => $codp]); } } arquivo nfArquivo.php <?php require 'menuView.php' ?> <script>btmenu.innerHTML="Nota do Fornecedor";document.title="Nota do Fornecedor"</script> <div class=mb-3> <form method=post enctype="multipart/form-data" action="<?=$action?>"> <label for=arquivo class=form-label>Escolha o arquivo XML</label> <input type=file name=arquivo class=form-control id=formfile required onchange=submit()> </form> </div> arquivo nfCFOPview.php <?php include('menuView.php'); ?> <script> btMenu.innerHTML='NF Fornecedor CFOP';document.title="NF Fornecedor CFOP" function atualizar(cfop, codprod) { var xmlhttp = new XMLHttpRequest(); var url = "?NF.CFOPatualizar"; var formData = new FormData(); formData.append('cfop', cfop); formData.append('codprod', codprod); xmlhttp.open("POST", url, true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) { console.log("Estado da requisição: " + xmlhttp.readyState); if (xmlhttp.status == 200) { location.reload(); } else { alert("Erro na requisição: " + xmlhttp.status); } } }; xmlhttp.send(formData); } </script> <div class="flex"> <div class="w-[50px] text-right">Cforn</div> <div class="w-[50px] text-right">Cod</div> <div class="w-[448px] ml-2">Produto</div> <div class="w-[50px] text-right">CFOP</div> <div class="w-[100px] text-right">NCM</div> </div> <?php foreach($previa as $p): ?> <div class="flex odd:bg-gray-200"> <div class="w-[50px] text-right"><?=$p->codforn?></div> <div class="w-[50px] text-right"><?=$p->codprod?></div> <div class="w-[448px] ml-2 truncate"><?=$p->prod?></div> <div class="<?=$p->class?>" onclick="atualizar(<?=$p->cfop?>,<?=$p->codprod?>)"> <?=$p->cfop?> </div> <div class="<?=$p->class2?>"><?=$p->ncm?></div> </div> <?php endforeach; ?>
  22. Eu ouvi dizer que os bancos trabalham com muitos técnicos de informação, mas eu não conheço nenhum em particular. Eu aconselho a pegar uma pessoa real e ver a história particular dele, principalmente quanto que ele ganha. Eu fiz o estudo da programação por conta própria. Quem me ajudou a ter noção de programação foi o recurso da macro encontrado dentro da planilha Excel. Além da macro, o Excel oferece Visual Basic for Aplications. O tutorial deles é de amargar, fiz vários testes e experimentei várias frustrações. Em 2020, eu vi um vídeo bacana do professor Guanabara, ele me ensinou a instalar o servidor WampServe. Levei dois meses para instalar no meu notebook, depois de ver e ler várias matérias espalhadas na internet. Depois que eu consegui instalar o servidor, eu ganhei de brinde o MySQL e o PHP. Levei mais dois meses para mexer com ele. Enfim, comecei o meu projeto chamado orçamento, e eu sofri muito porque não sabia nada de HTML e nem de JavaScript. Finalmente chegou 2024, e surgiu o Copilot da Microsoft. Ele me ajudou a programar melhor, dominar principalmente o espinhoso capítulo do CSS. Enfim, eu já sei como escrever "olá mundo" na tela do celular, eu consegui hospedar o meu código na Hostinger, o plano inicial é de R$ 10,00 por mês, só que não dá para usar o programa npm e nem node. Logo, ao invés de assinar um curso, por que você não conversa com o Copilot? Aqui o endereço: www.copilot.com. A página está em inglês, mas você pode usar a gramática portuguesa, comece assim: olá Copilot, eu não sei nada de programação, por onde eu começo?
  23. Recebi a resposta da Bling, ainda não tive tempo de verificar, mas acho oportuno publicar a resposta aqui, uma vez que é o nome da Bling é que está em jogo: Atendente: Maria M. Mensagem: Bom dia, tudo bem? Espero que sim! Temos como criar regras por produtos, NCM e grupo de produtos. Na natureza de operação, você poderá criar regras tributárias para diferentes produtos. Para isso, siga os passos descritos abaixo: Passo 1: Posicione o mouse sobre o ícone da engrenagem > Todas as configurações > Notas fiscais > Naturezas de operação Passo 2: Clique sobre a natureza desejada Passo 3: Em Regras de Tributação, clique sobre a regra que deseja alterar ou em '+ Adicionar regra' para adicionar uma nova regra Passo 4: Clicando sobre a opção 'Qualquer produto', selecione uma das opções: • Produto • NCM • Grupo de Produtos Exemplo em anexo: https://prnt.sc/y0t0BUfWpWEj E preencha o campo ao lado com a informação: Caso tenha selecionado a opção 'Produto', informe o nome do produto cadastrado, e selecione-o. Caso tenha selecionado a opção 'NCM', informe o NCM do produto e selecione-o. Caso tenha selecionado a opção 'Grupo de Produtos', informe o nome do grupo cadastrado, e selecione-o. Clique aqui para verificar mais sobre o grupo de produtos OBS: Caso deseje adicionar mais de um produto, basta clicar na opção 'Adicionar outro item', para produtos que compartilharão das mesmas regras tributárias. Em seguida, preencha os dados tributários conforme orientado por sua contabilidade. Ao finalizar as alterações, clique em 'Salvar'. Em seguida, salve a natureza. Assim, após a configuração das regras por produto, a informação e tributos serão informados automaticamente nas notas com essa natureza de operação selecionada. Para saber quais informações preencher, seria somente com a contabilidade. Em caso de dúvidas, sigo a disposição! -- Atenciosamente, Eduarda M. - Suporte Bling (54) 3771-7278
  24. Eu sou do tempo que se emitia a Nota Fiscal na mão, eu tinha que ter o cuidado na hora de preencher a Natureza da Operação, e em seguida registrava a NF no Livro de Saída. Hoje é 2025, tudo é moderno, você não usa mais a caneta e o papel de carbono para emitir, basta um teclado. O máximo que eu consegui fazer com o PHP é montar um orçamento, mas eu não sou capaz de fazer um código que emita uma nota fiscal. Eu contratei a Bling, e hoje ela cobra R$ 70,00 por mês para emitir a Nota Fiscal do tipo NFCe. Uso a Bling para importar o orçamento que fiz no PHP, e de lá eu emito a NFCe. Tudo parece fácil e tudo parece mágica, me faz acreditar que os R$ 70,00 é uma pechincha. A NFCe é gravado na Secretaria da Fazenda, tudo parece tranquilo. Só que eu pedi o Registro de Saída do serviço contábil, e eu cai de costa. Todas as NFCe foram registrados como 5.102 venda a não contribuinte, quando tem muito produto que eu vendo e que foram previamente tributados pelo ICMS antecipado, ou seja, eu esperava que o livro mostrasse um monte de CFOP 5.405 e um pouco de 5.102. Eu pedi socorro para o Copilot e a resposta dele é bem imprecisa, indica vários vídeos do YouTube que são mais imprecisas. A Inteligência Artificial ainda não está preparada para entender o Regulamento do ICMS e ensinar como emitir a Nota Fiscal. Estou muito tranquilo com o meu programa Orçamento que não emite Nota Fiscal. O que me deixa apavorado é a Bling emitir a Nota Fiscal sem nenhum contador ou fiscal da Secretaria da Fazenda para homologar o serviço que eu pago: de que adianta pagar R$ 70,00 para emitir a Nota Fiscal com a natureza da operação errada? Eu não posso exigir muito do Copilot, pois ele é um serviço gratuito. Mas quem está pagando um serviço melhor que o Copilot, por favor, pergunte a ele se é possível saber se uma Nota Fiscal foi emitida corretamente, principalmente no tópico Natureza da Operação. Grato.
  25. Eu tenho um projeto chamado orçamento que estou desenvolvendo desde 1999, eu uso o código PHP e o código Laravel, ambos têm a mesma lógica e a mesma imagem, menos o formulário do login. O formulário do Laravel é capaz de preencher toda a tela do celular, no modo retrato, e isso eu não consegui no código PHP. Você pode traduzir o código PHP em Laravel, o contrário é impossível. Por exemplo, o Laravel não deixa você submeter um formulário se não usar o recurso Blade @csrf, já o PHP não tem esse recurso. A minha única saída foi tentar copiar o código HTML produzido pelo Laravel e copiar no PHP. Eu nunca imaginei que fosse possível ver o código fonte no navegador do celular, mas hoje o Copilot me deu a dica de modificar a barra de endereço de "https://frank.com" para "view-source:https://frank.com", e assim consegui ver o código HTML no celular. Selecionei tudo, copiei num bloco do Google Keep, e no notebook eu copiei o código para o Visual Studio, e assim consegui criar o código PHP que faz a mesma mágica que o Laravel: arquivo loginView.php <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="https://cdn.tailwindcss.com"></script> <script>document.title="Login"</script> <div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100"> <div class="text-2xl">Projeto Classe</div> <div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white shadow-md overflow-hidden sm:rounded-lg"> <form method="POST" action="?Login.menu"> <div> <label class="block font-medium text-sm text-gray-700" for="email"> Email </label> <input class="px-2 border rounded-md shadow-sm mt-2 focus:outline-blue-700" id="email" type="email" name="email" required="required" autofocus autocomplete="username"> </div> <!-- Password --> <div class="mt-4"> <label class="block font-medium text-sm text-gray-700" for="password"> Senha </label> <input class="px-2 border rounded-md shadow-sm block mt-1 focus:outline-blue-700" id="password" type="password" name="password" required="required" autocomplete="current-password"> </div> <button type="submit" class="px-2 mt-4 rounded-lg text-gray-500 font-semibold hover:bg-gray-200"> Entrar </button> </form> </div> </div>
×
×
  • Criar Novo...