diff --git a/.env.example b/.env.example index 00044c6..10958ce 100644 --- a/.env.example +++ b/.env.example @@ -167,3 +167,13 @@ WSFOTO_PASS= # Caminho para o arquivo de imagem desejada para ser utilizada # como a foto fake WS_FOTO_FAKE_PATH= + + + +# Configurações específicas da aplicação ################################ + +# Define quais códigos de habilitação serão considerados pela aplicação. +# Na EESC somente as com codhab = 0, default +CODHABS=0 +# Na ECA são consideradas as com codhab terminando em 0, 2 e 4 +# CODHABS=0,2,4 \ No newline at end of file diff --git a/app/Http/Controllers/EquivalenciaController.php b/app/Http/Controllers/EquivalenciaController.php index fc5a872..ec3a391 100644 --- a/app/Http/Controllers/EquivalenciaController.php +++ b/app/Http/Controllers/EquivalenciaController.php @@ -5,19 +5,55 @@ use App\Http\Requests\StoreEquivalenciaRequest; use App\Http\Requests\UpdateEquivalenciaRequest; use App\Models\Equivalencia; -use Symfony\Component\HttpFoundation\Request; +use App\Replicado\Graduacao; +use Illuminate\Http\Request; use Uspdev\Forms\Form; -use Uspdev\Replicado\Graduacao; class EquivalenciaController extends Controller { + public function __construct() + { + // Adiciona o middleware para marcar a URL ativa no menu da aplicação, utilizando o pacote Uspdev/Theme. + $this->middleware(function ($request, $next) { + \UspTheme::activeUrl('equivalencias'); + + return $next($request); + }); + } + /** - * Display a listing of the resource. + * Lista os cursos e habilitações disponíveis para cadastro de equivalências. + * Cada curso/habilitação é um link que leva para a página de disciplinas + * USP equivalentes cadastradas para aquele curso/habilitação. */ - public function index() + public function cursos() { + $cursos = Graduacao::listarCursosHabilitacoes(); + + return view('equivalencias.cursos', [ + 'cursos' => $cursos, + ]); + } + + /** + * Exibe a lista de disciplinas USP equivalentes para um curso/habilitação específico. + * Pega o codcur e codhab da rota, + * busca as disciplinas USP equivalentes cadastradas para esse curso/habilitação, + * e retorna para a view. A view é responsável por exibir as disciplinas USP + * e os formulários para criar/editar as disciplinas USP e adicionar/remover equivalências. + */ + public function index(int $codcur, int $codhab) + { + + $curso = collect(Graduacao::listarCursosHabilitacoes()) + ->first(fn ($item) => (int) $item['codcur'] === $codcur && (int) $item['codhab'] === $codhab); + + abort_unless($curso, 404); + $disciplinas = Equivalencia::query() ->usp() + ->where('codcur', $codcur) + ->where('codhab', $codhab) ->with(['equivalentes' => function ($query) { $query->orderBy('coddis'); }]) @@ -26,9 +62,12 @@ public function index() return view('equivalencias.index', [ 'disciplinas' => $disciplinas, + 'codcur' => $codcur, + 'codhab' => $codhab, + 'nomeCurso' => $curso['nomcur'], 'formHtmlCreate' => $this->buildFormHtml( 'eq_usp_create', - route('equivalencias.store'), + route('equivalencias.store', ['codcur' => $codcur, 'codhab' => $codhab]), 'POST', $this->oldInputForFields(['coddis']) ), @@ -36,28 +75,38 @@ public function index() } /** - * Store a newly created resource in storage. + * Armazena uma nova disciplina USP equivalente para um curso/habilitação específico. + * Pega o codcur e codhab da rota, valida os dados do formulário utilizando a StoreEquivalenciaRequest, + * preenche os dados da disciplina USP com as informações do Replicado */ - public function store(StoreEquivalenciaRequest $request) + public function store(StoreEquivalenciaRequest $request, int $codcur, int $codhab) { $dados = $request->validated(); $dados['equivalencias_id'] = null; $dados['tipo'] = Equivalencia::TIPO_AUTOMATICA; + $dados['codcur'] = $codcur; + $dados['codhab'] = $codhab; $dados = $this->preencherDadosDisciplinaUsp($dados); $equivalencia = Equivalencia::create($dados); return redirect() - ->route('equivalencias.show', $equivalencia) + ->route('equivalencias.show', [$codcur, $codhab, $equivalencia]) ->with('alert-success', 'Disciplina USP criada com sucesso.'); } /** * Display the specified resource. */ - public function show(Equivalencia $equivalencia) + public function show(int $codcur, int $codhab, Equivalencia $equivalencia) { abort_unless($equivalencia->isUsp(), 404); + abort_unless($this->equivalenciaPertenceAoCurso($equivalencia, $codcur, $codhab), 404); + + $curso = collect(Graduacao::listarCursosHabilitacoes()) + ->first(fn ($item) => (int) $item['codcur'] === $codcur && (int) $item['codhab'] === $codhab); + + abort_unless($curso, 404); $equivalencia->load(['equivalentes' => function ($query) { $query->orderBy('coddis'); @@ -66,93 +115,149 @@ public function show(Equivalencia $equivalencia) return view('equivalencias.show', [ 'disciplina' => $equivalencia, 'equivalencias' => $equivalencia->equivalentes, - 'formHtmlEdit' => $this->addHiddenModalField( - $this->buildFormHtml( - 'eq_usp_edit', - route('equivalencias.update', $equivalencia), - 'PUT', - $this->oldInputForFields( - ['coddis'], - ['coddis' => $equivalencia->coddis] - ) - ), - 'equivalencia-edit' + 'nomeCurso' => $curso['nomcur'], + 'formHtmlEdit' => $this->buildFormHtml( + 'eq_usp_edit', + route('equivalencias.update', [$codcur, $codhab, $equivalencia]), + 'PUT', + $this->oldInputForFields( + ['coddis'], + ['coddis' => $equivalencia->coddis] + ) ), 'formHtmlEquivalencia' => $this->buildFormHtml( 'eq_child_add', - route('equivalencias.add-equivalencia', $equivalencia), + route('equivalencias.add-equivalencia', [$codcur, $codhab, $equivalencia]), 'POST', $this->oldInputForFields([ 'coddis', 'nome_disciplina', 'ies', - 'creditos', - 'carga_horaria', ]) ), + 'formHtmlEquivalenciaEdit' => $equivalencia->equivalentes + ->mapWithKeys(function (Equivalencia $equivalenciaFilha) use ($codcur, $codhab, $equivalencia) { + return [ + $equivalenciaFilha->id => $this->buildFormHtml( + 'eq_child_add', + route('equivalencias.update-equivalencia', [$codcur, $codhab, $equivalencia, $equivalenciaFilha]), + 'PUT', + [ + 'coddis' => $equivalenciaFilha->coddis, + 'nome_disciplina' => $equivalenciaFilha->nome_disciplina, + 'ies' => $equivalenciaFilha->ies, + ] + ), + ]; + }) + ->all(), + 'codcur' => $codcur, + 'codhab' => $codhab, ]); } /** * Update the specified resource in storage. */ - public function update(UpdateEquivalenciaRequest $request, Equivalencia $equivalencia) + public function update(UpdateEquivalenciaRequest $request, int $codcur, int $codhab, Equivalencia $equivalencia) { abort_unless($equivalencia->isUsp(), 404); + abort_unless($this->equivalenciaPertenceAoCurso($equivalencia, $codcur, $codhab), 404); $dados = $request->validated(); $dados['tipo'] = Equivalencia::TIPO_AUTOMATICA; + $dados['codcur'] = $codcur; + $dados['codhab'] = $codhab; $dados = $this->preencherDadosDisciplinaUsp($dados, $equivalencia->coddis); $equivalencia->update($dados); return redirect() - ->route('equivalencias.show', $equivalencia) + ->route('equivalencias.show', [$codcur, $codhab, $equivalencia]) ->with('alert-success', 'Disciplina USP atualizada com sucesso.'); } /** - * Remove the specified resource from storage. + * Deleta a disciplina USP, o que também deleta as equivalências + filhas devido à relação de chave estrangeira com cascade on delete */ - public function destroy(Equivalencia $equivalencia) + public function destroy(int $codcur, int $codhab, Equivalencia $equivalencia) { abort_unless($equivalencia->isUsp(), 404); + abort_unless($this->equivalenciaPertenceAoCurso($equivalencia, $codcur, $codhab), 404); $equivalencia->delete(); return redirect() - ->route('equivalencias.index') + ->route('equivalencias.curso', [$codcur, $codhab]) ->with('alert-success', 'Disciplina USP removida com sucesso.'); } - public function addEquivalencia(Request $request, Equivalencia $equivalencia) + /** + * Adiciona uma nova disciplina equivalente (filha) para uma disciplina USP (pai). + * Pega o codcur, codhab e a disciplina USP (pai) da rota + */ + public function addEquivalencia(Request $request, int $codcur, int $codhab, Equivalencia $equivalencia) { abort_unless($equivalencia->isUsp(), 404); + abort_unless($this->equivalenciaPertenceAoCurso($equivalencia, $codcur, $codhab), 404); $request['equivalencias_id'] = $equivalencia->id; $request['tipo'] = Equivalencia::TIPO_CURSADA; + $request['codcur'] = $codcur; + $request['codhab'] = $codhab; Equivalencia::create($request->all()); return redirect() - ->route('equivalencias.show', $equivalencia) + ->route('equivalencias.show', [$codcur, $codhab, $equivalencia]) ->with('alert-success', 'Equivalência adicionada com sucesso.'); } - public function destroyEquivalencia(Equivalencia $equivalencia, Equivalencia $equivalenciaFilha) + /** + * Atualiza uma disciplina equivalente (filha) de uma disciplina USP (pai). + */ + public function updateEquivalencia(Request $request, int $codcur, int $codhab, Equivalencia $equivalencia, Equivalencia $equivalenciaFilha) { abort_unless($equivalencia->isUsp(), 404); + abort_unless($this->equivalenciaPertenceAoCurso($equivalencia, $codcur, $codhab), 404); + abort_unless($equivalenciaFilha->isEquivalencia(), 404); + abort_unless($equivalenciaFilha->equivalencias_id === $equivalencia->id, 404); + + $dados = $request->all(); + + $dados['equivalencias_id'] = $equivalencia->id; + $dados['tipo'] = Equivalencia::TIPO_CURSADA; + $dados['codcur'] = $codcur; + $dados['codhab'] = $codhab; + + $equivalenciaFilha->update($dados); + + return redirect() + ->route('equivalencias.show', [$codcur, $codhab, $equivalencia]) + ->with('alert-success', 'Equivalência atualizada com sucesso.'); + } + + /** + * Remove uma disciplina equivalente (filha) de uma disciplina USP (pai). + */ + public function destroyEquivalencia(int $codcur, int $codhab, Equivalencia $equivalencia, Equivalencia $equivalenciaFilha) + { + abort_unless($equivalencia->isUsp(), 404); + abort_unless($this->equivalenciaPertenceAoCurso($equivalencia, $codcur, $codhab), 404); abort_unless($equivalenciaFilha->equivalencias_id === $equivalencia->id, 404); $equivalenciaFilha->delete(); return redirect() - ->route('equivalencias.show', $equivalencia) + ->route('equivalencias.show', [$codcur, $codhab, $equivalencia]) ->with('alert-success', 'Equivalência removida com sucesso.'); } - // Cria um formulário HTML para as views, utilizando a classe Form do pacote Uspdev/Forms. + /** + * Cria o HTML do formulário utilizando o pacote Uspdev/Forms + */ private function buildFormHtml(string $name, string $action, string $method, array $values): string { $form = new Form([ @@ -198,17 +303,20 @@ private function preencherDadosDisciplinaUsp(array $dados, ?string $coddisAtual $dados['creditos'] = $disciplina['creaul'] ?? $dados['creditos'] ?? null; $dados['carga_horaria'] = $disciplina['numhor'] ?? $dados['carga_horaria'] ?? null; $dados['nomcur'] = $disciplina['nomcur'] ?? $dados['nomcur'] ?? null; - $dados['codcur'] = $disciplina['codcur'] ?? $dados['codcur'] ?? null; - $dados['codhab'] = $disciplina['codhab'] ?? $dados['codhab'] ?? null; + $dados['codcur'] = $dados['codcur'] ?? $disciplina['codcur'] ?? null; + $dados['codhab'] = $dados['codhab'] ?? $disciplina['codhab'] ?? null; return $dados; } - private function addHiddenModalField(string $formHtml, string $value): string + // Verifica se a disciplina USP (equivalencia) pertence ao curso e habilitação especificados pelos códigos codcur e codhab. + private function equivalenciaPertenceAoCurso(Equivalencia $equivalencia, int $codcur, int $codhab): bool { - return str_replace('', '', $formHtml); + return (int) $equivalencia->codcur === $codcur + && (int) $equivalencia->codhab === $codhab; } + // Busca os dados da disciplina no Replicado a partir do código da disciplina (coddis). private function buscarDisciplinaNoReplicado(?string $coddis): ?array { if (! $coddis) { diff --git a/app/Http/Requests/StoreEquivalenciaRequest.php b/app/Http/Requests/StoreEquivalenciaRequest.php index ef7fb43..d1a7923 100644 --- a/app/Http/Requests/StoreEquivalenciaRequest.php +++ b/app/Http/Requests/StoreEquivalenciaRequest.php @@ -22,9 +22,16 @@ public function authorize(): bool */ public function rules(): array { + // Obter os parâmetros da rota + $codcur = (int) $this->route('codcur'); + $codhab = (int) $this->route('codhab'); + return [ 'coddis' => [ - Rule::unique('equivalencias')->whereNull('equivalencias_id'), + Rule::unique('equivalencias') + ->whereNull('equivalencias_id') + ->where('codcur', $codcur) + ->where('codhab', $codhab), ], ]; diff --git a/app/Http/Requests/UpdateEquivalenciaRequest.php b/app/Http/Requests/UpdateEquivalenciaRequest.php index ecaa3e6..d479faa 100644 --- a/app/Http/Requests/UpdateEquivalenciaRequest.php +++ b/app/Http/Requests/UpdateEquivalenciaRequest.php @@ -27,12 +27,16 @@ public function rules(): array $equivalenciaId = $equivalencia instanceof Equivalencia ? $equivalencia->id : $equivalencia; + // Obter os parâmetros da rota + $codcur = (int) $this->route('codcur'); + $codhab = (int) $this->route('codhab'); return [ 'coddis' => [ - 'sometimes', Rule::unique('equivalencias') ->whereNull('equivalencias_id') + ->where('codcur', $codcur) + ->where('codhab', $codhab) ->ignore($equivalenciaId), ], ]; diff --git a/app/Replicado/Graduacao.php b/app/Replicado/Graduacao.php new file mode 100644 index 0000000..9dfb705 --- /dev/null +++ b/app/Replicado/Graduacao.php @@ -0,0 +1,45 @@ + explode(',', env('CODHABS', 0)), +]; diff --git a/database/seeders/FormDefinitionsTableSeeder.php b/database/seeders/FormDefinitionsTableSeeder.php index 835efdd..2a82b74 100644 --- a/database/seeders/FormDefinitionsTableSeeder.php +++ b/database/seeders/FormDefinitionsTableSeeder.php @@ -33,7 +33,7 @@ public function run() [21, 'tr_finalizar_enviar', 'equivalencia', null, '[{"name":"obs","type":"texttextarea","label":"Observações sobre finalização","required":false},{"name":"definition_name","type":"hidden","value":"workflowDefinitionName"},{"name":"place","type":"hidden","value":"place_name"},{"name":"transition","type":"hidden","value":"transition_name"}]', '2025-03-17 19:33:49', '2025-03-17 19:33:49'], [22, 'eq_usp_create', 'equivalencia-crud', 'Cadastro de disciplina USP', '[[{"name":"coddis","type":"disciplina-usp","label":"Código da disciplina","required":true}]]', '2025-03-17 19:33:49', '2025-03-17 19:33:49'], [23, 'eq_usp_edit', 'equivalencia-crud', 'Edição de disciplina USP', '[[{"name":"coddis","type":"disciplina-usp","label":"Código da disciplina","required":true}]]', '2025-03-17 19:33:49', '2025-03-17 19:33:49'], - [24, 'eq_child_add', 'equivalencia-crud', 'Cadastro de equivalência', '[[{"name":"coddis","type":"text","label":"Código","maxlength":"7","width":3,"required":true},{"name":"nome_disciplina","type":"text","label":"Nome da equivalência","maxlength":"240","required":true}],[{"name":"ies","type":"text","label":"IES","maxlength":"255","required":true}],[{"name":"creditos","type":"number","label":"Créditos","min":0,"max":20,"width":3,"required":true},{"name":"carga_horaria","type":"number","label":"Carga horária","min":0,"max":1000,"width":3,"required":true}]]', '2025-03-17 19:33:49', '2025-03-17 19:33:49'], + [24, 'eq_child_add', 'equivalencia-crud', 'Cadastro de equivalência', '[[{"name":"coddis","type":"text","label":"Código","maxlength":"7","width":3,"required":true},{"name":"nome_disciplina","type":"text","label":"Nome da equivalência","maxlength":"240","required":true}],[{"name":"ies","type":"text","label":"IES","maxlength":"255","required":true}]]', '2025-03-17 19:33:49', '2025-03-17 19:33:49'], ]; foreach ($formDefinitions as $formDefinition) { diff --git a/resources/views/equivalencias/cursos.blade.php b/resources/views/equivalencias/cursos.blade.php new file mode 100644 index 0000000..8405118 --- /dev/null +++ b/resources/views/equivalencias/cursos.blade.php @@ -0,0 +1,40 @@ +@extends('layouts.app') + +@section('content') +
Nenhum curso/habilitação ativo encontrado.
+ @else +| Curso | +Habilitação | +
|---|---|
| + + {{ $curso['nomcur'] ?? '-' }} ({{ $curso['codcur'] ?? '-' }}) + | +{{ $curso['nomhab'] ?? '-' }} ({{ $curso['codhab'] ?? '-' }}) | + +
| Código | -Nome | +Disciplina requerida | Verdis | -Codcur | -Codhab | Ações |
|---|---|---|---|---|---|---|
| {{ $disciplina->coddis ?: '-' }} | -{{ $disciplina->nome_disciplina ?: '-' }} | +({{ $disciplina->coddis ?: '-' }}) {{ $disciplina->nome_disciplina ?: '-' }} | {{ $disciplina->verdis ?: '-' }} | -{{ $disciplina->codcur ?: '-' }} | -{{ $disciplina->codhab ?: '-' }} |
@include('equivalencias.partials.modal-edit')
- |