npm package: @isaackosmos/react-native-hka-printer
Description: React Native library for HKA fiscal printers
Author: Your Name
Latest version: 1.0.0

# react-native-hka-printer

Biblioteca React Native para impresoras fiscales HKA (Venezuela). Proporciona una interfaz sencilla para conectar, imprimir facturas fiscales y gestionar impresoras fiscales HKA desde aplicaciones React Native Android.

## Características

- ✅ Conexión con impresoras fiscales HKA vía puerto serial
- ✅ Impresión de facturas fiscales
- ✅ Verificación de estado de la impresora
- ✅ Reportes X y Z
- ✅ Cancelación de facturas
- ✅ Manejo de errores robusto
- ✅ TypeScript completo
- ✅ Compatible con React Native 0.73+

## Instalación

```bash
npm install react-native-hka-printer
# o
yarn add react-native-hka-printer
```

### Configuración Android

1. **Permisos**: Añade los siguientes permisos a tu `android/app/src/main/AndroidManifest.xml`:

```xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
```

2. **Reconstruir la aplicación**:

```bash
cd android && ./gradlew clean
cd ..
npx react-native run-android
```

## Uso Básico

```typescript
import HkaPrinter from 'react-native-hka-printer';

// Conectar a la impresora
try {
  await HkaPrinter.connect('/dev/ttyS0');
  console.log('Conectado exitosamente');
} catch (error) {
  console.error('Error al conectar:', error);
}

// Verificar estado
try {
  const status = await HkaPrinter.checkStatus();
  console.log('Estado:', status);
} catch (error) {
  console.error('Error al verificar estado:', error);
}

// Desconectar
try {
  await HkaPrinter.disconnect();
  console.log('Desconectado');
} catch (error) {
  console.error('Error al desconectar:', error);
}
```

## API Reference

### Métodos

#### `connect(port: string): Promise<boolean>`

Conecta con la impresora fiscal HKA.

**Parámetros:**
- `port`: Ruta del puerto serial (ej: `/dev/ttyS0`, `/dev/ttyUSB0`)

**Retorna:** `Promise<boolean>` - `true` si la conexión fue exitosa

**Ejemplo:**
```typescript
await HkaPrinter.connect('/dev/ttyS0');
```

**Puertos comunes en Android:**
- `/dev/ttyS0`, `/dev/ttyS1` - Puertos seriales internos
- `/dev/ttyUSB0`, `/dev/ttyUSB1` - Adaptadores USB-Serial
- `/dev/ttyACM0` - Algunos dispositivos USB

---

#### `disconnect(): Promise<void>`

Desconecta de la impresora.

**Ejemplo:**
```typescript
await HkaPrinter.disconnect();
```

---

#### `checkStatus(): Promise<PrinterStatus>`

Verifica el estado actual de la impresora.

**Retorna:** `Promise<PrinterStatus>`

```typescript
interface PrinterStatus {
  statusCode: number;      // Código de estado de la impresora
  statusDesc: string;      // Descripción del estado
  errorCode: number;       // Código de error (si existe)
  errorDesc: string;       // Descripción del error
  errorValid: boolean;     // Indica si hay un error válido
}
```

**Ejemplo:**
```typescript
const status = await HkaPrinter.checkStatus();
console.log(`Estado: ${status.statusDesc}`);
if (status.errorValid) {
  console.error(`Error: ${status.errorDesc}`);
}
```

---

#### `sendCommand(command: string): Promise<boolean>`

Envía un comando directo a la impresora.

**Parámetros:**
- `command`: Comando HKA a enviar

**Retorna:** `Promise<boolean>` - `true` si el comando fue exitoso

**Ejemplo:**
```typescript
await HkaPrinter.sendCommand('s1'); // Obtener información del serial
```

---

#### `printFiscalInvoice(invoice: FiscalInvoice): Promise<FiscalInvoiceResult>`

Imprime una factura fiscal completa.

**Parámetros:**

```typescript
interface FiscalInvoice {
  customerName?: string;     // Nombre del cliente
  customerRif?: string;      // RIF del cliente
  customerAddress?: string;  // Dirección del cliente
  items: FiscalInvoiceItem[]; // Artículos de la factura
  payments: FiscalInvoicePayment[]; // Formas de pago
}

interface FiscalInvoiceItem {
  description: string;  // Descripción del artículo
  quantity: number;     // Cantidad
  price: number;        // Precio unitario
  taxRate?: string;     // Tasa de IVA ('1' = IVA normal, '2' = IVA reducido, etc.)
}

interface FiscalInvoicePayment {
  type: string;   // Tipo de pago ('01' = Efectivo, '02' = Tarjeta, etc.)
  amount: number; // Monto del pago
}
```

