# 01 — Novo importador de dados

Roteiro de teste do **importador de dados via template** (CSV → tabelas do
banco). Você executa os passos manualmente no ambiente QA e anota o resultado
na coluna **Obtido**.

> Ambiente: https://mad5qa.lura.zadotec.com.br/web/mad-framework/
> Branch: `testes/pr3-pr4-aplicados` · DBs SQLite presentes (ver [01-ambiente.md](../01-ambiente.md))

## Como o recurso funciona (mapa rápido)

| Etapa | Onde | Classe / arquivo |
|-------|------|------------------|
| Listar/CRUD de templates | Dashboard de importação | [`SystemDataImportDashboard`](../../web/mad-framework/app/control/admin/SystemDataImportDashboard.php) |
| Criar/editar template (mapeamento CSV→colunas) | Drawer | [`SystemDataImportTemplateForm`](../../web/mad-framework/app/control/admin/SystemDataImportTemplateForm.php) |
| Importar de fato (upload do CSV preenchido) | Drawer | [`SystemDataImportUseForm`](../../web/mad-framework/app/control/admin/SystemDataImportUseForm.php) |
| Botão que abre a importação | Componente Blade | [`<mad-import-btn>`](../../web/mad-framework/lib/mad/views/components/import-btn.blade.php) |
| Modelo de dados | `system_import_template` (DB `permission`) | [`SystemImportTemplate`](../../web/mad-framework/app/model/admin/SystemImportTemplate.php) |

**Detalhes que importam para o teste:**

- O template guarda: `title`, `code`, `database_name`, `mapping_json`
  (mapa CSV↔coluna), `import_mode` e `active` (`Y`/`N`).
- `import_mode`: **`atomic`** (tudo-ou-nada numa transação) ou
  **`partial`** (lotes de 100, com fallback linha-a-linha; padrão).
- Ao salvar o template, o sistema **gera automaticamente um CSV modelo**
  (`DataImportCsvModelService`) com as colunas mapeadas.
