コード例 #1
0
ファイル: clouseau.py プロジェクト: pacoqueen/ginn
def parse_consumos(fconsumos):
    """
    Abre el fichero y parsea los consumos devolviendo un diccionario de
    productos y la cantidad de cada uno que ha salido del almacén para 
    consumirse en la línea.
    """
    res = {}
    for qlty in ("A", "B", "C", "total"):
        res[qlty] = defaultdict(lambda: 0.0)
    f_in = open(fconsumos)
    data_in = reader(f_in, delimiter=";", lineterminator="\n")
    cabecera = True     # La primera fila son los títulos de columnas
    for linea in data_in:
        if cabecera:
            cabecera = False
            continue
        producto, cantidad, cant_a, cant_b, cant_c = linea[:5]
        try:
            cons_a = utils.parse_float(cant_a)
            cons_b = utils.parse_float(cant_b)
            cons_c = utils.parse_float(cant_c)
        except ValueError:  # No aplicable. Son productos de compra.
            cons_a = cons_b = cons_c = 0.0
        consumos = utils.parse_float(cantidad)
        res["A"][producto] += cons_a
        res["B"][producto] += cons_b
        res["C"][producto] += cons_c
        res["total"][producto] += consumos
    f_in.close()
    return res
コード例 #2
0
 def cell_func2(column, cell, model, itr):
     p = utils.parse_float(model[itr][2])
     m = utils.parse_float(model[itr][4])
     if p < m:
         color = "red"
     elif p > m:
         color = "green"
     else:
         color = "blue"
     cell.set_property("foreground", color)
コード例 #3
0
ファイル: balas_cable.py プロジェクト: pacoqueen/ginn
 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)
コード例 #4
0
ファイル: treeview2csv.py プロジェクト: pacoqueen/ginn
def to_float(t, sensibilidad = 2):
    """
    Si t es una cadena de texto con el símbolo del euro o de metros cuadrados,
    convierte todo lo que puede a flotante con técnica "greedy".
    En otro caso lanza una excepción ValueError al igual que hace el _float
    de utils.
    sensibilidad es un parámetro para evitar falsos positivos. Si en la cadena
    hay un cierto número de palabras (2 por defecto) entonces no convierte a
    número flotante.
    """
    if isinstance(t, (int, float)):
        return float(t)
    from string import digits as numeros
    palabras = []
    for p in t.split():
        if p[0] not in numeros:
            palabras.append(p)
            if len(palabras) >= sensibilidad:
                raise ValueError
    simbolos = ("€", "m²", " m", " kg", " k")
    for s in simbolos:
        if s in t:
            res = utils.parse_float(t[:t.index(s)])
            return res
    raise ValueError
コード例 #5
0
def build_gdata(model_fibra, model_gtx, model_otros):
    """
    Devuelve una lista de días y la demanda de los productos previstos para
    esa fecha. La demanda se calcula como las existencias iniciales menos
    las cantidades pedidas acumuladas por los pedidos de la consulta. La cifra
    final es la suma de la demanda de todos los productos para ese día.
    """
    # PLAN: Para que esto fuera útil de verdad necesitaría que los pedidos
    # llevaran fecha de entrega y que la planificación de las líneas se
    # metiera en el programa.
    from collections import defaultdict
    res = defaultdict(lambda: 0)
    productos = {}  # Existencias iniciales de los productos actualizada
                    # con la demanda de cada pedido.
    for model, ffecha, fproducto, fcantidad in ((model_fibra, 1, 3, 4),
                                                (model_gtx, 1, 3, 5),
                                                (model_otros, 1, 3, 4)):
        for fila in model:  # Debería ordenaro por día... ¿no?
            fecha = utils.parse_fecha(fila[1])
            producto = fila[3]
            while (producto.startswith("-") or producto.startswith(">")
                    or producto.startswith(" ")):
                producto = producto[1:]
            try:
                cantidad = utils.parse_float(fila[5])
            except ValueError:  # caso "-4.848." ¿punto como unidad? WTF?
                cantidad = utils.parse_float(fila[5][:-1])
            try:
                demanda = productos[producto] - cantidad
            except KeyError:
                try:
                    productodb = pclases.ProductoVenta.selectBy(
                                    descripcion=producto)[0]
                    stockdb = productodb.get_stock_A()
                except IndexError:  # Es producto "de compra"
                    productodb = pclases.ProductoCompra.selectBy(
                                    descripcion=producto)[0]
                    stockdb = productodb.get_stock()
                productos[producto] = stockdb - cantidad
            res[fecha] += productos[producto]
    fechas = res.keys()
    fechas.sort()
    gdata = []
    for f in fechas:
        gdata.append("[ new Date(%d, %d, %d), %f ]" % (f.year, f.month, f.day,
                                                       res[f]))
    return gdata
