# Análise do módulo Banco de Talentos (legado)

**Escopo dos projetos:** a API está em [`legacy/api-siati-angra`](../legacy/api-siati-angra) (namespace `App\Models\TalentBank`, `App\Http\Controllers\TalentBank`, prefixo de rota `api/talent-bank`). O front é Flutter (`front_bt_angra`) com **flutter_modular**, HTTP via pacote `angra_commons`, consumindo endpoints sob `/api/talent-bank/...` e `/api/options/...`.

---

## 1. Regras de negócio (API + implicações no front)

### Identidade e permissões (SSO + Banco de Talentos)

- O grupo de rotas `talent-bank` está dentro do middleware **`auth.sso`**: na prática, a maioria das operações exige sessão/token do ecossistema SIATI.
- Middleware [`TalentBank`](../legacy/api-siati-angra/app/Http/Middleware/TalentBank.php): para rotas que **não** desabilitam esse middleware, o usuário SSO precisa ter permissão **`gestao-de-usuarios`** ou **`talent-bank-admin`**. O documento do usuário é resolvido para o registro local **candidato (CPF)** ou **empresa (CNPJ)**; se não existir, retorna **404**. O modelo encontrado é injetado em `talentBankUser`.
- Perfis adicionais por controller: exemplos em [`CandidateController`](../legacy/api-siati-angra/app/Http/Controllers/TalentBank/CandidateController.php) (`talent-bank-user-candidate`, `talent-bank-user-company`, `gestao-de-usuarios`, `talent-bank-admin`) e [`JobController`](../legacy/api-siati-angra/app/Http/Controllers/TalentBank/JobController.php) (empresa/admin para CRUD de vaga; candidato para candidatura).

### Candidatos

- **Cadastro**: `POST candidate/register` chama `AuthService::register` com permissão `talent-bank-user-candidate`, depois cria linha em `candidates` com `cpf` = documento do SSO.
- **Login**: `POST candidate/login`; se autenticar no SSO mas **não** houver registro local, o sistema **auto-atribui** permissão, obtém sessão e **cria** o candidato automaticamente.
- **Atualização pelo próprio usuário**: `PUT candidate/{id}` remove `cpf` e `email` do payload (não alteráveis por essa rota). **Self-edit** (`POST candidate/self-edit`) sincroniza nome/email com `UserService` e atualiza o candidato pelo CPF.

### Empresas (modelo compartilhado Tech Park)

- Empresas do Banco de Talentos usam [`Company`](../legacy/api-siati-angra/app/Models/TechPark/Company.php) com `module_name` = constante [`Module::TALENT_BANK`](../legacy/api-siati-angra/app/Models/Module.php) (`'Banco de Talentos'`).
- **Registro**: validação de CNPJ em [`CompanyController::register`](../legacy/api-siati-angra/app/Http/Controllers/TechPark/CompanyController.php); após SSO, se já existir empresa com o CNPJ, **reutiliza** o registro em vez de criar outro.
- **Login** de empresa: mesmo padrão de “criar empresa se não existir” após login (CNPJ no `store`).
- **Listagem pública de empresas do BT**: [`CompanyService::getFromTalentBank`](../legacy/api-siati-angra/app/Http/Services/TechPark/CompanyService.php) filtra `module_name = TALENT_BANK` + filtros do model (`like` em `corporate_name`, etc.).

### Vagas (`Job`)

- **Listagem pública** ([`JobService::index`](../legacy/api-siati-angra/app/Http/Services/TalentBank/JobService.php)): apenas vagas com **`is_hiring = 1`**, com filtros (`FilterQueryString`) e paginação manual (`perPage`, `page`).
- **Resposta pública** ([`JobPublicResource`](../legacy/api-siati-angra/app/Http/Resources/TalentBank/JobPublicResource.php)): **não** expõe empresa nem `hide_company` (anonimato na vitrine).
- **Detalhe / admin** ([`JobResource`](../legacy/api-siati-angra/app/Http/Resources/TalentBank/JobResource.php)): se `hide_company`, o nome da empresa é substituído por mensagem traduzida de “classificado”; caso contrário mostra `trading_name`.
- **CRUD de vaga**: apenas usuário cuja `talentBankUser` é **Company**; `update`/`destroy` validam que a vaga pertence ao `company_id` da sessão.
- **Candidatura**: `syncWithoutDetaching` na tabela pivô `job_applications`; envia e-mail em fila para o e-mail da empresa ([`CandidateApplicationMail`](../legacy/api-siati-angra/app/Mail/TalentBank/CandidateApplicationMail.php)).

