From b59925d3e29eac218335cb05f69d51a4ad11770d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Larra=C3=ADn?= Date: Sat, 11 Apr 2020 21:53:37 -0400 Subject: [PATCH 1/3] dte.data_models.DteDataL2: make some fields optional Fields `emisor_razon_social` and `receptor_razon_social` are now optional. --- cl_sii/dte/data_models.py | 18 ++++++++++-------- tests/test_dte_data_models.py | 19 ++++++------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/cl_sii/dte/data_models.py b/cl_sii/dte/data_models.py index be44f07a..b93c0775 100644 --- a/cl_sii/dte/data_models.py +++ b/cl_sii/dte/data_models.py @@ -347,12 +347,12 @@ class DteDataL2(DteDataL1): # fields ########################################################################### - emisor_razon_social: str = dc_field() + emisor_razon_social: Optional[str] = dc_field() """ "Razón social" (legal name) of the "emisor" of the DTE. """ - receptor_razon_social: str = dc_field() + receptor_razon_social: Optional[str] = dc_field() """ "Razón social" (legal name) of the "receptor" of the DTE. """ @@ -405,13 +405,15 @@ def __post_init__(self) -> None: """ super().__post_init__() - if not isinstance(self.emisor_razon_social, str): - raise TypeError("Inappropriate type of 'emisor_razon_social'.") - validate_contribuyente_razon_social(self.emisor_razon_social) + if self.emisor_razon_social is not None: + if not isinstance(self.emisor_razon_social, str): + raise TypeError("Inappropriate type of 'emisor_razon_social'.") + validate_contribuyente_razon_social(self.emisor_razon_social) - if not isinstance(self.receptor_razon_social, str): - raise TypeError("Inappropriate type of 'receptor_razon_social'.") - validate_contribuyente_razon_social(self.receptor_razon_social) + if self.receptor_razon_social is not None: + if not isinstance(self.receptor_razon_social, str): + raise TypeError("Inappropriate type of 'receptor_razon_social'.") + validate_contribuyente_razon_social(self.receptor_razon_social) if self.fecha_vencimiento_date is not None: if not isinstance(self.fecha_vencimiento_date, date): diff --git a/tests/test_dte_data_models.py b/tests/test_dte_data_models.py index 2af47153..c79702bd 100644 --- a/tests/test_dte_data_models.py +++ b/tests/test_dte_data_models.py @@ -238,19 +238,12 @@ def test_init_fail_razon_social_empty(self) -> None: ) self.assertEqual(cm.exception.args, ("Value must not be empty.", )) - def test_init_fail_razon_social_none(self) -> None: - with self.assertRaises(TypeError) as cm: - dataclasses.replace( - self.dte_l2_1, - emisor_razon_social=None, - ) - self.assertEqual(cm.exception.args, ("Inappropriate type of 'emisor_razon_social'.", )) - with self.assertRaises(TypeError) as cm: - dataclasses.replace( - self.dte_l2_1, - receptor_razon_social=None, - ) - self.assertEqual(cm.exception.args, ("Inappropriate type of 'receptor_razon_social'.", )) + def test_init_ok_razon_social_none(self) -> None: + _ = dataclasses.replace( + self.dte_l2_1, + emisor_razon_social=None, + receptor_razon_social=None, + ) def test_init_fail_regression_signature_value_bytes_with_x20(self) -> None: bytes_value_with_x20_as_base64 = 'IN2pkDBxqDnGl4Pfvboi' From 1f214634f5a694d336bd028fffcfefe5da5cfa21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Larra=C3=ADn?= Date: Mon, 13 Apr 2020 20:24:22 -0400 Subject: [PATCH 2/3] rcv.data_models: make unnecessary fields optional For subclasses of `RcvDetalleEntry` only one of these fields is necessary, which depends on the specific class. Later on the optional field will be removed; this is the first step for achieving that without breaking other people's code. - `emisor_razon_social` - `receptor_razon_social` --- cl_sii/rcv/data_models.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/cl_sii/rcv/data_models.py b/cl_sii/rcv/data_models.py index 3bf416d4..4c68fc2c 100644 --- a/cl_sii/rcv/data_models.py +++ b/cl_sii/rcv/data_models.py @@ -224,7 +224,7 @@ class RvDetalleEntry(RcvDetalleEntry): RCV_KIND = RcvKind.VENTAS RC_ESTADO_CONTABLE = None - emisor_razon_social: str = dc_field() + emisor_razon_social: Optional[str] = dc_field() """ "Razón social" (legal name) of the "emisor" of the "documento". """ @@ -244,9 +244,10 @@ class RvDetalleEntry(RcvDetalleEntry): def __post_init__(self) -> None: super().__post_init__() - if not isinstance(self.emisor_razon_social, str): - raise TypeError("Inappropriate type of 'emisor_razon_social'.") - cl_sii.dte.data_models.validate_contribuyente_razon_social(self.emisor_razon_social) + if self.emisor_razon_social is not None: + if not isinstance(self.emisor_razon_social, str): + raise TypeError("Inappropriate type of 'emisor_razon_social'.") + cl_sii.dte.data_models.validate_contribuyente_razon_social(self.emisor_razon_social) if not isinstance(self.receptor_razon_social, str): raise TypeError("Inappropriate type of 'receptor_razon_social'.") @@ -280,7 +281,7 @@ class RcRegistroDetalleEntry(RcvDetalleEntry): # TODO: docstring # TODO: can it be None? What happens for those "tipo docto" that do not have a receptor? - receptor_razon_social: str = dc_field() + receptor_razon_social: Optional[str] = dc_field() # TODO: docstring # note: must be timezone-aware. @@ -293,9 +294,10 @@ def __post_init__(self) -> None: raise TypeError("Inappropriate type of 'emisor_razon_social'.") cl_sii.dte.data_models.validate_contribuyente_razon_social(self.emisor_razon_social) - if not isinstance(self.receptor_razon_social, str): - raise TypeError("Inappropriate type of 'receptor_razon_social'.") - cl_sii.dte.data_models.validate_contribuyente_razon_social(self.receptor_razon_social) + if self.receptor_razon_social is not None: + if not isinstance(self.receptor_razon_social, str): + raise TypeError("Inappropriate type of 'receptor_razon_social'.") + cl_sii.dte.data_models.validate_contribuyente_razon_social(self.receptor_razon_social) if self.fecha_acuse_dt is not None: if not isinstance(self.fecha_acuse_dt, datetime): @@ -331,7 +333,7 @@ class RcReclamadoDetalleEntry(RcvDetalleEntry): # TODO: docstring # TODO: can it be None? What happens for those "tipo docto" that do not have a receptor? - receptor_razon_social: str = dc_field() + receptor_razon_social: Optional[str] = dc_field() # TODO: docstring # note: must be timezone-aware. @@ -344,9 +346,10 @@ def __post_init__(self) -> None: raise TypeError("Inappropriate type of 'emisor_razon_social'.") cl_sii.dte.data_models.validate_contribuyente_razon_social(self.emisor_razon_social) - if not isinstance(self.receptor_razon_social, str): - raise TypeError("Inappropriate type of 'receptor_razon_social'.") - cl_sii.dte.data_models.validate_contribuyente_razon_social(self.receptor_razon_social) + if self.receptor_razon_social is not None: + if not isinstance(self.receptor_razon_social, str): + raise TypeError("Inappropriate type of 'receptor_razon_social'.") + cl_sii.dte.data_models.validate_contribuyente_razon_social(self.receptor_razon_social) if self.fecha_reclamo_dt is not None: if not isinstance(self.fecha_reclamo_dt, datetime): @@ -371,7 +374,7 @@ class RcPendienteDetalleEntry(RcvDetalleEntry): # TODO: docstring # TODO: can it be None? What happens for those "tipo docto" that do not have a receptor? - receptor_razon_social: str = dc_field() + receptor_razon_social: Optional[str] = dc_field() def __post_init__(self) -> None: super().__post_init__() @@ -380,6 +383,7 @@ def __post_init__(self) -> None: raise TypeError("Inappropriate type of 'emisor_razon_social'.") cl_sii.dte.data_models.validate_contribuyente_razon_social(self.emisor_razon_social) - if not isinstance(self.receptor_razon_social, str): - raise TypeError("Inappropriate type of 'receptor_razon_social'.") - cl_sii.dte.data_models.validate_contribuyente_razon_social(self.receptor_razon_social) + if self.receptor_razon_social is not None: + if not isinstance(self.receptor_razon_social, str): + raise TypeError("Inappropriate type of 'receptor_razon_social'.") + cl_sii.dte.data_models.validate_contribuyente_razon_social(self.receptor_razon_social) From b113594013bd4c431adcbab5223ab121cb182a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Germ=C3=A1n=20Larra=C3=ADn?= Date: Tue, 14 Apr 2020 10:42:57 -0400 Subject: [PATCH 3/3] =?UTF-8?q?Bump=20version:=200.10.0.a1=20=E2=86=92=200?= =?UTF-8?q?.10.0.a2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- cl_sii/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index e840a9c8..d439e210 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.10.0.a1 +current_version = 0.10.0.a2 commit = True tag = True diff --git a/cl_sii/__init__.py b/cl_sii/__init__.py index d13abab4..91c4a55c 100644 --- a/cl_sii/__init__.py +++ b/cl_sii/__init__.py @@ -5,4 +5,4 @@ """ -__version__ = '0.10.0.a1' +__version__ = '0.10.0.a2'