Example #1
0
 def rellenar_tabla(self, facturas):
     """
     Rellena el model con los items de la consulta
     """        
     model = self.wids['tv_datos'].get_model()
     model.clear()
     self.wids['tv_datos'].freeze_child_notify()
     self.wids['tv_datos'].set_model(None)
     for cliente in facturas:
         padre = model.append(None, (cliente and cliente.nombre 
                                         or "Sin cliente", 
                                     "0.00", 
                                     "", 
                                     "0.00", 
                                     cliente and cliente.get_puid() or ""))
         for factura in facturas[cliente]:
             formapago = factura.get_forma_de_pago()
             importe = factura.calcular_total()
             pdte = factura.calcular_pendiente_de_documento_de_pago()
             model[padre][1] = utils.float2str(utils._float(model[padre][1])
                 + importe)
             model[padre][3] = utils.float2str(utils._float(model[padre][3])
                 + pdte)
             model.append(padre, (factura.numfactura, 
                                  utils.float2str(importe), 
                                  utils.str_fecha(factura.fecha), 
                                  utils.float2str(pdte), 
                                  factura.get_puid()))
     self.wids['tv_datos'].set_model(model)
     self.wids['tv_datos'].thaw_child_notify()
Example #2
0
def parsear_fraccion(txt):
    """
    Devuelve la cantidad de producto compra y unidad que hay que descontar 
    por cada cantidad de producto venta y unidad (que también se devuelven).
    Es necesario que venga la cantidadpc aunque en el registro, en el campo 
    "unidad" no aparece.
    """
    import re
    regexp_float = re.compile("-?\d+[\.,]?\d*")
    regexp_unidad = re.compile("\w+")
    cantidades = regexp_float.findall(txt)
    if len(cantidades) == 1:
        cantidadpc = cantidades[0]
        cantidadpv = '1'
        txt = txt.replace(cantidadpc, "")
    elif len(cantidades) == 2:
        cantidadpc, cantidadpv = cantidades[0:2]
        txt = txt.replace(cantidadpc, "")
        txt = txt.replace(cantidadpv, "")
    else:
        cantidadpc = '1'
        cantidadpv = '1'
    txt = txt.replace("/", "")
    unidadpc, unidadpv = regexp_unidad.findall(txt)[0:2]
    cantidadpc = utils._float(cantidadpc)
    cantidadpv = utils._float(cantidadpv)
    return cantidadpc, unidadpc, cantidadpv, unidadpv
 def cell_func(column, cell, model, itr, numcol):
     """
     Si la fila corresponde a un parte de producción no verificado, 
     lo colorea en rojo oscuro, si no, lo hace en verde oscuro.
     """
     consumido = model[itr][1]
     producido = model[itr][2]
     try:
         consumido = utils._float(consumido)
         producido = utils._float(producido)
         if consumido < producido:
             if numcol == 1:
                 color = "red"
             elif numcol == 2:
                 color = "blue"
         else:
             if numcol == 1:
                 color = "blue"
             else:
                 color = "red"
     except:
         color = None
     if consumido == 0 or producido == 0:
         color = None
         cell.set_property("cell-background", "red")
     else:
         cell.set_property("cell-background", None)
     cell.set_property("foreground", color)
Example #4
0
    def cambiar_existencias(self, cell, path, texto):
        # Chequeo permiso de escritura para camibar precios, existencias y demás:
        try:
            ventana = pclases.Ventana.select(pclases.Ventana.q.fichero == "productos.py")[0]
            if self.usuario and (not self.usuario.get_permiso(ventana).escritura or self.usuario.nivel >= 2):
                utils.dialogo_info(titulo = "USUARIO SIN PRIVILEGIOS", 
                                   texto = "Necesita permiso de escritura para modificar las existencias.", 
                                   padre = self.wids['ventana'])
                return
        except IndexError:
            if self.usuario and self.usuario.nivel >= 2:
                utils.dialogo_info(titulo = "USUARIO SIN PRIVILEGIOS", 
                                   texto = "No tiene permisos suficientes para modificar las existencias.", 
                                   padre = self.wids['ventana'])
                return

        model = self.wids['tv_datos'].get_model()
        id = model[path][-1]
        try:
            existencias = utils._float(texto)
        except ValueError:
            utils.dialogo_info(titulo = "ERROR DE FORMATO", 
                               texto = "El texto %s no es correcto." % (texto), 
                               padre = self.wids['ventana'])
        else:
            if "PC" in model[path][0]:
                producto = pclases.ProductoCompra.get(id)
                producto.sync()
                producto.existencias = existencias
                producto.syncUpdate()
                model[path][3] = utils.float2str(producto.existencias)
Example #5
0
 def cambiar_precio_ldp(self, cell, path, texto):
     """
     Cambia el precio de la LDP conforme al texto recibido.
     """
     try:
         precio = utils._float(texto)
     except:
         utils.dialogo_info(titulo = "ERROR", 
                            texto = 'El texto "%s" no es un número.' % (texto), 
                            padre = self.wids['ventana'])
     else:
         model = self.wids['tv_ldps'].get_model()
         ldp = pclases.LineaDePedido.get(model[path][-1])
         if ldp.precio != precio:
             ldp.precio = precio
             if ldp.get_lineas_de_venta() != [] \
                and utils.dialogo(titulo = "¿CAMBIAR PRECIO PRODUCTOS SERVIDOS?", 
                              texto = """
             Al cambiar el precio de una parte del presupuesto ofertado,             
             se cambian automáticamente los precios de los pedidos                   
             involucrados. También puede cambiar los albaranes y facturas            
             si el pedido ya ha sido servido.                                        
                                                                                     
             ¿Desea cambiar el precio de todos los artículos servidos                
             de este producto?                                                       
                                                                                     
             Si lo hace, se cambiará también en la factura en caso de                
             que se haya facturado el albarán o albaranes                            
             correspondientes.                                                       
             """, 
                             padre = self.wids['ventana']):
                 for ldv in ldp.get_lineas_de_venta():
                     ldv.precio = ldp.precio
         self.rellenar_tablas()
Example #6
0
 def cambiar_peso(self, cell, path, texto):
     """
     Cambia el peso de la bala editada.
     """
     try:
         peso = utils._float(texto)
     except ValueError:
         utils.dialogo_info(titulo = "ERROR", 
                            texto = "El valor tecleado %s no es correcto." % (peso), 
                            padre = self.wids['ventana'])
     else:
         model = self.wids['tv_balas'].get_model()
         try:
             bala = pclases.BalaCable.get(model[path][-1])
         except:
             utils.dialogo_info(titulo = "ERROR", 
                                texto = "No se pudo acceder a la bala.", 
                                padre = self.wids['ventana'])
             self.actualizar_tabla()
         else:
             difpeso = bala.peso - peso
             bala.peso = peso
             bala.syncUpdate()
             model[path][2] = utils.float2str(bala.peso, 1) 
             try:
                 totpantalla = utils.parse_float(
                     self.wids['e_pantalla'].get_text())
             except:
                 totpantalla = 0.0
             totpantalla -= difpeso
             self.rellenar_totales(totpantalla)
