Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Giovani Silva

PHP NFSe com SOAP envio de XML RPS para Betha Fly-enota

Recommended Posts

Boa noite, estou tentando enviar com PHP SOAP o XML de um lote RPS assinado para o Web Service da Betha também conhecido como Fly e-nota. 

No entanto, não tenho tido nenhum retorno quanto a se deu algum erro ou algo do tipo.

 

Documentação https://e-gov.betha.com.br/e-nota-test/ambienteteste.faces 

 

Ambiente Teste Webservice 

https://e-gov.betha.com.br/e-nota-contribuinte-test-ws/recepcionarLoteRps?wsdl

https://e-gov.betha.com.br/e-nota-contribuinte-test-ws/consultarLoteRps?wsdl 

 

Layout https://e-gov.betha.com.br/e-nota/manuais/layout.pdf 
Modelo Conceitual http://www.abrasf.org.br/arquivos/files/NFSE-NACIONAL_Modelo_Conceitual versao 2-02.pdf

Manual de Integração ABRASF http://www.abrasf.org.br/arquivos/files/NFSE-NACIONAL_Manual_De_Integracao versao 2-02.pdf 

 

Tem uma opção na área administrativa Fly e-nota para solicitar a prefeitura autorização para impressão de RPS tanto manual como eletrônica.
Não sei se isso é obrigatório ou se é necessário para o meu objetivo.

  

Parte do código para o envio:

------------------------------

function transmiteRps($xmlAssinado,$certificadoPem,$senha){
    $wsdl            = 'https://e-gov.betha.com.br/e-nota-contribuinte-test-ws/recepcionarLoteRps?wsdl';
    $endpoint        = 'https://e-gov.betha.com.br/e-nota-contribuinte-test-ws/recepcionarLoteRps';
    $certificate    = $certificadoPem;
    $password        = $senha;
    
    $options = array(
        'location'        => $endpoint,
        'keep_alive'    => true,
        'trace'            => true,
        'local_cert'    => $certificate,
        'passphrase'    => $password,
        'cache_wsdl'    => WSDL_CACHE_NONE
    );
    
    try {
        
        $client = new SoapClient($wsdl, $options);



        $function = 'EnviarLoteRpsEnvio';
        $arguments = ['EnviarLoteRpsEnvio' => ['xml'=>$xmlAssinado]];
        
        $options = [];
        $result = $client -> __soapCall($function, $arguments, $options);



    } catch(Exception $e){
        $result = false;
    }
      
    if($result!==false){
        return xml2array($result->return);
    }else{
        return false;
    }
    
}//transmiteRps





----------------------------------------------------------


function xml2array($xmlstring){
    $xml = simplexml_load_string($xmlstring);
    $json = json_encode($xml);
    $array = json_decode($json, TRUE);
    return $array;
    
}



-----------------------------------------------



function consultaRps($cnpj, $inscricao, $protocolo, $certificadoPem, $senha){
    
    $wsdl            = 'https://e-gov.betha.com.br/e-nota-contribuinte-test-ws/consultarLoteRps?wsdl';
    $endpoint        = 'https://e-gov.betha.com.br/e-nota-contribuinte-test-ws/consultarLoteRps';
    $certificate    = $certificadoPem;
    $password        = $senha;

    

$xml = '<?xml version="1.0" encoding="utf-8"?>
    <ConsultarLoteRpsEnvio xmlns="http://www.betha.com.br/e-nota-contribuinte-test-ws">
    <Prestador>
        <CpfCnpj>
            <Cnpj>'.$cnpj.'</Cnpj>
        </CpfCnpj>
        <InscricaoMunicipal>'.$inscricao.'</InscricaoMunicipal>
    </Prestador>
    <Protocolo>'.$protocolo.'</Protocolo>
    </ConsultarLoteRpsEnvio>';
    
    
    $options = array(
        'location'        => $endpoint,
        'keep_alive'    => true,
        'trace'            => true,
        'local_cert'    => $certificate,
        'passphrase'    => $password,
        'cache_wsdl'    => WSDL_CACHE_NONE
    );
    
    try {
        
        $client = new SoapClient($wsdl, $options);
        $function = 'consultarLoteRps';
        $arguments = ['consultarLoteRps' => ['xml'=>$xml]];
        
        $options = [];
        $result = $client -> __soapCall($function, $arguments, $options);
    } catch(Exception $e){
        $result = false;
    }
    
    if($result!==false){
        return $result->return;
    }else{
        return false;
    }
    
} //consultaRps



