# Guia de Implementação: NFS-e (Integração Digisan) - Padrão CD9

Este documento é um **script instrucional para agentes Antigravity**. Se você é a IA responsável por implementar a lógica financeira de emissão de Notas Fiscais de Serviço Eletrônicas (NFS-e) em um projeto irmão com características semelhantes ao CD9, **leia e siga este guia**.

---

## Passo 1: Entendimento do Domínio e Arquitetura
A integração usa a API da **Digisan**. O fluxo é semi-assíncrono:
1. O Front pede a emissão enviando dados básicos.
2. O Backend monta o XML/JSON e envia para a Digisan. Recebe um ID de rastreio e status inicial (Ex: "EM_PROCESSAMENTO").
3. Um **Webhook** do backend é ativado pela Digisan posteriormente notificando "AUTORIZADA" ou "REJEITADA", devolvendo os links do PDF/XML.

---

## Passo 2: Estrutura de Banco de Dados (Backend)
No seu banco relacional, você precisa replicar a estrutura financeira da tabela de "Contas a Receber" ou criar se ela não existir. 

**2.1. Estrutura Base de Contas a Receber (Migration Create):**
Crie uma migration semelhante:
```php
Schema::create('fin_contas_receber', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->unsignedBigInteger('fk_empresa')->index()->comment('ID do Cliente');
    $table->decimal('valor_total', 15, 2)->comment('A soma total das movimentações faturadas');
    $table->date('data_vencimento');
    $table->date('data_pagamento')->nullable();
    $table->tinyInteger('status')->default(1)->comment('1=pendente, 2=vencido, 3=pago, 4=cancelado');
    $table->text('observacoes')->nullable();
    $table->timestamps();
});
```

**2.2. Campos para Integração NFS-e (Migration Add Columns):**
Caso a tabela já exista, você deve adicionar os campos abaixo, ou caso contrário, consolide-os na mesma migration de criação:
```php
Schema::table('fin_contas_receber', function (Blueprint $table) {
    // Esse é o status específico com a Receita/Digisan
    $table->enum('status_faturamento', ['A_FATURAR', 'FATURADO', 'CANCELADO', 'ERRO'])->default('A_FATURAR')->after('status');
    $table->string('id_faturamento')->nullable()->comment('ID retornado no processamento pela Digisan');
    $table->text('url_pdf_nfse')->nullable()->comment('Link com validade para o PDF retornado por webhook');
    $table->text('url_xml_nfse')->nullable()->comment('Link com validade para o XML retornado por webhook');
    $table->text('mensagem_erro_nfse')->nullable()->comment('Guarda o motivo de rejeição');
});
```
*(Nota: No CD9, implementamos o enum `status_faturamento` com os estados `A_FATURAR`, `FATURADO`, `CANCELADO`)*

---

## Passo 3: Classe de Integração (DigisanService)
Crie um Service (`app/Services/DigisanService.php` ou equivalente) contendo as chamadas REST:
- Base URL do `.env` (ex: `https://qadata.digisan.com.br/api` para homologação).
- **CRÍTICO - Formatação de Payload Fiscal**: A Digisan é extremamente estrita com a validação do Schema. O objeto payload deve conter:
  - Nó principal `nfse` com as chaves obrigatórias.
  - `tributacao`: Precisa dos campos `codigo_tributacao_municipio`, `codigo_servico_lc116`, `aliquota` e `tipo_retencao_issqn` (geralmente `1` dependendo da regra). **Verifique esses dados conforme a cidade**.
  - `cliente`: Precisa separar `telefone` se tiver DDI, formatar CNPJ remover pontuação, e enviar `codigo_ibge_cidade`.
  - `valores`: Os decimais precisam estar coerentes e baterem: `valor_servicos`, `valor_liquido_nfs`.
  - Mapear corretamente erros. Ex: Rejeição `RNG6110` geralmente é falha no objeto `tributacao`.

---

## Passo 4: Webhook Assíncrono (Obrigatoriamente Exposto)
Crie o Controller `WebhookNfseController`:
1. Rota: `POST /api/webhook/nfse` (sem middleware `auth:sanctum`).
2. **Segurança**: Crie uma chave secreta no `.env` (`WEBHOOK_DIGISAN_SECRET`). O método deve verificar se o cabeçalho bate com o segredo estipulado (ex: `X-Webhook-Token`).
3. Lógica:
   - Resgatar o JSON de disparo da Digisan.
   - Localizar a fatura via `$fatura = ContasReceber::where('id_faturamento', $payload['id'])->first()`.
   - De acordo com o `status` recebido ("sucesso" / "erro"), alterar o status no banco e salvar a URL dos anexos.

---

## Passo 5: Interface Frontend (UI/UX)
1. **Regra de Design Geral**: Siga as regras puras do projeto (MUI, Tailwind, Design System "Orange/Purple" se for o caso, sem violar as regras globais do workspace atual).
2. **Listagem Padrão**:
   - Exiba a coluna "NF-e". Pode ser um Chip/Badge.
   - Verde para "Autorizada" (com ícone para baixar PDF/XML abrindo em nova guia).
   - Cinza/Laranja para "Pendente".
   - Botão para "Emitir" (Abre o Modal).
3. **ModalEmissaoNfse**:
   - Faça um modal responsivo (`ModalCentral` padrão se houver) para pré-visualizar a emissão.
   - Exiba ao usuário: "Cliente: Tal, CNPJ: Tal, Valor: R$ X,XX". Mostre que a operação faturará o documento e não tem reversão fácil.
   - Se ocorrer erro do Backend ao emitir (retorno de esquema falho), exiba o erro textualmente em um box vermelho, decodificando as mensagens da Digisan (evite expor JSON raw na tela, formate para o humano ler).

---

## Passo 6: Instruções Finais de Checklist
- [ ] O banco de dados recebeu as colunas.
- [ ] O envio do valor da nota (ex: R$ 0,50) foi testado e formatado sem virar zero para a API.
- [ ] O Webhook foi testado com Postman confirmando atualização no BD e log.
- [ ] Frontend bloqueia múltiplas requisições (disable + loading) no momento do "Emitir" para não gerar NF duplicada.