コード例 #6
0
ファイル: clouseau.py プロジェクト: pacoqueen/ginn
def parse_existencias(fexistencias_ini, res=None):
    """
    Abre el CSV de existencias y devuelve un diccionario de productos con
    sus existencias.
    """
    if not res:
        res = {}
        for qlty in ("A", "B", "C", "total"):
            res[qlty] = defaultdict(lambda: 0.0)
    f_in = open(fexistencias_ini)
    data_in = reader(f_in, delimiter=";", lineterminator="\n")
    cabecera = True     # La primera fila son los títulos de columnas
    for linea in data_in:
        if cabecera:
            cabecera = False
            continue
        try:
            (producto, kg_a, m_a, b_a, kg_b, m_b, b_b, kg_c, m_c, b_c,
                kg_total, m_total, b_total) = linea
            stock_a = utils.parse_float(m_a)
            stock_b = utils.parse_float(m_b)
            try:
                stock_c = utils.parse_float(m_c)
            except ValueError:  # No lleva metros de C. Geotextiles C en kg.
                stock_c = m_c
            total = utils.parse_float(m_total)
            if total == 0.0:    # Puede que sea un producto C. No lo puedo
                # saber únicamente por los datos de la hoja de cálculo. Uso
                # como total los kg. En el caso de los geotextiles normales
                # será también cero. No pasa nada. Solo habré perdido tiempo
                # parseando el valor. Pero si se mide en kg como los C,
                # entonces es el valor que me interesa.
                total = utils.parse_float(kg_total)
        except ValueError:  # Es el listado de fibra. No lleva metros.
            (producto, kg_a, b_a, kg_b, b_b, kg_c, b_c,
                kg_total, b_total) = linea
            stock_a = utils.parse_float(kg_a)
            stock_b = utils.parse_float(kg_b)
            stock_c = utils.parse_float(kg_c)
            total = utils.parse_float(kg_total)
        res["A"][producto] += stock_a
        res["B"][producto] += stock_b
        try:
            res["C"][producto] += stock_c
        except TypeError:   # Viene un "No Aplicable"
            pass
        res["total"][producto] += total
    f_in.close()
    return res
コード例 #7
0
ファイル: presupuesto.py プロジェクト: pacoqueen/ginn
 def volcar_a_tv(self, filas, vpro, padres, model):
     i = 0.0
     nodos_conceptos = {}
     for concepto in filas:
         vpro.set_valor(i / len(filas.keys()), 
                        "Montando matriz...")
         pa = concepto.presupuestoAnual
         nodo_padre = padres[pa]
         fila = [concepto.descripcion] + filas[concepto] + [concepto.puid]
         nodos_conceptos[concepto] = model.append(nodo_padre, fila)
         for mes_matriz in range(1, 13):
             try:
                 model[nodo_padre][mes_matriz] = utils.float2str(
                         utils.parse_float(model[nodo_padre][mes_matriz]) 
                         + utils.parse_float(fila[mes_matriz]))
             except (TypeError, ValueError):
                 model[nodo_padre][mes_matriz] = utils.float2str(
                         utils.parse_float(fila[mes_matriz]))
         i += 1
コード例 #8
0
def crear_fake_treeview(tvorig,
                        filtro = lambda fila: fila[4] == "-" and fila or None): 
    """
    Crea un TreeView idéntico al recibido (model clonado, mismas columnas y 
    cabeceras, etc.).
    «filtro» debe ser una función que devuelve la fila filtrada o None si
    no debe incluirse en el nuevo TreeView.
    """
    tv = gtk.TreeView()
    tv.set_name(tvorig.get_name())
    modelorig = tvorig.get_model()
    cols = []
    origcols = tvorig.get_columns()
    colsnulas = []
    anchos = []
    aligns = []
    for col, i in zip(origcols, range(len(origcols))):
        cols.append((col.get_title(), 
                     "gobject.TYPE_STRING", # STRING se lo traga todo. Premio
                                # especial del jurado de los AVN Awards 2015.
                     False, 
                     False, 
                     False, 
                     None))
        anchos.append(col.get_width())
        aligns.append(col.get_cell_renderers()[0].get_property("xalign"))
    cols.append(("ID", "gobject.TYPE_STRING", False, False, False, None))
    utils.preparar_treeview(tv, cols)
    for col, align in zip(tv.get_columns(), aligns):
        col.get_cell_renderers()[0].set_property("xalign", align) 
    model = tv.get_model()
    for padre in modelorig:
        producto = pclases.ProductoVenta.get(padre[-1])
        try:
            ancho_estandar = producto.camposEspecificosRollo.ancho
        except AttributeError:
            ancho_estandar = 1
        iterpadre = model.append(None, padre)
        total_metros = 0.0
        for fila in modelorig[padre.iter].iterchildren():
            _fila = filtro(fila)
            if _fila:
                model.append(iterpadre, fila)
                total_metros += utils.parse_float(fila[5])
        model[iterpadre][5] = total_metros * ancho_estandar
    return tv
コード例 #9
0
ファイル: balas_cable.py プロジェクト: pacoqueen/ginn
 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
             except TypeError:   # Ha cancelado
                 return
         nueva_bala = self.crear_objeto_bala(producto, peso)
         if nueva_bala == None:
             utils.dialogo_info(titulo = "ERROR",
                 texto = "La bala no se pudo crear. Verifique el peso "
                         "e 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)
コード例 #10
0
ファイル: productos.py プロジェクト: pacoqueen/ginn
    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()
        ide = model[path][-1]
        try:
            precio = utils.parse_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(ide)
            elif "PV" in model[path][0]:
                producto = pclases.ProductoVenta.get(ide)
            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.21
                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)
コード例 #11
0
ファイル: pclase2tv.py プロジェクト: pacoqueen/ginn
def edit_float(cell, path, newtext, tv, numcol, clase, atributo):
    """
    Cambia el texto del model[path][numcol] y del objeto relacionado que 
    saca a partir del ID de la última columna del model.
    """
    try:
        numero = utils.parse_float(newtext)
    except (ValueError, TypeError):
        parent = tv.parent
        while parent != None:
            parent = parent.parent
        utils.dialogo_info(titulo = "ERROR EN NÚMERO", 
            texto = "El texto «%s» no es un número válido." % (newtext), 
            padre = parent)
    else:
        model = tv.get_model()
        ide = model[path][-1]
        objeto = clase.get(ide)
        setattr(objeto, atributo, numero) 
        objeto.syncUpdate()
    model[path][numcol] = utils.float2str(getattr(objeto, atributo), 
                                          autodec = True)
コード例 #12
0
ファイル: productos.py プロジェクト: pacoqueen/ginn
    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()
        ide = model[path][-1]
        try:
            existencias = utils.parse_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(ide)
                producto.sync()
                #producto.existencias = existencias
                producto.set_existencias(existencias)
                producto.syncUpdate()
                model[path][3] = utils.float2str(producto.existencias)
コード例 #13
0
ファイル: empleados.py プロジェクト: pacoqueen/ginn
 def comparar_float(self, col):
     res = 0.0
     try:
         valor_ventana = self.wids[col].get_text()
     except KeyError:
         txt_error = "empleados.py: No se pudo obtener el valor de la "\
                     "ventana para %s." % col
         myprint(txt_error)
         self.logger.error(txt_error)
         valor_ventana = 0.0
     try:
         valor_ventana = utils.parse_float(valor_ventana)
     except ValueError:
         txt_error = "empleados.py: No se pudo convertir %s(%s) a "\
                     "float." % (col, valor_ventana)
         myprint(txt_error)
         self.logger.error(txt_error)
         valor_ventana = 0.0
     try:
         valor_campo = self.objeto._SO_getValue(col)
         if not isinstance(valor_campo, type(0.0)):  # Porque es posible
             # que el SOCol no contenga un float. El SOCol es la clase
             # base. Se asume flotante por eliminación. O, escucha que te
             # diga, o que sea un decimal.Decimal
             try:
                 valor_campo = utils._float(valor_campo)
             except TypeError:
                 res = False
         res = valor_ventana == valor_campo
     except KeyError:
         txt_error = "empleados.py: No se pudo obtener el valor del "\
                     "objeto para %s." % col
         myprint(txt_error)
         self.logger.error(txt_error)
         valor_campo = 0.0
     return res
