# Generador de PDF para Facturas SIAT

Una librería TypeScript optimizada para generar PDFs de facturas según el estándar SIAT (Sistema de Información de Administración Tributaria) de Bolivia.

## 🚀 Características

- **Múltiples formatos**: Letter, Legal, Half-Letter, Half-Legal, Roll, Ticket
- **4 estilos diferentes**: Clásico, Moderno, Minimalista, Corporativo
- **Colores personalizables**: Paleta de colores predefinidos
- **Validación robusta**: Validación automática de datos SIAT
- **Configuración flexible**: Opciones configurables para diferentes necesidades
- **Fuentes embebidas**: Fuentes Roboto incluidas
- **Marcas de agua automáticas**: Para documentos de pruebas y anulados
- **Código optimizado**: Estructura modular y mantenible
- **Branding profesional**: Mensaje de autorización con soporte técnico
- **QR dinámico**: Código QR con URL específica por factura

## 📦 Instalación

```bash
npm install siat-pdf
# o
bun add siat-pdf
# o
yarn add siat-pdf
```

## 🔧 Uso Básico

```typescript
import { PdfGenerator, DocumentStyle, PdfFormat } from 'siat-pdf';

// Configurar el generador
const pdfGenerator = new PdfGenerator();

// Datos SIAT
const siatData = {
  urls: {
    xml: 'https://example.com/invoice-001.xml',
    pdf: 'https://example.com/invoice-001.pdf'
  },
  invoice: {
    cabecera: {
      codigoDocumentoSector: 1,
      razonSocialEmisor: 'EMPRESA EJEMPLO S.A.',
      nitEmisor: 12345678,
      numeroFactura: 1001,
      cuf: 'ABC123DEF456GHI789JKL',
      fechaEmision: '2024-01-15T10:30:00',
      nombreRazonSocial: 'CLIENTE EJEMPLO S.R.L.',
      montoTotal: 175.00,
      // ... más campos
    },
    detalle: [
      {
        codigoProducto: 12345,
        descripcion: 'Producto de ejemplo',
        cantidad: 2,
        precioUnitario: 50.00,
        subTotal: 100.00
      }
    ]
  },
  metadata: {
    cuf: 'ABC123DEF456GHI789JKL',
    siatBranchCode: 1,
    siatPointOfSaleCode: 1,
    siatEnvironmentCode: 1, // 1 = Producción, 2 = Pruebas
    siatModalityCode: 1,
    siatDocumentSectorCode: 1,
    siatActivityCode: 1,
    siatNit: 12345678,
    total: 175.00,
    emissionCode: 1,
    statusCode: 1, // 1 = Válido, 3 = Anulado
    completedAt: '2024-01-15T10:30:00',
    extraInfo: [
      { key: 'CustomField', value: 'Valor personalizado' },
      { key: 'Version', value: '1.0' }
    ]
  }
};

// Generar PDF con estilo clásico
const pdfBuffer = await pdfGenerator.makeInvoiceDoc(
  siatData, 
  '#1e40af', // Color
  PdfFormat.LETTER,  // Formato
  DocumentStyle.CLASSIC, // Estilo
  'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==' // Logo en base64
);

// Generar rollo para impresora térmica
const rollPdf = await pdfGenerator.makeInvoiceRoll(siatData, PdfFormat.ROLL);

// Generar ticket minimalista
const ticketPdf = await pdfGenerator.makeInvoiceRoll(siatData, PdfFormat.TICKET);
```

## 📄 Formatos Disponibles

### Formatos de Página
- `PdfFormat.LETTER` - Carta estándar (8.5" x 11")
- `PdfFormat.LEGAL` - Legal (8.5" x 14")
- `PdfFormat.HALF_LETTER` - Media carta (5.5" x 8.5")
- `PdfFormat.HALF_LEGAL` - Media legal (5.5" x 7")
- `PdfFormat.ROLL` - Formato roll para impresoras térmicas
- `PdfFormat.TICKET` - Formato ticket ultra minimalista

### Estilos de Diseño
- `DocumentStyle.CLASSIC` - Diseño clásico con logo centrado
- `DocumentStyle.MODERN` - Diseño moderno con barra lateral
- `DocumentStyle.MINIMALIST` - Diseño elegante con líneas decorativas
- `DocumentStyle.CORPORATE` - Diseño premium con gradientes

## 🎨 Colores Personalizables

Puedes usar cualquier color en formato hexadecimal:

```typescript
// Ejemplos de colores
'#1e40af'  // Azul
'#10b981'  // Verde
'#f59e0b'  // Naranja
'#dc2626'  // Rojo
'#8b5cf6'  // Púrpura
'#64748b'  // Gris
```

