---
id: migration-19-internship-requests
title: Migration 19 — internship_requests
description: Contrato da solicitação única de abertura de estágio preenchida pelo discente.
type: migration-reference
status: implemented
visibility: public
tags: sge/migrations, sge/estagio, sge/formularios
related: enum-legalcapacitydeclaration, enum-internshiprequeststatus, migration-base-04-activity-log, migration-19a-emancipation-evidences, cadastros-pendentes-de-supervisor-e-concedente, backlog-e-decisoes, migration-04-affiliations, migration-09-courses, migration-11-internship-types, migration-12-granting-parties, migration-12a-supervisor-registration-requests, migration-12b-granting-party-registration-requests, migration-15-internships, migration-20-internship-request-corrections
source_refs:
---
> [!success] Estado
> Migration, Model, factory, relações e testes PostgreSQL implementados. A tabela vem depois de `internships` por causa da FK única `internship_id`; o fluxo de envio, análise, aceite e criação transacional do estágio ainda será implementado.

## Contrato

| Campo | Regra |
| --- | --- |
| `id` | bigint, chave primária. |
| `affiliation_id` | FK obrigatória para o vínculo discente dono da solicitação. |
| `course_id` | FK obrigatória fora de `Draft`; o curso deve estar disponível no contexto do vínculo. |
| `internship_type_id` | FK obrigatória fora de `Draft`; o tipo deve estar ativo e pertencer ao curso selecionado. |
| `advisor_affiliation_id` | FK nullable enquanto o Setor ainda não atribuiu orientador; obrigatória no aceite. |
| `granting_party_id` | FK nullable para concedente validada do campus do vínculo discente. |
| `granting_party_registration_request_id` | FK nullable para solicitação pendente do mesmo campus; é alternativa a `granting_party_id`, nunca texto livre solto. |
| `supervisor_affiliation_id` | FK nullable para o supervisor já cadastrado. |
| `supervisor_registration_request_id` | FK nullable para a solicitação pendente de cadastro; é alternativa a `supervisor_affiliation_id`. |
| `student_year_semester` | string nullable em `Draft`; período/semestre declarado pelo discente e congelado no snapshot no aceite. |
| `legal_capacity_declaration` | [`LegalCapacityDeclaration`](doc:enum-legalcapacitydeclaration) nullable em `Draft`; rádio obrigatório no envio: maior, menor ou menor emancipado. |
| `legal_guardian_name` | texto nullable; obrigatório quando a opção for `minor`. |
| `legal_guardian_cpf` | `varchar(255)` nullable; obrigatório quando a opção for `minor`, normalizado e validado pelo `CpfCast`. |
| `legal_guardian_kinship` | `varchar(80)` nullable; obrigatório quando a opção for `minor`. |
| `legal_guardian_email` | `varchar(255)` nullable; obrigatório quando a opção for `minor`. |
| `activities` | texto nullable em `Draft`; obrigatório no envio. |
| `internship_sector` | texto nullable; setor/área de realização, obrigatório se a concedente ou o tipo o exigir. |
| `weekly_hours` | JSONB nullable em `Draft`; mapa validado com domingo a sábado. |
| `planned_start_date` | data nullable em `Draft`; obrigatória no envio e usada para calcular o término. |
| `projected_end_date` | data nullable calculada no servidor; nunca editável pelo discente. |
| `is_remunerated` | boolean nullable em `Draft`; obrigatório no envio. |
| `grant_value` | decimal(10,2) nullable; bolsa obrigatória e positiva se remunerado. |
| `transportation_allowance` | decimal(10,2) nullable; auxílio pode ser zero ou nulo. |
| `observations` | texto nullable; observações complementares. |
| `status` | [`InternshipRequestStatus`](doc:enum-internshiprequeststatus): rascunho, enviada, em análise, com pendência, aceita, recusada ou desistida. |
| `internship_id` | FK nullable e única para o estágio criado depois do aceite. |
| `terms_accepted_at` | data e hora do aceite explícito; nulo antes do primeiro envio e atualizado em cada reenvio. Não há coluna de versão, hash ou booleano. |
| timestamps | auditoria temporal. |

Há somente uma solicitação para o processo aberto pelo discente. Ela é atualizada no mesmo registro quando o discente salva ou responde uma pendência; o Livewire pode persistir valores nulos enquanto estiver em `Draft`. Nos demais estados, todos os campos obrigatórios do caminho condicional escolhido devem estar válidos; campos de ramos não escolhidos continuam nulos. O Model registra criação e alterações no [`activity_log`](doc:migration-base-04-activity-log); com o vínculo ativo como autor em requisições autenticadas; Actions e Policies para o fluxo de análise ainda estão pendentes. Os Models validam que a concedente ou pedido pendente referenciado pertence ao campus do vínculo discente. Não há FK de revisor nesta tabela. Ao ser aceita pela primeira vez, os valores validados criam `internships`, que preserva `student_affiliation_id = affiliation_id`, as demais FKs, a jornada inicial e os snapshots históricos próprios. Se a solicitação já possuir `internship_id`, uma correção aprovada atualiza apenas os campos autorizados do estágio existente, recalcula os derivados e preserva os documentos anteriores no histórico.

### Contrato de `weekly_hours`

```json
{
  "sunday": 0,
  "monday": 4,
  "tuesday": 4,
  "wednesday": 4,
  "thursday": 4,
  "friday": 4,
  "saturday": 0
}
```