Example #7
0
 def seleccionar_cantidad(self, producto):
     """
     Muestra un diálogo para introducir la cantidad.
     Si el producto es un rollo, se introducirá en 
     metros cuadrados.
     Si es una bala, se introducirá en kilos.
     En las LDV se mantendrán también estas unidades
     ya que el precio por unidad va en función de 
     kilos y rollos en el producto.
     Cuando se haga el albarán es cuando habrá que
     calcular cuantos rollos (y cuáles en concreto)
     y cuántas balas entran. Aunque en realidad es 
     el usuario el que las seleccionará y el programa
     irá informando si se satisface la LDV o no.
     """
     if isinstance(producto, pclases.ProductoCompra):
         txt = "Introduzca la cantidad en %s." % (producto.unidad)
     else:
         txterror = "presupuestos::seleccionar_cantidad -> ERROR: Producto %s no es producto de compra ni de venta." % (producto)
         self.logger.error(txterror)
     cantidad = utils.dialogo_entrada(titulo = 'CANTIDAD', texto = txt, padre = self.wids['ventana'])
     try:
         cantidad = utils._float(cantidad)
         return cantidad
     except:
         utils.dialogo_info(titulo = 'ERROR', texto = 'La cantidad introducida no es correcta.', padre = self.wids['ventana'])
         return None
Example #8
0
def parsear_porcentaje(txt):
    """
    Devuelve la cantidad del porcentaje como fracción de 1.
    """
    import re
    regexp_float = re.compile("^-?\d+[\.,]?\d*")
    num = regexp_float.findall(txt)[0]
    return utils._float(num) / 100
Example #9
0
 def rellenar_tabla(self, res):
     """
     Rellena la tabla de datos con los resultados del diccionario.
     """
     model = self.wids['tv_datos'].get_model()
     model.clear()
     if not res:
         self.wids['e_total'].set_text("")
         return
     total = 0.0
     productos = {}  # Para facturar solo una vez cada producto a 
                     # cada cliente.
                     # TO-DO: OJO: Si se deja más de un producto sin 
                     # facturar en el mismo periodo de la consulta, solo se 
                     # va a ver una vez.
     for cliente in res:
         if cliente not in productos:
             productos[cliente] = []
         abuelo = model.append(None, (cliente.nombre, 
                                      "0.00", 
                                      cliente.get_puid()))
         for p in res[cliente]:
             try:
                 descripcion_producto = p.descripcion
                 puid_producto = p.get_puid()
             except AttributeError:
                 descripcion_producto = "Sin producto relacionado "\
                                        "(clases sueltas)"
                 puid_producto = ""
             padre = model.append(abuelo, (descripcion_producto, 
                                           "0.00", 
                                           puid_producto))
             for a in res[cliente][p]:
                 producto = a.get_or_guess_productoCompra()
                 if producto not in productos[cliente]:
                     importe = a.get_precio(cliente)
                     model.append(padre, (a.get_hora_y_descripcion(), 
                                          utils.float2str(importe), 
                                          a.get_puid()))
                     model[padre][1] = utils.float2str(
                         utils._float(model[padre][1]) + importe)
                     model[abuelo][1] = utils.float2str(
                         utils._float(model[abuelo][1]) + importe)
                     total += importe
                     productos[cliente].append(producto)
     self.wids['e_total'].set_text(utils.float2str(total))
Example #10
0
def numerals(nNumero, lFemenino=0, moneda = "", fraccion = "", autoomitir = False):
    """
    numerals(nNumero, lFemenino) --> cLiteral

    Convierte el número a una cadena literal de caracteres
    P.e.:       201     -->   "doscientos uno"
               1111     -->   "mil ciento once"

    <nNumero>       Número a convertir
    <lFemenino>     = 'true' si el Literal es femenino
                    P.e.:   201     -->    "doscientas una"
    Los parámetros "moneda" y "fracción" se usarán tras las
    cantidades enteras y decimales respectivamente. Si por
    ejemplo moneda == "euros" y fraccion == "céntimos", se
    obtendrá algo como:
    dieciséis euros con cincuenta céntimos
    (Legalmente se acepta tanto la preposición "con" como
    la conjunción copulativa "y" para expresión en letra
    de la moneda en España.)
    Si "autoomitir" es True y la parte fraccionaria es 0, 
    no la devuelve.
    """
    # Nos aseguramos del tipo de <nNumero>
    # se podría adaptar para usar otros tipos (pe: float)
    cRes = None
    if isinstance(nNumero, str):
        try:
            nNumero = long(nNumero)
        except ValueError:
            nNumero = _float(nNumero)
    if isinstance(nNumero, int):
        if nNumero<0:       cRes = "menos "+_numerals(-nNumero, lFemenino)
        elif nNumero==0:    cRes = "cero"
        else:               cRes = _numerals(nNumero, lFemenino)
        # Excepciones a considerar
        if not lFemenino and nNumero%10 == 1 and nNumero%100!=11:
            cRes += "o"
    elif isinstance(nNumero, (float, ffloat)):
        if nNumero >= 0:
            parte_entera = numerals(int(nNumero), lFemenino)
            numparte_decimal = int(round((nNumero % 1) * 100))
            if not(numparte_decimal == 0 and autoomitir):
                parte_decimal = numerals(numparte_decimal, lFemenino)
                cRes = "%s %s con %s %s" % (parte_entera, moneda, parte_decimal, fraccion)
            else:
                cRes = "%s %s" % (parte_entera, moneda)
        else:
            nNumero *= -1
            parte_entera = numerals(int(nNumero), lFemenino)
            parte_decimal = numerals(int(round((nNumero % 1) * 100)), lFemenino)
            cRes = "menos %s %s con %s %s" % (parte_entera, moneda, parte_decimal, fraccion)
    try:
        cRes = reduce(lambda x, y: x[-1] == " " and y == " " and x or x+y, cRes)    # Elimino los "dobles espacios".
    except TypeError:
        pass    # cRes es "" (vacío), None (no es iterable) o algo así.
    return cRes
Example #11
0
 def add(self, w):
     if self.producto != None:
         fecha = self.wids['e_fecha'].get_text()
         if fecha == '':
             utils.dialogo_info(titulo = 'SIN FECHA',
                                texto = 'Debe introducir la fecha del resultado de la prueba.')
             return
         resultado1 = self.wids['e_resultado1'].get_text()
         if resultado1 == '':
             utils.dialogo_info(titulo = 'SIN RESULTADO',
                                texto = 'Debe introducir el resultado de la prueba en resultado1.', 
                                padre = self.wids['ventana'])
             return
         resultado2 = self.wids['e_resultado2'].get_text()
         try:
             mfi = utils._float(self.wids['e_mfi'].get_text())
         except:
             utils.dialogo_info(titulo = "MFI INCORRECTO", 
                 texto = "No ha introducido un valor correcto para el MFI del proveedor.", 
                 padre = self.wids['ventana'])
             return
         try:
             resultado = float(resultado1)
             prueba = pclases.PruebaGranza(fecha = utils.parse_fecha(fecha),
                                                      resultado = resultado,
                                             productoCompra = self.producto, 
                                     fechaEntrada = mx.DateTime.localtime(), 
                                      silo = self.wids['e_silo'].get_text(), 
                                      lote = self.wids['e_lote'].get_text(), 
                                                                  mfi = mfi)
             if resultado2:
                 try:
                     resultado = float(resultado2)
                     prueba = pclases.PruebaGranza(
                         fecha = utils.parse_fecha(fecha),
                         resultado = resultado,
                         productoCompra = self.producto, 
                         fechaEntrada = mx.DateTime.localtime(), 
                         silo = self.wids['e_silo'].get_text(), 
                         lote = self.wids['e_lote'].get_text(),
                         mfi = mfi)
                 except Exception, msg:
                     utils.dialogo_info(titulo = 'ERROR', 
                                        texto = 'Verifique que ha introducido los datos correctamente.\n\n\nInformación de depuración: %s' % (msg), 
                                        padre = self.wids['ventana'])
         except Exception, msg:
             utils.dialogo_info(titulo = 'ERROR', 
                                texto = 'Verifique que ha introducido los datos correctamente.\n\n\nInformación de depuración: %s' % (msg), 
                                padre = self.wids['ventana'])
         self.wids['e_fecha'].set_text(utils.str_fecha(time.localtime()))
         self.wids['e_resultado1'].set_text('')
         self.wids['e_resultado2'].set_text('')
         self.wids['e_lote'].set_text('')
         self.wids['e_silo'].set_text('')
         self.wids['e_mfi'].set_text('0')
         self.rellenar_pruebas()