コード例 #14
0
    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 = utils.parse_float(self.wids['e_precio'].get_text())
        except ValueError:
            precio = producto.preciopordefecto
        try:
            minimo = utils.parse_float(self.wids['e_minimo'].get_text())
        except ValueError:
            minimo = producto.minimo
        try:
            stock = utils.parse_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 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
        try:
            self.objeto.obsoleto = self.wids['ch_obsoleto'].get_active()
        except (KeyError, AttributeError):
            pass    # Versión antigua de la base de datos.
        # 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)
コード例 #15
0
ファイル: clouseau.py プロジェクト: pacoqueen/ginn
def parse_salidas(fsalidas_fib, fsalidas_gtx, fsalidas_cem):
    """
    Abre cada fichero y parsea las salidas de almacén devolviendo un 
    diccionario de productos y las salidas de cada uno EN SUS UNIDADES: kg 
    para fibra y metros cuadrados para geotextiles.
    """
    res = {}
    for qlty in ("A", "B", "C", "total"):
        res[qlty] = defaultdict(lambda: 0.0)
    for fname in fsalidas_fib, fsalidas_gtx, fsalidas_cem:
        f_in = open(fname)
        data_in = reader(f_in, delimiter=";", lineterminator="\n")
        cabecera = True     # La primera fila son los títulos de columnas
        for linea in data_in:
            if cabecera:
                cabecera = False
                continue
            try:
                (producto,
                 m_a, kg_a, b_a, 
                 m_b, kg_b, b_c, 
                 m_c, kg_c, b_c, 
                 m_total, kg_total, b_total) = linea
                es_gtx = True
            except ValueError:  # Hay valores de menos. No es geotextiles.
                (producto,
                 kg_a, b_a, 
                 kg_b, b_b, 
                 kg_c, b_c, 
                 kg_total, b_total) = linea
                es_gtx = False
            if es_gtx:
                salidas = utils.parse_float(m_total)
                # Caso especial para producto C. Se mide en Kg. En m_total
                # tendrá un cero. Otros productos normales también pueden
                # tener un cero en producción de metros, pero también lo
                # tendrán en la columna de kg producidos. So...
                if not salidas:
                    sals_a = utils.parse_float(kg_a)
                    sals_b = utils.parse_float(kg_b)
                    sals_c = utils.parse_float(kg_c)
                    salidas = utils.parse_float(kg_total)
                else:
                    sals_a = utils.parse_float(m_a)
                    sals_b = utils.parse_float(m_b)
                    sals_c = utils.parse_float(m_c)
            else:
                sals_a = utils.parse_float(kg_a)
                sals_b = utils.parse_float(kg_b)
                sals_c = utils.parse_float(kg_c)
                salidas = utils.parse_float(kg_total)
            res["A"][producto] += sals_a
            res["B"][producto] += sals_b
            res["C"][producto] += sals_c
            res["total"][producto] += salidas
        f_in.close()
    return res
コード例 #16
0
ファイル: clouseau.py プロジェクト: pacoqueen/ginn
def parse_produccion(fproduccion_fib, fproduccion_gtx, fproduccion_cem):
    """
    Abre el fichero y devuelve un diccionario de productos con la producción.
    """
    res = {}
    for qlty in ("A", "B", "C", "total"):
        res[qlty] = defaultdict(lambda: 0.0)
    for fproduccion in (fproduccion_fib, fproduccion_gtx, fproduccion_cem):
        f_in = open(fproduccion)
        data_in = reader(f_in, delimiter=";", lineterminator="\n")
        cabecera = True     # La primera fila son los títulos de columnas
        for linea in data_in:
            if cabecera:
                cabecera = False
                continue
            try:
                (producto,
                 m_a, m_b, m_c, m_total,
                 kg_a, kg_teorico_a, kg_b, kg_teorico_b, kg_c, kg_total,
                 b_a, b_b, b_c, b_total,
                 t_teorico, t_real) = linea
                es_gtx = True
            except ValueError:  # Hay valores de menos. No es geotextiles.
                (producto,
                 kg_a, kg_b, kg_c, kg_total,
                 b_a, b_b, b_c, b_total,
                 t_teorico, t_real) = linea
                es_gtx = False
            if producto.startswith(">"):
                continue    # Es un desglose. No me interesa.
            if producto == "Sin producción".encode("latin1"):
                continue    # Es un resumen de tiempo sin producir.
            if es_gtx:
                try:
                    prod_a = utils.parse_float(m_a)
                    prod_b = utils.parse_float(m_b)
                    prod_c = utils.parse_float(m_c)
                    producido = utils.parse_float(m_total)
                    # Caso especial para producto C. Se mide en Kg. En m_total
                    # tendrá un cero. Otros productos normales también pueden
                    # tener un cero en producción de metros, pero también lo
                    # tendrán en la columna de kg producidos. So...
                    if not producido:
                        prod_a = utils.parse_float(kg_a)
                        prod_b = utils.parse_float(kg_b)
                        prod_c = utils.parse_float(kg_c)
                        producido = utils.parse_float(kg_total)
                except ValueError:  # Es una línea de resumen.
                    continue
            else:
                prod_a = utils.parse_float(kg_a)
                prod_b = utils.parse_float(kg_b)
                prod_c = utils.parse_float(kg_c)
                producido = utils.parse_float(kg_total)
            res["A"][producto] += prod_a
            res["B"][producto] += prod_b
            res["C"][producto] += prod_c
            res["total"][producto] += producido
        f_in.close()
    return res
コード例 #17
0
ファイル: treeview2pdf.py プロジェクト: pacoqueen/ginn
def treeview2pdf(tv, titulo = None, fecha = None, apaisado = None, 
                 pijama = False, graficos = [], numcols_a_totalizar = [], 
                 extra_data = []):
    """
    A partir de un TreeView crea un PDF con su contenido.
    1.- Asigna un nombre de archivo en función del nombre del TreeView.
    2.- Si titulo es None, asigna como título el nombre del TreeView.
    3.- El ancho de los campos será el ancho relativo en porcentaje que ocupa 
        el ancho de la columna (get_width) a la que correspondería. El título 
        del campo será el título (get_title) de la columna.
    4.- Si fecha no es None debe ser una cadena de texto. Si es None, se 
        usará la fecha actual del sistema.
    5.- Si la suma del ancho de las columnas del TreeView es superior a 800 
        píxeles el PDF generado será apaisado, a no ser que se fuerce mediante 
        el parámetro "apaisado" que recibe la función.
    numcols_a_totalizar es una lista de índices (empezando por 0) de las 
    columnas a las que se va a intentar convertir a número y sumar para 
    mostrar una última línea con el texto "TOTAL" o "TOTALES" si hay más de 
    una.
    extra_data son líneas que se añadirán a las que tiene el TreeView 
    *al final* del informe (incluso detrás de los totales, si los hubiera).
    """
    archivo = get_nombre_archivo_from_tv(tv)
    if titulo == None:
        titulo = get_titulo_from_tv(tv)
    campos, pdf_apaisado, cols_a_derecha, cols_centradas=get_campos_from_tv(tv)
    datos = get_datos_from_tv(tv)
    totales = dict(zip(numcols_a_totalizar, len(numcols_a_totalizar) * [0]))
    for fila in datos:  # Si es un TreeView solo sumaré los totales de primer 
                    # nivel. Los hijos se marcan con ">" al inicio del texto.
        try:
            if (fila and 
                    (fila[0].startswith(">") 
                        or ("]" in fila[0] 
                            and fila[0].split("]")[1].startswith(">")))):
                continue
        except (AttributeError, IndexError):
            pass    # Aquí no ha pasado nada. 
        for numcol in totales:
            # Primero hay que limpiar de formato el texto.
            valor_a_parsear = fila[numcol]
            try:
                valor_a_parsear = valor_a_parsear.split("]")[1]
            except IndexError:
                pass
            if valor_a_parsear in ("---", "==="):
                continue
            try:
                valor_a_sumar = utils.parse_float(valor_a_parsear)
            except ValueError:  # ¿No hay dato en esa fila? Entonces cuento 
                                # instancias.
                valor_a_sumar = 1
                #print fila, numcol, fila[numcol]
            if pclases.DEBUG:
                print "+", fila[numcol], "=", valor_a_sumar
            totales[numcol] += valor_a_sumar
    if totales and datos:
        last_i = len(datos) - 1  # Apuntará a la última línea no nula
        while (last_i > 0 
               and reduce(lambda x, y: str(x) + str(y), datos[last_i]) == ""):
            last_i -= 1
        if (datos[last_i] and 
            not reduce(lambda x, y: x == y == "---" and "---", datos[last_i])):
            datos.append(("---", ) * len(campos))
        fila = ["TOTAL"] + [""] * (len(campos) - 1)
        if len(totales) > 1:
            fila[0] = "TOTALES"
        for total in totales:
            fila[total] = utils.float2str(totales[total])
                                            #, precision = 2, autodec = True)
        datos.append(fila)
    if extra_data and not isinstance(extra_data[0], (tuple, list)):
        extra_data = [extra_data]
    for extra in extra_data:
        dif_len = len(campos) - len(extra)
        if dif_len <> 0 and not isinstance(extra, list):
            extra = list(extra)
        if dif_len > 0:
            extra += [""] * dif_len
        elif dif_len < 0:
            extra = extra[:len(campos)]
        datos.append(extra)
    if not fecha:
        fecha = utils.str_fecha(mx.DateTime.localtime())
    if apaisado != None:
        pdf_apaisado = apaisado
    return geninformes.imprimir2(archivo, 
                                 titulo, 
                                 campos, 
                                 datos, 
                                 fecha, 
                                 apaisado = pdf_apaisado, 
                                 cols_a_derecha = cols_a_derecha, 
                                 cols_centradas = cols_centradas, 
                                 pijama = pijama, 
                                 graficos = graficos) 
コード例 #18
0
    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()
        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 = utils.parse_float(self.wids['e_precio'].get_text().replace(',','.'))
        except ValueError:
            precio = producto.precio
        try:
            minimo = utils.parse_float(self.wids['e_minimo'].get_text())
        except ValueError:
            minimo = producto.minimo
        try:
            gramos = int(self.wids['e_gramos'].get_text())
        except ValueError:
            gramos = producto.camposEspecificosRollo.gramos
        try:
            ancho = utils.parse_float(self.wids['e_ancho'].get_text())
        except ValueError:
            ancho = producto.camposEspecificosRollo.ancho
        try:
            diametro = int(self.wids['e_diametro'].get_text())
        except ValueError:
            diametro = producto.camposEspecificosRollo.diametro
        try:
            metrosLineales = int(self.wids['e_metros_lineales'].get_text())
        except:
            metrosLineales = producto.camposEspecificosRollo.metrosLineales
        try:
            rolloCamion = int(self.wids['e_rollo_camion'].get_text())
        except ValueError:
            rolloCamion = producto.camposEspecificosRollo.rollosPorCamion
        composan = self.wids['e_composan'].get_text()
 
        # Desactivo el notificador momentáneamente
        producto.notificador.activar(lambda: None)
        # Actualizo los datos del objeto
        producto.codigo = codigo
        producto.descripcion = descripcion
        producto.nombre = nombre
        producto.preciopordefecto = precio
        producto.minimo = minimo
        producto.arancel = arancel
        producto.camposEspecificosRollo.gramos = gramos
        producto.camposEspecificosRollo.ancho = ancho
        producto.camposEspecificosRollo.diametro = diametro
        producto.camposEspecificosRollo.codigoComposan = composan
        producto.camposEspecificosRollo.rollosPorCamion = rolloCamion
        producto.camposEspecificosRollo.metrosLineales = metrosLineales
        try:
            self.objeto.obsoleto = self.wids['ch_obsoleto'].get_active()
        except (KeyError, AttributeError):
            pass    # Versión antigua de la base de datos.
        # 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)
        self.actualizar_ventana()
        self.wids['b_guardar'].set_sensitive(False)
コード例 #19
0
 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 correct"
                                        "o. Se corregirá automáticamente.",
                                padre = self.wids['ventana'])
             codigo = codigo[:12] + digitocontrol
     descripcion = self.wids['e_descripcion'].get_text()
     linea = pclases.LineaDeProduccion.select(
         pclases.LineaDeProduccion.q.nombre.contains('fibra'))[0]
     lineaembol = pclases.LineaDeProduccion.select(
         pclases.LineaDeProduccion.q.nombre.contains('bolsa'))[0]
     nombre = self.wids['e_nombre'].get_text()
     arancel = self.wids['e_arancel'].get_text()
     try:
         precio = utils.parse_float(self.wids['e_precio'].get_text().replace(',','.'))
     except ValueError:
         precio = producto.preciopordefecto
     try:
         minimo = utils.parse_float(self.wids['e_minimo'].get_text())
     except ValueError:
         minimo = producto.minimo
     try:
         dtex = utils.parse_float(self.wids['e_dtex'].get_text())
     except ValueError:
         dtex = producto.camposEspecificosBala.dtex
     try:
         corte = int(self.wids['e_corte'].get_text())
     except ValueError:
         dtex = producto.camposEspecificosBala.dtex
     gramosBolsa = utils.parse_numero(self.wids['e_gramosBolsa'].get_text())
     producto.camposEspecificosBala.gramosBolsa = gramosBolsa
     bolsasCaja = utils.parse_numero(self.wids['e_bolsasCaja'].get_text())
     producto.camposEspecificosBala.bolsasCaja = bolsasCaja
     cajasPale = utils.parse_numero(self.wids['e_cajasPale'].get_text())
     producto.camposEspecificosBala.cajasPale = cajasPale
     color = self.wids['e_color'].get_text()
     antiuv = self.wids['chk_antiuv'].get_active()
     reciclada = self.wids['ch_reciclada'].get_active()
     idtipoMaterialBala = utils.combo_get_value(self.wids['cb_material'])
     prodestandar = self.wids['e_prodestandar'].get_text()
     try:
         prodestandar = utils.parse_float(prodestandar)
     except ValueError:
         prodestandar = 0.0
     # Desactivo el notificador momentáneamente
     producto.notificador.activar(lambda: None)
     # Actualizo los datos del objeto
     producto.prodestandar = prodestandar
     try:
         producto.codigo = codigo
     except 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
     if producto.camposEspecificosBala.gramosBolsa:
         producto.lineaDeProduccionID = lineaembol.id
     else:
         producto.lineaDeProduccionID = linea.id
     producto.nombre = nombre
     producto.preciopordefecto = precio
     producto.minimo = minimo
     producto.arancel = arancel
     producto.camposEspecificosBala.dtex = dtex
     producto.camposEspecificosBala.corte = corte
     producto.camposEspecificosBala.color = color
     producto.camposEspecificosBala.antiuv = antiuv
     producto.camposEspecificosBala.reciclada = reciclada
     producto.camposEspecificosBala.tipoMaterialBalaID = idtipoMaterialBala
     producto.dni = self.wids['e_dni'].get_text()
     producto.uso = self.wids['e_uso'].get_text()
     if self.wids['ch_no_anno_cert'].get_active():
         producto.annoCertificacion = None
     else:
         producto.annoCertificacion \
                 = self.wids['sp_anno_certificacion'].get_value_as_int()
     cliente = utils.combo_get_value(self.wids['cbe_cliente'])
     if cliente == 0:
         cliente = None
     producto.camposEspecificosBala.clienteID = cliente
     try:
         self.objeto.obsoleto = self.wids['ch_obsoleto'].get_active()
     except (KeyError, AttributeError):
         pass    # Versión antigua de la base de datos.
     # 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)
     self.wids['b_guardar'].set_sensitive(False)
     self.actualizar_ventana()