Crie o model Emitente
para criar o model emitente use o comando: php artisan make:model Emitente -m
adicione os seguintes campos:
Schema::create('emitentes', function (Blueprint $table) {
$table->id();
$table->string('razao_social', 100)->nullable();
$table->string('nome_fantasia', 80)->nullable();
$table->string('cnpj', 19)->nullable();
$table->string('ie', 20)->nullable();
$table->string('isento', 20)->nullable();
$table->string('iest', 20)->nullable();
$table->string('im', 20)->nullable();
$table->string('cep', 10)->nullable();
$table->string('logradouro', 80)->nullable();
$table->string('numero', 10)->nullable();
$table->string('bairro', 50)->nullable();
$table->string('complemento', 80)->nullable();
$table->char('uf', 2)->nullable();
$table->string('cidade', 30)->nullable();
$table->string('fone', 20)->nullable();
$table->string('ibge', 20)->nullable();
$table->string('email', 90)->nullable();
$table->string('pais', 20)->nullable();
$table->integer('codPais')->nullable();
$table->integer('crt')->nullable();
$table->string('cnae', 7)->nullable();
$table->decimal('pCredSN',10,2)->nullable();
$table->string('indIntermed',1)->nullable();
$table->string('cnpjIntermed',15)->nullable();
$table->string('idCadIntTran',80)->nullable();
$table->text('infAdFisco')->nullable();
$table->text('infCpl')->nullable();
//NFE
$table->integer('ambiente_nfe')->default(2);
$table->integer('numero_serie_nfe')->nullable();
$table->integer('ultimo_numero_nfe')->nullable();
//NFCE
$table->integer('ambiente_nfce')->default(2);
$table->integer('numero_serie_nfce')->nullable();
$table->integer('ultimo_numero_nfce')->nullable();
$table->string('csc', 60)->nullable();
$table->string('csc_id', 10)->nullable();
//Responsável tecnico
$table->string('resp_CNPJ',50)->nullable();
$table->string('resp_xContato',50)->nullable();
$table->string('resp_email',50)->nullable();
$table->string('resp_fone',50)->nullable();
$table->string('resp_CSRT',50)->nullable();
$table->string('resp_idCSRT',50)->nullable();
$table->string('nome_contador', 90)->nullable();
$table->string('email_contador', 90)->nullable();
$table->timestamps();
});
Configure os fillables do Model Emitente
protected $fillable =[
'cliente_consumidor',
'razao_social',
'nome_fantasia',
'loja_conta_corrente_id',
'pdv_conta_corrente_id',
'loja_classificacao_financeira_id',
'pdv_classificacao_financeira_id',
'cnpj',
'ie',
'iest',
'im',
'cep',
'logradouro',
'numero',
'bairro',
'complemento',
'uf',
'email',
'cidade',
'fone',
'ibge',
'cnae',
'pais',
'codPais',
'crt',
'cst_csosn_padrao',
'cst_cofins_padrao',
'cst_pis_padrao',
'cst_ipi_padrao',
'frete_padrao',
'tipo_pagamento_padrao',
'nat_op_padrao',
'ambiente',
'numero_serie_nfe',
'numero_serie_nfce',
'ultimo_numero_nfe',
'ultimo_numero_nfce',
'ultimo_numero_cte',
'ultimo_numero_mdfe',
'certificado_nome_arquivo',
'certificado_arquivo_binario',
'certificado_senha',
'csc',
'csc_id',
'resp_CNPJ',
'resp_xContato',
'resp_email',
'resp_fone',
'resp_CSRT',
'resp_idCSRT',
'gerar_nfce',
'transmitir_nfce',
'imprimir_nfce',
'infAdFisco',
'infCpl'
];
Crie a seed Emitente
para criar a seed Emitente use o comando: php artisan make:seed EmitenteSeeder
Emitente::create([
'razao_social' => 'Intelimax Comércio Ltda',
'nome_fantasia' => 'mjailton Cursos',
'cnpj' => '11111111111111',
'ie' => '123499364',
'crt' => '3',
'fone' => '999999999',
'email' => 'email@gmail.com',
'cep' => '650000000',
'logradouro' => 'Rua Dezesseis',
'numero' => '01',
'uf' => 'MA',
'cidade' => 'São Luís',
'bairro' => 'Cidade Operária',
'ibge' => '2111300',
'pais' => 'Brasil',
'codPais' => '1058',
'ambiente_nfe' => '2',
'numero_serie_nfe' => '1',
'numero_serie_nfce' => '1',
'ultimo_numero_nfe' => '12',
'ultimo_numero_nfce' => '1',
'csc' => '1',
'csc_id' => '1'
]);
Crie um emitente para poder emitir suas notas
Emitente::create([
'razao_social' => 'Intelimax Comércio Ltda',
'nome_fantasia' => 'mjailton Cursos',
'cnpj' => '11111111111111',
'ie' => '123499364',
'crt' => '3',
'fone' => '999999999',
'email' => 'email@gmail.com',
'cep' => '650000000',
'logradouro' => 'Rua Dezesseis',
'numero' => '01',
'uf' => 'MA',
'cidade' => 'São Luís',
'bairro' => 'Cidade Operária',
'ibge' => '2111300',
'pais' => 'Brasil',
'codPais' => '1058',
'ambiente_nfe' => '2',
'numero_serie_nfe' => '1',
'numero_serie_nfce' => '1',
'ultimo_numero_nfe' => '12',
'ultimo_numero_nfce' => '1',
'csc' => '1',
'csc_id' => '1'
]);
Crie um controller de recursos chamado Emitente, para que o projeto fique mais organizado salve o controller numa pasta chamada NotaFiscal
Crie a view para a listagem de emitente
Dentro da pasta resources/view crie uma pasta chamada de NotaFiscal e dentro de Cadastro crie uma outra chamada de Emitente e dentro da pasta Emitente crie um arquivo chamado Index.blade.php
Copie o conteúdo do arquivo lst_emitente para o arquivo Cadastro/Emitente/Index.blade.php, não esqueça envolvê-lo pelos comandos:
@extends('template')
@section('conteudo')
//aqui fica o conteúdo do arquivo
@endsection
Na view Index, faça os seguintes procedimentos:
- Faça o loop para receber os dados do banco e listar na tabela
- Configure o link para fazer a edição de um registro
- Configure o link para fazer a exclusão de um registro
@foreach ($lista as $l)
<tr>
<td align="center">{{ $l->id }}</td>
<td align="left">{{ $l->nome_razao_social }}</td>
<td align="left">{{ $l->cpf_cnpj }}</td>
<td align="center">{{ $l->email }}</td>
<td align="center">{{ $l->celular }}</td>
<td align="center">
<a href="{{ route('cliente.edit', $l->id) }}"
class="btn d-inline-block btn-outline-roxo"><i class="fas fa-edit"></i>
Editar</a>
<a href="javascript:;"
onclick="confirm('Tem Certeza?') ? document.getElementById('apagar{{ $l->id }}').submit() : '';"
class="btn d-inline-block btn-outline-vermelho ml-1"><i
class="fas fa-trash-alt"></i> Excluir
<form action="{{ route('cliente.destroy', $l->id) }}" method="POST"
id="apagar{{ $l->id }}">
@method('delete')
@csrf
</form>
</a>
</td>
</tr>
@endforeach
Para fazer o cadastro de emitente crie uma view chamada Create na pasta NotaFiscal/Emitente
Copie o conteúdo do arquivo frm_emitente para o arquivo NotaFiscal/Emitente/Create.blade.php, não esqueça envolvê-lo pelos comandos:
@extends('template')
@section('conteudo')
//aqui fica o conteúdo do arquivo
@endsection
configure os input atribuindo a eles na propriedade name o nome igual ao que foi definido na criação da tabela,
também observe os tipos de dados específicos e os que são obrigatórios atribua a propriedade required
<div class="col-6 mb-3">
<label class="text-label">Razão Social</label>
<input type="text" name="razao_social" maxlength="60" id="razao_social"
value="{{ isset($emitente->razao_social) ? $emitente->razao_social : old('razao_social') }}"
class="form-campo">
</div>
Após fazer a busca pelo cep é preciso configurar os inputs que receberão os dados da busca, para isso faça o seguinte:
- no logradouro, coloque a classe rua
- no UF, coloque a classe estado
- no Bairro, coloque a classe bairro
- no Cidade, coloque a classe cidade
- no IBGE, coloque a classe ibge (esse campo é importante para emissão da nfe)
<div class="col-2 mb-3">
<label class="text-label">Cep</label>
<input type="text" name="cep" id="cep"
value="{{ isset($emitente->cep) ? $emitente->cep : old('cep') }}"
class="form-campo busca_cep">
</div>
<div class="col-4 mb-3">
<label class="text-label">Logradouro</label>
<input type="text" name="logradouro" maxlength="60" id="logradouro"
value="{{ isset($emitente->logradouro) ? $emitente->logradouro : old('logradouro') }}"
class="form-campo rua">
</div>
<div class="col-2 mb-4">
<label class="text-label">Numero</label>
<input type="text" name="numero" id="numero"
value="{{ isset($emitente->numero) ? $emitente->numero : old('numero') }}"
class="form-campo">
</div>
<div class="col-4 mb-3">
<label class="text-label">Bairro</label>
<input type="text" name="bairro" id="bairro" maxlength="60"
value="{{ isset($emitente->bairro) ? $emitente->bairro : old('bairro') }}"
class="form-campo bairro">
</div>
<div class="col-4 mb-3">
<label class="text-label">Complemento</label>
<input type="text" name="complemento" maxlength="60"
value="{{ isset($emitente->complemento) ? $emitente->complemento : old('complemento') }}"
class="form-campo">
</div>
<div class="col-2 mb-2">
<label class="text-label">UF</label>
<input type="text" name="uf" id="uf"
value="{{ isset($emitente->uf) ? $emitente->uf : old('uf') }}"
class="form-campo estado">
</div>
<div class="col-4 mb-3">
<label class="text-label">Cidade</label>
<input type="text" name="cidade" maxlength="60" id="cidade"
value="{{ isset($emitente->cidade) ? $emitente->cidade : old('cidade') }}"
class="form-campo cidade">
</div>
<div class="col-2 mb-3">
<label class="text-label">Ibge</label>
<input type="text" name="ibge" id="ibge"
value="{{ isset($emitente->ibge) ? $emitente->ibge : old('ibge') }}"
class="form-campo ibge ">
</div>
Para facilitar os cadastros de Emitente, vamos criar uma função que busque os dados de empresa pelo cnpj
no arquivo javascript, crie uma função chamada pesquisarCnpj, a qual deverá receber o cnpj retorne os dados do emitente, a função deverá chamar a rota util/buscarcnpj/cnpj e como retorno deverá preencher os inputs com os dados da empresa
function pesquisarCnpj() {
var cnpj = tira_mascara($("#codigocnpj").val());
if (cnpj == "") {
return false;
}
$.ajax({
url: base_url + "util/buscarcnpj/" + cnpj,
type: "GET",
dataType: "json",
data: {},
success: function(data) {
if (data.tem_erro == true) {
fecharGiraGira();
$("#erroModalLivre").html(data.erro);
abrirModalLivre("#modalLivreErro");
} else {
fecharModal();
preencher(data.retorno);
fecharGiraGira();
}
},
beforeSend: function() {
giraGira();
}
});
}
function preencher(data) {
$("#razao_social").val(data.razao_social);
$("#nome_fantasia").val(data.nome_fantasia);
$("#numero").val(data.numero);
$("#bairro").val(data.bairro);
$("#complemento").val(data.complemento);
$("#cnpj").val(data.cnpj);
$("#cep").val(data.cep);
$("#logradouro").val(data.logradouro);
$("#cidade").val(data.cidade);
$("#bairro").val(data.bairro);
$("#uf").val(data.uf);
$("#ibge").val(data.ibge);
$("#telefone").val(data.telefone);
$("#email").val(data.email);
$("#ultima_atualizacao").val(data.ultima_atualizacao);
$("#data_criacao").val(data.abertura)
}
Caso ainda não tenha criado, crie um controller chamado UtilController
para criar o controller UtilController use o comando: php artisan make:controller UtilController
Dentro do controller UtilController crie um método chamado buscarCNPJ, o qual deverá:
- Receber como parâmetro um CNPJ
- Chamar o método estático buscarCNPJ, o qual deverá fazer a consulta e retornar resultado
- retornar o resultado em forma de json
public function buscarCNPJ($cnpj){
$retorno =new stdClass;
try {
$empresa = UtilService::buscarCNPJ($cnpj);
$retorno->tem_erro = false;
$retorno->retorno = $empresa;
return response()->json($retorno);
} catch (\Throwable $th) {
$retorno->tem_erro =true;
$retorno->erro = $th->getMessage();
return response()->json($retorno);
}
}
Na classe UtilService crie um método chamado buscarCNPJ que faça o seguinte:
- receba o cnpj como parâmetro
- Consuma o endpoint http://receitaws.com.br/v1/cnpj/
- receba os dados enviados, organize os dados referentes à empresa e devolva o resultado
public static function buscarCNPJ($cnpj){
$retorno = enviarGetCurl("http://receitaws.com.br/v1/cnpj/".$cnpj);
$achou = $retorno->cnpj ?? null;
if(!$achou){
throw new \Exception("CNPJ Não encontado");
}
$empresa = new \stdClass();
$empresa->razao_social = $retorno->nome;
$empresa->nome_fantasia = $retorno->fantasia;
$empresa->numero = $retorno->numero;
$empresa->bairro = $retorno->bairro;
$empresa->complemento = $retorno->complemento;
$empresa->cnpj = $retorno->cnpj;
$empresa->cep = tira_mascara($retorno->cep);
$empresa->telefone = $retorno->telefone;
$empresa->email = $retorno->email;
$empresa->abertura = dataen($retorno->abertura);
$empresa->ultima_atualizacao = dataNfe($retorno->ultima_atualizacao) . " " . horaNfe($retorno->ultima_atualizacao) ;
$endereco = enviarGetCurl("https://viacep.com.br/ws/" . $empresa->cep . "/json/");
if($endereco){
$empresa->logradouro= $endereco->logradouro;
$empresa->cidade = $endereco->localidade;
$empresa->bairro = $endereco->bairro;
$empresa->uf = $endereco->uf;
$empresa->ibge = $endereco->ibge;
$empresa->ddd = $endereco->ddd;
}
return $empresa;
}
implemente o método store para receber e salvar os dados do formulário no Banco de dados
Implemente o método store de forma que o mesmo receba os dados do formulário e salve no banco de dados, caso ache necessário use um bloco try/catch e retire as máscaras necessárias
public function store(Request $request)
{
$req = $request->except(["_token","_method","arquivo"]);
try {
$req["pCredSN"] = ($req["pCredSN"]!=null) ? getFloat($req["pCredSN"]) : $req["pCredSN"];
$req["cnpj"] = tira_mascara($req["cnpj"]);
$req["cep"] = tira_mascara($req["cep"]);
$req["fone"] = tira_mascara($req["fone"]);
Emitente::Create($req);
return redirect()->route("emitente.index")->with("msg_sucesso","Registro alterado com sucesso");
} catch (\Throwable $th) {
return redirect()->back()->with("msg_erro", "Erro: " . $th->getMessage());
}
}
Uma boa prática de programação é validar os dados antes de enviá-los para o banco de dados e uma bom recurso que o laravel oferece são os requests.
implemente um request de forma que faça todas as validações necessárias para salvar a informações no banco
No arquivo de request configure as validações necessárias e não esqueça de setar o método authorize para true;
public function rules()
{
$regras = [
'razao_social' => 'required',
'cnpj' => 'required',
'logradouro' => 'required',
'numero' => 'required',
'bairro' => 'required',
'cep' => 'required',
'cidade' => 'required',
'uf' => 'required',
'ibge' => 'required',
'fone' => 'max:14'
];
return $regras;
}
Teste o sistema fazendo cadastros
Configure o método edit do Controller, com as seguinte ações:
- Busque o emitente pelo id passado no parâmetro e guarde a informação em um array $dados
- no array dados sete a variável emitenteJs para true
- chame a view Emitente/Edit passando o array $dados
$dados["emitente"] = Emitente::find($id);
$dados["emitenteJs"] = true;
return view('NotaFiscal.Emitente.Create', $dados);
Configure o elemento form da view Create, com as seguintes ações:
- o sistema deve verificar se o objeto emitente existe,
- caso ele exista, no formulário deve ser configurada a rota emitente.update
- caso não exista, no formulário deve ser configurada a rota emitente.store
@if (isset($emitente))
<form action="{{ route('emitente.update', $emitente->id) }}" method="POST" enctype="multipart/form-data">
<input name="_method" type="hidden" value="PUT" />
@else
<form action="{{ route('emitente.store') }}" method="Post" enctype="multipart/form-data">
@endif
@csrf
Implemente o método update de forma que o mesmo receba os dados do formulário e salve no banco de dados, caso ache necessário use um bloco try/catch
try {
$req = $request->except(["_token","_method","arquivo"]);
$req["pCredSN"] = ($req["pCredSN"]!=null) ? getFloat($req["pCredSN"]) : $req["pCredSN"];
$req["cnpj"] = tira_mascara($req["cnpj"]);
$req["cep"] = tira_mascara($req["cep"]);
$req["fone"] = tira_mascara($req["fone"]);
Emitente::where("id", $id)->update($req);
return redirect()->route("emitente.index")->with("msg_sucesso","Registro alterado com sucesso");
} catch (\Throwable $th) {
return redirect()->back()->with("msg_erro", "Erro: " . $th->getMessage());
}
Faça o teste do seu sistema de forma que o mesmo consiga criar um novo registro e também alterá-lo
implemente o método destroy do Controller, com as seguinte ações:
- Busque o produto pelo id passado no parâmetro
- Caso encontre, exclua a mesma do banco, coloque esta instrução em um bloco try/catch
- Verifique se o campo imagem está preenchido e se tiver, verifique se a imagem existe e caso exista exclua-a
- redirecione para a rota index
public function destroy(string $id)
{
try{
$emitente = Emitente::find($id);
if($emitente){
$emitente->delete();
}
return redirect()->back()->with('msg_sucesso', "Ítem apagado com sucesso.");
}catch (\Exception $e){
$cod = $e->getCode();
return redirect()->back()->with('msg_erro', "Houve um problema ao apagar [$cod]");
}
}
Teste o seu sistema, para que você tenha certeza que está tudo o ok, o sistema deverá:
- Listar todos os cliente
- Criar um cliente novo
- Editar um cliente selecionado
- Excluir um cliente selecionado