Desarrollo de un Sistema de Gestión de Restaurantes en Python

Enviado por Chuletator online y clasificado en Informática y Telecomunicaciones

Escrito el en con un tamaño de 21,4 KB

Este documento detalla la implementación de un sistema básico de gestión para un restaurante, desarrollado en Python. El sistema permite a los usuarios interactuar con diversas funcionalidades, como la visualización del estado de las mesas, la realización de reservas, la gestión de pedidos de la carta y el procesamiento de pagos, incluyendo la aplicación de descuentos y el cálculo de impuestos. Se utilizan estructuras de datos simples y funciones para modularizar las diferentes funcionalidades, ofreciendo una solución práctica para la administración de un establecimiento.

Estructura del Código y Variables Globales

El programa inicia con la importación de las librerías necesarias y la definición de las estructuras de datos globales que almacenarán la información del restaurante y las reservas activas.

Importaciones y Configuración Inicial

Las siguientes librerías son esenciales para el funcionamiento del sistema:

import os
import time
import numpy
  • os: Se utiliza para interactuar con el sistema operativo, permitiendo, por ejemplo, limpiar la consola (os.system('clear')) para una mejor experiencia de usuario.
  • time: Proporciona funciones para pausar la ejecución del programa por un tiempo determinado (time.sleep()), lo que es útil para mostrar mensajes al usuario antes de continuar.
  • numpy: Empleada para crear y manipular una matriz que representa el estado de las mesas del restaurante, facilitando la gestión de su disponibilidad.

Representación del Restaurante y Listas de Datos

La disposición de las mesas se modela eficientemente con una matriz de NumPy, y la información de las reservas se gestiona mediante listas paralelas para mantener la coherencia de los datos.

restaurant = numpy.zeros((3, 3), int)

Esta línea inicializa una matriz de 3x3 con valores enteros. Cada celda de la matriz representa una mesa: un valor de 0 indica que la mesa está disponible, mientras que 1 significa que está reservada.

Listas para la Gestión de Reservas

Se utilizan las siguientes listas globales para almacenar de forma organizada la información detallada de cada reserva:

  • lista_ruts: Almacena los R.U.T. (Rol Único Tributario) de los clientes que han realizado una reserva.
  • lista_nombres: Guarda los nombres completos de los clientes.
  • lista_correos: Contiene las direcciones de correo electrónico de los clientes.
  • lista_filas: Registra el índice de la fila de la mesa que ha sido reservada.
  • lista_columnas: Registra el índice de la columna de la mesa que ha sido reservada.
  • lista_totales: Almacena el total acumulado de los pedidos realizados para cada reserva, inicializado en 0.
lista_ruts = []
lista_nombres = []
lista_correos = []
lista_filas = []
lista_columnas = []
lista_totales = []

Funciones Principales del Sistema

El sistema se estructura en torno a un conjunto de funciones que manejan la interacción con el usuario, la validación de entradas y la lógica de negocio del restaurante.

mostrar_menu(): Presentación del Menú Principal

Esta función es responsable de limpiar la consola y mostrar las opciones principales disponibles para el usuario, facilitando la navegación por el sistema.

def mostrar_menu():
    os.system('clear')
    print("""MENÚ PRINCIPAL
    1. Ver restaurante
    2. Reservar
    3. Ver carta
    4. Pagar
    5. Cancelar reserva
    6. Salir""")

validar_opcion(): Validación de la Entrada del Menú Principal

Asegura que el usuario ingrese una opción numérica válida y dentro del rango permitido para el menú principal, manejando posibles errores de entrada.

def validar_opcion():
    while True:
        try:
            opc = int(input("Ingrese opción: "))
            if opc in (1, 2, 3, 4, 5, 6):
                return opc
            else:
                print("Error: Opción incorrecta. Por favor, ingrese un número entre 1 y 6.")
        except ValueError:
            print("Error: Debe ingresar un número entero.")

ver_restaurant(): Visualización del Estado de las Mesas

Esta función limpia la consola y presenta visualmente el estado actual de las mesas del restaurante. Indica la capacidad de cada fila de mesas y si cada mesa individual está disponible (0) o reservada (1).

def ver_restaurant():
    os.system('clear')
    print("\tVER RESTAURANTE\n")
    contador = 1
    for x in range(3):
        print(f"Mesas para {(x+1)*2} personas: ", end=" ")
        for y in range(3):
            print(f"Mesa {contador}: {restaurant[x][y]} ", end=" ")
            contador += 1
        print("\n")
    time.sleep(3)

Funciones de Validación de Datos del Cliente

Estas funciones son cruciales para solicitar y validar la información personal del cliente durante el proceso de reserva, garantizando la integridad de los datos.

validar_rut(): Validación del R.U.T.

Solicita el R.U.T. del cliente y verifica que sea un número entero dentro de un rango válido, sin puntos ni dígito verificador.

def validar_rut():
    while True:
        try:
            rut = int(input("Ingrese RUT (sin puntos ni dígito verificador): "))
            if 1000000 <= rut <= 99999999:
                return rut
            else:
                print("Error: El RUT debe estar entre 1.000.000 y 99.999.999.")
        except ValueError:
            print("Error: Debe ingresar un número entero.")

validar_nombre(): Validación del Nombre del Cliente

Pide el nombre del cliente y comprueba que tenga al menos 3 letras. Se permite el uso de espacios, pero la validación de caracteres alfabéticos se realiza sobre el nombre sin espacios.

def validar_nombre():
    while True:
        nombre = input("Ingrese nombre: ")
        if len(nombre.strip()) >= 3 and nombre.replace(' ', '').isalpha():
            return nombre
        else:
            print("Error: El nombre debe tener al menos 3 letras y contener solo caracteres alfabéticos (se permiten espacios).")

validar_correo(): Validación del Correo Electrónico

Solicita la dirección de correo electrónico y verifica que contenga el símbolo '@', un requisito básico para un formato de correo válido.

def validar_correo():
    while True:
        correo = input("Ingrese correo: ")
        if "@" in correo:
            return correo
        else:
            print("Error: Correo electrónico incorrecto. Debe contener '@'.")

validar_cantidad(): Validación de la Cantidad de Personas

Asegura que la cantidad de personas para la reserva esté dentro del rango de 1 a 6, acorde a las capacidades de las mesas.

def validar_cantidad():
    while True:
        try:
            cantidad = int(input("Ingrese cantidad de personas (1-6): "))
            if 1 <= cantidad <= 6:
                return cantidad
            else:
                print("Error: La cantidad de personas debe estar entre 1 y 6.")
        except ValueError:
            print("Error: Debe ingresar un número entero.")

mesas_disponibles(p_cantidad): Búsqueda de Mesas Adecuadas

Esta función identifica y retorna una lista de mesas disponibles que son adecuadas para la cantidad de personas especificada. La lógica de asignación de mesas es la siguiente:

  • Grupos de 1-2 personas pueden ocupar cualquier mesa disponible (de 2, 4 o 6 personas).
  • Grupos de 3-4 personas pueden ocupar mesas disponibles en las filas 1 o 2 (mesas de 4 o 6 personas).
  • Grupos de 5-6 personas solo pueden ocupar mesas disponibles en la fila 2 (mesas de 6 personas).
def mesas_disponibles(p_cantidad):
    contador = 1
    lista_mesas = []
    for x in range(3): # Itera sobre las filas (0, 1, 2)
        for y in range(3): # Itera sobre las columnas (0, 1, 2)
            if restaurant[x][y] == 0: # Si la mesa está disponible
                if p_cantidad <= 2: # Para 1 o 2 personas, cualquier mesa disponible es válida
                    lista_mesas.append(contador)
                elif 3 <= p_cantidad <= 4 and x in (1, 2): # Para 3 o 4 personas, mesas de la fila 1 o 2
                    lista_mesas.append(contador)
                elif 5 <= p_cantidad <= 6 and x == 2: # Para 5 o 6 personas, solo mesas de la fila 2
                    lista_mesas.append(contador)
            contador += 1
    return lista_mesas