As sete chaves sempre existem quando o formulário é enviado; cada valor é inteiro não negativo em horas. A soma semanal deve ser positiva. Para o tipo selecionado, cada dia deve respeitar `internship_types.max_daily_hours` e a soma da semana deve respeitar `internship_types.max_weekly_hours`. Na configuração do tipo, esses limites começam em 6 horas diárias e 30 semanais e podem ser aumentados, nunca reduzidos. `projected_end_date` deverá ser calculada pelo fluxo a partir desta jornada, da carga exigida do tipo, do calendário nacional, estadual e municipal aplicável ao endereço do local de trabalho e das pausas posteriormente registradas. Por enquanto, o Model exige a data preenchida fora de `Draft` e valida que ela não antecede o início; o cálculo automático ainda não existe.

### Caminhos condicionais de cadastro

- Concedente: exatamente uma de `granting_party_id` ou `granting_party_registration_request_id` deve ser informada no envio. A concedente ou solicitação deve pertencer ao campus do vínculo discente, conferido no servidor. A segunda aponta para um registro próprio, com documento, endereço, representante, contatos, área, conselho e processo, aguardando análise do Setor. CPF/CNPJ iguais em outro cadastro não autorizam reutilizá-lo entre campi.
- Supervisor: exatamente uma de `supervisor_affiliation_id` ou `supervisor_registration_request_id` deve ser informada no envio. A segunda preserva nome, CPF, telefone, e-mail, cargo, qualificação, formação e experiência propostos pelo discente até que o Setor crie/associe o vínculo de supervisor. O supervisor completa ou confirma seus dados profissionais atuais em `user_personal_data` no futuro fluxo do formulário.
- Capacidade civil: o rádio oferece `adult`, `minor` e `emancipated_minor`. `adult` só é válido para quem tiver 18 anos completos na data do envio. `minor` exige os quatro campos de responsável legal. `emancipated_minor` dispensará responsável legal e exigirá ao menos uma [evidência](doc:migration-19a-emancipation-evidences) enviada; o aceite final exigirá evidência aprovada pelo Setor. A Migration 19A já implementa no Model a exigência de anexo no envio e de evidência aprovada no aceite; a análise manual e a autorização ficam para o fluxo. Se a devolução apontar comprovante inválido, o discente cria novo envio ou troca para `minor` e informa o responsável.
- Remuneração: `is_remunerated = true` exige `grant_value`; se for `false`, ambos os valores monetários ficam nulos, salvo decisão posterior que admita auxílio sem bolsa.

As duas solicitações pendentes de cadastro são estruturas de domínio próprias, conforme [Cadastros pendentes de supervisor e concedente](doc:cadastros-pendentes-de-supervisor-e-concedente) e [D-011](doc:backlog-e-decisoes#d-011-solicitacoes-pendentes-sao-registros-proprios); não são JSON genérico nem notificações. As migrations que as criam devem preceder a FK desta tabela. As duas migrations de cadastro pendente já existem no código; esta tabela usa somente FKs para esses caminhos.

## Validações do formulário

- `affiliation_id` deve ser o vínculo discente ativo e autorizado;
- o curso deve ser elegível para o vínculo;
- ao escolher um curso, a interface apresenta apenas seus tipos de estágio ativos: um tipo é selecionado automaticamente quando for único; mais de um exige seleção explícita;
- a validação no servidor confirma a relação entre curso e tipo, exige que os limites configurados no tipo sejam de pelo menos 6 horas diárias e 30 semanais e valida a jornada diária e semanal contra esses limites;
- a parte concedente deve estar cadastrada antes de ser aceita; o número de processo de credenciamento é opcional e preenche o documento quando aplicável;
- a data prevista de término é calculada, e não digitada, a partir do tipo e da jornada.
- envio e reenvio exigirão checkbox explícito de ciência na interface; somente a data e hora do aceite serão persistidas em `terms_accepted_at`.

## Checklist

- [x] Definir uma solicitação única pertencente ao vínculo discente.
- [x] Definir a associação única com o estágio criado após o aceite.
- [x] Definir curso, tipo e parte concedente como referências validadas.
- [x] Separar o enum de status da solicitação do status de `internships`.
- [x] Mapear todas as colunas do formulário de abertura e seus casts.
- [x] Fechar os critérios de validação da parte concedente e do supervisor pendentes.
- [x] Especificar as migrations tipadas das solicitações de cadastro pendente antes desta migration.
- [x] Definir o histórico privado de evidências e o aceite das normas por data e hora.
- [x] Criar migration, Model, factory, relações, índice por vínculo/status e FK única para o estágio.
- [ ] Criar Policies e fluxos de envio, análise, aceite e reenvio.
- [x] Testar no Model a compatibilidade de curso/tipo, os limites de carga horária e os ramos condicionais.
- [ ] Implementar seleção na interface, cálculo da data projetada e fluxo de análise da evidência de emancipação e autorização por vínculo.

## Dependências

- [affiliations](doc:migration-04-affiliations)
- [courses](doc:migration-09-courses)
- [internship_types](doc:migration-11-internship-types)
- [granting_parties](doc:migration-12-granting-parties)
- [supervisor_registration_requests](doc:migration-12a-supervisor-registration-requests)
- [granting_party_registration_requests](doc:migration-12b-granting-party-registration-requests)
- [internships](doc:migration-15-internships)
- [correções de solicitações](doc:migration-20-internship-request-corrections)
- [provas de emancipação](doc:migration-19a-emancipation-evidences)