### Relatório e contadores de candidatos

- [`CandidateService::getCounters`](../legacy/api-siati-angra/app/Http/Services/TalentBank/CandidateService.php): totais por **PCD** (`special_needs`), **gênero** (Feminino/Masculino/Outro — via relação `gender`), **etnia** (valores fixos: Branco, Preto, Pardo, Indígena, Amarelo), **total**; se filtros `gender_id` ou `ethnicity` vierem na query, parte dos contadores de gênero/etnia é omitida; com `neighbourhoods` ou `occupations`, há contadores por nome de bairro/ocupação.
- **Candidatos “desejados”** (`wantedOccupations`): existe tabela e relação no model e **importação CSV**, mas **não** há controller dedicado na API analisada — gestão via importação/dados legados.

### Dashboard

- [`DashboardService::home`](../legacy/api-siati-angra/app/Http/Services/TalentBank/DashboardService.php): contadores de candidatos **ativos**, total de **vagas**, empresas BT **ativas** e com módulo BT.
- `dashjobs`: vagas abertas/fechadas e contagem de relacionamento candidatos–vagas (implementação usa `candidates()` em instância vazia de `Job` — interpretar como métrica de API).

### Contato (Fale conosco)

- `POST contact` ([`CandidateController`](../legacy/api-siati-angra/app/Http/Controllers/TalentBank/CandidateController.php)): valida nome, e-mail, telefone, assunto, mensagem; envia para `MAIL_CONTACT` ([`TalentBankContact`](../legacy/api-siati-angra/app/Mail/TalentBank/TalentBankContact.php)).

### Dados auxiliares (options)

- [`GET /api/options/talent-bank`](../legacy/api-siati-angra/app/Http/Controllers/OptionsController.php): opções de formulário de candidato (disciplinas, ramos, níveis de escolaridade, gênero, idiomas, estados civis, bairros, ocupações, proficiências).
- [`GET /api/options/job`](../legacy/api-siati-angra/app/Http/Controllers/OptionsController.php): faixa salarial, tipo de contrato, nível de expertise, modalidade, carga horária.

---

## 2. Fluxos principais do sistema

```mermaid
flowchart LR
  subgraph public [Visitante]
    Home[Home vagas e dashboard]
    Jobs[Listagem e filtros]
    Detail[Detalhe da vaga]
    Companies[Empresas BT]
    Contact[Fale conosco]
  end
  subgraph cand [Candidato SSO]
    RegC[Registro BT]
    LoginC[Login]
    Prof[Perfil e currículo]
    Apply[Candidatura]
  end
  subgraph comp [Empresa SSO]
    RegE[Registro BT]
    LoginE[Login]
    JobsCo[CRUD vagas]
    Apps[Ver candidatos por vaga]
  end
  Home --> Jobs
  Jobs --> Detail
  Detail --> Apply
  RegC --> LoginC
  LoginC --> Prof
  RegE --> LoginE
  LoginE --> JobsCo
  JobsCo --> Apps
```

### Front Flutter ([`front_bt_angra`](../legacy/front_bt_angra))

- **App shell**: [`BasePage`](../legacy/front_bt_angra/lib/modules/base/base_page.dart) + [`BaseCubit.loadSession`](../legacy/front_bt_angra/lib/modules/base/cubit/base_cubit.dart): tenta sessão de **candidato** (`/api/talent-bank/candidate/session`); se falhar, tenta **empresa** + carrega vagas da empresa (`/api/talent-bank/company/jobs`).
- **Home**: [`HomeCubit`](../legacy/front_bt_angra/lib/modules/home/cubit/home_cubit.dart) — lista vagas, notícias externas e **dashboard** (`GET /api/talent-bank/dashboard`).
- **Vagas**: [`JobsListCubit`](../legacy/front_bt_angra/lib/modules/jobs/list/cubit/jobs_list_cubit.dart) monta query com `like` na descrição e `in[]` para IDs (salário, contrato, etc.) conforme [`JobsDatasource`](../legacy/front_bt_angra/lib/datasources/jobs_datasource.dart); detalhe e candidatura em [`JobDetailsCubit`](../legacy/front_bt_angra/lib/modules/jobs/details/cubit/job_details_cubit.dart).
- **Candidato**: wizard de cadastro em `modules/candidate/register` (passos: acesso, dados pessoais, escolaridade, experiência, cursos, habilidades) usando [`CandidateDatasource`](../legacy/front_bt_angra/lib/datasources/candidate_datasource.dart); currículo/PDF em [`curriculum_page`](../legacy/front_bt_angra/lib/modules/profile/curriculum_page.dart).
- **Empresa**: cadastro em `modules/company/register` e listagem de vagas com abas **Vagas / Candidatos** em [`company_profile_page`](../legacy/front_bt_angra/lib/modules/profile/company_profile_page.dart).
- **Fale conosco**: [`FaleConoscoCubit`](../legacy/front_bt_angra/lib/modules/fale_conosco/cubit/fale_conosco_cubit.dart) → `POST /api/talent-bank/contact`.

