def etiqueta_nied(rollos, mostrar_marcado = False): """ Genera un PDF con tantas páginas iguales como número de elementos tenga la lista de rollos recibida. Si el rollo va a 0.80 m de ancho, devuelve en cada página el diseño de GNT11_080.pdf. Si va a un metro, el diseño de GNT11_100.pdf. En otro caso usa el GNT11_120.pdf por defecto. """ try: pv = rollos[0]['objeto'].productoVenta except (IndexError, AttributeError): nomarchivo = os.path.abspath(os.path.join(os.path.dirname(__file__), "GNT11_120.pdf")) else: modelo = "GNT11_120.png" try: if pv.camposEspecificosRollo.ancho == 0.8: modelo = "GNT11_080.png" elif pv.camposEspecificosRollo.ancho == 1.0: modelo = "GNT11_100.png" except AttributeError: pass # Uso modelo por defecto. pagina = os.path.abspath(os.path.join(os.path.dirname(__file__), modelo)) height = 12.55 * cm width = 8.4 * cm nomarchivo = os.path.join(gettempdir(), "etiqNied_%s.pdf" % give_me_the_name_baby()) c = canvas.Canvas(nomarchivo, pagesize = (width, height)) for rollo in rollos: # @UnusedVariable c.drawImage(pagina, 0, 0, width, height) c.showPage() c.save() return nomarchivo
def get_nombre_archivo_from_tv(tv): """ Devuelve el nombre del archivo que se generará a partir del nombre del widget TreeView. """ nomtreeview = tv.get_name().replace(" ", "_").replace(":", "_") nomarchivo = os.path.join(gettempdir(), "%s_%s.csv" % (nomtreeview, geninformes.give_me_the_name_baby())) return nomarchivo
def get_nombre_archivo_from_tv(tv): """ Devuelve el nombre del archivo que se generará a partir del nombre del widget TreeView. """ # Algunos caracteres dan problemas en SO Windows. nomtreeview = tv.get_name().replace(" ", "_").replace(":", "_") nomarchivo = os.path.join(gettempdir(), "%s_%s.pdf" % ( nomtreeview, geninformes.give_me_the_name_baby())) return nomarchivo
def mandar_a_imprimir_con_ghostscript(fichero, rotate = False): """ Lanza un trabajo de impresión a través de acrobat reader. Usa parámetros no documentados y oficialmente no soportados por acrobat. Esta función es temporal, hasta que encuentre un visor/impresor de PDF desde línea de comandos. Win-only. No funciona en posix ni aún teniendo el reader para esa plataforma (creo). NO USAR CON ROLLOS: No cuadra bien la etiqueta y además deja abierta la ventana después. Impresora CAB harcoded (y además no es el nombre por defecto de la impresora). ¡MENTIRA COCHINA! Lo hace a través de Ghostscript. """ if rotate: from lib.PyPDF2 import PyPDF2 fichrotado = os.path.join(tempfile.gettempdir(), "gs_rotated_%s.pdf" % give_me_the_name_baby() ) rotado = PyPDF2.PdfFileWriter() original = PyPDF2.PdfFileReader(open(fichero, "rb")) for page in range(original.getNumPages()): rotado.addPage(original.getPage(page).rotateClockwise(270)) rotado.write(open(fichrotado, "wb")) fichero = fichrotado # OJO: Ruta al reader harcoded !!! # comando = """"C:\\Archivos de programa\\Adobe\\Acrobat 6.0\\Reader\\AcroRd32.exe" /t "%s" GEMINI2 """ % (fichero) # comando = """start /B AcroRd32 /t "%s" CAB """ % (fichero) comando = """gswin32c.exe -dQueryUser=3 -dNoCancel -dNOPAUSE -dBATCH"""\ """ -sDEVICE=mswinpr2 -sOutputFile="%%printer%%CAB" %s """ % ( fichero) # NOTA: Necesita que: # 1.- La impresora CAB esté como predeterminada en la "carpeta" # impresoras de Windows. # 2.- Tenga la configuración adecuada por defecto (apaisado, tamaño de # etiqueta, etc. # 3.- gs esté en el PATH (añadiendo C:\Archivos de programa...\bin en la # variable de entorno PATH desde las propiedades avanzadas de Mi PC.) if os.system(comando): print "No se pudo hacer la impresión directa. Lanzo el visor." abrir_pdf(fichero)
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 crear_etiquetas_balas(balas, mostrar_marcado=True, lang="es"): """ Construye una etiqueta por cada objeto bala recibido y las devuelve en un solo PDF. Si lang = "en", etiqueta en inglés. Si "es", en castellano. Crea etiquetas para las balas de un parte de la línea de fibra. Una por etiqueta del tamaño estándar de la impresora CAB: 12.55 x 8.4. Lleva el código especial para Domenech en horizontal. «seriep» es la serie del pedido y si no es None, se muestra en los 3 primeros dígitos. «numped» es el número de pedido procedente de Domenech y si no es None se muestra en 6 dígitos tras la serie (si la hubiera). Estos dos grupos de dígitos opcionales («seriep» y «numped») son comunes a toda la serie de balas de las que se generarán las etiquetas. El formato completo es: * 3 dígitos: serie del pedido, completado con ceros por la izquierda. * 6 dígitos: número de pedido, completado con ceros por la izquierda. *-7-dígitos:-código-de-producto:--- YA NO (tercera vez que vuelven a ser 6) * 6 dígitos: código de producto: - 007336 FIBRA PP 6.7 Dtx NATURAL. - 007337 FIBRA PP 6.7 Dtx NEGRO. - 007674 FIBRA PP 4.5 Dtx NEGRO. - 007852 FIBRA PP 4.5 Dtx NATURAL. * 10 dígitos: número de lote, completado con ceros por la izquierda. * 15 dígitos: número de bala, completado con ceros por la izquierda. * 3 dígitos: parte entera del peso de la bala en kilogramos, completado con ceros por la izquierda. * 2 dígitos: parte decimal del peso de la bala en kilogramos, completado con ceros por la derecha. Por ejemplo, el código correspondiente a una bala de fibra negra de polipropileno de 6.7 dtex, correspondiente al lote 660, de número 57394, con 286.50 kg de peso y solicitada en el pedido 4/2158; sería: 004002158007337000000066000000000005739428650 007337000000066000000000005739428650 Si no lleva serie ni pedido. """ # TODO: De momento solo español. No hay inglés. Se ignora el parámetro. from reportlab.pdfgen import canvas from informes.geninformes import escribe, _build_codigo_domenech try: import Image except ImportError: from PIL import Image width = 12.55 * cm height = 8.4 * cm # Creo la hoja nomarchivo = os.path.join(gettempdir(), "dh_etiqbala_%s.pdf"%give_me_the_name_baby()) c = canvas.Canvas(nomarchivo, pagesize = (width, height)) ancho, alto = width, height # arribaArriba significa linea de "arriba" de los cuadros de "Arriba" # El 0 vertical es el borde de abajo # El 0 horizontal es el margen derecho arriba = alto - 1.45*cm #arriba = alto - 5 abajo = 5 #abajo = 1.45*cm izq = width - 5 der = 5 # ¿Va a resultar al final que también soy disléxico? xLogo = der + 0.5 * cm yLogo = arriba - 1.3 * cm xIzquierda = 20 xDerecha = ancho/2 + 0.25*inch yPrimeraLinea = yLogo - 0.8*inch ySegundaLinea = yPrimeraLinea - 0.31*inch yTerceraLinea = ySegundaLinea - 0.31*inch yCuartaLinea = yTerceraLinea - 0.31*inch yQuintaLinea = yCuartaLinea - 0.31*inch xCodigo = xDerecha + 3.50 * cm yCodigo = arriba - 3.75 * cm for bala in balas: # @UnusedVariable if not bala: # Es None. Por lo que sea :o continue if isinstance(bala, pclases.Articulo): bala = _build_dict_etiqueta_articulo_bala(bala) rectangulo(c, (izq, arriba), (der, abajo)) c.setFont("Helvetica-Bold", 28) c.drawString(xLogo, yLogo, "GEOTEXAN S.A.") c.setFont("Helvetica", 14) c.drawString(xIzquierda, yPrimeraLinea, escribe("CÓDIGO: " + bala['codigo'])) from barcode import code39 codigobarras = code39.Extended39(bala['codigo'], xdim = .020*inch) codigobarras.drawOn(c, xIzquierda - 0.5 * cm, yPrimeraLinea + 15) c.drawString(xIzquierda, yQuintaLinea, escribe("COLOR: %s" % (bala['color']))) c.drawString(xIzquierda, ySegundaLinea, escribe("LOTE: %s" % (bala['lote']))) c.drawString(xDerecha, ySegundaLinea, escribe("PESO KG: %s" % (bala['peso']))) c.drawString(xIzquierda, yTerceraLinea, escribe("TIPO: %s" % (bala['tipo']))) c.drawString(xDerecha, yTerceraLinea, escribe("LONGITUD: %s" % (bala['longitud']))) c.drawString(xIzquierda, yCuartaLinea, escribe("BALA Nº: %s" % (bala['nbala']))) c.drawString(xDerecha, yCuartaLinea, escribe("DTEX: %s" % (bala['dtex']))) c.drawString(xDerecha, yQuintaLinea, escribe("ACABADO: %s" % (bala['acabado']))) from barcode.EANBarCode import EanBarCode bar = EanBarCode() nombreficheroean13 = bar.getImage(bala['codigoBarra']) ean13rotado = Image.open(nombreficheroean13) ean13rotado = ean13rotado.rotate(90) ean13rotado.save(nombreficheroean13) c.drawImage(nombreficheroean13, xCodigo, yCodigo) # XXX: DOMENECH: from barcode import code128 seriep = None # Esto ya no se usa. Es la serie del pedido para el cliente numped = None # Esto ya no se usa. Es el núm. del pedido para el cliente codigodomenech = _build_codigo_domenech(bala, seriep, numped) if codigodomenech: barcodedomenech = code128.Code128(codigodomenech, #xdim = 0.015 * inch, #height = 0.5 * cm) xdim = 0.0205 * inch, height = 0.95 * cm) #barcodedomenech = code39.Extended39(codigodomenech, # #xdim = 0.015 * inch, # #height = 0.5 * cm) # xdim = 0.0094 * inch, # height = 0.95 * cm) ydom = alto - 1.2 * cm #ydom = 0.4 * cm xdom = (width - barcodedomenech.width) / 2.0 barcodedomenech.drawOn(c, xdom, ydom) c.saveState() c.setFont("Courier-Bold", 8) c.drawCentredString(xdom + (barcodedomenech.width / 2.0), ydom - 0.20 * cm, codigodomenech) c.restoreState() # XXX: EODOMENECH # XXX: Marca para identificar las nuevas. c.saveState() c.setFillColorRGB(0, 0, 0) c.circle(izq - 0.3*cm, yQuintaLinea, 0.1*cm, fill=1) c.restoreState() # XXX: EOMarca c.showPage() c.save() return nomarchivo
def go(dde_nombre = "", dde_direccion1 = "", dde_direccion2 = "", cliente_nombre = "", cliente_direccion1 = "", cliente_direccion2 = "", entrega1 = "", entrega2 = "", transportista_nombre = "", transportista_direccion1 = "", transportista_direccion2 = "", observaciones = "", ldvs = [], estipulaciones = "", ciudad = "", mes = "", # Día y mes o solo nombre del mes. Como se quiera. anno = "", # OJO: Sólo los dos últimos dígitos del año. solo_texto = False, porteador = "", sucesivos = "", ciudad_formalizado = ""): """ A partir de los parámetros recibidos construye un PDF con el CMR. ldvs es una lista de bultos, embalaje y kgs. Si solo_texto es True, no se dibuja la plantilla del albarán, solo los datos. Devuelve en nombre del fichero generado. """ # Inicialización y medidas: nomarchivo = os.path.join(gettempdir(), "cmr_%s.pdf" % ( geninformes.give_me_the_name_baby())) c = canvas.Canvas(nomarchivo) tampag = A4 c.setPageSize(tampag) tm, bm, lm, rm = 0.3*cm, 0.8*cm, 1*cm, 1*cm fuente, tamanno = "Helvetica", 8 hlin = 0.7*cm MAXLINEAS = int(5.5*cm / hlin) paginas = int(len(ldvs)/ MAXLINEAS) + 1 # Dato a imprimir, x1, x2 (o None si no va centrado) e y. # Si dato es una lista, se usará hlin para decrementar la y. # Si x1 y x2 son listas/tuplas, es porque el dato también se # divide en listas/tuplas (columnas) y se corresponden entre sí. medidas = { "dde_nombre": (dde_nombre, 2*cm, None, 27.50*cm), "dde_direccion1": (dde_direccion1, 2*cm, None, 27 *cm), "dde_direccion2": (dde_direccion2, 2*cm, None, 26.5 *cm), "cliente_nombre": (cliente_nombre, 2*cm, None, 25 *cm), "cliente_direccion1": (cliente_direccion1, 2*cm, None, 24.50*cm), "cliente_direccion2": (cliente_direccion2, 2*cm, None, 24 *cm), "entrega1": (entrega1, 2*cm, None, 22.25*cm), "entrega2": (entrega2, 2*cm, None, 22.65*cm), "transportista1_nombre": (transportista_nombre, 11.35*cm, None, 25.00*cm), "transportista1_direccion1": (transportista_direccion1, 11.35*cm, None, 24.50*cm), "transportista1_direccion2": (transportista_direccion2, 11.35*cm, None, 24.00*cm), "transportista2_nombre": (transportista_nombre, 7.80*cm, 13.30*cm, 3.5 *cm), "transportista2_direccion1": (transportista_direccion1, 7.80*cm, 13.30*cm, 2.75*cm), "transportista2_direccion2": (transportista_direccion2, 7.80*cm, 13.30*cm, 2.00*cm), "observaciones": (observaciones, 11.10*cm, 19.40*cm, 20.8 *cm), "porteador": (porteador, 11.10*cm, 19.40*cm, 24.50*cm), "sucesivos": (sucesivos, 11.10*cm, 19.40*cm, 22.65*cm), "ldvs": (ldvs, ( 4.50*cm, 7.30*cm, 15.20*cm),( 7.00*cm, 10.00*cm, 17.45*cm), 17.25*cm), "estipulaciones": (estipulaciones, 11.10*cm, 19.40*cm, 10 *cm), "ciudad1": (ciudad_formalizado, 3.75*cm, None, 4.85 *cm), "mes1": (mes, 7.8 *cm, None, 4.85 *cm), "anno1": (anno, 10.0 *cm, None, 4.85 *cm), "ciudad2": (ciudad, 14.50*cm, None, 3.10*cm), "mes2": (mes, 17.75*cm, None, 3.10*cm), "anno2": (anno, 19.2 *cm, None, 3.10*cm), } # Páginas del albarán for pag in range(1, paginas + 1): # Parte preimpresa: if not solo_texto: dibujar_imprenta(c, tampag) # Datos: c.setFont(fuente, tamanno) rellenar_datos(c, medidas, fuente, tamanno, hlin) rellenar_ldvs(c, ldvs[:MAXLINEAS], medidas, fuente, tamanno, hlin) ldvs = ldvs[MAXLINEAS:] c.showPage() c.save() return nomarchivo
def go(numalbaran = "XXXXXX", fecha = "", nombre_cliente = "", direccion = "", ciudad = "", cif = "", matricula = "", ldvs = [], total = 0.0, solo_texto = False): """ A partir de los parámetros recibidos construye un PDF con el albarán completo. ldvs es una lista de cantidad (float), concepto, kgs (float), precio (float) e importe (float). Si len(ldvs) > 12 genera (len(ldvs)/12) + 1 páginas, con el número de página entre paréntesis tras el número de albarán. Si solo_texto es True, no se dibuja la plantulla del albarán, solo los datos. Devuelve en nombre del fichero generado. """ # Inicialización y medidas: nomarchivo = os.path.join(gettempdir(), "albaran_%s.pdf" % ( geninformes.give_me_the_name_baby())) c = canvas.Canvas(nomarchivo) tampag = (19*cm, 14.8*cm) c.setPageSize(tampag) tm, bm, lm, rm = 1*cm, 1*cm, .7*cm, 1*cm fuente, tamanno = "Helvetica", 10 hlin = 0.7*cm MAXLINEAS = 12 paginas = int(len(ldvs) / MAXLINEAS) + 1 medidas = {"Albarán": (9*cm, tampag[1] - 1.4*cm), "N.º": (15.3*cm, tampag[1] - 1.3*cm), "Fecha": (14.3*cm, tampag[1] - 1.9*cm), "Cliente": (7.7*cm, tampag[1] - 2.5*cm), "Domicilio": (8*cm, tampag[1] - 3.1*cm), "Población": (2.7*cm, tampag[1] - 3.9*cm), "N.I.F.": (8.8*cm, tampag[1] - 3.9*cm), "Matrícula": (14.5*cm, tampag[1] - 3.9*cm), } xcantidad = 1.2*cm xconcepto = 3.4*cm xcateg = 9.4*cm xkgs = 11.25*cm xprecio = 13.05*cm ximporte = 15.7*cm y0 = tampag[1] - 4.2*cm yfinal = 1.75*cm y1 = yfinal + (MAXLINEAS * hlin) medidas_tabla = {"xcantidad": xcantidad, "xconcepto": xconcepto, "xcateg": xcateg, "xkgs": xkgs, "xprecio": xprecio, "ximporte": ximporte, "y0": y0, "yfinal": yfinal, "y1": y1, "ytotal": bm, "xfinal": tampag[0] - rm, } # Páginas del albarán for pag in range(1, paginas + 1): # Parte preimpresa: if not solo_texto: dibujar_imprenta(c, hlin, tm, bm, lm, rm, tampag, medidas, fuente, tamanno, MAXLINEAS, medidas_tabla) # Datos: c.setFont(fuente, tamanno) if paginas > 1: numalb = numalbaran + "(%d)" % pag if pag == paginas: strtot = utils.float2str(total) else: strtot = "" else: numalb = numalbaran strtot = utils.float2str(total) rellenar_datos(c, numalb, fecha, nombre_cliente, direccion, ciudad, cif, matricula, medidas, fuente, tamanno) rellenar_ldvs(c, ldvs[:MAXLINEAS], strtot, medidas_tabla, hlin) ldvs = ldvs[MAXLINEAS:] c.showPage() c.save() return nomarchivo
def go_from_albaranSalida(albaranSalida): """ Construye el PDF a partir de un objeto albaranSalida y no de sus datos sueltos. """ cliente = albaranSalida.cliente datos_cliente = {"código": cliente.id, "cif": cliente.cif, "razón social": cliente.nombre, "dirección": cliente.direccion, "población": cliente.ciudad, "provincia": cliente.provincia} if cliente.cp and cliente.cp.strip(): datos_cliente["población"] = (cliente.cp + " - " + datos_cliente["población"]) datos_albaran = {"fecha": utils.str_fecha(albaranSalida.fecha), "número": albaranSalida.numalbaran, "codcliente": albaranSalida.cliente and `albaranSalida.cliente.id` or ""} iva = cliente.iva lineas_contenido = [(ldv.producto.codigo, ldv.producto.descripcion, ldv.cantidad, ldv.precio * (1.0 - ldv.descuento) * (1 + iva), ldv.pedidoVenta and ldv.pedidoVenta.numpedido or "") for ldv in albaranSalida.lineasDeVenta] totales = [albaranSalida.calcular_total(iva_incluido = False), iva, albaranSalida.calcular_total(iva_incluido = True)] try: dde = pclases.DatosDeLaEmpresa.select()[0] datos_de_la_empresa = [os.path.join("..", "imagenes", dde.logo), dde.nombre + (dde.cif and " (" + dde.str_cif_o_nif() +": " + dde.cif + ")" or ""), dde.direccion, "%s %s (%s), %s" % (dde.cp, dde.ciudad, dde.provincia, dde.pais), ] if dde.fax: if dde.fax.strip() == dde.telefono.strip(): datos_de_la_empresa.append("Telf. y fax: %s" % dde.telefono) else: datos_de_la_empresa.append("Telf.: %s" % (dde.telefono)) datos_de_la_empresa.append("Fax: %s" % (dde.fax)) if dde.email: datos_de_la_empresa.append(dde.email) except IndexError: pass nomarchivo = os.path.join(gettempdir(), "albaranSalida_%s.pdf" % give_me_the_name_baby()) return go("Albaran de salida %s (%s)" % ( albaranSalida.cliente.nombre, utils.str_fecha(albaranSalida.fecha)), nomarchivo, datos_cliente, datos_albaran, lineas_contenido, totales, datos_de_la_empresa)
def etiqueta_rollos_polaco(rollos, mostrar_marcado = True): """ Construye una etiqueta en polaco para Alians Trade. """ # Dimensiones de la etiqueta en impresora térmica GEMINI. height = h = 12.55 * cm width = w = 8.4 * cm MARGEN = 0.05 * cm if DEBUG: print_debug(height = height, width = width) try: logo_marcado = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "imagenes", "CE.png")) except IOError: # Reportlab o PIL sin soporte libzip logo_marcado = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "imagenes", "CE.gif")) logo_alians = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "imagenes", "alians_trade.png")) WM = 1.0 * cm WA = 1.5 * cm im_width, im_height = Image.open(logo_marcado).size WH_MARCADO = (WM, im_height * (WM / im_width)) im_width, im_height = Image.open(logo_alians).size WH_ALIANS = (WA, im_height * (WA / im_width)) if DEBUG: print_debug(WH_MARCADO = WH_MARCADO, WH_ALIANS = WH_ALIANS) # Medidas relativas sobre papel. H_TEXTMARCADO = 0.2 * cm xy_logo = (1.5*mm, h - (WH_MARCADO[1] + H_TEXTMARCADO + WH_ALIANS[1])) xy_ce = ((w - WH_MARCADO[0]) / 2, h - WH_MARCADO[1] - 1.5*mm) xy_textmarcado = (w/2, xy_logo[1] + WH_ALIANS[1] - H_TEXTMARCADO) if DEBUG: print_debug(xy_ce = xy_ce, xy_textmarcado = xy_textmarcado, xy_logo = xy_logo) # Datos texto_marcado1 = "1488-CPD-0275/Z" texto_marcado2 = "12" X_HEADER = WH_ALIANS[0] + 0.2*cm data = [("PRODUCENT/PRODUCER:", {'x': X_HEADER, 'format': CENTER}), ("ALIANS TRADE SP. Z O.O.", {'x': X_HEADER, 'format': BOLD + CENTER}), ("ul. Wyzwolenia 367a, 43-300 Bielsko-Biała", {'x': X_HEADER, 'format': CENTER}), ("www.alians-trade.eu", {'x': X_HEADER, 'format': CENTER}), ("ZAKŁAD PRODUKCYJNY/FACTORY CODE: 34-133", {'x': X_HEADER, 'format': CENTER}), ("NAZWA PRODUKTU/ PRODUCT NAME:", {'format': CENTER}), #("Geowłóknina PINEMA® ST ", {'format': CENTER}), ("$PRODUCTO", {'format': CENTER}), # Geowłóknina PINEMA® ST + Texto variable {80, 100, 180, 250} ("geowłóknina wyprodukowana ze 100% polipropylenu/", {'format': CENTER}), ("nonwoven geotextile composed of 100% polypropilene", {'format': CENTER}), "NORMY/ APPLICATION STANDARDS:", ("EN 13249:2000, EN 13250:2000, EN 13251:2000, EN 13252:2000,", {'format': BOLD}), ("EN 13253:2000, EN 13254:2000, EN 13255:2000, EN 13256:2000,", {'format': BOLD}), ("EN 13257:2000, EN 13265:2000,", # Negrita {'format': BOLD}), # Las siguientes 5 líneas en fuente más pequeña. ("EN 13249:2000/A1:2005, EN 13250:2000/A1:2005, EN 13251:2000/A1:2005,", {'size': SIZE-1}), ("EN 13252:2000/A1:2005, EN 13253:2000/A1:2005, EN 13254:2000/AC:2003,", {'size': SIZE-1}), ("EN 13254:2000/A1:2005, EN 13255:2000/AC:2003, EN 13255:2000/A1:2005,", {'size': SIZE-1}), ("EN 13256:2000/AC:2003,EN 13256:2000/A1:2005, EN 13257:2000/AC:2003,", {'size': SIZE-1}), # Esta última, además de pequeña, en negrita. ("EN 13257:2000/A1:2005, EN 13265:2000/AC:2003, EN 13265:2000/A1:2005", {'format': BOLD, 'size': SIZE-1}), "ZASTOSOWANIE/ APPLICATION: w drogownictwie, kolejnictwie, w robotach ", "ziemnych i konstrukcjach oporowych, w systemach drenażowych, w ", "zabezpieczeniach antyerozyjnych, w budowie zbiorników wodnych i zapór, ", "w budowie kanałów, tuneli i konstrukcji podziemnych, w budowie ", "składowisk odpadów stałych i zbiorników odpadów ciekłych.", "PRZEZNACZENIE/ INTENDED FUNCTIONS: rozdzielenie, filtracja, ", "drenaż, wzmocnienie.", # De aquí para abajo, en dos columnas (("NR ROLKI/ ", "GRAMATURA/"), {'size': SIZE - 2}), (("ROLL NO.:", "$NUMROLLO", "NOMINAL MASS (g/m2):", "$GRAMAJE"), {'format': ITALIC, 'size': SIZE - 2}), (("DŁUGOŚĆ/", "SZEROKOŚĆ/"), {'size': SIZE - 2}), (("LENGHT (m):", "$LARGO", "WIDTH (m):", "$ANCHO"), {'format': ITALIC, 'size': SIZE - 2}), (("WAGA BRUTTO/", "DATA PRODUKCJI/"), {'size': SIZE - 2}), (("GROSS WEIGHT (kg):", "$PESO", "DATE OF PRODUCTION:", "$FECHA"), {'format': ITALIC, 'size': SIZE - 2}) ] # 31 líneas. En principio distribuyo uniformemente: alto_linea = (xy_textmarcado[1] - 2*H_TEXTMARCADO) / (len(data) + 1) # (0,0) está abajo. Yo relleno la etiqueta de arriba a abajo. y_lines = [(xy_textmarcado[1] - 2*H_TEXTMARCADO) - (y * alto_linea) for y in range(len(data) +1)[1:]] if DEBUG: print_debug(y_lines = y_lines) print_debug(alto_linea = alto_linea) # Creo la hoja nomarchivo = os.path.join(gettempdir(), "etiqAliansT_%s.pdf" % give_me_the_name_baby()) c = canvas.Canvas(nomarchivo, pagesize = (width, height)) # import code; code.interact(local = locals()) for rollo in rollos: # Elementos gráficos: borde etiqueta y logos. rectangulo(c, (MARGEN, MARGEN), (width - MARGEN, height - MARGEN)) c.drawImage(logo_alians, xy_logo[0], xy_logo[1], WH_ALIANS[0], WH_ALIANS[1]) if mostrar_marcado and not rollo['defectuoso']: c.drawImage(logo_marcado, xy_ce[0], xy_ce[1], width = WH_MARCADO[0], height = WH_MARCADO[1]) c.setFont("Helvetica-Bold", SIZE) c.drawCentredString(xy_textmarcado[0], xy_textmarcado[1], escribe(texto_marcado1)) c.drawCentredString(xy_textmarcado[0], xy_textmarcado[1] - H_TEXTMARCADO, escribe(texto_marcado2)) c.setFont(FONT, SIZE) # Texto de la etiqueta c.setFont(FONT, SIZE) for i in range(len(data)): #c.drawString(0, y_lines[i], escribe(data[i])) #c.drawString(2*mm, y_lines[i], data[i]) if isinstance(data[i], (list, tuple)): texto = data[i][0] opciones = data[i][1] if not isinstance(opciones, dict): texto = (texto, opciones) else: texto = data[i] opciones = {} render(c, 2*mm, y_lines[i], texto, opciones = opciones, fuente = FONT, tamanno = SIZE, w = w, h = h, margen = MARGEN, rollo = rollo) c.showPage() c.save() return nomarchivo
def imprimir(self, boton): # OJO: Como no hay catálogo de pruebas en la base de datos, las # unidades, métodos y descripciones de las pruebas sobre geotextiles # están HARCODED aquí. # PLAN: Meter todo esto en el tablas.sql, como debe de ser. data_prueba = { "Resistencia longitudinal": {"descripción": "Resistencia a la tracción DM", "método": "EN ISO 10319", "unidad": "kN/m"}, "Resistencia transversal": {"descripción": "Resistencia a la tracción DT", "método": "EN ISO 10319", "unidad": "kN/m"}, "Alargamiento longitudinal": {"descripción": "Alargamiento DM", "método": "EN ISO 10319", "unidad": "%"}, "Alargamiento transversal": {"descripción": "Alargamiento DT", "método": "EN ISO 10319", "unidad": "%"}, "Perforación": {"descripción": "Resistencia a la perforación dinámica (Caída de cono)", "método": "EN ISO 13433", "unidad": "mm"}, "Resistencia a la compresión": {"descripción": "Resistencia al punzonado estático (CBR a perforación)", "método": "EN ISO 12236", "unidad": "kN"}, "Apertura de poros": {"descripción": "Medida de apertura (Porometría 090)", "método": "EN ISO 12956", "unidad": "mm"}, "Punzonado piramidal": {"descripción": "Resistencia al punzonado piramidal", "método": "NF G38-019", "unidad": "kN"}, "Permeabilidad": {"descripción": "Permeabilidad perpendicular al agua", "método": "EN ISO 11058", "unidad": "l/m²/s"}, "Gramaje": {"descripción": "Gramaje", "método": "EN ISO 9864", "unidad": "g/m²"}, "Espesor": {"descripción": "Espesor bajo 2 kPa", "método": "EN ISO 9863-1", "unidad": "mm"} } if not self.objeto: return #tv = self.wids['tv_datos'] #from informes.treeview2pdf import treeview2pdf from formularios.reports import abrir_pdf #strfecha = "%s - %s" % (utils.str_fecha(mx.DateTime.localtime()), # utils.str_hora(mx.DateTime.localtime())) #abrir_pdf(treeview2pdf(tv, # titulo = "Certificado de calidad de albarán %s" % ( # self.objeto.numalbaran), # fecha = strfecha, # apaisado = False)) from informes import informe_certificado_calidad from informes.geninformes import give_me_the_name_baby from time import sleep dic_productos = {} model = self.wids['tv_datos'].get_model() for fila in model: producto = pclases.getObjetoPUID(fila[-1]) dic_productos[producto] = {} for hijo in fila.iterchildren(): caracteristica = hijo[0] valor = hijo[-2] dic_productos[producto][caracteristica] = { "descripción": data_prueba[caracteristica]["descripción"], "método": data_prueba[caracteristica]["método"], "unidad": data_prueba[caracteristica]["unidad"], "valor": valor} for producto in dic_productos: dic_valores = dic_productos[producto] if producto.es_rollo(): orden = ("Resistencia longitudinal", "Resistencia transversal", "Alargamiento longitudinal", "Alargamiento transversal", "Perforación", "Resistencia a la compresión", "Apertura de poros", "Permeabilidad", "Gramaje", "Espesor", "Punzonado piramidal") nomfich = informe_certificado_calidad.go( "certcalidad_%s.pdf" % give_me_the_name_baby(), producto, dic_valores, pclases.DatosDeLaEmpresa.select()[0], self.objeto, orden = orden) sleep(1) abrir_pdf(nomfich)
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
def go_from_presupuesto(presupuesto): """ Construye el PDF a partir de un objeto presupuesto y no de sus datos sueltos. """ try: dde = pclases.DatosDeLaEmpresa.select()[0] lineas_empresa = [dde.nombre, dde.direccion, "%s %s (%s), %s" % (dde.cp, dde.ciudad, dde.provincia, dde.pais), "Telf.: %s" % (dde.telefono)] if dde.fax: lineas_empresa.append("Fax: %s" % (dde.fax)) if dde.email: lineas_empresa.append(dde.email) except IndexError: lineas_empresa = [] lineas_contenido = presupuesto.lineasDePedido + presupuesto.servicios datos_cliente = [] if presupuesto.personaContacto != "": datos_cliente.append("A la atención de %s" % (presupuesto.personaContacto)) datos_cliente.append(presupuesto.nombrecliente) datos_cliente.append(presupuesto.direccion) listadireccion = [presupuesto.cp, presupuesto.ciudad] if presupuesto.ciudad.strip() != presupuesto.provincia.strip(): listadireccion.append(presupuesto.provincia) listadireccion.append(presupuesto.pais) segunda_linea_direccion = " ".join([token.strip() for token in listadireccion if token.strip() != ""]) datos_cliente.append(segunda_linea_direccion) if presupuesto.telefono.strip() != "": datos_cliente.append("Tlf.: %s" % (presupuesto.telefono)) if presupuesto.fax.strip() != "": datos_cliente.append("Fax.: %s" % (presupuesto.fax)) fecha_entradilla = utils.str_fecha(presupuesto.fecha) try: dde = pclases.DatosDeLaEmpresa.select()[0] iva = dde.iva except IndexError: iva = 0.21 totales = {"orden": ["Base imponible", "IVA %d%%" % (iva * 100), "TOTAL"], "Base imponible": utils.float2str(presupuesto.calcular_base_imponible()), "IVA %d%%" % (iva * 100): utils.float2str(presupuesto.calcular_total_iva()), "TOTAL": utils.float2str(presupuesto.calcular_importe_total()) } if presupuesto.descuento: fila_descuento = "Descuento %s %%" % ( utils.float2str(presupuesto.descuento*100, autodec = True)) totales['orden'].insert(0, fila_descuento) totales[fila_descuento] = utils.float2str( presupuesto.calcular_subtotal(incluir_descuento = False) * presupuesto.descuento * -1) fila_subtotal = "Subtotal" totales['orden'].insert(0, fila_subtotal) totales[fila_subtotal] = utils.float2str( presupuesto.calcular_subtotal(incluir_descuento = False)) total_irpf = presupuesto.calcular_total_irpf() if total_irpf != 0: try: dde = pclases.DatosDeLaEmpresa.select()[0] irpf = dde.irpf except IndexError: irpf = None texto_irpf = "IRPF" if irpf: texto_irpf += " (%d%%)" % (irpf*100) totales[texto_irpf] = utils.float2str(total_irpf) totales["orden"].insert(-2, texto_irpf) try: dde = pclases.DatosDeLaEmpresa.select()[0] logo = dde.get_ruta_completa_logo() except IndexError: logo = None if presupuesto.validez: validez = presupuesto.validez else: validez = None nomarchivo = os.path.join(gettempdir(), "presupuesto_%s.pdf" % give_me_the_name_baby()) go("Presupuesto %s (%s)" % (presupuesto.cliente.nombre, utils.str_fecha(presupuesto.fecha)), nomarchivo, lineas_empresa, datos_cliente, lineas_contenido, fecha_entradilla, totales, presupuesto.texto, presupuesto.despedida, ruta_logo = logo, validez = validez, numpresupuesto = presupuesto.numpresupuesto) return nomarchivo
def go_from_albaranSalida(albaranSalida, kilos = None, imprimir_recogida = True): """ Construye el PDF a partir de un objeto albaranSalida y no de sus datos sueltos. «kilos» es un texto que se imprimirá en el cuadro correspondiente. Si es none intenta calcularlo. «imprimir_recogida» es un booleano. Si es False no genera la última página. """ cliente = albaranSalida.cliente datos_cliente = {"código": cliente.id, "cif": cliente.cif, "razón social": cliente.nombre, "dirección": cliente.direccion, "población": cliente.ciudad, "provincia": cliente.provincia} if cliente.cp and cliente.cp.strip(): datos_cliente["población"] = (cliente.cp + " - " + datos_cliente["población"]) if kilos is None: try: kilos = utils.float2str( sum([ldv.producto.calcular_kilos() * ldv.cantidad for ldv in albaranSalida.lineasDeVenta])) except (TypeError, ValueError): kilos = "" datos_albaran = {"fecha": utils.str_fecha(albaranSalida.fecha), "número": albaranSalida.numalbaran, "kilos": kilos, "bultos": utils.float2str( sum([ldv.cantidad for ldv in albaranSalida.lineasDeVenta]), autodec = True)} iva = cliente.iva lineas_contenido = [(ldv.producto.codigo, ldv.producto.descripcion, ldv.cantidad, #ldv.precio * (1.0 - ldv.descuento) * (1 + iva), # CWT: Ahora prefiere los precios sin IVA. ldv.precio * (1.0 - ldv.descuento), ldv.pedidoVenta and ldv.pedidoVenta.numpedido or "") for ldv in albaranSalida.lineasDeVenta] totales = [albaranSalida.calcular_total(iva_incluido = False), iva, albaranSalida.calcular_total(iva_incluido = True)] try: dde = pclases.DatosDeLaEmpresa.select()[0] datos_de_la_empresa = [os.path.join("..", "imagenes", dde.logo), dde.nombre + (dde.cif and " (" + dde.str_cif_o_nif() +": " + dde.cif + ")" or ""), dde.direccion, "%s %s (%s), %s" % (dde.cp, dde.ciudad, dde.provincia, dde.pais), ] if dde.fax: if dde.fax.strip() == dde.telefono.strip(): datos_de_la_empresa.append("Telf. y fax: %s" % dde.telefono) else: datos_de_la_empresa.append("Telf.: %s" % (dde.telefono)) datos_de_la_empresa.append("Fax: %s" % (dde.fax)) if dde.email: datos_de_la_empresa.append(dde.email) titular = dde.nombreContacto except IndexError: datos_de_la_empresa = [None] titular = "" nomarchivo = os.path.join(gettempdir(), "albaranSalida_%s.pdf" % give_me_the_name_baby()) return go("Albaran de salida - Carta de portes %s (%s)" % ( albaranSalida.cliente.nombre, utils.str_fecha(albaranSalida.fecha)), nomarchivo, datos_cliente, datos_albaran, lineas_contenido, totales, datos_de_la_empresa, titular, imprimir_recogida)
def crear_etiquetas_bigbags(bigbags, mostrar_marcado=True, lang="es"): """ Construye una etiqueta por cada objeto bigbag 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_bigbag13_%s_%s.pdf" % (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": "EN 14889-2:2008", # Fijo "11 blanco2": "", # Separador "12 producto": None, "13 descripcion": "", "14 uso": None, "15 blanco3": "", # Separador # "16 1 separador": "", # Fijo "16 codigo": "Lote {} · Bigbag {}", # Código bigbag y código lote. "17 caracteristicas": "Corte: {} mm · Peso: {} kg/br" # Corte y peso. } if lang == "en": for k in _data: _data[k] = helene_laanest(_data[k]) estilos = defaultdict(lambda: ("Helvetica-Bold", 11)) # Helvética a 11 por defecto estilos["01 texto_marcado"] = ("Times-Bold", 9) estilos["02 fabricado_por"] = ("Helvetica-Bold", 13) estilos["12 producto"] = ("Courier-Bold", 17) estilos["14 uso"] = ("Helvetica-Bold", 10) estilos["15 blanco3"] = ("Helvetica-Bold", 10) estilos["16 codigo"] = ("Courier-Bold", 13) estilos["17 caracteristicas"] = ("Helvetica-Bold", 14) data = {} # Datos de la BD dependientes del bigbag for bigbag in bigbags: # 0.- ¿En qué formato viene? Si es el antiguo (datos en diccionario) # me quedo con el objeto de pclases en sí. producto_venta = bigbag.articulo.productoVenta numpartida = bigbag.articulo.loteCem.codigo numbigbag = bigbag.codigo # 1.- Empresa try: # Si hay distribuidor, este texto cambia. distribuidor = bigbag.articulo.productoVenta.camposEspecificosBala.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 data["12 producto"] = producto.nombre if producto.uso: if lang == "en": produso = helene_laanest(producto.uso) else: produso = producto.uso if len(produso) > 30: # Wrap si el texto es largo. produso = textwrap.wrap(produso, (len(produso) + max([len(w) for w in produso.split()])) / 2) data["14 uso"] = produso[0] data["15 blanco3"] = produso[1] # Era un separador, pero # necesito el espacio. else: data["14 uso"] = produso else: data["14 uso"] = "" # 3.- Bigbag data["16 codigo"] = _data["16 codigo"].format(numpartida, numbigbag) corte = producto.camposEspecificosBala.corte peso = float2str(bigbag.articulo.peso_bruto) corte_peso = _data["17 caracteristicas"].format(corte, peso) data["17 caracteristicas"] = corte_peso 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) 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 canvas.showPage() canvas.save() return nomarchivo
def go(titulo, ruta_archivo, lineas_datos_empresa, datos_cliente, lineas_contenido, fecha_entradilla, totales = {}, texto = None, despedida = None, ruta_logo = None, validez = None, condicionado = None, texto_riesgo = None, numpresupuesto = "", incluir_condicionado_general = True, forma_de_pago = None, dir_fiscal = None, firma_comercial = None, para_estudio = False, idioma = "es"): """ Recibe el título del documento y la ruta completa del archivo. Si validez != None escribe una frase con la validez del presupuesto. """ if idioma not in ("en", "es"): raise NotImplementedError,\ __file__ + ": Idioma '%s' no implementado." % idioma doc = SimpleDocTemplate(ruta_archivo, title = titulo) encabezado = build_encabezado(lineas_datos_empresa) try: nombrecliente = datos_cliente[0].replace(" ", "_") except: nombrecliente = "" datos_cliente = build_datos_cliente(datos_cliente) entradilla = build_entradilla(fecha_entradilla, numpresupuesto, para_estudio, lang = idioma) texto = build_texto(texto) contenido = build_tabla_contenido(lineas_contenido, lang = idioma) totales = build_tabla_totales(totales) despedida = build_texto(despedida) forma_pago = build_texto(forma_de_pago) comercial = build_texto(firma_comercial) story = [encabezado, datos_cliente, entradilla, Spacer(1, 0.2 * cm), contenido, Spacer(1, 0.25 * cm), totales, Spacer(1, 1 * cm), forma_pago, Spacer(1, 2 * cm), texto, Spacer(1, 0.2 * cm), despedida, Spacer(1, 0.5 * cm), comercial] #if validez: #story.insert(9, build_validez(validez)) if texto_riesgo: story.insert(-8, build_texto_riesgo(texto_riesgo)) #if condicionado: # El condicionado es el texto en sí. # story.insert(-2, Spacer(1, 2 * cm)) # story.insert(-2, build_condicionado(condicionado)) story = utils.aplanar([i for i in story if i]) _dibujar_logo = lambda c, d: dibujar_logo(c, d, ruta_logo, idioma) _dibujar_dir_fiscal = lambda c, d: dibujar_dir_fiscal(c, d, dir_fiscal) def dibujar_logo_y_dir_fiscal(c, d): _dibujar_logo(c, d) _dibujar_dir_fiscal(c, d) doc.build(story, onFirstPage = dibujar_logo_y_dir_fiscal, onLaterPages = _dibujar_dir_fiscal) # Agrego condiciones generales: if incluir_condicionado_general: from lib.PyPDF2 import PyPDF2 pdf_presupuesto = open(ruta_archivo, "rb") if idioma == "en": fcond = "condiciones_generales_en.pdf" else: fcond = "condiciones_generales.pdf" pdf_condiciones = open( os.path.join(os.path.dirname(os.path.abspath(__file__)), fcond), "rb") merger = PyPDF2.PdfFileMerger() merger.append(pdf_presupuesto) merger.append(pdf_condiciones) combinado = os.path.join(gettempdir(), "oferta_%d_%s_%s.pdf" % (numpresupuesto, sanitize(nombrecliente, strict = True), give_me_the_name_baby())) merger.write(open(combinado, "wb")) ruta_archivo = combinado return ruta_archivo
def etiqueta_rollos_portrait(rollos, mostrar_marcado = True): """ Construye una etiqueta """ # Voy a tratar de reescribir esto regla en mano a ver si consigo # cuadrarlo bien en la etiquetadora GEMINI. height = 12.55 * cm width = 8.4 * cm # Escala ancho = 7.2 # @UnusedVariable alto = 11.3 scale = height / alto # Medidas en papel. brand = (0.4 * scale, (alto - 2.0) * scale) logo = (3.8 * scale, (alto - 2.8) * scale) marcado = ((7.2/2) * scale, (alto - 3.0) * scale) column1 = .35 * scale column2 = logo[0] lineas = map(lambda x: (alto - x) * scale, [3.4 + (i*.6) for i in range(13)]) # Datos data = {'brand': "EkoTex", "c100": "UK Distributor", "c108": "Product Name", "c109": "Roll Number", "c110": "Product Dimensions", "c111": "Polymer", "c112": "Product Classification", "c200": "Geosynthetics Limited", "c201": "Fleming Road", "c202": "Harrowbrook Ind Est", "c203": "Hinckley", "c204": "Leicestershire", "c205": "LE10 3 DU", "c206": "Tel 01455 617139", "c207": "Fax 01455 617140", "c211": "Polypropylene", "c212": "GTX-N", "marcado": "0799-CPD", # Hay que incluirle el logotipo CE delante. } data["logo"] = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "imagenes", "logo_ekotex.png")) # Ruta absoluta # a la imagen del logotipo. try: logo_marcado = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "imagenes", "CE.png")) except IOError: # Reportlab o PIL sin soporte libzip logo_marcado = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "imagenes", "CE.gif")) # Creo la hoja nomarchivo = os.path.join(gettempdir(), "etiqEkotex_%s.pdf" % give_me_the_name_baby()) c = canvas.Canvas(nomarchivo, pagesize = (width, height)) for rollo in rollos: try: data["c208"] = rollo['objeto'].productoVenta.nombre data["c209"] = rollo['objeto'].numrollo cer = rollo['objeto'].productoVenta.camposEspecificosRollo except AttributeError: # No se ha creado el objeto todavía. Es None. data["c208"] = rollo['productoVenta'].nombre data["c209"] = rollo['nrollo'] cer = rollo['productoVenta'].camposEspecificosRollo data["c210"] = "%sm x %dm" % (float2str(cer.ancho, autodec = True, separador_decimales = "."), cer.metrosLineales) rectangulo(c, (0.3 * cm, 0.3 * cm), (width - 0.3 * cm, height - 0.3 * cm)) c.setFont("Helvetica-Bold", 16) c.drawString(brand[0], brand[1], escribe(data['brand'])) c.setFont("Helvetica-Bold", 10) c.drawString(column1, lineas[0], escribe(data['c100'])) c.drawString(column1, lineas[8], escribe(data['c108'])) c.drawString(column1, lineas[9], escribe(data['c109'])) c.drawString(column1, lineas[10], escribe(data['c110'])) c.drawString(column1, lineas[11], escribe(data['c111'])) c.drawString(column1, lineas[12], escribe(data['c112'])) c.drawString(column2, lineas[0], escribe(data['c200'])) c.drawString(column2, lineas[1], escribe(data['c201'])) c.drawString(column2, lineas[2], escribe(data['c202'])) c.drawString(column2, lineas[3], escribe(data['c203'])) c.drawString(column2, lineas[4], escribe(data['c204'])) c.drawString(column2, lineas[5], escribe(data['c205'])) c.drawString(column2, lineas[6], escribe(data['c206'])) c.drawString(column2, lineas[7], escribe(data['c207'])) c.drawString(column2, lineas[8], escribe(data['c208'])) c.drawString(column2, lineas[9], escribe(data['c209'])) c.drawString(column2, lineas[10], escribe(data['c210'])) c.drawString(column2, lineas[11], escribe(data['c211'])) c.drawString(column2, lineas[12], escribe(data['c212'])) c.drawImage(data['logo'], logo[0], logo[1], 2.5 * cm, 2.5 * cm) if mostrar_marcado and not rollo['defectuoso']: c.drawImage(logo_marcado, marcado[0] - ((0.30*cm + c.stringWidth(data['marcado']) ) / 2), marcado[1], width = 0.35 * cm, height = 6) c.setFont("Helvetica-Bold", 8) c.drawCentredString(marcado[0] + ((0.35*cm) / 2), marcado[1], escribe(data["marcado"])) #c.setPageRotation(-90) #c.rotate(-90) c.showPage() c.save() return nomarchivo
def go_from_presupuesto(presupuesto, incluir_condicionado_general = True, idioma = "es"): """ Construye el PDF a partir de un objeto presupuesto y no de sus datos sueltos. """ try: dde = pclases.DatosDeLaEmpresa.select()[0] lineas_empresa = [dde.nombre, dde.direccion, "%s %s (%s), %s" % (dde.cp, dde.ciudad, dde.provincia, dde.pais), "Tel.: %s" % (dde.telefono)] if dde.fax: lineas_empresa.append("Fax: %s" % (dde.fax)) if dde.email: lineas_empresa.append(dde.email) elif presupuesto.comercial and presupuesto.comercial.correoe: lineas_empresa.append(presupuesto.comercial.correoe) if dde.web: lineas_empresa.append('<a href=http://%s>%s</a>' % ( dde.web, dde.web)) # Son pocos textos. No merece la pena tirar de gettext hasta que # no me pidan un tercer idioma. if idioma == "en": strfiscal = "Corp. data: %s %s %s %s" else: strfiscal = "Datos fiscales: %s %s %s %s" dir_fiscal = strfiscal % ( dde.nombre, dde.get_dir_facturacion_completa(), dde.str_cif_o_nif(), dde.cif) except IndexError: lineas_empresa = [] dir_fiscal = "" #lineas_contenido = presupuesto.lineasDePedido + presupuesto.servicios lineas_contenido = presupuesto.lineasDePresupuesto lineas_contenido.sort(key = lambda ldp: ldp.id) datos_cliente = [] nombre_cliente = presupuesto.nombrecliente datos_cliente.append(nombre_cliente) cif = presupuesto.cliente and presupuesto.cliente.cif or presupuesto.cif datos_cliente.append(" <small>(%s)</small>" % cif) if presupuesto.personaContacto != "": if idioma == "en": stratt = "Att: %s" else: stratt = "A la atención de %s" datos_cliente.append(stratt % ( presupuesto.personaContacto)) datos_cliente.append(presupuesto.direccion) listadireccion = [presupuesto.cp, presupuesto.ciudad] if presupuesto.ciudad.strip() != presupuesto.provincia.strip(): if presupuesto.ciudad.strip(): listadireccion.append("(" + presupuesto.provincia + ")") else: listadireccion.append(presupuesto.provincia) listadireccion.append(presupuesto.pais) segunda_linea_direccion = " ".join([token.strip() for token in listadireccion if token.strip() != ""]) datos_cliente.append(segunda_linea_direccion) if presupuesto.telefono.strip() != "": if idioma == "en": strphone = "Phone n.: %s" else: strphone = "Tlf.: %s" datos_cliente.append(strphone % (presupuesto.telefono)) if presupuesto.fax.strip() != "": datos_cliente.append("Fax.: %s" % (presupuesto.fax)) if presupuesto.obra or presupuesto.nombreobra.strip(): try: ref_obra = presupuesto.obra.obra.get_str_obra() except AttributeError: ref_obra = presupuesto.nombreobra if idioma == "en": strobra = "Ref.: <b>%s</b>" else: strobra = "Ref. obra: <b>%s</b>" datos_cliente.append(strobra % ref_obra) fecha_entradilla = utils.str_fecha(presupuesto.fecha) try: iva = presupuesto.cliente.get_iva_norm() except AttributeError: if (presupuesto.pais and presupuesto.pais.upper() not in ("ESPAÑA", "ESPAñA", "SPAIN")): iva = 0 else: iva = 0.21 if idioma == "en": strbimp = "Subtotal" striva = "VAT %d%%" % (iva * 100) strtot = "TOTAL" else: strbimp = "Base imponible" striva = "IVA %d%%" % (iva * 100) strtot = "TOTAL" totales = {"orden": [strbimp, striva, strtot], strbimp: utils.float2str(presupuesto.calcular_base_imponible())+" €", striva: utils.float2str(presupuesto.calcular_total_iva())+" €", strtot: utils.float2str(presupuesto.calcular_importe_total())+" €", } if presupuesto.descuento: if idioma == "en": strdto = "Descuento %s %%" else: strdto = "Discount %s %%" fila_descuento = strdto % ( utils.float2str(presupuesto.descuento*100, autodec = True)) totales['orden'].insert(0, fila_descuento) totales[fila_descuento] = utils.float2str( presupuesto.calcular_subtotal(incluir_descuento = False) * presupuesto.descuento * -1) fila_subtotal = "Subtotal" totales['orden'].insert(0, fila_subtotal) totales[fila_subtotal] = utils.float2str( presupuesto.calcular_subtotal(incluir_descuento = False)) total_irpf = presupuesto.calcular_total_irpf() if total_irpf != 0: try: dde = pclases.DatosDeLaEmpresa.select()[0] irpf = dde.irpf except IndexError: irpf = None texto_irpf = "IRPF" if irpf: texto_irpf += " (%d%%)" % (irpf*100) totales[texto_irpf] = utils.float2str(total_irpf) totales["orden"].insert(-2, texto_irpf) try: dde = pclases.DatosDeLaEmpresa.select()[0] logo = dde.get_ruta_completa_logo() except IndexError: logo = None if presupuesto.validez: validez = presupuesto.validez else: validez = None if presupuesto.texto: condiciones = presupuesto.texto + "\n" else: condiciones = None # Condiciones "blandas" del presupuesto # CWT: Se debe imprimir en todos los presupuestos, por si a la hora de # formalizarlo como pedido se ha quedado sin crédito por alguna operación # anterior al pedido y posterior a la oferta. #if (not presupuesto.cliente # or presupuesto.cliente.calcular_credito_disponible( # base = presupuesto.calcular_importe_total(iva = True)) <= 0): if True: if idioma == "en": texto_riesgo = "Operation conditioned by a previous credit "\ "approbation by %s." % dde.nombre else: texto_riesgo = "Esta operación está sujeta a la concesión de "\ "crédito por parte de %s." % dde.nombre else: texto_riesgo = None nomarchivo = os.path.join(gettempdir(), "presupuesto_%s.pdf" % give_me_the_name_baby()) if presupuesto.texto: if idioma == "en": condicionado = "Particular conditions:\n" + presupuesto.texto else: condicionado = "Condiciones particulares:\n" + presupuesto.texto else: condicionado = None try: if idioma == "en": strpresupuesto = "Offer " fdp = "Payment terms: %s" % presupuesto.formaDePago.toString( presupuesto.cliente) else: strpresupuesto = "Presupuesto" fdp = "Forma de pago: %s" % presupuesto.formaDePago.toString( presupuesto.cliente) except AttributeError: fdp = "" if presupuesto.comercial: firma_comercial = '<b>%s %s</b>\n<i>%s</i>\n%s\n<u>'\ '<a href="mailto:%s">%s</a></u>'\ '<b> </b>' % ( presupuesto.comercial.empleado.nombre and presupuesto.comercial.empleado.nombre or "", presupuesto.comercial.empleado.apellidos and presupuesto.comercial.empleado.apellidos or "", presupuesto.comercial.cargo and presupuesto.comercial.cargo or "", presupuesto.comercial.telefono and presupuesto.comercial.telefono or "", presupuesto.comercial.correoe and presupuesto.comercial.correoe or "", presupuesto.comercial.correoe and presupuesto.comercial.correoe or "") else: firma_comercial = "" nomarchivo = go( "%s %s (%s)" % (strpresupuesto, presupuesto.nombrecliente, utils.str_fecha(presupuesto.fecha)), nomarchivo, lineas_empresa, datos_cliente, lineas_contenido, fecha_entradilla, totales, condicionado, presupuesto.despedida, ruta_logo = logo, validez = validez, texto_riesgo = texto_riesgo, #numpresupuesto = presupuesto.numpresupuesto) numpresupuesto = presupuesto.id, forma_de_pago = fdp, dir_fiscal = dir_fiscal, firma_comercial = firma_comercial, para_estudio = presupuesto.estudio, idioma = idioma) return nomarchivo
def go( numfactura="", fecha="", nombre_cliente="", direccion="", ciudad="", cif="", ldvs=[], totales=[], solo_texto=False ): """ A partir de los parámetros recibidos construye un PDF con el factura completo. ldvs es una lista de cantidad (float), concepto, kgs (float), precio (float) e importe (float). Si len(ldvs) > MAXLINEAS genera (len(ldvs)/MAXLINEAS) + 1 páginas, con el número de página entre paréntesis tras el número de factura. Si solo_texto es True, no se dibuja la plantulla de la factura, solo los datos. Devuelve en nombre del fichero generado. """ # Inicialización y medidas: nomarchivo = os.path.join(gettempdir(), "factura_%s.pdf" % (geninformes.give_me_the_name_baby())) c = canvas.Canvas(nomarchivo) c.setTitle("factura_%s" % numfactura) tampag = A4 c.setPageSize(tampag) tm, bm, lm, rm = 1 * cm, 0.6 * cm, 0.6 * cm, 1 * cm fuente, tamanno = "Helvetica", 10 hlin = 0.7 * cm MAXLINEAS = 30 paginas = int((len(ldvs) + len(totales)) / MAXLINEAS) + 1 medidas = { "cliente": (10 * cm, tampag[1] - 1 * cm, 18.6 * cm, tampag[1] - 4.95 * cm), # x e y para la esquina sup. izq. e inf. der. "logo": (2.2 * cm, tampag[1] - 1.3 * cm, 5.2 * cm, 3.4 * cm), # (x,y) de esquina sup. izq. y ancho y alto "dde": (tampag[1] / 2, -0.6 * cm), # (x,y) sabiendo que va con CenteredString y girado 90º "regmercantil": (tampag[0] / 2, 0.6 * cm), # (x,y) sabiendo que va centrado. "ldvs": (1 * cm, tampag[1] - 6.2 * cm, tampag[0] - rm, 2.7 * cm), # (x,y) de esquinas sup. izq. e inf. der. "watermark": (9.5 * cm, 13.5 * cm, 9.5 * cm, 10 * cm), # esquina sup. izq., ancho y alto "numfactura": (1.5 * cm, tampag[1] - 5.8 * cm), # (x,y) "fecha": (10.5 * cm, tampag[1] - 5.8 * cm), # (x,y) } hcab = 0.5 * cm # altura cabecera medidas_tabla = { "xnumalb": 1.0 * cm, "xdesc": 1.0 * cm + 2.7 * cm, "xfecha": 1.0 * cm + 2.7 * cm + 7.4 * cm, "xkgs": 1.0 * cm + 2.7 * cm + 7.4 * cm + 2.6 * cm, "xprecio": 1.0 * cm + 2.7 * cm + 7.4 * cm + 2.6 * cm + 1.7 * cm, "ximporte": 1.0 * cm + 2.7 * cm + 7.4 * cm + 2.6 * cm + 1.7 * cm + 2 * cm, "xfinal": medidas["ldvs"][2], "y0": medidas["ldvs"][1] - hcab, "yfinal": medidas["ldvs"][3], "y1": medidas["ldvs"][1] - hcab - hlin, "h": hlin, "hcab": hcab, } # Páginas de la factura for pag in range(1, paginas + 1): # Parte preimpresa: if not solo_texto: dibujar_imprenta(c, hlin, tm, bm, lm, rm, tampag, medidas, fuente, tamanno, MAXLINEAS, medidas_tabla) # Datos: c.setFont(fuente, tamanno) if paginas > 1: numalb = numfactura + "(%d)" % pag if pag == paginas: printot = totales else: printot = [] else: numalb = numfactura printot = totales rellenar_datos(c, numalb, fecha, nombre_cliente, direccion, ciudad, cif, medidas, fuente, tamanno) rellenar_ldvs(c, ldvs[:MAXLINEAS], printot, medidas_tabla, hlin) ldvs = ldvs[MAXLINEAS:] c.showPage() c.save() return nomarchivo
def go_from_facturaVenta(facturaVenta): """ Construye el PDF a partir de un objeto facturaVenta y no de sus datos sueltos. """ cliente = facturaVenta.cliente datos_cliente = {"código": cliente.id, "cif": cliente.cif, "razón social": cliente.nombre, "dirección": cliente.direccion, "población": cliente.ciudad, "provincia": cliente.provincia} if cliente.cp and cliente.cp.strip(): datos_cliente["población"] = (cliente.cp + " - " + datos_cliente["población"]) datos_factura = {"fecha": utils.str_fecha(facturaVenta.fecha), "número": facturaVenta.numfactura, "codcliente": facturaVenta.cliente and `facturaVenta.cliente.id` or ""} iva = cliente.iva # TODO: ¿Usar el float2str_autoprecision? lineas_contenido = [(ldv.producto.codigo, ldv.producto.descripcion, ldv.cantidad, ldv.precio * (1.0 - ldv.descuento) * (1 + iva)) for ldv in facturaVenta.lineasDeVenta] lineas_contenido += [("", srv.concepto, srv.cantidad, srv.precio * (1.0 - srv.descuento) * (1 + iva)) for srv in facturaVenta.servicios] totales = [facturaVenta.calcular_base_imponible(), iva, facturaVenta.calcular_total()] try: dde = pclases.DatosDeLaEmpresa.select()[0] datos_de_la_empresa = [os.path.join("..", "imagenes", dde.logo), dde.nombre + (dde.cif and " (" + dde.str_cif_o_nif() +": " + dde.cif + ")" or ""), dde.direccion, "%s %s (%s), %s" % (dde.cp, dde.ciudad, dde.provincia, dde.pais), ] if dde.fax: if dde.fax.strip() == dde.telefono.strip(): datos_de_la_empresa.append("Telf. y fax: %s" % dde.telefono) else: datos_de_la_empresa.append("Telf.: %s" % (dde.telefono)) datos_de_la_empresa.append("Fax: %s" % (dde.fax)) if dde.email: datos_de_la_empresa.append(dde.email) except IndexError: datos_de_la_empresa = [None] nomarchivo = os.path.join(gettempdir(), "facturaVenta_%s.pdf" % give_me_the_name_baby()) vencimientos = [] forma_de_pago = [] vtos = facturaVenta.vencimientosCobro[:] vtos.sort(lambda v1, v2: (v1.fecha < v2.fecha and 1) or (v1.fecha > v2.fecha and -1) or 0) for v in vtos: strvto = "%s (%s €)" % (utils.str_fecha(v.fecha), utils.float2str(v.importe)) vencimientos.append(strvto) forma_de_pago.append(v.observaciones) observaciones = ["Importa la presente factura:", numerals.numerals(totales[-1], moneda = "EUROS", fraccion = "CÉNTIMOS").upper()] if facturaVenta.observaciones: observaciones.append(facturaVenta.observaciones) return go("Factura de venta %s (%s)" % ( facturaVenta.cliente.nombre, utils.str_fecha(facturaVenta.fecha)), nomarchivo, datos_cliente, datos_factura, lineas_contenido, totales, datos_de_la_empresa, observaciones, vencimientos, forma_de_pago)