def test_truncate_fecha_cesion_dt_to_minutes(self) -> None:
        self._set_obj_1()

        obj = self.obj_1
        expected_fecha_cesion_dt = datetime.fromisoformat(
            '2020-12-31T22:33-03:00')
        self.assertEqual(expected_fecha_cesion_dt.second, 0)
        self.assertEqual(expected_fecha_cesion_dt.microsecond, 0)

        obj_with_microseconds = dataclasses.replace(
            obj,
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2020, 12, 31, 22, 33, 44, 555555),
                tz=CesionAltNaturalKey.DATETIME_FIELDS_TZ,
            ),
        )
        obj_with_datetime_truncated = dataclasses.replace(
            obj,
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2020, 12, 31, 22, 33),
                tz=CesionAltNaturalKey.DATETIME_FIELDS_TZ,
            ),
        )
        self.assertEqual(obj_with_microseconds.fecha_cesion_dt,
                         expected_fecha_cesion_dt)
        self.assertEqual(obj_with_datetime_truncated.fecha_cesion_dt,
                         expected_fecha_cesion_dt)
        self.assertEqual(obj_with_microseconds, obj_with_datetime_truncated)
    def test_alt_natural_key(self) -> None:
        self._set_obj_1()
        self._set_obj_2()

        obj = self.obj_1
        expected_output = CesionAltNaturalKey(
            dte_key=DteNaturalKey(
                emisor_rut=Rut('76354771-K'),
                tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
                folio=170,
            ),
            cedente_rut=Rut('76354771-K'),
            cesionario_rut=Rut('76389992-6'),
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 1, 10, 22),
                tz=CesionAltNaturalKey.DATETIME_FIELDS_TZ,
            ),
        )
        self.assertEqual(obj.alt_natural_key, expected_output)

        obj = self.obj_2
        expected_output = CesionAltNaturalKey(
            dte_key=DteNaturalKey(
                emisor_rut=Rut('76354771-K'),
                tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
                folio=170,
            ),
            cedente_rut=Rut('76389992-6'),
            cesionario_rut=Rut('76598556-0'),
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 5, 12, 57),
                tz=CesionAltNaturalKey.DATETIME_FIELDS_TZ,
            ),
        )
        self.assertEqual(obj.alt_natural_key, expected_output)
    def test_as_cesion_l2(self) -> None:
        self._set_obj_1()

        obj = self.obj_1
        expected_output = CesionL2(
            dte_key=DteNaturalKey(
                emisor_rut=Rut('76354771-K'),
                tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
                folio=170,
            ),
            seq=2,
            cedente_rut=Rut('76389992-6'),
            cesionario_rut=Rut('76598556-0'),
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 5, 12, 57, 32),
                tz=CesionL2.DATETIME_FIELDS_TZ,
            ),
            monto_cedido=2996301,
            fecha_firma_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 5, 12, 57, 32),
                tz=CesionL2.DATETIME_FIELDS_TZ,
            ),
            dte_receptor_rut=Rut('96790240-3'),
            dte_fecha_emision=date(2019, 4, 1),
            dte_monto_total=2996301,
            fecha_ultimo_vencimiento=date(2019, 5, 1),
            cedente_razon_social='ST CAPITAL S.A.',
            cedente_email='*****@*****.**',
            cesionario_razon_social=
            'Fondo de Inversión Privado Deuda y Facturas',
            cesionario_email='*****@*****.**',
            dte_emisor_razon_social='INGENIERIA ENACON SPA',
            dte_receptor_razon_social='MINERA LOS PELAMBRES',
            dte_deudor_email=None,
            cedente_declaracion_jurada=
            ('Se declara bajo juramento que ST CAPITAL S.A., RUT 76389992-6 ha puesto '
             'a disposicion del cesionario Fondo de Inversión Privado Deuda y Facturas, '
             'RUT 76598556-0, el documento validamente emitido al deudor MINERA LOS '
             'PELAMBRES, RUT 96790240-3.'),
            dte_fecha_vencimiento=None,
            contacto_nombre='ST Capital Servicios Financieros',
            contacto_telefono=None,
            contacto_email='*****@*****.**',
        )
        obj_cesion_l2 = obj.as_cesion_l2()
        self.assertEqual(obj_cesion_l2, expected_output)
        self.assertEqual(obj_cesion_l2.natural_key, obj.natural_key)
        self.assertEqual(obj_cesion_l2.alt_natural_key, obj.alt_natural_key)
        self.assertEqual(obj_cesion_l2.dte_key, obj.dte.natural_key)
    def test_parse_dte_xml_ok_1b(self) -> None:
        xml_doc = xml_utils.parse_untrusted_xml(self.dte_clean_xml_1b_xml_bytes)

        parsed_dte = parse_dte_xml(xml_doc)
        self.assertDictEqual(
            dict(parsed_dte.as_dict()),
            dict(
                emisor_rut=Rut('76354771-K'),
                tipo_dte=cl_sii.dte.constants.TipoDteEnum.FACTURA_ELECTRONICA,
                folio=170,
                fecha_emision_date=date(2019, 4, 1),
                receptor_rut=Rut('96790240-3'),
                monto_total=2996301,
                emisor_razon_social='INGENIERIA ENACON SPA',
                receptor_razon_social='MINERA LOS PELAMBRES',
                fecha_vencimiento_date=None,
                firma_documento_dt=tz_utils.convert_naive_dt_to_tz_aware(
                    dt=datetime(2019, 4, 1, 1, 36, 40),
                    tz=DteDataL2.DATETIME_FIELDS_TZ),
                signature_value=self._TEST_DTE_1_SIGNATURE_VALUE,
                signature_x509_cert_der=self.dte_clean_xml_1_cert_der,
                emisor_giro='Ingenieria y Construccion',
                emisor_email=None,
                receptor_email=None,
            ))
    def test_parse_dte_xml_ok_3(self) -> None:
        xml_doc = xml_utils.parse_untrusted_xml(self.dte_clean_xml_3_xml_bytes)

        parsed_dte = parse_dte_xml(xml_doc)
        self.assertDictEqual(
            dict(parsed_dte.as_dict()),
            dict(
                emisor_rut=Rut('60910000-1'),
                tipo_dte=cl_sii.dte.constants.TipoDteEnum.FACTURA_ELECTRONICA,
                folio=2336600,
                fecha_emision_date=date(2019, 8, 8),
                receptor_rut=Rut('76555835-2'),
                monto_total=10642,
                emisor_razon_social='Universidad de Chile',
                receptor_razon_social='FYNPAL SPA',
                fecha_vencimiento_date=date(2019, 8, 8),
                firma_documento_dt=tz_utils.convert_naive_dt_to_tz_aware(
                    dt=datetime(2019, 8, 9, 9, 41, 9),
                    tz=DteDataL2.DATETIME_FIELDS_TZ),
                signature_value=self._TEST_DTE_3_SIGNATURE_VALUE,
                signature_x509_cert_der=self.dte_clean_xml_3_cert_der,
                emisor_giro=
                'Corporación Educacional y Servicios                 Profesionales',
                emisor_email=None,
                receptor_email=None,
            ))
    def test_parse_dte_xml_ok_2(self) -> None:
        xml_doc = xml_utils.parse_untrusted_xml(self.dte_clean_xml_2_xml_bytes)

        parsed_dte = parse_dte_xml(xml_doc)
        self.assertDictEqual(
            dict(parsed_dte.as_dict()),
            dict(
                emisor_rut=Rut('76399752-9'),
                tipo_dte=cl_sii.dte.constants.TipoDteEnum.FACTURA_ELECTRONICA,
                folio=25568,
                fecha_emision_date=date(2019, 3, 29),
                receptor_rut=Rut('96874030-K'),
                monto_total=230992,
                emisor_razon_social='COMERCIALIZADORA INNOVA MOBEL SPA',
                receptor_razon_social='EMPRESAS LA POLAR S.A.',
                fecha_vencimiento_date=None,
                firma_documento_dt=tz_utils.convert_naive_dt_to_tz_aware(
                    dt=datetime(2019, 3, 28, 13, 59, 52),
                    tz=DteDataL2.DATETIME_FIELDS_TZ),
                signature_value=self._TEST_DTE_2_SIGNATURE_VALUE,
                signature_x509_cert_der=self.dte_clean_xml_2_cert_der,
                emisor_giro='COMERCIALIZACION DE PRODUCTOS PARA EL HOGAR',
                emisor_email='*****@*****.**',
                receptor_email=None,
            ))
    def _set_obj_1(self) -> None:
        obj_dte_natural_key = DteNaturalKey(
            emisor_rut=Rut('76354771-K'),
            tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
            folio=170,
        )

        obj = CesionL1(
            dte_key=obj_dte_natural_key,
            seq=32,
            cedente_rut=Rut('76389992-6'),
            cesionario_rut=Rut('76598556-0'),
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 5, 12, 57, 32),
                tz=CesionL1.DATETIME_FIELDS_TZ,
            ),
            monto_cedido=2996301,
            fecha_ultimo_vencimiento=date(2019, 5, 1),
            dte_fecha_emision=date(2019, 4, 1),
            dte_receptor_rut=Rut('96790240-3'),
            dte_monto_total=2996301,
        )
        self.assertIsInstance(obj, CesionL1)

        self.obj_1_dte_natural_key = obj_dte_natural_key
        self.obj_1 = obj
Beispiel #8
0
    def test_as_cesion_l2_ok_1(self) -> None:
        obj = CesionesPeriodoEntry(**self.valid_kwargs)
        expected_output = CesionL2(
            dte_key=cl_sii.dte.data_models.DteNaturalKey(
                emisor_rut=Rut('51532520-4'),
                tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
                folio=3608460,
            ),
            seq=None,
            cedente_rut=Rut('51532520-4'),
            cesionario_rut=Rut('96667560-8'),
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 3, 7, 13, 32),
                tz=CesionL2.DATETIME_FIELDS_TZ,
            ),
            monto_cedido=256357,
            dte_receptor_rut=Rut('75320502-0'),
            dte_fecha_emision=date(2019, 2, 11),
            dte_monto_total=256357,
            fecha_ultimo_vencimiento=date(2019, 4, 12),
            cedente_razon_social='MI CAMPITO SA',
            cedente_email='*****@*****.**',
            cesionario_razon_social='POBRES SERVICIOS FINANCIEROS S.A.',
            cesionario_email='[email protected],[email protected]',
        )
        obj_cesion_l2 = obj.as_cesion_l2()
        self.assertEqual(obj_cesion_l2, expected_output)

        self.assertIsNone(obj_cesion_l2.natural_key)
        self.assertEqual(obj_cesion_l2.alt_natural_key.dte_key.emisor_rut, obj.dte_vendedor_rut)
        self.assertEqual(obj_cesion_l2.alt_natural_key.cedente_rut, obj.cedente_rut)
        self.assertEqual(obj_cesion_l2.alt_natural_key.cesionario_rut, obj.cesionario_rut)
        self.assertEqual(obj_cesion_l2.alt_natural_key.fecha_cesion_dt, obj.fecha_cesion_dt)

        self.assertEqual(obj_cesion_l2.dte_receptor_rut, obj.dte_deudor_rut)
    def postprocess(self, data: dict) -> dict:
        # >>> data['fecha_recepcion_dt'].isoformat()
        # '2018-10-23T01:54:13'
        data['fecha_recepcion_dt'] = tz_utils.convert_naive_dt_to_tz_aware(
            dt=data['fecha_recepcion_dt'], tz=self.FIELD_FECHA_RECEPCION_DT_TZ)
        # >>> data['fecha_recepcion_dt'].isoformat()
        # '2018-10-23T01:54:13-03:00'
        # >>> data['fecha_recepcion_dt'].astimezone(pytz.UTC).isoformat()
        # '2018-10-23T04:54:13+00:00'

        if data['fecha_reclamo_dt']:
            data['fecha_reclamo_dt'] = tz_utils.convert_naive_dt_to_tz_aware(
                dt=data['fecha_reclamo_dt'], tz=self.FIELD_FECHA_RECLAMO_DT_TZ)

        # note: to express this value in another timezone (but the value does not change), do
        #   `dt_obj.astimezone(pytz.timezone('some timezone'))`

        return data
 def test_as_dte_data_l2(self) -> None:
     self.assertEqual(
         self.dte_xml_data_1.as_dte_data_l2(),
         DteDataL2(
             emisor_rut=Rut('76354771-K'),
             tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
             folio=170,
             fecha_emision_date=date(2019, 4, 1),
             receptor_rut=Rut('96790240-3'),
             monto_total=2996301,
             emisor_razon_social='INGENIERIA ENACON SPA',
             receptor_razon_social='MINERA LOS PELAMBRES',
             fecha_vencimiento_date=None,
             firma_documento_dt=tz_utils.convert_naive_dt_to_tz_aware(
                 dt=datetime(2019, 4, 1, 1, 36, 40),
                 tz=DteXmlData.DATETIME_FIELDS_TZ),
             signature_value=self.dte_1_xml_signature_value,
             signature_x509_cert_der=self.dte_1_xml_cert_der,
             emisor_giro='Ingenieria y Construccion',
             emisor_email='*****@*****.**',
             receptor_email=None,
         ))
     self.assertEqual(
         self.dte_xml_data_2.as_dte_data_l2(),
         DteDataL2(
             emisor_rut=Rut('60910000-1'),
             tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
             folio=2336600,
             fecha_emision_date=date(2019, 8, 8),
             receptor_rut=Rut('76555835-2'),
             monto_total=10642,
             emisor_razon_social='Universidad de Chile',
             receptor_razon_social='FYNPAL SPA',
             fecha_vencimiento_date=date(2019, 8, 8),
             firma_documento_dt=tz_utils.convert_naive_dt_to_tz_aware(
                 dt=datetime(2019, 8, 9, 9, 41, 9),
                 tz=DteXmlData.DATETIME_FIELDS_TZ),
             signature_value=self.dte_2_xml_signature_value,
             signature_x509_cert_der=self.dte_2_xml_cert_der,
             emisor_giro=
             'Corporación Educacional y Servicios                 Profesionales',
             emisor_email=None,
             receptor_email=None,
         ))
    def test_validate_dt_tz_tzinfo_zone_attribute_check(self) -> None:
        # Time zone: UTC. Source: Pytz:
        tzinfo_utc_pytz = TZ_UTC
        dt_with_tzinfo_utc_pytz = convert_naive_dt_to_tz_aware(
            datetime.datetime(2021, 1, 6, 15, 21),
            tzinfo_utc_pytz,
        )

        # Time zone: UTC. Source: Python Standard Library:
        tzinfo_utc_stdlib = datetime.timezone.utc
        dt_with_tzinfo_utc_stdlib = datetime.datetime.fromisoformat(
            '2021-01-06T15:04+00:00')

        # Time zone: Not UTC. Source: Pytz:
        tzinfo_not_utc_pytz = _TZ_CL_SANTIAGO
        dt_with_tzinfo_not_utc_pytz = convert_naive_dt_to_tz_aware(
            datetime.datetime(2021, 1, 6, 15, 21),
            tzinfo_not_utc_pytz,
        )

        # Time zone: Not UTC. Source: Python Standard Library:
        tzinfo_not_utc_stdlib = datetime.timezone(
            datetime.timedelta(days=-1, seconds=75600))
        dt_with_tzinfo_not_utc_stdlib = datetime.datetime.fromisoformat(
            '2021-01-06T15:04-03:00')

        # Test datetimes with UTC time zone:
        expected_error_message = re.compile(
            r"^Object datetime.timezone.utc must have 'zone' attribute.$")
        with self.assertRaisesRegex(AssertionError, expected_error_message):
            validate_dt_tz(dt_with_tzinfo_utc_pytz, tzinfo_utc_stdlib)
        with self.assertRaisesRegex(AssertionError, expected_error_message):
            validate_dt_tz(dt_with_tzinfo_utc_stdlib, tzinfo_utc_pytz)

        # Test datetimes with non-UTC time zone:
        expected_error_message = re.compile(
            r"^Object"
            r" datetime.timezone\(datetime.timedelta\(days=-1, seconds=75600\)\)"
            r" must have 'zone' attribute.$")
        with self.assertRaisesRegex(AssertionError, expected_error_message):
            validate_dt_tz(dt_with_tzinfo_not_utc_pytz,
                           tzinfo_not_utc_stdlib)  # type: ignore
        with self.assertRaisesRegex(AssertionError, expected_error_message):
            validate_dt_tz(dt_with_tzinfo_not_utc_stdlib, tzinfo_not_utc_pytz)
    def test_validate_datetime_tz(self) -> None:
        self._set_obj_1()

        obj = self.obj_1

        # Test TZ-awareness:

        expected_validation_errors = [
            {
                'loc': ('fecha_firma_dt', ),
                'msg': 'Value must be a timezone-aware datetime object.',
                'type': 'value_error',
            },
        ]

        with self.assertRaises(pydantic.ValidationError) as assert_raises_cm:
            dataclasses.replace(
                obj,
                fecha_firma_dt=datetime(2019, 4, 5, 12, 57, 32),
            )

        validation_errors = assert_raises_cm.exception.errors()
        self.assertEqual(len(validation_errors),
                         len(expected_validation_errors))
        for expected_validation_error in expected_validation_errors:
            self.assertIn(expected_validation_error, validation_errors)

        # Test TZ-value:

        expected_validation_errors = [
            {
                'loc': ('fecha_firma_dt', ),
                'msg':
                '('
                '''"Timezone of datetime value must be 'America/Santiago'.",'''
                ' datetime.datetime(2019, 4, 5, 12, 57, 32, tzinfo=<UTC>)'
                ')',
                'type':
                'value_error',
            },
        ]

        with self.assertRaises(pydantic.ValidationError) as assert_raises_cm:
            dataclasses.replace(
                obj,
                fecha_firma_dt=tz_utils.convert_naive_dt_to_tz_aware(
                    dt=datetime(2019, 4, 5, 12, 57, 32),
                    tz=tz_utils.TZ_UTC,
                ),
            )

        validation_errors = assert_raises_cm.exception.errors()
        self.assertEqual(len(validation_errors),
                         len(expected_validation_errors))
        for expected_validation_error in expected_validation_errors:
            self.assertIn(expected_validation_error, validation_errors)
Beispiel #13
0
    def validate_datetime(cls, v: object) -> object:
        if isinstance(v, str):
            v = datetime.fromisoformat(v)

        if isinstance(v, datetime):
            v = tz_utils.convert_naive_dt_to_tz_aware(
                dt=v,
                tz=data_models_aec.AecXml.DATETIME_FIELDS_TZ,
            )
        return v
Beispiel #14
0
    def postprocess(self, data: dict) -> dict:
        # >>> data['fecha_recepcion_dt'].isoformat()
        # '2018-10-23T01:54:13'
        data['fecha_recepcion_dt'] = tz_utils.convert_naive_dt_to_tz_aware(
            dt=data['fecha_recepcion_dt'], tz=self.FIELD_FECHA_RECEPCION_DT_TZ)
        # >>> data['fecha_recepcion_dt'].isoformat()
        # '2018-10-23T01:54:13-03:00'
        # >>> data['fecha_recepcion_dt'].astimezone(pytz.UTC).isoformat()
        # '2018-10-23T04:54:13+00:00'

        if data['fecha_acuse_dt']:
            data['fecha_acuse_dt'] = tz_utils.convert_naive_dt_to_tz_aware(
                dt=data['fecha_acuse_dt'], tz=self.FIELD_FECHA_ACUSE_DT_TZ)

        # note: to express this value in another timezone (but the value does not change), do
        #   `dt_obj.astimezone(pytz.timezone('some timezone'))`

        # Remove leading and trailing whitespace.
        data['emisor_razon_social'] = data['emisor_razon_social'].strip()

        return data
    def _set_obj_1(self) -> None:
        obj_dte_natural_key = DteNaturalKey(
            emisor_rut=Rut('76354771-K'),
            tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
            folio=170,
        )

        obj = CesionAltNaturalKey(
            dte_key=obj_dte_natural_key,
            cedente_rut=Rut('76389992-6'),
            cesionario_rut=Rut('76598556-0'),
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 5, 12, 57),
                tz=CesionAltNaturalKey.DATETIME_FIELDS_TZ,
            ),
        )
        self.assertIsInstance(obj, CesionAltNaturalKey)

        self.obj_1_dte_natural_key = obj_dte_natural_key
        self.obj_1 = obj
    def _set_obj_1(self) -> None:
        obj = CesionAecXml(
            dte=DteDataL1(
                emisor_rut=Rut('76354771-K'),
                tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
                folio=170,
                fecha_emision_date=date(2019, 4, 1),
                receptor_rut=Rut('96790240-3'),
                monto_total=2996301,
            ),
            seq=1,
            cedente_rut=Rut('76354771-K'),
            cesionario_rut=Rut('76389992-6'),
            monto_cesion=2996301,
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 1, 10, 22, 2),
                tz=CesionAecXml.DATETIME_FIELDS_TZ,
            ),
            fecha_ultimo_vencimiento=date(2019, 5, 1),
            cedente_razon_social=
            'SERVICIOS BONILLA Y LOPEZ Y COMPAÑIA LIMITADA',
            cedente_direccion='MERCED 753  16 ARBOLEDA DE QUIILOTA',
            cedente_email='*****@*****.**',
            cedente_persona_autorizada_rut=Rut('76354771-K'),
            cedente_persona_autorizada_nombre=
            'SERVICIOS BONILLA Y LOPEZ Y COMPAÑIA LIM',
            cesionario_razon_social='ST CAPITAL S.A.',
            cesionario_direccion='Isidora Goyenechea 2939 Oficina 602',
            cesionario_email='*****@*****.**',
            dte_deudor_email=None,
            cedente_declaracion_jurada=
            ('Se declara bajo juramento que SERVICIOS BONILLA Y LOPEZ Y COMPAÑIA '
             'LIMITADA, RUT 76354771-K ha puesto a disposición del cesionario ST '
             'CAPITAL S.A., RUT 76389992-6, el o los documentos donde constan los '
             'recibos de las mercaderías entregadas o servicios prestados, entregados '
             'por parte del deudor de la factura MINERA LOS PELAMBRES, RUT 96790240-3, '
             'deacuerdo a lo establecido en la Ley N°19.983.'),
        )
        self.assertIsInstance(obj, CesionAecXml)

        self.obj_1 = obj
    def test_as_cesion_l2(self) -> None:
        self._set_obj_1()

        obj = self.obj_1
        expected_output = CesionL2(
            dte_key=DteNaturalKey(
                emisor_rut=Rut('76354771-K'),
                tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
                folio=170,
            ),
            seq=1,
            cedente_rut=Rut('76354771-K'),
            cesionario_rut=Rut('76389992-6'),
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 1, 10, 22, 2),
                tz=CesionL2.DATETIME_FIELDS_TZ,
            ),
            monto_cedido=2996301,
            dte_receptor_rut=Rut('96790240-3'),
            dte_fecha_emision=date(2019, 4, 1),
            dte_monto_total=2996301,
            fecha_ultimo_vencimiento=date(2019, 5, 1),
            cedente_razon_social=
            'SERVICIOS BONILLA Y LOPEZ Y COMPAÑIA LIMITADA',
            cedente_email='*****@*****.**',
            cesionario_razon_social='ST CAPITAL S.A.',
            cesionario_email='*****@*****.**',
            dte_deudor_email=None,
            cedente_declaracion_jurada=
            ('Se declara bajo juramento que SERVICIOS BONILLA Y LOPEZ Y COMPAÑIA '
             'LIMITADA, RUT 76354771-K ha puesto a disposición del cesionario ST '
             'CAPITAL S.A., RUT 76389992-6, el o los documentos donde constan los '
             'recibos de las mercaderías entregadas o servicios prestados, entregados '
             'por parte del deudor de la factura MINERA LOS PELAMBRES, RUT 96790240-3, '
             'deacuerdo a lo establecido en la Ley N°19.983.'),
        )
        obj_cesion_l2 = obj.as_cesion_l2()
        self.assertEqual(obj_cesion_l2, expected_output)
        self.assertEqual(obj_cesion_l2.natural_key, obj.natural_key)
        self.assertEqual(obj_cesion_l2.alt_natural_key, obj.alt_natural_key)
        self.assertEqual(obj_cesion_l2.dte_key, obj.dte.natural_key)
