libredte-lib-sdk 0.5.2__tar.gz → 0.6.0__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.
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/PKG-INFO +15 -3
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/README.rst +14 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/book/builder.py +3 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/book/loader.py +3 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/book/models.py +5 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/common.py +30 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/__init__.py +8 -0
- libredte_lib_sdk-0.6.0/libredte_lib_sdk/billing/document/batch_processor.py +72 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/builder.py +15 -10
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/dispatcher.py +9 -6
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/loader.py +5 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/models.py +54 -6
- libredte_lib_sdk-0.6.0/libredte_lib_sdk/billing/document/parser.py +58 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/renderer.py +3 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/exchange/document_response.py +5 -4
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/exchange/models.py +7 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/identifier/caf_faker.py +3 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/identifier/caf_loader.py +5 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/identifier/caf_validator.py +5 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/identifier/models.py +4 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/integration/models.py +32 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/integration/sii_dte.py +13 -10
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/integration/sii_rcv.py +9 -8
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/integration/sii_rtc.py +3 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/ownership_transfer/aec.py +3 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/ownership_transfer/models.py +4 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/trading_parties/mandatario_manager.py +5 -4
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/trading_parties/models.py +8 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/client.py +52 -4
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/exceptions.py +10 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/human_resources/payroll/renderer.py +3 -2
- libredte_lib_sdk-0.6.0/libredte_lib_sdk/response_registry.py +81 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/sdk.py +7 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/system/certificate/loader.py +3 -2
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/pyproject.toml +1 -1
- libredte_lib_sdk-0.6.0/tests/fixtures/certificate_112223339.p12 +0 -0
- libredte_lib_sdk-0.6.0/tests/integration/test_batch_processor.py +96 -0
- libredte_lib_sdk-0.6.0/tests/integration/test_certificate_loader.py +55 -0
- libredte_lib_sdk-0.6.0/tests/integration/test_document_parser.py +44 -0
- libredte_lib_sdk-0.6.0/tests/integration/test_operation_not_found.py +26 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/test_client.py +15 -0
- libredte_lib_sdk-0.6.0/tests/test_response_registry.py +170 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/test_services.py +413 -33
- libredte_lib_sdk-0.5.2/.claude/scheduled_tasks.lock +0 -1
- libredte_lib_sdk-0.5.2/tests/integration/test_certificate_loader.py +0 -74
- libredte_lib_sdk-0.5.2/tests/integration/test_operation_not_found.py +0 -34
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/.github/workflows/ci.yml +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/.github/workflows/docs.yml +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/.gitignore +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/.readthedocs.yaml +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/CLAUDE.md +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/LICENSE +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/Makefile +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/docs/Makefile +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/docs/conf.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/docs/index.rst +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/book/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/book/validator.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/examples.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/validator.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/enums.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/exchange/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/identifier/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/integration/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/ownership_transfer/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/trading_parties/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/human_resources/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/human_resources/integration/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/human_resources/integration/previred_provider.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/human_resources/payroll/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/human_resources/payroll/calculator.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/py.typed +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/system/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/system/certificate/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/system/repository/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/system/repository/catalog.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/conftest.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/__init__.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/conftest.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/test_book.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/test_caf.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/test_document_loader.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/test_document_rendering.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/test_document_validation.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/test_examples.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/test_exchange.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/test_human_resources.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/test_ownership_transfer.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/integration/test_repository.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/test_exceptions.py +0 -0
- {libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/tests/test_models.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: libredte-lib-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: SDK Python para la API de LibreDTE Lib (facturacion electronica de Chile).
|
|
5
5
|
Project-URL: Homepage, https://www.libredte.cl
|
|
6
6
|
Project-URL: Source, https://github.com/libredte/libredte-lib-sdk-python
|
|
@@ -187,14 +187,26 @@ entorno ``LIBREDTE_LIB_SDK_BASE_URL``:
|
|
|
187
187
|
``core.libredte.cl`` y ``pro.libredte.cl`` exponen el mismo contrato con
|
|
188
188
|
límites de solicitudes distintos; ambos aceptan la variante ``LibreDTE
|
|
189
189
|
(base_url=..., ...)`` con el resto de los parámetros de configuración
|
|
190
|
-
(``api_token``, ``timeout``, ``http_client``).
|
|
190
|
+
(``api_token``, ``auth_scheme``, ``timeout``, ``http_client``).
|
|
191
191
|
|
|
192
192
|
Autenticación
|
|
193
193
|
~~~~~~~~~~~~~
|
|
194
194
|
|
|
195
195
|
``LibreDTE(api_token=...)`` o la variable de entorno
|
|
196
196
|
``LIBREDTE_LIB_SDK_TOKEN`` — si está presente, se manda como header
|
|
197
|
-
``Authorization:
|
|
197
|
+
``Authorization: <esquema> <token>``. El esquema es ``Bearer`` por
|
|
198
|
+
defecto (lo que espera ``core.libredte.cl``/``pro.libredte.cl``);
|
|
199
|
+
configurable con ``LibreDTE(auth_scheme=...)`` o la variable de entorno
|
|
200
|
+
``LIBREDTE_LIB_SDK_AUTH_SCHEME`` para hablar con otra API que use un
|
|
201
|
+
esquema distinto (ej. ``'Token'``):
|
|
202
|
+
|
|
203
|
+
.. code-block:: python
|
|
204
|
+
|
|
205
|
+
sdk = LibreDTE(
|
|
206
|
+
base_url='https://app.apigateway.cl/api/v2/libredte',
|
|
207
|
+
api_token='...',
|
|
208
|
+
auth_scheme='Token',
|
|
209
|
+
)
|
|
198
210
|
|
|
199
211
|
Recursos de ``system``
|
|
200
212
|
-----------------------
|
|
@@ -143,14 +143,26 @@ entorno ``LIBREDTE_LIB_SDK_BASE_URL``:
|
|
|
143
143
|
``core.libredte.cl`` y ``pro.libredte.cl`` exponen el mismo contrato con
|
|
144
144
|
límites de solicitudes distintos; ambos aceptan la variante ``LibreDTE
|
|
145
145
|
(base_url=..., ...)`` con el resto de los parámetros de configuración
|
|
146
|
-
(``api_token``, ``timeout``, ``http_client``).
|
|
146
|
+
(``api_token``, ``auth_scheme``, ``timeout``, ``http_client``).
|
|
147
147
|
|
|
148
148
|
Autenticación
|
|
149
149
|
~~~~~~~~~~~~~
|
|
150
150
|
|
|
151
151
|
``LibreDTE(api_token=...)`` o la variable de entorno
|
|
152
152
|
``LIBREDTE_LIB_SDK_TOKEN`` — si está presente, se manda como header
|
|
153
|
-
``Authorization:
|
|
153
|
+
``Authorization: <esquema> <token>``. El esquema es ``Bearer`` por
|
|
154
|
+
defecto (lo que espera ``core.libredte.cl``/``pro.libredte.cl``);
|
|
155
|
+
configurable con ``LibreDTE(auth_scheme=...)`` o la variable de entorno
|
|
156
|
+
``LIBREDTE_LIB_SDK_AUTH_SCHEME`` para hablar con otra API que use un
|
|
157
|
+
esquema distinto (ej. ``'Token'``):
|
|
158
|
+
|
|
159
|
+
.. code-block:: python
|
|
160
|
+
|
|
161
|
+
sdk = LibreDTE(
|
|
162
|
+
base_url='https://app.apigateway.cl/api/v2/libredte',
|
|
163
|
+
api_token='...',
|
|
164
|
+
auth_scheme='Token',
|
|
165
|
+
)
|
|
154
166
|
|
|
155
167
|
Recursos de ``system``
|
|
156
168
|
-----------------------
|
|
@@ -8,6 +8,7 @@ from __future__ import annotations
|
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
10
|
from ...client import ApiClient
|
|
11
|
+
from ...response_registry import build_response
|
|
11
12
|
from ..trading_parties.models import Certificate
|
|
12
13
|
from .models import BookBag
|
|
13
14
|
|
|
@@ -37,8 +38,8 @@ class BookBuilderService:
|
|
|
37
38
|
.load()`, acá `BookBag.book` viene poblado (el libro construido
|
|
38
39
|
y firmado, con su `xml`).
|
|
39
40
|
"""
|
|
40
|
-
|
|
41
|
+
response = self._client.call_response(
|
|
41
42
|
self._BUILD_OPERATION,
|
|
42
43
|
bag={**bag, 'certificate': certificate.to_payload()},
|
|
43
44
|
)
|
|
44
|
-
return BookBag
|
|
45
|
+
return build_response(BookBag, response)
|
|
@@ -8,6 +8,7 @@ from __future__ import annotations
|
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
10
|
from ...client import ApiClient
|
|
11
|
+
from ...response_registry import build_response
|
|
11
12
|
from ..trading_parties.models import Certificate
|
|
12
13
|
from .models import BookBag
|
|
13
14
|
|
|
@@ -35,8 +36,8 @@ class BookLoaderService:
|
|
|
35
36
|
el libro); `BookBag.book_auth` viene poblado solo si
|
|
36
37
|
`bag['emisor']` incluye `autorizacion_dte`.
|
|
37
38
|
"""
|
|
38
|
-
|
|
39
|
+
response = self._client.call_response(
|
|
39
40
|
self._LOAD_OPERATION,
|
|
40
41
|
bag={**bag, 'certificate': certificate.to_payload()},
|
|
41
42
|
)
|
|
42
|
-
return BookBag
|
|
43
|
+
return build_response(BookBag, response)
|
|
@@ -9,7 +9,12 @@ import base64
|
|
|
9
9
|
from dataclasses import dataclass
|
|
10
10
|
from typing import Any, cast
|
|
11
11
|
|
|
12
|
+
from ...response_registry import api_response
|
|
12
13
|
|
|
14
|
+
|
|
15
|
+
@api_response(
|
|
16
|
+
'libredte\\lib\\Core\\Package\\Billing\\Component\\Book\\Support\\BookBag',
|
|
17
|
+
)
|
|
13
18
|
@dataclass(frozen=True, slots=True)
|
|
14
19
|
class BookBag:
|
|
15
20
|
"""
|
|
@@ -6,6 +6,36 @@
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
import base64
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def encode_content(content: str | bytes) -> str:
|
|
13
|
+
"""
|
|
14
|
+
Codifica en base64 un contenido para enviarlo a la API.
|
|
15
|
+
|
|
16
|
+
Un `bytes` se envía tal cual, sin alterar su codificación (lo correcto
|
|
17
|
+
para el contenido de un archivo). Un `str` ya es texto decodificado, así
|
|
18
|
+
que se codifica en UTF-8.
|
|
19
|
+
"""
|
|
20
|
+
raw = content if isinstance(content, bytes) else content.encode('utf-8')
|
|
21
|
+
|
|
22
|
+
return base64.b64encode(raw).decode()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def encode_input_data(
|
|
26
|
+
input_data: str | bytes | dict[str, Any],
|
|
27
|
+
) -> str | dict[str, Any]:
|
|
28
|
+
"""
|
|
29
|
+
Prepara el `inputData` de una bolsa para enviarlo a la API.
|
|
30
|
+
|
|
31
|
+
Un `dict` son los datos en JSON y viaja tal cual. Todo lo demás es el
|
|
32
|
+
contenido original en otro formato (XML, YAML, texto, etc.) y viaja en
|
|
33
|
+
base64 (ver `encode_content()`).
|
|
34
|
+
"""
|
|
35
|
+
if isinstance(input_data, dict):
|
|
36
|
+
return input_data
|
|
37
|
+
|
|
38
|
+
return encode_content(input_data)
|
|
9
39
|
|
|
10
40
|
|
|
11
41
|
class XmlPayloadMixin:
|
{libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/__init__.py
RENAMED
|
@@ -6,29 +6,35 @@
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
from ...client import ApiClient
|
|
9
|
+
from .batch_processor import DocumentBatchProcessorService
|
|
9
10
|
from .builder import DocumentBuilderService
|
|
10
11
|
from .dispatcher import DocumentDispatcherService
|
|
11
12
|
from .examples import DocumentExamplesService
|
|
12
13
|
from .loader import DocumentLoaderService
|
|
13
14
|
from .models import (
|
|
14
15
|
DocumentBag,
|
|
16
|
+
DocumentBatch,
|
|
15
17
|
DocumentEnvelope,
|
|
16
18
|
Example,
|
|
17
19
|
ExampleSummary,
|
|
18
20
|
RenderedDocument,
|
|
19
21
|
RenderResult,
|
|
20
22
|
)
|
|
23
|
+
from .parser import DocumentParserService
|
|
21
24
|
from .renderer import DocumentRendererService
|
|
22
25
|
from .validator import DocumentValidatorService
|
|
23
26
|
|
|
24
27
|
__all__ = [
|
|
25
28
|
'DocumentBag',
|
|
29
|
+
'DocumentBatch',
|
|
30
|
+
'DocumentBatchProcessorService',
|
|
26
31
|
'DocumentBuilderService',
|
|
27
32
|
'DocumentComponent',
|
|
28
33
|
'DocumentDispatcherService',
|
|
29
34
|
'DocumentEnvelope',
|
|
30
35
|
'DocumentExamplesService',
|
|
31
36
|
'DocumentLoaderService',
|
|
37
|
+
'DocumentParserService',
|
|
32
38
|
'DocumentRendererService',
|
|
33
39
|
'DocumentValidatorService',
|
|
34
40
|
'Example',
|
|
@@ -49,3 +55,5 @@ class DocumentComponent:
|
|
|
49
55
|
self.examples = DocumentExamplesService(client)
|
|
50
56
|
self.validator = DocumentValidatorService(client)
|
|
51
57
|
self.loader = DocumentLoaderService(client)
|
|
58
|
+
self.parser = DocumentParserService(client)
|
|
59
|
+
self.batch_processor = DocumentBatchProcessorService(client)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Copyright (C) 2026 LibreDTE <https://www.libredte.cl>
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
"""Servicio para `billing.document.batch_processor`."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from ...client import ApiClient
|
|
11
|
+
from ...response_registry import build_response
|
|
12
|
+
from ..common import encode_content
|
|
13
|
+
from .models import DocumentBatch
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DocumentBatchProcessorService:
|
|
17
|
+
"""
|
|
18
|
+
Parsea un lote de documentos de una emisión masiva.
|
|
19
|
+
|
|
20
|
+
Solo cubre `parse`: entrega los documentos parseados, sin construirlos
|
|
21
|
+
(sin folios, CAF ni certificado).
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
_PARSE_OPERATION = 'billing.document.batch_processor::parse'
|
|
25
|
+
|
|
26
|
+
def __init__(self, client: ApiClient) -> None:
|
|
27
|
+
"""Guarda el `ApiClient` compartido usado para llamar a la API."""
|
|
28
|
+
self._client = client
|
|
29
|
+
|
|
30
|
+
def parse(
|
|
31
|
+
self,
|
|
32
|
+
input_data: str | bytes,
|
|
33
|
+
*,
|
|
34
|
+
emisor: dict[str, Any] | None = None,
|
|
35
|
+
strategy: str | None = None,
|
|
36
|
+
complete: bool | None = None,
|
|
37
|
+
) -> DocumentBatch:
|
|
38
|
+
"""
|
|
39
|
+
Parsea el archivo de un lote y entrega las bolsas de sus documentos.
|
|
40
|
+
|
|
41
|
+
`input_data` es el contenido del archivo (CSV, XLSX, etc.). Se debe
|
|
42
|
+
pasar como `bytes` (leído en modo `rb`): se envía sin alterar. Un
|
|
43
|
+
`str` ya es texto decodificado y se envía en UTF-8.
|
|
44
|
+
|
|
45
|
+
`emisor` es un `dict` con `rut`/`razon_social` (y demás datos del
|
|
46
|
+
emisor): con `complete` activo (por defecto) se usan para completar
|
|
47
|
+
los datos del emisor de cada documento.
|
|
48
|
+
|
|
49
|
+
`strategy` es la estrategia del archivo (`'spreadsheet.csv'` por
|
|
50
|
+
defecto; `'spreadsheet.xlsx'` solo existe en Lib Pro). `complete`
|
|
51
|
+
indica si se completan los datos del documento con los del emisor
|
|
52
|
+
(por defecto la API lo hace).
|
|
53
|
+
|
|
54
|
+
Un error en el archivo lanza `LibreDteApiError` indicando la fila
|
|
55
|
+
(ej. ``Fila 3: ...``).
|
|
56
|
+
"""
|
|
57
|
+
batch: dict[str, Any] = {'inputData': encode_content(input_data)}
|
|
58
|
+
if emisor is not None:
|
|
59
|
+
batch['emisor'] = emisor
|
|
60
|
+
|
|
61
|
+
options: dict[str, Any] = {}
|
|
62
|
+
if strategy is not None:
|
|
63
|
+
options['strategy'] = strategy
|
|
64
|
+
if complete is not None:
|
|
65
|
+
options['complete'] = complete
|
|
66
|
+
if options:
|
|
67
|
+
batch['options'] = {'batch_processor': options}
|
|
68
|
+
|
|
69
|
+
return build_response(
|
|
70
|
+
DocumentBatch,
|
|
71
|
+
self._client.call_response(self._PARSE_OPERATION, batch=batch),
|
|
72
|
+
)
|
{libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/builder.py
RENAMED
|
@@ -8,6 +8,8 @@ from __future__ import annotations
|
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
10
|
from ...client import ApiClient
|
|
11
|
+
from ...response_registry import build_response
|
|
12
|
+
from ..common import encode_input_data
|
|
11
13
|
from ..trading_parties.models import Certificate
|
|
12
14
|
from .models import DocumentBag
|
|
13
15
|
|
|
@@ -30,7 +32,7 @@ class DocumentBuilderService:
|
|
|
30
32
|
|
|
31
33
|
def build_draft(
|
|
32
34
|
self,
|
|
33
|
-
input_data: str | dict[str, Any],
|
|
35
|
+
input_data: str | bytes | dict[str, Any],
|
|
34
36
|
*,
|
|
35
37
|
options: dict[str, Any] | None = None,
|
|
36
38
|
) -> DocumentBag:
|
|
@@ -39,25 +41,28 @@ class DocumentBuilderService:
|
|
|
39
41
|
|
|
40
42
|
`input_data` es el `Encabezado`/`Detalle` (y demás nodos) del
|
|
41
43
|
formato DTE del SII como `dict` — o datos en otro formato
|
|
42
|
-
(XML/YAML, un formulario, etc.) junto con
|
|
44
|
+
(XML/YAML, un formulario, etc.), como `bytes` o `str`, junto con
|
|
43
45
|
`options={'parser': {'strategy': '<estrategia>'}}` para indicar
|
|
44
|
-
cómo parsearlos.
|
|
46
|
+
cómo parsearlos. El contenido de un archivo se debe pasar como
|
|
47
|
+
`bytes` (leído en modo `rb`): se envía sin alterar su
|
|
48
|
+
codificación. Un `str` ya es texto decodificado y se envía en
|
|
49
|
+
UTF-8. Sin `options`, la API asume que `input_data` ya
|
|
45
50
|
viene en el formato DTE del SII (estrategia `default.json`).
|
|
46
51
|
`Encabezado.IdDoc.Folio` es opcional acá — un borrador sin folio
|
|
47
52
|
no falla (queda con folio `0` en `DocumentBag.document_id`, sin
|
|
48
53
|
nodo `Folio` en el XML). Sin CAF ni certificado, el resultado no
|
|
49
54
|
queda timbrado (`DocumentBag.is_timbrado` es `False`).
|
|
50
55
|
"""
|
|
51
|
-
bag: dict[str, Any] = {'inputData': input_data}
|
|
56
|
+
bag: dict[str, Any] = {'inputData': encode_input_data(input_data)}
|
|
52
57
|
if options is not None:
|
|
53
58
|
bag['options'] = options
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
return DocumentBag
|
|
60
|
+
response = self._client.call_response(self._BUILD_OPERATION, bag=bag)
|
|
61
|
+
return build_response(DocumentBag, response)
|
|
57
62
|
|
|
58
63
|
def build_signed(
|
|
59
64
|
self,
|
|
60
|
-
input_data: str | dict[str, Any],
|
|
65
|
+
input_data: str | bytes | dict[str, Any],
|
|
61
66
|
*,
|
|
62
67
|
options: dict[str, Any] | None = None,
|
|
63
68
|
caf_xml: str,
|
|
@@ -75,11 +80,11 @@ class DocumentBuilderService:
|
|
|
75
80
|
`IdentifierComponent.caf_faker` y
|
|
76
81
|
`TradingPartiesComponent.mandatario_manager`.
|
|
77
82
|
"""
|
|
78
|
-
bag: dict[str, Any] = {'inputData': input_data}
|
|
83
|
+
bag: dict[str, Any] = {'inputData': encode_input_data(input_data)}
|
|
79
84
|
if options is not None:
|
|
80
85
|
bag['options'] = options
|
|
81
86
|
bag['caf'] = caf_xml
|
|
82
87
|
bag['certificate'] = certificate.to_payload()
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
return DocumentBag
|
|
89
|
+
response = self._client.call_response(self._BUILD_OPERATION, bag=bag)
|
|
90
|
+
return build_response(DocumentBag, response)
|
{libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/dispatcher.py
RENAMED
|
@@ -9,6 +9,7 @@ from collections.abc import Sequence
|
|
|
9
9
|
from typing import Any, cast
|
|
10
10
|
|
|
11
11
|
from ...client import ApiClient
|
|
12
|
+
from ...response_registry import build_response
|
|
12
13
|
from .models import DocumentBag, DocumentEnvelope
|
|
13
14
|
|
|
14
15
|
|
|
@@ -37,11 +38,11 @@ class DocumentDispatcherService:
|
|
|
37
38
|
`emisor` incluidos, no hace falta pasarlos aparte. El sobre
|
|
38
39
|
resultante es lo que se envía al SII (`SiiDteService.send`).
|
|
39
40
|
"""
|
|
40
|
-
|
|
41
|
+
response = self._client.call_response(
|
|
41
42
|
self._CREATE_OPERATION,
|
|
42
43
|
bag=self._bag_payload(bag),
|
|
43
44
|
)
|
|
44
|
-
return DocumentEnvelope
|
|
45
|
+
return build_response(DocumentEnvelope, response)
|
|
45
46
|
|
|
46
47
|
def create_many(self, bags: Sequence[DocumentBag]) -> DocumentEnvelope:
|
|
47
48
|
"""
|
|
@@ -53,11 +54,11 @@ class DocumentDispatcherService:
|
|
|
53
54
|
del PRIMER `DocumentBag` (el sobre en sí también se firma, no
|
|
54
55
|
solo cada documento).
|
|
55
56
|
"""
|
|
56
|
-
|
|
57
|
+
response = self._client.call_response(
|
|
57
58
|
self._CREATE_MANY_OPERATION,
|
|
58
59
|
bags=[self._bag_payload(bag) for bag in bags],
|
|
59
60
|
)
|
|
60
|
-
return DocumentEnvelope
|
|
61
|
+
return build_response(DocumentEnvelope, response)
|
|
61
62
|
|
|
62
63
|
@staticmethod
|
|
63
64
|
def _bag_payload(bag: DocumentBag) -> dict[str, Any]:
|
|
@@ -87,8 +88,10 @@ class DocumentDispatcherService:
|
|
|
87
88
|
más — y en `caratula` los datos de la carátula ya presente en
|
|
88
89
|
ese XML.
|
|
89
90
|
"""
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
response = self._client.call_response(
|
|
92
|
+
self._LOAD_XML_OPERATION, xml=xml_base64
|
|
93
|
+
)
|
|
94
|
+
return build_response(DocumentEnvelope, response)
|
|
92
95
|
|
|
93
96
|
def validate(self, source: str) -> dict[str, Any]:
|
|
94
97
|
"""
|
{libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/loader.py
RENAMED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
from ...client import ApiClient
|
|
9
|
+
from ...response_registry import build_response
|
|
9
10
|
from .models import DocumentBag
|
|
10
11
|
|
|
11
12
|
|
|
@@ -34,5 +35,7 @@ class DocumentLoaderService:
|
|
|
34
35
|
acá, `document`/`document_type`/`document_stamp_base64`/etc.
|
|
35
36
|
son el valor agregado real: los datos ya normalizados.
|
|
36
37
|
"""
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
response = self._client.call_response(
|
|
39
|
+
self._LOAD_XML_OPERATION, xml=xml_base64
|
|
40
|
+
)
|
|
41
|
+
return build_response(DocumentBag, response)
|
{libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/models.py
RENAMED
|
@@ -15,18 +15,25 @@ import base64
|
|
|
15
15
|
from dataclasses import dataclass
|
|
16
16
|
from typing import Any
|
|
17
17
|
|
|
18
|
+
from ...response_registry import api_response
|
|
18
19
|
from ..common import XmlPayloadMixin
|
|
19
20
|
from ..identifier.models import Caf
|
|
20
21
|
from ..trading_parties.models import Certificate
|
|
21
22
|
|
|
23
|
+
_PHP_SUPPORT = (
|
|
24
|
+
'libredte\\lib\\Core\\Package\\Billing\\Component\\Document\\Support'
|
|
25
|
+
)
|
|
22
26
|
|
|
27
|
+
|
|
28
|
+
@api_response(f'{_PHP_SUPPORT}\\DocumentBag')
|
|
23
29
|
@dataclass(frozen=True, slots=True)
|
|
24
30
|
class DocumentBag:
|
|
25
31
|
"""
|
|
26
32
|
Bolsa de un documento tributario.
|
|
27
33
|
|
|
28
|
-
Devuelta por `document.builder::build`/`document.loader::loadXml
|
|
29
|
-
—
|
|
34
|
+
Devuelta por `document.builder::build`/`document.loader::loadXml`/
|
|
35
|
+
`document.parser::parse` — todas en esta misma forma, con los campos
|
|
36
|
+
que correspondan a cuánto se hizo con el documento. `document`
|
|
30
37
|
(`Encabezado`/`Detalle`, con el merge de `libredte_data.extra.dte`
|
|
31
38
|
si se pasó al renderizar) es la vista "de datos" limpia del
|
|
32
39
|
documento — SIN los campos opcionales no usados (se omiten, no
|
|
@@ -66,13 +73,20 @@ class DocumentBag:
|
|
|
66
73
|
(`document_stamp_base64` es el mismo dato, pero como XML) — `None`
|
|
67
74
|
si el documento aún no está timbrado.
|
|
68
75
|
|
|
76
|
+
Una bolsa que solo se parseó (`DocumentParserService`, o cada bolsa de
|
|
77
|
+
un `DocumentBatch`) trae `document_parsed` (los datos en el formato
|
|
78
|
+
DTE del SII, tal como los entregó el parser) y deja en `None` lo que
|
|
79
|
+
requiere construir el documento: `document`, `document_type`, el XML,
|
|
80
|
+
etc.
|
|
81
|
+
|
|
69
82
|
No usa `XmlPayloadMixin`: acá `xml_base64` es una `@property` (el
|
|
70
83
|
documento puede no estar construido), no un campo simple.
|
|
71
84
|
"""
|
|
72
85
|
|
|
73
|
-
document: dict[str, Any]
|
|
86
|
+
document: dict[str, Any] | None
|
|
87
|
+
document_parsed: dict[str, Any] | None
|
|
74
88
|
document_normalized: dict[str, Any] | None
|
|
75
|
-
document_type: dict[str, Any]
|
|
89
|
+
document_type: dict[str, Any] | None
|
|
76
90
|
document_stamp_base64: str | None
|
|
77
91
|
document_extra: dict[str, Any] | None
|
|
78
92
|
document_auth: dict[str, Any] | None
|
|
@@ -116,9 +130,10 @@ class DocumentBag:
|
|
|
116
130
|
def from_api(cls, data: dict[str, Any]) -> DocumentBag:
|
|
117
131
|
"""Construye un `DocumentBag` desde el `data` de la API."""
|
|
118
132
|
return cls(
|
|
119
|
-
document=data
|
|
133
|
+
document=data.get('document'),
|
|
134
|
+
document_parsed=data.get('document_parsed'),
|
|
120
135
|
document_normalized=data.get('document_normalized'),
|
|
121
|
-
document_type=data
|
|
136
|
+
document_type=data.get('document_type'),
|
|
122
137
|
document_stamp_base64=data.get('document_stamp'),
|
|
123
138
|
document_extra=data.get('document_extra'),
|
|
124
139
|
document_auth=data.get('document_auth'),
|
|
@@ -136,6 +151,36 @@ class DocumentBag:
|
|
|
136
151
|
)
|
|
137
152
|
|
|
138
153
|
|
|
154
|
+
@api_response(f'{_PHP_SUPPORT}\\DocumentBatch')
|
|
155
|
+
@dataclass(frozen=True, slots=True)
|
|
156
|
+
class DocumentBatch:
|
|
157
|
+
"""
|
|
158
|
+
Lote de documentos de una emisión masiva, ya parseado.
|
|
159
|
+
|
|
160
|
+
Devuelto por `batch_processor::parse`. `document_bags` trae una bolsa
|
|
161
|
+
(`DocumentBag`) por cada documento del archivo, en el orden del archivo,
|
|
162
|
+
con los datos parseados en `document_parsed` — todavía no se construyó
|
|
163
|
+
ningún documento. No incluye el contenido enviado ni el certificado.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
document_bags: tuple[DocumentBag, ...]
|
|
167
|
+
raw: dict[str, Any]
|
|
168
|
+
|
|
169
|
+
@classmethod
|
|
170
|
+
def from_api(cls, data: dict[str, Any]) -> DocumentBatch:
|
|
171
|
+
"""Construye un `DocumentBatch` desde el `data` de la API."""
|
|
172
|
+
return cls(
|
|
173
|
+
document_bags=tuple(
|
|
174
|
+
DocumentBag.from_api(item)
|
|
175
|
+
for item in data.get('document_bags') or []
|
|
176
|
+
),
|
|
177
|
+
raw=data,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@api_response(
|
|
182
|
+
'libredte\\lib\\Core\\Package\\Billing\\Component\\Document\\Support\\DocumentEnvelope',
|
|
183
|
+
)
|
|
139
184
|
@dataclass(frozen=True, slots=True)
|
|
140
185
|
class DocumentEnvelope(XmlPayloadMixin):
|
|
141
186
|
"""
|
|
@@ -258,6 +303,9 @@ class Example:
|
|
|
258
303
|
)
|
|
259
304
|
|
|
260
305
|
|
|
306
|
+
@api_response(
|
|
307
|
+
'libredte\\lib\\Core\\Package\\System\\Component\\Rendering\\Support\\RenderResult',
|
|
308
|
+
)
|
|
261
309
|
@dataclass(frozen=True, slots=True)
|
|
262
310
|
class RenderResult:
|
|
263
311
|
"""
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Copyright (C) 2026 LibreDTE <https://www.libredte.cl>
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
"""Servicio para `billing.document.parser`."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from ...client import ApiClient
|
|
11
|
+
from ...response_registry import build_response
|
|
12
|
+
from ..common import encode_input_data
|
|
13
|
+
from .models import DocumentBag
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DocumentParserService:
|
|
17
|
+
"""
|
|
18
|
+
Parsea los datos de entrada de un documento (`billing.document.parser`).
|
|
19
|
+
|
|
20
|
+
Solo transforma los datos al formato DTE del SII: no normaliza ni
|
|
21
|
+
construye el documento, no necesita CAF ni certificado.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
_PARSE_OPERATION = 'billing.document.parser::parse'
|
|
25
|
+
|
|
26
|
+
def __init__(self, client: ApiClient) -> None:
|
|
27
|
+
"""Guarda el `ApiClient` compartido usado para llamar a la API."""
|
|
28
|
+
self._client = client
|
|
29
|
+
|
|
30
|
+
def parse(
|
|
31
|
+
self,
|
|
32
|
+
input_data: str | bytes | dict[str, Any],
|
|
33
|
+
*,
|
|
34
|
+
strategy: str | None = None,
|
|
35
|
+
) -> DocumentBag:
|
|
36
|
+
"""
|
|
37
|
+
Parsea `input_data` y entrega la bolsa con los datos parseados.
|
|
38
|
+
|
|
39
|
+
`input_data` es el documento en el formato DTE del SII como `dict`,
|
|
40
|
+
o datos en otro formato (XML, YAML, un formulario, etc.) como `bytes`
|
|
41
|
+
o `str`. El contenido de un archivo se debe pasar como `bytes` (leído
|
|
42
|
+
en modo `rb`): se envía sin alterar su codificación. Un `str` ya es
|
|
43
|
+
texto decodificado y se envía en UTF-8.
|
|
44
|
+
|
|
45
|
+
`strategy` es la estrategia de parseo (ej. `'default.xml'`,
|
|
46
|
+
`'form.lite'`); sin ella la API asume `default.json`.
|
|
47
|
+
|
|
48
|
+
El resultado es una `DocumentBag` con `document_parsed`; `document`,
|
|
49
|
+
`document_type` y el XML quedan en `None`.
|
|
50
|
+
"""
|
|
51
|
+
bag: dict[str, Any] = {'inputData': encode_input_data(input_data)}
|
|
52
|
+
if strategy is not None:
|
|
53
|
+
bag['options'] = {'parser': {'strategy': strategy}}
|
|
54
|
+
|
|
55
|
+
return build_response(
|
|
56
|
+
DocumentBag,
|
|
57
|
+
self._client.call_response(self._PARSE_OPERATION, bag=bag),
|
|
58
|
+
)
|
{libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/document/renderer.py
RENAMED
|
@@ -8,6 +8,7 @@ from __future__ import annotations
|
|
|
8
8
|
from typing import Any
|
|
9
9
|
|
|
10
10
|
from ...client import ApiClient
|
|
11
|
+
from ...response_registry import build_response
|
|
11
12
|
from .models import RenderResult
|
|
12
13
|
|
|
13
14
|
|
|
@@ -68,5 +69,5 @@ class DocumentRendererService:
|
|
|
68
69
|
if libredte_data is not None:
|
|
69
70
|
bag['libredteData'] = libredte_data
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
return RenderResult
|
|
72
|
+
response = self._client.call_response(self._RENDER_OPERATION, bag=bag)
|
|
73
|
+
return build_response(RenderResult, response)
|
|
@@ -8,6 +8,7 @@ from __future__ import annotations
|
|
|
8
8
|
from typing import Any, cast
|
|
9
9
|
|
|
10
10
|
from ...client import ApiClient
|
|
11
|
+
from ...response_registry import build_response
|
|
11
12
|
from ..trading_parties.models import Certificate
|
|
12
13
|
from .models import EnvioRecibos, RespuestaEnvio
|
|
13
14
|
|
|
@@ -53,7 +54,7 @@ class DocumentResponseService:
|
|
|
53
54
|
`MntTotal`/`Recinto`, y opcionalmente `RutFirma`/`Declaracion`).
|
|
54
55
|
`caratula` trae `RutResponde`/`RutRecibe`.
|
|
55
56
|
"""
|
|
56
|
-
|
|
57
|
+
response = self._client.call_response(
|
|
57
58
|
self._BUILD_ENVIO_RECIBOS_OPERATION,
|
|
58
59
|
bag={
|
|
59
60
|
'tipo': 'envio_recibos',
|
|
@@ -62,7 +63,7 @@ class DocumentResponseService:
|
|
|
62
63
|
'certificate': certificate.to_payload(),
|
|
63
64
|
},
|
|
64
65
|
)
|
|
65
|
-
return EnvioRecibos
|
|
66
|
+
return build_response(EnvioRecibos, response)
|
|
66
67
|
|
|
67
68
|
def build_respuesta_envio(
|
|
68
69
|
self,
|
|
@@ -78,7 +79,7 @@ class DocumentResponseService:
|
|
|
78
79
|
cual el formato SII. `caratula` trae `RutResponde`/`RutRecibe`/
|
|
79
80
|
`IdRespuesta`.
|
|
80
81
|
"""
|
|
81
|
-
|
|
82
|
+
response = self._client.call_response(
|
|
82
83
|
self._BUILD_RESPUESTA_ENVIO_OPERATION,
|
|
83
84
|
bag={
|
|
84
85
|
'tipo': 'respuesta_envio',
|
|
@@ -87,7 +88,7 @@ class DocumentResponseService:
|
|
|
87
88
|
'certificate': certificate.to_payload(),
|
|
88
89
|
},
|
|
89
90
|
)
|
|
90
|
-
return RespuestaEnvio
|
|
91
|
+
return build_response(RespuestaEnvio, response)
|
|
91
92
|
|
|
92
93
|
def validate_schema(self, source: str) -> dict[str, Any]:
|
|
93
94
|
"""
|
{libredte_lib_sdk-0.5.2 → libredte_lib_sdk-0.6.0}/libredte_lib_sdk/billing/exchange/models.py
RENAMED
|
@@ -8,9 +8,13 @@ from __future__ import annotations
|
|
|
8
8
|
from dataclasses import dataclass
|
|
9
9
|
from typing import Any
|
|
10
10
|
|
|
11
|
+
from ...response_registry import api_response
|
|
11
12
|
from ..common import XmlPayloadMixin
|
|
12
13
|
|
|
13
14
|
|
|
15
|
+
@api_response(
|
|
16
|
+
'libredte\\lib\\Core\\Package\\Billing\\Component\\Exchange\\Entity\\EnvioRecibos',
|
|
17
|
+
)
|
|
14
18
|
@dataclass(frozen=True, slots=True)
|
|
15
19
|
class EnvioRecibos(XmlPayloadMixin):
|
|
16
20
|
"""
|
|
@@ -33,6 +37,9 @@ class EnvioRecibos(XmlPayloadMixin):
|
|
|
33
37
|
)
|
|
34
38
|
|
|
35
39
|
|
|
40
|
+
@api_response(
|
|
41
|
+
'libredte\\lib\\Core\\Package\\Billing\\Component\\Exchange\\Entity\\RespuestaEnvio',
|
|
42
|
+
)
|
|
36
43
|
@dataclass(frozen=True, slots=True)
|
|
37
44
|
class RespuestaEnvio(XmlPayloadMixin):
|
|
38
45
|
"""
|