Files
Antonio Lopes dos Santos afec302c3e
All checks were successful
build-api-image / build (push) Successful in 51s
init commit
2026-08-04 16:52:02 -03:00

352 lines
13 KiB
PHP

<?php
namespace App\Services\Almoxarifado;
use App\Enums\Almoxarifado\SaidaTipo;
use App\Exceptions\Almoxarifado\BaixaEstoqueIndisponivelException;
use App\Exceptions\Almoxarifado\EstoqueIndisponivelException;
use App\Models\Almoxarifado\EntradaItem;
use App\Models\Almoxarifado\MotivoBaixa;
use App\Models\Almoxarifado\Saida;
use App\Models\Almoxarifado\SaidaItem;
use App\Models\Cadastro\Material\Material;
use App\Models\Cadastro\SujeitoAtencao\Usuario;
use App\Services\Cadastro\Material\MaterialService;
use App\Services\Service;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class BaixaService extends Service
{
public static function datatable()
{
$materiais = DB::table('cadastro_material')
->join(
'cadastro_grupo',
'cadastro_grupo.id',
'cadastro_material.grupo_id'
)
->join(
'cadastro_apresentacao',
'cadastro_apresentacao.id',
'cadastro_material.apresentacao_id'
)
->leftJoin(
'cadastro_subgrupo',
'cadastro_subgrupo.id',
'cadastro_material.subgrupo_id'
)
->leftJoin(
'cadastro_unidade_medida as apresentacao_unidade_medida',
'apresentacao_unidade_medida.id',
'cadastro_material.apresentacao_unidade_medida_id'
)
->leftJoin('almoxarifado_entrada_item', function ($join) {
$join
->on('almoxarifado_entrada_item.material_id', 'cadastro_material.id')
->whereExists(function ($query) {
$query
->select(DB::raw('1'))
->from('almoxarifado_entrada')
->whereColumn('almoxarifado_entrada.id', 'almoxarifado_entrada_item.entrada_id')
->where('almoxarifado_entrada.finalizada', true)
->where('almoxarifado_entrada.centro_custo_id', self::getCurrentCentroCusto()->id);
});
})
->whereNull('cadastro_material.deleted_at')
->where(function ($query) {
$query->where(function ($query) {
$query
->whereNull('cadastro_material.subgrupo_id')
->whereExists(function ($query) {
$query
->select(DB::raw(1))
->from('almoxarifado_parametrizacao_controle_estoque_grupo')
->whereColumn('almoxarifado_parametrizacao_controle_estoque_grupo.grupo_id', 'cadastro_material.grupo_id')
->where('almoxarifado_parametrizacao_controle_estoque_grupo.centro_custo_id', self::getCurrentCentroCusto()->id);
});
})->orWhere(function ($query) {
$query
->whereNotNull('cadastro_material.subgrupo_id')
->whereExists(function ($query) {
$query
->select(DB::raw(1))
->from('almoxarifado_parametrizacao_controle_estoque_subgrupo')
->join(
'almoxarifado_parametrizacao_controle_estoque_grupo',
'almoxarifado_parametrizacao_controle_estoque_grupo.id',
'almoxarifado_parametrizacao_controle_estoque_subgrupo.parametrizacao_controle_estoque_grupo_id'
)
->whereColumn('almoxarifado_parametrizacao_controle_estoque_subgrupo.subgrupo_id', 'cadastro_material.subgrupo_id')
->where('almoxarifado_parametrizacao_controle_estoque_grupo.centro_custo_id', self::getCurrentCentroCusto()->id);
});
});
})
->select(
'cadastro_material.id',
'cadastro_material.codigo_material',
DB::raw(MaterialService::getDescricaoCompletaRaw(
'cadastro_material',
'cadastro_apresentacao',
'apresentacao_unidade_medida'
) . " as descricao"),
'cadastro_material.is_ativo',
'cadastro_grupo.nome AS grupo',
'cadastro_subgrupo.nome AS subgrupo',
)
->distinct();
return datatables()
->of($materiais)
->filterColumn('descricao', function ($query, $keyword) {
$query->whereRaw(MaterialService::getDescricaoCompletaRaw(
'cadastro_material',
'cadastro_apresentacao',
'apresentacao_unidade_medida'
) . " like ?", ["%{$keyword}%"]);
})
->skipTotalRecords()
->toJson();
}
public static function history()
{
$saidas = DB::table('almoxarifado_saida')
->join(
'almoxarifado_saida_item',
'almoxarifado_saida_item.saida_id',
'almoxarifado_saida.id'
)
->join(
'almoxarifado_saida_baixa',
'almoxarifado_saida_baixa.saida_id',
'almoxarifado_saida.id'
)
->join(
'cadastro_lotacao as baixa_lotacao',
'baixa_lotacao.id',
'almoxarifado_saida_baixa.created_lotacao_id'
)
->join(
'cadastro_usuario as baixa_usuario',
'baixa_usuario.id',
'baixa_lotacao.usuario_id'
)
->join(
'cadastro_cidadao as baixa_cidadao',
'baixa_cidadao.id',
'baixa_usuario.cidadao_id'
)
->join(
'almoxarifado_motivo_baixa',
'almoxarifado_motivo_baixa.id',
'almoxarifado_saida_baixa.motivo_id'
)
->leftJoin(
'cadastro_usuario',
'cadastro_usuario.id',
'almoxarifado_saida_baixa.usuario_solicitante_id'
)
->leftJoin(
'cadastro_cidadao',
'cadastro_cidadao.id',
'cadastro_usuario.cidadao_id'
)
->select(
'almoxarifado_saida_item.id AS saida_item_id',
DB::raw("DATE_FORMAT(almoxarifado_saida.created_at, '%d/%m/%Y') AS data"),
'almoxarifado_motivo_baixa.descricao AS motivo_descricao',
'almoxarifado_saida_baixa.justificativa',
'baixa_cidadao.nome AS usuario_baixa_nome',
'cadastro_cidadao.nome AS usuario_solicitante_nome',
DB::raw('(
SELECT SUM(se.quantidade_saida)
FROM almoxarifado_saida_item_entrada_item se
WHERE se.saida_item_id = almoxarifado_saida_item.id
) as quantidade'),
DB::raw("DATE_FORMAT(almoxarifado_saida_item.estornado_em, '%d/%m/%Y') as data_estorno"),
DB::raw('IF (almoxarifado_saida_item.estornado_em IS NULL, 0, 1) AS estornado'),
)
->addSelect([
'usuario_estorno_nome' => function ($query) {
$query->select('entrada_item_estorno_cidadao.nome')
->from('almoxarifado_saida_item_entrada_item as saida_item_entrada_item')
->leftJoin(
'almoxarifado_entrada_item as entrada_item_estorno',
'entrada_item_estorno.id',
'saida_item_entrada_item.entrada_item_estornado_id'
)
->leftJoin(
'cadastro_lotacao as entrada_item_estorno_lotacao',
'entrada_item_estorno_lotacao.id',
'entrada_item_estorno.created_lotacao_id'
)
->leftJoin(
'cadastro_usuario as entrada_item_estorno_usuario',
'entrada_item_estorno_usuario.id',
'entrada_item_estorno_lotacao.usuario_id'
)
->leftJoin(
'cadastro_cidadao as entrada_item_estorno_cidadao',
'entrada_item_estorno_cidadao.id',
'entrada_item_estorno_usuario.cidadao_id'
)
->whereColumn('saida_item_entrada_item.saida_item_id', 'almoxarifado_saida_item.id')
->limit(1);
},
])
->where('almoxarifado_saida.tipo_id', SaidaTipo::BAIXA)
->where('almoxarifado_saida_item.material_id', request()->query('material_id'))
->where('almoxarifado_saida.centro_custo_id', self::getCurrentCentroCusto()->id);
return datatables()
->of($saidas)
->filterColumn('almoxarifado_saida.created_at', function ($query, $keyword) {
$query->whereRaw("DATE_FORMAT(almoxarifado_saida.created_at, '%d/%m/%Y') like ?", ["%{$keyword}%"]);
})
->toJson();
}
public static function create($materialId)
{
$material = Material::findOrFail($materialId);
$estoque = AlmoxarifadoService::getEstoque($material->id);
$entradaItens = collect($estoque['por_entrada'])->map(function ($entradaItem) {
$entradaItem->quantidade_saida = 0;
return $entradaItem;
});
return [
'form' => [
'motivos' => MotivoBaixa::orderBy('descricao')
->get(['id', 'tipo_id', 'descricao', 'justificar']),
'possui_entrada_com_lote' => !is_null($entradaItens->whereNotNull('lote')->first()),
],
'model' => [
'motivo_id' => null,
'justificativa' => null,
'usuario_solicitante' => null,
'estoque' => $estoque['total'],
'quantidade' => null,
'escolheu_entrada_item_manualmente' => false,
'entrada_itens' => $entradaItens,
],
];
}
public static function store()
{
self::validate();
$saida = new Saida();
DB::transaction(function () use (&$saida) {
try {
$saida = AlmoxarifadoService::saveSaidaDeBaixa(self::getParams());
}
catch (EstoqueIndisponivelException $e) {
throw new BaixaEstoqueIndisponivelException();
}
});
return $saida->itens()->first();
}
private static function getParams()
{
return [
'material_id' => request()->material_id,
'motivo_id' => request()->motivo_id,
'justificativa' => request()->justificativa,
'usuario_solicitante_id' => request()->usuario_solicitante_id,
'quantidade' => (int) request()->quantidade,
'entrada_itens' => collect(request()->entrada_itens)->map(fn ($entradaItem) => [
'entrada_item_id' => $entradaItem['entrada_item_id'],
'quantidade_saida' => (int) $entradaItem['quantidade_saida'],
]),
'escolheu_entrada_item_manualmente' => request()->escolheu_entrada_item_manualmente,
];
}
public static function reverse($saidaItemId)
{
$saidaItem = SaidaItem::findOrFail($saidaItemId);
DB::transaction(function () use ($saidaItem) {
AlmoxarifadoService::estornarSaidaItens(collect([
['id' => $saidaItem->id]
]));
});
}
public static function validate()
{
$rules = [
'material_id' => [
'required',
'integer',
Rule::exists(Material::class, 'id'),
],
'motivo_id' => [
'required',
'integer',
Rule::exists(MotivoBaixa::class, 'id'),
],
'justificativa' => [
'nullable',
'string',
'max:100',
],
'usuario_solicitante_id' => [
'nullable',
'integer',
Rule::exists(Usuario::class, 'id'),
],
'quantidade' => [
'required',
'integer',
'min:1',
],
'escolheu_entrada_item_manualmente' => [
'required',
'boolean',
],
'entrada_itens' => [
'present',
'array',
],
'entrada_itens.*.entrada_item_id' => [
'required',
'integer',
Rule::exists(EntradaItem::class, 'id'),
],
'entrada_itens.*.quantidade_saida' => [
'required',
'integer',
'min:1',
],
];
$messages = [];
request()->validate($rules, $messages);
}
}