**Retorna:** `Promise<FiscalInvoiceResult>`

```typescript
interface FiscalInvoiceResult {
  success: boolean;
  statusCode: number;
  statusDesc: string;
}
```

**Ejemplo:**
```typescript
const invoice = {
  customerName: 'Juan Pérez',
  customerRif: 'V-12345678',
  customerAddress: 'Caracas, Venezuela',
  items: [
    {
      description: 'Producto A',
      quantity: 2,
      price: 10.50,
      taxRate: '1' // IVA normal
    },
    {
      description: 'Producto B',
      quantity: 1,
      price: 25.00,
      taxRate: '1'
    }
  ],
  payments: [
    {
      type: '01', // Efectivo
      amount: 46.00
    }
  ]
};

try {
  const result = await HkaPrinter.printFiscalInvoice(invoice);
  console.log('Factura impresa:', result);
} catch (error) {
  console.error('Error al imprimir factura:', error);
}
```

**Notas importantes:**
- El total de los pagos debe coincidir con el total de los artículos
- La biblioteca valida automáticamente que los totales coincidan
- Si los totales no coinciden, se lanzará un error `E_INVALID_INVOICE`

---

#### `cancelFiscalInvoice(): Promise<boolean>`

Cancela una factura fiscal en curso.

**Retorna:** `Promise<boolean>` - `true` si la cancelación fue exitosa

**Ejemplo:**
```typescript
await HkaPrinter.cancelFiscalInvoice();
```

---

#### `printXReport(): Promise<boolean>`

Imprime el reporte X (reporte de ventas sin cerrar el día).

**Retorna:** `Promise<boolean>` - `true` si el reporte fue impreso

**Ejemplo:**
```typescript
await HkaPrinter.printXReport();
```

---

#### `printZReport(): Promise<boolean>`

Imprime el reporte Z (cierre fiscal del día).

**Retorna:** `Promise<boolean>` - `true` si el reporte fue impreso

**Ejemplo:**
```typescript
await HkaPrinter.printZReport();
```

---

## Manejo de Errores

La biblioteca lanza errores del tipo `HkaPrinterError` con los siguientes códigos:

### Códigos de Error

| Código | Descripción |
|--------|-------------|
| `E_CONNECT_FAILED` | Error al conectar con la impresora |
| `E_NOT_CONNECTED` | Impresora no conectada |
| `E_PRINTER_EXCEPTION` | Error del SDK de la impresora |
| `E_CMD_FAILED` | Comando falló |
| `E_STATUS_FAILED` | Error al verificar estado |
| `E_INVALID_INVOICE` | Factura inválida (totales no coinciden) |
| `E_OPEN_INVOICE_FAILED` | Error al abrir factura |
| `E_ADD_ITEM_FAILED` | Error al agregar artículo |
| `E_ADD_PAYMENT_FAILED` | Error al agregar pago |
| `E_CLOSE_INVOICE_FAILED` | Error al cerrar factura |
| `E_CANCEL_FAILED` | Error al cancelar factura |
| `E_PRINT_FAILED` | Error al imprimir |
| `E_DISCONNECT_FAILED` | Error al desconectar |
| `E_UNKNOWN_ERROR` | Error desconocido |

### Ejemplo de Manejo de Errores

```typescript
import HkaPrinter, { HkaPrinterError } from 'react-native-hka-printer';

try {
  await HkaPrinter.printFiscalInvoice(invoice);
} catch (error) {
  if (error instanceof HkaPrinterError) {
    console.error(`Error [${error.code}]: ${error.message}`);

    switch (error.code) {
      case 'E_NOT_CONNECTED':
        // Intentar reconectar
        await HkaPrinter.connect('/dev/ttyS0');
        break;
      case 'E_INVALID_INVOICE':
        // Validar la factura
        console.error('Verifica que los totales coincidan');
        break;
      default:
        console.error('Error inesperado');
    }
  }
}
```

## Ejemplo Completo

