def buscar(self): """ Inicia la consulta para el año indicado en el widget y rellena las tablas con la información obtenida. """ cuantas = int(self.wids['sp_ver'].get_value()) balas = [] n = 0 qbalas = pclases.BalaCable.select(orderBy = "-id") vpro = VentanaProgreso(padre = self.wids['ventana']) vpro.mostrar() if cuantas == 0: tot = qbalas.count() * 1.0 else: tot = cuantas * 1.0 for b in qbalas: b.sync() # Con 999 balas se gana únicamente 1 segundo si omito # la sincronización. try: balas.insert(0, (b, b.productoVenta)) # Para optimizar los accesos a la BD cacheo los datos aquí. except: # ¿Bala sin producto de venta? Mal asunto balas.insert(0, (b, None)) vpro.set_valor(n/tot, 'Recuperando bala %s' % (b.codigo)) n += 1 if n == cuantas: break vpro.set_valor(1, 'Actualizando ventana...') vpro.ocultar() return balas
def rellenar_tabla(self, items): """ Rellena el model con los items de la consulta """ vpro = VentanaProgreso(padre = self.wids['ventana']) vpro.mostrar() vpro.set_valor(0.0, "Contando existencias...") act = 0.0 tot = len(items) * len(self.tvs) try: fecha = utils.parse_fecha(self.wids['e_fecha'].get_text()) except (TypeError, ValueError, AttributeError): fecha = mx.DateTime.today() self.wids['e_fecha'].set_text(utils.str_fecha(fecha)) # XXX: Optimización (cosas de cómo están hechas las funciones de get_* # por dentro en pclases): if fecha >= mx.DateTime.today(): fecha = None for tv, kg, bultos, a in self.tvs: model = tv.get_model() model.clear() totalkgs = 0.0 totalbultos = 0 for pv in items: vpro.set_valor(act/tot, "Contando existencias...\t[%s]" % pv.get_puid()) stock = pv.get_stock(hasta = fecha, almacen = a) totalkgs += stock existencias = pv.get_existencias(hasta=fecha, almacen = a) totalbultos += existencias stock_A = pv.get_stock_A(hasta = fecha, almacen = a) existencias_A = pv.get_existencias_A(hasta=fecha, almacen = a) stock_B = pv.get_stock_B(hasta = fecha, almacen = a) existencias_B = pv.get_existencias_B(hasta=fecha, almacen = a) stock_C = pv.get_stock_C(hasta = fecha, almacen = a) existencias_C = pv.get_existencias_C(hasta=fecha, almacen = a) model.append((pv.codigo, pv.descripcion, utils.float2str(stock), utils.float2str(existencias, autodec = True), utils.float2str(stock_A!=None and stock_A or 0), utils.float2str(existencias_A != None and existencias_A or 0, autodec = True), utils.float2str(stock_B!=None and stock_B or 0), utils.float2str(existencias_B != None and existencias_B or 0, autodec = True), utils.float2str(stock_C!=None and stock_C or 0), utils.float2str(existencias_C != None and existencias_C or 0, autodec = True), pv.get_puid())) act += 1 kg.set_text(utils.float2str(totalkgs)) bultos.set_text(utils.float2str(totalbultos, autodec = True)) vpro.ocultar()
def rellenar_tabla(self, facturas): """ Rellena el model con los facturas de la consulta. """ from formularios.ventana_progreso import VentanaProgreso vpro = VentanaProgreso(padre = self.wids['ventana']) tot = facturas.count() vpro.mostrar() model = self.wids['tv_datos'].get_model() model.clear() total = 0.0 rows_proveedor = {} total_facturado = 0.0 for fra in facturas: vpro.set_valor(total / tot, "Recuperando facturas... [%d/%d]" % (total, tot)) total += 1 proveedor = fra.proveedor importe = fra.calcular_importe_total() total_facturado += importe vencimientos = sum([vto.importe for vto in fra.vencimientosPago]) pagado = sum([c.importe for c in fra.pagos]) pendiente = importe - pagado try: row_proveedor = rows_proveedor[proveedor.puid] except KeyError: rows_proveedor[proveedor.puid] = row_proveedor = model.append( None, (proveedor.nombre, "", "", "0", "0", "0", "0", proveedor.puid)) model.append(row_proveedor, ("", fra.numfactura, utils.str_fecha(fra.fecha), utils.float2str(importe), utils.float2str(vencimientos), utils.float2str(pagado), utils.float2str(pendiente), fra.puid)) model[row_proveedor][3] = utils.float2str( utils._float(model[row_proveedor][3]) + importe) model[row_proveedor][4] = utils.float2str( utils._float(model[row_proveedor][4]) + vencimientos) model[row_proveedor][5] = utils.float2str( utils._float(model[row_proveedor][5]) + pagado) model[row_proveedor][6] = utils.float2str( utils._float(model[row_proveedor][6]) + pendiente) self.wids['e_facturas'].set_text(str(facturas.count())) self.wids['e_total'].set_text(utils.float2str(total_facturado)) vpro.ocultar()
def rellenar_tabla(self, pedidos): """ Rellena el model con los pedidos de la consulta. """ from formularios.ventana_progreso import VentanaProgreso vpro = VentanaProgreso(padre = self.wids['ventana']) tot = pedidos.count() vpro.mostrar() model = self.wids['tv_datos'].get_model() model.clear() total = 0.0 importetotal = 0.0 importetotal_servido = 0.0 self.servido_por_producto = defaultdict(lambda: 0) for p in pedidos: vpro.set_valor(total / tot, "Buscando productos en pedidos..." "\n(ignorando servicios) [%d/%d]" % ( total, tot)) total += 1 prods = p.get_pendiente_servir()[0] # Devuelve 3 cosas. for producto in prods: importe_ldp = sum([ldp.calcular_subtotal(iva = True) for ldp in p.lineasDePedido if ldp.producto == producto]) importe_ldv = sum([ldv.calcular_subtotal(iva = True) for ldv in p.lineasDeVenta if ldv.albaranSalida and ldv.producto == producto]) importetotal += importe_ldp importetotal_servido += importe_ldv cantidad_ldp = prods[producto]['pedido'] cantidad_ldv = prods[producto]['servido'] self.servido_por_producto[producto] += importe_ldv model.append((p.cliente.nombre, utils.str_fecha(p.fecha), p.numpedido, producto.descripcion, utils.float2str(cantidad_ldp), utils.float2str(cantidad_ldv), utils.float2str(importe_ldp), utils.float2str(importe_ldv), p.bloqueado, p.cerrado, ";".join((p.puid, producto.puid)))) vpro.ocultar() self.wids['e_total'].set_text("%d " % total) self.wids['e_importe_total'].set_text( "%s €" % (utils.float2str(importetotal))) self.wids['e_total_servido'].set_text( "%s €" % (utils.float2str(importetotal_servido))) self.actualizar_grafica()
def rellenar_tabla(self, visitas): """ Rellena el model con las visitas de la consulta. """ from formularios.ventana_progreso import VentanaProgreso vpro = VentanaProgreso(padre = self.wids['ventana']) tot = visitas.count() vpro.mostrar() model = self.wids['tv_datos'].get_model() model.clear() total = 0.0 dias = set() rows_comercial = {} visitas_comercial = {} first_day = None last_day = None for visita in visitas: vpro.set_valor(total / tot, "Recuperando visitas... [%d/%d]" % (total, tot)) comercial = visita.comercial if not first_day or visita.fechahora.date() < first_day: first_day = visita.fechahora.date() if not last_day or visita.fechahora.date() > last_day: last_day = visita.fechahora.date() total += 1 cliente = visita.nombrecliente dias.add(visita.fechahora.date()) try: row_comercial = rows_comercial[comercial.puid] except KeyError: visitas_comercial[comercial.puid] = {'visitas': [], 'clientes': set()} rows_comercial[comercial.puid] = row_comercial = model.append( None, (comercial.get_nombre_completo(), "", "", "", comercial.puid)) visitas_comercial[comercial.puid]['visitas'].append(visita) visitas_comercial[comercial.puid]['clientes'].add(cliente) model.append(row_comercial, (cliente, utils.str_fechahora(visita.fechahora), visita.motivoVisita and visita.motivoVisita.motivo or "", visita.observaciones, visita.puid)) # Totales en TreeView clientes_totales = set() for row in model: puid = row[-1] row[3] = "%d visitas a %d clientes diferentes." % ( len(visitas_comercial[puid]['visitas']), len(visitas_comercial[puid]['clientes'])) clientes_totales = clientes_totales.union( visitas_comercial[puid]['clientes']) # Totales en ventana try: str_media = utils.float2str(total / len(dias), autodec = True) except ZeroDivisionError: str_media = "" self.wids['e_media'].set_text(str_media) self.wids['e_total'].set_text(utils.float2str(total, autodec = True) + " (%d clientes diferentes)" % len(clientes_totales)) try: dias_rango = (last_day - first_day).days + 1 except (AttributeError, TypeError): dias_rango = 0 self.wids['e_dias'].set_text( "%d días con visita | %d días totales" % ( len(dias), dias_rango)) vpro.ocultar()
def rellenar_resultados(self): vpro = VentanaProgreso(padre = self.wids['ventana']) txtpro = self.clase.__name__ vpro.set_valor(0.0, txtpro) vpro.mostrar() model = self.wids['tv_datos'].get_model() try: tot = len(self.resultados) except TypeError: tot = self.resultados.count() if tot*len(self.columnas) > NUMERO_ARBITRARIAMENTE_GRANDE: self.wids['tv_datos'].freeze_child_notify() self.wids['tv_datos'].set_model(None) model.clear() i = 0.0 padres = {} for registro in self.resultados: vpro.set_valor(i / tot, "[%d/%d] %s (%s)" % ( i, tot, txtpro, registro.get_puid())) i += 1 fila = [] for columna in self.columnas: valor = getattr(registro, columna) valor = humanizar(valor, registro.sqlmeta.columns[columna]) fila.append(valor) fila.append(registro.get_puid()) if not self.agrupar_por: model.append(None, (fila)) # Es un treeview plano que usaré # como listview. Por eso el nodo padre es None. else: try: padre = padres[getattr(registro, self.agrupar_por)] except KeyError: # Primera vez que aparece este padre. valor_cabecera = getattr(registro, self.agrupar_por) puid = None if isinstance(self.clase.sqlmeta.columns[self.agrupar_por], pclases.SOForeignKey): valor_cabecera = getattr(registro, self.agrupar_por.replace("ID", "")) # CHAPU try: puid = valor_cabecera.get_puid() valor_cabecera = valor_cabecera.get_info() except AttributeError: # Es None valor_cabecera = "Sin %s" % ( labelize(self.agrupar_por)) puid = None fila_padre = [valor_cabecera] for i in range(len(self.columnas) - 1): fila_padre.append("") fila_padre.append(puid) padre = padres[getattr(registro, self.agrupar_por)] \ = model.append(None, (fila_padre)) model.append(padre, (fila)) # Actualizo totales numéricos del padre: ncell = 0 for columna in self.columnas: valor_hijo_columna = getattr(registro, columna) sqlcolumna = registro.sqlmeta.columns[columna] if (isinstance(valor_hijo_columna, (int, float)) and not isinstance(sqlcolumna, pclases.SOForeignKey)): try: nuevo_valor_padre = utils.numero._float( model[padre][ncell]) except ValueError: nuevo_valor_padre = 0 nuevo_valor_padre += valor_hijo_columna nuevo_valor_padre = utils.numero.float2str( nuevo_valor_padre) model[padre][ncell] = nuevo_valor_padre ncell += 1 self.actualizar_totales() if tot*len(self.columnas) > NUMERO_ARBITRARIAMENTE_GRANDE: self.wids['tv_datos'].set_model(model) self.wids['tv_datos'].thaw_child_notify() vpro.ocultar()
def rellenar_tabla_facturas(self): vpro = VentanaProgreso(padre = self.wids['ventana']) vpro.mostrar() idcliente = utils.combo_get_value(self.wids['cbe_cliente']) fechaini, fechafin = self.leer_fechas() if idcliente >= 0 and fechaini and fechafin: modelcesce = self.wids['tv_cesce'].get_model() modelcesce.clear() model = self.wids['tv_facturas'].get_model() model.clear() total = total_vencimientos = pendiente = cobrado = 0.0 total_pagares = pendiente_pagares = cobrado_pagares = 0.0 total_otros = pendiente_otros = cobrado_otros = 0.0 total_cobrado_strict = 0.0 subtotal = {} # (Sub)totales de FACTURACIÓN (no vencimientos, # sino suma de totales de factura) por mes. nodos_clientes = {} # Diccionario con # "ID[anno][mes]: nodo del TreeView" # Para ir insertando las facturas de cada # cliente en su rama. if idcliente == 0: idscliente = [c.id for c in pclases.Cliente.select()] else: idscliente = [idcliente] i = 0.0 for idcliente in idscliente: i += 1 vpro.set_valor(i / len(idscliente), "%d %%" % (i / len(idscliente) * 100)) (total, pendiente, cobrado, total_pagares, pendiente_pagares, cobrado_pagares, total_otros, pendiente_otros, cobrado_otros, total_vencimientos, total_cobrado_strict)=self.procesar_cliente(idcliente, total, pendiente, cobrado, total_pagares, pendiente_pagares, cobrado_pagares, total_otros, pendiente_otros, cobrado_otros, total_vencimientos, total_cobrado_strict, model, fechaini, fechafin, subtotal, nodos_clientes) vpro.set_valor("100 %") self.rellenar_pies(total, pendiente, cobrado, total_pagares, pendiente_pagares, cobrado_pagares, total_otros, pendiente_otros, cobrado_otros, total_vencimientos, total_cobrado_strict) # XXX vpro.set_valor("Creando agrupaciones...") self.invertir_agrupaciones_cliente_fechas() vpro.ocultar()
def rellenar_balas(self): """ Puebla el treeview de balas en la partida de carga. """ model = self.wids['tv_balas'].get_model() model.clear() cantidad = 0 partida = self.get_partida() if partida is not None: vpro = VentanaProgreso(padre=self.wids['ventana']) vpro.mostrar() i = 0.0 vpro.set_valor(i/1.0, 'Cargando datos...') while gtk.events_pending(): gtk.main_iteration(False) partida.sync() tot = len(partida.balas) consumos_estimados, merma = self.get_consumos_estimados(partida, vpro) self.wids['e_peso_gtx'].set_text("%s kg" % ( utils.float2str(consumos_estimados, 2))) self.wids['label_gtx'].set_label("Peso aproximado geotextiles" " producidos: \n" "<small><i>Contando merma estimada media del %.2f%%." "Sin embalaje.</i></small>" % (merma)) # try: # articulo = partida.rollos[0].articulos[0] # producto = articulo.productoVenta.descripcion # except IndexError: # producto = "SIN PRODUCCIÓN" # except: # producto = "ERROR" # self.wids['e_gtx'].set_text(producto) balas = [b for b in partida.balas] balas.sort(func_orden_balas) productos = {} for bala in balas: vpro.set_valor(i/tot, 'Cargando datos (%d)...' % ( bala.numbala)) lote_id = bala.loteID if lote_id not in productos: lote = bala.lote try: producto = bala.articulos[0].productoVenta except IndexError: producto = None productos[lote_id] = {'cantidad': 0, 'peso': 0, 'lote': lote, 'producto': producto} productos[lote_id]['peso'] += bala.pesobala productos[lote_id]['cantidad'] += 1 if consumos_estimados >= bala.pesobala: # Se ha gastado la # bala entera. porcion_consumida = 100 consumos_estimados -= bala.pesobala else: porcion_consumida = (consumos_estimados / bala.pesobala) * 100 # % consumido consumos_estimados = 0 # Ya no puedo descontar más o # me quedaré por debajo de 0. model.append((bala.codigo, "{}: {}".format( bala.articulo.productoVenta.id, bala.articulo.productoVenta.descripcion), bala.articulo.peso_neto, porcion_consumida, bala.id)) cantidad += bala.pesobala i += 1 model = self.wids['tv_resumen'].get_model() model.clear() for lote_id in productos: try: lote = "%d (%s)" % (productos[lote_id]['lote'].numlote, productos[lote_id]['lote'].codigo) except AttributeError: lote = "" try: producto = productos[lote_id]['producto'].descripcion except AttributeError: producto = "" model.append((productos[lote_id]['cantidad'], productos[lote_id]['peso'], lote, producto, lote_id)) vpro.ocultar() self.wids['e_total'].set_text("%s kg" % (utils.float2str(cantidad, 2)))
def rellenar_treeviews(self): almacenid = utils.combo_get_value(self.wids['cb_almacen']) if almacenid != 0: almacen = pclases.Almacen.get(almacenid) else: almacen = None vpro = VentanaProgreso(padre = self.wids['ventana']) vpro.mostrar() totales = {'kgA': {}, 'kgB': {}, 'kgC': {}, 'kgTotal': {}, 'mA': {}, 'mB': {}, 'mC': {}, 'mTotal': {}, '#A': {}, '#B': {}, '#C': {}, '#Total': {} } i = 0.0 tot = sum([len(self.productos[k]) for k in self.productos.keys()]) for nombre_tv in ("tv_fibra", "tv_gtx", "tv_cemento"): tv = self.wids[nombre_tv] model = tv.get_model() model.clear() tipo = nombre_tv.split("_")[-1] for pv in self.productos[tipo]: i += 1 vpro.set_valor(i / tot, "Contando existencias de %s (%d) [%s]..." % ( pv.nombre, pv.id, tipo)) kgA = pv.get_stock_A(almacen = almacen) kgB = pv.get_stock_B(almacen = almacen) kgC = pv.get_stock_C(almacen = almacen) bultosA = pv.get_existencias_A(almacen = almacen) bultosB = pv.get_existencias_B(almacen = almacen) bultosC = pv.get_existencias_C(almacen = almacen) total_kg = pv.get_stock(almacen = almacen, contar_defectuosos = True) total_bultos = pv.get_existencias(almacen = almacen, contar_defectuosos = True) if pclases.DEBUG: assert round(kgA + kgB + kgC) == round( total_kg), pv.puid # XXX # Esto de arriba, aunque mezcle metros con kilos, no # debe fallar. Ya que en el total de un producto C, # A y B se quedan a 0.0. Y al contrario. Si el producto # no es C, A y B valdrán algo y C siempre es 0. assert round(bultosA + bultosB + bultosC) == round( total_bultos), pv.puid # XXX if nombre_tv != "tv_gtx": fila = [pv.descripcion, utils.float2str(kgA), utils.int2str(bultosA), utils.float2str(kgB), utils.int2str(bultosB), utils.float2str(kgC), utils.int2str(bultosC), utils.float2str(total_kg), utils.int2str(total_bultos), pv.puid] actualizar_totales(totales, tipo, kgA, kgB, kgC, total_kg, bultosA, bultosB, bultosC, total_bultos) else: # Los metros ya los tenía calculados. Es lo que devuelve # el get_stock. Solo que arriba lo he llamado kg* metrosA = kgA metrosB = kgB metrosC = "N/A" # No aplicable. Solo se mide en kilos. kilosA = pv.get_stock_kg_A(almacen = almacen) kilosB = pv.get_stock_kg_B(almacen = almacen) kilosC = kgC # Ya estaba calculado total_kilos = kilosA + kilosB + kilosC total_metros = metrosA + metrosB # total bultos ya se calcula arriba. fila = [pv.descripcion, utils.float2str(kilosA), utils.float2str(metrosA), utils.int2str(bultosA), utils.float2str(kilosB), utils.float2str(metrosB), utils.int2str(bultosB), utils.float2str(kilosC), metrosC, # No es aplicable. Solo kg. No m² en C. utils.int2str(bultosC), utils.float2str(total_kilos), utils.float2str(total_metros), utils.int2str(total_bultos), pv.puid] actualizar_totales(totales, tipo, kilosA, kilosB, kilosC, total_kilos, bultosA, bultosB, bultosC, total_bultos, metrosA, metrosB, 0.0, total_metros) # m² de C es "N/A". Le paso un 0 aquí para que no pete. model.append(fila) vpro.ocultar() return totales
def buscar(self,boton): """ Dadas fecha de inicio y de fin, lista todos los albaranes pendientes de facturar. """ i = 0.0 vpro = VentanaProgreso(padre = self.wids['ventana']) vpro.mostrar() self.resultado = [] self.comisiones = [] self.transportes = [] selfinicio = self.inicio and utils.parse_fecha( "/".join(self.inicio.split("/")[::-1])) or None selffin = utils.parse_fecha("/".join(self.fin.split("/")[::-1])) if not selfinicio: albaranesentrada = pclases.AlbaranEntrada.select( pclases.AlbaranEntrada.q.fecha <= selffin, orderBy = 'fecha') albaranessalida = pclases.AlbaranSalida.select( pclases.AND(pclases.AlbaranSalida.q.fecha <= selffin, pclases.AlbaranSalida.q.facturable == True), orderBy = 'fecha') else: albaranesentrada = pclases.AlbaranEntrada.select( pclases.AND(pclases.AlbaranEntrada.q.fecha >= selfinicio, pclases.AlbaranEntrada.q.fecha <= selffin), orderBy='fecha') albaranessalida = pclases.AlbaranSalida.select( pclases.AND(pclases.AlbaranSalida.q.fecha >= selfinicio, pclases.AlbaranSalida.q.fecha <= selffin, pclases.AlbaranSalida.q.facturable == True), orderBy='fecha') proveedores = pclases.Proveedor.select() tot = (proveedores.count() + albaranessalida.count() + albaranesentrada.count()) for proveedor in proveedores: vpro.set_valor(i/tot, "Buscando albaranes de comisiones y transportes...\n" "(%s)" % proveedor.nombre) i += 1 if not selfinicio: self.comisiones += [c for c in proveedor.get_comisiones_pendientes_de_facturar() if c.fecha <= selffin and c not in self.comisiones] self.transportes += [t for t in proveedor.get_transportes_pendientes_de_facturar() if t.fecha <= selffin and t not in self.transportes] else: for c in proveedor.get_comisiones_pendientes_de_facturar(): if (selfinicio <= c.fecha <= selffin and c not in self.comisiones): self.comisiones.append(c) for t in proveedor.get_transportes_pendientes_de_facturar(): if (selfinicio <= t.fecha <= selffin and t not in self.transportes): self.transportes.append(t) # DONE: Mostrar solo lo pendiente de facturar. No todas las líneas. for a in albaranessalida: vpro.set_valor(i/tot, "Buscando albaranes de salida...") i += 1 total_lineas = len([ldv for ldv in a.lineasDeVenta if ldv.cantidad]) if a.contar_lineas_facturadas() < total_lineas: self.resultado.append(a) for a in albaranesentrada: vpro.set_valor(i/tot, "Buscando albaranes de entrada...") i += 1 total_lineas = len([ldc for ldc in a.lineasDeCompra if ldc.cantidad]) if a.contar_lineas_facturadas() < total_lineas: self.resultado.append(a) self.resultado.sort(self.por_fecha) self.comisiones.sort(self.por_fecha) self.transportes.sort(self.por_fecha) self.rellenar_tabla(self.resultado, self.comisiones, self.transportes) self.wids['tv_producto'].get_columns()[0].set_expand(True) vpro.ocultar()