Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions backend/src/modulos/cursos/repositorio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,16 @@ export async function coordenadorTemCurso(coordenadorId: string, cursoId: string
return (res.rowCount ?? 0) > 0;
}

// Vincula um coordenador a um curso (idempotente)
export async function vincularCoordenadorAoCurso(coordenadorId: string, cursoId: string): Promise<void> {
await pool.query(
`INSERT INTO coordenadores_cursos (coordenador_id, curso_id)
VALUES ($1, $2)
ON CONFLICT DO NOTHING`,
[coordenadorId, cursoId],
);
}

// Lista os estudantes vinculados a um curso (somente leitura)
export async function listarAlunosDoCurso(cursoId: string): Promise<AlunoDoCurso[]> {
const res = await pool.query<AlunoDoCurso>(
Expand Down
9 changes: 9 additions & 0 deletions backend/src/modulos/usuarios/rotas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import bcrypt from 'bcryptjs';
import { autenticar } from '../../middleware/autenticacao';
import { exigirPerfil } from '../../middleware/autorizacao';
import * as repositorio from './repositorio';
import { vincularCoordenadorAoCurso } from '../cursos/repositorio';
import { tratarErro } from '../../utils/erros';

const router = Router();
Expand Down Expand Up @@ -189,6 +190,10 @@ router.post('/', autenticar, exigirPerfil('admin'), async (req, res) => {
curso_id: curso_id || null,
});

if (perfil === 'coordenador' && curso_id) {
await vincularCoordenadorAoCurso(usuario.id, curso_id);
}

res.status(201).json(usuario);
} catch (err: unknown) {
tratarErro(res, err, 'usuarios/criar');
Expand Down Expand Up @@ -247,6 +252,10 @@ router.put('/:id', autenticar, exigirPerfil('admin'), async (req, res) => {
return;
}

if (usuario.perfil === 'coordenador' && usuario.curso_id) {
await vincularCoordenadorAoCurso(usuario.id, usuario.curso_id);
}

res.json(usuario);
} catch (err: unknown) {
tratarErro(res, err, 'usuarios/atualizar');
Expand Down
10 changes: 10 additions & 0 deletions infra/migrations/005_backfill_coordenadores_cursos.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- Migration 005: Re-sincroniza coordenadores_cursos para coordenadores
-- que possuem curso_id em usuarios mas não têm entrada na tabela de vínculo.
--
-- Aplicar:
-- psql -U postgres -d valida_db -f infra/migrations/005_backfill_coordenadores_cursos.sql

INSERT INTO coordenadores_cursos (coordenador_id, curso_id)
SELECT id, curso_id FROM usuarios
WHERE perfil = 'coordenador' AND curso_id IS NOT NULL
ON CONFLICT DO NOTHING;
Loading