lunes, 11 de noviembre de 2024

Ejercicio de caja registradora en Python

Este ejercicio consta de una recreación de una caja registradora totalmente funcional con una gran variedad de funcionalidades que la hacen asemejarse a una real.


Entre las funcionalidades de este programa encontramos las siguientes:

  • Gestión de empleados por parte de un archivo externo (a modo de pequeña base de datos).
  • Inserción de 100 productos reales con sus datos asociados (nombre, precio, identificador) en un archivo externo (a modo de pequeña base de datos).
  • Funcionalidades relacionadas a la naturaleza de la aplicación: insertar productos, añadir múltiples productos simultáneamente, añadir productos con descuento, retirar productos, añadir descuentos al total...
  • Además, el programa permite generar un ticket de compra en formato .txt en el que se muestran los productos adquiridos.
El código es:

import random

import datetime

import csv

# Cargar productos desde archivo CSV
productos = {}
trabajadores = {}

with open('productos.csv', mode='r') as archivo:
    leerfilas = csv.DictReader(archivo)
    for fila in leerfilas:
        productos[fila['id']] = {'nombre': fila['nombre'], 'precio': float(fila['precio'])}
with open('trabajadores.csv', mode='r') as archivo:
    leerfilas = csv.DictReader(archivo)
    for fila in leerfilas:
        trabajadores[fila["id"]] = {"nombre": fila["nombre"], "pw": fila["pw"]}        

# Función para generar el ticket en un archivo de texto
def generar_ticket(lista, listap, listan, total, pedido, nombre, mediopago, haycupon, cupon, descuento_nom, hayeliminados, listae, haygratis, listag):
    with open(f"ticket{pedido}.txt", "w") as f:
        f.write("Ticket de compra\n")
        f.write("==============================\n")
        for i in range(0, len(lista)):
            f.write(f" - {listan[i]} ({lista[i]}): {listap[i]}€\n")
        f.write("")
        if hayeliminados == True:
            for j in range(len(listae)):
                f.write(f" - {listae[j]}€\n")
        if haygratis == True:
            for j in range(len(listag)):
                f.write(f" - {listag[j]}€\n")
        f.write("______________________________\n")
        a = float(round((total + cupon), 2))
        f.write(f"      -> Subtotal: {a:.2f}€\n")
        if haycupon:
            f.write(f"  · Cupón de descuento: {cupon}€ ({descuento_nom}%)\n")
            f.write(f"      -> Total: {total:.2f}€\n")
        else:
            f.write(f"    (No se han aplicado cupones de descuento)\n")
            f.write(f"      -> Total: {total:.2f}€\n")
        f.write("______________________________\n")
        f.write(f"Medio de pago: {mediopago}.\n")
        f.write("")
        fechayhora = datetime.datetime.now()
        fecha = fechayhora.date()
        hora = fechayhora.hour
        minuto = str(fechayhora.minute).zfill(2)
        f.write(f"Fecha: {fecha} - {hora}:{minuto}\n")
        f.write("==============================\n")
        f.write(f"Le atendió: {nombreT}\n")
        f.write("Gracias por confiar en nosotros\n")
        f.write("==============================\n")
    print(f"Ticket generado: ticket{pedido}.txt")


def verificar_trabajador(IDTrabajador, seguir):
    
    # Verificamos si el IDTrabajador existe en el diccionario trabajadores. Si existe, comprobamos la contraseña introducieda. Todo con sus correspondientes errores asociados.
    while seguir == False:
        if IDTrabajador in trabajadores:
            pwTrab = trabajadores[IDTrabajador]["pw"]
            pwIntrod = input("Introduzca su contraseña personal -> ")
            if pwTrab == pwIntrod:
                global nombreT
                nombreT = trabajadores[IDTrabajador]["nombre"]
                seguir = True
            else:
                print("Contraseña incorrecta. Pruebe de nuevo.")
                seguir = False
        else:
            IDTrabajador = input("No se ha podido verificar su ID. Introdúzcalo de nuevo -> ")
            seguir = False

    while not IDTrabajador:
        IDTrabajador = input("No se ha podido obtener su ID. Introdúzcalo de nuevo -> ")
            


