join( 'almoxarifado_saida_transferencia', 'almoxarifado_saida_transferencia.saida_id', 'almoxarifado_saida.id' ) ->join( 'cadastro_centro_custo', 'cadastro_centro_custo.id', 'almoxarifado_saida_transferencia.centro_custo_id' ) ->join( 'cadastro_setor', 'cadastro_setor.id', 'cadastro_centro_custo.setor_id' ) ->join( 'cadastro_infraestrutura', 'cadastro_infraestrutura.id', 'cadastro_centro_custo.infraestrutura_id' ) ->join( 'cadastro_unidade', 'cadastro_unidade.id', 'cadastro_infraestrutura.unidade_id' ) ->join( 'cadastro_usuario', 'cadastro_usuario.id', 'almoxarifado_saida_transferencia.usuario_id' ) ->join( 'cadastro_cidadao', 'cadastro_cidadao.id', 'cadastro_usuario.cidadao_id' ) ->select( 'almoxarifado_saida.id', DB::raw("cadastro_unidade.nome_fantasia AS unidade_nome_fantasia"), DB::raw("COALESCE(cadastro_infraestrutura.nome, cadastro_unidade.nome_fantasia) AS infraestrutura_nome"), 'cadastro_setor.nome as setor_nome', 'cadastro_cidadao.nome AS usuario_nome', DB::raw("DATE_FORMAT(almoxarifado_saida.created_at, '%d/%m/%Y') as data_transferencia"), 'almoxarifado_saida.finalizada', 'almoxarifado_saida_transferencia.confirmado', 'almoxarifado_saida_transferencia.recusado' ) ->where('almoxarifado_saida.tipo_id', SaidaTipo::TRANSFERENCIA) ->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}%"]) ->orWhereRaw( "CONCAT( SUBSTR(almoxarifado_saida.created_at,9,2), SUBSTR(almoxarifado_saida.created_at,6,2), SUBSTR(almoxarifado_saida.created_at,1,4) ) like ?", ["%{$keyword}%"] ); }) ->filterColumn('cadastro_infraestrutura.nome', function ($query, $keyword) { $query->whereRaw("COALESCE(cadastro_infraestrutura.nome, cadastro_unidade.nome_fantasia) like ?", ["%{$keyword}%"]); }) ->filterColumn('almoxarifado_saida.finalizada', function ($query, $keyword) { $query->whereRaw("IF(almoxarifado_saida.finalizada = 1, 'SIM', 'NÃO') = ?", [Str::upper($keyword)]); }) ->skipTotalRecords() ->toJson(); } public static function datatableRecebidas() { $saidas = DB::table('almoxarifado_saida') ->join( 'almoxarifado_saida_transferencia', 'almoxarifado_saida_transferencia.saida_id', 'almoxarifado_saida.id' ) ->join( 'cadastro_centro_custo', 'cadastro_centro_custo.id', 'almoxarifado_saida.centro_custo_id' ) ->join( 'cadastro_setor', 'cadastro_setor.id', 'cadastro_centro_custo.setor_id' ) ->join( 'cadastro_infraestrutura', 'cadastro_infraestrutura.id', 'cadastro_centro_custo.infraestrutura_id' ) ->join( 'cadastro_unidade', 'cadastro_unidade.id', 'cadastro_infraestrutura.unidade_id' ) ->join( 'cadastro_usuario', 'cadastro_usuario.id', 'almoxarifado_saida_transferencia.usuario_id' ) ->join( 'cadastro_cidadao', 'cadastro_cidadao.id', 'cadastro_usuario.cidadao_id' ) ->select( 'almoxarifado_saida.id', DB::raw("cadastro_unidade.nome_fantasia AS unidade_nome_fantasia"), DB::raw("COALESCE(cadastro_infraestrutura.nome, cadastro_unidade.nome_fantasia) AS infraestrutura_nome"), 'cadastro_setor.nome as setor_nome', 'cadastro_cidadao.nome AS usuario_nome', DB::raw("DATE_FORMAT(almoxarifado_saida.created_at, '%d/%m/%Y') as data_transferencia"), 'almoxarifado_saida_transferencia.confirmado', 'almoxarifado_saida_transferencia.recusado' ) ->where('almoxarifado_saida.tipo_id', SaidaTipo::TRANSFERENCIA) ->where('almoxarifado_saida.finalizada', true) ->where('almoxarifado_saida_transferencia.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}%"]) ->orWhereRaw( "CONCAT( SUBSTR(almoxarifado_saida.created_at,9,2), SUBSTR(almoxarifado_saida.created_at,6,2), SUBSTR(almoxarifado_saida.created_at,1,4) ) like ?", ["%{$keyword}%"] ); }) ->filterColumn('cadastro_infraestrutura.nome', function ($query, $keyword) { $query->whereRaw("COALESCE(cadastro_infraestrutura.nome, cadastro_unidade.nome_fantasia) like ?", ["%{$keyword}%"]); }) ->skipTotalRecords() ->toJson(); } public static function create() { return [ 'form' => self::getFormData(), 'model' => [ 'finalizada' => false, 'confirmado' => false, 'recusado' => false, 'destino' => [ 'centro_custo_id' => null, 'usuario' => null, ], 'itens' => [], 'ultimo_balancete_fechado' => [BalanceteFechamento::Latest() ->select('mes', 'ano') ->first() ?? null, Carbon::now()] ] ]; } public static function store() { self::validate(); $saida = null; DB::transaction(function () use (&$saida) { $saida = AlmoxarifadoService::saveTransferencia(self::getParams()); }); return $saida; } public static function edit($id) { $saida = Saida::findOrFail($id); return [ 'form' => self::getFormData($saida), 'model' => [ 'finalizada' => $saida->finalizada, 'confirmado' => $saida->transferencia->confirmado, 'recusado' => $saida->transferencia->recusado, 'destino' => [ 'centro_custo_id' => $saida->transferencia->centroCusto->id, 'usuario' => [ 'id' => $saida->transferencia->usuario->id, 'cidadao_nome' => $saida->transferencia->usuario->cidadao->nome, ], ], 'itens' => $saida->itens->map(fn ($item) => [ 'id' => $item->id, 'material' => [ 'id' => $item->material->id, 'codigo_material' => $item->material->codigo_material, 'descricao_completa' => $item->material->descricao_completa, ], 'quantidade' => $item->quantidade, 'estorno_salvo' => $item->estornado, 'estornado' => $item->estornado, 'entrada_itens' => $item->entradaItens->map(fn ($entradaItem) => [ 'entrada_item_id' => $entradaItem->id, 'quantidade_saida' => $entradaItem->pivotSaidaItemEntradaItem->quantidade_saida, 'lote' => $entradaItem->lote, 'validade_lote' => $entradaItem->validade_lote, ]), 'escolheu_entrada_item_manualmente' => $item->escolheu_entrada_item_manualmente, ]), 'ultimo_balancete_fechado' => [BalanceteFechamento::Latest() ->select('mes', 'ano') ->first() ?? null, Carbon::now()] ] ]; } private static function getFormData($saida = null) { $centroCustoLogadoId = self::getCurrentCentroCusto()->id; return [ 'destino' => [ 'unidades' => Unidade::orderBy('nome_fantasia') ->whereHas('infraestruturas', function ($query) use ($centroCustoLogadoId) { $query->whereHas('centrosCusto', function ($query) use ($centroCustoLogadoId) { $query->where('id', '<>', $centroCustoLogadoId); }); }) ->get() ->map(fn ($unidade) => [ 'id' => $unidade->id, 'nome_fantasia' => $unidade->nome_fantasia, 'infraestruturas' => $unidade->infraestruturas() ->whereHas('centrosCusto', function ($query) use ($centroCustoLogadoId) { $query->where('id', '<>', $centroCustoLogadoId); }) ->get() ->sortBy('nome') ->map(fn ($infraestrutura) => [ 'id' => $infraestrutura->id, 'nome' => $infraestrutura->nome, 'centros_custo' => $infraestrutura->centrosCusto() ->where('id', '<>', $centroCustoLogadoId) ->get() ->map(fn ($centroCusto) => [ 'id' => $centroCusto->id, 'setor_nome' => $centroCusto->setor->nome, ]) ->sortBy('setor_nome') ->values() ]) ->values() ]), 'unidade_id' => $saida ? $saida->transferencia->centroCusto->infraestrutura->unidade_id : null, 'infraestrutura_id' => $saida ? $saida->transferencia->centroCusto->infraestrutura->id : null, ] ]; } public static function update($id) { self::validate(); $saida = Saida::findOrFail($id); if ($saida->transferencia->confirmado || $saida->transferencia->recusado) { throw new TransferenciaRespondidaPeloDestinoException(); } DB::transaction(function () use (&$saida) { $saida = AlmoxarifadoService::saveTransferencia(self::getParams(), $saida->id); }); return $saida; } private static function getParams() { return [ 'finalizada' => request()->finalizada, 'destino' => [ 'centro_custo_id' => request()->destino['centro_custo_id'], 'usuario_id' => request()->destino['usuario_id'], ], 'itens' => collect(request()->itens)->map(fn ($item) => [ 'id' => $item['id'], 'material_id' => $item['material_id'], 'quantidade' => (int) $item['quantidade'], 'estornado' => $item['estornado'], 'entrada_itens' => collect($item['entrada_itens'])->map(fn ($entradaItem) => [ 'entrada_item_id' => $entradaItem['entrada_item_id'], 'quantidade_saida' => (int) $entradaItem['quantidade_saida'], ]), 'escolheu_entrada_item_manualmente' => $item['escolheu_entrada_item_manualmente'], ]) ]; } public static function validate() { $rules = [ 'finalizada' => [ 'required', 'boolean', ], 'destino.centro_custo_id' => [ 'required', 'integer', Rule::exists(CentroCusto::class, 'id'), ], 'destino.usuario_id' => [ 'required', 'integer', Rule::exists(Usuario::class, 'id'), ], 'itens' => [ 'required', 'array', ], 'itens.*.id' => [ 'nullable', 'integer', Rule::exists(SaidaItem::class, 'id'), ], 'itens.*.material_id' => [ 'required', 'integer', Rule::exists(Material::class, 'id'), ], 'itens.*.quantidade' => [ 'required', 'integer', 'min:1', ], 'itens.*.escolheu_entrada_item_manualmente' => [ 'required', 'boolean', ], 'itens.*.estornado' => [ 'required', 'boolean', ], 'itens.*.entrada_itens' => [ 'present', 'array', ], 'itens.*.entrada_itens.*.entrada_item_id' => [ 'required', 'integer', Rule::exists(EntradaItem::class, 'id'), ], 'itens.*.entrada_itens.*.quantidade_saida' => [ 'required', 'integer', 'min:1', ], ]; $messages = []; request()->validate($rules, $messages); } public static function destroy($id) { $saida = Saida::findOrFail($id); DB::transaction(function () use ($saida) { $saida->itens->each(fn ($i) => $i->entradaItens()->detach()); $saida->delete(); }); return null; } public static function getTransferenciaRecebida($id) { $saida = Saida::findOrFail($id); return [ 'origem' => [ 'unidade_nome_fantasia' => $saida->centroCusto->infraestrutura->unidade->nome_fantasia, 'infraestrutura_nome' => $saida->centroCusto->infraestrutura->nome, 'setor_nome' => $saida->centroCusto->setor->nome, ], 'itens' => $saida->transferencia->recusado ? $saida->itensRecusadosTransferencia->map(fn ($item) => [ 'material_descricao' => $item->saidaItem->material->descricao_completa, 'quantidade' => $item->saidaItem->quantidade, ]) : $saida->itens->filter(fn ($i) => !$i->estornado)->map(fn ($item) => [ 'material_descricao' => $item->material->descricao_completa, 'quantidade' => $item->quantidade, ])->values() ]; } public static function accept($id) { $saida = Saida::findOrFail($id); DB::transaction(function () use ($saida) { AlmoxarifadoService::saveEntradasDeTransferencia($saida); $saida->transferencia->confirmado = true; $saida->transferencia->save(); }); } public static function reject($id) { $saida = Saida::findOrFail($id); DB::transaction(function () use ($saida) { $itensNaoEstornados = collect(); $saida->itens->filter(fn ($i) => !$i->estornado)->each(function ($item) use ($saida, $itensNaoEstornados) { $saida->itensRecusadosTransferencia()->create(['saida_item_id' => $item->id]); $itensNaoEstornados->push(['id' => $item->id]); }); AlmoxarifadoService::saveEstornoDeTransferencia($itensNaoEstornados); $saida->transferencia->recusado = true; $saida->transferencia->save(); }); } }