Crie o model TipoMovimento
para criar o model TipoMovimento use o comando: php artisan make:model TipoMovimento -m
crie a seed TipoMovimento
para criar a seed TipoMovimento use o comando: php artisan make:seed TipoMovimentoSeeder
Crie o model Movimento
para criar o model Movimento use o comando: php artisan make:model Movimento -m
adicione os campos:
- tipo_movimento_id (relacionada com a tabela tipo_movimento)
- produto_id (relacionada com a tabela produto)
- entrada_avulsa_id (relacionada com a tabela entrada ) - opcional
- entrada_avulsa_id (relacionada com a tabela saisa) - opcional
- ent_sai varchar(1)
- estorno varchar(1)
- data_movimento data
- qtde_movimento decimal
- valor_movimento decimal
- subtotal_movimento
- descricao string varchar (150)
- decimal
Schema::create('movimentos', function (Blueprint $table) {
$table->id();
$table->BigInteger("tipo_movimento_id")->unsigned();
$table->foreign("tipo_movimento_id")->references("id")->on("tipo_movimentos");
$table->BigInteger("produto_id")->unsigned();
$table->foreign("produto_id")->references("id")->on("produtos");
$table->BigInteger("entrada_avulsa_id")->unsigned()->nullable();
$table->foreign("entrada_avulsa_id")->references("id")->on("entradas");
$table->BigInteger("saida_avulsa_id")->unsigned()->nullable();
$table->foreign("saida_avulsa_id")->references("id")->on("saidas");
$table->string("ent_sai",1);
$table->string("estorno",1)->default("N");
$table->date("data_movimento");
$table->decimal("qtde_movimento", 10,2);
$table->decimal("valor_movimento",10,2)->default(0);
$table->decimal("subtotal_movimento",10,2)->default(0);
$table->string("descricao");
$table->decimal("saldoestoque", 10,2);
$table->timestamps();
});
Configure os fillables do Model Movimento
protected $fillable = [
"id",
"status_id",
"estorno",
"tipo_movimento_id",
"produto_id",
"compra_id",
"venda_id",
"pedido_id",
"entrada_avulsa_id",
"saida_avulsa_id",
"ent_sai",
"data_movimento",
"qtde_movimento",
"valor_movimento",
"subtotal_movimento",
"descricao",
"saldoestoque",
];
Controlando o estoque
Na classe EstoqueService crie um método adicionarEstoque, o qual recebe os campos produto_id e qtde e faça o seguinte:
- localize o produto pelo produto_id
- faça um cast na variável qtde transformando em float
- verifique se o produto exista, em caso positivo adicione o campo estoque_atual do objeto com a qtde recebe
- salve o objeto produto
public static function adicionarEstoque($produto_id, $qtde){
$produto = Produto::find($produto_id);
$qtde = (float)$qtde;
if($produto){ // update
$produto->estoque_atual += $qtde;
$produto->save();
}
}
Na classe EstoqueService crie um método subtrairEstoque, o qual recebe os campos produto_id e qtde e faça o seguinte:
- localize o produto pelo produto_id
- faça um cast na variável qtde transformando em float
- verifique se o produto exista, em caso positivo subtraia o campo estoque_atual do objeto com a qtde recebida
- salve o objeto produto
public static function subtrairEstoque($produto_id, $qtde){
$qtde = (float)$qtde;
$produto = Produto::find($produto_id);
if($produto){ // update
$produto->estoque_atual -= $qtde;
$produto->save();
}
}
Vamos configurar os movimento
Crie um método chamado saldoEstoque, com o seguintes detalhes:
- receba como parâmetro o código do produto
- retorne o último valor do campo saldoestoque da tabela movimento
public static function saldoEstoque($produto_id){
$resultado = Movimento::where("produto_id", $produto_id)
->select("saldoestoque as saldo")
->orderBy("id","Desc")
->limit(1)
->first() ;
return ($resultado) ? $resultado->saldo : 0;
}
Crie um método chamado inserir, com o seguintes detalhes
- Receba um objeto com parâmetro
- Verifique o saldo anterior do do produto na tabela de movimentos
- acrescente ou subtraia o saldo anterior com a nova quantidade e atribua o resultado ao campo saldoestoque
- salve os dados na tabela movimento
public static function inserir($mov ){
$saldo_anterior = Movimento::saldoEstoque($mov->produto_id);
$qtde = ($mov->ent_sai=="E") ? $mov->qtde_movimento : - $mov->qtde_movimento;
$mov->saldoestoque = $saldo_anterior + ($qtde) ;
return Movimento::create(objToArray($mov));
}
Vamos criar um observer para a tabela de movimento
Para criar o observer use o comando: php artisan make:observer MovimentoObserver
Para que o observer possa funcionar é necessário configurá-lo, para isso faça o seguinte
- Abra a classe AppServiceProvider em App/Provider
- no método boot adicione o comando para registrar a classe: Movimento::observe(MovimentoObserver::class);
public function boot(): void
{
Movimento::observe(MovimentoObserver::class);
}
No MovimentoObserver crie o método created, com os seguintes detalhes:
- receba como parâmetro um objeto do tipo Movimento
- se campo ent_sai for igual ao "E" chame o método adicionarEstoque da classe EstoqueService
- se campo ent_sai for igual ao "S" chame o método subtrairEstoqueda classe EstoqueService
public function created(Movimento $mov)
{
if($mov->ent_sai=="E"){
EstoqueService::adicionarEstoque($mov->produto_id, $mov->qtde_movimento);
}else if($mov->ent_sai=="S"){
EstoqueService::subtrairEstoque($mov->produto_id, $mov->qtde_movimento);
}
}
No MovimentoObserver crie o método created, com os seguintes detalhes:
- receba como parâmetro um objeto do tipo Movimento
- se campo ent_sai for igual ao "E" chame o método subtrairEstoqueda classe EstoqueService
- se campo ent_sai for igual ao "S" chame o método adicionarEstoqueclasse EstoqueService
public function deleted(Movimento $mov)
{
if($mov->ent_sai=="E"){
EstoqueService::subtrairEstoque($mov->produto_id, $mov->qtde_movimento);
}else if($mov->ent_sai=="S"){
EstoqueService::adicionarEstoque($mov->produto_id, $mov->qtde_movimento);
}
}
Vamos criar um observer para a tabela de entrada
Para criar o observer use o comando: php artisan make:observer EntradaObserver
Para que o observer possa funcionar é necessário configurá-lo, para isso faça o seguinte
- Abra a classe AppServiceProvider em App/Provider
- no método boot adicione o comando para registrar a classe: Entrada::observe(EntradaObserver::class);
public function boot(): void
{
Entrada::observe(EntradaObserver::class);
}
No EntradaObserver crie o método created, com os seguintes detalhes:
- Receba como parâmetro um objeto do tipo Entrada
- Insira a entrada na tabela da movimento chamando o método inserir do MovimentoService
public function created(Entrada $entrada)
{
$mov = new \stdClass();
$mov->tipo_movimento_id = config("constantes.tipo_movimento.ENTRADA_AVULSA");
$mov->produto_id = $entrada->produto_id;
$mov->entrada_avulsa_id = $entrada->id;
$mov->ent_sai = 'E';
$mov->estorno = 'N';
$mov->data_movimento = $entrada->data_entrada;
$mov->qtde_movimento = $entrada->qtde_entrada;
$mov->valor_movimento = $entrada->valor_entrada;
$mov->subtotal_movimento= $entrada->subtotal_entrada;
$mov->descricao = "Entrada Avulsa num: " . $entrada->id;
MovimentoService::inserir($mov);
}
Vamos criar um observer para a tabela de entrada
Para criar o observer use o comando: php artisan make:observer SaidaObserver
ara que o observer possa funcionar é necessário configurá-lo, para isso faça o seguinte
- Abra a classe AppServiceProvider em App/Provider
- no método boot adicione o comando para registrar a classe: Saida::observe(SaidaObserver::class);
public function boot(): void
{
Saida::observe(SaidaObserver::class);
}
No SaidaObserver crie o método created, com os seguintes detalhes:
- Receba como parâmetro um objeto do tipo Saida
- Insira a saida na tabela da movimento chamando o método inserir do MovimentoService
public function created(Saida $saida)
{
$mov = new \stdClass();
$mov->tipo_movimento_id = config("constantes.tipo_movimento.SAIDA_AVULSA");
$mov->produto_id = $saida->produto_id;
$mov->saida_avulsa_id = $saida->id;
$mov->ent_sai = 'S';
$mov->estorno = 'N';
$mov->data_movimento = $saida->data_saida;
$mov->qtde_movimento = $saida->qtde_saida;
$mov->valor_movimento = $saida->valor_saida;
$mov->subtotal_movimento= $saida->subtotal_saida;
$mov->descricao = "Saida Avulsa num: " . $saida->id;
MovimentoService::inserir($mov);
}