def format_wrt(self, output_file, dat): c = Comprobante() c.Version = '3.3' c.Folio = "test attribute" #optional c.Fecha = '{0:%Y-%m-%dT%H:%M:%S}'.format(datetime.datetime.now()) c.Sello = "BLABLALASELLO" c.FormaPago = "01" #optional c.NoCertificado = "00001000000202529199" c.Certificado = "certificado en base64" c.SubTotal = "4180.0" c.Total = "4848.80" c.Moneda = "MXN" c.TipoCambio = "1.0" #optional (requerido en ciertos casos) c.TipoDeComprobante = 'I' # c.metodoDePago = "NO IDENTIFICADO" #optional c.LugarExpedicion = "60050" c.Emisor = pyxb.BIND() c.Emisor.Nombre = "PRODUCTOS INDUSTRIALES SAAR S.A. DE C.V." #opcional c.Emisor.Rfc = "PIS850531CS4" c.Emisor.RegimenFiscal = '601' c.Receptor = pyxb.BIND() c.Receptor.Nombre = "PRODUCTOS INDUSTRIALES SAAR S.A. DE C.V." #opcional c.Receptor.Rfc = "PIS850531CS4" c.Receptor.UsoCFDI = 'G01' c.Conceptos = pyxb.BIND( pyxb.BIND(Cantidad=5, ClaveUnidad='C81', ClaveProdServ='01010101', Descripcion='Palitroche', ValorUnitario='10', Importe='50')) writedom_cfdi(c.toDOM(), self.__MAKEUP_PROPOS, output_file)
def format_wrt(self, output_file, dat): self.logger.debug('dumping contents of dat: {}'.format(repr(dat))) def save(xo): tmp_dir = tempfile.gettempdir() f = os.path.join(tmp_dir, HelperStr.random_str()) writedom_cfdi(xo.toDOM(), self.__MAKEUP_PROPOS, f) return f def wa(tf): """ The sundry work arounds to apply """ HelperStr.edit_pattern('TipoCambio="1.0"', 'TipoCambio="1"', tf) HelperStr.edit_pattern( '(Importe=)"([0-9]*(\.[0-9]{0,1})?)"', lambda x: 'Importe="%.2f"' % (float(x.group(2)),), tf ) def wrap_up(tf, of): with open(of, 'w', encoding="utf-8") as a: a.write( sign_cfdi( dat['KEY_PRIVATE'], dat['XSLT_SCRIPT'], tf ) ) os.remove(tf) c = Comprobante() c.Version = '3.3' c.MetodoPago = "PPD" # optional and hardcode until ui can suply such value c.LugarExpedicion = dat['LUGAR_EXPEDICION'] c.Serie = dat['CONTROL']['SERIE'] # optional c.Folio = dat['CONTROL']['FOLIO'] # optional c.Fecha = dat['TIME_STAMP'] c.Sello = '__DIGITAL_SIGN_HERE__' c.FormaPago = dat["FORMA_PAGO"]['CLAVE'] # optional c.NoCertificado = dat['NUMERO_CERTIFICADO'] c.Certificado = dat['CERT_B64'] c.TipoDeComprobante = 'E' c.SubTotal = dat['TOTALES']['IMPORTE_SUM'] c.Total = dat['TOTALES']['MONTO_TOTAL'] if dat['MONEDA']['ISO_4217'] == 'MXN': c.TipoCambio = 1 else: # optional (requerido en ciertos casos) c.TipoCambio = truncate(dat['MONEDA']['TIPO_DE_CAMBIO'], self.__NDECIMALS) c.Moneda = dat['MONEDA']['ISO_4217'] c.Emisor = pyxb.BIND() c.Emisor.Nombre = dat['EMISOR']['RAZON_SOCIAL'] # optional c.Emisor.Rfc = dat['EMISOR']['RFC'] c.Emisor.RegimenFiscal = dat['EMISOR']['REGIMEN_FISCAL'] c.Receptor = pyxb.BIND() c.Receptor.Nombre = dat['RECEPTOR']['RAZON_SOCIAL'] # optional c.Receptor.Rfc = dat['RECEPTOR']['RFC'] c.Receptor.UsoCFDI = dat['RECEPTOR']['USO_CFDI'] c.Conceptos = pyxb.BIND() for i in dat['CONCEPTOS']: c.Conceptos.append(pyxb.BIND( Cantidad=i['CANTIDAD'], ClaveUnidad=i['UNIDAD'], ClaveProdServ=i['PRODSERV'], Descripcion=i['DESCRIPCION'], ValorUnitario=i['PRECIO_UNITARIO'], NoIdentificacion=i['SKU'], # optional Importe=i['IMPORTE'], Impuestos=self.__tag_impuestos(i) if i['TASA_IMPUESTO'] > 0 else None )) def traslado(c, tc, imp): return pyxb.BIND(TipoFactor='Tasa', Impuesto=c, TasaOCuota=tc, Importe=imp) def zigma(v): z = Decimal(0) for w in v: z += self.__narf(w['importe']) return z c.Impuestos = pyxb.BIND( TotalImpuestosRetenidos=0, TotalImpuestosTrasladados=zigma(dat['TRASLADOS']), Traslados=pyxb.BIND( *tuple([traslado(t['clave'], self.__place_tasa(t['tasa']), t['importe']) for t in dat['TRASLADOS']]) ) ) tmp_file = save(c) wa(tmp_file) wrap_up(tmp_file, output_file)
def format_wrt(self, output_file, dat): self.logger.debug('dumping contents of dat: {}'.format(repr(dat))) def save(xo): tmp_dir = tempfile.gettempdir() f = os.path.join(tmp_dir, HelperStr.random_str()) writedom_cfdi(xo.toDOM(), self.__MAKEUP_PROPOS, f) return f def wa(tf): """ The sundry work arounds to apply """ def two_dec_attr(attr): HelperStr.edit_pattern( '(' + attr + '=)"([0-9]*(\.[0-9]{0,1})?)"', lambda x: attr + '="%.2f"' % (float(x.group(2)), ), tf) HelperStr.edit_pattern('ValorUnitario="0.0"', 'ValorUnitario="0"', tf) HelperStr.edit_pattern('Importe="0(\.0{1})"', 'Importe="0"', tf) HelperStr.edit_pattern('Cantidad="1.0"', 'Cantidad="1"', tf) HelperStr.edit_pattern('TipoCambio="1.0"', 'TipoCambio="1"', tf) HelperStr.edit_pattern('Total="0.0"', 'Total="0"', tf) HelperStr.edit_pattern('SubTotal="0.0"', 'SubTotal="0"', tf) for a in ['Monto', 'ImpSaldoInsoluto', 'ImpPagado', 'ImpSaldoAnt']: two_dec_attr(a) def wrap_up(tf, of): with open(of, 'w', encoding="utf-8") as a: a.write(sign_cfdi(dat['KEY_PRIVATE'], dat['XSLT_SCRIPT'], tf)) os.remove(tf) def paste_tag_pagos(tf, elements): import xml.dom.minidom doc = xml.dom.minidom.Document() base_ns = "http://www.sat.gob.mx/Pagos" pagos = doc.createElementNS(base_ns, 'pago10:Pagos') pagos.setAttribute("xmlns:pago10", base_ns) pagos.setAttribute( "xsi:schemaLocation", "http://www.sat.gob.mx/Pagos http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos10.xsd" ) pagos.setAttribute("Version", "1.0") for d in elements: payment = doc.createElement('pago10:Pago') payment.setAttribute('NumOperacion', d['NUMERO_OPERACION']) payment.setAttribute('Monto', d['MONTO']) payment.setAttribute('MonedaP', d['ISO_4217']) #GAS payment.setAttribute('TipoCambioP', d['TIPO_DE_CAMBIO']) if (d['ISO_4217']) == 'USD': payment.setAttribute('TipoCambioP', d['TIPO_DE_CAMBIO']) payment.setAttribute('FormaDePagoP', d['CLAVE']) payment.setAttribute('FechaPago', d['TIME_STAMP']) dr = doc.createElement('pago10:DoctoRelacionado') dr.setAttribute('IdDocumento', d['UUID_DOC']) dr.setAttribute('ImpSaldoInsoluto', d['IMP_SALDO_INSOLUTO']) dr.setAttribute('ImpSaldoAnt', d['IMP_SALDO_ANT']) dr.setAttribute('ImpPagado', d['IMP_PAGADO']) dr.setAttribute('MonedaDR', d['MONEDA_DR']) dr.setAttribute('NumParcialidad', '1') dr.setAttribute('MetodoDePagoDR', 'PPD') if (d['MONEDA_DR']) == 'USD': if (d['ISO_4217']) == 'MXN': dr.setAttribute('TipoCambioDR', d['TIPO_DE_CAMBIO_DR']) payment.appendChild(dr) pagos.appendChild(payment) doc.appendChild(pagos) content_xml = output = doc.toprettyxml() chunk = "{}\n{}\n{}\n{}".format( '<cfdi:Complemento>', content_xml[22:], # omits xml declaration '</cfdi:Complemento>', '</cfdi:Comprobante>') HelperStr.edit_pattern('</cfdi:Comprobante>', chunk, tf) c = Comprobante() c.Version = '3.3' c.Fecha = dat['TIME_STAMP'] c.Sello = '__DIGITAL_SIGN_HERE__' c.Receptor = pyxb.BIND() c.Receptor.Nombre = dat['RECEPTOR']['RAZON_SOCIAL'] # optional c.Receptor.Rfc = dat['RECEPTOR']['RFC'] c.Receptor.UsoCFDI = dat['RECEPTOR']['USO_CFDI'] c.Emisor = pyxb.BIND() c.Emisor.Nombre = dat['EMISOR']['RAZON_SOCIAL'] # optional c.Emisor.Rfc = dat['EMISOR']['RFC'] c.Emisor.RegimenFiscal = dat['EMISOR']['REGIMEN_FISCAL'] c.LugarExpedicion = dat['LUGAR_EXPEDICION'] c.Serie = dat['CONTROL']['SERIE'] # optional c.Folio = dat['CONTROL']['FOLIO'] # optional c.NoCertificado = dat['NUMERO_CERTIFICADO'] c.Certificado = dat['CERT_B64'] c.TipoDeComprobante = 'P' c.Total = '0' c.SubTotal = '0' c.Moneda = dat['MONEDA']['ISO_4217'] c.Conceptos = pyxb.BIND() for i in dat['CONCEPTOS']: c.Conceptos.append( pyxb.BIND(Cantidad=i['CANTIDAD'], ClaveUnidad=i['UNIDAD'], ClaveProdServ=i['PRODSERV'], Descripcion=i['DESCRIPCION'], ValorUnitario=i['PRECIO_UNITARIO'], Importe=i['IMPORTE'])) tmp_file = save(c) paste_tag_pagos(tmp_file, dat['COMPLEMENTO_PAGOS']) wa(tmp_file) wrap_up(tmp_file, output_file)