```typescript
import React, { useState } from 'react';
import { View, Button, Text, Alert } from 'react-native';
import HkaPrinter, { FiscalInvoice } from 'react-native-hka-printer';

export default function App() {
  const [connected, setConnected] = useState(false);

  const connect = async () => {
    try {
      await HkaPrinter.connect('/dev/ttyS0');
      setConnected(true);
      Alert.alert('Éxito', 'Conectado a la impresora');
    } catch (error: any) {
      Alert.alert('Error', error.message);
    }
  };

  const printInvoice = async () => {
    const invoice: FiscalInvoice = {
      customerName: 'Cliente Ejemplo',
      customerRif: 'V-12345678',
      customerAddress: 'Caracas',
      items: [
        {
          description: 'Producto 1',
          quantity: 2,
          price: 15.50,
          taxRate: '1'
        }
      ],
      payments: [
        {
          type: '01',
          amount: 31.00
        }
      ]
    };

    try {
      const result = await HkaPrinter.printFiscalInvoice(invoice);
      Alert.alert('Éxito', 'Factura impresa correctamente');
    } catch (error: any) {
      Alert.alert('Error', error.message);
    }
  };

  const disconnect = async () => {
    try {
      await HkaPrinter.disconnect();
      setConnected(false);
      Alert.alert('Éxito', 'Desconectado de la impresora');
    } catch (error: any) {
      Alert.alert('Error', error.message);
    }
  };

  return (
    <View style={{ flex: 1, justifyContent: 'center', padding: 20 }}>
      <Text style={{ marginBottom: 20, textAlign: 'center' }}>
        Estado: {connected ? '🟢 Conectado' : '🔴 Desconectado'}
      </Text>

      <Button
        title="Conectar"
        onPress={connect}
        disabled={connected}
      />

      <Button
        title="Imprimir Factura"
        onPress={printInvoice}
        disabled={!connected}
      />

      <Button
        title="Desconectar"
        onPress={disconnect}
        disabled={!connected}
      />
    </View>
  );
}
```

## Tipos de IVA (taxRate)

Los valores comunes para `taxRate` en Venezuela:

| Valor | Descripción |
|-------|-------------|
| `'1'` | IVA General (16%) |
| `'2'` | IVA Reducido (8%) |
| `'3'` | IVA Adicional |
| `'E'` | Exento de IVA |

## Tipos de Pago (payment.type)

| Código | Descripción |
|--------|-------------|
| `'01'` | Efectivo |
| `'02'` | Tarjeta de débito |
| `'03'` | Tarjeta de crédito |
| `'04'` | Cheque |
| `'05'` | Transferencia |
| `'06'` | Pago móvil |

## Requisitos del Sistema

- React Native >= 0.73.0
- Android minSdkVersion 24+
- Dispositivo Android físico con puerto serial o adaptador USB-Serial
- Impresora fiscal HKA compatible

## Limitaciones Conocidas

- **Solo Android**: Esta biblioteca actualmente solo soporta Android
- **Emulador**: No funciona en emuladores Android (requiere hardware serial real)
- **Puerto Serial**: Requiere acceso a `/dev/ttyS*` o `/dev/ttyUSB*`

## Solución de Problemas

### Error: "Could not invoke HkaPrinter.connect"

**Causa:** Biblioteca nativa JSSC no cargada correctamente.

**Solución:**
```bash
cd android && ./gradlew clean
cd ..
npx react-native run-android
```

### Error: "Printer not connected"

**Causas posibles:**
1. Puerto serial incorrecto
2. Impresora apagada o desconectada
3. Permisos insuficientes

**Solución:**
- Verifica que el puerto serial sea correcto (`/dev/ttyS0`, `/dev/ttyUSB0`, etc.)
- Asegúrate de que la impresora esté encendida
- Verifica los permisos en AndroidManifest.xml

### Error: "E_INVALID_INVOICE"

**Causa:** El total de pagos no coincide con el total de artículos.

**Solución:**
```typescript
// Calcular el total correcto
const itemsTotal = invoice.items.reduce(
  (sum, item) => sum + (item.quantity * item.price),
  0
);

const paymentsTotal = invoice.payments.reduce(
  (sum, payment) => sum + payment.amount,
  0
);

console.log(`Items: ${itemsTotal}, Pagos: ${paymentsTotal}`);
```

## Contributing

- [Development workflow](CONTRIBUTING.md#development-workflow)
- [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
- [Code of conduct](CODE_OF_CONDUCT.md)

## Licencia

MIT

---

Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)