cpe-engine


Namecpe-engine JSON
Version 0.2.0 PyPI version JSON
download
home_pageNone
SummarySistema de Emisión del Contribuyente - Facturación Electrónica Peruana
upload_time2025-08-29 03:19:50
maintainerNone
docs_urlNone
authorNone
requires_python>=3.11.6
licenseMIT
keywords peru sunat facturacion electronica ubl invoice xml
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # cpe-engine

Sistema de Emisión del Contribuyente - Facturación Electrónica Peruana

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![Tests](https://img.shields.io/badge/tests-passing-brightgreen.svg)](#testing)
[![Production Ready](https://img.shields.io/badge/status-production%20ready-success.svg)](#production-status)

> **🎉 Status: Production Ready** - Comprehensive testing, complete documentation, and verified greenter compatibility.

## Descripción

**cpe-engine** es una librería completa de Python para facturación electrónica peruana que integra con SUNAT. Es un port completo de la librería PHP Greenter, proporcionando funcionalidades end-to-end para generación de documentos, firma digital, y envío a SUNAT.

### Características

- ✅ **Facturas (01)** y **Boletas (03)** - Facturas y recibos
- ✅ **Notas de Crédito (07)** y **Notas de Débito (08)**
- ✅ **35 Catálogos SUNAT oficiales** - Todos los códigos validados contra fuentes oficiales
- ✅ **Validador opcional** - DocumentValidator separado del core (como Greenter/validator)
- ✅ **Mapeo dinámico de tributos** - XML correcto según tipo de operación (gravado, exonerado, exportación)
- ✅ **Arquitectura declarativa** - Compatible 100% con Greenter (no cálculos automáticos)
- ✅ Generación XML UBL 2.1 con templates Jinja2
- ✅ Firmas digitales usando SHA-256 (certificados X.509)
- ✅ Integración SOAP con servicios web SUNAT y procesamiento CDR
- ✅ Compresión ZIP para transmisión de documentos
- ✅ Soporte para ambientes TEST y PRODUCCIÓN
- ✅ API de alto nivel con funciones simples
- ✅ **100% compatible con Greenter** con validaciones adicionales opcionales

## 📚 Documentación de Referencia

**Para desarrolladores y contribuidores:**

- **[API_REFERENCE.md](./API_REFERENCE.md)** - Documentación completa de APIs con firmas exactas y tipos de datos
- **[TEST_PATTERNS.md](./TEST_PATTERNS.md)** - Patrones de testing verificados (usar exactamente estos patrones) 
- **[ARCHITECTURE.md](./ARCHITECTURE.md)** - Arquitectura del sistema y principios de diseño
- **[CLAUDE.md](./CLAUDE.md)** - Guía específica para desarrollo con Claude Code
- **[CHANGELOG.md](./CHANGELOG.md)** - Registro de cambios, mejoras y correcciones por versión

> ⚠️ **Importante**: Lee estos archivos antes de contribuir para evitar errores comunes y patrones incorrectos.

## Instalación

```bash
pip install cpe-engine
```

## Uso Rápido

### 1. Configurar Credenciales

```python
from cpe_engine import SunatCredentials

# Para ambiente de pruebas
credentials = SunatCredentials(
    ruc="20000000001",
    usuario="20000000001MODDATOS",
    password="moddatos",
    certificado=certificado_pem_content,  # Contenido PEM como string
    es_test=True
)

# Para producción
credentials = SunatCredentials(
    ruc="20123456789",
    usuario="20123456789USUARIO1", 
    password="mi_password",
    certificado="/path/to/certificado.pem",  # O path al archivo
    es_test=False
)
```

### 2. Enviar Factura

```python
from cpe_engine import create_invoice_data, send_invoice

# Datos de la empresa
company_data = {
    'ruc': '20000000001',
    'razon_social': 'MI EMPRESA S.A.C.',
    'email': 'facturacion@miempresa.com',
    'address': {
        'ubigeo': '150101',
        'departamento': 'Lima',
        'provincia': 'Lima', 
        'distrito': 'Lima',
        'direccion': 'Av. Principal 123'
    }
}

# Datos del cliente
client_data = {
    'tipo_doc': 6,  # RUC
    'num_doc': '20000000002',
    'razon_social': 'CLIENTE EMPRESA S.A.C.'
}

# Items de la factura
items = [
    {
        'cod_item': 'PROD001',
        'des_item': 'Producto de ejemplo',
        'cantidad': 2,
        'mto_valor_unitario': 100.00,
        'unidad': 'NIU'
    }
]

# Crear datos de factura
invoice_data = create_invoice_data(
    serie='F001',
    correlativo=123,
    company_data=company_data,
    client_data=client_data,
    items=items
)

# Enviar a SUNAT
result = send_invoice(credentials, invoice_data)

if result.get('success'):
    print(f"Factura enviada exitosamente: {result}")
else:
    print(f"Error: {result['error']}")
```

### 3. Enviar Nota de Crédito

```python
from cpe_engine import create_note_data, send_credit_note

# Crear datos de nota de crédito
note_data = create_note_data(
    serie='FC01',
    correlativo=1,
    tipo_nota='07',  # Crédito
    documento_afectado='F001-123',
    motivo='Anulación de la operación',
    company_data=company_data,
    client_data=client_data,
    items=items
)

# Enviar a SUNAT
result = send_credit_note(credentials, note_data)
```

## Catálogos SUNAT

La librería incluye **35 catálogos oficiales de SUNAT** descargados directamente de fuentes gubernamentales:

### Importación Directa

```python
# Importar catálogos directamente desde el paquete principal
from cpe_engine import (
    CODIGOS_AFECTACION_IGV,
    TIPOS_MONEDA,
    UNIDADES_MEDIDA,
    TIPOS_OPERACION,
    MOTIVOS_NOTA_CREDITO,
    MOTIVOS_NOTA_DEBITO,
    validar_afectacion_igv,
    validar_tipo_moneda
)
```

### Consultar Catálogos

```python
from cpe_engine import CODIGOS_AFECTACION_IGV, TIPOS_OPERACION

# Ver códigos de afectación IGV disponibles
print("Códigos de afectación IGV:")
for codigo, descripcion in CODIGOS_AFECTACION_IGV.items():
    print(f"  {codigo}: {descripcion}")
# 10: Gravado - Operación Onerosa
# 20: Exonerado - Operación Onerosa  
# 30: Inafecto - Operación Onerosa
# 40: Exportación
# ... y más

# Ver tipos de operación
print("Tipos de operación:")
for codigo, descripcion in TIPOS_OPERACION.items():
    print(f"  {codigo}: {descripcion}")
# 0101: Venta interna
# 0200: Exportación de bienes
# ... y más
```

### Validación de Códigos

```python
from cpe_engine import validar_afectacion_igv, validar_tipo_moneda

# Validar antes de usar
if validar_afectacion_igv("40"):
    print("Código 40 (exportación) es válido")

if validar_tipo_moneda("USD"):
    print("USD es una moneda válida")

# La librería valida automáticamente al crear documentos
try:
    item = SaleDetail(
        cod_item="PROD001",
        des_item="Producto",
        cantidad=1,
        mto_valor_unitario=100.00,
        unidad="INVALID_UNIT",  # ❌ Código inválido
        tip_afe_igv="10"
    )
except ValueError as e:
    print(f"Error de validación: {e}")
    # Error: Código de unidad de medida inválido: 'INVALID_UNIT'
```

### Catálogos Disponibles (35 Catálogos Oficiales)

| Catálogo | Descripción | Fuente Oficial |
|----------|-------------|----------------|
| `TIPOS_DOCUMENTO_IDENTIDAD` | Tipos de documento (DNI, RUC, etc.) | Catálogo 06 |
| `TIPOS_MONEDA` | Monedas (PEN, USD, EUR) | Catálogo 02 |
| `UNIDADES_MEDIDA` | Unidades de medida (NIU, ZZ, KGM, etc.) | Catálogo 03 |
| `CODIGOS_AFECTACION_IGV` | Códigos de afectación del IGV | Catálogo 07 |
| `MOTIVOS_NOTA_CREDITO` | Motivos de notas de crédito | Catálogo 09 |
| `MOTIVOS_NOTA_DEBITO` | Motivos de notas de débito | Catálogo 10 |
| `TIPOS_OPERACION` | Tipos de operación (venta interna, exportación, etc.) | Catálogo 17 |
| `TIPOS_CARGOS_DESCUENTOS` | Tipos de cargos y descuentos | Catálogo 53 |
| `TIPOS_DOCUMENTOS` | Tipos de comprobantes (01, 03, 07, etc.) | Catálogo 01 |
| **+26 catálogos adicionales** | Regímenes, percepciones, tributos, etc. | Catálogos 04-59 |

### Ejemplo: Factura de Exportación

```python
from cpe_engine import create_invoice_data, CODIGOS_AFECTACION_IGV, TIPOS_OPERACION

# Consultar códigos antes de usar
print("Código para exportación:", CODIGOS_AFECTACION_IGV["40"])
print("Operación de exportación:", TIPOS_OPERACION["0200"])

# Crear factura de exportación
items_exportacion = [
    {
        'cod_item': 'EXP001',
        'des_item': 'Producto de exportación',
        'cantidad': 10,
        'mto_valor_unitario': 50.00,
        'unidad': 'NIU',
        'tip_afe_igv': '40'  # Exportación (sin IGV)
    }
]

invoice_data = create_invoice_data(
    serie='F001',
    correlativo=100,
    company_data={...},
    client_data={...},
    items=items_exportacion
)

# El XML generado tendrá automáticamente:
# <cbc:TaxExemptionReasonCode>40</cbc:TaxExemptionReasonCode>
# <cbc:ID>9995</cbc:ID>
# <cbc:Name>EXP</cbc:Name>  
# <cbc:TaxTypeCode>FRE</cbc:TaxTypeCode>
```

### 4. Ejemplo Completo

```python
from cpe_engine import send_invoice, SunatCredentials

def main():
    # Configurar credenciales (ejemplo con ambiente de prueba)
    credenciales = SunatCredentials(
        ruc="20000000001",
        usuario="20000000001MODDATOS",
        password="moddatos", 
        certificado="""-----BEGIN CERTIFICATE-----
        ...tu certificado PEM aquí...
        -----END CERTIFICATE-----""",
        es_test=True  # Cambiar a False para producción
    )
    
    # Datos de la empresa
    empresa_data = {
        'ruc': '20000000001',
        'razon_social': 'MI EMPRESA S.A.C.',
        'nombre_comercial': 'Mi Empresa',
        'email': 'facturacion@miempresa.com',
        'address': {
            'ubigeo': '150101',
            'departamento': 'Lima',
            'provincia': 'Lima',
            'distrito': 'Lima',
            'direccion': 'Av. Principal 123'
        }
    }
    
    # Datos del cliente
    cliente_data = {
        'tipo_doc': 6,  # 6=RUC, 1=DNI, 4=Carné extranjería, etc.
        'num_doc': '20000000002',
        'razon_social': 'CLIENTE EMPRESA S.A.C.'
    }
    
    # Productos/servicios
    items = [
        {
            'cod_item': 'PROD001',
            'des_item': 'Producto ejemplo',
            'cantidad': 2,
            'mto_valor_unitario': 100.00,
            'unidad': 'NIU'  # NIU=Unidad, ZZ=Servicio, etc.
        },
        {
            'cod_item': 'SERV001', 
            'des_item': 'Servicio ejemplo',
            'cantidad': 1,
            'mto_valor_unitario': 50.00,
            'unidad': 'ZZ'
        }
    ]
    
    # Enviar factura
    resultado = send_invoice(
        serie="F001",
        correlativo=123,
        empresa_data=empresa_data,
        cliente_data=cliente_data, 
        items=items,
        credenciales=credenciales
    )
    
    # Procesar resultado
    if resultado.get('success'):
        print("✅ Factura enviada exitosamente")
        
        # Información del CDR (Constancia de Recepción)
        if resultado.get('cdr'):
            cdr = resultado['cdr']
            print(f"Código SUNAT: {cdr.get('response_code')}")
            print(f"Descripción: {cdr.get('description')}")
            
            if cdr.get('notes'):
                print(f"Observaciones: {cdr.get('notes')}")
                
        print(f"XML generado guardado en: {resultado.get('xml_path')}")
    else:
        print("❌ Error al enviar factura:")
        print(f"Error: {resultado.get('error')}")

if __name__ == "__main__":
    main()
```

## API de Bajo Nivel

Para mayor control, puedes usar las clases directamente:

```python
from cpe_engine import Invoice, Company, Client, Address, SaleDetail
from cpe_engine import SignedXmlBuilder
from datetime import datetime

# Crear modelos
company = Company(
    ruc="20000000001",
    razon_social="MI EMPRESA S.A.C.",
    # ...
)

invoice = Invoice(
    serie="F001",
    correlativo=123,
    fecha_emision=datetime.now(),
    # ...
)

# Generar XML, firmar y enviar
builder = SignedXmlBuilder()
result = builder.build_sign_and_send(invoice, credentials)
```

## Configuración

### Certificados Digitales

La librería soporta certificados en dos formatos:

```python
# Como contenido PEM (recomendado para BD)
certificado_string = """-----BEGIN CERTIFICATE-----
MIICljCCAX4CAQEwDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHVGVzdCBDQTAe...
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC5example...
-----END PRIVATE KEY-----"""

# Como path a archivo
certificado_path = "/path/to/certificado.pem"
```

### Ambientes SUNAT

```python
# TEST (Beta)
credentials = SunatCredentials(..., es_test=True)
# Endpoints: https://e-beta.sunat.gob.pe/...

# PRODUCCIÓN  
credentials = SunatCredentials(..., es_test=False)
# Endpoints: https://e-factura.sunat.gob.pe/...
```

## Validación Opcional

La librería incluye un **DocumentValidator opcional** completamente separado del core (igual que Greenter/validator):

```python
from cpe_engine import DocumentValidator, Invoice, Company, Client
from datetime import datetime

# Crear validador (opcional)
validator = DocumentValidator()

# Crear documento (core siempre funciona sin validador)
invoice = Invoice(
    serie="F001",
    correlativo=123,
    fecha_emision=datetime.now(),
    # ... otros campos
)

# Validar opcionalmente usando catálogos oficiales SUNAT
errores = validator.validate(invoice)

if errores:
    print(f"❌ {len(errores)} errores encontrados:")
    for error in errores:
        print(f"  - {error.field}: {error.message}")
else:
    print("✅ Documento válido según catálogos SUNAT")

# El documento se puede usar independientemente del validador
xml_content = invoice.build_xml()  # Siempre funciona
```

### Ventajas del Validador Opcional

- ✅ **Separado del core** - Los documentos se crean sin validar (como Greenter)
- ✅ **35 catálogos oficiales** - Validación contra fuentes gubernamentales SUNAT
- ✅ **Mensajes descriptivos** - Errores con códigos válidos sugeridos
- ✅ **Totalmente opcional** - El core funciona independientemente
- ✅ **Compatible con Greenter** - Misma arquitectura que PHP Greenter/validator

## Testing

La librería incluye tests completos que **no requieren configuración adicional**:

```bash
# Ejecutar todos los tests (incluye credenciales oficiales de SUNAT)
python -m pytest -v

# Tests específicos  
python -m pytest tests/test_models.py -v      # Tests de modelos (declarativo como Greenter)
python -m pytest tests/test_validator.py -v   # Tests del validador opcional
python -m pytest tests/test_api.py -v         # Tests de API de alto nivel
python -m pytest tests/test_certificate.py -v # Tests de certificados
python -m pytest tests/test_xml_generation.py -v # Tests de XML y mapeo dinámico
```

### Funcionalidades Validadas en Tests

- ✅ **Arquitectura declarativa** - Sin cálculos automáticos (compatible con Greenter)
- ✅ **35 catálogos SUNAT** - Validación opcional usando códigos oficiales
- ✅ **Mapeo dinámico de tributos** - XML correcto según tipo de operación  
- ✅ **Facturas de exportación** - Soporte completo para operaciones sin IGV
- ✅ **DocumentValidator** - Validación opcional separada del core
- ✅ **Compatibilidad total** - Mismos resultados que Greenter PHP

### Credenciales de Test

Los tests usan automáticamente las **credenciales oficiales de prueba de SUNAT**:
- RUC: `20000000001`
- Usuario: `20000000001MODDATOS`  
- Password: `moddatos`
- Certificado: Hardcodeado (no requiere archivos externos)

### Personalizar Credenciales (Opcional)

Si necesitas usar tus propias credenciales para testing:

```bash
export SUNAT_TEST_RUC="tu_ruc"
export SUNAT_TEST_USER="tu_usuario"
export SUNAT_TEST_PASSWORD="tu_password"
export SUNAT_TEST_CERT="/path/to/tu/cert.pem"
export SUNAT_TEST_PRODUCTION="false"  # true para producción

python -m pytest
```

## Desarrollo

```bash
# Instalar en modo desarrollo
pip install -e ".[dev]"

# Formatear código
black src/
isort src/

# Verificar tipos
mypy src/
```

## Arquitectura

La librería sigue el **mismo diseño declarativo que Greenter** con 4 fases:

1. **Fase 1 - Modelos**: `Invoice`, `Company`, `Client` declarativos (sin cálculos automáticos)
2. **Fase 2 - XML**: Generación UBL 2.1 con templates Jinja2 y mapeo dinámico de tributos
3. **Fase 3 - Firma**: Firma digital X.509 con SHA-256
4. **Fase 4 - SUNAT**: Envío SOAP autenticado y procesamiento CDR

### Componentes Adicionales (Opcionales)

- **DocumentValidator**: Validador opcional usando 35 catálogos oficiales SUNAT
- **Catálogos SUNAT**: 35 catálogos oficiales descargados de fuentes gubernamentales
- **API de Alto Nivel**: Funciones simplificadas para casos de uso comunes

### Compatibilidad con Greenter

- ✅ **Arquitectura declarativa**: Sin cálculos automáticos (como Greenter)
- ✅ **Modelos equivalentes**: Mismos campos y comportamiento
- ✅ **Templates XML**: Generación idéntica de UBL 2.1
- ✅ **Validador separado**: DocumentValidator opcional (como Greenter/validator)
- ✅ **Mapeo de tributos**: TributoFunction equivalente al PHP original

## Testing

La librería incluye una suite completa de tests que valida todas las funcionalidades críticas:

### Test Coverage

| Categoría | Archivos | Descripción |
|-----------|----------|-------------|
| **API Tests** | `test_api.py`, `test_models.py` | APIs de alto nivel y modelos core |
| **SUNAT Integration** | `test_sunat_integration.py` | Cliente SOAP, envío de documentos, CDR |
| **Digital Signature** | `test_digital_signature.py` | Gestión certificados y firma XML |
| **End-to-End** | `test_end_to_end.py` | Flujos completos desde creación hasta envío |
| **Error Handling** | `test_error_handling.py` | Manejo de errores de red y datos malformados |
| **XML Generation** | `test_xml_generation.py` | Generación de XML UBL 2.1 |
| **Certificate Management** | `test_certificate.py` | Carga y validación de certificados |
| **Validation** | `test_validator.py` | Validador opcional con catálogos SUNAT |

### Ejecutar Tests

```bash
# Tests completos
python -m pytest

# Tests específicos
python -m pytest tests/test_api.py -v

# Con coverage
python -m pytest --cov=cpe_engine

# Tests de integración con SUNAT (requiere credenciales)
export SUNAT_TEST_RUC="20000000001"
export SUNAT_TEST_USER="20000000001MODDATOS"
export SUNAT_TEST_PASSWORD="moddatos"
python -m pytest tests/test_sunat_integration.py -v
```

### Official SUNAT Test Credentials

Los tests incluyen credenciales oficiales de SUNAT (hardcodeadas) que funcionan sin configuración adicional:

- **RUC**: 20000000001
- **Usuario**: 20000000001MODDATOS  
- **Password**: moddatos
- **Ambiente**: BETA (pruebas)

## Production Status

### ✅ Ready for Production Use

La librería ha sido probada extensivamente y está lista para uso en producción:

**Verified Components:**
- ✅ **Core Models**: Todos los modelos validados contra Greenter
- ✅ **XML Generation**: Templates UBL 2.1 probadas con SUNAT
- ✅ **Digital Signatures**: Firma SHA-256 funcionando correctamente
- ✅ **SUNAT Communication**: Cliente SOAP probado con servicios reales
- ✅ **Error Handling**: Manejo robusto de errores de red y datos
- ✅ **Data Validation**: 35 catálogos oficiales SUNAT integrados

**Performance & Security:**
- ✅ **Thread-Safe**: Soporte para procesamiento concurrente
- ✅ **Security**: SHA-256 signatures, secure certificate handling
- ✅ **Memory Efficient**: Procesamiento optimizado para documentos grandes
- ✅ **Error Recovery**: Reintentos automáticos para errores transitorios

**Production Deployment:**
- ✅ **Environment Support**: TEST y PRODUCTION endpoints
- ✅ **Certificate Management**: Soporte para certificados reales y prueba  
- ✅ **Monitoring**: Logging detallado para auditoría
- ✅ **Scalability**: Arquitectura stateless para alta disponibilidad

## Licencia

MIT License. Ver [LICENSE](LICENSE) para más detalles.

## Contribuir

1. Fork el proyecto
2. Crear branch para feature (`git checkout -b feature/amazing-feature`)
3. Commit cambios (`git commit -m 'Add amazing feature'`)
4. Push al branch (`git push origin feature/amazing-feature`)
5. Abrir Pull Request

## Soporte

- 📖 [Documentación](https://github.com/tu-repo/cpe-engine)
- 🐛 [Issues](https://github.com/tu-repo/cpe-engine/issues)
- 💬 [Discusiones](https://github.com/tu-repo/cpe-engine/discussions)

---

**Nota**: Esta librería es un port de [Greenter](https://greenter.dev/) de PHP a Python. Agradecimientos al equipo original por su excelente trabajo.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "cpe-engine",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11.6",
    "maintainer_email": null,
    "keywords": "peru, sunat, facturacion, electronica, ubl, invoice, xml",
    "author": null,
    "author_email": "Quanta Solutions <suma@bequanta.com>",
    "download_url": "https://files.pythonhosted.org/packages/50/41/a020c9665ea49125193ac3bff3b26c3c473d258482865802ec63480ab2ef/cpe_engine-0.2.0.tar.gz",
    "platform": null,
    "description": "# cpe-engine\n\nSistema de Emisi\u00f3n del Contribuyente - Facturaci\u00f3n Electr\u00f3nica Peruana\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)\n[![Tests](https://img.shields.io/badge/tests-passing-brightgreen.svg)](#testing)\n[![Production Ready](https://img.shields.io/badge/status-production%20ready-success.svg)](#production-status)\n\n> **\ud83c\udf89 Status: Production Ready** - Comprehensive testing, complete documentation, and verified greenter compatibility.\n\n## Descripci\u00f3n\n\n**cpe-engine** es una librer\u00eda completa de Python para facturaci\u00f3n electr\u00f3nica peruana que integra con SUNAT. Es un port completo de la librer\u00eda PHP Greenter, proporcionando funcionalidades end-to-end para generaci\u00f3n de documentos, firma digital, y env\u00edo a SUNAT.\n\n### Caracter\u00edsticas\n\n- \u2705 **Facturas (01)** y **Boletas (03)** - Facturas y recibos\n- \u2705 **Notas de Cr\u00e9dito (07)** y **Notas de D\u00e9bito (08)**\n- \u2705 **35 Cat\u00e1logos SUNAT oficiales** - Todos los c\u00f3digos validados contra fuentes oficiales\n- \u2705 **Validador opcional** - DocumentValidator separado del core (como Greenter/validator)\n- \u2705 **Mapeo din\u00e1mico de tributos** - XML correcto seg\u00fan tipo de operaci\u00f3n (gravado, exonerado, exportaci\u00f3n)\n- \u2705 **Arquitectura declarativa** - Compatible 100% con Greenter (no c\u00e1lculos autom\u00e1ticos)\n- \u2705 Generaci\u00f3n XML UBL 2.1 con templates Jinja2\n- \u2705 Firmas digitales usando SHA-256 (certificados X.509)\n- \u2705 Integraci\u00f3n SOAP con servicios web SUNAT y procesamiento CDR\n- \u2705 Compresi\u00f3n ZIP para transmisi\u00f3n de documentos\n- \u2705 Soporte para ambientes TEST y PRODUCCI\u00d3N\n- \u2705 API de alto nivel con funciones simples\n- \u2705 **100% compatible con Greenter** con validaciones adicionales opcionales\n\n## \ud83d\udcda Documentaci\u00f3n de Referencia\n\n**Para desarrolladores y contribuidores:**\n\n- **[API_REFERENCE.md](./API_REFERENCE.md)** - Documentaci\u00f3n completa de APIs con firmas exactas y tipos de datos\n- **[TEST_PATTERNS.md](./TEST_PATTERNS.md)** - Patrones de testing verificados (usar exactamente estos patrones) \n- **[ARCHITECTURE.md](./ARCHITECTURE.md)** - Arquitectura del sistema y principios de dise\u00f1o\n- **[CLAUDE.md](./CLAUDE.md)** - Gu\u00eda espec\u00edfica para desarrollo con Claude Code\n- **[CHANGELOG.md](./CHANGELOG.md)** - Registro de cambios, mejoras y correcciones por versi\u00f3n\n\n> \u26a0\ufe0f **Importante**: Lee estos archivos antes de contribuir para evitar errores comunes y patrones incorrectos.\n\n## Instalaci\u00f3n\n\n```bash\npip install cpe-engine\n```\n\n## Uso R\u00e1pido\n\n### 1. Configurar Credenciales\n\n```python\nfrom cpe_engine import SunatCredentials\n\n# Para ambiente de pruebas\ncredentials = SunatCredentials(\n    ruc=\"20000000001\",\n    usuario=\"20000000001MODDATOS\",\n    password=\"moddatos\",\n    certificado=certificado_pem_content,  # Contenido PEM como string\n    es_test=True\n)\n\n# Para producci\u00f3n\ncredentials = SunatCredentials(\n    ruc=\"20123456789\",\n    usuario=\"20123456789USUARIO1\", \n    password=\"mi_password\",\n    certificado=\"/path/to/certificado.pem\",  # O path al archivo\n    es_test=False\n)\n```\n\n### 2. Enviar Factura\n\n```python\nfrom cpe_engine import create_invoice_data, send_invoice\n\n# Datos de la empresa\ncompany_data = {\n    'ruc': '20000000001',\n    'razon_social': 'MI EMPRESA S.A.C.',\n    'email': 'facturacion@miempresa.com',\n    'address': {\n        'ubigeo': '150101',\n        'departamento': 'Lima',\n        'provincia': 'Lima', \n        'distrito': 'Lima',\n        'direccion': 'Av. Principal 123'\n    }\n}\n\n# Datos del cliente\nclient_data = {\n    'tipo_doc': 6,  # RUC\n    'num_doc': '20000000002',\n    'razon_social': 'CLIENTE EMPRESA S.A.C.'\n}\n\n# Items de la factura\nitems = [\n    {\n        'cod_item': 'PROD001',\n        'des_item': 'Producto de ejemplo',\n        'cantidad': 2,\n        'mto_valor_unitario': 100.00,\n        'unidad': 'NIU'\n    }\n]\n\n# Crear datos de factura\ninvoice_data = create_invoice_data(\n    serie='F001',\n    correlativo=123,\n    company_data=company_data,\n    client_data=client_data,\n    items=items\n)\n\n# Enviar a SUNAT\nresult = send_invoice(credentials, invoice_data)\n\nif result.get('success'):\n    print(f\"Factura enviada exitosamente: {result}\")\nelse:\n    print(f\"Error: {result['error']}\")\n```\n\n### 3. Enviar Nota de Cr\u00e9dito\n\n```python\nfrom cpe_engine import create_note_data, send_credit_note\n\n# Crear datos de nota de cr\u00e9dito\nnote_data = create_note_data(\n    serie='FC01',\n    correlativo=1,\n    tipo_nota='07',  # Cr\u00e9dito\n    documento_afectado='F001-123',\n    motivo='Anulaci\u00f3n de la operaci\u00f3n',\n    company_data=company_data,\n    client_data=client_data,\n    items=items\n)\n\n# Enviar a SUNAT\nresult = send_credit_note(credentials, note_data)\n```\n\n## Cat\u00e1logos SUNAT\n\nLa librer\u00eda incluye **35 cat\u00e1logos oficiales de SUNAT** descargados directamente de fuentes gubernamentales:\n\n### Importaci\u00f3n Directa\n\n```python\n# Importar cat\u00e1logos directamente desde el paquete principal\nfrom cpe_engine import (\n    CODIGOS_AFECTACION_IGV,\n    TIPOS_MONEDA,\n    UNIDADES_MEDIDA,\n    TIPOS_OPERACION,\n    MOTIVOS_NOTA_CREDITO,\n    MOTIVOS_NOTA_DEBITO,\n    validar_afectacion_igv,\n    validar_tipo_moneda\n)\n```\n\n### Consultar Cat\u00e1logos\n\n```python\nfrom cpe_engine import CODIGOS_AFECTACION_IGV, TIPOS_OPERACION\n\n# Ver c\u00f3digos de afectaci\u00f3n IGV disponibles\nprint(\"C\u00f3digos de afectaci\u00f3n IGV:\")\nfor codigo, descripcion in CODIGOS_AFECTACION_IGV.items():\n    print(f\"  {codigo}: {descripcion}\")\n# 10: Gravado - Operaci\u00f3n Onerosa\n# 20: Exonerado - Operaci\u00f3n Onerosa  \n# 30: Inafecto - Operaci\u00f3n Onerosa\n# 40: Exportaci\u00f3n\n# ... y m\u00e1s\n\n# Ver tipos de operaci\u00f3n\nprint(\"Tipos de operaci\u00f3n:\")\nfor codigo, descripcion in TIPOS_OPERACION.items():\n    print(f\"  {codigo}: {descripcion}\")\n# 0101: Venta interna\n# 0200: Exportaci\u00f3n de bienes\n# ... y m\u00e1s\n```\n\n### Validaci\u00f3n de C\u00f3digos\n\n```python\nfrom cpe_engine import validar_afectacion_igv, validar_tipo_moneda\n\n# Validar antes de usar\nif validar_afectacion_igv(\"40\"):\n    print(\"C\u00f3digo 40 (exportaci\u00f3n) es v\u00e1lido\")\n\nif validar_tipo_moneda(\"USD\"):\n    print(\"USD es una moneda v\u00e1lida\")\n\n# La librer\u00eda valida autom\u00e1ticamente al crear documentos\ntry:\n    item = SaleDetail(\n        cod_item=\"PROD001\",\n        des_item=\"Producto\",\n        cantidad=1,\n        mto_valor_unitario=100.00,\n        unidad=\"INVALID_UNIT\",  # \u274c C\u00f3digo inv\u00e1lido\n        tip_afe_igv=\"10\"\n    )\nexcept ValueError as e:\n    print(f\"Error de validaci\u00f3n: {e}\")\n    # Error: C\u00f3digo de unidad de medida inv\u00e1lido: 'INVALID_UNIT'\n```\n\n### Cat\u00e1logos Disponibles (35 Cat\u00e1logos Oficiales)\n\n| Cat\u00e1logo | Descripci\u00f3n | Fuente Oficial |\n|----------|-------------|----------------|\n| `TIPOS_DOCUMENTO_IDENTIDAD` | Tipos de documento (DNI, RUC, etc.) | Cat\u00e1logo 06 |\n| `TIPOS_MONEDA` | Monedas (PEN, USD, EUR) | Cat\u00e1logo 02 |\n| `UNIDADES_MEDIDA` | Unidades de medida (NIU, ZZ, KGM, etc.) | Cat\u00e1logo 03 |\n| `CODIGOS_AFECTACION_IGV` | C\u00f3digos de afectaci\u00f3n del IGV | Cat\u00e1logo 07 |\n| `MOTIVOS_NOTA_CREDITO` | Motivos de notas de cr\u00e9dito | Cat\u00e1logo 09 |\n| `MOTIVOS_NOTA_DEBITO` | Motivos de notas de d\u00e9bito | Cat\u00e1logo 10 |\n| `TIPOS_OPERACION` | Tipos de operaci\u00f3n (venta interna, exportaci\u00f3n, etc.) | Cat\u00e1logo 17 |\n| `TIPOS_CARGOS_DESCUENTOS` | Tipos de cargos y descuentos | Cat\u00e1logo 53 |\n| `TIPOS_DOCUMENTOS` | Tipos de comprobantes (01, 03, 07, etc.) | Cat\u00e1logo 01 |\n| **+26 cat\u00e1logos adicionales** | Reg\u00edmenes, percepciones, tributos, etc. | Cat\u00e1logos 04-59 |\n\n### Ejemplo: Factura de Exportaci\u00f3n\n\n```python\nfrom cpe_engine import create_invoice_data, CODIGOS_AFECTACION_IGV, TIPOS_OPERACION\n\n# Consultar c\u00f3digos antes de usar\nprint(\"C\u00f3digo para exportaci\u00f3n:\", CODIGOS_AFECTACION_IGV[\"40\"])\nprint(\"Operaci\u00f3n de exportaci\u00f3n:\", TIPOS_OPERACION[\"0200\"])\n\n# Crear factura de exportaci\u00f3n\nitems_exportacion = [\n    {\n        'cod_item': 'EXP001',\n        'des_item': 'Producto de exportaci\u00f3n',\n        'cantidad': 10,\n        'mto_valor_unitario': 50.00,\n        'unidad': 'NIU',\n        'tip_afe_igv': '40'  # Exportaci\u00f3n (sin IGV)\n    }\n]\n\ninvoice_data = create_invoice_data(\n    serie='F001',\n    correlativo=100,\n    company_data={...},\n    client_data={...},\n    items=items_exportacion\n)\n\n# El XML generado tendr\u00e1 autom\u00e1ticamente:\n# <cbc:TaxExemptionReasonCode>40</cbc:TaxExemptionReasonCode>\n# <cbc:ID>9995</cbc:ID>\n# <cbc:Name>EXP</cbc:Name>  \n# <cbc:TaxTypeCode>FRE</cbc:TaxTypeCode>\n```\n\n### 4. Ejemplo Completo\n\n```python\nfrom cpe_engine import send_invoice, SunatCredentials\n\ndef main():\n    # Configurar credenciales (ejemplo con ambiente de prueba)\n    credenciales = SunatCredentials(\n        ruc=\"20000000001\",\n        usuario=\"20000000001MODDATOS\",\n        password=\"moddatos\", \n        certificado=\"\"\"-----BEGIN CERTIFICATE-----\n        ...tu certificado PEM aqu\u00ed...\n        -----END CERTIFICATE-----\"\"\",\n        es_test=True  # Cambiar a False para producci\u00f3n\n    )\n    \n    # Datos de la empresa\n    empresa_data = {\n        'ruc': '20000000001',\n        'razon_social': 'MI EMPRESA S.A.C.',\n        'nombre_comercial': 'Mi Empresa',\n        'email': 'facturacion@miempresa.com',\n        'address': {\n            'ubigeo': '150101',\n            'departamento': 'Lima',\n            'provincia': 'Lima',\n            'distrito': 'Lima',\n            'direccion': 'Av. Principal 123'\n        }\n    }\n    \n    # Datos del cliente\n    cliente_data = {\n        'tipo_doc': 6,  # 6=RUC, 1=DNI, 4=Carn\u00e9 extranjer\u00eda, etc.\n        'num_doc': '20000000002',\n        'razon_social': 'CLIENTE EMPRESA S.A.C.'\n    }\n    \n    # Productos/servicios\n    items = [\n        {\n            'cod_item': 'PROD001',\n            'des_item': 'Producto ejemplo',\n            'cantidad': 2,\n            'mto_valor_unitario': 100.00,\n            'unidad': 'NIU'  # NIU=Unidad, ZZ=Servicio, etc.\n        },\n        {\n            'cod_item': 'SERV001', \n            'des_item': 'Servicio ejemplo',\n            'cantidad': 1,\n            'mto_valor_unitario': 50.00,\n            'unidad': 'ZZ'\n        }\n    ]\n    \n    # Enviar factura\n    resultado = send_invoice(\n        serie=\"F001\",\n        correlativo=123,\n        empresa_data=empresa_data,\n        cliente_data=cliente_data, \n        items=items,\n        credenciales=credenciales\n    )\n    \n    # Procesar resultado\n    if resultado.get('success'):\n        print(\"\u2705 Factura enviada exitosamente\")\n        \n        # Informaci\u00f3n del CDR (Constancia de Recepci\u00f3n)\n        if resultado.get('cdr'):\n            cdr = resultado['cdr']\n            print(f\"C\u00f3digo SUNAT: {cdr.get('response_code')}\")\n            print(f\"Descripci\u00f3n: {cdr.get('description')}\")\n            \n            if cdr.get('notes'):\n                print(f\"Observaciones: {cdr.get('notes')}\")\n                \n        print(f\"XML generado guardado en: {resultado.get('xml_path')}\")\n    else:\n        print(\"\u274c Error al enviar factura:\")\n        print(f\"Error: {resultado.get('error')}\")\n\nif __name__ == \"__main__\":\n    main()\n```\n\n## API de Bajo Nivel\n\nPara mayor control, puedes usar las clases directamente:\n\n```python\nfrom cpe_engine import Invoice, Company, Client, Address, SaleDetail\nfrom cpe_engine import SignedXmlBuilder\nfrom datetime import datetime\n\n# Crear modelos\ncompany = Company(\n    ruc=\"20000000001\",\n    razon_social=\"MI EMPRESA S.A.C.\",\n    # ...\n)\n\ninvoice = Invoice(\n    serie=\"F001\",\n    correlativo=123,\n    fecha_emision=datetime.now(),\n    # ...\n)\n\n# Generar XML, firmar y enviar\nbuilder = SignedXmlBuilder()\nresult = builder.build_sign_and_send(invoice, credentials)\n```\n\n## Configuraci\u00f3n\n\n### Certificados Digitales\n\nLa librer\u00eda soporta certificados en dos formatos:\n\n```python\n# Como contenido PEM (recomendado para BD)\ncertificado_string = \"\"\"-----BEGIN CERTIFICATE-----\nMIICljCCAX4CAQEwDQYJKoZIhvcNAQELBQAwEjEQMA4GA1UEAwwHVGVzdCBDQTAe...\n-----END CERTIFICATE-----\n-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC5example...\n-----END PRIVATE KEY-----\"\"\"\n\n# Como path a archivo\ncertificado_path = \"/path/to/certificado.pem\"\n```\n\n### Ambientes SUNAT\n\n```python\n# TEST (Beta)\ncredentials = SunatCredentials(..., es_test=True)\n# Endpoints: https://e-beta.sunat.gob.pe/...\n\n# PRODUCCI\u00d3N  \ncredentials = SunatCredentials(..., es_test=False)\n# Endpoints: https://e-factura.sunat.gob.pe/...\n```\n\n## Validaci\u00f3n Opcional\n\nLa librer\u00eda incluye un **DocumentValidator opcional** completamente separado del core (igual que Greenter/validator):\n\n```python\nfrom cpe_engine import DocumentValidator, Invoice, Company, Client\nfrom datetime import datetime\n\n# Crear validador (opcional)\nvalidator = DocumentValidator()\n\n# Crear documento (core siempre funciona sin validador)\ninvoice = Invoice(\n    serie=\"F001\",\n    correlativo=123,\n    fecha_emision=datetime.now(),\n    # ... otros campos\n)\n\n# Validar opcionalmente usando cat\u00e1logos oficiales SUNAT\nerrores = validator.validate(invoice)\n\nif errores:\n    print(f\"\u274c {len(errores)} errores encontrados:\")\n    for error in errores:\n        print(f\"  - {error.field}: {error.message}\")\nelse:\n    print(\"\u2705 Documento v\u00e1lido seg\u00fan cat\u00e1logos SUNAT\")\n\n# El documento se puede usar independientemente del validador\nxml_content = invoice.build_xml()  # Siempre funciona\n```\n\n### Ventajas del Validador Opcional\n\n- \u2705 **Separado del core** - Los documentos se crean sin validar (como Greenter)\n- \u2705 **35 cat\u00e1logos oficiales** - Validaci\u00f3n contra fuentes gubernamentales SUNAT\n- \u2705 **Mensajes descriptivos** - Errores con c\u00f3digos v\u00e1lidos sugeridos\n- \u2705 **Totalmente opcional** - El core funciona independientemente\n- \u2705 **Compatible con Greenter** - Misma arquitectura que PHP Greenter/validator\n\n## Testing\n\nLa librer\u00eda incluye tests completos que **no requieren configuraci\u00f3n adicional**:\n\n```bash\n# Ejecutar todos los tests (incluye credenciales oficiales de SUNAT)\npython -m pytest -v\n\n# Tests espec\u00edficos  \npython -m pytest tests/test_models.py -v      # Tests de modelos (declarativo como Greenter)\npython -m pytest tests/test_validator.py -v   # Tests del validador opcional\npython -m pytest tests/test_api.py -v         # Tests de API de alto nivel\npython -m pytest tests/test_certificate.py -v # Tests de certificados\npython -m pytest tests/test_xml_generation.py -v # Tests de XML y mapeo din\u00e1mico\n```\n\n### Funcionalidades Validadas en Tests\n\n- \u2705 **Arquitectura declarativa** - Sin c\u00e1lculos autom\u00e1ticos (compatible con Greenter)\n- \u2705 **35 cat\u00e1logos SUNAT** - Validaci\u00f3n opcional usando c\u00f3digos oficiales\n- \u2705 **Mapeo din\u00e1mico de tributos** - XML correcto seg\u00fan tipo de operaci\u00f3n  \n- \u2705 **Facturas de exportaci\u00f3n** - Soporte completo para operaciones sin IGV\n- \u2705 **DocumentValidator** - Validaci\u00f3n opcional separada del core\n- \u2705 **Compatibilidad total** - Mismos resultados que Greenter PHP\n\n### Credenciales de Test\n\nLos tests usan autom\u00e1ticamente las **credenciales oficiales de prueba de SUNAT**:\n- RUC: `20000000001`\n- Usuario: `20000000001MODDATOS`  \n- Password: `moddatos`\n- Certificado: Hardcodeado (no requiere archivos externos)\n\n### Personalizar Credenciales (Opcional)\n\nSi necesitas usar tus propias credenciales para testing:\n\n```bash\nexport SUNAT_TEST_RUC=\"tu_ruc\"\nexport SUNAT_TEST_USER=\"tu_usuario\"\nexport SUNAT_TEST_PASSWORD=\"tu_password\"\nexport SUNAT_TEST_CERT=\"/path/to/tu/cert.pem\"\nexport SUNAT_TEST_PRODUCTION=\"false\"  # true para producci\u00f3n\n\npython -m pytest\n```\n\n## Desarrollo\n\n```bash\n# Instalar en modo desarrollo\npip install -e \".[dev]\"\n\n# Formatear c\u00f3digo\nblack src/\nisort src/\n\n# Verificar tipos\nmypy src/\n```\n\n## Arquitectura\n\nLa librer\u00eda sigue el **mismo dise\u00f1o declarativo que Greenter** con 4 fases:\n\n1. **Fase 1 - Modelos**: `Invoice`, `Company`, `Client` declarativos (sin c\u00e1lculos autom\u00e1ticos)\n2. **Fase 2 - XML**: Generaci\u00f3n UBL 2.1 con templates Jinja2 y mapeo din\u00e1mico de tributos\n3. **Fase 3 - Firma**: Firma digital X.509 con SHA-256\n4. **Fase 4 - SUNAT**: Env\u00edo SOAP autenticado y procesamiento CDR\n\n### Componentes Adicionales (Opcionales)\n\n- **DocumentValidator**: Validador opcional usando 35 cat\u00e1logos oficiales SUNAT\n- **Cat\u00e1logos SUNAT**: 35 cat\u00e1logos oficiales descargados de fuentes gubernamentales\n- **API de Alto Nivel**: Funciones simplificadas para casos de uso comunes\n\n### Compatibilidad con Greenter\n\n- \u2705 **Arquitectura declarativa**: Sin c\u00e1lculos autom\u00e1ticos (como Greenter)\n- \u2705 **Modelos equivalentes**: Mismos campos y comportamiento\n- \u2705 **Templates XML**: Generaci\u00f3n id\u00e9ntica de UBL 2.1\n- \u2705 **Validador separado**: DocumentValidator opcional (como Greenter/validator)\n- \u2705 **Mapeo de tributos**: TributoFunction equivalente al PHP original\n\n## Testing\n\nLa librer\u00eda incluye una suite completa de tests que valida todas las funcionalidades cr\u00edticas:\n\n### Test Coverage\n\n| Categor\u00eda | Archivos | Descripci\u00f3n |\n|-----------|----------|-------------|\n| **API Tests** | `test_api.py`, `test_models.py` | APIs de alto nivel y modelos core |\n| **SUNAT Integration** | `test_sunat_integration.py` | Cliente SOAP, env\u00edo de documentos, CDR |\n| **Digital Signature** | `test_digital_signature.py` | Gesti\u00f3n certificados y firma XML |\n| **End-to-End** | `test_end_to_end.py` | Flujos completos desde creaci\u00f3n hasta env\u00edo |\n| **Error Handling** | `test_error_handling.py` | Manejo de errores de red y datos malformados |\n| **XML Generation** | `test_xml_generation.py` | Generaci\u00f3n de XML UBL 2.1 |\n| **Certificate Management** | `test_certificate.py` | Carga y validaci\u00f3n de certificados |\n| **Validation** | `test_validator.py` | Validador opcional con cat\u00e1logos SUNAT |\n\n### Ejecutar Tests\n\n```bash\n# Tests completos\npython -m pytest\n\n# Tests espec\u00edficos\npython -m pytest tests/test_api.py -v\n\n# Con coverage\npython -m pytest --cov=cpe_engine\n\n# Tests de integraci\u00f3n con SUNAT (requiere credenciales)\nexport SUNAT_TEST_RUC=\"20000000001\"\nexport SUNAT_TEST_USER=\"20000000001MODDATOS\"\nexport SUNAT_TEST_PASSWORD=\"moddatos\"\npython -m pytest tests/test_sunat_integration.py -v\n```\n\n### Official SUNAT Test Credentials\n\nLos tests incluyen credenciales oficiales de SUNAT (hardcodeadas) que funcionan sin configuraci\u00f3n adicional:\n\n- **RUC**: 20000000001\n- **Usuario**: 20000000001MODDATOS  \n- **Password**: moddatos\n- **Ambiente**: BETA (pruebas)\n\n## Production Status\n\n### \u2705 Ready for Production Use\n\nLa librer\u00eda ha sido probada extensivamente y est\u00e1 lista para uso en producci\u00f3n:\n\n**Verified Components:**\n- \u2705 **Core Models**: Todos los modelos validados contra Greenter\n- \u2705 **XML Generation**: Templates UBL 2.1 probadas con SUNAT\n- \u2705 **Digital Signatures**: Firma SHA-256 funcionando correctamente\n- \u2705 **SUNAT Communication**: Cliente SOAP probado con servicios reales\n- \u2705 **Error Handling**: Manejo robusto de errores de red y datos\n- \u2705 **Data Validation**: 35 cat\u00e1logos oficiales SUNAT integrados\n\n**Performance & Security:**\n- \u2705 **Thread-Safe**: Soporte para procesamiento concurrente\n- \u2705 **Security**: SHA-256 signatures, secure certificate handling\n- \u2705 **Memory Efficient**: Procesamiento optimizado para documentos grandes\n- \u2705 **Error Recovery**: Reintentos autom\u00e1ticos para errores transitorios\n\n**Production Deployment:**\n- \u2705 **Environment Support**: TEST y PRODUCTION endpoints\n- \u2705 **Certificate Management**: Soporte para certificados reales y prueba  \n- \u2705 **Monitoring**: Logging detallado para auditor\u00eda\n- \u2705 **Scalability**: Arquitectura stateless para alta disponibilidad\n\n## Licencia\n\nMIT License. Ver [LICENSE](LICENSE) para m\u00e1s detalles.\n\n## Contribuir\n\n1. Fork el proyecto\n2. Crear branch para feature (`git checkout -b feature/amazing-feature`)\n3. Commit cambios (`git commit -m 'Add amazing feature'`)\n4. Push al branch (`git push origin feature/amazing-feature`)\n5. Abrir Pull Request\n\n## Soporte\n\n- \ud83d\udcd6 [Documentaci\u00f3n](https://github.com/tu-repo/cpe-engine)\n- \ud83d\udc1b [Issues](https://github.com/tu-repo/cpe-engine/issues)\n- \ud83d\udcac [Discusiones](https://github.com/tu-repo/cpe-engine/discussions)\n\n---\n\n**Nota**: Esta librer\u00eda es un port de [Greenter](https://greenter.dev/) de PHP a Python. Agradecimientos al equipo original por su excelente trabajo.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Sistema de Emisi\u00f3n del Contribuyente - Facturaci\u00f3n Electr\u00f3nica Peruana",
    "version": "0.2.0",
    "project_urls": null,
    "split_keywords": [
        "peru",
        " sunat",
        " facturacion",
        " electronica",
        " ubl",
        " invoice",
        " xml"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "181b8b157eb41f6ef094f0bc32c46d9e7a603e521e6bad5ba03c8edb962a0ccc",
                "md5": "247ad1887366ba794f382328e53978b1",
                "sha256": "ec801fdd68804e9cf91392213c574e24ace58d3a03a4f54c89718c4ec12a093c"
            },
            "downloads": -1,
            "filename": "cpe_engine-0.2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "247ad1887366ba794f382328e53978b1",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.11.6",
            "size": 113472,
            "upload_time": "2025-08-29T03:19:48",
            "upload_time_iso_8601": "2025-08-29T03:19:48.358299Z",
            "url": "https://files.pythonhosted.org/packages/18/1b/8b157eb41f6ef094f0bc32c46d9e7a603e521e6bad5ba03c8edb962a0ccc/cpe_engine-0.2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5041a020c9665ea49125193ac3bff3b26c3c473d258482865802ec63480ab2ef",
                "md5": "12fe01203c527c3122f9afb9fc846a1a",
                "sha256": "4c8d9f18876def80ab7eb7d4fce35540dedbad3fefa37094ebb0c62fc8ed70d6"
            },
            "downloads": -1,
            "filename": "cpe_engine-0.2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "12fe01203c527c3122f9afb9fc846a1a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11.6",
            "size": 121176,
            "upload_time": "2025-08-29T03:19:50",
            "upload_time_iso_8601": "2025-08-29T03:19:50.824942Z",
            "url": "https://files.pythonhosted.org/packages/50/41/a020c9665ea49125193ac3bff3b26c3c473d258482865802ec63480ab2ef/cpe_engine-0.2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-29 03:19:50",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "cpe-engine"
}
        
Elapsed time: 0.46583s