$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); }); }); $selectSemLotes = DB::table('cadastro_material') ->select(array_merge($mainFields, [DB::raw(" NULL AS integracao_bnafar_medicamento_id, '0' AS is_novo_lote, NULL AS lote, NULL AS validade_lote, '0' AS a_vencer_ou_vencido, {$estoqueSum} AS estoque ")])) ->join('cadastro_apresentacao', 'cadastro_apresentacao.id', 'cadastro_material.apresentacao_id') ->join('cadastro_grupo', 'cadastro_grupo.id', 'cadastro_material.grupo_id') ->leftJoin( 'cadastro_unidade_medida as apresentacao_unidade_medida', 'apresentacao_unidade_medida.id', 'cadastro_material.apresentacao_unidade_medida_id' ) ->leftJoin('cadastro_subgrupo', 'cadastro_subgrupo.id', 'cadastro_material.subgrupo_id') ->leftJoin('almoxarifado_entrada_item', function ($join) { $join->on('almoxarifado_entrada_item.material_id', 'cadastro_material.id') ->whereNull('almoxarifado_entrada_item.lote') ->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); }); }) ->leftJoin('almoxarifado_inventario', function ($join) { $join->on('almoxarifado_inventario.material_id', 'cadastro_material.id') ->where('almoxarifado_inventario.finalizado', false) ->whereNull('almoxarifado_inventario.lote') ->where('almoxarifado_inventario.created_centro_custo_id', self::getCurrentCentroCusto()->id); }) ->whereNull('cadastro_material.deleted_at') ->where(function ($query) { $query->where('cadastro_material.is_ativo', true)->orWhere(function ($query) { $query->where('cadastro_material.is_ativo', false)->whereExists(function ($query) { $query ->select(DB::raw('1')) ->from('almoxarifado_entrada_item') ->join( 'almoxarifado_entrada', 'almoxarifado_entrada.id', 'almoxarifado_entrada_item.entrada_id' ) ->whereColumn('almoxarifado_entrada_item.material_id', 'cadastro_material.id') ->where('almoxarifado_entrada.finalizada', true) ->where('almoxarifado_entrada.centro_custo_id', self::getCurrentCentroCusto()->id); }); }); }) ->where(fn ($query) => $addWherePermissao($query)) ->when(request()->query('grupo_id'), fn ($q, $id) => $q->where('cadastro_grupo.id', $id)) ->when(request()->query('subgrupo_id'), fn ($q, $id) => $q->where('cadastro_subgrupo.id', $id)) ->groupBy( 'cadastro_material.id', 'cadastro_material.codigo_material', DB::raw(MaterialService::getDescricaoCompletaRaw( 'cadastro_material', 'cadastro_apresentacao', 'apresentacao_unidade_medida' )), 'cadastro_grupo.nome', 'cadastro_subgrupo.nome', 'cadastro_material.is_ativo', 'almoxarifado_inventario.contagem', DB::raw("NULL"), DB::raw("'0'"), DB::raw("NULL"), DB::raw("NULL"), DB::raw("'0'") ); $selectComLotes = DB::table('cadastro_material') ->select(array_merge($mainFields, [DB::raw(" NULL AS integracao_bnafar_medicamento_id, '0' AS is_novo_lote, almoxarifado_entrada_item.lote, DATE_FORMAT(almoxarifado_entrada_item.validade_lote, '%d/%m/%Y') AS validade_lote, IF(DATEDIFF(almoxarifado_entrada_item.validade_lote, CURRENT_DATE) < 90, '1', '0') AS a_vencer_ou_vencido, {$estoqueSum} AS estoque ")])) ->join('cadastro_apresentacao', 'cadastro_apresentacao.id', 'cadastro_material.apresentacao_id') ->join('cadastro_grupo', 'cadastro_grupo.id', 'cadastro_material.grupo_id') ->join('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); }); }) ->leftJoin( 'cadastro_unidade_medida as apresentacao_unidade_medida', 'apresentacao_unidade_medida.id', 'cadastro_material.apresentacao_unidade_medida_id' ) ->leftJoin('cadastro_subgrupo', 'cadastro_subgrupo.id', 'cadastro_material.subgrupo_id') ->leftJoin('almoxarifado_inventario', function ($join) { $join->on('almoxarifado_inventario.material_id', 'cadastro_material.id') ->where('almoxarifado_inventario.finalizado', false) ->where('almoxarifado_inventario.is_novo_lote', false) ->whereNotNull('almoxarifado_inventario.lote') ->whereColumn('almoxarifado_inventario.lote', 'almoxarifado_entrada_item.lote') ->whereColumn('almoxarifado_inventario.validade_lote', 'almoxarifado_entrada_item.validade_lote') ->where('almoxarifado_inventario.created_centro_custo_id', self::getCurrentCentroCusto()->id); }) ->whereNull('cadastro_material.deleted_at') ->whereNotNull('almoxarifado_entrada_item.lote') ->where(fn ($query) => $addWherePermissao($query)) ->when(request()->query('grupo_id'), fn ($q, $id) => $q->where('cadastro_grupo.id', $id)) ->when(request()->query('subgrupo_id'), fn ($q, $id) => $q->where('cadastro_subgrupo.id', $id)) ->groupBy( 'cadastro_material.id', 'cadastro_material.codigo_material', DB::raw(MaterialService::getDescricaoCompletaRaw( 'cadastro_material', 'cadastro_apresentacao', 'apresentacao_unidade_medida' )), 'cadastro_grupo.nome', 'cadastro_subgrupo.nome', 'cadastro_material.is_ativo', 'almoxarifado_inventario.contagem', DB::raw("NULL"), DB::raw("'0'"), 'almoxarifado_entrada_item.lote', DB::raw("DATE_FORMAT(almoxarifado_entrada_item.validade_lote, '%d/%m/%Y')"), DB::raw("IF(DATEDIFF(almoxarifado_entrada_item.validade_lote, CURRENT_DATE) < 90, 1, 0)") ) ->havingRaw("estoque > 0"); $selectNovosLotes = DB::table('cadastro_material') ->select(array_merge($mainFields, [DB::raw(" almoxarifado_inventario.integracao_bnafar_medicamento_id, '1' AS is_novo_lote, almoxarifado_inventario.lote, DATE_FORMAT(almoxarifado_inventario.validade_lote, '%d/%m/%Y') AS validade_lote, IF(DATEDIFF(almoxarifado_inventario.validade_lote, CURRENT_DATE) < 90, '1', '0') AS a_vencer_ou_vencido, 0 AS estoque ")])) ->join('cadastro_apresentacao', 'cadastro_apresentacao.id', 'cadastro_material.apresentacao_id') ->join('cadastro_grupo', 'cadastro_grupo.id', 'cadastro_material.grupo_id') ->join('almoxarifado_inventario', 'almoxarifado_inventario.material_id', 'cadastro_material.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' ) ->whereNull('cadastro_material.deleted_at') ->where('almoxarifado_inventario.finalizado', false) ->where('almoxarifado_inventario.is_novo_lote', true) ->where('almoxarifado_inventario.created_centro_custo_id', self::getCurrentCentroCusto()->id) ->when(request()->query('grupo_id'), fn ($q, $id) => $q->where('cadastro_grupo.id', $id)) ->when(request()->query('subgrupo_id'), fn ($q, $id) => $q->where('cadastro_subgrupo.id', $id)) ->where(fn ($query) => $addWherePermissao($query)); return$selectSemLotes ->unionAll($selectComLotes) ->unionAll($selectNovosLotes) ->orderBy('descricao') ->get() ->each(function ($material) { $material->is_novo_lote = $material->is_novo_lote === '1'; $material->a_vencer_ou_vencido = $material->a_vencer_ou_vencido === '1'; }); } public static function list() { return [ 'additionals' => [ 'data_atual' => Carbon::now()->format('d/m/Y'), ], 'form' => [ 'has_inventario_nao_finalizado' => self::getInventariosNaoFinalizadosBuilder()->get()->isNotEmpty(), 'grupos' => Grupo::whereHas('almoxarifadoParametrizacoesControleEstoqueGrupo', function ($query) { $query->where('centro_custo_id', self::getCurrentCentroCusto()->id); }) ->orderBy('nome') ->get() ->map(fn ($grupo) => [ 'id' => $grupo->id, 'nome' => $grupo->nome, 'subgrupos' => $grupo->subgrupos() ->whereHas('almoxarifadoParametrizacoesControleEstoqueSubgrupo') ->orderBy('nome') ->get() ->map(fn ($subgrupo) => [ 'id' => $subgrupo->id, 'nome' => $subgrupo->nome, ]) ]), 'grupo_id' => null, 'subgrupo_id' => null, ] ]; } public static function store() { self::validate(); DB::transaction(function () { $itensData = collect(self::getItensData()); self::deleteContagensExcluidas($itensData); $contagens = self::saveContagens($itensData); if (request()->finalizar) { self::ajustarEstoque($contagens); } }); } private static function getInventariosNaoFinalizadosBuilder() { return Inventario::where('finalizado', false) ->where('created_centro_custo_id', self::getCurrentCentroCusto()->id) ->whereHas('material', function ($query) { $query->where(function ($query) { $query ->whereNull('subgrupo_id') ->whereHas('grupo', function ($query) { $query->whereHas('almoxarifadoParametrizacoesControleEstoqueGrupo', function ($query) { $query->where('centro_custo_id', self::getCurrentCentroCusto()->id); }); }); })->orWhere(function ($query) { $query ->whereNotNull('subgrupo_id') ->whereHas('grupo', function ($query) { $query->whereHas('almoxarifadoParametrizacoesControleEstoqueGrupo', function ($query) { $query->where('centro_custo_id', self::getCurrentCentroCusto()->id); }); }) ->whereHas('subgrupo', function ($query) { $query->whereHas('almoxarifadoParametrizacoesControleEstoqueSubgrupo'); }); }); }); } private static function getItensData() { $itens = request()->itens; foreach ($itens as &$item) { if (!is_null($item['validade_lote'])) { $item['validade_lote'] = Carbon::createFromFormat('d/m/Y', $item['validade_lote']); } } unset($item); return $itens; } private static function deleteContagensExcluidas(&$itensData) { $itensData ->filter(fn ($i) => is_null($i['contagem']) && !$i['is_novo_lote']) ->each(function ($itemData) { $itemComContagemExcluida = self::getInventariosNaoFinalizadosBuilder() ->where('material_id', $itemData['material_id']) ->where('is_novo_lote', false) ->where('lote', $itemData['lote']) ->when($itemData['validade_lote'], fn ($q, $v) => $q->whereDate('validade_lote', $v)) ->first(); if (!is_null($itemComContagemExcluida)) { $itemComContagemExcluida->delete(); } }); } private static function saveContagens($itensData) { $contagens = collect(); $finalizado = request()->finalizar; $finalizadoEm = $finalizado ? Carbon::now() : null; $itensData ->filter(fn ($i) => !is_null($i['contagem']) || $i['is_novo_lote']) ->each(function ($itemData) use ($contagens, $finalizado, $finalizadoEm) { $inventario = self::getInventariosNaoFinalizadosBuilder() ->where('material_id', $itemData['material_id']) ->where('is_novo_lote', $itemData['is_novo_lote']) ->where('lote', $itemData['lote']) ->when($itemData['validade_lote'], fn ($q, $v) => $q->whereDate('validade_lote', $v)) ->first(); if ($itemData['is_novo_lote'] && $itemData['deleted']) { if (!is_null($inventario)) { $inventario->delete(); } } else { if (is_null($inventario)) { $inventario = new Inventario([ 'material_id' => $itemData['material_id'], 'lote' => $itemData['lote'], 'validade_lote' => $itemData['validade_lote'], ]); } $inventario->integracao_bnafar_medicamento_id = $itemData['integracao_bnafar_medicamento_id']; $inventario->finalizado = $finalizado; $inventario->finalizado_em = $finalizadoEm; $inventario->contagem = $itemData['contagem']; $inventario->is_novo_lote = $itemData['is_novo_lote']; $inventario->save(); $contagens->push($inventario); } }); return $contagens; } public static function ajustarEstoque($contagens) { $itens = collect(); $contagens->each(function ($contagem) use ($itens) { $item = $itens ->where('material_id', $contagem->material_id) ->where('lote', $contagem->lote) ->first(); if (!is_null($item) && $item['validade_lote']->format('d/m/Y') === $contagem->validade_lote->format('d/m/Y') ) { $item['contagem'] += (int)$contagem->contagem; } else { $itens->push(collect([ 'material_id' => $contagem->material_id, 'integracao_bnafar_medicamento_id' => $contagem->integracao_bnafar_medicamento_id, 'lote' => $contagem->lote, 'validade_lote' => $contagem->validade_lote, 'contagem' => (int)$contagem->contagem, ])); } }); AlmoxarifadoService::saveAjusteDeEstoqueDeInventario($itens); } public static function validate() { $rules = [ 'finalizar' => [ 'required', 'boolean', ], 'itens' => [ 'present', 'array', ], 'itens.*.material_id' => [ 'required', 'integer', Rule::exists(Material::class, 'id'), ], 'itens.*.lote' => [ 'nullable', 'string', 'max:15', ], 'itens.*.validade_lote' => [ 'nullable', 'date_format:d/m/Y', ], 'itens.*.contagem' => [ 'nullable', 'integer', 'between:0,99999999', ], 'itens.*.is_novo_lote' => [ 'required', 'boolean', ], 'itens.*.deleted' => [ 'required', 'boolean', ] ]; $messages = []; request()->validate($rules, $messages); } public static function getIntegracaoBnafarMedicamentos() { return DB::table('integracao_bnafar_medicamento') ->select([ 'integracao_bnafar_medicamento.id AS medicamento_id', 'integracao_bnafar_medicamento.codigo AS medicamento_codigo', 'integracao_bnafar_medicamento.descricao AS medicamento_descricao', ]) ->whereExists(function ($query) { $query->select(DB::raw(1)) ->from('cadastro_material_integracao_bnafar_medicamento') ->where('cadastro_material_integracao_bnafar_medicamento.material_id', request()->material_id) ->whereColumn('cadastro_material_integracao_bnafar_medicamento.medicamento_id', 'integracao_bnafar_medicamento.id'); }) ->get(); } }