def __calc_traslados(self, l_items, l_ieps, l_iva): """ Calcula los impuestos trasladados """ traslados = [] for tax in l_iva: # next two variables shall get lastest value of loop # It's not me. It is the Noe approach :| impto_id = 0 tasa = 0 importe_sum = Decimal(0) for item in l_items: if tax['ID'] == item['IMPUESTO_ID']: impto_id = item['IMPUESTO_ID'] tasa = item['TASA_IMPUESTO'] importe_sum += self.__narf( self.__calc_imp_tax( self.__calc_base( self.__abs_importe(item), self.__place_tasa(item['TASA_IEPS'])), self.__place_tasa(item['TASA_IMPUESTO']))) if impto_id > 0: traslados.append({ 'impuesto': 'IVA', 'clave': '002', 'importe': truncate(float(importe_sum), self.__NDECIMALS), 'tasa': tasa }) for tax in l_ieps: # next two variables shall get lastest value of loop # It's not me. It is the Noe approach :| impto_id = 0 tasa = 0 importe_sum = Decimal(0) for item in l_items: if tax['ID'] == item['IEPS_ID']: impto_id = item['IEPS_ID'] tasa = item['TASA_IEPS'] importe_sum += self.__narf( self.__calc_imp_tax( self.__abs_importe(item), self.__place_tasa(item['TASA_IEPS']))) if impto_id > 0: traslados.append({ 'impuesto': 'IEPS', 'clave': '003', 'importe': truncate(float(importe_sum), self.__NDECIMALS), 'tasa': tasa }) return traslados
def __calc_totales(self, l_items): totales = { 'MONTO_TOTAL': Decimal(0), 'IMPORTE_SUM': Decimal(0), 'IMPORTE_SUM_IMPUESTO': Decimal(0), 'IMPORTE_SUM_IEPS': Decimal(0), 'DESCTO_SUM': Decimal(0), } for item in l_items: totales['IMPORTE_SUM'] += self.__narf(item['IMPORTE']) totales['DESCTO_SUM'] += self.__narf(item['DESCTO']) totales['IMPORTE_SUM_IEPS'] += self.__narf( self.__calc_imp_tax(self.__abs_importe(item), self.__place_tasa(item['TASA_IEPS']))) totales['IMPORTE_SUM_IMPUESTO'] += self.__narf( self.__calc_imp_tax( self.__calc_base(self.__abs_importe(item), self.__place_tasa(item['TASA_IEPS'])), self.__place_tasa(item['TASA_IMPUESTO']))) totales['MONTO_TOTAL'] = self.__narf( totales['IMPORTE_SUM']) - self.__narf( totales['DESCTO_SUM']) + self.__narf( totales['IMPORTE_SUM_IEPS']) + self.__narf( totales['IMPORTE_SUM_IMPUESTO']) return { k: truncate(float(v), self.__NDECIMALS) for k, v in totales.items() }
def __calc_retenciones(self, l_items, l_riva): """ Calcula los impuestos retenidos """ retenciones = [] for tax in l_riva: # next two variables shall get lastest value of loop # It's not me. It is the Noe approach :| impto_id = 0 tasa = 0 importe_sum = Decimal(0) for item in l_items: if tax['ID'] == item['RET_ID']: impto_id = item['RET_ID'] tasa = item['TASA_RET'] importe_sum += self.__narf( self.__calc_imp_tax( self.__abs_importe(item), self.__place_tasa(item['TASA_RET']))) if impto_id > 0: retenciones.append({ 'impuesto': 'ISR', 'clave': '001', 'importe': truncate(float(importe_sum), self.__NDECIMALS), 'tasa': tasa }) return retenciones
def __calc_totales(self, l_items): totales = { 'MONTO_TOTAL': 0, 'MONTO_RETENCION': 0, 'IMPORTE_SUM': 0, 'IMPORTE_SUM_IMPUESTO': 0, 'IMPORTE_SUM_IEPS': 0, 'IMPORTE_SUM_RETENCION': 0, 'TASA_RETENCION': 0 } for item in l_items: totales['IMPORTE_SUM'] += (item['IMPORTE']) totales['IMPORTE_SUM_IEPS'] += self.__calc_imp_tax( item['IMPORTE'], self.__place_tasa(item['TASA_IEPS']) ) totales['IMPORTE_SUM_IMPUESTO'] += self.__calc_imp_tax( self.__calc_base(item['IMPORTE'], self.__place_tasa(item['TASA_IEPS'])), self.__place_tasa(item['TASA_IMPUESTO']) ) totales['TASA_RETENCION'] = item['TASA_RETENCION'] totales['IMPORTE_SUM_RETENCION'] += (item['IMPORTE_RETENCION']) totales['MONTO_RETENCION'] = totales['IMPORTE_SUM'] * totales['TASA_RETENCION'] totales['MONTO_TOTAL'] = totales['IMPORTE_SUM'] + totales['IMPORTE_SUM_IEPS'] + totales['IMPORTE_SUM_IMPUESTO'] - totales['MONTO_RETENCION'] # Sumar el acumulado de retencion de las partidas totales['MONTO_RETENCION'] += totales['IMPORTE_SUM_RETENCION'] return {k: truncate(v, self.__NDECIMALS) for k, v in totales.items()}
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 __narf(self, v): return Decimal(truncate(float(v), self.__NDECIMALS, True))
def __calc_imp_tax(self, imp, tasa): return truncate(float(Decimal(imp) * Decimal(tasa)), self.__NDECIMALS)
def __q_conceptos(self, conn, prefact_id): """ Consulta los conceptos de la prefactura en dbms """ SQL = """SELECT upper(inv_prod.sku) as sku, upper(inv_prod.descripcion) as descripcion, cfdi_claveprodserv.clave AS prodserv, cfdi_claveunidad.clave AS unidad, erp_prefacturas_detalles.cant_facturar AS cantidad, erp_prefacturas_detalles.precio_unitario, ( erp_prefacturas_detalles.cant_facturar * erp_prefacturas_detalles.precio_unitario ) AS importe, ( (erp_prefacturas_detalles.cant_facturar * erp_prefacturas_detalles.precio_unitario) * (erp_prefacturas_detalles.descto::double precision/100) ) AS descto, -- From this point onwards tax related columns ( (erp_prefacturas_detalles.cant_facturar * erp_prefacturas_detalles.precio_unitario) * erp_prefacturas_detalles.valor_ieps ) AS importe_ieps, ( ( (erp_prefacturas_detalles.cant_facturar * erp_prefacturas_detalles.precio_unitario) + ( (erp_prefacturas_detalles.cant_facturar * erp_prefacturas_detalles.precio_unitario) * erp_prefacturas_detalles.valor_ieps ) ) * erp_prefacturas_detalles.valor_imp ) AS importe_impuesto, (erp_prefacturas_detalles.valor_ieps * 100::double precision) AS tasa_ieps, (erp_prefacturas_detalles.valor_imp * 100::double precision) AS tasa_impuesto, erp_prefacturas_detalles.gral_ieps_id as ieps_id, erp_prefacturas_detalles.tipo_impuesto_id as impto_id FROM erp_prefacturas JOIN erp_prefacturas_detalles on erp_prefacturas_detalles.prefacturas_id=erp_prefacturas.id LEFT JOIN inv_prod on inv_prod.id = erp_prefacturas_detalles.producto_id LEFT JOIN inv_prod_unidades on inv_prod_unidades.id = erp_prefacturas_detalles.inv_prod_unidad_id LEFT JOIN inv_prod_tipos on inv_prod_tipos.id = inv_prod.tipo_de_producto_id LEFT JOIN cfdi_claveunidad on inv_prod_unidades.cfdi_unidad_id = cfdi_claveunidad.id LEFT JOIN cfdi_claveprodserv on inv_prod_tipos.cfdi_prodserv_id = cfdi_claveprodserv.id WHERE erp_prefacturas_detalles.prefacturas_id=""" rowset = [] for row in self.pg_query(conn, "{0}{1}".format(SQL, prefact_id)): rowset.append({ 'SKU': row['sku'], 'DESCRIPCION': unidecode.unidecode(row['descripcion']), 'UNIDAD': row['unidad'], 'PRODSERV': row['prodserv'], 'CANTIDAD': row['cantidad'], 'PRECIO_UNITARIO': self.__narf(row['precio_unitario']), 'IMPORTE': row['importe'], 'DESCTO': truncate(row['descto'], self.__NDECIMALS), # From this point onwards tax related elements 'IMPORTE_IEPS': row['importe_ieps'], 'IMPORTE_IMPUESTO': row['importe_impuesto'], 'TASA_IEPS': row['tasa_ieps'], 'TASA_IMPUESTO': row['tasa_impuesto'], 'IEPS_ID': row['ieps_id'], 'IMPUESTO_ID': row['impto_id'] }) return rowset
def __calc_imp_tax(self, imp, tasa): return truncate(imp * tasa, self.__NDECIMALS)