Skip to content

Commit 518df4e

Browse files
feat(inbound): implementa recurso InboundProductInvoices (NF-e Distribuição)
Adiciona suporte completo à API consulta-nfe-distribuicao-v1 para consulta de NF-e recebidas via Distribuição DFe (SEFAZ), seguindo o padrão do TransportationInvoicesResource existente. ## Novos arquivos - src/core/resources/inbound-product-invoices.ts Classe InboundProductInvoicesResource com 13 métodos públicos: - enableAutoFetch / disableAutoFetch / getSettings (gerenciamento) - getDetails / getProductInvoiceDetails (consulta webhook v1/v2) - getEventDetails / getProductInvoiceEventDetails (eventos) - getXml / getEventXml / getPdf / getJson (downloads) - manifest (Manifestação do Destinatário: 210210/210220/210240) - reprocessWebhook (reprocessar por chave de acesso ou NSU) - tests/unit/resources/inbound-product-invoices.test.ts 31 testes unitários cobrindo validação de parâmetros, caminhos HTTP corretos, métodos HTTP corretos e valores de retorno. - examples/inbound-product-invoices.js Exemplo completo demonstrando todos os fluxos principais. ## Arquivos modificados - src/core/types.ts 12 novos tipos/interfaces: InboundInvoiceMetadata, InboundProductInvoiceMetadata, InboundSettings, EnableInboundOptions, ManifestEventType, InboundCompany, InboundIssuer, InboundBuyer, InboundTransportation, InboundLinks, InboundProductInvoice, AutomaticManifesting. - src/core/client.ts Lazy getter `inboundProductInvoices` usando cteHttp (api.nfse.io). - src/core/resources/index.ts Export do InboundProductInvoicesResource. - src/index.ts Re-exports de todos os tipos de NF-e Distribuição. - docs/API.md Referência completa da API com assinaturas, tabelas de parâmetros, tabelas de resposta e exemplos de código para todos os 13 métodos. - README.md Seção "NF-e de Entrada - Distribuição" com exemplos de uso em português e tabela de tipos de manifestação. ## Decisões técnicas - Reutiliza o HttpClient de CT-e (mesmo host api.nfse.io) - Tipos handwritten (nomes gerados são ilegíveis: Sucessonarequisio) - tpEvent do manifest é passado como query param na URL - Webhook v2 (getProductInvoice*) omite nsuParent/nfeSerialNumber/ operationType e adiciona productInvoices[] - Validação de chave de acesso: 44 dígitos numéricos
1 parent 4a86ee8 commit 518df4e

17 files changed

Lines changed: 2023 additions & 9 deletions

