212 lines
10 KiB
Markdown
212 lines
10 KiB
Markdown
# 🇨🇴 DIAN Electronic Invoicing Hub ("Software Propio")
|
|
## Innovación & Desarrollo S.A.S. • NIT 901.554.892-9
|
|
### Hub Fiscal Centralizado Multi-Tenant para **DripZone** y **PacificTrans**
|
|
|
|
[](https://nodejs.org/)
|
|
[](https://www.typescriptlang.org/)
|
|
[](https://www.fastify.io/)
|
|
[](https://www.prisma.io/)
|
|
[](https://www.postgresql.org/)
|
|
[](https://react.dev/)
|
|
[](https://www.dian.gov.co/)
|
|
|
|
---
|
|
|
|
## 🏛️ 1. Arquitectura de Software y Principios de Diseño (Clean Architecture & DDD)
|
|
|
|
El sistema ha sido diseñado por el equipo de Arquitectura de Software & Seguridad Cloud aplicando **Clean Architecture (Uncle Bob)** y **Domain-Driven Design (DDD)** con separación estricta de capas e inversión de dependencias:
|
|
|
|
```
|
|
facturacion-dian-hub/
|
|
├── backend/
|
|
│ ├── src/
|
|
│ │ ├── domain/ # Capa de Dominio (Entidades, Value Objects, Puertos, Eventos, Reglas Fiscales)
|
|
│ │ │ ├── entities/ # Factura (Aggregate Root), Cliente, ItemFactura, ResolucionDian, Tenant
|
|
│ │ │ ├── value-objects/ # Cufe (SHA-384), Nit (Módulo 11), Money, SoftwareSecurityCode, FiscalEnums
|
|
│ │ │ ├── ports/ # IFacturaRepository, ITenantRepository, IResolucionRepository, IDianClient, IXmlSigner...
|
|
│ │ │ └── exceptions/ # ValidacionFiscalException, ResolucionAgotadaException, FirmaDigitalException
|
|
│ │ ├── application/ # Capa de Aplicación (Casos de Uso, DTOs y Servicios de Orquestación)
|
|
│ │ │ ├── use-cases/ # EmitirFacturaUseCase, ConsultarFacturasUseCase...
|
|
│ │ │ ├── services/ # DianUblBuilderService (Generador UBL 2.1 estándar)
|
|
│ │ │ └── dtos/ # EmitirFacturaInputDto (Zod), FacturaResponseDto
|
|
│ │ ├── infrastructure/ # Capa de Infraestructura (Adaptadores de Frameworks y Drivers)
|
|
│ │ │ ├── database/ # Prisma Client, PostgreSQL 16 Repositorios y Store Resiliente
|
|
│ │ │ ├── security/ # XadesSigner (Firma XAdES-BES RSA-SHA256), CryptoService (AES-256-GCM)
|
|
│ │ │ ├── dian/ # DianSoapClient (SOAP VPFE y Simulador DIAN Integrado)
|
|
│ │ │ ├── qr/ # QrGeneratorService (SVG y Base64 Data URL)
|
|
│ │ │ └── printing/ # PdfGeneratorService (Representación Gráfica Oficial)
|
|
│ │ └── presentation/ # Capa de Presentación (Controladores, Rutas y Middlewares Fastify)
|
|
│ │ ├── controllers/ # InvoiceController, TenantController, ResolutionController
|
|
│ │ ├── middlewares/ # AuthenticationMiddleware (API Keys), ErrorHandlerMiddleware
|
|
│ │ ├── routes/ # /api/v1/invoices, /api/v1/tenants, /api/v1/resolutions, /health
|
|
│ │ └── server.ts # Fastify App Builder con Helmet, CORS, Rate Limit y Swagger UI
|
|
├── frontend/ # Panel Administrativo Web Moderno (React 18 + Vite 5 + Tailwind CSS v3.4)
|
|
│ ├── src/
|
|
│ │ ├── api/ # Cliente HTTP con soporte Multi-Tenant
|
|
│ │ ├── store/ # Zustand Global State
|
|
│ │ ├── components/ # Navbar, KpiMetrics, InvoicesTable, InvoiceDetailModal, InvoiceEmitterModal...
|
|
│ │ └── App.tsx # Dashboard Principal y Explorador de Facturas
|
|
├── docker-compose.yml # Orquestación de Contenedores (Postgres 16, Backend y Frontend)
|
|
├── Dockerfile.backend # Multi-stage Alpine con usuario no root
|
|
├── Dockerfile.frontend # Multi-stage Nginx Alpine con compresión gzip y headers de seguridad
|
|
└── nginx.conf # Configuración de producción para proxy inverso y SPA
|
|
```
|
|
|
|
---
|
|
|
|
## ⚖️ 2. Cumplimiento Normativo DIAN Colombia (UBL 2.1)
|
|
|
|
El microservicio implementa con exactitud los requerimientos de la **Resolución 000165 de 2023** y el **Anexo Técnico de Factura Electrónica de Venta (Versión 1.9 vigente)**:
|
|
|
|
1. **Algoritmo de Dígito de Verificación (NIT):**
|
|
- Implementa el algoritmo oficial de **Módulo 11** de la DIAN utilizando la serie de primos descendentes `[3, 7, 13, 17, 19, 23, 29, 37, 41, 43, 47, 53, 59, 67, 71]`.
|
|
- Para **Innovación & Desarrollo S.A.S.** (NIT `901554892`), el dígito calculado es **`9`** (`901.554.892-9`).
|
|
|
|
2. **Cálculo de CUFE (Código Único de Factura Electrónica):**
|
|
- Función hash **SHA-384** con formato estricto de 96 caracteres hexadecimales:
|
|
$$\text{CUFE} = \text{SHA-384}(\text{NumFac} + \text{FecFac} + \text{HorFac} + \text{ValFac} + \text{CodImp1} + \text{ValImp1} + \dots + \text{ValTot} + \text{NitOFE} + \text{NumAdq} + \text{ClaveTecnica} + \text{TipoAmbiente})$$
|
|
|
|
3. **Código de Seguridad del Software (`SoftwareSecurityCode`):**
|
|
- Incrustado en `sts:DianExtensions`:
|
|
$$\text{SoftwareSecurityCode} = \text{SHA-384}(\text{SoftwareID} + \text{SoftwarePIN} + \text{NumeroFactura})$$
|
|
|
|
4. **Firma Digital XAdES-BES (XMLDSig):**
|
|
- Firma electrónica enveloped con algoritmo **RSA-SHA256** y Canonicalización **C14N** (`http://www.w3.org/TR/2001/REC-xml-c14n-20010315`).
|
|
- Bloque `xades:QualifyingProperties` con `xades:SignedProperties`, `SigningTime`, `SigningCertificate` y `SignaturePolicyIdentifier` oficial de la DIAN (`https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf`).
|
|
|
|
5. **Código QR Estándar:**
|
|
- URL de validación inmediata:
|
|
`https://catalogo-vpfe.dian.gov.co/document/searchqr?documentkey={CUFE}`
|
|
|
|
6. **Control de Consecutivos y Bloqueo Atómico:**
|
|
- La reserva de número consecutivo se ejecuta mediante transacciones ACID atómicas en PostgreSQL (`dian_resolutions.currentConsecutive = currentConsecutive + 1`), impidiendo saltos o colisiones en emisiones concurrentes.
|
|
|
|
---
|
|
|
|
## 🏢 3. Aislamiento Multi-Tenant (DripZone & PacificTrans)
|
|
|
|
El microservicio funciona como un **Hub Fiscal Centralizado** para múltiples unidades de negocio de la compañía:
|
|
|
|
| Tenant | Slug | Caso de Uso Fiscal | Prefijo Autorizado | Actividad Económica (CIIU) | API Key de Prueba |
|
|
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
| **DripZone** | `dripzone` | Venta minorista de Sneakers y Streetwear (IVA 19%) | `DRIP` (1 al 50.000) | 4771 (Prendas de vestir y calzado) | `dz_live_key_98f4bc12e87a` |
|
|
| **PacificTrans** | `pacifictrans` | Transporte terrestre intermunicipal de pasajeros y flete de carga marítima/terrestre (Excluido IVA Art. 476 ET) | `PACT` (1 al 50.000) | 4923 (Transporte de carga por carretera) | `pt_live_key_33c9a184ef10` |
|
|
|
|
---
|
|
|
|
## 🚀 4. Guía de Ejecución Rápida
|
|
|
|
### Opción A: Desarrollo Local con Node 22 (Sin Docker)
|
|
|
|
1. **Iniciar Backend:**
|
|
```bash
|
|
cd backend
|
|
npm install
|
|
npm run dev
|
|
```
|
|
*Servidor API disponible en:* `http://localhost:3001`
|
|
*Swagger Docs:* `http://localhost:3001/api/docs`
|
|
*Health Check:* `http://localhost:3001/health`
|
|
|
|
2. **Iniciar Frontend Panel:**
|
|
```bash
|
|
cd frontend
|
|
npm install
|
|
npm run dev
|
|
```
|
|
*Panel Administrativo disponible en:* `http://localhost:3000`
|
|
|
|
3. **Ejecutar Pruebas Unitarias de Reglas Fiscales:**
|
|
```bash
|
|
cd backend
|
|
npx tsx --test tests/DianFiscalRules.test.ts
|
|
```
|
|
|
|
---
|
|
|
|
### Opción B: Ejecución Contenerizada con Docker Compose v2
|
|
|
|
```bash
|
|
docker compose up -d --build
|
|
```
|
|
|
|
Servicios desplegados:
|
|
- **Base de Datos:** PostgreSQL 16 Alpine en `localhost:5432` con volumen persistente `dian_hub_pgdata`.
|
|
- **Backend API:** Fastify en `http://localhost:3001`.
|
|
- **Frontend Panel:** Nginx en `http://localhost:3000`.
|
|
|
|
---
|
|
|
|
## 📡 5. Catálogo de Endpoints de la API (REST / JSON)
|
|
|
|
Todas las peticiones a la API protegida requieren la cabecera `x-api-key`.
|
|
|
|
### Emitir Factura Electrónica
|
|
`POST /api/v1/invoices`
|
|
**Headers:** `x-api-key: dz_live_key_98f4bc12e87a`, `Content-Type: application/json`
|
|
|
|
```json
|
|
{
|
|
"operationType": "10",
|
|
"paymentType": "1",
|
|
"paymentMethodCode": "10",
|
|
"customer": {
|
|
"identificationType": "13",
|
|
"identificationNumber": "1144987654",
|
|
"legalOrFullName": "Juan David Gómez",
|
|
"email": "juan.gomez@gmail.com",
|
|
"address": "Carrera 100 # 16-20",
|
|
"cityName": "Cali",
|
|
"departmentCode": "76",
|
|
"cityCode": "76001",
|
|
"taxRegime": "49"
|
|
},
|
|
"items": [
|
|
{
|
|
"sku": "DZ-AIR-JORDAN-01",
|
|
"description": "Air Jordan 1 Retro High OG Lost and Found (Talla 42)",
|
|
"quantity": 1,
|
|
"unitPrice": 890000,
|
|
"taxPercentage": 19,
|
|
"taxTypeCode": "01",
|
|
"discountAmount": 0
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Respuesta Exitosa (201 Created):
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"id": "e4f876c1-...",
|
|
"fullNumber": "DRIP-1043",
|
|
"cufe": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855...",
|
|
"subtotal": 890000,
|
|
"taxTotal": 169100,
|
|
"grandTotal": 1059100,
|
|
"dianStatus": "ACEPTADA",
|
|
"dianStatusCode": "00",
|
|
"dianStatusDescription": "Procesado y Validado con Éxito por la DIAN (VPFE Validación Previa).",
|
|
"xmlSignedUrl": "/api/v1/invoices/e4f876c1-.../xml",
|
|
"pdfUrl": "/api/v1/invoices/e4f876c1-.../pdf"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Otros Endpoints:
|
|
- `GET /api/v1/invoices`: Listado con filtros por estado, tenant y búsqueda.
|
|
- `GET /api/v1/invoices/metrics`: Métricas consolidadas (Total Facturado, IVA, % Aprobación).
|
|
- `GET /api/v1/invoices/:id/xml`: Descarga el archivo XML UBL 2.1 con la firma digital XAdES-BES.
|
|
- `GET /api/v1/invoices/:id/pdf`: Visualiza o descarga la representación gráfica oficial en PDF.
|
|
- `GET /api/v1/tenants`: Listado de tenants autorizados.
|
|
- `GET /api/v1/resolutions`: Control de numeración autorizada y alertas de vencimiento.
|
|
|
|
---
|
|
|
|
## 🔒 6. Directrices de Despliegue en VPS (Coolify)
|
|
|
|
> [!IMPORTANT]
|
|
> De conformidad con las políticas operativas del sistema, los despliegues en el servidor VPS de producción se administran **exclusivamente a través de Coolify**. No se deben levantar contenedores manuales fuera de Coolify para garantizar la integridad del enrutamiento de Traefik y evitar duplicidades de puertos o instancias.
|