Sistema de Gestión de Óptica
Índice
1. Introducción
2. Paso 1: Creación de la Base de Datos y Tablas
3. Paso 2: Gestión de Clientes
4. Paso 3: Gestión de Productos
5. Paso 4: Gestión de Ventas
6. Paso 5: Gestión de Doctores
7. Paso 6: Gestión de Citas
8. Paso 7: Generación de Reportes y Estadísticas
9. Paso 8: Integración en el Menú Principal
10.Conclusión
1. Introducción
Este Sistema de Gestión de Óptica está diseñado para administrar
eficientemente clientes, productos, ventas, doctores y citas, además de
generar reportes y estadísticas para facilitar la toma de decisiones. A
continuación, se detallan los pasos para su creación, acompañados de los
scripts necesarios.
2. Paso 1: Creación de la Base de Datos y Tablas
Descripción
En este paso, crearemos la base de datos optica.db y definiremos las tablas
necesarias para almacenar la información de clientes, productos, ventas,
doctores y citas.
Script de Python
python
Copiar código
import sqlite3
def crear_conexion():
conexion = sqlite3.connect('optica.db')
return conexion
def crear_tablas():
conexion = crear_conexion()
cursor = conexion.cursor()
# Tabla de clientes
cursor.execute('''
CREATE TABLE IF NOT EXISTS clientes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nombre TEXT NOT NULL,
apellido TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
telefono TEXT,
direccion TEXT
)
''')
# Tabla de productos
cursor.execute('''
CREATE TABLE IF NOT EXISTS productos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nombre TEXT NOT NULL,
descripcion TEXT,
precio REAL NOT NULL,
stock INTEGER NOT NULL
)
''')
# Tabla de ventas
cursor.execute('''
CREATE TABLE IF NOT EXISTS ventas (
id INTEGER PRIMARY KEY AUTOINCREMENT,
cliente_id INTEGER NOT NULL,
producto_id INTEGER NOT NULL,
cantidad INTEGER NOT NULL,
fecha TEXT NOT NULL,
FOREIGN KEY(cliente_id) REFERENCES clientes(id),
FOREIGN KEY(producto_id) REFERENCES productos(id)
)
''')
# Tabla de doctores
cursor.execute('''
CREATE TABLE IF NOT EXISTS doctor (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nombre TEXT NOT NULL,
apellido TEXT NOT NULL,
especialidad TEXT,
email TEXT UNIQUE,
telefono TEXT
)
''')
# Tabla de citas
cursor.execute('''
CREATE TABLE IF NOT EXISTS citas (
id INTEGER PRIMARY KEY AUTOINCREMENT,
cliente_id INTEGER NOT NULL,
doctor_id INTEGER NOT NULL,
fecha TEXT NOT NULL,
motivo TEXT,
FOREIGN KEY(cliente_id) REFERENCES clientes(id),
FOREIGN KEY(doctor_id) REFERENCES doctor(id)
)
''')
conexion.commit()
conexion.close()
if __name__ == "__main__":
crear_tablas()
print("Tablas creadas exitosamente.")
Instrucciones
1. Guardar el Script: Crea un archivo llamado optica.py y pega el código
anterior.
2. Ejecutar el Script: Ejecuta el archivo en tu entorno de desarrollo (por
ejemplo, Spyder) para crear la base de datos y las tablas.
3. Paso 2: Gestión de Clientes
Descripción
Permite agregar nuevos clientes y visualizar la lista de clientes registrados.
a) Función para Agregar Clientes
python
Copiar código
def agregar_cliente():
print("\n--- Agregar Cliente ---")
nombre = input("Nombre: ")
apellido = input("Apellido: ")
email = input("Email: ")
telefono = input("Teléfono: ")
direccion = input("Dirección: ")
conexion = crear_conexion()
cursor = conexion.cursor()
try:
cursor.execute('''
INSERT INTO clientes (nombre, apellido, email, telefono, direccion)
VALUES (?, ?, ?, ?, ?)
''', (nombre, apellido, email, telefono, direccion))
conexion.commit()
print("Cliente agregado exitosamente.")
except sqlite3.IntegrityError:
print("Error: El email ya existe.")
conexion.close()
b) Función para Mostrar Clientes
python
Copiar código
def mostrar_clientes():
print("\n--- Lista de Clientes ---")
conexion = crear_conexion()
cursor = conexion.cursor()
cursor.execute('SELECT * FROM clientes')
clientes = cursor.fetchall()
if clientes:
print("ID\tNombre\tApellido\tEmail\t\t\tTeléfono\tDirección")
print("-" * 100)
for cliente in clientes:
id_cliente = cliente[0]
nombre = cliente[1]
apellido = cliente[2]
email = cliente[3]
telefono = cliente[4]
direccion = cliente[5]
print(f"{id_cliente}\t{nombre}\t{apellido}\t{email}\t{telefono}\
t{direccion}")
else:
print("No hay clientes registrados.")
conexion.close()
4. Paso 3: Gestión de Productos
Descripción
Permite agregar nuevos productos y visualizar la lista de productos disponibles.
a) Función para Agregar Productos
python
Copiar código
def agregar_producto():
print("\n--- Agregar Producto ---")
nombre = input("Nombre del producto: ")
descripcion = input("Descripción: ")
try:
precio = float(input("Precio: "))
except ValueError:
print("Error: El precio debe ser un número.")
return
try:
stock = int(input("Stock: "))
except ValueError:
print("Error: El stock debe ser un número entero.")
return
conexion = crear_conexion()
cursor = conexion.cursor()
try:
cursor.execute('''
INSERT INTO productos (nombre, descripcion, precio, stock)
VALUES (?, ?, ?, ?)
''', (nombre, descripcion, precio, stock))
conexion.commit()
print("Producto agregado exitosamente.")
except sqlite3.IntegrityError as e:
print(f"Error al agregar el producto: {e}")
conexion.close()
b) Función para Mostrar Productos
python
Copiar código
def mostrar_productos():
print("\n--- Lista de Productos ---")
conexion = crear_conexion()
cursor = conexion.cursor()
cursor.execute('SELECT * FROM productos')
productos = cursor.fetchall()
if productos:
print("ID\tNombre\tDescripción\tPrecio\tStock")
print("-" * 80)
for producto in productos:
id_producto = producto[0]
nombre = producto[1]
descripcion = producto[2]
precio = producto[3]
stock = producto[4]
print(f"{id_producto}\t{nombre}\t{descripcion}\t{precio}\t{stock}")
else:
print("No hay productos registrados.")
conexion.close()
5. Paso 4: Gestión de Ventas
Descripción
Permite registrar nuevas ventas y visualizar la lista de ventas realizadas.
a) Función para Registrar Ventas
python
Copiar código
def registrar_venta():
print("\n--- Registrar Venta ---")
# Mostrar clientes para referencia
mostrar_clientes()
try:
cliente_id = int(input("Ingrese el ID del cliente: "))
except ValueError:
print("Error: El ID del cliente debe ser un número entero.")
return
# Mostrar productos para referencia
mostrar_productos()
try:
producto_id = int(input("Ingrese el ID del producto: "))
except ValueError:
print("Error: El ID del producto debe ser un número entero.")
return
try:
cantidad = int(input("Cantidad a vender: "))
if cantidad <= 0:
print("Error: La cantidad debe ser un número positivo.")
return
except ValueError:
print("Error: La cantidad debe ser un número entero.")
return
fecha = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
conexion = crear_conexion()
cursor = conexion.cursor()
try:
# Verificar existencia del cliente
cursor.execute('SELECT id FROM clientes WHERE id = ?', (cliente_id,))
if not cursor.fetchone():
print("Error: El cliente no existe.")
return
# Verificar existencia del producto y stock
cursor.execute('SELECT stock FROM productos WHERE id = ?',
(producto_id,))
resultado = cursor.fetchone()
if resultado:
stock_actual = resultado[0]
if stock_actual >= cantidad:
# Registrar la venta
cursor.execute('''
INSERT INTO ventas (cliente_id, producto_id, cantidad, fecha)
VALUES (?, ?, ?, ?)
''', (cliente_id, producto_id, cantidad, fecha))
# Actualizar el stock del producto
nuevo_stock = stock_actual - cantidad
cursor.execute('UPDATE productos SET stock = ? WHERE id = ?',
(nuevo_stock, producto_id))
conexion.commit()
print("Venta registrada exitosamente.")
else:
print(f"Error: Stock insuficiente. Stock actual: {stock_actual}")
else:
print("Error: El producto no existe.")
except sqlite3.Error as e:
print(f"Error al registrar la venta: {e}")
finally:
conexion.close()
b) Función para Mostrar Ventas
python
Copiar código
def mostrar_ventas():
print("\n--- Lista de Ventas ---")
conexion = crear_conexion()
cursor = conexion.cursor()
cursor.execute('''
SELECT ventas.id, clientes.nombre || ' ' || clientes.apellido AS cliente,
productos.nombre AS producto, ventas.cantidad, ventas.fecha
FROM ventas
INNER JOIN clientes ON ventas.cliente_id = clientes.id
INNER JOIN productos ON ventas.producto_id = productos.id
ORDER BY ventas.fecha DESC
''')
ventas = cursor.fetchall()
if ventas:
print("ID\tCliente\t\tProducto\tCantidad\tFecha")
print("-" * 100)
for venta in ventas:
id_venta = venta[0]
cliente = venta[1]
producto = venta[2]
cantidad = venta[3]
fecha = venta[4]
print(f"{id_venta}\t{cliente}\t{producto}\t{cantidad}\t{fecha}")
else:
print("No hay ventas registradas.")
conexion.close()
6. Paso 5: Gestión de Doctores
Descripción
Permite agregar nuevos doctores y visualizar la lista de doctores registrados.
a) Función para Agregar Doctores
python
Copiar código
def agregar_doctor():
print("\n--- Agregar Doctor ---")
nombre = input("Nombre del doctor: ")
apellido = input("Apellido del doctor: ")
especialidad = input("Especialidad: ")
email = input("Email: ")
telefono = input("Teléfono: ")
conexion = crear_conexion()
cursor = conexion.cursor()
try:
cursor.execute('''
INSERT INTO doctor (nombre, apellido, especialidad, email, telefono)
VALUES (?, ?, ?, ?, ?)
''', (nombre, apellido, especialidad, email, telefono))
conexion.commit()
print("Doctor agregado exitosamente.")
except sqlite3.IntegrityError:
print("Error: El email ya existe o hay un problema con los datos
ingresados.")
finally:
conexion.close()
b) Función para Mostrar Doctores
python
Copiar código
def mostrar_doctores():
print("\n--- Lista de Doctores ---")
conexion = crear_conexion()
cursor = conexion.cursor()
cursor.execute('SELECT * FROM doctor')
doctores = cursor.fetchall()
if doctores:
print("ID\tNombre\tApellido\tEspecialidad\tEmail\t\t\tTeléfono")
print("-" * 100)
for doctor in doctores:
id_doctor = doctor[0]
nombre = doctor[1]
apellido = doctor[2]
especialidad = doctor[3]
email = doctor[4]
telefono = doctor[5]
print(f"{id_doctor}\t{nombre}\t{apellido}\t{especialidad}\t{email}\
t{telefono}")
else:
print("No hay doctores registrados.")
conexion.close()
7. Paso 6: Gestión de Citas
Descripción
Permite programar nuevas citas entre clientes y doctores, y visualizar la lista
de citas registradas.
a) Función para Agregar Citas
python
Copiar código
def agregar_cita():
print("\n--- Agregar Cita ---")
# Mostrar clientes para referencia
mostrar_clientes()
try:
cliente_id = int(input("Ingrese el ID del cliente: "))
except ValueError:
print("Error: El ID del cliente debe ser un número entero.")
return
# Mostrar doctores para referencia
mostrar_doctores()
try:
doctor_id = int(input("Ingrese el ID del doctor: "))
except ValueError:
print("Error: El ID del doctor debe ser un número entero.")
return
fecha = input("Ingrese la fecha de la cita (YYYY-MM-DD): ")
hora = input("Ingrese la hora de la cita (HH:MM): ")
motivo = input("Ingrese el motivo de la cita: ")
# Validar formato de fecha y hora
try:
datetime.datetime.strptime(fecha, "%Y-%m-%d")
datetime.datetime.strptime(hora, "%H:%M")
except ValueError:
print("Error: Fecha u hora en formato incorrecto.")
return
fecha_completa = f"{fecha} {hora}:00"
conexion = crear_conexion()
cursor = conexion.cursor()
try:
# Verificar existencia del cliente
cursor.execute('SELECT id FROM clientes WHERE id = ?', (cliente_id,))
if not cursor.fetchone():
print("Error: El cliente no existe.")
return
# Verificar existencia del doctor
cursor.execute('SELECT id FROM doctor WHERE id = ?', (doctor_id,))
if not cursor.fetchone():
print("Error: El doctor no existe.")
return
# Registrar la cita
cursor.execute('''
INSERT INTO citas (cliente_id, doctor_id, fecha, motivo)
VALUES (?, ?, ?, ?)
''', (cliente_id, doctor_id, fecha_completa, motivo))
conexion.commit()
print("Cita agregada exitosamente.")
except sqlite3.Error as e:
print(f"Error al agregar la cita: {e}")
finally:
conexion.close()
b) Función para Mostrar Citas
python
Copiar código
def mostrar_citas():
print("\n--- Lista de Citas ---")
conexion = crear_conexion()
cursor = conexion.cursor()
cursor.execute('''
SELECT citas.id, clientes.nombre || ' ' || clientes.apellido AS cliente,
doctor.nombre || ' ' || doctor.apellido AS doctor,
citas.fecha, citas.motivo
FROM citas
INNER JOIN clientes ON citas.cliente_id = clientes.id
INNER JOIN doctor ON citas.doctor_id = doctor.id
ORDER BY citas.fecha DESC
''')
citas = cursor.fetchall()
if citas:
print("ID\tCliente\t\tDoctor\t\t\tFecha\t\t\tMotivo")
print("-" * 150)
for cita in citas:
id_cita = cita[0]
cliente = cita[1]
doctor = cita[2]
fecha = cita[3]
motivo = cita[4]
print(f"{id_cita}\t{cliente}\t{doctor}\t{fecha}\t{motivo}")
else:
print("No hay citas registradas.")
conexion.close()
8. Paso 7: Generación de Reportes y Estadísticas
Descripción
Permite generar reportes detallados sobre ventas y citas, como ventas por
cliente, ventas por producto, ventas por período, citas por doctor y citas por
período.
a) Funciones para Reportes de Ventas
i. Ventas por Cliente
python
Copiar código
def ventas_por_cliente():
print("\n--- Ventas por Cliente ---")
conexion = crear_conexion()
cursor = conexion.cursor()
cursor.execute('''
SELECT clientes.nombre || ' ' || clientes.apellido AS cliente,
COUNT(ventas.id) AS total_ventas,
SUM(ventas.cantidad * productos.precio) AS total_monto
FROM ventas
INNER JOIN clientes ON ventas.cliente_id = clientes.id
INNER JOIN productos ON ventas.producto_id = productos.id
GROUP BY ventas.cliente_id
ORDER BY total_monto DESC
''')
resultados = cursor.fetchall()
if resultados:
print("Cliente\t\tTotal Ventas\tTotal Monto")
print("-" * 50)
for fila in resultados:
cliente = fila[0]
total_ventas = fila[1]
total_monto = fila[2]
print(f"{cliente}\t{total_ventas}\t\t${total_monto:.2f}")
else:
print("No hay ventas registradas.")
conexion.close()
ii. Ventas por Producto
python
Copiar código
def ventas_por_producto():
print("\n--- Ventas por Producto ---")
conexion = crear_conexion()
cursor = conexion.cursor()
cursor.execute('''
SELECT productos.nombre AS producto,
COUNT(ventas.id) AS total_ventas,
SUM(ventas.cantidad) AS total_unidades,
SUM(ventas.cantidad * productos.precio) AS total_monto
FROM ventas
INNER JOIN productos ON ventas.producto_id = productos.id
GROUP BY ventas.producto_id
ORDER BY total_monto DESC
''')
resultados = cursor.fetchall()
if resultados:
print("Producto\tTotal Ventas\tUnidades Vendidas\tTotal Monto")
print("-" * 80)
for fila in resultados:
producto = fila[0]
total_ventas = fila[1]
total_unidades = fila[2]
total_monto = fila[3]
print(f"{producto}\t{total_ventas}\t\t{total_unidades}\t\t\t$
{total_monto:.2f}")
else:
print("No hay ventas registradas.")
conexion.close()
iii. Ventas por Período
python
Copiar código
def ventas_por_periodo():
print("\n--- Ventas por Período ---")
inicio = input("Ingrese la fecha de inicio (YYYY-MM-DD): ")
fin = input("Ingrese la fecha de fin (YYYY-MM-DD): ")
# Validar formato de fecha
try:
inicio_dt = datetime.datetime.strptime(inicio, "%Y-%m-%d")
fin_dt = datetime.datetime.strptime(fin, "%Y-%m-%d")
except ValueError:
print("Error: Formato de fecha incorrecto.")
return
conexion = crear_conexion()
cursor = conexion.cursor()
cursor.execute('''
SELECT ventas.id, clientes.nombre || ' ' || clientes.apellido AS cliente,
productos.nombre AS producto, ventas.cantidad, ventas.fecha
FROM ventas
INNER JOIN clientes ON ventas.cliente_id = clientes.id
INNER JOIN productos ON ventas.producto_id = productos.id
WHERE DATE(ventas.fecha) BETWEEN ? AND ?
ORDER BY ventas.fecha DESC
''', (inicio, fin))
ventas = cursor.fetchall()
if ventas:
print("ID\tCliente\t\tProducto\tCantidad\tFecha")
print("-" * 100)
for venta in ventas:
id_venta = venta[0]
cliente = venta[1]
producto = venta[2]
cantidad = venta[3]
fecha = venta[4]
print(f"{id_venta}\t{cliente}\t{producto}\t{cantidad}\t{fecha}")
else:
print("No hay ventas registradas en este período.")
conexion.close()
b) Funciones para Reportes de Citas
i. Citas por Doctor
python
Copiar código
def citas_por_doctor():
print("\n--- Citas por Doctor ---")
conexion = crear_conexion()
cursor = conexion.cursor()
cursor.execute('''
SELECT doctor.nombre || ' ' || doctor.apellido AS doctor,
COUNT(citas.id) AS total_citas
FROM citas
INNER JOIN doctor ON citas.doctor_id = doctor.id
GROUP BY citas.doctor_id
ORDER BY total_citas DESC
''')
resultados = cursor.fetchall()
if resultados:
print("Doctor\t\tTotal Citas")
print("-" * 30)
for fila in resultados:
doctor = fila[0]
total_citas = fila[1]
print(f"{doctor}\t{total_citas}")
else:
print("No hay citas registradas.")
conexion.close()
ii. Citas por Período
python
Copiar código
def citas_por_periodo():
print("\n--- Citas por Período ---")
inicio = input("Ingrese la fecha de inicio (YYYY-MM-DD): ")
fin = input("Ingrese la fecha de fin (YYYY-MM-DD): ")
# Validar formato de fecha
try:
inicio_dt = datetime.datetime.strptime(inicio, "%Y-%m-%d")
fin_dt = datetime.datetime.strptime(fin, "%Y-%m-%d")
except ValueError:
print("Error: Formato de fecha incorrecto.")
return
conexion = crear_conexion()
cursor = conexion.cursor()
cursor.execute('''
SELECT citas.id, clientes.nombre || ' ' || clientes.apellido AS cliente,
doctor.nombre || ' ' || doctor.apellido AS doctor,
citas.fecha, citas.motivo
FROM citas
INNER JOIN clientes ON citas.cliente_id = clientes.id
INNER JOIN doctor ON citas.doctor_id = doctor.id
WHERE DATE(citas.fecha) BETWEEN ? AND ?
ORDER BY citas.fecha DESC
''', (inicio, fin))
citas = cursor.fetchall()
if citas:
print("ID\tCliente\t\tDoctor\t\t\tFecha\t\t\tMotivo")
print("-" * 150)
for cita in citas:
id_cita = cita[0]
cliente = cita[1]
doctor = cita[2]
fecha = cita[3]
motivo = cita[4]
print(f"{id_cita}\t{cliente}\t{doctor}\t{fecha}\t{motivo}")
else:
print("No hay citas registradas en este período.")
conexion.close()
9. Paso 8: Integración en el Menú Principal
Descripción
Integra todas las funciones desarrolladas en un menú interactivo que permite
al usuario navegar y utilizar las diferentes funcionalidades del sistema.
Script Completo del Menú Principal
python
Copiar código
def menu():
crear_tablas()
while True:
print("\n=== Sistema de Gestión de Óptica ===")
print("1. Agregar Cliente")
print("2. Mostrar Clientes")
print("3. Agregar Producto")
print("4. Mostrar Productos")
print("5. Registrar Venta")
print("6. Mostrar Ventas")
print("7. Agregar Doctor")
print("8. Mostrar Doctores")
print("9. Agregar Cita")
print("10. Mostrar Citas")
print("11. Reportes de Ventas")
print("12. Reportes de Citas")
print("13. Salir")
opcion = input("Selecciona una opción: ")
if opcion == '1':
agregar_cliente()
elif opcion == '2':
mostrar_clientes()
elif opcion == '3':
agregar_producto()
elif opcion == '4':
mostrar_productos()
elif opcion == '5':
registrar_venta()
elif opcion == '6':
mostrar_ventas()
elif opcion == '7':
agregar_doctor()
elif opcion == '8':
mostrar_doctores()
elif opcion == '9':
agregar_cita()
elif opcion == '10':
mostrar_citas()
elif opcion == '11':
# Submenú para reportes de ventas
while True:
print("\n--- Reportes de Ventas ---")
print("1. Ventas por Cliente")
print("2. Ventas por Producto")
print("3. Ventas por Período")
print("4. Volver al Menú Principal")
reporte_venta = input("Selecciona una opción: ")
if reporte_venta == '1':
ventas_por_cliente()
elif reporte_venta == '2':
ventas_por_producto()
elif reporte_venta == '3':
ventas_por_periodo()
elif reporte_venta == '4':
break
else:
print("Opción no válida. Por favor, intenta de nuevo.")
elif opcion == '12':
# Submenú para reportes de citas
while True:
print("\n--- Reportes de Citas ---")
print("1. Citas por Doctor")
print("2. Citas por Período")
print("3. Volver al Menú Principal")
reporte_cita = input("Selecciona una opción: ")
if reporte_cita == '1':
citas_por_doctor()
elif reporte_cita == '2':
citas_por_periodo()
elif reporte_cita == '3':
break
else:
print("Opción no válida. Por favor, intenta de nuevo.")
elif opcion == '13':
print("Gracias por utilizar el sistema. ¡Hasta luego!")
break
else:
print("Opción no válida. Por favor, intenta de nuevo.")
if __name__ == "__main__":
menu()
10. Conclusión
Has completado los ocho pasos fundamentales para crear un Sistema de
Gestión de Óptica en Python utilizando SQLite. Este sistema te permitirá
gestionar clientes, productos, ventas, doctores y citas, además de generar
reportes y estadísticas que facilitarán la toma de decisiones en tu óptica.
Próximos Pasos Sugeridos
1. Implementar Funciones de Actualización y Eliminación:
o Permitir al usuario actualizar y eliminar registros según sea
necesario.
2. Agregar Seguridad y Autenticación:
o Implementar un sistema de usuarios con roles y permisos.
3. Optimizar la Base de Datos:
o Añadir índices y asegurarse de que la base de datos esté bien
normalizada.
4. Desarrollar una Interfaz Gráfica (Opcional):
o Utilizar bibliotecas como Tkinter para mejorar la experiencia del
usuario.
5. Implementar Copias de Seguridad y Recuperación:
o Asegurar la integridad y disponibilidad de los datos mediante
respaldos regulares.