示例#1
0
class Envio(object):
    def __init__(self, vals, resumen=False):
        self._iniciar()
        util.set_from_keys(self, vals, priorizar=['Emisor'])
        self.conexion = self.test
        self._resumen = resumen

    @property
    def Cesion(self):
        if not hasattr(self, '_cesion'):
            return False
        return self._cesion

    @Cesion.setter
    def Cesion(self, vals):
        self._cesion = AEC(vals)
        self._cesion._dte_emisor = self.Emisor
        self._cesion._firma = self.firma
        self._cesion.verify = self.verify
        self._cesion.test = self.test

    @property
    def conexion(self):
        if not hasattr(self, '_conexion'):
            return False
        return self._conexion

    @conexion.setter
    def conexion(self, val):
        if val:
            self._conexion = False
            return
        self._conexion = Conexion(self.Emisor, self.firma)

    @property
    def ConsumoFolios(self):
        if not hasattr(self, '_consumo_folios'):
            return []
        return self._consumo_folios

    @ConsumoFolios.setter
    def ConsumoFolios(self, vals):
        _cfs = []
        for cf in vals:
            _cfs.append(CF(cf))
        self._consumo_folios = _cfs

    @property
    def Documento(self):
        if not hasattr(self, '_documentos'):
            return []
        return self._documentos

    @Documento.setter
    def Documento(self, docs):
        _documentos = []
        for vals in docs:
            if vals.get('TipoDTE'):
                TipoDTE = vals['TipoDTE']
            if TipoDTE in [39, 41]:
                self.es_boleta = True
                self.test = True
            caf_file = vals.get('caf_file', [])
            for docData in vals["documentos"]:
                docu = Doc(docData, resumen=False)
                docu._dte_emsior = self.Emisor
                docu._firma = self.firma
                docu.verify = self.verify
                docu.test = self.test
                if caf_file:
                    docu.caf_file = caf_file
                docu.TipoDTE = TipoDTE
                _documentos.append(docu)
        self._documentos = sorted(_documentos, key=lambda t: t.NroDTE)

    @property
    def Emisor(self):
        if not hasattr(self, '_emisor'):
            self._emisor = Emis()
        return self._emisor

    @Emisor.setter
    def Emisor(self, vals):
        if not hasattr(self, '_emisor'):
            self._emisor = Emis()
        self._emisor.set_from_keys(vals)

    @property
    def errores(self):
        if not hasattr(self, '_errores'):
            return []
        return self._errores

    @errores.setter
    def errores(self, val):
        if not hasattr(self, '_errores'):
            self._errores = [val]
        else:
            self._errores.append(val)

    @property
    def es_boleta(self):
        if not hasattr(self, '_es_boleta'):
            return False
        return self._es_boleta

    @es_boleta.setter
    def es_boleta(self, val):
        self._es_boleta = val

    @property
    def filename(self):
        if not hasattr(self, '_filename'):
            return ''
        return self._filename

    @filename.setter
    def filename(self, val):
        self._filename = val

    @property
    def firma(self):
        return self.firma_electronica

    @property
    def firma_electronica(self):
        if not hasattr(self, '_firma_electronica'):
            return False
        return self._firma_electronica

    @firma_electronica.setter
    def firma_electronica(self, vals):
        if vals:
            self._firma_electronica = Firma(vals)
        else:
            print("firma no soportada")
            self._firma_electronica = False

    @property
    def Libro(self):
        if not hasattr(self, '_libro'):
            return False
        return self._libro

    @Libro.setter
    def Libro(self, vals):
        self._libro = Lib()
        self._libro._dte_emisor = self.Emisor
        util.set_from_keys(self._libro, vals)

    @property
    def Recepciones(self):
        if not hasattr(self, '_recepciones'):
            return []
        return self._recepciones

    @Recepciones.setter
    def Recepciones(self, vals):
        def recursive_xml(el):
            if el.text and bool(el.text.strip()):
                return el.text
            res = {}
            for e in el:
                res[el.tag] = recursive_xml(e)
            return res

        Respuesta._dte_emisor = self._emisor
        _recepciones = []
        for recep in vals:
            respuesta = Respuesta(recep)
            respuesta.firma = self.firma_electronica
            envio = respuesta.xml_envio
            respuesta.Emisor = {
                'RUTEmisor': envio.find('SetDTE/Caratula/RutEmisor').text,
            }
            respuesta.Receptor = {
                'RUTRecep': envio.find('SetDTE/Caratula/RutReceptor').text,
            }
            for dte in envio.findall('SetDTE/DTE'):
                res = recursive_xml(dte)
                respuesta.DTEs = res
            _recepciones.append(respuesta)
        self._recepciones = _recepciones

    @property
    def RecepcionMer(self):
        if not hasattr(self, '_recep_mer'):
            return False
        return self._recep_mer

    @RecepcionMer.setter
    def RecepcionMer(self, vals):
        Respuesta.firma = self.firma
        Respuesta._dte_emisor = self._emisor
        self._recep_mer = Respuesta(vals)

    @property
    def RutReceptor(self):
        if not hasattr(self, '_rut_receptor'):
            return '60803000-K'
        return self._rut_receptor

    @RutReceptor.setter
    def RutReceptor(self, val):
        self._rut_receptor = val

    @property
    def ValidacionCom(self):
        if not hasattr(self, '_validacion_com'):
            return False
        return self._validacion_com

    @ValidacionCom.setter
    def ValidacionCom(self, vals):
        Respuesta.firma = self.firma
        Respuesta._dte_emisor = self._emisor
        self._validacion_com = Respuesta(vals)

    @property
    def test(self):
        if not hasattr(self, '_test'):
            return False
        return self._test

    @test.setter
    def test(self, val):
        self._test = val

    @property
    def verify(self):
        if not hasattr(self, '_verify'):
            return True
        return self._verify

    @verify.setter
    def verify(self, val):
        self._verify = val

    def _iniciar(self):
        self._resumen = False

    def caratula_aec(self):
        dte_cedido = self.Cesion.dte_cedido()
        doc_cedido = self.Cesion.xml_doc_cedido()
        xml = '''<DocumentoAEC ID="{0}">
    <Caratula version="1.0">
    <RutCedente>{1}</RutCedente>
    <RutCesionario>{2}</RutCesionario>
    <NmbContacto>{3}</NmbContacto>
    <FonoContacto>{4}</FonoContacto>
    <MailContacto>{5}</MailContacto>
    <TmstFirmaEnvio>{6}</TmstFirmaEnvio>
</Caratula>
    <Cesiones>
        {7}
    </Cesiones>
</DocumentoAEC>
'''.format(
            self.Cesion.ID,
            self.Emisor.RUTEmisor,
            self.Cesion._cesionario.RUT,
            self.Cesion._cedente.Nombre,
            self.Cesion._cedente.Phono,
            self.Cesion._cedente.eMail,
            util.time_stamp(),
            (dte_cedido + '\n' + doc_cedido),
        )
        return xml

    def caratula_consumo_folios(self, cf, IdEnvio='SetDoc'):
        if cf.Correlativo != 0:
            Correlativo = "<Correlativo>"\
                + str(cf.Correlativo) + "</Correlativo>"
        else:
            Correlativo = ''
        xml = '''<DocumentoConsumoFolios ID="{10}">
<Caratula  version="1.0" >
<RutEmisor>{0}</RutEmisor>
<RutEnvia>{1}</RutEnvia>
<FchResol>{2}</FchResol>
<NroResol>{3}</NroResol>
    <FchInicio>{4}</FchInicio>
<FchFinal>{5}</FchFinal>{6}
<SecEnvio>{7}</SecEnvio>
<TmstFirmaEnv>{8}</TmstFirmaEnv>
</Caratula>
{9}
</DocumentoConsumoFolios>
'''.format(self.Emisor.RUTEmisor, self.firma_electronica.rut_firmante,
           self.Emisor.FchResol, self.Emisor.NroResol,
           cf.FchInicio, cf.FchFinal, Correlativo, str(cf.SecEnvio),
           util.time_stamp(), cf.sii_xml_request, IdEnvio)
        return xml

    def caratula_dte(self, EnvioDTE, SubTotDTE):
        xml = '''<SetDTE ID="SetDoc">
<Caratula version="1.0">
<RutEmisor>{0}</RutEmisor>
<RutEnvia>{1}</RutEnvia>
<RutReceptor>{2}</RutReceptor>
<FchResol>{3}</FchResol>
<NroResol>{4}</NroResol>
<TmstFirmaEnv>{5}</TmstFirmaEnv>
{6}</Caratula>{7}
</SetDTE>
'''.format(self.Emisor.RUTEmisor,
           self.firma_electronica.rut_firmante\
            if self.firma_electronica else '66666666-6',
           self.RutReceptor,
           self.Emisor.FchResol,
           self.Emisor.NroResol,
           util.time_stamp(),
           SubTotDTE,
           EnvioDTE)
        return xml

    def caratula_libro(self):
        if self.Libro.TipoOperacion == 'BOLETA' and\
                self.Libro.TipoLibro != 'ESPECIAL':
            raise UserError(
                "Boletas debe ser solamente Tipo Operación ESPECIAL")
        if self.Libro.TipoLibro in ['ESPECIAL'] or\
                self.Libro.TipoOperacion in ['BOLETA']:
            FolioNotificacion = '<FolioNotificacion>{0}</FolioNotificacion>'\
                .format(self.Libro.FolioNotificacion)
        else:
            FolioNotificacion = ''
        if self.Libro.TipoOperacion in ['BOLETA', 'GUIA']:
            TipoOperacion = ''
        else:
            TipoOperacion = '<TipoOperacion>' + self.Libro.TipoOperacion\
                + '</TipoOperacion>'
        CodigoRectificacion = ''
        if self.Libro.TipoLibro == 'RECTIFICA':
            CodigoRectificacion = '\n<CodAutRec>' +\
                self.Libro.CodigoRectificacion + '</CodAutRec>'
        xml = '''<EnvioLibro ID="{10}">
<Caratula>
<RutEmisorLibro>{0}</RutEmisorLibro>

<RutEnvia>{1}</RutEnvia>
<PeriodoTributario>{2}</PeriodoTributario>
<FchResol>{3}</FchResol>
<NroResol>{4}</NroResol>{5}
<TipoLibro>{6}</TipoLibro>
<TipoEnvio>{7}</TipoEnvio>
{8}{11}
</Caratula>
{9}
</EnvioLibro>
'''.format(self.Emisor.RUTEmisor,
           self.firma_electronica.rut_firmante\
            if self.firma_electronica else '66666666-6',
           self.Libro.PeriodoTributario,
           self.Emisor.FchResol,
           self.Emisor.NroResol,
           TipoOperacion,
           self.Libro.TipoLibro,
           self.Libro.TipoEnvio,
           FolioNotificacion,
           self.Libro.sii_xml_request,
           self.doc_id,
           CodigoRectificacion,
           )
        return xml

    def envio_aec(self):
        doc_aec = self.caratula_aec()
        xml = '''<AEC xmlns="http://www.sii.cl/SiiDte" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="http://www.sii.cl/SiiDte AEC_v10.xsd" \
version="1.0">
    {}
</AEC>'''.format(doc_aec)
        self.sii_xml_request = xml

    def envio_dte(self, doc):
        xml = '''<EnvioDTE xmlns="http://www.sii.cl/SiiDte" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="http://www.sii.cl/SiiDte EnvioDTE_v10.xsd" \
version="1.0">
{}
</EnvioDTE>'''.format(doc)
        self.sii_xml_request = xml

    def envio_boleta(self, doc):
        xml = '''<EnvioBOLETA xmlns="http://www.sii.cl/SiiDte" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="http://www.sii.cl/SiiDte EnvioBOLETA_v11.xsd" \
version="1.0">
{}
</EnvioBOLETA>'''.format(doc)
        return xml

    def envio_libro_cv(self, simplificado=False):
        doc = self.caratula_libro()
        simp = 'http://www.sii.cl/SiiDte LibroCV_v10.xsd'
        if simplificado:
            simp = 'http://www.sii.cl/SiiDte LibroCVS_v10.xsd'
        xml = '''<LibroCompraVenta xmlns="http://www.sii.cl/SiiDte" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="{0}" \
version="1.0">
{1}</LibroCompraVenta>'''.format(simp, doc)
        return xml

    def envio_libro_boleta(self):
        doc = self.caratula_libro()
        xsd = 'http://www.sii.cl/SiiDte LibroBOLETA_v10.xsd'
        xml = '''<LibroBoleta xmlns="http://www.sii.cl/SiiDte" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="{0}" \
version="1.0">
{1}</LibroBoleta>'''.format(xsd, doc)
        return xml

    def envio_consumo_folios(self, doc):
        xsd = 'http://www.sii.cl/SiiDte ConsumoFolio_v10.xsd'
        xml = '''<ConsumoFolios xmlns="http://www.sii.cl/SiiDte" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="{0}" \
version="1.0">
{1}</ConsumoFolios>'''.format(xsd, doc)
        return xml

    def envio_libro_guia(self):
        doc = self.caratula_libro()
        xsd = 'http://www.sii.cl/SiiDte LibroGuia_v10.xsd'
        xml = '''<LibroGuia xmlns="http://www.sii.cl/SiiDte" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="{0}" \
version="1.0">
{1}</LibroGuia>'''.format(xsd, doc)
        return xml

    def envio_recep(self):
        caratula = self.RecepcionMer.Caratula
        recibos = self.RecepcionMer.Recibos
        xml = '''<EnvioRecibos xmlns='http://www.sii.cl/SiiDte' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.sii.cl/SiiDte EnvioRecibos_v10.xsd' version="1.0">
    <SetRecibos ID="SetDteRecibidos">
        {0}
        {1}
    </SetRecibos>
</EnvioRecibos>'''.format(caratula, recibos)
        self.sii_xml_request = xml

    def RespuestaDTE(self, caratula, resultados):
        resp = '''<RespuestaDTE version="1.0" xmlns="http://www.sii.cl/SiiDte" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="http://www.sii.cl/SiiDte RespuestaEnvioDTE_v10.xsd" >
    <Resultado ID="Odoo_resp">
            {0}
            {1}
    </Resultado>
</RespuestaDTE>'''.format(caratula, resultados)
        self.sii_xml_request = resp

    def Recibo(self, r):
        doc = '''<Recibo version="1.0" xmlns="http://www.sii.cl/SiiDte" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sii.cl/SiiDte Recibos_v10.xsd" >
    <DocumentoRecibo ID="{0}" >
        {1}
    </DocumentoRecibo>
</Recibo>
        '''.format(r.ID, self.RecepcionMer.recibo(r))
        self.sii_xml_request = doc

    def firmar(self, uri, type='env'):
        result = b''
        if self.firma_electronica.firma:
            result = self.firma_electronica.firmar(self.sii_xml_request, uri,
                                                   type)
        self.sii_xml_request = result

    def generate_xml_send(self):
        tots_dte = {}
        documentos = ''
        for dte in self.Documento:
            try:
                dte.timbrar()
                tots_dte.setdefault(dte.TipoDTE, {'total': 0, 'folios': []})
                tots_dte[dte.TipoDTE]['total'] += 1
                tots_dte[dte.TipoDTE]['folios'].append(dte.Folio)
                documentos += '\n' + dte.sii_xml_request
            except Exception as e:
                err = {
                    'FechaEmis': dte.FechaEmis,
                    'Folio': dte.Folio,
                    'TipoDTE': dte.TipoDTE,
                    'error': str(e),
                }
                print(err)
                self.errores = err
        SubTotDTE = ''
        for key, value in tots_dte.items():
            SubTotDTE += '<SubTotDTE>\n<TpoDTE>' + str(key)\
                + '</TpoDTE>\n<NroDTE>'+str(value['total'])+'</NroDTE>\n</SubTotDTE>\n'
            self.filename += 'T%sF' % (key)
            for f in value['folios']:
                self.filename += '%s-' % (f)
        self.filename = self.filename[:-1] + ".xml"
        # firma del sobre
        dtes = self.caratula_dte(documentos, SubTotDTE)
        env = 'env'
        if self.es_boleta:
            self.sii_xml_request = self.envio_boleta(dtes)
            env = 'env_boleta'
        else:
            self.envio_dte(dtes)
        self.firmar('SetDoc', env)

    def do_dte_send(self):
        self.generate_xml_send()
        barcodes = []
        for r in self.Documento:
            barcodes.append({
                'Folio': r.Folio,
                'TpoDTE': r.TipoDTE,
                'sii_barcode_img': r.sii_barcode_img
            })
        result = {
            'sii_result': 'draft',
        }
        if not self.test and self.conexion:
            result = self.conexion.send_xml_file(self.sii_xml_request,
                                                 self.filename)
        result.update({
                'sii_xml_request': '<?xml version="1.0" encoding="ISO-8859-1"?>\n'\
                + self.sii_xml_request,
                'sii_send_filename': self.filename,
                'barcodes': barcodes,
                'errores': self.errores,
                })
        return result

    def do_libro_send(self):
        if not self.Libro.validar():
            return []
        self.doc_id = self.Libro.TipoOperacion + '_' + \
            self.Libro.PeriodoTributario
        env = 'libro'
        if self.Libro.TipoOperacion in ['BOLETA']:
            xml = self.envio_libro_boleta()
            env = 'libro_boleta'
        elif self.Libro.TipoOperacion == 'GUIA':
            xml = self.envio_libro_guia()
            env = 'libro_guia'
        else:
            xml = self.envio_libro_cv()
        self.sii_xml_request = xml
        self.firmar(self.doc_id, env)
        result = {'sii_result': 'draft'}
        self.sii_xml_request = self.sii_xml_request
        if not self.test:
            result = self.conexion.send_xml_file(self.sii_xml_request,
                                                 self.doc_id + '.xml')
        result.update({
            'sii_xml_request': '<?xml version="1.0" encoding="ISO-8859-1"?>\n'\
                + self.sii_xml_request,
            'sii_send_filename': self.filename + ".xml",
            'errores': self.errores,
            })
        return result

    def do_consumo_folios_send(self):
        results = []
        for _cf in self.ConsumoFolios:
            if not _cf.validar():
                continue
            self.filename = 'CF_' + _cf.FchInicio
            cf = self.caratula_consumo_folios(_cf)
            self.envio_consumo_folios(cf)
            self.firmar(
                'SetDoc',
                type='consu',
            )
            result = {'sii_result': 'draft'}
            sii_xml_request = '<?xml version="1.0" encoding="ISO-8859-1"?>\n'\
                + self.sii_xml_request
            if not self.test:
                result = self.conexion.send_xml_file(sii_xml_request,
                                                     self.filename)
            result.update({
                'sii_xml_request': sii_xml_request,
                'sii_send_filename': self.filename + ".xml",
            })
            results.append(result)
        return results

    def do_receipt_deliver(self):
        resps = []
        for r in self.Recepciones:
            self.RespuestaDTE(r.Caratula, r.RecepcionEnvio)
            self.firmar(
                'Odoo_resp',
                'env_resp',
            )
            resp = {
                'respuesta_xml': '<?xml version="1.0" encoding="ISO-8859-1"?>\n'\
                + self.sii_xml_request,
                'nombre_xml': 'recepcion_envio_%s_%s.xml' %
                (r.xml_nombre, str(r.IdRespuesta)),
                'EstadoRecepEnv': r.EstadoRecepEnv,
                'RecepEnvGlosa': r.RecepEnvGlosa,
            }
            resps.append(resp)
        return resps

    def do_recep_merc(self):
        for r in self.RecepcionMer.DTEs:
            self.Recibo(r)
            self.firmar(r.ID, 'env_recep')
            self.RecepcionMer.Recibos = self.sii_xml_request
        self.envio_recep()
        self.firmar('SetDteRecibidos', 'env_recep')
        return {
                'respuesta_xml': '<?xml version="1.0" encoding="ISO-8859-1"?>\n'\
                + self.sii_xml_request,
                'nombre_xml': 'recepcion_mercaderias_%s.xml' % str(
                            self.RecepcionMer.DTEs[0].ID)
            }

    def do_validar_com(self):
        self.ValidacionCom.gen_validacion_comercial()
        self.RespuestaDTE(self.ValidacionCom.Caratula,
                          self.ValidacionCom.Resultados)
        self.firmar('Odoo_resp', 'env_resp')
        return {
            'respuesta_xml': '<?xml version="1.0" encoding="ISO-8859-1"?>\n'\
                + self.sii_xml_request,
            'nombre_xml': 'validacion_comercial_%s.xml' % str(
                            self.ValidacionCom.IdRespuesta),
            'EstadoDTE': self.ValidacionCom.EstadoDTE,
            'EstadoDTEGlosa': self.ValidacionCom.EstadoDTEGlosa,
        }

    def do_envio_cesion(self):
        self.envio_aec()
        self.firmar(
            self.Cesion.ID,
            'aec',
        )
        result = {}
        if not self.test:
            self.conexion.cesion = True
            result = self.conexion.send_xml_file(self.sii_xml_request,
                                                 self.filename)
        sii_xml_request = '<?xml version="1.0" encoding="ISO-8859-1"?>\n'\
            + self.sii_xml_request
        result.update({
            'sii_xml_request': sii_xml_request,
            'sii_send_filename': self.filename + ".xml",
        })
        return result