validar_mesa(p_mesas): Validación de la Selección de Mesa

Asegura que el usuario seleccione un número de mesa válido de la lista de mesas previamente identificadas como disponibles.

def validar_mesa(p_mesas):
    while True:
        try:
            mesa = int(input("Ingrese número de mesa: "))
            if mesa in p_mesas:
                return mesa
            else:
                print("Error: Número de mesa no disponible o inválido. Por favor, elija una de las opciones mostradas.")
        except ValueError:
            print("Error: Debe ingresar un número entero.")

reservar(): Proceso de Reserva de Mesa

Esta función coordina todo el proceso de reserva, desde la recopilación y validación de los datos del cliente hasta la asignación final de una mesa y el registro de la reserva en las listas globales.

def reservar():
    os.system('clear')
    print("RESERVAR MESA\n")
    rut = validar_rut()
    if rut in lista_ruts:
        print("Advertencia: Ya existe una reserva activa para el RUT indicado.")
        time.sleep(3)
        return

    nombre = validar_nombre()
    correo = validar_correo()
    ver_restaurant()
    cant_personas = validar_cantidad()
    lista_mesas = mesas_disponibles(cant_personas)

    if len(lista_mesas) == 0:
        print("Información: No existen mesas disponibles para la cantidad de personas solicitada en este momento.")
        time.sleep(3)
        return
    
    print("Mesas disponibles:", lista_mesas)
    mesa = validar_mesa(lista_mesas)
    
    contador = 1
    for x in range(3):
        for y in range(3):
            if contador == mesa:
                restaurant[x][y] = 1 # Marca la mesa como reservada en la matriz
                lista_ruts.append(rut)
                lista_nombres.append(nombre)
                lista_correos.append(correo)
                lista_filas.append(x)
                lista_columnas.append(y)
                lista_totales.append(0) # Inicializa el total de la cuenta para esta reserva en 0
                print("Mesa reservada con éxito.")
                time.sleep(3)
                return # Sale de la función después de completar la reserva
            contador += 1

Funciones para la Gestión de la Carta y Pedidos

Estas funciones permiten a los clientes con reserva explorar la carta del restaurante, seleccionar productos y acumular el total de su pedido.

validar_opcion_menu(): Validación de Opciones del Menú de Carta

Similar a la función validar_opcion(), pero adaptada para las opciones específicas del menú de la carta (categorías de productos y acciones de pedido/cancelación).

def validar_opcion_menu():
    while True:
        try:
            opc = int(input("Ingrese opción: "))
            if opc in (1, 2, 3, 4, 5):
                return opc
            else:
                print("Error: Opción incorrecta. Por favor, ingrese un número entre 1 y 5.")
        except ValueError:
            print("Error: Debe ingresar un número entero.")

validar_opciones_carta(): Validación de Opciones de Productos

Valida la selección de un producto específico dentro de una categoría de la carta (bebestibles, platos de fondo, postres), asegurando que la opción sea numérica y esté dentro del rango permitido.

def validar_opciones_carta():
    while True:
        try:
            opc = int(input("Ingrese opción: "))
            if opc in (1, 2, 3):
                return opc
            else:
                print("Error: Opción incorrecta. Por favor, ingrese un número entre 1 y 3.")
        except ValueError:
            print("Error: Debe ingresar un número entero.")

validar_cantidad_prod(): Validación de la Cantidad de Productos

Asegura que la cantidad de productos a pedir sea un número entero no negativo, evitando entradas inválidas.

