def buscar_cod_libre(self):
     """
     Devuelve un código de tres cifras como 
     cadena que no esté ya en la tabla de 
     productos como producto terminado.
     Siempre devolverá el primer código
     libre más cercano a 000.
     Si no quedan más mostrará un mensaje
     de error por pantalla y devolverá
     999.
     """
     prods = pclases.ProductoVenta.select(pclases.AND(
         pclases.OR(
             pclases.ProductoVenta.q.camposEspecificosBalaID !=None, 
             pclases.ProductoVenta.q.camposEspecificosRolloID !=None, 
             pclases.ProductoVenta.q.camposEspecificosEspecialID !=None), 
         pclases.ProductoVenta.q.codigo.startswith('843603219')))
     # Incluyo todo tipo de productos porque aunque la fibra esté limitada 
     # al rango 300~400, el resto no, y al crearlos ha podido pillar uno 
     # de esos números.
     codsproducto = [int(p.codigo[-4:-1]) for p in prods]
     codsproducto.sort()
     for i in xrange(300, 400):  # OJO: Códigos hardcoded. Para balas se 
                                 # han asignado los códigos 300 a 399.
         try:
             if not i in codsproducto:
                 return "%03d" % i
         except IndexError:  # No hay o me pasé de rango
             return "%03d" % i
     utils.dialogo_info('NO QUEDAN CÓDIGOS DISPONIBLES', 
                        'Todos los códigos EAN13 fueron asignados.', 
                        padre = self.wids['ventana'])
     return '999'
 def pedir_producto_compra(self):
     """
     Devuelve UN producto de compra obtenido a partir 
     de una búsqueda, etc.
     """
     producto = None
     a_buscar = utils.dialogo_entrada(titulo = "BUSCAR MATERIAL", 
             texto = "Introduzca texto a buscar en productos de compra:", 
             padre = self.wids['ventana'])
     if a_buscar != None:
         resultados = utils.buscar_productos_compra(a_buscar)
         if resultados.count() > 1:
             ## Refinar los resultados:
             filas_res = []
             for r in resultados:
                 filas_res.append((r.id, r.codigo, r.descripcion))
             idproducto = utils.dialogo_resultado(filas_res, 
                     titulo = 'Seleccione producto', 
                     cabeceras = ('ID Interno', 'Código', 'Descripción'), 
                     padre = self.wids['ventana'])
             if idproducto < 0:
                 return
             producto = pclases.ProductoCompra.get(idproducto)
                 # id es clave primaria, esta comprensión debería devolver un único producto
         elif resultados.count() < 1:
             ## La búsqueda no produjo resultados.
             utils.dialogo_info('SIN RESULTADOS', 
                 'La búsqueda no produjo ningún resultado.\nIntente una '
                 'búsqueda menos restrictiva usando un texto más corto.', 
                 padre = self.wids['ventana'])
             return None
         else:
             producto = resultados[0]
     return producto
Example #3
0
 def drop_consumo_por_producto(self, boton):
     """
     Elimina el consumo o consumos seleccionados en el TreeView.
     """
     texto = """
     Si ha seleccionado un consumo se eliminará el consumo completo.             
     Si seleccionó uno o varios productos, se eliminarán del consumo al          
     que pertenece, por lo que ya no empleará el material relacionado            
     cuando se fabriquen artículos del mismo.                                    
                                                                                 
     ¿Está seguro de querer continuar?                                           
                                                                                 
     """
     model, paths = self.wids['tv_consumos'].get_selection().get_selected_rows()
     if paths and utils.dialogo(titulo = "¿ELIMINAR?", texto = texto, padre = self.wids['ventana']):
         for path in paths:
             if model[path].parent == None:
                 id_consumo = model[path][-1]
                 consumo_adicional_por_producto = pclases.ConsumoAdicional.get(id_consumo)
                 try:
                     for p in consumo_adicional_por_producto.productosVenta:
                         consumo_adicional_por_producto.removeProductoVenta(p)
                     consumo_adicional_por_producto.destroySelf()
                 except pclases.psycopg_ProgrammingError, msg:
                     utils.dialogo_info(titulo = "ERROR: INFORME A LOS DESARROLLADORES", 
                                        texto = "Ocurrió un error al eliminar el consumo.\nDEBUG: Traza de la excepción:\n%s" % (msg), 
                                        padre = self.wids['ventana'])
             else:
                 id_consumo = model[path].parent[-1]
                 idproductov = model[path][-1]
                 consumo_adicional_por_producto = pclases.ConsumoAdicional.get(id_consumo)
                 productov = pclases.ProductoVenta.get(idproductov)
                 consumo_adicional_por_producto.removeProductoVenta(productov)
         self.rellenar_consumos_adicionales_por_producto()