Example #12
0
def get_datos_from_tv(tv, filtro_ceros):
    """
    Devuelve una lista de tuplas. Cada tupla contiene los datos de las cells 
    del TreeView para cada fila.
    Si la fila es padre de otra fila, añade debajo de la misma las filas hijas 
    con espacios a su izquierda y un separador horizontal al final.
    """
    # PLAN: Se pueden volcar también fórmulas simplemente como texto en el csv.
    # P. ej.: "=A1+B1". El problema es que en los datos extraídos tal cual del 
    # TreeView no sé qué columnas corresponden a sumatorios. Necesitaría un 
    # marcado especial o un cell invisible dentro de la columna o algo así; y 
    # llevar además el control de la columna [A..n] y fila [1..m] para poder 
    # escribir correctamente la expresión.
    datos = []
    model = tv.get_model()
    numcols = len(tv.get_columns())
    for fila in model:
        filadato = []
        for i in xrange(numcols):
            index_columna = tv.get_column(i).get_data("q_ncol")
            if index_columna is None:
                index_columna = i
            valor = fila[index_columna]
            if isinstance(valor, bool):
                dato = valor and u"Sí".encode("iso-8859-15") or "No"
            else:
                try:
                    valor = utils._float(valor)
                    valor = str(valor).replace(".", ",")
                except ValueError:
                    pass    # No es flotante ni se puede convertir a él.
                finally:
                    try:
                        dato = ("%s" % 
                         (valor)).replace(";", ",").encode("iso-8859-15")
                    except UnicodeEncodeError:
                        dato = ("%s" % 
                         (valor)).replace(";", ",").encode("iso-8859-15", 
                                                           "replace")
                if i in filtro_ceros:
                    if dato in ("0", "0,0", "0,00", "0,000", 
                                 0,  "0.0", "0.00", "0.000"):
                        dato = ""   # Más rápido que una regexp.
            filadato.append(dato)
        datos.append(filadato)
        if hasattr(fila, 'iterchildren'):
            filas_hijas = agregar_hijos(fila, numcols, 1, tv)
            #if filas_hijas != [] and len(datos) > 1 and datos[-2][0] != "---":
            #    datos.insert(-1, ("---", ) * numcols)
            for fila_hija in filas_hijas:
                datos.append(fila_hija)
            #if filas_hijas != []:
            #    datos.append(("---", ) * numcols)
    return datos
Example #13
0
 def cambiar_resultado(self, tv, path, texto, columna):
     texto = texto.replace(" ", "")
     if texto != "":
         try:
             resultado = utils._float(texto)
         except:
             utils.dialogo_info('RESULTADO INCORRECTO',
                                'El número tecleado (%s) no es correcto.' % (texto), 
                                padre = self.wids['ventana'])
             return
     clase = self.get_clase(columna)
     columnaid = columna-1    # Porque en los IDS empieza por 0
     if clase != None:
         model = self.wids['tv_pruebas'].get_model()
         ids = map(int, model[path][-1].split(','))
         id = ids[columnaid]
         if id == 0:
             if texto != "":
                 fecha = time.strptime(model[path][0], '%d/%m/%Y')
                 try: 
                     prueba = clase(fecha = fecha, 
                                    resultado = resultado,
                                    loteCem = self.loteCem, 
                                    lote = None)
                 except TypeError:   # Es prueba de Humedad, no lleva relación con lote de fibra:
                     prueba = clase(fecha = fecha, 
                                    resultado = resultado,
                                    loteCem = self.loteCem)
                 ids[columnaid] = prueba.id
                 model[path][-1] = ','.join(map(str, ids))
                 model[path][columna] = "%.2f" % resultado
         else:
             prueba = clase.get(int(id))
             if texto == "": 
                 try:
                     prueba.destroySelf()
                 except:
                     utils.dialogo_info(titulo = "ERROR", 
                                        texto = "El resultado no se pudo eliminar.", 
                                        padre = self.wids['ventana'])
                     return
                 model[path][columna] = ""
                 ids[columnaid] = 0 
                 model[path][-1] = ','.join(map(str, ids))
                 self.rellenar_pruebas() # Prefiero esto a comprobar si la fila se ha quedado vacía, etc...
             else:
                 prueba.resultado = resultado
                 if columna != 6:
                     model[path][columna] = "%.2f" % resultado
                 else:
                     model[path][columna] = "%d" % resultado
         self.calcular_caracteristicas()
Example #14
0
 def cambiar_cantidad_ldp(self, cell, path, texto):
     """
     Cambia la cantidad de la LDP conforme al texto recibido.
     """
     try:
         cantidad = utils._float(texto)
     except:
         utils.dialogo_info(titulo = "ERROR", 
                            texto = 'El texto "%s" no es un número.' % (texto), 
                            padre = self.wids['ventana'])
     else:
         model = self.wids['tv_ldps'].get_model()
         ldp = pclases.LineaDePedido.get(model[path][-1])
         ldp.cantidad = cantidad
         self.rellenar_tablas()
Example #15
0
 def pedir_cantidad(self):
     """
     Pide una cantidad que debe ser un número float.
     """
     res = utils.dialogo_entrada(titulo = "CANTIDAD", 
                                 texto = "Introduzca la cantidad a consumir del producto de compra (sin unidades):", 
                                 padre = self.wids['ventana'])
     try:
         res = utils._float(res)
     except ValueError:
         utils.dialogo_info(titulo = "CANTIDAD INCORRECTA", 
                            texto = "El texto introducido %s no es correcto." % (res), 
                            padre = self.wids['ventana'])
         res = None
     return res
Example #16
0
 def editar_precio_srv(self, cell, path, texto):
     """
     Cambia el precio del servicio.
     """
     try:
         precio = utils._float(texto)
     except ValueError:
         utils.dialogo_info(titulo = "ERROR", 
                            texto = 'El texto "%s" no es un número.' % (texto), 
                            padre = self.wids['ventana'])
     else:
         model = self.wids['tv_servicios'].get_model()
         srv = pclases.Servicio.get(model[path][-1])
         srv.precio = precio
         self.rellenar_tablas()
Example #17
0
 def cambiar_cantidad(self, cell, path, texto):
     """
     Cambia la cantidad del descuento adicional por producto.
     """
     try:
         cantidad = utils._float(texto)
     except ValueError:
         utils.dialogo_info(titulo = "FORMATO INCORRECTO", 
                            texto = "El texto %s no es válido." % (texto), 
                            padre = self.wids['ventana'])
         return
     model = self.wids['tv_consumos'].get_model()
     if model[path].parent == None:
         idconsumo = model[path][-1]
         consumo = pclases.ConsumoAdicional.get(idconsumo)
         consumo.cantidad = cantidad
     self.rellenar_consumos_adicionales_por_producto()
