Metadata-Version: 2.4
Name: py-vucem
Version: 0.1.1
Summary: Cliente en Python para la Ventanilla Única de Comercio Exterior Mexicano (VUCEM)
Project-URL: Homepage, https://github.com/pesatto/py-vucem
Project-URL: Repository, https://github.com/pesatto/py-vucem
Project-URL: Issues, https://github.com/pesatto/py-vucem/issues
Author-email: Fernando Ruiz <fernando.ruiz@pesatto.com>
License: MIT
Keywords: aduanas,comercio exterior,manifestacion de valor,mexico,soap,vucem
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: Spanish
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: cryptography>=42.0.0
Requires-Dist: lxml>=4.9.0
Requires-Dist: requests>=2.28.0
Requires-Dist: zeep>=4.2.1
Description-Content-Type: text/markdown

# py-vucem

Cliente Python para la **Ventanilla Única de Comercio Exterior Mexicano (VUCEM)**. Permite registrar Manifestaciones de Valor Electrónicas (MVE), digitalizar documentos, consultar pedimentos y descargar acuses, todo mediante los servicios SOAP oficiales de VUCEM firmados con e.firma (FIEL).

## Requisitos

- Python 3.9+
- e.firma (FIEL) vigente de la empresa importadora (archivos `.cer` y `.key`)
- Clave de acceso a servicios web de VUCEM (`claveWS`)
- Token de Banxico SIE (opcional, para tipo de cambio automático)

## Instalación

```bash
pip install py-vucem
```

O en modo desarrollo:

```bash
git clone https://github.com/pesatto/py_vucem
cd py_vucem
pip install -e .
```

## Configuración inicial

```python
from py_vucem import VucemClient

client = VucemClient(
    cer_path="ruta/a/fiel.cer",   # e.firma de la empresa (NO el CSD de facturación)
    key_path="ruta/a/fiel.key",
    password="tu-password-fiel",
    clave_ws="tu-clave-ws-vucem",
    rfc="TU_RFC",
)
```

> **Importante:** VUCEM requiere la **e.firma (FIEL)** de la empresa, no el CSD. Son archivos diferentes.

---

## Servicios disponibles

### 1. Manifestación de Valor Electrónica (MVE)

La MVE documenta el valor declarado de las mercancías importadas (Art. 59-A Ley Aduanera).

#### Construir y enviar una MVE

```python
from py_vucem import VucemClient
from py_vucem.models.mv_builder import ManifestacionValor
from py_vucem.utils.banxico import BanxicoClient

banxico = BanxicoClient("tu-token-banxico")

client = VucemClient(
    cer_path="fiel.cer",
    key_path="fiel.key",
    password="password",
    clave_ws="clave_ws",
    rfc="PME241011C34",
)

# Construir el modelo
mv = ManifestacionValor("PME241011C34", banxico=banxico)

# Personas autorizadas a consultar la MV (agente aduanal)
mv.agregar_consulta("LWO041215F90", "TIPFIG.AGE")

# eDocuments relacionados (COVEs digitalizados en VUCEM)
mv.agregar_documento("03602601109K2")
mv.agregar_documento("0170261DD0RU6")

# Pedimento aduanal
mv.agregar_pedimento(pedimento="6003095", patente="3977", aduana="160")

# Factura / COVE
factura = mv.nueva_factura(
    cove="COVE2680TJDY6",
    incoterm="TIPINC.FOB",
    vinculacion=False,
    metodo="VALADU.VTM",
)

# Pagos realizados (TC se consulta automáticamente de Banxico)
factura.agregar_pago(
    fecha="2026-02-03", total=21328.00,
    forma="FORPAG.TE", moneda="USD",
)
factura.agregar_pago(
    fecha="2026-03-11", total=47613.00,
    forma="FORPAG.TE", moneda="USD",
)

# Incrementables al valor en aduana (fletes, seguros, etc.)
factura.agregar_incrementable(
    tipo="INCRE.GS", fecha="2026-03-21",
    total=1800.00, moneda="USD",
    cargo_importador=True,
)

# Enviar a VUCEM
resultado = client.registrar_manifestacion_desde_modelo(mv.to_dict())
print(resultado["numeroOperacion"])  # ej. 530502
```

#### Tipos de cambio

Si no configuras `BanxicoClient`, debes proporcionar `tc=` en cada pago:

```python
mv = ManifestacionValor("PME241011C34")  # sin banxico

factura.agregar_pago(
    fecha="2026-02-03", total=21328.00,
    forma="FORPAG.TE", moneda="USD",
    tc=20.1234,  # obligatorio sin BanxicoClient
)
```

Con `BanxicoClient`, el TC FIX oficial se consulta automáticamente por fecha y moneda. Si proporcionas `tc=` junto con `BanxicoClient`, valida que tu TC no difiera más del 1% del oficial.