## 🖼️ Logo Personalizado

Puedes incluir tu logo personalizado en formato base64:

```typescript
// Logo en base64 (PNG, JPG, etc.)
const logoBase64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';

// Generar PDF con logo personalizado
const pdfBuffer = await pdfGenerator.makeInvoiceDoc(
  siatData, 
  '#1e40af', // Color
  PdfFormat.LETTER,  // Formato
  DocumentStyle.CLASSIC, // Estilo
  logoBase64 // Logo en base64
);

// También puedes usar las opciones
const pdfBuffer2 = await pdfGenerator.makeInvoiceDoc(
  siatData, 
  '#1e40af', 
  PdfFormat.LETTER, 
  DocumentStyle.CLASSIC, 
  undefined, // Sin logo directo
  { logo: logoBase64 } // Logo en opciones
);
```

**Nota**: Si no proporcionas un logo, se usará un logo por defecto transparente.

## ⚙️ Configuración

```typescript
interface IPdfGeneratorConfig {
  defaultFormat: PdfFormat;
  defaultStyle: DocumentStyle;
  defaultColor: string;
  embeddedFonts: boolean;
  enableValidation: boolean;
  enableLogging: boolean;
}
```

## 📋 Métodos Principales

### `makeInvoiceDoc(data, color, format?, style?, logo?, options?)`
Genera un PDF completo con formato, estilo y logo personalizables.

### `makeInvoiceRoll(data, format?, options?)`
Genera un PDF en formato roll o ticket para impresoras térmicas.
- `PdfFormat.ROLL` - Formato roll estándar
- `PdfFormat.TICKET` - Formato ticket ultra minimalista

### `validateData(data)`
Valida los datos SIAT y retorna errores específicos.

## 🔍 Validación de Datos

La librería incluye validación automática de datos SIAT:

```typescript
const validation = pdfGenerator.validateData(siatData);
if (validation.isValid) {
  console.log('✅ Datos válidos');
} else {
  console.log('❌ Errores:', validation.errors);
}
```

## 🏷️ Marcas de Agua Automáticas

La librería aplica automáticamente marcas de agua según el estado del documento:

- **"SIN VALOR LEGAL"**: Cuando `metadata.siatEnvironmentCode === 2` (ambiente de pruebas)
- **"ANULADO"**: Cuando `metadata.statusCode === 3` (documento anulado)

```typescript
// Documento de pruebas (marca de agua automática)
const pruebaData = {
  ...siatData,
  metadata: {
    ...siatData.metadata,
    siatEnvironmentCode: 2 // Marca "SIN VALOR LEGAL"
  }
};

// Documento anulado (marca de agua automática)
const anuladoData = {
  ...siatData,
  metadata: {
    ...siatData.metadata,
    statusCode: 3 // Marca "ANULADO"
  }
};

// Documento de pruebas y anulado (ambas marcas de agua)
const pruebasAnuladoData = {
  ...siatData,
  metadata: {
    ...siatData.metadata,
    siatEnvironmentCode: 2, // Marca "SIN VALOR LEGAL"
    statusCode: 3 // Marca "ANULADO"
  }
};
```

## 🏢 Branding y Autorización

Todos los documentos incluyen un mensaje de autorización profesional:

```
Generado con "FACTUGEST", sistema autorizado por Impuestos Nacionales. Soporte y contacto: 75434250
```

### Características del branding:
- **Fuente optimizada**: Tamaño reducido para mejor presentación
- **Elementos destacados**: "FACTUGEST" y número de teléfono en negro puro
- **Información completa**: Sistema, autorización y contacto en una sola línea
- **URL dinámica**: QR code con URL específica por factura

### QR Code dinámico:
- **URL**: `https://factugest.iathings.com/facturas?cuf={CUF}`
- **Enlace directo**: `https://factugest.iathings.com/facturas`
- **Soporte técnico**: 75434250

## 📊 Estructura de Datos SIAT

```typescript
interface InvoiceResponse {
  urls: {
    xml: string;
    pdf: string;
  };
  invoice: {
    cabecera: {
      codigoDocumentoSector?: number;
      razonSocialEmisor?: string;
      nitEmisor?: number;
      numeroFactura?: number;
      cuf?: string;
      fechaEmision?: string;
      nombreRazonSocial?: string;
      montoTotal?: number;
      // ... más campos
    };
    detalle: Array<{
      codigoProducto?: number;
      descripcion?: string;
      cantidad?: number;
      precioUnitario?: number;
      subTotal?: number;
      // ... más campos
    }>;
  };
  metadata: {
    cuf: string;
    siatBranchCode: number;
    siatPointOfSaleCode: number;
    siatEnvironmentCode: number; // 1=Producción, 2=Pruebas
    siatModalityCode: number;
    siatDocumentSectorCode: number;
    siatActivityCode: number;
    siatNit: number;
    total: number;
    emissionCode: number;
    statusCode: number; // 1=Válido, 3=Anulado
    completedAt: string;
    extraInfo?: Array<{
      key: string;
      value: string;
    }>;
  };
}
```

