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); } }