---

## 3. Entidades (models) e relacionamentos

| Entidade | Tabela / notas | Relacionamentos principais |
|----------|----------------|----------------------------|
| **Candidate** | `candidates` | `belongsTo` Neighbourhood, Gender, MaritalStatus, Occupation; `hasMany` Education, Course, Experience, Skill; `belongsToMany` Language (pivô `candidate_languages` + proficiência), Job (pivô `job_applications`); `belongsToMany` Occupation como **wantedOccupations** (`candidate_wanted_occupations`). |
| **Job** | `jobs` | `belongsTo` Company, Occupation, SalaryRange, ContractType, Neighbourhood (opcional), ExpertiseLevel, Modality, Workload; `belongsToMany` Candidate via `job_applications`. |
| **Company** (Tech Park) | `companies` | `hasMany` Job; `belongsTo` Neighbourhood; filtro por `module_name` para BT. |
| **Education** | `candidate_education` | `belongsTo` Candidate, EducationLevel, AcademicDiscipline. |
| **Course** | `candidate_courses` | `belongsTo` Candidate. |
| **Experience** | `candidate_experiences` | `belongsTo` Candidate, BusinessLine, Occupation. |
| **Skill** | `candidate_skills` | `belongsTo` Candidate. |
| **Tabelas de domínio** | `occupations`, `neighbourhoods`, `genders`, `marital_statuses`, `languages`, `language_proficiencies` (pivô), `education_levels`, `academic_disciplines`, `business_lines`, `proficiencies` | Usadas em filtros, FKs e `OptionsController`. |
| **Opções de vaga** | `salary_ranges`, `contract_types`, `expertise_levels`, `modalities`, `workloads` | FKs em `jobs`. |

---

## 4. Validações aplicadas

| Área | Onde | Regras relevantes |
|------|------|-------------------|
| Candidato (FormRequest) | [`CandidateRequest`](../legacy/api-siati-angra/app/Http/Requests/TalentBank/CandidateRequest.php) | `cpf` obrigatório (string); demais campos opcionais com tipos; `PUT` altera regra de `cpf` para `integer` (inconsistência com CPF como string de 11 dígitos); FKs com `exists` nas tabelas de domínio. Método estático `validateCpf` implementa dígito verificador — **não** está ligado automaticamente às regras do FormRequest. |
| Vaga | [`JobRequest`](../legacy/api-siati-angra/app/Http/Requests/TalentBank/JobRequest.php) | POST: campos obrigatórios incl. `descripton`, `hide_company`, `is_hiring`, ocupações e faixas; PUT/PATCH: tudo nullable. Typo persistente: campo `descripton` (também no banco). |
| Educação | [`EducationRequest`](../legacy/api-siati-angra/app/Http/Requests/TalentBank/Candidate/EducationRequest.php) | Níveis e disciplina obrigatórios; datas opcionais. |
| Experiência | [`ExperienceRequest`](../legacy/api-siati-angra/app/Http/Requests/TalentBank/Candidate/ExperienceRequest.php) | Ramo de atividade, ocupação e empresa obrigatórios. |
| Curso | [`CourseRequest`](../legacy/api-siati-angra/app/Http/Requests/TalentBank/Candidate/CourseRequest.php) | Nome e instituição obrigatórios. |
| Skill | inline no [`SkillController`](../legacy/api-siati-angra/app/Http/Controllers/TalentBank/Candidate/SkillController.php) | Apenas `name` required string. |
| Idioma | [`CandidateController::attachLanguage`](../legacy/api-siati-angra/app/Http/Controllers/TalentBank/CandidateController.php) | `language_id` e `language_proficiency_id` com `exists`. |
| Contato | [`CandidateController::contact`](../legacy/api-siati-angra/app/Http/Controllers/TalentBank/CandidateController.php) | email, name, phone, subject, message obrigatórios. |
| Empresa (store/update) | [`CompanyController`](../legacy/api-siati-angra/app/Http/Controllers/TechPark/CompanyController.php) + [`CompanyRequest`](../legacy/api-siati-angra/app/Http/Requests/TechPark/CompanyRequest.php) | Validação de CNPJ no controller; registro público valida documento. |

