Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 74 additions & 64 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,107 +2,117 @@

# Sifende CLI

CLI en Python para testear/explorar integración con la API de facturación electrónica
[Sifende](https://www.sifende.com.py) (Paraguay / SIFEN).
![CI](https://github.com/ithdev/sifende-cli/actions/workflows/ci.yml/badge.svg)
![Licencia: MIT](https://img.shields.io/badge/licencia-MIT-blue)

Implementa los flujos típicos contra `https://api.sifende.com.py/api/v1/`:
emitir documentos, consultar estado, descargar el KuDE (PDF), cancelar y
inutilizar rangos de numeración. Sólo usa la stdlib + `requests`.
CLI en Python para probar la API de [Sifende](https://www.sifende.com.py) desde la terminal: emitir facturas y notas,
consultar su estado, descargar el KuDE, cancelar e inutilizar numeración en SIFEN.

## Quickstart
Sirve para explorar la API antes de integrarla. Para integrarla en tu sistema, usá un SDK:
[`@sifende/sdk`](https://github.com/ithdev/sifende-node) (TypeScript) o
[`sifende-go`](https://github.com/ithdev/sifende-go).

## Requisitos

- Python 3.11 o posterior. Solo depende de `requests`.
- Una API key de Sifende ([cómo crearla](https://www.sifende.com.py/docs/inicio-rapido/paso-1-credenciales#14-crear-tu-api-key)).
Para probar sin enviar nada a SIFEN, usá una de Sandbox (`sk_sandbox_`).

## Primeros pasos

```bash
make setup # crea venv, instala deps, prepara .env
git clone https://github.com/ithdev/sifende-cli
cd sifende-cli
make setup # crea el venv, instala dependencias y copia .env.example a .env
$EDITOR .env # poné tu SIFENDE_API_KEY
make emitir FILE=sample_factura.json
make emitir # emite sample_factura.json y espera la respuesta de SIFEN
```

O sin Make:
Sin Make:

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # editá .env con tu API key
cp .env.example .env # poné tu SIFENDE_API_KEY
python sifende.py emitir --file sample_factura.json
```

## Configuración
Cuando SIFEN aprueba el documento, la CLI guarda `documentos/{cdc}/` con `payload.json`, `response.json` y `kude.pdf`.

Necesitás una API key de Sifende — [cómo crearla](https://www.sifende.com.py/docs/inicio-rapido/paso-1-credenciales#14-crear-tu-api-key).
## Configuración

Variables soportadas en `.env`:
Variables de `.env`:

| Variable | Default |
|----------------------|-----------------------------------------------|
| `SIFENDE_API_KEY` | (requerido) |
| `SIFENDE_BASE_URL` | `https://api.sifende.com.py/api/v1/` |
| `SIFENDE_TIMEOUT_S` | `30` |
| Variable | Por defecto |
|---|---|
| `SIFENDE_API_KEY` | Obligatoria. |
| `SIFENDE_BASE_URL` | `https://api.sifende.com.py/api/v1/` |
| `SIFENDE_TIMEOUT_S` | `30` |

## Comandos

| Operación | Make | Python |
|-----------|------|--------|
| Emitir (archivo) | `make emitir FILE=factura.json` | `python sifende.py emitir --file factura.json` |
| Emitir (interactivo) | `make emitir-i` | `python sifende.py emitir` |
|---|---|---|
| Emitir desde un archivo | `make emitir FILE=factura.json` | `python sifende.py emitir --file factura.json` |
| Emitir en modo interactivo | `make emitir-i` | `python sifende.py emitir` |
| Nota de crédito | `make nota-credito FILE_NC=nc.json` | `python sifende.py emitir --file nc.json` |
| Nota de débito | `make nota-debito FILE_ND=nd.json` | `python sifende.py emitir --file nd.json` |
| Consultar estado | `make estado CDC=<cdc>` | `python sifende.py estado <cdc>` |
| Descargar KuDE | `make kude CDC=<cdc> OUT=factura.pdf` | `python sifende.py kude <cdc> --out factura.pdf` |
| Cancelar | `make cancelar CDC=<cdc> MOTIVO="..."` | `python sifende.py cancelar <cdc> --motivo "..."` |
| Inutilizar | `make inutilizar TIPO=1 EST=001 PE=001 TIMBRADO=<t> DESDE=1 HASTA=3 MOTIVO="..."` | `python sifende.py inutilizar --tipo-documento 1 --establecimiento 001 --punto-expedicion 001 --numero-timbrado <t> --desde 1 --hasta 3 --motivo "..."` |
| Debug HTTP | `make debug FILE=factura.json` | `python sifende.py --debug emitir --file factura.json` |
| Ver el tráfico HTTP | `make debug FILE=factura.json` | `python sifende.py --debug emitir --file factura.json` |

Flags globales disponibles en todos los comandos: `--quiet`, `--json`, `--debug`, `--api-key`, `--base-url`.
Con Make se pasan como `EXTRA="--json"`.
`make help` lista todos los comandos.

La inutilización admite rangos de 2 a 1000 números por evento, conforme a las
restricciones de SIFEN. Una respuesta HTTP exitosa cuyo evento termine en
`RECHAZADO` o con un código distinto de `0600` devuelve exit code `2`.
Todos los comandos aceptan `--quiet`, `--json`, `--debug`, `--api-key` y `--base-url`. Con Make, se pasan en `EXTRA`:
`make emitir EXTRA="--json"`. `--debug` enmascara la API key. `emitir --no-wait` devuelve el CDC sin esperar la
respuesta de SIFEN.

Al aprobar un documento, la CLI guarda automáticamente `documentos/{cdc}/` con `payload.json`, `response.json` y `kude.pdf`.
La inutilización admite rangos de 2 a 1000 números por evento, como exige SIFEN.

### Notas de crédito y débito

Las notas de crédito (`NOTA_DE_CREDITO_ELECTRONICA`) y débito
(`NOTA_DE_DEBITO_ELECTRONICA`) usan el mismo comando `emitir`. Respecto a una
factura, requieren dos campos extra y **no** llevan `condicionOperacion`/`condicionPago`:
Las notas de crédito (`NOTA_DE_CREDITO_ELECTRONICA`) y de débito (`NOTA_DE_DEBITO_ELECTRONICA`) usan el mismo comando
`emitir`. A diferencia de una factura, no llevan `condicionOperacion` ni `condicionPago`, y requieren dos campos más:

- `motivoEmision`: uno de `DEVOLUCION`, `DEVOLUCION_Y_AJUSTES_DE_PRECIOS`,
`DESCUENTO`, `BONIFICACION`, `CREDITO_INCOBRABLE`, `RECUPERO_DE_COSTO`,
`RECUPERO_DE_GASTO`, `AJUSTE_DE_PRECIO`.
- `documentoAsociado`: la referencia al DE original. Hoy sólo se admite
`{"tipoDocumento": "ELECTRONICO", "cdc": "<44 dígitos>"}`, donde el CDC es el
de una factura ya aprobada.
- `motivoEmision`: `DEVOLUCION`, `DEVOLUCION_Y_AJUSTES_DE_PRECIOS`, `DESCUENTO`, `BONIFICACION`,
`CREDITO_INCOBRABLE`, `RECUPERO_DE_COSTO`, `RECUPERO_DE_GASTO` o `AJUSTE_DE_PRECIO`.
- `documentoAsociado`: el documento original. Por ahora solo se admite
`{"tipoDocumento": "ELECTRONICO", "cdc": "<44 dígitos>"}`, con el CDC de una factura aprobada.

Hay ejemplos en `sample_nota_credito.json` y `sample_nota_debito.json` — reemplazá
el `cdc` del `documentoAsociado` por el de una factura real antes de emitir. El
modo interactivo (`make emitir-i`) también guía la carga de estos campos cuando
elegís tipo 2 (nota de crédito) o 3 (nota de débito).
Hay ejemplos en `sample_nota_credito.json` y `sample_nota_debito.json`: antes de emitir, reemplazá el `cdc` del
`documentoAsociado` por el de una factura real. El modo interactivo también pide estos campos cuando elegís el tipo 2
(nota de crédito) o 3 (nota de débito).

### Códigos de salida

## Estructura del proyecto
| Código | Significado |
|---|---|
| `0` | La operación terminó bien. |
| `1` | Error no clasificado. |
| `2` | SIFEN rechazó el documento o el evento (también un evento con código distinto de `0600`). |
| `3` | Se agotó la espera de la respuesta de SIFEN. Consultá el estado más tarde con `estado`. |
| `4` | Datos o configuración inválidos (por ejemplo, falta la API key). |
| `5` | Error de la API o de red: autenticación, documento inexistente, HTTP o conexión. |
| `130` | Cancelado con Ctrl+C. |

## Desarrollo

```bash
pip install requests pytest
pytest tests/
```
sifende_cli/
├── ARCHITECTURE.md
├── README.md
├── Makefile
├── requirements.txt
├── .env.example
├── sample_factura.json
├── sample_nota_credito.json
├── sample_nota_debito.json
├── sifende.py
└── sifende/
├── __main__.py
├── cli.py
├── config.py
├── client.py
├── errors.py
├── models.py
├── polling.py
├── interactive.py
├── commands/{emitir,estado,kude,cancelar,inutilizar}.py
└── utils/{formatting,validation,io}.py
```

La CI corre los tests con Python 3.11 y 3.12. Los cambios se anotan en el [CHANGELOG](CHANGELOG.md).

## Soporte

- Errores de la CLI: abrí un [issue](https://github.com/ithdev/sifende-cli/issues).
- Tu cuenta, tus documentos o la API: escribinos a [soporte@sifende.com.py](mailto:soporte@sifende.com.py).
- La documentación de la API está en [sifende.com.py/docs](https://www.sifende.com.py/docs).

## Licencia

[MIT](LICENSE).
Loading