pedido = 0
descuento_nom = 0
repetirBucle = True
seguir = False
nombre = ""

IDTrabajador = str(input("Introduzca su ID de trabajador: "))
verificar_trabajador(IDTrabajador, seguir)
print(f"Te has identificado correctamente como {nombreT}")

# Bucle principal para gestionar múltiples pedidos
while repetirBucle == True:
    total = 0
    hayeliminados = False
    haygratis = False
    lista = []  #ids de los productos
    listap = [] #precios de los productos
    listan = [] #nombres de los productos
    listae = [] #productos eliminados
    listag = [] #productos gratis
    pedido += 1

    if pedido > 1:
        cambio = input("¿Cambio de trabajador? (s/n) ")
        if cambio == "s":
            IDTrabajador = str(input("Introduzca su ID de trabajador: "))
            verificar_trabajador(IDTrabajador, seguir)
            print(f"Te has identificado correctamente como {nombreT}")
        else:
            print(f"De acuerdo, {nombreT}\n")
    
    auto = input("¿Desea recibir una lista de productos aleatoria? (s/n) -> ")
    if auto == "s":
        cantidad_prod = random.randint(5, 15)
        lista_ids = list(productos.keys())
        print("Lista de productos:    \n")
        for i in range(cantidad_prod):  # Itera sobre un rango de enteros
            id_random = random.choice(lista_ids)  # No es necesario convertir a float
            print(f"{id_random}, ")
    else:
        print("De acuerdo, introducirá los artículos manualmente.\n") 
    print("Introduzca los artículos\n(escriba 'd' para descuento, 'a' para entrada múltiple, 'r' para retirar un artículo o 's' para finalizar):")
    

    # Bucle interno para gestionar los artículos de un pedido
    #Va con la misma variable pues si se sale de la de dentro, de la de fuera tambien, pero si solo hay una comprueba todos los if y vuelve a donde el trabajador

    while repetirBucle == True:
        entrada = str(input("-> ")).zfill(4) #esto es para rellenar 4 digitos (25 -> 0025)
        if entrada.isnumeric() and entrada in productos:
            total += productos[entrada]["precio"]
            print(f"Producto {productos[entrada]['nombre']} (ID:{entrada}): {productos[entrada]['precio']:.2f}€")
            print(f"Total hasta ahora: {total:.2f}€")
            lista.insert(0, entrada)
            listap.insert(0, f"{productos[entrada]['precio']:.2f}")
            listan.insert(0, f"{productos[entrada]['nombre']}")
            
        elif entrada.lower() == "000d": #el entrada.lower() hace que todas las letras en dicha variable pasen a minusculas
            print("Introduzca el descuento:")
            desc = float(input("Descuento (%): "))
            while desc > 100:
                desc = float(input("El descuento no puede superar el 100%. Introdúzcalo de nuevo -> "))
                
            print("Introduzca el artículo:")
            art = str(input("ID artículo: ")).zfill(4)
            if art in productos:
                if desc == 100:
                    precio = productos[art]["precio"]
                    print(f"Producto {productos[art]['nombre']} (ID:{art}): 0.00€ -> 100% descuento (GRATIS)")
                    listag.append(f"{productos[art]['nombre']} -> GRATIS (PVP: {precio:.2f}) - 0.00")
                    haygratis = True
                else:
                    precio_descuento = productos[art]['precio'] * (1 - desc / 100)
                    listap.insert(0, f"{precio_descuento:.2f}")
                    total += precio_descuento
                    print(f"Producto {productos[art]['nombre']} (ID:{art}): {productos[art]['precio']} -> {precio_descuento:.2f}€ ({desc}% desc)")
                    listan.insert(0, f"{productos[art]['nombre']}")
                    lista.insert(0, art)
                #el listap (precios) está arriba en cada condicion del if, ya que si el descuento es del 100, es gratis
                    
                print(f"Total hasta ahora: {total:.2f}€")
                
                
            else:
                print("Código de artículo no válido.")
                
        elif entrada.lower() == "000a":
            cantidad = int(input("Cantidad: "))
            art = str(input("ID artículo: ")).zfill(4) 
            if art in productos:
                precio = productos[art]['precio'] * cantidad
                total += precio
                print(f"Has añadido {cantidad} productos {productos[art]['nombre']} (ID:{art}) -> {cantidad} x {productos[art]['precio']} = {precio:.2f}€")
                print(f"Total hasta ahora: {total:.2f}€")
                for i in range(cantidad):
                    lista.insert(0, art)
                    listap.insert(0, f"{productos[art]['precio']:.2f}")
                    listan.insert(0, f"{productos[art]['nombre']}")
            else:
                print("Código de artículo no válido.")
                
        elif entrada.lower() == "000r":
            art = str(input("ID artículo a QUITAR: ")).zfill(4) 
            if art in lista:
                indice = lista.index(art)
                precio = float(listap[indice])
                total = total - precio
                
                print(f"Has eliminado {art} (ID:{art}) -> Bajado el importe total en {precio:.2f}€")
                print(f"Total hasta ahora: {total:.2f}€")
                lista.pop(indice) # estos dos serian para eliminar el producto a quitar de la lista, pero prefiero que aparezcan
                listap.pop(indice)
                listan.pop(indice)
                listae.append(f"{productos[art]['nombre']} -> Eliminado: -{precio:.2f}")
                hayeliminados = True
            else:
                print("Código de artículo no válido o no en el carrito.")
        elif entrada.lower() == "0000":
            nomart = input("Introduzca el nombre del artículo -> ")
            precioart = round((float(input("Introduzca el precio del artículo -> "))), 2)
            total = total + precioart
            print(f"Producto {nomart} (ID:{entrada:4}): {precioart}€")
            print(f"Total hasta ahora: {total:.2f}€")
            lista.insert(0, "-No ID asociado-")
            listap.insert(0, f"{precioart:.2f}")
            listan.insert(0, f"{nomart}")
            
        elif entrada.lower() == "000s":
            a = input("¿Hay un cupón de descuento? (s/n) -> ")
            if a == "s":
                haycupon = True
                cupon = float(input("Introduzca el % de descuento sobre el total -> "))
                print(f"Descuento del {cupon:.2f}% aplicado.")
                descuento_nom = cupon
                cupon = round((total - (total * (1 - cupon / 100))), 2)
                total = total - cupon
                print(f"Descuento total: {cupon}€")
            else:
                print("- Sin cupón -")
                haycupon = False
                cupon = 0
                    
            print(f"Total final: {total:.2f}€")
            pago = input("¿Efectivo o tarjeta? (e/t) -> ")
            while pago not in ["e", "t"]:
                pago = input("No se ha podido obtener. Introduzca medio de pago -> ")

            if pago == "e":
                continuar = False
                while not continuar:
                    entregado = float(input("¿Cuánto ha entregado? -> "))
                    if entregado > total or entregado == total:
                        devolver = entregado - total
                        print(f"Devolver {devolver:.2f}€")
                        mediopago = "Efectivo"
                        continuar = True
                    else:
                        print("No puede haber entregado menos. Revise la cantidad")
            elif pago == "t":
                continuar = False
                while not continuar:
                    terminal = float(input("Introduzca cantidad para terminal de pago -> "))
        
                    print(f"Pago de {terminal:.2f}€ introducido correctamente")
                    if terminal == float(f"{total:.2f}"):
                        mediopago = "Tarjeta"
                        continuar = True
                    else:
                        print("Cantidad incorrecta")

            print(f"Objetos comprados: {lista}")
            siono = input("¿Quiere ticket? (s/n) -> ")
            if siono.lower() == "s":
                generar_ticket(lista, listap, listan, total, pedido, nombre, mediopago, haycupon, cupon, descuento_nom, hayeliminados, listae, haygratis, listag)

            seguirpreg = input("¿Desea seguir? (s/n) -> ")
            if seguirpreg.lower() == "n":
                repetirBucle = False
            break
            
        else:
            print("Código no válido. Introduzca otro artículo o 's' para finalizar.")

print("Gracias, ¡Hasta pronto!")

No hay comentarios:

Publicar un comentario

Cartel RV, RA y RM

Hola a todos, hoy vamos a tratar el tema de los distintos tipos de realidades diferentes que existen: realidad virtual, aumentada y mixta. E...