**Filtros dinâmicos (API):** pacote `FilterQueryString` nos models `Candidate` e `Job` — filtros customizados como `education_level`, `age`, `age_between`, `neighbourhoods`, `occupations` (CSV), `in` composto no Job, etc.

---

## 5. Funcionalidades principais (CRUDs, filtros, relatórios)

### API

- **CRUD catálogos** (prefixo `talent-bank/`): `language`, `proficiency`, `academic-discipline`, `education-level`, `business-line`, `occupation`, `neighbourhood`, `marital-status`, `contract-type`, `expertise-level`, `salary-range`, `modality`, `workload` — em geral `apiResource` completo protegido por `talent.bank` + SSO.
- **Candidatos**: listagem/show (admin); create/update/delete conforme permissões; sub-CRUDs aninhados em `candidate/` (skill, course, education, experience); relatório `GET report/candidate` com paginação opcional e **counters**; registro/login/contato públicos (sem `talent.bank` nas rotas indicadas).
- **Vagas**: listagem pública filtrada; `jobs-admin` para admin; CRUD para empresa; candidatura e cancelamento.
- **Empresa BT**: `company/register`, `login`, `session`, `self-edit`, `jobs` (vagas com candidatos); `company` GET público para listagem de empresas do módulo.
- **Dashboard**: `dashboard`, `dashjobs`.

### Front

- Listagem de vagas com **filtros múltiplos** e paginação; detalhe; candidatura.
- Home com **métricas** e amostra de vagas; listagem de empresas; cadastro/login candidato e empresa; perfil, currículo PDF, gestão de vagas e visualização de candidatos (empresa); fale conosco.

---

## Migração para o app Laravel 9 principal

Este repositório contém o app principal em Laravel 9 na raiz e o legado em [`legacy/`](../legacy/). Para priorizar a migração do Banco de Talentos:

1. **Paridade de domínio**: replicar models, migrações e relacionamentos equivalentes (ou mapear tabelas existentes) no app principal.
2. **Autenticação**: alinhar SSO/permissions com o que o middleware `TalentBank` e `auth.permissions` esperam, ou substituir pelo stack de auth do projeto novo.
3. **Front**: decidir entre manter Flutter, incorporar fluxos em Blade/Livewire do app principal, ou API-only + novo cliente.
4. **Dados**: planejar importação de `candidates`, `companies`, `jobs`, pivôs e catálogos; tratar `wantedOccupations` se ainda forem necessários.

**Próximo passo sugerido para stakeholders:** revisar este documento, validar escopo de migração e critérios de aceite antes de implementar modelos e rotas no app principal.

---

## Esquema no app Laravel 9 (raiz)

Migrations e models Eloquent vivem na raiz do repositório em [`database/migrations`](../database/migrations) e [`app/Models/TalentBank`](../app/Models/TalentBank). Mapeamento em relação ao legado:

| Legado (`api-siati-angra`) | App Laravel 9 | Notas |
|---------------------------|---------------|--------|
| `jobs` | `job_listings` | Evita conflito com a tabela `jobs` do driver de queue do Laravel. Model: `JobListing`. |
| `descripton` | `description` | Coluna corrigida na nova tabela. |
| `job_applications` | `job_listing_candidate` | Pivô de candidaturas com `timestamps`. |
| `candidate_education` | `candidate_educations` | Pluralização; model `Candidate\Education`. |
| Empresa com `module_id` / `module_name` | `companies` sem esses campos | App dedicado ao Banco de Talentos. |
| `ethnicity` (string no candidato) | `ethnicities` + `candidates.ethnicity_id` | Lookup normalizado. |
| Telefone / CPF / CNPJ como inteiro | `string` / `char` | Preserva máscaras e zeros à esquerda; CPF/CNPJ únicos como texto só dígitos. |

---

### Observação de escopo

O **`front_bt_angra`** está em [`legacy/front_bt_angra`](../legacy/front_bt_angra) neste repositório; a análise reflete esse código e a API em [`legacy/api-siati-angra`](../legacy/api-siati-angra).
