# OCR do documento de empresa

<https://unifokal.com/docs/modulos/cnpj-ocr>

## OCR do documento de empresa

O módulo `cnpj_ocr` lê o **documento societário** que a empresa enviou (cartão CNPJ, CCMEI, contrato social, alteração contratual registrada na Junta, certidão, estatuto ou ata) e extrai os campos **impressos nele**. Diferente do documento de pessoa, aqui **não há câmera**: é envio de arquivo, e o documento pode ter várias páginas.

! **Tudo aqui é o que o PAPEL diz, na data em que o papel foi emitido.** Inclusive `situacao_cadastral` e `cnae_principal`: eles são **leitura do documento**, e não consulta à Receita. Para a situação cadastral **vigente** você precisa de `cnpj_cadastro` ou `cnpj_receita`, que perguntam à fonte. Tratar o campo lido do papel como situação atual é a confusão mais cara desta seção, porque uma certidão de 2019 diz "ATIVA" para sempre.

**Campo que o documento não trazia simplesmente não aparece no objeto.** Ele não vem `null`: a chave não existe. A única que sempre existe é `cnpj`, e ela pode vir **string vazia**, o que é um resultado **legítimo** e não uma falha: contrato de constituição original não traz CNPJ, porque a empresa ainda não tinha um. Vazio também é o que sai quando o documento cita mais de um CNPJ sem rótulo que desempate, porque **preferimos não responder a chutar** entre a empresa titular e uma sócia pessoa jurídica. Quando resolvemos, o número vem com **14 posições e dígito verificador conferido** (inclusive no formato alfanumérico da Receita), nunca um número que não fecha.

```
// cnpj_ocr no check_details: o que foi LIDO do documento societário
{ "module": "cnpj_ocr", "passed": true, "outcome": "approved", "score": 90,
  "data": { "cnpj": "11222333000181",
            "razao_social": "EMPRESA MOCK LTDA",
            "nome_fantasia": "MOCK",
            "nire": "31201234567",              // registro na Junta, NÃO é o CNPJ
            "tipo_documento": "cartao_cnpj",    // cartao_cnpj | ccmei | contrato_social |
                                                // alteracao_contratual | certidao |
                                                // estatuto_ata | requerimento_empresario | outro
            "situacao_cadastral": "ATIVA",      // IMPRESSA no papel, não consultada
            "cnae_principal": "6201-5/01 Desenvolvimento de programas de computador sob encomenda",
            "data_abertura": "01/06/2015",
            "socios": [ { "nome": "SOCIO MOCK UM", "qualificacao": "Administrador",
                          "participacao": "60%" } ] } }
// contrato de constituição original, que ainda não tem CNPJ: resultado VÁLIDO
{ "module": "cnpj_ocr", "passed": true, "outcome": "approved", "score": 90,
  "data": { "cnpj": "", "razao_social": "EMPRESA NOVA LTDA",
            "tipo_documento": "contrato_social", "data_abertura": "12/08/2026" } }
```

! **O sandbox deste módulo emite os mesmos nomes de campo da produção**, então dá para fixar o shape contra ele. O que muda entre os dois ambientes é só o conteúdo: no sandbox os valores são fixos e nenhum documento é lido de verdade. Continua valendo a regra de cima: campo que o documento não trazia **não aparece** no objeto, então programe por presença de chave e não por posição.
