File manager - Edit - /var/www/html/gop/api/app/Http/Controllers/ObraController.php
Back
<?php namespace App\Http\Controllers; use App\Http\Requests\Store\StoreArquivoRequest; use App\Http\Requests\Store\StoreImageRequest; use App\Http\Requests\Store\StoreObraRequest; use App\Http\Requests\Store\StorePrivateFieldRequest; use App\Http\Requests\Update\UpdateObraRequest; use App\Http\Services\ArquivoService; use App\Http\Services\DocumentoService; use App\Http\Services\ImageService; use App\Http\Services\PrivateFieldService; use App\Models\Obra; use App\Models\ObraFiscal; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; /** * @OA\Tag( * name="Obra", * description="Gerenciamento de Obras" * ) */ class ObraController extends Controller { /** * @OA\Get( * path="/api/obras", * summary="Lista obras com filtros e paginação", * operationId="IndexObra", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter( * name="nome", * in="query", * * @OA\Schema(type="string"), * description="Filtra obras pelo nome" * ), * * @OA\Parameter( * name="contrato", * in="query", * * @OA\Schema(type="string"), * description="Filtra obras pelo contrato" * ), * * @OA\Parameter( * name="processo", * in="query", * * @OA\Schema(type="string"), * description="Filtra obras pelo processo" * ), * * @OA\Parameter( * name="bairro", * in="query", * * @OA\Schema(type="string"), * description="Filtra obras pelo bairro do endereço" * ), * * @OA\Parameter( * name="organization_id", * in="query", * * @OA\Schema(type="string"), * description="Filtra obras por organizations" * ), * * @OA\Parameter( * name="unid_orcamentaria_id", * in="query", * * @OA\Schema(type="string"), * description="Filtra obras por unidades orçamentárias" * ), * * @OA\Parameter( * name="unid_fiscalizadora_id", * in="query", * * @OA\Schema(type="string"), * description="Filtra obras por unidades fiscalizadoras" * ), * * @OA\Parameter( * name="status", * in="query", * * @OA\Schema(type="string"), * description="Filtra obras pelo status" * ), * * @OA\Parameter( * name="empresa_id", * in="query", * * @OA\Schema(type="integer"), * description="Filtra obras por empresa" * ), * * @OA\Parameter( * name="perPage", * in="query", * * @OA\Schema(type="integer", default=10), * description="Quantidade de obras por página" * ), * * @OA\Parameter( * name="page", * in="query", * * @OA\Schema(type="integer", default=1), * description="Número da página atual" * ), * * @OA\Response( * response=200, * description="Lista de obras retornada com sucesso", * ), * ) */ public function index() { $perPage = request()->get('perPage', 10); $obra = Obra::with('endereco', 'organizations', 'unidOrcamentarias', 'unidFiscalizadoras') ->where('is_fornecimento', false); if (! auth()->check()) { $obra = $this->aplicarFiltrosPublicos($obra); return response()->json( $obra->where('is_habilitado', true) ->paginate($perPage) ); } $obra = $this->aplicarFiltros($obra); $permissions = auth()->user()->permissions['gop']; $visualizarTudo = in_array('visualizar-outras-organizacoes', $permissions); if ($visualizarTudo) { return response()->json($obra->paginate($perPage)); } $organizations = collect(auth()->user()->organization)->pluck('id'); $userId = auth()->user()->id; $obra = $obra->where(function ($query) use ($organizations, $userId) { $query->whereHas('organizations', function ($q) use ($organizations) { $q->whereIn('organization_id', $organizations); }) ->orWhereNull('organization_id') // mantém compatibilidade com dados antigos ->orWhereHas('fiscais', function ($q) use ($userId) { $q->where('responsavel_fiscalizacao_id', $userId); }); }); return response()->json($obra->latest('id')->paginate($perPage)); } private function aplicarFiltrosPublicos($query) { $term = trim((string) request('search')); if ($term !== '') { $query->where(function ($q) use ($term) { $q->where('nome', 'LIKE', "%{$term}%") ->orWhereHas('endereco', function ($sub) use ($term) { $sub->where('bairro', 'LIKE', "%{$term}%"); }); }); } return $query; } private function aplicarFiltros($query) { // Filtros diretos na obra if (request()->filled('nome')) { $query->where('nome', 'LIKE', '%'.request('nome').'%'); } if (request()->filled('contrato')) { $query->where('contrato', 'LIKE', '%'.request('contrato').'%'); } if (request()->filled('processo')) { $query->where('processo', 'LIKE', '%'.request('processo').'%'); } if (request()->filled('empresa_id')) { $query->where('empresa_id', request('empresa_id')); } if (request()->filled('status')) { $status = request('status'); $query->whereHas('statuses', function ($q) use ($status) { $q->where('name', $status); }); } // Filtro pelo endereço if (request()->filled('bairro')) { $bairro = request('bairro'); $query->whereHas('endereco', function ($q) use ($bairro) { $q->where('bairro', 'LIKE', "%{$bairro}%"); }); } // Filtro por organizations if (request()->filled('organization_id')) { $orgId = request('organization_id'); $query->whereHas('organizations', function ($q) use ($orgId) { $q->where('organization_id', $orgId); }); } // Filtro por unidFiscalizadoras if (request()->filled('unid_fiscalizadora_id')) { $unidFiscalId = request('unid_fiscalizadora_id'); $query->whereHas('unidFiscalizadoras', function ($q) use ($unidFiscalId) { $q->where('organization_id', $unidFiscalId); }); } // Filtro por unidOrcamentarias if (request()->filled('unid_orcamentaria_id')) { $unidOrcId = request('unid_orcamentaria_id'); $query->whereHas('unidOrcamentarias', function ($q) use ($unidOrcId) { $q->where('organization_id', $unidOrcId); }); } return $query; } /** * @OA\Get( * path="/api/obras/{obra}/gera-pdf", * summary="Gera PDF da ordem de serviço", * operationId="GeraPdfObra", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter(name="obra", in="path", required=true, @OA\Schema(type="integer")), * * @OA\Response(response=200, description="PDF gerado com sucesso"), * @OA\Response(response=422, description="Validação falhou") * ) */ public function geraPdf(Obra $obra) { $this->authorize('viewAny', Obra::class); $obra->load('endereco'); $validate = Validator::make($obra->toArray(), [ 'responsavel_firma_id' => 'required', 'responsavel_tecnico_id' => 'required', ], [ 'responsavel_firma_id.required' => 'O responsável pela firma precisa ser informado no cadastro de obras.', 'responsavel_tecnico_id.required' => 'O responsável técnico precisa ser informado no cadastro de obras.', ]); if ($validate->fails()) { return response()->json($validate->errors(), JsonResponse::HTTP_UNPROCESSABLE_ENTITY); } $documentoService = new DocumentoService; $path = $documentoService->pdfOrdemServico($obra); return response()->json($path); } /** * @OA\Post( * path="/obras", * summary="Cria nova obra", * operationId="StoreObra", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\RequestBody( * required=true, * * @OA\JsonContent( * type="object", * * @OA\Property(property="nome", type="string", example="Construção da Escola Técnica"), * @OA\Property(property="contrato", type="string", example="CT-2025-001"), * @OA\Property(property="modalidade", type="string", example="Tomada de Preços"), * @OA\Property(property="processo", type="string", example="PRC-2025-045"), * @OA\Property(property="numero", type="string", example="101"), * @OA\Property(property="ano", type="integer", example=2025), * @OA\Property(property="valor_inicial", type="number", format="float", example=1000000.00), * @OA\Property(property="servico", type="string", example="Execução de obras civis"), * @OA\Property(property="endereco_id", type="integer", example=1), * @OA\Property(property="empresa_id", type="integer", example=3), * @OA\Property(property="ordenador_id", type="integer", example=5), * @OA\Property(property="fiscais", type="array", @OA\Items( * type="object", * @OA\Property(property="id", type="integer", example=100) * )), * @OA\Property(property="responsavel_firma_id", type="integer", example=4), * @OA\Property(property="responsavel_tecnico_id", type="integer", example=6), * @OA\Property(property="data", type="string", format="date", example="2025-08-06"), * @OA\Property(property="prazo_inicial", type="string", format="date", example="2025-10-01"), * @OA\Property(property="is_fornecimento", type="boolean", example=true), * @OA\Property(property="is_habilitado", type="boolean", example=true) * ) * ), * * @OA\Response( * response=201, * description="Obra criada com sucesso" * ) * ) */ public function store(StoreObraRequest $request) { $this->authorize('create', Obra::class); $obra = Obra::create($request->validated()); $obra->update([ 'valor_ajustado' => (float) $obra->valor_inicial, 'prazo_ajustado' => $obra->prazo_inicial, ]); if ($request->has('fiscais')) { foreach ($request->fiscais as $fiscal) { ObraFiscal::create([ 'responsavel_fiscalizacao_id' => $fiscal['responsavel_fiscalizacao_id'], 'obra_id' => $obra->id, 'nome' => $fiscal['nome'], 'document' => $fiscal['document'], ]); } } if ($request->has('organizations')) { foreach ($request->organizations as $organization) { $obra->organizations()->create([ 'organization_id' => $organization['organization_id'], ]); } } if ($request->has('unid_orcamentarias')) { foreach ($request->unid_orcamentarias as $unidOrcamentaria) { $obra->unidOrcamentarias()->create([ 'organization_id' => $unidOrcamentaria['organization_id'], ]); } } if ($request->has('unid_fiscalizadoras')) { foreach ($request->unid_fiscalizadoras as $unidFiscalizadora) { $obra->unidFiscalizadoras()->create([ 'organization_id' => $unidFiscalizadora['organization_id'], ]); } } return response()->json($obra->load(['fiscais', 'organizations', 'unidOrcamentarias', 'unidFiscalizadoras']), JsonResponse::HTTP_CREATED); } /** * @OA\Get( * path="/api/obra/{obra}", * summary="Exibe obra pública", * operationId="ShowObraPublic", * tags={"Obra"}, * security={}, * * @OA\Parameter( * name="obra", * in="path", * required=true, * * @OA\Schema(type="integer") * ), * * @OA\Response( * response=200, * description="Obra pública retornada com sucesso" * ) * ), * * @OA\Get( * path="/api/obras/{obra}", * summary="Exibe obra autenticada", * operationId="ShowObra", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter( * name="obra", * in="path", * required=true, * * @OA\Schema(type="integer") * ), * * @OA\Response( * response=200, * description="Obra autenticada retornada com sucesso" * ) * ) */ public function show(Obra $obra) { $relacoes = [ 'responsavelFirma', 'responsavelTecnico', 'empresa', 'reajustes', 'empenhos', 'fiscalizacoes.medicoes', 'statuses', 'historicos', 'endereco', 'fases.servicos.subitens', 'logImportacoes', 'fornecimentos', 'fiscais', 'organizations', 'unidOrcamentarias', 'unidFiscalizadoras', ]; if (! auth()->check()) { if (! $obra->is_habilitado) { return response()->json(['message' => 'Obra não disponível.'], Response::HTTP_NOT_FOUND); } return response()->json($obra->load($relacoes), Response::HTTP_OK); } return response()->json($obra->load($relacoes), Response::HTTP_OK); } /** * @OA\Put( * path="/api/obras/{obra}", * summary="Atualiza obra", * operationId="UpdateObra", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter( * name="obra", * in="path", * required=true, * * @OA\Schema(type="integer") * ), * * @OA\RequestBody( * required=true, * * @OA\JsonContent( * type="object", * * @OA\Property(property="nome", type="string", example="string"), * @OA\Property(property="contrato", type="string", example="string"), * @OA\Property(property="modalidade", type="string", example="string"), * @OA\Property(property="processo", type="string", example="string"), * @OA\Property(property="numero", type="integer", example=0), * @OA\Property(property="ano", type="integer", example=0), * @OA\Property(property="valor_inicial", type="number", format="float", example=0), * @OA\Property(property="servico", type="string", example="string"), * @OA\Property(property="endereco_id", type="integer", example=1), * @OA\Property(property="empresa_id", type="integer", example=2), * @OA\Property(property="ordenador_id", type="integer", example=3), * @OA\Property(property="organization_id", type="integer", example=4), * @OA\Property(property="responsavel_fiscalizacao_id", type="integer", example=5), * @OA\Property(property="motivo", type="string", example="string"), * @OA\Property(property="responsavel_firma_id", type="integer", example=6), * @OA\Property(property="responsavel_tecnico_id", type="integer", example=7), * @OA\Property(property="data", type="string", format="date", example="2025-08-07"), * @OA\Property(property="prazo_inicial", type="string", format="date", example="2025-08-07"), * @OA\Property(property="is_fornecimento", type="boolean", example=true), * @OA\Property(property="is_habilitado", type="boolean", example=true) * ) * ), * * @OA\Response(response=200, description="Obra atualizada com sucesso") * ) */ public function update(UpdateObraRequest $request, Obra $obra) { $this->authorize('update', Obra::class); $obra->update($request->validated()); if ($request->has('organizations')) { $obra->organizations()->delete(); foreach ($request->organizations as $organization) { $obra->organizations()->create([ 'organization_id' => $organization['organization_id'], ]); } } if ($request->has('unid_orcamentarias')) { $obra->unidOrcamentarias()->delete(); foreach ($request->unid_orcamentarias as $unidOrcamentaria) { $obra->unidOrcamentarias()->create([ 'organization_id' => $unidOrcamentaria['organization_id'], ]); } } if ($request->has('unid_fiscalizadoras')) { $obra->unidFiscalizadoras()->delete(); foreach ($request->unid_fiscalizadoras as $unidFiscalizadora) { $obra->unidFiscalizadoras()->create([ 'organization_id' => $unidFiscalizadora['organization_id'], ]); } } return response()->json($obra->load(['historicos']), Response::HTTP_OK); } /** * @OA\Patch( * path="/api/obras/{obra}/remove-fiscais", * summary="Remove fiscais de obra", * operationId="RemoveFiscaisObra", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter(name="obra", in="path", required=true, @OA\Schema(type="integer")), * * @OA\RequestBody(required=true, @OA\JsonContent( * * @OA\Property(property="fiscais", type="array", @OA\Items(type="object")) * )), * * @OA\Response(response=200, description="Fiscais removidos com sucesso") * ) */ public function removeFiscais(Request $request, Obra $obra) { $this->authorize('update', Obra::class); $this->validate($request, [ 'fiscais' => 'required|array', 'fiscais.*.motivo' => 'required|string', 'fiscais.*.responsavel_fiscalizacao_id' => 'required|string', ]); foreach ($request->fiscais as $fiscal) { $obra->historicos()->create([ 'campo' => 'responsavel_fiscalizacao_id', 'titulo' => 'Ocorreu remoção do responsavel pela Fiscalização da Obra.', 'descricao' => $fiscal['motivo'], 'valor_antigo' => $fiscal['responsavel_fiscalizacao_id'], 'valor_novo' => null, ]); ObraFiscal::where('responsavel_fiscalizacao_id', $fiscal['responsavel_fiscalizacao_id'])->delete(); } return response()->json($obra->load(['historicos', 'fiscais']), JsonResponse::HTTP_OK); } /** * @OA\Patch( * path="/api/obras/{obra}/add-fiscais", * summary="Adiciona fiscais à obra", * operationId="AddFiscaisObra", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter(name="obra", in="path", required=true, @OA\Schema(type="integer")), * * @OA\RequestBody(required=true, @OA\JsonContent( * * @OA\Property(property="fiscais", type="array", @OA\Items(type="object")) * )), * * @OA\Response(response=200, description="Fiscais adicionados com sucesso") * ) */ public function addFiscais(Request $request, Obra $obra) { $this->authorize('update', Obra::class); $this->validate($request, [ 'fiscais' => 'required|array', 'fiscais.*.motivo' => 'required|string', 'fiscais.*.responsavel_fiscalizacao_id' => 'required|string', 'fiscais.*.nome', 'fiscais.*.document', ]); foreach ($request->fiscais as $fiscal) { $exists = ObraFiscal::where('obra_id', $obra->id) ->where('responsavel_fiscalizacao_id', $fiscal['responsavel_fiscalizacao_id']) ->exists(); if ($exists) { continue; } $obra->historicos()->create([ 'campo' => 'responsavel_fiscalizacao_id', 'titulo' => 'Ocorreu adição do responsavel pela Fiscalização da Obra.', 'descricao' => $fiscal['motivo'], 'valor_antigo' => null, 'valor_novo' => $fiscal['responsavel_fiscalizacao_id'], ]); ObraFiscal::create([ 'responsavel_fiscalizacao_id' => $fiscal['responsavel_fiscalizacao_id'], 'obra_id' => $obra->id, 'nome' => $fiscal['nome'], 'document' => $fiscal['document'], ]); } return response()->json($obra->load(['historicos', 'fiscais']), JsonResponse::HTTP_OK); } /** * @OA\Delete( * path="/api/obras/{obra}", * summary="Remove obra", * operationId="DeleteObra", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter(name="obra", in="path", required=true, @OA\Schema(type="integer")), * * @OA\Response(response=204, description="Obra removida com sucesso") * ) */ public function destroy(Obra $obra) { $this->authorize('delete', Obra::class); $obra->organizations()->delete(); $obra->unidOrcamentarias()->delete(); $obra->unidFiscalizadoras()->delete(); $obra->delete(); return response()->json([], JsonResponse::HTTP_NO_CONTENT); } /** * @OA\Get( * path="/api/obras/{obra}/campos-ocultos", * summary="Campos privados da obra", * operationId="ShowObraPrivateFields", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter(name="obra", in="path", required=true, @OA\Schema(type="integer")), * * @OA\Response(response=200, description="Campos privados retornados com sucesso") * ) */ public function showPrivateFields(Obra $obra) { $privateFieldService = new PrivateFieldService; return $privateFieldService->show($obra); } /** * @OA\Post( * path="/api/obras/{obra}/campos-ocultos", * summary="Atualiza campos privados da obra", * operationId="SetObraPrivateFields", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter( * name="obra", * in="path", * required=true, * * @OA\Schema(type="integer") * ), * * @OA\RequestBody( * required=true, * * @OA\JsonContent( * type="object", * * @OA\Property( * property="fields", * type="array", * * @OA\Items(type="string", nullable=true), * example={null} * ) * ) * ), * * @OA\Response( * response=200, * description="Campos privados atualizados com sucesso" * ) * ) */ public function setPrivateFields(StorePrivateFieldRequest $request, Obra $obra) { $privateFieldService = new PrivateFieldService; return $privateFieldService->setPrivateFields($request, $obra); } /** * @OA\Post( * path="/api/obras/{obra}/store-image", * summary="Adiciona imagem à obra", * operationId="StoreObraImage", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter( * name="obra", * in="path", * required=true, * * @OA\Schema(type="integer") * ), * * @OA\RequestBody( * required=true, * * @OA\MediaType( * mediaType="multipart/form-data", * * @OA\Schema( * type="object", * required={"image"}, * * @OA\Property( * property="image", * type="string", * format="binary", * description="Imagem da obra (jpeg, png, jpg, gif)" * ), * @OA\Property( * property="description", * type="string", * description="Descrição da imagem (opcional)", * example="Uma descrição detalhada da obra" * ) * ) * ) * ), * * @OA\Response( * response=201, * description="Imagem adicionada com sucesso" * ), * @OA\Response( * response=400, * description="Requisição inválida" * ) * ) */ public function storeImage(StoreImageRequest $request, Obra $obra) { $imageService = new ImageService; $image = $imageService->storeImage($request, $obra); return response()->json($image, Response::HTTP_CREATED); } /** * @OA\Get( * path="/api/obras/{obra}/show-image", * summary="Lista imagens da obra", * operationId="ShowObraImages", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter(name="obra", in="path", required=true, @OA\Schema(type="integer")), * * @OA\Response(response=200, description="Imagens retornadas com sucesso") * ) */ public function showModelImages(Obra $obra) { $imageService = new ImageService; $images = $imageService->showModelImages($obra); return response()->json($images, Response::HTTP_OK); } /** * @OA\Post( * path="/api/obras/{obra}/store-file", * summary="Adiciona arquivo à obra", * operationId="StoreObraFile", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter( * name="obra", * in="path", * required=true, * * @OA\Schema(type="integer") * ), * * @OA\RequestBody( * required=true, * * @OA\MediaType( * mediaType="multipart/form-data", * * @OA\Schema( * type="object", * required={"arquivo"}, * * @OA\Property( * property="arquivo", * type="string", * format="binary", * description="Arquivo PDF a ser enviado" * ), * @OA\Property( * property="is_public", * type="boolean", * description="Se o arquivo será público ou não (opcional)" * ) * ) * ) * ), * * @OA\Response( * response=201, * description="Arquivo adicionado com sucesso" * ) * ) */ public function storeFile(StoreArquivoRequest $request, Obra $obra) { $arquivoService = new ArquivoService; $arquivo = $arquivoService->storeFile($request, $obra); return response()->json($arquivo, Response::HTTP_CREATED); } /** * @OA\Get( * path="/api/obras/{obra}/show-file", * summary="Lista arquivos da obra", * operationId="ShowObraFiles", * tags={"Obra"}, * security={{"bearerAuth":{}}}, * * @OA\Parameter(name="obra", in="path", required=true, @OA\Schema(type="integer")), * * @OA\Response(response=200, description="Arquivos retornados com sucesso") * ) */ public function showModelFiles(Obra $obra) { $arquivoService = new ArquivoService; $arquivos = $arquivoService->showModelFiles($obra); return response()->json($arquivos, Response::HTTP_OK); } public function porcentagemObra(Obra $obra) { if (! auth()->check()) { if (! $obra->is_habilitado) { return response()->json([], Response::HTTP_UNAUTHORIZED); } else { } $obra->load('notasFiscais'); $valorAjustado = $obra->valor_ajustado; $valorPago = $obra->notasFiscais->sum('valor'); $porcentagem = $valorAjustado > 0 ? ($valorPago / $valorAjustado) : 0; $porcentagemPercent = round($porcentagem * 100, 2); return response()->json([ 'porcentagem' => $porcentagemPercent, ], Response::HTTP_OK); } $obra->load('notasFiscais'); $valorAjustado = $obra->valor_ajustado; $valorPago = $obra->notasFiscais->sum('valor'); $porcentagem = $valorAjustado > 0 ? ($valorPago / $valorAjustado) : 0; $porcentagemPercent = round($porcentagem * 100, 2); return response()->json([ 'porcentagem' => $porcentagemPercent, ], Response::HTTP_OK); } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.28 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings