# Procesador de DTE → Contabilidad (El Salvador)

Aplicación web (100% cliente, sin backend) que lee los archivos JSON de tus Documentos
Tributarios Electrónicos (DTE) y genera:

1. Un **libro contable en Excel** (`.xlsx`) con todos los documentos, clasificados, con
   hojas dedicadas para Notas de Crédito/Débito y Documentos Anulados, y los totales de
   IVA débito/crédito (bruto y neto).
2. Los **Anexos 1, 2, 3 y el Anexo de Documentos Anulados** del Formulario F-07 (declaración
   mensual de IVA) del Ministerio de Hacienda, listos para subir al portal, en formato CSV.
3. Detección automática de **eventos de invalidación** (anulaciones): si subes el JSON del
   evento junto con los DTE, el documento anulado se excluye de los Anexos 1/2/3 y aparece
   en el Anexo de Documentos Anulados.
4. **Ajuste por documento** de las columnas que requieren criterio contable (tipo de operación,
   costo/gasto) directamente en la vista previa, sin editar el CSV a mano.

Todo el procesamiento ocurre en el navegador del usuario. Ningún archivo ni dato fiscal se
envía a un servidor — importante porque los DTE contienen NIT, montos y datos de clientes.

## Monetización (opcional): licencias con PayPal

La app puede pedir una licencia paga antes de permitir **descargar** el Excel/anexos —
procesar y previsualizar los DTE sigue siendo gratis y 100% local, solo el botón de
descarga queda condicionado. Esto requiere desplegar un backend pequeño (Cloudflare
Worker) que cobra vía PayPal y decide qué NIT tiene acceso; ver
[`backend/README.md`](backend/README.md) para desplegarlo paso a paso, y editar
`js/license.js` (`API_BASE` y `PAYPAL_CLIENT_ID`) una vez desplegado. Mientras no lo
configures, el candado de pago se desactiva solo (muestra un aviso en vez de bloquear).

Planes incluidos por defecto (ajustables en `backend/src/plans.js`): pago único de 7 días,
mensual/anual individual (1 empresa), y mensual/anual para despachos contables (hasta 10
NIT distintos bajo la misma licencia) — pensado así porque el F-07 es una obligación
mensual recurrente, y la app también valida que el NIT del JSON que subes coincida con
una empresa registrada en tu licencia (evita procesar/cobrar por la empresa equivocada).

## Cómo correrla

No requiere instalación. Dos formas:

- **Más simple:** doble clic en `index.html` (se abre en tu navegador; toda la lógica corre localmente).
- **Con servidor local** (recomendado si tu navegador restringe `file://`): en PowerShell,
  ```powershell
  powershell -ExecutionPolicy Bypass -File .\serve.ps1 -Port 5500
  ```
  y abre `http://localhost:5500`.

Hay archivos DTE de ejemplo (ficticios) en `sample/` para probar el flujo.

---

## Investigación: cómo funciona la Facturación Electrónica en El Salvador

**Resumen del sistema.** Desde 2022 el Ministerio de Hacienda (MH) exige a los contribuyentes
emitir sus comprobantes fiscales como **DTE (Documento Tributario Electrónico)**: el emisor
genera un JSON con una estructura definida por la DGII, lo firma electrónicamente, lo transmite
al MH para que lo selle ("sello de recepción"), y entrega el JSON/PDF resultante al receptor.
El JSON resultante es el que las empresas descargan y archivan — y es el insumo que esta app procesa.

**Los 11 tipos de DTE (catálogo CAT-002)** — los más relevantes para contabilidad:

| Código | Documento | Uso |
|---|---|---|
| 01 | Factura | Ventas a consumidor final |
| 03 | Comprobante de Crédito Fiscal (CCF) | Ventas/compras entre contribuyentes |
| 04 | Nota de Remisión | Traslado de mercadería sin valor fiscal |
| 05 / 06 | Nota de Crédito / Débito | Ajustan un CCF u otro DTE previo |
| 07 | Comprobante de Retención | Retenciones de IVA (1%) o Renta |
| 08 / 09 | Comprobante / Documento de Liquidación | Ventas por comisionista |
| 11 | Factura de Exportación | Ventas al exterior |
| 14 | Factura de Sujeto Excluido | Compras a personas no inscritas |
| 15 | Comprobante de Donación | Donaciones |

Cada JSON de DTE comparte una estructura base: `identificacion` (tipo, número de control,
código de generación, fecha), `emisor`, `receptor`, `cuerpoDocumento` (detalle de ítems) y
`resumen` (totales: exento, no sujeto, gravado, IVA, total a pagar). Esta app lee esos campos
para normalizar cada documento en un registro contable.

**Lo que hay que presentarle a Hacienda con esos datos: los Anexos del F-07.** Desde 2021,
la declaración mensual de IVA (Formulario F-07) exige adjuntar anexos en **CSV separado por
punto y coma (`;`), sin encabezados, codificación UTF-8**, uno por tipo de operación:

- **Anexo 1 — Ventas a Contribuyentes**: una fila por CCF/Nota emitida, con NRC del cliente,
  montos exentos/gravados, IVA y el código de generación del DTE.
- **Anexo 2 — Ventas a Consumidor Final / Exportación**: una fila **por día y tipo de
  documento** (se agrupan, porque el consumidor final no se identifica).
- **Anexo 3 — Detalle de Compras**: una fila por documento recibido (CCF, notas, sujeto
  excluido), con el crédito fiscal correspondiente.

Además existen columnas que **el DTE no trae** y que la ley exige asignar con criterio
contable (tipo de operación de renta, sector económico, si es costo o gasto). Esta app las
deja como parámetro global configurable, con la opción de **sobrescribirlas documento por
documento** desde la tabla de vista previa (solo aplica a Anexo 1 y 3, que no se agrupan;
el Anexo 2 agrupa por día y usa siempre el valor global).

**Notas de Crédito/Débito y anulaciones.** Un DTE tipo 05/06 (Nota de Crédito/Débito) trae
un `documentoRelacionado` que apunta al CCF/factura que ajusta; la app cruza ese código contra
el resto del lote y avisa si el documento relacionado no aparece (puede ser normal si es de
un período anterior). Para anulaciones, el Ministerio de Hacienda no las declara dentro del
DTE mismo sino con un **Evento de Invalidación** aparte: un JSON con las secciones
`documento` (el DTE anulado) y `motivo` (causa, fechas, responsable). Esta app detecta ese
segundo tipo de archivo automáticamente, marca el DTE original como anulado, lo excluye de
los Anexos 1/2/3 (tal como exige el manual: "no incluir documentos anulados") y lo reporta
en el Anexo de Documentos Anulados.

### Fuentes consultadas

- [Guía de Integración de Facturación Electrónica SV — MH](https://factura.gob.sv/wp-content/uploads/2021/11/FESVDGIIMH_GuiaIntegracionFacturaElectronicasSV.pdf)
- [Tipos de DTE — algoritmos.io](https://algoritmos.io/factura-sv/tipos-dte.html)
- [Modificación a los Anexos F-07/F-14 — Ministerio de Hacienda](https://www.mh.gob.sv/modificacion-a-los-anexos-de-los-formularios-de-iva-f07-y-pago-a-cuenta-f14-a-partir-del-periodo-tributario-de-enero-2025/)
- [Manual de Usuario Carga de Anexos F-07 — transparenciafiscal.gob.sv](https://www.transparenciafiscal.gob.sv/downloads/pdf/700-DGII-MN-2021-26031.pdf) *(PDF escaneado, no se pudo extraer texto automáticamente)*
- Detalle de columnas por anexo: [Anexo 1](https://dojo.facturallama.com/anexo-1-detalle-de-ventas-a-contribuyentes/), [Anexo 2](https://dojo.facturallama.com/anexo-2-detalle-de-ventas-a-consumidor-final/), [Anexo 3](https://dojo.facturallama.com/anexo-3-detalle-de-compras/), [Anexo de Documentos Anulados](https://dojo.facturallama.com/anexo-de-documentos-anulados/) — FacturaLlama DOJO
- [Evento de Invalidación 2.0 — Contaportable](https://www.contaportable.com/evento-de-invalidacion-normativa-2-0/)
- [Evento de Invalidación y Evento de Contingencia — Contaportable](https://www.contaportable.com/evento-de-invalidacion-y-evento-de-contingencia-en-facturacion-electronica/)
- [Actualización DTE El Salvador 2026 (Normativa de Cumplimiento DTE 2.0)](https://llbsolutions.com/es/actualizacion-dte-el-salvador-2026/)
- [Guía completa de Facturación Electrónica 2026 — Facxi](https://facxi.com/blog/guia-facturacion-electronica-el-salvador)

---

## Factibilidad: qué es viable y qué no

**Totalmente viable (implementado en esta app):**
- Parsear JSON de DTE ya emitidos/recibidos (no requiere certificado digital ni conexión a Hacienda).
- Consolidar todos los documentos de un período en un libro contable en Excel.
- Generar los Anexos 1, 2, 3 y el Anexo de Documentos Anulados en el formato CSV que pide
  el portal de declaraciones.
- Cruzar Notas de Crédito/Débito contra el documento que afectan, y eventos de invalidación
  contra el DTE que anulan, avisando cuando falta una de las dos partes en el lote cargado.
- Corre sin backend, sin exponer datos fiscales sensibles a terceros.

**Fuera de alcance de esta app (y por qué):**
- **Emitir/firmar/transmitir DTE a Hacienda.** Eso ocurre *antes* de tener el JSON final y
  requiere un certificado/llave privada emitido por el MH y un "firmador" homologado — es
  responsabilidad del sistema de facturación del contribuyente, no de un procesador posterior.
- **Subir el anexo directamente al portal del MH.** El portal (`admin.factura.gob.sv` /
  DEC IVA) no tiene una API pública de carga; se sube manualmente el CSV en su interfaz web.
- **Generar el propio Evento de Invalidación.** La app solo *lee* eventos de invalidación ya
  emitidos (para excluir el DTE anulado de los anexos); crear y firmar uno nuevo requiere el
  mismo certificado/firmador que emitir un DTE.
- Comprobante de Retención (07) y Comprobante de Donación (15) se muestran en el Excel pero
  no tienen un anexo dedicado propio en esta versión.

**Nivel de confianza de los formatos — léase antes de usar en producción:**
Las columnas exactas de los Anexos 1/2/3 y del Anexo de Documentos Anulados, así como la
estructura del JSON del Evento de Invalidación, se reconstruyeron a partir de manuales de
contadores y proveedores certificados, **no del manual oficial completo del MH** (sus PDFs
están escaneados como imagen y no pudieron extraerse automáticamente en esta investigación).
Antes de presentar un archivo real:
1. Compara las columnas generadas contra el "Manual de Usuario para Carga de Archivo de los
   Anexos F-07" vigente en [mh.gob.sv](https://www.mh.gob.sv).
2. Ten a un contador autorizado revisando las columnas marcadas `[juicio]` en el código
   (tipo de operación, sector, costo/gasto) — la ley exige criterio profesional ahí, no un
   valor automático.
3. Si vas a procesar eventos de invalidación reales, compara primero uno tuyo contra lo que
   `js/dte-parser.js` espera (`documento.tipoDte`, `documento.codigoGeneracion`,
   `motivo.tipoAnulacion`, etc.) — es la parte de esta app con menor confianza documental.
4. Ten en cuenta que el MH publicó la **Normativa de Cumplimiento DTE 2.0**, obligatoria
   desde el **1 de diciembre de 2026** — si tu volumen de DTEs se genera después de esa
   fecha, valida que los nombres de campo del JSON no hayan cambiado (`js/dte-parser.js`
   está escrito para tolerar variaciones menores, pero no una reestructuración mayor).

## Estructura del proyecto

```
dte-contabilidad-sv/
├── index.html            # UI
├── css/styles.css
├── js/
│   ├── dte-parser.js      # normaliza el JSON de un DTE a un registro plano
│   ├── anexos.js          # arma las filas de los Anexos 1/2/3 y el CSV final
│   ├── excel-export.js    # arma el libro de Excel (SheetJS)
│   └── app.js             # UI: carga de archivos, validaciones, descargas
├── vendor/                # SheetJS, JSZip, FileSaver (vendorizados para uso offline)
├── sample/                # DTE de ejemplo (datos ficticios): venta, CCF venta/compra,
│                          # Nota de Crédito y su Evento de Invalidación de ejemplo
└── serve.ps1              # servidor estático local opcional
```

## Limitaciones conocidas

- El Anexo 2 asume "Exportación dentro del área centroamericana" por defecto para tipoDte 11;
  si tu empresa exporta fuera de Centroamérica, ajusta esa columna manualmente en el CSV.
- No maneja Comprobante de Retención (07) ni Comprobante de Donación (15) más allá de
  contarlos y mostrarlos en el Excel — no arma anexos específicos para ellos.
- El ajuste por documento (override) de tipo de operación/clasificación solo está disponible
  para Anexo 1 y 3; el Anexo 2 agrupa varios documentos en una sola fila por día, así que
  siempre usa el valor global configurado en el paso 3.
- El "neto informativo" de ventas/compras que resta Notas de Crédito en la hoja Resumen es
  solo para lectura rápida — los anexos CSV reportan cada DTE con su monto tal cual, porque
  así es como el sistema del MH espera netearlos (por tipo de documento, no por un total
  pre-calculado).
- Si subes un Evento de Invalidación cuyo DTE original no está en el mismo lote, la app lo
  reporta igual en el Anexo de Documentos Anulados (con una advertencia), pero no puede
  marcar ese DTE como anulado en el Excel porque no lo tiene cargado.