def validar_cantidad_prod():
    while True:
        try:
            cantidad = int(input("Ingrese cantidad: "))
            if cantidad >= 0:
                return cantidad
            else:
                print("Error: La cantidad debe ser 0 o un valor positivo.")
        except ValueError:
            print("Error: Debe ingresar un número entero.")

ver_carta(): Interfaz para Realizar Pedidos

Esta función permite a un cliente con una reserva activa ver la carta del restaurante, seleccionar productos de diferentes categorías (bebestibles, platos de fondo, postres) y acumular el total de su pedido. El cliente puede añadir múltiples productos antes de confirmar o cancelar el pedido.

def ver_carta():
    os.system('clear')
    rut = validar_rut()
    if rut not in lista_ruts:
        print("Información: No existe reserva para el RUT indicado. Por favor, realice una reserva primero.")
        time.sleep(3)
        return

    posicion = lista_ruts.index(rut)
    acumulador = 0
    while True:
        os.system('clear')
        print("""CARTA DEL RESTAURANTE
        1. BEBESTIBLES
        2. PLATOS DE FONDO
        3. POSTRES
        4. PEDIR
        5. CANCELAR""")
        opcion = validar_opcion_menu()

        if opcion == 1:
            print("""\nBEBESTIBLES
            1. Limonada $2.500
            2. Bebida $1.500
            3. Jugo $2.000""")
            opcion_bebestible = validar_opciones_carta()
            cantidad = validar_cantidad_prod()
            if opcion_bebestible == 1:
                acumulador += 2500 * cantidad
            elif opcion_bebestible == 2:
                acumulador += 1500 * cantidad
            else:
                acumulador += 2000 * cantidad
        elif opcion == 2:
            print("""\nPLATOS DE FONDO
            1. Consomé $3.000
            2. Pollo con Papas Fritas $4.500
            3. Ensalada $2.000""")
            opcion_plato = validar_opciones_carta()
            cantidad = validar_cantidad_prod()
            if opcion_plato == 1:
                acumulador += 3000 * cantidad
            elif opcion_plato == 2:
                acumulador += 4500 * cantidad
            else:
                acumulador += 2000 * cantidad
        elif opcion == 3:
            print("""\nPOSTRES
            1. Helado $2.000
            2. Tiramisú $2.500
            3. Jalea $1.000""")
            opcion_postre = validar_opciones_carta()
            cantidad = validar_cantidad_prod()
            if opcion_postre == 1:
                acumulador += 2000 * cantidad
            elif opcion_postre == 2:
                acumulador += 2500 * cantidad
            else:
                acumulador += 1000 * cantidad
        elif opcion == 4:
            lista_totales[posicion] += acumulador
            print("Pedido realizado con éxito. El total se ha añadido a su cuenta.")
            break
        else:
            print("Pedido cancelado de la carta. No se han añadido productos a su cuenta.")
            break
    time.sleep(3)

Funciones de Pago y Cancelación de Reservas

Estas funciones gestionan el cierre de la cuenta del cliente y la liberación de las mesas, completando el ciclo de vida de una reserva.

validar_descuento(): Validación del Descuento

Solicita un valor de descuento a aplicar y asegura que sea un número entero no negativo, evitando entradas erróneas.

def validar_descuento():
    while True:
        try:
            desc = int(input("Ingrese descuento (valor entero): "))
            if desc >= 0:
                return desc
            else:
                print("Error: El descuento debe ser 0 o un valor positivo.")
        except ValueError:
            print("Error: Debe ingresar un número entero.")

pagar(): Procesamiento del Pago de la Cuenta

Permite a un cliente con reserva pagar su cuenta. La función calcula el subtotal, el IVA, el total antes del descuento y el total final, presentando una boleta detallada. Posteriormente, libera la mesa y elimina todos los datos asociados a la reserva.