- O `<mad-import-btn code="X">` **só aparece** se existir um template com
  `code = X` **e** `active = 'Y'` — ver
  [`findByCode`](../../web/mad-framework/app/model/admin/SystemImportTemplate.php#L37).
- Já existe um botão real em
  [`cidade-header-list.blade.php:5`](../../web/mad-framework/app/resources/views/pessoas/cidade-header-list.blade.php#L5):
  `<mad-import-btn code="importar-cidades">Importar Cidades</mad-import-btn>`.
  Ou seja: **basta criar o template com `code = importar-cidades` e ativá-lo**
  que o botão na listagem de Cidades passa a renderizar.

---

## Checklist (objetivo desta rodada)

- [ ] **Criar templates de importação**
- [ ] **Testar importação**
- [ ] **Testar template de importação**
- [ ] **Adicionar botão que abre um template de importação**
      (`<mad-import-btn code="importar-cidades">Importar Cidades</mad-import-btn>`)

---

## Casos

### IMP-01 — Criar template de importação
- **Pré-condição:** logado, com acesso ao dashboard de importação.
- **Passos:**
  1. Abrir o dashboard de importação (`SystemDataImportDashboard`).
  2. Clicar em **Novo** → abre o drawer do template.
  3. Preencher `Título`, escolher o **Banco** (`database_name`).
  4. Definir o `Código` = `importar-cidades` (para casar com o botão da tela de Cidades).
  5. Montar o **mapeamento** (field-list): para cada linha, escolher
     `Tabela destino` → `Campo destino` → informar o `Campo CSV`.
  6. Escolher o `import_mode` (`partial` para o primeiro teste).
  7. Marcar **Ativo** e salvar.
- **Esperado:** toast "Template salvo!", drawer fecha, linha aparece/atualiza
  no dashboard (`manageRow`). CSV modelo gerado automaticamente.
- **Obtido:** ⏳

### IMP-02 — Cascata do mapeamento (tabela → campos)
- **Passos:**
  1. No drawer do template, ao trocar a **Tabela destino** numa linha do
     mapeamento, observar o select de **Campo destino**.
- **Esperado:** o `Campo destino` recarrega com as colunas da tabela escolhida
  (`onChangeTable` repopula o combo da linha). Sem erro JS no console.
- **Obtido:** ⏳

### IMP-03 — Baixar CSV modelo
- **Passos:**
  1. No template salvo, acionar **Baixar modelo CSV**.
- **Esperado:** download de um `.csv` cujo cabeçalho são as colunas CSV
  mapeadas (`csv_column`). Nome do arquivo = "{título} - modelo.csv".
- **Obtido:** ⏳

### IMP-04 — Testar template de importação (validações do CRUD)
- **Passos:**
  1. Tentar salvar template **sem título** / **sem banco** / **sem nenhuma
     linha de mapeamento**.
  2. Editar um template existente e salvá-lo (deve preservar o mapeamento).
  3. Excluir um template e confirmar que pivots de grupo/usuário e o CSV
     modelo são removidos junto.
- **Esperado:** (1) modal de validação listando os campos faltantes;
  (2) edição recarrega o mapeamento corretamente; (3) exclusão limpa
  dependências sem erro.
- **Obtido:** ⏳

### IMP-05 — Testar importação (modo partial)
- **Pré-condição:** template `importar-cidades` ativo + CSV modelo preenchido
  com algumas linhas válidas e **1 linha inválida** de propósito.
- **Passos:**
  1. Abrir o template para uso (`SystemDataImportUseForm`) — via botão ou dashboard.
  2. Baixar o modelo, preencher, e enviar o CSV (`onUpload`).
  3. Clicar em **Importar**.
- **Esperado:** importação processa em lote; linhas válidas entram, a inválida
  é reportada; resumo mostra `total / sucesso / erro`. Um registro é gravado
  em `SystemImportLog`.
- **Obtido:** ⏳

### IMP-06 — Testar importação (modo atomic)
- **Pré-condição:** template com `import_mode = atomic` + CSV com 1 linha inválida.
- **Passos:**
  1. Repetir a importação do IMP-05 com o CSV que contém erro.
- **Esperado:** **nenhuma** linha é gravada (rollback total) — comportamento
  tudo-ou-nada. Log registra a falha.
- **Obtido:** ⏳

### IMP-07 — Botão que abre o template de importação
- **Pré-condição:** template com `code = importar-cidades` e `active = 'Y'`
  (criado no IMP-01).
- **Passos:**
  1. Abrir a listagem de **Cidades** (que já tem
     `<mad-import-btn code="importar-cidades">` no header).
  2. Conferir que o botão **"Importar Cidades"** aparece.
  3. Clicar nele.
- **Esperado:** botão renderiza (some se o template estiver inativo/inexistente)
  e abre o drawer de importação (`SystemDataImportUseForm`) já apontando para o
  template correto.
- **Obtido:** ⏳

### IMP-08 — Adicionar um novo botão em outra tela (opcional)
- **Passos:**
  1. Inserir `<mad-import-btn code="SEU-CODE">Importar X</mad-import-btn>` no
     header de outra listagem.
  2. Garantir que existe um template ativo com aquele `code`.
- **Esperado:** botão aparece e abre o importador do template correspondente.
- **Obtido:** ⏳

---

## Casos RH & Folha de Pagamento (IMP-09 a IMP-14)

> **Pré-requisito:** executar o SQL [`docs/testes/fixtures/00-criar-tabelas-rh.sql`](fixtures/00-criar-tabelas-rh.sql) no banco `minierp` para criar as tabelas `rh_cargo`, `rh_departamento`, `rh_funcionario` e `rh_folha_lancamento`.
>
> Criar os templates **na ordem indicada** (há dependência de FK entre tabelas).
> Planilhas: [`docs/testes/fixtures/`](fixtures/)

### IMP-09 — Template e importação de cargos (partial, dados limpos)
- **Pré-condição:** tabela `rh_cargo` criada; usuário logado no dashboard de importação.
- **Passos:**
  1. Criar template: título `RH – Cargos`, banco `minierp`, tabela `rh_cargo`, modo `partial`, code `rh-cargos`.
  2. Mapeamento: `nome → nome`, `nivel → nivel`, `salario_base → salario_base`, `carga_horaria_mensal → carga_horaria_mensal`, `ativo → ativo`.
  3. Baixar o CSV modelo gerado e conferir que tem as 5 colunas mapeadas.
  4. Enviar a planilha [`01-rh-cargos.csv`](fixtures/01-rh-cargos.csv) e executar a importação.
  5. Verificar no banco: `SELECT COUNT(*) FROM rh_cargo;` → deve retornar **8**.
- **Esperado:** 8 inserções, 0 erros, `system_import_log.success_rows = 8`.
- **Obtido:** ⏳

### IMP-10 — Template e importação de departamentos (partial, FK inválida na linha 6)
- **Pré-condição:** IMP-09 concluído; tabela `rh_departamento` criada.
- **Passos:**
  1. Criar template: título `RH – Departamentos`, tabela `rh_departamento`, modo `partial`, code `rh-departamentos`.
  2. Mapeamento: `nome`, `sigla`, `centro_custo`, `responsavel_id`, `ativo`.
  3. Enviar [`02-rh-departamentos.csv`](fixtures/02-rh-departamentos.csv).
  4. Verificar no banco: `SELECT COUNT(*) FROM rh_departamento;` → **5**.
  5. Verificar `system_import_log.errors_json` para a linha 6 — deve conter FK violation (`responsavel_id = 999`).
- **Esperado (partial):** 5 linhas OK, 1 com erro; `error_rows = 1`; as 5 primeiras persistem.
- **Obtido:** ⏳

### IMP-11 — Importação de funcionários (partial, armadilhas múltiplas)
- **Pré-condição:** IMP-09 e IMP-10 concluídos; `rh_funcionario` criada; `pessoa_id` 1–20 existem no banco.
- **Passos:**
  1. Criar template: título `RH – Funcionários`, tabela `rh_funcionario`, modo `partial`, code `rh-funcionarios`.
  2. Mapeamento: `pessoa_id`, `cargo_id`, `departamento_id`, `matricula`, `data_admissao`, `salario`, `regime`, `status`.
  3. Enviar [`03-rh-funcionarios-partial.csv`](fixtures/03-rh-funcionarios-partial.csv).
  4. Verificar contagem: `SELECT COUNT(*) FROM rh_funcionario;`
  5. Verificar `errors_json`: quais linhas falharam e qual o motivo reportado.
  6. Verificar se linha com `salario = 1412,50` foi convertida para `1412.50`: `SELECT salario FROM rh_funcionario WHERE matricula = 'F-0009';`
  7. Verificar se linha com `data_admissao = 15/04/2023` falhou ou foi aceita.
  8. Verificar comportamento da matrícula duplicada `F-0001` (linha 14): foi substituída (REPLACE) ou gerou erro?
- **Esperado:** ≥12 linhas inseridas; erros nas linhas 10 (cargo FK), 11 (depto FK), 13 (data malformada); linha 12 ignorada (vazia); duplicata F-0001 faz REPLACE silencioso.
- **Obtido:** ⏳

### IMP-12 — Importação de funcionários (atomic, rollback total)
- **Pré-condição:** `rh_funcionario` vazia ou apenas com dados do IMP-11 (anotar contagem antes).
- **Passos:**
  1. Criar template igual ao IMP-11 mas com modo `atomic`, code `rh-funcionarios-atomic`.
  2. Enviar [`04-rh-funcionarios-atomic.csv`](fixtures/04-rh-funcionarios-atomic.csv) (linha 8 tem `cargo_id = 99` — FK inválida).
  3. Verificar contagem após importação: `SELECT COUNT(*) FROM rh_funcionario WHERE matricula LIKE 'F-01%';` → deve ser **0**.
  4. Verificar `system_import_log`: `aborted = true` (ou campo equivalente), `success_rows = 0`, `error_rows = 15`.
- **Esperado:** nenhuma linha persistida; rollback completo; log registra a falha com linha 8 como causa.
- **Obtido:** ⏳

### IMP-13 — Importação de lançamentos de folha (partial, decimais PT-BR e FK inválida)
- **Pré-condição:** IMP-11 concluído; `rh_folha_lancamento` criada; funcionários com IDs 1–6 existem.
- **Passos:**
  1. Criar template: título `RH – Folha de Pagamento`, tabela `rh_folha_lancamento`, modo `partial`, code `rh-folha`.
  2. Mapeamento: `funcionario_id`, `competencia`, `tipo`, `descricao`, `valor`, `referencia`.
  3. Enviar [`05-rh-folha-lancamentos.csv`](fixtures/05-rh-folha-lancamentos.csv).
  4. Verificar contagem: `SELECT COUNT(*) FROM rh_folha_lancamento;`
  5. Verificar conversão de decimais com ponto de milhar: `SELECT valor FROM rh_folha_lancamento WHERE descricao = 'Salário Base' AND funcionario_id = 3;` → deve ser `3500.00` (não `3.500,00` nem `3500`).
  6. Verificar linha com `funcionario_id = 999`: deve aparecer em `errors_json`.
  7. Verificar duplicata (linha 25, repetição do lançamento do funcionário 1): `SELECT COUNT(*) FROM rh_folha_lancamento WHERE funcionario_id = 1 AND tipo = 'PROVENTO' AND descricao = 'Salário Base';` → **1** (REPLACE, não duplicado).
  8. Verificar campos `referencia` em branco: `SELECT referencia FROM rh_folha_lancamento WHERE referencia IS NULL OR referencia = '' LIMIT 5;`
- **Esperado:** ≥27 inserções; 1 erro (FK inválida); decimais pt-BR convertidos corretamente; `referencia` vazio aceito como NULL.
- **Obtido:** ⏳

### IMP-14 — Botão `<mad-import-btn>` para o módulo RH
- **Pré-condição:** IMP-09 a IMP-13 concluídos; template `rh-funcionarios` com `active = Y`.
- **Passos:**
  1. Verificar que o template `rh-funcionarios` está ativo no dashboard.
  2. Desativar o template (`active = N`) e recarregar a tela que teria o botão — confirmar que o botão some.
  3. Reativar e confirmar que o botão volta a aparecer.
- **Esperado:** botão renderiza apenas quando `active = 'Y'`; ausência do template (ou inativo) não quebra a tela — botão simplesmente não aparece.
- **Obtido:** ⏳

## Resultado

| Caso | Status | Observação |
|------|--------|------------|
| IMP-01 Criar template | ⏳ | |
| IMP-02 Cascata mapeamento | ⏳ | |
| IMP-03 Baixar CSV modelo | ⏳ | |
| IMP-04 Validações CRUD | ⏳ | |
| IMP-05 Importação partial | ⏳ | |
| IMP-06 Importação atomic | ⏳ | |
| IMP-07 Botão importar-cidades | ⏳ | |
| IMP-08 Botão novo (opcional) | ⏳ | |
| IMP-09 Cargos (partial limpo) | ⏳ | |
| IMP-10 Departamentos (FK inválida) | ⏳ | |
| IMP-11 Funcionários partial (múltiplas armadilhas) | ⏳ | |
| IMP-12 Funcionários atomic (rollback total) | ⏳ | |
| IMP-13 Folha (decimais PT-BR, duplicatas) | ⏳ | |
| IMP-14 Botão mad-import-btn RH | ⏳ | |

## Notas / dúvidas para o teste

- Confirmar onde o dashboard de importação está no menu (ou rota direta).
- Conferir se `database_name` aceita os DBs SQLite do ambiente (minierp, etc.).
- Anotar aqui qualquer erro 500 / stack trace observado durante a importação.
