import ipywidgets as widgets from IPython.display import display, clear_output import pandas as pd import os

EXPORTAR A EXCEL BBDD AUTOMÁTICO

EXCEL_FILE = 'inventario_minimarket.xlsx'

--- ESTILO GLOBAL PARA FORZAR CALIBRI Y DISEÑO SOBRIO ---

estilo_global = widgets.HTML( value=""" """ )

TITULO (Fuente Calibri)

titulo = widgets.HTML( value="

INVENTARIO PRODUCTOS MINIMARKET

" "

FORMULARIO DE REGISTRO E INTERFAZ DE PRODUCTOS

" )

--- ESTRUCTURAS DE DATOS ---

productos = []

--- WIDGETS DE INGRESO DE DATOS ---

nombre_producto = widgets.Text(placeholder='Ej. Leche', description='Producto:', layout=widgets.Layout(width='180px')) categoria_producto = widgets.Dropdown(options=['Abarrotes', 'Lácteos', 'Bebidas', 'Limpieza', 'Frutas y Verduras', 'Otros'], value='Abarrotes', description='Categoría:', layout=widgets.Layout(width='180px')) costo_unitario_widget = widgets.FloatText(value=0.0, description='Costo Unit ($):', layout=widgets.Layout(width='150px')) precio_venta_widget = widgets.FloatText(value=0.0, description='P. Venta ($):', layout=widgets.Layout(width='150px')) stock_minimo_widget = widgets.BoundedIntText(value=5, min=0, max=1000, description='Stock Mín:', layout=widgets.Layout(width='130px')) stock_actual_widget = widgets.BoundedIntText(value=1, min=0, max=10000, step=1, description='Stock Act:', layout=widgets.Layout(width='130px'))

--- BOTONES PRINCIPALES DE ACCIÓN ---

boton_registrar = widgets.Button(description='Registrar', icon='plus-circle') boton_registrar.add_class('btn-sobrio-principal')

boton_mostrar = widgets.Button(description='Mostrar', icon='list') boton_mostrar.add_class('btn-sobrio-secundario')

boton_limpiar = widgets.Button(description='Limpiar', icon='eraser') boton_limpiar.add_class('btn-sobrio-limpiar')

boton_vaciar = widgets.Button(description='Vaciar', icon='trash') boton_vaciar.add_class('btn-sobrio-peligro')

output_area = widgets.Output(layout={'border': '1px solid #CCC', 'padding': '10px', 'margin_top': '10px'})

--- CARGAR RESPALDO DE EXCEL SI EXISTE AL INICIAR ---

if os.path.exists(EXCEL_FILE): try: df_previo = pd.read_excel(EXCEL_FILE) column_mapping = { 'Nombre': 'producto', 'producto': 'producto', 'Categoría': 'categoria', 'categoria': 'categoria', 'Costo Unitario': 'costo_unitario', 'costo_unitario': 'costo_unitario', 'Precio Venta': 'precio_venta', 'precio_venta': 'precio_venta', 'Stock Mínimo': 'stock_minimo', 'stock_minimo': 'stock_minimo', 'Cantidad': 'stock_actual', 'stock_actual': 'stock_actual', 'Unidades Vendidas': 'unidades_vendidas', 'unidades_vendidas': 'unidades_vendidas' } df_previo = df_previo.rename(columns=column_mapping)

    for col in ['costo_unitario', 'precio_venta', 'stock_minimo', 'stock_actual', 'unidades_vendidas']:
        if col not in df_previo.columns:
            df_previo[col] = 0

    productos = df_previo.to_dict('records')
except Exception:
    pass

--- FUNCIONES DE RESPALDO Y EXPORTACIÓN AUTOMÁTICA ---

def guardar_en_excel(): try: tabla_productos = pd.DataFrame(productos) columnas_ordenadas = [ 'producto', 'categoria', 'costo_unitario', 'precio_venta', 'stock_minimo', 'stock_actual', 'unidades_vendidas' ] for col in columnas_ordenadas: if col not in tabla_productos.columns: tabla_productos[col] = 0 tabla_productos = tabla_productos[columnas_ordenadas] tabla_productos.to_excel(EXCEL_FILE, index=False) except Exception: pass

--- FUNCIONES DE EVENTOS ---

def limpiar_formulario(b): nombre_producto.value = "" categoria_producto.value = "Abarrotes" costo_unitario_widget.value = 0.0 precio_venta_widget.value = 0.0 stock_minimo_widget.value = 5 stock_actual_widget.value = 1 with output_area: clear_output() print("Formulario de registro limpio.")

def registrar_producto(b): nombre = nombre_producto.value.strip() categoria = categoria_producto.value costo_unit = costo_unitario_widget.value precio_venta = precio_venta_widget.value stock_min = stock_minimo_widget.value stock_act = stock_actual_widget.value

with output_area:
    clear_output()
    if not nombre:
        print("⚠️ Error: El nombre del producto no puede estar vacío.")
        return
    if stock_act < 0:
        print("⚠️ Error: El stock actual no puede ser negativo.")
        return
    if costo_unit < 0 or precio_venta < 0:
        print("⚠️ Error: Los valores monetarios no pueden ser negativos.")
        return

    duplicado = False
    for p in productos:
        if p["producto"].lower() == nombre.lower():
            p["stock_actual"] += stock_act
            p["costo_unitario"] = costo_unit
            p["precio_venta"] = precio_venta
            p["stock_minimo"] = stock_min
            duplicado = True
            print(f"🔄 El producto '{nombre}' ya existía. Se actualizó su stock y valores.")
            break

    if not duplicado:
        nuevo_producto = {
            "producto": nombre,
            "categoria": categoria,
            "costo_unitario": costo_unit,
            "precio_venta": precio_venta,
            "stock_minimo": stock_min,
            "stock_actual": stock_act,
            "unidades_vendidas": 0
        }
        productos.append(nuevo_producto)
        print(f"✅ Producto registrado correctamente: {nombre}")

    guardar_en_excel()
    print("💾 Base de datos 'inventario_minimarket.xlsx' actualizada automáticamente.")

def mostrar_productos(b): with output_area: clear_output() if not productos: print("ℹ| No hay productos registrados en la lista.") return print("--- LISTA DE PRODUCTOS REGISTRADOS ---") for i, prod in enumerate(productos, 1): alerta_stock = "⚠️ STOCK BAJO" if prod['stock_actual'] <= prod['stock_minimo'] else "" print(f"{i}. {prod['producto']} | Cat: {prod['categoria']} | Costo Unit: ${prod['costo_unitario']:.2f} | " f"P. Venta: ${prod['precio_venta']:.2f} | Stock Min: {prod['stock_minimo']} | " f"Stock Act: {prod['stock_actual']} uds | Vendidas: {prod.get('unidades_vendidas', 0)} uds {alerta_stock}")

def vaciar_productos(b): global productos with output_area: clear_output() if len(productos) > 0: productos.clear() if os.path.exists(EXCEL_FILE): try: os.remove(EXCEL_FILE) except Exception: pass print("🗑️ Todos los productos fueron eliminados de la memoria y del archivo Excel.") else: print("La lista ya está vacía.")

--- CONECTAR BOTONES CON SUS RESPECTIVAS FUNCIONES ---

boton_registrar.on_click(registrar_producto) boton_mostrar.on_click(mostrar_productos) boton_limpiar.on_click(limpiar_formulario) boton_vaciar.on_click(vaciar_productos)

--- RENDERIZADO DE LA INTERFAZ INTEGRAL EN HORIZONTAL ---

formulario_entrada_horizontal = widgets.HBox([ nombre_producto, categoria_producto, costo_unitario_widget, precio_venta_widget, stock_minimo_widget, stock_actual_widget ], layout=widgets.Layout(flex_flow='row wrap', gap='10px', margin='10px 0px'))

botones_accion = widgets.HBox([ boton_registrar, boton_mostrar, boton_limpiar, boton_vaciar ], layout=widgets.Layout(gap='10px', margin='15px 0px'))

ui_final = widgets.VBox([ estilo_global, titulo, widgets.HTML("

Formulario de Producto

"), formulario_entrada_horizontal, widgets.HTML('
'), botones_accion, output_area ])

display(ui_final)

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support