Example #4
0
 def buscar_pedido(self, numero):
     """
     Muestra una ventana de búsqueda y a continuación los
     resultados. El objeto seleccionado se hará activo
     en la ventana a no ser que se pulse en Cancelar en
     la ventana de resultados.
     """
     if numero != None:
         resultados = pclases.PedidoVenta.select(pclases.PedidoVenta.q.numpedido.contains(numero))
         if resultados.count() > 1:
                 ## Refinar los resultados
                 idpedido = self.refinar_resultados_busqueda(resultados)
                 if idpedido == None:
                     return
                 resultados = [pclases.PedidoVenta.get(idpedido)]
                 # Se supone que la comprensión de listas es más rápida que hacer un nuevo get a SQLObject.
                 # Me quedo con una lista de resultados de un único objeto ocupando la primera posición.
                 # (Más abajo será cuando se cambie realmente el objeto actual por este resultado.)
         elif resultados.count() < 1:
             ## Sin resultados de búsqueda
             utils.dialogo_info('SIN RESULTADOS', 'La búsqueda no produjo resultados.\nPruebe a cambiar el texto buscado o déjelo en blanco para ver una lista completa.\n(Atención: Ver la lista completa puede resultar lento si el número de elementos es muy alto)', padre = self.wids['ventana'])
             return
         ## Un único resultado
         return resultados[0]
     else:
         return None
Example #5
0
 def pedir_producto(self):
     """
     Solicita un código de producto, muestra una
     ventana de resultados coincidentes con la 
     búsqueda de ese código y devuelve un 
     objeto producto seleccionado de entre
     los resultados o None si se cancela o 
     no se encuentra.
     """
     producto = None
     codigo = utils.dialogo_entrada(texto = 'Introduzca código o descripción del producto.', 
                                    titulo = 'PRODUCTO', 
                                    padre = self.wids['ventana'])
     if codigo != None:
         prods = pclases.ProductoCompra.select(pclases.AND(pclases.OR(pclases.ProductoCompra.q.descripcion.contains(codigo), #@UndefinedVariable
                                                                      pclases.ProductoCompra.q.codigo.contains(codigo)), #@UndefinedVariable
                                                           pclases.ProductoCompra.q.controlExistencias == True)) #@UndefinedVariable
         prods = tuple(prods)
         mens_error = 'No se encontró ningún producto con ese código o descripción.'
         if len(prods) > 1:
             idproducto = self.refinar_busqueda_productos(prods)
             if idproducto != None:
                 prods = [pclases.ProductoCompra.get(idproducto)]
             else:
                 return None
         elif len(prods) < 1:
             utils.dialogo_info(titulo = 'CÓDIGO NO ENCONTRADO', 
                                texto = mens_error, 
                                padre = self.wids['ventana'])
             return None
         producto = prods[0]
     return producto
Example #6
0
 def buscar_usuario(self, widget):
     """
     Muestra una ventana de búsqueda y a continuación los
     resultados. El objeto seleccionado se hará activo
     en la ventana a no ser que se pulse en Cancelar en
     la ventana de resultados.
     """
     usuario = self.objeto
     a_buscar = utils.dialogo_entrada("Introduzca nombre de usuario o nombre real:") 
     if a_buscar != None:
         resultados = pclases.Usuario.select(sqlobject.OR(pclases.Usuario.q.usuario.contains(a_buscar),
                                                          pclases.Usuario.q.nombre.contains(a_buscar)))
         if resultados.count() > 1:
             ## Refinar los resultados
             idusuario = self.refinar_resultados_busqueda(resultados)
             if idusuario == None:
                 return
             resultados = [pclases.Uduario.get(idusuario)]
         elif resultados.count() < 1:
             ## Sin resultados de búsqueda
             utils.dialogo_info('SIN RESULTADOS', 'La búsqueda no produjo resultados.\nPruebe a cambiar el texto buscado o déjelo en blanco para ver una lista completa.\n(Atención: Ver la lista completa puede resultar lento si el número de elementos es muy alto)')
             return
         ## Un único resultado
         # Primero anulo la función de actualización
         if usuario != None:
             usuario.notificador.desactivar()
         # Pongo el objeto como actual
         usuario = resultados[0]
         # Y activo la función de notificación:
         usuario.notificador.activar(self.aviso_actualizacion)
     self.objeto = usuario
     self.actualizar_ventana()
Example #7
0
 def nuevo(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í.
     """
     silo = self.objeto
     nombre = utils.dialogo_entrada('Introduzca el nombre del silo:', 'NOMBRE', padre = self.wids['ventana'])
     if nombre != None:
         capacidad = utils.dialogo_entrada(titulo = "CAPACIDAD", 
                                           texto = "Introduzca la capacidad del silo:",
                                           padre = self.wids['ventana'])
         try:
             capacidad = float(capacidad)
         except:
             utils.dialogo_info(titulo = "VALOR INCORRECTO",
                                texto = "El valor %s no es correcto. Inténtelo de nuevo.\nAsegúrese de no introducir unidades.", 
                                padre = self.wids['ventana'])
             return
         observaciones = utils.dialogo_entrada(titulo = "OBSERVACIONES", 
                                               texto = "Introduzca observaciones si lo desea:", 
                                               padre = self.wids['ventana'])
         if observaciones != None:
             silo = pclases.Silo(nombre = nombre,
                                 capacidad = capacidad, 
                                 observaciones = observaciones)
             self.rellenar_widgets()
 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.
     """
     albaran = self.objeto
         # Campos del objeto que hay que guardar:
     numalbaran = self.wids['e_numalbaran'].get_text()
     fecha = self.wids['e_fecha'].get_text()
     # Desactivo el notificador momentáneamente
     albaran.notificador.set_func(lambda: None)
     # Actualizo los datos del objeto
     albaran.numalbaran = numalbaran
     albaran.proveedor = utils.combo_get_value(self.wids['cmbe_proveedor'])
     albaran.almacen = utils.combo_get_value(self.wids['cbe_almacenID'])
     try:
         albaran.fecha = utils.parse_fecha(fecha)
     except:
         albaran.fecha = time.localtime()
         utils.dialogo_info(titulo = "ERROR GUARDANDO FECHA", 
                            texto = "La fecha %s no es correcta." % (fecha), 
                            padre = self.wids['ventana'])
     # Fuerzo la actualización de la BD y no espero a que SQLObject lo haga por mí:
     albaran.syncUpdate()
     # Vuelvo a activar el notificador
     albaran.notificador.set_func(self.aviso_actualizacion)
     self.actualizar_ventana()
     self.wids['b_guardar'].set_sensitive(False)
Example #9
0
 def salir(self, boton, event=None, mostrar_ventana=False):
     """
     Muestra una ventana de confirmación y 
     sale de la ventana cerrando el bucle
     local de gtk_main.
     Si mostrar_ventana es False, sale directamente
     sin preguntar al usuario.
     """
     try:
         b_guardar = self.wids['b_guardar']
     except KeyError:
         b_guardar = None
     if  b_guardar != None and b_guardar.get_property('sensitive'):
         # Hay cambios pendientes de guardar.
         if utils.dialogo('Hay cambios pendientes de guardar.\n¿Desea hace'
                          'rlo ahora?', 
                          '¿GUARDAR CAMBIOS?', 
                          padre = self.wids['ventana'], 
                          icono = gtk.STOCK_SAVE, 
                          #defecto = "Sí"):  # CWT: A veces en BlancoPe 
                             # abren la ventana de productos para buscar 
                             # un precio y le dan al botón antes de que se 
                             # carguen los datos, provocando que se detecte 
                             # como un falso cambio de datos de la ventana 
                             # (todo blanco) respecto a la caché (datos 
                             # reales de la BD). Al darle a ENTER, 
                             # responden Sí por defecto -hasta ahora- y 
                             # sobreescriben con blanco todos los datos del 
                             # registro en la base de datos.
                          defecto = "No"):
             try:
                 self.guardar(None)
             except:
                 utils.dialogo_info(titulo = 'NO SE PUDO GUARDAR', 
                                    texto = 'Los cambios no se pudieron gua'
                                            'rdar automáticamente.\nDebe ha'
                                            'cerlo de forma manual',
                                    padre = self.wids['ventana'])
                 return True # Si devuelvo False, None, etc... continúa la 
                             # cadena de eventos y destruye la ventana.
                             # Devuelvo True para cancelar el cierre de la 
                             # ventana. 
     if event == None:
         # Me ha invocado el botón
         if not mostrar_ventana or \
             utils.dialogo('¿Desea salir de la ventana actual?', 
                          'SALIR', 
                          padre = self.wids['ventana'], 
                          icono = gtk.STOCK_QUIT):
             self.wids['ventana'].destroy()
             return False
         else:
             return True
     else:
         if not mostrar_ventana or not \
                 utils.dialogo('¿Desea salir de la ventana actual?',
                 'SALIR', padre=self.wids['ventana'], icono=gtk.STOCK_QUIT):
             return False
         else:
             return True
 def pedir_transportista(self, widget):
     """
     Solicita un número de pedido, muestra una
     ventana de resultados coincidentes con la 
     búsqueda de ese número y devuelve un 
     objeto pedido seleccionado de entre
     los resultados o None si se cancela o 
     no se encuentra.
     """
     global transportista
     codigo = utils.dialogo_entrada(texto = 'Introduzca nombre del transportista', titulo = 'TRANSPORTISTA', padre = self.wids['ventana'])
     if codigo != None:
         trans = pclases.Transportista.select(pclases.Transportista.q.nombre.contains(codigo))
         trans = [p for p in trans]
         mens_error = 'No se encontró ningún transportista con ese nombre.'
         if len(trans) > 1:
             idtrans = refinar_busqueda_transportista(trans)
             if idtrans != None:
                 trans = [p for p in trans if p.id == idtrans]
             else:
                 return None
         elif len(trans) < 1:
             utils.dialogo_info('TRANSPORTISTA NO ENCONTRADO', mens_error, padre = self.wids['ventana'])
             return None
         transportista = trans[0]
 def cambiar_precio(self, cell, path, texto):
     try:
         precio = float(texto)
     except:
         utils.dialogo_info(titulo = "ERROR FORMATO", 
                            texto = "El texto %s no es un número." % texto, 
                            padre = self.wids['ventana'])
     else:
         model = self.wids['tv_ldvs'].get_model()
         ldc = pclases.LineaDeCompra.get(model[path][-1])
         ldc.precio = precio
         # CWT: Si el precio cambia al alza, respetar porcentaje. Si meto 
         # un precio inferior, entonces respetar el precio final de las 
         # tarifas y adaptar el porcentaje a ese precio de forma que nunca 
         # venda más barato al cambiar el precio del proveedor.
         pc = ldc.productoCompra
         pc.sync()
         if precio > pc.precioDefecto:
             # Si el precio sube, actualizo tarifas respetando porcentajes.
             for t in pclases.Tarifa.select(orderBy = "nombre"):
                 if t.vigente:
                     porcentaje = t.get_porcentaje(pc, fraccion = True)
                     nuevo_precio = precio * (1 + porcentaje)
                     t.asignarTarifa(pc, nuevo_precio)
         # Si el precio ha bajado o se mantiene, respeto precio final. La 
         # ventana ya calculará el porcentaje que sea.
         pc.precioDefecto = precio
         pc.syncUpdate()
         self.actualizar_ventana()
Example #12
0
 def seleccionar_cantidad(self, producto):
     """
     Muestra un diálogo para introducir la cantidad.
     Si el producto es un rollo, se introducirá en 
     metros cuadrados.
     Si es una bala, se introducirá en kilos.
     En las LDV se mantendrán también estas unidades
     ya que el precio por unidad va en función de 
     kilos y rollos en el producto.
     Cuando se haga el albarán es cuando habrá que
     calcular cuantos rollos (y cuáles en concreto)
     y cuántas balas entran. Aunque en realidad es 
     el usuario el que las seleccionará y el programa
     irá informando si se satisface la LDV o no.
     """
     if isinstance(producto, pclases.ProductoCompra):
         txt = "Introduzca la cantidad en %s." % (producto.unidad)
     else:
         txterror = "presupuestos::seleccionar_cantidad -> ERROR: Producto %s no es producto de compra ni de venta." % (producto)
         self.logger.error(txterror)
     cantidad = utils.dialogo_entrada(titulo = 'CANTIDAD', texto = txt, padre = self.wids['ventana'])
     try:
         cantidad = utils._float(cantidad)
         return cantidad
     except:
         utils.dialogo_info(titulo = 'ERROR', texto = 'La cantidad introducida no es correcta.', padre = self.wids['ventana'])
         return None
Example #13
0
 def borrar(self, widget):
     """
     Elimina la cuenta de la tabla pero NO
     intenta eliminar ninguna de sus relaciones,
     de forma que si se incumple alguna 
     restricción de la BD, cancelará la eliminación
     y avisará al usuario.
     """
     if not utils.dialogo('¿Eliminar %s?'%self.clase.sqlmeta.table.lower(), 
                          'BORRAR', 
                          padre = self.wids['ventana']):
         return
     self.objeto.notificador.desactivar()
     try:
         self.objeto.destroySelf()
     except Exception, e:
         self.logger.error("grupos_alumnos.py::borrar -> %s ID %d no se "
                           "pudo eliminar. Excepción: %s." % (
                             self.objeto.sqlmeta.table, self.objeto.id, e))
         utils.dialogo_info(
             titulo = "%s NO BORRADO" % self.clase.sqlmeta.table.upper(), 
             texto = "%s no se pudo eliminar.\n\nSe generó un informe de "
                     "error en el «log» de la aplicación." % (
                         self.clase.sqlmeta.table.title()),
             padre = self.wids['ventana'])
         self.actualizar_ventana()
         return
 def borrar_producto(self, widget):
     """
     Elimina el producto de la tabla pero NO
     intenta eliminar ninguna de sus relaciones,
     de forma que si se incumple alguna 
     restricción de la BD, cancelará la eliminación
     y avisará al usuario.
     """
     producto = self.objeto
     if not utils.dialogo('¿Eliminar el producto?', 'BORRAR'):
         return
     if producto.articulos != [] or producto.precios != []:
         utils.dialogo_info('PRODUCTO NO ELIMINADO', 'El producto está implicado en operaciones que impiden su borrado.', padre = self.wids['ventana'])
     else:
         producto.notificador.desactivar()
         campos = producto.camposEspecificosBala
         try:
             producto.destroySelf()
             campos.destroySelf()
         except:
             utils.dialogo_info(titulo = "NO SE PUEDE ELIMINAR",
                                texto = "El producto no se puede eliminar. Verifique que no\ntiene ventas o producción relacionada.", 
                                padre = self.wids['ventana'])
         else:
             self.objeto = None
             self.ir_a_primero()
Example #15
0
 def cambiar_precio_ldp(self, cell, path, texto):
     """
     Cambia el precio de la LDP conforme al texto recibido.
     """
     try:
         precio = utils._float(texto)
     except:
         utils.dialogo_info(titulo = "ERROR", 
                            texto = 'El texto "%s" no es un número.' % (texto), 
                            padre = self.wids['ventana'])
     else:
         model = self.wids['tv_ldps'].get_model()
         ldp = pclases.LineaDePedido.get(model[path][-1])
         if ldp.precio != precio:
             ldp.precio = precio
             if ldp.get_lineas_de_venta() != [] \
                and utils.dialogo(titulo = "¿CAMBIAR PRECIO PRODUCTOS SERVIDOS?", 
                              texto = """
             Al cambiar el precio de una parte del presupuesto ofertado,             
             se cambian automáticamente los precios de los pedidos                   
             involucrados. También puede cambiar los albaranes y facturas            
             si el pedido ya ha sido servido.                                        
                                                                                     
             ¿Desea cambiar el precio de todos los artículos servidos                
             de este producto?                                                       
                                                                                     
             Si lo hace, se cambiará también en la factura en caso de                
             que se haya facturado el albarán o albaranes                            
             correspondientes.                                                       
             """, 
                             padre = self.wids['ventana']):
                 for ldv in ldp.get_lineas_de_venta():
                     ldv.precio = ldp.precio
         self.rellenar_tablas()
 def buscar(self, boton):
     """
     Dadas fecha de inicio y de fin, lista todos los albaranes
     pendientes de facturar.
     """
     idcliente = utils.combo_get_value(self.wids['cmbe_cliente'])
     if idcliente == None:
         utils.dialogo_info(titulo = 'ERROR',
                            texto = 'Seleccione un cliente',
                            padre = self.wids['ventana'])
     else:
         idcliente = utils.combo_get_value(self.wids['cmbe_cliente'])
         self.cliente = pclases.Cliente.get(idcliente)
         cliente = self.cliente
         if self.inicio == None:
             pedidos = pclases.PedidoVenta.select(pclases.AND(
                             pclases.PedidoVenta.q.fecha <= self.fin,
                             pclases.PedidoVenta.q.clienteID == cliente.id),
                         orderBy = 'fecha')
         else:
             pedidos = pclases.PedidoVenta.select(pclases.AND(
                             pclases.PedidoVenta.q.fecha >= self.inicio,
                             pclases.PedidoVenta.q.fecha <= self.fin,
                             pclases.PedidoVenta.q.clienteID == cliente.id),
                         orderBy='fecha')
         self.resultado = pedidos
         self.rellenar_tabla(self.resultado)
Example #17
0
    def expandir(self, tv, iter, path):
        model = tv.get_model()
        child = model[path].iterchildren().next()
        if child[0] == "" and \
           child[1] == "" and \
           child[2] == "" and \
           child[3] == "":
            model.remove(child.iter)
            id = int(model[path][0])
            clase = model[path][-1]
#            print clase, id
            try:
                objeto = eval('pclases.%s.get(%d)' % (clase, id))
            except pclases.SQLObjectNotFound:
                utils.dialogo_info(titulo = "ERROR", texto = "El objeto %s con ID %d no existe." % (clase, id))
            padre = model.get_iter(path)
            try:
                objeto.sync()
            except pclases.SQLObjectNotFound:
                model[path][0] = ""
                model[path][2] = ""
                model[path][3] = ""
            self.insertar_campos(objeto, padre, model)
            self.insertar_ajenos(objeto, padre, model)
            self.insertar_multiples(objeto, padre, model)
            tv.expand_row(path, False)
Example #18
0
 def enviar_a_laboratorio(self, parametro):
     # NOTA: Ni idea de qué es lo que traerá el parámetro, sólo me interesa
     # el parte que está seleccionado en el treeview.
     model, iter = self.wids['tv_datos'].get_selection().get_selected()
     if iter == None:
         utils.dialogo_info(titulo = "PARTE NO SELECCIONADO", 
                            texto = "Seleccione un parte para enviar una muestra de su\nlote o partida al laboratorio.", 
                            padre = self.wids['ventana'])
     else:
         idparte = model[iter][-1]
         if idparte > 0:
             parte = pclases.ParteDeProduccion.get(idparte)
             if not parte.articulos:
                 utils.dialogo_info(titulo = "PARTE VACÍO", texto = "En el parte seleccionado no hubo producción.", padre = self.wids['ventana'])
             else:
                 a = parte.articulos[0]  # Al menos tiene 1 artículo. Con el primero me vale.
                 if parte.es_de_balas():
                     try:
                         lote = a.bala.lote
                         loteCem = None
                     except AttributeError:
                         lote = None
                         loteCem = a.bigbag.loteCem
                     partida = None
                 else:
                     lote = None
                     partida = a.rollo.partida
                 self.crear_muestra(lote, partida, loteCem)
Example #19
0
 def __init__(self, objeto = None, usuario = None):
     """
     Constructor. objeto puede ser un objeto de pclases con el que
     comenzar la ventana (en lugar del primero de la tabla, que es
     el que se muestra por defecto).
     """
     Ventana.__init__(self, 'ventana_usuario.glade', objeto)
     connections = {'b_salir/clicked': self.salir,
                    'b_actualizar/clicked': self.actualizar_ventana, 
                    'b_guardar/clicked': self.guardar, 
                    'b_nuevo/clicked': self.crear_nuevo_usuario, 
                    'b_borrar/clicked': self.borrar_usuario, 
                    'b_buscar/clicked': self.buscar_usuario,
                    'b_enviar/clicked': self.enviar_mensaje,
                    'b_passw/clicked': self.nueva_contrasenna,
                    'b_drop/clicked': self.borrar_mensaje
                   }
     self.add_connections(connections)
     self.inicializar_ventana()
     if self.objeto == None:
         self.ir_a_primero()
         utils.dialogo_info(titulo = "NO SE PUDO DETERMINAR SU USUARIO",
                            texto = "No se pudo determinar su nombre de usuario.\nAsegúrese de haber iniciado sesión correctamente y vuelva a intentarlo.",
                            padre = self.wids['ventana'])
         self.logger.error("ventana_usuario::__init__:No se pudo determinar nombre de usuario.")
     else:
         self.ir_a(objeto)
         self.wids['ventana'].maximize()
         gtk.main()
 def ir_a_siguiente(self,widget):
     """
     Hace que el siguiente registro (ordenados por ID interno)
     sea el objeto activo
     """
     if self.wids['b_guardar'] != None and self.wids['b_guardar'].get_property('sensitive'):
         # Hay cambios pendientes de guardar.
         if utils.dialogo('Hay cambios pendientes de guardar.\n¿Desea hacerlo ahora?', '¿GUARDAR CAMBIOS?'):
             try:
                 self.guardar(None)
             except:
                 utils.dialogo_info(titulo = 'NO SE PUDO GUARDAR', 
                                    texto = 'Los cambios no se pudieron guardar automáticamente.\nDebe hacerlo de forma manual',
                                    padre = self.wids['ventana'])
                 return 
     producto = self.objeto
     try:
         siguiente = pclases.ProductoVenta.select(pclases.AND(pclases.ProductoVenta.q.camposEspecificosEspecialID != None, pclases.ProductoVenta.q.id > producto.id),orderBy='id')[0]
     except IndexError:
         utils.dialogo_info(texto = "El elemento seleccionado es el último registrado en el sistema",
                            titulo="ERROR",
                            padre = self.wids['ventana'])
         return
     self.objeto = siguiente
     self.actualizar_ventana()
Example #21
0
    def agregar_a_pedido(self, widget):
        """
        Asigna la linea sin pedido a un pedido ya creado
        """
    	model, iter = self.wids['tv_tipos'].get_selection().get_selected()
    	if iter != None:
    	    idtipo = model[iter][-1]
            linea_sin_pedido = pclases.LineaDeVenta.get(idtipo)
        else:
            utils.dialogo_info('ERROR','Seleccione una línea para asignarla al pedido')
            return

        numpedido = utils.dialogo_entrada(titulo = 'NÚMERO DE PEDIDO', texto = 'Introduzca el número del pedido al que desea añadir la línea seleccionada')
        pedido = self.buscar_pedido(numpedido)
        if pedido == None:
            utils.dialogo_info(texto = 'No se encontró ningún pedido con ese número', titulo = 'ERROR')
            return
        linea_sin_pedido.pedidoVenta = pedido
        ldc = pclases.LineaDePedido(presupuesto = None, 
                                    pedidoVenta = pedido,
                                    productoVenta = linea_sin_pedido.productoVenta,
                                    productoCompra = linea_sin_pedido.productoCompra, 
                                    fechahora = mx.DateTime.localtime(), 
                                    cantidad = linea_sin_pedido.cantidad, 
                                    precio = linea_sin_pedido.precio, 
                                    descuento = linea_sin_pedido.descuento, 
                                    fechaEntrega = None, 
                                    textoEntrega='')
    	self.rellenar_tabla()
        import pedidos_de_venta
        pedidos_de_venta.PedidosDeVenta(objeto = pedido, usuario = self.usuario)
 def buscar_cod_libre(self):
     """
     Devuelve un código de tres cifras como 
     cadena que no esté ya en la tabla de 
     productos como producto terminado.
     Siempre devolverá el primer código
     libre más cercano a 000.
     Si no quedan más mostrará un mensaje
     de error por pantalla y devolverá
     999.
     """
     prods = pclases.ProductoVenta.select(pclases.AND(
         pclases.OR(
             pclases.ProductoVenta.q.camposEspecificosBalaID !=None, 
             pclases.ProductoVenta.q.camposEspecificosRolloID !=None, 
             pclases.ProductoVenta.q.camposEspecificosEspecialID !=None), 
         pclases.ProductoVenta.q.codigo.startswith('843603219')))
     codsproducto = [p.codigo[-4:-1] for p in prods]
     codsproducto.sort()
     for i in xrange(1000):  # Si el subcódigo de producto del EAN-13 está 
         # duplicado esto no funcionará. Añadida restricción UNIQUE en la 
         # BD para evitarlo.
         # print i, int(codsproducto[i])
         try:
             if i != int(codsproducto[i]):
                 return "%03d" % i
         except IndexError:  # No hay o me pasé de rango
             return "%03d" % i
     utils.dialogo_info('NO QUEDAN CÓDIGOS DISPONIBLES', 
                        'Todos los códigos EAN13 fueron asignados.',
                        padre = self.wids['ventana'])
     return '999'
Example #23
0
 def nuevo(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í.
     """
     anterior = self.objeto
     if anterior != None:
         anterior.notificador.desactivar()
     factura = self.buscar_factura()     # Si lo que va a pagar es un LOGIC, que lo haga desde la ventana de vencimientos_pendientes.
     if factura != None:
         importe = factura.get_importe_primer_vencimiento_pendiente()    # Devuelve 0 si no quedan.
         try:
             nuevo = pclases.Pago(cuentaOrigen = pclases.CuentaOrigen.select(orderBy = "-id")[0], 
                                  fecha = mx.DateTime.localtime(), 
                                  facturaCompra = factura, 
                                  proveedor = factura.proveedor, 
                                  importe = importe)
         except IndexError:
             utils.dialogo_info(titulo = "ERROR CREANDO TRANSFERENCIA", 
                                texto = "Se produjo un error al crear una nueva transferencia.\nProbablemente no existan cuentas en la aplicación desde donde realizar transferencias.", 
                                padre = self.wids['ventana'])
         else:
             utils.dialogo_info('NUEVA TRANSFERENCIA CREADA', 
                                'Se ha creado una transferencia nueva.\nA continuación complete la información de la misma y guarde los cambios.', 
                                padre = self.wids['ventana'])
         self.objeto = nuevo
         self.objeto.notificador.activar(self.aviso_actualizacion)
         self.activar_widgets(True)
         self.actualizar_ventana(objeto_anterior = anterior)
 def crear_nuevo_producto(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í.
     """
     producto = self.objeto
     if producto != None:
         producto.notificador.desactivar()
         producto.camposEspecificosEspecial.notificador.desactivar()
     campos = pclases.CamposEspecificosEspecial(unidad = '',
                                                observaciones = '',
                                                stock = 0.0,
                                                existencias = 0)
     producto = pclases.ProductoVenta(lineaDeProduccion = None,
                                      camposEspecificosBala = None,
                                      camposEspecificosRollo = None, 
                                      camposEspecificosEspecial = campos,
                                      codigo = self.generar_codigo_ean(), 
                                      nombre = '',
                                      descripcion = '', 
                                      preciopordefecto = 0, 
                                      minimo = 0,
                                      arancel = '')
     self._objetoreciencreado = producto
     utils.dialogo_info('PRODUCTO CREADO', 
                        'Se ha creado un producto nuevo.\n\n\nA continuación complete la información del producto y guarde los cambios.\n', 
                        padre = self.wids['ventana'])
     producto.notificador.activar(self.aviso_actualizacion)
     producto.camposEspecificosEspecial.notificador.activar(self.aviso_actualizacion)
     self.objeto = producto
     self.activar_widgets(True)
     self.actualizar_ventana()
Example #25
0
 def borrar(self, widget):
     """
     Elimina la cuenta de la tabla pero NO
     intenta eliminar ninguna de sus relaciones,
     de forma que si se incumple alguna 
     restricción de la BD, cancelará la eliminación
     y avisará al usuario.
     """
     cuenta = self.objeto
     if not utils.dialogo('¿Eliminar la cuenta?', 'BORRAR', padre = self.wids['ventana']):
         return
     if cuenta.pagos != []:
         utils.dialogo_info('CUENTA NO ELIMINADA', 
                            'La cuenta está implicada en operaciones que impiden su borrado.', 
                            padre = self.wids['ventana'])
     else:
         cuenta.notificador.desactivar()
         try:
             cuenta.destroySelf()
         except Exception, e:
             self.logger.error("cuentas_destino::borrar -> Cuenta ID %d no se pudo eliminar. Excepción: %s." % (cuenta.id, e))
             utils.dialogo_info(titulo = "CUENTA NO BORRADA", 
                                texto = "La cuenta no se pudo eliminar.\n\nSe generó un informe de error en el «log» de la aplicación.",
                                padre = self.wids['ventana'])
             self.actualizar_ventana()
             return
         self.objeto = None
         self.ir_a_primero()
 def borrar_producto(self, widget):
     """
     Elimina el producto de la tabla pero NO
     intenta eliminar ninguna de sus relaciones,
     de forma que si se incumple alguna 
     restricción de la BD, cancelará la eliminación
     y avisará al usuario.
     """
     producto = self.objeto
     if not utils.dialogo('¿Eliminar el producto?', 'BORRAR', padre = self.wids['ventana']):
         return
     if producto.articulos != [] or producto.precios != []:
         utils.dialogo_info('PRODUCTO NO ELIMINADO', 
                            'El producto está implicado en operaciones que impiden su borrado.', 
                            padre = self.wids['ventana'])
     else:
         producto.notificador.desactivar()
         producto.camposEspecificosEspecial.notificador.desactivar()
         cee = producto.camposEspecificosEspecial
         producto.camposEspecificosEspecial = None
         try:
             producto.destroySelf()
         except:
             producto.camposEspecificosEspecial = cee
             utils.dialogo_info(titulo = "PRODUCTO NO BORRADO", 
                                texto = "El producto no se pudo eliminar",
                                padre = self.wids['ventana'])
             self.actualizar_ventana()
             return
         cee.destroySelf()
         self.objeto = None
         self.ir_a_primero()
Example #27
0
 def add_producto_a_consumo(self, boton):
     """
     Añade un producto de venta a un consumo existente.
     """
     model, paths = self.wids['tv_consumos'].get_selection().get_selected_rows()
     if paths != []:
         productos = self.pedir_productos_venta()
         if productos:
             for path in paths:
                 if model[path].parent == None:
                     id_consumo = model[path][-1]
                 else:
                     id_consumo = model[path].parent[-1]
                 consumo_adicional_por_producto = pclases.ConsumoAdicional.get(id_consumo)
                 for producto in productos:
                     if producto not in consumo_adicional_por_producto.productosVenta:
                         consumo_adicional_por_producto.addProductoVenta(producto)
                     else:
                         utils.dialogo_info(titulo = "YA EXISTE", 
                                            texto = "El producto %s ya consume según la fórmula de %s.\n\nPulse «Aceptar» para continuar." % (producto.descripcion, consumo_adicional_por_producto.nombre), 
                                            padre = self.wids['ventana'])
             self.rellenar_consumos_adicionales_por_producto()
     else:
         utils.dialogo_info(titulo = "SELECCIONE UN CONSUMO", 
                            texto = "Debe seleccionar un consumo existente.", 
                            padre = self.wids['ventana'])
 def set_partida(self, w):
     numpartida = utils.dialogo_entrada(titulo = 'Nº PARTIDA', 
                                     texto = 'Introduzca número de partida:')
     if numpartida != None:
         partidas = pclases.Partida.select(pclases.Partida.q.numpartida.contains(numpartida))
         if partidas.count() == 0:
             utils.dialogo_info(titulo = 'PARTIDA NO ENCONTRADA', 
                                texto = 'No se encontró ninguna partida %s.' % numpartida)
             return
         elif partidas.count() > 1:
             filas = [(l.id, l.numpartida, l.codigo, l.longitudinal, l.transversal, l.compresion, l.perforacion, l.permeabilidad, l.poros, l.espesor) for l in partidas]
             idpartida = utils.dialogo_resultado(filas, 
                                              titulo = 'SELECCIONE PARTIDA',
                                              cabeceras = ('ID', 'Número', 'Código', 'Longitudinal', 'Transversal', 'CBR', 'Perforación', 'Permeabilidad', 'Poros', 'Espesor'))
             if idpartida < 0:
                 return
             partida = pclases.Partida.get(idpartida)
         else:
             partida = partidas[0]
         if len(partida.rollos) == 0:
             utils.dialogo_info(titulo = 'PARTIDA VACÍA', 
                                texto = 'La partida no contiene rollos, no puede\nrealizar pruebas sobre una partida vacía.')
             self.partida = None
             return
         self.partida = partida
         self.actualizar_ventana()
 def pedir_producto(self):
     """
     Solicita una descripción de producto, muestra una
     ventana de resultados coincidentes con la 
     búsqueda de ese código y devuelve un 
     objeto producto seleccionado de entre
     los resultados o None si se cancela o 
     no se encuentra.
     """
     producto = None
     codigo = utils.dialogo_entrada(texto = 'Introduzca descripción del producto.', 
                                    titulo = 'PRODUCTO', 
                                    padre = self.wids['ventana'])
     if codigo == None:  # Ha cancelado
         producto = self.producto
     if codigo != None:
         prods = pclases.ProductoCompra.select(pclases.ProductoCompra.q.descripcion.contains(codigo))
         prods = [p for p in prods]
         mens_error = 'No se encontró ningún producto con esa descripción.'
         if len(prods) > 1:
             idproducto = self.refinar_busqueda_productos(prods)
             if idproducto != None:
                 prods = [p for p in prods if p.id == idproducto]
             else:
                 return None
         elif len(prods) < 1:
             utils.dialogo_info('CÓDIGO NO ENCONTRADO', mens_error)
             return None
         producto = prods[0]
     return producto
Example #30
0
 def anular_carga_y_crear_nueva(self, ldc, silo):
     """
     Busca la carga asociada a la línea de compra, 
     la anula y crea una nueva relacionada con 
     el silo recibido.
     Devuelve True si se anuló la carga creando la nueva.
     """
     ldc.sync()
     if ldc.cargaSilo:
         try:
             carga_anterior = ldc.cargaSilo
             ldc.cargaSilo = None
             ldc.silo = None
             carga_anterior.destroySelf()
         except:
             utils.dialogo_info(titulo = "OPERACIÓN NO PERMITIDA", 
                                texto="No puede cambiar el silo de carga.", 
                                padre = self.wids['ventana'])
             ldc.cargaSilo = carga_anterior
             ldc.silo = carga_anterior.silo
             return False
     ldc.silo = silo
     carga = pclases.CargaSilo(silo = silo, 
                               fechaCarga = ldc.albaranEntrada.fecha, 
                               cantidad = ldc.cantidad, 
                               productoCompra = ldc.productoCompra)
     ldc.cargaSilo = carga
     return True