Ver Mensaje Individual
  #3 (permalink)  
Antiguo 11/01/2013, 11:23
Avatar de korg1988
korg1988
 
Fecha de Ingreso: junio-2006
Ubicación: Santa Fe, Argentina
Mensajes: 825
Antigüedad: 18 años, 4 meses
Puntos: 19
Respuesta: Python, y problema de ejecucion!

Aca paso el codigo de la clase "Rastrillador" que es la clase encargada de realizar el proceso..

Quiero aclarar algo antes... y que no se olvide... TODO EL RESTO DEL SISTEMA funciona OK.. Solo falla en este momento, y no arroja NINGUNA clase de error o excepcion...

El bucle en cuestion donde la aplicacion muere es el siguiente, y se encuentra en el metodo "run" (que sobreescribe al metodo run de la clase Thread) ya que ejecuto el proceso como un hilo aparte
Código:
for asociado, total_asociados in Asociado.factory():
Código Python:
Ver original
  1. class Rastrillador(threading.Thread, QtCore.QObject):
  2.     "Clase que se encarga de revisar asociado por asociado. Es un thread independiente"
  3.     confirmado = QtCore.Signal() # sucede cuando todo esta ok, y se inicia el bucle de rastrillaje
  4.     actual = QtCore.Signal((Asociado, tuple))
  5.     terminado = QtCore.Signal()
  6.     error = QtCore.Signal((unicode,))
  7.    
  8.     def __init__(self, fecha_periodo):
  9.         threading.Thread.__init__(self)
  10.         QtCore.QObject.__init__(self)
  11.        
  12.         self.fecha_periodo = fecha_periodo
  13.  
  14.     def periodo_fue_rastrillado(self, fecha_periodo):
  15.         tabla = abrir_tabla(Config.config.get("db_paths", "uif_periodos"))
  16.         for registro in tabla:
  17.             if str(registro.periodo).zfill(6) == fecha_periodo.strftime("%m%Y"):
  18.                 return True
  19.         return False
  20.    
  21.     def __registrar_rastrillaje(self, operador, asoc_r, asoc_e):
  22.         a = abrir_tabla(Config.config.get("db_paths", "uif_periodos"))
  23.         a.append((self.fecha_periodo.strftime("%m%Y"), datetime.date.today(), operador, asoc_r, asoc_e))
  24.    
  25.     def run_dbf_filter(self):
  26.         """Llama a una rutina externa encargada de filtrar las tablas de movimientos correspondiendo al periodo dado.
  27.         A partir de aqui toda operación sobre estas tablas asume que los datos son del período en cuestión"""
  28.         cmd = Config.config.get("engines", "uif_filter").format(periodo=self.fecha_periodo.strftime("%m%Y"))
  29.         return subprocess.call(cmd, shell=True)
  30.    
  31.     def run(self):
  32.         index = 0
  33.         total_excedidos = 0
  34.        
  35.         try:
  36.             if self.periodo_fue_rastrillado(self.fecha_periodo):
  37.                 raise Exception(u"El período ya fue rastrillado")
  38.            
  39.             if sys.platform == "win32":
  40.                 if self.run_dbf_filter() != 0:
  41.                     raise Exception(u"No se ha podido ejecutar la rutina de filtrado.\nVerifique la misma en el archivo uif.cfg > engines > uif_filter.")
  42.         except dbf.DbfError:
  43.             print "error en dbf iniciando rastrillaje"
  44.         except Exception, e:
  45.             self.error.emit(e.message)
  46.         else:
  47.             self.confirmado.emit()
  48.  
  49.             for asociado, total_asociados in Asociado.factory():
  50.                 index += 1
  51.                 self.actual.emit(asociado, (index, total_asociados)) # Asociado, tupla_porcentaje
  52.                
  53.                 asociado.calcular_totales()
  54.                 tope_asociado = asociado.obtener_tope_uif()
  55.                
  56.                 total_asociado = asociado.total_amt + asociado.total_cac + asociado.total_cae
  57.                
  58.                 valor_tope_general = Parametros().valoruif
  59.                 try:
  60.                     """ Si no existe tope personal, entonces la expresion arroja un error, y caigo en el except, utilizando el tope general.
  61.                     Si existe un tope personal, lo comparo al general, y utilizo el de mayor valor"""
  62.                     valor_tope, tipo_tope = ((valor_tope_general, "generico")
  63.                                              if valor_tope_general > tope_asociado.valor else
  64.                                              (tope_asociado.valor, "personal"))
  65.                 except:
  66.                     valor_tope, tipo_tope = valor_tope_general, "generico"
  67.  
  68.                 esta_excedido = total_asociado > valor_tope
  69.  
  70.                 if esta_excedido:
  71.                     total_excedidos += 1
  72.                     exceso = total_asociado - valor_tope
  73.                     asociado.informar_exceso(fecha_periodo=self.fecha_periodo, exceso=exceso, tipo_tope=tipo_tope,
  74.                                              valor_tope=valor_tope, generar_documento=True)
  75.            
  76.             self.__registrar_rastrillaje(operador=obtener_nombre_operador(),
  77.                                          asoc_r=total_asociados, asoc_e=total_excedidos)
  78.             self.terminado.emit()

