{
  "id": "migration-12a-supervisor-registration-requests",
  "title": "Migration 12A — supervisor_registration_requests",
  "description": "Solicitações tipadas de cadastro de supervisor feitas durante a abertura.",
  "type": "migration-reference",
  "status": "implemented",
  "visibility": "public",
  "tags": [
    "sge/migrations",
    "sge/cadastro"
  ],
  "related": [
    "migration-02-user-personal-data",
    "migration-04-affiliations",
    "migration-12-granting-parties",
    "enum-registrationrequeststatus",
    "migration-19-internship-requests"
  ],
  "sourceRefs": [
    "https://github.com/sge-suite/sge/blob/master/database/migrations/2026_09_23_162229_create_supervisor_registration_requests_table.php",
    "https://github.com/sge-suite/sge/blob/master/app/Models/SupervisorRegistrationRequest.php",
    "https://github.com/sge-suite/sge/blob/master/database/factories/SupervisorRegistrationRequestFactory.php",
    "https://github.com/sge-suite/sge/blob/master/tests/Feature/SupervisorRegistrationRequestTest.php"
  ],
  "authors": [],
  "updated": null,
  "diagram": null,
  "body": "> [!success] Estado\n> Migration, Model, factory, relação com o vínculo resultante, casts, validação e testes PostgreSQL implementados. O fluxo transacional de aprovação e a Migration 12B permanecem fora desta etapa.\n\n## Finalidade\n\nEsta tabela guarda o pedido de cadastro quando o discente não seleciona um vínculo de supervisor já existente na abertura. Ela preserva os dados informados e a decisão do Setor como histórico da proposta. `users` guarda a identidade, e `user_personal_data` guarda os dados pessoais e profissionais atuais compartilhados pela conta.\n\nNa Migration 19, a solicitação de estágio aponta diretamente para um vínculo de supervisor existente ou para este pedido pendente. Após a análise, a aprovação deve associar um vínculo existente ou criar/associar `User` e `Affiliation` do tipo `Supervisor` na mesma transação, gravar `supervisor_affiliation_id` e marcar o pedido como `Approved`. Antes do aceite do estágio, a solicitação de estágio troca a referência pendente pela FK do vínculo resultante. Recusa e cancelamento preservam o pedido e seu motivo.\n\n## Schema PostgreSQL\n\n| Campo | Tipo e regra |\n| --- | --- |\n| `id` | `bigint`, chave primária. |\n| `cpf` | `varchar(255)` nullable no banco; obrigatório fora de `Draft`, validado e normalizado pelo `CpfCast`. O banco não limita o comprimento. |\n| `name`, `phone`, `email`, `job_role`, `qualification` | `varchar(255)` nullable no banco; no Model são obrigatórios e validados fora de `Draft`. |\n| `training`, `professional_experience` | `text` nullable e opcionais. |\n| `status` | `varchar(255)` obrigatório, convertido pelo cast PHP `RegistrationRequestStatus`. |\n| `supervisor_affiliation_id` | `bigint` nullable, única FK para `affiliations`, com `ON DELETE RESTRICT`; deve ser vínculo do tipo `Supervisor` e é obrigatório em `Approved`. |\n| `reviewed_at` | `timestamp(0)` nullable, convertido para datetime. |\n| `decision_reason` | `text` nullable; obrigatório em `Rejected` e `Cancelled`. |\n| `created_at`, `updated_at` | timestamps nativos do Laravel. |\n\nO schema cria somente a chave primária e a FK do vínculo resultante. Não há FKs de autoria ou de revisor nesta tabela, índices secundários, unicidade ou constraints `CHECK`. A solicitação de estágio da Migration 19 identifica o vínculo discente responsável pelo envio. O Model participa do Activity Log Eloquent e registra a autoria conforme o contexto da requisição; as Actions e Policies da análise ainda estão pendentes. O Model bloqueia a exclusão pelo Eloquent; não existe coluna `deleted_at`.\n\n## Model, relação e validação\n\n`SupervisorRegistrationRequest` relaciona-se com a `Affiliation` do supervisor resultante; `Affiliation` expõe a relação inversa. O Model usa os casts de `RegistrationRequestStatus`, `CpfCast`, `PhoneCast` e datetime.\n\nNo evento `saving`, nome, CPF, telefone, e-mail, cargo e qualificação podem ficar nulos somente em `Draft`; nos demais status exigem conteúdo válido. O `CpfCast` valida CPF brasileiro e o persiste apenas com dígitos; o telefone usa o `PhoneCast` existente e também é persistido apenas com dígitos. Treinamento e experiência profissional são opcionais. Aprovação exige uma FK para vínculo do tipo `Supervisor`; recusa e cancelamento exigem motivo. Não há transições de status ou fluxo de análise nesta migration.\n\nA identidade da conta fica em `users`, que possui CPF único, nome e e-mail. O pedido guarda o CPF informado pelo discente, sem unicidade própria; na criação da conta, a unicidade de `users.cpf` continua sendo a regra final. A associação a uma conta ou vínculo existente e a criação transacional pertencem ao fluxo futuro. Os campos profissionais atuais pertencem a `user_personal_data`; o usuário supervisor poderá preenchê-los ou confirmá-los no futuro formulário, após a criação da conta e do vínculo. A autorização de edição por tipo de vínculo e a composição do snapshot do estágio serão implementadas no fluxo funcional.\n\n## Auditoria\n\nA tabela não duplica os campos de negócio em JSONB. O Activity Log registra os campos configurados no Model e a autoria disponível no contexto; respostas de consultas externas não são persistidas nesta tabela.\n\n## Testes verificados\n\n`tests/Feature/SupervisorRegistrationRequestTest.php` cobre tipos do schema PostgreSQL, a FK resultante e exclusões, casts e relação, estados `Draft` e não-`Draft`, obrigatoriedade e validação dos campos, CPF normalizado, motivos de decisão, associação de supervisor em `Approved` e rollback/reaplicação da migration. Os testes afetados são executados por Sail.",
  "sections": [
    {
      "id": "finalidade",
      "level": 2,
      "title": "Finalidade",
      "text": "Esta tabela guarda o pedido de cadastro quando o discente não seleciona um vínculo de supervisor já existente na abertura. Ela preserva os dados informados e a decisão do Setor como histórico da proposta. `users` guarda a identidade, e `user_personal_data` guarda os dados pessoais e profissionais atuais compartilhados pela conta.  Na Migration 19, a solicitação de estágio aponta diretamente para um vínculo de supervisor existente ou para este pedido pendente. Após a análise, a aprovação deve associar um vínculo existente ou criar/associar `User` e `Affiliation` do tipo `Supervisor` na mesma transação, gravar `supervisor_affiliation_id` e marcar o pedido como `Approved`. Antes do aceite do estágio, a solicitação de estágio troca a referência pendente pela FK do vínculo resultante. Recusa e cancelamento preservam o pedido e seu motivo.",
      "line": 4
    },
    {
      "id": "schema-postgresql",
      "level": 2,
      "title": "Schema PostgreSQL",
      "text": "| Campo | Tipo e regra | | --- | --- | | `id` | `bigint`, chave primária. | | `cpf` | `varchar(255)` nullable no banco; obrigatório fora de `Draft`, validado e normalizado pelo `CpfCast`. O banco não limita o comprimento. | | `name`, `phone`, `email`, `job_role`, `qualification` | `varchar(255)` nullable no banco; no Model são obrigatórios e validados fora de `Draft`. | | `training`, `professional_experience` | `text` nullable e opcionais. | | `status` | `varchar(255)` obrigatório, convertido pelo cast PHP `RegistrationRequestStatus`. | | `supervisor_affiliation_id` | `bigint` nullable, única FK para `affiliations`, com `ON DELETE RESTRICT`; deve ser vínculo do tipo `Supervisor` e é obrigatório em `Approved`. | | `reviewed_at` | `timestamp(0)` nullable, convertido para datetime. | | `decision_reason` | `text` nullable; obrigatório em `Rejected` e `Cancelled`. | | `created_at`, `updated_at` | timestamps nativos do Laravel. |  O schema cria somente a chave primária e a FK do vínculo resultante. Não há FKs de autoria ou de revisor nesta tabela, índices secundários, unicidade ou constraints `CHECK`. A solicitação de estágio da Migration 19 identifica o vínculo discente responsável pelo envio. O Model participa do Activity Log Eloquent e registra a autoria conforme o contexto da requisição; as Actions e Policies da análise ainda estão pendentes. O Model bloqueia a exclusão pelo Eloquent; não existe coluna `deleted_at`.",
      "line": 10
    },
    {
      "id": "model-relacao-e-validacao",
      "level": 2,
      "title": "Model, relação e validação",
      "text": "`SupervisorRegistrationRequest` relaciona-se com a `Affiliation` do supervisor resultante; `Affiliation` expõe a relação inversa. O Model usa os casts de `RegistrationRequestStatus`, `CpfCast`, `PhoneCast` e datetime.  No evento `saving`, nome, CPF, telefone, e-mail, cargo e qualificação podem ficar nulos somente em `Draft`; nos demais status exigem conteúdo válido. O `CpfCast` valida CPF brasileiro e o persiste apenas com dígitos; o telefone usa o `PhoneCast` existente e também é persistido apenas com dígitos. Treinamento e experiência profissional são opcionais. Aprovação exige uma FK para vínculo do tipo `Supervisor`; recusa e cancelamento exigem motivo. Não há transições de status ou fluxo de análise nesta migration.  A identidade da conta fica em `users`, que possui CPF único, nome e e-mail. O pedido guarda o CPF informado pelo discente, sem unicidade própria; na criação da conta, a unicidade de `users.cpf` continua sendo a regra final. A associação a uma conta ou vínculo existente e a criação transacional pertencem ao fluxo futuro. Os campos profissionais atuais pertencem a `user_personal_data`; o usuário supervisor poderá preenchê-los ou confirmá-los no futuro formulário, após a criação da conta e do vínculo. A autorização de edição por tipo de vínculo e a composição do snapshot do estágio serão implementadas no fluxo funcional.",
      "line": 26
    },
    {
      "id": "auditoria",
      "level": 2,
      "title": "Auditoria",
      "text": "A tabela não duplica os campos de negócio em JSONB. O Activity Log registra os campos configurados no Model e a autoria disponível no contexto; respostas de consultas externas não são persistidas nesta tabela.",
      "line": 34
    },
    {
      "id": "testes-verificados",
      "level": 2,
      "title": "Testes verificados",
      "text": "`tests/Feature/SupervisorRegistrationRequestTest.php` cobre tipos do schema PostgreSQL, a FK resultante e exclusões, casts e relação, estados `Draft` e não-`Draft`, obrigatoriedade e validação dos campos, CPF normalizado, motivos de decisão, associação de supervisor em `Approved` e rollback/reaplicação da migration. Os testes afetados são executados por Sail.",
      "line": 38
    }
  ],
  "sourcePath": "content/migration-12a-supervisor-registration-requests.md",
  "visuals": [],
  "apiVersion": 1
}
