def refinar_resultados_busqueda(self, resultados): """ Muestra en una ventana de resultados todos los registros de "resultados". Devuelve el id (primera columna de la ventana de resultados) de la fila seleccionada o None si se canceló. """ filas_res = [] for r in resultados: filas_res.append((r.id, r.empleado and r.empleado.nombre or "SIN EMPLEADO", utils.str_fechahora(r.fechahoraInicio), utils.str_fechahora(r.fechahoraFin))) id = utils.dialogo_resultado(filas_res, titulo = 'SELECCIONE %s' % self.clase.sqlmeta.table.upper(), cabeceras = ('ID', 'Empleado', 'Inicio', 'Fin'), padre = self.wids['ventana']) if id < 0: return None else: return id
def volcar_info(pdp, csv): producto = pdp.productoVenta and pdp.productoVenta nombre_producto = producto and producto.descripcion or "" prod_estandar_parte = pdp.prodestandar prod_estandar_producto = producto and producto.prodestandar or "" fecha = utils.str_fecha(pdp.fecha) #horaini = utils.str_hora_corta(pdp.horainicio) #horafin = utils.str_hora_corta(pdp.horafin) horaini = utils.str_fechahora(pdp.fechahorainicio) horafin = utils.str_fechahora(pdp.fechahorafin) produccion_m2 = pdp.get_produccion()[0] produccion_kg = sum([a.peso_sin for a in pdp.articulos]) productividad = pdp.calcular_productividad() rendimiento = pdp.calcular_rendimiento() observaciones = pdp.observaciones observaciones_paradas = "; ".join( [parada.observaciones for parada in pdp.incidencias]) tiempo_produccion, tiempo_paradas = calcular_tiempo_trabajado(pdp) csv.writerow((nombre_producto, prod_estandar_parte, prod_estandar_producto, fecha, horaini, horafin, produccion_m2, produccion_kg, productividad, rendimiento, observaciones, observaciones_paradas, tiempo_produccion, tiempo_paradas))
def rellenar_tabla(self, balas): """ Introduce las balas recibidas en el TreeView «tv» y lo desplaza a la última fila (la más baja) """ tv = self.wids['tv_balas'] model = tv.get_model() tv.freeze_child_notify() tv.set_model(None) model.clear() totpantalla = 0.0 for bala, producto in balas: if producto != None: desc = producto.descripcion else: desc = "?" fila = (utils.str_fechahora(bala.fechahora), bala.codigo, utils.float2str(bala.peso, 1), desc, bala.observaciones, bala.id) model.append(fila) totpantalla += bala.peso_sin tv.set_model(model) tv.thaw_child_notify() self.rellenar_totales(totpantalla) self.mover_al_final(self.wids['tv_balas'])
def set_fin(self, boton): temp = utils.mostrar_calendario( fecha_defecto=utils.parse_fechahora( self.wids['e_fechafin'].get_text()), padre=self.wids['ventana']) temp = mx.DateTime.DateFrom(day=temp[0], month=temp[1], year=temp[2]) + mx.DateTime.TimeDelta(hours = 6) self.wids['e_fechafin'].set_text(utils.str_fechahora(temp))
def imprimir(self, boton): """ Prepara la vista preliminar para la impresión del informe """ from formularios import reports datos = [] model = self.wids['tv_datos'].get_model() for i in xrange(len(model)): datos.append((model[i][0], model[i][1])) if not self.inicio: fechaInforme = 'Hasta ' + utils.str_fechahora(self.fin) else: fechaInforme = (utils.str_fechahora(self.inicio) + ' - ' + utils.str_fechahora(self.fin)) if datos != []: reports.abrir_pdf(geninformes.consumo_produccion(datos, fechaInforme))
def add_jornal(self, b): """ Muestra un diálogo de resultados con los jornales sin salarios relacionados, pertenecientes al empleado del registro salario y su fechahoraInicio esté entre la fecha del salario y el final del mes de esa misma fecha. """ findemes = mx.DateTime.DateTimeFrom(day = -1, month = self.objeto.fecha.month, year = self.objeto.fecha.year) findemes += mx.DateTime.oneDay # Porque vamos a comparar con fechahora. J = pclases.Jornal jornales = J.select(pclases.AND(J.q.salarioID == None, J.q.empleadoID == self.objeto.empleadoID, J.q.fechahoraInicio < findemes, J.q.fechahoraInicio >= self.objeto.fecha), orderBy = "fechahoraInicio") cabeceras=("ID", "Inicio", "Fin", "Actividad", "Parcela", "Produccion") filas = [(j.id, utils.str_fechahora(j.fechahoraInicio), utils.str_fechahora(j.fechahoraFin), j.actividad and j.actividad.descripcion or "", j.parcela and j.parcela.parcela or "", utils.float2str(j.produccion)) for j in jornales] resjornales = utils.dialogo_resultado(filas, "SELECCIONE JORNADAS", self.wids['ventana'], cabeceras, multi = True) if resjornales and resjornales[0] > 0: for jid in resjornales: jornal = pclases.Jornal.get(jid) jornal.salario = self.objeto jornal.salario.horasCampo += jornal.horasCampo jornal.salario.totalEuros += (jornal.eurosCampo + jornal.eurosManipulacion) dia = utils.abs_mxfecha(jornal.fechahoraInicio) dias = [utils.abs_mxfecha(j.fechahoraInicio) for j in jornal.salario.jornales] if dia not in dias: jornal.salario.totalEuros += jornal.empleado.precioDiario self.objeto.update_actividad() self.actualizar_ventana()
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). """ global fin Ventana.__init__(self, 'consulta_consumo.glade', objeto, usuario=usuario) connections = {'b_salir/clicked': self.salir, 'b_buscar/clicked': self.buscar, 'b_imprimir/clicked': self.imprimir, 'b_fecha_inicio/clicked': self.set_inicio, 'b_fecha_fin/clicked': self.set_fin, 'e_fechainicio/focus-out-event': utils.act_fechahora, 'e_fechafin/focus-out-event': utils.act_fechahora, "b_exportar/clicked": self.exportar} self.add_connections(connections) cols = (('Producto', 'gobject.TYPE_STRING', False, True, False, None), ('Cantidad consumida', 'gobject.TYPE_STRING', False, True, False, None), ('A', 'gobject.TYPE_STRING', False, True, False, None), ('B', 'gobject.TYPE_STRING', False, True, False, None), ('C', 'gobject.TYPE_STRING', False, True, False, None), ('Media diaria', 'gobject.TYPE_STRING', False, True, False, None), ('ID', 'gobject.TYPE_STRING', False, False, False, None)) utils.preparar_treeview(self.wids['tv_datos'], cols) for ncol in range(1, 4): self.wids['tv_datos'].get_column(ncol).get_cell_renderers()[0].set_property("xalign", 1) self.fin = mx.DateTime.today() + mx.DateTime.TimeDelta(hours = 6) self.wids['e_fechafin'].set_text(utils.str_fechahora(self.fin)) self.wids['e_fechainicio'].set_text( utils.str_fechahora(self.fin - (7 * mx.DateTime.oneDay))) self.inicio = utils.parse_fechahora(self.wids['e_fechainicio'].get_text()) # self.wids['ch_fibra'].set_active(True) self.wids['ch_geotextiles'].set_active(True) gtk.main()
def rellenar_tabla(self, rollos): """ Rellena la tabla con la información de los rollos recibidos. """ model = self.wids['tv_datos'].get_model() model.clear() for r in rollos: model.append((r.codigo, r.partida and r.partida.codigo or "", r.albaranSalida and r.albaranSalida.numalbaran or "", utils.str_fechahora(r.fechahora), r.id))
def add_nuevo_rollo_tv(self, rollo): """ Introduce el rollo al final del TreeView y lo desplaza. """ model = self.wids['tv_rollos'].get_model() fila = (utils.str_fechahora(rollo.fechahora), rollo.codigo, utils.float2str(rollo.peso, 2), rollo.productoVenta.descripcion, rollo.observaciones, rollo.id) model.append(fila) self.mover_al_final(self.wids['tv_rollos'])
def fecha_from_pdp(self, boton): """ Busca la fecha más temprana de producción y se la asigna a la partida de carga. Si no hay producción aún, deja la actual. """ partida = self.get_partida() if partida is not None: fecha = partida.get_fecha_inicio() if fecha: partida.fecha = fecha self.wids['e_fecha'].set_text( utils.str_fechahora(partida.fecha))
def add_nueva_bala_tv(self, bala): """ Introduce la bala al final del TreeView y lo desplaza. """ model = self.wids['tv_balas'].get_model() fila = (utils.str_fechahora(bala.fechahora), bala.codigo, utils.float2str(bala.peso, 1), bala.productoVenta.descripcion, bala.observaciones, bala.id) model.append(fila) self.mover_al_final(self.wids['tv_balas'])
def rellenar_tabla_jornales(self): model = self.wids['tv_jornales'].get_model() model.clear() totalprod = 0.0 totalhoras = mx.DateTime.DateTimeDelta(0) for p in self.objeto.jornales: totalprod += p.produccion totalhoras += p.fechahoraFin - p.fechahoraInicio #model.append((p.campanna # and utils.str_fecha(p.campanna.fechaInicio) or "", definicion_actividad = p.actividad and p.actividad.descripcion or "" if p.actividad: if p.actividad.campo: definicion_actividad += " (campo)" elif p.actividad.manipulacion: definicion_actividad += " (manipulación)" model.append((definicion_actividad, p.parcela and p.parcela.parcela or "", utils.str_fechahora(p.fechahoraInicio), utils.str_fechahora(p.fechahoraFin), utils.float2str(p.get_duracion()), utils.float2str(p.produccion), p.id))
def buscar_fecha(self, boton): """ Muestra el diálogo calendario y establece la fecha de la partida. """ partida = self.get_partida() if partida is not None: fecha = utils.mostrar_calendario(fecha_defecto=partida.fecha, padre=self.wids['ventana']) fecha = utils.parse_fecha(utils.str_fecha(fecha)) partida.fecha = mx.DateTime.DateTimeFrom(day=fecha.day, month=fecha.month, year=fecha.year, hour=partida.fecha.hour, minute=partida.fecha.minute, second=partida.fecha.second) self.wids['e_fecha'].set_text(utils.str_fechahora(partida.fecha))
def imprimir(self, boton): """ Exporta a PDF. """ idempl = utils.combo_get_value(self.wids['cb_empleado']) if idempl: nomempl = pclases.Empleado.get(idempl) titulo = "%s: producción diaria." % nomempl.nombre else: titulo = "Producción diaria" strfecha = utils.str_fechahora(mx.DateTime.localtime()) abrir_pdf(treeview2pdf(self.wids['tv_datos'], titulo = titulo, fecha = strfecha))
def mostrar_hora_parte(self, tv): """ Muestra la hora del parte del artículo donde se encuentra el cursor en el TreeView. """ model, paths = tv.get_selection().get_selected_rows() for path in paths: itr = model.get_iter(path) if itr != None and model[itr][2] == "CLIC PARA VER": articulo = pclases.Articulo.get(model[itr][-1]) if articulo.parteDeProduccionID != None: model[itr][2] = utils.str_fecha( articulo.parteDeProduccion.fecha) elif articulo.es_rolloC(): model[itr][2] = utils.str_fechahora( articulo.rolloC.fechahora) else: model[itr][2] = "¡Sin parte de producción!"
def edit_fechahora(cell, path, newtext, tv, numcol, clase, atributo): """ Cambia el texto del model[path][numcol] y del objeto relacionado que saca a partir del ID de la última columna del model. """ model = tv.get_model() ide = model[path][-1] objeto = clase.get(ide) try: fecha = utils.parse_fechahora(newtext) except (ValueError, TypeError): parent = tv.parent while parent != None: parent = parent.parent utils.dialogo_info(titulo = "ERROR EN FECHA Y HORA", texto = "El texto «%s» no es una fecha y hora válida." % (newtext), padre = parent) else: setattr(objeto, atributo, fecha) objeto.syncUpdate() model[path][numcol] = utils.str_fechahora(getattr(objeto, atributo))
def build_jornal(data = None, intentos = 5): """ Devuelve un registro jornal con la producción recibida en data. Si data es None, pide los datos de nuevo hasta un máximo de «n» intentos. Si no consigue recibir o procesar bien los datos, devuelve None. """ n = 0 while (not data and n < intentos) or n == 0: # La primera vez siempre debe entrar if not data: data = pedir_datos() n += 1 try: ide, ida, idp, inicio, fin, prod = procesar(data) except ValueError: data = None if data != None: # Los ha procesado correctamente. empleado = pclases.Empleado.get(ide) actividad = pclases.Actividad.get(ida) parcela = pclases.Parcela.get(idp) C = pclases.Campanna try: campanna = C.buscar_campanna(inicio) if campanna == None: raise IndexError except IndexError, msg: # No existe la campaña. Devuelvo error y aviso por stderr. jornal = None sys.stderr.write("No existe campaña para la fecha %s.\n%s" % ( utils.str_fechahora(inicio), msg)) else: jornal = pclases.Jornal(empleado = empleado, actividad = actividad, campanna = campanna, parcela = parcela, salario = None, fechahoraInicio = inicio, fechahoraFin = fin, produccion = prod)
def rellenar_widgets(self): """ Copia los valores del objeto a los widgets de la ventana. """ partida = self.get_partida() if partida is not None: self.wids['e_partida'].set_text("%d (%s)" % (partida.numpartida, partida.codigo)) self.wids['e_fecha'].set_text(utils.str_fechahora(partida.fecha)) self.wids['ch_api'].set_active(bool(partida.api)) else: self.wids['e_partida'].set_text("") self.wids['e_fecha'].set_text("") self.wids['ch_api'].set_active(False) self.rellenar_balas() self.rellenar_partidas_gtx() self.comprobar_permisos() api = self.wids['ch_api'].get_active() self.wids['b_add_balas'].set_sensitive(not api) self.wids['b_add_producto'].set_sensitive(not api) self.wids['b_drop_bala'].set_sensitive(not api) self.wids['b_phaser'].set_sensitive(not api)
def rellenar_partidas_gtx(self): """ Rellena la tabla con las partidas de geotextiles relacionadas con la de carga actual. """ model = self.wids['tv_gtx'].get_model() model.clear() for partida in self.objeto.partidas: if partida.rollos != []: producto = partida.rollos[0].productoVenta.descripcion fechas_partes = set() for rollo in partida.rollos: parte = rollo.articulo.parteDeProduccion if parte: fechas_partes.add((parte.fechahorainicio, parte.bloqueado)) partes = "; ".join(["{}{}".format(utils.str_fechahora(f), v and "✔" or "✘") for f,v in sorted(fechas_partes, key=lambda t: t[0])]) else: producto = "SIN PRODUCCIÓN" partes = "" model.append((partida.codigo, producto, partes, partida.id))
def fecha_from_albaran(self, boton): """ Busca la fecha del albarán interno. Si hay más de uno, selecciona el más temprano de ellos. Si no hay albarán interno, deja la actual. """ partida = self.get_partida() if partida is not None: fecha = partida.get_fecha_inicio() if fecha: albaranes_internos = list(partida.get_albaranes_internos()) if albaranes_internos: albaranes_internos.sort( lambda a1, a2: (a1.fecha < a2.fecha and -1) or (a1.fecha > a2.fecha and 1) or 0) fecha = albaranes_internos[0].fecha partida.fecha = mx.DateTime.DateTimeFrom( day=fecha.day, month=fecha.month, year=fecha.year, hour=partida.fecha.hour, minute=partida.fecha.minute, second=partida.fecha.second) self.wids['e_fecha'].set_text( utils.str_fechahora(partida.fecha))
def col2value(objeto, col): """ Convierte el valor del objeto a un formato legible en función de su tipo de datos. """ valor = getattr(objeto, col.name) if isinstance(col, pclases.SODateCol): # Es DATE. return utils.str_fecha(valor) elif isinstance(col, pclases.SOStringCol): # TEXT return valor elif isinstance(col, pclases.SOFloatCol): # FLOAT return utils.float2str(valor, autodec = True) elif isinstance(col, pclases.SOIntCol): # INT return valor elif isinstance(col, pclases.SOBoolCol): # BOOLEAN return valor elif isinstance(col, pclases.SOForeignKey): # Clave ajena. return valor # and valor.id or "" elif isinstance(col, pclases.SOCol): # Es TIMESTAMP o TIME if "timestamp" in str(col) or ("fecha" in col.name and "hora" in col.name): return utils.str_fechahora(valor) else: return utils.str_hora(valor)
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()