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()
def cambiar_resultado(self, tv, path, texto): model = self.wids["tv_pruebas"].get_model() prueba = claseprueba.get(model[path][-1]) try: prueba.resultado = float(texto) except: utils.dialogo_info("RESULTADO INCORRECTO", "El número tecleado (%s) no es correcto." % texto) self.rellenar_pruebas()
def cambiar_cantidad(self, cell, path, texto): """ Cambia la cantidad de una linea de venta de un albarán de entrada, en el caso de que se escriba una cantidad menor de la que estaba en el pedido de compra (si es que tenía uno asociado), se desdobla la línea de venta original en dos líneas: una con el albarán asociado (por lo que deja de estar pendiente) y otra con la cantidad pendiente que no queda asociada al albarán. Si en el pedido quedara alguna LDV sin "albaranear" del mismo producto, al mismo precio, etc... esta segunda línea con la cantidad excedente se suma a la del pedido y se elimina, para evitar líneas sueltas de cantidades pequeñas. En el caso de que se escriba una cantidad mayor a la que estaba originalmente en el pedido se darán dos opciones: - Crear una nueva linea de compra sin pedido asociado, con la cantidad incrementada. - Incrementar la cantidad en la línea de compra del pedido original. ... Bla, bla, bla, bla. ¡Hola! Soy Troy McLure. Tal vez me recuerden de otros cambios de requisitos en caliente como «cambiemos "en albarán" por "albaraneada"», «vendamos productos de compra sin manufacturar» o «tal vez necesitemos un histórico de existencias»... Todo lo de arriba YA NO SIRVE. Ahora, con las nuevas líneas de pedido de compra, la cantidad se aumenta directamente en la línea de compra y santas pascuas. """ try: cantidad = float(texto) except: return model = self.wids['tv_ldvs'].get_model() try: ldc = pclases.LineaDeCompra.get(model[path][-1]) except pclases.SQLObjectNotFound: utils.dialogo_info(titulo = "LÍNEA BORRADA", texto = "La línea seleccionada fue eliminada desde otro puesto.", padre = self.wids['ventana']) else: antigua = ldc.cantidad ldc.cantidad = cantidad if ldc.productoCompra.controlExistencias: # XXX DEBUG #print ldc.productoCompra.existencias # XXX EODEBUG diferencia = cantidad - antigua ldc.productoCompra.sync() ldc.productoCompra.existencias += diferencia ldc.productoCompra.add_existencias(diferencia, almacen=self.objeto.almacen) ldc.productoCompra.syncUpdate() ldc.productoCompra.sync() # XXX DEBUG #print ldc.productoCompra.existencias # XXX EODEBUG if ldc.cargaSilo: ldc.cargaSilo.cantidad = cantidad self.actualizar_ventana()
def cambiar_precio(self, cell, path, texto): try: precio = float(texto) except: return model = self.wids['tv_ldvs'].get_model() ldc = pclases.LineaDeCompra.get(model[path][-1]) ldc.precio = precio self.actualizar_ventana()
def pedir_cantidad(self): cant = utils.dialogo_entrada(titulo = '¿CANTIDAD?', texto = 'Introduzca cantidad', valor_por_defecto = '1', padre = self.wids['ventana']) try: cant = float(cant) except: utils.dialogo_info(titulo = 'ERROR EN CANTIDAD', texto = 'Cantidad incorrecta.\nAsegúrese de escribirla con punto (.) como separador decimal.\nSe añadirá el producto al albarán, modifique la cantidad directamente ahí.', padre = self.wids['ventana']) cant = 1 return cant
def cambiar_precio_tarifa(self, cell, path, texto, idtarifa): 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]) producto = ldc.productoCompra tarifa = pclases.Tarifa.get(idtarifa) precio_sin_iva = precio / 1.21 tarifa.asignarTarifa(producto, precio_sin_iva) self.actualizar_ventana()
def rellenar_tabla(self, partes, solobalas): """ Rellena el model con los partes rescatados de la BD en `buscar`. PRERREQUISITO: Los partes vienen en una lista y deben estar ordenados por fecha y hora de inicio. """ # Lo primero de todo. Si está activado el DEBUG, muestro las columnas. tv = self.wids['tv_datos'] for ncol in range(7, len(tv.get_columns())): tv.get_column(ncol).set_property("visible", pclases.DEBUG) self.huecos = [] # Lista de los últimos partes tratados por línea. self.incidencias_horaini = [] self.incidencias_horafin = [] self.tiempo_faltante = mx.DateTime.TimeDeltaFrom(0) vpro = VentanaProgreso(padre = self.wids['ventana']) model = self.wids['tv_datos'].get_model() model.clear() total = 0 kilosproducidos = 0 kilosgranza = 0 vector = [] tot = len(partes) i = 0.0 vpro.mostrar() e_personasturno = 0 tiempototal = 0 tiempo_sin_incidencias = 0 # Por si inicia una consulta sin resultados metrosproducidos = 0 kilosconsumidos = kilosconsumidos_partidas_completas = 0 tiempototaltotal = mx.DateTime.DateTimeDelta(0) #selffin = utils.parse_fecha('/'.join(self.fin.split('/')[::-1])) selffin = self.fin # ... WTF? Esto está hecho como el culo. ¡REFACTORIZAR! # XXX Primer intento de acelerar los treeview self.wids['tv_datos'].freeze_child_notify() self.wids['tv_datos'].set_model(None) # XXX personashora = [] dia_actual = "" # Estos tres parámetros son para medir la # producción y productividad por día. produccion_actual = 0.0 #productividad_actual = 0.0 t_teorico_por_dia = 0 t_real_por_dia = 0 pdps_dia = [] # Ojo. Los partes deben venir ordenados para que # esta lista solo contenga los partes del día tratado en la # iteración por la que vaya. Se limpia al cambiar de un día al # siguiente mientras relleno los datos. #nodos_hijos_por_dia = 0 balas_consumidas = [] # Lista con las balas consumidas por # todos los partes, así evito contar la misma dos veces si en dos # partes se ha usado la misma partida o dos partidas de la misma # partida de carga. padre = None # En una de las iteraciones se espera que padre se haya # instanciado en el final de la anterior. Inicializo para evitar # errores y errores en análisis sintáctico de algunos IDE en la # línea 342. for pdp in partes: if pdp.se_solapa(): texto_warning = "%sconsulta_productividad::rellenar_tabla"\ " -> El parte ID %d se solapa con otros de la misma línea"\ ". Si estaba verificado, lo desbloqueo para que se vuelva"\ " a revisar y lo ignoro para el cálculo actual." % ( self.usuario and self.usuario.usuario + ": " or "", pdp.id) self.logger.warning(texto_warning) myprint(texto_warning) pdp.bloqueado = False continue vpro.set_valor(i/tot, 'Añadiendo parte %s...' % ( utils.str_fecha(pdp.fecha))) delta_entre_partes, parte_anterior = detectar_hueco(pdp, self.huecos) if delta_entre_partes: self.marcar_hueco(parte_anterior, pdp) self.tiempo_faltante += delta_entre_partes kilosgranza_del_parte = 0.0 (tiempototal, tiempo_sin_incidencias) = self.calcular_tiempo_trabajado(pdp) tiempototaltotal += tiempototal #productividad = pdp.calcular_productividad() # CWT: Ahora no se calcula así, sino como el antiguo rendimiento. productividad = pdp.calcular_rendimiento() # Tratamiento especial para partes de balas try: str_producto = pdp.productoVenta.descripcion except AttributeError: str_producto = "Sin producción" if (self.wids['r_balas'].get_active() or self.wids['r_ambos'].get_active()): # Sólo balas o todos. if pdp.es_de_fibra(): balas = [a.bala for a in pdp.articulos if a.balaID != None] bigbags = [a.bigbag for a in pdp.articulos if a.bigbagID != None] for b in balas: kilosproducidos += b.pesobala for b in bigbags: kilosproducidos += b.pesobigbag kilosgranza_del_parte = pdp.get_granza_consumida() kilosgranza += kilosgranza_del_parte if pdp.get_produccion()[0] - kilosgranza_del_parte > 1000: # XXX DEBUG self.logger.warning("El parte ID %d (%s) ha consumido " "(%s) mucha menos granza que fibra ha " "producido (%s) !!!" % (pdp.id, utils.str_fecha(pdp.fecha), utils.float2str(kilosgranza_del_parte), utils.float2str(pdp.get_produccion()[0]))) # XXX DEBUG if (self.wids['r_cemento'].get_active() or self.wids['r_ambos'].get_active()): kilosproducidos += pdp.get_produccion()[0] kilosconsumidos += sum([bb.pesobigbag for bb in pdp.bigbags]) if (self.wids['r_rollos'].get_active() or self.wids['r_ambos'].get_active()): # Sólo rollos o todos. if pdp.es_de_geotextiles(): superficies_defectuosos = [a.superficie for a in pdp.articulos if a.es_rollo_defectuoso()] metrosproducidos += sum(superficies_defectuosos) rollos = [a.rollo for a in pdp.articulos if a.rollo != None] if len(rollos) > 0: # Para que no intente hacer el # cálculo con partes que tengan balas y/o no rollos. pv = pdp.articulos[0].productoVenta cer = pv.camposEspecificosRollo metrosproducidos += (len(rollos) * cer.metros_cuadrados) if pdp.articulos[0].es_rollo(): partida = pdp.articulos[0].rollo.partida elif pdp.articulos[0].es_rollo_defectuoso(): partida = pdp.articulos[0].rolloDefectuoso.partida else: partida = None if partida != None: contar_kilosconsums_partidas_completas \ = partida.entra_en_cota_superior(selffin) for b in partida.balas: if b not in balas_consumidas: # Evito contar # la misma bala dos veces. bpesobala = b.pesobala kilosconsumidos += bpesobala if contar_kilosconsums_partidas_completas: kilosconsumidos_partidas_completas \ += bpesobala balas_consumidas.append(b) empleados = len(pdp.horasTrabajadas) e_personasturno += empleados tiempoparte = pdp.get_duracion().hours if tiempoparte > 0: personashora.append(empleados/tiempoparte) else: personashora.append(0.0) vector.append(productividad) produccion = pdp.get_produccion() # Resúmenes por día como nodos padre del TreeView. if not dia_actual: pdps_dia.append(pdp) if dia_actual == utils.str_fecha(pdp.fecha): pdps_dia.append(pdp) else: if dia_actual != "": # Actualizo el padre if not self.wids['r_ambos'].get_active(): model[padre][4] = "%s %s" % ( utils.float2str(produccion_actual), produccion[1]) else: # Evito mezclar kilos con metros model[padre][4] = "-" productividad_actual = calcular_productividad_conjunta( tuple(pdps_dia)) model[padre][5] = "%s %%" % ( utils.float2str(productividad_actual)) model[padre][6] = min(productividad_actual, 100) model[padre][7] = t_teorico_por_dia model[padre][8] = t_real_por_dia pdps_dia = [pdp] # He cambiado de día. Limpio. t_teorico_por_dia = 0 t_real_por_dia = 0 dia_actual = utils.str_fecha(pdp.fecha) produccion_actual = 0.0 productividad_actual = 0.0 #nodos_hijos_por_dia = 0 padre = model.append(None, (dia_actual, "", "", "", "", "%s %%" % (utils.float2str(productividad_actual)), min(productividad_actual, 100), "", # t. teórico "", # t. real 0)) t_teorico_pdp = pdp.calcular_tiempo_teorico() t_teorico_por_dia += t_teorico_pdp t_real_pdp = pdp.calcular_tiempo_real() t_real_por_dia += t_real_pdp model.append(padre, (utils.str_fecha(pdp.fecha), str(pdp.horainicio)[:5], str(pdp.horafin)[:5], str_producto, "%s %s" % (utils.float2str(produccion[0]), produccion[1]), "%s %%" % (utils.float2str(productividad)), min(productividad, 100), t_teorico_pdp, t_real_pdp, pdp.id)) produccion_actual += produccion[0] i+=1 # Actualizo el padre de los últimos nodos: if dia_actual != "": # Actualizo el padre if not self.wids['r_ambos'].get_active(): model[padre][4] = "%s %s" % ( utils.float2str(produccion_actual), produccion[1]) else: # Evito mezclar kilos con metros model[padre][4] = "-" productividad_actual = calcular_productividad_conjunta( tuple(pdps_dia)) model[padre][5] = "%s %%" % (utils.float2str(productividad_actual)) model[padre][6] = min(productividad_actual, 100) # Campos de depuración model[padre][7] = t_teorico_por_dia model[padre][8] = t_real_por_dia vpro.ocultar() # XXX Primer intento de acelerar los treeview self.wids['tv_datos'].set_model(model) self.wids['tv_datos'].thaw_child_notify() # XXX if partes != []: total = calcular_productividad_conjunta(tuple(partes)) # Campos especiales de "Sólo balas" if self.wids['r_balas'].get_active(): self.wids['label7'].set_text('Kilos producidos:') self.wids['label8'].set_text('Kilos granza consumidos:') self.wids['label9'].set_text('Kilos / Hora producción:') self.wids['e_kilosproducidos'].set_text( "%s kg" % (utils.float2str(kilosproducidos))) self.wids['e_kilosgranza'].set_text( "%s kg" % (utils.float2str(kilosgranza))) try: e_kiloshora = (kilosproducidos /float(tiempototaltotal.hours)) except ZeroDivisionError: self.logger.warning( "consulta_productividad.py::rellenar_tabla" " -> tiempototaltotal = 0") e_kiloshora = 0 # Cero por poner algo. Porque un parte # de tiempo transcurrido=0... se las trae. self.wids['e_kiloshora'].set_text("%s kg/h" % ( utils.float2str(e_kiloshora))) elif self.wids['r_rollos'].get_active(): tips = gtk.Tooltips() tips.set_tip(self.wids['e_kilosgranza'], "Kilogramos consumidos contando partidas " "completas por defecto y por exceso.\n(En un caso" " se cuentan solo partidas de carga cuyas " "partidas de geotextiles se hayan completado " "estrictamente antes o en la cota superior.\n" "En el otro, por exceso, se contabilizan " "partidas completas aunque parte de su " "producción se salga del rango de fechas.\n" "En ambos casos el límite inferior es flexible " "-por compensación-.)") tips.enable() self.wids['label7'].set_text('m² producidos:') self.wids['label8'].set_text('Kg fibra consumidos:') self.wids['label9'].set_text('m²/h producción:') try: e_kiloshora = (metrosproducidos/float(tiempototaltotal.hours)) except ZeroDivisionError: self.logger.warning( "consulta_productividad.py::rellenar_tabla -> " "tiempototaltotal = 0") e_kiloshora = 0 self.wids['e_kilosproducidos'].set_text("%s m²" % ( utils.float2str(metrosproducidos))) if kilosconsumidos_partidas_completas != kilosconsumidos: self.wids['e_kilosgranza'].set_text("%s kg ~ %s kg" % ( utils.float2str(kilosconsumidos_partidas_completas), utils.float2str(kilosconsumidos))) else: self.wids['e_kilosgranza'].set_text("%s kg" % ( utils.float2str(kilosconsumidos))) self.wids['e_kiloshora'].set_text("%s m²/h" % ( utils.float2str(e_kiloshora))) else: self.wids['label7'].set_text('Producido:') self.wids['label8'].set_text('Consumido:') self.wids['label9'].set_text('Producción combinada a la hora:') try: e_kiloshora = (kilosproducidos/float(tiempototaltotal.hours)) metros_hora = (metrosproducidos/float(tiempototaltotal.hours)) except ZeroDivisionError: self.logger.warning("consulta_productividad.py::" "rellenar_tabla -> tiempototaltotal = 0") e_kiloshora = 0 metros_hora = 0 self.wids['e_kilosproducidos'].set_text("%s m²; %s kg" % ( utils.float2str(metrosproducidos), utils.float2str(kilosproducidos))) self.wids['e_kilosgranza'].set_text( "%s kg fibra; %s kg granza" % (utils.float2str( kilosconsumidos), utils.float2str(kilosgranza))) self.wids['e_kiloshora'].set_text("%s m²/h; %s kg/h" % ( utils.float2str(metros_hora), utils.float2str(e_kiloshora))) # Fin campos especiales de "Sólo balas" self.wids['curva'].set_range(0, len(vector), 0, 100) self.wids['curva'].set_vector(vector) self.wids['curva'].set_curve_type(gtk.CURVE_TYPE_SPLINE) # self.wids['curva'].set_curve_type(gtk.CURVE_TYPE_LINEAR) self.wids['pb'].set_fraction(max(min(total, 100), 0) / 100.0) else: self.wids['curva'].set_range(0, 2, 0, 100) self.wids['curva'].set_vector((0, 0)) self.wids['pb'].set_fraction(1 / 100.0) self.wids['e_kilosproducidos'].set_text('') self.wids['e_kilosgranza'].set_text('') self.wids['e_kiloshora'].set_text('') self.wids['e_total'].set_text("%s %%" % (utils.float2str(total))) try: personashora = sum(personashora)/len(personashora) except ZeroDivisionError: personashora = 0 try: e_personasturno = float(e_personasturno) / len(partes) except ZeroDivisionError: e_personasturno = 0 self.wids['e_personasturno'].set_text("%s (%s personas/h)" % ( utils.float2str(e_personasturno), utils.float2str(personashora))) self.wids['e_tiempo_faltante'].set_text( self.tiempo_faltante and (str_horas(self.tiempo_faltante) + " h") or "") self.wids['e_tiempo_partes'].set_text( str_horas(tiempototaltotal) + " h")