# Contract: Profissional create/update/read (US4, US5)

Endpoints: `includes/ajax/profissional/create.php`, `includes/ajax/profissional/update.php`, `includes/ajax/profissional/read.php`
Callers: `includes/js/profissionais.js`

## Request — create/update (changed)

| Field | Type | Change |
|---|---|---|
| `sexo`, `estado_civil`, `conjuge_sexo` | string | now additionally accept `"nao_sei"` |
| `filho` | `"0"` \| `"1"` | unchanged meaning ("has children") |
| `filhos[]` (new, replaces `filho_sexo`/`filho_nome`/`filho_nascimento_ano`) | array of `{ nome, sexo, nascimento_ano }` | one entry per child; length = "número de filhos" entered by the user; `sexo` also accepts `"nao_sei"` |
| `telefone[]` / `telefoneddi[]` / `telefonetipo[]` | existing arrays | fully unchanged — no server-side phone classification of any kind; `Telefone新` and its write path are untouched by this feature (see research.md §5 for why the write-time/schema approach was reverted) |

## Server-side handling — create/update

- Write one `ProfissionalFilho新` row per entry in `filhos[]`. On `update.php`, delete existing `ProfissionalFilho新` rows for the profissional first, then reinsert — same wipe-and-reinsert shape already used for `InteracaoProduto新`/`InteracaoProfissional新`.
- `nao_sei` on `sexo`/`estado_civil`/`conjuge_sexo` is stored as-is (plain string, no new column/enum needed).

## Response — read (changed)

| Field | Type | Change |
|---|---|---|
| `filhos` (new, replaces flat `filho_sexo`/`filho_nome`/`filho_nascimento_ano`) | array of `{ nome, sexo, nascimento_ano }` | one entry per `ProfissionalFilho新` row |
| `telefones` / `telefonesDdis` / `telefoneTipos` (existing pipe-joined strings) | string | **unchanged** — still `ORDER BY t.id` server-side; cellphone-first ordering is applied client-side instead (see below) |

## Client-side handling

- `profissionais.js` / the Profissional form: render one child fieldset (`nome`, `sexo`, `nascimento_ano`) per entry in `número de filhos`, using the same add/remove pattern already implemented for `#formacoes-container` / `#enderecos-anteriores-container`, replacing the current single fixed `campos-filho` block.
- Add a `"Não sei"` radio option to the `sexo`, `estado_civil`, and `conjuge_sexo` groups (and the per-child `sexo` group).
- Phone ordering (FR-015): `isTelefoneCelular(cc, value)` / `ordenarTelefonesCelularPrimeiro(telefones)` in `profissionais.js` reuse the same `getPhoneFormat()`/`formatPhone()` digit-count match already used for input masking (works for any country `libphonenumber` knows). Applied at all three render sites that consume the server's (still `ORDER BY t.id`) phone list: the Profissionais list column, the info panel, and the edit-form repopulation on reopen.

## Downstream consumer

- `includes/ajax/indicadores/qualificacao.php` (`getDadosCargos()`, `getCargoInfoList()`): treat the literal string value `"nao_sei"` as empty/unfilled when computing the qualification-completeness ratio, so choosing "Não sei" does not count as a filled field (spec edge case).

## Acceptance mapping

- FR-009 ↔ User Story 4, Acceptance Scenario 1.
- FR-010, FR-011, FR-012, FR-013 ↔ User Story 4, Acceptance Scenarios 2–4.
- FR-014, FR-015 ↔ User Story 5, Acceptance Scenarios 1–2.