Example #18
0
    def cambiar_precio_defecto(self, cell, path, texto):
        # Chequeo permiso de escritura para camibar precios, existencias y demás:
        try:
            ventana = pclases.Ventana.select(pclases.Ventana.q.fichero == "productos.py")[0]
            if self.usuario and (not self.usuario.get_permiso(ventana).escritura or self.usuario.nivel >= 2):
                utils.dialogo_info(titulo = "USUARIO SIN PRIVILEGIOS", 
                                   texto = "Necesita permiso de escritura para modificar el precio.", 
                                   padre = self.wids['ventana'])
                return
        except IndexError:
            if self.usuario and self.usuario.nivel >= 2:
                utils.dialogo_info(titulo = "USUARIO SIN PRIVILEGIOS", 
                                   texto = "No tiene permisos suficientes para modificar el precio.", 
                                   padre = self.wids['ventana'])
                return

        model = self.wids['tv_datos'].get_model()
        id = model[path][-1]
        try:
            precio = utils._float(texto)
        except ValueError:
            utils.dialogo_info(titulo = "ERROR DE FORMATO", 
                               texto = "El texto %s no es correcto." % (texto), 
                               padre = self.wids['ventana'])
        else:
            if "PC" in model[path][0]:
                producto = pclases.ProductoCompra.get(id)
            elif "PV" in model[path][0]:
                producto = pclases.ProductoVenta.get(id)
            else:
                return
            for numcol in range(5, 5 + len(self.__tarifas)):
                tarifa = self.__tarifas[numcol - 5]
                porcentaje = tarifa.get_porcentaje(producto, True)
                precio_tarifa = precio * (1 + porcentaje)
                tarifa.asignarTarifa(producto, precio_tarifa)
                precio_tarifa *= 1.18
                porcentaje *= 100.0
                model[path][numcol] = "%s (%s %%)" % (utils.float2str(precio_tarifa), 
                                                      utils.float2str(porcentaje, 1))
            producto.sync()
            producto.precioDefecto = precio
            producto.syncUpdate()
            model[path][4] = utils.float2str(producto.precioDefecto)
Example #19
0
def convertir_a_flotante(valor, vdefecto = 0.0, col = None):
    """
    Devuelve el valor por defecto "vdefecto" en caso de excepción.
    Antes de lanzarla, prueba como número flotante y como flotante con 
    símbolo de porcentaje.
    Fuerza la comprobación de porcentaje si col es distinto de None y 
    está entre las columnas a tratar así.
    """
    from utils import _float, parse_porcentaje
    try:
        if col != None and col.name in NOMBRES_COLUMNAS_PORCENTAJE:
            raise Exception, "Forzando comprobación de porcentaje."
        return _float(valor)
    except:
        try:
            # 5 decimales de precisión es bastante para un porcentaje. Es lo 
            # que uso también para mostrar en pantalla (ver el getter arriba).
            return round(parse_porcentaje(valor, fraccion = True), 5)
        except:
            return vdefecto
Example #20
0
 def crear_bala(self, boton = None, peso = None):
     """
     Crea una bala del producto mostrado en pantalla e introduce 
     su información en el TreeView. El peso lo solicita en una 
     ventana de diálogo.
     Si se recibe peso, debe ser un float.
     """
     # TODO: Hacer que el peso lo tome del puerto serie y se le pase a 
     # esta función.
     producto = utils.combo_get_value(self.wids['cbe_producto'])
     if producto == None:
         utils.dialogo_info(titulo = "SELECCIONE UN PRODUCTO", 
                 texto = "Debe seleccionar un producto en el desplegable.", 
                 padre = self.wids['ventana'])
     else:
         if peso == None:
             peso = utils.dialogo_entrada(titulo = "PESO", 
                                          texto = "Introduzca peso:", 
                                          padre = self.wids['ventana'], 
                                          valor_por_defecto = "0")
             try:
                 peso = utils._float(peso)
             except ValueError:
                 utils.dialogo_info(titulo = "ERROR", 
                                    texto = "El valor tecleado %s no es correcto." % (peso), 
                                    padre = self.wids['ventana'])
                 peso = 0
         nueva_bala = self.crear_objeto_bala(producto, peso)
         if nueva_bala == None:
             utils.dialogo_info(titulo = "ERROR", 
                                texto = "La bala no se pudo crear. Inténtelo de nuevo.", 
                                padre = self.wids['ventana'])
         else:
             self.add_nueva_bala_tv(nueva_bala)
             try:
                 totpantalla = utils.parse_float(
                     self.wids['e_pantalla'].get_text())
             except:
                 totpantalla = 0.0
             totpantalla += peso
             self.rellenar_totales(totpantalla)
Example #21
0
 def cambiar_valor(self, cell, path, text):
     model = self.wids['tv_datos'].get_model()
     if model[path][0] == "":
         if model[path].parent != None:
             id = model[path].parent[0]
             clase = model[path].parent[-1]
             campo = model[path][1]
             objeto = eval("pclases.%s.get(%d)" % (clase, int(id)))
             objeto.syncUpdate()
             try:
                 try:
                     setattr(objeto, campo, text)
                 except Exception, inner_e:
                     try:
                         setattr(objeto, campo, utils._float(text))
                     except Exception, float_e:
                         try:
                             setattr(objeto, campo, int(text))
                         except Exception, int_e:
                             raise inner_e
                 model[path][2] = getattr(objeto, campo)
Example #22
0
def agregar_hijos(fila, numcols, numespacios, tv):
    """
    Devuelve una lista con los hijos de "fila", y éstos a 
    su vez con sus hijos, etc... en diferentes niveles.
    numespacios normalmente será el nivel de profundidad de 
    la recursión * 2.
    """
    iterator_hijos = fila.iterchildren()
    if iterator_hijos == None:
        return []
    else:
        filas = []
        for hijo in iterator_hijos:
            filahijo = []
            for col in xrange(numcols):
                index_columna = tv.get_column(col).get_data("q_ncol")
                if index_columna is None:
                    index_columna = col
                valor = hijo[index_columna]
                if isinstance(valor, bool):
                    dato = valor and u"Sí".encode("iso-8859-15") or "No"
                else:
                    try:
                        valor = utils._float(valor)
                        valor = str(valor).replace(".", ",")
                    except ValueError:
                        pass    # No es flotante ni se puede convertir a él.
                    finally:
                        dato = ("%s" % 
                            valor).replace(";", ",").encode("iso-8859-15", 
                                                            "replace")
                        # Por si acaso trae un entero, un float o algo asina.
                if index_columna == 0:
                    filahijo.append("%s%s" % ("> " * numespacios, dato))
                else:
                    filahijo.append(dato)     
            filas += [filahijo] + agregar_hijos(hijo, numcols, numespacios + 1, tv)
        return filas
def rellenar_subtabla(filas, w):
    """
    Introduce las filas en el modelo del widget w y devuelve los totales
    de los campos numéricos en una lista (incluidos los IDs aunque no 
    tenga sentido).
    """
    totales = []
    model = w.get_model()
    model.clear()
    for fila in filas:
        filaformateada = []
        for valor in fila:
            try:
                strv = utils.float2str(valor)
            except:
                strv = valor
            filaformateada.append(strv)
        model.append(filaformateada)
        # Actualizo lista de totales con los valores numéricos únicamente
        offset = 0
        for i in range(len(fila)):
            try:
                valor = utils._float(fila[i])
            except ValueError:
                if fila[i] == "": # Es cadena vacía para el personal indirecto
                    valor = 0
                else:   # Si no, definitivamente es un campo no numérico.
                    offset -= 1 # Para saltar las primeras columnas de texto
            else:
                idest = i + offset
                try:
                    totales[idest] += valor
                except IndexError:
                    while len(totales) < idest:
                        totales.append(0)
                    totales.append(valor)
    return [totales]
Example #24
0
 def rellenar_tabla(self, facturas):
     """
     Rellena el model con los items de la consulta
     """        
     model = self.wids['tv_datos'].get_model()
     model.clear()
     totfact = totsiniva = totbeneficio = 0.0
     self.wids['tv_datos'].freeze_child_notify()
     self.wids['tv_datos'].set_model(None)
     nodos_formapago = {}
     for f in facturas:
         formapago = f.get_forma_de_pago()
         try:
             abuelo = nodos_formapago[formapago]
         except KeyError:
             abuelo = model.append(None, (formapago, 
                                          "", 
                                          "", 
                                          "0.00", 
                                          "0.00", 
                                          "0.00", 
                                          0))
             nodos_formapago[formapago] = abuelo
         total = f.calcular_total()
         iva = f.calcular_total_iva()
         irpf = f.calcular_total_irpf()
         siniva = total - iva - irpf
         beneficio = f.calcular_beneficio()
         totfact += total
         totsiniva += siniva
         totbeneficio += beneficio
         model[abuelo][3] = utils.float2str(utils._float(model[abuelo][3])
             + total)
         model[abuelo][4] = utils.float2str(utils._float(model[abuelo][4])
             + siniva)
         model[abuelo][5] = utils.float2str(utils._float(model[abuelo][5])
             + beneficio)
         padre = model.append(abuelo, (utils.str_fecha(f.fecha), 
                                       f.numfactura, 
                                       f.cliente and f.cliente.nombre or "", 
                                       utils.float2str(total), 
                                       utils.float2str(siniva), 
                                       utils.float2str(beneficio), 
                                       f.id))
         for srv in f.servicios:
             model.append(padre, (utils.float2str(srv.cantidad, 
                                                  autodec = True), 
                                  utils.float2str(srv.precio), 
                                  srv.concepto, 
                                  utils.float2str(srv.calcular_subtotal() 
                                                  * (1 + f.iva)), 
                                  utils.float2str(srv.calcular_subtotal()), 
                                  utils.float2str(srv.calcular_beneficio()), 
                                  srv.id))
         for ldv in f.lineasDeVenta:
             model.append(padre, (utils.float2str(ldv.cantidad, 
                                                  autodec = True), 
                                  utils.float2str(ldv.precio), 
                                  ldv.producto.descripcion, 
                                  utils.float2str(ldv.calcular_subtotal() 
                                                  * (1 + f.iva)), 
                                  utils.float2str(ldv.calcular_subtotal()), 
                                  utils.float2str(ldv.calcular_beneficio()), 
                                  ldv.id))
     self.rellenar_totales(totfact, totsiniva, totbeneficio)
     self.wids['tv_datos'].set_model(model)
     self.wids['tv_datos'].thaw_child_notify()
 def rellenar_tabla_por_proveedor(self, resultados):
     """
     Rellena el model con los items de la consulta
     """        
     model = self.wids['tv_datos'].get_model()
     model.clear()
     totfact = totsiniva = totbeneficio = totbeneficio_cobro = 0.0
     self.wids['tv_datos'].freeze_child_notify()
     self.wids['tv_datos'].set_model(None)
     totcobrado = totpendiente = 0.0
     total_costo = total_costo_cobrado = 0.0
     padres = {}
     for material in resultados:
         for fecha in resultados[material]:
             for ldv in resultados[material][fecha]:
                 # Para que coincidan los totales con la suma de las 
                 # columnas y por coherencia con todas las cifras de la 
                 # ventana, es necesario redondear a 2 decimales.
                 subtotal = round(ldv.get_subtotal(iva = True), 2)
                 subtotal_siva = round(ldv.get_subtotal(iva = False), 2)
                 beneficio = round(ldv.calcular_beneficio(), 2)
                 costo = round(ldv.calcular_precio_costo()*ldv.cantidad, 2)
                 if ldv.facturaVenta:
                     fac_alb_tic = ldv.facturaVenta.numfactura
                     cobradofra = ldv.facturaVenta.calcular_cobrado()
                     pendientefra = ldv.facturaVenta.calcular_pendiente_cobro()
                     try:
                         fraccion = cobradofra / (cobradofra + pendientefra)
                     except ZeroDivisionError:
                         fraccion = 1.0
                     cobrado = subtotal * fraccion
                     pendiente = subtotal - cobrado
                     beneficio_cobro = beneficio * fraccion
                     costo_cobrado = costo * fraccion
                 elif ldv.albaranSalida:
                     fac_alb_tic = ldv.albaranSalida.numalbaran
                     cobrado = 0.0
                     pendiente = subtotal
                     beneficio_cobro = 0.0
                     costo_cobrado = 0.0
                 elif ldv.ticket:
                     fac_alb_tic = "Ticket %d" % ldv.ticket.numticket
                     cobrado = subtotal
                     pendiente = 0.0
                     beneficio_cobro = beneficio
                     costo_cobrado = costo
                     # Los tickets se asume que se cobran siempre, por 
                     # tanto el costo de los productos sobre lo cobrado 
                     # es del 100%.
                 else:
                     fac_alb_tic = ""
                     cobrado = pendiente = beneficio_cobro = 0.0
                     costo_cobrado = 0.0
                 desc_producto = utils.wrap(ldv.producto.descripcion, 40)
                 try:
                     beneficio_costo = 100.0 * beneficio / costo
                 except ZeroDivisionError:
                     beneficio_costo = 0.0
                 proveedor = ldv.get_proveedor()
                 try:
                     padre = padres[proveedor]
                 except KeyError:
                     padre = padres[proveedor] = model.append(None, 
                         (proveedor and proveedor.nombre 
                             or "Sin proveedor", 
                          "-", 
                          utils.float2str(0.0), 
                          utils.float2str(0.0), 
                          utils.float2str(0.0),  
                          proveedor and proveedor.get_puid() or ""
                         ))
                 model.append(padre, (desc_producto, 
                                      fac_alb_tic, 
                                      utils.float2str(subtotal), 
                                      utils.float2str(subtotal_siva), 
                                      "%s (%s%%)" % (
                                         utils.float2str(beneficio), 
                                         utils.float2str(
                                                 beneficio_costo)), 
                                      ldv.get_puid()
                                     ))
                 # Actualizo totales en memoria y en nodos padre TreeView
                 totfact += subtotal
                 totsiniva += subtotal_siva
                 totbeneficio += beneficio
                 totbeneficio_cobro += beneficio_cobro
                 totcobrado += cobrado
                 totpendiente += pendiente
                 total_costo += costo
                 total_costo_cobrado += costo_cobrado
                 model[padre][2] = utils.float2str(
                                         utils._float(model[padre][2]) 
                                                      + subtotal)
                 model[padre][3] = utils.float2str(
                                         utils._float(model[padre][3]) 
                                                      + subtotal_siva)
                 model[padre][4] = utils.float2str(
                                         utils._float(model[padre][4]) 
                                                      + beneficio)
     self.rellenar_totales(totfact, totsiniva, totbeneficio, 
                           totcobrado, totpendiente, totbeneficio_cobro, 
                           total_costo, total_costo_cobrado)
     self.wids['tv_datos'].set_model(model)
     self.wids['tv_datos'].thaw_child_notify()
 def cambiar_importe_libre(self, cell, path, texto):
     """
     Guarda el plus de no absentismo del empleado en un registro de 
     control de horas dentro del rango de fechas de la consulta.
     La fecha elegida para guardar el plus es la fecha intermedia entre 
     los dos extremos, así aparecerá el plus de no absentismo en el mes 
     que sea aunque las fechas inicial y final varíen ligeramente.
     El truco para no tener que buscar el registro elegido en dos consultas 
     ligeramente distintas y así que al cambiar un 100 por 120 no se 
     convierta mágicamente en 220 (100 en un registro y 120 en otro) es 
     guardar siempre la diferencia entre el texto escrito y el nuevo.
     PLAN: Se podría tratar de usar el campo de nóminas dedicado a este 
     plus, pero se intenta mantener todo lo independiente posible esas 
     tablas, ya que probablemente la ventana de nóminas será DEPRECATED 
     para la siguiente versión. De cualquier forma, siempre se podría 
     tratar de actualizar los valores de la nómina desde esta ventana. 
     También hay que tener en cuenta que las nóminas son para meses 
     completos, mientras que esta consulta está enfocada a granularidad 
     que va desde un solo día a años enteros.
     """
     try:
         pabs = utils._float(texto)
     except:
         utils.dialogo_info(titulo = "ERROR DE FORMATO", 
             texto = "El texto tecleado %s no es un número." % texto, 
             padre = self.wids['ventana'])
         return
     model = self.wids['tv_plus'].get_model()
     id = model[path][-1]
     if not isinstance(id, int):
         try:
             id = int(utils._float(id))
         except:
             txt = ("Identificador %s no se pudo convertir a entero. An" + 
                    "ulo edición de importe libre" % id)
             self.logger.error("%consulta_mensual_nominas.py::cambiar_importe_libre -> %s" % (self.usuario and self.usuario.usuario + ": " or "", txt))
             return
     empleado = pclases.Empleado.get(id)
     f1 = self.inicio
     f2 = self.fin
     fecha = mx.DateTime.DateTimeFromTicks((f1.ticks() + f2.ticks()) / 2)
     # Por si acaso, aseguro día, mes y año redondos, sin hora.
     fecha = mx.DateTime.DateTimeFrom(day = fecha.day, 
                                      month = fecha.month, 
                                      year = fecha.year)
     valor_anterior = utils._float(model[path][4])
     a_guardar = pabs - valor_anterior
     try:
         ch = pclases.ControlHoras.select(pclases.AND(
                 pclases.ControlHoras.q.empleadoID == empleado.id, 
                 pclases.ControlHoras.q.fecha == fecha))[0]
     except IndexError:  # Es posible que no haya registro en esa fecha.
         ch = pclases.ControlHoras(fecha = fecha, 
                                   empleado = empleado, 
                                   grupo = None, 
                                   horasRegulares = 0.0, 
                                   nocturnidad = False,
                                   horasExtraDiaProduccion = 0.0, 
                                   horasExtraDiaMantenimiento = 0.0, 
                                   horasExtraDiaAlmacen = 0.0, 
                                   horasExtraDiaVarios = 0.0, 
                                   horasExtraNocheProduccion = 0.0, 
                                   horasExtraNocheMantenimiento = 0.0, 
                                   horasExtraNocheAlmacen = 0.0, 
                                   horasExtraNocheVarios = 0.0, 
                                   horasAlmacen = 0.0, 
                                   horasVarios = 0.0, 
                                   varios = '', 
                                   comentarios = '', 
                                   bajaLaboral = False, 
                                   vacacionesYAsuntosPropios = False, 
                                   festivo = False, 
                                   plusAbsentismo = 0.0, 
                                   conceptoLibre = "", 
                                   importeLibre = 0.0)
     ch.importeLibre += a_guardar  # Por si era el mismo, sumo.
     ch.syncUpdate()
     model[path][4] = utils.float2str(
         empleado.calcular_importe_libre(self.inicio, 
                                         self.fin))
     total = sum([utils._float(model[p][4]) for p in range(len(model))])
     self.wids['tv_totales_plus'].get_model()[0][2] = utils.float2str(total)
    def buscar(self, boton):
        # DONE: Faltan los abonos por descontar.
        fechaini = self.wids["e_fechaini"].get_text().strip()
        if fechaini:
            try:
                fechaini = utils.parse_fecha(fechaini)
            except (ValueError, TypeError):
                utils.dialogo_info(
                    titulo="ERROR EN FECHA INICIAL",
                    texto="El texto «%s» no es una fecha correcta." % fechaini,
                    padre=self.wids["ventana"],
                )
                fechaini = None
        fechafin = self.wids["e_fechafin"].get_text().strip()
        if fechafin:
            try:
                fechafin = utils.parse_fecha(fechafin)
            except (ValueError, TypeError):
                utils.dialogo_info(
                    titulo="ERROR EN FECHA FINAL",
                    texto="El texto «%s» no es una fecha correcta." % fechafin,
                    padre=self.wids["ventana"],
                )
                fechafin = None
        if fechaini and fechafin and fechafin < fechaini:
            fechaini, fechafin = fechafin, fechaini
            self.wids["e_fechaini"].set_text(utils.str_fecha(fechaini))
            self.wids["e_fechafin"].set_text(utils.str_fecha(fechafin))
        if fechafin:
            FV = pclases.FacturaVenta
            VC = pclases.VencimientoCobro  # Para asegurarme de
            # que tiene vencimientos.
            FDA = pclases.FacturaDeAbono
            C = pclases.Cobro
            T = pclases.Tarea
            if fechaini:
                facturas = FV.select(
                    pclases.AND(FV.q.fecha >= fechaini, FV.q.fecha <= fechafin, VC.q.facturaVentaID == FV.q.id)
                )
                # Busco los abonos (facturas de abono, en realidad, que no
                # tienen por qué tener la misma fecha) que no hayan sido
                # incluidos en facturas (porque si no el importe ya se habría
                # contado en la factura anterior) ni en pagarés (porque
                # entonces ya estarían en un documento de pago y por tanto
                # no deberían aparecer en esta consulta)
                # ...
                # He decidido que no voy a sacar los abonos. No van a tener
                # ventana de seguimiento y no se le pueden relacionar tareas.
                # Además, esta ventana era para reclamar pagos, no para pagar.
                # abonos = FDA.select(pclases.AND(
                #    FDA.q.fecha >= fechaini,
                #    FDA.q.fecha <= fechafin))
                abonos = []
            else:
                facturas = FV.select(pclases.AND(FV.q.fecha <= fechafin, VC.q.facturaVentaID == FV.q.id))
                # abonos = FDA.select(FDA.q.fecha <= fechafin)
                abonos = []
            # No me queda otra que filtrar así aunque sea lento:
            abonos_pendientes = []
            for a in abonos:
                if not a.abono:
                    continue  # ¿Error de borrado de un abono? Mmm... mal rollo.
                if a.abono.facturasVenta:
                    continue
                if a.cobros:  # Cada cobro de abono está relacionado
                    # con un pagaré (o con lo que sea en un
                    # posible futuro, el caso es que no
                    # estaría pendiente).
                    continue
                abonos_pendientes.append(a)
            from ventana_progreso import VentanaProgreso

            vpro = VentanaProgreso(padre=self.wids["ventana"])
            vpro.mostrar()
            txtvpro = "Buscando facturas sin documento de pago..."
            nodos_clientes = {}
            total = 0.0
            i = 0.0
            vpro.set_valor(i, txtvpro)
            model = self.wids["tv_datos"].get_model()
            model.clear()
            facturas_added = []
            # Aprovecho para chequear alarmas automáticas.
            pclases.Alarma.crear_alarmas_automaticas(facturas)
            for f in facturas:
                # Aquí voy a hacer un segundo filtro usando la cantidad
                # pendiente de cobro de cada factura.
                # pendiente = f.calcular_pendiente_cobro()
                pendiente = f.calcular_pendiente_de_documento_de_pago()
                pendiente = round(pendiente, 2)
                if pendiente and f not in facturas_added:
                    total += pendiente
                    cliente = f.cliente
                    if cliente not in nodos_clientes:
                        tmp_nodo = model.append(None, (cliente.nombre, "", "", "", "0", "", cliente.id))
                        nodos_clientes[cliente] = {"nodo_cliente": tmp_nodo}
                    obra = f.obra
                    nodo_cliente_padre = nodos_clientes[cliente]["nodo_cliente"]
                    if obra not in nodos_clientes[cliente]:
                        nodos_clientes[cliente][obra] = model.append(
                            nodo_cliente_padre,
                            (obra and obra.nombre or "Sin obra", "", "", "", "0", "", obra and obra.id or 0),
                        )
                    fechas_vto = f.vencimientosCobro[:]
                    fechas_vto.sort(lambda v1, v2: (v1.fecha < v2.fecha and -1) or (v1.fecha > v2.fecha and 1) or 0)
                    fechas_vto = [utils.str_fecha(v.fecha) for v in f.vencimientosCobro]
                    vtos = "; ".join(fechas_vto)
                    nodo_padre = nodos_clientes[cliente][obra]
                    last_evento = f.get_last_evento()
                    if last_evento:
                        last_evento = "[%s] %s" % (utils.str_fechahora(last_evento.fechahora), last_evento.texto)
                    else:
                        last_evento = ""
                    model.append(
                        nodo_padre,
                        (
                            "",
                            # (f.cliente.nombre,
                            f.numfactura,
                            utils.str_fecha(f.fecha),
                            vtos,
                            utils.float2str(pendiente),
                            last_evento,
                            f.id,
                        ),
                    )
                    model[nodo_padre][4] = utils.float2str(utils._float(model[nodo_padre][4]) + pendiente)
                    model[nodo_cliente_padre][4] = utils.float2str(
                        utils._float(model[nodo_cliente_padre][4]) + pendiente
                    )
                    facturas_added.append(f)
                i += 1
                vpro.set_valor(i / (facturas.count() + len(abonos_pendientes)), txtvpro)
            for a in abonos_pendientes:
                pendiente = a.calcular_importe_total()  # O está descontada
                # entera o no lo está. Con los abonos no hay pagos parciales.
                pendiente = round(pendiente, 2)
                if pendiente:
                    total += pendiente
                    vtos = utils.str_fecha(a.fecha)  # Tampoco tiene
                    # vencimientos. La obligación nace desde el mismo día
                    # en que el abono se convierte en factura de abono.
                    try:
                        cliente = a.cliente
                    except AttributeError:
                        txt = (
                            "crm_seguimiento_impagos.py::buscar"
                            " -> FacturaDeAbono %d sin Abono o Cliente."
                            " Ignorando. " % a.id
                        )
                        self.logger.error(txt)
                        continue
                    if cliente not in nodos_clientes:
                        tmp_nodo = model.append(None, (cliente.nombre, "", "", "", "0", "", cliente.id))
                        nodos_clientes[cliente] = {"nodo_cliente": tmp_nodo}
                    obra = a.obra
                    nodo_cliente_padre = nodos_clientes[cliente]["nodo_cliente"]
                    if obra not in nodos_clientes[cliente]:
                        nodos_clientes[cliente][obra] = model.append(
                            nodo_cliente_padre,
                            (obra and obra.nombre or "Sin obra", "", "", "", "0", "", obra and obra.id or 0),
                        )
                    nodo_padre = nodos_clientes[cliente][obra]
                    model.append(
                        nodo_padre,
                        # (a.cliente.nombre,
                        (
                            "",
                            a.numfactura,
                            utils.str_fecha(a.fecha),
                            vtos,
                            utils.float2str(pendiente),
                            "",  # Facturas de abono no tienen anotaciones.
                            -a.id,
                        ),
                    )  # Para distinguirlo de las facturas.
                    model[nodo_padre][4] = utils.float2str(utils._float(model[nodo_padre][4]) + pendiente)
                    model[nodo_cliente_padre][4] = utils.float2str(
                        utils._float(model[nodo_cliente_padre][4]) + pendiente
                    )
                i += 1
                vpro.set_valor(i / (facturas.count() + len(abonos_pendientes)), txtvpro)
            vpro.ocultar()
            self.wids["e_total"].set_text(utils.float2str(total))
            self.buscar_todos()
            self.buscar_anotaciones()
            self.buscar_alertas()
 def rellenar_tabla(self, items):
 	"""
     Rellena el model con los items de la consulta
     """ 
 	model = self.wids['tv_datos'].get_model()
 	model.clear()
     total = totben = totpdte = 0.0
     clientes = {}
 	for f in items:
         cliente = f.cliente
         if cliente not in clientes:
             clientes[cliente] = model.append(None, (cliente and cliente.nombre or "Sin cliente", 
                                                     "", 
                                                     "", 
                                                     "0.0", 
                                                     "0.0", 
                                                     "0.0", 
                                                     cliente and cliente.id or 0))
         nodo_padre = clientes[cliente]
         totalpfra = f.importeTotal
         beneficio = f.calcular_beneficio()
         pdte = f.calcular_pendiente_cobro()
         model.append(nodo_padre, ("", 
                                   f.numfactura,
                                   utils.str_fecha(f.fecha), 
                                   utils.float2str(totalpfra), 
                                   utils.float2str(beneficio),
                                   utils.float2str(pdte), 
                                   f.id))
         model[nodo_padre][3] = utils.float2str(
             utils._float(model[nodo_padre][3]) + totalpfra)
         model[nodo_padre][4] = utils.float2str(
             utils._float(model[nodo_padre][4]) + beneficio)
         model[nodo_padre][5] = utils.float2str(
             utils._float(model[nodo_padre][5]) + pdte)
         total += totalpfra
         totben += beneficio
         totpdte += pdte
     self.wids['e_total'].set_text("%s" % (utils.float2str(total)))
     self.wids['e_total_kilos'].set_text("%s" % (utils.float2str(totben)))
     self.wids['e_totpdte'].set_text("%s" % (utils.float2str(totpdte)))
     # Y ahora la gráfica.
     datachart = [["Total", total], 
                  ["Beneficio", totben], 
                  ["Pendiente", totpdte]]
     try:
         import gtk, gobject, cairo, copy, math
     except ImportError:
         return      # No se pueden dibujar gráficas. # TODO: Temporal.
     try:
         import charting
     except ImportError:
         import sys, os
         sys.path.append(os.path.join("..", "utils"))
         import charting
     try:
         oldchart = self.wids['eventbox_chart'].get_child()
         if oldchart != None:
             #self.wids['eventbox_chart'].remove(oldchart)
             chart = oldchart
         else:
             chart = charting.Chart(orient = "horizontal")
             self.wids['eventbox_chart'].add(chart)
         chart.plot(datachart)
         self.wids['eventbox_chart'].show_all()
     except Exception, msg:
         txt = "consulta_ventas_prefacturas.py::rellenar_tabla -> "\
               "Error al dibujar gráfica (charting): %s" % msg
         print txt
         self.logger.error(txt)
Example #29
0
 def rellenar_tabla(self, resultados):
     """
     Rellena el model con los items de la consulta
     """        
     model = self.wids['tv_datos'].get_model()
     model.clear()
     totfact = totsiniva = totbeneficio = totbeneficio_cobro = 0.0
     self.wids['tv_datos'].freeze_child_notify()
     self.wids['tv_datos'].set_model(None)
     totcobrado = totpendiente = 0.0
     total_costo = total_costo_cobrado = 0.0
     for material in resultados:
         if material != None:
             nombre_mat = material.descripcion
         else:
             nombre_mat = ""
         padre_mat = model.append(None, (nombre_mat, 
                                         "", 
                                         "0", 
                                         "0", 
                                         "0", 
                                         "M:%d" % (material 
                                                   and material.id
                                                   or -1)))
         for fecha in resultados[material]:
             if fecha:
                 str_fecha = utils.str_fecha(fecha)
             else:
                 str_fecha = ""
             padre_fec = model.append(padre_mat, (str_fecha, 
                                                  "", 
                                                  "0", 
                                                  "0", 
                                                  "0", 
                                                  ""))
             for ldv in resultados[material][fecha]:
                 subtotal = ldv.get_subtotal(iva = True)
                 subtotal_siva = ldv.get_subtotal(iva = False)
                 beneficio = ldv.calcular_beneficio()
                 costo = ldv.calcular_precio_costo() * ldv.cantidad
                 if ldv.facturaVenta:
                     fac_alb_tic = ldv.facturaVenta.numfactura
                     cobradofra = ldv.facturaVenta.calcular_cobrado()
                     pendientefra = ldv.facturaVenta.calcular_pendiente_cobro()
                     try:
                         fraccion = cobradofra / (cobradofra + pendientefra)
                     except ZeroDivisionError:
                         fraccion = 1.0
                     cobrado = subtotal * fraccion
                     pendiente = subtotal - cobrado
                     beneficio_cobro = beneficio * fraccion
                     costo_cobrado = costo * fraccion
                 elif ldv.albaranSalida:
                     fac_alb_tic = ldv.albaranSalida.numalbaran
                     cobrado = 0.0
                     pendiente = subtotal
                     beneficio_cobro = 0.0
                     costo_cobrado = 0.0
                 elif ldv.ticket:
                     fac_alb_tic = "Ticket %d" % ldv.ticket.numticket
                     cobrado = subtotal
                     pendiente = 0.0
                     beneficio_cobro = beneficio
                     costo_cobrado = costo
                     # Los tickets se asume que se cobran siempre, por 
                     # tanto el costo de los productos sobre lo cobrado 
                     # es del 100%.
                 else:
                     fac_alb_tic = ""
                     cobrado = pendiente = beneficio_cobro = 0.0
                     costo_cobrado = 0.0
                 desc_producto = utils.wrap(ldv.producto.descripcion, 40)
                 try:
                     beneficio_costo = 100.0 * beneficio / costo
                 except ZeroDivisionError:
                     beneficio_costo = 0.0
                 model.append(padre_fec, (desc_producto, 
                                          fac_alb_tic, 
                                          utils.float2str(subtotal), 
                                          utils.float2str(subtotal_siva), 
                                          "%s (%s%%)" % (
                                             utils.float2str(beneficio), 
                                             utils.float2str(
                                                 beneficio_costo)), 
                                          "LDV:%d" % ldv.id))
                 # Actualizo totales en memoria y en nodos padre TreeView
                 totfact += subtotal
                 totsiniva += subtotal_siva
                 totbeneficio += beneficio
                 totbeneficio_cobro += beneficio_cobro
                 totcobrado += cobrado
                 totpendiente += pendiente
                 total_costo += costo
                 total_costo_cobrado += costo_cobrado
                 model[padre_fec][2] = utils.float2str(
                                         utils._float(model[padre_fec][2]) 
                                                      + subtotal)
                 model[padre_fec][3] = utils.float2str(
                                         utils._float(model[padre_fec][3]) 
                                                      + subtotal_siva)
                 model[padre_fec][4] = utils.float2str(
                                         utils._float(model[padre_fec][4]) 
                                                      + beneficio)
                 model[padre_mat][2] = utils.float2str(
                                         utils._float(model[padre_mat][2]) 
                                                      + subtotal)
                 model[padre_mat][3] = utils.float2str(
                                         utils._float(model[padre_mat][3]) 
                                                      + subtotal_siva)
                 model[padre_mat][4] = utils.float2str(
                                         utils._float(model[padre_mat][4]) 
                                                      + beneficio)
     self.rellenar_totales(totfact, totsiniva, totbeneficio, 
                           totcobrado, totpendiente, totbeneficio_cobro, 
                           total_costo, total_costo_cobrado)
     self.wids['tv_datos'].set_model(model)
     self.wids['tv_datos'].thaw_child_notify()
    def guardar(self, widget):
        """
        Guarda el contenido de los entry y demás widgets de entrada
        de datos en el objeto y lo sincroniza con la BD.
        """
        producto = self.objeto
        codigo = self.wids['e_codigo'].get_text()
        if len(codigo) < 12:
            utils.dialogo_info(titulo = "CÓDIGO DEMASIADO CORTO", 
                               texto = "El código debe tener 13 dígitos para ajustarse al formato EAN-13.\nSe va a completar con ceros.", 
                               padre = self.wids['ventana'])
            codigo += "0" * (12 - len(codigo))  # Completo hasta 12 para que después se le haga la suma de control.
        if len(codigo) == 12:
            codigo = codigo + self.calcular_digitoc(codigo)
        if len(codigo) > 13:
            utils.dialogo_info(titulo = "CÓDIGO INCORRECTO", 
                               texto = "Código EAN-13 incorrecto. Debe tener exactamente 13 dígitos.\nPuede introducir 12 y dejar que se calcule atomáticamente el dígito de control, si le es más cómodo.\n\nA continuación se va a recortar el código a 13 dígitos y se intentará comprobar la suma de control.", 
                               padre = self.wids['ventana'])
            codigo = codigo[:13]
        if len(codigo) == 13:
            digitocontrol = self.calcular_digitoc(codigo[:12])
            if codigo[12] != digitocontrol:
                utils.dialogo_info(titulo = "FALLÓ SUMA DE COMPROBACIÓN", 
                                   texto = "El dígito de control no es correcto. Se corregirá automáticamente.", 
                                   padre = self.wids['ventana'])
                codigo = codigo[:12] + digitocontrol
        descripcion = self.wids['e_descripcion'].get_text()
        # idlinea Un producto pertenece a una línea, no se puede cambiar
        nombre = self.wids['e_nombre'].get_text()
        arancel = self.wids['e_arancel'].get_text()
        try:
            precio = float(self.wids['e_precio'].get_text())
        except ValueError:
            precio = producto.preciopordefecto
        try:
            minimo = float(self.wids['e_minimo'].get_text())
        except ValueError:
            minimo = producto.minimo
        try:
            stock = utils._float(self.wids['e_stock'].get_text())
        except ValueError:
            stock = producto.camposEspecificosEspecial.stock
        try:
            existencias = int(self.wids['e_existencias'].get_text())
        except:
            existencias = producto.camposEspecificosEspecial.existencias
        # TODO: Falta ajustar los almacenes a la nueva cantidad en existencias.
        unidad = self.wids['e_unidad'].get_text()
        observaciones = self.wids['e_observaciones'].get_text()
 
        # Desactivo el notificador momentáneamente
        producto.notificador.activar(lambda: None)
        producto.camposEspecificosEspecial.notificador.activar(lambda: None)
        # Actualizo los datos del objeto
        try:
            producto.codigo = codigo
        except pclases.psycopg_ProgrammingError:
            try:
                producto_asignado = pclases.ProductoVenta.select(pclases.ProductoVenta.q.codigo == codigo)[0]
                producto_asignado = producto_asignado.descripcion
            except IndexError:
                producto_asignado = "?"
            utils.dialogo_info(titulo = "CÓDIGO DUPLICADO", 
                               texto = "El código EAN %s no se encuentra disponible.\nActualmente está asignado a: %s" % (codigo, producto_asignado), 
                               padre = self.wids['ventana'])
        producto.descripcion = descripcion
        producto.nombre = nombre
        producto.preciopordefecto = precio
        producto.minimo = minimo
        producto.arancel = arancel
        producto.camposEspecificosEspecial.stock = stock
        producto.camposEspecificosEspecial.unidad = unidad
        producto.camposEspecificosEspecial.observaciones = observaciones 
        producto.camposEspecificosEspecial.existencias = existencias
        # Fuerzo la actualización de la BD y no espero a que SQLObject lo haga por mí:
        producto.syncUpdate()
        # Vuelvo a activar el notificador
        producto.notificador.activar(self.aviso_actualizacion)
        producto.camposEspecificosEspecial.notificador.activar(self.aviso_actualizacion)
        self.actualizar_ventana()
        self.wids['b_guardar'].set_sensitive(False)