Beispiel #18
0
 def test_as_dict(self) -> None:
     self.assertDictEqual(
         self.dte_l2_1.as_dict(),
         dict(
             emisor_rut=Rut('76354771-K'),
             tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
             folio=170,
             fecha_emision_date=date(2019, 4, 1),
             receptor_rut=Rut('96790240-3'),
             monto_total=2996301,
             emisor_razon_social='INGENIERIA ENACON SPA',
             receptor_razon_social='MINERA LOS PELAMBRES',
             fecha_vencimiento_date=None,
             firma_documento_dt=tz_utils.convert_naive_dt_to_tz_aware(
                 dt=datetime(2019, 4, 1, 1, 36, 40),
                 tz=DteDataL2.DATETIME_FIELDS_TZ),
             signature_value=self.dte_1_xml_signature_value,
             signature_x509_cert_der=self.dte_1_xml_cert_der,
             emisor_giro='Ingenieria y Construccion',
             emisor_email='*****@*****.**',
             receptor_email=None,
         ))
    def _set_obj_2(self) -> None:
        obj = CesionAecXml(
            dte=DteDataL1(
                emisor_rut=Rut('76354771-K'),
                tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
                folio=170,
                fecha_emision_date=date(2019, 4, 1),
                receptor_rut=Rut('96790240-3'),
                monto_total=2996301,
            ),
            seq=2,
            cedente_rut=Rut('76389992-6'),
            cesionario_rut=Rut('76598556-0'),
            monto_cesion=2996301,
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 5, 12, 57, 32),
                tz=CesionAecXml.DATETIME_FIELDS_TZ,
            ),
            fecha_ultimo_vencimiento=date(2019, 5, 1),
            cedente_razon_social='ST CAPITAL S.A.',
            cedente_direccion='Isidora Goyenechea 2939 Oficina 602',
            cedente_email='*****@*****.**',
            cedente_persona_autorizada_rut=Rut('16360379-9'),
            cedente_persona_autorizada_nombre='ANDRES  PRATS VIAL',
            cesionario_razon_social=
            'Fondo de Inversión Privado Deuda y Facturas',
            cesionario_direccion='Arrayan 2750 Oficina 703 Providencia',
            cesionario_email='*****@*****.**',
            dte_deudor_email=None,
            cedente_declaracion_jurada=
            ('Se declara bajo juramento que ST CAPITAL S.A., RUT 76389992-6 ha puesto '
             'a disposicion del cesionario Fondo de Inversión Privado Deuda y Facturas, '
             'RUT 76598556-0, el documento validamente emitido al deudor MINERA LOS '
             'PELAMBRES, RUT 96790240-3.'),
        )
        self.assertIsInstance(obj, CesionAecXml)

        self.obj_2 = obj
    def test_as_cesion_l1(self):
        self._set_obj_1()

        obj = self.obj_1
        expected_output = CesionL1(
            dte_key=DteNaturalKey(
                emisor_rut=Rut('76354771-K'),
                tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
                folio=170,
            ),
            seq=32,
            cedente_rut=Rut('76389992-6'),
            cesionario_rut=Rut('76598556-0'),
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 5, 12, 57, 32),
                tz=CesionL1.DATETIME_FIELDS_TZ,
            ),
            monto_cedido=2996301,
            fecha_ultimo_vencimiento=date(2019, 5, 1),
            dte_fecha_emision=date(2019, 4, 1),
            dte_receptor_rut=Rut('96790240-3'),
            dte_monto_total=2996301,
        )
        self.assertEqual(obj.as_cesion_l1(), expected_output)