#### Tipos de pago disponibles

| Método | Descripción |
|--------|-------------|
| `agregar_pago()` | Precio ya pagado |
| `agregar_por_pagar()` | Precio pendiente de pago (crédito) |
| `agregar_compenso()` | Pago por compensación (intercambio de bienes/servicios) |
| `agregar_incrementable()` | Fletes, seguros, cargos incrementables al valor |
| `agregar_decrementable()` | Descuentos, devoluciones, conceptos decrementables |

#### Previsualizar el XML antes de enviar

```python
xml = client.generar_xml_mv(mv.to_dict(), con_firma=True)
print(xml)

# Validar contra el XSD de VUCEM
errores = client.validar_xml_mv(xml)
if not errores:
    resultado = client.registrar_manifestacion_desde_modelo(mv.to_dict())
```

#### Consultar una MVE registrada

```python
# Por número de operación
data = client.consultar_manifestacion(numero_operacion=530502)

# Por número de MV (MNVA...)
data = client.consultar_manifestacion(edocument="MNVA2600GAO73")

print(data["estatus"])       # "Aceptado"
print(data["eDocument"])     # "MNVA2600GAO73"
print(data["fechaRegistro"]) # "2026-06-29T..."
```

---

### 2. Digitalización de documentos

Convierte documentos PDF en eDocuments registrados en VUCEM (facturas, listas de empaque, certificados, etc.).

```python
# Ver catálogo de tipos de documento disponibles
tipos = client.consultar_tipos_documento()

# Digitalizar un PDF
with open("factura.pdf", "rb") as f:
    pdf_bytes = f.read()

resultado = client.digitalizar_documento(
    correo="contacto@empresa.com",
    id_tipo_documento="1",       # 1 = Factura comercial
    nombre_documento="Factura ST2601016",
    archivo_bytes=pdf_bytes,
    rfc_consulta="PME241011C34", # RFC autorizado a consultar
)

print(resultado["eDocument"])    # ej. "03602601109K2"
print(resultado["numeroOperacion"])

# Consultar el estatus de la digitalización
estatus = client.consultar_estatus_digitalizacion(resultado["numeroOperacion"])
```

> El PDF debe pesar menos de 3 MB y ser un PDF válido (no escaneado como imagen sin OCR).

---

### 3. Consulta de COVEs

```python
# Consultar un COVE por su eDocument
cove = client.consultar_cove("COVE2680TJDY6")
print(cove)
```

---

### 4. Consulta de pedimentos

```python
# Listar pedimentos por aduana y fecha
pedimentos = client.listar_pedimentos(
    aduana="160",
    patente=3977,
    fecha_inicio=date(2026, 1, 1),
    fecha_fin=date(2026, 6, 30),
)

# Consultar estado de un pedimento
estado = client.consultar_estado_pedimentos(
    aduana=160, patente=3977,
    pedimento=6003095,
    numero_operacion=530502,
)

# Detalle completo del pedimento
detalle = client.consultar_pedimento_completo(
    aduana="160", patente=3977, pedimento=6003095,
)

# Consultar una partida específica
partida = client.consultar_partida(
    aduana="160", patente=3977, pedimento=6003095,
    numero_operacion=530502, numero_partida=1,
)

# Consultar remesas
remesas = client.consultar_remesas(
    aduana=160, patente=3977,
    pedimento=6003095,
    numero_operacion=530502,
)
```

---

### 5. Descarga de acuses

```python
# Acuse de un eDocument digitalizado (número numérico)
resultado = client.descargar_acuse("03602601109K2")

if resultado.get("pdf"):
    with open("acuse.pdf", "wb") as f:
        f.write(resultado["pdf"])

# Acuse de un COVE
resultado = client.descargar_acuse("COVE2680TJDY6", es_cove=True)
```

> El servicio de acuses (`ConsultaAcusesServiceWS`) soporta eDocuments con formato numérico y COVEs. Los números MVE (MNVA...) no son compatibles con este servicio.

---

## Banco de México — Tipo de cambio

```python
from py_vucem.utils.banxico import BanxicoClient

banxico = BanxicoClient("tu-token")

# TC FIX para una fecha específica
tc = banxico.tc("USD", "2026-02-03")
# Decimal('20.1234')

# Monedas soportadas
# USD, EUR, GBP, JPY, CAD, CHF, CNY
```

Token gratuito en: `https://www.banxico.org.mx/SieAPIRest/service/v1/token`

El TC FIX de Banxico es el mismo que usa el SAT para convertir montos en moneda extranjera en pedimentos y MVE (Art. 20 Ley Aduanera).

---

## Claves de catálogos VUCEM

