Crie o model Entrada
para criar o model Entrada use o comando: php artisan make:model Entrada -m
adicione os seguintes campos:
- produto_id (relacionado com a tabela produto)
- qtde_entrada decimal
- valor_entrada decimal
- subtotal_entrada decimal
- data_entrada data
- observacao text (opcional)
Schema::create('entradas', function (Blueprint $table) {
$table->id();
$table->BigInteger("produto_id")->unsigned();
$table->foreign("produto_id")->references("id")->on("produtos");
$table->decimal("qtde_entrada",10,2)->default(1);
$table->decimal("valor_entrada")->default(0);
$table->decimal("subtotal_entrada",10,2);
$table->date("data_entrada");
$table->string("observacao")->nullable();
$table->timestamps();
});
Crie um controller chamado Entrada, para que o projeto fique mais organizado salve o controller numa pasta chamada Estoque
No controller ProdutoController crie o método index, o qual deverá:
- pegar a lista de entradas e colocar um array
- chamar a view Entrada/Index com o array criado com a lista de entradas
public function index(){
$dados["lista"] = Entrada::get();
$dados["entradaJs"] = true;
return view("Estoque.Entrada.Create", $dados);
}
Crie uma rota get chamando o método index do controller EntradaController
Route::get("/entrada", [EntradaController::class,"index"])->name("entrada.index");
Crie a view para a listagem de entrada
Dentro da pasta resources/view crie uma pasta chamada de Estoque e dentro de Estoque crie uma outra chamada de Entrada e dentro da pasta Entrada crie um arquivo chamado Create.blade.php
Copie o conteúdo do arquivo lst_entrada para o arquivo Estoque/Entrada/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
@foreach ($lista as $l)
<tr>
<td align="center">{{ $l->id }}</td>
<td align="center">{{ databr($l->data_entrada) }}</td>
<td align="left">{{ $l->produto->nome }}</td>
<td align="center">{{ $l->qtde_entrada }}</td>
<td align="center">{{ $l->valor_entrada }}</td>
<td align="center">{{ $l->subtotal_entrada }}</td>
</tr>
@endforeach
Configure os elementos inputs da view Index para inserção das entradas, com as seguintes ações:
- Para o input valor sete o id para preco e insira a classe mascara-float
- Para o input qtde sete o id para qtde e insira a classe mascara-float
- crie um input hidden com o id ="produto_id"
- no link chame o método inserirEntradaEstoque para o evento onclick
<div class="border p-3 radius-4 pb-4 caixafield">
<div class="rows center-middle">
<div class="col-6 position-relative">
<label class="text-label">Produto</label>
<div class="grupo-form-btn">
<input type="text" name="produtoentrada" id="produtoentrada" class="form-campo">
<a href="{{ route('produto.create') }}" class="border radius-50 p-1 fas fa-plus"
title="Inserir novo Produto"></a>
</div>
</div>
<div class="col-2">
<label class="text-label">Valor</label>
<input type="text" id="preco" name="preco" value=""
class="form-campo mascara-float">
</div>
<div class="col-2">
<label class="text-label">Qtde</label>
<input type="text" name="qtde" id="qtde" value=""
class="form-campo mascara-float">
</div>
<div class="col-2 mt-4">
<input type="hidden" id="produto_id" name="produto_id">
<a href="javascript:;" onclick="inserirEntradaEstoque()" class="btn btn-roxo width-100">
Inserir</a>
</div>
</div>
</div>
Vamos criar uma função para buscar os produtos via jquery
Crie um arquivo javascript chamado js_entrada.js dentro da public/assets/js
Crie um método chamado produtoentrada, o que deverá ser disparado no evento keyup, este método deverá fazer uma consulta no banco via jquery, passando como parâmetro o texto a ser pesquisado e deverá a lista de produtos que contenha o respectivo texto, em seguida deverá mostrar essa lista em uma div abaixo do componente no qual foi digitado o texto.
Ao clicar em um dos itens da lista deverá popular os componentes qtde, preco e produto_id com os respectivos valor e fechar a lista, levando o foco para a qtde.
$(function(){
$("#produtoentrada").on("keyup", function(){
var q = $(this).val();
if(q==""){
$(".listaProdutos").hide();
return false;
}
$.ajax({
url:base_url+"produto/pesquisa",
type:"GET",
dataType:"JSON",
data:{q:q},
success:function(data){
console.log(data);
$("#produtoentrada").after('<div class="listaProdutos"></div>');
html="";
for(var i in data){
html +='<div class="si"><a href="javascript:;" onclick="selecionarProdutoEntrada(this)" ' +
'data-id="'+data[i].id +
'" data-preco = "' + data[i].preco_venda +
'" data-nome = "' + data[i].nome +
'" data-estoque = "' + data[i].estoque_atual + '">' +
data[i].id + " - " + data[i].nome + " - RS " + data[i].preco_venda + '</a></div>';
}
$(".listaProdutos").html(html);
$(".listaProdutos").show();
},
error:function(data){
}
});
});
})
function selecionarProdutoEntrada(obj){
var id = $(obj).attr('data-id');
var nome = $(obj).attr('data-nome');
var preco = $(obj).attr('data-preco');
var estoque = $(obj).attr('data-estoque');
$(".listaProdutos").hide();
$("#produto_id").val(id);
$("#produtoentrada").val(nome);
$("#preco").val(preco);
$("#subtotal").val(preco);
$("#qtde").val(1);
$("#qtde").focus();
}
No controller ProdutoController crie um método chamado pesquisa, o qual deverá receber via get uma variável chamada q, e em seguida pesquisar a lista de produtos que contenha o valor da variável e retorne o resultado no formato json
public function pesquisa(){
$q = $_GET["q"];
$produtos = Produto::where("nome", "like","%$q%")->get();
return response()->json($produtos);
}
Vamos criar os métodos para fazer inserção da entrada de produto
No arquivo js_entrada.js crie um método chamado inserirEntradaEstoque, o que deverá invocar a rota entrada/salvarjs e enviar como parâmetros o produto_id, qtde, valor e caso não retorne nenhum erro dar um refresh na tela. Além disso, antes de invocar o método faça a validação se:
- O produto_id é diferente de vazio
- A qtde é diferente de vazio.
function inserirEntradaEstoque(){
var produto_id = $("#produto_id").val();
var qtde = $("#qtde").val();
var valor = $("#preco").val();
if(produto_id==""){
alert("Selecione um produto primeiramente");
$("#produtoentrada").focus();
return false;
}
if(qtde==""){
alert("Digite a quantidade");
$("#qtde").focus();
return false;
}
$.ajax({
url:base_url+"entrada/salvarJs",
type:"POST",
dataType:"JSON",
data:{
produto_id:produto_id,
qtde :qtde,
valor :valor
},
success:function(data){
fecharModal();
if(data.tem_erro==true){
$("#mostrarUmErro").html(MostrarUmaMsgErro("Erro: " + data.erro));
}else{
$("#mostrarSucesso").html(MostrarUmaMsgSucesso("inserido com sucesso"));
location.reload();
}
},
error:function(data){
}
});
}
Crie um método chamado salvarJs no controller EntradaController, este método deverá:
- Validar os campos qtde e valor para que fiquem no formato correto para inserçao de dados (decimal), use o método getFloat para isso
- fazer a multiplicação da qtde x valor e atribuir o resultado ao campo subtotal_entrada.
- inserir os dados no banco de dados e retornar se a operação foi ou não realizada com sucesso, retornando um json
public function salvarJs(Request $request) {
$retorno = new \stdClass();
try {
$obj = new \stdClass();
$obj->produto_id = $request->produto_id ;
$obj->qtde_entrada = getFloat($request->qtde) ;
$obj->valor_entrada = getFloat($request->valor);
$obj->subtotal_entrada = $obj->qtde_entrada * $obj->valor_entrada;
$obj->data_entrada = date("Y-m-d");
$entrada = Entrada::create(objToArray($obj));
$retorno->tem_erro = false;
return response()->json($retorno);
} catch (\Exception $e) {
$retorno->tem_erro = true;
$retorno->erro = $e->getMessage();
return response()->json($retorno);
}
}
Tente fazer uma entrada de produto, a essa altura já é pra dar tudo certo.
Prepare seu sistema para que permita que sejam feitos filtros por produto e intervalo de datas
No método index faça as seguintes implementações:
- Coloque um Request como parâmetro de recebimento do método
- Crie um objeto chamado filtro com os campos data1, data2 e produto_id
- No array $dados["lista"] chame o método filtro do model entrda e passe como parâmetro o objeto filtro criado
- No array $dados["produtos"] chame a lista de produtos para ser mostrado no combo de filtro
- para o array $dados liste as entradas
public function index(Request $request){
$filtro = new \stdClass();
$filtro->data1 = $request->data1 ?? hoje();
$filtro->data2 = $request->data2 ?? hoje();
$filtro->produto_id = $request->produto_id ?? null;
$dados["lista"] = Entrada::filtro($filtro);
$dados["produtos"] = Produto::get();
$dados["filtro"] = $filtro;
$dados["entradaJs"] = true;
return view("Estoque.Entrada.Create", $dados);
}
No model Entrada, crie um método chamado filtro que receba como parâmetro um objeto $filtro e um variável chamada $paginas inicializada com zero e implemente o método de forma que:
- Se houver o campo $filtro->produto_id, faça o filtro pelo produto_id
- se houver o campo $filtro->data1, faça o filtro pela data1
- se o parametro data2 for enviado faça uma busca no intervalo de data1 e data2
- se a variável páginas for maior que zero que o seja do tipo paginate(), senão que seja get()
public static function filtro($filtro, $paginas=0){
$retorno = self::query();
if($filtro->produto_id){
$retorno->where("produto_id", $filtro->produto_id);
}
if($filtro->data1){
if($filtro->data2){
$retorno->where("data_entrada",">=", $filtro->data1)->where("data_entrada","<=", $filtro->data2);
}else{
$retorno->where("data_entrada", $filtro->data1);
}
}
if($paginas>0){
$retorno = $retorno->paginate($paginas);
}else{
$retorno = $retorno->get();
}
return $retorno;
}
Na view index, no formulário do filtro implemente o seguinte:
- Preencha o elemento select do filtro com a lista de Produto e sete a propriedade name para produto_id
- Para o input de data1 atribua a propriedade name para data1 e no value faça a verificação se existe o objetivo $filtro->data1 se sim mostre.
- Para o input de data2 atribua a propriedade name para data1 e no value faça a verificação se existe o objetivo $filtro->data2 se sim mostre.
<div class="col-3">
<label class="text-label d-block text-branco">Data 1</label>
<input type="date" name="data1" value="{{ $filtro->data1 ?? null }}"
class="form-campo">
</div>
<div class="col-3">
<label class="text-label d-block text-branco">Data 2</label>
<input type="date" name="data2" value="{{ $filtro->data2 ?? null }}"
class="form-campo">
</div>
<div class="col-4">
<label class="text-label d-block text-branco">Selecionar Produto </label>
<select name="produto_id" class="form-campo">
<option value="">Selecione uma Produto</option>
@foreach ($produtos as $prod)
<option value="{{ $prod->id }}"
{{ ($filtro->produto_id ?? null) == $prod->id ? 'selected' : '' }}>
{{ $prod->nome }}</option>
@endforeach
</select>
</div>
Faça o teste com os filtros