def ejemplo_cf_csv(): data = json.load(open("ejemplos/ejemplo_consumo_folios_csv.json")) folios = csv.reader(base64.b64decode(data['consumo_folios']).splitlines(), csv.excel, delimiter=',', quotechar='|') i = 0 listado = ['Fecha', 'Folio', 'RUTRecep', 'MntNeto', 'MntIVA', 'MntExento', 'MntTotal'] firma = Firma(data["firma_electronica"]) emisor = Emisor(data["Emisor"]) fechas = {} for row in folios: if i >0: if row[0] not in fechas: fechas[row[0]] = ConsumoFolios(emisor, firma) else: docu = Documento({ 'Fecha': row[0], 'Folio': int(row[2]), 'MntNeto': float(row[3]), 'MntIVA': float(row[4]), 'MntExento': float(row[5]), 'MntTotal': float(row[6]), 'Anulado': row[7], }, int(row[1]), resumen=True) fechas[row[0]].set_docu(docu) else: cabezera = row i += 1 for key, cf in fechas.items(): cf.validar() print (cf.sii_xml_request)
def Documento(self, vals): documentos = [] for dteDoc in vals: for docData in dteDoc.get("documentos", []): if not docData.get('sii_xml_request'): docu = Doc( docData, resumen=True ) docu.TipoDTE = dteDoc["TipoDTE"] if self.TipoOperacion == 'COMPRA' and \ (not docData['Encabezado'].get('Emisor') or \ docu._receptor.RUTRecep == self.Emisor.RUTEmisor): new_recep = { 'RUTRecep': self.Emisor.RUTEmisor, 'RznSocRecep': self.Emisor.RznSoc, 'CdgSIISucur': self.Emisor.CdgSIISucur, } new_emis = { 'RUTEmisor': docu._receptor.RUTRecep, 'RznSoc': docu._receptor.RznSocRecep, 'CdgSIISucur': docu._receptor.CdgSIISucur, } docu._dte_emisor = Emisor(new_emis) docu._receptor = Recep(new_recep) documentos.append(docu) self._documentos = documentos
def consulta_estado_dte(vals): firma = Firma(vals["firma_electronica"]) emisor = Emisor(vals["Emisor"]) conex = Conexion(emisor, firma, vals.get('api', False)) if vals.get('cesion'): conex.cesion = vals['cesion'] return conex._get_send_status(vals["codigo_envio"])
def consulta_reclamo_documento(vals): firma = Firma(vals["firma_electronica"]) emisor = Emisor(vals["Emisor"]) respuesta = {} for d in vals['DTEClaim']: key = "RUT%sT%sF%s" %(d['RUTEmisor'], d['TipoDTE'], d['Folio']) conexion = Conexion(emisor, firma) respuesta[key] = conexion.get_dte_claim(d) return respuesta
def consulta_reclamo_documento(vals): firma = Firma(vals["firma_electronica"]) emisor = Emisor(vals["Emisor"]) respuesta = [] for d in vals['Documento']: Documento.Emisor = emisor for r in d['documentos']: tipoDoc = int(d["TipoDTE"]) documento = Documento(r, resumen=True) documento.TipoDTE = tipoDoc conexion = Conexion(emisor, firma) respuesta.append(conexion.get_dte_claim(documento)) return respuesta
def consulta_estado_documento(vals): firma = Firma(vals["firma_electronica"]) emisor = Emisor(vals["Emisor"]) respuesta = {} for d in vals['Documento']: for r in d['documentos']: tipoDoc = int(d["TipoDTE"]) documento = Documento( r, emisor=emisor, resumen=True) documento.TipoDTE = tipoDoc conexion = Conexion(emisor, firma, vals.get('api', documento.es_boleta())) conexion.cesion = r.get('cesion', False) respuesta[documento.ID] = conexion._get_dte_status( documento) return respuesta
def procesar_documento(vals): firma = Firma(vals["firma_electronica"]) emisor = Emisor(vals["Emisor"]) verify = vals.get('verify', True) test = vals.get('test', False) _documentos = [] for docs in vals.get('Documento'): TipoDTE = docs.get('TipoDTE', 33) caf_file = docs.get('caf_file', []) for docData in docs["documentos"]: docu = Documento(docData, resumen=False) docu._dte_emisor = emisor docu._firma = firma docu.verify = verify docu.test = test docu.caf_file = caf_file docu.TipoDTE = TipoDTE _documentos.append(docu) return _documentos
def libro_resumen(dicDocs, csv=False): firma = Firma(dicDocs["firma_electronica"]) emisor = Emisor(dicDocs["Emisor"]) libro = Libro(emisor, firma) libro.set_periodo_tributario(dicDocs["periodo_tributario"]) libro.set_tipo_operacion(dicDocs["tipo_operacion"]) libro.set_tipo_libro(dicDocs["tipo_libro"]) test = dicDocs['test'] if 'test' in dicDocs else False envio = Envio(emisor, firma, test=test) respuesta = [] if csv: libro = _libro_csv(libro, csv) else: for dteDoc in dicDocs["Documentos"]: for docData in dteDoc["documentos"]: docu = Documento(docData, dteDoc["TipoDTE"]) libro.set_docu(docu) libro.validar() envio.setLibro(libro) respuesta = envio.do_libro_send() return respuesta
def Emisor(self, vals): if not hasattr(self, '_emisor'): self._emisor = Emis() self._emisor.set_from_keys(vals)
def Emisor(self): if not hasattr(self, '_emisor'): self._emisor = Emis() return self._emisor
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
def consulta_estado_dte(vals): firma = Firma(vals["firma_electronica"]) emisor = Emisor(vals["Emisor"]) conex = Conexion(emisor, firma) return conex._get_send_status(vals["codigo_envio"])
def consumo_folios_resumen(data, folios=False): test = data['test'] if 'test' in data else False emisor = Emisor(data["Emisor"]) firma = Firma(data["firma_electronica"]) fechas = {} if folios: i = 0 for row in folios: if i > 0: if row[0] not in fechas: fechas[row[0]] = ConsumoFolios(emisor, firma) if 'Correlativo' in data: fechas[row[0]].set_correlativo(data['Correlativo']) if 'SecEnvio' in data: fechas[row[0]].set_sec_envio(data['SecEnvio']) docu = Documento( { 'TasaImp': data["Emisor"]['ValorIva'], 'Fecha': row[0], 'Folio': int(row[2]), 'MntNeto': int(row[3]), 'MntIVA': int(row[4]), 'MntExento': int(row[5]), 'MntTotal': int(row[6]), 'Anulado': row[7], }, int(row[1]), resumen=True) fechas[row[0]].set_docu(docu) else: cabezera = row i += 1 elif 'Documentos' in data: for r in data['Documentos']: for d in r['documentos']: fecha = d['Encabezado']['IdDoc']['Fecha'] if fecha not in fechas: fechas[fecha] = ConsumoFolios(emisor, firma) if 'Correlativo' in data: fechas[fecha].set_correlativo(data['Correlativo']) if 'SecEnvio' in data: fechas[fecha].set_sec_envio(data['SecEnvio']) docu = Documento(d, r['TipoDTE']) fechas[fecha].set_docu(docu) else: cf = ConsumoFolios(emisor, firma) cf.FchInicio = data['FechaInicio'] cf.FchFinal = data['FechaFinal'] if 'Correlativo' in data: cf.set_correlativo(data['Correlativo']) if 'SecEnvio' in data: cf.set_sec_envio(data['SecEnvio']) envio = Envio(emisor, firma, test=test) envio.setLibro(cf) res = envio.do_consumo_folios_send() res.update({ 'correlativo': cf.Correlativo, 'fecha_inicio': cf.FchInicio, 'fecha_final': cf.FchFinal, 'total_neto': cf.total_neto, 'total_exento': cf.total_exento, 'total_iva': cf.total_iva, 'total': cf.total, 'total_boletas': cf.total_boletas, }) return [res] cfs = [] respuestas = [] envio = Envio(emisor, firma, test=test) for key, cf in fechas.items(): cf.validar() cfs.append(cf.sii_xml_request) envio.setLibro(cf) res = envio.do_consumo_folios_send() res.update({ 'correlativo': cf.Correlativo, 'fecha_inicio': cf.FchInicio, 'fecha_final': cf.FchFinal, 'total_neto': cf.total_neto, 'total_exento': cf.total_exento, 'total_iva': cf.total_iva, 'total': cf.total, 'total_boletas': cf.total_boletas, 'rangos': cf.get_rangos(), }) respuestas.append(res) return respuestas
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