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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digifact-sdk
3
- Version: 2.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 (digits only; will be padded to 12 chars).
66
- username:
67
- Short username, e.g. "FELUSER".
68
- password:
69
- Account password. Either password or token must be provided.
70
- environment:
71
- "test" (default) or "production".
72
- token:
73
- Pre-obtained bearer token. If provided, login is skipped.
74
- seller_name:
75
- Override the seller name (default: fetched from SAT NIT lookup).
76
- seller_address:
77
- Override the seller address.
78
- afiliacion_iva:
79
- IVA affiliation code ("GEN", "PEQ", "EXE"). Default "GEN".
80
- tipo_personeria:
81
- Required for RDON; e.g. "719".
82
- timeout:
83
- HTTP request timeout in seconds (default 120).
84
- session:
85
- Optional ``requests.Session`` to use (useful for testing / mocking).
86
- petroleo_rates:
87
- Optional mapping of PETROLEO code → per-unit tax amount, e.g.
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.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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "digifact-sdk"
7
- version = "2.2.2"
7
+ version = "2.2.3"
8
8
  description = "Python SDK for Digifact FEL Guatemala e-invoicing API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes