Beispiel #1
0
def pasar_presufi(s):
    """
    Detecta en la cadena «s» la posible aparición del año y devuelve la 
    misma cadena pero con todos los números (completos, no sus cifras por 
    separado) que encuentre incrementados en uno.
    """
    def agregar(c, l):
        """
        Si «c» es del mismo tipo que los caracteres del último grupo de «l» 
        devuelve True.
        """
        if len(l) and len(l[-1]):
            if l[-1][-1].isalpha() and c.isalpha():
                return True
            if l[-1][-1].isdigit() and c.isdigit():
                return True
        return False
    # Primero separo letras y números.
    letras_nums = []
    for c in s:
        if agregar(c, letras_nums):
            letras_nums[-1].append(c)
        else:
            letras_nums.append([c])
    # Ahora intento pasar año:
    res = ""
    for grupo_de_letras_o_nums in letras_nums:
        palabraca = "".join(grupo_de_letras_o_nums)
        numeraco = utils.parse_numero(palabraca)
        if isinstance(numeraco, int):
            numeraco += 1
            palabraca = `numeraco`
        res += palabraca
    return res
 def add_partida_gtx(self, boton):
     """
     Busca o crea una partida de geotextiles y la asocia con la de carga.
     """
     numpartida = utils.dialogo_entrada(
         titulo="NÚMERO DE PARTIDA DE GEOTEXTILES",
         texto="Introduzca el número de partida de geotextiles",
         padre=self.wids['ventana'])
     if numpartida is not None:
         numpartida = numpartida.upper().strip().replace("P-", "")
         numpartida = utils.parse_numero(numpartida)
         if numpartida is None:
             encontradas = 0
         else:
             partida = pclases.Partida.select(
                 pclases.Partida.q.numpartida == numpartida)
             try:
                 encontradas = partida.count()
             except AttributeError:
                 encontradas = 0
         if encontradas == 1:
             partida = partida[0]
             if partida.partidaCargaID is not None:
                 if utils.dialogo(titulo="PARTIDA USADA",
                         texto="La partida de geotextiles %s ya se agregó "
                               "a la partida de carga %s.\n"
                               "¿Desea cambiarla a la actual?" % (
                                   partida.codigo,
                                   partida.partidaCarga.codigo),
                         padre=self.wids['ventana']):
                     partida.partidaCarga = self.objeto
             else:
                 partida.partidaCarga = self.objeto
         elif encontradas == 0:
             try:
                 numpartida = int(numpartida)
             except (TypeError, ValueError):
                 utils.dialogo_info(
                         titulo="ERROR NÚMERO DE PARTIDA",
                         texto="El número de partida %s no es "
                               "correcto." % (numpartida),
                         padre=self.wids['ventana'])
                 return
             partida = pclases.Partida(numpartida=numpartida,
                                       codigo="P-%s" % (numpartida),
                                       partidaCarga=self.objeto)
             pclases.Auditoria.nuevo(partida, self.usuario, __file__)
         else:
             self.logger.error("consumo_balas_partida.py::add_partida_gtx"
                               " -> Encontrada más de una partida con el "
                               "mismo número. NO DEBERÍA OCURRIR.")
     self.actualizar_ventana()
Beispiel #3
0
def editar_entero_tv(w, clase, campo, text, path, col):
    try:
        numero = utils.parse_numero(text)
        if numero == None:
            raise ValueError
    except (ValueError, TypeError):
        utils.dialogo_info(titulo = "ERROR DE FORMATO", 
                           texto = "El texto %s no es un número entero." % text)
    else:
        model = w.get_model()
        o = clase.get(model[path][-1])
        setattr(o, campo, numero)
        model[path][col] = getattr(o, campo)
Beispiel #4
0
 def formaDePago(self):
     """
     Devuelve la forma de pago de la base de datos que se corresponde con
     la información de la forma de pago del cliente, que se encuentra
     dividida en varios atributos. Si no la encuentra, devuelve None.
     """
     plazo = utils.parse_numero(self.formadepago)
     docu = self.get_documentoDePago()
     fdps = FormaDePago.select(AND(FormaDePago.q.activa == True,
                                   FormaDePago.q.plazo == plazo,
                                   FormaDePago.q.documentoDePago == docu),
                               orderBy = "id")
     try:
         fdp = fdps[0]
     except IndexError:
         fdp = None
     return fdp
Beispiel #5
0
def edit_int(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_numero(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 entero 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] = getattr(objeto, atributo)
Beispiel #6
0
 def set_loteCem(self, w):
     comprobar_y_preguntar_si_guardar(self)
     codlote = utils.dialogo_entrada(titulo = 'Nº LOTE', 
                 texto = 'Introduzca número o código de lote de fibra '
                         'de cemento:',
                 padre = self.wids['ventana'])
     if codlote != None:
         numlote = utils.parse_numero(codlote)
         loteCems = pclases.LoteCem.select(pclases.OR(
             pclases.LoteCem.q.numlote == numlote, 
             pclases.LoteCem.q.codigo.contains(codlote)))
         if loteCems.count() == 0:
             utils.dialogo_info(titulo = 'LOTE NO ENCONTRADO', 
                 texto = 'No se encontró ningún lote de fibra de cemento'
                         ' %s.' % (codlote), 
                 padre = self.wids['ventana'])
             return
         elif loteCems.count() > 1:
             filas = [(l.id, l.numlote, l.codigo, l.tenacidad, 
                       l.elongacion, l.humedad, l.encogimiento) 
                      for l in loteCems]
             idloteCem = utils.dialogo_resultado(filas, 
                 titulo = 'SELECCIONE LOTE',
                 cabeceras = ('ID', 'Número', 'Código', 'Tenacidad', 
                              'Elongación', 'Humedad', 'Encogimiento'), 
                 padre = self.wids['ventana'])
             if idloteCem < 0:
                 return
             loteCem = pclases.LoteCem.get(idloteCem)
         else:
             loteCem = loteCems[0]
         if len(loteCem.bigbags) == 0:
             utils.dialogo_info(titulo = 'LOTE VACÍO', 
                 texto = 'El lote de cemento no contiene bigbags, no '
                         'puede\nrealizar pruebas sobre un lote vacío.', 
                 padre = self.wids['ventana'])
             self.loteCem = None
             return
         self.loteCem = loteCem
         self.actualizar_ventana()
Beispiel #7
0
def etiqueta_rollos_norma13(rollos, mostrar_marcado=True, lang="es"):
    """
    Construye una etiqueta por cada objeto rollo recibido y las devuelve
    en un solo PDF.
    Si lang = "en", etiqueta en inglés. Si "es", en castellano.
    """
    # Voy a tratar de reescribir esto regla en mano a ver si consigo
    # cuadrarlo bien en la etiquetadora GEMINI.
    alto = 12.55 * cm
    ancho = 8.4 * cm

    # Creo la hoja
    nomarchivo = os.path.join(gettempdir(),
                              "etiq_norma13_{}_{}.pdf".format(
                                  lang, give_me_the_name_baby()))
    canvas = reportlabcanvas.Canvas(nomarchivo, pagesize=(ancho, alto))

    # Medidas:
    logo = (3.8 * cm * 0.75, 2.8 * cm * 0.75)
    margen = 0.1 * cm
    marcado = (((ancho - logo[0]) / 2) - margen, (alto - margen - logo[1] - 2))

    # Imágenes:
    logo_marcado = os.path.abspath(
        os.path.join(os.path.dirname(__file__), "..", "imagenes", "CE.png"))

    # Datos fijos:
    # pylint: disable=bad-continuation
    _data = {# "00 logo_marcado": None,
             "01 texto_marcado": "1035",    # Fijo
             "02 fabricado_por": "Fabricado por: %s",
             "03 direccion1": None,
             "04 direccion2": None,
             "05 telefono": "Tfno: %s, %s",
             "06 año_certif": None,
             "07 blanco1": "",      # Separador
             "08 dni": None,
             # "09 iso1": "De EN13249:2001 a EN13257:2001",  # Fijo
             # "10 iso2": "EN13265:2001",     # Fijo
             # La norma ha cambiado. Ahora nos regimos por la del 2014
             "09 iso1": "De EN13249:2014 a EN13257:2014",  # Fijo
             "10 iso2": "EN13265:2014",     # Fijo
             "11 blanco2": "",      # Separador
             "12 producto": None,
             "13 descripcion":
                 "Geotextil no tejido de polipropileno 100% virgen",
             "14 uso": "Uso: %s",
             "15 blanco3": "",      # Separador
             "16 codigo": "Partida: %d Rollo: %s",
             "17 caracteristicas": "Gramaje: %d g/m² Ancho: %s m Largo: %d m"
            }
    if lang == "en":
        for k in _data:
            _data[k] = helene_laanest(_data[k])
    estilos = defaultdict(lambda: ("Helvetica", 9)) # Helvética a 9 por defecto
    estilos["02 fabricado_por"] = ("Helvetica-Bold", 11)
    estilos["12 producto"] = ("Helvetica-Bold", 17)
    estilos["16 codigo"] = ("Helvetica-Bold", 17)
    estilos["17 caracteristicas"] = ("Helvetica-Bold", 13)
    data = {}
    # Datos de la BD dependientes del rollo
    for rollo in rollos:
        # 0.- ¿En qué formato viene? Si es el antiguo (datos en diccionario)
        #     me quedo con el objeto de pclases en sí.
        if isinstance(rollo, dict):
            try:
                producto_venta = rollo['productoVenta']
            except KeyError:
                # Si no me lo mandan en el diccionario, tiene que traer
                # el objeto rollo. Los partes mandan producto en dicccionario
                # porque a veces se genera etiqueta antes de crear el objeto
                # en la BD. Si viene de la consulta del listado de rollos,
                # como el rollo ya existe, me viene en el objeto toda la info.
                producto_venta = rollo['objeto'].productoVenta
            numpartida = utils.parse_numero(rollo['partida'])
            numrollo = rollo['nrollo']
            barcode39 = rollo['codigo39']
        else:
            producto_venta = rollo.productoVenta
            numpartida = rollo.partida.numpartida
            numrollo = rollo.numrollo
            barcode39 = rollo.codigo
        #   1.- Empresa
        try:
            # Si hay distribuidor, este texto cambia.
            distribuidor = producto_venta.camposEspecificosRollo.cliente
            if distribuidor:
                if lang == "en":
                    data["02 fabricado_por"] = helene_laanest(
                            "%s") % (distribuidor.nombre)
                else:
                    data["02 fabricado_por"] = "%s" % (
                                                        distribuidor.nombre)
                dird = distribuidor.get_direccion_completa()
                dircompleta = textwrap.wrap(dird,
                        (len(dird) + max([len(w) for w in dird.split()])) / 2)
                data["03 direccion1"] = dircompleta[0]
                data["04 direccion2"] = dircompleta[1]
                data["05 telefono"] = _data["05 telefono"] % (
                        distribuidor.telefono, distribuidor.email)
            else:   # Sigo con los datos de "propia empresa". Distribuyo yo.
                empresa = pclases.DatosDeLaEmpresa.select()[0]
                data["02 fabricado_por"] = _data["02 fabricado_por"] % (
                                                                empresa.nombre)
                data["03 direccion1"] = empresa.direccion + ", " + empresa.cp
                data["04 direccion2"] = ", ".join((empresa.ciudad,
                                                   empresa.provincia,
                                                   empresa.pais))
                data["05 telefono"] = _data["05 telefono"] % (empresa.telefono,
                                                              empresa.email)
            # Para los clientes sin teléfono o sin email:
            data["05 telefono"] = data["05 telefono"].strip()
            if data["05 telefono"].startswith(","):
                data["05 telefono"] = data["05 telefono"][1:]
            if data["05 telefono"].endswith(","):
                data["05 telefono"] = data["05 telefono"][:-1]
            if len(data["05 telefono"]) <= 7:
                data["05 telefono"] = ""
        except IndexError:
            data["02 fabricado_por"] = ""
            data["03 direccion1"] = ""
            data["04 direccion2"] = ""
            data["05 telefono"] = ""
    #   2.- Producto
        producto = producto_venta
        if producto.annoCertificacion != None:
            data["06 año_certif"] = "%02d" % producto.annoCertificacion
        else:
            data["06 año_certif"] = ""
        data["08 dni"] = producto.dni
        if len(producto.nombre) <= 50:
            data["12 producto"] = producto.nombre
        else:
            #if "//" in producto.nombre: # Productos Intermas
            #    data["11 blanco2"], data["12 producto"] = producto.nombre.split("//")
            #else:
            data["11 blanco2"], data["12 producto"] = utils.dividir_cadena(
                    producto.nombre)
            data["11 blanco2"] = data["11 blanco2"].strip()
            data["12 producto"] = data["12 producto"].strip()
            estilos["11 blanco2"] = estilos["12 producto"]
        if producto.uso:
            if lang == "en":
                data["14 uso"] = _data["14 uso"] % helene_laanest(producto.uso)
            else:
                data["14 uso"] = _data["14 uso"] % producto.uso
        else:
            data["14 uso"] = ""
    #   3.- Rollo
        data["16 codigo"] = _data["16 codigo"] % (numpartida,
                                                  numrollo)
        data["17 caracteristicas"] = _data["17 caracteristicas"] % (
            producto.camposEspecificosRollo.gramos,
            float2str(producto.camposEspecificosRollo.ancho,
                      autodec=True, separador_decimales="."),
            producto.camposEspecificosRollo.metrosLineales)

        rectangulo(canvas, (margen, margen),
                      (ancho - margen, alto - margen))
        if mostrar_marcado:
            canvas.drawImage(logo_marcado,
                        marcado[0],
                        marcado[1],
                        width=logo[0], height=logo[1])
        else:
            data["01 texto_marcado"] = ""
        lineas = _data.keys()
        lineas.sort()
        # Posición y estilo de la primera línea.
        tamfuente = estilos[lineas[0]][1]
        crd_y = alto - logo[1] - 0.1 * cm - tamfuente
        # ¿Cuánto me desplazaré de línea a línea?
        offset_y = (crd_y - margen) / (len(lineas) + 3)   # 3 líneas para barcode
        for linea in lineas:
            try:
                dato = data[linea]
            except KeyError:    # Si no está en los valores asignados, busco
                                # en los originales. Deben ser datos fijos.
                dato = _data[linea]
            if dato is None:
                dato = ""
            canvas.setFont(*estilos[linea])
            #canvas.drawCentredString((ancho / 2),
            #                    crd_y,
            #                    escribe(dato))
            el_encogedor_de_fuentes_de_doraemon(canvas,
                                                fuente=estilos[linea][0],
                                                tamannoini=estilos[linea][1],
                                                xini=margen,
                                                xfin=ancho - margen,
                                                y=crd_y,
                                                texto=dato,
                                                alineacion=0)
            crd_y -= offset_y
        # Lo último: el código de barras:
        #######################################################################
        canvas.saveState()
        crd_y -= 2*offset_y
        crd_y -= 0.2*cm
        codigo_rollo = barcode39
        codigobarras = Extended39(codigo_rollo, xdim=.065*cm)
        codigobarras.drawOn(canvas, margen-0.5*cm, crd_y)
        xcode = ancho / 2.0
        ycode = 0.15*cm
        canvas.setFont("Courier-Bold", 9)
        try:
            canvas.drawCentredString(xcode, ycode, codigo_rollo, charSpace=0.25*cm)
        except TypeError:   # Versión antigua de ReportLab.
            canvas.drawCentredString(xcode, ycode, codigo_rollo)
        canvas.restoreState()
        # Y el QR de regalo
        # # De momento lo desactivo porque nuestras pistolas no lo reconocen.
        #try:
        #    from lib.pyqrcode import pyqrcode
        #    bidicode = pyqrcode.create(codigo_rollo)
        #    nomfichbidi = os.path.join(gettempdir(),
        #                               "bidi_%s.svg" % give_me_the_name_baby())
        #    bidicode.svg(nomfichbidi, scale=3)
        #    from lib.svglib.svglib import svglib
        #    drawing = svglib.svg2rlg(nomfichbidi)
        #    drawing.drawOn(canvas, margen - 0.25*cm, alto - margen - 3.0*cm + 0.25*cm)
        #except ImportError:
        #    pass    # No hay bidi porque no hay lxml instalado. Probablemente.
        #    print("No se generará código QR. Puede intentar lo siguiente:")
        #    print("C:\Python27\Scripts\easy_install.exe pip")
        #    print('pip install "D:\Informatica\Software\softwin python 2.7'
        #          '\lxml-3.7.2-cp27-cp27m-win32.whl"')
        #######################################################################
        canvas.showPage()
        # Y ahora la etiqueta adicional por si se pierde la otra y para cargar.
        create_etiqueta_backup(canvas, rollo)
        canvas.showPage()
    canvas.save()
    return nomarchivo
 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()
 def crear_nuevo_albaran(self, widget):
     """
     Función callback del botón b_nuevo.
     Pide los datos básicos para crear un nuevo objeto.
     Una vez insertado en la BD hay que hacerlo activo
     en la ventana para que puedan ser editados el resto
     de campos que no se hayan pedido aquí.
     """
     albaran = self.objeto
     nuevo_numalbaran = \
         pclases.AlbaranSalida.get_siguiente_numero_numalbaran_str()
         # Datos a pedir:
     numalbaran = utils.dialogo_entrada(
                     titulo = "NÚMERO DE ALBARÁN", 
                     texto = 'Introduzca un número para el albarán.\nDeje'
                             ' el número de albarán por defecto si no est'
                             'á seguro.', 
                     valor_por_defecto = nuevo_numalbaran, 
                     padre = self.wids['ventana'])
     if numalbaran == None: 
         return
     # numero_numalbaran = utils.parse_numero(numalbaran)
     numero_numalbaran_usuario = utils.parse_numero(numalbaran, invertir = True)
     numero_numalbaran_sugerido = utils.parse_numero(nuevo_numalbaran, invertir = True)
     #if self.usuario != None and self.usuario.nivel > 1 and numero_numalbaran != None and numero_numalbaran > nuevo_numalbaran:
     if (self.usuario 
         and self.usuario.nivel > 1 
         and numero_numalbaran_usuario != None 
         and numero_numalbaran_usuario > numero_numalbaran_sugerido):
         utils.dialogo_info(titulo = "NÚMERO DE ALBARÁN INCORRECTO", 
                            texto = "No es estrictamente necesario que todos los albaranes sean consecutivos.\n\nSin embargo, no se aconseja crear albaranes con número superior al sugerido.\n\nSi considera que debe hacerlo, contacte con un usuario con mayor nivel de privilegios.", 
                            padre = self.wids['ventana'])
         return
     if albaran != None: albaran.notificador.desactivar()
     propia_empresa = pclases.Cliente.id_propia_empresa_cliente()
     almacenes = [(a.id, a.nombre) 
                  for a in pclases.Almacen.select(
                      pclases.Almacen.q.activo == True, 
                      orderBy = "id")]
     almacenppal = pclases.Almacen.get_almacen_principal_id_or_none()
     almo = utils.dialogo_combo(titulo = "ALMACÉN ORIGEN", 
                 texto = "Seleccione el almacén origen de la mercancía",  
                 ops = almacenes, 
                 padre = self.wids['ventana'], 
                 valor_por_defecto = almacenppal)
     if not almo:    # Cancelar
         return
     try:
         albaran = pclases.AlbaranSalida(numalbaran = numalbaran,
                                 transportista = None,
                                 clienteID = propia_empresa, 
                                 bloqueado = False, 
                                 facturable = False, 
                                 motivo = "Es de consumo de repuestos", 
                                 observaciones = "repuestos", 
                                 destino = None, 
                                 fecha = mx.DateTime.localtime(), 
                                 almacenOrigenID = almo, 
                                 almacenDestino = None)
         pclases.Auditoria.nuevo(albaran, self.usuario, __file__)
         utils.dialogo_info('ALBARÁN CREADO', 
                            'El albarán %s ha sido creado.\nNo olvide asociar las salidas.' % albaran.numalbaran, 
                            padre = self.wids['ventana'])
         self.nuevo = True
         self.modificado = False
     except Exception, e:
         texto = "%salbaranes_de_salida::crear_nuevo_albaran -> Error al crear nuevo albarán. Excepción capturada: %s" % (self.usuario and self.usuario.usuario+": " or "", e)
         print texto
         self.logger.error(texto)
         utils.dialogo_info('ERROR: ALBARÁN NO CREADO', 
                            'El albarán %s no ha sido creado.\nCompruebe que el número no esté siendo usado y vuelva a intentarlo.\n\n\n' % (numalbaran), 
                            padre = self.wids['ventana']) 
Beispiel #10
0
def etiqueta_rollos_norma13(rollos, mostrar_marcado = True, lang = "es"):
    """
    Construye una etiqueta por cada objeto rollo recibido y las devuelve 
    en un solo PDF.
    Si lang = "en", etiqueta en inglés. Si "es", en castellano.
    """
    # Voy a tratar de reescribir esto regla en mano a ver si consigo 
    # cuadrarlo bien en la etiquetadora GEMINI.
    alto = 12.55 * cm
    ancho = 8.4 * cm

    # Creo la hoja
    nomarchivo = os.path.join(gettempdir(),
        "etiq_norma13_%s_%s.pdf" % (lang, give_me_the_name_baby()))
    c = canvas.Canvas(nomarchivo, pagesize = (ancho, alto))
    
    # Medidas:
    logo = (3.8 * cm * 0.75, 2.8 * cm * 0.75)
    margen = 0.1 * cm
    marcado = (((ancho - logo[0]) / 2) - margen, (alto - margen - logo[1] - 2))
    
    # Imágenes:
    logo_marcado = os.path.abspath(os.path.join(os.path.dirname(__file__), 
                                   "..", "imagenes", "CE.png"))

    # Datos fijos:
    _data = {# "00 logo_marcado": None, 
             "01 texto_marcado": "1035",    # Fijo
             "02 fabricado_por": "Fabricado por: %s", 
             "03 direccion1": None, 
             "04 direccion2": None, 
             "05 telefono": "Tfno: %s, %s", 
             "06 año_certif": None, 
             "07 blanco1": "",      # Separador
             "08 dni": None, 
             #"09 iso1": "De EN13249:2001 a EN13257:2001",  # Fijo
             #"10 iso2": "EN13265:2001",     # Fijo
             # La norma ha cambiado. Ahora nos regimos por la del 2014
             "09 iso1": "De EN13249:2014 a EN13257:2014",  # Fijo
             "10 iso2": "EN13265:2014",     # Fijo
             "11 blanco2": "",      # Separador
             "12 producto": None, 
             "13 descripcion": 
                 "Geotextil no tejido de polipropileno 100% virgen", 
             "14 uso": "Uso: %s", 
             "15 blanco3": "",      # Separador 
             "16 codigo": "Partida: %d Rollo: %s", 
             "17 caracteristicas": "Gramaje: %d g/m² Ancho: %s m Largo: %d m" 
            }
    if lang == "en":
        for k in _data:
            _data[k] = helene_laanest(_data[k])
    estilos = defaultdict(lambda: ("Helvetica", 9)) # Helvética a 9 por defecto
    estilos["02 fabricado_por"] = ("Helvetica-Bold", 11)
    estilos["12 producto"] = ("Helvetica-Bold", 17)
    estilos["16 codigo"] = ("Helvetica-Bold", 17)
    estilos["17 caracteristicas"] = ("Helvetica-Bold", 13)
    data = {}
    # Datos de la BD dependientes del rollo
    for rollo in rollos:
        # 0.- ¿En qué formato viene? Si es el antiguo (datos en diccionario) 
        #     me quedo con el objeto de pclases en sí.
        if isinstance(rollo, dict):
            try:
                productoVenta = rollo['productoVenta']
            except KeyError:
                # Si no me lo mandan en el diccionario, tiene que traer 
                # el objeto rollo. Los partes mandan producto en dicccionario 
                # porque a veces se genera etiqueta antes de crear el objeto 
                # en la BD. Si viene de la consulta del listado de rollos, 
                # como el rollo ya existe, me viene en el objeto toda la info.
                productoVenta = rollo['objeto'].productoVenta
            numpartida = utils.parse_numero(rollo['partida'])
            numrollo = rollo['nrollo']
        else:
            productoVenta = rollo.productoVenta
            numpartida = rollo.partida.numpartida
            numrollo = rollo.numrollo
        #   1.- Empresa
        try:
            # Si hay distribuidor, este texto cambia.
            distribuidor = productoVenta.camposEspecificosRollo.cliente
            if distribuidor:
                if lang == "en":
                    data["02 fabricado_por"] = helene_laanest(
                            "Distribuido por: %s") % (distribuidor.nombre)
                else:
                    data["02 fabricado_por"] = "Distribuido por: %s" % (
                                                        distribuidor.nombre)
                d = distribuidor.get_direccion_completa()
                dircompleta = textwrap.wrap(d, 
                        (len(d) + max([len(w) for w in d.split()])) / 2)
                data["03 direccion1"] = dircompleta[0]
                data["04 direccion2"] = dircompleta[1]
                data["05 telefono"] = _data["05 telefono"] % (
                        distribuidor.telefono, distribuidor.email)
            else:   # Sigo con los datos de "propia empresa". Distribuyo yo.
                empresa = pclases.DatosDeLaEmpresa.select()[0]
                data["02 fabricado_por"] = _data["02 fabricado_por"] % (
                                                                empresa.nombre)
                data["03 direccion1"] = empresa.direccion + ", " + empresa.cp
                data["04 direccion2"] = ", ".join((empresa.ciudad, 
                                                   empresa.provincia, 
                                                   empresa.pais))
                data["05 telefono"] = _data["05 telefono"] % (empresa.telefono,
                                                              empresa.email)
            # Para los clientes sin teléfono o sin email:
            data["05 telefono"] = data["05 telefono"].strip()
            if data["05 telefono"].startswith(","):
                data["05 telefono"] = data["05 telefono"][1:]
            if data["05 telefono"].endswith(","):
                data["05 telefono"] = data["05 telefono"][:-1]
            if len(data["05 telefono"]) <= 7: 
                data["05 telefono"] = ""
        except IndexError:
            data["02 fabricado_por"] = ""
            data["03 direccion1"] = ""
            data["04 direccion2"] = ""
            data["05 telefono"] = ""
    #   2.- Producto
        producto = productoVenta
        if producto.annoCertificacion != None:
            data["06 año_certif"] = "%02d" % producto.annoCertificacion
        else:
            data["06 año_certif"] = ""
        data["08 dni"] = producto.dni
        if len(producto.nombre) <= 50:
            data["12 producto"] = producto.nombre
        else:
            #if "//" in producto.nombre: # Productos Intermas
            #    data["11 blanco2"], data["12 producto"] = producto.nombre.split("//")
            #else:
            data["11 blanco2"], data["12 producto"] = utils.dividir_cadena(
                    producto.nombre)
            data["11 blanco2"] = data["11 blanco2"].strip()
            data["12 producto"] =data["12 producto"].strip()
            estilos["11 blanco2"] = estilos["12 producto"]
        if producto.uso:
            if lang == "en":
                data["14 uso"] = _data["14 uso"] % helene_laanest(producto.uso)
            else:
                data["14 uso"] = _data["14 uso"] % producto.uso
        else:
            data["14 uso"] = ""
    #   3.- Rollo
        data["16 codigo"] = _data["16 codigo"] % (numpartida, 
                                                  numrollo)
        data["17 caracteristicas"] = _data["17 caracteristicas"] % (
            producto.camposEspecificosRollo.gramos, 
            float2str(producto.camposEspecificosRollo.ancho, 
                      autodec = True, separador_decimales = "."), 
            producto.camposEspecificosRollo.metrosLineales)

        rectangulo(c, (margen, margen),
                      (ancho - margen, alto - margen))
        if mostrar_marcado: 
            c.drawImage(logo_marcado, 
                        marcado[0], 
                        marcado[1],
                        width = logo[0], height = logo[1])
        else:
            data["01 texto_marcado"] = ""
        lineas = _data.keys()
        lineas.sort()
        # Posición y estilo de la primera línea.
        tamfuente = estilos[lineas[0]][1]
        y = alto - logo[1] - 0.1 * cm - tamfuente
        # ¿Cuánto me desplazaré de línea a línea?
        offset_y = (y - margen) / len(lineas)
        for linea in lineas:
            try:
                dato = data[linea]
            except KeyError:    # Si no está en los valores asignados, busco  
                                # en los originales. Deben ser datos fijos.
                dato = _data[linea]
            if dato is None:
                dato = ""
            c.setFont(*estilos[linea])
            #c.drawCentredString((ancho / 2), 
            #                    y, 
            #                    escribe(dato))
            el_encogedor_de_fuentes_de_doraemon(c, 
                                                fuente = estilos[linea][0], 
                                                tamannoini = estilos[linea][1],
                                                xini = margen, 
                                                xfin = ancho - margen, 
                                                y = y, 
                                                texto = dato, 
                                                alineacion = 0)
            y -= offset_y
        c.showPage()
    c.save()
    return nomarchivo