README.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,97 @@ const eventoXml = await nfe.transportationInvoices.downloadEventXml(
426426
- Empresa deve estar cadastrada com certificado digital A1 válido
427427
- Webhook deve estar configurado para receber notificações de CT-e
428428

429+
#### 📦 NF-e de Entrada - Distribuição (`nfe.inboundProductInvoices`)
430+
431+
Consultar NF-e (Nota Fiscal Eletrônica de Produto) recebidas via Distribuição NF-e:
432+
433+
```typescript
434+
// Ativar busca automática de NF-e para uma empresa
435+
const settings = await nfe.inboundProductInvoices.enableAutoFetch('empresa-id', {
436+
environmentSEFAZ: 'Production',
437+
webhookVersion: '2',
438+
});
439+
console.log('Status:', settings.status);
440+
441+
// Ativar a partir de um NSU específico
442+
const settings = await nfe.inboundProductInvoices.enableAutoFetch('empresa-id', {
443+
startFromNsu: '999999',
444+
environmentSEFAZ: 'Production',
445+
});
446+
447+
// Verificar configurações atuais
448+
const config = await nfe.inboundProductInvoices.getSettings('empresa-id');
449+
console.log('Busca ativa:', config.status);
450+
451+
// Desativar busca automática
452+
await nfe.inboundProductInvoices.disableAutoFetch('empresa-id');
453+
454+
// Consultar NF-e por chave de acesso - formato webhook v2 (recomendado)
455+
const nfe_doc = await nfe.inboundProductInvoices.getProductInvoiceDetails(
456+
'empresa-id',
457+
'35240112345678000190550010000001231234567890'
458+
);
459+
console.log('Emissor:', nfe_doc.issuer?.name);
460+
console.log('Valor:', nfe_doc.totalInvoiceAmount);
461+
462+
// Baixar XML da NF-e
463+
const xml = await nfe.inboundProductInvoices.getXml(
464+
'empresa-id',
465+
'35240112345678000190550010000001231234567890'
466+
);
467+
fs.writeFileSync('nfe.xml', xml);
468+
469+
// Baixar PDF (DANFE)
470+
const pdf = await nfe.inboundProductInvoices.getPdf(
471+
'empresa-id',
472+
'35240112345678000190550010000001231234567890'
473+
);
474+
475+
// Enviar manifestação (Ciência da Operação por padrão)
476+
await nfe.inboundProductInvoices.manifest(
477+
'empresa-id',
478+
'35240112345678000190550010000001231234567890'
479+
);
480+
481+
// Manifestar com evento específico
482+
await nfe.inboundProductInvoices.manifest(
483+
'empresa-id',
484+
'35240112345678000190550010000001231234567890',
485+
210220 // Confirmação da Operação
486+
);
487+
488+
// Consultar evento da NF-e
489+
const evento = await nfe.inboundProductInvoices.getEventDetails(
490+
'empresa-id',
491+
'35240112345678000190550010000001231234567890',
492+
'chave-evento'
493+
);
494+
495+
// Baixar XML do evento
496+
const eventoXml = await nfe.inboundProductInvoices.getEventXml(
497+
'empresa-id',
498+
'35240112345678000190550010000001231234567890',
499+
'chave-evento'
500+
);
501+
502+
// Reprocessar webhook
503+
await nfe.inboundProductInvoices.reprocessWebhook('empresa-id', '35240...');
504+
```
505+
506+
> **Nota:** A API de NF-e Distribuição usa um host separado (`api.nfse.io`). Você pode configurar uma chave API específica com `dataApiKey`, ou o SDK usará `apiKey` como fallback.
507+
508+
**Pré-requisitos:**
509+
- Empresa deve estar cadastrada com certificado digital A1 válido
510+
- Webhook deve estar configurado para receber notificações de NF-e
511+
512+
**Tipos de Manifestação:**
513+
514+
| Código | Evento |
515+
|--------|--------|
516+
| `210210` | Ciência da Operação (padrão) |
517+
| `210220` | Confirmação da Operação |
518+
| `210240` | Operação não Realizada |
519+
429520
---
430521

431522
### Opções de Configuração

docs/API.md

Lines changed: 257 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Complete API reference for the NFE.io Node.js SDK v3.
1616
- [Natural People](#natural-people)
1717
- [Webhooks](#webhooks)
1818
- [Transportation Invoices (CT-e)](#transportation-invoices-ct-e)
19+
- [Inbound Product Invoices (NF-e Distribuição)](#inbound-product-invoices-nf-e-distribuição)
1920
- [Types](#types)
2021
- [Error Handling](#error-handling)
2122
- [Advanced Usage](#advanced-usage)
@@ -1644,6 +1645,256 @@ fs.writeFileSync('cte-event.xml', eventXml);
16441645

16451646
---
16461647

1648+
### Inbound Product Invoices (NF-e Distribuição)
1649+
1650+
**Resource:** `nfe.inboundProductInvoices`
1651+
1652+
Query NF-e (Nota Fiscal Eletrônica de Produto) documents received via SEFAZ Distribuição NF-e.
1653+
1654+
> **Note:** This resource uses a separate API host (`api.nfse.io`). You can configure a specific API key with `dataApiKey`, or the SDK will use `apiKey` as fallback.
1655+
1656+
**Prerequisites:**
1657+
- Company must be registered with a valid A1 digital certificate
1658+
- Webhook must be configured to receive NF-e notifications
1659+
1660+
#### `enableAutoFetch(companyId: string, options: EnableInboundOptions): Promise<InboundSettings>`
1661+
1662+
Enable automatic NF-e inbound fetching for a company.
1663+
1664+
```typescript
1665+
// Enable with production environment and webhook v2
1666+
const settings = await nfe.inboundProductInvoices.enableAutoFetch('company-id', {
1667+
environmentSEFAZ: 'Production',
1668+
webhookVersion: '2',
1669+
});
1670+
1671+
// Enable starting from a specific NSU
1672+
const settings = await nfe.inboundProductInvoices.enableAutoFetch('company-id', {
1673+
startFromNsu: '999999',
1674+
environmentSEFAZ: 'Production',
1675+
});
1676+
1677+
// Enable with automatic manifesting
1678+
const settings = await nfe.inboundProductInvoices.enableAutoFetch('company-id', {
1679+
environmentSEFAZ: 'Production',
1680+
automaticManifesting: { minutesToWaitAwarenessOperation: '30' },
1681+
});
1682+
```
1683+
1684+
**Options:**
1685+
1686+
| Property | Type | Description |
1687+
|----------|------|-------------|
1688+
| `startFromNsu` | `string` | Start searching from this NSU number |
1689+
| `startFromDate` | `string` | Start searching from this date (ISO 8601) |
1690+
| `environmentSEFAZ` | `string \| null` | SEFAZ environment ('Production', etc.) |
1691+
| `automaticManifesting` | `AutomaticManifesting` | Auto-manifest configuration |
1692+
| `webhookVersion` | `string` | Webhook version ('1' or '2') |
1693+
1694+
#### `disableAutoFetch(companyId: string): Promise<InboundSettings>`
1695+
1696+
Disable automatic NF-e inbound fetching for a company.
1697+
1698+
```typescript
1699+
const settings = await nfe.inboundProductInvoices.disableAutoFetch('company-id');
1700+
console.log('Status:', settings.status); // 'Inactive'
1701+
```
1702+
1703+
#### `getSettings(companyId: string): Promise<InboundSettings>`
1704+
1705+
Get current automatic NF-e inbound settings.
1706+
1707+
```typescript
1708+
const settings = await nfe.inboundProductInvoices.getSettings('company-id');
1709+
console.log('Status:', settings.status);
1710+
console.log('Environment:', settings.environmentSEFAZ);
1711+
console.log('Webhook version:', settings.webhookVersion);
1712+
console.log('Start NSU:', settings.startFromNsu);
1713+
```
1714+
1715+
**Response (`InboundSettings`):**
1716+
1717+
| Property | Type | Description |
1718+
|----------|------|-------------|
1719+
| `status` | `string` | Current status ('Active', 'Inactive', etc.) |
1720+
| `startFromNsu` | `string` | Starting NSU number |
1721+
| `startFromDate` | `string` | Starting date (if configured) |
1722+
| `environmentSEFAZ` | `string \| null` | SEFAZ environment |
1723+
| `automaticManifesting` | `AutomaticManifesting` | Auto-manifest configuration |
1724+
| `webhookVersion` | `string` | Webhook version |
1725+
| `companyId` | `string` | Company ID |
1726+
| `createdOn` | `string` | Creation timestamp |
1727+
| `modifiedOn` | `string` | Last modification timestamp |
1728+
1729+
#### `getDetails(companyId: string, accessKey: string): Promise<InboundInvoiceMetadata>`
1730+
1731+
Retrieve NF-e metadata by 44-digit access key (webhook v1 format).
1732+
1733+
```typescript
1734+
const nfeDoc = await nfe.inboundProductInvoices.getDetails(
1735+
'company-id',
1736+
'35240112345678000190550010000001231234567890'
1737+
);
1738+
console.log('Issuer:', nfeDoc.issuer?.name);
1739+
console.log('Amount:', nfeDoc.totalInvoiceAmount);
1740+
console.log('Issued:', nfeDoc.issuedOn);
1741+
```
1742+
1743+
#### `getProductInvoiceDetails(companyId: string, accessKey: string): Promise<InboundProductInvoiceMetadata>`
1744+
1745+
Retrieve NF-e metadata by 44-digit access key (webhook v2 format, recommended).
1746+
1747+
```typescript
1748+
const nfeDoc = await nfe.inboundProductInvoices.getProductInvoiceDetails(
1749+
'company-id',
1750+
'35240112345678000190550010000001231234567890'
1751+
);
1752+
console.log('Issuer:', nfeDoc.issuer?.name);
1753+
console.log('Amount:', nfeDoc.totalInvoiceAmount);
1754+
console.log('Product invoices:', nfeDoc.productInvoices?.length);
1755+
```
1756+
1757+
**Response (`InboundInvoiceMetadata` / `InboundProductInvoiceMetadata`):**
1758+
1759+
| Property | Type | Description |
1760+
|----------|------|-------------|
1761+
| `id` | `string` | Document ID |
1762+
| `accessKey` | `string` | 44-digit access key |
1763+
| `nsu` | `string` | NSU number |
1764+
| `nfeNumber` | `string` | NF-e number |
1765+
| `issuer` | `InboundIssuer` | Issuer information |
1766+
| `buyer` | `InboundBuyer` | Buyer information |
1767+
| `totalInvoiceAmount` | `string` | Total amount |
1768+
| `issuedOn` | `string` | Issue date |
1769+
| `description` | `string` | Description |
1770+
| `links` | `InboundLinks` | XML/PDF download links |
1771+
| `productInvoices` | `InboundProductInvoice[]` | Product invoices (v2 only) |
1772+
1773+
#### `getEventDetails(companyId: string, accessKey: string, eventKey: string): Promise<InboundInvoiceMetadata>`
1774+
1775+
Retrieve NF-e event metadata (webhook v1 format).
1776+
1777+
```typescript
1778+
const event = await nfe.inboundProductInvoices.getEventDetails(
1779+
'company-id',
1780+
'35240112345678000190550010000001231234567890',
1781+
'event-key-123'
1782+
);
1783+
```
1784+
1785+
#### `getProductInvoiceEventDetails(companyId: string, accessKey: string, eventKey: string): Promise<InboundProductInvoiceMetadata>`
1786+
1787+
Retrieve NF-e event metadata (webhook v2 format).
1788+
1789+
```typescript
1790+
const event = await nfe.inboundProductInvoices.getProductInvoiceEventDetails(
1791+
'company-id',
1792+
'35240112345678000190550010000001231234567890',
1793+
'event-key-123'
1794+
);
1795+
```
1796+
1797+
#### `getXml(companyId: string, accessKey: string): Promise<string>`
1798+
1799+
Download NF-e XML content.
1800+
1801+
```typescript
1802+
const xml = await nfe.inboundProductInvoices.getXml(
1803+
'company-id',
1804+
'35240112345678000190550010000001231234567890'
1805+
);
1806+
fs.writeFileSync('nfe.xml', xml);
1807+
```
1808+
1809+
#### `getEventXml(companyId: string, accessKey: string, eventKey: string): Promise<string>`
1810+
1811+
Download NF-e event XML content.
1812+
1813+
```typescript
1814+
const eventXml = await nfe.inboundProductInvoices.getEventXml(
1815+
'company-id',
1816+
'35240112345678000190550010000001231234567890',
1817+
'event-key-123'
1818+
);
1819+
fs.writeFileSync('nfe-event.xml', eventXml);
1820+
```
1821+
1822+
#### `getPdf(companyId: string, accessKey: string): Promise<string>`
1823+
1824+
Download NF-e PDF (DANFE).
1825+
1826+
```typescript
1827+
const pdf = await nfe.inboundProductInvoices.getPdf(
1828+
'company-id',
1829+
'35240112345678000190550010000001231234567890'
1830+
);
1831+
```
1832+
1833+
#### `getJson(companyId: string, accessKey: string): Promise<InboundInvoiceMetadata>`
1834+
1835+
Get NF-e data in JSON format.
1836+
1837+
```typescript
1838+
const json = await nfe.inboundProductInvoices.getJson(
1839+
'company-id',
1840+
'35240112345678000190550010000001231234567890'
1841+
);
1842+
```
1843+
1844+
#### `manifest(companyId: string, accessKey: string, tpEvent?: ManifestEventType): Promise<string>`
1845+
1846+
Send a manifest event for an NF-e. Defaults to `210210` (Ciência da Operação).
1847+
1848+
```typescript
1849+
// Ciência da Operação (default)
1850+
await nfe.inboundProductInvoices.manifest(
1851+
'company-id',
1852+
'35240112345678000190550010000001231234567890'
1853+
);
1854+
1855+
// Confirmação da Operação
1856+
await nfe.inboundProductInvoices.manifest(
1857+
'company-id',
1858+
'35240112345678000190550010000001231234567890',
1859+
210220
1860+
);
1861+
1862+
// Operação não Realizada
1863+
await nfe.inboundProductInvoices.manifest(
1864+
'company-id',
1865+
'35240112345678000190550010000001231234567890',
1866+
210240
1867+
);
1868+
```
1869+
1870+
**Manifest Event Types:**
1871+
1872+
| Code | Event |
1873+
|------|-------|
1874+
| `210210` | Ciência da Operação (awareness, default) |
1875+
| `210220` | Confirmação da Operação (confirmation) |
1876+
| `210240` | Operação não Realizada (operation not performed) |
1877+
1878+
#### `reprocessWebhook(companyId: string, accessKeyOrNsu: string): Promise<InboundProductInvoiceMetadata>`
1879+
1880+
Reprocess a webhook notification by access key or NSU.
1881+
1882+
```typescript
1883+
// By access key
1884+
await nfe.inboundProductInvoices.reprocessWebhook(
1885+
'company-id',
1886+
'35240112345678000190550010000001231234567890'
1887+
);
1888+
1889+
// By NSU
1890+
await nfe.inboundProductInvoices.reprocessWebhook(
1891+
'company-id',
1892+
'12345'
1893+
);
1894+
```
1895+
1896+
---
1897+
16471898
## Types
16481899

16491900
### Core Types
@@ -1922,7 +2173,12 @@ import type {
19222173
NaturalPerson,
19232174
Webhook,
19242175
ListResponse,
1925-
PaginationOptions
2176+
PaginationOptions,
2177+
InboundInvoiceMetadata,
2178+
InboundProductInvoiceMetadata,
2179+
InboundSettings,
2180+
EnableInboundOptions,
2181+
ManifestEventType
19262182
} from 'nfe-io';
19272183

19282184
const config: NfeConfig = {

0 commit comments

Comments
 (0)