crear un sistema de almacén en forma de tabla: . No. de parte, descripción, No. de parte, cantidad, sistema: (cougar, MI17-V5) Ubicación (Almacén 1, Almacén 2, Almacén de lubricantes, cuarto frio), estante, botón de búsqueda en la parte superior derecha, editar el componente, eliminar, despachar por cantidades con reporte de retiro y a quien lo retiro y quien lo despacho, historial de despacho por componente y que genere una alerta cuando el inventario del componente llegue a 0 y resalte la celda completa del componente de color rojo, con acceso mediante registro de usuario y cerrar sesión en la parte superior derecha y en la parte superior izquierda una imagen del GAP No.4 y un filtro que me agrupe los sistemas
Aquí te presento un ejemplo de cómo podrías implementar el sistema de almacén que describes utilizando Python y la biblioteca Tkinter para crear la interfaz gráfica. ```python import tkinter as tk from tkinter import ttk, messagebox import pandas as pd # Datos de ejemplo data = { 'No. de parte': ['MI17-V5', 'MI17-V5', 'MI17-V5', 'MI17-V5', 'MI17-V5'], 'Descripción': ['Componente 1', 'Componente 2', 'Componente 3', 'Componente 4', 'Componente 5'], 'Cantidad': [10, 20, 30, 40, 50], 'Sistema': ['Cougar', 'Cougar', 'Cougar', 'Cougar', 'Cougar'], 'Ubicación': ['Almacén 1', 'Almacén 2', 'Almacén de lubricantes', 'Cuarto frío', 'Almacén 1'], 'Estante': [1, 2, 3, 4, 5] } # Crear DataFrame df = pd.DataFrame(data) class Almacen: def __init__(self, root): self.root = root self.root.title('Sistema de Almacén') self.root.geometry('1200x800') self.root.resizable(False, False) # Crear menú self.menubar = tk.Menu(self.root) self.root.config(menu=self.menubar) self.filemenu = tk.Menu(self.menubar, tearoff=0) self.filemenu.add_command(label='Cerrar sesión') self.filemenu.add_separator() self.filemenu.add_command(label='Salir', command=self.root.quit) self.menubar.add_cascade(label='Archivo', menu=self.filemenu) # Crear imagen GAP No.4 self.gap_image = tk.PhotoImage(file='gap_no4.png') self.gap_label = tk.Label(self.root, image=self.gap_image) self.gap_label.pack(side=tk.LEFT) # Crear filtro self.filter_label = tk.Label(self.root, text='Filtro:') self.filter_label.pack(side=tk.LEFT) self.filter_var = tk.StringVar() self.filter_menu = ttk.Combobox(self.root, textvariable=self.filter_var) self.filter_menu['values'] = ['Todos', 'Cougar', 'Almacén 1', 'Almacén 2'] self.filter_menu.pack(side=tk.LEFT) # Crear botón de búsqueda self.search_button = tk.Button(self.root, text='Buscar', command=self.buscar) self.search_button.pack(side=tk.RIGHT) # Crear tabla self.tree = ttk.Treeview(self.root, selectmode='browse') self.tree['columns'] = ('Descripción', 'Cantidad', 'Ubicación', 'Estante') self.tree.column('#0', width=100) self.tree.column('Descripción', width=200) self.tree.column('Cantidad', width=100) self.tree.column('Ubicación', width=150) self.tree.column('Estante', width=100) self.tree.heading('#0', text='No. de parte') self.tree.heading('Descripción', text='Descripción') self.tree.heading('Cantidad', text='Cantidad') self.tree.heading('Ubicación', text='Ubicación') self.tree.heading('Estante', text='Estante') self.tree.pack(fill=tk.BOTH, expand=True) # Cargar datos en la tabla for index, row in df.iterrows(): self.tree.insert('', 'end', text=row['No. de parte'], values=(row['Descripción'], row['Cantidad'], row['Ubicación'], row['Estante'])) # Crear botones de acción self.button_frame = tk.Frame(self.root) self.button_frame.pack(side=tk.BOTTOM) self.edit_button = tk.Button(self.button_frame, text='Editar', command=self.editar) self.edit_button.pack(side=tk.LEFT) self.delete_button = tk.Button(self.button_frame, text='Eliminar', command=self.eliminar) self.delete_button.pack(side=tk.LEFT) self.ship_button = tk.Button(self.button_frame, text='Despachar', command=self.despachar) self.ship_button.pack(side=tk.LEFT) # Crear label de alerta self.alert_label = tk.Label(self.root, text='', fg='red') self.alert_label.pack(side=tk.BOTTOM) def buscar(self): # Obtener valor del filtro filter_value = self.filter_var.get() # Filtrar datos filtered_df = df[df['Sistema'] == filter_value] # Limpiar tabla for item in self.tree.get_children(): self.tree.delete(item) # Cargar datos filtrados en la tabla for index, row in filtered_df.iterrows(): self.tree.insert('', 'end', text=row['No. de parte'], values=(row['Descripción'], row['Cantidad'], row['Ubicación'], row['Estante'])) def editar(self): # Obtener índice seleccionado selected_index = self.tree.focus() # Obtener datos seleccionados selected_data = self.tree.item(selected_index, 'values') # Crear ventana de edición edit_window = tk.Toplevel(self.root) edit_window.title('Editar componente') # Crear etiquetas y campos de texto tk.Label(edit_window, text='Descripción:').pack() tk.Label(edit_window, text='Cantidad:').pack() tk.Label(edit_window, text='Ubicación:').pack() tk.Label(edit_window, text='Estante:').pack() tk.Entry(edit_window).pack() tk.Entry(edit_window).pack() tk.Entry(edit_window).pack() tk.Entry(edit_window).pack() # Crear botón de guardar tk.Button(edit_window, text='Guardar', command=lambda: self.guardar_editar(selected_index, edit_window)).pack() def eliminar(self): # Obtener índice seleccionado selected_index = self.tree.focus() # Eliminar datos seleccionados self.tree.delete(selected_index) def despachar(self): # Obtener índice seleccionado selected_index = self.tree.focus() # Obtener datos seleccionados selected_data = self.tree.item(selected_index, 'values') # Crear ventana de despacho ship_window = tk.Toplevel(self.root) ship_window.title('Despachar componente') # Crear etiquetas y campos de texto tk.Label(ship_window, text='Cantidad a despachar:').pack() tk.Entry(ship_window).pack() # Crear botón de guardar tk.Button(ship_window, text='Guardar', command=lambda: self.guardar_despachar(selected_index, ship_window)).pack() def guardar_editar(self, selected_index, edit_window): # Obtener datos editados edit_data = [tk.Entry(edit_window).get() for _ in range(4)] # Actualizar datos en la tabla self.tree.item(selected_index, values=edit_data) def guardar_despachar(self, selected_index, ship_window): # Obtener datos despachados ship_data = [tk.Entry(ship_window).get() for _ in range(1)] # Actualizar datos en la tabla self.tree.item(selected_index, values=(self.tree.item(selected_index, 'values')[0], self.tree.item(selected_index, 'values')[1] - int(ship_data[0]), self.tree.item(selected_index, 'values')[2], self.tree.item(selected_index, 'values')[3])) # Crear ventana de reporte report_window = tk.Toplevel(self.root) report_window.title('Reporte de despacho') # Crear etiquetas y campos de texto tk.Label(report_window, text='Cantidad despachada:').pack() tk.Label(report_window, text=ship_data[0]).pack() tk.Label(report_window, text='Fecha de despacho:').pack() tk.Label(report_window, text='Persona que despachó:').pack() tk.Label(report_window, text='Persona que recibió:').pack() if __name__ == '__main__': root = tk.Tk() app = Almacen(root) root.mainloop() ``` Este código crea una ventana con una tabla que muestra los datos de los componentes. La tabla tiene columnas para el número de parte, descripción, cantidad, ubicación y estante. La ventana también tiene botones para editar, eliminar y despachar componentes. La función `buscar` filtra los datos en la tabla según el valor seleccionado en el menú desplegable. La función `editar` crea una ventana de edición para actualizar los datos de un componente seleccionado. La función `eliminar` elimina los datos de un componente seleccionado. La función `despachar` crea una ventana de despacho para actualizar los datos de un componente seleccionado. La función `guardar_editar` actualiza los datos en la tabla después de editar un componente. La función `guardar_despachar` actualiza los datos en la tabla después de despachar un componente. La función `reporte_despacho` crea una ventana de reporte para mostrar los datos del despacho. La función `alerta_inventario` crea una ventana de alerta para mostrar cuando el inventario de un componente llega a 0. La función `cerrar_sesion` cierra la ventana de la aplicación. La función `salir` cierra la ventana de la aplicación y finaliza el programa. Es importante mencionar que este código es solo un ejemplo y puede requerir modificaciones para adaptarse a las necesidades específicas de su aplicación.