Ejemplo n.º 1
0
    def setUpClass(cls) -> None:
        super().setUpClass()

        cls.dte_bad_xml_1_xml_bytes = read_test_file_bytes(
            'test_data/sii-dte/DTE--76354771-K--33--170.xml')
        cls.dte_bad_xml_2_xml_bytes = read_test_file_bytes(
            'test_data/sii-dte/DTE--76399752-9--33--25568.xml')

        cls.dte_clean_xml_1_xml_bytes = read_test_file_bytes(
            'test_data/sii-dte/DTE--76354771-K--33--170--cleaned.xml')
        cls.dte_clean_xml_2_xml_bytes = read_test_file_bytes(
            'test_data/sii-dte/DTE--76399752-9--33--25568--cleaned.xml')
        cls.dte_clean_xml_1b_xml_bytes = read_test_file_bytes(
            'test_data/sii-dte/DTE--76354771-K--33--170--cleaned-mod-empty-emails.xml')

        cls.dte_clean_xml_1_cert_pem_bytes = encoding_utils.clean_base64(
            crypto_utils.remove_pem_cert_header_footer(
                read_test_file_bytes('test_data/sii-crypto/DTE--76354771-K--33--170-cert.pem')))
        cls.dte_clean_xml_1_cert_der = read_test_file_bytes(
            'test_data/sii-crypto/DTE--76354771-K--33--170-cert.der')
        cls.dte_clean_xml_2_cert_pem_bytes = encoding_utils.clean_base64(
            crypto_utils.remove_pem_cert_header_footer(
                read_test_file_bytes('test_data/sii-crypto/DTE--76399752-9--33--25568-cert.pem')))
        cls.dte_clean_xml_2_cert_der = read_test_file_bytes(
            'test_data/sii-crypto/DTE--76399752-9--33--25568-cert.der')

        cls._TEST_DTE_1_SIGNATURE_VALUE = encoding_utils.decode_base64_strict(
            read_test_file_bytes(
                'test_data/sii-crypto/DTE--76354771-K--33--170-signature-value-base64.txt'))
        cls._TEST_DTE_2_SIGNATURE_VALUE = encoding_utils.decode_base64_strict(
            read_test_file_bytes(
                'test_data/sii-crypto/DTE--76399752-9--33--25568-signature-value-base64.txt'))
    def setUpClass(cls) -> None:
        super().setUpClass()

        cls.dte_1_xml_signature_value = encoding_utils.decode_base64_strict(
            read_test_file_bytes(
                'test_data/sii-crypto/DTE--76354771-K--33--170-signature-value-base64.txt'
            ))
        cls.dte_1_xml_cert_der = read_test_file_bytes(
            'test_data/sii-crypto/DTE--76354771-K--33--170-cert.der')
        cls.dte_2_xml_signature_value = encoding_utils.decode_base64_strict(
            read_test_file_bytes(
                'test_data/sii-crypto/DTE--60910000-1--33--2336600-signature-value-base64.txt'
            ))
        cls.dte_2_xml_cert_der = read_test_file_bytes(
            'test_data/sii-crypto/DTE--60910000-1--33--2336600-cert.der')
    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
Ejemplo n.º 4
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,
    )
Ejemplo n.º 5
0
 def validate_base64(cls, v: object) -> object:
     if isinstance(v, (str, bytes)):
         v = encoding_utils.decode_base64_strict(v)  # Raises ValueError.
     return v