### Incoterms (`incoterm`)
| Clave | Descripción |
|-------|-------------|
| `TIPINC.FOB` | Free on Board |
| `TIPINC.CIF` | Cost, Insurance and Freight |
| `TIPINC.CFR` | Cost and Freight |
| `TIPINC.EXW` | Ex Works |
| `TIPINC.DAP` | Delivered at Place |

### Formas de pago (`forma`)
| Clave | Descripción |
|-------|-------------|
| `FORPAG.TE` | Transferencia electrónica |
| `FORPAG.CH` | Cheque |
| `FORPAG.EF` | Efectivo |
| `FORPAG.OT` | Otro (requiere `especifique=`) |

### Incrementables (`tipo`)
| Clave | Descripción |
|-------|-------------|
| `INCRE.GS` | Gastos de envío / flete |
| `INCRE.SE` | Seguro |
| `INCRE.CA` | Cargos de carga |
| `INCRE.OT` | Otros incrementables |

### Métodos de valoración (`metodo`)
| Clave | Descripción |
|-------|-------------|
| `VALADU.VTM` | Valor de transacción de mercancías (default) |
| `VALADU.VTI` | Valor de transacción de mercancías idénticas |
| `VALADU.VTS` | Valor de transacción de mercancías similares |
| `VALADU.VD`  | Valor deductivo |
| `VALADU.VR`  | Valor reconstruido |
| `VALADU.VU`  | Valor en última instancia |

### Tipo de figura (`figura` en `agregar_consulta`)
| Clave | Descripción |
|-------|-------------|
| `TIPFIG.AGE` | Agente aduanal |
| `TIPFIG.REP` | Representante legal |
| `TIPFIG.IMP` | Importador |

---

## Scripts de ejemplo

Los scripts en `ejemplos/` muestran flujos completos listos para ejecutar:

| Script | Descripción |
|--------|-------------|
| `ejemplos/enviar_mv_6003095.py` | Construye, valida y envía una MVE completa |
| `ejemplos/consultar_mv_530488.py` | Consulta el estatus de una MVE y descarga el acuse PDF |
| `ejemplos/cargar_documentos_6003095.py` | Digitaliza documentos PDF en VUCEM |
| `ejemplos/crear_pedimento_6003095.py` | Construye el modelo de MVE en JSON para revisión |

```bash
cd py_vucem
.\venv\Scripts\python.exe ejemplos\enviar_mv_6003095.py
```

---

## Notas técnicas

### Conectividad con VUCEM

Los servicios de VUCEM requieren configuración SSL especial (certificados legacy, TLS 1.0/1.1). La librería maneja esto internamente mediante `LegacyVucemAdapter` — no es necesaria ninguna configuración adicional.

### WSDL remoto vs local

La librería usa WSDLs remotos cuando el servidor los sirve correctamente. Para servicios donde el XSD remoto devuelve 404 (como `ConsultaManifestacionService`), usa WSDLs locales empaquetados solo para validación, mientras la comunicación sigue siendo contra el endpoint en producción.

### Cadena original y firma

La cadena original de la MVE usa el mismo formato numérico que el XML (máximo 3 decimales redondeados, sin ceros finales), garantizando que la firma electrónica sea válida. Este formato es equivalente al `formatVucemNumber()` de la implementación PHP de referencia de VUCEM.

### Prerequisito para acuses de MVE

El acuse de una MVE solo se genera cuando el COVE referenciado existe y está validado en VUCEM. El COVE debe ser registrado por el agente aduanal **antes** de presentar la MVE.

---

## Estructura del proyecto

```
py_vucem/
├── src/py_vucem/
│   ├── client.py                  # VucemClient — punto de entrada principal
│   ├── models/
│   │   ├── mv_builder.py          # ManifestacionValor y Factura (API fluida)
│   │   ├── mv_mapper.py           # Convierte modelo a estructura interna
│   │   └── mv_xml.py              # Generador de XML SOAP firmado
│   ├── services/
│   │   ├── manifestacion_service.py   # Registro, consulta y acuses de MVE
│   │   ├── digitalizar_documento.py   # Digitalización de PDFs
│   │   ├── pedimentos_service.py      # Consulta de pedimentos aduaneros
│   │   └── cove_consulta.py           # Consulta de COVEs
│   └── utils/
│       ├── __init__.py            # FielHandler, LegacyVucemAdapter
│       └── banxico.py             # BanxicoClient — TC FIX oficial
├── ejemplos/                      # Scripts listos para ejecutar
├── tests/                         # Pruebas unitarias
│   └── fixtures/                  # Certificados de prueba
└── wsdl/                          # WSDLs locales de respaldo
```

---

## Licencia

MIT © Fernando Ruiz — [Pesatto México](https://pesatto.com)
