digifact-sdk 2.2.2__tar.gz → 2.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/PKG-INFO +61 -1
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/README.md +60 -0
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/digifact_sdk/client.py +62 -24
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/digifact_sdk.egg-info/PKG-INFO +61 -1
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/pyproject.toml +1 -1
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/digifact_sdk/__init__.py +0 -0
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/digifact_sdk/builder.py +0 -0
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/digifact_sdk/exceptions.py +0 -0
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/digifact_sdk/tax.py +0 -0
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/digifact_sdk.egg-info/SOURCES.txt +0 -0
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/digifact_sdk.egg-info/dependency_links.txt +0 -0
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/digifact_sdk.egg-info/requires.txt +0 -0
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/digifact_sdk.egg-info/top_level.txt +0 -0
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/setup.cfg +0 -0
- {digifact_sdk-2.2.2 → digifact_sdk-2.2.3}/tests/test_integration.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: digifact-sdk
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.3
|
|
4
4
|
Summary: Python SDK for Digifact FEL Guatemala e-invoicing API
|
|
5
5
|
Author-email: AALONZOLU <noreply@github.com>
|
|
6
6
|
License: MIT
|
|
@@ -38,6 +38,27 @@ O desde el código fuente:
|
|
|
38
38
|
pip install -e sdk/python/
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
## Configuración del cliente (`DigifactClient(...)`)
|
|
42
|
+
|
|
43
|
+
| Parámetro | Tipo | Por defecto | Descripción |
|
|
44
|
+
|-----------|------|-------------|-------------|
|
|
45
|
+
| `taxid` | `str` | **requerido** | NIT del emisor. Acepta dígitos o con separadores (`"12345678"`, `"1234567-8"`); los no-dígitos se eliminan. Se rellena internamente a 12 caracteres. |
|
|
46
|
+
| `username` | `str` | **requerido** | Usuario corto de Digifact (la parte después de `GT.<NIT>.`, p. ej. `"FELUSER"`). |
|
|
47
|
+
| `password` | `str` | `""` | Contraseña de la cuenta. **Requerido** si no se provee `token`. |
|
|
48
|
+
| `environment` | `str` | `"test"` | `"test"` o `"production"`. |
|
|
49
|
+
| `token` | `str` | `""` | Bearer token preobtenido. Si se provee, se omite el login. |
|
|
50
|
+
| `seller_name` | `str` | `""` | Nombre comercial del emisor. Si está vacío, se consulta en SAT vía `lookup_nit()`. |
|
|
51
|
+
| `seller_address` | `str` | `""` | Dirección del emisor. Si está vacía, se consulta en SAT. |
|
|
52
|
+
| `afiliacion_iva` | `str` | `"GEN"` | Afiliación IVA del RTU: `"GEN"`, `"PEQ"` o `"EXE"`. |
|
|
53
|
+
| `tipo_personeria` | `str` | `"1"` | Código de `TipoPersoneria` del RTU (usado en RDON). |
|
|
54
|
+
| `branch_code` | `str` | `"1"` | **Código del establecimiento** del RTU. Un NIT puede tener varios establecimientos (1, 2, 3…). Se escribe en `Seller.BranchInfo.Code`. |
|
|
55
|
+
| `branch_name` | `str` | `"ESTABLECIMIENTO PRINCIPAL"` | Nombre comercial del establecimiento. Se escribe en `Seller.BranchInfo.Name`. |
|
|
56
|
+
| `tipo_frase` | `str \| None` | `None` | Sobreescritura global de `TipoFrase`. Ver [frases](#configuración-de-frases-tipofrase--codigoescenario). |
|
|
57
|
+
| `escenario` | `str \| None` | `None` | Sobreescritura global de `CodigoEscenario`. |
|
|
58
|
+
| `timeout` | `int` | `120` | Timeout HTTP en segundos. |
|
|
59
|
+
| `session` | `requests.Session \| None` | `None` | Sesión HTTP personalizada (útil para tests). |
|
|
60
|
+
| `petroleo_rates` | `dict[str, float] \| None` | `None` | Mapa código PETROLEO → tarifa por unidad. Usado por `fuel_invoice()`. |
|
|
61
|
+
|
|
41
62
|
## Inicio rápido
|
|
42
63
|
|
|
43
64
|
```python
|
|
@@ -282,6 +303,45 @@ client = DigifactClient(
|
|
|
282
303
|
Para descubrir el par correcto en un caso particular, revisa las afiliaciones
|
|
283
304
|
del RTU en el portal de SAT.
|
|
284
305
|
|
|
306
|
+
## Referencia de métodos
|
|
307
|
+
|
|
308
|
+
Todos los métodos de emisión devuelven `DteResult` con `result.auth_number`, `series`, `number`, `issue_datetime`, `raw`.
|
|
309
|
+
|
|
310
|
+
| Método | Firma | Descripción |
|
|
311
|
+
|--------|-------|-------------|
|
|
312
|
+
| `invoice()` | `invoice(buyer, items, *, doc_type="FACT", payment_terms=None, amount_str="", observaciones="-", tipo_personeria=None, tipo_frase=None, escenario=None)` | Emite FACT, FCAM, FESP, FPEQ, NABN, RDON o RECI según `doc_type`. |
|
|
313
|
+
| `cca_invoice()` | `cca_invoice(buyer, items, cobros, *, tipo_frase=None, escenario=None)` | FACT con complemento CCA. |
|
|
314
|
+
| `fuel_invoice()` | `fuel_invoice(buyer, items, *, tipo_frase=None, escenario=None)` | FACT con complemento combustible (IVA + PETROLEO). |
|
|
315
|
+
| `credit_note()` | `credit_note(buyer, items, origin, reason, *, tipo_frase=None, escenario=None)` | Nota de crédito (NCRE). |
|
|
316
|
+
| `debit_note()` | `debit_note(buyer, items, origin, reason, *, tipo_frase=None, escenario=None)` | Nota de débito (NDEB). |
|
|
317
|
+
| `credit_note_total()` | `credit_note_total(auth_number, issue_datetime, reason="...", reference="")` | Nota de crédito total. Devuelve `dict`. |
|
|
318
|
+
| `cancel()` | `cancel(auth_number, receiver_id, issue_datetime, reason="Anulación")` | Anula un DTE. Devuelve `dict`. |
|
|
319
|
+
| `lookup_nit()` | `lookup_nit(nit)` | Consulta SAT. Devuelve `{"nit","name","address","city","district","state"}`. |
|
|
320
|
+
| `get_dte()` | `get_dte(auth_number, fmt="JSON")` | Recupera el DTE (`"JSON"`, `"XML"`, `"HTML"`, `"PDF"`). |
|
|
321
|
+
| `get_dte_info()` | `get_dte_info(auth_number)` | Metadatos del DTE. |
|
|
322
|
+
|
|
323
|
+
### Parámetros comunes
|
|
324
|
+
|
|
325
|
+
- **`buyer`**: `"CF"` (consumidor final), un NIT string (`"12345678"` — se consulta el nombre), un dict CUI (`{"type":"CUI","taxid":...,"name":...}`) o un dict NIT explícito (`{"taxid","name","address","city","district","state","country","email"}`).
|
|
326
|
+
- **`items`**: lista de dicts con `description` (str, req), `price` (float/Decimal, req), `qty` (1), `type` (`"Servicio"`/`"Bien"`), `unit_of_measure` (`"UNI"`), `discount` (opcional).
|
|
327
|
+
- **`origin`** (NCRE/NDEB): `{"auth_number": ..., "date": "YYYY-MM-DD", "series": ..., "number": ...}`.
|
|
328
|
+
|
|
329
|
+
## Establecimiento (sucursal)
|
|
330
|
+
|
|
331
|
+
Cada NIT puede tener varios establecimientos registrados en el RTU. Configúralos al crear el cliente:
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
client = DigifactClient(
|
|
335
|
+
taxid="12345678",
|
|
336
|
+
username="FELUSER",
|
|
337
|
+
password="secret",
|
|
338
|
+
branch_code="2",
|
|
339
|
+
branch_name="SUCURSAL ZONA 10",
|
|
340
|
+
)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Aplican a todos los DTE emitidos por ese cliente. Si se omiten, se usan los defaults `"1"` / `"ESTABLECIMIENTO PRINCIPAL"`.
|
|
344
|
+
|
|
285
345
|
## Ejecutar las pruebas
|
|
286
346
|
|
|
287
347
|
```bash
|
|
@@ -14,6 +14,27 @@ O desde el código fuente:
|
|
|
14
14
|
pip install -e sdk/python/
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
## Configuración del cliente (`DigifactClient(...)`)
|
|
18
|
+
|
|
19
|
+
| Parámetro | Tipo | Por defecto | Descripción |
|
|
20
|
+
|-----------|------|-------------|-------------|
|
|
21
|
+
| `taxid` | `str` | **requerido** | NIT del emisor. Acepta dígitos o con separadores (`"12345678"`, `"1234567-8"`); los no-dígitos se eliminan. Se rellena internamente a 12 caracteres. |
|
|
22
|
+
| `username` | `str` | **requerido** | Usuario corto de Digifact (la parte después de `GT.<NIT>.`, p. ej. `"FELUSER"`). |
|
|
23
|
+
| `password` | `str` | `""` | Contraseña de la cuenta. **Requerido** si no se provee `token`. |
|
|
24
|
+
| `environment` | `str` | `"test"` | `"test"` o `"production"`. |
|
|
25
|
+
| `token` | `str` | `""` | Bearer token preobtenido. Si se provee, se omite el login. |
|
|
26
|
+
| `seller_name` | `str` | `""` | Nombre comercial del emisor. Si está vacío, se consulta en SAT vía `lookup_nit()`. |
|
|
27
|
+
| `seller_address` | `str` | `""` | Dirección del emisor. Si está vacía, se consulta en SAT. |
|
|
28
|
+
| `afiliacion_iva` | `str` | `"GEN"` | Afiliación IVA del RTU: `"GEN"`, `"PEQ"` o `"EXE"`. |
|
|
29
|
+
| `tipo_personeria` | `str` | `"1"` | Código de `TipoPersoneria` del RTU (usado en RDON). |
|
|
30
|
+
| `branch_code` | `str` | `"1"` | **Código del establecimiento** del RTU. Un NIT puede tener varios establecimientos (1, 2, 3…). Se escribe en `Seller.BranchInfo.Code`. |
|
|
31
|
+
| `branch_name` | `str` | `"ESTABLECIMIENTO PRINCIPAL"` | Nombre comercial del establecimiento. Se escribe en `Seller.BranchInfo.Name`. |
|
|
32
|
+
| `tipo_frase` | `str \| None` | `None` | Sobreescritura global de `TipoFrase`. Ver [frases](#configuración-de-frases-tipofrase--codigoescenario). |
|
|
33
|
+
| `escenario` | `str \| None` | `None` | Sobreescritura global de `CodigoEscenario`. |
|
|
34
|
+
| `timeout` | `int` | `120` | Timeout HTTP en segundos. |
|
|
35
|
+
| `session` | `requests.Session \| None` | `None` | Sesión HTTP personalizada (útil para tests). |
|
|
36
|
+
| `petroleo_rates` | `dict[str, float] \| None` | `None` | Mapa código PETROLEO → tarifa por unidad. Usado por `fuel_invoice()`. |
|
|
37
|
+
|
|
17
38
|
## Inicio rápido
|
|
18
39
|
|
|
19
40
|
```python
|
|
@@ -258,6 +279,45 @@ client = DigifactClient(
|
|
|
258
279
|
Para descubrir el par correcto en un caso particular, revisa las afiliaciones
|
|
259
280
|
del RTU en el portal de SAT.
|
|
260
281
|
|
|
282
|
+
## Referencia de métodos
|
|
283
|
+
|
|
284
|
+
Todos los métodos de emisión devuelven `DteResult` con `result.auth_number`, `series`, `number`, `issue_datetime`, `raw`.
|
|
285
|
+
|
|
286
|
+
| Método | Firma | Descripción |
|
|
287
|
+
|--------|-------|-------------|
|
|
288
|
+
| `invoice()` | `invoice(buyer, items, *, doc_type="FACT", payment_terms=None, amount_str="", observaciones="-", tipo_personeria=None, tipo_frase=None, escenario=None)` | Emite FACT, FCAM, FESP, FPEQ, NABN, RDON o RECI según `doc_type`. |
|
|
289
|
+
| `cca_invoice()` | `cca_invoice(buyer, items, cobros, *, tipo_frase=None, escenario=None)` | FACT con complemento CCA. |
|
|
290
|
+
| `fuel_invoice()` | `fuel_invoice(buyer, items, *, tipo_frase=None, escenario=None)` | FACT con complemento combustible (IVA + PETROLEO). |
|
|
291
|
+
| `credit_note()` | `credit_note(buyer, items, origin, reason, *, tipo_frase=None, escenario=None)` | Nota de crédito (NCRE). |
|
|
292
|
+
| `debit_note()` | `debit_note(buyer, items, origin, reason, *, tipo_frase=None, escenario=None)` | Nota de débito (NDEB). |
|
|
293
|
+
| `credit_note_total()` | `credit_note_total(auth_number, issue_datetime, reason="...", reference="")` | Nota de crédito total. Devuelve `dict`. |
|
|
294
|
+
| `cancel()` | `cancel(auth_number, receiver_id, issue_datetime, reason="Anulación")` | Anula un DTE. Devuelve `dict`. |
|
|
295
|
+
| `lookup_nit()` | `lookup_nit(nit)` | Consulta SAT. Devuelve `{"nit","name","address","city","district","state"}`. |
|
|
296
|
+
| `get_dte()` | `get_dte(auth_number, fmt="JSON")` | Recupera el DTE (`"JSON"`, `"XML"`, `"HTML"`, `"PDF"`). |
|
|
297
|
+
| `get_dte_info()` | `get_dte_info(auth_number)` | Metadatos del DTE. |
|
|
298
|
+
|
|
299
|
+
### Parámetros comunes
|
|
300
|
+
|
|
301
|
+
- **`buyer`**: `"CF"` (consumidor final), un NIT string (`"12345678"` — se consulta el nombre), un dict CUI (`{"type":"CUI","taxid":...,"name":...}`) o un dict NIT explícito (`{"taxid","name","address","city","district","state","country","email"}`).
|
|
302
|
+
- **`items`**: lista de dicts con `description` (str, req), `price` (float/Decimal, req), `qty` (1), `type` (`"Servicio"`/`"Bien"`), `unit_of_measure` (`"UNI"`), `discount` (opcional).
|
|
303
|
+
- **`origin`** (NCRE/NDEB): `{"auth_number": ..., "date": "YYYY-MM-DD", "series": ..., "number": ...}`.
|
|
304
|
+
|
|
305
|
+
## Establecimiento (sucursal)
|
|
306
|
+
|
|
307
|
+
Cada NIT puede tener varios establecimientos registrados en el RTU. Configúralos al crear el cliente:
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
client = DigifactClient(
|
|
311
|
+
taxid="12345678",
|
|
312
|
+
username="FELUSER",
|
|
313
|
+
password="secret",
|
|
314
|
+
branch_code="2",
|
|
315
|
+
branch_name="SUCURSAL ZONA 10",
|
|
316
|
+
)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Aplican a todos los DTE emitidos por ese cliente. Si se omiten, se usan los defaults `"1"` / `"ESTABLECIMIENTO PRINCIPAL"`.
|
|
320
|
+
|
|
261
321
|
## Ejecutar las pruebas
|
|
262
322
|
|
|
263
323
|
```bash
|
|
@@ -61,30 +61,52 @@ class DigifactClient:
|
|
|
61
61
|
|
|
62
62
|
Parameters
|
|
63
63
|
----------
|
|
64
|
-
taxid:
|
|
65
|
-
Fiscal ID of the issuer
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
64
|
+
taxid : str
|
|
65
|
+
Fiscal ID / NIT of the issuer. Digits only or with separators
|
|
66
|
+
(e.g. ``"12345678"`` or ``"1234567-8"``); non-digits are stripped.
|
|
67
|
+
Internally padded to 12 chars.
|
|
68
|
+
username : str
|
|
69
|
+
Short Digifact username (the part after the ``GT.<NIT>.`` prefix,
|
|
70
|
+
e.g. ``"FELUSER"``).
|
|
71
|
+
password : str, optional
|
|
72
|
+
Account password. Required unless ``token`` is supplied.
|
|
73
|
+
environment : {"test", "production"}, default "test"
|
|
74
|
+
Target environment.
|
|
75
|
+
token : str, optional
|
|
76
|
+
Pre-obtained bearer token. If provided, login is skipped and
|
|
77
|
+
``password`` is not needed.
|
|
78
|
+
seller_name : str, optional
|
|
79
|
+
Overrides the issuer display name. When empty, the SDK resolves it
|
|
80
|
+
from SAT via :meth:`lookup_nit`.
|
|
81
|
+
seller_address : str, optional
|
|
82
|
+
Overrides the issuer address. When empty, the SDK resolves it from
|
|
83
|
+
SAT via :meth:`lookup_nit`.
|
|
84
|
+
afiliacion_iva : {"GEN", "PEQ", "EXE"}, default "GEN"
|
|
85
|
+
IVA affiliation recorded in SAT RTU. "PEQ" = Pequeño Contribuyente,
|
|
86
|
+
"EXE" = Exento.
|
|
87
|
+
tipo_personeria : str, default "1"
|
|
88
|
+
``TipoPersoneria`` code from the RTU (used by RDON).
|
|
89
|
+
tipo_frase : str, optional
|
|
90
|
+
Global override for ``TipoFrase`` (SAT ``AdditionlInfo``). When
|
|
91
|
+
``None`` (default), the SDK uses :func:`default_frase` based on
|
|
92
|
+
DocType + afiliación. Can be overridden per-call.
|
|
93
|
+
escenario : str, optional
|
|
94
|
+
Global override for ``CodigoEscenario``. When ``None`` (default),
|
|
95
|
+
uses the defaults table. For GEN, common values are ``"1"`` (ISR
|
|
96
|
+
régimen sobre utilidades, default) or ``"2"`` (ISR opcional
|
|
97
|
+
simplificado sobre ingresos).
|
|
98
|
+
branch_code : str, default "1"
|
|
99
|
+
Código del establecimiento (SAT RTU). Each NIT may have several
|
|
100
|
+
establecimientos (1, 2, 3, …); ``"1"`` is usually the principal.
|
|
101
|
+
branch_name : str, default "ESTABLECIMIENTO PRINCIPAL"
|
|
102
|
+
Nombre comercial del establecimiento.
|
|
103
|
+
timeout : int, default 120
|
|
104
|
+
HTTP request timeout in seconds.
|
|
105
|
+
session : requests.Session, optional
|
|
106
|
+
Optional :class:`requests.Session` to use (useful for testing or
|
|
107
|
+
connection pooling).
|
|
108
|
+
petroleo_rates : dict[str, float], optional
|
|
109
|
+
Mapping of PETROLEO code → per-unit tax amount, e.g.
|
|
88
110
|
``{"1": 4.70, "2": 4.60, "4": 1.30}`` (SUPER/REGULAR/DIESEL).
|
|
89
111
|
When set, fuel items in :meth:`fuel_invoice` that provide
|
|
90
112
|
``petroleo_code`` but omit ``petroleo_amount`` will have the amount
|
|
@@ -105,6 +127,8 @@ class DigifactClient:
|
|
|
105
127
|
tipo_personeria: str = "1",
|
|
106
128
|
tipo_frase: str | None = None,
|
|
107
129
|
escenario: str | None = None,
|
|
130
|
+
branch_code: str = "1",
|
|
131
|
+
branch_name: str = "ESTABLECIMIENTO PRINCIPAL",
|
|
108
132
|
timeout: int = 120,
|
|
109
133
|
session: requests.Session | None = None,
|
|
110
134
|
petroleo_rates: dict[str, float] | None = None,
|
|
@@ -125,6 +149,8 @@ class DigifactClient:
|
|
|
125
149
|
self.tipo_personeria = tipo_personeria
|
|
126
150
|
self.tipo_frase = tipo_frase
|
|
127
151
|
self.escenario = escenario
|
|
152
|
+
self.branch_code = branch_code
|
|
153
|
+
self.branch_name = branch_name
|
|
128
154
|
self.timeout = timeout
|
|
129
155
|
|
|
130
156
|
base = _BASE_URLS.get(environment)
|
|
@@ -244,7 +270,19 @@ class DigifactClient:
|
|
|
244
270
|
|
|
245
271
|
# ── Raw API calls ─────────────────────────────────────────────────────────
|
|
246
272
|
|
|
273
|
+
def _apply_branch_info(self, payload: dict) -> dict:
|
|
274
|
+
"""Overlay configured ``branch_code`` / ``branch_name`` onto the
|
|
275
|
+
``Seller.BranchInfo`` block so callers don't have to plumb it through
|
|
276
|
+
every builder.
|
|
277
|
+
"""
|
|
278
|
+
branch = payload.get("Seller", {}).get("BranchInfo")
|
|
279
|
+
if isinstance(branch, dict):
|
|
280
|
+
branch["Code"] = self.branch_code
|
|
281
|
+
branch["Name"] = self.branch_name
|
|
282
|
+
return payload
|
|
283
|
+
|
|
247
284
|
def _certify(self, payload: dict) -> dict:
|
|
285
|
+
payload = self._apply_branch_info(payload)
|
|
248
286
|
resp = self._session.post(
|
|
249
287
|
f"{self.base_url}/v2/transform/nuc_json",
|
|
250
288
|
params={
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: digifact-sdk
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.3
|
|
4
4
|
Summary: Python SDK for Digifact FEL Guatemala e-invoicing API
|
|
5
5
|
Author-email: AALONZOLU <noreply@github.com>
|
|
6
6
|
License: MIT
|
|
@@ -38,6 +38,27 @@ O desde el código fuente:
|
|
|
38
38
|
pip install -e sdk/python/
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
## Configuración del cliente (`DigifactClient(...)`)
|
|
42
|
+
|
|
43
|
+
| Parámetro | Tipo | Por defecto | Descripción |
|
|
44
|
+
|-----------|------|-------------|-------------|
|
|
45
|
+
| `taxid` | `str` | **requerido** | NIT del emisor. Acepta dígitos o con separadores (`"12345678"`, `"1234567-8"`); los no-dígitos se eliminan. Se rellena internamente a 12 caracteres. |
|
|
46
|
+
| `username` | `str` | **requerido** | Usuario corto de Digifact (la parte después de `GT.<NIT>.`, p. ej. `"FELUSER"`). |
|
|
47
|
+
| `password` | `str` | `""` | Contraseña de la cuenta. **Requerido** si no se provee `token`. |
|
|
48
|
+
| `environment` | `str` | `"test"` | `"test"` o `"production"`. |
|
|
49
|
+
| `token` | `str` | `""` | Bearer token preobtenido. Si se provee, se omite el login. |
|
|
50
|
+
| `seller_name` | `str` | `""` | Nombre comercial del emisor. Si está vacío, se consulta en SAT vía `lookup_nit()`. |
|
|
51
|
+
| `seller_address` | `str` | `""` | Dirección del emisor. Si está vacía, se consulta en SAT. |
|
|
52
|
+
| `afiliacion_iva` | `str` | `"GEN"` | Afiliación IVA del RTU: `"GEN"`, `"PEQ"` o `"EXE"`. |
|
|
53
|
+
| `tipo_personeria` | `str` | `"1"` | Código de `TipoPersoneria` del RTU (usado en RDON). |
|
|
54
|
+
| `branch_code` | `str` | `"1"` | **Código del establecimiento** del RTU. Un NIT puede tener varios establecimientos (1, 2, 3…). Se escribe en `Seller.BranchInfo.Code`. |
|
|
55
|
+
| `branch_name` | `str` | `"ESTABLECIMIENTO PRINCIPAL"` | Nombre comercial del establecimiento. Se escribe en `Seller.BranchInfo.Name`. |
|
|
56
|
+
| `tipo_frase` | `str \| None` | `None` | Sobreescritura global de `TipoFrase`. Ver [frases](#configuración-de-frases-tipofrase--codigoescenario). |
|
|
57
|
+
| `escenario` | `str \| None` | `None` | Sobreescritura global de `CodigoEscenario`. |
|
|
58
|
+
| `timeout` | `int` | `120` | Timeout HTTP en segundos. |
|
|
59
|
+
| `session` | `requests.Session \| None` | `None` | Sesión HTTP personalizada (útil para tests). |
|
|
60
|
+
| `petroleo_rates` | `dict[str, float] \| None` | `None` | Mapa código PETROLEO → tarifa por unidad. Usado por `fuel_invoice()`. |
|
|
61
|
+
|
|
41
62
|
## Inicio rápido
|
|
42
63
|
|
|
43
64
|
```python
|
|
@@ -282,6 +303,45 @@ client = DigifactClient(
|
|
|
282
303
|
Para descubrir el par correcto en un caso particular, revisa las afiliaciones
|
|
283
304
|
del RTU en el portal de SAT.
|
|
284
305
|
|
|
306
|
+
## Referencia de métodos
|
|
307
|
+
|
|
308
|
+
Todos los métodos de emisión devuelven `DteResult` con `result.auth_number`, `series`, `number`, `issue_datetime`, `raw`.
|
|
309
|
+
|
|
310
|
+
| Método | Firma | Descripción |
|
|
311
|
+
|--------|-------|-------------|
|
|
312
|
+
| `invoice()` | `invoice(buyer, items, *, doc_type="FACT", payment_terms=None, amount_str="", observaciones="-", tipo_personeria=None, tipo_frase=None, escenario=None)` | Emite FACT, FCAM, FESP, FPEQ, NABN, RDON o RECI según `doc_type`. |
|
|
313
|
+
| `cca_invoice()` | `cca_invoice(buyer, items, cobros, *, tipo_frase=None, escenario=None)` | FACT con complemento CCA. |
|
|
314
|
+
| `fuel_invoice()` | `fuel_invoice(buyer, items, *, tipo_frase=None, escenario=None)` | FACT con complemento combustible (IVA + PETROLEO). |
|
|
315
|
+
| `credit_note()` | `credit_note(buyer, items, origin, reason, *, tipo_frase=None, escenario=None)` | Nota de crédito (NCRE). |
|
|
316
|
+
| `debit_note()` | `debit_note(buyer, items, origin, reason, *, tipo_frase=None, escenario=None)` | Nota de débito (NDEB). |
|
|
317
|
+
| `credit_note_total()` | `credit_note_total(auth_number, issue_datetime, reason="...", reference="")` | Nota de crédito total. Devuelve `dict`. |
|
|
318
|
+
| `cancel()` | `cancel(auth_number, receiver_id, issue_datetime, reason="Anulación")` | Anula un DTE. Devuelve `dict`. |
|
|
319
|
+
| `lookup_nit()` | `lookup_nit(nit)` | Consulta SAT. Devuelve `{"nit","name","address","city","district","state"}`. |
|
|
320
|
+
| `get_dte()` | `get_dte(auth_number, fmt="JSON")` | Recupera el DTE (`"JSON"`, `"XML"`, `"HTML"`, `"PDF"`). |
|
|
321
|
+
| `get_dte_info()` | `get_dte_info(auth_number)` | Metadatos del DTE. |
|
|
322
|
+
|
|
323
|
+
### Parámetros comunes
|
|
324
|
+
|
|
325
|
+
- **`buyer`**: `"CF"` (consumidor final), un NIT string (`"12345678"` — se consulta el nombre), un dict CUI (`{"type":"CUI","taxid":...,"name":...}`) o un dict NIT explícito (`{"taxid","name","address","city","district","state","country","email"}`).
|
|
326
|
+
- **`items`**: lista de dicts con `description` (str, req), `price` (float/Decimal, req), `qty` (1), `type` (`"Servicio"`/`"Bien"`), `unit_of_measure` (`"UNI"`), `discount` (opcional).
|
|
327
|
+
- **`origin`** (NCRE/NDEB): `{"auth_number": ..., "date": "YYYY-MM-DD", "series": ..., "number": ...}`.
|
|
328
|
+
|
|
329
|
+
## Establecimiento (sucursal)
|
|
330
|
+
|
|
331
|
+
Cada NIT puede tener varios establecimientos registrados en el RTU. Configúralos al crear el cliente:
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
client = DigifactClient(
|
|
335
|
+
taxid="12345678",
|
|
336
|
+
username="FELUSER",
|
|
337
|
+
password="secret",
|
|
338
|
+
branch_code="2",
|
|
339
|
+
branch_name="SUCURSAL ZONA 10",
|
|
340
|
+
)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Aplican a todos los DTE emitidos por ese cliente. Si se omiten, se usan los defaults `"1"` / `"ESTABLECIMIENTO PRINCIPAL"`.
|
|
344
|
+
|
|
285
345
|
## Ejecutar las pruebas
|
|
286
346
|
|
|
287
347
|
```bash
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|