示例#2
0
class DTE(object):

    def __init__(self, vals):
        self._iniciar()
        priorizar = ['Emisor']
        util.set_from_keys(self, vals, priorizar=priorizar)

    @property
    def Emisor(self):
        if not hasattr(self, '_dte_emisor'):
            self._dte_emisor = Emis()
        return self._dte_emisor

    @Emisor.setter
    def Emisor(self, vals):
        if not hasattr(self, '_dte_emisor'):
            self._dte_emisor = Emis()
        self._dte_emisor.set_from_keys(vals)

    @property
    def caf_files(self):
        return self.caf_file

    @property
    def caf_file(self):
        if not hasattr(self, '_cafs'):
            return []
        return self._cafs

    @caf_file.setter
    def caf_file(self, vals):
        try:
            self._cafs = Caf(vals)
        except Exception as e:
            print("Caf no Soportado o vacío: %s" % str(e))

    @property
    def firma(self):
        if not hasattr(self, '_firma'):
            return False
        return self._firma

    @firma.setter
    def firma(self, val):
        val.verify = self.verify
        self._firma = val

    @property
    def ID(self):
        if not hasattr(self, '_id'):
            return "T{}F{}".format(self.TipoDTE, self.Folio)
        return self._id

    @ID.setter
    def ID(self, val):
        self._id = val

    @property
    def sii_barcode(self):
        if not hasattr(self, '_sii_barcode'):
            return False
        return self._sii_barcode

    @sii_barcode.setter
    def sii_barcode(self, val):
        self._sii_barcode = val

    @property
    def sii_xml_request(self):
        if not hasattr(self, '_sii_xml_request'):
            return False
        return self._sii_xml_request

    @sii_xml_request.setter
    def sii_xml_request(self, val):
        self._sii_xml_request = val

    @property
    def timestamp_timbre(self):
        if not hasattr(self, '_timestamp_timbre') or not self._timestamp_timbre:
            self._timestamp_timbre = util.time_stamp()
        return self._timestamp_timbre

    @timestamp_timbre.setter
    def timestamp_timbre(self, val):
        self._timestamp_timbre = val

    @property
    def verify(self):
        if not hasattr(self, '_verify'):
            return True
        return self._verify

    @verify.setter
    def verify(self, val):
        self._verify = val

    def _iniciar(self):
        self.respuesta = False
        self.estado_recep_dte = None
        #string con una de las opciones
        '''estado_recep_dte = [
                ('no_revisado','No Revisado'),
                ('0','Conforme'),
                ('1','Error de Schema'),
                ('2','Error de Firma'),
                ('3','RUT Receptor No Corresponde'),
                ('90','Archivo Repetido'),
                ('91','Archivo Ilegible'),
                ('99','Envio Rechazado - Otros')
            ]
        '''

    def crear_DTE(self, doc, tag='DTE'):
        xml = '<' + tag + ' xmlns="http://www.sii.cl/SiiDte" version="1.0">\n'\
            + doc + '\n</' + tag + '>'
        return xml

    def firmar(self, message, uri, type='doc'):
        string = message.replace('<item>', '').replace('</item>', '')\
            .replace('<item/>', '').replace('<itemRefs>', '')\
            .replace('</itemRefs>', '').replace('<itemDscRcgGlobal>', '')\
            .replace('</itemDscRcgGlobal>', '').replace('<cdg_items>', '')\
            .replace('</cdg_items>', '')
        if self.firma.firma:
            return self.firma.firmar(string, uri, type)
        raise UserError('No tiene Firma Válida')

    def get_xml_file(self):
        filename = (self.document_number+'.xml').replace(' ', '')
        return {
            'type': 'ir.actions.act_url',
            'url': '/web/binary/download_document?model=account.invoice\
&field=sii_xml_request&id=%s&filename=%s' % (self.id, filename),
            'target': 'self',
        }

    def get_folio(self):
        return self.Folio

    def pdf417bc(self, ted):
        bc = pdf417gen.encode(
            ted,
            security_level=5,
            columns=13,
            encoding='ISO-8859-1',
        )
        image = pdf417gen.render_image(
            bc,
            padding=10,
            scale=3,
        )
        return image

    def get_related_invoices_data(self):
        """
        List related invoice information to fill CbtesAsoc.
        """
        self.ensure_one()
        rel_invoices = self.search([
            ('number', '=', self.origin),
            ('state', 'not in',
                ['draft', 'proforma', 'proforma2', 'cancel'])])
        return rel_invoices

    def do_dte_send_invoice(self):
        for inv in self:
            if inv.sii_result not in ['', 'NoEnviado', 'Rechazado']:
                raise UserError("El documento %s ya ha sido enviado o está en cola de envío" % inv.Folio)
            inv.responsable_envio = self.env.user.id
            inv.sii_result = 'EnCola'
        self.env['sii.cola_envio'].create({
                                    'doc_ids': self.ids,
                                    'model': 'account.invoice',
                                    'user_id': self.env.user.id,
                                    'tipo_trabajo': 'envio',
                                    })

    def _giros_emisor(self):
        giros_emisor = []
        for turn in self.Emisor.Actecos:
            giros_emisor.extend([{'Acteco': turn}])
        return giros_emisor

    def _emisor(self):
        Emisor = collections.OrderedDict()
        if not self.Emisor.RUTEmisor:
            raise UserError("Debe ingresar el rut del emisor")
        Emisor['RUTEmisor'] = self.Emisor.RUTEmisor
        if not self.es_boleta() and not self.Emisor.GiroEmis:
            raise UserError("Debe ingresar la glosa descriptiva del giro del emisor")
        if self.es_boleta():
            Emisor['RznSocEmisor'] = self.Emisor.RznSoc
            if self.Emisor.GiroEmis:
                Emisor['GiroEmisor'] = util._acortar_str(self.Emisor.GiroEmisor, 80)
        else:
            Emisor['RznSoc'] = self.Emisor.RznSoc
            Emisor['GiroEmis'] = util._acortar_str(self.Emisor.GiroEmis, 80)
            if self.Emisor.Telefono:
                Emisor['Telefono'] = self.Emisor.Telefono
            Emisor['CorreoEmisor'] = self.Emisor.CorreoEmisor
            Emisor['item'] = self._giros_emisor()
        if self.Emisor.CdgSIISucur:
            Emisor['Sucursal'] = self.Emisor.Sucursal
            Emisor['CdgSIISucur'] = self.Emisor.CdgSIISucur
        Emisor['DirOrigen'] = util._acortar_str(self.Emisor.DirOrigen, 70)
        Emisor['CmnaOrigen'] = self.Emisor.CmnaOrigen
        Emisor['CiudadOrigen'] = self.Emisor.CiudadOrigen
        return Emisor

    def set_barcode(self, xml):
        ted = False
        folio = self.Folio
        timbre = """<TED><DD><RE>99999999-9</RE><TD>11</TD><F>1</F>\
<FE>2000-01-01</FE><RR>99999999-9</RR><RSR>\
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</RSR><MNT>10000</MNT><IT1>IIIIIII\
</IT1></DD></TED>"""
        parser = etree.XMLParser(remove_blank_text=True)
        result = etree.fromstring(timbre, parser=parser)
        xml.append(result)
        result.find('DD/RE').text = self.Emisor.RUTEmisor
        result.find('DD/TD').text = str(self.TipoDTE)
        result.find('DD/F').text = str(folio)
        if not self.FechaEmis:
            raise UserError("Problema con la fecha %s" % self.FechaEmis)
        result.find('DD/FE').text = self.FechaEmis
        if not self._receptor.RUTRecep:
            raise UserError("Completar RUT del Receptor")
        result.find('DD/RR').text = '55555555-5' if self.es_exportacion else self._receptor.RUTRecep
        result.find('DD/RSR').text = util._acortar_str(
                    self._receptor.RznSocRecep, 40)
        result.find('DD/MNT').text = str(self.MntTotal)
        if self.no_product:
            result.find('DD/MNT').text = '0'
        for line in self._lineas_detalle:
            if line.NroLinDet == 1:
                result.find('DD/IT1').text = util._acortar_str(line.NmbItem, 40)
                break
        resultcaf = self.caf_files.get_caf_file(folio, self.TipoDTE)
        result.find('DD').append(resultcaf.find('CAF'))
        timestamp = self.timestamp_timbre
        etree.SubElement(result.find('DD'), 'TSTED').text = timestamp
        keypriv = resultcaf.find('RSASK').text.replace('\t', '')
        ddxml = etree.tostring(result.find('DD'), encoding="ISO-8859-1", xml_declaration=False).replace(b'\n', b'')
        firma_caf = Firma({
                    'priv_key': keypriv,
                    'init_signature': False,
                    'rut_firmante': '60803000-K',
                    })
        frmt = firma_caf.generar_firma(ddxml)
        result.set("version", "1.0")
        ted_xml = etree.SubElement(result, 'FRMT')
        ted_xml.set("algoritmo", "SHA1withRSA")
        ted_xml.text = frmt
        ted = etree.tostring(result, encoding="ISO-8859-1", xml_declaration=False).replace(b'\n', b'')
        self.sii_barcode = ted
        image = False
        if ted:
            barcodefile = BytesIO()
            image = self.pdf417bc(ted)
            image.save(barcodefile, 'PNG')
            data = barcodefile.getvalue()
            self.sii_barcode_img = base64.b64encode(data)
        ted_xml = etree.SubElement(xml, 'TmstFirma')
        ted_xml.text = timestamp

    def _dte(self):
        dte = collections.OrderedDict()
        dte['Encabezado'] = self.Encabezado
        if not self._receptor.RUTRecep and not self.es_boleta() and not self.es_nc_boleta():
            raise UserError("Debe Ingresar RUT Receptor")
        dte['Encabezado']['Emisor'] = self._emisor()
        if not self.Detalle and self.TipoDTE not in [56, 61]:
            raise UserError("El documento debe llevar una línea, doc: %s\
folio: %s" % (
                                            self.TipoDTE,
                                            self.Folio,
                                        ))
        if not self._resumen and self.TipoDTE in [56, 61] \
                and not self.Referencia:
            raise UserError("Error en %s folio %s, Los documentos de tipo Nota,\
 deben incluir una referencia por obligación" % (self.TipoDTE, self.Folio))
        dte['item'] = self.Detalle
        if self.DscRcgGlobal:
            dte['itemDscRcgGlobal'] = self.DscRcgGlobal
        if self.Referencia:
            dte['itemRefs'] = self.Referencia
        return dte

    def _dte_to_xml(self, dte, tpo_dte="Documento"):
        #ted = dte[tpo_dte + ' ID']['TEDd']
        #dte[(tpo_dte + ' ID')]['TEDd'] = ''
        xml = util.create_xml(dte)
        return xml

    def _tag_dte(self):
        tpo_dte = "Documento"
        if self.TipoDTE == 43:
            tpo_dte = 'Liquidacion'
        elif self.es_exportacion:
            tpo_dte = 'Exportaciones'
        return tpo_dte

    def timbrar(self):
        if self.sii_xml_request:
            return
        folio = self.Folio
        tpo_dte = self._tag_dte()
        dte = collections.OrderedDict()
        dte[tpo_dte] = self._dte()
        xml = self._dte_to_xml(dte, tpo_dte)
        if self.caf_files:
            self.set_barcode(xml)
        #xml.set('xmlns', xmlns)
        xml.set('ID', self.ID)
        xml_pret = etree.tostring(
                xml,
                pretty_print=True, encoding="ISO-8859-1", xml_declaration=False).decode('ISO-8859-1')
        dte_xml = self.crear_DTE(xml_pret)
        type = 'doc'
        if self.es_boleta():
            type = 'bol'
        einvoice = self.firmar(dte_xml, self.ID, type)
        self.sii_xml_request = einvoice

    def timbrar_xml(self):
        if not self.sii_xml_request:
            return
        folio = self.Folio
        tpo_dte = self._tag_dte()
        xml = etree.fromstring(self.sii_xml_request.encode('ISO-8859-1'))
        if self.caf_files:
            self.set_barcode(xml)
        xml_pret = etree.tostring(
                xml,
                pretty_print=True, encoding="ISO-8859-1", xml_declaration=False).decode('ISO-8859-1')
        dte_xml = self.crear_DTE(xml_pret)
        type = 'doc'
        if self.es_boleta():
            type = 'bol'
        einvoice = self.firmar(dte_xml, self.ID, type)
        self.sii_xml_request = einvoice