Aca te pongo la clase "Asociado"

Código Python:
Ver original
  1. class Asociado(object):
  2.  
  3.     @staticmethod
  4.     def factory(nro_socio=None):
  5.         tabla = abrir_tabla(Config.config.get("db_paths", "asociados"))
  6.         if nro_socio is not None:
  7.             registros = tabla.query("select * where nro_socio == " + str(nro_socio))
  8.         else:
  9.             registros = tabla
  10.        
  11.         total_registros = len(registros)
  12.         for registro in registros:
  13.             yield Asociado(nro_socio=registro.nro_socio, apeynom=registro.apeynom, cuil=registro.cuil), total_registros
  14.            
  15.             """Este modo fue anulado porque el campo fecha de algunos registros tenia un caracter extraño que hacia
  16.             crashear la libreria al acceder al mismo e intentar transformarlo a datetime"""
  17.             #yield Asociado(**dict(zip(tabla.field_names, registro))), total_registros
  18.            
  19.     def __init__(self, nro_socio, apeynom, cuil, **kwargs):
  20.         self.nro_socio = nro_socio
  21.         self.apeynom = apeynom
  22.         self.cuil = cuil
  23.        
  24.         self.total_amt = None
  25.         self.total_cac = None
  26.         self.total_cae = None
  27.        
  28.     def __calcular_total_amt(self):
  29.         self.total_amt = 0.00
  30.         tabla = abrir_tabla(Config.config.get("db_paths", "amt"))
  31.        
  32.         for registro in tabla.query("select * where nrotit1 == " + str(self.nro_socio)):
  33.             cotiz = registro.cotiz if registro.cotiz else 1
  34.             self.total_amt += round(registro.capital * cotiz, 2)
  35.    
  36.     def __calcular_total_cac(self):
  37.         self.total_cac = 0.00
  38.         tabla = abrir_tabla(Config.config.get("db_paths", "cac"))
  39.        
  40.         for registro in tabla.query("select * where nrocta == " + str(self.nro_socio)):
  41.             self.total_cac += registro.importe
  42.    
  43.     def __calcular_total_cae(self):
  44.         self.total_cae = 0.00
  45.         tabla = abrir_tabla(Config.config.get("db_paths", "cae"))
  46.        
  47.         for registro in tabla.query("select * where nrocta == " + str(self.nro_socio)):
  48.             self.total_cae += registro.importe
  49.    
  50.     def calcular_totales(self):
  51.         self.__calcular_total_amt()
  52.         self.__calcular_total_cac()
  53.         self.__calcular_total_cae()
  54.    
  55.     def obtener_tope_uif(self):
  56.         tabla = abrir_tabla(Config.config.get("db_paths", "uif_asociados"))
  57.         query = tabla.query("select * where nro_socio == " + str(self.nro_socio))
  58.        
  59.         # obtengo el registro con fecha mas actual
  60.         registro_mas_actual = None
  61.         for registro in query:
  62.             if not registro_mas_actual:
  63.                 registro_mas_actual = registro
  64.                 continue
  65.            
  66.             if registro.fecha >= registro_mas_actual.fecha:
  67.                 registro_mas_actual = registro
  68.                
  69.         return registro_mas_actual if registro_mas_actual else None # devuelvo valor de tope personal
  70.    
  71.     def guardar_tope(self, valor, fecha, motivo):
  72.         fecha_dbfdate = dbf.Date(fecha.year,fecha.month,fecha.day)
  73.        
  74.         tabla = abrir_tabla(Config.config.get("db_paths", "uif_asociados"))
  75.         tabla.append((self.nro_socio, fecha_dbfdate, obtener_nombre_operador(), motivo, valor))
  76.    
  77.     def informar_exceso(self, fecha_periodo, exceso, valor_tope, tipo_tope, generar_documento=False):
  78.         hoy = datetime.datetime.today()
  79.         hoy_dbfdate = dbf.Date(hoy.year,hoy.month,hoy.day)
  80.         periodo = fecha_periodo.strftime("%m%Y")
  81.        
  82.         if self.total_cae is None and self.total_cac is None and self.total_amt is None:
  83.             self.calcular_totales()
  84.        
  85.         tabla = abrir_tabla(Config.config.get("db_paths", "uif_registro"))
  86.         tabla.append((self.nro_socio, self.apeynom, hoy_dbfdate, periodo, obtener_nombre_operador(), self.total_cae, self.total_cac, self.total_amt, exceso))
  87.        
  88.         if generar_documento:
  89.             filename = "%s_%s" % (re.sub("[^A-Za-z0-9]", "_", self.apeynom.strip()), self.nro_socio)
  90.             base_dir_path = Config.config.get("documentos", "dir_path").strip("/")
  91.             periodo_dir_path = base_dir_path + "/" + fecha_periodo.strftime("%Y-%m")
  92.             doc_filename = periodo_dir_path + "/" + filename + ".txt"
  93.            
  94.             create_folder(periodo_dir_path)
  95.            
  96.             total = self.total_amt + self.total_cac + self.total_cae
  97.            
  98.             "Patterns"
  99.             lalign = "{:<15}" # alinea a la izquierda
  100.             ralign = "{:>15}" # alinea a la derecha con 15 lugares
  101.             pcurrency = "${:,.2f}" # 2 decimales; la "," separa millares (3,000,000.00)
  102.            
  103.             if self.cuil:
  104.                 cuil_text = "%s-%s-%s" % (str(self.cuil)[:2], str(self.cuil)[2:-1], str(self.cuil)[-1:])
  105.             else:
  106.                 cuil_text = "Falta"
  107.                
  108.             with open(doc_filename, "w+") as f:
  109.                 doc_content = (u"ASOCIACIÓN DE PROTECCIÓN RECIPROCA ENTRE PRODUCTORES AGROPECUARIOS\n"
  110.                 u"MODULO DE CONTROL UIF {fecha}\n\n"
  111.                 u"{asociado}\n"
  112.                 u"{t_nro_socio}{nro_socio}\n"
  113.                 u"{t_cuil}{cuil}\n"
  114.                 u"{t_periodo}{periodo}\n\n"
  115.                 u"{t_amt}{total_amt}\n"
  116.                 u"{t_cac}{total_cac}\n"
  117.                 u"{t_cae}{total_cae}\n"
  118.                 u"{t_total}{total}\n\n"
  119.                 u"{t_tope}{valor_tope}\n"
  120.                 u"{t_exceso}{exceso}\n\n"
  121.                 u"Notas:\n\n\n\n"
  122.                 u"Firma ____________________________________"
  123.                 .format(t_cuil=lalign.format(u"CUIL:"), t_nro_socio=lalign.format(u"Nro. Socio:"),
  124.                     t_periodo=lalign.format(u"Período"), t_amt=lalign.format(u"Total AMT:"), t_cac=lalign.format(u"Total CAC:"),
  125.                     t_cae=lalign.format(u"Total CAE:"), t_total=lalign.format(u"Total:"), t_exceso=lalign.format(u"Exceso:"),
  126.                     t_tope=lalign.format(u"Tope %s:" % tipo_tope), cuil=ralign.format(cuil_text),
  127.                     fecha=hoy.strftime("%d/%m/%Y"), asociado=self.apeynom,
  128.                     nro_socio=ralign.format("%s/%s" % (str(self.nro_socio)[:-1], str(self.nro_socio)[-1:])),
  129.                     periodo=ralign.format(fecha_periodo.strftime("%m/%Y")),
  130.                     total_amt=ralign.format(pcurrency.format(self.total_amt)),
  131.                     total_cac=ralign.format(pcurrency.format(self.total_cac)),
  132.                     total_cae=ralign.format(pcurrency.format(self.total_cae)),
  133.                     total=ralign.format(pcurrency.format(total)), exceso=ralign.format(pcurrency.format(exceso)),
  134.                     valor_tope=ralign.format(pcurrency.format(valor_tope))))
  135.                 f.write(doc_content.upper())

La funcion "abrir_tabla" que veras por todos lados es simplemente un shortcut, y la pongo aca
Código Python:
Ver original
  1. def abrir_tabla(archivo):
  2.     tabla = dbf.Table(archivo, codepage="\x02", ignore_memos=True)
  3.     tabla.open()
  4.     return tabla