## 🛠️ Utilidades

### DebugUtils
```typescript
import { DebugUtils } from 'siat-pdf';

// Crear resumen visual de datos
const summary = DebugUtils.createDataSummary(siatData);
console.log(summary);

// Logging con timestamp
DebugUtils.log('Mensaje de debug');
DebugUtils.logError('Error encontrado', error);
```

### ValidationUtils
```typescript
import { ValidationUtils } from 'siat-pdf';

ValidationUtils.isNotEmpty('texto');           // true
ValidationUtils.isPositiveNumber(100);         // true
ValidationUtils.isValidEmail('test@test.com'); // true
ValidationUtils.isValidNIT('1234567890');      // true
```

### FormatUtils
```typescript
import { FormatUtils } from 'siat-pdf';

FormatUtils.formatCurrency(1000);              // "Bs 1.000,00"
FormatUtils.formatDate(new Date());            // "24 de agosto de 2025"
FormatUtils.truncateText('texto largo', 10);   // "texto lar..."
```

## 🚀 Ejemplo Completo

```bash
# Ejecutar el ejemplo incluido
bun run example.ts
```

El ejemplo genera múltiples PDFs con diferentes configuraciones y los guarda en la carpeta `result/`.

### Ejemplos de uso avanzado:

```typescript
import { PdfGenerator, DocumentStyle, PdfFormat } from 'siat-pdf';

const pdfGenerator = new PdfGenerator();

// Generar diferentes estilos
const classicPdf = await pdfGenerator.makeInvoiceDoc(siatData, '#1e40af', PdfFormat.LETTER, DocumentStyle.CLASSIC);
const modernPdf = await pdfGenerator.makeInvoiceDoc(siatData, '#10b981', PdfFormat.LEGAL, DocumentStyle.MODERN);
const minimalistPdf = await pdfGenerator.makeInvoiceDoc(siatData, '#f59e0b', PdfFormat.HALF_LETTER, DocumentStyle.MINIMALIST);
const corporatePdf = await pdfGenerator.makeInvoiceDoc(siatData, '#8b5cf6', PdfFormat.HALF_LEGAL, DocumentStyle.CORPORATE);

// Generar rollos y tickets
const rollPdf = await pdfGenerator.makeInvoiceRoll(siatData, PdfFormat.ROLL);
const ticketPdf = await pdfGenerator.makeInvoiceRoll(siatData, PdfFormat.TICKET);

// Validar datos antes de generar
const validation = pdfGenerator.validateData(siatData);
if (validation.isValid) {
  const pdf = await pdfGenerator.makeInvoiceDoc(siatData, '#1e40af', PdfFormat.LETTER, DocumentStyle.CLASSIC);
  // Guardar PDF...
} else {
  console.log('Errores de validación:', validation.errors);
}
```

## 📁 Estructura del Proyecto

```
src/
├── index.ts              # Punto de entrada principal
├── pdf/                  # Componentes de generación de PDF
│   ├── generator.ts     # Clase principal PdfGenerator
│   ├── components.ts    # Componentes de documentos
│   ├── builders.ts      # Constructores de documentos
│   ├── config.ts        # Configuración y constantes
│   └── utils.ts         # Utilidades específicas
├── types/               # Definiciones de tipos
├── styles/              # Estilos y fuentes
└── utils/               # Utilidades generales
```

## 🔧 Desarrollo

```bash
# Instalar dependencias
bun install

# Compilar
bun run build

# Ejecutar ejemplo
bun run example.ts

# Ejecutar tests
bun test
```

## 📝 Licencia

MIT License - ver archivo LICENSE para más detalles.

## 🤝 Contribuir

1. Fork el proyecto
2. Crea una rama para tu feature (`git checkout -b feature/AmazingFeature`)
3. Commit tus cambios (`git commit -m 'Add some AmazingFeature'`)
4. Push a la rama (`git push origin feature/AmazingFeature`)
5. Abre un Pull Request

## 📞 Soporte

Para soporte técnico o preguntas:
- **Teléfono**: 75434250
- **Website**: https://factugest.iathings.com
- **Issues**: Abre un issue en el repositorio