def pagar():
    os.system('clear')
    print("PAGAR CUENTA\n")
    rut = validar_rut()
    if rut in lista_ruts:
        posicion = lista_ruts.index(rut)
        descuento = validar_descuento()
        subtotal = lista_totales[posicion]
        iva = round(0.19 * subtotal)
        total_sin_descuento = round(1.19 * subtotal)
        total_final = total_sin_descuento - descuento

        print(f"""BOLETA
        -----------------------------------
        SUBTOTAL:    ${subtotal:,.0f}
        IVA (19%):   ${iva:,.0f}
        TOTAL:       ${total_sin_descuento:,.0f}
        DESCUENTO:   ${descuento:,.0f}
        -----------------------------------
        TOTAL FINAL: ${total_final:,.0f}""")

        fila = lista_filas[posicion]
        columna = lista_columnas[posicion]
        restaurant[fila][columna] = 0 # Libera la mesa en la matriz
        
        # Elimina la reserva de todas las listas paralelas
        lista_ruts.pop(posicion)
        lista_nombres.pop(posicion)
        lista_correos.pop(posicion)
        lista_filas.pop(posicion)
        lista_columnas.pop(posicion)
        lista_totales.pop(posicion)
        print("\nPago realizado con éxito. ¡Gracias por su visita!")
    else:
        print("Información: El RUT indicado no tiene reserva activa para procesar el pago.")
    time.sleep(5)

cancelar_reserva(): Anulación de una Reserva Existente

Permite a un cliente cancelar su reserva. La función libera la mesa correspondiente en la matriz del restaurante y elimina todos los datos asociados a la reserva de las listas globales.

def cancelar_reserva():
    os.system('clear')
    print("CANCELAR RESERVA\n")
    rut = validar_rut()
    if rut in lista_ruts:
        posicion = lista_ruts.index(rut)
        fila = lista_filas[posicion]
        columna = lista_columnas[posicion]
        restaurant[fila][columna] = 0 # Libera la mesa en la matriz
        
        # Elimina la reserva de todas las listas paralelas
        lista_ruts.pop(posicion)
        lista_nombres.pop(posicion)
        lista_correos.pop(posicion)
        lista_filas.pop(posicion)
        lista_columnas.pop(posicion)
        lista_totales.pop(posicion)
        print("\nReserva cancelada con éxito.")
    else:
        print("Información: El RUT indicado no tiene reserva activa para cancelar.")
    time.sleep(5)

Consideraciones Adicionales y Mejoras Potenciales

Este sistema proporciona una base sólida para la gestión de un restaurante. Para futuras mejoras y una mayor robustez, se podrían considerar las siguientes extensiones:

  • Persistencia de Datos: Implementar mecanismos para guardar y cargar los datos de reservas y el estado de las mesas en archivos (por ejemplo, CSV, JSON) o una base de datos, para que la información no se pierda al cerrar el programa.
  • Interfaz Gráfica de Usuario (GUI): Desarrollar una interfaz más intuitiva y amigable utilizando librerías como Tkinter, PyQt o Kivy, mejorando significativamente la experiencia del usuario.
  • Gestión de Errores Mejorada: Implementar un manejo de excepciones más granular y específico, proporcionando mensajes de error más descriptivos y acciones de recuperación.
  • Optimización de Búsquedas: Para escenarios con un gran volumen de datos, considerar el uso de estructuras de datos más eficientes que las listas paralelas (como diccionarios o clases de objetos) para mejorar el rendimiento de las búsquedas y manipulaciones.
  • Detalle de Pedidos: Almacenar los detalles específicos de cada pedido (qué productos y en qué cantidad) en lugar de solo el total acumulado, lo que permitiría generar facturas más detalladas.
  • Autenticación de Usuarios: Añadir un sistema de autenticación para el personal del restaurante, con diferentes niveles de acceso según el rol (e.g., mesero, administrador).
  • Validación de RUT Completa: Implementar la validación del dígito verificador del RUT para una verificación más exhaustiva de la identidad del cliente.

Entradas relacionadas: