import { Aside } from "@astrojs/starlight/components";

## Qué es un e-NCF

El e-NCF (número de comprobante fiscal electrónico) identifica cada e-CF de
forma única. Tiene 13 caracteres, en tres partes:

```
E   31   0000000001
```

- **Serie**: una letra de la `E` a la `Z` (la `P` está reservada, no se
  usa). Puedes tener varias series activas para el mismo tipo.
- **Tipo**: el código del [tipo de e-CF](/conceptos/tipos-de-ecf/), 2
  dígitos.
- **Secuencial**: la posición dentro del rango que la DGII te autorizó,
  10 dígitos.

## Cómo lo asigna NovaFE

La DGII te autoriza un rango por tipo, serie y ambiente (por ejemplo,
"serie E, tipo 31, del 1 al 1,000,000, en Producción"). Cuando emites un
comprobante, NovaFE toma el siguiente número disponible de ese rango de
forma atómica: si dos emisiones llegan al mismo tiempo, nunca reciben el
mismo número. Por defecto no envías el e-NCF en el payload: NovaFE lo asigna y
te lo devuelve en la respuesta. Si tu propio sistema ya numera los comprobantes,
consulta la sección Numeración propia, más abajo.

## Vencimiento

Al registrar un rango indicas su vencimiento (`expiresOn`): es la fecha que
figura en la autorización de la DGII. NovaFE no la calcula por ti, porque va
firmada en cada comprobante. Normalmente es el 31 de diciembre del año siguiente
a la autorización, pero confírmala con tu carta de autorización. No puede estar
en el pasado.

En pruebas (TesteCF) y certificación (CerteCF) la DGII usa la misma fecha para
todos los rangos; el panel la propone al registrar el rango y puedes cambiarla.

<Aside type="note" title="Excepción: tipos 32 y 34">
  Los rangos de los tipos 32 (Consumo) y 34 (Nota de Crédito) no vencen: la DGII
  no les exige fecha límite.
</Aside>

<Aside
  type="caution"
  title="Un número consumido por un comprobante rechazado no vuelve a tu stock"
>
  Cuando la DGII rechaza un comprobante, en la mayoría de los casos ese e-NCF
  queda consumido: no vuelve a estar disponible. Esto es correcto y esperado, no
  un error de NovaFE: la DGII no exige que uses los números de un rango de forma
  consecutiva sin huecos, así que perder algunos números a rechazos no genera
  ningún problema de cumplimiento. La excepción es el rechazo en el que la
  propia DGII informa que no consumió el número (`dgii.sequenceUsed` en
  `false`): ese mismo comprobante se puede reenviar con el mismo e-NCF. Ver
  [Rechazos y reintentos](/emision/rechazos-y-reintentos/).
</Aside>

## Numeración propia

Si tu sistema ya asigna los números, por ejemplo un servicio intermedio que
numera los comprobantes de varios puntos de facturación y necesita saber de
cuál salió cada uno, puedes conservar ese control. El ajuste `sequences.mode`
de la configuración de tu tenant admite dos valores:

| Valor                   | Quién numera                                    |
| ----------------------- | ----------------------------------------------- |
| `managed` (por defecto) | NovaFE, desde los rangos que registras.         |
| `external`              | Tu sistema, que envía el e-NCF en cada emisión. |

Con `external`:

- `POST /ecf` exige `encf`, de 13 caracteres y con el tipo que corresponde al
  comprobante. En todos los tipos salvo el 32 y el 34 exige además
  `sequenceExpiresOn` (formato `dd-MM-yyyy`), la fecha de vencimiento de tu
  rango. En los tipos 32 y 34 no se envía.
- No necesitas registrar rangos en NovaFE. Que cada número pertenezca a un rango
  autorizado y vigente es responsabilidad de tu sistema: NovaFE no lo valida y,
  por lo mismo, no emite alertas de stock ni de vencimiento de secuencias.
- NovaFE comprueba que el número no se haya usado ya en ese ambiente. Si se
  repite, responde `409`: un e-NCF no se emite dos veces.
- Si NovaFE rechaza la petición antes de guardar el comprobante (por una
  validación, la cuota del plan o la firma), no se consumió nada de su lado y
  puedes reintentar con el mismo número.
- `POST /sequences/allocate` deja de estar disponible y responde `409`.

Con `managed`, enviar `encf` o `sequenceExpiresOn` produce un error `400`; no se
ignoran en silencio.

<Aside type="caution" title="Al volver a la numeración de NovaFE">
  Mientras numeras tú, NovaFE no avanza el contador de tus rangos. Si más
  adelante vuelves a `managed`, registra un rango nuevo que empiece después del
  último número que usaste. De lo contrario, NovaFE podría intentar entregar
  números que ya existen.
</Aside>

## Registrar un rango y consultar tu stock

```
POST /api/v1/sequences        registra un rango autorizado por la DGII (con su expiresOn)
GET  /api/v1/sequences        todos tus rangos, con su stock
GET  /api/v1/sequences/{id}   un rango puntual
```

```json
{
  "id": "...",
  "environment": "Test",
  "type": 31,
  "series": "E",
  "rangeFrom": 1,
  "rangeTo": 1000000,
  "next": 42,
  "capacity": 1000000,
  "remaining": 999959,
  "isLowStock": false,
  "expiresOn": "31-12-2027",
  "active": true
}
```

`remaining`, `capacity` e `isLowStock` los calcula NovaFE en cada consulta;
no tienes que llevar la cuenta tú mismo. Cuando `isLowStock` pasa a `true`
(por defecto, al 20 % o menos de stock), también te llega el webhook
[`sequence.low`](/webhooks/catalogo-de-eventos/).

Dos operaciones más, de uso ocasional:

```
POST /api/v1/sequences/allocate       toma el siguiente número a mano
POST /api/v1/sequences/{id}/deactivate  desactiva un rango (típicamente, ya agotado)
```

<Aside type="tip" title="Normalmente no necesitas /allocate">
  `POST /ecf` ya asigna el número por ti como parte de la emisión. `/allocate`
  existe para el caso puntual en que necesitas reservar un e-NCF fuera del flujo
  normal de emisión. No está disponible si numeras tú (`sequences.mode` en
  `external`).
</Aside>

Si te queda un rango sin usar y quieres descartarlo formalmente ante la
DGII, esa es una [anulación de e-NCF](/anulacion-ncf/), no una operación de
esta sección.