--------------------------------



$certificadoPem=dirname(__FILE__).'/certificado.pem';
$senha='xxxxx'; //senha do certificado



----------------------------------



//assina RPS
$xmlAssinado=assinaRps(dirname(__FILE__).'/only_rps.xml'); //usei para assinar só a RPS



file_put_contents(dirname(__FILE__).'/rps_temp/rps1.xml','<?xml version="1.0" encoding="utf-8"?>
<EnviarLoteRpsEnvio xmlns="https://e-gov.betha.com.br/e-nota-contribuinte-test-ws"><LoteRps Id="LOTE1"><NumeroLote>1</NumeroLote><Cnpj>xxxxxxxxxxxxxx</Cnpj><InscricaoMunicipal>xxxx</InscricaoMunicipal><QuantidadeRps>1</QuantidadeRps>
<ListaRps>'.str_replace('<?xml version="1.0" encoding="utf-8"?>','',$xmlAssinado).'</ListaRps></LoteRps></EnviarLoteRpsEnvio>');

$_SESSION['nome_uri']='LOTE1';



$xmlAssinado=assinaRps(dirname(__FILE__).'/rps_temp/rps1.xml'); //usei para assinar o Lote RPS






$resultado=transmiteRps($xmlAssinado,
                       $certificadoPem,
                       $senha);


if(!empty($resultado["Protocolo"])){//se tem protocolo e sucesso
    //$resultado["NumeroLote"]
    //$resultado["Protocolo"]
    //consulta lote e pega nfse
    
    $nfseResposta = consultaRps('xxxxxxxxxxxxx', //cnpj
                               'xxxx', //inscrição municipal
                               $resultado["Protocolo"],
                               $certificadoPem,
                               $senha);
    
    if($nfseResposta!==false){
        echo '<textarea cols="120" rows="70">';
        echo $nfseResposta;
        echo '</textarea>';
    }else{
        echo 'Erro ao consultar RPS';
    }
    
}else{
    echo "erro no envio";
}


 

Vídeo Tutorial do código NFSe acima porém para outro webservice que não é da Betha.

https://www.youtube.com/watch?v=v1rByVX1_FY

 

Desde já agradeço a atenção e colaboração dos colegas.
Funcionando postarei aqui a solução com o código completo para quem precisar.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Um dos pontos que analizei, é que você está enviando os dados de forma errada. Apesar do WSDL definir os tipos como um XML, não é um XML que deve ser enviado. Você deve criar um objeto que corresponda ao tipo definido na mensageria.

 

Veja o seguinte XML:

<ConsultarLoteRpsEnvio xmlns="http://www.betha.com.br/e-nota-contribuinte-test-ws">
    <Prestador>
        <CpfCnpj>
            <Cnpj>?</Cnpj>
        </CpfCnpj>
        <InscricaoMunicipal>?</InscricaoMunicipal>
    </Prestador>
    <Protocolo>?</Protocolo>
</ConsultarLoteRpsEnvio>

Sendo ConsultarLoteRpsEnvio o nome do método, o que está abaixo são as propriedades.

 

Com anos de experiência, eu compreendi que o Soap trabalha melhor quando lhe é enviado um objeto do tipo stdClass ao invés de um array. Logo, quando for montar o objeto, ele deve ser similar a este:

//Cria o objeto nó raiz
$consultarLoteRpsEnvio = new stdClass();

//cria o objeto do nó Prestador
$prestador = new stdClass();

//Cria o objeto do nó CpfCnpj
$cpfCnpj = new stdClass();
$cpfCnpj->Cnpj = 'xxxxxxxxxxxx';

//Adiciona o nó CpfCnpj ao nó Prestador
$prestador->CpfCnpj = $cpfCnpj;
$prestador->InstricaoMunicipal = 'xxxxxx';

//Adiciona o nó Prestador ao nó Raiz
$consultarLoteRpsEnvio->Prestador = $crestador;
$consultarLoteRpsEnvio->Protocolo = 'xxxxx';

E, na hora de enviar, utilize apenas o objeto:

$result = $client->ConsultarLoteRpsEnvio($consultarLoteRpsEnvio);

Você pode encontrar outro exemplo aqui:

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom dia Gabriel, muito obrigado pela dica.
Gostei do conceito de criar e enviar o objeto.

 

Vou tentar fazer como você mencionou.

 

Bem, pelo que entendi o mesmo conceito deve ser aplicado a função transmiteRps.

 

Mas a parte que diz no manual que tanto a RPS como o Lote devem ser Assinados
a assinatura também deve ser colocada no objeto da forma que mencionasse?
Em nenhuma parte enviarei um arquivo XML do Lote RPS, apenas o objeto? quanto a senha, assinatura,... e outras coisas para ter um minimo de segurança?

 

O certificado eu converti para .pem Nesse caso o processo de assinar o objeto seria o mesmo praticamente que eu havia usado?

 

Só lembrando a parte que receberá o RPS https://e-gov.betha.com.br/e-nota-contribuinte-test-ws/recepcionarLoteRps?wsdl 

 

Obs. No caso que fiz eu gravei o XML assinado, mas na hora de enviar não tive o Protocolo para a parte da consulta. Ou seja, algo errado mas também não tive resposta de erro do webservice.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Quanto a essas situações do certificado, terei de pesquisar, nunca precisei enviar nada assinado digitalmente via SOAP.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Obrigado, vou dar uma olhada.

Aproveitando, você sabe interpretar o WSDL? 
https://e-gov.betha.com.br/e-nota-contribuinte-test-ws/recepcionarLoteRps?wsdl 
é que na chamada
__soapCall($function, $arguments, $options); 

 

Tenho duvida quanto a função e os argumentos usados para o envio dos dados.
         $function = 'EnviarLoteRpsEnvio';
        $arguments = ['EnviarLoteRpsEnvio' => ['xml'=>$xmlAssinado]];

 

--- Dúvida: EnviarLoteRpsEnvioResponse ou EnviarLoteRpsEnvio em ambos os casos (função e nos argumentos) ?

 

Outra questão: ao usar stdClass na real não estaria criando a mesma estrutura do XML manualmente e salvando em um objeto para enviá-la ao webservice?

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Caso você não conheça todas as partes do WSDL, use o SoapUI para interpretar o WSDL, ele lhe ajudar bastante.

 

6 minutos atrás, didio20ss disse:

[...] ao usar stdClass na real não estaria criando a mesma estrutura do XML manualmente e salvando em um objeto para enviá-la ao webservice?

 

 

Sim e não. A ideia é criar exatamente a estrutura do XML, entretanto, a sua estrutura de XML é apenas uma string, por isso elas possuem comportamentos diferentes.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi, tive mais uma dúvida, tenho dois modelos de lote RPS onde um baixei da Betha e outro fornecido por uma empresa de automação que usa o sistema da Betha.
No cabeçalho dessa outra empresa tem o "e:" e no na Betha não.

Empresa Midia
<e:EnviarLoteRpsEnvio xmlns:e="http://www.betha.com.br/e-nota-contribuinte-ws">
Betha 
<EnviarLoteRpsEnvio xmlns = "http://www.betha.com.br/e-nota-contribuinte-ws">

Esse "e:" ou as vezes já notei outras expressões no lugar,
como se chama e para que serve? 
Faz diferença usar ?

 

----------------
Outra dúvida

Nos exemplos da Betha tem:
envioSoapUi.xml que tem o comentário "Quando utilizar, por exemplo, o Soap-UI para envio do XML deve ser utilizada a estrutura abaixo" que teria um cabeçalho <soapenv 
E tem exemplos sem isso. 
Na hora de montar a estrutura do XML devo usar isso no meu código php ou não?

Outros exemplos que tem:
RecepcionarLoteRps.xml

RecepcionarLoteRpsSincrono.xml
GerarNfse.xml <GerarNfseEnvio xmlns = "http://www.betha.com.br/e-nota-contribuinte-ws">

 

Qual a diferença do Sincrono e do outro? Qual a melhor opção?

 

E eu estava a usar o RecepcionarLoteRps.
Me passaram a informação que gerando e enviando o XML do lote RPS para o Webservice da Betha, 
o sistema deles gera a DANFE e até envia a NFSe para o e-mail do cliente se o mesmo for informado no XML
.

 

Então devo continuar a usar apenas o RecepecionarLoteRps ou também devo usar o GerarNfse?

 

Obrigado mais uma vez

Compartilhar este post


Link para o post
Compartilhar em outros sites
2 horas atrás, didio20ss disse:

Esse "e:" ou as vezes já notei outras expressões no lugar,
como se chama e para que serve? 
Faz diferença usar ?

 

É um prefixo de namespace. Quando não utilizado, tudo que é global, cai no namespace sem prefixo. Já, caso você utilizar, você pode usar o prefixo para informar o namespace utilizado.

 

Para saber mais, de uma olhada aqui: https://msdn.microsoft.com/en-us/library/aa468565.aspx

 

2 horas atrás, didio20ss disse:

Nos exemplos da Betha tem:
envioSoapUi.xml que tem o comentário "Quando utilizar, por exemplo, o Soap-UI para envio do XML deve ser utilizada a estrutura abaixo" que teria um cabeçalho <soapenv 
E tem exemplos sem isso. 
Na hora de montar a estrutura do XML devo usar isso no meu código php ou não?

 

essa estrutura deve ser usada quando você quiser manipular completamente a chamada do SOAP (cabeçalho e corpo da requisição). Isso normalmente acontece quando utiliza-se a biblioteca cURL. Com a biblioteca SOAP do PHP, ele já faz isso por ti.

 

2 horas atrás, didio20ss disse:

Outros exemplos que tem:
RecepcionarLoteRps.xml

RecepcionarLoteRpsSincrono.xml
GerarNfse.xml <GerarNfseEnvio xmlns = "http://www.betha.com.br/e-nota-contribuinte-ws">

 

Qual a diferença do Sincrono e do outro? Qual a melhor opção?

 

Sincrono será feita a requisição e o sistema irá esperar o retorno dessa requisição. Assíncrono é o contrário, a requisição é efetuada, o script não esperar o retorno e continua executando. Qual é melhor? Nenhum. Cada um tem seu propósito.

 

2 horas atrás, didio20ss disse:

E eu estava a usar o RecepcionarLoteRps.
Me passaram a informação que gerando e enviando o XML do lote RPS para o Webservice da Betha, 
o sistema deles gera a DANFE e até envia a NFSe para o e-mail do cliente se o mesmo for informado no XML
.

 

Então devo continuar a usar apenas o RecepecionarLoteRps ou também devo usar o GerarNfse?

 

Não sei, isso foge da área de programação e entra na área de negócio da empresa Betha. Entre em contato com eles e verifique o que for melhor.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Agradeço a ajuda do Gabriel Heming e outras fontes sobre o assunto.

Para quem precisar assinar e enviar lote RPS para a Betha emitindo assim a NFSe seguem algumas dicas que me ajudaram a resolver o problema:

 

1º - Ao gerar o XML da RPS, deve-se assinar primeiro a RPS e depois o Lote.
2º - para assinar o XML converte-se o arquivo .pfx do certificado para .pem para assim poder trabalhar com assinatura no servidor PHP

Para a conversão basta procurar na internet por "convert pfx to pem" e terá como exemplo https://www.sslshopper.com/ssl-converter.html 

O meu certificado baixei da Betha e ao converter o arquivo continua contendo tanto a chave privada quanto a publica.
Por isso, após a conversão para "pem" deve-se abrir o arquivo com Bloco de Notas, Notepad++ ou outro, 
Verá vários blocos de código. O primeiro é a chave primaria. Deve-se copiar o segundo bloco que é a chave publica e salvar em um novo arquivo chavepublica.pem 
Irá precisar dos dois arquivos .pem para a assinatura, o completo e o com apenas a chave pública.

 

Biblioteca para assinar o XML https://github.com/robrichards/xmlseclibs 

Vídeo bem útil do Bill Barsch da Geranet https://www.youtube.com/watch?v=v1rByVX1_FY

Usei apenas a parte para assinar o documento.

 

* Importante: Usar o "force_uri". Não sei se porque usei o certificado da Betha no meu caso o atributo URI não apareceu no XML como no exemplo do vídeo, mas teve efeito na assinatura. Sem essa opção ela não é válida.

 

3º - Para o envio usei o cURL adicionando o cabeçalho SOAP por ele.
Segundo algumas fontes, usando o somente o SOAP pode ocorre de não trazer retorno em caso de erros e ai você não sabe o que fazer. Já com o cURL você recebe sempre as mensagens. Quanto usei só o SOAP tinha erro mas a página ficava em branco, de mogo que eu não sabia o que estava acontecendo.


Agradeço ao POST do Luiz Paulo Franz aqui do fórum sobre o envio por cURL.

 

* Tive que fazer algumas modificações no código dele pois tava dando erro de assinatura inválida.

Tirei toda a parte do código dele que fazia alterações no XML, onde ele usava str_replace
Motivo: após você assinar um documento, ele não deve ser alterado, pois assim a assinatura se tornaria inválida.

 

Observações finais:

Fazer os testes no ambiente de homologação.

cuidar de acentos ou caracteres especiais no XML.
Também é bom remover os espaços em branco e quebras de linha antes de se assinar o documento.

Nunca repetir o número do lote e usar em sequência.

 

Espero que estas informações possam ajudar a outros.

 

Um forte abraço a todos
Giovani Silva
Virthuz Anunciante Virtual

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa tarde Josemir Costa,  você conseguiu resolver sua questão? 
Chegou a olhar os links que mencionei? 

Biblioteca para assinar o XML https://github.com/robrichards/xmlseclibs 

Vídeo bem útil do Bill Barsch da Geranet https://www.youtube.com/watch?v=v1rByVX1_FY 

 

Para assinar individual, colocamos a primeira parte do XML em uma string e então chamamos a função de assinar enviando o código. Após pegamos o retorno e concatenamos com o restante do XML de deveria estar antes e após a primeira string já assinada. Daí chamamos novamente a função de assinar passando a segunda string (XML completo) a ser assinada.

 

Não sei se ficou claro.

 

O único cuidado que tem que ter é não modificar nada no primeiro bloco após assinado, pois remover espaços após a assinatura por exemplo, a invalidaria.

 

Att.

Giovani Silva
Virthuz Anunciante Virtual

Compartilhar este post


Link para o post
Compartilhar em outros sites
4 minutos atrás, Giovani Silva disse:

Boa tarde Josemir Costa,  você conseguiu resolver sua questão? 
Chegou a olhar os links que mencionei? 

Biblioteca para assinar o XML https://github.com/robrichards/xmlseclibs 

Vídeo bem útil do Bill Barsch da Geranet https://www.youtube.com/watch?v=v1rByVX1_FY 

 

Para assinar individual, colocamos a primeira parte do XML em uma string e então chamamos a função de assinar enviando o código. Após pegamos o retorno e concatenamos com o restante do XML de deveria estar antes e após a primeira string já assinada. Daí chamamos novamente a função de assinar passando a segunda string (XML completo) a ser assinada.

 

Não sei se ficou claro.

 

O único cuidado que tem que ter é não modificar nada no primeiro bloco após assinado, pois remover espaços após a assinatura por exemplo, a invalidaria.

 

Att.

Giovani Silva
Virthuz Anunciante Virtual

Então! A questão é que quando assino o xml usando a biblioteca ele só assina a primeira tag, como faço p assinar a tag correta? tipo assinar a tag <rps> depois a tag <LoteRps> que são as que devem conter os ids e serem assinadas. Deu pra entender?

Compartilhar este post


Link para o post
Compartilhar em outros sites

$rps="<Rps><InfRps Id="rps1"> ... </InfRps></Rps";

$RpsAssinado=assinaRps($rps,$chave_publica);

 

$Lote='<e:EnviarLoteRpsEnvio xmlns:e="http://www.betha.com.br/e-nota-contribuinte-ws"><LoteRps Id="LOTE1'"><NumeroLote>1</NumeroLote><Cnpj>xxxxxxx</Cnpj><InscricaoMunicipal>xxxx</InscricaoMunicipal><QuantidadeRps>1</QuantidadeRps><ListaRps>'.$RpsAssinado.'</ListaRps></LoteRps></e:EnviarLoteRpsEnvio>';

$LoteAssinado=assinaRps($Lote , $chave_publica);

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mais um detalhe Josemir, na função assinaRps não sei se você estava enviando um arquivo com o XML.
Caso era um arquivo, na função teria a opção $doc -> load($arquivo)

Nessa caso tem que substituir por 
$doc -> loadXML($arquivo) 

para funcionar com a string 
$rps="<Rps><InfRps Id="rps1"> ... </InfRps></Rps";

Compartilhar este post


Link para o post
Compartilhar em outros sites

Veja meu xml:

<Rps>
 <InfDeclaracaoPrestacaoServico>
  <Rps Id="1">
   <IdentificacaoRps>
    <Numero>254122</Numero>
    <Serie>serie</Serie>
    <Tipo>1</Tipo>
   </IdentificacaoRps>
   <DataEmissao>2018-04-10</DataEmissao>
   <Status>1</Status>
  </Rps>
  <Competencia>2018-04-10</Competencia>
  <Servico>
   <Valores>
    <ValorServicos>400.00</ValorServicos>
    <ValorIss>8.00</ValorIss>
    <Aliquota>0.0200</Aliquota>
   </Valores>
   <IssRetido>1</IssRetido>
   <ItemListaServico>1401</ItemListaServico>
   <Discriminacao>Descriminação do serviço</Discriminacao>
   <CodigoMunicipio>3100401</CodigoMunicipio>
   <ExigibilidadeISS>3</ExigibilidadeISS>
  </Servico>
  <Prestador>
   <CpfCnpj>
    <Cnpj>01139388000179</Cnpj>
   </CpfCnpj>
   <InscricaoMunicipal>1234</InscricaoMunicipal>
  </Prestador>
  <Tomador>
   <IdentificacaoTomador>
    <CpfCnpj>
     <Cnpj>12345678912345</Cnpj>
    </CpfCnpj>
    <InscricaoMunicipal>1234</InscricaoMunicipal>
   </IdentificacaoTomador>
   <RazaoSocial>TOMADOR</RazaoSocial>
   <Endereco>
    <Endereco>teste</Endereco>
    <Numero>123</Numero>
    <Bairro>teste</Bairro>
    <CodigoMunicipio>1234</CodigoMunicipio>
    <Uf>SE</Uf>
    <Cep>35438000</Cep>
   </Endereco>
   <Contato>
    <Telefone>32554411</Telefone>
    <Email>teste@dominiodoemail.com</Email>
   </Contato>
  </Tomador>
  <RegimeEspecialTributacao>1</RegimeEspecialTributacao>
  <OptanteSimplesNacional>2</OptanteSimplesNacional>
  <IncentivoFiscal>2</IncentivoFiscal>
 </InfDeclaracaoPrestacaoServico>
</Rps>';

quando eu coloco a opção do force_uri não aparece na assinatura, na verdade aparece um código aleatório, quando coloco o id na tag pai <rps> aí sim aparece mas na estrutura correta o id aparece na tag rps filho. Não consegui chegar a uma solução ainda. 

 

Muito obrigado pela atenção e pasciência!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa noite, em nossos testes não lembro se tentamos colocar um ID na tag Rps e sim na InfRps.

Conforme havia comentado na solução aqui neste post, é necessário deixar o force_uri como true mesmo que aparentemente não apareça na estrutura do seu xml ou que fique em branco. Funciona dessa maneira mesmo. Agora se desativar o force_uri da erro na assinatura.

 

Então mesmo que não apareça o uri na assinatura de seu xml, ele fez alguma coisa nela tornando-a válida.

Compartilhar este post


Link para o post
Compartilhar em outros sites

  • Conteúdo Similar

    • Por violin101
      Caros amigos, saudações.
       
      Por favor, me permita tirar uma dúvida com os amigos.

      Tenho um Formulário onde o Usuário digita todos os Dados necessários.

      Minha dúvida:
      --> como faço após o usuário digitar os dados e salvar, o Sistema chamar uma Modal ou mensagem perguntando se deseja imprimir agora ?

      Grato,
       
      Cesar
    • Por Carcleo
      Tenho uma abela de usuarios e uma tabela de administradores e clientes.
      Gostaria de uma ajuda para implementar um cadastro
       
      users -> name, login, passord (pronta) admins -> user_id, registratiom, etc.. client -> user_id, registratiom, etc...
      Queria ajuda para extender de user as classes Admin e Client
      Olhem como estáAdmin
      <?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Admin extends User {     use HasFactory;            protected $fillable = [         'name',         'email',         'password',         'registration'     ];      private string $registration;     public function create(         string $name,          string $email,          string $password,         string $registration     )     {         //parent::create(['name'=>$name, 'email'=>$email, 'password'=>$password]);         parent::$name = $name;         parent::$email = $email;         parent::$password = $password;         $this->registration = $registration;     } } User
      <?php namespace App\Models; // use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Database\Eloquent\Relations\BelongsToMany; class User extends Authenticatable {     /** @use HasFactory<\Database\Factories\UserFactory> */     use HasFactory, Notifiable;     static string $name;     static string $email;     static string $password;     /**      * The attributes that are mass assignable.      *      * @var list<string>      */     protected $fillable = [         'name',         'email',         'password',     ];          /**      * The attributes that should be hidden for serialization.      *      * @var list<string>      */     protected $hidden = [         'remember_token',     ];     /**      * Get the attributes that should be cast.      *      * @return array<string, string>      */     protected function casts(): array     {         return [             'email_verified_at' => 'datetime',             'password' => 'hashed',         ];     }          public function roles() : BelongsToMany {         return $this->belongsToMany(Role::class);     }       public function hasHole(Array $roleName): bool     {                 foreach ($this->roles as $role) {             if ($role->name === $roleName) {                 return true;             }         }         return false;     }         public function hasHoles(Array $rolesName): bool     {                 foreach ($this->roles as $role) {             foreach ($rolesName as $rolee) {             if ($role->name === $rolee) {                 return true;             }          }         }         return false;     }         public function hasAbility(string $ability): bool     {         foreach ($this->roles as $role) {             if ($role->abilities->contains('name', $ability)) {                 return true;             }         }         return false;     }     } Como gravar um Admin na tabela admins sendo que ele é um User por extensão?
      Tentei assim mas é claro que está errado...
      public function store(Request $request, Admin $adminModel) {         $dados = $request->validate([             "name" => "required",             "email" => "required|email",             "password" => "required",             "registration" => "required"         ]);         $dados["password"] =  Hash::make($dados["password"]);                  $admin = Admin::where("registration",  $dados["registration"])->first();                  if ($admin)              return                    redirect()->route("admin.new")                             ->withErrors([                                 'fail' => 'Administrador já cadastrados<br>, favor verificar!'                   ]);                            $newAdmin = $adminModel->create(                                    $dados['name'],                                    $dados['email'],                                    $dados['password'],                                    $dados['registration']                                 );         dd($newAdmin);         $adminModel->save();         //$adminModel::create($admin);                  return redirect()->route("admin.new")->with("success",'Cadastrado com sucesso');     }  
    • Por violin101
      Caros amigos, saudações.
       
      Gostaria de tirar uma dúvida com os amigos, referente a PDV.
       
      Estou escrevendo um Sistema com Ponto de Vendas, a minha dúvida é o seguinte, referente ao procedimento mais correto.

      Conforme o caixa vai efetuando a venda, o Sistema de PDV já realiza:
      a baixa direto dos produtos no estoque
      ou
      somente após concretizar a venda o sistema baixa os produtos do estoque ?
       
      Grato,
       
      Cesar
       
    • Por violin101
      Caros amigos do grupo, saudações e um feliz 2025.
       
      Estou com uma pequena dúvida referente a Teclas de Atalho.

      Quando o Caps Lock está ativado o Comando da Tecla de Atalho não funciona.
      ou seja:
      se estiver para letra minúscula ====> funciona
      se estiver para letra maiúscula ====> não funciona
       
      Como consigo evitar essa falha, tanto para Letra Maiúscula quanto Minúscula ?

      o Código está assim:
      document.addEventListener( 'keydown', evt => { if (!evt.ctrlKey || evt.key !== 'r' ) return;// Não é Ctrl+r, portanto interrompemos o script evt.preventDefault(); });  
      Grato,
       
      Cesar
    • Por violin101
      Caros amigos, saudações.
       
      Por favor, poderiam me ajudar.

      Estou com a seguinte dúvida:
      --> como faço para para implementar o input código do produto, para quando o usuário digitar o ID o sistema espera de 1s a 2s, sem ter que pressionar a tecla ENTER.

      exemplo:
      código   ----   descrição
           1       -----   produto_A
       
      Grato,
       
      Cesar
×

Informação importante

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