Beispiel #21
0
    def setUp(self) -> None:
        super().setUp()

        self.valid_kwargs = dict(
            dte_vendedor_rut=Rut('51532520-4'),
            dte_deudor_rut=Rut('75320502-0'),
            dte_tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
            dte_folio=3608460,
            dte_fecha_emision=date(2019, 2, 11),
            dte_monto_total=256357,
            cedente_rut=Rut('51532520-4'),
            cedente_razon_social='MI CAMPITO SA',
            cedente_email='*****@*****.**',
            cesionario_rut=Rut('96667560-8'),
            cesionario_razon_social='POBRES SERVICIOS FINANCIEROS S.A.',
            cesionario_emails='[email protected],[email protected]',
            deudor_email=None,
            fecha_cesion_dt=convert_naive_dt_to_tz_aware(
                datetime(2019, 3, 7, 13, 32), tz=SII_OFFICIAL_TZ),
            fecha_cesion=date(2019, 3, 7),
            monto_cedido=256357,
            fecha_ultimo_vencimiento=date(2019, 4, 12),
            estado='Cesion Vigente',
        )
Beispiel #22
0
def parse_dte_xml(xml_doc: XmlElement) -> data_models.DteXmlData:
    """
    Parse data from a DTE XML doc.

    .. warning::
        It is assumed that ``xml_doc`` is an
        ``{http://www.sii.cl/SiiDte}/DTE``  XML element.

    :raises ValueError:
    :raises TypeError:
    :raises NotImplementedError:

    """
    # TODO: separate the XML parsing stage from the deserialization stage, which could be
    #   performed by XML-agnostic code (perhaps using Marshmallow or data clacases?).
    #   See :class:`cl_sii.rcv.parse_csv.RcvVentaCsvRowSchema`.

    if not isinstance(xml_doc, (XmlElement, XmlElementTree)):
        raise TypeError("'xml_doc' must be an 'XmlElement'.")

    xml_em = xml_doc

    ###########################################################################
    # XML elements finding
    ###########################################################################

    # Schema requires one, and only one, of these:
    # a) 'Documento'
    # b) 'Liquidacion'
    # c) 'Exportaciones'
    documento_em = xml_em.find(
        'sii-dte:Documento',  # "Informacion Tributaria del DTE"
        namespaces=DTE_XMLNS_MAP)
    liquidacion_em = xml_em.find(
        'sii-dte:Liquidacion',  # "Informacion Tributaria de Liquidaciones"
        namespaces=DTE_XMLNS_MAP)
    exportaciones_em = xml_em.find(
        'sii-dte:Exportaciones',  # "Informacion Tributaria de exportaciones"
        namespaces=DTE_XMLNS_MAP)
    signature_em = xml_em.find(
        'ds:Signature',  # "Firma Digital sobre Documento"
        namespaces=xml_utils.XML_DSIG_NS_MAP)

    if liquidacion_em is not None or exportaciones_em is not None:
        raise NotImplementedError("XML element 'Documento' is the only one supported.")

    if documento_em is None:
        raise ValueError("Top level XML element 'Document' is required.")

    # This value seems to be worthless (only useful for internal references in the XML doc).
    #   e.g. 'MiPE76354771-13419', 'MiPE76399752-6048'
    # documento_em_id = documento_em.attrib['ID']

    # 'Documento'
    # Excluded elements (optional according to the XML schema but the SII may require some of these
    #   depending on 'tipo_dte' and other criteria):
    #   - 'Detalle': (occurrences: 0..60)
    #     "Detalle de Itemes del Documento"
    #   - 'SubTotInfo': (occurrences: 0..20)
    #     "Subtotales Informativos"
    #   - 'DscRcgGlobal': (occurrences: 0..20)
    #     "Descuentos y/o Recargos que afectan al total del Documento"
    #   - 'Referencia': (occurrences: 0..40)
    #     "Identificacion de otros documentos Referenciados por Documento"
    #   - 'Comisiones': (occurrences: 0..20)
    #     "Comisiones y otros cargos es obligatoria para Liquidaciones Factura"
    encabezado_em = documento_em.find(
        'sii-dte:Encabezado',  # "Identificacion y Totales del Documento"
        namespaces=DTE_XMLNS_MAP)
    # note: excluded because currently it is not useful.
    # ted_em = documento_em.find(
    #     'sii-dte:TED',  # "Timbre Electronico de DTE"
    #     namespaces=DTE_XMLNS_MAP)
    tmst_firma_em = documento_em.find(
        'sii-dte:TmstFirma',  # "Fecha y Hora en que se Firmo Digitalmente el Documento"
        namespaces=DTE_XMLNS_MAP)

    # 'Documento.Encabezado'
    # Excluded elements (optional according to the XML schema but the SII may require some of these
    #   depending on 'tipo_dte' and other criteria):
    #   - 'RUTMandante':
    #     "RUT a Cuenta de Quien se Emite el DTE"
    #   - 'RUTSolicita':
    #     "RUT que solicita el DTE en Venta a Publico"
    #   - 'Transporte':
    #     "Informacion de Transporte de Mercaderias"
    #   - 'OtraMoneda':
    #     "Otra Moneda"
    id_doc_em = encabezado_em.find(
        'sii-dte:IdDoc',  # "Identificacion del DTE"
        namespaces=DTE_XMLNS_MAP)
    emisor_em = encabezado_em.find(
        'sii-dte:Emisor',  # "Datos del Emisor"
        namespaces=DTE_XMLNS_MAP)
    receptor_em = encabezado_em.find(
        'sii-dte:Receptor',  # "Datos del Receptor"
        namespaces=DTE_XMLNS_MAP)
    totales_em = encabezado_em.find(
        'sii-dte:Totales',  # "Montos Totales del DTE"
        namespaces=DTE_XMLNS_MAP)

    # 'Documento.Encabezado.IdDoc'
    # Excluded elements (optional according to the XML schema but the SII may require some of these
    #   depending on 'tipo_dte' and other criteria):
    #   - 'IndNoRebaja':
    #     "Nota de Credito sin Derecho a Descontar Debito"
    #   - 'TipoDespacho':
    #     "Indica Modo de Despacho de los Bienes que Acompanan al DTE"
    #   - 'IndTraslado':
    #     "Incluido en Guias de Despacho para Especifiicar el Tipo de Traslado de Productos"
    #   - 'TpoImpresion':
    #     "Tipo de impresión N (Normal)  o T (Ticket)"
    #   - 'IndServicio':
    #     "Indica si Transaccion Corresponde a la Prestacion de un Servicio"
    #   - 'MntBruto':
    #     "Indica el Uso de Montos Brutos en Detalle"
    #   - 'TpoTranCompra':
    #     "Tipo de Transacción para el comprador"
    #   - 'TpoTranVenta':
    #     "Tipo de Transacción para el vendedor"
    #   - 'FmaPago':
    #     "Forma de Pago del DTE"
    #   - 'FmaPagExp':
    #     "Forma de Pago Exportación Tabla Formas de Pago de Aduanas"
    #   - 'FchCancel':
    #     "Fecha de Cancelacion del DTE"
    #   - 'MntCancel':
    #     "Monto Cancelado al emitirse el documento"
    #   - 'SaldoInsol':
    #     "Saldo Insoluto al emitirse el documento"
    #   - 'MntPagos': (occurrences: 0..30)
    #     "Tabla de Montos de Pago"
    #   - 'PeriodoDesde':
    #     "Periodo de Facturacion - Desde"
    #   - 'PeriodoHasta':
    #     "Periodo Facturacion - Hasta"
    #   - 'MedioPago':
    #     "Medio de Pago"
    #   - 'TpoCtaPago':
    #     "Tipo Cuenta de Pago"
    #   - 'NumCtaPago':
    #     "Número de la cuenta del pago"
    #   - 'BcoPago':
    #     "Banco donde se realiza el pago"
    #   - 'TermPagoCdg':
    #     "Codigo del Termino de Pago Acordado"
    #   - 'TermPagoGlosa':
    #     "Términos del Pago - glosa"
    #   - 'TermPagoDias':
    #     "Dias de Acuerdo al Codigo de Termino de Pago"
    # (required):
    tipo_dte_em = id_doc_em.find(
        'sii-dte:TipoDTE',  # "Tipo de DTE"
        namespaces=DTE_XMLNS_MAP)
    folio_em = id_doc_em.find(
        'sii-dte:Folio',  # "Folio del Documento Electronico"
        namespaces=DTE_XMLNS_MAP)
    fecha_emision_em = id_doc_em.find(
        'sii-dte:FchEmis',  # "Fecha Emision Contable del DTE"
        namespaces=DTE_XMLNS_MAP)
    # (optional):
    fecha_vencimiento_em = id_doc_em.find(
        'sii-dte:FchVenc',  # "Fecha de Vencimiento del Pago"
        namespaces=DTE_XMLNS_MAP)

    # 'Documento.Encabezado.Emisor'
    # Excluded elements (optional according to the XML schema but the SII may require some of these
    #   depending on 'tipo_dte' and other criteria):
    #   - 'Telefono': (occurrences: 0..2)
    #     "Telefono Emisor"
    #   - 'Acteco': (occurrences: 0..4)
    #     "Codigo de Actividad Economica del Emisor Relevante para el DTE"
    #   - 'GuiaExport':
    #     "Emisor de una Guía de despacho para Exportación"
    #   - 'Sucursal':
    #     "Sucursal que Emite el DTE"
    #   - 'CdgSIISucur':
    #     "Codigo de Sucursal Entregado por el SII"
    #   - 'DirOrigen':
    #     "Direccion de Origen"
    #   - 'CmnaOrigen':
    #     "Comuna de Origen"
    #   - 'CiudadOrigen':
    #     "Ciudad de Origen"
    #   - 'CdgVendedor':
    #     "Codigo del Vendedor"
    #   - 'IdAdicEmisor':
    #     "Identificador Adicional del Emisor"
    # (required):
    emisor_rut_em = emisor_em.find(
        'sii-dte:RUTEmisor',  # "RUT del Emisor del DTE"
        namespaces=DTE_XMLNS_MAP)
    emisor_razon_social_em = emisor_em.find(
        'sii-dte:RznSoc',  # "Nombre o Razon Social del Emisor"
        namespaces=DTE_XMLNS_MAP)
    emisor_giro_em = emisor_em.find(
        'sii-dte:GiroEmis',  # "Giro Comercial del Emisor Relevante para el DTE"
        namespaces=DTE_XMLNS_MAP)
    # (optional):
    emisor_email_em = emisor_em.find(
        'sii-dte:CorreoEmisor',  # "Correo Elect. de contacto en empresa del receptor" (wrong!)
        namespaces=DTE_XMLNS_MAP)

    # 'Documento.Encabezado.Receptor'
    # Excluded elements (optional according to the XML schema but the SII may require some of these
    #   depending on 'tipo_dte' and other criteria):
    #   - 'CdgIntRecep':
    #     "Codigo Interno del Receptor"
    #   - 'Extranjero':
    #     "Receptor Extranjero"
    #   - 'GiroRecep':
    #     "Giro Comercial del Receptor"
    #   - 'Contacto':
    #     "Telefono o E-mail de Contacto del Receptor"
    #   - 'CorreoRecep':
    #     "Correo Elect. de contacto en empresa del receptor"
    #   - 'DirRecep':
    #     "Direccion en la Cual se Envian los Productos o se Prestan los Servicios"
    #   - 'CmnaRecep':
    #     "Comuna de Recepcion"
    #   - 'CiudadRecep':
    #     "Ciudad de Recepcion"
    #   - 'DirPostal':
    #     "Direccion Postal"
    #   - 'CmnaPostal':
    #     "Comuna Postal"
    #   - 'CiudadPostal':
    #     "Ciudad Postal"
    # (required):
    receptor_rut_em = receptor_em.find(
        'sii-dte:RUTRecep',  # "RUT del Receptor del DTE"
        namespaces=DTE_XMLNS_MAP)
    receptor_razon_social_em = receptor_em.find(
        'sii-dte:RznSocRecep',  # "Nombre o Razon Social del Receptor"
        namespaces=DTE_XMLNS_MAP)
    # (optional):
    receptor_email_em = emisor_em.find(
        'sii-dte:CorreoRecep',  # "Correo Elect. de contacto en empresa del receptor"
        namespaces=DTE_XMLNS_MAP)

    # 'Documento.Encabezado.Totales'
    # Excluded elements (optional according to the XML schema but the SII may require some of these
    #   depending on 'tipo_dte' and other criteria):
    # - 'MntNeto':
    #   "Monto Neto del DTE"
    # - 'MntExe':
    #   "Monto Exento del DTE"
    # - 'MntBase':
    #   "Monto Base Faenamiento Carne" (???)
    # - 'MntMargenCom':
    #   "Monto Base de Márgenes de Comercialización. Monto informado"
    # - 'TasaIVA':
    #   "Tasa de IVA" (percentage)
    # - 'IVA':
    #   "Monto de IVA del DTE"
    # - 'IVAProp':
    #   "Monto del IVA propio"
    # - 'IVATerc':
    #   "Monto del IVA de Terceros"
    # - 'ImptoReten': (occurrences: 0..20)
    #   "Impuestos y Retenciones Adicionales"
    # - 'IVANoRet':
    #   "IVA No Retenido"
    # - 'CredEC':
    #   "Credito Especial Empresas Constructoras"
    # - 'GrntDep':
    #   "Garantia por Deposito de Envases o Embalajes"
    # - 'Comisiones':
    #   "Comisiones y otros cargos es obligatoria para Liquidaciones Factura"
    # - 'MontoNF':
    #   "Monto No Facturable - Corresponde a Bienes o Servicios Facturados Previamente"
    # - 'MontoPeriodo':
    #   "Total de Ventas o Servicios del Periodo"
    # - 'SaldoAnterior':
    #   "Saldo Anterior - Puede ser Negativo o Positivo"
    # - 'VlrPagar':
    #   "Valor a Pagar Total del documento"
    monto_total_em = totales_em.find(
        'sii-dte:MntTotal',  # "Monto Total del DTE"
        namespaces=DTE_XMLNS_MAP)

    # 'Signature'
    # signature_signed_info_em = signature_em.find(
    #     'ds:SignedInfo',  # "Descripcion de la Informacion Firmada y del Metodo de Firma"
    #     namespaces=xml_utils.XML_DSIG_NS_MAP)
    # signature_signed_info_canonicalization_method_em = signature_signed_info_em.find(
    #     'ds:CanonicalizationMethod',  # "Algoritmo de Canonicalizacion"
    #     namespaces=xml_utils.XML_DSIG_NS_MAP)
    # signature_signed_info_signature_method_em = signature_signed_info_em.find(
    #     'ds:SignatureMethod',  # "Algoritmo de Firma"
    #     namespaces=xml_utils.XML_DSIG_NS_MAP)
    # signature_signed_info_reference_em = signature_signed_info_em.find(
    #     'ds:Reference',  # "Referencia a Elemento Firmado"
    #     namespaces=xml_utils.XML_DSIG_NS_MAP)
    signature_signature_value_em = signature_em.find(
        'ds:SignatureValue',  # "Valor de la Firma Digital"
        namespaces=xml_utils.XML_DSIG_NS_MAP)
    signature_key_info_em = signature_em.find(
        'ds:KeyInfo',  # "Informacion de Claves Publicas y Certificado"
        namespaces=xml_utils.XML_DSIG_NS_MAP)
    # signature_key_info_key_value_em = signature_key_info_em.find(
    #     'ds:KeyValue',
    #     namespaces=xml_utils.XML_DSIG_NS_MAP)
    signature_key_info_x509_data_em = signature_key_info_em.find(
        'ds:X509Data',  # "Informacion del Certificado Publico"
        namespaces=xml_utils.XML_DSIG_NS_MAP)
    signature_key_info_x509_cert_em = signature_key_info_x509_data_em.find(
        'ds:X509Certificate',  # "Certificado Publico"
        namespaces=xml_utils.XML_DSIG_NS_MAP)

    ###########################################################################
    # values parsing
    ###########################################################################

    tipo_dte_value = constants.TipoDteEnum(int(_text_strip_or_raise(tipo_dte_em)))
    folio_value = int(_text_strip_or_raise(folio_em))
    fecha_emision_value = date.fromisoformat(_text_strip_or_raise(fecha_emision_em))
    fecha_vencimiento_value = None
    if fecha_vencimiento_em is not None:
        fecha_vencimiento_value = date.fromisoformat(
            _text_strip_or_raise(fecha_vencimiento_em))

    emisor_rut_value = Rut(_text_strip_or_raise(emisor_rut_em))
    emisor_razon_social_value = _text_strip_or_raise(emisor_razon_social_em)
    emisor_giro_value = _text_strip_or_raise(emisor_giro_em)
    emisor_email_value = None
    if emisor_email_em is not None:
        emisor_email_value = _text_strip_or_none(emisor_email_em)

    receptor_rut_value = Rut(_text_strip_or_raise(receptor_rut_em))
    receptor_razon_social_value = _text_strip_or_raise(receptor_razon_social_em)
    receptor_email_value = None
    if receptor_email_em is not None:
        receptor_email_value = _text_strip_or_none(receptor_email_em)

    monto_total_value = int(_text_strip_or_raise(monto_total_em))

    tmst_firma_value = tz_utils.convert_naive_dt_to_tz_aware(
        dt=datetime.fromisoformat(_text_strip_or_raise(tmst_firma_em)),
        tz=data_models.DteXmlData.DATETIME_FIELDS_TZ)

    signature_signature_value = encoding_utils.decode_base64_strict(
        _text_strip_or_raise(signature_signature_value_em))
    signature_key_info_x509_cert_der = encoding_utils.decode_base64_strict(
        _text_strip_or_raise(signature_key_info_x509_cert_em))

    return data_models.DteXmlData(
        emisor_rut=emisor_rut_value,
        tipo_dte=tipo_dte_value,
        folio=folio_value,
        fecha_emision_date=fecha_emision_value,
        receptor_rut=receptor_rut_value,
        monto_total=monto_total_value,
        emisor_razon_social=emisor_razon_social_value,
        receptor_razon_social=receptor_razon_social_value,
        fecha_vencimiento_date=fecha_vencimiento_value,
        firma_documento_dt=tmst_firma_value,
        signature_value=signature_signature_value,
        signature_x509_cert_der=signature_key_info_x509_cert_der,
        emisor_giro=emisor_giro_value,
        emisor_email=emisor_email_value,
        receptor_email=receptor_email_value,
    )
 def as_datetime(self) -> datetime:
     # note: timezone-aware
     return tz_utils.convert_naive_dt_to_tz_aware(
         datetime(self.year, self.month, day=1, hour=0, minute=0, second=0),
         SII_OFFICIAL_TZ)
    def _set_obj_1(self) -> None:
        obj_dte_signature_value = encoding_utils.decode_base64_strict(
            read_test_file_bytes(
                'test_data/sii-crypto/DTE--76354771-K--33--170-signature-value-base64.txt',
            ), )
        obj_dte_signature_x509_cert_der = read_test_file_bytes(
            'test_data/sii-crypto/DTE--76354771-K--33--170-cert.der', )
        obj_dte = DteXmlData(
            emisor_rut=Rut('76354771-K'),
            tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
            folio=170,
            fecha_emision_date=date(2019, 4, 1),
            receptor_rut=Rut('96790240-3'),
            monto_total=2996301,
            emisor_razon_social='INGENIERIA ENACON SPA',
            receptor_razon_social='MINERA LOS PELAMBRES',
            fecha_vencimiento_date=None,
            firma_documento_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 1, 1, 36, 40),
                tz=DteXmlData.DATETIME_FIELDS_TZ,
            ),
            signature_value=obj_dte_signature_value,
            signature_x509_cert_der=obj_dte_signature_x509_cert_der,
            emisor_giro='Ingenieria y Construccion',
            emisor_email='*****@*****.**',
            receptor_email=None,
        )

        obj_cesion_1 = CesionAecXml(
            dte=DteDataL1(
                emisor_rut=Rut('76354771-K'),
                tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
                folio=170,
                fecha_emision_date=date(2019, 4, 1),
                receptor_rut=Rut('96790240-3'),
                monto_total=2996301,
            ),
            seq=1,
            cedente_rut=Rut('76354771-K'),
            cesionario_rut=Rut('76389992-6'),
            monto_cesion=2996301,
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 1, 10, 22, 2),
                tz=CesionAecXml.DATETIME_FIELDS_TZ,
            ),
            fecha_ultimo_vencimiento=date(2019, 5, 1),
            cedente_razon_social=
            'SERVICIOS BONILLA Y LOPEZ Y COMPAÑIA LIMITADA',
            cedente_direccion='MERCED 753  16 ARBOLEDA DE QUIILOTA',
            cedente_email='*****@*****.**',
            cedente_persona_autorizada_rut=Rut('76354771-K'),
            cedente_persona_autorizada_nombre=
            'SERVICIOS BONILLA Y LOPEZ Y COMPAÑIA LIM',
            cesionario_razon_social='ST CAPITAL S.A.',
            cesionario_direccion='Isidora Goyenechea 2939 Oficina 602',
            cesionario_email='*****@*****.**',
            dte_deudor_email=None,
            cedente_declaracion_jurada=
            ('Se declara bajo juramento que SERVICIOS BONILLA Y LOPEZ Y COMPAÑIA '
             'LIMITADA, RUT 76354771-K ha puesto a disposición del cesionario ST '
             'CAPITAL S.A., RUT 76389992-6, el o los documentos donde constan los '
             'recibos de las mercaderías entregadas o servicios prestados, entregados '
             'por parte del deudor de la factura MINERA LOS PELAMBRES, RUT 96790240-3, '
             'deacuerdo a lo establecido en la Ley N°19.983.'),
        )

        obj_cesion_2 = CesionAecXml(
            dte=DteDataL1(
                emisor_rut=Rut('76354771-K'),
                tipo_dte=TipoDteEnum.FACTURA_ELECTRONICA,
                folio=170,
                fecha_emision_date=date(2019, 4, 1),
                receptor_rut=Rut('96790240-3'),
                monto_total=2996301,
            ),
            seq=2,
            cedente_rut=Rut('76389992-6'),
            cesionario_rut=Rut('76598556-0'),
            monto_cesion=2996301,
            fecha_cesion_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 5, 12, 57, 32),
                tz=CesionAecXml.DATETIME_FIELDS_TZ,
            ),
            fecha_ultimo_vencimiento=date(2019, 5, 1),
            cedente_razon_social='ST CAPITAL S.A.',
            cedente_direccion='Isidora Goyenechea 2939 Oficina 602',
            cedente_email='*****@*****.**',
            cedente_persona_autorizada_rut=Rut('16360379-9'),
            cedente_persona_autorizada_nombre='ANDRES  PRATS VIAL',
            cesionario_razon_social=
            'Fondo de Inversión Privado Deuda y Facturas',
            cesionario_direccion='Arrayan 2750 Oficina 703 Providencia',
            cesionario_email='*****@*****.**',
            dte_deudor_email=None,
            cedente_declaracion_jurada=
            ('Se declara bajo juramento que ST CAPITAL S.A., RUT 76389992-6 ha puesto '
             'a disposicion del cesionario Fondo de Inversión Privado Deuda y Facturas, '
             'RUT 76598556-0, el documento validamente emitido al deudor MINERA LOS '
             'PELAMBRES, RUT 96790240-3.'),
        )

        obj = AecXml(
            dte=obj_dte,
            cedente_rut=Rut('76389992-6'),
            cesionario_rut=Rut('76598556-0'),
            fecha_firma_dt=tz_utils.convert_naive_dt_to_tz_aware(
                dt=datetime(2019, 4, 5, 12, 57, 32),
                tz=AecXml.DATETIME_FIELDS_TZ,
            ),
            # signature_value=None,
            # signature_x509_cert_der=None,
            cesiones=[
                obj_cesion_1,
                obj_cesion_2,
            ],
            contacto_nombre='ST Capital Servicios Financieros',
            contacto_telefono=None,
            contacto_email='*****@*****.**',
        )
        self.assertIsInstance(obj, AecXml)

        self.obj_1 = obj
        self.obj_1_dte = obj_dte
        self.obj_1_cesion_1 = obj_cesion_1
        self.obj_1_cesion_2 = obj_cesion_2