diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 60ef7b2..94a25f7 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git "a/Documentaci\303\263n/AlcanceProyecto" "b/Documentaci\303\263n/AlcanceProyecto" deleted file mode 100644 index 7904321..0000000 --- "a/Documentaci\303\263n/AlcanceProyecto" +++ /dev/null @@ -1,4 +0,0 @@ -Alcance del proyecto. - -Creación de un sitio web que muestre los productos de la panadería con descripciones detalladas y fotografías. -Implementación de funcionalidades como un formulario de contacto y un apartado para comentarios. diff --git "a/Documentaci\303\263n/Cuadro-de-Cotizaciones Panaderia EL CASTILLO DEL PAN.xlsx" "b/Documentaci\303\263n/Cuadro-de-Cotizaciones Panaderia EL CASTILLO DEL PAN.xlsx" deleted file mode 100644 index b14ba19..0000000 Binary files "a/Documentaci\303\263n/Cuadro-de-Cotizaciones Panaderia EL CASTILLO DEL PAN.xlsx" and /dev/null differ diff --git "a/Documentaci\303\263n/Delimitaci\303\263nProyecto" "b/Documentaci\303\263n/Delimitaci\303\263nProyecto" deleted file mode 100644 index 7ac9fff..0000000 --- "a/Documentaci\303\263n/Delimitaci\303\263nProyecto" +++ /dev/null @@ -1,5 +0,0 @@ -Delimitación del Proyecto - --El proyecto no incluirá la gestión de inventario de productos ni un sistema de pedidos en línea. --El proyecto se ejecutará con un presupuesto limitado y en un plazo definido, priorizando las características esenciales del sitio web. --El mantenimiento y actualización del sitio web después de su lanzamiento no están incluidos en esta fase del proyecto. diff --git "a/Documentaci\303\263n/Diagrama casos de uso Proyecto.vpp" "b/Documentaci\303\263n/Diagrama casos de uso Proyecto.vpp" deleted file mode 100644 index 37fde4d..0000000 Binary files "a/Documentaci\303\263n/Diagrama casos de uso Proyecto.vpp" and /dev/null differ diff --git "a/Documentaci\303\263n/DiagramaDesprendiblePanaderia (1).png" "b/Documentaci\303\263n/DiagramaDesprendiblePanaderia (1).png" deleted file mode 100644 index d1a86f1..0000000 Binary files "a/Documentaci\303\263n/DiagramaDesprendiblePanaderia (1).png" and /dev/null differ diff --git "a/Documentaci\303\263n/FORMATO SRS [PANADERIA].docx" "b/Documentaci\303\263n/FORMATO SRS [PANADERIA].docx" deleted file mode 100644 index e4bb1f9..0000000 Binary files "a/Documentaci\303\263n/FORMATO SRS [PANADERIA].docx" and /dev/null differ diff --git "a/Documentaci\303\263n/MODELO PROYECTO PANADERIA.png" "b/Documentaci\303\263n/MODELO PROYECTO PANADERIA.png" deleted file mode 100644 index 06a12fc..0000000 Binary files "a/Documentaci\303\263n/MODELO PROYECTO PANADERIA.png" and /dev/null differ diff --git "a/Documentaci\303\263n/Normalizacion PanAndCode.xlsx" "b/Documentaci\303\263n/Normalizacion PanAndCode.xlsx" deleted file mode 100644 index 792017a..0000000 Binary files "a/Documentaci\303\263n/Normalizacion PanAndCode.xlsx" and /dev/null differ diff --git "a/Documentaci\303\263n/Objetivo General.pdf" "b/Documentaci\303\263n/Objetivo General.pdf" deleted file mode 100644 index 37348a1..0000000 Binary files "a/Documentaci\303\263n/Objetivo General.pdf" and /dev/null differ diff --git "a/Documentaci\303\263n/Pregunta problema.docx" "b/Documentaci\303\263n/Pregunta problema.docx" deleted file mode 100644 index d89b791..0000000 Binary files "a/Documentaci\303\263n/Pregunta problema.docx" and /dev/null differ diff --git "a/Documentaci\303\263n/Preguntas.txt" "b/Documentaci\303\263n/Preguntas.txt" deleted file mode 100644 index ee36846..0000000 --- "a/Documentaci\303\263n/Preguntas.txt" +++ /dev/null @@ -1,117 +0,0 @@ -Se utilizará un cuestionario como instrumento de recolección de información, dirigido a dos puestos clave en el proceso de ventas: el dueño y los empleados de la panadería. -Este método permitirá obtener datos precisos y estandarizados de manera rápida, facilitando la evaluación del rendimiento de las ventas y las estrategias implementadas. -Se utilizara la metodología de pirámide organizará las preguntas desde aspectos generales hasta cuestiones más específicas, lo que favorecerá una comprensión clara y respuestas reflexivas, contribuyendo así a la mejora de las operaciones de venta en la panadería. -Las preguntas se centrarán en cómo gestionan los productos, pedidos, comentarios de los compradores y en que podría ayudar el sistema de información a desarrollar. - -Encuesta para el dueño de "El Castillo del Pan" (modificada) -Datos generales - -¿Cuál es su nombre? -Tu respuesta - -1. ¿Cuáles son los roles que tiene en el negocio? -Tu respuesta - -2. ¿Cuál es el horario de atención al público de la panadería? -Tu respuesta - -Métodos y procesos actuales -3. ¿Actualmente utiliza algún sistema de comunicación con los clientes que no sea presencial? - -Sí -No -4. ¿La panadería maneja métodos de pago diferentes al efectivo? En caso afirmativo, indique cuáles. -Tu respuesta - -5. ¿Cómo realiza actualmente la gestión de las ventas? - -En un cuaderno -Software de ofimática o similares (Excel, Word, LibreOffice, etc.) -Otros: _________ -Gestión de ventas y atención al cliente -6. ¿Considera que los clientes conocen todos los productos que ofrece la panadería? - -Sí -No -7. ¿Cuánto tiempo invierte en consolidar las ventas diarias? - -Menos de 10 minutos -Entre 10 y 20 minutos -Más de 20 minutos -8. ¿Ha experimentado descuadres entre el dinero de la caja y el sistema que usa para llevar el inventario? - -Sí -No -9. Si respondió afirmativamente a la pregunta anterior, ¿con qué frecuencia ocurre? - -Dos o más veces a la semana -Una vez a la semana -Una vez al mes -Una vez cada seis meses -10. ¿Qué problemas enfrenta durante las entregas a domicilio? (e.g., errores en la toma de pedidos, direcciones incorrectas, retrasos, etc.) -Tu respuesta -Percepción y necesidades tecnológicas -11. ¿Qué tan importante es para usted recibir reportes sobre productos más vendidos? - -Muy importante -Poco importante -No es importante -12. Si se desarrollara un sistema de información (página web, aplicación, etc.) para la panadería, ¿qué funciones le parecerían útiles? -Tu respuesta - -Encuesta para empleados de "El Castillo del Pan" -En cumplimiento de lo establecido en la Ley 1581 de 2012 y el Decreto 1377 de 2013 sobre la protección de datos personales en Colombia, le informamos que la información recopilada a través de esta encuesta será utilizada únicamente con fines académicos y de investigación relacionados con el diseño de un sistema de información para la panadería. -Su participación es voluntaria, y los datos proporcionados serán tratados de manera confidencial, garantizando su privacidad y seguridad. En ningún caso, la información será compartida con terceros sin su autorización previa. -Al completar esta encuesta, usted autoriza el uso de los datos suministrados conforme a los términos mencionados. Si tiene alguna inquietud o desea ejercer sus derechos sobre sus datos personales, puede contactarnos para mayor información. -Gracias por su colaboración. - -¿Cuál es su nombre completo? -Tu respuesta - -1. ¿Cuánto tiempo lleva trabajando en esta panadería? - -Menos de 1 mes -Entre 1 a 3 meses -4 a 6 meses -Más de 6 meses -2. ¿Cuál es su rol dentro de la panadería? -Tu respuesta - -3. ¿Cómo se realiza actualmente el registro de ventas? - -Manualmente (en papel) -Software de ofimática -Otros: -4. ¿Con qué frecuencia utiliza medios digitales para comunicarse con los clientes (Facebook, WhatsApp, Instagram, etc.)? - -Siempre -Ocasionalmente -Nunca -5. ¿Qué tan frecuente los clientes solicitan domicilios? - -Más de 40 veces al mes -20 a 40 veces por mes -10 a 20 veces por mes -1 a 10 veces por mes -No piden domicilios -6. ¿Cuáles son los productos que más solicitan los clientes? -Tu respuesta - -7. ¿Qué desafíos enfrenta al gestionar pedidos o atender a los clientes? -Tu respuesta - -8. ¿Con qué frecuencia los clientes solicitan productos que no están a la vista? - -Muy seguido -Ocasionalmente -Casi nunca -9. ¿Cree que un sistema que genere tickets de pedidos facilitaría su trabajo? - -Sí -No -10. ¿Considera que sería útil tener acceso a reportes sobre ventas diarias y productos más vendidos? - -Sí -No -11. Si se desarrollara un sistema de información para la panadería, ¿qué funciones cree que le serían útiles (e.g., registro de ventas, gestión de pedidos, comunicación con clientes)? -Tu respuesta diff --git "a/Documentaci\303\263n/Problem\303\241tica.docx" "b/Documentaci\303\263n/Problem\303\241tica.docx" deleted file mode 100644 index 4d4ef36..0000000 Binary files "a/Documentaci\303\263n/Problem\303\241tica.docx" and /dev/null differ diff --git "a/Documentaci\303\263n/README.md" "b/Documentaci\303\263n/README.md" deleted file mode 100644 index ad7f93c..0000000 --- "a/Documentaci\303\263n/README.md" +++ /dev/null @@ -1,20 +0,0 @@ -# PROYECTO-PANADERIA - - INTRODUCCIÓN A NUESTRO PROYECTO EDUCATIVO - EL CASTILLO DEL PAN - ------------------- - -Como tecnólogos en formación en el área de análisis y desarrollo de software del SENA (Servicio Nacional de Aprendizaje), buscamos ofrecer a un negocio de barrio, específicamente una panadería denominada El Castillo del Pan, que lleva más de seis meses en el mercado local, una solución tecnológica. Los dueños nos comentan que han experimentado una baja fluctuación en las ventas, por lo que han decidido recurrir a un sistema de información para mejorar su desempeño. - -Nuestro principal objetivo es desarrollar un sistema de información orientado a los consumidores. Optaremos por un menú gráfico donde se mostrarán los productos (panes, tortas, postres, hojaldres, etc.). Adicionalmente, se incluirá un formulario de registro, de modo que los consumidores puedan dejar comentarios y retroalimentaciones, lo que permitirá la mejora continua del sitio web. - -A lo largo de nuestra formación académica, iremos implementando nuevas funcionalidades, líneas de código más eficientes y entornos de usuario más interactivos e inmersivos, con el fin de ofrecer un producto final de alta calidad, tanto para los dueños como para los consumidores en general. -_______________________________________________________________________________________________________________________________ - -Andrés Alcalá, -Damián Ávila, -Ana Goyeneche, -Sharyth Zamora, -Brayan Jiménez. - -Ficha: 2996176 diff --git "a/Documentaci\303\263n/Requerimientos Funcionales Proyecto.txt" "b/Documentaci\303\263n/Requerimientos Funcionales Proyecto.txt" deleted file mode 100644 index bec529f..0000000 --- "a/Documentaci\303\263n/Requerimientos Funcionales Proyecto.txt" +++ /dev/null @@ -1,38 +0,0 @@ -Requerimientos Funcionales. - -RF 01-Registro de Usuario -RF 02-Inico de Sesión -RF 03-Generación de informes -RF 04-Respaldo y Recuperación -RF 05-Gestión de menú -RF 06-Consulta de elementos del menú -RF 07-Modificar elementos del menú -RF 08-Gestión de ventas -RF 09-Consultar ventas -RF 10-Crear Pedido -RF 11-Agregar Productos a Pedido -RF 12-Aplicar Descuentos -RF 13-Cancelar Venta -RF 14-Gestión de ofertas y promociones -RF 15-Consultar promociones -RF 16-Agregar promociones -RF 17-Modificar ofertas y promociones -RF 18-Eliminar ofertas y promociones -RF 19-Gestion de usuarios -RF 20-Consulta de usuarios -RF 21-Crear usuarios -RF 22-Modificar usuarios -RF 23-Gestión de información -RF 24-Consultar información del sistema -RF 25-Modificar información de la panaderia -RF 26-Gestión de reportes -RF 27-Consulta de reportes -RF 28-Visualización de reportes -RF 29-Gestión de usuarios -RF 30-Registro de usuario -RF 31-Ingreso al sistema -RF 32-Actualización de datos -RF 33-Eliminar perfil - - - diff --git "a/Documentaci\303\263n/Requerimientos no Funcionales.txt" "b/Documentaci\303\263n/Requerimientos no Funcionales.txt" deleted file mode 100644 index 811f60b..0000000 --- "a/Documentaci\303\263n/Requerimientos no Funcionales.txt" +++ /dev/null @@ -1,15 +0,0 @@ -Requerimientos No Funcionales. - -RNF 01- Interfaz -RNF 02- Usabilidad -RNF 03- Seguridad -RNF 04- Escalabilidad -RNF 05- Disponibilidad -RNF 06- Rendimiento -RNF 07- Mantenibilidad -RNF 08- Portabilidad -RNF 09- Confiabilidad -RNF 10- Accesibilidad -RNF 11- Interoperabilidad -RNF 12- Auditoría y Registro -RNF 13- Recuperación diff --git "a/Documentaci\303\263n/Requisitos Funcionales.pdf" "b/Documentaci\303\263n/Requisitos Funcionales.pdf" deleted file mode 100644 index 3df34dd..0000000 Binary files "a/Documentaci\303\263n/Requisitos Funcionales.pdf" and /dev/null differ diff --git "a/Documentaci\303\263n/Requisitosnofuncionales.txt" "b/Documentaci\303\263n/Requisitosnofuncionales.txt" deleted file mode 100644 index 0abd1a5..0000000 --- "a/Documentaci\303\263n/Requisitosnofuncionales.txt" +++ /dev/null @@ -1,21 +0,0 @@ - -RNF01 - Interfaz del sistema -RNF02 - Escalabilidad -RNF03 - Compatibilidad y portabilidad -RNF04 - Rendimiento -RNF05 - Seguridad -RNF06 - Disponibilidad -RNF07 - Respaldo de datos -RNF08 - Mantenimiento -RNF09 - Usabilidad -RNF10 - Soporte técnico - - - - - - - - - - diff --git a/Pan&Code/database/PROYECTOPANADERIA.sql b/Pan&Code/database/PROYECTOPANADERIA.sql deleted file mode 100644 index 48462ea..0000000 --- a/Pan&Code/database/PROYECTOPANADERIA.sql +++ /dev/null @@ -1,1034 +0,0 @@ --- ================================================================== --- PROYECTO PANADERÍA - BASE DE DATOS --- ================================================================== --- Autor: Sistema de Gestión de Panadería --- Fecha: 2025 --- Descripción: Base de datos completa para gestión de panadería --- Versión: 2.1 - Incluye sistema de logs y actualización de estructura --- ================================================================== - --- CARACTERÍSTICAS PRINCIPALES: --- - Gestión completa de productos con descripción opcional --- - Sistema de pedidos con detalles de productos --- - Control de inventario y stock mínimo --- - Gestión de empleados, clientes y administradores --- - Sistema de logs para auditoría de cambios en productos --- - Triggers automáticos para actualización de totales --- - Funciones de utilidad para encriptación y generación de códigos --- - Estructura optimizada para dashboard de empleados y administradores - --- ESTRUCTURA DE TABLAS PRINCIPALES: --- - Productos: Incluye DESCRIPCION_PRODUCTO opcional --- - Detalle_Pedidos: Sin columnas de imagen, solo datos esenciales --- - Empleados: Con control de estado activo/inactivo --- - Pedidos: Con estados y totales automáticos --- - Sistema de logs: Para auditoría de cambios - --- INSTRUCCIONES DE INSTALACIÓN: --- --- OPCIÓN 1: INSTALACIÓN NUEVA (Base de datos desde cero) --- 1. Ejecutar todo el script completo --- 2. La base de datos se creará con todas las tablas y datos --- --- OPCIÓN 2: ACTUALIZACIÓN DE BASE EXISTENTE --- 1. Ejecutar solo las secciones de "MIGRACIONES Y ACTUALIZACIONES" --- 2. Verificar que los cambios se aplicaron correctamente --- 3. Los datos existentes se mantendrán intactos --- --- ================================================================== - --- Configuración inicial -DROP DATABASE IF EXISTS ProyectoPanaderia; -SET SQL_SAFE_UPDATES = 0; -CREATE DATABASE ProyectoPanaderia; -USE ProyectoPanaderia; - --- ================================================================== --- DDL (DATA DEFINITION LANGUAGE) - DEFINICIÓN DE ESTRUCTURA --- ================================================================== - --- ================================================================== --- CREACIÓN DE TABLAS PRINCIPALES --- ================================================================== - --- Tabla: Clientes - Almacena información de los clientes -CREATE TABLE Clientes ( - ID_CLIENTE INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_CLI VARCHAR(100) NOT NULL, - TELEFONO_CLI VARCHAR(20), - ACTIVO_CLI BOOLEAN DEFAULT TRUE, - EMAIL_CLI VARCHAR(100), - CONTRASEÑA_CLI VARCHAR(255), - SALT_CLI VARCHAR(32) -); - --- Tabla: Empleados - Almacena información de los empleados -CREATE TABLE Empleados ( - ID_EMPLEADO INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_EMPLEADO VARCHAR(100) NOT NULL, - EMAIL_EMPLEADO VARCHAR(100) NOT NULL, - ACTIVO_EMPLEADO BOOLEAN DEFAULT TRUE, - CONTRASEÑA_EMPLEADO VARCHAR(255), - SALT_EMPLEADO VARCHAR(32), - FECHA_REGISTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - --- Tabla: Administradores - Almacena información de los administradores -CREATE TABLE Administradores ( - ID_ADMIN INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_ADMIN VARCHAR(100) NOT NULL, - TELEFONO_ADMIN VARCHAR(20), - EMAIL_ADMIN VARCHAR(100), - CONTRASEÑA_ADMIN VARCHAR(255), - SALT_ADMIN VARCHAR(32) -); - --- Tabla: Proveedores - Almacena información de los proveedores -CREATE TABLE Proveedores ( - ID_PROVEEDOR INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_PROV VARCHAR(100) NOT NULL, - TELEFONO_PROV VARCHAR(20) NOT NULL, - ACTIVO_PROV BOOLEAN DEFAULT TRUE, - EMAIL_PROV VARCHAR(100) NOT NULL, - DIRECCION_PROV VARCHAR(200) -); - --- Tabla: Pedidos_Proveedores - Almacena pedidos realizados a proveedores -CREATE TABLE Pedidos_Proveedores ( - ID_PEDIDO_PROV INT PRIMARY KEY AUTO_INCREMENT, - ID_PROVEEDOR INT NOT NULL, - NUMERO_PEDIDO INT NOT NULL, - FECHA_PEDIDO DATE NOT NULL, - ESTADO_PEDIDO VARCHAR(50) DEFAULT 'Pendiente', - CONSTRAINT FK_PEDIDO_PROVEEDOR - FOREIGN KEY (ID_PROVEEDOR) REFERENCES Proveedores(ID_PROVEEDOR) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- Tabla: Categoria_Productos - Almacena categorías de productos -CREATE TABLE Categoria_Productos ( - ID_CATEGORIA_PRODUCTO INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_CATEGORIAPRODUCTO VARCHAR(100) NOT NULL -); - --- Tabla: Estado_Pedidos - Almacena estados de pedidos -CREATE TABLE Estado_Pedidos ( - ID_ESTADO_PEDIDO INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_ESTADO VARCHAR(50) -); - --- Tabla: Categoria_Ingredientes - Almacena categorías de ingredientes -CREATE TABLE Categoria_Ingredientes ( - ID_CATEGORIA INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_CATEGORIA_INGREDIENTE VARCHAR(100) NOT NULL -); - --- Tabla: Ingredientes - Almacena ingredientes utilizados en productos -CREATE TABLE Ingredientes ( - ID_INGREDIENTE INT PRIMARY KEY AUTO_INCREMENT, - ID_PROVEEDOR INT, - ID_CATEGORIA INT, - NOMBRE_INGREDIENTE VARCHAR(100) NOT NULL, - CANTIDAD_INGREDIENTE INT NOT NULL, - FECHA_VENCIMIENTO DATE NOT NULL, - REFERENCIA_INGREDIENTE VARCHAR(100) NOT NULL, - FECHA_ENTREGA_INGREDIENTE DATE NOT NULL, - CONSTRAINT FK_PROVEEDOR_INGREDIENTE - FOREIGN KEY (ID_PROVEEDOR) REFERENCES Proveedores(ID_PROVEEDOR) ON UPDATE CASCADE ON DELETE RESTRICT, - CONSTRAINT FK_CATEGORIA_INGREDIENTE - FOREIGN KEY (ID_CATEGORIA) REFERENCES Categoria_Ingredientes(ID_CATEGORIA) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- Tabla: Productos - Almacena productos de la panadería -CREATE TABLE Productos ( - ID_PRODUCTO INT PRIMARY KEY AUTO_INCREMENT, - ID_ADMIN INT, - ID_CATEGORIA_PRODUCTO INT, - NOMBRE_PRODUCTO VARCHAR(100) NOT NULL, - DESCRIPCION_PRODUCTO TEXT, - PRODUCTO_STOCK_MIN INT NOT NULL, - PRECIO_PRODUCTO DECIMAL(10,2) NOT NULL, - FECHA_VENCIMIENTO_PRODUCTO DATE NOT NULL, - FECHA_INGRESO_PRODUCTO DATE NOT NULL, - TIPO_PRODUCTO_MARCA VARCHAR(100) NOT NULL, - ACTIVO BOOLEAN DEFAULT TRUE, - FECHA_ULTIMA_MODIFICACION TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - CONSTRAINT FK_CATEGORIA_PRODUCTO - FOREIGN KEY (ID_CATEGORIA_PRODUCTO) REFERENCES Categoria_Productos(ID_CATEGORIA_PRODUCTO) ON UPDATE CASCADE ON DELETE RESTRICT, - CONSTRAINT FK_ADMIN_PRODUCTO - FOREIGN KEY (ID_ADMIN) REFERENCES Administradores(ID_ADMIN) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- Tabla: Pedidos - Almacena pedidos realizados por clientes -CREATE TABLE Pedidos ( - ID_PEDIDO INT PRIMARY KEY AUTO_INCREMENT, - ID_CLIENTE INT, - ID_EMPLEADO INT, - ID_ESTADO_PEDIDO INT, - FECHA_INGRESO DATETIME NOT NULL, - FECHA_ENTREGA DATETIME NOT NULL, - TOTAL_PRODUCTO DECIMAL(10,2) NOT NULL, - CONSTRAINT FK_CLIENTE_PEDIDO - FOREIGN KEY (ID_CLIENTE) REFERENCES Clientes(ID_CLIENTE) ON UPDATE CASCADE ON DELETE RESTRICT, - CONSTRAINT FK_EMPLEADO_PEDIDO - FOREIGN KEY (ID_EMPLEADO) REFERENCES Empleados(ID_EMPLEADO) ON UPDATE CASCADE ON DELETE RESTRICT, - CONSTRAINT FK_ESTADO_PEDIDO_PEDIDO - FOREIGN KEY (ID_ESTADO_PEDIDO) REFERENCES Estado_Pedidos(ID_ESTADO_PEDIDO) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- Tabla: Detalle_Pedidos - Almacena detalles de productos por pedido -CREATE TABLE Detalle_Pedidos ( - ID_DETALLE INT PRIMARY KEY AUTO_INCREMENT, - ID_PEDIDO INT NOT NULL, - ID_PRODUCTO INT NOT NULL, - CANTIDAD_PRODUCTO INT NOT NULL, - PRECIO_UNITARIO DECIMAL(10,2) NOT NULL, - SUBTOTAL DECIMAL(10,2) NOT NULL, - CONSTRAINT FK_DETALLE_PEDIDO - FOREIGN KEY (ID_PEDIDO) REFERENCES Pedidos(ID_PEDIDO) ON UPDATE CASCADE ON DELETE CASCADE, - CONSTRAINT FK_DETALLE_PRODUCTO - FOREIGN KEY (ID_PRODUCTO) REFERENCES Productos(ID_PRODUCTO) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- Tabla: Ordenes_Salida - Almacena facturas de pedidos -CREATE TABLE Ordenes_Salida ( - ID_FACTURA INT PRIMARY KEY AUTO_INCREMENT, - ID_CLIENTE INT, - ID_PEDIDO INT, - FECHA_FACTURACION DATETIME NOT NULL, - TOTAL_FACTURA DECIMAL(10,2) NOT NULL, - CONSTRAINT FK_ORDENSALIDA_CLIENTE - FOREIGN KEY (ID_CLIENTE) REFERENCES Clientes(ID_CLIENTE) ON UPDATE CASCADE ON DELETE RESTRICT, - CONSTRAINT FK_ORDENSALIDA_PEDIDO - FOREIGN KEY (ID_PEDIDO) REFERENCES Pedidos(ID_PEDIDO) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- ================================================================== --- TABLA DE LOGS PARA CAMBIOS EN PRODUCTOS --- ================================================================== - --- Tabla para registrar cambios en productos (logs de auditoría) -CREATE TABLE productos_logs ( - id INT PRIMARY KEY AUTO_INCREMENT, - producto_id INT NOT NULL, - tipo_cambio ENUM('precio', 'stock', 'activacion', 'desactivacion') NOT NULL, - valor_anterior VARCHAR(50), - valor_nuevo VARCHAR(50), - usuario_id INT, - usuario_tipo ENUM('admin', 'empleado') DEFAULT 'admin', - fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - ip_usuario VARCHAR(45), - INDEX idx_producto_logs_fecha (fecha_cambio), - INDEX idx_producto_logs_producto (producto_id), - INDEX idx_producto_logs_tipo (tipo_cambio), - CONSTRAINT FK_PRODUCTO_LOG - FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE -); - --- Trigger para actualizar FECHA_ULTIMA_MODIFICACION automáticamente -DELIMITER // -CREATE TRIGGER tr_actualizar_fecha_producto - BEFORE UPDATE ON Productos - FOR EACH ROW -BEGIN - SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP; -END// -DELIMITER ; - --- ================================================================== --- FUNCIONES DE UTILIDAD --- ================================================================== - --- Función: GenerateSalt - Genera salt aleatorio para encriptación -DELIMITER // - -CREATE FUNCTION GenerateSalt() -RETURNS VARCHAR(32) -READS SQL DATA -DETERMINISTIC -BEGIN - RETURN SUBSTRING(MD5(CONCAT(RAND(), NOW(), CONNECTION_ID())), 1, 32); -END// - -DELIMITER ; - --- Función: HashPassword - Hashea contraseñas con salt -DELIMITER // - -CREATE FUNCTION HashPassword(password VARCHAR(255), salt VARCHAR(32)) -RETURNS VARCHAR(255) -READS SQL DATA -DETERMINISTIC -BEGIN - RETURN SHA2(CONCAT(password, salt), 256); -END// - -DELIMITER ; - --- Función: GenerarCodigoProducto - Genera códigos de producto por categoría -DELIMITER // -CREATE FUNCTION GenerarCodigoProducto(categoria_id INT, producto_id INT) -RETURNS VARCHAR(50) -READS SQL DATA -DETERMINISTIC -BEGIN - DECLARE prefijo VARCHAR(10); - - -- Obtener prefijo según categoría - SELECT CASE - WHEN categoria_id = 1 THEN 'TL' -- Tortas Tres Leches - WHEN categoria_id = 2 THEN 'TM' -- Tortas Milkyway - WHEN categoria_id = 3 THEN 'TE' -- Tortas Encargo - WHEN categoria_id = 4 THEN 'PG' -- Pan Grande - WHEN categoria_id = 5 THEN 'PP' -- Pan Pequeño - WHEN categoria_id = 6 THEN 'PS' -- Postres - WHEN categoria_id = 7 THEN 'GA' -- Galletas - WHEN categoria_id = 8 THEN 'TA' -- Tamales - WHEN categoria_id = 9 THEN 'YO' -- Yogures - WHEN categoria_id = 10 THEN 'PC' -- Pasteles Pollo - WHEN categoria_id = 11 THEN 'BE' -- Bebidas - WHEN categoria_id = 12 THEN 'PI' -- Panadería Integral - ELSE 'PR' - END INTO prefijo; - - RETURN CONCAT(prefijo, '-', LPAD(producto_id, 4, '0')); -END// -DELIMITER ; - --- Función: GenerarNumeroPedido - Genera números de pedido automáticos -DELIMITER // -CREATE FUNCTION GenerarNumeroPedido(pedido_id INT) -RETURNS VARCHAR(50) -READS SQL DATA -DETERMINISTIC -BEGIN - RETURN CONCAT('PED-', YEAR(NOW()), '-', LPAD(pedido_id, 6, '0')); -END// -DELIMITER ; - --- ================================================================== --- TRIGGERS --- ================================================================== - --- Trigger: Actualizar total del pedido cuando se inserta detalle -DELIMITER // - -CREATE TRIGGER tr_actualizar_total_pedido -AFTER INSERT ON Detalle_Pedidos -FOR EACH ROW -BEGIN - UPDATE Pedidos - SET TOTAL_PRODUCTO = ( - SELECT SUM(SUBTOTAL) - FROM Detalle_Pedidos - WHERE ID_PEDIDO = NEW.ID_PEDIDO - ) - WHERE ID_PEDIDO = NEW.ID_PEDIDO; -END// - -DELIMITER ; - --- Trigger: Actualizar total del pedido cuando se modifica detalle -DELIMITER // - -CREATE TRIGGER tr_actualizar_total_pedido_update -AFTER UPDATE ON Detalle_Pedidos -FOR EACH ROW -BEGIN - UPDATE Pedidos - SET TOTAL_PRODUCTO = ( - SELECT SUM(SUBTOTAL) - FROM Detalle_Pedidos - WHERE ID_PEDIDO = NEW.ID_PEDIDO - ) - WHERE ID_PEDIDO = NEW.ID_PEDIDO; -END// - -DELIMITER ; - --- ================================================================== --- PROCEDIMIENTOS ALMACENADOS --- ================================================================== - --- Procedimiento: sp_productos_por_categoria - Busca productos por categoría -DELIMITER // - -CREATE PROCEDURE sp_productos_por_categoria( - IN nombre_categoria VARCHAR(100) -) -BEGIN - -- Buscar productos por nombre de categoría - SELECT - p.ID_PRODUCTO, - p.NOMBRE_PRODUCTO, - p.PRECIO_PRODUCTO, - p.PRODUCTO_STOCK_MIN, - p.TIPO_PRODUCTO_MARCA, - cp.NOMBRE_CATEGORIAPRODUCTO as CATEGORIA - FROM Productos p - INNER JOIN Categoria_Productos cp ON p.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO - WHERE cp.NOMBRE_CATEGORIAPRODUCTO LIKE CONCAT('%', nombre_categoria, '%') - ORDER BY p.NOMBRE_PRODUCTO; - - -- Mostrar el total de productos encontrados - SELECT COUNT(*) as TOTAL_PRODUCTOS_ENCONTRADOS - FROM Productos p - INNER JOIN Categoria_Productos cp ON p.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO - WHERE cp.NOMBRE_CATEGORIAPRODUCTO LIKE CONCAT('%', nombre_categoria, '%'); -END// - -DELIMITER ; - --- Procedimiento: sp_crear_pedido - Crear un nuevo pedido -DELIMITER // - -CREATE PROCEDURE sp_crear_pedido( - IN p_id_cliente INT, - IN p_id_empleado INT, - IN p_fecha_entrega DATETIME -) -BEGIN - DECLARE nuevo_id_pedido INT; - - -- Insertar el pedido - INSERT INTO Pedidos (ID_CLIENTE, ID_EMPLEADO, ID_ESTADO_PEDIDO, FECHA_INGRESO, FECHA_ENTREGA, TOTAL_PRODUCTO) - VALUES (p_id_cliente, p_id_empleado, 1, NOW(), p_fecha_entrega, 0.00); - - -- Obtener el ID del pedido recién creado - SET nuevo_id_pedido = LAST_INSERT_ID(); - - -- Devolver el ID del nuevo pedido - SELECT nuevo_id_pedido as NUEVO_ID_PEDIDO; -END// - -DELIMITER ; - --- ================================================================== --- DML (DATA MANIPULATION LANGUAGE) - INSERCIÓN DE DATOS --- ================================================================== - --- ================================================================== --- INSERCIÓN DE DATOS BASE --- ================================================================== - --- Inserción en tabla: Clientes -INSERT INTO Clientes (NOMBRE_CLI, TELEFONO_CLI, EMAIL_CLI) VALUES -('Ana Pérez', '3101234567', 'ana.p@mail.com'), -('Luis Gómez', '3209876543', 'luis.g@mail.com'), -('Maria Rodriguez', '3001122334', 'maria.r@mail.com'); - --- Inserción en tabla: Empleados -INSERT INTO Empleados (NOMBRE_EMPLEADO) VALUES -('Andres Alkaeda'), -('Damian Avila'), -('Brayan Jimenez'), -('Ana Goyeneche'), -('Sharyt Zamora'); - --- Inserción en tabla: Administradores -INSERT INTO Administradores (NOMBRE_ADMIN, TELEFONO_ADMIN, EMAIL_ADMIN) VALUES -('Admin Uno', '3005550101', 'admin1@store.com'); - --- Inserción en tabla: Proveedores -INSERT INTO `proveedores` (`ID_PROVEEDOR`, `NOMBRE_PROV`) VALUES -('1', 'Harina Dorada'), -('2', 'Dulce Granero'), -('3', 'El Horno Mágico S.A.S.'), -('4', 'Masa Maestra Distribuciones'), -('5', 'Insumos Panaderos del Sol'), -('6', 'La Esencia del Pan'), -('7', 'Proveedora Integral del Panadero'), -('8', 'Alimentos para Hornear Cía. Ltda.'); - --- Inserción en tabla: Pedidos_Proveedores -INSERT INTO Pedidos_Proveedores (ID_PROVEEDOR, NUMERO_PEDIDO, FECHA_PEDIDO, ESTADO_PEDIDO) VALUES -(1, 1001, '2024-01-15', 'Entregado'), -(2, 1002, '2024-02-10', 'Entregado'), -(3, 1003, '2024-03-05', 'Entregado'); - --- Inserción en tabla: Categoria_Productos -INSERT INTO Categoria_Productos (NOMBRE_CATEGORIAPRODUCTO) VALUES -('Tortas Tres Leches'), -('Tortas Milyway'), -('Tortas por Encargo'), -('Pan Grande'), -('Pan Pequeño'), -('Postres'), -('Galletas'), -('Tamales'), -('Yogures'), -('Pasteles Pollo'); - --- Inserción en tabla: Estado_Pedidos -INSERT INTO Estado_Pedidos (NOMBRE_ESTADO) VALUES -('Pendiente'), -('En Preparación'), -('Listo para Entrega'), -('Entregado'), -('Cancelado'); - --- Inserción en tabla: Categoria_Ingredientes -INSERT INTO `categoria_ingredientes` (`ID_CATEGORIA`, `NOMBRE_CATEGORIA_INGREDIENTE`) VALUES -('1', 'Harinas'), -('2', 'Lácteos y Derivados'), -('3', 'Azúcares y Endulzantes'), -('4', 'Grasas'), -('5', 'Esencias'), -('6', 'Fruta'), -('7', 'Frutos Secos'), -('8', 'Levaduras'), -('9', 'Huevos'), -('10', 'Chocolate y Cacao'), -('11', 'Espesantes y Gelificantes'), -('12', 'Colorantes Alimentarios'), -('13', 'Sal'), -('14', 'Aditivos y Mejoradores'), -('15', 'Semillas'), -('16', 'Coberturas y Rellenos'); - --- Inserción en tabla: Ingredientes -INSERT INTO `ingredientes` (`ID_INGREDIENTE`, `ID_PROVEEDOR`, `ID_CATEGORIA`, `NOMBRE_INGREDIENTE`, `CANTIDAD_INGREDIENTE`, `FECHA_VENCIMIENTO`, `REFERENCIA_INGREDIENTE`) VALUES -('1', '2', '1', 'Harina de Trigo', '100', '2025-12-20', 'HAR-TRG-05'), -('2', '1', '2', 'Leche Entera UHT', '30', '2025-08-01', 'LECH-ENT-1L'), -('3', '3', '3', 'Azúcar Blanca', '70', '2026-01-30', 'AZUC-BLN-KG'), -('4', '4', '4', 'Mantequilla sin Sal', '25', '2025-09-15', 'MANT-SS-KG'), -('5', '5', '9', 'Huevos Grandes', '120', '2025-07-25', 'HUEV-GR-DZ'), -('6', '6', '10', 'Chocolate Semi-Amargo (Gotas)', '15', '2026-03-10', 'CHOC-SM-KG'), -('7', '7', '8', 'Levadura Fresca', '5', '2025-07-10', 'LEV-FRES-GR'), -('8', '1', '3', 'Azúcar Moreno', '10', '2026-02-20', 'AZUC-MRN-KG'), -('9', '2', '1', 'Harina Integral', '50', '2025-11-01', 'HAR-INT-02'), -('10', '3', '4', 'Aceite Vegetal', '20', '2026-05-01', 'ACET-VEG-LT'), -('11', '4', '10', 'Cacao en Polvo', '8', '2026-04-15', 'CACAO-POL-KG'), -('12', '5', '6', 'Manzanas Verdes (Kg)', '10', '2025-07-12', 'MANZ-VRD-KG'), -('13', '6', '7', 'Nueces Picadas', '5', '2025-10-01', 'NUEZ-PIC-KG'), -('14', '7', '5', 'Esencia de Vainilla', '2', '2027-01-01', 'ESEN-VN-LT'), -('15', '8', '13', 'Sal Fina', '2', '2028-01-01', 'SAL-FIN-KG'), -('16', '1', '2', 'Crema de Leche', '5', '2025-08-05', 'CREM-LECH-LT'), -('17', '2', '11', 'Gelatina sin Sabor', '1', '2026-09-01', 'GEL-SS-KG'), -('18', '3', '12', 'Colorante Alimentario Rojo', '0.5', '2027-03-01', 'COLR-ROJ-ML'), -('19', '4', '15', 'Semillas de Sésamo', '3', '2026-06-01', 'SEM-SES-KG'), -('20', '5', '16', 'Dulce de Leche', '10', '2025-11-15', 'DDL-KG'); - --- Inserción en tabla: Productos -INSERT INTO `productos` (`ID_PRODUCTO`, `ID_ADMIN`, `ID_CATEGORIA_PRODUCTO`, `NOMBRE_PRODUCTO`, `DESCRIPCION_PRODUCTO`, `PRODUCTO_STOCK_MIN`, `PRECIO_PRODUCTO`, `FECHA_VENCIMIENTO_PRODUCTO`, `FECHA_INGRESO_PRODUCTO`, `TIPO_PRODUCTO_MARCA`) VALUES -('1', '1', '8', 'Tamales Tolimenses', 'Tradicionales tamales envueltos en hoja de plátano, con masa de maíz y relleno de carne de cerdo y pollo', '10', '3800.00', '2025-09-15', '2025-07-01', 'Propio'), -('2', '1', '4', 'Pan Tajado Integral', 'Pan de molde integral, ideal para desayunos saludables, rico en fibra', '15', '4200.00', '2025-07-02', '2025-07-01', 'Propio'), -('3', '1', '7', 'Yogurt Fresa Litro', 'Yogurt cremoso con trozos de fresa natural, sin conservantes artificiales', '12', '6000.00', '2025-07-30', '2025-07-03', 'Alpina'), -('4', '1', '5', 'Galleta de Tres Ojos', 'Galleta tradicional colombiana con tres círculos de dulce, crujiente y deliciosa', '20', '2500.00', '2025-11-01', '2025-07-01', 'Propio'), -('5', '1', '1', 'Pan Campesino Grande', 'Pan artesanal de corteza dorada y miga suave, ideal para acompañar comidas', '8', '5500.00', '2025-07-08', '2025-07-04', 'Propio'), -('6', '1', '3', 'Torta de Chocolate Pequeña', 'Deliciosa torta de chocolate húmeda con cobertura de chocolate, perfecta para ocasiones especiales', '5', '18000.00', '2025-07-07', '2025-07-04', 'Propio'), -('7', '1', '2', 'Croissant de Almendras', NULL, '18', '3500.00', '2025-07-06', '2025-07-05', 'Propio'), -('8', '1', '1', 'Baguette Clásica', 'Pan francés tradicional con corteza crujiente y miga aireada', '25', '2800.00', '2025-07-06', '2025-07-05', 'Propio'), -('9', '1', '5', 'Bizcochos de Achira', NULL, '15', '4000.00', '2025-12-01', '2025-07-01', 'Propio'), -('10', '1', '6', 'Jugo de Naranja Natural (500ml)', 'Jugo 100% natural exprimido de naranjas frescas, sin azúcar añadido', '10', '4500.00', '2025-07-05', '2025-07-04', 'Postobón'), -('11', '1', '7', 'Postre de Tres Leches', 'Clásico postre colombiano empapado en tres tipos de leche, suave y cremoso', '7', '7500.00', '2025-07-08', '2025-07-04', 'Propio'), -('12', '1', '4', 'Pan Blanco de Molde', NULL, '20', '3900.00', '2025-07-02', '2025-07-01', 'Propio'), -('13', '1', '3', 'Muffin de Arándanos', 'Muffin esponjoso con arándanos frescos, perfecto para el desayuno o merienda', '15', '3000.00', '2025-07-07', '2025-07-04', 'Propio'), -('14', '1', '2', 'Pan de Bono Pequeño', NULL, '30', '1500.00', '2025-07-06', '2025-07-05', 'Propio'), -('15', '1', '8', 'Empanadas de Carne (unidad)', 'Empanada frita rellena de carne molida sazonada con especias tradicionales', '20', '2000.00', '2025-07-06', '2025-07-05', 'Propio'), -('16', '1', '3', 'Brazo de Reina', 'Bizcocho enrollado relleno de dulce de leche y cubierto con coco rallado', '10', '9500.00', '2025-07-09', '2025-07-04', 'Propio'), -('17', '1', '1', 'Pan Trenza Integral', NULL, '12', '4800.00', '2025-07-07', '2025-07-03', 'Propio'), -('18', '1', '5', 'Galletas Surtidas de Mantequilla', 'Variedad de galletas caseras de mantequilla con diferentes formas y sabores', '25', '3200.00', '2025-12-30', '2025-07-01', 'Propio'), -('19', '1', '7', 'Avena La Lechera (500ml)', NULL, '18', '5800.00', '2025-08-20', '2025-07-03', 'Nestlé'), -('20', '1', '9', 'Ponqué de Naranja (Porción)', 'Porción individual de ponqué de naranja con glaseado cítrico', '15', '3000.00', '2025-07-08', '2025-07-04', 'Propio'), -('21', '1', '10', 'Pan Artesanal de Masa Madre', 'Pan elaborado con masa madre natural, fermentación larga para mejor digestibilidad', '7', '8000.00', '2025-07-07', '2025-07-05', 'Propio'), -('22', '1', '3', 'Cheesecake de Frutos Rojos', 'Cheesecake cremoso con base de galleta y cobertura de frutos rojos frescos', '6', '25000.00', '2025-07-09', '2025-07-04', 'Propio'), -('23', '1', '4', 'Pan de Hamburguesa', NULL, '30', '4500.00', '2025-07-10', '2025-07-02', 'Propio'), -('24', '1', '5', 'Galletas de Avena y Pasas', 'Galletas nutritivas con avena integral y pasas, sin azúcar refinado', '22', '2700.00', '2026-01-01', '2025-07-01', 'Propio'), -('25', '1', '7', 'Kumiss Natural', NULL, '10', '4900.00', '2025-07-25', '2025-07-03', 'Alquería'), -('26', '1', '9', 'Brownie con Nuez', 'Brownie de chocolate intenso con trozos de nuez, húmedo y delicioso', '40', '1800.00', '2025-07-08', '2025-07-05', 'Propio'), -('27', '1', '1', 'Pan Blandito', NULL, '28', '2500.00', '2025-07-07', '2025-07-05', 'Propio'), -('28', '1', '3', 'Milhoja de Arequipe', 'Delicada milhoja rellena de arequipe casero y cubierta con azúcar glass', '12', '6000.00', '2025-07-08', '2025-07-04', 'Propio'), -('29', '1', '2', 'Mogolla Chicharrona', NULL, '15', '3500.00', '2025-07-06', '2025-07-05', 'Propio'), -('30', '1', '8', 'Arequipe (Tarro 500g)', 'Arequipe casero cremoso y dulce, perfecto para postres y acompañamientos', '8', '9000.00', '2026-04-10', '2025-07-01', 'Propio'); - --- Inserción en tabla: Pedidos -INSERT INTO Pedidos (ID_CLIENTE, ID_EMPLEADO, ID_ESTADO_PEDIDO, FECHA_INGRESO, FECHA_ENTREGA, TOTAL_PRODUCTO) VALUES -(1, 1, 2, '2025-06-20 09:00:00', '2025-06-20 15:00:00', 10000.00), -(2, 2, 4, '2025-06-19 10:30:00', '2025-06-19 16:30:00', 7500.00), -(3, 1, 1, '2025-06-21 08:00:00', '2025-06-21 14:00:00', 12500.00); - --- Inserción en tabla: Detalle_Pedidos -INSERT INTO Detalle_Pedidos (ID_PEDIDO, ID_PRODUCTO, CANTIDAD_PRODUCTO, PRECIO_UNITARIO, SUBTOTAL) VALUES -(1, 1, 2, 3500.00, 7000.00), -(1, 3, 1, 6000.00, 6000.00), -(2, 2, 1, 4200.00, 4200.00), -(2, 4, 3, 2500.00, 7500.00), -(3, 1, 3, 3500.00, 10500.00), -(3, 4, 2, 2500.00, 5000.00); - --- Inserción en tabla: Ordenes_Salida -INSERT INTO Ordenes_Salida (ID_CLIENTE, ID_PEDIDO, FECHA_FACTURACION, TOTAL_FACTURA) VALUES -(1, 1, '2025-06-20 15:30:00', 13000.00), -(2, 2, '2025-06-19 17:00:00', 11700.00), -(3, 3, '2025-06-21 14:30:00', 15500.00); - --- ================================================================== --- DSL (DATA SECURITY LANGUAGE) - SEGURIDAD Y ENCRIPTACIÓN --- ================================================================== - --- ================================================================== --- CONFIGURACIÓN DE SEGURIDAD - CONTRASEÑAS --- ================================================================== - --- Actualizar contraseñas de administradores con encriptación -UPDATE Administradores -SET SALT_ADMIN = GenerateSalt() -WHERE ID_ADMIN = 1; - -UPDATE Administradores -SET CONTRASEÑA_ADMIN = HashPassword('admin123', SALT_ADMIN) -WHERE ID_ADMIN = 1; - --- Actualizar contraseñas de clientes con encriptación -UPDATE Clientes -SET SALT_CLI = GenerateSalt() -WHERE ID_CLIENTE IN (1, 2, 3); - -UPDATE Clientes -SET CONTRASEÑA_CLI = HashPassword('cliente123', SALT_CLI) -WHERE ID_CLIENTE = 1; - -UPDATE Clientes -SET CONTRASEÑA_CLI = HashPassword('cliente456', SALT_CLI) -WHERE ID_CLIENTE = 2; - -UPDATE Clientes -SET CONTRASEÑA_CLI = HashPassword('cliente789', SALT_CLI) -WHERE ID_CLIENTE = 3; - --- Actualizar contraseñas de empleados con encriptación -UPDATE Empleados -SET SALT_EMPLEADO = GenerateSalt() -WHERE ID_EMPLEADO IN (1, 2, 3, 4, 5); - -UPDATE Empleados -SET CONTRASEÑA_EMPLEADO = HashPassword('empleado123', SALT_EMPLEADO) -WHERE ID_EMPLEADO = 1; - -UPDATE Empleados -SET CONTRASEÑA_EMPLEADO = HashPassword('empleado456', SALT_EMPLEADO) -WHERE ID_EMPLEADO = 2; - --- ================================================================== --- DQL (DATA QUERY LANGUAGE) - CONSULTAS Y VERIFICACIONES --- ================================================================== - --- ================================================================== --- CONSULTAS DE VERIFICACIÓN --- ================================================================== - --- Verificación de registros en todas las tablas -SELECT 'CLIENTES' as Tabla, COUNT(*) as Total_Registros FROM Clientes -UNION ALL -SELECT 'EMPLEADOS', COUNT(*) FROM Empleados -UNION ALL -SELECT 'ADMINISTRADORES', COUNT(*) FROM Administradores -UNION ALL -SELECT 'PROVEEDORES', COUNT(*) FROM Proveedores -UNION ALL -SELECT 'PEDIDOS_PROVEEDORES', COUNT(*) FROM Pedidos_Proveedores -UNION ALL -SELECT 'CATEGORIA_PRODUCTOS', COUNT(*) FROM Categoria_Productos -UNION ALL -SELECT 'ESTADO_PEDIDOS', COUNT(*) FROM Estado_Pedidos -UNION ALL -SELECT 'CATEGORIA_INGREDIENTES', COUNT(*) FROM Categoria_Ingredientes -UNION ALL -SELECT 'INGREDIENTES', COUNT(*) FROM Ingredientes -UNION ALL -SELECT 'PRODUCTOS', COUNT(*) FROM Productos -UNION ALL -SELECT 'PEDIDOS', COUNT(*) FROM Pedidos -UNION ALL -SELECT 'DETALLE_PEDIDOS', COUNT(*) FROM Detalle_Pedidos -UNION ALL -SELECT 'ORDENES_SALIDA', COUNT(*) FROM Ordenes_Salida; - --- Consulta detallada de productos con información completa -SELECT - p.ID_PRODUCTO, - p.NOMBRE_PRODUCTO, - cp.NOMBRE_CATEGORIAPRODUCTO as CATEGORIA, - p.PRECIO_PRODUCTO, - p.PRODUCTO_STOCK_MIN, - p.TIPO_PRODUCTO_MARCA, - a.NOMBRE_ADMIN as ADMINISTRADOR, - p.FECHA_ULTIMA_MODIFICACION -FROM Productos p -INNER JOIN Categoria_Productos cp ON p.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO -INNER JOIN Administradores a ON p.ID_ADMIN = a.ID_ADMIN -ORDER BY p.NOMBRE_PRODUCTO; - --- Consulta detallada de pedidos con información completa -SELECT - ped.ID_PEDIDO, - c.NOMBRE_CLI as CLIENTE, - e.NOMBRE_EMPLEADO as EMPLEADO, - ep.NOMBRE_ESTADO as ESTADO, - ped.FECHA_INGRESO, - ped.FECHA_ENTREGA, - p.NOMBRE_PRODUCTO, - dp.CANTIDAD_PRODUCTO, - dp.PRECIO_UNITARIO, - dp.SUBTOTAL -FROM Pedidos ped -INNER JOIN Clientes c ON ped.ID_CLIENTE = c.ID_CLIENTE -INNER JOIN Empleados e ON ped.ID_EMPLEADO = e.ID_EMPLEADO -INNER JOIN Estado_Pedidos ep ON ped.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO -INNER JOIN Detalle_Pedidos dp ON ped.ID_PEDIDO = dp.ID_PEDIDO -INNER JOIN Productos p ON dp.ID_PRODUCTO = p.ID_PRODUCTO -ORDER BY ped.ID_PEDIDO, dp.ID_DETALLE; - --- ================================================================== --- CONSULTAS DE VERIFICACIÓN DE SEGURIDAD --- ================================================================== - --- Verificación del hasheo de contraseñas de administradores -SELECT - ID_ADMIN, - NOMBRE_ADMIN, - SALT_ADMIN, - CONTRASEÑA_ADMIN, - LENGTH(CONTRASEÑA_ADMIN) as LONGITUD_HASH -FROM Administradores; - --- Verificación del hasheo de contraseñas de clientes - -SELECT - ID_CLIENTE, - NOMBRE_CLI, - SALT_CLI, - CONTRASEÑA_CLI, - LENGTH(CONTRASEÑA_CLI) as LONGITUD_HASH -FROM Clientes; - --- Verificación del hasheo de contraseñas de empleados - -SELECT - ID_EMPLEADO, - NOMBRE_EMPLEADO, - SALT_EMPLEADO, - CONTRASEÑA_EMPLEADO, - LENGTH(CONTRASEÑA_EMPLEADO) as LONGITUD_HASH -FROM Empleados; - --- Consulta consolidada de todas las contraseñas hasheadas - -SELECT 'ADMIN' as TIPO, NOMBRE_ADMIN as NOMBRE, SALT_ADMIN as SALT, CONTRASEÑA_ADMIN as HASH -FROM Administradores -WHERE CONTRASEÑA_ADMIN IS NOT NULL - -UNION ALL - -SELECT 'CLIENTE' as TIPO, NOMBRE_CLI as NOMBRE, SALT_CLI as SALT, CONTRASEÑA_CLI as HASH -FROM Clientes -WHERE CONTRASEÑA_CLI IS NOT NULL - -UNION ALL - -SELECT 'EMPLEADO' as TIPO, NOMBRE_EMPLEADO as NOMBRE, SALT_EMPLEADO as SALT, CONTRASEÑA_EMPLEADO as HASH -FROM Empleados -WHERE CONTRASEÑA_EMPLEADO IS NOT NULL; - - --- ================================================================== --- PRUEBAS Y VALIDACIONES --- ================================================================== - --- Prueba de trigger de actualización de fecha de modificación -UPDATE Productos -SET PRECIO_PRODUCTO = 3800.00 -WHERE NOMBRE_PRODUCTO = 'Tamales Tolimenses'; - --- Verificación de la actualización de fecha de modificación -SELECT - NOMBRE_PRODUCTO, - PRECIO_PRODUCTO, - FECHA_ULTIMA_MODIFICACION -FROM Productos -WHERE NOMBRE_PRODUCTO = 'Tamales Tolimenses'; - --- Pruebas de procedimientos almacenados -CALL sp_productos_por_categoria('Pan'); -CALL sp_productos_por_categoria('Torta'); -CALL sp_productos_por_categoria('Yogur'); - --- Prueba de creación de nuevo pedido -CALL sp_crear_pedido(1, 2, '2025-06-25 16:00:00'); - --- ================================================================== --- VERIFICACIONES FINALES DEL SISTEMA --- ================================================================== - --- Verificar triggers creados -SHOW TRIGGERS WHERE `Table` IN ('Productos', 'Detalle_Pedidos'); - --- Verificar procedimientos almacenados creados -SHOW PROCEDURE STATUS WHERE Name LIKE 'sp_%'; - --- Verificar funciones creadas -SHOW FUNCTION STATUS WHERE Name LIKE '%Password%' OR Name LIKE '%Salt%'; - --- Verificar estructura de las tablas principales -DESCRIBE Productos; -DESCRIBE Pedidos; -DESCRIBE Detalle_Pedidos; - --- Script para actualizar estados de pedidos --- Ejecutar solo si es necesario ajustar los estados - --- Verificar estados existentes -SELECT * FROM Estado_Pedidos; - --- Si necesitas ajustar los estados, puedes usar estas consultas: --- UPDATE Estado_Pedidos SET NOMBRE_ESTADO = 'Pendiente' WHERE ID_ESTADO_PEDIDO = 1; --- UPDATE Estado_Pedidos SET NOMBRE_ESTADO = 'En Preparación' WHERE ID_ESTADO_PEDIDO = 2; --- UPDATE Estado_Pedidos SET NOMBRE_ESTADO = 'Listo' WHERE ID_ESTADO_PEDIDO = 3; --- UPDATE Estado_Pedidos SET NOMBRE_ESTADO = 'Entregado' WHERE ID_ESTADO_PEDIDO = 4; --- UPDATE Estado_Pedidos SET NOMBRE_ESTADO = 'Cancelado' WHERE ID_ESTADO_PEDIDO = 5; - --- O insertar si no existen: --- INSERT INTO Estado_Pedidos (NOMBRE_ESTADO) VALUES --- ('Pendiente'), --- ('En Preparación'), --- ('Listo'), --- ('Entregado'), --- ('Cancelado'); - --- ================================================================== --- MIGRACIONES Y ACTUALIZACIONES DEL SISTEMA --- ================================================================== - --- ================================================================== --- MIGRACIÓN: ACTUALIZAR TIPO DE DATO PRECIO_PRODUCTO --- ================================================================== --- NOTA: Solo ejecutar si la base de datos ya existe y necesita actualización --- Descomentar las siguientes líneas para migrar una base de datos existente: - -<> --- Actualizar tipo de dato de PRECIO_PRODUCTO de INT a DECIMAL -ALTER TABLE Productos MODIFY COLUMN PRECIO_PRODUCTO DECIMAL(10,2) NOT NULL; - --- Verificar la estructura actualizada -DESCRIBE Productos; -<> - --- ================================================================== --- VERIFICACIÓN Y CREACIÓN DE TABLA DE LOGS --- ================================================================== --- Script para verificar y crear tabla productos_logs si no existe - --- Verificar si la tabla productos_logs existe -SET @table_exists = ( - SELECT COUNT(*) - FROM information_schema.tables - WHERE table_schema = DATABASE() - AND table_name = 'productos_logs' -); - --- Crear tabla productos_logs si no existe (para bases de datos existentes) -SET @sql = IF(@table_exists = 0, - 'CREATE TABLE productos_logs ( - id INT PRIMARY KEY AUTO_INCREMENT, - producto_id INT NOT NULL, - tipo_cambio ENUM(''precio'', ''stock'', ''activacion'', ''desactivacion'') NOT NULL, - valor_anterior VARCHAR(50), - valor_nuevo VARCHAR(50), - usuario_id INT, - usuario_tipo ENUM(''admin'', ''empleado'') DEFAULT ''admin'', - fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - ip_usuario VARCHAR(45), - INDEX idx_producto_logs_fecha (fecha_cambio), - INDEX idx_producto_logs_producto (producto_id), - INDEX idx_producto_logs_tipo (tipo_cambio), - CONSTRAINT FK_PRODUCTO_LOG - FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE - )', - 'SELECT ''Tabla productos_logs ya existe'' as mensaje' -); - -PREPARE stmt FROM @sql; -EXECUTE stmt; -DEALLOCATE PREPARE stmt; - --- ================================================================== --- VERIFICACIÓN Y CREACIÓN DE TRIGGER --- ================================================================== --- Script para verificar y crear trigger si no existe - --- Verificar si el trigger existe -SET @trigger_exists = ( - SELECT COUNT(*) - FROM information_schema.triggers - WHERE trigger_schema = DATABASE() - AND trigger_name = 'tr_actualizar_fecha_producto' -); - --- Crear trigger si no existe -SET @sql_trigger = IF(@trigger_exists = 0, - 'CREATE TRIGGER tr_actualizar_fecha_producto - BEFORE UPDATE ON Productos - FOR EACH ROW - BEGIN - SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP; - END', - 'SELECT ''Trigger tr_actualizar_fecha_producto ya existe'' as mensaje' -); - -PREPARE stmt_trigger FROM @sql_trigger; -EXECUTE stmt_trigger; -DEALLOCATE PREPARE stmt_trigger; - --- ================================================================== --- CONSULTAS DE MANTENIMIENTO Y VERIFICACIÓN --- ================================================================== - --- Verificar estructura de tabla Productos -SELECT - COLUMN_NAME as 'Campo', - COLUMN_TYPE as 'Tipo', - IS_NULLABLE as 'Nulo', - COLUMN_DEFAULT as 'Por_Defecto', - EXTRA as 'Extra' -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'Productos' -ORDER BY ORDINAL_POSITION; - --- Verificar existencia de tabla productos_logs -SELECT - TABLE_NAME as 'Tabla', - TABLE_ROWS as 'Filas', - CREATE_TIME as 'Fecha_Creacion' -FROM information_schema.TABLES -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME IN ('Productos', 'productos_logs'); - --- Verificar triggers relacionados con Productos -SELECT - TRIGGER_NAME as 'Trigger', - EVENT_MANIPULATION as 'Evento', - EVENT_OBJECT_TABLE as 'Tabla', - TRIGGER_BODY as 'Accion' -FROM information_schema.TRIGGERS -WHERE TRIGGER_SCHEMA = DATABASE() -AND EVENT_OBJECT_TABLE = 'Productos'; - --- Verificar índices de la tabla productos_logs -SELECT - INDEX_NAME as 'Indice', - COLUMN_NAME as 'Columna', - NON_UNIQUE as 'No_Unico' -FROM information_schema.STATISTICS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'productos_logs' -ORDER BY INDEX_NAME, SEQ_IN_INDEX; - --- ================================================================== --- CONSULTAS DE PRUEBA PARA LOGS --- ================================================================== - --- Consulta para ver logs recientes (ejecutar después de hacer cambios) --- SELECT * FROM productos_logs ORDER BY fecha_cambio DESC LIMIT 10; - --- Consulta para ver cambios de un producto específico --- SELECT --- pl.*, --- p.NOMBRE_PRODUCTO --- FROM productos_logs pl --- JOIN Productos p ON pl.producto_id = p.ID_PRODUCTO --- WHERE pl.producto_id = 1 --- ORDER BY pl.fecha_cambio DESC; - --- Consulta para ver estadísticas de cambios --- SELECT --- tipo_cambio, --- COUNT(*) as total_cambios, --- DATE(fecha_cambio) as fecha --- FROM productos_logs --- GROUP BY tipo_cambio, DATE(fecha_cambio) --- ORDER BY fecha DESC, tipo_cambio; - --- ================================================================== --- SCRIPT DE LIMPIEZA (OPCIONAL) --- ================================================================== - --- Limpiar logs antiguos (ejecutar solo si es necesario) --- DELETE FROM productos_logs WHERE fecha_cambio < DATE_SUB(NOW(), INTERVAL 90 DAY); - --- Resetear AUTO_INCREMENT de la tabla logs --- ALTER TABLE productos_logs AUTO_INCREMENT = 1; - --- ============================================================ --- MIGRACIÓN: Agregar columna FECHA_REGISTRO a tabla Empleados --- ============================================================ - --- Verificar y agregar columna FECHA_REGISTRO a la tabla Empleados si no existe -SET @sql = (SELECT IF( - (SELECT COUNT(*) FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'Empleados' - AND COLUMN_NAME = 'FECHA_REGISTRO') = 0, - 'ALTER TABLE Empleados ADD COLUMN FECHA_REGISTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP', - 'SELECT "La columna FECHA_REGISTRO ya existe en la tabla Empleados" as mensaje' -)); - -PREPARE stmt FROM @sql; -EXECUTE stmt; -DEALLOCATE PREPARE stmt; - --- ============================================================ --- MIGRACIÓN: Agregar columna DESCRIPCION_PRODUCTO a tabla Productos --- ============================================================ - --- Verificar y agregar columna DESCRIPCION_PRODUCTO a la tabla Productos si no existe -SET @sql = (SELECT IF( - (SELECT COUNT(*) FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'Productos' - AND COLUMN_NAME = 'DESCRIPCION_PRODUCTO') = 0, - 'ALTER TABLE Productos ADD COLUMN DESCRIPCION_PRODUCTO TEXT AFTER NOMBRE_PRODUCTO', - 'SELECT "La columna DESCRIPCION_PRODUCTO ya existe en la tabla Productos" as mensaje' -)); - -PREPARE stmt FROM @sql; -EXECUTE stmt; -DEALLOCATE PREPARE stmt; - --- ================================================================== --- VERIFICACIÓN DE ESTRUCTURA FINAL --- ================================================================== - --- Verificar que todas las tablas principales existen -SELECT - TABLE_NAME as 'Tabla_Existente' -FROM information_schema.TABLES -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME IN ('Productos', 'Detalle_Pedidos', 'Pedidos', 'Empleados', 'Clientes', 'Administradores') -ORDER BY TABLE_NAME; - --- Verificar estructura de tabla Productos (debe incluir DESCRIPCION_PRODUCTO) -SELECT - COLUMN_NAME as 'Columna', - DATA_TYPE as 'Tipo', - IS_NULLABLE as 'Permite_NULL' -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'Productos' -ORDER BY ORDINAL_POSITION; - --- Verificar estructura de tabla Detalle_Pedidos (debe tener solo columnas esenciales) -SELECT - COLUMN_NAME as 'Columna', - DATA_TYPE as 'Tipo', - IS_NULLABLE as 'Permite_NULL' -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'Detalle_Pedidos' -ORDER BY ORDINAL_POSITION; - --- ================================================================== --- FIN DE ACTUALIZACIONES DEL SISTEMA --- ================================================================== - -COMMIT; diff --git a/Pan&Code/frontend/public/images/992710.png b/Pan&Code/frontend/public/images/992710.png deleted file mode 100644 index 1dade7e..0000000 Binary files a/Pan&Code/frontend/public/images/992710.png and /dev/null differ diff --git a/Pan&Code/frontend/public/images/PAN-INTEGRAL.jpg b/Pan&Code/frontend/public/images/PAN-INTEGRAL.jpg deleted file mode 100644 index 879660a..0000000 Binary files a/Pan&Code/frontend/public/images/PAN-INTEGRAL.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/Pan1.jpg b/Pan&Code/frontend/public/images/Pan1.jpg deleted file mode 100644 index dd4bfca..0000000 Binary files a/Pan&Code/frontend/public/images/Pan1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/arequipe-alpina.png b/Pan&Code/frontend/public/images/arequipe-alpina.png deleted file mode 100644 index 508908f..0000000 Binary files a/Pan&Code/frontend/public/images/arequipe-alpina.png and /dev/null differ diff --git a/Pan&Code/frontend/public/images/baguette.jpg b/Pan&Code/frontend/public/images/baguette.jpg deleted file mode 100644 index 5121398..0000000 Binary files a/Pan&Code/frontend/public/images/baguette.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/brazoreina1.jpg b/Pan&Code/frontend/public/images/brazoreina1.jpg deleted file mode 100644 index 5183e0a..0000000 Binary files a/Pan&Code/frontend/public/images/brazoreina1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/browni-con-nueces.jpg b/Pan&Code/frontend/public/images/browni-con-nueces.jpg deleted file mode 100644 index 2d6b6f2..0000000 Binary files a/Pan&Code/frontend/public/images/browni-con-nueces.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/brownie1.jpg b/Pan&Code/frontend/public/images/brownie1.jpg deleted file mode 100644 index 0ecee86..0000000 Binary files a/Pan&Code/frontend/public/images/brownie1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/cheesecake-frutos-rojos.jpg b/Pan&Code/frontend/public/images/cheesecake-frutos-rojos.jpg deleted file mode 100644 index 36ebc57..0000000 Binary files a/Pan&Code/frontend/public/images/cheesecake-frutos-rojos.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/chicharrona.png b/Pan&Code/frontend/public/images/chicharrona.png deleted file mode 100644 index 23b7561..0000000 Binary files a/Pan&Code/frontend/public/images/chicharrona.png and /dev/null differ diff --git a/Pan&Code/frontend/public/images/croissant1.jpg b/Pan&Code/frontend/public/images/croissant1.jpg deleted file mode 100644 index 0f3c958..0000000 Binary files a/Pan&Code/frontend/public/images/croissant1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/croissants.jpg b/Pan&Code/frontend/public/images/croissants.jpg deleted file mode 100644 index 2ffc6b8..0000000 Binary files a/Pan&Code/frontend/public/images/croissants.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/empanadas.png b/Pan&Code/frontend/public/images/empanadas.png deleted file mode 100644 index 268d546..0000000 Binary files a/Pan&Code/frontend/public/images/empanadas.png and /dev/null differ diff --git a/Pan&Code/frontend/public/images/flan de caramelo.jpeg b/Pan&Code/frontend/public/images/flan de caramelo.jpeg deleted file mode 100644 index 39d4910..0000000 Binary files a/Pan&Code/frontend/public/images/flan de caramelo.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/galleta avena.jpeg b/Pan&Code/frontend/public/images/galleta avena.jpeg deleted file mode 100644 index b5d648b..0000000 Binary files a/Pan&Code/frontend/public/images/galleta avena.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/galleta chocolate.jpeg b/Pan&Code/frontend/public/images/galleta chocolate.jpeg deleted file mode 100644 index 05fce90..0000000 Binary files a/Pan&Code/frontend/public/images/galleta chocolate.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/galleta integral.jpeg b/Pan&Code/frontend/public/images/galleta integral.jpeg deleted file mode 100644 index 2f71315..0000000 Binary files a/Pan&Code/frontend/public/images/galleta integral.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/galleta mantequilla.jpeg b/Pan&Code/frontend/public/images/galleta mantequilla.jpeg deleted file mode 100644 index 8d1d193..0000000 Binary files a/Pan&Code/frontend/public/images/galleta mantequilla.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/galleta vainilla.jpeg b/Pan&Code/frontend/public/images/galleta vainilla.jpeg deleted file mode 100644 index f2d6d98..0000000 Binary files a/Pan&Code/frontend/public/images/galleta vainilla.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/galleta1.jpg b/Pan&Code/frontend/public/images/galleta1.jpg deleted file mode 100644 index dba5b74..0000000 Binary files a/Pan&Code/frontend/public/images/galleta1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/galletas-de-avena-con-pasas-y-nuez.jpg b/Pan&Code/frontend/public/images/galletas-de-avena-con-pasas-y-nuez.jpg deleted file mode 100644 index 89cb9c3..0000000 Binary files a/Pan&Code/frontend/public/images/galletas-de-avena-con-pasas-y-nuez.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/galletasmantequilla.jpg b/Pan&Code/frontend/public/images/galletasmantequilla.jpg deleted file mode 100644 index 338de8e..0000000 Binary files a/Pan&Code/frontend/public/images/galletasmantequilla.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/galletatresojos.png b/Pan&Code/frontend/public/images/galletatresojos.png deleted file mode 100644 index d616ab7..0000000 Binary files a/Pan&Code/frontend/public/images/galletatresojos.png and /dev/null differ diff --git a/Pan&Code/frontend/public/images/hojaldre bocadillo.jpeg b/Pan&Code/frontend/public/images/hojaldre bocadillo.jpeg deleted file mode 100644 index c9db65d..0000000 Binary files a/Pan&Code/frontend/public/images/hojaldre bocadillo.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/hojaldre pollo.jpeg b/Pan&Code/frontend/public/images/hojaldre pollo.jpeg deleted file mode 100644 index 3182845..0000000 Binary files a/Pan&Code/frontend/public/images/hojaldre pollo.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/hojaldre queso.jpeg b/Pan&Code/frontend/public/images/hojaldre queso.jpeg deleted file mode 100644 index 7b42ddc..0000000 Binary files a/Pan&Code/frontend/public/images/hojaldre queso.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/hojaldre1.jpg b/Pan&Code/frontend/public/images/hojaldre1.jpg deleted file mode 100644 index 288ac40..0000000 Binary files a/Pan&Code/frontend/public/images/hojaldre1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/iconoboton1.jpg b/Pan&Code/frontend/public/images/iconoboton1.jpg deleted file mode 100644 index a04dc73..0000000 Binary files a/Pan&Code/frontend/public/images/iconoboton1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/jugo.jpg b/Pan&Code/frontend/public/images/jugo.jpg deleted file mode 100644 index 4b790b2..0000000 Binary files a/Pan&Code/frontend/public/images/jugo.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/kumiss.1.png b/Pan&Code/frontend/public/images/kumiss.1.png deleted file mode 100644 index 64c516b..0000000 Binary files a/Pan&Code/frontend/public/images/kumiss.1.png and /dev/null differ diff --git a/Pan&Code/frontend/public/images/logo proyecto.jpeg b/Pan&Code/frontend/public/images/logo proyecto.jpeg deleted file mode 100644 index 0026376..0000000 Binary files a/Pan&Code/frontend/public/images/logo proyecto.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/logoprincipal.jpg b/Pan&Code/frontend/public/images/logoprincipal.jpg deleted file mode 100644 index 0026376..0000000 Binary files a/Pan&Code/frontend/public/images/logoprincipal.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/merengon.jpeg b/Pan&Code/frontend/public/images/merengon.jpeg deleted file mode 100644 index 59b10b6..0000000 Binary files a/Pan&Code/frontend/public/images/merengon.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/milhoja.jpeg b/Pan&Code/frontend/public/images/milhoja.jpeg deleted file mode 100644 index 34ff6ef..0000000 Binary files a/Pan&Code/frontend/public/images/milhoja.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/miloha_de_arequipe.jpg b/Pan&Code/frontend/public/images/miloha_de_arequipe.jpg deleted file mode 100644 index 2b5bb4e..0000000 Binary files a/Pan&Code/frontend/public/images/miloha_de_arequipe.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/muffins1.jpg b/Pan&Code/frontend/public/images/muffins1.jpg deleted file mode 100644 index 8b5766b..0000000 Binary files a/Pan&Code/frontend/public/images/muffins1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/napoleon.jpeg b/Pan&Code/frontend/public/images/napoleon.jpeg deleted file mode 100644 index af1f734..0000000 Binary files a/Pan&Code/frontend/public/images/napoleon.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/naranja.jpg b/Pan&Code/frontend/public/images/naranja.jpg deleted file mode 100644 index 49e6a48..0000000 Binary files a/Pan&Code/frontend/public/images/naranja.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/naranjaponque.jpg b/Pan&Code/frontend/public/images/naranjaponque.jpg deleted file mode 100644 index f4ed502..0000000 Binary files a/Pan&Code/frontend/public/images/naranjaponque.jpg and /dev/null differ diff --git "a/Pan&Code/frontend/public/images/pan alin\314\203ado.jpeg" "b/Pan&Code/frontend/public/images/pan alin\314\203ado.jpeg" deleted file mode 100644 index c997f05..0000000 Binary files "a/Pan&Code/frontend/public/images/pan alin\314\203ado.jpeg" and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pan blandito .jpeg b/Pan&Code/frontend/public/images/pan blandito .jpeg deleted file mode 100644 index f00869c..0000000 Binary files a/Pan&Code/frontend/public/images/pan blandito .jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pan campesino.jpeg b/Pan&Code/frontend/public/images/pan campesino.jpeg deleted file mode 100644 index fb1454c..0000000 Binary files a/Pan&Code/frontend/public/images/pan campesino.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pan coco.jpeg b/Pan&Code/frontend/public/images/pan coco.jpeg deleted file mode 100644 index 941fa72..0000000 Binary files a/Pan&Code/frontend/public/images/pan coco.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pan frances.jpeg b/Pan&Code/frontend/public/images/pan frances.jpeg deleted file mode 100644 index 3c7ec0f..0000000 Binary files a/Pan&Code/frontend/public/images/pan frances.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pan maiz.jpeg b/Pan&Code/frontend/public/images/pan maiz.jpeg deleted file mode 100644 index 2c63dae..0000000 Binary files a/Pan&Code/frontend/public/images/pan maiz.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pan queso.jpeg b/Pan&Code/frontend/public/images/pan queso.jpeg deleted file mode 100644 index 7f04f23..0000000 Binary files a/Pan&Code/frontend/public/images/pan queso.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pan rollo.jpeg b/Pan&Code/frontend/public/images/pan rollo.jpeg deleted file mode 100644 index 4bb0829..0000000 Binary files a/Pan&Code/frontend/public/images/pan rollo.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pan-con-masa-madre-.jpg b/Pan&Code/frontend/public/images/pan-con-masa-madre-.jpg deleted file mode 100644 index c5ddfe0..0000000 Binary files a/Pan&Code/frontend/public/images/pan-con-masa-madre-.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pan-de-molde.jpg b/Pan&Code/frontend/public/images/pan-de-molde.jpg deleted file mode 100644 index c934fc2..0000000 Binary files a/Pan&Code/frontend/public/images/pan-de-molde.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pan-rtzqhi1ok4k1bxlo.jpg b/Pan&Code/frontend/public/images/pan-rtzqhi1ok4k1bxlo.jpg deleted file mode 100644 index 5e48815..0000000 Binary files a/Pan&Code/frontend/public/images/pan-rtzqhi1ok4k1bxlo.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/panabuela1.jpg b/Pan&Code/frontend/public/images/panabuela1.jpg deleted file mode 100644 index 87ef700..0000000 Binary files a/Pan&Code/frontend/public/images/panabuela1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/panbaguette1.jpg b/Pan&Code/frontend/public/images/panbaguette1.jpg deleted file mode 100644 index 5ff2ab2..0000000 Binary files a/Pan&Code/frontend/public/images/panbaguette1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/panblando.jpeg b/Pan&Code/frontend/public/images/panblando.jpeg deleted file mode 100644 index 29e595a..0000000 Binary files a/Pan&Code/frontend/public/images/panblando.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pancampesino.png b/Pan&Code/frontend/public/images/pancampesino.png deleted file mode 100644 index a3b9481..0000000 Binary files a/Pan&Code/frontend/public/images/pancampesino.png and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pandebono.jpeg b/Pan&Code/frontend/public/images/pandebono.jpeg deleted file mode 100644 index 49e7df1..0000000 Binary files a/Pan&Code/frontend/public/images/pandebono.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pandebono.png b/Pan&Code/frontend/public/images/pandebono.png deleted file mode 100644 index 4cc61dd..0000000 Binary files a/Pan&Code/frontend/public/images/pandebono.png and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pangrande1.jpg b/Pan&Code/frontend/public/images/pangrande1.jpg deleted file mode 100644 index cd2c2ab..0000000 Binary files a/Pan&Code/frontend/public/images/pangrande1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/panhamburguesa.jpg b/Pan&Code/frontend/public/images/panhamburguesa.jpg deleted file mode 100644 index 9cd6656..0000000 Binary files a/Pan&Code/frontend/public/images/panhamburguesa.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pantrenza.jpg b/Pan&Code/frontend/public/images/pantrenza.jpg deleted file mode 100644 index b18b142..0000000 Binary files a/Pan&Code/frontend/public/images/pantrenza.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/panunidad1.jpg b/Pan&Code/frontend/public/images/panunidad1.jpg deleted file mode 100644 index e7e4f31..0000000 Binary files a/Pan&Code/frontend/public/images/panunidad1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/panunidad2.jpg b/Pan&Code/frontend/public/images/panunidad2.jpg deleted file mode 100644 index 051ad0d..0000000 Binary files a/Pan&Code/frontend/public/images/panunidad2.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/pastel carne.jpeg b/Pan&Code/frontend/public/images/pastel carne.jpeg deleted file mode 100644 index 8f14805..0000000 Binary files a/Pan&Code/frontend/public/images/pastel carne.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/ponquenaranja.png b/Pan&Code/frontend/public/images/ponquenaranja.png deleted file mode 100644 index b2f3ba2..0000000 Binary files a/Pan&Code/frontend/public/images/ponquenaranja.png and /dev/null differ diff --git a/Pan&Code/frontend/public/images/postreleche.jpg b/Pan&Code/frontend/public/images/postreleche.jpg deleted file mode 100644 index e6ce8bc..0000000 Binary files a/Pan&Code/frontend/public/images/postreleche.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/tamal de pollo .jpeg b/Pan&Code/frontend/public/images/tamal de pollo .jpeg deleted file mode 100644 index 5cf6a5b..0000000 Binary files a/Pan&Code/frontend/public/images/tamal de pollo .jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/tamal santandereano .jpeg b/Pan&Code/frontend/public/images/tamal santandereano .jpeg deleted file mode 100644 index de8911d..0000000 Binary files a/Pan&Code/frontend/public/images/tamal santandereano .jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/tamal tolimense.jpeg b/Pan&Code/frontend/public/images/tamal tolimense.jpeg deleted file mode 100644 index 112b376..0000000 Binary files a/Pan&Code/frontend/public/images/tamal tolimense.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/tamal1.jpg b/Pan&Code/frontend/public/images/tamal1.jpg deleted file mode 100644 index b9aa2fa..0000000 Binary files a/Pan&Code/frontend/public/images/tamal1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/tamales.jpg b/Pan&Code/frontend/public/images/tamales.jpg deleted file mode 100644 index b8b8d92..0000000 Binary files a/Pan&Code/frontend/public/images/tamales.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/torta chocolate.jpeg b/Pan&Code/frontend/public/images/torta chocolate.jpeg deleted file mode 100644 index 01800c2..0000000 Binary files a/Pan&Code/frontend/public/images/torta chocolate.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/torta tres leches.jpeg b/Pan&Code/frontend/public/images/torta tres leches.jpeg deleted file mode 100644 index 6406f12..0000000 Binary files a/Pan&Code/frontend/public/images/torta tres leches.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/torta zanahoria.jpeg b/Pan&Code/frontend/public/images/torta zanahoria.jpeg deleted file mode 100644 index 0e71597..0000000 Binary files a/Pan&Code/frontend/public/images/torta zanahoria.jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/torta1.jpg b/Pan&Code/frontend/public/images/torta1.jpg deleted file mode 100644 index d457539..0000000 Binary files a/Pan&Code/frontend/public/images/torta1.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/torta2.jpg b/Pan&Code/frontend/public/images/torta2.jpg deleted file mode 100644 index b04e62f..0000000 Binary files a/Pan&Code/frontend/public/images/torta2.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/tortachocolate.jpg b/Pan&Code/frontend/public/images/tortachocolate.jpg deleted file mode 100644 index 18ca9b6..0000000 Binary files a/Pan&Code/frontend/public/images/tortachocolate.jpg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/tortatresleches.png b/Pan&Code/frontend/public/images/tortatresleches.png deleted file mode 100644 index 72fa823..0000000 Binary files a/Pan&Code/frontend/public/images/tortatresleches.png and /dev/null differ diff --git a/Pan&Code/frontend/public/images/tres leches vaso .jpeg b/Pan&Code/frontend/public/images/tres leches vaso .jpeg deleted file mode 100644 index ff39005..0000000 Binary files a/Pan&Code/frontend/public/images/tres leches vaso .jpeg and /dev/null differ diff --git a/Pan&Code/frontend/public/images/yogurt1.jpg b/Pan&Code/frontend/public/images/yogurt1.jpg deleted file mode 100644 index 3d4c174..0000000 Binary files a/Pan&Code/frontend/public/images/yogurt1.jpg and /dev/null differ diff --git a/Proyecto b/Proyecto deleted file mode 160000 index f313186..0000000 --- a/Proyecto +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f313186ec2728c0483b8f60aa09e490c729aed8a diff --git a/Proyecto.zip b/Proyecto.zip new file mode 100644 index 0000000..b75100a Binary files /dev/null and b/Proyecto.zip differ diff --git a/Proyecto/.gitattributes b/Proyecto/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/Proyecto/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/Proyecto/.gitignore b/Proyecto/.gitignore new file mode 100644 index 0000000..667aaef --- /dev/null +++ b/Proyecto/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/Proyecto/.idea/.gitignore b/Proyecto/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/Proyecto/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/Proyecto/.idea/compiler.xml similarity index 100% rename from .idea/compiler.xml rename to Proyecto/.idea/compiler.xml diff --git a/.idea/encodings.xml b/Proyecto/.idea/encodings.xml similarity index 100% rename from .idea/encodings.xml rename to Proyecto/.idea/encodings.xml diff --git a/.idea/jarRepositories.xml b/Proyecto/.idea/jarRepositories.xml similarity index 100% rename from .idea/jarRepositories.xml rename to Proyecto/.idea/jarRepositories.xml diff --git a/Proyecto/.idea/misc.xml b/Proyecto/.idea/misc.xml new file mode 100644 index 0000000..81caee1 --- /dev/null +++ b/Proyecto/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/Proyecto/.idea/vcs.xml b/Proyecto/.idea/vcs.xml new file mode 100644 index 0000000..d843f34 --- /dev/null +++ b/Proyecto/.idea/vcs.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Proyecto/.mvn/wrapper/maven-wrapper.properties b/Proyecto/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..12fbe1e --- /dev/null +++ b/Proyecto/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip diff --git a/Proyecto/.vscode/settings.json b/Proyecto/.vscode/settings.json new file mode 100644 index 0000000..c5f3f6b --- /dev/null +++ b/Proyecto/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.configuration.updateBuildConfiguration": "interactive" +} \ No newline at end of file diff --git a/HELP.md b/Proyecto/HELP.md similarity index 100% rename from HELP.md rename to Proyecto/HELP.md diff --git a/Proyecto/PROYECTOPANADERIA.sql b/Proyecto/PROYECTOPANADERIA.sql new file mode 100644 index 0000000..1c0efb7 --- /dev/null +++ b/Proyecto/PROYECTOPANADERIA.sql @@ -0,0 +1,456 @@ +-- ================================================================== +-- DDL (DATA DEFINITION LANGUAGE) - DEFINICIÓN DE ESTRUCTURA +-- ================================================================== + +DROP DATABASE IF EXISTS ProyectoPanaderia; +SET SQL_SAFE_UPDATES = 0; +CREATE DATABASE ProyectoPanaderia; +USE ProyectoPanaderia; +CREATE TABLE Clientes ( + ID_CLIENTE INT PRIMARY KEY AUTO_INCREMENT, + NOMBRE_CLI VARCHAR(100) NOT NULL, + TELEFONO_CLI VARCHAR(20), + ACTIVO_CLI BOOLEAN DEFAULT TRUE, + EMAIL_CLI VARCHAR(100), + CONTRASEÑA_CLI VARCHAR(255), + FECHA_ULTIMA_MODIFICACION TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); + +-- Tabla: Empleados +CREATE TABLE Empleados ( + ID_EMPLEADO INT PRIMARY KEY AUTO_INCREMENT, + NOMBRE_EMPLEADO VARCHAR(100) NOT NULL, + EMAIL_EMPLEADO VARCHAR(100), + ACTIVO_EMPLEADO BOOLEAN DEFAULT TRUE, + CONTRASEÑA_EMPLEADO VARCHAR(255), + FECHA_REGISTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FECHA_ULTIMA_MODIFICACION TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); + +-- Tabla: Administradores +CREATE TABLE Administradores ( + ID_ADMIN INT PRIMARY KEY AUTO_INCREMENT, + NOMBRE_ADMIN VARCHAR(100) NOT NULL, + TELEFONO_ADMIN VARCHAR(20), + EMAIL_ADMIN VARCHAR(100), + CONTRASEÑA_ADMIN VARCHAR(255) +); + +-- Tabla: Proveedores +CREATE TABLE Proveedores ( + ID_PROVEEDOR INT PRIMARY KEY AUTO_INCREMENT, + NOMBRE_PROV VARCHAR(100) NOT NULL, + TELEFONO_PROV VARCHAR(20), + ACTIVO_PROV BOOLEAN DEFAULT TRUE, + EMAIL_PROV VARCHAR(100), + DIRECCION_PROV VARCHAR(200) +); + +-- Tabla: Pedidos_Proveedores - Almacena pedidos realizados a proveedores +CREATE TABLE Pedidos_Proveedores ( + ID_PEDIDO_PROV INT PRIMARY KEY AUTO_INCREMENT, + ID_PROVEEDOR INT NOT NULL, + NUMERO_PEDIDO INT NOT NULL, + FECHA_PEDIDO DATE NOT NULL, + ESTADO_PEDIDO VARCHAR(50) DEFAULT 'Pendiente', + CONSTRAINT FK_PEDIDO_PROVEEDOR + FOREIGN KEY (ID_PROVEEDOR) REFERENCES Proveedores(ID_PROVEEDOR) ON UPDATE CASCADE ON DELETE RESTRICT +); + +-- Tabla: Categoria_Productos - Almacena categorías de productos +CREATE TABLE Categoria_Productos ( + ID_CATEGORIA_PRODUCTO INT PRIMARY KEY AUTO_INCREMENT, + NOMBRE_CATEGORIAPRODUCTO VARCHAR(100) NOT NULL +); + +-- Tabla: Estado_Pedidos - Almacena estados de pedidos +CREATE TABLE Estado_Pedidos ( + ID_ESTADO_PEDIDO INT PRIMARY KEY AUTO_INCREMENT, + NOMBRE_ESTADO VARCHAR(50) +); + +-- Tabla: Categoria_Ingredientes +CREATE TABLE Categoria_Ingredientes ( + ID_CATEGORIA INT PRIMARY KEY AUTO_INCREMENT, + NOMBRE_CATEGORIA_INGREDIENTE VARCHAR(100) NOT NULL +); + +-- Tabla: Ingredientes +CREATE TABLE Ingredientes ( + ID_INGREDIENTE INT PRIMARY KEY AUTO_INCREMENT, + ID_PROVEEDOR INT, + ID_CATEGORIA INT, + NOMBRE_INGREDIENTE VARCHAR(100) NOT NULL, + CANTIDAD_INGREDIENTE INT, + FECHA_VENCIMIENTO DATE, + REFERENCIA_INGREDIENTE VARCHAR(100), + FECHA_ENTREGA_INGREDIENTE DATE, + CONSTRAINT FK_PROVEEDOR_INGREDIENTE + FOREIGN KEY (ID_PROVEEDOR) REFERENCES Proveedores(ID_PROVEEDOR) ON UPDATE CASCADE ON DELETE RESTRICT, + CONSTRAINT FK_CATEGORIA_INGREDIENTE + FOREIGN KEY (ID_CATEGORIA) REFERENCES Categoria_Ingredientes(ID_CATEGORIA) ON UPDATE CASCADE ON DELETE RESTRICT +); + +-- Tabla: Productos +CREATE TABLE Productos ( + ID_PRODUCTO INT PRIMARY KEY AUTO_INCREMENT, + ID_ADMIN INT, + ID_CATEGORIA_PRODUCTO INT, + NOMBRE_PRODUCTO VARCHAR(100) NOT NULL, + DESCRIPCION_PRODUCTO TEXT, + PRODUCTO_STOCK_MIN INT, + PRECIO_PRODUCTO DECIMAL(10,2) NOT NULL, + FECHA_VENCIMIENTO_PRODUCTO DATE, + FECHA_INGRESO_PRODUCTO DATE, + TIPO_PRODUCTO_MARCA VARCHAR(100), + ACTIVO BOOLEAN DEFAULT TRUE, + FECHA_ULTIMA_MODIFICACION TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + CONSTRAINT FK_CATEGORIA_PRODUCTO + FOREIGN KEY (ID_CATEGORIA_PRODUCTO) REFERENCES Categoria_Productos(ID_CATEGORIA_PRODUCTO) ON UPDATE CASCADE ON DELETE RESTRICT, + CONSTRAINT FK_ADMIN_PRODUCTO + FOREIGN KEY (ID_ADMIN) REFERENCES Administradores(ID_ADMIN) ON UPDATE CASCADE ON DELETE RESTRICT +); + +-- Tabla: Pedidos +CREATE TABLE Pedidos ( + ID_PEDIDO INT PRIMARY KEY AUTO_INCREMENT, + ID_CLIENTE INT, + ID_EMPLEADO INT, + ID_ESTADO_PEDIDO INT, + FECHA_INGRESO DATETIME, + FECHA_ENTREGA DATETIME, + TOTAL_PRODUCTO DECIMAL(10,2), + CONSTRAINT FK_CLIENTE_PEDIDO + FOREIGN KEY (ID_CLIENTE) REFERENCES Clientes(ID_CLIENTE) ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT FK_EMPLEADO_PEDIDO + FOREIGN KEY (ID_EMPLEADO) REFERENCES Empleados(ID_EMPLEADO) ON UPDATE CASCADE ON DELETE RESTRICT, + CONSTRAINT FK_ESTADO_PEDIDO_PEDIDO + FOREIGN KEY (ID_ESTADO_PEDIDO) REFERENCES Estado_Pedidos(ID_ESTADO_PEDIDO) ON UPDATE CASCADE ON DELETE RESTRICT +); + +-- Tabla: Detalle_Pedidos +CREATE TABLE Detalle_Pedidos ( + ID_DETALLE INT PRIMARY KEY AUTO_INCREMENT, + ID_PEDIDO INT NOT NULL, + ID_PRODUCTO INT NOT NULL, + CANTIDAD_PRODUCTO INT, + PRECIO_UNITARIO DECIMAL(10,2), + SUBTOTAL DECIMAL(10,2), + CONSTRAINT FK_DETALLE_PEDIDO + FOREIGN KEY (ID_PEDIDO) REFERENCES Pedidos(ID_PEDIDO) ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT FK_DETALLE_PRODUCTO + FOREIGN KEY (ID_PRODUCTO) REFERENCES Productos(ID_PRODUCTO) ON UPDATE CASCADE ON DELETE RESTRICT +); + +-- Tabla: Ordenes_Salida +CREATE TABLE Ordenes_Salida ( + ID_FACTURA INT PRIMARY KEY AUTO_INCREMENT, + ID_CLIENTE INT, + ID_PEDIDO INT, + FECHA_FACTURACION DATETIME, + TOTAL_FACTURA DECIMAL(10,2), + CONSTRAINT FK_ORDENSALIDA_CLIENTE + FOREIGN KEY (ID_CLIENTE) REFERENCES Clientes(ID_CLIENTE) ON UPDATE CASCADE ON DELETE CASCADE, + CONSTRAINT FK_ORDENSALIDA_PEDIDO + FOREIGN KEY (ID_PEDIDO) REFERENCES Pedidos(ID_PEDIDO) ON UPDATE CASCADE ON DELETE CASCADE +); + +-- Función: HashPassword (simplificada sin salt) +DELIMITER // +CREATE FUNCTION HashPassword(password VARCHAR(255)) +RETURNS VARCHAR(255) +READS SQL DATA +DETERMINISTIC +BEGIN + RETURN SHA2(password, 256); +END// +DELIMITER ; + +-- Trigger: Actualizar fecha de modificación de productos +DELIMITER // +CREATE TRIGGER tr_actualizar_fecha_producto + BEFORE UPDATE ON Productos + FOR EACH ROW +BEGIN + SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP; +END// +DELIMITER ; + +-- Trigger: Actualizar total del pedido cuando se inserta detalle +DELIMITER // +CREATE TRIGGER tr_actualizar_total_pedido +AFTER INSERT ON Detalle_Pedidos +FOR EACH ROW +BEGIN + UPDATE Pedidos + SET TOTAL_PRODUCTO = ( + SELECT SUM(SUBTOTAL) + FROM Detalle_Pedidos + WHERE ID_PEDIDO = NEW.ID_PEDIDO + ) + WHERE ID_PEDIDO = NEW.ID_PEDIDO; +END// +DELIMITER ; + +-- Trigger: Actualizar total del pedido cuando se modifica detalle +DELIMITER // +CREATE TRIGGER tr_actualizar_total_pedido_update +AFTER UPDATE ON Detalle_Pedidos +FOR EACH ROW +BEGIN + UPDATE Pedidos + SET TOTAL_PRODUCTO = ( + SELECT SUM(SUBTOTAL) + FROM Detalle_Pedidos + WHERE ID_PEDIDO = NEW.ID_PEDIDO + ) + WHERE ID_PEDIDO = NEW.ID_PEDIDO; +END// +DELIMITER ; + +-- Trigger: Auditoría - Actualizar fecha de modificación de clientes +DELIMITER // +CREATE TRIGGER tr_clientes_fecha_modificacion + BEFORE UPDATE ON Clientes + FOR EACH ROW +BEGIN + SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP; +END// +DELIMITER ; + +-- Trigger: Auditoría - Actualizar fecha de modificación de empleados +DELIMITER // +CREATE TRIGGER tr_empleados_fecha_modificacion + BEFORE UPDATE ON Empleados + FOR EACH ROW +BEGIN + SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP; +END// +DELIMITER ; + +-- Trigger: Validación de email para clientes +DELIMITER // +CREATE TRIGGER tr_clientes_validar_email + BEFORE INSERT ON Clientes + FOR EACH ROW +BEGIN + IF NEW.EMAIL_CLI IS NOT NULL AND NEW.EMAIL_CLI NOT REGEXP '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$' THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Email inválido para cliente'; + END IF; +END// +DELIMITER ; + +-- Trigger: Validación de email para empleados +DELIMITER // +CREATE TRIGGER tr_empleados_validar_email + BEFORE INSERT ON Empleados + FOR EACH ROW +BEGIN + IF NEW.EMAIL_EMPLEADO IS NOT NULL AND NEW.EMAIL_EMPLEADO NOT REGEXP '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$' THEN + SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Email inválido para empleado'; + END IF; +END// +DELIMITER ; + +-- ================================================================== +-- DML (DATA MANIPULATION LANGUAGE) - INSERCIÓN DE DATOS +-- ================================================================== + +-- ================================================================== +-- INSERCIÓN DE DATOS BASE +-- ================================================================== + +-- Inserción en tabla: Clientes +INSERT INTO Clientes (NOMBRE_CLI, TELEFONO_CLI, EMAIL_CLI) VALUES +('Ana Pérez', '3101234567', 'ana.p@mail.com'), +('Luis Gómez', '3209876543', 'luis.g@mail.com'), +('Maria Rodriguez', '3001122334', 'maria.r@mail.com'); + +-- Inserción en tabla: Empleados +INSERT INTO Empleados (NOMBRE_EMPLEADO) VALUES +('Andres Alkaeda'), +('Damian Avila'), +('Brayan Jimenez'), +('Ana Goyeneche'), +('Sharyt Zamora'), +('Carlos Mendoza'), +('Sofia Rodriguez'), +('Miguel Torres'), +('Valentina Castro'), +('Diego Herrera'), +('Camila Vargas'), +('Alejandro Morales'), +('Isabella Gutierrez'), +('Sebastian Ramirez'), +('Natalia Delgado'); + +-- Inserción en tabla: Administradores +INSERT INTO Administradores (NOMBRE_ADMIN, TELEFONO_ADMIN, EMAIL_ADMIN) VALUES +('Admin Uno', '3005550101', 'admin1@store.com'); + +-- Inserción en tabla: Proveedores +INSERT INTO Proveedores (ID_PROVEEDOR, NOMBRE_PROV, TELEFONO_PROV, EMAIL_PROV) VALUES +(1, 'Harina Dorada', '3001234567', 'ventas@harinadorada.com'), +(2, 'Dulce Granero', '3007654321', 'pedidos@dulcegranero.com'), +(3, 'El Horno Mágico S.A.S.', '3009876543', 'contacto@hornoimagico.com'), +(4, 'Masa Maestra Distribuciones', '3005555555', 'info@masamaestra.com'), +(5, 'Insumos Panaderos del Sol', '3002222222', 'ventas@insumossol.com'), +(6, 'La Esencia del Pan', '3003333333', 'pedidos@esenciapan.com'), +(7, 'Proveedora Integral del Panadero', '3004444444', 'contacto@provintegral.com'), +(8, 'Alimentos para Hornear Cía. Ltda.', '3006666666', 'ventas@alimentoshornear.com'); + +-- Inserción en tabla: Pedidos_Proveedores +INSERT INTO Pedidos_Proveedores (ID_PROVEEDOR, NUMERO_PEDIDO, FECHA_PEDIDO, ESTADO_PEDIDO) VALUES +(1, 1001, '2024-01-15', 'Entregado'), +(2, 1002, '2024-02-10', 'Entregado'), +(3, 1003, '2024-03-05', 'Entregado'); + +-- Inserción en tabla: Categoria_Productos +INSERT INTO Categoria_Productos (NOMBRE_CATEGORIAPRODUCTO) VALUES +('Tortas Tres Leches'), +('Tortas Milyway'), +('Tortas por Encargo'), +('Pan Grande'), +('Pan Pequeño'), +('Postres'), +('Galletas'), +('Tamales'), +('Yogures'), +('Pasteles Pollo'); + +-- Inserción en tabla: Estado_Pedidos +INSERT INTO Estado_Pedidos (NOMBRE_ESTADO) VALUES +('Pendiente'), +('En Preparación'), +('Listo para Entrega'), +('Entregado'), +('Cancelado'); + +-- Inserción en tabla: Categoria_Ingredientes +INSERT INTO `categoria_ingredientes` (`ID_CATEGORIA`, `NOMBRE_CATEGORIA_INGREDIENTE`) VALUES +('1', 'Harinas'), +('2', 'Lácteos y Derivados'), +('3', 'Azúcares y Endulzantes'), +('4', 'Grasas'), +('5', 'Esencias'), +('6', 'Fruta'), +('7', 'Frutos Secos'), +('8', 'Levaduras'), +('9', 'Huevos'), +('10', 'Chocolate y Cacao'), +('11', 'Espesantes y Gelificantes'), +('12', 'Colorantes Alimentarios'), +('13', 'Sal'), +('14', 'Aditivos y Mejoradores'), +('15', 'Semillas'), +('16', 'Coberturas y Rellenos'); + +-- Inserción en tabla: Ingredientes +INSERT INTO Ingredientes (ID_INGREDIENTE, ID_PROVEEDOR, ID_CATEGORIA, NOMBRE_INGREDIENTE, CANTIDAD_INGREDIENTE, FECHA_VENCIMIENTO, REFERENCIA_INGREDIENTE, FECHA_ENTREGA_INGREDIENTE) VALUES +(1, 2, 1, 'Harina de Trigo', 100, '2025-12-20', 'HAR-TRG-05', '2025-07-01'), +(2, 1, 2, 'Leche Entera UHT', 30, '2025-08-01', 'LECH-ENT-1L', '2025-07-01'), +(3, 3, 3, 'Azúcar Blanca', 70, '2026-01-30', 'AZUC-BLN-KG', '2025-07-01'), +(4, 4, 4, 'Mantequilla sin Sal', 25, '2025-09-15', 'MANT-SS-KG', '2025-07-01'), +(5, 5, 9, 'Huevos Grandes', 120, '2025-07-25', 'HUEV-GR-DZ', '2025-07-01'), +(6, 6, 10, 'Chocolate Semi-Amargo (Gotas)', 15, '2026-03-10', 'CHOC-SM-KG', '2025-07-01'), +(7, 7, 8, 'Levadura Fresca', 5, '2025-07-10', 'LEV-FRES-GR', '2025-07-01'), +(8, 1, 3, 'Azúcar Moreno', 10, '2026-02-20', 'AZUC-MRN-KG', '2025-07-01'), +(9, 2, 1, 'Harina Integral', 50, '2025-11-01', 'HAR-INT-02', '2025-07-01'), +(10, 3, 4, 'Aceite Vegetal', 20, '2026-05-01', 'ACET-VEG-LT', '2025-07-01'), +(11, 4, 10, 'Cacao en Polvo', 8, '2026-04-15', 'CACAO-POL-KG', '2025-07-01'), +(12, 5, 6, 'Manzanas Verdes (Kg)', 10, '2025-07-12', 'MANZ-VRD-KG', '2025-07-01'), +(13, 6, 7, 'Nueces Picadas', 5, '2025-10-01', 'NUEZ-PIC-KG', '2025-07-01'), +(14, 7, 5, 'Esencia de Vainilla', 2, '2027-01-01', 'ESEN-VN-LT', '2025-07-01'), +(15, 8, 13, 'Sal Fina', 2, '2028-01-01', 'SAL-FIN-KG', '2025-07-01'), +(16, 1, 2, 'Crema de Leche', 5, '2025-08-05', 'CREM-LECH-LT', '2025-07-01'), +(17, 2, 11, 'Gelatina sin Sabor', 1, '2026-09-01', 'GEL-SS-KG', '2025-07-01'), +(18, 3, 12, 'Colorante Alimentario Rojo', 0.5, '2027-03-01', 'COLR-ROJ-ML', '2025-07-01'), +(19, 4, 15, 'Semillas de Sésamo', 3, '2026-06-01', 'SEM-SES-KG', '2025-07-01'), +(20, 5, 16, 'Dulce de Leche', 10, '2025-11-15', 'DDL-KG', '2025-07-01'); + +-- Inserción en tabla: Productos +INSERT INTO Productos (ID_PRODUCTO, ID_ADMIN, ID_CATEGORIA_PRODUCTO, NOMBRE_PRODUCTO, DESCRIPCION_PRODUCTO, PRODUCTO_STOCK_MIN, PRECIO_PRODUCTO, FECHA_VENCIMIENTO_PRODUCTO, FECHA_INGRESO_PRODUCTO, TIPO_PRODUCTO_MARCA) VALUES +(1, 1, 8, 'Tamales Tolimenses', 'Tradicionales tamales envueltos en hoja de plátano, con masa de maíz y relleno de carne de cerdo y pollo', 10, 3800.00, '2025-09-15', '2025-07-01', 'Propio'), +(2, 1, 4, 'Pan Tajado Integral', 'Pan de molde integral, ideal para desayunos saludables, rico en fibra', 15, 4200.00, '2025-07-02', '2025-07-01', 'Propio'), +(3, 1, 7, 'Yogurt Fresa Litro', 'Yogurt cremoso con trozos de fresa natural, sin conservantes artificiales', 12, 6000.00, '2025-07-30', '2025-07-03', 'Alpina'), +(4, 1, 5, 'Galleta de Tres Ojos', 'Galleta tradicional colombiana con tres círculos de dulce, crujiente y deliciosa', 20, 2500.00, '2025-11-01', '2025-07-01', 'Propio'), +(5, 1, 1, 'Pan Campesino Grande', 'Pan artesanal de corteza dorada y miga suave, ideal para acompañar comidas', 8, 5500.00, '2025-07-08', '2025-07-04', 'Propio'), +(6, 1, 3, 'Torta de Chocolate Pequeña', 'Deliciosa torta de chocolate húmeda con cobertura de chocolate, perfecta para ocasiones especiales', 5, 18000.00, '2025-07-07', '2025-07-04', 'Propio'), +(7, 1, 2, 'Croissant de Almendras', NULL, 18, 3500.00, '2025-07-06', '2025-07-05', 'Propio'), +(8, 1, 1, 'Baguette Clásica', 'Pan francés tradicional con corteza crujiente y miga aireada', 25, 2800.00, '2025-07-06', '2025-07-05', 'Propio'), +(9, 1, 5, 'Bizcochos de Achira', NULL, 15, 4000.00, '2025-12-01', '2025-07-01', 'Propio'), +(10, 1, 6, 'Jugo de Naranja Natural (500ml)', 'Jugo 100% natural exprimido de naranjas frescas, sin azúcar añadido', 10, 4500.00, '2025-07-05', '2025-07-04', 'Postobón'), +(11, 1, 7, 'Postre de Tres Leches', 'Clásico postre colombiano empapado en tres tipos de leche, suave y cremoso', 7, 7500.00, '2025-07-08', '2025-07-04', 'Propio'), +(12, 1, 4, 'Pan Blanco de Molde', NULL, 20, 3900.00, '2025-07-02', '2025-07-01', 'Propio'), +(13, 1, 3, 'Muffin de Arándanos', 'Muffin esponjoso con arándanos frescos, perfecto para el desayuno o merienda', 15, 3000.00, '2025-07-07', '2025-07-04', 'Propio'), +(14, 1, 2, 'Pan de Bono Pequeño', NULL, 30, 1500.00, '2025-07-06', '2025-07-05', 'Propio'), +(15, 1, 8, 'Empanadas de Carne (unidad)', 'Empanada frita rellena de carne molida sazonada con especias tradicionales', 20, 2000.00, '2025-07-06', '2025-07-05', 'Propio'), +(16, 1, 3, 'Brazo de Reina', 'Bizcocho enrollado relleno de dulce de leche y cubierto con coco rallado', 10, 9500.00, '2025-07-09', '2025-07-04', 'Propio'), +(17, 1, 1, 'Pan Trenza Integral', NULL, 12, 4800.00, '2025-07-07', '2025-07-03', 'Propio'), +(18, 1, 5, 'Galletas Surtidas de Mantequilla', 'Variedad de galletas caseras de mantequilla con diferentes formas y sabores', 25, 3200.00, '2025-12-30', '2025-07-01', 'Propio'), +(19, 1, 7, 'Avena La Lechera (500ml)', NULL, 18, 5800.00, '2025-08-20', '2025-07-03', 'Nestlé'), +(20, 1, 9, 'Ponqué de Naranja (Porción)', 'Porción individual de ponqué de naranja con glaseado cítrico', 15, 3000.00, '2025-07-08', '2025-07-04', 'Propio'), +(21, 1, 10, 'Pan Artesanal de Masa Madre', 'Pan elaborado con masa madre natural, fermentación larga para mejor digestibilidad', 7, 8000.00, '2025-07-07', '2025-07-05', 'Propio'), +(22, 1, 3, 'Cheesecake de Frutos Rojos', 'Cheesecake cremoso con base de galleta y cobertura de frutos rojos frescos', 6, 25000.00, '2025-07-09', '2025-07-04', 'Propio'), +(23, 1, 4, 'Pan de Hamburguesa', NULL, 30, 4500.00, '2025-07-10', '2025-07-02', 'Propio'), +(24, 1, 5, 'Galletas de Avena y Pasas', 'Galletas nutritivas con avena integral y pasas, sin azúcar refinado', 22, 2700.00, '2026-01-01', '2025-07-01', 'Propio'), +(25, 1, 7, 'Kumiss Natural', NULL, 10, 4900.00, '2025-07-25', '2025-07-03', 'Alquería'), +(26, 1, 9, 'Brownie con Nuez', 'Brownie de chocolate intenso con trozos de nuez, húmedo y delicioso', 40, 1800.00, '2025-07-08', '2025-07-05', 'Propio'), +(27, 1, 1, 'Pan Blandito', NULL, 28, 2500.00, '2025-07-07', '2025-07-05', 'Propio'), +(28, 1, 3, 'Milhoja de Arequipe', 'Delicada milhoja rellena de arequipe casero y cubierta con azúcar glass', 12, 6000.00, '2025-07-08', '2025-07-04', 'Propio'), +(29, 1, 2, 'Mogolla Chicharrona', NULL, 15, 3500.00, '2025-07-06', '2025-07-05', 'Propio'), +(30, 1, 8, 'Arequipe (Tarro 500g)', 'Arequipe casero cremoso y dulce, perfecto para postres y acompañamientos', 8, 9000.00, '2026-04-10', '2025-07-01', 'Propio'); + +-- Inserción en tabla: Pedidos +INSERT INTO Pedidos (ID_CLIENTE, ID_EMPLEADO, ID_ESTADO_PEDIDO, FECHA_INGRESO, FECHA_ENTREGA, TOTAL_PRODUCTO) VALUES +(1, 1, 2, '2025-06-20 09:00:00', '2025-06-20 15:00:00', 10000.00), +(2, 2, 4, '2025-06-19 10:30:00', '2025-06-19 16:30:00', 7500.00), +(3, 1, 1, '2025-06-21 08:00:00', '2025-06-21 14:00:00', 12500.00); + +-- Inserción en tabla: Detalle_Pedidos +INSERT INTO Detalle_Pedidos (ID_PEDIDO, ID_PRODUCTO, CANTIDAD_PRODUCTO, PRECIO_UNITARIO, SUBTOTAL) VALUES +(1, 1, 2, 3500.00, 7000.00), +(1, 3, 1, 6000.00, 6000.00), +(2, 2, 1, 4200.00, 4200.00), +(2, 4, 3, 2500.00, 7500.00), +(3, 1, 3, 3500.00, 10500.00), +(3, 4, 2, 2500.00, 5000.00); + +-- Inserción en tabla: Ordenes_Salida +INSERT INTO Ordenes_Salida (ID_CLIENTE, ID_PEDIDO, FECHA_FACTURACION, TOTAL_FACTURA) VALUES +(1, 1, '2025-06-20 15:30:00', 13000.00), +(2, 2, '2025-06-19 17:00:00', 11700.00), +(3, 3, '2025-06-21 14:30:00', 15500.00); + +-- ================================================================== +-- DCL (DATA CONTROL LANGUAGE) - SEGURIDAD Y ENCRIPTACIÓN +-- ================================================================== + +-- Actualizar contraseñas de administradores con encriptación (sin salt) +UPDATE Administradores +SET CONTRASEÑA_ADMIN = HashPassword('admin123') +WHERE ID_ADMIN = 1; + +-- Actualizar contraseñas de clientes con encriptación (sin salt) +UPDATE Clientes +SET CONTRASEÑA_CLI = HashPassword('cliente123') +WHERE ID_CLIENTE = 1; + +UPDATE Clientes +SET CONTRASEÑA_CLI = HashPassword('cliente456') +WHERE ID_CLIENTE = 2; + +UPDATE Clientes +SET CONTRASEÑA_CLI = HashPassword('cliente789') +WHERE ID_CLIENTE = 3; + +-- Actualizar contraseñas de empleados con encriptación (sin salt) +UPDATE Empleados +SET CONTRASEÑA_EMPLEADO = HashPassword('empleado123') +WHERE ID_EMPLEADO = 1; + +UPDATE Empleados +SET CONTRASEÑA_EMPLEADO = HashPassword('empleado456') +WHERE ID_EMPLEADO = 2; + +COMMIT; \ No newline at end of file diff --git a/Proyecto/mvnw b/Proyecto/mvnw new file mode 100644 index 0000000..19529dd --- /dev/null +++ b/Proyecto/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/Proyecto/mvnw.cmd b/Proyecto/mvnw.cmd new file mode 100644 index 0000000..249bdf3 --- /dev/null +++ b/Proyecto/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/Proyecto/pom.xml b/Proyecto/pom.xml new file mode 100644 index 0000000..7e9881b --- /dev/null +++ b/Proyecto/pom.xml @@ -0,0 +1,90 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.5.4 + + + com.example + Proyecto + 0.0.1-SNAPSHOT + Proyecto + Demo project for Spring Boot + + + + + + + + + + + + + + + 21 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security + spring-security-crypto + + + org.springframework.boot + spring-boot-starter-jdbc + + + com.mysql + mysql-connector-j + runtime + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + org.mockito + mockito-core + 5.14.2 + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + 21 + 21 + + + + + \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/Controllers/ConexionController.java b/Proyecto/src/main/java/com/example/Proyecto/Controllers/ConexionController.java new file mode 100644 index 0000000..2dfb75e --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/Controllers/ConexionController.java @@ -0,0 +1,126 @@ +package com.example.Proyecto.Controllers; +import com.example.Proyecto.Services.Administrador.ConexionAdminService; +import com.example.Proyecto.Services.Administrador.PojoAdmin; +import com.example.Proyecto.Services.Clientes.ConexionClienteService; +import com.example.Proyecto.Services.Clientes.PojoCliente; +import com.example.Proyecto.Services.Empleados.ConexionEmpleadoService; +import com.example.Proyecto.Services.Empleados.PojoDeleteEmpleado; +import com.example.Proyecto.Services.Empleados.PojoEmpleado; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import java.util.List; +import java.util.Map; + + +@RequestMapping("/") +@RestController +public class ConexionController { + @Autowired + private ConexionAdminService conexionAdminService; + @Autowired + private ConexionEmpleadoService conexionEmpleadoService; + @Autowired + private ConexionClienteService conexionClienteService; + + // ----> Administradores GET + @GetMapping("/detalle/administrador") + public List> obtenerDetallesAdministrador() { + return conexionAdminService.obtenerDetallesAdministrador(); + } + // ----> Administradores POST + @PostMapping("/crear/administrador") + public String crearAdmin(@RequestBody PojoAdmin pojoAdmin) { + boolean creado = conexionAdminService.crearAdmin(pojoAdmin); + if (creado) { + return "Nuevo Administrador creado exitosamente"; + } else { + return "Error al crear un nuevo Administrador"; + } + } + + // ----> Administradores PATCH + @PatchMapping("/actualizar/administrador") + public ResponseEntity actualizarAdministrador(@RequestBody PojoAdmin pojoAdmin){ + boolean actualizado = conexionAdminService.actualizarAdministrador(pojoAdmin); + if(actualizado) { + return ResponseEntity.ok("El Administrador ha sido actualizado correctamente"); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("Error al actualizar el Administrador"); + } + } + + // ----> Clientes GET + @GetMapping("/detalle/cliente") + public List> obtenerDetallesCliente() { + return conexionClienteService.obtenerDetallesCliente(); + } + + // ----> Clientes POST + @PostMapping("/crear/cliente") + public String crearCliente(@RequestBody PojoCliente pojoCliente) { + boolean creado = conexionClienteService.crearCliente(pojoCliente); + if (creado) { + return "Nuevo Cliente creado exitosamente"; + } else { + return "Error al crear un nuevo Cliente"; + } + } + + // ----> Clientes PATCH + @PatchMapping("/actualizar/cliente/{id}") + public ResponseEntity actualizarCliente(@PathVariable int id, @RequestBody PojoCliente pojoCliente) { + pojoCliente.setId(id); + boolean actualizado = conexionClienteService.actualizarCliente(pojoCliente); + + if (actualizado) { + return ResponseEntity.ok("El Usuario ha sido actualizado correctamente"); + } else { + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body("No se encontró un usuario con el ID especificado"); + } + } + + // ----> Empleados GET + @GetMapping("/detalle/empleado") + public List> obtenerDetallesEmpleado(){ + return conexionEmpleadoService.obtenerDetallesEmpleado(); + } + + // ----> Empleados POST + @PostMapping("/crear/empleado") + public String crearEmpleado(@RequestBody PojoEmpleado pojoEmpleado) { + boolean creado = conexionEmpleadoService.crearEmpleado(pojoEmpleado); + if (creado) { + return "Nuevo Empleado creado exitosamente"; + } else { + return "Error al crear un nuevo Empleado"; + } + } + + // ----> Empleados UPDATE + @PatchMapping("/actualizar/empleado/{id}") + public ResponseEntity actualizarEmpleado(@PathVariable int id, @RequestBody PojoEmpleado pojoEmpleado){ + pojoEmpleado.setId(id); + boolean actualizado = conexionEmpleadoService.actualizarEmpleado(pojoEmpleado); + if(actualizado) { + return ResponseEntity.ok("El Empleado ha sido actualizado correctamente"); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("Error al actualizar el Empleado"); + } + } + + // ----> Empleados DELETE + @DeleteMapping("/eliminar/empleado") + public String eliminarEmpleado(@RequestBody PojoDeleteEmpleado pojoDeleteEmpleado) { + boolean eliminado = conexionEmpleadoService.eliminarEmpleado(pojoDeleteEmpleado.getId()); + if (eliminado) { + return "Empleado eliminado exitosamente"; + } else { + return "Error al eliminar el Empleado"; + } + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/ProyectoApplication.java b/Proyecto/src/main/java/com/example/Proyecto/ProyectoApplication.java new file mode 100644 index 0000000..e74f9ae --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/ProyectoApplication.java @@ -0,0 +1,13 @@ +package com.example.Proyecto; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ProyectoApplication { + + public static void main(String[] args) { + SpringApplication.run(ProyectoApplication.class, args); + } + +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/Services/Administrador/ConexionAdminService.java b/Proyecto/src/main/java/com/example/Proyecto/Services/Administrador/ConexionAdminService.java new file mode 100644 index 0000000..a989759 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/Services/Administrador/ConexionAdminService.java @@ -0,0 +1,65 @@ +package com.example.Proyecto.Services.Administrador; +import com.example.Proyecto.Services.Empleados.PojoEmpleado; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.jdbc.core.RowMapper; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class ConexionAdminService { + @Autowired + private JdbcTemplate jdbcTemplate; + @Autowired + private PasswordEncoder passwordEncoder; + + public List> obtenerDetallesAdministrador() { + String sql = "SELECT ID_ADMIN, NOMBRE_ADMIN, TELEFONO_ADMIN, EMAIL_ADMIN FROM Administradores"; + return jdbcTemplate.query(sql, new RowMapper>() { + @Override + public Map mapRow(ResultSet rs, int rowNum) throws SQLException { + Map administrador = new HashMap<>(); + administrador.put("Id:", rs.getInt("ID_ADMIN")); + administrador.put("Nombre:", rs.getString("NOMBRE_ADMIN")); + administrador.put("Correo Electronico:", rs.getString("EMAIL_ADMIN")); + administrador.put("Telefono:", rs.getString("TELEFONO_ADMIN")); + return administrador; + } + }); + } + + public boolean crearAdmin(PojoAdmin pojoAdmin) { + String sql = "INSERT INTO Administradores (NOMBRE_ADMIN, EMAIL_ADMIN, TELEFONO_ADMIN, CONTRASEÑA_ADMIN) VALUES (?, ?, ?, ?)"; + try { + if (pojoAdmin.getContrasena() == null || pojoAdmin.getContrasena().trim().isEmpty()) { + System.out.println("Error: La contraseña no puede ser nula o vacía"); + return false; + } + + String contrasenaHasheada = passwordEncoder.encode(pojoAdmin.getContrasena()); + int result = jdbcTemplate.update(sql, pojoAdmin.getNombre(), pojoAdmin.getEmail(), pojoAdmin.getTelefono(), contrasenaHasheada); + return result > 0; + } catch (DataAccessException e) { + return false; + } + } + + public boolean actualizarAdministrador(PojoAdmin pojoAdmin) { + String sql = "UPDATE Administradores SET NOMBRE_ADMIN = ?, EMAIL_ADMIN = ?, TELEFONO_ADMIN=?, CONTRASENA_ADMIN = ? WHERE ID_ADMIN = ?"; + try { + String contrasenaHasheada = passwordEncoder.encode(pojoAdmin.getContrasena()); + int value = jdbcTemplate.update( + sql, pojoAdmin.getNombre(), pojoAdmin.getEmail(), pojoAdmin.getTelefono(), contrasenaHasheada, pojoAdmin.getId()); + return value > 0; + } catch (DataAccessException e) { + e.printStackTrace(); + return false; + } + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/Services/Administrador/PojoAdmin.java b/Proyecto/src/main/java/com/example/Proyecto/Services/Administrador/PojoAdmin.java new file mode 100644 index 0000000..0f2eb82 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/Services/Administrador/PojoAdmin.java @@ -0,0 +1,51 @@ +package com.example.Proyecto.Services.Administrador; +public class PojoAdmin { + private int id; + private String nombre; + private String email; + private String telefono; + private String contrasena; + + public PojoAdmin() { + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getNombre() { + return nombre; + } + + public void setNombre(String nombre) { + this.nombre = nombre; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getTelefono() { + return telefono; + } + + public void setTelefono(String telefono) { + this.telefono = telefono; + } + + public String getContrasena() { + return contrasena; + } + + public void setContrasena(String contrasena) { + this.contrasena = contrasena; + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/Services/Clientes/ConexionClienteService.java b/Proyecto/src/main/java/com/example/Proyecto/Services/Clientes/ConexionClienteService.java new file mode 100644 index 0000000..6155f1e --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/Services/Clientes/ConexionClienteService.java @@ -0,0 +1,62 @@ +package com.example.Proyecto.Services.Clientes; +import com.example.Proyecto.Services.Empleados.PojoEmpleado; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; +import org.springframework.jdbc.core.RowMapper; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class ConexionClienteService { + @Autowired + private JdbcTemplate jdbcTemplate; + @Autowired + private PasswordEncoder passwordEncoder; + + public List> obtenerDetallesCliente() { + String sql = "SELECT TELEFONO_CLI, EMAIL_CLI, NOMBRE_CLI FROM Clientes"; + return jdbcTemplate.query(sql, new RowMapper>() { + @Override + public Map mapRow(ResultSet rs, int rowNum) throws SQLException { + Map cliente = new HashMap<>(); + cliente.put("Nombre:", rs.getString("NOMBRE_CLI")); + cliente.put("Correo Electronico:", rs.getString("EMAIL_CLI")); + cliente.put("Telefono:", rs.getString("TELEFONO_CLI")); + return cliente; + } + }); + } + + public boolean crearCliente(PojoCliente pojoCliente) { + String sql = "INSERT INTO Clientes (NOMBRE_CLI, EMAIL_CLI, TELEFONO_CLI, CONTRASENA_CLI) VALUES (?, ?, ?, ?)"; + try { + if (pojoCliente.getContrasena() == null || pojoCliente.getContrasena().trim().isEmpty()) { + System.out.println("Error: La contraseña no puede ser nula o vacía"); + return false; + } + String contrasenaHasheada = passwordEncoder.encode(pojoCliente.getContrasena()); + int result = jdbcTemplate.update(sql, pojoCliente.getNombre(), pojoCliente.getEmail(), pojoCliente.getTelefono(), contrasenaHasheada); + return result > 0; + } catch (DataAccessException e) { + return false; + } + } + public boolean actualizarCliente(PojoCliente pojoCliente) { + String sql = "UPDATE Clientes SET NOMBRE_CLI = ?, EMAIL_CLI = ?, TELEFONO_CLI = ?, CONTRASENA_CLI = ? WHERE ID_CLIENTE = ?"; + try { + String contrasenaHasheada = passwordEncoder.encode(pojoCliente.getContrasena()); + int value = jdbcTemplate.update(sql, pojoCliente.getNombre(), pojoCliente.getEmail(), pojoCliente.getTelefono(), contrasenaHasheada, pojoCliente.getId()); + return value > 0; + } catch (DataAccessException e) { + e.printStackTrace(); + return false; + } + } +} + diff --git a/Proyecto/src/main/java/com/example/Proyecto/Services/Clientes/PojoCliente.java b/Proyecto/src/main/java/com/example/Proyecto/Services/Clientes/PojoCliente.java new file mode 100644 index 0000000..98f74ad --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/Services/Clientes/PojoCliente.java @@ -0,0 +1,43 @@ +package com.example.Proyecto.Services.Clientes; + +public class PojoCliente { + private int id; + private String nombre; + private String email; + private String telefono; + private String contrasena; + + public PojoCliente() {} + + public int getId() {return id;} + + public void setId(int id) {this.id = id;} + + public String getNombre() { + return nombre; + } + + public void setNombre(String nombre) { + this.nombre = nombre; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getTelefono() { + return telefono; + } + + public void setTelefono(String telefono) { this.telefono = telefono; } + + public String getContrasena() { return contrasena; } + + public void setContrasena(String contrasena) {this.contrasena = contrasena;} +} + + diff --git a/Proyecto/src/main/java/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.java b/Proyecto/src/main/java/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.java new file mode 100644 index 0000000..ede0166 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.java @@ -0,0 +1,76 @@ +package com.example.Proyecto.Services.Empleados; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.jdbc.core.RowMapper; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service + +public class ConexionEmpleadoService { + @Autowired + private JdbcTemplate jdbcTemplate; + @Autowired + private PasswordEncoder passwordEncoder; + + public List> obtenerDetallesEmpleado() { + String sql = "SELECT ID_EMPLEADO, NOMBRE_EMPLEADO, EMAIL_EMPLEADO, ACTIVO_EMPLEADO FROM Empleados"; + return jdbcTemplate.query(sql, new RowMapper>() { + @Override + public Map mapRow(ResultSet rs, int rowNum) throws SQLException { + Map empleado = new HashMap<>(); + empleado.put("Id:", rs.getInt("ID_EMPLEADO")); + empleado.put("Nombre:", rs.getString("NOMBRE_EMPLEADO")); + empleado.put("Correo Electronico:", rs.getString("EMAIL_EMPLEADO")); + + int estado = rs.getInt("ACTIVO_EMPLEADO"); + String estadoTexto = (estado == 1) ? "ACTIVO" : "INACTIVO"; + empleado.put("Estado del Empleado", estadoTexto); + return empleado; + } + }); + } + + public boolean crearEmpleado(PojoEmpleado pojoEmpleado) { + String sql = "INSERT INTO Empleados (ID_EMPLEADO, NOMBRE_EMPLEADO, EMAIL_EMPLEADO, CONTRASENA_EMPLEADO) VALUES (?, ?, ?, ?)"; + try { + if (pojoEmpleado.getContrasena() == null || pojoEmpleado.getContrasena().trim().isEmpty()) { + System.out.println("Error: La contraseña no puede ser nula o vacía"); + return false; + } + String contrasenaHasheada = passwordEncoder.encode(pojoEmpleado.getContrasena()); + int result = jdbcTemplate.update(sql, pojoEmpleado.getId(), pojoEmpleado.getNombre(), pojoEmpleado.getEmail(), contrasenaHasheada); + return result > 0; + } finally { + } + } + + public boolean eliminarEmpleado(Long id) { + String sql = "DELETE FROM Empleados WHERE ID_EMPLEADO = ?"; + try { + int value = jdbcTemplate.update(sql, id); + return value > 0; + } catch (DataAccessException e) { + return false; + } + } + + public boolean actualizarEmpleado(PojoEmpleado pojoEmpleado) { + String sql = "UPDATE Empleados SET NOMBRE_EMPLEADO = ?, EMAIL_EMPLEADO = ?, CONTRASENA_EMPLEADO = ? WHERE ID_EMPLEADO = ?"; + try { + String contrasenaHasheada = passwordEncoder.encode(pojoEmpleado.getContrasena()); + int value = jdbcTemplate.update( + sql, pojoEmpleado.getNombre(), pojoEmpleado.getEmail(), contrasenaHasheada, pojoEmpleado.getId()); + return value > 0; + } catch (DataAccessException e) { + e.printStackTrace(); + return false; + } + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.java b/Proyecto/src/main/java/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.java new file mode 100644 index 0000000..32e04a3 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.java @@ -0,0 +1,19 @@ +package com.example.Proyecto.Services.Empleados; + +public class PojoDeleteEmpleado { + + private Long id; + + public PojoDeleteEmpleado() {} + + public PojoDeleteEmpleado(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + } diff --git a/Proyecto/src/main/java/com/example/Proyecto/Services/Empleados/PojoEmpleado.java b/Proyecto/src/main/java/com/example/Proyecto/Services/Empleados/PojoEmpleado.java new file mode 100644 index 0000000..8728be7 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/Services/Empleados/PojoEmpleado.java @@ -0,0 +1,44 @@ +package com.example.Proyecto.Services.Empleados; + +public class PojoEmpleado { + private int id; + private String nombre; + private String email; + private String contrasena; + + public PojoEmpleado() { + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getNombre() { + return nombre; + } + + public void setNombre(String nombre) { + this.nombre = nombre; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + + public String getContrasena(){ + return contrasena; + } + + public void setContrasena(String contrasena){ + this.contrasena = contrasena; + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/config/SecurityConfig.java b/Proyecto/src/main/java/com/example/Proyecto/config/SecurityConfig.java new file mode 100644 index 0000000..0b53bae --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/config/SecurityConfig.java @@ -0,0 +1,31 @@ +package com.example.Proyecto.config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; + + @Configuration + @EnableWebSecurity + public class SecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(authorize -> authorize + .anyRequest().permitAll() + ) + .csrf(csrf -> csrf.disable()) + .formLogin(form -> form.disable()) + .httpBasic(basic -> basic.disable()) + .logout(logout -> logout.disable()); + return http.build(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + } diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/CategoriaIngredientesController.java b/Proyecto/src/main/java/com/example/Proyecto/controller/CategoriaIngredientesController.java new file mode 100644 index 0000000..379a40a --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/CategoriaIngredientesController.java @@ -0,0 +1,53 @@ +package com.example.Proyecto.controller; +import com.example.Proyecto.controller.CategoriaIngredientesController; +import com.example.Proyecto.service.CategoriaIngredientesService.CategoriaIngredientes; +import com.example.Proyecto.controller.CategoriaIngredientesController; +import com.example.Proyecto.service.CategoriaIngredientesService.CategoriaIngredientesService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import java.util.List; + +@RestController +@RequestMapping +public class CategoriaIngredientesController { + + @Autowired + private CategoriaIngredientesService categoriaIngredientesService; + + // GET - Obtener todas las categorías de ingredientes + @GetMapping("/categorias/ingredientes") + public List obtenerTodasLasCategoriasIngredientes() { + return categoriaIngredientesService.obtenerTodasLasCategoriasIngredientes(); + } + + // POST - Crear una nueva categoría de ingrediente + @PostMapping("/nuevacategoriaingrediente") + public ResponseEntity crearCategoriaIngrediente(@RequestBody CategoriaIngredientes categoria) { + categoriaIngredientesService.crearCategoriaIngrediente(categoria); + return ResponseEntity.ok("Categoría " + categoria.getNombreCategoria() + " creada con éxito."); + } + + // PUT - Actualizar una categoría existente + @PutMapping("categoriaingrediente/{id}") + public ResponseEntity editarCategoriaIngrediente(@PathVariable int id, @RequestBody CategoriaIngredientes categoria) { + categoria.setIdCategoriaIngrediente(id); + int filas = categoriaIngredientesService.editarCategoriaIngrediente(categoria); + if (filas > 0) { + return ResponseEntity.ok("Categoría de ingrediente con ID " + id + " actualizada correctamente."); + } else { + return ResponseEntity.notFound().build(); + } + } + + // DELETE - Eliminar una categoría por ID + @DeleteMapping("eliminarcategoria/{id}") + public ResponseEntity eliminarCategoriaIngrediente(@PathVariable int id) { + int filas = categoriaIngredientesService.eliminarCategoriaIngrediente(id); + if (filas > 0) { + return ResponseEntity.ok("Categoría de ingrediente con ID " + id + " eliminada correctamente."); + } else { + return ResponseEntity.notFound().build(); + } + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/ConexionControllerUsers.java b/Proyecto/src/main/java/com/example/Proyecto/controller/ConexionControllerUsers.java new file mode 100644 index 0000000..3e062b2 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/ConexionControllerUsers.java @@ -0,0 +1,122 @@ +package com.example.Proyecto.controller; +import com.example.Proyecto.service.Clientes.ConexionClienteService; +import com.example.Proyecto.service.Administrador.ConexionAdminService; +import com.example.Proyecto.model.PojoAdmin; +import com.example.Proyecto.model.PojoCliente; +import com.example.Proyecto.service.Empleados.ConexionEmpleadoService; +import com.example.Proyecto.model.PojoDeleteEmpleado; +import com.example.Proyecto.model.PojoEmpleado; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import java.util.List; +import java.util.Map; + + +@RequestMapping("/") +@RestController +public class ConexionControllerUsers { + @Autowired + private ConexionAdminService conexionAdminService; + @Autowired + private ConexionEmpleadoService conexionEmpleadoService; + @Autowired + private ConexionClienteService conexionClienteService; + + + // ----> Administradores GET + @GetMapping("/detalle/administrador") + public List> obtenerDetallesAdministrador() { + return conexionAdminService.obtenerDetallesAdministrador(); + } + // ----> Administradores POST + @PostMapping("/crear/administrador") + public String crearAdmin(@RequestBody PojoAdmin pojoAdmin) { + boolean creado = conexionAdminService.crearAdmin(pojoAdmin); + if (creado) { + return "Nuevo Administrador creado exitosamente"; + } else { + return "Error al crear un nuevo Administrador"; + } + } + + // ----> Administradores PATCH + @PatchMapping("/actualizar/administrador") + public ResponseEntity actualizarAdministrador(@RequestBody PojoAdmin pojoAdmin){ + boolean actualizado = conexionAdminService.actualizarAdministrador(pojoAdmin); + if(actualizado) { + return ResponseEntity.ok("El Administrador ha sido actualizado correctamente"); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("Error al actualizar el Administrador"); + } + } + + // ----> Clientes GET + @GetMapping("/detalle/cliente") + public List> obtenerDetallesCliente() { + return conexionClienteService.obtenerDetallesCliente(); + } + + // ----> Clientes POST + @PostMapping("/crear/cliente") + public String crearCliente(@RequestBody PojoCliente pojoCliente) { + boolean creado = conexionClienteService.crearCliente(pojoCliente); + return ""; + } + + // ----> Clientes PATCH + @PatchMapping("/actualizar/cliente/{id}") + public ResponseEntity actualizarCliente(@PathVariable int id, @RequestBody PojoCliente pojoCliente) { + pojoCliente.setId(id); + boolean actualizado = conexionClienteService.actualizarCliente(pojoCliente); + + if (actualizado) { + return ResponseEntity.ok("El Usuario ha sido actualizado correctamente"); + } else { + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body("No se encontró un usuario con el ID especificado"); + } + } + + // ----> Empleados GET + @GetMapping("/detalle/empleado") + public List> obtenerDetallesEmpleado(){ + return conexionEmpleadoService.obtenerDetallesEmpleado(); + } + + // ----> Empleados POST + @PostMapping("/crear/empleado") + public String crearEmpleado(@RequestBody PojoEmpleado pojoEmpleado) { + boolean creado = conexionEmpleadoService.crearEmpleado(pojoEmpleado); + if (creado) { + return "Nuevo Empleado creado exitosamente"; + } else { + return "Error al crear un nuevo Empleado"; + } + } + + // ----> Empleados UPDATE + @PatchMapping("/actualizar/empleado/{id}") + public ResponseEntity actualizarEmpleado(@PathVariable int id, @RequestBody Map camposActualizar){ + boolean actualizado = conexionEmpleadoService.actualizarEmpleado(id, camposActualizar); + if(actualizado) { + return ResponseEntity.ok("El Empleado ha sido actualizado correctamente"); + } else { + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("Error al actualizar el Empleado"); + } + } + + // ----> Empleados DELETE + @DeleteMapping("/eliminar/empleado") + public String eliminarEmpleado(@RequestBody PojoDeleteEmpleado pojoDeleteEmpleado) { + boolean eliminado = conexionEmpleadoService.eliminarEmpleado(pojoDeleteEmpleado.getId()); + if (eliminado) { + return "Empleado eliminado exitosamente"; + } else { + return "Error al eliminar el Empleado"; + } + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/DetallePedidosController.java b/Proyecto/src/main/java/com/example/Proyecto/controller/DetallePedidosController.java new file mode 100644 index 0000000..cdc6a01 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/DetallePedidosController.java @@ -0,0 +1,52 @@ +package com.example.Proyecto.controller; + +import com.example.Proyecto.service.DetallePedidos.DetallePedidos; +import com.example.Proyecto.service.DetallePedidos.DetallePedidosService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import java.util.List; + +@RestController +@RequestMapping("/detalles-pedidos") +public class DetallePedidosController { + + @Autowired + private DetallePedidosService detallePedidosService; + + // GET - Obtener todos los detalles de pedidos + @GetMapping + public List obtenerTodosLosDetallesPedidos() { + return detallePedidosService.obtenerTodosLosDetallesPedidos(); + } + + // POST - Crear un nuevo detalle de pedido + @PostMapping + public ResponseEntity crearDetallePedido(@RequestBody DetallePedidos detalle) { + detallePedidosService.crearDetallePedido(detalle); + return ResponseEntity.ok("Detalle de pedido " + detalle.getIdDetalle() + " creado con éxito."); + } + + // PUT - Actualizar un detalle de pedido existente + @PutMapping("/{id}") + public ResponseEntity editarDetallePedido(@PathVariable int id, @RequestBody DetallePedidos detalle) { + detalle.setIdDetalle(id); + int filas = detallePedidosService.editarDetallePedido(detalle); + if (filas > 0) { + return ResponseEntity.ok("Detalle de pedido con ID " + id + " actualizado correctamente."); + } else { + return ResponseEntity.notFound().build(); + } + } + + // DELETE - Eliminar un detalle de pedido por ID + @DeleteMapping("/{id}") + public ResponseEntity eliminarDetallePedido(@PathVariable int id) { + int filas = detallePedidosService.eliminarDetallePedido(id); + if (filas > 0) { + return ResponseEntity.ok("Detalle de pedido con ID " + id + " eliminado correctamente."); + } else { + return ResponseEntity.notFound().build(); + } + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/Estados_PedidosController.java b/Proyecto/src/main/java/com/example/Proyecto/controller/Estados_PedidosController.java new file mode 100644 index 0000000..7a9b288 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/Estados_PedidosController.java @@ -0,0 +1,41 @@ +package com.example.Proyecto.controller; +import com.example.Proyecto.model.Estado_Pedidos; +import com.example.Proyecto.service.Pedidos.Estados_PedidosService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping +public class Estados_PedidosController { + + @Autowired + private Estados_PedidosService estados_PedidosService; + + @GetMapping("/estadosPedidos") + public ResponseEntity> obtenerTodosLosEstados_Pedidos() { + List estadoPedidos = estados_PedidosService.obtenerEstado_Pedidos(); + return new ResponseEntity<>(estadoPedidos, HttpStatus.OK); + } + + @PostMapping("/estadosPedidos") + public ResponseEntity crearEstadoPedido(@RequestBody Estado_Pedidos estado) { + Long estadoId = estados_PedidosService.crearEstadoPedido(estado); + return new ResponseEntity<>("Estado de pedido " + estadoId + " creado con éxito.", HttpStatus.CREATED); + } + + @PutMapping("/{id}") + public ResponseEntity actualizarEstado(@PathVariable("id") Long id, @RequestBody Estado_Pedidos estadoPedidos) { + estados_PedidosService.actualizarEstado(id, estadoPedidos); + return new ResponseEntity<>("Estado de pedido con ID " + id + " actualizado con éxito.", HttpStatus.OK); + } + + @DeleteMapping("/{id}") + public ResponseEntity eliminarestadoPedidos(@PathVariable("id") Long id) { + estados_PedidosService.eliminarestadoPedido(id); + return new ResponseEntity<>("Estado de pedido con ID " + id + " eliminado con éxito.", HttpStatus.OK); + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/Ingredientescontroller.java b/Proyecto/src/main/java/com/example/Proyecto/controller/Ingredientescontroller.java new file mode 100644 index 0000000..50bf68e --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/Ingredientescontroller.java @@ -0,0 +1,77 @@ +package com.example.Proyecto.controller; + +import com.example.Proyecto.model.Ingredientes; +import com.example.Proyecto.service.Ingredientes.IngredientesService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import java.util.List; +import java.util.Map; + +@RestController +public class Ingredientescontroller { + + @Autowired + private IngredientesService ingredientesService; + + // GET → obtener todos los ingredientes + @GetMapping("/ingredientes") + public List obtenerIngredientes() { + return ingredientesService.obtenerIngredientes(); + } + + @GetMapping("ingredientes/lista") + public List obtenerIngredientesListas() { + return ingredientesService.obtenerTodosLosIngredientes(); + } + + // Metodo post crear un nuevo ingrediente + @PostMapping("/crearingrediente") + public String crearIngrediente(@RequestBody Ingredientes ingrediente) { + ingredientesService.crearIngrediente(ingrediente); + System.out.println("Ingrediente recibido: " + ingrediente.getNombreIngrediente()); + return "Ingrediente " + ingrediente.getNombreIngrediente() + " creado con éxito."; + } + + // PUT → editar un ingrediente existente + @PutMapping("ingrediente/{id}") + public String editarIngrediente(@PathVariable int id, @RequestBody Ingredientes ingrediente) { + ingrediente.setIdIngrediente(id); // asigna el ID de la URL al objeto + + int filas = ingredientesService.editarIngrediente(ingrediente); + + if (filas > 0) { + return "Ingrediente con ID " + id + " actualizado correctamente."; + } else { + return "No se encontró el ingrediente con ID " + id; + } + } + + // Metodo PATCH + @PatchMapping("/{id}/cantidad") + public String patchCantidad(@PathVariable int id, @RequestBody Map updates) { + if (updates.containsKey("cantidadIngrediente")) { + int cantidad = (int) updates.get("cantidadIngrediente"); + int filas = ingredientesService.actualizarCantidad(id, cantidad); + return filas > 0 ? "Cantidad actualizada" : "Ingrediente no encontrado"; + } + return "No se envió la cantidad"; + } + + + // DELETE → eliminar un ingrediente por ID + @DeleteMapping("ingrediente/{id}") + public String eliminarIngrediente(@PathVariable int id) { + int filas = ingredientesService.eliminarIngrediente(id); + if (filas > 0) { + return "Ingrediente con ID " + id + " eliminado correctamente."; + } else { + return "No se encontró el ingrediente con ID " + id; + } + } + + + + + + +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/Ordenes_salidaController.java b/Proyecto/src/main/java/com/example/Proyecto/controller/Ordenes_salidaController.java new file mode 100644 index 0000000..23e1a6f --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/Ordenes_salidaController.java @@ -0,0 +1,21 @@ +package com.example.Proyecto.controller; +import com.example.Proyecto.model.Ordenes_salida; +import com.example.Proyecto.service.Ordenes_salida.Ordenes_salidaService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +public class Ordenes_salidaController { + private final Ordenes_salidaService ordenes_salidaService; + + public Ordenes_salidaController(Ordenes_salidaService ordenes_salidaService) { + this.ordenes_salidaService = ordenes_salidaService; + } + + @GetMapping("/ventas") + public ListobtenerOrdenesSalida() { + return ordenes_salidaService.obtenerOrdenesSalida(); + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/PedidosController.java b/Proyecto/src/main/java/com/example/Proyecto/controller/PedidosController.java new file mode 100644 index 0000000..f97cac5 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/PedidosController.java @@ -0,0 +1,38 @@ +package com.example.Proyecto.controller; +import com.example.Proyecto.model.Pedidos; +import com.example.Proyecto.service.Pedidos.pedidosService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.*; +import java.util.List; + +@Transactional +@RestController +@RequestMapping("/pedidos") +public class PedidosController { + @Autowired + private pedidosService pedidosService; + @GetMapping + public ResponseEntity> obtenerTodosLosPedidos() { + List pedidos = pedidosService.obtenerPedidos(); + return new ResponseEntity<>(pedidos, HttpStatus.OK); + } + @PostMapping + public String crearPedidos(@RequestBody Pedidos pedidos) { + int pedidoId = pedidosService.crearPedido(pedidos); + System.out.println("Pedido recibido con ID: " + pedidoId); + return "Pedido " + pedidoId + " creado con éxito."; + } + @PutMapping("/{id}") + public String actualizarPedidos(@PathVariable("id") Long id, @RequestBody Pedidos pedidos) { + pedidosService.actualizarPedido(id, pedidos); + return "Pedido con ID " + id + " actualizado con éxito."; + } + @DeleteMapping("/{id}") + public String eliminarPedido(@PathVariable("id") Long id) { + pedidosService.eliminarPedido(id); + return "Pedido con ID " + id + " eliminado con éxito."; + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/PedidosProveedoresController.java b/Proyecto/src/main/java/com/example/Proyecto/controller/PedidosProveedoresController.java new file mode 100644 index 0000000..2b97b3d --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/PedidosProveedoresController.java @@ -0,0 +1,52 @@ +package com.example.Proyecto.controller; + +import com.example.Proyecto.service.PedidosProveedores.PedidosProveedores; +import com.example.Proyecto.service.PedidosProveedores.PedidosProveedoresService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import java.util.List; + +@RestController +@RequestMapping +public class PedidosProveedoresController { + + @Autowired + private PedidosProveedoresService pedidosProveedoresService; + + // GET - Obtener todos los pedidos de proveedores + @GetMapping("/pedido/proveedores") + public List obtenerTodosLosPedidosProveedores() { + return pedidosProveedoresService.obtenerTodosLosPedidosProveedores(); + } + + // POST - Crear un nuevo pedido de proveedor + @PostMapping("/pedido/proveedores") + public ResponseEntity crearPedidoProveedor(@RequestBody PedidosProveedores pedido) { + pedidosProveedoresService.crearPedidoProveedor(pedido); + return ResponseEntity.ok("Pedido " + pedido.getNumeroPedido() + " creado con éxito."); + } + + // PUT - Actualizar un pedido de proveedor existente + @PutMapping("/pedido/proveedores/{id}") + public ResponseEntity editarPedidoProveedor(@PathVariable int id, @RequestBody PedidosProveedores pedido) { + pedido.setIdPedidoProv(id); + int filas = pedidosProveedoresService.editarPedidoProveedor(pedido); + if (filas > 0) { + return ResponseEntity.ok("Pedido de proveedor con ID " + id + " actualizado correctamente."); + } else { + return ResponseEntity.notFound().build(); + } + } + + // DELETE - Eliminar un pedido de proveedor por ID + @DeleteMapping("/pedido/proveedores/{id}") + public ResponseEntity eliminarPedidoProveedor(@PathVariable int id) { + int filas = pedidosProveedoresService.eliminarPedidoProveedor(id); + if (filas > 0) { + return ResponseEntity.ok("Pedido de proveedor con ID " + id + " eliminado correctamente."); + } else { + return ResponseEntity.notFound().build(); + } + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/ProductosController.java b/Proyecto/src/main/java/com/example/Proyecto/controller/ProductosController.java new file mode 100644 index 0000000..345977f --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/ProductosController.java @@ -0,0 +1,51 @@ +package com.example.Proyecto.controller; + +import com.example.Proyecto.model.PojoProductos; +import com.example.Proyecto.service.Productos.ProductosService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +@RequestMapping("/") +@RestController +public class ProductosController { + @Autowired + private ProductosService productosService; + + // ----> Productos GET + @GetMapping("/detalle/producto") + public List> obtenerDetallesProductos() { + return productosService.obtenerDetallesProducto(); + } + // ----> Productos POST + @PostMapping("/crear/producto") + public String crearProducto(@RequestBody PojoProductos pojoProductos) { + boolean creado = productosService.crearProducto(pojoProductos); + if (creado) { + return "Nuevo Producto creado e ingresado exitosamente"; + } else { + return "Error al crear un nuevo Producto"; + } + } + @PatchMapping("/actualizar/producto/{id}") + public ResponseEntity actualizarProducto(@PathVariable("id") Long id, @RequestBody PojoProductos pojoProductos) { + try { + pojoProductos.setId(id.intValue()); + boolean actualizado = productosService.actualizarProducto(pojoProductos); + if (actualizado) { + return ResponseEntity.ok("El producto " + pojoProductos.getNombreProducto() + " ha sido actualizado correctamente"); + } else { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body("Error al actualizar el producto"); + } + } catch (Exception e) { + e.printStackTrace(); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("Excepción: " + e.getMessage()); + } + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/ProveedoresController.java b/Proyecto/src/main/java/com/example/Proyecto/controller/ProveedoresController.java new file mode 100644 index 0000000..67b3dd9 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/ProveedoresController.java @@ -0,0 +1,51 @@ +package com.example.Proyecto.controller; +import com.example.Proyecto.service.Proveedores.Proveedores; +import com.example.Proyecto.service.Proveedores.ProveedoresService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import java.util.List; + +@RestController +@RequestMapping("/proveedores") +public class ProveedoresController { + + @Autowired + private ProveedoresService proveedoresService; + + // GET - Obtener todos los proveedores + @GetMapping + public List obtenerTodosLosProveedores() { + return proveedoresService.obtenerTodosLosProveedores(); + } + + // POST - Crear un nuevo proveedor + @PostMapping + public ResponseEntity crearProveedor(@RequestBody Proveedores proveedor) { + proveedoresService.crearProveedor(proveedor); + return ResponseEntity.ok("Proveedor " + proveedor.getNombreProv() + " creado con éxito."); + } + + // PUT - Actualizar un proveedor existente + @PutMapping("/{id}") + public ResponseEntity editarProveedor(@PathVariable int id, @RequestBody Proveedores proveedor) { + proveedor.setIdProveedor(id); + int filas = proveedoresService.editarProveedor(proveedor); + if (filas > 0) { + return ResponseEntity.ok("Proveedor con ID " + id + " actualizado correctamente."); + } else { + return ResponseEntity.notFound().build(); + } + } + + // DELETE - Eliminar un proveedor por ID + @DeleteMapping("/{id}") + public ResponseEntity eliminarProveedor(@PathVariable int id) { + int filas = proveedoresService.eliminarProveedor(id); + if (filas > 0) { + return ResponseEntity.ok("Proveedor con ID " + id + " eliminado correctamente."); + } else { + return ResponseEntity.notFound().build(); + } + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/controller/UsuariosRegistradosController.java b/Proyecto/src/main/java/com/example/Proyecto/controller/UsuariosRegistradosController.java new file mode 100644 index 0000000..9fa4e1e --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/controller/UsuariosRegistradosController.java @@ -0,0 +1,21 @@ +package com.example.Proyecto.controller; + +import com.example.Proyecto.dto.UsuariosRegistradosDTO; +import com.example.Proyecto.service.UsuariosRegistradosService.UsuariosRegistradosService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +public class UsuariosRegistradosController { + + @Autowired + private UsuariosRegistradosService usuariosRegistradosService; + + @GetMapping("/reporte/usuarios") + public List obtenerReporteUsuarios() { + return usuariosRegistradosService.obtenerUsuariosRegistrados(); + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/dto/UsuariosRegistradosDTO.java b/Proyecto/src/main/java/com/example/Proyecto/dto/UsuariosRegistradosDTO.java new file mode 100644 index 0000000..b6a9f71 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/dto/UsuariosRegistradosDTO.java @@ -0,0 +1,27 @@ +package com.example.Proyecto.dto; + +public class UsuariosRegistradosDTO { + private String nombre; + private String email; + private String telefono; + private String rol; + + public UsuariosRegistradosDTO(String nombre, String email, String telefono, String rol) { + this.nombre = nombre; + this.email = email; + this.telefono = telefono; + this.rol = rol; + } + // Getters y Setters + public String getNombre() { return nombre; } + public void setNombre(String nombre) { this.nombre = nombre; } + + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + public String getTelefono() { return telefono; } + public void setTelefono(String telefono) { this.telefono = telefono; } + public String getRol() { return rol; } + public void setRol(String rol) { this.rol = rol; } + + } + diff --git a/Proyecto/src/main/java/com/example/Proyecto/model/Estado_Pedidos.java b/Proyecto/src/main/java/com/example/Proyecto/model/Estado_Pedidos.java new file mode 100644 index 0000000..5ccf072 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/model/Estado_Pedidos.java @@ -0,0 +1,28 @@ +package com.example.Proyecto.model; + +public class Estado_Pedidos { + + private Long ID_ESTADO_PEDIDO; + private String NOMBRE_ESTADO; + + public Estado_Pedidos() { + this.ID_ESTADO_PEDIDO = ID_ESTADO_PEDIDO; + this.NOMBRE_ESTADO = NOMBRE_ESTADO; + } + + public Long getID_ESTADO_PEDIDO() { + return ID_ESTADO_PEDIDO; + } + + public void setID_ESTADO_PEDIDO(Long ID_ESTADO_PEDIDO) { + this.ID_ESTADO_PEDIDO = ID_ESTADO_PEDIDO; + } + + public String getNOMBRE_ESTADO() { + return NOMBRE_ESTADO; + } + + public void setNOMBRE_ESTADO(String NOMBRE_ESTADO) { + this.NOMBRE_ESTADO = NOMBRE_ESTADO; + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/model/Ingredientes.java b/Proyecto/src/main/java/com/example/Proyecto/model/Ingredientes.java new file mode 100644 index 0000000..a6ada94 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/model/Ingredientes.java @@ -0,0 +1,61 @@ +package com.example.Proyecto.model; + +import java.util.Date; + +public class Ingredientes { + private int idIngrediente; + private int idProveedor; + private int idCategoria; + private String nombreIngrediente; + private int cantidadIngrediente; + private Date fechaVencimiento; + private String referenciaIngrediente; + private Date fechaEntregaIngrediente; + + // Constructor vacío + public Ingredientes() {} + + // Constructor con parámetros + public Ingredientes(int idIngrediente, + int idProveedor, + int idCategoria, + String nombreIngrediente, + int cantidadIngrediente, + Date fechaVencimiento, + String referenciaIngrediente, + Date fechaEntregaIngrediente) { + this.idIngrediente = idIngrediente; + this.idProveedor = idProveedor; + this.idCategoria = idCategoria; + this.nombreIngrediente = nombreIngrediente; + this.cantidadIngrediente = cantidadIngrediente; + this.fechaVencimiento = fechaVencimiento; + this.referenciaIngrediente = referenciaIngrediente; + this.fechaEntregaIngrediente = fechaEntregaIngrediente; + } + + // Getters y Setters + public int getIdIngrediente() { return idIngrediente; } + public void setIdIngrediente(int idIngrediente) { this.idIngrediente = idIngrediente; } + + public int getIdProveedor() { return idProveedor; } + public void setIdProveedor(int idProveedor) { this.idProveedor = idProveedor; } + + public int getIdCategoria() { return idCategoria; } + public void setIdCategoria(int idCategoria) { this.idCategoria = idCategoria; } + + public String getNombreIngrediente() { return nombreIngrediente; } + public void setNombreIngrediente(String nombreIngrediente) { this.nombreIngrediente = nombreIngrediente; } + + public int getCantidadIngrediente() { return cantidadIngrediente; } + public void setCantidadIngrediente(int cantidadIngrediente) { this.cantidadIngrediente = cantidadIngrediente; } + + public Date getFechaVencimiento() { return fechaVencimiento; } + public void setFechaVencimiento(Date fechaVencimiento) { this.fechaVencimiento = fechaVencimiento; } + + public String getReferenciaIngrediente() { return referenciaIngrediente; } + public void setReferenciaIngrediente(String referenciaIngrediente) { this.referenciaIngrediente = referenciaIngrediente; } + + public Date getFechaEntregaIngrediente() { return fechaEntregaIngrediente; } + public void setFechaEntregaIngrediente(Date fechaEntregaIngrediente) { this.fechaEntregaIngrediente = fechaEntregaIngrediente; } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/model/Ordenes_salida.java b/Proyecto/src/main/java/com/example/Proyecto/model/Ordenes_salida.java new file mode 100644 index 0000000..d4ca71d --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/model/Ordenes_salida.java @@ -0,0 +1,80 @@ +package com.example.Proyecto.model; + +import jakarta.persistence.*; + +import java.time.LocalDate; + +@Entity +@Table(name = "ordenes_salida") +public class Ordenes_salida { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ID_FACTURA") + private int idFactura; // ID_FACTURA + + @Column(name = "ID_CLIENTE") + private Long idCliente; // ID_CLIENTE + + @Column(name = "ID_PEDIDO") + private Long idPedido; // ID_PEDIDO + + @Column(name = "FECHA_FACTURACION") + private LocalDate fechaFacturacion; // FECHA_FACTURACION + + @Column(name = "TOTAL_FACTURA") + private double totalFactura; // TOTAL_FACTURA + + // Constructor vacío requerido por JPA + public Ordenes_salida() {} + + // Constructor + public Ordenes_salida(int idFactura, Long idCliente, Long idPedido, LocalDate fechaFacturacion, double totalFactura) { + this.idFactura = idFactura; + this.idCliente = idCliente; + this.idPedido = idPedido; + this.fechaFacturacion = fechaFacturacion; + this.totalFactura = totalFactura; + } + + // METODOS + public int getIdFactura() { + return idFactura; + } + + public void setIdFactura(int idFactura) { + this.idFactura = idFactura; + } + + public Long getIdCliente() { + return idCliente; + } + + public void setIdCliente(Long idCliente) { + this.idCliente = idCliente; + } + + public Long getIdPedido() { + return idPedido; + } + + public void setIdPedido(Long idPedido) { + this.idPedido = idPedido; + } + + public LocalDate getFechaFacturacion() { + return fechaFacturacion; + } + + public void setFechaFacturacion(LocalDate fechaFacturacion) { + this.fechaFacturacion = fechaFacturacion; + } + + public double getTotalFactura() { + return totalFactura; + } + + public void setTotalFactura(double totalFactura) { + this.totalFactura = totalFactura; + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/model/Pedidos.java b/Proyecto/src/main/java/com/example/Proyecto/model/Pedidos.java new file mode 100644 index 0000000..71e279a --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/model/Pedidos.java @@ -0,0 +1,73 @@ +package com.example.Proyecto.model; + +import java.math.BigDecimal; +import java.util.Date; + +public class Pedidos { + + private long ID_CLIENTE; + private long ID_EMPLEADO; + private long ID_ESTADO_PEDIDO; + private Date FECHA_INGRESO; + private Date FECHA_ENTREGA; + private BigDecimal TOTAL_PRODUCTO; + + public Pedidos() { + this.ID_CLIENTE = ID_CLIENTE; + this.ID_EMPLEADO = ID_EMPLEADO; + this.ID_ESTADO_PEDIDO = ID_ESTADO_PEDIDO; + this.FECHA_INGRESO = FECHA_INGRESO; + this.FECHA_ENTREGA = FECHA_ENTREGA; + this.TOTAL_PRODUCTO = TOTAL_PRODUCTO; + } + + public int getID_CLIENTE() { + return (int) ID_CLIENTE; + } + + public void setID_CLIENTE(long ID_CLIENTE) { + this.ID_CLIENTE = ID_CLIENTE; + } + + public int getID_EMPLEADO() { + return (int) ID_EMPLEADO; + } + + public void setID_EMPLEADO(long ID_EMPLEADO) { + this.ID_EMPLEADO = ID_EMPLEADO; + } + + public int getID_ESTADO_PEDIDO() { + return (int) ID_ESTADO_PEDIDO; + } + + public void setID_ESTADO_PEDIDO(long ID_ESTADO_PEDIDO) { + this.ID_ESTADO_PEDIDO = ID_ESTADO_PEDIDO; + } + + public Date getFECHA_INGRESO() { + return FECHA_INGRESO; + } + + public void setFECHA_INGRESO(Date FECHA_INGRESO) { + this.FECHA_INGRESO = FECHA_INGRESO; + } + + public Date getFECHA_ENTREGA() { + return FECHA_ENTREGA; + } + + public void setFECHA_ENTREGA(Date FECHA_ENTREGA) { + this.FECHA_ENTREGA = FECHA_ENTREGA; + } + + public BigDecimal getTOTAL_PRODUCTO() { + return TOTAL_PRODUCTO; + } + + public void setTOTAL_PRODUCTO(BigDecimal TOTAL_PRODUCTO) { + this.TOTAL_PRODUCTO = TOTAL_PRODUCTO; + } +} + + diff --git a/Proyecto/src/main/java/com/example/Proyecto/model/Pedidos_Proveedores.java b/Proyecto/src/main/java/com/example/Proyecto/model/Pedidos_Proveedores.java new file mode 100644 index 0000000..6e23547 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/model/Pedidos_Proveedores.java @@ -0,0 +1,50 @@ +package com.example.Proyecto.model; + +import java.sql.Date; + +public class Pedidos_Proveedores { + + private Long ID_PROVEEDOR; + private long NUMERO_PEDIDO; + private long FECHA_PEDIDO; + private Date ESTADO_PEDIDO; + + public Pedidos_Proveedores() { + this.ID_PROVEEDOR = ID_PROVEEDOR; + this.NUMERO_PEDIDO = NUMERO_PEDIDO; + this.FECHA_PEDIDO = FECHA_PEDIDO; + this.ESTADO_PEDIDO = ESTADO_PEDIDO; + } + + public Long getID_PROVEEDOR() { + return ID_PROVEEDOR; + } + + public void setID_PROVEEDOR(Long ID_PROVEEDOR) { + this.ID_PROVEEDOR = ID_PROVEEDOR; + } + + public long getNUMERO_PEDIDO() { + return NUMERO_PEDIDO; + } + + public void setNUMERO_PEDIDO(long NUMERO_PEDIDO) { + this.NUMERO_PEDIDO = NUMERO_PEDIDO; + } + + public long getFECHA_PEDIDO() { + return FECHA_PEDIDO; + } + + public void setFECHA_PEDIDO(long FECHA_PEDIDO) { + this.FECHA_PEDIDO = FECHA_PEDIDO; + } + + public Date getESTADO_PEDIDO() { + return ESTADO_PEDIDO; + } + + public void setESTADO_PEDIDO(java.sql.Date ESTADO_PEDIDO) { + this.ESTADO_PEDIDO = ESTADO_PEDIDO; + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/model/PojoAdmin.java b/Proyecto/src/main/java/com/example/Proyecto/model/PojoAdmin.java new file mode 100644 index 0000000..e9a07ac --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/model/PojoAdmin.java @@ -0,0 +1,51 @@ +package com.example.Proyecto.model; +public class PojoAdmin { + private int id; + private String nombre; + private String email; + private String telefono; + private String contrasena; + + public PojoAdmin() { + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getNombre() { + return nombre; + } + + public void setNombre(String nombre) { + this.nombre = nombre; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getTelefono() { + return telefono; + } + + public void setTelefono(String telefono) { + this.telefono = telefono; + } + + public String getContrasena() { + return contrasena; + } + + public void setContrasena(String contrasena) { + this.contrasena = contrasena; + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/model/PojoCliente.java b/Proyecto/src/main/java/com/example/Proyecto/model/PojoCliente.java new file mode 100644 index 0000000..65f72fd --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/model/PojoCliente.java @@ -0,0 +1,43 @@ +package com.example.Proyecto.model; + +public class PojoCliente { + private int id; + private String nombre; + private String email; + private String telefono; + private String contrasena; + + public PojoCliente() {} + + public int getId() {return id;} + + public void setId(int id) {this.id = id;} + + public String getNombre() { + return nombre; + } + + public void setNombre(String nombre) { + this.nombre = nombre; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getTelefono() { + return telefono; + } + + public void setTelefono(String telefono) { this.telefono = telefono; } + + public String getContrasena() { return contrasena; } + + public void setContrasena(String contrasena) {this.contrasena = contrasena;} +} + + diff --git a/Proyecto/src/main/java/com/example/Proyecto/model/PojoDeleteEmpleado.java b/Proyecto/src/main/java/com/example/Proyecto/model/PojoDeleteEmpleado.java new file mode 100644 index 0000000..78f59d5 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/model/PojoDeleteEmpleado.java @@ -0,0 +1,19 @@ +package com.example.Proyecto.model; + +public class PojoDeleteEmpleado { + + private Long id; + + public PojoDeleteEmpleado() {} + + public PojoDeleteEmpleado(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + } diff --git a/Proyecto/src/main/java/com/example/Proyecto/model/PojoEmpleado.java b/Proyecto/src/main/java/com/example/Proyecto/model/PojoEmpleado.java new file mode 100644 index 0000000..e82f3d0 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/model/PojoEmpleado.java @@ -0,0 +1,44 @@ +package com.example.Proyecto.model; + +public class PojoEmpleado { + private int id; + private String nombre; + private String email; + private String contrasena; + + public PojoEmpleado() { + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getNombre() { + return nombre; + } + + public void setNombre(String nombre) { + this.nombre = nombre; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + + public String getContrasena(){ + return contrasena; + } + + public void setContrasena(String contrasena){ + this.contrasena = contrasena; + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/model/PojoProductos.java b/Proyecto/src/main/java/com/example/Proyecto/model/PojoProductos.java new file mode 100644 index 0000000..73acefd --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/model/PojoProductos.java @@ -0,0 +1,62 @@ +package com.example.Proyecto.model; +import java.time.LocalDate; + + +public class PojoProductos { + private int id; + private String nombreProducto; + private int stockMinimo; + private int precio; + private LocalDate fechaVencimiento; + private String marcaProducto; + + public PojoProductos() {} + + // Getters y Setters + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getNombreProducto() { + return nombreProducto; + } + + public void setNombreProducto(String nombreProducto) { + this.nombreProducto = nombreProducto; + } + + public int getStockMinimo() { + return stockMinimo; + } + + public void setStockMinimo(int stockMinimo) { + this.stockMinimo = stockMinimo; + } + + public int getPrecio() { + return precio; + } + + public void setPrecio(int precio) { + this.precio = precio; + } + + public LocalDate getFechaVencimiento() { + return fechaVencimiento; + } + + public void setFechaVencimiento(LocalDate fechaVencimiento) { + this.fechaVencimiento = fechaVencimiento; + } + public String getMarcaProducto(){ + return marcaProducto; + } + + public void setMarcaProducto(String marcaProducto) { + this.marcaProducto = marcaProducto; + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/Administrador/ConexionAdminService.java b/Proyecto/src/main/java/com/example/Proyecto/service/Administrador/ConexionAdminService.java new file mode 100644 index 0000000..1ad8de8 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/Administrador/ConexionAdminService.java @@ -0,0 +1,66 @@ +package com.example.Proyecto.service.Administrador; +import com.example.Proyecto.model.PojoAdmin; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.lang.NonNull; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class ConexionAdminService { + @Autowired + private JdbcTemplate jdbcTemplate; + @Autowired + private PasswordEncoder passwordEncoder; + + public List> obtenerDetallesAdministrador() { + String sql = "SELECT ID_ADMIN, NOMBRE_ADMIN, TELEFONO_ADMIN, EMAIL_ADMIN FROM Administradores"; + return jdbcTemplate.query(sql, new RowMapper>() { + @Override + public Map mapRow(@NonNull ResultSet rs, int rowNum) throws SQLException { + Map administrador = new HashMap<>(); + administrador.put("Id:", rs.getInt("ID_ADMIN")); + administrador.put("Nombre:", rs.getString("NOMBRE_ADMIN")); + administrador.put("Correo Electronico:", rs.getString("EMAIL_ADMIN")); + administrador.put("Telefono:", rs.getString("TELEFONO_ADMIN")); + return administrador; + } + }); + } + + public boolean crearAdmin(PojoAdmin pojoAdmin) { + String sql = "INSERT INTO Administradores (NOMBRE_ADMIN, EMAIL_ADMIN, TELEFONO_ADMIN, CONTRASEÑA_ADMIN) VALUES (?, ?, ?, ?)"; + try { + if (pojoAdmin.getContrasena() == null || pojoAdmin.getContrasena().trim().isEmpty()) { + System.out.println("Error: La contraseña no puede ser nula o vacía"); + return false; + } + + String contrasenaHasheada = passwordEncoder.encode(pojoAdmin.getContrasena()); + int result = jdbcTemplate.update(sql, pojoAdmin.getNombre(), pojoAdmin.getEmail(), pojoAdmin.getTelefono(), contrasenaHasheada); + return result > 0; + } catch (DataAccessException e) { + return false; + } + } + + public boolean actualizarAdministrador(PojoAdmin pojoAdmin) { + String sql = "UPDATE Administradores SET NOMBRE_ADMIN = ?, EMAIL_ADMIN = ?, TELEFONO_ADMIN=?, CONTRASENA_ADMIN = ? WHERE ID_ADMIN = ?"; + try { + String contrasenaHasheada = passwordEncoder.encode(pojoAdmin.getContrasena()); + int value = jdbcTemplate.update( + sql, pojoAdmin.getNombre(), pojoAdmin.getEmail(), pojoAdmin.getTelefono(), contrasenaHasheada, pojoAdmin.getId()); + return value > 0; + } catch (DataAccessException e) { + e.printStackTrace(); + return false; + } + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/CategoriaIngredientesService/CategoriaIngredientes.java b/Proyecto/src/main/java/com/example/Proyecto/service/CategoriaIngredientesService/CategoriaIngredientes.java new file mode 100644 index 0000000..6394fbd --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/CategoriaIngredientesService/CategoriaIngredientes.java @@ -0,0 +1,25 @@ +// Archivo: CategoriaIngredientes.java +package com.example.Proyecto.service.CategoriaIngredientesService; + +public class CategoriaIngredientes { + private int idCategoriaIngrediente; + private String nombreCategoria; + + public CategoriaIngredientes() {} + + public int getIdCategoriaIngrediente() { + return idCategoriaIngrediente; + } + + public void setIdCategoriaIngrediente(int idCategoriaIngrediente) { + this.idCategoriaIngrediente = idCategoriaIngrediente; + } + + public String getNombreCategoria() { + return nombreCategoria; + } + + public void setNombreCategoria(String nombreCategoria) { + this.nombreCategoria = nombreCategoria; + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/CategoriaIngredientesService/CategoriaIngredientesService.java b/Proyecto/src/main/java/com/example/Proyecto/service/CategoriaIngredientesService/CategoriaIngredientesService.java new file mode 100644 index 0000000..8e58512 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/CategoriaIngredientesService/CategoriaIngredientesService.java @@ -0,0 +1,50 @@ +package com.example.Proyecto.service.CategoriaIngredientesService; + +import com.example.Proyecto.service.CategoriaIngredientesService.CategoriaIngredientes; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +@Service +public class CategoriaIngredientesService { + + @Autowired + private JdbcTemplate jdbcTemplate; + + // Obtener todas las categorías de ingredientes + public List obtenerTodasLasCategoriasIngredientes() { + String sql = "SELECT * FROM Categoria_Ingredientes"; + return jdbcTemplate.query(sql, new RowMapper() { + @Override + public CategoriaIngredientes mapRow(@NonNull ResultSet rs, int rowNum) throws SQLException { + CategoriaIngredientes categoria = new CategoriaIngredientes(); + categoria.setIdCategoriaIngrediente(rs.getInt("ID_CATEGORIA")); + categoria.setNombreCategoria(rs.getString("NOMBRE_CATEGORIA_INGREDIENTE")); + return categoria; + } + }); + } + + // Crear una nueva categoría (POST) + public void crearCategoriaIngrediente(CategoriaIngredientes categoria) { + String sql = "INSERT INTO Categoria_Ingredientes (NOMBRE_CATEGORIA_INGREDIENTE) VALUES (?)"; + jdbcTemplate.update(sql, categoria.getNombreCategoria()); + } + + // Actualizar una categoría existente (PUT) + public int editarCategoriaIngrediente(CategoriaIngredientes categoria) { + String sql = "UPDATE Categoria_Ingredientes SET NOMBRE_CATEGORIA_INGREDIENTE=? WHERE ID_CATEGORIA=?"; + return jdbcTemplate.update(sql, categoria.getNombreCategoria(), categoria.getIdCategoriaIngrediente()); + } + + // Eliminar una categoría por ID (DELETE) + public int eliminarCategoriaIngrediente(int idCategoria) { + String sql = "DELETE FROM Categoria_Ingredientes WHERE ID_CATEGORIA = ?"; + return jdbcTemplate.update(sql, idCategoria); + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/Clientes/ConexionClienteService.java b/Proyecto/src/main/java/com/example/Proyecto/service/Clientes/ConexionClienteService.java new file mode 100644 index 0000000..e541b3b --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/Clientes/ConexionClienteService.java @@ -0,0 +1,63 @@ +package com.example.Proyecto.service.Clientes; +import com.example.Proyecto.model.PojoCliente; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.lang.NonNull; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class ConexionClienteService { + @Autowired + private JdbcTemplate jdbcTemplate; + @Autowired + private PasswordEncoder passwordEncoder; + + public List> obtenerDetallesCliente() { + String sql = "SELECT TELEFONO_CLI, EMAIL_CLI, NOMBRE_CLI FROM Clientes"; + return jdbcTemplate.query(sql, new RowMapper>() { + @Override + public Map mapRow(@NonNull ResultSet rs, int rowNum) throws SQLException { + Map cliente = new HashMap<>(); + cliente.put("Nombre:", rs.getString("NOMBRE_CLI")); + cliente.put("Correo Electronico:", rs.getString("EMAIL_CLI")); + cliente.put("Telefono:", rs.getString("TELEFONO_CLI")); + return cliente; + } + }); + } + + public boolean crearCliente(PojoCliente pojoCliente) { + String sql = "INSERT INTO Clientes (NOMBRE_CLI, EMAIL_CLI, TELEFONO_CLI, CONTRASENA_CLI) VALUES (?, ?, ?, ?)"; + try { + if (pojoCliente.getContrasena() == null || pojoCliente.getContrasena().trim().isEmpty()) { + System.out.println("Error: La contraseña no puede ser nula o vacía"); + return false; + } + String contrasenaHasheada = passwordEncoder.encode(pojoCliente.getContrasena()); + int result = jdbcTemplate.update(sql, pojoCliente.getNombre(), pojoCliente.getEmail(), pojoCliente.getTelefono(), contrasenaHasheada); + return result > 0; + } catch (DataAccessException e) { + return false; + } + } + public boolean actualizarCliente(PojoCliente pojoCliente) { + String sql = "UPDATE Clientes SET NOMBRE_CLI = ?, EMAIL_CLI = ?, TELEFONO_CLI = ?, CONTRASENA_CLI = ? WHERE ID_CLIENTE = ?"; + try { + String contrasenaHasheada = passwordEncoder.encode(pojoCliente.getContrasena()); + int value = jdbcTemplate.update(sql, pojoCliente.getNombre(), pojoCliente.getEmail(), pojoCliente.getTelefono(), contrasenaHasheada, pojoCliente.getId()); + return value > 0; + } catch (DataAccessException e) { + e.printStackTrace(); + return false; + } + } +} + diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/DetallePedidos/DetallePedidos.java b/Proyecto/src/main/java/com/example/Proyecto/service/DetallePedidos/DetallePedidos.java new file mode 100644 index 0000000..5dd3f10 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/DetallePedidos/DetallePedidos.java @@ -0,0 +1,33 @@ +// Archivo: DetallePedidos.java +package com.example.Proyecto.service.DetallePedidos; + +import java.math.BigDecimal; + +public class DetallePedidos { + private int idDetalle; + private int idPedido; + private int idProducto; + private int cantidadProducto; + private BigDecimal precioUnitario; + private BigDecimal subtotal; + + public DetallePedidos() {} + + public int getIdDetalle() { return idDetalle; } + public void setIdDetalle(int idDetalle) { this.idDetalle = idDetalle; } + + public int getIdPedido() { return idPedido; } + public void setIdPedido(int idPedido) { this.idPedido = idPedido; } + + public int getIdProducto() { return idProducto; } + public void setIdProducto(int idProducto) { this.idProducto = idProducto; } + + public int getCantidadProducto() { return cantidadProducto; } + public void setCantidadProducto(int cantidadProducto) { this.cantidadProducto = cantidadProducto; } + + public BigDecimal getPrecioUnitario() { return precioUnitario; } + public void setPrecioUnitario(BigDecimal precioUnitario) { this.precioUnitario = precioUnitario; } + + public BigDecimal getSubtotal() { return subtotal; } + public void setSubtotal(BigDecimal subtotal) { this.subtotal = subtotal; } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/DetallePedidos/DetallePedidosService.java b/Proyecto/src/main/java/com/example/Proyecto/service/DetallePedidos/DetallePedidosService.java new file mode 100644 index 0000000..6c3e8cf --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/DetallePedidos/DetallePedidosService.java @@ -0,0 +1,67 @@ +package com.example.Proyecto.service.DetallePedidos; + +import com.example.Proyecto.service.DetallePedidos.DetallePedidos; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +@Service +public class DetallePedidosService { + + @Autowired + private JdbcTemplate jdbcTemplate; + + // Obtener todos los detalles de pedidos + public List obtenerTodosLosDetallesPedidos() { + String sql = "SELECT * FROM Detalle_Pedidos"; + return jdbcTemplate.query(sql, new RowMapper() { + @Override + public DetallePedidos mapRow(@NonNull ResultSet rs, int rowNum) throws SQLException { + DetallePedidos detalle = new DetallePedidos(); + detalle.setIdDetalle(rs.getInt("ID_DETALLE")); + detalle.setIdPedido(rs.getInt("ID_PEDIDO")); + detalle.setIdProducto(rs.getInt("ID_PRODUCTO")); + detalle.setCantidadProducto(rs.getInt("CANTIDAD_PRODUCTO")); + detalle.setPrecioUnitario(rs.getBigDecimal("PRECIO_UNITARIO")); + detalle.setSubtotal(rs.getBigDecimal("SUBTOTAL")); + return detalle; + } + }); + } + + // Crear un nuevo detalle de pedido (POST) + public void crearDetallePedido(DetallePedidos detalle) { + String sql = "INSERT INTO Detalle_Pedidos (ID_PEDIDO, ID_PRODUCTO, CANTIDAD_PRODUCTO, PRECIO_UNITARIO, SUBTOTAL) VALUES (?, ?, ?, ?, ?)"; + jdbcTemplate.update(sql, + detalle.getIdPedido(), + detalle.getIdProducto(), + detalle.getCantidadProducto(), + detalle.getPrecioUnitario(), + detalle.getSubtotal() + ); + } + + // Actualizar un detalle de pedido (PUT) + public int editarDetallePedido(DetallePedidos detalle) { + String sql = "UPDATE Detalle_Pedidos SET ID_PEDIDO=?, ID_PRODUCTO=?, CANTIDAD_PRODUCTO=?, PRECIO_UNITARIO=?, SUBTOTAL=? WHERE ID_DETALLE=?"; + return jdbcTemplate.update(sql, + detalle.getIdPedido(), + detalle.getIdProducto(), + detalle.getCantidadProducto(), + detalle.getPrecioUnitario(), + detalle.getSubtotal(), + detalle.getIdDetalle() + ); + } + + // Eliminar un detalle de pedido (DELETE) + public int eliminarDetallePedido(int idDetalle) { + String sql = "DELETE FROM Detalle_Pedidos WHERE ID_DETALLE = ?"; + return jdbcTemplate.update(sql, idDetalle); + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/Empleados/ConexionEmpleadoService.java b/Proyecto/src/main/java/com/example/Proyecto/service/Empleados/ConexionEmpleadoService.java new file mode 100644 index 0000000..eacb04a --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/Empleados/ConexionEmpleadoService.java @@ -0,0 +1,108 @@ +package com.example.Proyecto.service.Empleados; +import com.example.Proyecto.model.PojoEmpleado; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.lang.NonNull; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service + +public class ConexionEmpleadoService { + @Autowired + private JdbcTemplate jdbcTemplate; + @Autowired + private PasswordEncoder passwordEncoder; + + public List> obtenerDetallesEmpleado() { + String sql = "SELECT ID_EMPLEADO, NOMBRE_EMPLEADO, EMAIL_EMPLEADO, ACTIVO_EMPLEADO FROM Empleados"; + return jdbcTemplate.query(sql, new RowMapper>() { + @Override + public Map mapRow(@NonNull ResultSet rs, int rowNum) throws SQLException { + Map empleado = new HashMap<>(); + empleado.put("Id:", rs.getInt("ID_EMPLEADO")); + empleado.put("Nombre:", rs.getString("NOMBRE_EMPLEADO")); + empleado.put("Correo Electronico:", rs.getString("EMAIL_EMPLEADO")); + + int estado = rs.getInt("ACTIVO_EMPLEADO"); + String estadoTexto = (estado == 1) ? "ACTIVO" : "INACTIVO"; + empleado.put("Estado del Empleado", estadoTexto); + return empleado; + } + }); + } + + public boolean crearEmpleado(PojoEmpleado pojoEmpleado) { + String sql = "INSERT INTO Empleados (ID_EMPLEADO, NOMBRE_EMPLEADO, EMAIL_EMPLEADO, CONTRASENA_EMPLEADO) VALUES (?, ?, ?, ?)"; + try { + if (pojoEmpleado.getContrasena() == null || pojoEmpleado.getContrasena().trim().isEmpty()) { + System.out.println("Error: La contraseña no puede ser nula o vacía"); + return false; + } + String contrasenaHasheada = passwordEncoder.encode(pojoEmpleado.getContrasena()); + int result = jdbcTemplate.update(sql, pojoEmpleado.getId(), pojoEmpleado.getNombre(), pojoEmpleado.getEmail(), contrasenaHasheada); + return result > 0; + } finally { + } + } + + public boolean eliminarEmpleado(Long id) { + String sql = "DELETE FROM Empleados WHERE ID_EMPLEADO = ?"; + try { + int value = jdbcTemplate.update(sql, id); + return value > 0; + } catch (DataAccessException e) { + return false; + } + } + + public boolean actualizarEmpleado(int id, Map camposActualizar) { + if (camposActualizar.isEmpty()) { + return false; + } + StringBuilder sql = new StringBuilder("UPDATE Empleados SET "); + List parametros = new ArrayList<>(); + + boolean primero = true; + if (camposActualizar.containsKey("nombre")) { + if (!primero) sql.append(", "); + sql.append("NOMBRE_EMPLEADO = ?"); + parametros.add(camposActualizar.get("nombre")); + primero = false; + } + + if (camposActualizar.containsKey("email")) { + if (!primero) sql.append(", "); + sql.append("EMAIL_EMPLEADO = ?"); + parametros.add(camposActualizar.get("email")); + primero = false; + } + + if (camposActualizar.containsKey("contrasena")) { + if (!primero) sql.append(", "); + sql.append("CONTRASENA_EMPLEADO = ?"); + String contrasenaHasheada = passwordEncoder.encode((String) camposActualizar.get("contrasena")); + parametros.add(contrasenaHasheada); + primero = false; + } + + sql.append(" WHERE ID_EMPLEADO = ?"); + parametros.add(id); + + try { + int value = jdbcTemplate.update(sql.toString(), parametros.toArray()); + return value > 0; + } catch (DataAccessException e) { + e.printStackTrace(); + return false; + } + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/Ingredientes/IngredientesService.java b/Proyecto/src/main/java/com/example/Proyecto/service/Ingredientes/IngredientesService.java new file mode 100644 index 0000000..6cd55fd --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/Ingredientes/IngredientesService.java @@ -0,0 +1,106 @@ +package com.example.Proyecto.service.Ingredientes; + +import com.example.Proyecto.controller.CategoriaIngredientesController; +import com.example.Proyecto.model.Ingredientes; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import org.springframework.jdbc.core.RowMapper; + +@Service +public class IngredientesService { + + @Autowired + private JdbcTemplate jdbcTemplate; + + // Metodo para obtener lista de nombres de ingredientes + public List obtenerIngredientes() { + String sql = "SELECT NOMBRE_INGREDIENTE FROM Ingredientes"; + return jdbcTemplate.query(sql, new RowMapper() { + @Override + public String mapRow(ResultSet rs, int rowNum) throws SQLException { + return rs.getString("NOMBRE_INGREDIENTE"); + } + }); + } + + // Metodo para obtener todos los ingredientes + public List obtenerTodosLosIngredientes() { + String sql = "SELECT * FROM Ingredientes"; + return jdbcTemplate.query(sql, new RowMapper() { + @Override + public Ingredientes mapRow(ResultSet rs, int rowNum) throws SQLException { + Ingredientes ingrediente = new Ingredientes(); + ingrediente.setIdIngrediente(rs.getInt("ID_INGREDIENTE")); + ingrediente.setIdProveedor(rs.getInt("ID_PROVEEDOR")); + ingrediente.setIdCategoria(rs.getInt("ID_CATEGORIA")); + ingrediente.setNombreIngrediente(rs.getString("NOMBRE_INGREDIENTE")); + ingrediente.setCantidadIngrediente(rs.getInt("CANTIDAD_INGREDIENTE")); + ingrediente.setFechaVencimiento(rs.getDate("FECHA_VENCIMIENTO")); + ingrediente.setReferenciaIngrediente(rs.getString("REFERENCIA_INGREDIENTE")); + return ingrediente; + } + }); + } + + + // Metodo para crear un nuevo ingrediente (POST) + public void crearIngrediente(Ingredientes ingrediente) { + String sql = "INSERT INTO Ingredientes (ID_PROVEEDOR, ID_CATEGORIA, NOMBRE_INGREDIENTE, CANTIDAD_INGREDIENTE, FECHA_VENCIMIENTO, REFERENCIA_INGREDIENTE, FECHA_ENTREGA_INGREDIENTE) " + + "VALUES (?, ?, ?, ?, ?, ?, ?)"; + jdbcTemplate.update(sql, + ingrediente.getIdProveedor(), // ID_PROVEEDOR + ingrediente.getIdCategoria(), // ID_CATEGORIA + ingrediente.getNombreIngrediente(), // NOMBRE_INGREDIENTE + ingrediente.getCantidadIngrediente(), // CANTIDAD_INGREDIENTE + ingrediente.getFechaVencimiento(), // FECHA_VENCIMIENTO + ingrediente.getReferenciaIngrediente(), // REFERENCIA_INGREDIENTE + ingrediente.getFechaEntregaIngrediente()// FECHA_ENTREGA_INGREDIENTE + ); + } + //Intento metodo + // Metodo para actualizar un ingrediente (PUT) + public int editarIngrediente(Ingredientes ingrediente) { + String sql = "UPDATE Ingredientes SET " + + "ID_PROVEEDOR = ?, " + + "ID_CATEGORIA = ?, " + + "NOMBRE_INGREDIENTE = ?, " + + "CANTIDAD_INGREDIENTE = ?, " + + "FECHA_VENCIMIENTO = ?, " + + "REFERENCIA_INGREDIENTE = ?, " + + "FECHA_ENTREGA_INGREDIENTE = ? " + + "WHERE ID_INGREDIENTE = ?"; + // + return jdbcTemplate.update(sql, + ingrediente.getIdProveedor(), + ingrediente.getIdCategoria(), + ingrediente.getNombreIngrediente(), + ingrediente.getCantidadIngrediente(), + ingrediente.getFechaVencimiento(), + ingrediente.getReferenciaIngrediente(), + ingrediente.getFechaEntregaIngrediente(), + ingrediente.getIdIngrediente() // se actualiza el que tiene este ID + ); + } + + + // Metodo para eliminar un ingrediente (DELETE) + public int eliminarIngrediente(int idIngrediente) { + String sql = "DELETE FROM Ingredientes WHERE ID_INGREDIENTE = ?"; + return jdbcTemplate.update(sql, idIngrediente); + } + + //Métodod para actualizar cantidad de ingrediente + public int actualizarCantidad(int id, int cantidad) { + return jdbcTemplate.update( + "UPDATE Ingredientes SET CANTIDAD_INGREDIENTE=? WHERE ID_INGREDIENTE=?", + cantidad, id + ); + } + + + +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/Ordenes_salida/Ordenes_salidaService.java b/Proyecto/src/main/java/com/example/Proyecto/service/Ordenes_salida/Ordenes_salidaService.java new file mode 100644 index 0000000..711e499 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/Ordenes_salida/Ordenes_salidaService.java @@ -0,0 +1,30 @@ +package com.example.Proyecto.service.Ordenes_salida; + +import com.example.Proyecto.model.Ordenes_salida; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; +import java.util.List; + +@Service +public class Ordenes_salidaService { + + private final JdbcTemplate jdbcTemplate; + + public Ordenes_salidaService(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + public List obtenerOrdenesSalida() { + String sql = "SELECT ID_FACTURA, ID_CLIENTE, ID_PEDIDO, FECHA_FACTURACION, TOTAL_FACTURA FROM ordenes_salida"; + + return jdbcTemplate.query(sql, (rs, rowNum) -> + new Ordenes_salida( + rs.getInt("ID_FACTURA"), + rs.getLong("ID_CLIENTE"), + rs.getLong("ID_PEDIDO"), + rs.getDate("FECHA_FACTURACION").toLocalDate(), + rs.getDouble("TOTAL_FACTURA") + ) + ); + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/Pedidos/Estados_PedidosService.java b/Proyecto/src/main/java/com/example/Proyecto/service/Pedidos/Estados_PedidosService.java new file mode 100644 index 0000000..0db426b --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/Pedidos/Estados_PedidosService.java @@ -0,0 +1,69 @@ +package com.example.Proyecto.service.Pedidos; + +import com.example.Proyecto.model.Estado_Pedidos; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; + +@Service +public class Estados_PedidosService { + + @Autowired + private JdbcTemplate jdbcTemplate; + + // Método para obtener todos los Estados (GET) + public List obtenerEstado_Pedidos() { + String sql = "SELECT * FROM Estado_Pedidos"; + + return jdbcTemplate.query(sql, new RowMapper() { + @Override + public Estado_Pedidos mapRow(@NonNull ResultSet rs, int rowNum) throws SQLException { + Estado_Pedidos estadoPedidos = new Estado_Pedidos(); + // Se agrega el mapeo para el ID + estadoPedidos.setID_ESTADO_PEDIDO(rs.getLong("ID_ESTADO_PEDIDO")); + estadoPedidos.setNOMBRE_ESTADO(rs.getString("NOMBRE_ESTADO")); + return estadoPedidos; + } + }); + } + + // Metodo para crear Estados Pedido (POST) + public Long crearEstadoPedido(Estado_Pedidos estado) { + String sql = "INSERT INTO Estado_Pedidos (NOMBRE_ESTADO) VALUES (?)"; + KeyHolder keyHolder = new GeneratedKeyHolder(); + + jdbcTemplate.update(connection -> { + PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); + ps.setString(1, estado.getNOMBRE_ESTADO()); + return ps; + }, keyHolder); + + // Se devuelve un Long para evitar posibles desbordamientos + Number key = keyHolder.getKey(); + return key != null ? key.longValue() : -1L; + } + + // Metodo para Actualizar Estados Pedido (PUT) + public void actualizarEstado(Long id, Estado_Pedidos estado) { + String sql = "UPDATE Estado_Pedidos SET NOMBRE_ESTADO = ? WHERE ID_ESTADO_PEDIDO = ?"; + jdbcTemplate.update(sql, estado.getNOMBRE_ESTADO(), id); + } + + // Metodo para Eliminar Estados Pedido (DELETE) + public void eliminarestadoPedido(Long id) { + // Se corrige el nombre de la columna para que coincida con la tabla + String sql = "DELETE FROM Estado_Pedidos WHERE ID_ESTADO_PEDIDO = ?"; + jdbcTemplate.update(sql, id); + } +} + diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/Pedidos/pedidosService.java b/Proyecto/src/main/java/com/example/Proyecto/service/Pedidos/pedidosService.java new file mode 100644 index 0000000..2f59c05 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/Pedidos/pedidosService.java @@ -0,0 +1,79 @@ +package com.example.Proyecto.service.Pedidos; + +import com.example.Proyecto.model.Pedidos; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; + +import java.sql.*; +import java.util.List; + +@Service +public class pedidosService { + + @Autowired + private JdbcTemplate jdbcTemplate; + + // Método para obtener todos los pedidos (GET) + public List obtenerPedidos() { + String sql = "SELECT * FROM Pedidos"; + return jdbcTemplate.query(sql, new RowMapper() { + @Override + public Pedidos mapRow(@NonNull ResultSet rs, int rowNum) throws SQLException { + Pedidos pedido = new Pedidos(); + // Utiliza los métodos get correspondientes + pedido.setID_CLIENTE(rs.getLong("ID_CLIENTE")); + pedido.setID_EMPLEADO(rs.getLong("ID_EMPLEADO")); + pedido.setID_ESTADO_PEDIDO(rs.getLong("ID_ESTADO_PEDIDO")); + pedido.setFECHA_INGRESO(rs.getDate("FECHA_INGRESO")); + pedido.setFECHA_ENTREGA(rs.getDate("FECHA_ENTREGA")); + pedido.setTOTAL_PRODUCTO(rs.getBigDecimal("TOTAL_PRODUCTO")); + return pedido; + } + }); + } + + // Método para crear un nuevo pedido (POST) + public int crearPedido(Pedidos pedido) { + String sql = "INSERT INTO Pedidos (ID_CLIENTE, ID_EMPLEADO, ID_ESTADO_PEDIDO, FECHA_INGRESO, FECHA_ENTREGA, TOTAL_PRODUCTO) VALUES (?, ?, ?, ?, ?, ?)"; + + KeyHolder keyHolder = new GeneratedKeyHolder(); + + jdbcTemplate.update(connection -> { + PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); + ps.setLong(1, pedido.getID_CLIENTE()); + ps.setLong(2, pedido.getID_EMPLEADO()); + ps.setLong(3, pedido.getID_ESTADO_PEDIDO()); + ps.setDate(4, new java.sql.Date(pedido.getFECHA_INGRESO().getTime())); + ps.setDate(5, new java.sql.Date(pedido.getFECHA_ENTREGA().getTime())); + ps.setBigDecimal(6, pedido.getTOTAL_PRODUCTO()); + return ps; + }, keyHolder); + + Number key = keyHolder.getKey(); + return key != null ? key.intValue() : -1; + } + // Método para actualizar un pedido (PUT) + public void actualizarPedido(Long id, Pedidos pedido) { + String sql = "UPDATE Pedidos SET ID_CLIENTE = ?, ID_EMPLEADO = ?, ID_ESTADO_PEDIDO = ?, FECHA_INGRESO = ?, FECHA_ENTREGA = ?, TOTAL_PRODUCTO = ? WHERE ID_PEDIDO = ?"; + + jdbcTemplate.update(sql, + pedido.getID_CLIENTE(), + pedido.getID_EMPLEADO(), + pedido.getID_ESTADO_PEDIDO(), + new java.sql.Date(pedido.getFECHA_INGRESO().getTime()), + new java.sql.Date(pedido.getFECHA_ENTREGA().getTime()), + pedido.getTOTAL_PRODUCTO(), + id + ); + } + // Método para eliminar un pedido (DELETE) + public void eliminarPedido(Long id) { + String sql = "DELETE FROM Pedidos WHERE ID_PEDIDO = ?"; + jdbcTemplate.update(sql, id); + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/PedidosProveedores/PedidosProveedores.java b/Proyecto/src/main/java/com/example/Proyecto/service/PedidosProveedores/PedidosProveedores.java new file mode 100644 index 0000000..fb21c2e --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/PedidosProveedores/PedidosProveedores.java @@ -0,0 +1,29 @@ +// Archivo: PedidosProveedores.java +package com.example.Proyecto.service.PedidosProveedores; + +import java.util.Date; + +public class PedidosProveedores { + private int IdPedidoProv; + private int IdProveedor; + private int NumeroPedido; // <-- Cambiado a 'int' + private Date FechaPedido; + private String EstadoPedido; + + public PedidosProveedores() {} + + public int getIdPedidoProv() { return IdPedidoProv; } + public void setIdPedidoProv(int IdPedidoProv) { this.IdPedidoProv = IdPedidoProv; } + + public int getIdProveedor() { return IdProveedor; } + public void setIdProveedor(int IdProveedor) { this.IdProveedor = IdProveedor; } + + public int getNumeroPedido() { return NumeroPedido; } // <-- Retorna 'int' + public void setNumeroPedido(int NumeroPedido) { this.NumeroPedido = NumeroPedido; } // <-- Recibe 'int' + + public Date getFechaPedido() { return FechaPedido; } + public void setFechaPedido(Date FechaPedido) { this.FechaPedido = FechaPedido; } + + public String getEstadoPedido() { return EstadoPedido; } + public void setEstadoPedido(String EstadoPedido) { this.EstadoPedido = EstadoPedido; } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/PedidosProveedores/PedidosProveedoresService.java b/Proyecto/src/main/java/com/example/Proyecto/service/PedidosProveedores/PedidosProveedoresService.java new file mode 100644 index 0000000..4c77839 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/PedidosProveedores/PedidosProveedoresService.java @@ -0,0 +1,69 @@ +// Archivo: PedidosProveedoresService.java +package com.example.Proyecto.service.PedidosProveedores; + +import com.example.Proyecto.service.PedidosProveedores.PedidosProveedores; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +@Service +public class PedidosProveedoresService { + + @Autowired + private JdbcTemplate jdbcTemplate; + + // Archivo: PedidosProveedoresService.java + +// ... + + // Obtener todos los pedidos de proveedores + public List obtenerTodosLosPedidosProveedores() { + String sql = "SELECT * FROM Pedidos_Proveedores"; + return jdbcTemplate.query(sql, new RowMapper() { + @Override + public PedidosProveedores mapRow(@NonNull ResultSet rs, int rowNum) throws SQLException { + PedidosProveedores pedido = new PedidosProveedores(); + pedido.setIdPedidoProv(rs.getInt("ID_PEDIDO_PROV")); + pedido.setIdProveedor(rs.getInt("ID_PROVEEDOR")); + pedido.setNumeroPedido(rs.getInt("NUMERO_PEDIDO")); // <-- CORRECCIÓN: Usar getInt + pedido.setFechaPedido(rs.getDate("FECHA_PEDIDO")); + pedido.setEstadoPedido(rs.getString("ESTADO_PEDIDO")); + return pedido; + } + }); + } + + // Crear un nuevo pedido de proveedor (POST) + public void crearPedidoProveedor(PedidosProveedores pedido) { + String sql = "INSERT INTO Pedidos_Proveedores (ID_PROVEEDOR, NUMERO_PEDIDO, FECHA_PEDIDO, ESTADO_PEDIDO) VALUES (?, ?, ?, ?)"; + jdbcTemplate.update(sql, + pedido.getIdProveedor(), + pedido.getNumeroPedido(), + pedido.getFechaPedido(), + pedido.getEstadoPedido() + ); + } + + // Actualizar un pedido de proveedor (PUT) + public int editarPedidoProveedor(PedidosProveedores pedido) { + String sql = "UPDATE Pedidos_Proveedores SET ID_PROVEEDOR=?, NUMERO_PEDIDO=?, FECHA_PEDIDO=?, ESTADO_PEDIDO=? WHERE ID_PEDIDO_PROV=?"; + return jdbcTemplate.update(sql, + pedido.getIdProveedor(), + pedido.getNumeroPedido(), + pedido.getFechaPedido(), + pedido.getEstadoPedido(), + pedido.getIdPedidoProv() + ); + } + + // Eliminar un pedido de proveedor (DELETE) + public int eliminarPedidoProveedor(int idPedidoProv) { + String sql = "DELETE FROM Pedidos_Proveedores WHERE ID_PEDIDO_PROV = ?"; + return jdbcTemplate.update(sql, idPedidoProv); + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/Productos/ProductosService.java b/Proyecto/src/main/java/com/example/Proyecto/service/Productos/ProductosService.java new file mode 100644 index 0000000..46affa0 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/Productos/ProductosService.java @@ -0,0 +1,57 @@ +package com.example.Proyecto.service.Productos; + +import com.example.Proyecto.model.PojoProductos; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class ProductosService { + + @Autowired + private JdbcTemplate jdbcTemplate; + + public List> obtenerDetallesProducto() { + String sql = "SELECT ID_PRODUCTO, NOMBRE_PRODUCTO, PRECIO_PRODUCTO FROM Productos"; + return jdbcTemplate.query(sql, new RowMapper>() { + @Override + public Map mapRow(@NonNull ResultSet rs, int rowNum) throws SQLException { + Map producto = new HashMap<>(); + producto.put("Id:", rs.getInt("ID_PRODUCTO")); + producto.put("Nombre:", rs.getString("NOMBRE_PRODUCTO")); + producto.put("Precio:", rs.getDouble("PRECIO_PRODUCTO")); + return producto; + } + }); + } + + public boolean crearProducto(PojoProductos pojoProductos) { + String sql = "INSERT INTO Productos (NOMBRE_PRODUCTO, PRECIO_PRODUCTO) VALUES (?, ?)"; + try { + int result = jdbcTemplate.update(sql, pojoProductos.getNombreProducto(), pojoProductos.getPrecio()); + return result > 0; + } catch (DataAccessException e) { + return false; + } + } + + public boolean actualizarProducto(PojoProductos pojoProductos) { + String sql = "UPDATE Productos SET NOMBRE_PRODUCTO = ?, PRECIO_PRODUCTO = ? WHERE ID_PRODUCTO = ?"; + try { + int value = jdbcTemplate.update(sql, pojoProductos.getNombreProducto(), pojoProductos.getPrecio(), pojoProductos.getId()); + return value > 0; + } catch (DataAccessException e) { + e.printStackTrace(); + return false; + } + } +} diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/Proveedores/Proveedores.java b/Proyecto/src/main/java/com/example/Proyecto/service/Proveedores/Proveedores.java new file mode 100644 index 0000000..12a4e81 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/Proveedores/Proveedores.java @@ -0,0 +1,31 @@ +// Archivo: Proveedores.java +package com.example.Proyecto.service.Proveedores; + +public class Proveedores { + private int idProveedor; + private String nombreProv; + private String telefonoProv; + private Boolean activoProv; + private String emailProv; + private String direccionProv; + + public Proveedores() {} + + public int getIdProveedor() { return idProveedor; } + public void setIdProveedor(int idProveedor) { this.idProveedor = idProveedor; } + + public String getNombreProv() { return nombreProv; } + public void setNombreProv(String nombreProv) { this.nombreProv = nombreProv; } + + public String getTelefonoProv() { return telefonoProv; } + public void setTelefonoProv(String telefonoProv) { this.telefonoProv = telefonoProv; } + + public Boolean getActivoProv() { return activoProv; } + public void setActivoProv(Boolean activoProv) { this.activoProv = activoProv; } + + public String getEmailProv() { return emailProv; } + public void setEmailProv(String emailProv) { this.emailProv = emailProv; } + + public String getDireccionProv() { return direccionProv; } + public void setDireccionProv(String direccionProv) { this.direccionProv = direccionProv; } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/Proveedores/ProveedoresService.java b/Proyecto/src/main/java/com/example/Proyecto/service/Proveedores/ProveedoresService.java new file mode 100644 index 0000000..134d180 --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/Proveedores/ProveedoresService.java @@ -0,0 +1,69 @@ +// Archivo: ProveedoresService.java +package com.example.Proyecto.service.Proveedores; + +import com.example.Proyecto.service.Proveedores.Proveedores; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Service; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +@Service +public class ProveedoresService { + + @Autowired + private JdbcTemplate jdbcTemplate; + + // Obtener todos los proveedores + public List obtenerTodosLosProveedores() { + String sql = "SELECT * FROM Proveedores"; + return jdbcTemplate.query(sql, new RowMapper() { + @Override + public Proveedores mapRow(@NonNull ResultSet rs, int rowNum) throws SQLException { + Proveedores proveedor = new Proveedores(); + proveedor.setIdProveedor(rs.getInt("ID_PROVEEDOR")); + proveedor.setNombreProv(rs.getString("NOMBRE_PROV")); + proveedor.setTelefonoProv(rs.getString("TELEFONO_PROV")); + proveedor.setActivoProv(rs.getBoolean("ACTIVO_PROV")); + proveedor.setEmailProv(rs.getString("EMAIL_PROV")); + proveedor.setDireccionProv(rs.getString("DIRECCION_PROV")); + return proveedor; + } + }); + } + + // Crear un nuevo proveedor (POST) + public void crearProveedor(Proveedores proveedor) { + String sql = "INSERT INTO Proveedores (NOMBRE_PROV, TELEFONO_PROV, ACTIVO_PROV, EMAIL_PROV, DIRECCION_PROV) " + + "VALUES (?, ?, ?, ?, ?)"; + jdbcTemplate.update(sql, + proveedor.getNombreProv(), + proveedor.getTelefonoProv(), + proveedor.getActivoProv(), + proveedor.getEmailProv(), + proveedor.getDireccionProv() + ); + } + + // Actualizar un proveedor (PUT) + public int editarProveedor(Proveedores proveedor) { + String sql = "UPDATE Proveedores SET NOMBRE_PROV=?, TELEFONO_PROV=?, ACTIVO_PROV=?, EMAIL_PROV=?, DIRECCION_PROV=? WHERE ID_PROVEEDOR=?"; + return jdbcTemplate.update(sql, + proveedor.getNombreProv(), + proveedor.getTelefonoProv(), + proveedor.getActivoProv(), + proveedor.getEmailProv(), + proveedor.getDireccionProv(), + proveedor.getIdProveedor() + ); + } + + // Eliminar un proveedor (DELETE) + public int eliminarProveedor(int idProveedor) { + String sql = "DELETE FROM Proveedores WHERE ID_PROVEEDOR = ?"; + return jdbcTemplate.update(sql, idProveedor); + } +} \ No newline at end of file diff --git a/Proyecto/src/main/java/com/example/Proyecto/service/UsuariosRegistradosService/UsuariosRegistradosService.java b/Proyecto/src/main/java/com/example/Proyecto/service/UsuariosRegistradosService/UsuariosRegistradosService.java new file mode 100644 index 0000000..5f6397e --- /dev/null +++ b/Proyecto/src/main/java/com/example/Proyecto/service/UsuariosRegistradosService/UsuariosRegistradosService.java @@ -0,0 +1,56 @@ +package com.example.Proyecto.service.UsuariosRegistradosService; + +import com.example.Proyecto.dto.UsuariosRegistradosDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class UsuariosRegistradosService { + + @Autowired + private JdbcTemplate jdbcTemplate; + + public List obtenerUsuariosRegistrados() { + List usuariosRegistrados = new ArrayList<>(); + + // Clientes + String sqlClientes = "SELECT NOMBRE_CLI, EMAIL_CLI, TELEFONO_CLI FROM clientes"; + usuariosRegistrados.addAll(jdbcTemplate.query(sqlClientes, (rs, rowNum) -> + new UsuariosRegistradosDTO( + rs.getString("NOMBRE_CLI"), + rs.getString("EMAIL_CLI"), + rs.getString("TELEFONO_CLI"), + "Cliente" + ) + )); + + // Empleados + String sqlEmpleados = "SELECT NOMBRE_EMPLEADO, EMAIL_EMPLEADO FROM empleados"; + usuariosRegistrados.addAll(jdbcTemplate.query(sqlEmpleados, (rs, rowNum) -> + new UsuariosRegistradosDTO( + rs.getString("NOMBRE_EMPLEADO"), + rs.getString("EMAIL_EMPLEADO"), + null, + "Empleado" + ) + )); + + // Administradores + String sqlAdmins = "SELECT NOMBRE_ADMIN, EMAIL_ADMIN FROM administradores"; + usuariosRegistrados.addAll(jdbcTemplate.query(sqlAdmins, (rs, rowNum) -> + new UsuariosRegistradosDTO( + rs.getString("NOMBRE_ADMIN"), + rs.getString("EMAIL_ADMIN"), + null, + "Administrador" + ) + )); + + return usuariosRegistrados; + } +} + diff --git a/target/classes/application.properties b/Proyecto/src/main/resources/application.properties similarity index 65% rename from target/classes/application.properties rename to Proyecto/src/main/resources/application.properties index 1999fef..15912fe 100644 --- a/target/classes/application.properties +++ b/Proyecto/src/main/resources/application.properties @@ -6,6 +6,8 @@ spring.datasource.password= spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # Hibernate/JPA Configuration spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect -spring.jpa.hibernate.ddl-auto=update -spring.datasource.initialization-mode=always -spring.sql.init.mode=always \ No newline at end of file +spring.jpa.hibernate.ddl-auto=none +spring.jpa.show-sql=true +spring.datasource.initialization-mode=never +spring.sql.init.mode=never +logging.level.org.springframework.web.servlet=DEBUG \ No newline at end of file diff --git a/Proyecto/src/test/java/com/example/Proyecto/ProyectoApplicationTests.java b/Proyecto/src/test/java/com/example/Proyecto/ProyectoApplicationTests.java new file mode 100644 index 0000000..e35eaaf --- /dev/null +++ b/Proyecto/src/test/java/com/example/Proyecto/ProyectoApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.Proyecto; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ProyectoApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/Proyecto/target/classes/application.properties b/Proyecto/target/classes/application.properties new file mode 100644 index 0000000..15912fe --- /dev/null +++ b/Proyecto/target/classes/application.properties @@ -0,0 +1,13 @@ +spring.application.name=Proyecto +# MySQL DataSource Configuration +spring.datasource.url=jdbc:mysql://localhost:3306/proyectopanaderia +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +# Hibernate/JPA Configuration +spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect +spring.jpa.hibernate.ddl-auto=none +spring.jpa.show-sql=true +spring.datasource.initialization-mode=never +spring.sql.init.mode=never +logging.level.org.springframework.web.servlet=DEBUG \ No newline at end of file diff --git a/Proyecto/target/classes/com/example/Proyecto/Controllers/ConexionController.class b/Proyecto/target/classes/com/example/Proyecto/Controllers/ConexionController.class new file mode 100644 index 0000000..ab7d04a Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Controllers/ConexionController.class differ diff --git a/target/classes/com/example/Proyecto/ProyectoApplication.class b/Proyecto/target/classes/com/example/Proyecto/ProyectoApplication.class similarity index 100% rename from target/classes/com/example/Proyecto/ProyectoApplication.class rename to Proyecto/target/classes/com/example/Proyecto/ProyectoApplication.class diff --git a/Proyecto/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService$1.class b/Proyecto/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService$1.class new file mode 100644 index 0000000..fde7521 Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService$1.class differ diff --git a/Proyecto/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService.class b/Proyecto/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService.class new file mode 100644 index 0000000..5d663c0 Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService.class differ diff --git a/Proyecto/target/classes/com/example/Proyecto/Services/Administrador/PojoAdmin.class b/Proyecto/target/classes/com/example/Proyecto/Services/Administrador/PojoAdmin.class new file mode 100644 index 0000000..747dfab Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Services/Administrador/PojoAdmin.class differ diff --git a/Proyecto/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService$1.class b/Proyecto/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService$1.class new file mode 100644 index 0000000..286f4ef Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService$1.class differ diff --git a/Proyecto/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService.class b/Proyecto/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService.class new file mode 100644 index 0000000..19c1dd2 Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService.class differ diff --git a/Proyecto/target/classes/com/example/Proyecto/Services/Clientes/PojoCliente.class b/Proyecto/target/classes/com/example/Proyecto/Services/Clientes/PojoCliente.class new file mode 100644 index 0000000..484c627 Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Services/Clientes/PojoCliente.class differ diff --git a/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService$1.class b/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService$1.class new file mode 100644 index 0000000..558be44 Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService$1.class differ diff --git a/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.class b/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.class new file mode 100644 index 0000000..d73da50 Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.class differ diff --git a/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.class b/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.class new file mode 100644 index 0000000..c3b8104 Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.class differ diff --git a/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/PojoEmpleado.class b/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/PojoEmpleado.class new file mode 100644 index 0000000..373fb85 Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/Services/Empleados/PojoEmpleado.class differ diff --git a/Proyecto/target/classes/com/example/Proyecto/config/SecurityConfig.class b/Proyecto/target/classes/com/example/Proyecto/config/SecurityConfig.class new file mode 100644 index 0000000..a6bffa8 Binary files /dev/null and b/Proyecto/target/classes/com/example/Proyecto/config/SecurityConfig.class differ diff --git a/Proyecto/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/Proyecto/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..62206b6 --- /dev/null +++ b/Proyecto/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,11 @@ +com\example\Proyecto\Services\Clientes\ConexionClienteService.class +com\example\Proyecto\Services\Empleados\PojoEmpleado.class +com\example\Proyecto\ProyectoApplication.class +com\example\Proyecto\Services\Empleados\ConexionEmpleadoService.class +com\example\Proyecto\Services\Clientes\PojoCliente.class +com\example\Proyecto\Services\Clientes\ConexionClienteService$1.class +com\example\Proyecto\Controllers\ConexionController.class +com\example\Proyecto\config\SecurityConfig.class +com\example\Proyecto\Services\Empleados\PojoDeleteEmpleado.class +com\example\Proyecto\Services\Empleados\ConexionEmpleadoService$1.class +com\example\Proyecto\Services\Administrador\PojoAdmin.class diff --git a/Proyecto/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/Proyecto/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..a00902d --- /dev/null +++ b/Proyecto/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,10 @@ +C:\Users\User\Desktop\Proyecto\Proyecto\src\main\java\com\example\Proyecto\config\SecurityConfig.java +C:\Users\User\Desktop\Proyecto\Proyecto\src\main\java\com\example\Proyecto\Controllers\ConexionController.java +C:\Users\User\Desktop\Proyecto\Proyecto\src\main\java\com\example\Proyecto\ProyectoApplication.java +C:\Users\User\Desktop\Proyecto\Proyecto\src\main\java\com\example\Proyecto\Services\Administrador\ConexionAdminService.java +C:\Users\User\Desktop\Proyecto\Proyecto\src\main\java\com\example\Proyecto\Services\Administrador\PojoAdmin.java +C:\Users\User\Desktop\Proyecto\Proyecto\src\main\java\com\example\Proyecto\Services\Clientes\ConexionClienteService.java +C:\Users\User\Desktop\Proyecto\Proyecto\src\main\java\com\example\Proyecto\Services\Clientes\PojoCliente.java +C:\Users\User\Desktop\Proyecto\Proyecto\src\main\java\com\example\Proyecto\Services\Empleados\ConexionEmpleadoService.java +C:\Users\User\Desktop\Proyecto\Proyecto\src\main\java\com\example\Proyecto\Services\Empleados\PojoDeleteEmpleado.java +C:\Users\User\Desktop\Proyecto\Proyecto\src\main\java\com\example\Proyecto\Services\Empleados\PojoEmpleado.java diff --git a/Proyecto/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/Proyecto/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst new file mode 100644 index 0000000..1ca9dbd --- /dev/null +++ b/Proyecto/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst @@ -0,0 +1 @@ +com\example\Proyecto\ProyectoApplicationTests.class diff --git a/Proyecto/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/Proyecto/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst new file mode 100644 index 0000000..57de393 --- /dev/null +++ b/Proyecto/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst @@ -0,0 +1 @@ +C:\Users\User\Desktop\Proyecto\Proyecto\src\test\java\com\example\Proyecto\ProyectoApplicationTests.java diff --git a/Proyecto/target/test-classes/com/example/Proyecto/ProyectoApplicationTests.class b/Proyecto/target/test-classes/com/example/Proyecto/ProyectoApplicationTests.class new file mode 100644 index 0000000..18bc2cf Binary files /dev/null and b/Proyecto/target/test-classes/com/example/Proyecto/ProyectoApplicationTests.class differ diff --git a/api-client.php b/api-client.php new file mode 100644 index 0000000..46c5ede --- /dev/null +++ b/api-client.php @@ -0,0 +1,125 @@ + $usuario) { + echo "Cliente " . ($recorrido + 1) . ":\n"; + foreach ($usuario as $atributo => $valor) { + echo " $atributo $valor\n"; + } + echo "------------------------\n"; + } + echo "====================================================\n"; + echo "Total de clientes: " . count($usuarios_clientes) . "\n"; + echo "====================================================\n"; + } else if ($opcion == 2) { + echo "Vista de clientes omitida.\n"; + } + +} else if ($decision == 2) { + echo "Bienvenido Empleado $nombre_user\n"; + echo "¿Desea ver todos los datos de los administradores?\n"; + echo "1. Sí\n"; + echo "2. No\n"; + $opcion = readline(); + + if ($opcion == 1) { + foreach ($usuarios_admins as $recorrido => $admin) { + echo "Administrador " . ($recorrido + 1) . ":\n"; + echo " Nombre: " . ($admin['Nombre:'] ?? 'No disponible') . "\n"; + echo " Telefono: " . ($admin['Telefono:'] ?? 'No disponible') . "\n"; + echo "------------------------\n"; + } + echo "====================================================\n"; + echo "Total de administradores: " . count($usuarios_admins) . "\n"; + echo "====================================================\n"; + } else if ($opcion == 2) { + echo "Saliendo del sistema....\n"; + } + +} else if ($decision == 3) { + echo "Cerrando programa...\n"; + exit; +} else { + echo "Opción inválida.\n"; +} + +// POST // +echo ("Desea ingresar un nuevo usuario?\n"); +echo "Seleccione el numero de opcion\n"; +echo "1. Si \n"; +echo "2. No \n"; +$peticion = readline (); + +if($peticion == 1) { + $nombre = readline ("Ingrese el nombre: "); + $telefono = readline ("Ingrese el telefono: "); + $correo = readline ("Ingrese el correo: "); + $contrasena = readline ("Ingrese la contraseña: "); + + $datos_nuevos = array( + "nombre" => $nombre, + "email" => $correo, + "telefono" => $telefono, + "contrasena" => $contrasena + ); + + $data_json = json_encode($datos_nuevos); + + $proceso = curl_init($url_crear_cliente); + curl_setopt($proceso, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($proceso, CURLOPT_POSTFIELDS, $data_json); + curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true); + curl_setopt($proceso, CURLOPT_HTTPHEADER, array( + "Content-Type: application/json", + "Content-Length: " . strlen($data_json) + )); + + $response = curl_exec($proceso); + $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE); + + if(curl_errno($proceso)) { + echo 'Error en la petición: ' . curl_error($proceso); + } else { + if ($http_code == 200) { + echo "Usuario creado exitosamente.\n"; + } else { + echo "Error al crear el usuario. Código HTTP: $http_code\n"; + } + } + curl_close($proceso); +} +?> diff --git a/files/CORRECCION_DETALLE_PEDIDOS.md b/files/CORRECCION_DETALLE_PEDIDOS.md deleted file mode 100644 index e69de29..0000000 diff --git a/files/DOCS_EDICION_INLINE.md b/files/DOCS_EDICION_INLINE.md deleted file mode 100644 index e69de29..0000000 diff --git a/files/DOCUMENTACION_MODAL_EMPLEADOS.md b/files/DOCUMENTACION_MODAL_EMPLEADOS.md deleted file mode 100644 index e69de29..0000000 diff --git a/files/ESTRUCTURA_BD_FINAL.md b/files/ESTRUCTURA_BD_FINAL.md deleted file mode 100644 index e69de29..0000000 diff --git a/files/Homepage.php b/files/Homepage.php deleted file mode 100644 index 971ded8..0000000 --- a/files/Homepage.php +++ /dev/null @@ -1,398 +0,0 @@ - - - - - - - El Castillo del Pan - - - - - - - - - - - - - - - - - - - -
- -
- - -
- - - - -
-

Nuestros Productos Destacados

-

Una selección de nuestras delicias más populares.

- -
- -
-
- Brazo de Reina -
-
Brazo de Reina
-

Bizcochuelo suave relleno de arequipe artesanal, un clásico irresistible.

-
-
-
Brazo de Reina
-

¡Especialidad de la casa! Preparado con ingredientes premium y amor artesanal.

-
-
-
- - -
-
- Hojaldres -
-
Hojaldres
-

Capas crujientes de masa fina con rellenos selectos y dorados perfectos.

-
-
-
Hojaldres
-

Masa hojaldrada artesanal con rellenos que cambian según la temporada.

-
-
-
- - -
-
- Panes grandes -
-
Panes Grandes
-

Pan artesanal con corteza dorada y miga suave, ideal para compartir.

-
-
-
Panes Grandes
-

Horneados diariamente con masa madre tradicional e ingredientes naturales.

-
-
-
- - -
-
- Brownies -
-
Brownies
-

Esponjosos con rellenos de Chocolate.

-
-
-
Brownies
-

Nuestra obra magna de años de tradición en cada bocado.

-
-
-
- - -
-
- Croissants -
-
Croissants
-

Hojaldre francés auténtico, mantequillosos y perfectamente dorados.

-
-
-
Croissants
-

Técnica francesa tradicional con ingredientes locales de primera calidad.

-
-
-
- - -
-
- Muffins -
-
Muffins
-

Esponjosos y llenos de sabor, perfectos para acompañar tu café.

-
-
-
Muffins
-

Variedad de sabores que cambian semanalmente para sorprenderte.

-
-
-
-
-
- - -
-
-
-
-

Un poco sobre nosotros...

-

- Somos una Panadería Artesanal con más de 10 años de experiencia, ubicada en Bogotá en el sector de Bosa el Recreo. Desde 2015, El Castillo del Pan ha sido el corazón de la panadería artesanal en nuestra comunidad. - Nos caracterizamos por ofrecer productos frescos y de alta calidad, elaborados con recetas tradicionales. - -

- Conoce más -
-
- Nuestra panadería -
-
-
-
-
- - -
-
-
-
-
- - El Castillo del Pan -
-

- Panadería artesanal con más de 10 años de experiencia, - ofreciendo productos frescos y de la más alta calidad. -

-
-
-
Enlaces
- -
-
-
Productos
- -
-
-
Contacto
-

- - 123 Calle Principal, Ciudad -

-

- - (555) 123-4567 -

-

- - info@elcastillodelpan.com -

-
- - - -
-
-
-
-
-
-

- © 2024 El Castillo del Pan. Todos los derechos reservados. -

-
-
- - Hecho con para nuestros clientes - -
-
-
-
- - - - - - - diff --git a/files/PROYECTOPANADERIA.sql b/files/PROYECTOPANADERIA.sql deleted file mode 100644 index 48462ea..0000000 --- a/files/PROYECTOPANADERIA.sql +++ /dev/null @@ -1,1034 +0,0 @@ --- ================================================================== --- PROYECTO PANADERÍA - BASE DE DATOS --- ================================================================== --- Autor: Sistema de Gestión de Panadería --- Fecha: 2025 --- Descripción: Base de datos completa para gestión de panadería --- Versión: 2.1 - Incluye sistema de logs y actualización de estructura --- ================================================================== - --- CARACTERÍSTICAS PRINCIPALES: --- - Gestión completa de productos con descripción opcional --- - Sistema de pedidos con detalles de productos --- - Control de inventario y stock mínimo --- - Gestión de empleados, clientes y administradores --- - Sistema de logs para auditoría de cambios en productos --- - Triggers automáticos para actualización de totales --- - Funciones de utilidad para encriptación y generación de códigos --- - Estructura optimizada para dashboard de empleados y administradores - --- ESTRUCTURA DE TABLAS PRINCIPALES: --- - Productos: Incluye DESCRIPCION_PRODUCTO opcional --- - Detalle_Pedidos: Sin columnas de imagen, solo datos esenciales --- - Empleados: Con control de estado activo/inactivo --- - Pedidos: Con estados y totales automáticos --- - Sistema de logs: Para auditoría de cambios - --- INSTRUCCIONES DE INSTALACIÓN: --- --- OPCIÓN 1: INSTALACIÓN NUEVA (Base de datos desde cero) --- 1. Ejecutar todo el script completo --- 2. La base de datos se creará con todas las tablas y datos --- --- OPCIÓN 2: ACTUALIZACIÓN DE BASE EXISTENTE --- 1. Ejecutar solo las secciones de "MIGRACIONES Y ACTUALIZACIONES" --- 2. Verificar que los cambios se aplicaron correctamente --- 3. Los datos existentes se mantendrán intactos --- --- ================================================================== - --- Configuración inicial -DROP DATABASE IF EXISTS ProyectoPanaderia; -SET SQL_SAFE_UPDATES = 0; -CREATE DATABASE ProyectoPanaderia; -USE ProyectoPanaderia; - --- ================================================================== --- DDL (DATA DEFINITION LANGUAGE) - DEFINICIÓN DE ESTRUCTURA --- ================================================================== - --- ================================================================== --- CREACIÓN DE TABLAS PRINCIPALES --- ================================================================== - --- Tabla: Clientes - Almacena información de los clientes -CREATE TABLE Clientes ( - ID_CLIENTE INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_CLI VARCHAR(100) NOT NULL, - TELEFONO_CLI VARCHAR(20), - ACTIVO_CLI BOOLEAN DEFAULT TRUE, - EMAIL_CLI VARCHAR(100), - CONTRASEÑA_CLI VARCHAR(255), - SALT_CLI VARCHAR(32) -); - --- Tabla: Empleados - Almacena información de los empleados -CREATE TABLE Empleados ( - ID_EMPLEADO INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_EMPLEADO VARCHAR(100) NOT NULL, - EMAIL_EMPLEADO VARCHAR(100) NOT NULL, - ACTIVO_EMPLEADO BOOLEAN DEFAULT TRUE, - CONTRASEÑA_EMPLEADO VARCHAR(255), - SALT_EMPLEADO VARCHAR(32), - FECHA_REGISTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); - --- Tabla: Administradores - Almacena información de los administradores -CREATE TABLE Administradores ( - ID_ADMIN INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_ADMIN VARCHAR(100) NOT NULL, - TELEFONO_ADMIN VARCHAR(20), - EMAIL_ADMIN VARCHAR(100), - CONTRASEÑA_ADMIN VARCHAR(255), - SALT_ADMIN VARCHAR(32) -); - --- Tabla: Proveedores - Almacena información de los proveedores -CREATE TABLE Proveedores ( - ID_PROVEEDOR INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_PROV VARCHAR(100) NOT NULL, - TELEFONO_PROV VARCHAR(20) NOT NULL, - ACTIVO_PROV BOOLEAN DEFAULT TRUE, - EMAIL_PROV VARCHAR(100) NOT NULL, - DIRECCION_PROV VARCHAR(200) -); - --- Tabla: Pedidos_Proveedores - Almacena pedidos realizados a proveedores -CREATE TABLE Pedidos_Proveedores ( - ID_PEDIDO_PROV INT PRIMARY KEY AUTO_INCREMENT, - ID_PROVEEDOR INT NOT NULL, - NUMERO_PEDIDO INT NOT NULL, - FECHA_PEDIDO DATE NOT NULL, - ESTADO_PEDIDO VARCHAR(50) DEFAULT 'Pendiente', - CONSTRAINT FK_PEDIDO_PROVEEDOR - FOREIGN KEY (ID_PROVEEDOR) REFERENCES Proveedores(ID_PROVEEDOR) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- Tabla: Categoria_Productos - Almacena categorías de productos -CREATE TABLE Categoria_Productos ( - ID_CATEGORIA_PRODUCTO INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_CATEGORIAPRODUCTO VARCHAR(100) NOT NULL -); - --- Tabla: Estado_Pedidos - Almacena estados de pedidos -CREATE TABLE Estado_Pedidos ( - ID_ESTADO_PEDIDO INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_ESTADO VARCHAR(50) -); - --- Tabla: Categoria_Ingredientes - Almacena categorías de ingredientes -CREATE TABLE Categoria_Ingredientes ( - ID_CATEGORIA INT PRIMARY KEY AUTO_INCREMENT, - NOMBRE_CATEGORIA_INGREDIENTE VARCHAR(100) NOT NULL -); - --- Tabla: Ingredientes - Almacena ingredientes utilizados en productos -CREATE TABLE Ingredientes ( - ID_INGREDIENTE INT PRIMARY KEY AUTO_INCREMENT, - ID_PROVEEDOR INT, - ID_CATEGORIA INT, - NOMBRE_INGREDIENTE VARCHAR(100) NOT NULL, - CANTIDAD_INGREDIENTE INT NOT NULL, - FECHA_VENCIMIENTO DATE NOT NULL, - REFERENCIA_INGREDIENTE VARCHAR(100) NOT NULL, - FECHA_ENTREGA_INGREDIENTE DATE NOT NULL, - CONSTRAINT FK_PROVEEDOR_INGREDIENTE - FOREIGN KEY (ID_PROVEEDOR) REFERENCES Proveedores(ID_PROVEEDOR) ON UPDATE CASCADE ON DELETE RESTRICT, - CONSTRAINT FK_CATEGORIA_INGREDIENTE - FOREIGN KEY (ID_CATEGORIA) REFERENCES Categoria_Ingredientes(ID_CATEGORIA) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- Tabla: Productos - Almacena productos de la panadería -CREATE TABLE Productos ( - ID_PRODUCTO INT PRIMARY KEY AUTO_INCREMENT, - ID_ADMIN INT, - ID_CATEGORIA_PRODUCTO INT, - NOMBRE_PRODUCTO VARCHAR(100) NOT NULL, - DESCRIPCION_PRODUCTO TEXT, - PRODUCTO_STOCK_MIN INT NOT NULL, - PRECIO_PRODUCTO DECIMAL(10,2) NOT NULL, - FECHA_VENCIMIENTO_PRODUCTO DATE NOT NULL, - FECHA_INGRESO_PRODUCTO DATE NOT NULL, - TIPO_PRODUCTO_MARCA VARCHAR(100) NOT NULL, - ACTIVO BOOLEAN DEFAULT TRUE, - FECHA_ULTIMA_MODIFICACION TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - CONSTRAINT FK_CATEGORIA_PRODUCTO - FOREIGN KEY (ID_CATEGORIA_PRODUCTO) REFERENCES Categoria_Productos(ID_CATEGORIA_PRODUCTO) ON UPDATE CASCADE ON DELETE RESTRICT, - CONSTRAINT FK_ADMIN_PRODUCTO - FOREIGN KEY (ID_ADMIN) REFERENCES Administradores(ID_ADMIN) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- Tabla: Pedidos - Almacena pedidos realizados por clientes -CREATE TABLE Pedidos ( - ID_PEDIDO INT PRIMARY KEY AUTO_INCREMENT, - ID_CLIENTE INT, - ID_EMPLEADO INT, - ID_ESTADO_PEDIDO INT, - FECHA_INGRESO DATETIME NOT NULL, - FECHA_ENTREGA DATETIME NOT NULL, - TOTAL_PRODUCTO DECIMAL(10,2) NOT NULL, - CONSTRAINT FK_CLIENTE_PEDIDO - FOREIGN KEY (ID_CLIENTE) REFERENCES Clientes(ID_CLIENTE) ON UPDATE CASCADE ON DELETE RESTRICT, - CONSTRAINT FK_EMPLEADO_PEDIDO - FOREIGN KEY (ID_EMPLEADO) REFERENCES Empleados(ID_EMPLEADO) ON UPDATE CASCADE ON DELETE RESTRICT, - CONSTRAINT FK_ESTADO_PEDIDO_PEDIDO - FOREIGN KEY (ID_ESTADO_PEDIDO) REFERENCES Estado_Pedidos(ID_ESTADO_PEDIDO) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- Tabla: Detalle_Pedidos - Almacena detalles de productos por pedido -CREATE TABLE Detalle_Pedidos ( - ID_DETALLE INT PRIMARY KEY AUTO_INCREMENT, - ID_PEDIDO INT NOT NULL, - ID_PRODUCTO INT NOT NULL, - CANTIDAD_PRODUCTO INT NOT NULL, - PRECIO_UNITARIO DECIMAL(10,2) NOT NULL, - SUBTOTAL DECIMAL(10,2) NOT NULL, - CONSTRAINT FK_DETALLE_PEDIDO - FOREIGN KEY (ID_PEDIDO) REFERENCES Pedidos(ID_PEDIDO) ON UPDATE CASCADE ON DELETE CASCADE, - CONSTRAINT FK_DETALLE_PRODUCTO - FOREIGN KEY (ID_PRODUCTO) REFERENCES Productos(ID_PRODUCTO) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- Tabla: Ordenes_Salida - Almacena facturas de pedidos -CREATE TABLE Ordenes_Salida ( - ID_FACTURA INT PRIMARY KEY AUTO_INCREMENT, - ID_CLIENTE INT, - ID_PEDIDO INT, - FECHA_FACTURACION DATETIME NOT NULL, - TOTAL_FACTURA DECIMAL(10,2) NOT NULL, - CONSTRAINT FK_ORDENSALIDA_CLIENTE - FOREIGN KEY (ID_CLIENTE) REFERENCES Clientes(ID_CLIENTE) ON UPDATE CASCADE ON DELETE RESTRICT, - CONSTRAINT FK_ORDENSALIDA_PEDIDO - FOREIGN KEY (ID_PEDIDO) REFERENCES Pedidos(ID_PEDIDO) ON UPDATE CASCADE ON DELETE RESTRICT -); - --- ================================================================== --- TABLA DE LOGS PARA CAMBIOS EN PRODUCTOS --- ================================================================== - --- Tabla para registrar cambios en productos (logs de auditoría) -CREATE TABLE productos_logs ( - id INT PRIMARY KEY AUTO_INCREMENT, - producto_id INT NOT NULL, - tipo_cambio ENUM('precio', 'stock', 'activacion', 'desactivacion') NOT NULL, - valor_anterior VARCHAR(50), - valor_nuevo VARCHAR(50), - usuario_id INT, - usuario_tipo ENUM('admin', 'empleado') DEFAULT 'admin', - fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - ip_usuario VARCHAR(45), - INDEX idx_producto_logs_fecha (fecha_cambio), - INDEX idx_producto_logs_producto (producto_id), - INDEX idx_producto_logs_tipo (tipo_cambio), - CONSTRAINT FK_PRODUCTO_LOG - FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE -); - --- Trigger para actualizar FECHA_ULTIMA_MODIFICACION automáticamente -DELIMITER // -CREATE TRIGGER tr_actualizar_fecha_producto - BEFORE UPDATE ON Productos - FOR EACH ROW -BEGIN - SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP; -END// -DELIMITER ; - --- ================================================================== --- FUNCIONES DE UTILIDAD --- ================================================================== - --- Función: GenerateSalt - Genera salt aleatorio para encriptación -DELIMITER // - -CREATE FUNCTION GenerateSalt() -RETURNS VARCHAR(32) -READS SQL DATA -DETERMINISTIC -BEGIN - RETURN SUBSTRING(MD5(CONCAT(RAND(), NOW(), CONNECTION_ID())), 1, 32); -END// - -DELIMITER ; - --- Función: HashPassword - Hashea contraseñas con salt -DELIMITER // - -CREATE FUNCTION HashPassword(password VARCHAR(255), salt VARCHAR(32)) -RETURNS VARCHAR(255) -READS SQL DATA -DETERMINISTIC -BEGIN - RETURN SHA2(CONCAT(password, salt), 256); -END// - -DELIMITER ; - --- Función: GenerarCodigoProducto - Genera códigos de producto por categoría -DELIMITER // -CREATE FUNCTION GenerarCodigoProducto(categoria_id INT, producto_id INT) -RETURNS VARCHAR(50) -READS SQL DATA -DETERMINISTIC -BEGIN - DECLARE prefijo VARCHAR(10); - - -- Obtener prefijo según categoría - SELECT CASE - WHEN categoria_id = 1 THEN 'TL' -- Tortas Tres Leches - WHEN categoria_id = 2 THEN 'TM' -- Tortas Milkyway - WHEN categoria_id = 3 THEN 'TE' -- Tortas Encargo - WHEN categoria_id = 4 THEN 'PG' -- Pan Grande - WHEN categoria_id = 5 THEN 'PP' -- Pan Pequeño - WHEN categoria_id = 6 THEN 'PS' -- Postres - WHEN categoria_id = 7 THEN 'GA' -- Galletas - WHEN categoria_id = 8 THEN 'TA' -- Tamales - WHEN categoria_id = 9 THEN 'YO' -- Yogures - WHEN categoria_id = 10 THEN 'PC' -- Pasteles Pollo - WHEN categoria_id = 11 THEN 'BE' -- Bebidas - WHEN categoria_id = 12 THEN 'PI' -- Panadería Integral - ELSE 'PR' - END INTO prefijo; - - RETURN CONCAT(prefijo, '-', LPAD(producto_id, 4, '0')); -END// -DELIMITER ; - --- Función: GenerarNumeroPedido - Genera números de pedido automáticos -DELIMITER // -CREATE FUNCTION GenerarNumeroPedido(pedido_id INT) -RETURNS VARCHAR(50) -READS SQL DATA -DETERMINISTIC -BEGIN - RETURN CONCAT('PED-', YEAR(NOW()), '-', LPAD(pedido_id, 6, '0')); -END// -DELIMITER ; - --- ================================================================== --- TRIGGERS --- ================================================================== - --- Trigger: Actualizar total del pedido cuando se inserta detalle -DELIMITER // - -CREATE TRIGGER tr_actualizar_total_pedido -AFTER INSERT ON Detalle_Pedidos -FOR EACH ROW -BEGIN - UPDATE Pedidos - SET TOTAL_PRODUCTO = ( - SELECT SUM(SUBTOTAL) - FROM Detalle_Pedidos - WHERE ID_PEDIDO = NEW.ID_PEDIDO - ) - WHERE ID_PEDIDO = NEW.ID_PEDIDO; -END// - -DELIMITER ; - --- Trigger: Actualizar total del pedido cuando se modifica detalle -DELIMITER // - -CREATE TRIGGER tr_actualizar_total_pedido_update -AFTER UPDATE ON Detalle_Pedidos -FOR EACH ROW -BEGIN - UPDATE Pedidos - SET TOTAL_PRODUCTO = ( - SELECT SUM(SUBTOTAL) - FROM Detalle_Pedidos - WHERE ID_PEDIDO = NEW.ID_PEDIDO - ) - WHERE ID_PEDIDO = NEW.ID_PEDIDO; -END// - -DELIMITER ; - --- ================================================================== --- PROCEDIMIENTOS ALMACENADOS --- ================================================================== - --- Procedimiento: sp_productos_por_categoria - Busca productos por categoría -DELIMITER // - -CREATE PROCEDURE sp_productos_por_categoria( - IN nombre_categoria VARCHAR(100) -) -BEGIN - -- Buscar productos por nombre de categoría - SELECT - p.ID_PRODUCTO, - p.NOMBRE_PRODUCTO, - p.PRECIO_PRODUCTO, - p.PRODUCTO_STOCK_MIN, - p.TIPO_PRODUCTO_MARCA, - cp.NOMBRE_CATEGORIAPRODUCTO as CATEGORIA - FROM Productos p - INNER JOIN Categoria_Productos cp ON p.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO - WHERE cp.NOMBRE_CATEGORIAPRODUCTO LIKE CONCAT('%', nombre_categoria, '%') - ORDER BY p.NOMBRE_PRODUCTO; - - -- Mostrar el total de productos encontrados - SELECT COUNT(*) as TOTAL_PRODUCTOS_ENCONTRADOS - FROM Productos p - INNER JOIN Categoria_Productos cp ON p.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO - WHERE cp.NOMBRE_CATEGORIAPRODUCTO LIKE CONCAT('%', nombre_categoria, '%'); -END// - -DELIMITER ; - --- Procedimiento: sp_crear_pedido - Crear un nuevo pedido -DELIMITER // - -CREATE PROCEDURE sp_crear_pedido( - IN p_id_cliente INT, - IN p_id_empleado INT, - IN p_fecha_entrega DATETIME -) -BEGIN - DECLARE nuevo_id_pedido INT; - - -- Insertar el pedido - INSERT INTO Pedidos (ID_CLIENTE, ID_EMPLEADO, ID_ESTADO_PEDIDO, FECHA_INGRESO, FECHA_ENTREGA, TOTAL_PRODUCTO) - VALUES (p_id_cliente, p_id_empleado, 1, NOW(), p_fecha_entrega, 0.00); - - -- Obtener el ID del pedido recién creado - SET nuevo_id_pedido = LAST_INSERT_ID(); - - -- Devolver el ID del nuevo pedido - SELECT nuevo_id_pedido as NUEVO_ID_PEDIDO; -END// - -DELIMITER ; - --- ================================================================== --- DML (DATA MANIPULATION LANGUAGE) - INSERCIÓN DE DATOS --- ================================================================== - --- ================================================================== --- INSERCIÓN DE DATOS BASE --- ================================================================== - --- Inserción en tabla: Clientes -INSERT INTO Clientes (NOMBRE_CLI, TELEFONO_CLI, EMAIL_CLI) VALUES -('Ana Pérez', '3101234567', 'ana.p@mail.com'), -('Luis Gómez', '3209876543', 'luis.g@mail.com'), -('Maria Rodriguez', '3001122334', 'maria.r@mail.com'); - --- Inserción en tabla: Empleados -INSERT INTO Empleados (NOMBRE_EMPLEADO) VALUES -('Andres Alkaeda'), -('Damian Avila'), -('Brayan Jimenez'), -('Ana Goyeneche'), -('Sharyt Zamora'); - --- Inserción en tabla: Administradores -INSERT INTO Administradores (NOMBRE_ADMIN, TELEFONO_ADMIN, EMAIL_ADMIN) VALUES -('Admin Uno', '3005550101', 'admin1@store.com'); - --- Inserción en tabla: Proveedores -INSERT INTO `proveedores` (`ID_PROVEEDOR`, `NOMBRE_PROV`) VALUES -('1', 'Harina Dorada'), -('2', 'Dulce Granero'), -('3', 'El Horno Mágico S.A.S.'), -('4', 'Masa Maestra Distribuciones'), -('5', 'Insumos Panaderos del Sol'), -('6', 'La Esencia del Pan'), -('7', 'Proveedora Integral del Panadero'), -('8', 'Alimentos para Hornear Cía. Ltda.'); - --- Inserción en tabla: Pedidos_Proveedores -INSERT INTO Pedidos_Proveedores (ID_PROVEEDOR, NUMERO_PEDIDO, FECHA_PEDIDO, ESTADO_PEDIDO) VALUES -(1, 1001, '2024-01-15', 'Entregado'), -(2, 1002, '2024-02-10', 'Entregado'), -(3, 1003, '2024-03-05', 'Entregado'); - --- Inserción en tabla: Categoria_Productos -INSERT INTO Categoria_Productos (NOMBRE_CATEGORIAPRODUCTO) VALUES -('Tortas Tres Leches'), -('Tortas Milyway'), -('Tortas por Encargo'), -('Pan Grande'), -('Pan Pequeño'), -('Postres'), -('Galletas'), -('Tamales'), -('Yogures'), -('Pasteles Pollo'); - --- Inserción en tabla: Estado_Pedidos -INSERT INTO Estado_Pedidos (NOMBRE_ESTADO) VALUES -('Pendiente'), -('En Preparación'), -('Listo para Entrega'), -('Entregado'), -('Cancelado'); - --- Inserción en tabla: Categoria_Ingredientes -INSERT INTO `categoria_ingredientes` (`ID_CATEGORIA`, `NOMBRE_CATEGORIA_INGREDIENTE`) VALUES -('1', 'Harinas'), -('2', 'Lácteos y Derivados'), -('3', 'Azúcares y Endulzantes'), -('4', 'Grasas'), -('5', 'Esencias'), -('6', 'Fruta'), -('7', 'Frutos Secos'), -('8', 'Levaduras'), -('9', 'Huevos'), -('10', 'Chocolate y Cacao'), -('11', 'Espesantes y Gelificantes'), -('12', 'Colorantes Alimentarios'), -('13', 'Sal'), -('14', 'Aditivos y Mejoradores'), -('15', 'Semillas'), -('16', 'Coberturas y Rellenos'); - --- Inserción en tabla: Ingredientes -INSERT INTO `ingredientes` (`ID_INGREDIENTE`, `ID_PROVEEDOR`, `ID_CATEGORIA`, `NOMBRE_INGREDIENTE`, `CANTIDAD_INGREDIENTE`, `FECHA_VENCIMIENTO`, `REFERENCIA_INGREDIENTE`) VALUES -('1', '2', '1', 'Harina de Trigo', '100', '2025-12-20', 'HAR-TRG-05'), -('2', '1', '2', 'Leche Entera UHT', '30', '2025-08-01', 'LECH-ENT-1L'), -('3', '3', '3', 'Azúcar Blanca', '70', '2026-01-30', 'AZUC-BLN-KG'), -('4', '4', '4', 'Mantequilla sin Sal', '25', '2025-09-15', 'MANT-SS-KG'), -('5', '5', '9', 'Huevos Grandes', '120', '2025-07-25', 'HUEV-GR-DZ'), -('6', '6', '10', 'Chocolate Semi-Amargo (Gotas)', '15', '2026-03-10', 'CHOC-SM-KG'), -('7', '7', '8', 'Levadura Fresca', '5', '2025-07-10', 'LEV-FRES-GR'), -('8', '1', '3', 'Azúcar Moreno', '10', '2026-02-20', 'AZUC-MRN-KG'), -('9', '2', '1', 'Harina Integral', '50', '2025-11-01', 'HAR-INT-02'), -('10', '3', '4', 'Aceite Vegetal', '20', '2026-05-01', 'ACET-VEG-LT'), -('11', '4', '10', 'Cacao en Polvo', '8', '2026-04-15', 'CACAO-POL-KG'), -('12', '5', '6', 'Manzanas Verdes (Kg)', '10', '2025-07-12', 'MANZ-VRD-KG'), -('13', '6', '7', 'Nueces Picadas', '5', '2025-10-01', 'NUEZ-PIC-KG'), -('14', '7', '5', 'Esencia de Vainilla', '2', '2027-01-01', 'ESEN-VN-LT'), -('15', '8', '13', 'Sal Fina', '2', '2028-01-01', 'SAL-FIN-KG'), -('16', '1', '2', 'Crema de Leche', '5', '2025-08-05', 'CREM-LECH-LT'), -('17', '2', '11', 'Gelatina sin Sabor', '1', '2026-09-01', 'GEL-SS-KG'), -('18', '3', '12', 'Colorante Alimentario Rojo', '0.5', '2027-03-01', 'COLR-ROJ-ML'), -('19', '4', '15', 'Semillas de Sésamo', '3', '2026-06-01', 'SEM-SES-KG'), -('20', '5', '16', 'Dulce de Leche', '10', '2025-11-15', 'DDL-KG'); - --- Inserción en tabla: Productos -INSERT INTO `productos` (`ID_PRODUCTO`, `ID_ADMIN`, `ID_CATEGORIA_PRODUCTO`, `NOMBRE_PRODUCTO`, `DESCRIPCION_PRODUCTO`, `PRODUCTO_STOCK_MIN`, `PRECIO_PRODUCTO`, `FECHA_VENCIMIENTO_PRODUCTO`, `FECHA_INGRESO_PRODUCTO`, `TIPO_PRODUCTO_MARCA`) VALUES -('1', '1', '8', 'Tamales Tolimenses', 'Tradicionales tamales envueltos en hoja de plátano, con masa de maíz y relleno de carne de cerdo y pollo', '10', '3800.00', '2025-09-15', '2025-07-01', 'Propio'), -('2', '1', '4', 'Pan Tajado Integral', 'Pan de molde integral, ideal para desayunos saludables, rico en fibra', '15', '4200.00', '2025-07-02', '2025-07-01', 'Propio'), -('3', '1', '7', 'Yogurt Fresa Litro', 'Yogurt cremoso con trozos de fresa natural, sin conservantes artificiales', '12', '6000.00', '2025-07-30', '2025-07-03', 'Alpina'), -('4', '1', '5', 'Galleta de Tres Ojos', 'Galleta tradicional colombiana con tres círculos de dulce, crujiente y deliciosa', '20', '2500.00', '2025-11-01', '2025-07-01', 'Propio'), -('5', '1', '1', 'Pan Campesino Grande', 'Pan artesanal de corteza dorada y miga suave, ideal para acompañar comidas', '8', '5500.00', '2025-07-08', '2025-07-04', 'Propio'), -('6', '1', '3', 'Torta de Chocolate Pequeña', 'Deliciosa torta de chocolate húmeda con cobertura de chocolate, perfecta para ocasiones especiales', '5', '18000.00', '2025-07-07', '2025-07-04', 'Propio'), -('7', '1', '2', 'Croissant de Almendras', NULL, '18', '3500.00', '2025-07-06', '2025-07-05', 'Propio'), -('8', '1', '1', 'Baguette Clásica', 'Pan francés tradicional con corteza crujiente y miga aireada', '25', '2800.00', '2025-07-06', '2025-07-05', 'Propio'), -('9', '1', '5', 'Bizcochos de Achira', NULL, '15', '4000.00', '2025-12-01', '2025-07-01', 'Propio'), -('10', '1', '6', 'Jugo de Naranja Natural (500ml)', 'Jugo 100% natural exprimido de naranjas frescas, sin azúcar añadido', '10', '4500.00', '2025-07-05', '2025-07-04', 'Postobón'), -('11', '1', '7', 'Postre de Tres Leches', 'Clásico postre colombiano empapado en tres tipos de leche, suave y cremoso', '7', '7500.00', '2025-07-08', '2025-07-04', 'Propio'), -('12', '1', '4', 'Pan Blanco de Molde', NULL, '20', '3900.00', '2025-07-02', '2025-07-01', 'Propio'), -('13', '1', '3', 'Muffin de Arándanos', 'Muffin esponjoso con arándanos frescos, perfecto para el desayuno o merienda', '15', '3000.00', '2025-07-07', '2025-07-04', 'Propio'), -('14', '1', '2', 'Pan de Bono Pequeño', NULL, '30', '1500.00', '2025-07-06', '2025-07-05', 'Propio'), -('15', '1', '8', 'Empanadas de Carne (unidad)', 'Empanada frita rellena de carne molida sazonada con especias tradicionales', '20', '2000.00', '2025-07-06', '2025-07-05', 'Propio'), -('16', '1', '3', 'Brazo de Reina', 'Bizcocho enrollado relleno de dulce de leche y cubierto con coco rallado', '10', '9500.00', '2025-07-09', '2025-07-04', 'Propio'), -('17', '1', '1', 'Pan Trenza Integral', NULL, '12', '4800.00', '2025-07-07', '2025-07-03', 'Propio'), -('18', '1', '5', 'Galletas Surtidas de Mantequilla', 'Variedad de galletas caseras de mantequilla con diferentes formas y sabores', '25', '3200.00', '2025-12-30', '2025-07-01', 'Propio'), -('19', '1', '7', 'Avena La Lechera (500ml)', NULL, '18', '5800.00', '2025-08-20', '2025-07-03', 'Nestlé'), -('20', '1', '9', 'Ponqué de Naranja (Porción)', 'Porción individual de ponqué de naranja con glaseado cítrico', '15', '3000.00', '2025-07-08', '2025-07-04', 'Propio'), -('21', '1', '10', 'Pan Artesanal de Masa Madre', 'Pan elaborado con masa madre natural, fermentación larga para mejor digestibilidad', '7', '8000.00', '2025-07-07', '2025-07-05', 'Propio'), -('22', '1', '3', 'Cheesecake de Frutos Rojos', 'Cheesecake cremoso con base de galleta y cobertura de frutos rojos frescos', '6', '25000.00', '2025-07-09', '2025-07-04', 'Propio'), -('23', '1', '4', 'Pan de Hamburguesa', NULL, '30', '4500.00', '2025-07-10', '2025-07-02', 'Propio'), -('24', '1', '5', 'Galletas de Avena y Pasas', 'Galletas nutritivas con avena integral y pasas, sin azúcar refinado', '22', '2700.00', '2026-01-01', '2025-07-01', 'Propio'), -('25', '1', '7', 'Kumiss Natural', NULL, '10', '4900.00', '2025-07-25', '2025-07-03', 'Alquería'), -('26', '1', '9', 'Brownie con Nuez', 'Brownie de chocolate intenso con trozos de nuez, húmedo y delicioso', '40', '1800.00', '2025-07-08', '2025-07-05', 'Propio'), -('27', '1', '1', 'Pan Blandito', NULL, '28', '2500.00', '2025-07-07', '2025-07-05', 'Propio'), -('28', '1', '3', 'Milhoja de Arequipe', 'Delicada milhoja rellena de arequipe casero y cubierta con azúcar glass', '12', '6000.00', '2025-07-08', '2025-07-04', 'Propio'), -('29', '1', '2', 'Mogolla Chicharrona', NULL, '15', '3500.00', '2025-07-06', '2025-07-05', 'Propio'), -('30', '1', '8', 'Arequipe (Tarro 500g)', 'Arequipe casero cremoso y dulce, perfecto para postres y acompañamientos', '8', '9000.00', '2026-04-10', '2025-07-01', 'Propio'); - --- Inserción en tabla: Pedidos -INSERT INTO Pedidos (ID_CLIENTE, ID_EMPLEADO, ID_ESTADO_PEDIDO, FECHA_INGRESO, FECHA_ENTREGA, TOTAL_PRODUCTO) VALUES -(1, 1, 2, '2025-06-20 09:00:00', '2025-06-20 15:00:00', 10000.00), -(2, 2, 4, '2025-06-19 10:30:00', '2025-06-19 16:30:00', 7500.00), -(3, 1, 1, '2025-06-21 08:00:00', '2025-06-21 14:00:00', 12500.00); - --- Inserción en tabla: Detalle_Pedidos -INSERT INTO Detalle_Pedidos (ID_PEDIDO, ID_PRODUCTO, CANTIDAD_PRODUCTO, PRECIO_UNITARIO, SUBTOTAL) VALUES -(1, 1, 2, 3500.00, 7000.00), -(1, 3, 1, 6000.00, 6000.00), -(2, 2, 1, 4200.00, 4200.00), -(2, 4, 3, 2500.00, 7500.00), -(3, 1, 3, 3500.00, 10500.00), -(3, 4, 2, 2500.00, 5000.00); - --- Inserción en tabla: Ordenes_Salida -INSERT INTO Ordenes_Salida (ID_CLIENTE, ID_PEDIDO, FECHA_FACTURACION, TOTAL_FACTURA) VALUES -(1, 1, '2025-06-20 15:30:00', 13000.00), -(2, 2, '2025-06-19 17:00:00', 11700.00), -(3, 3, '2025-06-21 14:30:00', 15500.00); - --- ================================================================== --- DSL (DATA SECURITY LANGUAGE) - SEGURIDAD Y ENCRIPTACIÓN --- ================================================================== - --- ================================================================== --- CONFIGURACIÓN DE SEGURIDAD - CONTRASEÑAS --- ================================================================== - --- Actualizar contraseñas de administradores con encriptación -UPDATE Administradores -SET SALT_ADMIN = GenerateSalt() -WHERE ID_ADMIN = 1; - -UPDATE Administradores -SET CONTRASEÑA_ADMIN = HashPassword('admin123', SALT_ADMIN) -WHERE ID_ADMIN = 1; - --- Actualizar contraseñas de clientes con encriptación -UPDATE Clientes -SET SALT_CLI = GenerateSalt() -WHERE ID_CLIENTE IN (1, 2, 3); - -UPDATE Clientes -SET CONTRASEÑA_CLI = HashPassword('cliente123', SALT_CLI) -WHERE ID_CLIENTE = 1; - -UPDATE Clientes -SET CONTRASEÑA_CLI = HashPassword('cliente456', SALT_CLI) -WHERE ID_CLIENTE = 2; - -UPDATE Clientes -SET CONTRASEÑA_CLI = HashPassword('cliente789', SALT_CLI) -WHERE ID_CLIENTE = 3; - --- Actualizar contraseñas de empleados con encriptación -UPDATE Empleados -SET SALT_EMPLEADO = GenerateSalt() -WHERE ID_EMPLEADO IN (1, 2, 3, 4, 5); - -UPDATE Empleados -SET CONTRASEÑA_EMPLEADO = HashPassword('empleado123', SALT_EMPLEADO) -WHERE ID_EMPLEADO = 1; - -UPDATE Empleados -SET CONTRASEÑA_EMPLEADO = HashPassword('empleado456', SALT_EMPLEADO) -WHERE ID_EMPLEADO = 2; - --- ================================================================== --- DQL (DATA QUERY LANGUAGE) - CONSULTAS Y VERIFICACIONES --- ================================================================== - --- ================================================================== --- CONSULTAS DE VERIFICACIÓN --- ================================================================== - --- Verificación de registros en todas las tablas -SELECT 'CLIENTES' as Tabla, COUNT(*) as Total_Registros FROM Clientes -UNION ALL -SELECT 'EMPLEADOS', COUNT(*) FROM Empleados -UNION ALL -SELECT 'ADMINISTRADORES', COUNT(*) FROM Administradores -UNION ALL -SELECT 'PROVEEDORES', COUNT(*) FROM Proveedores -UNION ALL -SELECT 'PEDIDOS_PROVEEDORES', COUNT(*) FROM Pedidos_Proveedores -UNION ALL -SELECT 'CATEGORIA_PRODUCTOS', COUNT(*) FROM Categoria_Productos -UNION ALL -SELECT 'ESTADO_PEDIDOS', COUNT(*) FROM Estado_Pedidos -UNION ALL -SELECT 'CATEGORIA_INGREDIENTES', COUNT(*) FROM Categoria_Ingredientes -UNION ALL -SELECT 'INGREDIENTES', COUNT(*) FROM Ingredientes -UNION ALL -SELECT 'PRODUCTOS', COUNT(*) FROM Productos -UNION ALL -SELECT 'PEDIDOS', COUNT(*) FROM Pedidos -UNION ALL -SELECT 'DETALLE_PEDIDOS', COUNT(*) FROM Detalle_Pedidos -UNION ALL -SELECT 'ORDENES_SALIDA', COUNT(*) FROM Ordenes_Salida; - --- Consulta detallada de productos con información completa -SELECT - p.ID_PRODUCTO, - p.NOMBRE_PRODUCTO, - cp.NOMBRE_CATEGORIAPRODUCTO as CATEGORIA, - p.PRECIO_PRODUCTO, - p.PRODUCTO_STOCK_MIN, - p.TIPO_PRODUCTO_MARCA, - a.NOMBRE_ADMIN as ADMINISTRADOR, - p.FECHA_ULTIMA_MODIFICACION -FROM Productos p -INNER JOIN Categoria_Productos cp ON p.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO -INNER JOIN Administradores a ON p.ID_ADMIN = a.ID_ADMIN -ORDER BY p.NOMBRE_PRODUCTO; - --- Consulta detallada de pedidos con información completa -SELECT - ped.ID_PEDIDO, - c.NOMBRE_CLI as CLIENTE, - e.NOMBRE_EMPLEADO as EMPLEADO, - ep.NOMBRE_ESTADO as ESTADO, - ped.FECHA_INGRESO, - ped.FECHA_ENTREGA, - p.NOMBRE_PRODUCTO, - dp.CANTIDAD_PRODUCTO, - dp.PRECIO_UNITARIO, - dp.SUBTOTAL -FROM Pedidos ped -INNER JOIN Clientes c ON ped.ID_CLIENTE = c.ID_CLIENTE -INNER JOIN Empleados e ON ped.ID_EMPLEADO = e.ID_EMPLEADO -INNER JOIN Estado_Pedidos ep ON ped.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO -INNER JOIN Detalle_Pedidos dp ON ped.ID_PEDIDO = dp.ID_PEDIDO -INNER JOIN Productos p ON dp.ID_PRODUCTO = p.ID_PRODUCTO -ORDER BY ped.ID_PEDIDO, dp.ID_DETALLE; - --- ================================================================== --- CONSULTAS DE VERIFICACIÓN DE SEGURIDAD --- ================================================================== - --- Verificación del hasheo de contraseñas de administradores -SELECT - ID_ADMIN, - NOMBRE_ADMIN, - SALT_ADMIN, - CONTRASEÑA_ADMIN, - LENGTH(CONTRASEÑA_ADMIN) as LONGITUD_HASH -FROM Administradores; - --- Verificación del hasheo de contraseñas de clientes - -SELECT - ID_CLIENTE, - NOMBRE_CLI, - SALT_CLI, - CONTRASEÑA_CLI, - LENGTH(CONTRASEÑA_CLI) as LONGITUD_HASH -FROM Clientes; - --- Verificación del hasheo de contraseñas de empleados - -SELECT - ID_EMPLEADO, - NOMBRE_EMPLEADO, - SALT_EMPLEADO, - CONTRASEÑA_EMPLEADO, - LENGTH(CONTRASEÑA_EMPLEADO) as LONGITUD_HASH -FROM Empleados; - --- Consulta consolidada de todas las contraseñas hasheadas - -SELECT 'ADMIN' as TIPO, NOMBRE_ADMIN as NOMBRE, SALT_ADMIN as SALT, CONTRASEÑA_ADMIN as HASH -FROM Administradores -WHERE CONTRASEÑA_ADMIN IS NOT NULL - -UNION ALL - -SELECT 'CLIENTE' as TIPO, NOMBRE_CLI as NOMBRE, SALT_CLI as SALT, CONTRASEÑA_CLI as HASH -FROM Clientes -WHERE CONTRASEÑA_CLI IS NOT NULL - -UNION ALL - -SELECT 'EMPLEADO' as TIPO, NOMBRE_EMPLEADO as NOMBRE, SALT_EMPLEADO as SALT, CONTRASEÑA_EMPLEADO as HASH -FROM Empleados -WHERE CONTRASEÑA_EMPLEADO IS NOT NULL; - - --- ================================================================== --- PRUEBAS Y VALIDACIONES --- ================================================================== - --- Prueba de trigger de actualización de fecha de modificación -UPDATE Productos -SET PRECIO_PRODUCTO = 3800.00 -WHERE NOMBRE_PRODUCTO = 'Tamales Tolimenses'; - --- Verificación de la actualización de fecha de modificación -SELECT - NOMBRE_PRODUCTO, - PRECIO_PRODUCTO, - FECHA_ULTIMA_MODIFICACION -FROM Productos -WHERE NOMBRE_PRODUCTO = 'Tamales Tolimenses'; - --- Pruebas de procedimientos almacenados -CALL sp_productos_por_categoria('Pan'); -CALL sp_productos_por_categoria('Torta'); -CALL sp_productos_por_categoria('Yogur'); - --- Prueba de creación de nuevo pedido -CALL sp_crear_pedido(1, 2, '2025-06-25 16:00:00'); - --- ================================================================== --- VERIFICACIONES FINALES DEL SISTEMA --- ================================================================== - --- Verificar triggers creados -SHOW TRIGGERS WHERE `Table` IN ('Productos', 'Detalle_Pedidos'); - --- Verificar procedimientos almacenados creados -SHOW PROCEDURE STATUS WHERE Name LIKE 'sp_%'; - --- Verificar funciones creadas -SHOW FUNCTION STATUS WHERE Name LIKE '%Password%' OR Name LIKE '%Salt%'; - --- Verificar estructura de las tablas principales -DESCRIBE Productos; -DESCRIBE Pedidos; -DESCRIBE Detalle_Pedidos; - --- Script para actualizar estados de pedidos --- Ejecutar solo si es necesario ajustar los estados - --- Verificar estados existentes -SELECT * FROM Estado_Pedidos; - --- Si necesitas ajustar los estados, puedes usar estas consultas: --- UPDATE Estado_Pedidos SET NOMBRE_ESTADO = 'Pendiente' WHERE ID_ESTADO_PEDIDO = 1; --- UPDATE Estado_Pedidos SET NOMBRE_ESTADO = 'En Preparación' WHERE ID_ESTADO_PEDIDO = 2; --- UPDATE Estado_Pedidos SET NOMBRE_ESTADO = 'Listo' WHERE ID_ESTADO_PEDIDO = 3; --- UPDATE Estado_Pedidos SET NOMBRE_ESTADO = 'Entregado' WHERE ID_ESTADO_PEDIDO = 4; --- UPDATE Estado_Pedidos SET NOMBRE_ESTADO = 'Cancelado' WHERE ID_ESTADO_PEDIDO = 5; - --- O insertar si no existen: --- INSERT INTO Estado_Pedidos (NOMBRE_ESTADO) VALUES --- ('Pendiente'), --- ('En Preparación'), --- ('Listo'), --- ('Entregado'), --- ('Cancelado'); - --- ================================================================== --- MIGRACIONES Y ACTUALIZACIONES DEL SISTEMA --- ================================================================== - --- ================================================================== --- MIGRACIÓN: ACTUALIZAR TIPO DE DATO PRECIO_PRODUCTO --- ================================================================== --- NOTA: Solo ejecutar si la base de datos ya existe y necesita actualización --- Descomentar las siguientes líneas para migrar una base de datos existente: - -<> --- Actualizar tipo de dato de PRECIO_PRODUCTO de INT a DECIMAL -ALTER TABLE Productos MODIFY COLUMN PRECIO_PRODUCTO DECIMAL(10,2) NOT NULL; - --- Verificar la estructura actualizada -DESCRIBE Productos; -<> - --- ================================================================== --- VERIFICACIÓN Y CREACIÓN DE TABLA DE LOGS --- ================================================================== --- Script para verificar y crear tabla productos_logs si no existe - --- Verificar si la tabla productos_logs existe -SET @table_exists = ( - SELECT COUNT(*) - FROM information_schema.tables - WHERE table_schema = DATABASE() - AND table_name = 'productos_logs' -); - --- Crear tabla productos_logs si no existe (para bases de datos existentes) -SET @sql = IF(@table_exists = 0, - 'CREATE TABLE productos_logs ( - id INT PRIMARY KEY AUTO_INCREMENT, - producto_id INT NOT NULL, - tipo_cambio ENUM(''precio'', ''stock'', ''activacion'', ''desactivacion'') NOT NULL, - valor_anterior VARCHAR(50), - valor_nuevo VARCHAR(50), - usuario_id INT, - usuario_tipo ENUM(''admin'', ''empleado'') DEFAULT ''admin'', - fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - ip_usuario VARCHAR(45), - INDEX idx_producto_logs_fecha (fecha_cambio), - INDEX idx_producto_logs_producto (producto_id), - INDEX idx_producto_logs_tipo (tipo_cambio), - CONSTRAINT FK_PRODUCTO_LOG - FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE - )', - 'SELECT ''Tabla productos_logs ya existe'' as mensaje' -); - -PREPARE stmt FROM @sql; -EXECUTE stmt; -DEALLOCATE PREPARE stmt; - --- ================================================================== --- VERIFICACIÓN Y CREACIÓN DE TRIGGER --- ================================================================== --- Script para verificar y crear trigger si no existe - --- Verificar si el trigger existe -SET @trigger_exists = ( - SELECT COUNT(*) - FROM information_schema.triggers - WHERE trigger_schema = DATABASE() - AND trigger_name = 'tr_actualizar_fecha_producto' -); - --- Crear trigger si no existe -SET @sql_trigger = IF(@trigger_exists = 0, - 'CREATE TRIGGER tr_actualizar_fecha_producto - BEFORE UPDATE ON Productos - FOR EACH ROW - BEGIN - SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP; - END', - 'SELECT ''Trigger tr_actualizar_fecha_producto ya existe'' as mensaje' -); - -PREPARE stmt_trigger FROM @sql_trigger; -EXECUTE stmt_trigger; -DEALLOCATE PREPARE stmt_trigger; - --- ================================================================== --- CONSULTAS DE MANTENIMIENTO Y VERIFICACIÓN --- ================================================================== - --- Verificar estructura de tabla Productos -SELECT - COLUMN_NAME as 'Campo', - COLUMN_TYPE as 'Tipo', - IS_NULLABLE as 'Nulo', - COLUMN_DEFAULT as 'Por_Defecto', - EXTRA as 'Extra' -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'Productos' -ORDER BY ORDINAL_POSITION; - --- Verificar existencia de tabla productos_logs -SELECT - TABLE_NAME as 'Tabla', - TABLE_ROWS as 'Filas', - CREATE_TIME as 'Fecha_Creacion' -FROM information_schema.TABLES -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME IN ('Productos', 'productos_logs'); - --- Verificar triggers relacionados con Productos -SELECT - TRIGGER_NAME as 'Trigger', - EVENT_MANIPULATION as 'Evento', - EVENT_OBJECT_TABLE as 'Tabla', - TRIGGER_BODY as 'Accion' -FROM information_schema.TRIGGERS -WHERE TRIGGER_SCHEMA = DATABASE() -AND EVENT_OBJECT_TABLE = 'Productos'; - --- Verificar índices de la tabla productos_logs -SELECT - INDEX_NAME as 'Indice', - COLUMN_NAME as 'Columna', - NON_UNIQUE as 'No_Unico' -FROM information_schema.STATISTICS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'productos_logs' -ORDER BY INDEX_NAME, SEQ_IN_INDEX; - --- ================================================================== --- CONSULTAS DE PRUEBA PARA LOGS --- ================================================================== - --- Consulta para ver logs recientes (ejecutar después de hacer cambios) --- SELECT * FROM productos_logs ORDER BY fecha_cambio DESC LIMIT 10; - --- Consulta para ver cambios de un producto específico --- SELECT --- pl.*, --- p.NOMBRE_PRODUCTO --- FROM productos_logs pl --- JOIN Productos p ON pl.producto_id = p.ID_PRODUCTO --- WHERE pl.producto_id = 1 --- ORDER BY pl.fecha_cambio DESC; - --- Consulta para ver estadísticas de cambios --- SELECT --- tipo_cambio, --- COUNT(*) as total_cambios, --- DATE(fecha_cambio) as fecha --- FROM productos_logs --- GROUP BY tipo_cambio, DATE(fecha_cambio) --- ORDER BY fecha DESC, tipo_cambio; - --- ================================================================== --- SCRIPT DE LIMPIEZA (OPCIONAL) --- ================================================================== - --- Limpiar logs antiguos (ejecutar solo si es necesario) --- DELETE FROM productos_logs WHERE fecha_cambio < DATE_SUB(NOW(), INTERVAL 90 DAY); - --- Resetear AUTO_INCREMENT de la tabla logs --- ALTER TABLE productos_logs AUTO_INCREMENT = 1; - --- ============================================================ --- MIGRACIÓN: Agregar columna FECHA_REGISTRO a tabla Empleados --- ============================================================ - --- Verificar y agregar columna FECHA_REGISTRO a la tabla Empleados si no existe -SET @sql = (SELECT IF( - (SELECT COUNT(*) FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'Empleados' - AND COLUMN_NAME = 'FECHA_REGISTRO') = 0, - 'ALTER TABLE Empleados ADD COLUMN FECHA_REGISTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP', - 'SELECT "La columna FECHA_REGISTRO ya existe en la tabla Empleados" as mensaje' -)); - -PREPARE stmt FROM @sql; -EXECUTE stmt; -DEALLOCATE PREPARE stmt; - --- ============================================================ --- MIGRACIÓN: Agregar columna DESCRIPCION_PRODUCTO a tabla Productos --- ============================================================ - --- Verificar y agregar columna DESCRIPCION_PRODUCTO a la tabla Productos si no existe -SET @sql = (SELECT IF( - (SELECT COUNT(*) FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 'Productos' - AND COLUMN_NAME = 'DESCRIPCION_PRODUCTO') = 0, - 'ALTER TABLE Productos ADD COLUMN DESCRIPCION_PRODUCTO TEXT AFTER NOMBRE_PRODUCTO', - 'SELECT "La columna DESCRIPCION_PRODUCTO ya existe en la tabla Productos" as mensaje' -)); - -PREPARE stmt FROM @sql; -EXECUTE stmt; -DEALLOCATE PREPARE stmt; - --- ================================================================== --- VERIFICACIÓN DE ESTRUCTURA FINAL --- ================================================================== - --- Verificar que todas las tablas principales existen -SELECT - TABLE_NAME as 'Tabla_Existente' -FROM information_schema.TABLES -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME IN ('Productos', 'Detalle_Pedidos', 'Pedidos', 'Empleados', 'Clientes', 'Administradores') -ORDER BY TABLE_NAME; - --- Verificar estructura de tabla Productos (debe incluir DESCRIPCION_PRODUCTO) -SELECT - COLUMN_NAME as 'Columna', - DATA_TYPE as 'Tipo', - IS_NULLABLE as 'Permite_NULL' -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'Productos' -ORDER BY ORDINAL_POSITION; - --- Verificar estructura de tabla Detalle_Pedidos (debe tener solo columnas esenciales) -SELECT - COLUMN_NAME as 'Columna', - DATA_TYPE as 'Tipo', - IS_NULLABLE as 'Permite_NULL' -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'Detalle_Pedidos' -ORDER BY ORDINAL_POSITION; - --- ================================================================== --- FIN DE ACTUALIZACIONES DEL SISTEMA --- ================================================================== - -COMMIT; diff --git a/files/README_API_SSE.md b/files/README_API_SSE.md deleted file mode 100644 index 617fdac..0000000 --- a/files/README_API_SSE.md +++ /dev/null @@ -1,205 +0,0 @@ -# Sistema de Actualización en Tiempo Real para Panadería - -## Resumen -Se ha implementado un sistema completo de API REST y Server-Sent Events (SSE) para mantener sincronizados los precios y stock entre el dashboard del administrador y el menú del cliente. - -## Archivos Creados/Modificados - -### 1. Base de Datos -- **crear_tabla_logs.sql**: Tabla para logging de cambios en productos -- **actualizar_producto_stock_precio.php**: Actualizado para incluir logging - -### 2. API REST -- **api_productos_admin.php**: API REST completa para gestión de productos - -### 3. Server-Sent Events -- **sse_menu_updates.php**: Endpoint SSE para notificaciones en tiempo real - -### 4. JavaScript del Cliente -- **js/menu-updater.js**: Cliente para recibir actualizaciones SSE en el menú -- **js/admin-products.js**: Interfaz de administración de productos - -## Pasos de Implementación - -### 1. Ejecutar Script de Base de Datos -```sql --- Ejecutar en MySQL/phpMyAdmin -source crear_tabla_logs.sql; -``` - -### 2. Incluir JavaScript en las Páginas - -#### En el Menú del Cliente (menu.php, dashboard_cliente.php) -```html - -``` - -#### En el Dashboard del Administrador (dashboard_admin.php) -```html - -``` - -### 3. Estructura HTML Requerida - -#### Para el Menú del Cliente -```html -
-

Nombre del Producto

-

$5000

-

Stock: 10

-
-``` - -#### Para el Dashboard del Admin -```html -
- -
-
- -
-``` - -## Funcionalidades Implementadas - -### API REST Endpoints - -#### GET `/api_productos_admin.php` -- Obtener todos los productos (con paginación) -- Obtener producto específico: `?id=1` -- Incluir logs: `?id=1&incluir_logs=1` -- Filtros: `?categoria=1&buscar=pan&activos_solo=1` - -#### POST `/api_productos_admin.php` -- Crear nuevo producto -```json -{ - "nombre_producto": "Pan Baguette", - "precio_producto": 2500, - "stock_min": 20, - "fecha_vencimiento": "2025-07-10", - "tipo_producto_marca": "Artesanal", - "id_categoria_producto": 1 -} -``` - -#### PATCH `/api_productos_admin.php` -- Actualizar precio: `{"id": 1, "campo": "precio", "valor": 3000}` -- Actualizar stock: `{"id": 1, "campo": "stock", "valor": 15}` -- Activar/desactivar: `{"id": 1, "campo": "activo", "valor": 1}` - -#### PUT `/api_productos_admin.php` -- Actualizar producto completo - -#### DELETE `/api_productos_admin.php` -- Soft delete: `{"id": 1}` -- Hard delete: `{"id": 1, "forzar": true}` - -### Server-Sent Events - -#### Conexión -```javascript -// Automática al cargar la página -// Manual: -const updater = new MenuUpdater({ - onMenuUpdate: function(data) { - console.log('Actualización recibida:', data); - } -}); -``` - -#### Eventos Recibidos -- `connected`: Conexión establecida -- `menu_update`: Cambios en productos detectados -- `heartbeat`: Verificación de conexión (cada 30s) -- `disconnected`: Conexión cerrada -- `error`: Error en el servidor - -## Configuración del Servidor - -### Requisitos -- PHP 7.4+ -- MySQL 5.7+ -- Extensiones: mysqli, json - -### Configuración Recomendada -```ini -; php.ini -max_execution_time = 300 -memory_limit = 256M -``` - -### Apache/Nginx -Asegurar que SSE no sea bloqueado por proxy/cache: -```apache -# .htaccess - - Header always set Cache-Control "no-cache, no-store, must-revalidate" - Header always set Pragma "no-cache" - Header always set Expires "0" - -``` - -## Seguridad - -### Validaciones Implementadas -- Verificación de sesión de administrador -- Validación de tipos de datos -- Sanitización de entradas -- Logging de cambios con IP y usuario - -### Headers de Seguridad -```php -header('Content-Type: application/json'); -header('X-Content-Type-Options: nosniff'); -header('X-Frame-Options: DENY'); -``` - -## Monitoreo y Logs - -### Tabla productos_logs -- Registra todos los cambios en productos -- Incluye IP del usuario y timestamp -- Tipos: precio, stock, activacion, desactivacion - -### Consultas Útiles -```sql --- Ver cambios recientes -SELECT * FROM productos_logs -ORDER BY fecha_cambio DESC -LIMIT 50; - --- Cambios por producto -SELECT pl.*, p.NOMBRE_PRODUCTO -FROM productos_logs pl -JOIN Productos p ON pl.producto_id = p.ID_PRODUCTO -WHERE pl.producto_id = 1; -``` - -## Resolución de Problemas - -### SSE No Funciona -1. Verificar que el navegador soporte EventSource -2. Revisar configuración de proxy/firewall -3. Comprobar logs de PHP por errores -4. Verificar permisos de archivo - -### API No Responde -1. Verificar sesión de administrador -2. Comprobar conexión a base de datos -3. Revisar logs de errores de PHP -4. Validar formato JSON de las peticiones - -### Actualizations No Se Ven -1. Verificar estructura HTML (data-producto-id) -2. Comprobar consola del navegador por errores -3. Verificar que el trigger de base de datos esté activo -4. Comprobar que FECHA_ULTIMA_MODIFICACION se actualice - -## Próximas Mejoras - -1. **Websockets**: Para comunicación bidireccional -2. **Push Notifications**: Para notificaciones móviles -3. **Cache Redis**: Para mejor rendimiento -4. **Métricas**: Dashboard de analytics de cambios -5. **Backup Automático**: Antes de cambios críticos diff --git a/files/SOLUCION_ERROR_FECHA_REGISTRO.md b/files/SOLUCION_ERROR_FECHA_REGISTRO.md deleted file mode 100644 index e69de29..0000000 diff --git a/files/actualizar_ingrediente_ajax.php b/files/actualizar_ingrediente_ajax.php deleted file mode 100644 index eac9c63..0000000 --- a/files/actualizar_ingrediente_ajax.php +++ /dev/null @@ -1,134 +0,0 @@ - false, - 'error' => 'No autorizado' - ]); - exit(); -} - -require_once 'conexion.php'; - -try { - // Verificar método de petición - if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - throw new Exception("Método no permitido"); - } - - // Verificar conexión - if (!$conexion) { - throw new Exception("No se pudo conectar a la base de datos"); - } - - // Obtener datos JSON - $input = json_decode(file_get_contents('php://input'), true); - - if (!$input) { - throw new Exception("Datos JSON inválidos"); - } - - // Validar datos requeridos - if (!isset($input['id']) || !isset($input['campo']) || !isset($input['valor'])) { - throw new Exception("Faltan datos requeridos: id, campo, valor"); - } - - $ingrediente_id = intval($input['id']); - $campo = trim($input['campo']); - $valor = trim($input['valor']); - - // Validar ID del ingrediente - if ($ingrediente_id <= 0) { - throw new Exception("ID de ingrediente inválido"); - } - - // Validar que el ingrediente existe - $stmt_check = $conexion->prepare("SELECT ID_INGREDIENTE, NOMBRE_INGREDIENTE FROM Ingredientes WHERE ID_INGREDIENTE = ?"); - $stmt_check->bind_param("i", $ingrediente_id); - $stmt_check->execute(); - $result_check = $stmt_check->get_result(); - - if ($result_check->num_rows === 0) { - throw new Exception("Ingrediente no encontrado"); - } - - $ingrediente_info = $result_check->fetch_assoc(); - - // Validar y procesar según el campo a actualizar - switch ($campo) { - case 'stock': - case 'cantidad': - $nuevo_stock = intval($valor); - if ($nuevo_stock < 0) { - throw new Exception("El stock no puede ser negativo"); - } - - $sql = "UPDATE Ingredientes SET CANTIDAD_INGREDIENTE = ? WHERE ID_INGREDIENTE = ?"; - $stmt = $conexion->prepare($sql); - $stmt->bind_param("ii", $nuevo_stock, $ingrediente_id); - - $mensaje_exito = "Stock del ingrediente '{$ingrediente_info['NOMBRE_INGREDIENTE']}' actualizado a {$nuevo_stock}"; - break; - - case 'precio': - case 'precio_compra': - $nuevo_precio = floatval($valor); - if ($nuevo_precio < 0) { - throw new Exception("El precio no puede ser negativo"); - } - - $sql = "UPDATE Ingredientes SET PRECIO_COMPRA = ? WHERE ID_INGREDIENTE = ?"; - $stmt = $conexion->prepare($sql); - $stmt->bind_param("di", $nuevo_precio, $ingrediente_id); - - $mensaje_exito = "Precio de compra del ingrediente '{$ingrediente_info['NOMBRE_INGREDIENTE']}' actualizado a $" . number_format($nuevo_precio, 2); - break; - - default: - throw new Exception("Campo no válido para actualización: {$campo}"); - } - - // Ejecutar la actualización - if (!$stmt->execute()) { - throw new Exception("Error al actualizar: " . $stmt->error); - } - - if ($stmt->affected_rows === 0) { - throw new Exception("No se realizaron cambios. Verifique que el valor sea diferente al actual."); - } - - // Registrar en logs (opcional - se puede implementar después) - // log_cambio_ingrediente($ingrediente_id, $campo, $valor_anterior, $valor, $_SESSION['usuario_id']); - - // Respuesta exitosa - echo json_encode([ - 'success' => true, - 'mensaje' => $mensaje_exito, - 'ingrediente_id' => $ingrediente_id, - 'campo_actualizado' => $campo, - 'nuevo_valor' => $valor - ]); - -} catch (Exception $e) { - error_log("Error en actualizar_ingrediente_ajax.php: " . $e->getMessage()); - - http_response_code(400); - echo json_encode([ - 'success' => false, - 'error' => $e->getMessage() - ]); -} -?> diff --git a/files/actualizar_producto_stock_precio.php b/files/actualizar_producto_stock_precio.php deleted file mode 100644 index 9b0a05b..0000000 --- a/files/actualizar_producto_stock_precio.php +++ /dev/null @@ -1,166 +0,0 @@ - false, 'message' => 'No autorizado']); - exit(); -} - -require_once 'conexion.php'; - -// Función para registrar cambios en el log -function registrarCambio($conexion, $producto_id, $tipo_cambio, $valor_anterior, $valor_nuevo, $usuario_id, $ip_usuario) { - $stmt = $conexion->prepare("INSERT INTO productos_logs (producto_id, tipo_cambio, valor_anterior, valor_nuevo, usuario_id, usuario_tipo, ip_usuario) VALUES (?, ?, ?, ?, ?, 'admin', ?)"); - $stmt->bind_param("isssss", $producto_id, $tipo_cambio, $valor_anterior, $valor_nuevo, $usuario_id, $ip_usuario); - $stmt->execute(); -} - -// Verificar que sea una petición POST -if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - header('Content-Type: application/json'); - echo json_encode(['success' => false, 'message' => 'Método no permitido']); - exit(); -} - -// Obtener los datos del POST -$producto_id = intval($_POST['producto_id'] ?? 0); -$accion = $_POST['accion'] ?? ''; -$nuevo_valor = $_POST['nuevo_valor'] ?? ''; - -// Obtener información del usuario y IP -$usuario_id = $_SESSION['usuario_id'] ?? 0; -$ip_usuario = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; - -// Validar datos -if ($producto_id <= 0 || empty($accion)) { - header('Content-Type: application/json'); - echo json_encode(['success' => false, 'message' => 'Datos incompletos']); - exit(); -} - -try { - // Verificar que el producto existe - $stmt = $conexion->prepare("SELECT ID_PRODUCTO, NOMBRE_PRODUCTO, PRECIO_PRODUCTO, PRODUCTO_STOCK_MIN FROM Productos WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("i", $producto_id); - $stmt->execute(); - $producto = $stmt->get_result()->fetch_assoc(); - - if (!$producto) { - header('Content-Type: application/json'); - echo json_encode(['success' => false, 'message' => 'Producto no encontrado']); - exit(); - } - - $response = ['success' => false, 'message' => '']; - - switch ($accion) { - case 'actualizar_precio': - $nuevo_precio = floatval($nuevo_valor); - if ($nuevo_precio <= 0) { - $response['message'] = 'El precio debe ser mayor a 0'; - break; - } - - $stmt = $conexion->prepare("UPDATE Productos SET PRECIO_PRODUCTO = ? WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("di", $nuevo_precio, $producto_id); - - if ($stmt->execute()) { - // Registrar el cambio en el log - registrarCambio($conexion, $producto_id, 'precio', $producto['PRECIO_PRODUCTO'], $nuevo_precio, $usuario_id, $ip_usuario); - - $response['success'] = true; - $response['message'] = 'Precio actualizado correctamente'; - $response['nuevo_precio'] = $nuevo_precio; - } else { - $response['message'] = 'Error al actualizar el precio'; - } - break; - - case 'actualizar_stock': - $nuevo_stock = intval($nuevo_valor); - if ($nuevo_stock < 0) { - $response['message'] = 'El stock no puede ser negativo'; - break; - } - - $stmt = $conexion->prepare("UPDATE Productos SET PRODUCTO_STOCK_MIN = ? WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("ii", $nuevo_stock, $producto_id); - - if ($stmt->execute()) { - // Registrar el cambio en el log - registrarCambio($conexion, $producto_id, 'stock', $producto['PRODUCTO_STOCK_MIN'], $nuevo_stock, $usuario_id, $ip_usuario); - - $response['success'] = true; - $response['message'] = 'Stock actualizado correctamente'; - $response['nuevo_stock'] = $nuevo_stock; - } else { - $response['message'] = 'Error al actualizar el stock'; - } - break; - - case 'incrementar_stock': - $incremento = intval($nuevo_valor); - if ($incremento <= 0) { - $response['message'] = 'El incremento debe ser mayor a 0'; - break; - } - - $nuevo_stock = $producto['PRODUCTO_STOCK_MIN'] + $incremento; - $stmt = $conexion->prepare("UPDATE Productos SET PRODUCTO_STOCK_MIN = ? WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("ii", $nuevo_stock, $producto_id); - - if ($stmt->execute()) { - // Registrar el cambio en el log - registrarCambio($conexion, $producto_id, 'stock', $producto['PRODUCTO_STOCK_MIN'], $nuevo_stock, $usuario_id, $ip_usuario); - - $response['success'] = true; - $response['message'] = "Stock incrementado en $incremento unidades"; - $response['nuevo_stock'] = $nuevo_stock; - } else { - $response['message'] = 'Error al incrementar el stock'; - } - break; - - case 'decrementar_stock': - $decremento = intval($nuevo_valor); - if ($decremento <= 0) { - $response['message'] = 'El decremento debe ser mayor a 0'; - break; - } - - $nuevo_stock = $producto['PRODUCTO_STOCK_MIN'] - $decremento; - if ($nuevo_stock < 0) { - $response['message'] = 'El stock no puede ser negativo'; - break; - } - - $stmt = $conexion->prepare("UPDATE Productos SET PRODUCTO_STOCK_MIN = ? WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("ii", $nuevo_stock, $producto_id); - - if ($stmt->execute()) { - // Registrar el cambio en el log - registrarCambio($conexion, $producto_id, 'stock', $producto['PRODUCTO_STOCK_MIN'], $nuevo_stock, $usuario_id, $ip_usuario); - - $response['success'] = true; - $response['message'] = "Stock decrementado en $decremento unidades"; - $response['nuevo_stock'] = $nuevo_stock; - } else { - $response['message'] = 'Error al decrementar el stock'; - } - break; - - default: - $response['message'] = 'Acción no válida'; - break; - } - - header('Content-Type: application/json'); - echo json_encode($response); - -} catch (Exception $e) { - header('Content-Type: application/json'); - echo json_encode(['success' => false, 'message' => 'Error del servidor: ' . $e->getMessage()]); -} -?> diff --git a/files/actualizar_tabla_empleados.php b/files/actualizar_tabla_empleados.php deleted file mode 100644 index 6d9d4b3..0000000 --- a/files/actualizar_tabla_empleados.php +++ /dev/null @@ -1,133 +0,0 @@ -🔧 Verificación y Actualización de Tabla Empleados"; - -// Verificar conexión -if ($conexion->connect_error) { - echo "

❌ Error de conexión: " . $conexion->connect_error . "

"; - exit(); -} - -echo "

✅ Conexión exitosa a la base de datos

"; - -try { - // Verificar estructura actual - $query = "DESCRIBE Empleados"; - $result = $conexion->query($query); - - $campos_existentes = []; - echo "

📋 Estructura actual de la tabla Empleados:

"; - echo ""; - echo ""; - - while ($row = $result->fetch_assoc()) { - $campos_existentes[] = $row['Field']; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - } - echo "
CampoTipoNullKeyDefaultExtra
" . $row['Field'] . "" . $row['Type'] . "" . $row['Null'] . "" . $row['Key'] . "" . $row['Default'] . "" . $row['Extra'] . "
"; - - // Verificar si existen los campos necesarios - $campos_requeridos = ['EMAIL_EMPLEADO', 'CONTRASEÑA_EMPLEADO', 'SALT_EMPLEADO']; - $campos_faltantes = []; - - foreach ($campos_requeridos as $campo) { - if (!in_array($campo, $campos_existentes)) { - $campos_faltantes[] = $campo; - } - } - - if (empty($campos_faltantes)) { - echo "

✅ Todos los campos requeridos están presentes

"; - } else { - echo "

⚠️ Campos faltantes encontrados:

"; - echo "
    "; - foreach ($campos_faltantes as $campo) { - echo "
  • $campo
  • "; - } - echo "
"; - - echo "

🔨 Agregando campos faltantes...

"; - - // Agregar campos faltantes - if (in_array('EMAIL_EMPLEADO', $campos_faltantes)) { - $alter_query = "ALTER TABLE Empleados ADD COLUMN EMAIL_EMPLEADO VARCHAR(100) UNIQUE"; - if ($conexion->query($alter_query)) { - echo "

✅ Campo EMAIL_EMPLEADO agregado exitosamente

"; - } else { - echo "

❌ Error al agregar EMAIL_EMPLEADO: " . $conexion->error . "

"; - } - } - - if (in_array('CONTRASEÑA_EMPLEADO', $campos_faltantes)) { - $alter_query = "ALTER TABLE Empleados ADD COLUMN CONTRASEÑA_EMPLEADO VARCHAR(255)"; - if ($conexion->query($alter_query)) { - echo "

✅ Campo CONTRASEÑA_EMPLEADO agregado exitosamente

"; - } else { - echo "

❌ Error al agregar CONTRASEÑA_EMPLEADO: " . $conexion->error . "

"; - } - } - - if (in_array('SALT_EMPLEADO', $campos_faltantes)) { - $alter_query = "ALTER TABLE Empleados ADD COLUMN SALT_EMPLEADO VARCHAR(32)"; - if ($conexion->query($alter_query)) { - echo "

✅ Campo SALT_EMPLEADO agregado exitosamente

"; - } else { - echo "

❌ Error al agregar SALT_EMPLEADO: " . $conexion->error . "

"; - } - } - - // Agregar campo FECHA_REGISTRO si no existe - if (!in_array('FECHA_REGISTRO', $campos_existentes)) { - $alter_query = "ALTER TABLE Empleados ADD COLUMN FECHA_REGISTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP"; - if ($conexion->query($alter_query)) { - echo "

✅ Campo FECHA_REGISTRO agregado exitosamente

"; - } else { - echo "

❌ Error al agregar FECHA_REGISTRO: " . $conexion->error . "

"; - } - } - - echo "

📋 Estructura actualizada:

"; - $query = "DESCRIBE Empleados"; - $result = $conexion->query($query); - - echo ""; - echo ""; - - while ($row = $result->fetch_assoc()) { - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - } - echo "
CampoTipoNullKeyDefaultExtra
" . $row['Field'] . "" . $row['Type'] . "" . $row['Null'] . "" . $row['Key'] . "" . $row['Default'] . "" . $row['Extra'] . "
"; - } - -} catch (Exception $e) { - echo "

❌ Error: " . $e->getMessage() . "

"; -} - -$conexion->close(); - -echo "
"; -echo "

💡 Información:

"; -echo "
    "; -echo "
  • EMAIL_EMPLEADO: Campo único para el email del empleado
  • "; -echo "
  • CONTRASEÑA_EMPLEADO: Campo para almacenar la contraseña hasheada con SHA256
  • "; -echo "
  • SALT_EMPLEADO: Campo para almacenar el salt usado en el hash
  • "; -echo "
  • FECHA_REGISTRO: Campo para registrar cuándo se agregó el empleado
  • "; -echo "
  • Sistema de hash: SHA256 + Salt (compatible con el sistema existente)
  • "; -echo "
"; -?> diff --git a/files/agregar_empleado_ajax.php b/files/agregar_empleado_ajax.php deleted file mode 100644 index 85fad52..0000000 --- a/files/agregar_empleado_ajax.php +++ /dev/null @@ -1,127 +0,0 @@ - false, 'mensaje' => 'Acceso no autorizado']); - exit(); -} - -// Headers de respuesta JSON -header('Content-Type: application/json'); - -// Verificar método POST -if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']); - exit(); -} - -// Incluir conexión a la base de datos -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception('Error de conexión a la base de datos'); - } - - // Obtener y validar datos del formulario - $nombre = trim($_POST['nombre'] ?? ''); - $email = trim($_POST['email'] ?? ''); - $password = trim($_POST['password'] ?? ''); - - // Validaciones - if (empty($nombre)) { - throw new Exception('El nombre es requerido'); - } - - if (empty($email)) { - throw new Exception('El email es requerido'); - } - - if (empty($password)) { - throw new Exception('La contraseña es requerida'); - } - - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - throw new Exception('El email no tiene un formato válido'); - } - - if (strlen($password) < 6) { - throw new Exception('La contraseña debe tener al menos 6 caracteres'); - } - - // Verificar si el email ya existe - $consulta_verificar = "SELECT ID_EMPLEADO FROM Empleados WHERE EMAIL_EMPLEADO = ? OR NOMBRE_EMPLEADO = ?"; - $stmt_verificar = $conexion->prepare($consulta_verificar); - - if (!$stmt_verificar) { - throw new Exception('Error al preparar la consulta de verificación: ' . $conexion->error); - } - - $stmt_verificar->bind_param('ss', $email, $nombre); - $stmt_verificar->execute(); - $resultado_verificar = $stmt_verificar->get_result(); - - if ($resultado_verificar->num_rows > 0) { - throw new Exception('Ya existe un empleado con este email o nombre'); - } - - $stmt_verificar->close(); - - // Generar salt y hashear la contraseña (compatible con el sistema existente) - $salt = bin2hex(random_bytes(16)); // Generar salt aleatorio - $password_hash = hash('sha256', $password . $salt); - - // Verificar si la columna FECHA_REGISTRO existe en la tabla - $check_column = "SHOW COLUMNS FROM Empleados LIKE 'FECHA_REGISTRO'"; - $column_result = $conexion->query($check_column); - $fecha_registro_exists = ($column_result && $column_result->num_rows > 0); - - // Insertar el nuevo empleado (con o sin FECHA_REGISTRO dependiendo de si existe) - if ($fecha_registro_exists) { - $consulta_insertar = "INSERT INTO Empleados (NOMBRE_EMPLEADO, EMAIL_EMPLEADO, CONTRASEÑA_EMPLEADO, SALT_EMPLEADO, ACTIVO_EMPLEADO, FECHA_REGISTRO) - VALUES (?, ?, ?, ?, 1, NOW())"; - } else { - $consulta_insertar = "INSERT INTO Empleados (NOMBRE_EMPLEADO, EMAIL_EMPLEADO, CONTRASEÑA_EMPLEADO, SALT_EMPLEADO, ACTIVO_EMPLEADO) - VALUES (?, ?, ?, ?, 1)"; - } - - $stmt_insertar = $conexion->prepare($consulta_insertar); - - if (!$stmt_insertar) { - throw new Exception('Error al preparar la consulta de inserción: ' . $conexion->error); - } - - $stmt_insertar->bind_param('ssss', $nombre, $email, $password_hash, $salt); - - if ($stmt_insertar->execute()) { - $nuevo_id = $conexion->insert_id; - - echo json_encode([ - 'success' => true, - 'mensaje' => 'Empleado agregado exitosamente', - 'empleado' => [ - 'id' => $nuevo_id, - 'nombre' => htmlspecialchars($nombre), - 'email' => htmlspecialchars($email) - ] - ]); - } else { - throw new Exception('Error al insertar el empleado: ' . $stmt_insertar->error); - } - - $stmt_insertar->close(); - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage() - ]); -} - -// Cerrar conexión -if (isset($conexion)) { - $conexion->close(); -} -?> diff --git a/files/agregar_empleado_ajax_pdo.php b/files/agregar_empleado_ajax_pdo.php deleted file mode 100644 index a078cda..0000000 --- a/files/agregar_empleado_ajax_pdo.php +++ /dev/null @@ -1,119 +0,0 @@ - false, 'mensaje' => 'Acceso no autorizado']); - exit(); -} - -// Headers de respuesta JSON -header('Content-Type: application/json'); - -// Verificar método POST -if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']); - exit(); -} - -try { - // Conexión PDO (igual que en el login) - $dsn = "mysql:host=localhost;dbname=proyectopanaderia;charset=utf8"; - $username = "root"; - $password = ""; - - $pdo_conexion = new PDO($dsn, $username, $password); - $pdo_conexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - // Obtener y validar datos del formulario - $nombre = trim($_POST['nombre'] ?? ''); - $email = trim($_POST['email'] ?? ''); - $password_input = trim($_POST['password'] ?? ''); - - // Validaciones - if (empty($nombre)) { - throw new Exception('El nombre es requerido'); - } - - if (empty($email)) { - throw new Exception('El email es requerido'); - } - - if (empty($password_input)) { - throw new Exception('La contraseña es requerida'); - } - - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - throw new Exception('El email no tiene un formato válido'); - } - - if (strlen($password_input) < 6) { - throw new Exception('La contraseña debe tener al menos 6 caracteres'); - } - - // Verificar si el email o nombre ya existe - $consulta_verificar = "SELECT ID_EMPLEADO FROM Empleados WHERE EMAIL_EMPLEADO = :email OR NOMBRE_EMPLEADO = :nombre"; - $stmt_verificar = $pdo_conexion->prepare($consulta_verificar); - $stmt_verificar->bindParam(':email', $email, PDO::PARAM_STR); - $stmt_verificar->bindParam(':nombre', $nombre, PDO::PARAM_STR); - $stmt_verificar->execute(); - - if ($stmt_verificar->rowCount() > 0) { - throw new Exception('Ya existe un empleado con este email o nombre'); - } - - // Generar salt y hashear la contraseña (exactamente como en el sistema existente) - $salt = bin2hex(random_bytes(16)); - $password_hash = hash('sha256', $password_input . $salt); - - // Insertar el nuevo empleado - $consulta_insertar = "INSERT INTO Empleados (NOMBRE_EMPLEADO, EMAIL_EMPLEADO, CONTRASEÑA_EMPLEADO, SALT_EMPLEADO, ACTIVO_EMPLEADO, FECHA_REGISTRO) - VALUES (:nombre, :email, :password_hash, :salt, 1, NOW())"; - - $stmt_insertar = $pdo_conexion->prepare($consulta_insertar); - $stmt_insertar->bindParam(':nombre', $nombre, PDO::PARAM_STR); - $stmt_insertar->bindParam(':email', $email, PDO::PARAM_STR); - $stmt_insertar->bindParam(':password_hash', $password_hash, PDO::PARAM_STR); - $stmt_insertar->bindParam(':salt', $salt, PDO::PARAM_STR); - - if ($stmt_insertar->execute()) { - $nuevo_id = $pdo_conexion->lastInsertId(); - - // Verificar inmediatamente el login - $consulta_verificar_login = "SELECT ID_EMPLEADO, NOMBRE_EMPLEADO, CONTRASEÑA_EMPLEADO, SALT_EMPLEADO, ACTIVO_EMPLEADO, EMAIL_EMPLEADO - FROM Empleados - WHERE (NOMBRE_EMPLEADO = :usuario OR EMAIL_EMPLEADO = :usuario) AND ACTIVO_EMPLEADO = 1"; - - $stmt_verificar_login = $pdo_conexion->prepare($consulta_verificar_login); - $stmt_verificar_login->bindParam(':usuario', $email, PDO::PARAM_STR); - $stmt_verificar_login->execute(); - - $user_data = $stmt_verificar_login->fetch(PDO::FETCH_ASSOC); - - $login_test = false; - if ($user_data) { - $hash_verificacion = hash('sha256', $password_input . $user_data['SALT_EMPLEADO']); - $login_test = ($hash_verificacion === $user_data['CONTRASEÑA_EMPLEADO']); - } - - echo json_encode([ - 'success' => true, - 'mensaje' => 'Empleado agregado exitosamente', - 'empleado' => [ - 'id' => $nuevo_id, - 'nombre' => htmlspecialchars($nombre), - 'email' => htmlspecialchars($email) - ], - 'login_test' => $login_test ? 'Login funcionará correctamente' : 'ADVERTENCIA: Puede haber problema con el login' - ]); - } else { - throw new Exception('Error al insertar el empleado'); - } - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage() - ]); -} -?> diff --git a/files/agregar_ingrediente_ajax.php b/files/agregar_ingrediente_ajax.php deleted file mode 100644 index 8245552..0000000 --- a/files/agregar_ingrediente_ajax.php +++ /dev/null @@ -1,152 +0,0 @@ - false, - 'error' => 'No autorizado' - ]); - exit(); -} - -require_once 'conexion.php'; - -try { - // Validar que se recibieron los datos por POST - if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - throw new Exception('Método no permitido'); - } - - // Obtener y validar datos - $nombre = trim($_POST['nombre'] ?? ''); - $cantidad = intval($_POST['cantidad'] ?? 0); - $precio_compra = floatval($_POST['precio_compra'] ?? 0); - $categoria = intval($_POST['categoria'] ?? 0); - $proveedor = intval($_POST['proveedor'] ?? 0); - $fecha_vencimiento = $_POST['fecha_vencimiento'] ?? ''; - $fecha_entrega = $_POST['fecha_entrega'] ?? ''; - $referencia = trim($_POST['referencia'] ?? ''); - - // Validaciones - if (empty($nombre)) { - throw new Exception('El nombre del ingrediente es obligatorio'); - } - - if ($cantidad < 0) { - throw new Exception('La cantidad no puede ser negativa'); - } - - if ($precio_compra < 0) { - throw new Exception('El precio de compra no puede ser negativo'); - } - - if ($categoria <= 0) { - throw new Exception('Debe seleccionar una categoría'); - } - - // El proveedor es opcional - if ($proveedor <= 0) { - $proveedor = null; - } - - if (empty($fecha_vencimiento)) { - throw new Exception('La fecha de vencimiento es obligatoria'); - } - - if (empty($fecha_entrega)) { - throw new Exception('La fecha de entrega es obligatoria'); - } - - if (empty($referencia)) { - throw new Exception('La referencia es obligatoria'); - } - - // Validar formato de fechas - $fecha_venc_obj = DateTime::createFromFormat('Y-m-d', $fecha_vencimiento); - $fecha_ent_obj = DateTime::createFromFormat('Y-m-d', $fecha_entrega); - - if (!$fecha_venc_obj || !$fecha_ent_obj) { - throw new Exception('Formato de fecha inválido'); - } - - // Validar que la fecha de vencimiento sea futura - $hoy = new DateTime(); - if ($fecha_venc_obj <= $hoy) { - throw new Exception('La fecha de vencimiento debe ser futura'); - } - - // Verificar que la categoría existe - $stmt = $conexion->prepare("SELECT ID_CATEGORIA FROM Categoria_Ingredientes WHERE ID_CATEGORIA = ?"); - $stmt->bind_param("i", $categoria); - $stmt->execute(); - if ($stmt->get_result()->num_rows === 0) { - throw new Exception('La categoría seleccionada no existe'); - } - - // Verificar que el proveedor existe y está activo (solo si se especificó) - if ($proveedor !== null) { - $stmt = $conexion->prepare("SELECT ID_PROVEEDOR FROM Proveedores WHERE ID_PROVEEDOR = ? AND ACTIVO_PROV = 1"); - $stmt->bind_param("i", $proveedor); - $stmt->execute(); - if ($stmt->get_result()->num_rows === 0) { - throw new Exception('El proveedor seleccionado no existe o no está activo'); - } - } - - // Insertar el ingrediente - $stmt = $conexion->prepare("INSERT INTO Ingredientes ( - ID_PROVEEDOR, - ID_CATEGORIA, - NOMBRE_INGREDIENTE, - CANTIDAD_INGREDIENTE, - PRECIO_COMPRA, - FECHA_VENCIMIENTO, - REFERENCIA_INGREDIENTE, - FECHA_ENTREGA_INGREDIENTE - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); - - $stmt->bind_param("iisidsss", - $proveedor, - $categoria, - $nombre, - $cantidad, - $precio_compra, - $cantidad, - $fecha_vencimiento, - $referencia, - $fecha_entrega - ); - - if ($stmt->execute()) { - $id_ingrediente = $conexion->insert_id; - - echo json_encode([ - 'success' => true, - 'mensaje' => 'Ingrediente agregado exitosamente', - 'id' => $id_ingrediente - ]); - } else { - throw new Exception('Error al insertar el ingrediente: ' . $stmt->error); - } - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage() - ]); -} - -$conexion->close(); -?> diff --git a/files/agregar_producto.php b/files/agregar_producto.php deleted file mode 100644 index 6e40763..0000000 --- a/files/agregar_producto.php +++ /dev/null @@ -1,238 +0,0 @@ -prepare($consulta); - - // Vincular parámetros - $stmt->bindParam(':nombre_producto', $nombre_producto, PDO::PARAM_STR); - $stmt->bindParam(':stock_min', $stock_min, PDO::PARAM_INT); - $stmt->bindParam(':precio_producto', $precio_producto, PDO::PARAM_STR); - $stmt->bindParam(':fecha_vencimiento', $fecha_vencimiento, PDO::PARAM_STR); - $stmt->bindParam(':fecha_ingreso', date('Y-m-d'), PDO::PARAM_STR); - $stmt->bindParam(':tipo_producto_marca', $tipo_producto_marca, PDO::PARAM_STR); - - // Ejecutar la consulta - if ($stmt->execute()) { - $id_producto_creado = $pdo_conexion->lastInsertId(); - $mensaje = "¡Producto agregado exitosamente! ID del producto: {$id_producto_creado}"; - $tipo_mensaje = "success"; - } else { - $mensaje = "Error: No se pudo agregar el producto."; - $tipo_mensaje = "error"; - } - - } catch (PDOException $e) { - $mensaje = "Error en la base de datos: " . $e->getMessage(); - $tipo_mensaje = "error"; - } - } else { - // Hay errores de validación - $mensaje = "Errores encontrados:
• " . implode("
• ", $errores); - $tipo_mensaje = "error"; - } -} else { - // Si se accede directamente sin POST, redirigir - header("Location: productostabla.php"); - exit(); -} -?> - - - - - - - Agregar Producto - Panadería - - - -
- -
-

¡Producto Agregado Exitosamente!

- -
- -
- -
-

Detalles del Producto Agregado:

-

Nombre:

-

Precio: $

-

Stock Mínimo:

-

Marca/Tipo:

-

Fecha de Vencimiento:

-

Fecha de Ingreso:

-
- - -
-

Error al Agregar Producto

- -
- -
- - -
- - - - - - - -
- -
- ⏱️ Por favor, lea la información mostrada arriba antes de continuar. - Los botones se activarán en 5 segundos. -
-
- - - - diff --git a/files/agregar_producto_ajax.php b/files/agregar_producto_ajax.php deleted file mode 100644 index 5cd6b17..0000000 --- a/files/agregar_producto_ajax.php +++ /dev/null @@ -1,99 +0,0 @@ -prepare($sql); - - if (!$stmt) { - throw new Exception('Error en la preparación de la consulta: ' . $conexion->error); - } - - $fecha_ingreso = date('Y-m-d'); - $stmt->bind_param('sidsss', $nombre, $stock, $precio, $fecha_vencimiento, $fecha_ingreso, $categoria); - - if ($stmt->execute()) { - // Obtener el ID del producto recién insertado - $producto_id = $conexion->insert_id; - - echo json_encode([ - 'success' => true, - 'mensaje' => 'Producto agregado exitosamente', - 'detalles' => [ - 'id' => $producto_id, - 'nombre' => htmlspecialchars($nombre), - 'precio' => number_format($precio, 2), - 'stock' => $stock, - 'categoria' => htmlspecialchars($categoria), - 'fecha_vencimiento' => date('d/m/Y', strtotime($fecha_vencimiento)), - 'fecha_ingreso' => date('d/m/Y') - ] - ]); - } else { - throw new Exception('Error al insertar el producto: ' . $stmt->error); - } - - $stmt->close(); - - } catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage() - ]); - } -} else { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Método de solicitud no válido' - ]); -} - -$conexion->close(); -?> diff --git a/files/api_productos_admin.php b/files/api_productos_admin.php deleted file mode 100644 index 3a6ebed..0000000 --- a/files/api_productos_admin.php +++ /dev/null @@ -1,456 +0,0 @@ - false, 'message' => 'No autorizado']); - exit(); -} - -require_once 'conexion.php'; - -// Función para registrar cambios en el log -function registrarCambio($conexion, $producto_id, $tipo_cambio, $valor_anterior, $valor_nuevo, $usuario_id, $ip_usuario) { - $stmt = $conexion->prepare("INSERT INTO productos_logs (producto_id, tipo_cambio, valor_anterior, valor_nuevo, usuario_id, usuario_tipo, ip_usuario) VALUES (?, ?, ?, ?, ?, 'admin', ?)"); - $stmt->bind_param("isssss", $producto_id, $tipo_cambio, $valor_anterior, $valor_nuevo, $usuario_id, $ip_usuario); - return $stmt->execute(); -} - -// Obtener información del usuario -$usuario_id = $_SESSION['usuario_id'] ?? 0; -$ip_usuario = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; - -// Manejar diferentes métodos HTTP -$method = $_SERVER['REQUEST_METHOD']; -$request_uri = $_SERVER['REQUEST_URI']; -$path_parts = explode('/', trim(parse_url($request_uri, PHP_URL_PATH), '/')); - -try { - switch ($method) { - case 'GET': - handleGet(); - break; - case 'POST': - handlePost(); - break; - case 'PUT': - handlePut(); - break; - case 'PATCH': - handlePatch(); - break; - case 'DELETE': - handleDelete(); - break; - default: - http_response_code(405); - echo json_encode(['success' => false, 'message' => 'Método no permitido']); - break; - } -} catch (Exception $e) { - http_response_code(500); - echo json_encode(['success' => false, 'message' => 'Error del servidor: ' . $e->getMessage()]); -} - -/** - * GET - Obtener productos o producto específico - */ -function handleGet() { - global $conexion; - - $producto_id = $_GET['id'] ?? null; - $incluir_logs = $_GET['incluir_logs'] ?? false; - - if ($producto_id) { - // Obtener producto específico - $stmt = $conexion->prepare(" - SELECT p.*, c.NOMBRE_CATEGORIA_PRODUCTO as categoria_nombre, - a.NOMBRE_ADMIN as admin_nombre - FROM Productos p - LEFT JOIN Categoria_Productos c ON p.ID_CATEGORIA_PRODUCTO = c.ID_CATEGORIA_PRODUCTO - LEFT JOIN Administradores a ON p.ID_ADMIN = a.ID_ADMIN - WHERE p.ID_PRODUCTO = ? - "); - $stmt->bind_param("i", $producto_id); - $stmt->execute(); - $producto = $stmt->get_result()->fetch_assoc(); - - if (!$producto) { - http_response_code(404); - echo json_encode(['success' => false, 'message' => 'Producto no encontrado']); - return; - } - - $response = ['success' => true, 'data' => $producto]; - - // Incluir logs si se solicita - if ($incluir_logs) { - $stmt = $conexion->prepare(" - SELECT * FROM productos_logs - WHERE producto_id = ? - ORDER BY fecha_cambio DESC - LIMIT 50 - "); - $stmt->bind_param("i", $producto_id); - $stmt->execute(); - $logs = $stmt->get_result()->fetch_all(MYSQLI_ASSOC); - $response['logs'] = $logs; - } - - echo json_encode($response); - } else { - // Obtener todos los productos - $activos_solo = $_GET['activos_solo'] ?? false; - $categoria = $_GET['categoria'] ?? null; - $buscar = $_GET['buscar'] ?? null; - $page = max(1, intval($_GET['page'] ?? 1)); - $limit = min(100, max(10, intval($_GET['limit'] ?? 20))); - $offset = ($page - 1) * $limit; - - $where_conditions = []; - $params = []; - $param_types = ""; - - if ($activos_solo) { - $where_conditions[] = "p.ACTIVO = 1"; - } - - if ($categoria) { - $where_conditions[] = "p.ID_CATEGORIA_PRODUCTO = ?"; - $params[] = $categoria; - $param_types .= "i"; - } - - if ($buscar) { - $where_conditions[] = "p.NOMBRE_PRODUCTO LIKE ?"; - $params[] = "%$buscar%"; - $param_types .= "s"; - } - - $where_clause = $where_conditions ? "WHERE " . implode(" AND ", $where_conditions) : ""; - - // Contar total de productos - $count_query = " - SELECT COUNT(*) as total - FROM Productos p - LEFT JOIN Categoria_Productos c ON p.ID_CATEGORIA_PRODUCTO = c.ID_CATEGORIA_PRODUCTO - $where_clause - "; - - if ($params) { - $stmt = $conexion->prepare($count_query); - $stmt->bind_param($param_types, ...$params); - $stmt->execute(); - $total = $stmt->get_result()->fetch_assoc()['total']; - } else { - $total = $conexion->query($count_query)->fetch_assoc()['total']; - } - - // Obtener productos paginados - $query = " - SELECT p.*, c.NOMBRE_CATEGORIA_PRODUCTO as categoria_nombre, - a.NOMBRE_ADMIN as admin_nombre - FROM Productos p - LEFT JOIN Categoria_Productos c ON p.ID_CATEGORIA_PRODUCTO = c.ID_CATEGORIA_PRODUCTO - LEFT JOIN Administradores a ON p.ID_ADMIN = a.ID_ADMIN - $where_clause - ORDER BY p.FECHA_ULTIMA_MODIFICACION DESC - LIMIT ? OFFSET ? - "; - - $params[] = $limit; - $params[] = $offset; - $param_types .= "ii"; - - $stmt = $conexion->prepare($query); - if ($params) { - $stmt->bind_param($param_types, ...$params); - } - $stmt->execute(); - $productos = $stmt->get_result()->fetch_all(MYSQLI_ASSOC); - - echo json_encode([ - 'success' => true, - 'data' => $productos, - 'pagination' => [ - 'page' => $page, - 'limit' => $limit, - 'total' => $total, - 'pages' => ceil($total / $limit) - ] - ]); - } -} - -/** - * POST - Crear nuevo producto - */ -function handlePost() { - global $conexion, $usuario_id, $ip_usuario; - - $input = json_decode(file_get_contents('php://input'), true); - - $required_fields = ['nombre_producto', 'precio_producto', 'stock_min', 'fecha_vencimiento', 'tipo_producto_marca', 'id_categoria_producto']; - - foreach ($required_fields as $field) { - if (!isset($input[$field]) || empty($input[$field])) { - http_response_code(400); - echo json_encode(['success' => false, 'message' => "Campo requerido: $field"]); - return; - } - } - - // Validaciones - if (floatval($input['precio_producto']) <= 0) { - http_response_code(400); - echo json_encode(['success' => false, 'message' => 'El precio debe ser mayor a 0']); - return; - } - - if (intval($input['stock_min']) < 0) { - http_response_code(400); - echo json_encode(['success' => false, 'message' => 'El stock no puede ser negativo']); - return; - } - - $stmt = $conexion->prepare(" - INSERT INTO Productos ( - ID_ADMIN, ID_CATEGORIA_PRODUCTO, NOMBRE_PRODUCTO, - PRODUCTO_STOCK_MIN, PRECIO_PRODUCTO, FECHA_VENCIMIENTO_PRODUCTO, - FECHA_INGRESO_PRODUCTO, TIPO_PRODUCTO_MARCA, ACTIVO - ) VALUES (?, ?, ?, ?, ?, ?, CURDATE(), ?, 1) - "); - - $stmt->bind_param("iiisdss", - $usuario_id, - $input['id_categoria_producto'], - $input['nombre_producto'], - $input['stock_min'], - $input['precio_producto'], - $input['fecha_vencimiento'], - $input['tipo_producto_marca'] - ); - - if ($stmt->execute()) { - $nuevo_id = $conexion->insert_id; - - // Registrar creación en logs - registrarCambio($conexion, $nuevo_id, 'precio', '0', $input['precio_producto'], $usuario_id, $ip_usuario); - registrarCambio($conexion, $nuevo_id, 'stock', '0', $input['stock_min'], $usuario_id, $ip_usuario); - - http_response_code(201); - echo json_encode([ - 'success' => true, - 'message' => 'Producto creado correctamente', - 'data' => ['id' => $nuevo_id] - ]); - } else { - http_response_code(500); - echo json_encode(['success' => false, 'message' => 'Error al crear el producto']); - } -} - -/** - * PUT - Actualizar producto completo - */ -function handlePut() { - global $conexion, $usuario_id, $ip_usuario; - - $input = json_decode(file_get_contents('php://input'), true); - $producto_id = intval($input['id'] ?? 0); - - if ($producto_id <= 0) { - http_response_code(400); - echo json_encode(['success' => false, 'message' => 'ID de producto requerido']); - return; - } - - // Obtener datos actuales del producto - $stmt = $conexion->prepare("SELECT * FROM Productos WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("i", $producto_id); - $stmt->execute(); - $producto_actual = $stmt->get_result()->fetch_assoc(); - - if (!$producto_actual) { - http_response_code(404); - echo json_encode(['success' => false, 'message' => 'Producto no encontrado']); - return; - } - - $stmt = $conexion->prepare(" - UPDATE Productos SET - ID_CATEGORIA_PRODUCTO = ?, NOMBRE_PRODUCTO = ?, - PRODUCTO_STOCK_MIN = ?, PRECIO_PRODUCTO = ?, - FECHA_VENCIMIENTO_PRODUCTO = ?, TIPO_PRODUCTO_MARCA = ? - WHERE ID_PRODUCTO = ? - "); - - $stmt->bind_param("isiissi", - $input['id_categoria_producto'], - $input['nombre_producto'], - $input['stock_min'], - $input['precio_producto'], - $input['fecha_vencimiento'], - $input['tipo_producto_marca'], - $producto_id - ); - - if ($stmt->execute()) { - // Registrar cambios específicos - if ($producto_actual['PRECIO_PRODUCTO'] != $input['precio_producto']) { - registrarCambio($conexion, $producto_id, 'precio', $producto_actual['PRECIO_PRODUCTO'], $input['precio_producto'], $usuario_id, $ip_usuario); - } - - if ($producto_actual['PRODUCTO_STOCK_MIN'] != $input['stock_min']) { - registrarCambio($conexion, $producto_id, 'stock', $producto_actual['PRODUCTO_STOCK_MIN'], $input['stock_min'], $usuario_id, $ip_usuario); - } - - echo json_encode(['success' => true, 'message' => 'Producto actualizado correctamente']); - } else { - http_response_code(500); - echo json_encode(['success' => false, 'message' => 'Error al actualizar el producto']); - } -} - -/** - * PATCH - Actualización parcial (precio/stock específicos) - */ -function handlePatch() { - global $conexion, $usuario_id, $ip_usuario; - - $input = json_decode(file_get_contents('php://input'), true); - $producto_id = intval($input['id'] ?? 0); - $campo = $input['campo'] ?? ''; - $valor = $input['valor'] ?? ''; - - if ($producto_id <= 0 || empty($campo)) { - http_response_code(400); - echo json_encode(['success' => false, 'message' => 'ID de producto y campo requeridos']); - return; - } - - // Obtener producto actual - $stmt = $conexion->prepare("SELECT PRECIO_PRODUCTO, PRODUCTO_STOCK_MIN FROM Productos WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("i", $producto_id); - $stmt->execute(); - $producto = $stmt->get_result()->fetch_assoc(); - - if (!$producto) { - http_response_code(404); - echo json_encode(['success' => false, 'message' => 'Producto no encontrado']); - return; - } - - switch ($campo) { - case 'precio': - $nuevo_precio = floatval($valor); - if ($nuevo_precio <= 0) { - http_response_code(400); - echo json_encode(['success' => false, 'message' => 'El precio debe ser mayor a 0']); - return; - } - - $stmt = $conexion->prepare("UPDATE Productos SET PRECIO_PRODUCTO = ? WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("di", $nuevo_precio, $producto_id); - - if ($stmt->execute()) { - registrarCambio($conexion, $producto_id, 'precio', $producto['PRECIO_PRODUCTO'], $nuevo_precio, $usuario_id, $ip_usuario); - echo json_encode(['success' => true, 'message' => 'Precio actualizado correctamente', 'nuevo_valor' => $nuevo_precio]); - } else { - http_response_code(500); - echo json_encode(['success' => false, 'message' => 'Error al actualizar precio']); - } - break; - - case 'stock': - $nuevo_stock = intval($valor); - if ($nuevo_stock < 0) { - http_response_code(400); - echo json_encode(['success' => false, 'message' => 'El stock no puede ser negativo']); - return; - } - - $stmt = $conexion->prepare("UPDATE Productos SET PRODUCTO_STOCK_MIN = ? WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("ii", $nuevo_stock, $producto_id); - - if ($stmt->execute()) { - registrarCambio($conexion, $producto_id, 'stock', $producto['PRODUCTO_STOCK_MIN'], $nuevo_stock, $usuario_id, $ip_usuario); - echo json_encode(['success' => true, 'message' => 'Stock actualizado correctamente', 'nuevo_valor' => $nuevo_stock]); - } else { - http_response_code(500); - echo json_encode(['success' => false, 'message' => 'Error al actualizar stock']); - } - break; - - case 'activo': - $activo = intval($valor); - $tipo_log = $activo ? 'activacion' : 'desactivacion'; - - $stmt = $conexion->prepare("UPDATE Productos SET ACTIVO = ? WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("ii", $activo, $producto_id); - - if ($stmt->execute()) { - registrarCambio($conexion, $producto_id, $tipo_log, $activo ? '0' : '1', $activo, $usuario_id, $ip_usuario); - echo json_encode(['success' => true, 'message' => 'Estado actualizado correctamente', 'nuevo_valor' => $activo]); - } else { - http_response_code(500); - echo json_encode(['success' => false, 'message' => 'Error al actualizar estado']); - } - break; - - default: - http_response_code(400); - echo json_encode(['success' => false, 'message' => 'Campo no válido']); - break; - } -} - -/** - * DELETE - Eliminar producto (soft delete) - */ -function handleDelete() { - global $conexion, $usuario_id, $ip_usuario; - - $input = json_decode(file_get_contents('php://input'), true); - $producto_id = intval($input['id'] ?? 0); - $forzar_eliminacion = $input['forzar'] ?? false; - - if ($producto_id <= 0) { - http_response_code(400); - echo json_encode(['success' => false, 'message' => 'ID de producto requerido']); - return; - } - - if ($forzar_eliminacion) { - // Eliminación física - $stmt = $conexion->prepare("DELETE FROM Productos WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("i", $producto_id); - - if ($stmt->execute()) { - echo json_encode(['success' => true, 'message' => 'Producto eliminado permanentemente']); - } else { - http_response_code(500); - echo json_encode(['success' => false, 'message' => 'Error al eliminar producto']); - } - } else { - // Soft delete - $stmt = $conexion->prepare("UPDATE Productos SET ACTIVO = 0 WHERE ID_PRODUCTO = ?"); - $stmt->bind_param("i", $producto_id); - - if ($stmt->execute()) { - registrarCambio($conexion, $producto_id, 'desactivacion', '1', '0', $usuario_id, $ip_usuario); - echo json_encode(['success' => true, 'message' => 'Producto desactivado correctamente']); - } else { - http_response_code(500); - echo json_encode(['success' => false, 'message' => 'Error al desactivar producto']); - } - } -} -?> diff --git a/files/borrar_producto.php b/files/borrar_producto.php deleted file mode 100644 index 687acc0..0000000 --- a/files/borrar_producto.php +++ /dev/null @@ -1,283 +0,0 @@ -alert('Método no permitido. Use POST.'); window.history.back();"; - exit(); -} - -// Verificar si se recibió el ID del producto -if (isset($_POST['id']) && !empty($_POST['id'])) { - $id_producto = $_POST['id']; - - try { - // Primero, obtener los datos del producto antes de eliminarlo para mostrar confirmación - $consulta_producto = "SELECT NOMBRE_PRODUCTO FROM Productos WHERE ID_PRODUCTO = ?"; - $stmt_producto = $conexion->prepare($consulta_producto); - $stmt_producto->bind_param('i', $id_producto); - $stmt_producto->execute(); - $resultado = $stmt_producto->get_result(); - $producto = $resultado->fetch_assoc(); - - if ($producto) { - $nombre_producto = $producto['NOMBRE_PRODUCTO']; - - // Verificar si el producto tiene referencias en otras tablas - $consulta_referencias = "SELECT COUNT(*) as total FROM Detalle_Pedidos WHERE ID_PRODUCTO = ?"; - $stmt_referencias = $conexion->prepare($consulta_referencias); - $stmt_referencias->bind_param('i', $id_producto); - $stmt_referencias->execute(); - $resultado_ref = $stmt_referencias->get_result(); - $referencias = $resultado_ref->fetch_assoc(); - - if ($referencias['total'] > 0) { - // El producto tiene referencias, no se puede eliminar - $mensaje = "No se puede eliminar el producto '{$nombre_producto}' porque está asociado a {$referencias['total']} pedido(s). Para eliminarlo, primero debe eliminar o modificar los pedidos que lo contienen."; - $tipo_mensaje = "warning"; - $mostrar_opciones = true; - } else { - // El producto no tiene referencias, se puede eliminar - $consulta_eliminar = "DELETE FROM Productos WHERE ID_PRODUCTO = ?"; - $stmt_eliminar = $conexion->prepare($consulta_eliminar); - $stmt_eliminar->bind_param('i', $id_producto); - - if ($stmt_eliminar->execute()) { - $mensaje = "El producto '{$nombre_producto}' ha sido eliminado exitosamente."; - $tipo_mensaje = "success"; - $mostrar_opciones = false; - } else { - $mensaje = "Error: No se pudo eliminar el producto."; - $tipo_mensaje = "error"; - $mostrar_opciones = false; - } - } - } else { - $mensaje = "Error: El producto no existe."; - $tipo_mensaje = "error"; - } - - } catch (Exception $e) { - // Verificar si es un error de restricción de clave foránea - if (strpos($e->getMessage(), '1451') !== false) { - $mensaje = "No se puede eliminar el producto porque está siendo utilizado en pedidos activos. Para eliminarlo, primero debe eliminar o modificar los pedidos que lo contienen."; - $tipo_mensaje = "warning"; - $mostrar_opciones = true; - } else { - $mensaje = "Error en la base de datos: " . $e->getMessage(); - $tipo_mensaje = "error"; - $mostrar_opciones = false; - } - } -} else { - $mensaje = "Error: ID de producto no válido."; - $tipo_mensaje = "error"; - $mostrar_opciones = false; -} -?> - - - - - - - Eliminar Producto - Panadería - - - -
- -
-

Eliminación Exitosa

- -
-

Error en la Eliminación

- - -
- -
- -
- - - - -
- -
- ⏱️ Por favor, lee toda la información mostrada arriba antes de continuar. - Los botones se activarán en 5 segundos. -
-
- - - - diff --git a/files/cambiar_estado_pedido.php b/files/cambiar_estado_pedido.php deleted file mode 100644 index 630ebac..0000000 --- a/files/cambiar_estado_pedido.php +++ /dev/null @@ -1,91 +0,0 @@ - false, 'message' => 'Acceso denegado']); - exit(); -} - -// Establecer el tipo de contenido como JSON -header('Content-Type: application/json'); - -// Obtener datos del POST -$input = json_decode(file_get_contents('php://input'), true); - -if (!$input || !isset($input['pedido_id']) || !isset($input['nuevo_estado'])) { - echo json_encode(['success' => false, 'message' => 'Datos incompletos']); - exit(); -} - -$pedido_id = (int)$input['pedido_id']; -$nuevo_estado = (int)$input['nuevo_estado']; - -// Validar que el estado sea válido (1-5) -if ($nuevo_estado < 1 || $nuevo_estado > 5) { - echo json_encode(['success' => false, 'message' => 'Estado inválido']); - exit(); -} - -try { - // Verificar que el pedido existe - $check_query = "SELECT ID_PEDIDO FROM Pedidos WHERE ID_PEDIDO = ?"; - $check_stmt = mysqli_prepare($conexion, $check_query); - - if (!$check_stmt) { - throw new Exception("Error preparando consulta de verificación: " . mysqli_error($conexion)); - } - - mysqli_stmt_bind_param($check_stmt, 'i', $pedido_id); - mysqli_stmt_execute($check_stmt); - $result = mysqli_stmt_get_result($check_stmt); - - if (mysqli_num_rows($result) == 0) { - echo json_encode(['success' => false, 'message' => 'Pedido no encontrado']); - exit(); - } - - // Actualizar el estado del pedido - $update_query = "UPDATE Pedidos SET ID_ESTADO_PEDIDO = ? WHERE ID_PEDIDO = ?"; - $update_stmt = mysqli_prepare($conexion, $update_query); - - if (!$update_stmt) { - throw new Exception("Error preparando consulta de actualización: " . mysqli_error($conexion)); - } - - mysqli_stmt_bind_param($update_stmt, 'ii', $nuevo_estado, $pedido_id); - - if (mysqli_stmt_execute($update_stmt)) { - // Obtener el nombre del estado para el log - $estados = [ - 1 => 'Pendiente', - 2 => 'En Preparación', - 3 => 'Listo para Entrega', - 4 => 'Entregado', - 5 => 'Cancelado' - ]; - - $nombre_estado = $estados[$nuevo_estado]; - - // Log de la acción (opcional) - error_log("Admin {$_SESSION['usuario_nombre']} cambió el estado del pedido #{$pedido_id} a {$nombre_estado}"); - - echo json_encode([ - 'success' => true, - 'message' => "Estado del pedido #{$pedido_id} actualizado a {$nombre_estado}" - ]); - } else { - throw new Exception("Error al actualizar el estado: " . mysqli_error($conexion)); - } - -} catch (Exception $e) { - error_log("Error en cambiar_estado_pedido.php: " . $e->getMessage()); - echo json_encode(['success' => false, 'message' => 'Error interno del servidor']); -} -?> diff --git a/files/cambiar_estado_pedido_ajax.php b/files/cambiar_estado_pedido_ajax.php deleted file mode 100644 index 6b8d7d5..0000000 --- a/files/cambiar_estado_pedido_ajax.php +++ /dev/null @@ -1,118 +0,0 @@ - session_id(), - 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'NO_SET', - 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'NO_SET', - 'all_session' => $_SESSION - ]; - - error_log("AJAX Auth Failed Cambiar Estado - Debug: " . json_encode($debug_info)); - - http_response_code(401); - echo json_encode([ - 'success' => false, - 'mensaje' => 'No autorizado para cambiar estados.' - ]); - exit(); -} - -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception("No se pudo conectar a la base de datos"); - } - - // Obtener datos de la petición - $input = file_get_contents('php://input'); - $data = json_decode($input, true); - - if (!$data) { - throw new Exception("Datos de entrada inválidos"); - } - - $pedido_id = isset($data['pedido_id']) ? intval($data['pedido_id']) : 0; - $nuevo_estado = isset($data['nuevo_estado']) ? intval($data['nuevo_estado']) : 0; - - // Validar datos - if ($pedido_id <= 0) { - throw new Exception("ID de pedido inválido"); - } - - if ($nuevo_estado < 1 || $nuevo_estado > 5) { - throw new Exception("Estado inválido"); - } - - error_log("Cambiando estado - Pedido: $pedido_id, Nuevo estado: $nuevo_estado, Empleado: " . $_SESSION['usuario_id']); - - // Verificar que el pedido existe - $stmt = $conexion->prepare("SELECT ID_PEDIDO, ID_ESTADO_PEDIDO, ID_EMPLEADO FROM Pedidos WHERE ID_PEDIDO = ?"); - $stmt->bind_param("i", $pedido_id); - $stmt->execute(); - $result = $stmt->get_result(); - $pedido = $result->fetch_assoc(); - - if (!$pedido) { - throw new Exception("Pedido no encontrado"); - } - - // Si el pedido no tiene empleado asignado, asignarlo al empleado actual - if (empty($pedido['ID_EMPLEADO'])) { - $stmt = $conexion->prepare("UPDATE Pedidos SET ID_EMPLEADO = ? WHERE ID_PEDIDO = ?"); - $stmt->bind_param("ii", $_SESSION['usuario_id'], $pedido_id); - $stmt->execute(); - - error_log("Pedido $pedido_id asignado al empleado " . $_SESSION['usuario_id']); - } - - // Actualizar el estado del pedido - $stmt = $conexion->prepare("UPDATE Pedidos SET ID_ESTADO_PEDIDO = ? WHERE ID_PEDIDO = ?"); - $stmt->bind_param("ii", $nuevo_estado, $pedido_id); - - if (!$stmt->execute()) { - throw new Exception("Error al actualizar el estado del pedido"); - } - - // Obtener el nombre del nuevo estado - $stmt = $conexion->prepare("SELECT NOMBRE_ESTADO FROM Estado_Pedidos WHERE ID_ESTADO_PEDIDO = ?"); - $stmt->bind_param("i", $nuevo_estado); - $stmt->execute(); - $result = $stmt->get_result(); - $estado = $result->fetch_assoc(); - - $nombre_estado = $estado ? $estado['NOMBRE_ESTADO'] : "Estado $nuevo_estado"; - - error_log("Estado cambiado exitosamente - Pedido: $pedido_id, Nuevo estado: $nombre_estado"); - - echo json_encode([ - 'success' => true, - 'mensaje' => "Estado del pedido #$pedido_id cambiado a '$nombre_estado'", - 'pedido_id' => $pedido_id, - 'nuevo_estado' => $nuevo_estado, - 'nombre_estado' => $nombre_estado - ]); - -} catch (Exception $e) { - error_log("Error en cambiar_estado_pedido_ajax.php: " . $e->getMessage()); - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error: ' . $e->getMessage() - ]); -} -?> diff --git a/files/conexion.php b/files/conexion.php deleted file mode 100644 index a4bf18b..0000000 --- a/files/conexion.php +++ /dev/null @@ -1,25 +0,0 @@ -connect_error) { - die("Error de conexión: " . $conexion->connect_error); -} - -// Establecer charset -$conexion->set_charset("utf8"); - -// Opcional: mantener compatibilidad con PDO para otros archivos que lo usen -try { - $pdo_conexion = new PDO("mysql:host=$servidor;dbname=$base_datos;charset=utf8", $usuario, $password); - $pdo_conexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); -} catch(PDOException $e) { - die("Error de conexión PDO: " . $e->getMessage()); -} -?> diff --git a/files/crear_tabla_logs.sql b/files/crear_tabla_logs.sql deleted file mode 100644 index d2a7957..0000000 --- a/files/crear_tabla_logs.sql +++ /dev/null @@ -1,63 +0,0 @@ --- ================================================================== --- TABLA DE LOGS PARA CAMBIOS EN PRODUCTOS --- ================================================================== --- Ejecutar esta consulta para crear la tabla de logs - -USE ProyectoPanaderia; - --- Primero verificar y mostrar la estructura de la tabla Productos -DESCRIBE Productos; - --- Crear tabla de logs SIN la restricción de clave foránea primero -DROP TABLE IF EXISTS productos_logs; - -CREATE TABLE productos_logs ( - id INT PRIMARY KEY AUTO_INCREMENT, - producto_id INT NOT NULL, - tipo_cambio ENUM('precio', 'stock', 'activacion', 'desactivacion') NOT NULL, - valor_anterior VARCHAR(50), - valor_nuevo VARCHAR(50), - usuario_id INT, - usuario_tipo ENUM('admin', 'empleado') DEFAULT 'admin', - fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - ip_usuario VARCHAR(45) -); - --- Crear índices para mejor rendimiento -CREATE INDEX idx_producto_logs_fecha ON productos_logs(fecha_cambio); -CREATE INDEX idx_producto_logs_producto ON productos_logs(producto_id); -CREATE INDEX idx_producto_logs_tipo ON productos_logs(tipo_cambio); - --- Ahora intentar agregar la clave foránea (opcional, puede fallar si hay problemas de integridad) --- Si falla, la tabla funcionará igual pero sin restricción de integridad referencial -SET FOREIGN_KEY_CHECKS = 0; -ALTER TABLE productos_logs -ADD CONSTRAINT fk_productos_logs_producto -FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE; -SET FOREIGN_KEY_CHECKS = 1; - --- Verificar que la tabla se creó correctamente -DESCRIBE productos_logs; - --- Trigger para actualizar FECHA_ULTIMA_MODIFICACION en Productos automáticamente --- Primero eliminar el trigger si existe -DROP TRIGGER IF EXISTS actualizar_fecha_producto; - -DELIMITER // -CREATE TRIGGER actualizar_fecha_producto - BEFORE UPDATE ON Productos - FOR EACH ROW -BEGIN - SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP; -END// -DELIMITER ; - --- Verificar que el trigger se creó -SHOW TRIGGERS LIKE 'actualizar_fecha_producto'; - --- Insertar un registro de prueba para verificar funcionamiento -INSERT INTO productos_logs (producto_id, tipo_cambio, valor_anterior, valor_nuevo, usuario_id, usuario_tipo, ip_usuario) -VALUES (1, 'precio', '1000', '1200', 1, 'admin', '127.0.0.1'); - --- Mostrar el registro insertado -SELECT * FROM productos_logs ORDER BY id DESC LIMIT 1; diff --git a/files/dashboard_admin.php b/files/dashboard_admin.php deleted file mode 100644 index 392a334..0000000 --- a/files/dashboard_admin.php +++ /dev/null @@ -1,1615 +0,0 @@ -prepare("SELECT COUNT(*) as total FROM Productos"); - if (!$stmt) { - throw new Exception("Error preparando consulta de productos: " . $conexion->error); - } - $stmt->execute(); - $result = $stmt->get_result(); - if ($result) { - $total_productos = $result->fetch_assoc()['total']; - } - - $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Productos WHERE ACTIVO = 1"); - if ($stmt) { - $stmt->execute(); - $result = $stmt->get_result(); - if ($result) { - $productos_activos = $result->fetch_assoc()['total']; - } - } - - $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Empleados WHERE ACTIVO_EMPLEADO = 1"); - if ($stmt) { - $stmt->execute(); - $result = $stmt->get_result(); - if ($result) { - $empleados_activos = $result->fetch_assoc()['total']; - } - } - - // Contar clientes activos - $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Clientes WHERE ACTIVO_CLI = 1"); - if ($stmt) { - $stmt->execute(); - $result = $stmt->get_result(); - if ($result) { - $clientes_activos = $result->fetch_assoc()['total']; - } - } - - // Contar pedidos del día - $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Pedidos WHERE DATE(FECHA_INGRESO) = CURDATE()"); - if ($stmt) { - $stmt->execute(); - $result = $stmt->get_result(); - if ($result) { - $pedidos_hoy = $result->fetch_assoc()['total']; - } - } - -} catch (Exception $e) { - $error_message = "Error obteniendo estadísticas: " . $e->getMessage(); - error_log($error_message); -} -?> - - - - - - - - - - - - Dashboard Administrador - El Castillo del Pan - - - -
-
-
- Bienvenido, -
-

Panel de Control

-
- - -
- - - - - -
-
-
-
- -
-
-
Total Productos
-
-
-
- -
-
-
Productos Activos
-
-
-
- -
-
-
Empleados Activos
-
-
-
- -
-
-
Clientes Activos
-
-
-
- -
-
-
Pedidos Hoy
-
-
-
- -
-
-
-

Gestión de Productos

-
- -
- -
-
-

Gestión de Personal

-
-
- - Ver Empleados - - - - Ver Clientes - -
-
- -
-
-

Reportes y Estadísticas

-
- -
- -
-
-

Gestión de Ingredientes

-
-
- - - - Gestionar Proveedores - -
-
-
-
-
- - - - - - - - - - - - - - - - -
- - - - - diff --git a/files/dashboard_cliente.php b/files/dashboard_cliente.php deleted file mode 100644 index 40f11c5..0000000 --- a/files/dashboard_cliente.php +++ /dev/null @@ -1,317 +0,0 @@ -prepare("SELECT COUNT(*) as total FROM Pedidos WHERE ID_CLIENTE = ?"); - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $mis_pedidos_total = $stmt->get_result()->fetch_assoc()['total']; - - // Contar mis pedidos pendientes - $stmt = $conexion->prepare(" - SELECT COUNT(*) as total - FROM Pedidos - WHERE ID_CLIENTE = ? AND ID_ESTADO_PEDIDO IN (1, 2, 3) - "); - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $mis_pedidos_pendientes = $stmt->get_result()->fetch_assoc()['total']; - - // Obtener mis pedidos recientes - $stmt = $conexion->prepare(" - SELECT p.ID_PEDIDO, e.NOMBRE_EMPLEADO, ep.NOMBRE_ESTADO, - p.FECHA_INGRESO, p.FECHA_ENTREGA, p.TOTAL_PRODUCTO - FROM Pedidos p - INNER JOIN Empleados e ON p.ID_EMPLEADO = e.ID_EMPLEADO - INNER JOIN Estado_Pedidos ep ON p.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO - WHERE p.ID_CLIENTE = ? - ORDER BY p.FECHA_INGRESO DESC - LIMIT 5 - "); - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $mis_pedidos_recientes = $stmt->get_result(); - -} catch (Exception $e) { - error_log("Error obteniendo estadísticas del cliente: " . $e->getMessage()); -} -?> - - - - - - - - - - Dashboard Cliente - Panadería - - - - - -
-
- - - - -
- - - - -
-
-

Bienvenido, !

-

Gestiona tus pedidos y explora nuestros deliciosos productos

-
- - -
-
-
- -
-
-
-
Total Pedidos
-
-
-
-
- -
-
-
-
Pendientes
-
-
-
- - - num_rows > 0): ?> -
-
-

Pedidos Recientes

- - Ver Todos - -
-
- fetch_assoc()): ?> -
-
-
Pedido #
-

Por:

-

Fecha:

-

Total: $

-
-
- -
-
- -
-
- -
-
-

Mis Pedidos

-
-
-
- -

No tienes pedidos aún

- - Explorar Productos - -
-
-
- -
- - -
-
-
- - - - - - - \ No newline at end of file diff --git a/files/dashboard_empleado.php b/files/dashboard_empleado.php deleted file mode 100644 index 95343d6..0000000 --- a/files/dashboard_empleado.php +++ /dev/null @@ -1,1635 +0,0 @@ -prepare(" - SELECT COUNT(*) as total - FROM Pedidos - WHERE ID_EMPLEADO = ? AND DATE(FECHA_INGRESO) = CURDATE() - "); - if ($stmt) { - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $result = $stmt->get_result(); - if ($result) { - $mis_pedidos_hoy = $result->fetch_assoc()['total']; - } - } - - // Contar mis pedidos pendientes - $stmt = $conexion->prepare(" - SELECT COUNT(*) as total - FROM Pedidos - WHERE ID_EMPLEADO = ? AND ID_ESTADO_PEDIDO IN (1, 2) - "); - if ($stmt) { - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $result = $stmt->get_result(); - if ($result) { - $mis_pedidos_pendientes = $result->fetch_assoc()['total']; - } - } - - // Contar productos disponibles - usar tabla correcta - $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Productos WHERE ACTIVO = 1"); - if ($stmt) { - $stmt->execute(); - $result = $stmt->get_result(); - if ($result) { - $productos_disponibles = $result->fetch_assoc()['total']; - } - } - - // Contar total de pedidos asignados - $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Pedidos WHERE ID_EMPLEADO = ?"); - if ($stmt) { - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $result = $stmt->get_result(); - if ($result) { - $total_pedidos = $result->fetch_assoc()['total']; - } - } - - // Contar pedidos completados hoy - $stmt = $conexion->prepare(" - SELECT COUNT(*) as total - FROM Pedidos - WHERE ID_EMPLEADO = ? AND ID_ESTADO_PEDIDO = 4 AND DATE(FECHA_INGRESO) = CURDATE() - "); - if ($stmt) { - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $result = $stmt->get_result(); - if ($result) { - $pedidos_completados_hoy = $result->fetch_assoc()['total']; - } - } - -} catch (Exception $e) { - $error_message = "Error obteniendo estadísticas: " . $e->getMessage(); - error_log($error_message); -} -?> - - - - - - - - - - - - - - Dashboard Empleado - El Castillo del Pan - - - - -
-
-
- Bienvenido, -
-

Panel de Empleado

-
- - -
- - - - - -
-
-
-

Gestión de Pedidos

-
-
-

Consulta y gestiona los pedidos del sistema. Cambia el estado de los pedidos de Pendiente → En Preparación → Listo para Entrega → Entregado

- -
-
- -
-
-

Consulta de Inventario

-
-
-

Revisa el estado actual del inventario de productos

- -
-
-
-
-
- - - - - - - - - - - -
- - - - - diff --git a/files/eliminar_empleado_ajax.php b/files/eliminar_empleado_ajax.php deleted file mode 100644 index ab17b54..0000000 --- a/files/eliminar_empleado_ajax.php +++ /dev/null @@ -1,122 +0,0 @@ - false, 'mensaje' => 'Acceso no autorizado']); - exit(); -} - -// Headers de respuesta JSON -header('Content-Type: application/json'); - -// Verificar método POST -if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']); - exit(); -} - -// Incluir conexión a la base de datos -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception('Error de conexión a la base de datos'); - } - - // Obtener datos JSON del cuerpo de la petición - $raw_input = file_get_contents('php://input'); - $input = json_decode($raw_input, true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new Exception('Error al decodificar JSON: ' . json_last_error_msg()); - } - - if (!$input || !isset($input['id'])) { - throw new Exception('ID de empleado requerido'); - } - - // Validar ID del empleado - $empleado_id = filter_var($input['id'], FILTER_VALIDATE_INT); - - if ($empleado_id === false || $empleado_id <= 0) { - throw new Exception('ID de empleado inválido'); - } - - // Verificar que el empleado existe - $consulta_verificar = "SELECT ID_EMPLEADO, NOMBRE_EMPLEADO FROM Empleados WHERE ID_EMPLEADO = ?"; - $stmt_verificar = $conexion->prepare($consulta_verificar); - - if (!$stmt_verificar) { - throw new Exception('Error al preparar la consulta de verificación: ' . $conexion->error); - } - - $stmt_verificar->bind_param('i', $empleado_id); - $stmt_verificar->execute(); - $resultado_verificar = $stmt_verificar->get_result(); - - if ($resultado_verificar->num_rows === 0) { - throw new Exception('Empleado no encontrado'); - } - - $empleado = $resultado_verificar->fetch_assoc(); - $stmt_verificar->close(); - - // Verificar si el empleado es administrador (prevenir eliminación accidental) - $consulta_admin = "SELECT ID_ADMIN FROM Administradores WHERE EMAIL_ADMIN = (SELECT EMAIL_EMPLEADO FROM Empleados WHERE ID_EMPLEADO = ?)"; - $stmt_admin = $conexion->prepare($consulta_admin); - - if ($stmt_admin) { - $stmt_admin->bind_param('i', $empleado_id); - $stmt_admin->execute(); - $resultado_admin = $stmt_admin->get_result(); - - if ($resultado_admin->num_rows > 0) { - throw new Exception('No se puede eliminar un empleado que también es administrador'); - } - - $stmt_admin->close(); - } - - // Eliminar el empleado - $consulta_eliminar = "DELETE FROM Empleados WHERE ID_EMPLEADO = ?"; - $stmt_eliminar = $conexion->prepare($consulta_eliminar); - - if (!$stmt_eliminar) { - throw new Exception('Error al preparar la consulta de eliminación: ' . $conexion->error); - } - - $stmt_eliminar->bind_param('i', $empleado_id); - - if ($stmt_eliminar->execute()) { - if ($stmt_eliminar->affected_rows > 0) { - echo json_encode([ - 'success' => true, - 'mensaje' => 'Empleado eliminado exitosamente', - 'empleado' => [ - 'id' => $empleado_id, - 'nombre' => htmlspecialchars($empleado['NOMBRE_EMPLEADO']) - ] - ]); - } else { - throw new Exception('No se pudo eliminar el empleado'); - } - } else { - throw new Exception('Error al eliminar el empleado: ' . $stmt_eliminar->error); - } - - $stmt_eliminar->close(); - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage() - ]); -} - -// Cerrar conexión -if (isset($conexion)) { - $conexion->close(); -} -?> diff --git a/files/eliminar_forzado.php b/files/eliminar_forzado.php deleted file mode 100644 index 88d2e99..0000000 --- a/files/eliminar_forzado.php +++ /dev/null @@ -1,324 +0,0 @@ -prepare($consulta_producto); - $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT); - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - - if ($producto) { - $nombre_producto = $producto['NOMBRE_PRODUCTO']; - - // Verificar si tiene referencias (para informar al usuario) - $consulta_referencias = "SELECT COUNT(*) as total FROM detalle_pedidos WHERE ID_PRODUCTO = :id"; - $stmt_referencias = $pdo_conexion->prepare($consulta_referencias); - $stmt_referencias->bindParam(':id', $id_producto, PDO::PARAM_INT); - $stmt_referencias->execute(); - $referencias = $stmt_referencias->fetch(PDO::FETCH_ASSOC); - - // ELIMINACIÓN FORZADA - Ignora las restricciones de clave foránea - // Primero deshabilitar temporalmente las verificaciones de clave foránea - $pdo_conexion->exec("SET FOREIGN_KEY_CHECKS = 0"); - - // Eliminar el producto - $consulta_eliminar = "DELETE FROM Productos WHERE ID_PRODUCTO = :id"; - $stmt_eliminar = $pdo_conexion->prepare($consulta_eliminar); - $stmt_eliminar->bindParam(':id', $id_producto, PDO::PARAM_INT); - - if ($stmt_eliminar->execute()) { - // Reactivar las verificaciones de clave foránea - $pdo_conexion->exec("SET FOREIGN_KEY_CHECKS = 1"); - - $mensaje = "El producto '{$nombre_producto}' ha sido ELIMINADO PERMANENTEMENTE."; - $tipo_mensaje = "success"; - $referencias_afectadas = $referencias['total']; - } else { - // Reactivar las verificaciones de clave foránea en caso de error - $pdo_conexion->exec("SET FOREIGN_KEY_CHECKS = 1"); - $mensaje = "Error: No se pudo eliminar el producto."; - $tipo_mensaje = "error"; - $referencias_afectadas = 0; - } - } else { - $mensaje = "Error: El producto no existe."; - $tipo_mensaje = "error"; - $referencias_afectadas = 0; - } - - } catch (PDOException $e) { - // Asegurar que las verificaciones de clave foránea se reactiven en caso de error - try { - $pdo_conexion->exec("SET FOREIGN_KEY_CHECKS = 1"); - } catch (Exception $ex) { - // Ignorar errores al reactivar - } - - $mensaje = "Error en la base de datos: " . $e->getMessage(); - $tipo_mensaje = "error"; - $referencias_afectadas = 0; - } -} else { - $mensaje = "Error: ID de producto no válido."; - $tipo_mensaje = "error"; - $referencias_afectadas = 0; -} -?> - - - - - - - Eliminación Forzada - Panadería - - - -
- -
⚠️
-

Producto Eliminado Permanentemente

- -
- -
- - 0): ?> -
-

🚨 ADVERTENCIA CRÍTICA:

-

Este producto tenía referencia(s) en pedidos.

-

La eliminación forzada puede haber causado:

-
    -
  • ❌ Pedidos con productos "huérfanos" (referencias rotas)
  • -
  • ❌ Posibles errores en reportes de ventas
  • -
  • ❌ Inconsistencias en el historial de transacciones
  • -
  • ❌ Problemas en cálculos de inventario
  • -
-

Recomendación: Revise inmediatamente la tabla de pedidos para verificar la integridad de los datos.

-
- -
-

✅ Eliminación Segura:

-

El producto no tenía referencias en otras tablas, por lo que la eliminación no causó inconsistencias en la base de datos.

-
- - -
-

Detalles del Producto Eliminado:

-

Nombre:

-

ID:

-

Fecha de Eliminación:

-

Referencias Afectadas:

-
- - -
-

Error en la Eliminación

- -
- -
- - -
- -
- -
- ⏱️ Por favor, lee toda la información mostrada arriba antes de continuar. - El botón se activará en 5 segundos. -
- - 0): ?> -
-

🔧 Acciones Recomendadas:

-
    -
  • Revisar la tabla de pedidos para identificar referencias rotas
  • -
  • Contactar al administrador de la base de datos
  • -
  • Considerar implementar un proceso de limpieza de datos
  • -
  • En el futuro, use la opción "Desactivar" en lugar de eliminar
  • -
-
- -
- - - - diff --git a/files/eliminar_forzado_ajax.php b/files/eliminar_forzado_ajax.php deleted file mode 100644 index 8a11398..0000000 --- a/files/eliminar_forzado_ajax.php +++ /dev/null @@ -1,65 +0,0 @@ - false, - 'mensaje' => 'Método no permitido. Use POST.' - ]); - exit(); -} - -// Verificar si se recibió el ID del producto -if (isset($_POST['id']) && !empty($_POST['id'])) { - $id_producto = $_POST['id']; - - try { - // Primero, obtener los datos del producto - $consulta_producto = "SELECT NOMBRE_PRODUCTO FROM Productos WHERE ID_PRODUCTO = ?"; - $stmt_producto = $conexion->prepare($consulta_producto); - $stmt_producto->bind_param("i", $id_producto); - $stmt_producto->execute(); - $resultado = $stmt_producto->get_result(); - $producto = $resultado->fetch_assoc(); - - if ($producto) { - $nombre_producto = $producto['NOMBRE_PRODUCTO']; - - // Realizar eliminación forzada - $consulta_eliminar = "DELETE FROM Productos WHERE ID_PRODUCTO = ?"; - $stmt_eliminar = $conexion->prepare($consulta_eliminar); - $stmt_eliminar->bind_param("i", $id_producto); - - if ($stmt_eliminar->execute()) { - echo json_encode([ - 'success' => true, - 'mensaje' => "⚠️ ELIMINACIÓN FORZADA COMPLETADA

El producto '{$nombre_producto}' ha sido eliminado permanentemente del sistema.

🚨 Nota: Si este producto tenía referencias en pedidos, esas referencias han sido rotas y pueden causar errores en el sistema." - ]); - } else { - echo json_encode([ - 'success' => false, - 'mensaje' => "Error: No se pudo eliminar el producto." - ]); - } - } else { - echo json_encode([ - 'success' => false, - 'mensaje' => "Error: El producto no existe." - ]); - } - - } catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => "Error en la base de datos: " . $e->getMessage() - ]); - } -} else { - echo json_encode([ - 'success' => false, - 'mensaje' => "Error: Parámetros no válidos." - ]); -} -?> diff --git a/files/eliminar_ingrediente_ajax.php b/files/eliminar_ingrediente_ajax.php deleted file mode 100644 index 99ccb50..0000000 --- a/files/eliminar_ingrediente_ajax.php +++ /dev/null @@ -1,61 +0,0 @@ -prepare("SELECT NOMBRE_INGREDIENTE FROM Ingredientes WHERE ID_INGREDIENTE = ?"); - $stmt->bind_param("i", $id_ingrediente); - $stmt->execute(); - $resultado = $stmt->get_result(); - - if ($resultado->num_rows === 0) { - throw new Exception('El ingrediente no existe'); - } - - $ingrediente = $resultado->fetch_assoc(); - - // Eliminar el ingrediente - $stmt = $conexion->prepare("DELETE FROM Ingredientes WHERE ID_INGREDIENTE = ?"); - $stmt->bind_param("i", $id_ingrediente); - - if ($stmt->execute()) { - if ($stmt->affected_rows > 0) { - echo json_encode([ - 'success' => true, - 'mensaje' => 'Ingrediente "' . $ingrediente['NOMBRE_INGREDIENTE'] . '" eliminado exitosamente' - ]); - } else { - throw new Exception('No se pudo eliminar el ingrediente'); - } - } else { - throw new Exception('Error al eliminar el ingrediente: ' . $stmt->error); - } - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage() - ]); -} - -$conexion->close(); -?> diff --git a/files/eliminar_producto_ajax.php b/files/eliminar_producto_ajax.php deleted file mode 100644 index fc2c63b..0000000 --- a/files/eliminar_producto_ajax.php +++ /dev/null @@ -1,87 +0,0 @@ - false, - 'mensaje' => 'Método no permitido. Use POST.' - ]); - exit(); -} - -// Verificar si se recibió el ID del producto -if (isset($_POST['id']) && !empty($_POST['id'])) { - $id_producto = $_POST['id']; - - try { - // Primero, obtener los datos del producto - $consulta_producto = "SELECT NOMBRE_PRODUCTO FROM Productos WHERE ID_PRODUCTO = ?"; - $stmt_producto = $conexion->prepare($consulta_producto); - $stmt_producto->bind_param("i", $id_producto); - $stmt_producto->execute(); - $resultado = $stmt_producto->get_result(); - $producto = $resultado->fetch_assoc(); - - if ($producto) { - $nombre_producto = $producto['NOMBRE_PRODUCTO']; - - // Verificar si el producto tiene referencias en otras tablas - $consulta_referencias = "SELECT COUNT(*) as total FROM Detalle_Pedidos WHERE ID_PRODUCTO = ?"; - $stmt_referencias = $conexion->prepare($consulta_referencias); - $stmt_referencias->bind_param("i", $id_producto); - $stmt_referencias->execute(); - $resultado_ref = $stmt_referencias->get_result(); - $referencias = $resultado_ref->fetch_assoc(); - - if ($referencias['total'] > 0) { - // El producto tiene referencias, no se puede eliminar - echo json_encode([ - 'success' => false, - 'hasReferences' => true, - 'mensaje' => "No se puede eliminar el producto '{$nombre_producto}' porque está asociado a {$referencias['total']} pedido(s).

🔄 Opciones:
• Desactivar el producto en lugar de eliminarlo
• Eliminar o modificar los pedidos que lo contienen
• Realizar eliminación forzada (⚠️ Riesgo de datos corruptos)" - ]); - } else { - // El producto no tiene referencias, se puede eliminar - $consulta_eliminar = "DELETE FROM Productos WHERE ID_PRODUCTO = ?"; - $stmt_eliminar = $conexion->prepare($consulta_eliminar); - $stmt_eliminar->bind_param("i", $id_producto); - - if ($stmt_eliminar->execute()) { - echo json_encode([ - 'success' => true, - 'hasReferences' => false, - 'mensaje' => "El producto '{$nombre_producto}' ha sido eliminado exitosamente." - ]); - } else { - echo json_encode([ - 'success' => false, - 'hasReferences' => false, - 'mensaje' => "Error: No se pudo eliminar el producto." - ]); - } - } - } else { - echo json_encode([ - 'success' => false, - 'hasReferences' => false, - 'mensaje' => "Error: El producto no existe." - ]); - } - - } catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'hasReferences' => false, - 'mensaje' => "Error en la base de datos: " . $e->getMessage() - ]); - } -} else { - echo json_encode([ - 'success' => false, - 'hasReferences' => false, - 'mensaje' => "Error: Parámetros no válidos." - ]); -} -?> diff --git a/files/employee_login_test.php b/files/employee_login_test.php deleted file mode 100644 index 5d66154..0000000 --- a/files/employee_login_test.php +++ /dev/null @@ -1,110 +0,0 @@ -Employee Login Debug"; - -// Clear any existing session -session_destroy(); -session_start(); - -echo "

Step 1: Session cleared and restarted

"; -echo "

Session ID: " . session_id() . "

"; - -// Simulate the login process for an employee -require_once 'conexion.php'; - -$test_employee = 'admin'; // or whatever employee username exists -$test_password = 'admin123'; // or whatever password - -echo "

Step 2: Testing Employee Login

"; -echo "

Testing user: $test_employee

"; - -try { - $consulta = "SELECT ID_EMPLEADO, NOMBRE_EMPLEADO, CONTRASEÑA_EMPLEADO, SALT_EMPLEADO, ACTIVO_EMPLEADO, EMAIL_EMPLEADO - FROM Empleados - WHERE (NOMBRE_EMPLEADO = :usuario OR EMAIL_EMPLEADO = :usuario) AND ACTIVO_EMPLEADO = 1"; - - $stmt = $pdo_conexion->prepare($consulta); - $stmt->bindParam(':usuario', $test_employee, PDO::PARAM_STR); - $stmt->execute(); - - $user_data = $stmt->fetch(PDO::FETCH_ASSOC); - - if ($user_data) { - echo "

✓ Employee found: " . $user_data['NOMBRE_EMPLEADO'] . "

"; - - // Test password - $password_hash = $user_data['CONTRASEÑA_EMPLEADO']; - $salt = $user_data['SALT_EMPLEADO']; - - $password_valid = false; - - if (!empty($salt) && !empty($password_hash)) { - $hash_to_check = hash('sha256', $test_password . $salt); - if ($hash_to_check === $password_hash) { - $password_valid = true; - } - } elseif (!empty($password_hash)) { - if ($test_password === $password_hash) { - $password_valid = true; - } - } - - if ($password_valid) { - echo "

✓ Password valid

"; - - // Set session like the real login process - $_SESSION['usuario_logueado'] = true; - $_SESSION['usuario_tipo'] = 'empleado'; - $_SESSION['usuario_id'] = $user_data['ID_EMPLEADO']; - $_SESSION['usuario_nombre'] = $user_data['NOMBRE_EMPLEADO']; - $_SESSION['user_name'] = $user_data['NOMBRE_EMPLEADO']; - $_SESSION['role'] = 'empleado'; - - echo "

✓ Session set

"; - echo "
Session data:\n" . print_r($_SESSION, true) . "
"; - - echo "

Step 3: Testing AJAX Endpoint

"; - - // Test if this session works with the AJAX endpoint - echo '
'; - echo ''; - - } else { - echo "

✗ Password invalid

"; - } - - } else { - echo "

✗ Employee not found

"; - } - -} catch (Exception $e) { - echo "

✗ Error: " . $e->getMessage() . "

"; -} - -echo "
"; -echo "

Navigation

"; -echo 'Go to Employee Dashboard
'; -echo 'Go to Login
'; -echo 'Session Debug
'; -?> diff --git a/files/gestionar_producto.php b/files/gestionar_producto.php deleted file mode 100644 index ac50aac..0000000 --- a/files/gestionar_producto.php +++ /dev/null @@ -1,498 +0,0 @@ -pdo = $pdo; - } - - /** - * Descuenta stock de un producto - */ - public function descontarStock($id_producto, $cantidad) { - try { - $this->pdo->beginTransaction(); - - // Verificar stock actual del producto - $stmt = $this->pdo->prepare(" - SELECT STOCK_ACTUAL, PRODUCTO_STOCK_MIN, NOMBRE_PRODUCTO, ACTIVO - FROM Productos - WHERE ID_PRODUCTO = ? AND ACTIVO = 1 - FOR UPDATE - "); - $stmt->execute([$id_producto]); - $producto = $stmt->fetch(PDO::FETCH_ASSOC); - - if (!$producto) { - throw new Exception("Producto no encontrado o inactivo"); - } - - // Verificar si hay suficiente stock - if ($producto['STOCK_ACTUAL'] < $cantidad) { - throw new Exception("Stock insuficiente. Stock disponible: " . $producto['STOCK_ACTUAL']); - } - - // Actualizar stock - $nuevo_stock = $producto['STOCK_ACTUAL'] - $cantidad; - $stmt = $this->pdo->prepare(" - UPDATE Productos - SET STOCK_ACTUAL = ? - WHERE ID_PRODUCTO = ? - "); - $stmt->execute([$nuevo_stock, $id_producto]); - - // Registrar movimiento en historial (opcional) - $this->registrarMovimiento($id_producto, 'SALIDA', $cantidad, $producto['STOCK_ACTUAL'], $nuevo_stock, 'Venta/Pedido'); - - $this->pdo->commit(); - - return [ - 'success' => true, - 'message' => 'Stock actualizado correctamente', - 'producto' => $producto['NOMBRE_PRODUCTO'], - 'stock_anterior' => $producto['STOCK_ACTUAL'], - 'stock_actual' => $nuevo_stock, - 'alerta_stock_minimo' => ($nuevo_stock <= $producto['PRODUCTO_STOCK_MIN']) - ]; - - } catch (Exception $e) { - $this->pdo->rollBack(); - return [ - 'success' => false, - 'message' => $e->getMessage() - ]; - } - } - - /** - * Aumenta stock de un producto - */ - public function aumentarStock($id_producto, $cantidad, $motivo = 'Reposición') { - try { - $this->pdo->beginTransaction(); - - $stmt = $this->pdo->prepare(" - SELECT STOCK_ACTUAL, NOMBRE_PRODUCTO, ACTIVO - FROM Productos - WHERE ID_PRODUCTO = ? - FOR UPDATE - "); - $stmt->execute([$id_producto]); - $producto = $stmt->fetch(PDO::FETCH_ASSOC); - - if (!$producto) { - throw new Exception("Producto no encontrado"); - } - - $nuevo_stock = $producto['STOCK_ACTUAL'] + $cantidad; - $stmt = $this->pdo->prepare(" - UPDATE Productos - SET STOCK_ACTUAL = ? - WHERE ID_PRODUCTO = ? - "); - $stmt->execute([$nuevo_stock, $id_producto]); - - $this->registrarMovimiento($id_producto, 'ENTRADA', $cantidad, $producto['STOCK_ACTUAL'], $nuevo_stock, $motivo); - - $this->pdo->commit(); - - return [ - 'success' => true, - 'message' => 'Stock aumentado correctamente', - 'producto' => $producto['NOMBRE_PRODUCTO'], - 'stock_anterior' => $producto['STOCK_ACTUAL'], - 'stock_actual' => $nuevo_stock - ]; - - } catch (Exception $e) { - $this->pdo->rollBack(); - return [ - 'success' => false, - 'message' => $e->getMessage() - ]; - } - } - - /** - * Registra movimiento de stock - */ - private function registrarMovimiento($id_producto, $tipo, $cantidad, $stock_anterior, $stock_nuevo, $motivo) { - try { - $stmt = $this->pdo->prepare(" - INSERT INTO MovimientosStock (ID_PRODUCTO, TIPO_MOVIMIENTO, CANTIDAD, STOCK_ANTERIOR, STOCK_NUEVO, MOTIVO) - VALUES (?, ?, ?, ?, ?, ?) - "); - $stmt->execute([$id_producto, $tipo, $cantidad, $stock_anterior, $stock_nuevo, $motivo]); - } catch (Exception $e) { - // Si no existe la tabla de movimientos, no hacer nada - } - } - - /** - * Obtiene información del stock - */ - public function obtenerInfoStock($id_producto) { - $stmt = $this->pdo->prepare(" - SELECT ID_PRODUCTO, NOMBRE_PRODUCTO, STOCK_ACTUAL, PRODUCTO_STOCK_MIN, - CASE - WHEN STOCK_ACTUAL = 0 THEN 'SIN STOCK' - WHEN STOCK_ACTUAL <= PRODUCTO_STOCK_MIN THEN 'CRÍTICO' - WHEN STOCK_ACTUAL <= (PRODUCTO_STOCK_MIN * 2) THEN 'BAJO' - ELSE 'NORMAL' - END as ESTADO_STOCK - FROM Productos - WHERE ID_PRODUCTO = ? - "); - $stmt->execute([$id_producto]); - return $stmt->fetch(PDO::FETCH_ASSOC); - } -} - -// Inicializar el gestor de stock -$stockManager = new StockManager($pdo_conexion); - -// Verificar si se recibió el ID del producto -if (isset($_GET['id']) && !empty($_GET['id'])) { - $id_producto = $_GET['id']; - - try { - // Obtener información del producto - $consulta_producto = "SELECT * FROM Productos WHERE ID_PRODUCTO = :id"; - $stmt_producto = $pdo_conexion->prepare($consulta_producto); - $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT); - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - - if ($producto) { - // Verificar referencias en detalle_pedidos - $consulta_referencias = "SELECT COUNT(*) as total FROM detalle_pedidos WHERE ID_PRODUCTO = :id"; - $stmt_referencias = $pdo_conexion->prepare($consulta_referencias); - $stmt_referencias->bindParam(':id', $id_producto, PDO::PARAM_INT); - $stmt_referencias->execute(); - $referencias = $stmt_referencias->fetch(PDO::FETCH_ASSOC); - - // Obtener información del stock - $info_stock = $stockManager->obtenerInfoStock($id_producto); - - // Procesar acciones - $mensaje = ""; - $tipo_mensaje = ""; - - if (isset($_POST['accion'])) { - switch ($_POST['accion']) { - case 'descontar_stock': - if (isset($_POST['cantidad']) && is_numeric($_POST['cantidad']) && $_POST['cantidad'] > 0) { - $cantidad = (int)$_POST['cantidad']; - $resultado = $stockManager->descontarStock($id_producto, $cantidad); - - if ($resultado['success']) { - $mensaje = "Stock descontado exitosamente. "; - $mensaje .= "Producto: " . $resultado['producto'] . ". "; - $mensaje .= "Stock anterior: " . $resultado['stock_anterior'] . ". "; - $mensaje .= "Stock actual: " . $resultado['stock_actual'] . "."; - - if ($resultado['alerta_stock_minimo']) { - $mensaje .= " ⚠️ ALERTA: Stock por debajo del mínimo!"; - } - - $tipo_mensaje = "success"; - } else { - $mensaje = "Error al descontar stock: " . $resultado['message']; - $tipo_mensaje = "error"; - } - - // Refrescar información del producto - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - $info_stock = $stockManager->obtenerInfoStock($id_producto); - } else { - $mensaje = "Cantidad inválida para descontar."; - $tipo_mensaje = "error"; - } - break; - - case 'aumentar_stock': - if (isset($_POST['cantidad']) && is_numeric($_POST['cantidad']) && $_POST['cantidad'] > 0) { - $cantidad = (int)$_POST['cantidad']; - $motivo = isset($_POST['motivo']) ? $_POST['motivo'] : 'Reposición manual'; - $resultado = $stockManager->aumentarStock($id_producto, $cantidad, $motivo); - - if ($resultado['success']) { - $mensaje = "Stock aumentado exitosamente. "; - $mensaje .= "Producto: " . $resultado['producto'] . ". "; - $mensaje .= "Stock anterior: " . $resultado['stock_anterior'] . ". "; - $mensaje .= "Stock actual: " . $resultado['stock_actual'] . "."; - $tipo_mensaje = "success"; - } else { - $mensaje = "Error al aumentar stock: " . $resultado['message']; - $tipo_mensaje = "error"; - } - - // Refrescar información del producto - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - $info_stock = $stockManager->obtenerInfoStock($id_producto); - } else { - $mensaje = "Cantidad inválida para aumentar."; - $tipo_mensaje = "error"; - } - break; - - case 'reducir_stock': - $consulta_update = "UPDATE Productos SET PRODUCTO_STOCK_MIN = 0 WHERE ID_PRODUCTO = :id"; - $stmt_update = $pdo_conexion->prepare($consulta_update); - $stmt_update->bindParam(':id', $id_producto, PDO::PARAM_INT); - - if ($stmt_update->execute()) { - $mensaje = "Stock mínimo del producto reducido a 0. El producto seguirá visible pero marcado como sin stock."; - $tipo_mensaje = "success"; - // Refrescar datos del producto - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - $info_stock = $stockManager->obtenerInfoStock($id_producto); - } else { - $mensaje = "Error al actualizar el producto."; - $tipo_mensaje = "error"; - } - break; - - case 'desactivar': - $consulta_update = "UPDATE Productos SET ACTIVO = 0 WHERE ID_PRODUCTO = :id"; - $stmt_update = $pdo_conexion->prepare($consulta_update); - $stmt_update->bindParam(':id', $id_producto, PDO::PARAM_INT); - - if ($stmt_update->execute()) { - $mensaje = "Producto desactivado exitosamente. Ya no aparecerá en búsquedas pero conserva todas sus referencias."; - $tipo_mensaje = "success"; - // Refrescar datos del producto - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - } else { - $mensaje = "Error al desactivar el producto."; - $tipo_mensaje = "error"; - } - break; - - case 'activar': - $consulta_update = "UPDATE Productos SET ACTIVO = 1 WHERE ID_PRODUCTO = :id"; - $stmt_update = $pdo_conexion->prepare($consulta_update); - $stmt_update->bindParam(':id', $id_producto, PDO::PARAM_INT); - - if ($stmt_update->execute()) { - $mensaje = "Producto activado exitosamente. Ahora está disponible para nuevos pedidos."; - $tipo_mensaje = "success"; - // Refrescar datos del producto - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - } else { - $mensaje = "Error al activar el producto."; - $tipo_mensaje = "error"; - } - break; - } - } - } else { - header("Location: productostabla.php"); - exit(); - } - - } catch (PDOException $e) { - $mensaje = "Error en la base de datos: " . $e->getMessage(); - $tipo_mensaje = "error"; - } -} else { - header("Location: productostabla.php"); - exit(); -} -?> - - - - - - Gestionar Producto - Panadería - - -
-

Gestión de Producto

- - -
- -
- - -
-

Información del Producto

-

ID:

-

Nombre:

-

Precio: $

-

Stock Mínimo:

-

Marca/Tipo:

-

Fecha de Vencimiento:

-

Estado: - - ✓ Activo - - ✗ Inactivo - -

-
- - - -
-

📦 Información de Stock

-

Stock Actual: unidades

-

Stock Mínimo: unidades

-

Estado: - - - -

- - -

⚠️ ¡Atención! Stock crítico - Considerar reabastecer

- -

⚠️ Stock bajo - Planificar reabastecimiento

- -
- - - -
-
-

📉 Descontar Stock

-
- -
- - -
- -
-
- -
-

📈 Aumentar Stock

-
- -
- - -
-
- - -
- -
-
-
- - 0): ?> -
-

⚠️ Producto con Referencias

-

Este producto está siendo utilizado en pedido(s). No se puede eliminar directamente.

-
- -

Opciones Disponibles

-
-
- -

❌ Desactivar Producto

-

Oculta el producto de búsquedas manteniendo todas las referencias intactas.

-
- - -
- -

✅ Activar Producto

-

Hace el producto visible y disponible para nuevos pedidos.

-
- - -
- -
- -
-

🔄 Reducir Stock Mínimo a 0

-

Marca el producto como sin stock mínimo manteniendo el historial de pedidos.

-
- - -
-
- -
-

📋 Ver Pedidos Relacionados

-

Consulta qué pedidos contienen este producto.

- - Ver Pedidos - -
-
- -
-

✅ Producto sin Referencias

-

Este producto no está siendo utilizado en ningún pedido. Se puede eliminar de forma segura.

-
- - -
-
- - - - - -
-

⚠️ Zona Peligrosa

-

- La eliminación forzada ignora todas las restricciones y puede causar inconsistencias en la base de datos. -

- - 🗑️ Forzar Eliminación - -
-
- - \ No newline at end of file diff --git a/files/gestionar_producto_modal.php b/files/gestionar_producto_modal.php deleted file mode 100644 index 9b1f933..0000000 --- a/files/gestionar_producto_modal.php +++ /dev/null @@ -1,555 +0,0 @@ -prepare($consulta_producto); - $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT); - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - - if (!$producto) { - header("Location: productostabla.php"); - exit(); - } - - // Verificar referencias en detalle_pedidos - $consulta_referencias = "SELECT COUNT(*) as total FROM detalle_pedidos WHERE ID_PRODUCTO = :id"; - $stmt_referencias = $pdo_conexion->prepare($consulta_referencias); - $stmt_referencias->bindParam(':id', $id_producto, PDO::PARAM_INT); - $stmt_referencias->execute(); - $referencias = $stmt_referencias->fetch(PDO::FETCH_ASSOC); - - } catch (PDOException $e) { - header("Location: productostabla.php"); - exit(); - } -} else { - header("Location: productostabla.php"); - exit(); -} -?> - - - - - - - Gestionar Producto - Panadería - - - - - -
-
-

-
ID:
-
- -
-
-

- info - Información General -

-
- Precio: - $ -
-
- Stock: - unidades -
-
- Categoría: - -
-
- Estado: - - - - check_circle - Activo - - - - cancel - Inactivo - - - -
-
- -
-

- schedule - Fechas y Vencimiento -

-
- Fecha de Vencimiento: - -
-
- Referencias en Pedidos: - - 0): ?> - - pedido(s) - - - - Sin referencias - - - -
-
-
- - 0): ?> -
-

- warning - Producto con Referencias -

-

Este producto está siendo utilizado en pedido(s). No se puede eliminar directamente.

-
- - -
- -
-

- delete - Eliminar Producto -

-

Elimina permanentemente el producto. Esta acción no se puede deshacer.

- -
- - -
-

- visibility - Ver Historial -

-

Consulta el historial de pedidos y movimientos de este producto.

- - visibility - Ver Historial - -
-
- - -
- - - - - - - diff --git a/files/img/992710.png b/files/img/992710.png deleted file mode 100644 index 1dade7e..0000000 Binary files a/files/img/992710.png and /dev/null differ diff --git a/files/img/Local.png b/files/img/Local.png deleted file mode 100644 index c1ed2cf..0000000 Binary files a/files/img/Local.png and /dev/null differ diff --git a/files/img/PAN-INTEGRAL.jpg b/files/img/PAN-INTEGRAL.jpg deleted file mode 100644 index 879660a..0000000 Binary files a/files/img/PAN-INTEGRAL.jpg and /dev/null differ diff --git a/files/img/Pan1.jpg b/files/img/Pan1.jpg deleted file mode 100644 index dd4bfca..0000000 Binary files a/files/img/Pan1.jpg and /dev/null differ diff --git a/files/img/arequipe-alpina.png b/files/img/arequipe-alpina.png deleted file mode 100644 index 508908f..0000000 Binary files a/files/img/arequipe-alpina.png and /dev/null differ diff --git a/files/img/baguette.jpg b/files/img/baguette.jpg deleted file mode 100644 index 5121398..0000000 Binary files a/files/img/baguette.jpg and /dev/null differ diff --git a/files/img/brazoreina1.jpg b/files/img/brazoreina1.jpg deleted file mode 100644 index 5183e0a..0000000 Binary files a/files/img/brazoreina1.jpg and /dev/null differ diff --git a/files/img/browni-con-nueces.jpg b/files/img/browni-con-nueces.jpg deleted file mode 100644 index 2d6b6f2..0000000 Binary files a/files/img/browni-con-nueces.jpg and /dev/null differ diff --git a/files/img/brownie1.jpg b/files/img/brownie1.jpg deleted file mode 100644 index 0ecee86..0000000 Binary files a/files/img/brownie1.jpg and /dev/null differ diff --git a/files/img/categoria/flan de caramelo.jpeg b/files/img/categoria/flan de caramelo.jpeg deleted file mode 100644 index 39d4910..0000000 Binary files a/files/img/categoria/flan de caramelo.jpeg and /dev/null differ diff --git a/files/img/categoria/galleta avena.jpeg b/files/img/categoria/galleta avena.jpeg deleted file mode 100644 index b5d648b..0000000 Binary files a/files/img/categoria/galleta avena.jpeg and /dev/null differ diff --git a/files/img/categoria/galleta chocolate.jpeg b/files/img/categoria/galleta chocolate.jpeg deleted file mode 100644 index 05fce90..0000000 Binary files a/files/img/categoria/galleta chocolate.jpeg and /dev/null differ diff --git a/files/img/categoria/galleta integral.jpeg b/files/img/categoria/galleta integral.jpeg deleted file mode 100644 index 2f71315..0000000 Binary files a/files/img/categoria/galleta integral.jpeg and /dev/null differ diff --git a/files/img/categoria/galleta mantequilla.jpeg b/files/img/categoria/galleta mantequilla.jpeg deleted file mode 100644 index 8d1d193..0000000 Binary files a/files/img/categoria/galleta mantequilla.jpeg and /dev/null differ diff --git a/files/img/categoria/galleta vainilla.jpeg b/files/img/categoria/galleta vainilla.jpeg deleted file mode 100644 index f2d6d98..0000000 Binary files a/files/img/categoria/galleta vainilla.jpeg and /dev/null differ diff --git a/files/img/categoria/hojaldre bocadillo.jpeg b/files/img/categoria/hojaldre bocadillo.jpeg deleted file mode 100644 index c9db65d..0000000 Binary files a/files/img/categoria/hojaldre bocadillo.jpeg and /dev/null differ diff --git a/files/img/categoria/hojaldre pollo.jpeg b/files/img/categoria/hojaldre pollo.jpeg deleted file mode 100644 index 3182845..0000000 Binary files a/files/img/categoria/hojaldre pollo.jpeg and /dev/null differ diff --git a/files/img/categoria/hojaldre queso.jpeg b/files/img/categoria/hojaldre queso.jpeg deleted file mode 100644 index 7b42ddc..0000000 Binary files a/files/img/categoria/hojaldre queso.jpeg and /dev/null differ diff --git a/files/img/categoria/merengon.jpeg b/files/img/categoria/merengon.jpeg deleted file mode 100644 index 59b10b6..0000000 Binary files a/files/img/categoria/merengon.jpeg and /dev/null differ diff --git a/files/img/categoria/milhoja.jpeg b/files/img/categoria/milhoja.jpeg deleted file mode 100644 index 34ff6ef..0000000 Binary files a/files/img/categoria/milhoja.jpeg and /dev/null differ diff --git a/files/img/categoria/napoleon.jpeg b/files/img/categoria/napoleon.jpeg deleted file mode 100644 index af1f734..0000000 Binary files a/files/img/categoria/napoleon.jpeg and /dev/null differ diff --git "a/files/img/categoria/pan alin\314\203ado.jpeg" "b/files/img/categoria/pan alin\314\203ado.jpeg" deleted file mode 100644 index c997f05..0000000 Binary files "a/files/img/categoria/pan alin\314\203ado.jpeg" and /dev/null differ diff --git a/files/img/categoria/pan blandito .jpeg b/files/img/categoria/pan blandito .jpeg deleted file mode 100644 index f00869c..0000000 Binary files a/files/img/categoria/pan blandito .jpeg and /dev/null differ diff --git a/files/img/categoria/pan campesino.jpeg b/files/img/categoria/pan campesino.jpeg deleted file mode 100644 index fb1454c..0000000 Binary files a/files/img/categoria/pan campesino.jpeg and /dev/null differ diff --git a/files/img/categoria/pan coco.jpeg b/files/img/categoria/pan coco.jpeg deleted file mode 100644 index 941fa72..0000000 Binary files a/files/img/categoria/pan coco.jpeg and /dev/null differ diff --git a/files/img/categoria/pan frances.jpeg b/files/img/categoria/pan frances.jpeg deleted file mode 100644 index 3c7ec0f..0000000 Binary files a/files/img/categoria/pan frances.jpeg and /dev/null differ diff --git a/files/img/categoria/pan maiz.jpeg b/files/img/categoria/pan maiz.jpeg deleted file mode 100644 index 2c63dae..0000000 Binary files a/files/img/categoria/pan maiz.jpeg and /dev/null differ diff --git a/files/img/categoria/pan queso.jpeg b/files/img/categoria/pan queso.jpeg deleted file mode 100644 index 7f04f23..0000000 Binary files a/files/img/categoria/pan queso.jpeg and /dev/null differ diff --git a/files/img/categoria/pan rollo.jpeg b/files/img/categoria/pan rollo.jpeg deleted file mode 100644 index 4bb0829..0000000 Binary files a/files/img/categoria/pan rollo.jpeg and /dev/null differ diff --git a/files/img/categoria/pandebono.jpeg b/files/img/categoria/pandebono.jpeg deleted file mode 100644 index 49e7df1..0000000 Binary files a/files/img/categoria/pandebono.jpeg and /dev/null differ diff --git a/files/img/categoria/pastel carne.jpeg b/files/img/categoria/pastel carne.jpeg deleted file mode 100644 index 8f14805..0000000 Binary files a/files/img/categoria/pastel carne.jpeg and /dev/null differ diff --git a/files/img/categoria/tamal de pollo .jpeg b/files/img/categoria/tamal de pollo .jpeg deleted file mode 100644 index 5cf6a5b..0000000 Binary files a/files/img/categoria/tamal de pollo .jpeg and /dev/null differ diff --git a/files/img/categoria/tamal santandereano .jpeg b/files/img/categoria/tamal santandereano .jpeg deleted file mode 100644 index de8911d..0000000 Binary files a/files/img/categoria/tamal santandereano .jpeg and /dev/null differ diff --git a/files/img/categoria/tamal tolimense.jpeg b/files/img/categoria/tamal tolimense.jpeg deleted file mode 100644 index 112b376..0000000 Binary files a/files/img/categoria/tamal tolimense.jpeg and /dev/null differ diff --git a/files/img/categoria/torta chocolate.jpeg b/files/img/categoria/torta chocolate.jpeg deleted file mode 100644 index 01800c2..0000000 Binary files a/files/img/categoria/torta chocolate.jpeg and /dev/null differ diff --git a/files/img/categoria/torta tres leches.jpeg b/files/img/categoria/torta tres leches.jpeg deleted file mode 100644 index 6406f12..0000000 Binary files a/files/img/categoria/torta tres leches.jpeg and /dev/null differ diff --git a/files/img/categoria/torta zanahoria.jpeg b/files/img/categoria/torta zanahoria.jpeg deleted file mode 100644 index 0e71597..0000000 Binary files a/files/img/categoria/torta zanahoria.jpeg and /dev/null differ diff --git a/files/img/categoria/tres leches vaso .jpeg b/files/img/categoria/tres leches vaso .jpeg deleted file mode 100644 index ff39005..0000000 Binary files a/files/img/categoria/tres leches vaso .jpeg and /dev/null differ diff --git a/files/img/cheesecake-frutos-rojos.jpg b/files/img/cheesecake-frutos-rojos.jpg deleted file mode 100644 index 36ebc57..0000000 Binary files a/files/img/cheesecake-frutos-rojos.jpg and /dev/null differ diff --git a/files/img/chicharrona.png b/files/img/chicharrona.png deleted file mode 100644 index 23b7561..0000000 Binary files a/files/img/chicharrona.png and /dev/null differ diff --git a/files/img/croissant1.jpg b/files/img/croissant1.jpg deleted file mode 100644 index 0f3c958..0000000 Binary files a/files/img/croissant1.jpg and /dev/null differ diff --git a/files/img/croissants.jpg b/files/img/croissants.jpg deleted file mode 100644 index 2ffc6b8..0000000 Binary files a/files/img/croissants.jpg and /dev/null differ diff --git a/files/img/empanadas.png b/files/img/empanadas.png deleted file mode 100644 index 268d546..0000000 Binary files a/files/img/empanadas.png and /dev/null differ diff --git a/files/img/galleta1.jpg b/files/img/galleta1.jpg deleted file mode 100644 index dba5b74..0000000 Binary files a/files/img/galleta1.jpg and /dev/null differ diff --git a/files/img/galletas-de-avena-con-pasas-y-nuez.jpg b/files/img/galletas-de-avena-con-pasas-y-nuez.jpg deleted file mode 100644 index 89cb9c3..0000000 Binary files a/files/img/galletas-de-avena-con-pasas-y-nuez.jpg and /dev/null differ diff --git a/files/img/galletasmantequilla.jpg b/files/img/galletasmantequilla.jpg deleted file mode 100644 index 338de8e..0000000 Binary files a/files/img/galletasmantequilla.jpg and /dev/null differ diff --git a/files/img/galletatresojos.png b/files/img/galletatresojos.png deleted file mode 100644 index d616ab7..0000000 Binary files a/files/img/galletatresojos.png and /dev/null differ diff --git a/files/img/hojaldre1.jpg b/files/img/hojaldre1.jpg deleted file mode 100644 index 288ac40..0000000 Binary files a/files/img/hojaldre1.jpg and /dev/null differ diff --git a/files/img/iconoboton1.jpg b/files/img/iconoboton1.jpg deleted file mode 100644 index a04dc73..0000000 Binary files a/files/img/iconoboton1.jpg and /dev/null differ diff --git a/files/img/jugo.jpg b/files/img/jugo.jpg deleted file mode 100644 index 4b790b2..0000000 Binary files a/files/img/jugo.jpg and /dev/null differ diff --git a/files/img/kumiss.1.png b/files/img/kumiss.1.png deleted file mode 100644 index 64c516b..0000000 Binary files a/files/img/kumiss.1.png and /dev/null differ diff --git a/files/img/logo proyecto.jpeg b/files/img/logo proyecto.jpeg deleted file mode 100644 index 0026376..0000000 Binary files a/files/img/logo proyecto.jpeg and /dev/null differ diff --git a/files/img/logoprincipal.jpg b/files/img/logoprincipal.jpg deleted file mode 100644 index 0026376..0000000 Binary files a/files/img/logoprincipal.jpg and /dev/null differ diff --git a/files/img/miloha_de_arequipe.jpg b/files/img/miloha_de_arequipe.jpg deleted file mode 100644 index 2b5bb4e..0000000 Binary files a/files/img/miloha_de_arequipe.jpg and /dev/null differ diff --git a/files/img/muffins1.jpg b/files/img/muffins1.jpg deleted file mode 100644 index 8b5766b..0000000 Binary files a/files/img/muffins1.jpg and /dev/null differ diff --git a/files/img/naranja.jpg b/files/img/naranja.jpg deleted file mode 100644 index 49e6a48..0000000 Binary files a/files/img/naranja.jpg and /dev/null differ diff --git a/files/img/naranjaponque.jpg b/files/img/naranjaponque.jpg deleted file mode 100644 index f4ed502..0000000 Binary files a/files/img/naranjaponque.jpg and /dev/null differ diff --git a/files/img/pan-con-masa-madre-.jpg b/files/img/pan-con-masa-madre-.jpg deleted file mode 100644 index c5ddfe0..0000000 Binary files a/files/img/pan-con-masa-madre-.jpg and /dev/null differ diff --git a/files/img/pan-de-molde.jpg b/files/img/pan-de-molde.jpg deleted file mode 100644 index c934fc2..0000000 Binary files a/files/img/pan-de-molde.jpg and /dev/null differ diff --git a/files/img/pan-rtzqhi1ok4k1bxlo.jpg b/files/img/pan-rtzqhi1ok4k1bxlo.jpg deleted file mode 100644 index 5e48815..0000000 Binary files a/files/img/pan-rtzqhi1ok4k1bxlo.jpg and /dev/null differ diff --git a/files/img/panabuela1.jpg b/files/img/panabuela1.jpg deleted file mode 100644 index 87ef700..0000000 Binary files a/files/img/panabuela1.jpg and /dev/null differ diff --git a/files/img/panbaguette1.jpg b/files/img/panbaguette1.jpg deleted file mode 100644 index 5ff2ab2..0000000 Binary files a/files/img/panbaguette1.jpg and /dev/null differ diff --git a/files/img/panblando.jpeg b/files/img/panblando.jpeg deleted file mode 100644 index 29e595a..0000000 Binary files a/files/img/panblando.jpeg and /dev/null differ diff --git a/files/img/pancampesino.png b/files/img/pancampesino.png deleted file mode 100644 index a3b9481..0000000 Binary files a/files/img/pancampesino.png and /dev/null differ diff --git a/files/img/pandebono.png b/files/img/pandebono.png deleted file mode 100644 index 4cc61dd..0000000 Binary files a/files/img/pandebono.png and /dev/null differ diff --git a/files/img/pangrande1.jpg b/files/img/pangrande1.jpg deleted file mode 100644 index cd2c2ab..0000000 Binary files a/files/img/pangrande1.jpg and /dev/null differ diff --git a/files/img/panhamburguesa.jpg b/files/img/panhamburguesa.jpg deleted file mode 100644 index 9cd6656..0000000 Binary files a/files/img/panhamburguesa.jpg and /dev/null differ diff --git a/files/img/pantrenza.jpg b/files/img/pantrenza.jpg deleted file mode 100644 index b18b142..0000000 Binary files a/files/img/pantrenza.jpg and /dev/null differ diff --git a/files/img/panunidad1.jpg b/files/img/panunidad1.jpg deleted file mode 100644 index e7e4f31..0000000 Binary files a/files/img/panunidad1.jpg and /dev/null differ diff --git a/files/img/panunidad2.jpg b/files/img/panunidad2.jpg deleted file mode 100644 index 051ad0d..0000000 Binary files a/files/img/panunidad2.jpg and /dev/null differ diff --git a/files/img/ponquenaranja.png b/files/img/ponquenaranja.png deleted file mode 100644 index b2f3ba2..0000000 Binary files a/files/img/ponquenaranja.png and /dev/null differ diff --git a/files/img/postreleche.jpg b/files/img/postreleche.jpg deleted file mode 100644 index e6ce8bc..0000000 Binary files a/files/img/postreleche.jpg and /dev/null differ diff --git a/files/img/tamal1.jpg b/files/img/tamal1.jpg deleted file mode 100644 index b9aa2fa..0000000 Binary files a/files/img/tamal1.jpg and /dev/null differ diff --git a/files/img/tamales.jpg b/files/img/tamales.jpg deleted file mode 100644 index b8b8d92..0000000 Binary files a/files/img/tamales.jpg and /dev/null differ diff --git a/files/img/torta1.jpg b/files/img/torta1.jpg deleted file mode 100644 index d457539..0000000 Binary files a/files/img/torta1.jpg and /dev/null differ diff --git a/files/img/torta2.jpg b/files/img/torta2.jpg deleted file mode 100644 index b04e62f..0000000 Binary files a/files/img/torta2.jpg and /dev/null differ diff --git a/files/img/tortachocolate.jpg b/files/img/tortachocolate.jpg deleted file mode 100644 index 18ca9b6..0000000 Binary files a/files/img/tortachocolate.jpg and /dev/null differ diff --git a/files/img/tortatresleches.png b/files/img/tortatresleches.png deleted file mode 100644 index 72fa823..0000000 Binary files a/files/img/tortatresleches.png and /dev/null differ diff --git a/files/img/yogurt1.jpg b/files/img/yogurt1.jpg deleted file mode 100644 index 3d4c174..0000000 Binary files a/files/img/yogurt1.jpg and /dev/null differ diff --git a/files/imprimir_pedido.php b/files/imprimir_pedido.php deleted file mode 100644 index be50486..0000000 --- a/files/imprimir_pedido.php +++ /dev/null @@ -1,232 +0,0 @@ - - - - - - - - Pedido #<?php echo $pedido['ID_PEDIDO']; ?> - Panadería - - - -
-

🥖 Panadería Artesanal

-

Delicias frescas todos los días

-

Teléfono: (555) 123-4567 | Email: info@panaderia.com

-
- -
-
-

Información del Cliente

-

Nombre:

-

Email:

- -

Teléfono:

- -
- -
-

Información del Pedido

-

Número de Pedido: #

-

Fecha:

-

Estado: - -

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
ProductoCantidadPrecio UnitarioSubtotal
$$
TOTAL:$
- - - -
- - -
- - - - diff --git a/files/js/admin-products.js b/files/js/admin-products.js deleted file mode 100644 index 4ff5894..0000000 --- a/files/js/admin-products.js +++ /dev/null @@ -1,462 +0,0 @@ -/** - * JavaScript para el Dashboard del Administrador - * Integración con la API REST de productos - */ - -class AdminProductManager { - constructor() { - this.apiUrl = 'api_productos_admin.php'; - this.initializeEventListeners(); - this.loadProductos(); - } - - /** - * Inicializar event listeners - */ - initializeEventListeners() { - // Formulario de actualización rápida de precios - document.addEventListener('click', (e) => { - if (e.target.matches('.btn-actualizar-precio')) { - this.mostrarModalActualizarPrecio(e.target.dataset.productoId); - } - - if (e.target.matches('.btn-actualizar-stock')) { - this.mostrarModalActualizarStock(e.target.dataset.productoId); - } - - if (e.target.matches('.btn-toggle-producto')) { - this.toggleProducto(e.target.dataset.productoId); - } - }); - - // Formulario de búsqueda - const searchForm = document.getElementById('form-buscar-productos'); - if (searchForm) { - searchForm.addEventListener('submit', (e) => { - e.preventDefault(); - this.buscarProductos(); - }); - } - } - - /** - * Cargar lista de productos - */ - async loadProductos(page = 1, filtros = {}) { - try { - const params = new URLSearchParams({ - page: page, - limit: 20, - ...filtros - }); - - const response = await fetch(`${this.apiUrl}?${params}`); - const data = await response.json(); - - if (data.success) { - this.renderProductos(data.data); - this.renderPaginacion(data.pagination); - } else { - this.showAlert('Error al cargar productos: ' + data.message, 'error'); - } - } catch (error) { - this.showAlert('Error de conexión: ' + error.message, 'error'); - } - } - - /** - * Actualizar precio de producto - */ - async actualizarPrecio(productoId, nuevoPrecio) { - try { - const response = await fetch(this.apiUrl, { - method: 'PATCH', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - id: productoId, - campo: 'precio', - valor: nuevoPrecio - }) - }); - - const data = await response.json(); - - if (data.success) { - this.showAlert(data.message, 'success'); - this.actualizarProductoEnDOM(productoId, 'precio', data.nuevo_valor); - } else { - this.showAlert('Error: ' + data.message, 'error'); - } - } catch (error) { - this.showAlert('Error de conexión: ' + error.message, 'error'); - } - } - - /** - * Actualizar stock de producto - */ - async actualizarStock(productoId, nuevoStock) { - try { - const response = await fetch(this.apiUrl, { - method: 'PATCH', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - id: productoId, - campo: 'stock', - valor: nuevoStock - }) - }); - - const data = await response.json(); - - if (data.success) { - this.showAlert(data.message, 'success'); - this.actualizarProductoEnDOM(productoId, 'stock', data.nuevo_valor); - } else { - this.showAlert('Error: ' + data.message, 'error'); - } - } catch (error) { - this.showAlert('Error de conexión: ' + error.message, 'error'); - } - } - - /** - * Toggle estado activo/inactivo del producto - */ - async toggleProducto(productoId) { - try { - const productoElement = document.querySelector(`[data-producto-id="${productoId}"]`); - const isActive = !productoElement.classList.contains('producto-inactivo'); - - const response = await fetch(this.apiUrl, { - method: 'PATCH', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - id: productoId, - campo: 'activo', - valor: isActive ? 0 : 1 - }) - }); - - const data = await response.json(); - - if (data.success) { - this.showAlert(data.message, 'success'); - this.actualizarEstadoProductoEnDOM(productoId, data.nuevo_valor); - } else { - this.showAlert('Error: ' + data.message, 'error'); - } - } catch (error) { - this.showAlert('Error de conexión: ' + error.message, 'error'); - } - } - - /** - * Crear nuevo producto - */ - async crearProducto(datosProducto) { - try { - const response = await fetch(this.apiUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(datosProducto) - }); - - const data = await response.json(); - - if (data.success) { - this.showAlert(data.message, 'success'); - this.loadProductos(); // Recargar lista - } else { - this.showAlert('Error: ' + data.message, 'error'); - } - } catch (error) { - this.showAlert('Error de conexión: ' + error.message, 'error'); - } - } - - /** - * Mostrar modal para actualizar precio - */ - mostrarModalActualizarPrecio(productoId) { - const modal = this.createModal('Actualizar Precio', ` -
-
- - -
-
- - -
-
- `); - - modal.querySelector('#form-actualizar-precio').addEventListener('submit', (e) => { - e.preventDefault(); - const nuevoPrecio = parseFloat(e.target.nuevo_precio.value); - this.actualizarPrecio(productoId, nuevoPrecio); - modal.remove(); - }); - - document.body.appendChild(modal); - modal.querySelector('#nuevo-precio').focus(); - } - - /** - * Mostrar modal para actualizar stock - */ - mostrarModalActualizarStock(productoId) { - const modal = this.createModal('Actualizar Stock', ` -
-
- - -
-
- - -
-
- `); - - modal.querySelector('#form-actualizar-stock').addEventListener('submit', (e) => { - e.preventDefault(); - const nuevoStock = parseInt(e.target.nuevo_stock.value); - this.actualizarStock(productoId, nuevoStock); - modal.remove(); - }); - - document.body.appendChild(modal); - modal.querySelector('#nuevo-stock').focus(); - } - - /** - * Crear modal genérico - */ - createModal(title, content) { - const modal = document.createElement('div'); - modal.className = 'modal'; - modal.style.cssText = ` - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: rgba(0,0,0,0.5); - display: flex; - align-items: center; - justify-content: center; - z-index: 10000; - `; - - modal.innerHTML = ` - - `; - - // Cerrar al hacer clic fuera del modal - modal.addEventListener('click', (e) => { - if (e.target === modal) { - modal.remove(); - } - }); - - return modal; - } - - /** - * Actualizar producto en el DOM - */ - actualizarProductoEnDOM(productoId, campo, valor) { - const elemento = document.querySelector(`[data-producto-id="${productoId}"]`); - if (elemento) { - if (campo === 'precio') { - const precioElement = elemento.querySelector('.precio'); - if (precioElement) { - precioElement.textContent = `$${parseFloat(valor).toLocaleString()}`; - this.highlightElement(precioElement); - } - } else if (campo === 'stock') { - const stockElement = elemento.querySelector('.stock'); - if (stockElement) { - stockElement.textContent = `Stock: ${valor}`; - this.highlightElement(stockElement); - } - } - } - } - - /** - * Actualizar estado del producto en el DOM - */ - actualizarEstadoProductoEnDOM(productoId, activo) { - const elemento = document.querySelector(`[data-producto-id="${productoId}"]`); - if (elemento) { - if (activo) { - elemento.classList.remove('producto-inactivo'); - elemento.style.opacity = '1'; - } else { - elemento.classList.add('producto-inactivo'); - elemento.style.opacity = '0.5'; - } - } - } - - /** - * Resaltar elemento - */ - highlightElement(element) { - element.style.transition = 'background-color 0.3s ease'; - element.style.backgroundColor = '#28a745'; - element.style.color = 'white'; - - setTimeout(() => { - element.style.backgroundColor = ''; - element.style.color = ''; - }, 1500); - } - - /** - * Renderizar lista de productos - */ - renderProductos(productos) { - const container = document.getElementById('productos-container'); - if (!container) return; - - container.innerHTML = productos.map(producto => ` -
-

${producto.NOMBRE_PRODUCTO}

-

${producto.categoria_nombre || 'Sin categoría'}

-

$${parseFloat(producto.PRECIO_PRODUCTO).toLocaleString()}

-

Stock: ${producto.PRODUCTO_STOCK_MIN}

-
- - - -
-
- `).join(''); - } - - /** - * Renderizar paginación - */ - renderPaginacion(pagination) { - const container = document.getElementById('paginacion-container'); - if (!container) return; - - let html = ''; - container.innerHTML = html; - } - - /** - * Mostrar alerta - */ - showAlert(message, type = 'info') { - const alert = document.createElement('div'); - alert.className = `alert alert-${type}`; - alert.style.cssText = ` - position: fixed; - top: 20px; - right: 20px; - z-index: 10001; - padding: 12px 16px; - border-radius: 4px; - color: white; - font-weight: bold; - max-width: 400px; - background: ${type === 'success' ? '#28a745' : type === 'error' ? '#dc3545' : '#17a2b8'}; - `; - alert.textContent = message; - - document.body.appendChild(alert); - - setTimeout(() => { - alert.remove(); - }, 5000); - } -} - -// Inicializar cuando el DOM esté listo -document.addEventListener('DOMContentLoaded', function() { - if (document.getElementById('productos-container')) { - window.adminManager = new AdminProductManager(); - } -}); - -// CSS básico para las tarjetas de productos -const style = document.createElement('style'); -style.textContent = ` - .producto-card { - border: 1px solid #ddd; - border-radius: 8px; - padding: 15px; - margin-bottom: 15px; - background: white; - transition: all 0.3s ease; - } - - .producto-card:hover { - box-shadow: 0 2px 8px rgba(0,0,0,0.1); - } - - .producto-inactivo { - opacity: 0.5; - filter: grayscale(50%); - } - - .acciones { - margin-top: 10px; - } - - .acciones .btn { - margin-right: 5px; - margin-bottom: 5px; - } - - .pagination { - text-align: center; - margin: 20px 0; - } - - .pagination .btn { - margin: 0 2px; - } -`; -document.head.appendChild(style); diff --git a/files/js/menu-updater.js b/files/js/menu-updater.js deleted file mode 100644 index 410181b..0000000 --- a/files/js/menu-updater.js +++ /dev/null @@ -1,403 +0,0 @@ -/** - * Cliente JavaScript para Server-Sent Events - * Escucha actualizaciones en tiempo real del menú - */ - -class MenuUpdater { - constructor(options = {}) { - this.baseUrl = options.baseUrl || ''; - this.eventSource = null; - this.lastCheck = options.lastCheck || Math.floor(Date.now() / 1000); - this.reconnectInterval = options.reconnectInterval || 5000; - this.maxReconnectAttempts = options.maxReconnectAttempts || 10; - this.reconnectAttempts = 0; - this.isConnected = false; - - // Callbacks - this.onMenuUpdate = options.onMenuUpdate || this.defaultMenuUpdateHandler; - this.onConnected = options.onConnected || this.defaultConnectedHandler; - this.onError = options.onError || this.defaultErrorHandler; - this.onDisconnected = options.onDisconnected || this.defaultDisconnectedHandler; - - // Elementos del DOM - this.notificationContainer = null; - this.createNotificationContainer(); - - this.init(); - } - - /** - * Inicializar la conexión SSE - */ - init() { - if (typeof(EventSource) === "undefined") { - console.error("Tu navegador no soporta Server-Sent Events"); - this.showNotification("Tu navegador no soporta actualizaciones en tiempo real", "warning"); - return; - } - - this.connect(); - } - - /** - * Conectar al servidor SSE - */ - connect() { - if (this.eventSource) { - this.disconnect(); - } - - const url = `${this.baseUrl}sse_menu_updates.php?last_check=${this.lastCheck}`; - console.log("Conectando a SSE:", url); - - this.eventSource = new EventSource(url); - - // Evento de conexión exitosa - this.eventSource.addEventListener('connected', (event) => { - this.isConnected = true; - this.reconnectAttempts = 0; - const data = JSON.parse(event.data); - console.log("Conectado a SSE:", data); - this.onConnected(data); - }); - - // Evento de actualización del menú - this.eventSource.addEventListener('menu_update', (event) => { - const data = JSON.parse(event.data); - console.log("Actualización del menú recibida:", data); - this.lastCheck = data.timestamp; - this.onMenuUpdate(data); - }); - - // Evento heartbeat - this.eventSource.addEventListener('heartbeat', (event) => { - const data = JSON.parse(event.data); - console.log("Heartbeat recibido:", data.timestamp); - }); - - // Evento de desconexión - this.eventSource.addEventListener('disconnected', (event) => { - const data = JSON.parse(event.data); - console.log("Desconectado del SSE:", data); - this.onDisconnected(data); - }); - - // Evento de error - this.eventSource.addEventListener('error', (event) => { - let errorData = { message: "Error de conexión" }; - try { - errorData = JSON.parse(event.data); - } catch (e) { - // Si no se puede parsear, usar mensaje por defecto - } - console.error("Error en SSE:", errorData); - this.onError(errorData); - }); - - // Manejar errores de conexión - this.eventSource.onerror = (event) => { - console.error("Error en EventSource:", event); - this.isConnected = false; - - if (this.eventSource.readyState === EventSource.CLOSED) { - this.attemptReconnect(); - } - }; - } - - /** - * Desconectar del servidor SSE - */ - disconnect() { - if (this.eventSource) { - this.eventSource.close(); - this.eventSource = null; - this.isConnected = false; - } - } - - /** - * Intentar reconexión automática - */ - attemptReconnect() { - if (this.reconnectAttempts >= this.maxReconnectAttempts) { - console.error("Máximo número de intentos de reconexión alcanzado"); - this.showNotification("No se pudo conectar para actualizaciones en tiempo real", "error"); - return; - } - - this.reconnectAttempts++; - console.log(`Intento de reconexión ${this.reconnectAttempts}/${this.maxReconnectAttempts} en ${this.reconnectInterval}ms`); - - setTimeout(() => { - this.connect(); - }, this.reconnectInterval); - } - - /** - * Handler por defecto para actualizaciones del menú - */ - defaultMenuUpdateHandler(data) { - this.showNotification(`Menú actualizado: ${data.total_cambios} cambios detectados`, "info"); - - // Actualizar productos en el DOM si están presentes - this.updateProductsInDOM(data.productos); - - // Mostrar notificación detallada - this.showDetailedUpdateNotification(data); - } - - /** - * Handler por defecto para conexión exitosa - */ - defaultConnectedHandler(data) { - this.showNotification("Conectado para actualizaciones en tiempo real", "success"); - } - - /** - * Handler por defecto para errores - */ - defaultErrorHandler(data) { - this.showNotification(`Error: ${data.message}`, "error"); - } - - /** - * Handler por defecto para desconexión - */ - defaultDisconnectedHandler(data) { - this.showNotification("Desconectado de actualizaciones en tiempo real", "warning"); - } - - /** - * Actualizar productos en el DOM - */ - updateProductsInDOM(productos) { - productos.forEach(producto => { - // Buscar elementos del producto en el DOM por ID - const precioElement = document.querySelector(`[data-producto-id="${producto.ID_PRODUCTO}"] .precio`); - const stockElement = document.querySelector(`[data-producto-id="${producto.ID_PRODUCTO}"] .stock`); - const productoElement = document.querySelector(`[data-producto-id="${producto.ID_PRODUCTO}"]`); - - if (precioElement) { - precioElement.textContent = `$${parseFloat(producto.PRECIO_PRODUCTO).toLocaleString()}`; - this.highlightElement(precioElement); - } - - if (stockElement) { - stockElement.textContent = `Stock: ${producto.PRODUCTO_STOCK_MIN}`; - this.highlightElement(stockElement); - } - - // Manejar productos desactivados - if (productoElement) { - if (producto.ACTIVO == 0) { - productoElement.style.opacity = '0.5'; - productoElement.style.filter = 'grayscale(50%)'; - } else { - productoElement.style.opacity = '1'; - productoElement.style.filter = 'none'; - } - } - }); - } - - /** - * Resaltar elemento actualizado - */ - highlightElement(element) { - element.style.transition = 'background-color 0.3s ease'; - element.style.backgroundColor = '#ffeb3b'; - - setTimeout(() => { - element.style.backgroundColor = ''; - }, 2000); - } - - /** - * Mostrar notificación detallada de actualización - */ - showDetailedUpdateNotification(data) { - if (data.logs && data.logs.length > 0) { - const cambios = data.logs.map(log => { - let mensaje = `${log.NOMBRE_PRODUCTO}: `; - switch (log.tipo_cambio) { - case 'precio': - mensaje += `Precio cambiado de $${log.valor_anterior} a $${log.valor_nuevo}`; - break; - case 'stock': - mensaje += `Stock cambiado de ${log.valor_anterior} a ${log.valor_nuevo}`; - break; - case 'activacion': - mensaje += 'Producto activado'; - break; - case 'desactivacion': - mensaje += 'Producto desactivado'; - break; - default: - mensaje += `${log.tipo_cambio}: ${log.valor_anterior} → ${log.valor_nuevo}`; - } - return mensaje; - }); - - this.showNotification( - `Cambios recientes:\n${cambios.slice(0, 3).join('\n')}${cambios.length > 3 ? '\n...' : ''}`, - "info", - 5000 - ); - } - } - - /** - * Crear contenedor de notificaciones - */ - createNotificationContainer() { - if (document.getElementById('sse-notifications')) { - return; - } - - const container = document.createElement('div'); - container.id = 'sse-notifications'; - container.style.cssText = ` - position: fixed; - top: 20px; - right: 20px; - z-index: 10000; - max-width: 400px; - `; - document.body.appendChild(container); - this.notificationContainer = container; - } - - /** - * Mostrar notificación - */ - showNotification(message, type = 'info', duration = 3000) { - const notification = document.createElement('div'); - notification.style.cssText = ` - background: ${this.getNotificationColor(type)}; - color: white; - padding: 12px 16px; - margin-bottom: 10px; - border-radius: 4px; - box-shadow: 0 2px 8px rgba(0,0,0,0.2); - font-family: Arial, sans-serif; - font-size: 14px; - line-height: 1.4; - white-space: pre-line; - animation: slideIn 0.3s ease-out; - cursor: pointer; - `; - - notification.textContent = message; - - // Agregar animación CSS - if (!document.getElementById('sse-notification-styles')) { - const style = document.createElement('style'); - style.id = 'sse-notification-styles'; - style.textContent = ` - @keyframes slideIn { - from { transform: translateX(100%); opacity: 0; } - to { transform: translateX(0); opacity: 1; } - } - @keyframes slideOut { - from { transform: translateX(0); opacity: 1; } - to { transform: translateX(100%); opacity: 0; } - } - `; - document.head.appendChild(style); - } - - // Hacer clic para cerrar - notification.addEventListener('click', () => { - this.removeNotification(notification); - }); - - this.notificationContainer.appendChild(notification); - - // Auto-remover después del tiempo especificado - if (duration > 0) { - setTimeout(() => { - this.removeNotification(notification); - }, duration); - } - } - - /** - * Remover notificación con animación - */ - removeNotification(notification) { - notification.style.animation = 'slideOut 0.3s ease-in'; - setTimeout(() => { - if (notification.parentNode) { - notification.parentNode.removeChild(notification); - } - }, 300); - } - - /** - * Obtener color según tipo de notificación - */ - getNotificationColor(type) { - const colors = { - success: '#4caf50', - error: '#f44336', - warning: '#ff9800', - info: '#2196f3' - }; - return colors[type] || colors.info; - } - - /** - * Obtener estado de conexión - */ - isConnectedToSSE() { - return this.isConnected && this.eventSource && this.eventSource.readyState === EventSource.OPEN; - } - - /** - * Destructor - */ - destroy() { - this.disconnect(); - if (this.notificationContainer && this.notificationContainer.parentNode) { - this.notificationContainer.parentNode.removeChild(this.notificationContainer); - } - } -} - -// Inicializar automáticamente si se está en una página de menú -document.addEventListener('DOMContentLoaded', function() { - // Verificar si estamos en una página que necesita actualizaciones de menú - const menuElements = document.querySelectorAll('[data-producto-id], .producto-card, .menu-item'); - - if (menuElements.length > 0) { - console.log("Página de menú detectada, iniciando MenuUpdater..."); - - window.menuUpdater = new MenuUpdater({ - onMenuUpdate: function(data) { - console.log("Actualización personalizada del menú:", data); - - // Llamar al handler por defecto - this.defaultMenuUpdateHandler(data); - - // Código personalizado adicional aquí - // Por ejemplo, recargar carrito, actualizar totales, etc. - if (typeof updateCartTotals === 'function') { - updateCartTotals(); - } - }.bind(window.menuUpdater) - }); - - // Agregar evento para limpiar al salir de la página - window.addEventListener('beforeunload', function() { - if (window.menuUpdater) { - window.menuUpdater.destroy(); - } - }); - } -}); - -// Exportar para uso manual -if (typeof module !== 'undefined' && module.exports) { - module.exports = MenuUpdater; -} diff --git a/files/js/navigation-system.js b/files/js/navigation-system.js deleted file mode 100644 index fde291a..0000000 --- a/files/js/navigation-system.js +++ /dev/null @@ -1,170 +0,0 @@ -/** - * Sistema de Navegación Inteligente para Panadería - * Maneja la navegación del navegador de manera inteligente, permitiendo - * navegación normal dentro del sistema mientras protege contra salidas accidentales - */ - -(function() { - 'use strict'; - - // Configuración del sistema - const config = { - maxBackAttempts: 3, - confirmationDelay: 1000, - debugMode: false - }; - - // Variables de estado - let isNavigatingWithinSystem = false; - let backButtonAttempts = 0; - let lastNavigationTime = 0; - - // Función de logging para debug - function log(message, data = null) { - if (config.debugMode) { - console.log('[NavSystem]', message, data); - } - } - - // Detectar si una URL es interna al sistema - function isInternalUrl(url) { - try { - const urlObj = new URL(url, window.location.origin); - const currentDomain = window.location.hostname; - const targetDomain = urlObj.hostname; - - return targetDomain === currentDomain; - } catch (error) { - // Si hay error parseando la URL, asumir que es interna (URL relativa) - return true; - } - } - - // Detectar clics en enlaces para determinar navegación interna - function setupLinkDetection() { - document.addEventListener('click', function(e) { - const link = e.target.closest('a'); - if (link && link.href) { - if (isInternalUrl(link.href)) { - isNavigatingWithinSystem = true; - lastNavigationTime = Date.now(); - log('Navegación interna detectada', link.href); - - // Resetear flag después de un tiempo - setTimeout(() => { - isNavigatingWithinSystem = false; - }, config.confirmationDelay); - } - } - }); - } - - // Manejar el botón atrás del navegador - function setupBackButtonHandling() { - // Solo aplicar si estamos en un dashboard o página protegida - const isProtectedPage = window.location.pathname.includes('dashboard') || - window.location.pathname.includes('perfil') || - window.location.pathname.includes('admin') || - window.location.pathname.includes('empleado') || - window.location.pathname.includes('cliente'); - - if (!isProtectedPage) { - log('Página no protegida, navegación libre'); - return; - } - - // Configurar historial inicial - if (window.history && window.history.replaceState) { - history.replaceState(null, null, window.location.pathname); - } - - // Manejar popstate - window.addEventListener('popstate', function(event) { - backButtonAttempts++; - const timeSinceLastNavigation = Date.now() - lastNavigationTime; - - log('Popstate detectado', { - attempts: backButtonAttempts, - isInternal: isNavigatingWithinSystem, - timeSince: timeSinceLastNavigation - }); - - // Si es navegación reciente dentro del sistema, permitirla - if (isNavigatingWithinSystem || timeSinceLastNavigation < config.confirmationDelay) { - log('Navegación interna permitida'); - return; - } - - // Solo mostrar confirmación después de múltiples intentos - if (backButtonAttempts > config.maxBackAttempts) { - const userType = getUserType(); - const message = `¿Estás seguro de que quieres cerrar la sesión${userType ? ' de ' + userType : ''}?`; - - if (confirm(message)) { - log('Usuario confirmó salida'); - window.location.href = 'logout.php'; - } else { - log('Usuario canceló salida'); - backButtonAttempts = 0; // Resetear contador - history.pushState(null, null, window.location.pathname); - } - } else { - // Permitir navegación normal las primeras veces - log('Navegación permitida, intento:', backButtonAttempts); - history.pushState(null, null, window.location.pathname); - } - }); - } - - // Obtener tipo de usuario para personalizar mensajes - function getUserType() { - const path = window.location.pathname; - if (path.includes('admin')) return 'administrador'; - if (path.includes('empleado')) return 'empleado'; - if (path.includes('cliente')) return 'cliente'; - return null; - } - - // Limpiar datos sensibles solo al cerrar completamente - function setupCleanup() { - window.addEventListener('beforeunload', function(e) { - // Solo limpiar si realmente está cerrando la página, no navegando - if (!isNavigatingWithinSystem) { - log('Preparando limpieza de datos'); - // No limpiar automáticamente sessionStorage para permitir navegación - // sessionStorage.clear(); // Comentado para permitir navegación normal - } - }); - } - - // Inicializar el sistema cuando el DOM esté listo - function initialize() { - log('Inicializando sistema de navegación inteligente'); - - setupLinkDetection(); - setupBackButtonHandling(); - setupCleanup(); - - log('Sistema inicializado correctamente'); - } - - // Inicializar cuando el DOM esté listo - if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initialize); - } else { - initialize(); - } - - // Exponer configuración para uso externo si es necesario - window.NavSystem = { - config: config, - setDebugMode: function(enabled) { - config.debugMode = enabled; - }, - resetAttempts: function() { - backButtonAttempts = 0; - log('Intentos de navegación reseteados'); - } - }; - -})(); diff --git a/files/limpiar_empleados.php b/files/limpiar_empleados.php deleted file mode 100644 index dfa5d21..0000000 --- a/files/limpiar_empleados.php +++ /dev/null @@ -1,63 +0,0 @@ -🧹 Limpieza de Empleados de Prueba"; - -// Mostrar empleados actuales -echo "

👥 Empleados Actuales

"; -$query = "SELECT * FROM Empleados ORDER BY ID_EMPLEADO"; -$result = $conexion->query($query); - -if ($result->num_rows > 0) { - echo ""; - echo ""; - - while ($row = $result->fetch_assoc()) { - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - } - echo "
IDNombreEmailAcción
" . $row['ID_EMPLEADO'] . "" . ($row['NOMBRE_EMPLEADO'] ?? 'N/A') . "" . ($row['EMAIL_EMPLEADO'] ?? 'N/A') . "Eliminar
"; -} else { - echo "

No hay empleados registrados

"; -} - -// Procesar eliminación -if (isset($_GET['delete'])) { - $id_empleado = (int)$_GET['delete']; - - $delete_query = "DELETE FROM Empleados WHERE ID_EMPLEADO = ?"; - $stmt = $conexion->prepare($delete_query); - $stmt->bind_param('i', $id_empleado); - - if ($stmt->execute()) { - echo "

✅ Empleado eliminado exitosamente

"; - echo ""; - } else { - echo "

❌ Error al eliminar empleado

"; - } - - $stmt->close(); -} - -// Opción para eliminar todos los empleados -if (isset($_GET['deleteall'])) { - $delete_all_query = "DELETE FROM Empleados"; - if ($conexion->query($delete_all_query)) { - echo "

✅ Todos los empleados eliminados

"; - echo ""; - } else { - echo "

❌ Error al eliminar todos los empleados

"; - } -} - -echo "
"; -echo "

🗑️ Eliminar Todos los Empleados

"; -echo "

← Volver al Dashboard

"; - -$conexion->close(); -?> diff --git a/files/listar_productos.php b/files/listar_productos.php deleted file mode 100644 index c0c4f6e..0000000 --- a/files/listar_productos.php +++ /dev/null @@ -1,9 +0,0 @@ -prepare('SELECT p.NOMBRE_PRODUCTO, cp.NOMBRE_CATEGORIAPRODUCTO FROM Productos p INNER JOIN Categoria_Productos cp ON p.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO WHERE p.ACTIVO = 1 ORDER BY cp.NOMBRE_CATEGORIAPRODUCTO, p.NOMBRE_PRODUCTO'); -$stmt->execute(); -$productos = $stmt->fetchAll(PDO::FETCH_ASSOC); -foreach($productos as $producto) { - echo $producto['NOMBRE_CATEGORIAPRODUCTO'] . ' - ' . $producto['NOMBRE_PRODUCTO'] . PHP_EOL; -} -?> diff --git a/files/login.php b/files/login.php deleted file mode 100644 index 56add6f..0000000 --- a/files/login.php +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - Iniciar Sesión - Panadería - - - - - - - diff --git a/files/logout.php b/files/logout.php deleted file mode 100644 index 36e6a96..0000000 --- a/files/logout.php +++ /dev/null @@ -1,29 +0,0 @@ - diff --git a/files/masvendidos.php b/files/masvendidos.php deleted file mode 100644 index 79ce59b..0000000 --- a/files/masvendidos.php +++ /dev/null @@ -1,56 +0,0 @@ -connect_error) { - die("Error de conexión: " . $conexion->connect_error); -} - -// Establecer charset -$conexion->set_charset("utf8"); - -// Opcional: mantener compatibilidad con PDO para otros archivos que lo usen -try { - $pdo_conexion = new PDO("mysql:host=$servidor;dbname=$base_datos;charset=utf8", $usuario, $password); - $pdo_conexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); -} catch(PDOException $e) { - die("Error de conexión PDO: " . $e->getMessage()); -} - -// Ordenar por: 'cantidad' o 'ingresos' -$ordenarPor = isset($_GET['orden']) ? $_GET['orden'] : 'cantidad'; - -$ordenSQL = $ordenarPor === 'ingresos' ? 'total_ingresos' : 'total_cantidad'; - -while ($fila = $resultado->fetch_assoc()): ?> - - - - - - query($sql); -?> - -close(); -?> \ No newline at end of file diff --git a/files/menu.php b/files/menu.php deleted file mode 100644 index 8f9fea0..0000000 --- a/files/menu.php +++ /dev/null @@ -1,498 +0,0 @@ -setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - // Obtener productos activos organizados por categoría - $stmt = $pdo->prepare(" - SELECT p.*, cp.NOMBRE_CATEGORIAPRODUCTO - FROM Productos p - INNER JOIN Categoria_Productos cp ON p.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO - WHERE p.ACTIVO = 1 - ORDER BY cp.NOMBRE_CATEGORIAPRODUCTO, p.NOMBRE_PRODUCTO - "); - $stmt->execute(); - $productos_data = $stmt->fetchAll(PDO::FETCH_ASSOC); - - // Organizar productos por categoría - $productos_por_categoria = []; - foreach ($productos_data as $producto) { - $categoria = $producto['NOMBRE_CATEGORIAPRODUCTO']; - $productos_por_categoria[$categoria][] = $producto; - } - - // Mapeo de categorías para mostrar nombres más amigables - $categorias_display = [ - 'Tortas Tres Leches' => 'Tortas', - 'Tortas Milyway' => 'Tortas', - 'Tortas por Encargo' => 'Tortas', - 'Pan Grande' => 'Pan Grande', - 'Pan Pequeño' => 'Pan Pequeño', - 'Postres' => 'Postres', - 'Galletas' => 'Galletas', - 'Tamales' => 'Tamales', - 'Yogures' => 'Productos Lácteos', - 'Pasteles Pollo' => 'Hojaldres' - ]; - -} catch(PDOException $e) { - $productos_por_categoria = []; - $error_msg = "Error al conectar con la base de datos: " . $e->getMessage(); -} -?> - - - - - - - - El Castillo del Pan - Menú - - - - - - - - - - - - - - - - - - - - - - -
- -
- - -
-
-
-
-

- ¿Estás Listo para Disfrutar de tú antojo? -

- Imagen representativa de un pan -

- Descubre nuestros deliciosos productos artesanales, elaborados con los mejores ingredientes y mucho amor -

-
-
-
-
- -
-
- - - - - -
-
-
-

- Busca tu Producto Favorito -

-
- - -
-
-
-
- - -
- - - 'img/tamal1.jpg', - 'Empanadas de Carne (unidad)' => 'img/empanadas.png', - 'Arequipe (Tarro 500g)' => 'img/arequipe-alpina.png', - - // Pan Grande (Categoría 4) - 'Pan Tajado Integral' => 'img/pan-integral.jpg', - 'Pan Blanco de Molde' => 'img/pan-de-molde.jpg', - 'Pan de Hamburguesa' => 'img/panhamburguesa.jpg', - - // Yogures (Categoría 7) - 'Yogurt Fresa Litro' => 'img/yogurt1.jpg', - 'Postre de Tres Leches' => 'img/postreleche.jpg', - 'Kumiss Natural' => 'img/kumiss.1.png', - - // Galletas (Categoría 5) - 'Galleta de Tres Ojos' => 'img/galletatresojos.png', - 'Galletas Surtidas de Mantequilla' => 'img/galletasmantequilla.jpg', - 'Galletas de Avena y Pasas' => 'img/galletas-de-avena-con-pasas-y-nuez.jpg', - - // Tortas Tres Leches (Categoría 1) - 'Pan Campesino Grande' => 'img/pancampesino.png', - 'Baguette Clásica' => 'img/baguette.jpg', - 'Pan Trenza Integral' => 'img/pantrenza.jpg', - 'Pan Artesanal de Masa Madre' => 'img/pan-con-masa-madre-.jpg', - 'Pan Blandito' => 'img/panblando.jpeg', - - // Tortas por Encargo (Categoría 3) - 'Torta de Chocolate Pequeña' => 'img/tortachocolate.jpg', - 'Muffin de Arándanos' => 'img/muffins1.jpg', - 'Brazo de Reina' => 'img/brazoreina1.jpg', - 'Cheesecake de Frutos Rojos' => 'img/cheesecake-frutos-rojos.jpg', - 'Milhoja de Arequipe' => 'img/miloha_de_arequipe.jpg', - - // Tortas Milyway (Categoría 2) - 'Croissant de Almendras' => 'img/croissants.jpg', - 'Pan de Bono Pequeño' => 'img/pandebono.png', - 'Mogolla Chicharrona' => 'img/chicharrona.png', - // Pasteles Pollo (Categoría 9) - 'Ponqué de Naranja (Porción)' => 'img/naranjaponque.jpg', - 'Brownie con Nuez' => 'img/browni-con-nueces.jpg' - ]; - - // Obtener la imagen del producto o usar imagen por defecto - $image_path = $product_images[$producto['NOMBRE_PRODUCTO']] ?? 'img/pan-rtzqhi1ok4k1bxlo.jpg'; - ?> -
-
-
- <?php echo htmlspecialchars($producto['NOMBRE_PRODUCTO']); ?> -
- $ -
-
-
-
- -
-

- -

-
-
- - Disponible - - Stock: -
-
-
- -
-
-
-
- - -
-
-

¡No hay productos!

-

Actualmente no tenemos productos disponibles en el menú. Por favor, vuelve a intentarlo más tarde.

-
-
- -
-
-
- - -
-
-
-
-

¿Listo para ordenar?

-

- Contacta con nosotros para realizar tu pedido personalizado o visita nuestra tienda -

- -
-
-
-
- - -
-
-
-
-
- - El Castillo del Pan -
-

- Panadería artesanal con más de 10 años de experiencia, - ofreciendo productos frescos y de la más alta calidad. -

-
-
-
Enlaces
- -
-
-
Productos
- -
-
-
Contacto
-

- - 123 Calle Principal, Ciudad -

-

- - (555) 123-4567 -

-

- - info@elcastillodelpan.com -

-
- - - -
-
-
-
-
-
-

- © 2024 El Castillo del Pan. Todos los derechos reservados. -

-
-
- - Hecho con para nuestros clientes - -
-
-
-
- - - - - - - - - - - - diff --git a/files/migrar_empleados_fecha.php b/files/migrar_empleados_fecha.php deleted file mode 100644 index c1ea930..0000000 --- a/files/migrar_empleados_fecha.php +++ /dev/null @@ -1,82 +0,0 @@ -Migración de Base de Datos - Tabla Empleados"; -echo "

Agregando columna FECHA_REGISTRO...

"; - -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception('Error de conexión a la base de datos'); - } - - // Verificar si la columna ya existe - $check_query = "SHOW COLUMNS FROM Empleados LIKE 'FECHA_REGISTRO'"; - $result = $conexion->query($check_query); - - if ($result && $result->num_rows > 0) { - echo "
✓ La columna FECHA_REGISTRO ya existe en la tabla Empleados.
"; - } else { - // Agregar la columna - $alter_query = "ALTER TABLE Empleados ADD COLUMN FECHA_REGISTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP"; - - if ($conexion->query($alter_query)) { - echo "
✓ Columna FECHA_REGISTRO agregada exitosamente a la tabla Empleados.
"; - - // Actualizar empleados existentes con fecha actual - $update_query = "UPDATE Empleados SET FECHA_REGISTRO = NOW() WHERE FECHA_REGISTRO IS NULL"; - if ($conexion->query($update_query)) { - echo "
✓ Fechas de registro actualizadas para empleados existentes.
"; - } - } else { - throw new Exception('Error al agregar la columna: ' . $conexion->error); - } - } - - // Verificar la estructura final - echo "

Estructura actual de la tabla Empleados:

"; - $structure_query = "DESCRIBE Empleados"; - $structure_result = $conexion->query($structure_query); - - if ($structure_result) { - echo ""; - echo ""; - - while ($row = $structure_result->fetch_assoc()) { - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - } - echo "
CampoTipoNuloClavePor defectoExtra
" . htmlspecialchars($row['Field']) . "" . htmlspecialchars($row['Type']) . "" . htmlspecialchars($row['Null']) . "" . htmlspecialchars($row['Key']) . "" . htmlspecialchars($row['Default']) . "" . htmlspecialchars($row['Extra']) . "
"; - } - - echo "
✓ Migración completada exitosamente.
"; - echo "

Volver al Dashboard

"; - -} catch (Exception $e) { - echo "
✗ Error: " . htmlspecialchars($e->getMessage()) . "
"; - echo "

Por favor, contacte al administrador del sistema.

"; -} - -// Cerrar conexión -if (isset($conexion)) { - $conexion->close(); -} -?> diff --git a/files/mis_pedidos_cliente.php b/files/mis_pedidos_cliente.php deleted file mode 100644 index 24cf856..0000000 --- a/files/mis_pedidos_cliente.php +++ /dev/null @@ -1,506 +0,0 @@ -prepare(" - SELECT p.ID_PEDIDO, p.FECHA_INGRESO, p.FECHA_ENTREGA, p.TOTAL_PRODUCTO, - e.NOMBRE_EMPLEADO, ep.NOMBRE_ESTADO, ep.ID_ESTADO_PEDIDO - FROM Pedidos p - INNER JOIN Empleados e ON p.ID_EMPLEADO = e.ID_EMPLEADO - INNER JOIN Estado_Pedidos ep ON p.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO - WHERE p.ID_CLIENTE = ? - ORDER BY p.FECHA_INGRESO DESC - "); - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $mis_pedidos = $stmt->get_result(); -} catch (Exception $e) { - error_log("Error obteniendo pedidos del cliente: " . $e->getMessage()); -} -?> - - - - - - - Mis Pedidos - Cliente - - - - - - -
-
-
-
-

- Mis Pedidos -

-

Consulta el estado de todos tus pedidos

-
- -
-
- -
- num_rows > 0): ?> -
-

- - Historial de Pedidos (num_rows; ?>) -

- - - Actualizado automáticamente cada 30 segundos - -
- -
- fetch_assoc()): ?> -
-
-
- - Pedido # -
-
- -
-
- -
-
- -
- Fecha de Pedido:
- -
-
- -
- -
- Fecha de Entrega:
- -
-
- -
- -
- Atendido por:
- -
-
- -
- -
- Total:
- $ -
-
-
- -
- -
-
- -
- -
- -

No tienes pedidos aún

-

Cuando realices tu primer pedido, aparecerá aquí.

- - Explorar Productos - -
- -
-
- - - - - - - - diff --git a/files/obtener_administradores_ajax.php b/files/obtener_administradores_ajax.php deleted file mode 100644 index 6248a07..0000000 --- a/files/obtener_administradores_ajax.php +++ /dev/null @@ -1,73 +0,0 @@ - false, 'mensaje' => 'Acceso no autorizado']); - exit(); -} - -// Headers de respuesta JSON -header('Content-Type: application/json'); - -// Incluir conexión a la base de datos -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception('Error de conexión a la base de datos'); - } - - // Consulta para obtener administradores usando prepared statement - $consulta = "SELECT - ID_ADMIN as id, - NOMBRE_ADMIN as nombre, - EMAIL_ADMIN as email, - ACTIVO_ADMIN as activo - FROM Administradores - ORDER BY NOMBRE_ADMIN ASC"; - - $stmt = $conexion->prepare($consulta); - - if (!$stmt) { - throw new Exception('Error al preparar la consulta: ' . $conexion->error); - } - - $stmt->execute(); - $resultado = $stmt->get_result(); - - if ($resultado) { - $administradores = []; - while ($fila = $resultado->fetch_assoc()) { - $administradores[] = [ - 'id' => $fila['id'] ?? 0, - 'nombre' => htmlspecialchars($fila['nombre'] ?? ''), - 'email' => htmlspecialchars($fila['email'] ?? ''), - 'activo' => $fila['activo'] ?? 1 - ]; - } - - echo json_encode([ - 'success' => true, - 'administradores' => $administradores, - 'total' => count($administradores) - ]); - } else { - throw new Exception('Error al ejecutar la consulta'); - } - - $stmt->close(); - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error del servidor: ' . $e->getMessage() - ]); -} - -// Cerrar conexión -if (isset($conexion)) { - $conexion->close(); -} -?> diff --git a/files/obtener_categorias_ingredientes_ajax.php b/files/obtener_categorias_ingredientes_ajax.php deleted file mode 100644 index bdb160a..0000000 --- a/files/obtener_categorias_ingredientes_ajax.php +++ /dev/null @@ -1,64 +0,0 @@ - false, - 'error' => 'No autorizado' - ]); - exit(); -} - -require_once 'conexion.php'; - -try { - // Consulta para obtener categorías de ingredientes - $consulta = "SELECT - ID_CATEGORIA as id, - NOMBRE_CATEGORIA_INGREDIENTE as nombre - FROM Categoria_Ingredientes - ORDER BY NOMBRE_CATEGORIA_INGREDIENTE ASC"; - - $resultado = $conexion->query($consulta); - - if ($resultado) { - $categorias = []; - while ($fila = $resultado->fetch_assoc()) { - $categorias[] = [ - 'id' => $fila['id'], - 'nombre' => $fila['nombre'] - ]; - } - - echo json_encode([ - 'success' => true, - 'categorias' => $categorias - ]); - } else { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error en la consulta: ' . $conexion->error - ]); - } - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error del servidor: ' . $e->getMessage() - ]); -} - -$conexion->close(); -?> diff --git a/files/obtener_clientes_ajax.php b/files/obtener_clientes_ajax.php deleted file mode 100644 index bd12747..0000000 --- a/files/obtener_clientes_ajax.php +++ /dev/null @@ -1,75 +0,0 @@ - false, 'mensaje' => 'Acceso no autorizado']); - exit(); -} - -// Headers de respuesta JSON -header('Content-Type: application/json'); - -// Incluir conexión a la base de datos -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception('Error de conexión a la base de datos'); - } - - // Consulta para obtener clientes usando prepared statement - $consulta = "SELECT - ID_CLIENTE as id, - NOMBRE_CLI as nombre, - EMAIL_CLI as email, - TELEFONO_CLI as telefono, - COALESCE(ACTIVO_CLI, 1) as activo - FROM Clientes - ORDER BY NOMBRE_CLI ASC"; - - $stmt = $conexion->prepare($consulta); - - if (!$stmt) { - throw new Exception('Error al preparar la consulta: ' . $conexion->error); - } - - $stmt->execute(); - $resultado = $stmt->get_result(); - - if ($resultado) { - $clientes = []; - while ($fila = $resultado->fetch_assoc()) { - $clientes[] = [ - 'id' => $fila['id'] ?? 0, - 'nombre' => htmlspecialchars($fila['nombre'] ?? ''), - 'email' => htmlspecialchars($fila['email'] ?? ''), - 'telefono' => htmlspecialchars($fila['telefono'] ?? ''), - 'activo' => (int)($fila['activo'] ?? 1) - ]; - } - - echo json_encode([ - 'success' => true, - 'clientes' => $clientes, - 'total' => count($clientes) - ]); - } else { - throw new Exception('Error al ejecutar la consulta'); - } - - $stmt->close(); - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error del servidor: ' . $e->getMessage() - ]); -} - -// Cerrar conexión -if (isset($conexion)) { - $conexion->close(); -} -?> diff --git a/files/obtener_detalle_pedido_ajax.php b/files/obtener_detalle_pedido_ajax.php deleted file mode 100644 index b22dad3..0000000 --- a/files/obtener_detalle_pedido_ajax.php +++ /dev/null @@ -1,169 +0,0 @@ - session_id(), - 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'NO_SET', - 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'NO_SET', - 'all_session' => $_SESSION - ]; - - error_log("AJAX Auth Failed Detalle Pedido - Debug: " . json_encode($debug_info)); - - http_response_code(401); - echo json_encode([ - 'success' => false, - 'mensaje' => 'No autorizado para ver detalles de pedidos.' - ]); - exit(); -} - -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception("No se pudo conectar a la base de datos"); - } - - // Obtener datos de la petición - $input = file_get_contents('php://input'); - $data = json_decode($input, true); - - if (!$data) { - throw new Exception("Datos de entrada inválidos"); - } - - $pedido_id = isset($data['pedido_id']) ? intval($data['pedido_id']) : 0; - - // Validar datos - if ($pedido_id <= 0) { - throw new Exception("ID de pedido inválido"); - } - - error_log("Obteniendo detalle del pedido: $pedido_id"); - - // Obtener información básica del pedido - $stmt = $conexion->prepare(" - SELECT - p.ID_PEDIDO, - p.FECHA_INGRESO, - p.FECHA_ENTREGA, - p.TOTAL_PRODUCTO, - COALESCE(c.NOMBRE_CLI, 'Cliente eliminado') as cliente, - COALESCE(c.EMAIL_CLI, '') as email_cliente, - COALESCE(c.TELEFONO_CLI, '') as telefono_cliente, - COALESCE(e.NOMBRE_EMPLEADO, 'No asignado') as empleado, - COALESCE(ep.NOMBRE_ESTADO, 'Estado desconocido') as estado_nombre, - p.ID_ESTADO_PEDIDO as estado_id - FROM Pedidos p - LEFT JOIN Clientes c ON p.ID_CLIENTE = c.ID_CLIENTE - LEFT JOIN Empleados e ON p.ID_EMPLEADO = e.ID_EMPLEADO - LEFT JOIN Estado_Pedidos ep ON p.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO - WHERE p.ID_PEDIDO = ? - "); - $stmt->bind_param("i", $pedido_id); - $stmt->execute(); - $result = $stmt->get_result(); - $pedido = $result->fetch_assoc(); - - if (!$pedido) { - throw new Exception("Pedido no encontrado"); - } - - // Verificar si la columna DESCRIPCION_PRODUCTO existe - $check_descripcion = $conexion->query("SHOW COLUMNS FROM Productos LIKE 'DESCRIPCION_PRODUCTO'"); - $has_descripcion = $check_descripcion && $check_descripcion->num_rows > 0; - - // Construir consulta según las columnas disponibles - $descripcion_field = $has_descripcion ? - "COALESCE(prod.DESCRIPCION_PRODUCTO, prod.TIPO_PRODUCTO_MARCA, '') as producto_descripcion" : - "COALESCE(prod.TIPO_PRODUCTO_MARCA, '') as producto_descripcion"; - - // Obtener los productos del pedido con información completa - $stmt = $conexion->prepare(" - SELECT - dp.ID_DETALLE, - dp.CANTIDAD_PRODUCTO, - dp.PRECIO_UNITARIO, - dp.SUBTOTAL, - COALESCE(prod.NOMBRE_PRODUCTO, 'Producto eliminado') as producto_nombre, - $descripcion_field, - COALESCE(cat.NOMBRE_CATEGORIAPRODUCTO, 'Sin categoría') as categoria_nombre, - prod.ID_PRODUCTO as producto_id - FROM Detalle_Pedidos dp - LEFT JOIN Productos prod ON dp.ID_PRODUCTO = prod.ID_PRODUCTO - LEFT JOIN Categoria_Productos cat ON prod.ID_CATEGORIA_PRODUCTO = cat.ID_CATEGORIA_PRODUCTO - WHERE dp.ID_PEDIDO = ? - ORDER BY dp.ID_DETALLE - "); - $stmt->bind_param("i", $pedido_id); - $stmt->execute(); - $result = $stmt->get_result(); - $productos = $result->fetch_all(MYSQLI_ASSOC); - - // Calcular totales - $total_items = 0; - $total_calculado = 0; - foreach ($productos as $producto) { - $total_items += $producto['CANTIDAD_PRODUCTO']; - $total_calculado += $producto['SUBTOTAL']; - } - - error_log("Detalle obtenido - Pedido: $pedido_id, Productos: " . count($productos) . ", Total items: $total_items"); - - echo json_encode([ - 'success' => true, - 'pedido' => [ - 'id' => $pedido['ID_PEDIDO'], - 'fecha_ingreso' => $pedido['FECHA_INGRESO'], - 'fecha_entrega' => $pedido['FECHA_ENTREGA'], - 'total' => $pedido['TOTAL_PRODUCTO'], - 'cantidad_productos' => $total_items, - 'cliente' => $pedido['cliente'], - 'email_cliente' => $pedido['email_cliente'], - 'telefono_cliente' => $pedido['telefono_cliente'], - 'empleado' => $pedido['empleado'], - 'estado_nombre' => $pedido['estado_nombre'], - 'estado_id' => $pedido['estado_id'] - ], - 'productos' => array_map(function($prod) { - return [ - 'id_detalle' => $prod['ID_DETALLE'], - 'producto_id' => $prod['producto_id'], - 'nombre' => $prod['producto_nombre'], - 'descripcion' => $prod['producto_descripcion'], - 'categoria' => $prod['categoria_nombre'], - 'cantidad' => $prod['CANTIDAD_PRODUCTO'], - 'precio_unitario' => $prod['PRECIO_UNITARIO'], - 'subtotal' => $prod['SUBTOTAL'] - ]; - }, $productos), - 'resumen' => [ - 'total_items' => $total_items, - 'total_calculado' => $total_calculado, - 'total_productos_diferentes' => count($productos) - ] - ]); - -} catch (Exception $e) { - error_log("Error en obtener_detalle_pedido_ajax.php: " . $e->getMessage()); - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error: ' . $e->getMessage() - ]); -} -?> diff --git a/files/obtener_detalles_pedido.php b/files/obtener_detalles_pedido.php deleted file mode 100644 index 7d22518..0000000 --- a/files/obtener_detalles_pedido.php +++ /dev/null @@ -1,177 +0,0 @@ - - -
-
-
Información del Cliente
-
-
-

Nombre:

-

Email:

- -

Teléfono:

- -
-
-
-
-
Información del Pedido
-
-
-

ID Pedido: #

-

Fecha:

-

Estado: - - - - -

-

Total: $

-
-
-
-
- -
-
Productos Pedidos
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
IDProductoCantidadPrecio Unit.Subtotal
- # - -
-
- - - -
-
$$
Total del Pedido:$
-
-
- -
- - -
- - diff --git a/files/obtener_empleados_ajax.php b/files/obtener_empleados_ajax.php deleted file mode 100644 index a02f804..0000000 --- a/files/obtener_empleados_ajax.php +++ /dev/null @@ -1,73 +0,0 @@ - false, 'mensaje' => 'Acceso no autorizado']); - exit(); -} - -// Headers de respuesta JSON -header('Content-Type: application/json'); - -// Incluir conexión a la base de datos -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception('Error de conexión a la base de datos'); - } - - // Consulta para obtener empleados usando prepared statement - $consulta = "SELECT - ID_EMPLEADO as id, - NOMBRE_EMPLEADO as nombre, - EMAIL_EMPLEADO as email, - COALESCE(ACTIVO_EMPLEADO, 1) as activo - FROM Empleados - ORDER BY NOMBRE_EMPLEADO ASC"; - - $stmt = $conexion->prepare($consulta); - - if (!$stmt) { - throw new Exception('Error al preparar la consulta: ' . $conexion->error); - } - - $stmt->execute(); - $resultado = $stmt->get_result(); - - if ($resultado) { - $empleados = []; - while ($fila = $resultado->fetch_assoc()) { - $empleados[] = [ - 'id' => $fila['id'] ?? 0, - 'nombre' => htmlspecialchars($fila['nombre'] ?? ''), - 'email' => htmlspecialchars($fila['email'] ?? ''), - 'activo' => (int)($fila['activo'] ?? 1) - ]; - } - - echo json_encode([ - 'success' => true, - 'empleados' => $empleados, - 'total' => count($empleados) - ]); - } else { - throw new Exception('Error al ejecutar la consulta'); - } - - $stmt->close(); - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error del servidor: ' . $e->getMessage() - ]); -} - -// Cerrar conexión -if (isset($conexion)) { - $conexion->close(); -} -?> diff --git a/files/obtener_estados_pedidos_cliente.php b/files/obtener_estados_pedidos_cliente.php deleted file mode 100644 index e684ad7..0000000 --- a/files/obtener_estados_pedidos_cliente.php +++ /dev/null @@ -1,59 +0,0 @@ - false, 'message' => 'No autorizado']); - exit(); -} - -require_once 'conexion.php'; - -// Obtener el cuerpo de la petición -$input = json_decode(file_get_contents('php://input'), true); -$cliente_id = $input['cliente_id'] ?? $_SESSION['usuario_id']; - -// Verificar que el cliente_id coincida con la sesión -if ($cliente_id != $_SESSION['usuario_id']) { - echo json_encode(['success' => false, 'message' => 'Cliente no autorizado']); - exit(); -} - -try { - // Obtener todos los pedidos del cliente con sus estados actuales - $stmt = $conexion->prepare(" - SELECT p.ID_PEDIDO, ep.NOMBRE_ESTADO - FROM Pedidos p - INNER JOIN Estado_Pedidos ep ON p.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO - WHERE p.ID_CLIENTE = ? - ORDER BY p.FECHA_INGRESO DESC - "); - - $stmt->bind_param("i", $cliente_id); - $stmt->execute(); - $result = $stmt->get_result(); - - $pedidos = []; - while ($row = $result->fetch_assoc()) { - $pedidos[] = [ - 'id' => $row['ID_PEDIDO'], - 'estado' => $row['NOMBRE_ESTADO'] - ]; - } - - echo json_encode([ - 'success' => true, - 'pedidos' => $pedidos, - 'timestamp' => date('Y-m-d H:i:s') - ]); - -} catch (Exception $e) { - error_log("Error obteniendo estados de pedidos: " . $e->getMessage()); - echo json_encode([ - 'success' => false, - 'message' => 'Error del servidor' - ]); -} -?> diff --git a/files/obtener_ingredientes_ajax.php b/files/obtener_ingredientes_ajax.php deleted file mode 100644 index b268fb5..0000000 --- a/files/obtener_ingredientes_ajax.php +++ /dev/null @@ -1,80 +0,0 @@ - false, 'mensaje' => 'Acceso no autorizado']); - exit(); -} - -header('Content-Type: application/json'); -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception('Error de conexión a la base de datos'); - } - - // Consulta para obtener ingredientes con información de categoría y proveedor - $consulta = "SELECT - i.ID_INGREDIENTE as id, - i.NOMBRE_INGREDIENTE as nombre, - i.CANTIDAD_INGREDIENTE as cantidad, - i.FECHA_VENCIMIENTO as fecha_vencimiento, - i.REFERENCIA_INGREDIENTE as referencia, - i.FECHA_ENTREGA_INGREDIENTE as fecha_entrega, - c.NOMBRE_CATEGORIA_INGREDIENTE as categoria, - p.NOMBRE_PROV as proveedor - FROM Ingredientes i - LEFT JOIN Categoria_Ingredientes c ON i.ID_CATEGORIA = c.ID_CATEGORIA - LEFT JOIN Proveedores p ON i.ID_PROVEEDOR = p.ID_PROVEEDOR - ORDER BY i.ID_INGREDIENTE DESC"; - - $stmt = $conexion->prepare($consulta); - - if (!$stmt) { - throw new Exception('Error al preparar la consulta: ' . $conexion->error); - } - - $stmt->execute(); - $resultado = $stmt->get_result(); - - if ($resultado) { - $ingredientes = []; - while ($fila = $resultado->fetch_assoc()) { - $ingredientes[] = [ - 'id' => $fila['id'] ?? 0, - 'nombre' => htmlspecialchars($fila['nombre'] ?? ''), - 'cantidad' => $fila['cantidad'] ?? 0, - 'categoria' => htmlspecialchars($fila['categoria'] ?? ''), - 'proveedor' => htmlspecialchars($fila['proveedor'] ?? ''), - 'fecha_vencimiento' => !empty($fila['fecha_vencimiento']) ? date('d/m/Y', strtotime($fila['fecha_vencimiento'])) : '', - 'referencia' => htmlspecialchars($fila['referencia'] ?? ''), - 'fecha_entrega' => !empty($fila['fecha_entrega']) ? date('d/m/Y', strtotime($fila['fecha_entrega'])) : '' - ]; - } - - echo json_encode([ - 'success' => true, - 'ingredientes' => $ingredientes, - 'total' => count($ingredientes) - ]); - } else { - throw new Exception('Error al ejecutar la consulta'); - } - - $stmt->close(); - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error del servidor: ' . $e->getMessage() - ]); -} - -// Cerrar conexión -if (isset($conexion)) { - $conexion->close(); -} -?> diff --git a/files/obtener_ingredientes_proveedores_ajax.php b/files/obtener_ingredientes_proveedores_ajax.php deleted file mode 100644 index b6e80e5..0000000 --- a/files/obtener_ingredientes_proveedores_ajax.php +++ /dev/null @@ -1,94 +0,0 @@ - false, - 'error' => 'No autorizado' - ]); - exit(); -} - -require_once 'conexion.php'; - -try { - if (!$conexion) { - throw new Exception("Error de conexión a la base de datos"); - } - - // Consulta para obtener ingredientes con información del proveedor - $sql = "SELECT - i.ID_INGREDIENTE, - i.NOMBRE_INGREDIENTE, - i.CANTIDAD_INGREDIENTE as STOCK, - i.PRECIO_COMPRA, - i.REFERENCIA_INGREDIENTE, - i.FECHA_VENCIMIENTO, - i.FECHA_ENTREGA_INGREDIENTE, - p.NOMBRE_PROV as PROVEEDOR, - p.TELEFONO_PROV as TELEFONO_PROVEEDOR, - p.EMAIL_PROV as EMAIL_PROVEEDOR, - p.ID_PROVEEDOR, - c.NOMBRE_CATEGORIA_INGREDIENTE as CATEGORIA, - c.ID_CATEGORIA - FROM Ingredientes i - LEFT JOIN Proveedores p ON i.ID_PROVEEDOR = p.ID_PROVEEDOR - LEFT JOIN Categoria_Ingredientes c ON i.ID_CATEGORIA = c.ID_CATEGORIA - ORDER BY i.NOMBRE_INGREDIENTE ASC"; - - $result = $conexion->query($sql); - - if (!$result) { - throw new Exception("Error en la consulta: " . $conexion->error); - } - - $ingredientes = []; - while ($row = $result->fetch_assoc()) { - $ingredientes[] = array( - 'id' => $row['ID_INGREDIENTE'], - 'nombre' => $row['NOMBRE_INGREDIENTE'], - 'stock' => $row['STOCK'], - 'precio_compra' => $row['PRECIO_COMPRA'], - 'referencia' => $row['REFERENCIA_INGREDIENTE'], - 'fecha_vencimiento' => $row['FECHA_VENCIMIENTO'], - 'fecha_entrega' => $row['FECHA_ENTREGA_INGREDIENTE'], - 'proveedor' => $row['PROVEEDOR'] ?? 'Sin asignar', - 'telefono_proveedor' => $row['TELEFONO_PROVEEDOR'] ?? '', - 'email_proveedor' => $row['EMAIL_PROVEEDOR'] ?? '', - 'categoria' => $row['CATEGORIA'] ?? 'Sin categoría', - 'id_categoria' => $row['ID_CATEGORIA'], - 'id_proveedor' => $row['ID_PROVEEDOR'] - ); - } - - $response = array( - 'success' => true, - 'data' => $ingredientes, - 'total' => count($ingredientes) - ); - - echo json_encode($response); - -} catch (Exception $e) { - http_response_code(500); - $response = array( - 'success' => false, - 'error' => $e->getMessage() - ); - echo json_encode($response); -} - -$conexion->close(); -?> diff --git a/files/obtener_pedidos_ajax.php b/files/obtener_pedidos_ajax.php deleted file mode 100644 index d1d86e9..0000000 --- a/files/obtener_pedidos_ajax.php +++ /dev/null @@ -1,174 +0,0 @@ - session_id(), - 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'NO_SET', - 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'NO_SET', - 'all_session' => $_SESSION, - 'cookies' => $_COOKIE - ]; - - error_log("AJAX Auth Failed - Debug: " . json_encode($debug_info)); - - http_response_code(401); - echo json_encode([ - 'success' => false, - 'mensaje' => 'No autorizado. Debug info logged.', - 'debug' => $debug_info - ]); - exit(); -} - -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception("Error de conexión a la base de datos"); - } - - // Obtener datos del POST - $input = json_decode(file_get_contents('php://input'), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new Exception("Error al decodificar JSON: " . json_last_error_msg()); - } - - // Para debug, loggear los parámetros - error_log("Pedidos AJAX - Input: " . print_r($input, true)); - error_log("Pedidos AJAX - Session: " . print_r($_SESSION, true)); - - $estado = isset($input['estado']) ? $input['estado'] : ''; - $fecha = isset($input['fecha']) ? $input['fecha'] : ''; - $solo_pendientes = isset($input['solo_pendientes']) ? $input['solo_pendientes'] : false; - - // Primero, verificar si las tablas existen - $test_query = "SHOW TABLES LIKE 'Pedidos'"; - $test_result = $conexion->query($test_query); - if (!$test_result || $test_result->num_rows == 0) { - throw new Exception("La tabla 'Pedidos' no existe"); - } - - // Construir consulta con las tablas correctas - $query = " - SELECT - p.ID_PEDIDO as id, - COALESCE(c.NOMBRE_CLI, 'Cliente eliminado') as cliente, - COALESCE(e.NOMBRE_EMPLEADO, 'No asignado') as empleado, - p.FECHA_INGRESO as fecha_ingreso, - p.FECHA_ENTREGA as fecha_entrega, - p.TOTAL_PRODUCTO as total, - p.ID_ESTADO_PEDIDO as estado, - COALESCE(ep.NOMBRE_ESTADO, 'Estado desconocido') as estado_nombre - FROM Pedidos p - LEFT JOIN Clientes c ON p.ID_CLIENTE = c.ID_CLIENTE - LEFT JOIN Empleados e ON p.ID_EMPLEADO = e.ID_EMPLEADO - LEFT JOIN Estado_Pedidos ep ON p.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO - WHERE 1=1 - "; - - $params = []; - $types = ''; - - // Filtros - if ($solo_pendientes) { - $query .= " AND p.ID_ESTADO_PEDIDO IN (1, 2, 3)"; // Pendiente, Preparación, Listo - } - - if (!empty($estado)) { - $query .= " AND p.ID_ESTADO_PEDIDO = ?"; - $params[] = $estado; - $types .= 'i'; - } - - if (!empty($fecha)) { - $query .= " AND DATE(p.FECHA_INGRESO) = ?"; - $params[] = $fecha; - $types .= 's'; - } - - $query .= " ORDER BY p.FECHA_INGRESO DESC, p.ID_PEDIDO DESC LIMIT 50"; - - error_log("Pedidos AJAX - Query: " . $query); - error_log("Pedidos AJAX - Params: " . print_r($params, true)); - - $stmt = $conexion->prepare($query); - - if (!$stmt) { - throw new Exception("Error preparando consulta: " . $conexion->error); - } - - if (!empty($params)) { - $stmt->bind_param($types, ...$params); - } - - if (!$stmt->execute()) { - throw new Exception("Error ejecutando consulta: " . $stmt->error); - } - - $result = $stmt->get_result(); - - if (!$result) { - throw new Exception("Error obteniendo resultados: " . $stmt->error); - } - - $pedidos = []; - while ($row = $result->fetch_assoc()) { - $pedidos[] = [ - 'id' => (int)$row['id'], - 'cliente' => $row['cliente'] ?: 'Cliente eliminado', - 'empleado' => $row['empleado'] ?: 'No asignado', - 'fecha_ingreso' => $row['fecha_ingreso'], - 'fecha_entrega' => $row['fecha_entrega'], - 'total' => (float)$row['total'], - 'estado' => (int)$row['estado'], - 'estado_nombre' => $row['estado_nombre'] ?: 'Estado desconocido' - ]; - } - - error_log("Pedidos AJAX - Resultado: " . count($pedidos) . " pedidos encontrados"); - - echo json_encode([ - 'success' => true, - 'pedidos' => $pedidos, - 'total' => count($pedidos), - 'debug' => [ - 'query' => $query, - 'params' => $params, - 'session_user' => $_SESSION['usuario_id'] ?? 'no_set' - ] - ]); - -} catch (Exception $e) { - error_log("Error en obtener_pedidos_ajax.php: " . $e->getMessage()); - error_log("Error stack: " . $e->getTraceAsString()); - http_response_code(500); - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage(), - 'debug' => [ - 'file' => $e->getFile(), - 'line' => $e->getLine(), - 'session_info' => [ - 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'not_set', - 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'not_set' - ] - ] - ]); -} -?> diff --git a/files/obtener_pedidos_bypass.php b/files/obtener_pedidos_bypass.php deleted file mode 100644 index 4b056a4..0000000 --- a/files/obtener_pedidos_bypass.php +++ /dev/null @@ -1,63 +0,0 @@ -prepare($sql); - $stmt->execute(); - $pedidos = $stmt->fetchAll(PDO::FETCH_ASSOC); - - echo json_encode([ - 'success' => true, - 'pedidos' => $pedidos, - 'total' => count($pedidos), - 'mensaje' => 'Datos cargados con bypass - SOLO PARA TESTING', - 'session_info' => $_SESSION - ]); - -} catch (Exception $e) { - error_log("BYPASS Pedidos Error: " . $e->getMessage()); - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error: ' . $e->getMessage(), - 'session_info' => $_SESSION - ]); -} -?> diff --git a/files/obtener_producto_ajax.php b/files/obtener_producto_ajax.php deleted file mode 100644 index c0f857f..0000000 --- a/files/obtener_producto_ajax.php +++ /dev/null @@ -1,89 +0,0 @@ - false, - 'mensaje' => 'Método no permitido. Solo se acepta POST.' - ]); - exit(); -} - -// Verificar que se envió el ID -if (!isset($_POST['id']) || empty($_POST['id'])) { - echo json_encode([ - 'success' => false, - 'mensaje' => 'ID de producto requerido.' - ]); - exit(); -} - -$id_producto = intval($_POST['id']); - -try { - // Obtener información del producto usando PDO - $consulta_producto = "SELECT - ID_PRODUCTO, - NOMBRE_PRODUCTO, - PRECIO_PRODUCTO, - PRODUCTO_STOCK_MIN, - TIPO_PRODUCTO_MARCA, - FECHA_VENCIMIENTO_PRODUCTO, - COALESCE(ACTIVO, 1) as ACTIVO - FROM Productos - WHERE ID_PRODUCTO = :id"; - - $stmt_producto = $pdo_conexion->prepare($consulta_producto); - $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT); - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - - if (!$producto) { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Producto no encontrado.' - ]); - exit(); - } - - // Verificar referencias en detalle_pedidos - $consulta_referencias = "SELECT COUNT(*) as total FROM detalle_pedidos WHERE ID_PRODUCTO = :id"; - $stmt_referencias = $pdo_conexion->prepare($consulta_referencias); - $stmt_referencias->bindParam(':id', $id_producto, PDO::PARAM_INT); - $stmt_referencias->execute(); - $referencias_result = $stmt_referencias->fetch(PDO::FETCH_ASSOC); - $referencias = $referencias_result ? $referencias_result['total'] : 0; - - // Preparar respuesta - $response = [ - 'success' => true, - 'producto' => [ - 'id' => $producto['ID_PRODUCTO'], - 'nombre' => $producto['NOMBRE_PRODUCTO'], - 'precio' => $producto['PRECIO_PRODUCTO'], - 'stock' => $producto['PRODUCTO_STOCK_MIN'], - 'categoria' => $producto['TIPO_PRODUCTO_MARCA'], - 'fecha_vencimiento' => date('d/m/Y', strtotime($producto['FECHA_VENCIMIENTO_PRODUCTO'])), - 'activo' => $producto['ACTIVO'] - ], - 'referencias' => $referencias - ]; - - echo json_encode($response); - -} catch (PDOException $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error en la base de datos: ' . $e->getMessage() - ]); -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error inesperado: ' . $e->getMessage() - ]); -} -?> diff --git a/files/obtener_productos_ajax.php b/files/obtener_productos_ajax.php deleted file mode 100644 index 138263f..0000000 --- a/files/obtener_productos_ajax.php +++ /dev/null @@ -1,179 +0,0 @@ - session_id(), - 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'NO_SET', - 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'NO_SET', - 'all_session' => $_SESSION - ]; - - error_log("AJAX Auth Failed Productos - Debug: " . json_encode($debug_info)); - - http_response_code(401); - echo json_encode([ - 'success' => false, - 'mensaje' => 'No autorizado para productos. Debug info logged.' - ]); - exit(); -} - -require_once 'conexion.php'; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception("Error de conexión a la base de datos"); - } - - // Obtener datos del POST - $input = json_decode(file_get_contents('php://input'), true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new Exception("Error al decodificar JSON: " . json_last_error_msg()); - } - - // Para debug, loggear los parámetros - error_log("Productos AJAX - Input: " . print_r($input, true)); - - $buscar = isset($input['buscar']) ? trim($input['buscar']) : ''; - $estado = isset($input['estado']) ? $input['estado'] : ''; - $categoria = isset($input['categoria']) ? $input['categoria'] : ''; - - // Primero, verificar si las tablas existen - $test_query = "SHOW TABLES LIKE 'Productos'"; - $test_result = $conexion->query($test_query); - if (!$test_result || $test_result->num_rows == 0) { - throw new Exception("La tabla 'Productos' no existe"); - } - - // Construir consulta base - simplificada inicialmente - $query = " - SELECT - p.ID_PRODUCTO as id, - p.NOMBRE_PRODUCTO as nombre, - 'Sin categoría' as categoria, - p.PRECIO_PRODUCTO as precio, - p.PRODUCTO_STOCK_MIN as stock_min, - p.FECHA_VENCIMIENTO_PRODUCTO as vencimiento, - p.ACTIVO as activo - FROM Productos p - WHERE 1=1 - "; - - $params = []; - $types = ''; - - // Filtros - if (!empty($buscar)) { - $query .= " AND p.NOMBRE_PRODUCTO LIKE ?"; - $params[] = '%' . $buscar . '%'; - $types .= 's'; - } - - if ($estado !== '') { - $query .= " AND p.ACTIVO = ?"; - $params[] = (int)$estado; - $types .= 'i'; - } - - $query .= " ORDER BY p.NOMBRE_PRODUCTO ASC LIMIT 100"; - - error_log("Productos AJAX - Query: " . $query); - error_log("Productos AJAX - Params: " . print_r($params, true)); - - $stmt = $conexion->prepare($query); - - if (!$stmt) { - throw new Exception("Error preparando consulta: " . $conexion->error); - } - - if (!empty($params)) { - $stmt->bind_param($types, ...$params); - } - - if (!$stmt->execute()) { - throw new Exception("Error ejecutando consulta: " . $stmt->error); - } - - $result = $stmt->get_result(); - - if (!$result) { - throw new Exception("Error obteniendo resultados: " . $stmt->error); - } - - $productos = []; - while ($row = $result->fetch_assoc()) { - $productos[] = [ - 'id' => (int)$row['id'], - 'nombre' => $row['nombre'], - 'categoria' => $row['categoria'] ?: 'Sin categoría', - 'precio' => (float)$row['precio'], - 'stock_min' => (int)$row['stock_min'], - 'vencimiento' => $row['vencimiento'], - 'activo' => (bool)$row['activo'] - ]; - } - - // Obtener categorías (simplificado) - $categorias = []; - try { - $cat_query = "SHOW TABLES LIKE 'Categoria_Productos'"; - $cat_result = $conexion->query($cat_query); - if ($cat_result && $cat_result->num_rows > 0) { - $categorias_query = "SELECT ID_CATEGORIA_PRODUCTO as id, NOMBRE_CATEGORIAPRODUCTO as nombre FROM Categoria_Productos ORDER BY NOMBRE_CATEGORIAPRODUCTO LIMIT 20"; - $categorias_result = $conexion->query($categorias_query); - - if ($categorias_result) { - while ($cat = $categorias_result->fetch_assoc()) { - $categorias[] = [ - 'id' => (int)$cat['id'], - 'nombre' => $cat['nombre'] - ]; - } - } - } - } catch (Exception $cat_error) { - error_log("Error cargando categorías: " . $cat_error->getMessage()); - } - - error_log("Productos AJAX - Resultado: " . count($productos) . " productos encontrados"); - - echo json_encode([ - 'success' => true, - 'productos' => $productos, - 'categorias' => $categorias, - 'total' => count($productos), - 'debug' => [ - 'query' => $query, - 'params' => $params - ] - ]); - -} catch (Exception $e) { - error_log("Error en obtener_productos_ajax.php: " . $e->getMessage()); - error_log("Error stack: " . $e->getTraceAsString()); - http_response_code(500); - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage(), - 'debug' => [ - 'file' => $e->getFile(), - 'line' => $e->getLine() - ] - ]); -} -?> diff --git a/files/obtener_proveedores_ajax.php b/files/obtener_proveedores_ajax.php deleted file mode 100644 index 6295bbe..0000000 --- a/files/obtener_proveedores_ajax.php +++ /dev/null @@ -1,65 +0,0 @@ - false, - 'error' => 'No autorizado' - ]); - exit(); -} - -require_once 'conexion.php'; - -try { - // Consulta para obtener proveedores activos - $consulta = "SELECT - ID_PROVEEDOR as id, - NOMBRE_PROV as nombre - FROM Proveedores - WHERE ACTIVO_PROV = 1 - ORDER BY NOMBRE_PROV ASC"; - - $resultado = $conexion->query($consulta); - - if ($resultado) { - $proveedores = []; - while ($fila = $resultado->fetch_assoc()) { - $proveedores[] = [ - 'id' => $fila['id'], - 'nombre' => $fila['nombre'] - ]; - } - - echo json_encode([ - 'success' => true, - 'proveedores' => $proveedores - ]); - } else { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error en la consulta: ' . $conexion->error - ]); - } - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => 'Error del servidor: ' . $e->getMessage() - ]); -} - -$conexion->close(); -?> diff --git a/files/on_off.php b/files/on_off.php deleted file mode 100644 index ada7a96..0000000 --- a/files/on_off.php +++ /dev/null @@ -1,273 +0,0 @@ -alert('Método no permitido. Use POST.'); window.history.back();"; - exit(); -} - -// Verificar si se recibió el ID del producto y el estado actual -if (isset($_POST['id']) && !empty($_POST['id']) && isset($_POST['estado'])) { - $id_producto = $_POST['id']; - $estado_actual = $_POST['estado']; - - // Determinar el nuevo estado (invertir el actual) - $nuevo_estado = ($estado_actual == 1) ? 0 : 1; - $accion_texto = ($nuevo_estado == 1) ? "activado" : "desactivado"; - - try { - // Obtener información del producto antes del cambio - $consulta_producto = "SELECT NOMBRE_PRODUCTO, ACTIVO FROM Productos WHERE ID_PRODUCTO = :id"; - $stmt_producto = $pdo_conexion->prepare($consulta_producto); - $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT); - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - - if ($producto) { - $nombre_producto = $producto['NOMBRE_PRODUCTO']; - - // Actualizar el estado del producto - $consulta_update = "UPDATE Productos SET ACTIVO = :nuevo_estado WHERE ID_PRODUCTO = :id"; - $stmt_update = $pdo_conexion->prepare($consulta_update); - $stmt_update->bindParam(':nuevo_estado', $nuevo_estado, PDO::PARAM_INT); - $stmt_update->bindParam(':id', $id_producto, PDO::PARAM_INT); - - if ($stmt_update->execute()) { - $mensaje = "El producto '{$nombre_producto}' ha sido {$accion_texto} exitosamente."; - $tipo_mensaje = "success"; - } else { - $mensaje = "Error: No se pudo cambiar el estado del producto."; - $tipo_mensaje = "error"; - } - } else { - $mensaje = "Error: El producto no existe."; - $tipo_mensaje = "error"; - } - - } catch (PDOException $e) { - $mensaje = "Error en la base de datos: " . $e->getMessage(); - $tipo_mensaje = "error"; - } -} else { - $mensaje = "Error: Parámetros no válidos."; - $tipo_mensaje = "error"; -} -?> - - - - - - - Cambiar Estado - Panadería - - - -
- -
-

Estado Cambiado

- -
-

Error al Cambiar Estado

- - -
- -
- - -
-

Información del Cambio:

-

Producto:

-

Nuevo Estado: - - ✓ Activo - - ✗ Inactivo - -

-

Fecha del Cambio:

-
- -
-

💡 Información Importante:

-
    - -
  • El producto está ahora INACTIVO y no aparecerá en búsquedas normales
  • -
  • Los pedidos existentes que contienen este producto NO se ven afectados
  • -
  • Puedes reactivarlo en cualquier momento
  • - -
  • El producto está ahora ACTIVO y disponible para nuevos pedidos
  • -
  • Aparecerá en todas las búsquedas y listados normales
  • -
  • Los clientes pueden volver a pedirlo
  • - -
-
- - -
- -
- -
- ⏱️ Por favor, lee toda la información mostrada arriba antes de continuar. - El botón se activará en 5 segundos. -
-
- - - - diff --git a/files/pedidos.php b/files/pedidos.php deleted file mode 100644 index 2d39512..0000000 --- a/files/pedidos.php +++ /dev/null @@ -1,557 +0,0 @@ -setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); -} catch(PDOException $e) { - $error_msg = "Error al conectar con la base de datos: " . $e->getMessage(); -} - -// Calcular totales -$subtotal = 0; -$carrito_items = []; - -if (!empty($_SESSION['carrito'])) { - foreach ($_SESSION['carrito'] as $item) { - $subtotal += $item['precio'] * $item['cantidad']; - $carrito_items[] = $item; - } -} - -$iva = $subtotal * 0.19; -$total = $subtotal + $iva; -?> - - - - - - - Mis Pedidos - El Castillo del Pan - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - -
-
-
-
-

- Mi Carrito de Compras -

-
-
- - -
-
-
-

Productos Seleccionados

-
- -
-
-
- <?php echo htmlspecialchars($item['nombre']); ?> -
-
-
-

Precio unitario: $

-
-
-
- - - -
- Stock: -
-
-

$

- -
-
-
- -
- -
-
- Cargando... -
-
-
-
- -
-
-

Resumen del Pedido

-
- Subtotal: - $ -
-
- IVA (19%): - $ -
-
-
- Total: - $ -
- - - - - Continuar Comprando - -
-
-
- -
-
-
-
- -

Tu carrito está vacío

-

¡Agrega algunos productos deliciosos a tu carrito!

- - Ver Menú - -
-
-
-
- -
-
- - -
-
-
-
-
- - El Castillo del Pan -
-

- Panadería artesanal con más de 10 años de experiencia. -

-
-
-
Enlaces Rápidos
- -
-
-
Contacto
-

- (555) 123-4567 -

-

- info@elcastillodelpan.com -

-
-
-
-
-

- © 2024 El Castillo del Pan. Todos los derechos reservados. -

-
-
-
- - - - - - - - diff --git a/files/pedidos_historial.php b/files/pedidos_historial.php deleted file mode 100644 index 0345e35..0000000 --- a/files/pedidos_historial.php +++ /dev/null @@ -1,407 +0,0 @@ - - - - - - - - Historial de Pedidos - Admin - - - - - - - - -
-
-

Historial de Pedidos

-
- -
-
- -
-
- - - - - - - - - - - - - - 0): ?> - - - - - - - - - - - - - - - - - -
ID PedidoClienteEmailFechaTotalEstadoAcciones
#$ - - - - - -
- - -
-
- -

No hay pedidos registrados

-
-
-
-
- - - - - - - - - - diff --git a/files/perfil_admin.php b/files/perfil_admin.php deleted file mode 100644 index dbbce57..0000000 --- a/files/perfil_admin.php +++ /dev/null @@ -1,242 +0,0 @@ -prepare("UPDATE Administradores SET NOMBRE_ADMIN = ?, TELEFONO_ADMIN = ?, EMAIL_ADMIN = ? WHERE ID_ADMIN = ?"); - $stmt->bind_param("sssi", $nuevo_nombre, $nuevo_telefono, $nuevo_email, $_SESSION['usuario_id']); - - if ($stmt->execute()) { - $_SESSION['usuario_nombre'] = $nuevo_nombre; - $mensaje = "Perfil actualizado correctamente"; - $tipo_mensaje = "success"; - } else { - $mensaje = "Error al actualizar el perfil"; - $tipo_mensaje = "error"; - } - } catch (Exception $e) { - $mensaje = "Error: " . $e->getMessage(); - $tipo_mensaje = "error"; - } - } -} - -// Obtener datos actuales del administrador -$admin_data = null; -try { - // Verificar que tenemos el ID de usuario - if (!isset($_SESSION['usuario_id'])) { - throw new Exception("ID de usuario no encontrado en la sesión"); - } - - $stmt = $conexion->prepare("SELECT * FROM Administradores WHERE ID_ADMIN = ?"); - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $result = $stmt->get_result(); - $admin_data = $result->fetch_assoc(); - - if (!$admin_data) { - throw new Exception("No se encontraron datos del administrador"); - } -} catch (Exception $e) { - error_log("Error en perfil_admin.php: " . $e->getMessage()); - $mensaje = "Error al cargar datos del perfil: " . $e->getMessage(); - $tipo_mensaje = "error"; -} -?> - - - - - - - Mi Perfil - Administrador - - - - - - - - -
- - - - - - -
-
-
-
-
- -
-

-

Administrador del Sistema

-
- -
-
-
- - -
-
- - -
-
-
- - -
- -
- -
-
-
-
-
-
- - - - - - diff --git a/files/perfil_cliente.php b/files/perfil_cliente.php deleted file mode 100644 index f7258b7..0000000 --- a/files/perfil_cliente.php +++ /dev/null @@ -1,245 +0,0 @@ -prepare("UPDATE Clientes SET NOMBRE_CLI = ?, TELEFONO_CLI = ?, EMAIL_CLI = ? WHERE ID_CLIENTE = ?"); - $stmt->bind_param("sssi", $nuevo_nombre, $nuevo_telefono, $nuevo_email, $_SESSION['usuario_id']); - - if ($stmt->execute()) { - $_SESSION['usuario_nombre'] = $nuevo_nombre; - $mensaje = "Perfil actualizado correctamente"; - $tipo_mensaje = "success"; - } else { - $mensaje = "Error al actualizar el perfil"; - $tipo_mensaje = "error"; - } - } catch (Exception $e) { - $mensaje = "Error: " . $e->getMessage(); - $tipo_mensaje = "error"; - } - } -} - -// Obtener datos actuales del cliente -$cliente_data = null; -try { - // Verificar que tenemos el ID de usuario - if (!isset($_SESSION['usuario_id'])) { - throw new Exception("ID de usuario no encontrado en la sesión"); - } - - $stmt = $conexion->prepare("SELECT * FROM Clientes WHERE ID_CLIENTE = ?"); - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $result = $stmt->get_result(); - $cliente_data = $result->fetch_assoc(); - - if (!$cliente_data) { - throw new Exception("No se encontraron datos del cliente"); - } -} catch (Exception $e) { - error_log("Error en perfil_cliente.php: " . $e->getMessage()); - $mensaje = "Error al cargar datos del perfil: " . $e->getMessage(); - $tipo_mensaje = "error"; -} -?> - - - - - - - Mi Perfil - Cliente - - - - - - - - -
-
-
-

- Mi Perfil -

- - Volver al Dashboard - -
- - - - - -
-
-
-
-
- -
-

-

Cliente de El Castillo del Pan

-
- -
-
-
- - -
-
- - -
-
-
- - -
- -
- -
-
-
-
-
-
-
- - - - - - diff --git a/files/perfil_empleado.php b/files/perfil_empleado.php deleted file mode 100644 index bc5f915..0000000 --- a/files/perfil_empleado.php +++ /dev/null @@ -1,241 +0,0 @@ -prepare("UPDATE Empleados SET NOMBRE_EMPLEADO = ?, EMAIL_EMPLEADO = ? WHERE ID_EMPLEADO = ?"); - $stmt->bind_param("ssi", $nuevo_nombre, $nuevo_email, $_SESSION['usuario_id']); - - if ($stmt->execute()) { - $_SESSION['usuario_nombre'] = $nuevo_nombre; - $mensaje = "Perfil actualizado correctamente"; - $tipo_mensaje = "success"; - } else { - $mensaje = "Error al actualizar el perfil"; - $tipo_mensaje = "error"; - } - } catch (Exception $e) { - $mensaje = "Error: " . $e->getMessage(); - $tipo_mensaje = "error"; - } - } -} - -// Obtener datos actuales del empleado -$empleado_data = null; -try { - // Verificar que tenemos el ID de usuario - if (!isset($_SESSION['usuario_id'])) { - throw new Exception("ID de usuario no encontrado en la sesión"); - } - - $stmt = $conexion->prepare("SELECT * FROM Empleados WHERE ID_EMPLEADO = ?"); - $stmt->bind_param("i", $_SESSION['usuario_id']); - $stmt->execute(); - $result = $stmt->get_result(); - $empleado_data = $result->fetch_assoc(); - - if (!$empleado_data) { - throw new Exception("No se encontraron datos del empleado"); - } -} catch (Exception $e) { - error_log("Error en perfil_empleado.php: " . $e->getMessage()); - $mensaje = "Error al cargar datos del perfil: " . $e->getMessage(); - $tipo_mensaje = "error"; -} -?> - - - - - - - Mi Perfil - Empleado - - - - - - - - -
-
-
-

- Mi Perfil -

- - Volver al Dashboard - -
- - - - - -
-
-
-
-
- -
-

-

Empleado de El Castillo del Pan

-
- -
-
-
- - -
-
- - -
-
-
- - -
- -
- -
-
-
-
-
-
-
- - - - - - diff --git a/files/procesar.php b/files/procesar.php deleted file mode 100644 index 9967e14..0000000 --- a/files/procesar.php +++ /dev/null @@ -1,42 +0,0 @@ -prepare($sql); - - $resultado = $consulta->execute([ - $nombre, - $telefono, - $email, - $contraseña_encriptada, - $salt - ]); - - if($resultado) { - echo "

✅ Cliente registrado exitosamente

"; - echo "

ID del cliente: " . $pdo_conexion->lastInsertId() . "

"; - echo "

Nombre: " . htmlspecialchars($nombre) . "

"; - echo "

Email: " . htmlspecialchars($email) . "

"; - echo "
Registrar otro cliente"; - } - - } catch(PDOException $e) { - echo "

❌ Error al registrar cliente

"; - echo "

Error: " . $e->getMessage() . "

"; - echo "
Volver al formulario"; - } -} else { - echo "

No hay datos para procesar

"; - echo "Ir al formulario"; -} -?> \ No newline at end of file diff --git a/files/procesar_carrito.php b/files/procesar_carrito.php deleted file mode 100644 index b7afc97..0000000 --- a/files/procesar_carrito.php +++ /dev/null @@ -1,269 +0,0 @@ - false, 'message' => 'Usuario no autenticado']); - exit(); -} - -// Configuración de la base de datos -$host = 'localhost'; -$db_name = 'proyectopanaderia'; -$username = 'root'; -$password = ''; - -try { - $pdo = new PDO("mysql:host=$host;dbname=$db_name;charset=utf8", $username, $password); - $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); -} catch(PDOException $e) { - echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']); - exit(); -} - -// Verificar el método de la solicitud -$method = $_SERVER['REQUEST_METHOD']; -$input = json_decode(file_get_contents('php://input'), true); - -// Inicializar carrito si no existe -if (!isset($_SESSION['carrito'])) { - $_SESSION['carrito'] = []; -} - -switch ($method) { - case 'POST': - if (isset($input['accion'])) { - switch ($input['accion']) { - case 'agregar': - agregarProducto($pdo, $input); - break; - case 'actualizar': - actualizarCantidad($input); - break; - case 'eliminar': - eliminarProducto($input); - break; - case 'finalizar': - finalizarPedido($pdo, $input); - break; - case 'obtener_carrito': - obtenerCarrito($pdo); - break; - default: - echo json_encode(['success' => false, 'message' => 'Acción no válida']); - } - } else { - echo json_encode(['success' => false, 'message' => 'Acción no especificada']); - } - break; - default: - echo json_encode(['success' => false, 'message' => 'Método no permitido']); -} - -function agregarProducto($pdo, $input) { - $producto_id = $input['producto_id'] ?? null; - $cantidad = $input['cantidad'] ?? 1; - - if (!$producto_id) { - echo json_encode(['success' => false, 'message' => 'ID de producto no especificado']); - return; - } - - // Verificar que el producto existe y está activo - $stmt = $pdo->prepare("SELECT * FROM Productos WHERE ID_PRODUCTO = ? AND ACTIVO = 1"); - $stmt->execute([$producto_id]); - $producto = $stmt->fetch(PDO::FETCH_ASSOC); - - if (!$producto) { - echo json_encode(['success' => false, 'message' => 'Producto no encontrado o no disponible']); - return; - } - - // Verificar stock disponible - if ($producto['PRODUCTO_STOCK_MIN'] < $cantidad) { - echo json_encode(['success' => false, 'message' => 'Stock insuficiente']); - return; - } - - // Agregar o actualizar producto en el carrito - if (isset($_SESSION['carrito'][$producto_id])) { - $nueva_cantidad = $_SESSION['carrito'][$producto_id]['cantidad'] + $cantidad; - if ($nueva_cantidad > $producto['PRODUCTO_STOCK_MIN']) { - echo json_encode(['success' => false, 'message' => 'Stock insuficiente para la cantidad solicitada']); - return; - } - $_SESSION['carrito'][$producto_id]['cantidad'] = $nueva_cantidad; - } else { - $_SESSION['carrito'][$producto_id] = [ - 'id' => $producto_id, - 'nombre' => $producto['NOMBRE_PRODUCTO'], - 'precio' => $producto['PRECIO_PRODUCTO'], - 'cantidad' => $cantidad, - 'stock_disponible' => $producto['PRODUCTO_STOCK_MIN'] - ]; - } - - echo json_encode([ - 'success' => true, - 'message' => 'Producto agregado al carrito', - 'carrito_count' => array_sum(array_column($_SESSION['carrito'], 'cantidad')) - ]); -} - -function actualizarCantidad($input) { - $producto_id = $input['producto_id'] ?? null; - $cantidad = $input['cantidad'] ?? 1; - - if (!$producto_id || $cantidad < 1) { - echo json_encode(['success' => false, 'message' => 'Datos inválidos']); - return; - } - - if (isset($_SESSION['carrito'][$producto_id])) { - // Verificar stock disponible - if ($cantidad > $_SESSION['carrito'][$producto_id]['stock_disponible']) { - echo json_encode(['success' => false, 'message' => 'Stock insuficiente']); - return; - } - - $_SESSION['carrito'][$producto_id]['cantidad'] = $cantidad; - echo json_encode([ - 'success' => true, - 'message' => 'Cantidad actualizada', - 'carrito_count' => array_sum(array_column($_SESSION['carrito'], 'cantidad')) - ]); - } else { - echo json_encode(['success' => false, 'message' => 'Producto no encontrado en el carrito']); - } -} - -function eliminarProducto($input) { - $producto_id = $input['producto_id'] ?? null; - - if (!$producto_id) { - echo json_encode(['success' => false, 'message' => 'ID de producto no especificado']); - return; - } - - if (isset($_SESSION['carrito'][$producto_id])) { - unset($_SESSION['carrito'][$producto_id]); - echo json_encode([ - 'success' => true, - 'message' => 'Producto eliminado del carrito', - 'carrito_count' => array_sum(array_column($_SESSION['carrito'], 'cantidad')) - ]); - } else { - echo json_encode(['success' => false, 'message' => 'Producto no encontrado en el carrito']); - } -} - -function finalizarPedido($pdo, $input) { - if (empty($_SESSION['carrito'])) { - echo json_encode(['success' => false, 'message' => 'El carrito está vacío']); - return; - } - - $user_id = $_SESSION['usuario_id'] ?? null; - - if (!$user_id) { - echo json_encode(['success' => false, 'message' => 'Usuario no identificado']); - return; - } - - try { - $pdo->beginTransaction(); - - // Calcular total del pedido - $total = 0; - foreach ($_SESSION['carrito'] as $item) { - $total += $item['precio'] * $item['cantidad']; - } - - $iva = $total * 0.19; - $total_con_iva = $total + $iva; - - // Insertar pedido en la base de datos - $stmt = $pdo->prepare(" - INSERT INTO Pedidos (ID_CLIENTE, ID_ESTADO_PEDIDO, FECHA_INGRESO, FECHA_ENTREGA, TOTAL_PRODUCTO) - VALUES (?, 1, NOW(), DATE_ADD(NOW(), INTERVAL 1 DAY), ?) - "); - $stmt->execute([$user_id, $total_con_iva]); - $pedido_id = $pdo->lastInsertId(); - - // Insertar detalles del pedido y actualizar stock - foreach ($_SESSION['carrito'] as $item) { - // Verificar stock actual - $stmt = $pdo->prepare("SELECT PRODUCTO_STOCK_MIN FROM Productos WHERE ID_PRODUCTO = ?"); - $stmt->execute([$item['id']]); - $stock_actual = $stmt->fetchColumn(); - - if ($stock_actual < $item['cantidad']) { - throw new Exception("Stock insuficiente para el producto: " . $item['nombre']); - } - - // Calcular subtotal - $subtotal = $item['precio'] * $item['cantidad']; - - // Insertar detalle del pedido - $stmt = $pdo->prepare(" - INSERT INTO Detalle_Pedidos (ID_PEDIDO, ID_PRODUCTO, CANTIDAD_PRODUCTO, PRECIO_UNITARIO, SUBTOTAL) - VALUES (?, ?, ?, ?, ?) - "); - $stmt->execute([$pedido_id, $item['id'], $item['cantidad'], $item['precio'], $subtotal]); - - // Actualizar stock - $stmt = $pdo->prepare(" - UPDATE Productos - SET PRODUCTO_STOCK_MIN = PRODUCTO_STOCK_MIN - ? - WHERE ID_PRODUCTO = ? - "); - $stmt->execute([$item['cantidad'], $item['id']]); - } - - $pdo->commit(); - - // Limpiar carrito - $_SESSION['carrito'] = []; - - echo json_encode([ - 'success' => true, - 'message' => 'Pedido realizado con éxito', - 'pedido_id' => $pedido_id, - 'total' => $total_con_iva - ]); - - } catch (Exception $e) { - $pdo->rollBack(); - echo json_encode(['success' => false, 'message' => 'Error al procesar el pedido: ' . $e->getMessage()]); - } -} - -function obtenerCarrito($pdo) { - $carrito_info = []; - $total = 0; - - foreach ($_SESSION['carrito'] as $item) { - // Verificar stock actual - $stmt = $pdo->prepare("SELECT PRODUCTO_STOCK_MIN FROM Productos WHERE ID_PRODUCTO = ?"); - $stmt->execute([$item['id']]); - $stock_actual = $stmt->fetchColumn(); - - $item['stock_disponible'] = $stock_actual; - $carrito_info[] = $item; - $total += $item['precio'] * $item['cantidad']; - } - - $iva = $total * 0.19; - $total_con_iva = $total + $iva; - - echo json_encode([ - 'success' => true, - 'carrito' => $carrito_info, - 'subtotal' => $total, - 'iva' => $iva, - 'total' => $total_con_iva, - 'carrito_count' => array_sum(array_column($_SESSION['carrito'], 'cantidad')) - ]); -} -?> diff --git a/files/procesar_login.php b/files/procesar_login.php deleted file mode 100644 index dc56b40..0000000 --- a/files/procesar_login.php +++ /dev/null @@ -1,189 +0,0 @@ -prepare($consulta); - $stmt->bindParam(':usuario', $usuario, PDO::PARAM_STR); - $stmt->execute(); - - $user_data = $stmt->fetch(PDO::FETCH_ASSOC); - - // Log para debug - error_log("Login Debug - Tipo: $tipo_usuario, Usuario buscado: $usuario, Usuario encontrado: " . ($user_data ? "SÍ" : "NO")); - - if ($user_data) { - // Usuario encontrado, verificar contraseña - $password_hash = ""; - $salt = ""; - - switch ($tipo_usuario) { - case 'admin': - $password_hash = $user_data['CONTRASEÑA_ADMIN']; - $salt = $user_data['SALT_ADMIN']; - break; - case 'empleado': - $password_hash = $user_data['CONTRASEÑA_EMPLEADO']; - $salt = $user_data['SALT_EMPLEADO']; - break; - case 'cliente': - $password_hash = $user_data['CONTRASEÑA_CLI']; - $salt = $user_data['SALT_CLI']; - break; - } - - // Verificar la contraseña - $password_valid = false; - - // Log para debug de verificación de contraseña - error_log("Verificando contraseña - Salt: " . ($salt ? "SÍ" : "NO") . ", Hash almacenado: " . ($password_hash ? "SÍ" : "NO")); - - if (!empty($salt) && !empty($password_hash)) { - // Verificar con hash SHA256 + salt (sistema actual) - $hash_to_check = hash('sha256', $password . $salt); - error_log("Hash generado para verificación: " . substr($hash_to_check, 0, 20) . "..."); - error_log("Hash almacenado en BD: " . substr($password_hash, 0, 20) . "..."); - - if ($hash_to_check === $password_hash) { - $password_valid = true; - error_log("Contraseña válida con hash SHA256"); - } - } elseif (!empty($password_hash)) { - // Verificar contraseña en texto plano (compatibilidad) - if ($password === $password_hash) { - $password_valid = true; - error_log("Contraseña válida en texto plano"); - } - } - - error_log("Resultado verificación de contraseña: " . ($password_valid ? "VÁLIDA" : "INVÁLIDA")); - - if ($password_valid) { - // Contraseña correcta, crear sesión - $_SESSION['usuario_logueado'] = true; - $_SESSION['usuario_tipo'] = $tipo_usuario; - $_SESSION['usuario_id'] = $user_data[$id_campo]; - $_SESSION['usuario_nombre'] = $user_data[$nombre_campo]; - - // Variables adicionales para compatibilidad - $_SESSION['user_name'] = $user_data[$nombre_campo]; - $_SESSION['role'] = $tipo_usuario; - - // Información adicional según el tipo de usuario - if ($tipo_usuario === 'admin') { - $_SESSION['usuario_email'] = $user_data['EMAIL_ADMIN'] ?? ''; - $_SESSION['usuario_telefono'] = $user_data['TELEFONO_ADMIN'] ?? ''; - } elseif ($tipo_usuario === 'cliente') { - $_SESSION['usuario_email'] = $user_data['EMAIL_CLI']; - $_SESSION['usuario_telefono'] = $user_data['TELEFONO_CLI'] ?? ''; - // Variable específica para el procesamiento de pedidos - $_SESSION['cliente_id'] = $user_data['ID_CLIENTE']; - } - - // Log del login exitoso - error_log("Login exitoso - Tipo: $tipo_usuario, Usuario: " . $user_data[$nombre_campo] . ", IP: " . $_SERVER['REMOTE_ADDR']); - - // Redirigir según el tipo de usuario - switch ($tipo_usuario) { - case 'admin': - header("Location: dashboard_admin.php"); - break; - case 'empleado': - header("Location: dashboard_empleado.php"); - break; - case 'cliente': - header("Location: dashboard_cliente.php"); - break; - } - exit(); - - } else { - // Contraseña incorrecta - header("Location: login.php?error=invalid_credentials"); - exit(); - } - - } else { - // Usuario no encontrado - header("Location: login.php?error=invalid_credentials"); - exit(); - } - - } catch (PDOException $e) { - // Error en la base de datos - error_log("Error de login (PDO): " . $e->getMessage() . " - Usuario: $usuario, Tipo: $tipo_usuario"); - header("Location: login.php?error=database_error&detail=" . urlencode($e->getMessage())); - exit(); - } catch (Exception $e) { - // Error general - error_log("Error de login (General): " . $e->getMessage() . " - Usuario: $usuario, Tipo: $tipo_usuario"); - header("Location: login.php?error=database_error&detail=" . urlencode($e->getMessage())); - exit(); - } - -} else { - // Acceso directo sin POST - header("Location: login.php"); - exit(); -} -?> diff --git a/files/procesar_pedido.php b/files/procesar_pedido.php deleted file mode 100644 index eb81bb0..0000000 --- a/files/procesar_pedido.php +++ /dev/null @@ -1,190 +0,0 @@ -setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - // Manejar solicitudes OPTIONS para CORS - if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { - http_response_code(200); - exit; - } - - // Solo permitir POST para pedidos - if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - throw new Exception('Método no permitido'); - } - - // Obtener datos del pedido - $input = json_decode(file_get_contents('php://input'), true); - - if (!$input) { - throw new Exception('Datos de pedido inválidos'); - } - - $producto_id = isset($input['producto_id']) ? (int)$input['producto_id'] : 0; - $cantidad = isset($input['cantidad']) ? (int)$input['cantidad'] : 1; - - // Validaciones básicas - if ($producto_id <= 0) { - throw new Exception('ID de producto inválido'); - } - - if ($cantidad <= 0) { - throw new Exception('Cantidad inválida'); - } - - // Verificar si el usuario está logueado - if (!validarSesionCliente()) { - throw new Exception('Debe iniciar sesión para realizar pedidos'); - } - - $cliente_id = $_SESSION['cliente_id']; - - // Iniciar transacción - $pdo->beginTransaction(); - - try { - // Verificar que el producto existe y está activo - $stmt = $pdo->prepare(" - SELECT - ID_PRODUCTO, - NOMBRE_PRODUCTO, - PRECIO_PRODUCTO, - PRODUCTO_STOCK_MIN, - ACTIVO - FROM Productos - WHERE ID_PRODUCTO = ? AND ACTIVO = 1 - FOR UPDATE - "); - $stmt->execute([$producto_id]); - $producto = $stmt->fetch(PDO::FETCH_ASSOC); - - if (!$producto) { - throw new Exception('Producto no encontrado o no disponible'); - } - - // Verificar stock disponible - if ($producto['PRODUCTO_STOCK_MIN'] < $cantidad) { - throw new Exception('Stock insuficiente. Stock disponible: ' . $producto['PRODUCTO_STOCK_MIN']); - } - - // Verificar que el stock no quede negativo - if ($producto['PRODUCTO_STOCK_MIN'] - $cantidad < 0) { - throw new Exception('No se puede procesar el pedido. Stock insuficiente'); - } - - // Descontar stock - $nuevo_stock = $producto['PRODUCTO_STOCK_MIN'] - $cantidad; - $stmt = $pdo->prepare(" - UPDATE Productos - SET PRODUCTO_STOCK_MIN = ?, - FECHA_ULTIMA_MODIFICACION = NOW() - WHERE ID_PRODUCTO = ? - "); - $stmt->execute([$nuevo_stock, $producto_id]); - - // Verificar que la actualización fue exitosa - if ($stmt->rowCount() === 0) { - throw new Exception('Error al actualizar el stock'); - } - - // Registrar el pedido en la tabla de pedidos - // Primero obtener el ID del estado "Pendiente" - $stmt = $pdo->prepare("SELECT ID_ESTADO_PEDIDO FROM Estado_Pedidos WHERE NOMBRE_ESTADO = 'Pendiente'"); - $stmt->execute(); - $estado_pendiente = $stmt->fetch(PDO::FETCH_ASSOC); - - $pedido_id = null; - if ($estado_pendiente) { - // Crear registro de pedido - $stmt = $pdo->prepare(" - INSERT INTO Pedidos (ID_CLIENTE, ID_ESTADO_PEDIDO, FECHA_INGRESO, FECHA_ENTREGA, TOTAL_PRODUCTO) - VALUES (?, ?, NOW(), DATE_ADD(NOW(), INTERVAL 1 DAY), ?) - "); - $total_pedido = $producto['PRECIO_PRODUCTO'] * $cantidad; - $stmt->execute([$cliente_id, $estado_pendiente['ID_ESTADO_PEDIDO'], $total_pedido]); - $pedido_id = $pdo->lastInsertId(); - - // Registrar detalle del pedido - $subtotal = $producto['PRECIO_PRODUCTO'] * $cantidad; - $stmt = $pdo->prepare(" - INSERT INTO Detalle_Pedidos (ID_PEDIDO, ID_PRODUCTO, CANTIDAD_PRODUCTO, PRECIO_UNITARIO, SUBTOTAL) - VALUES (?, ?, ?, ?, ?) - "); - $stmt->execute([$pedido_id, $producto_id, $cantidad, $producto['PRECIO_PRODUCTO'], $subtotal]); - } - - // Confirmar transacción - $pdo->commit(); - - // Log de actividad exitosa - logActividad("Pedido procesado exitosamente - Producto: {$producto['NOMBRE_PRODUCTO']}, Cantidad: $cantidad, Stock restante: $nuevo_stock", $cliente_id); - - // Respuesta exitosa - echo json_encode([ - 'success' => true, - 'mensaje' => 'Pedido procesado exitosamente', - 'producto' => [ - 'id' => $producto_id, - 'nombre' => $producto['NOMBRE_PRODUCTO'], - 'precio' => $producto['PRECIO_PRODUCTO'], - 'cantidad_pedida' => $cantidad, - 'stock_restante' => $nuevo_stock, - 'total' => $producto['PRECIO_PRODUCTO'] * $cantidad - ], - 'pedido_id' => $pedido_id, - 'timestamp' => time() - ]); - - } catch (Exception $e) { - // Rollback en caso de error - $pdo->rollback(); - throw $e; - } - -} catch (PDOException $e) { - logActividad("Error de base de datos: " . $e->getMessage()); - echo json_encode([ - 'success' => false, - 'error' => 'Error de base de datos: ' . $e->getMessage() - ]); -} catch (Exception $e) { - logActividad("Error del servidor: " . $e->getMessage()); - echo json_encode([ - 'success' => false, - 'error' => $e->getMessage() - ]); -} -?> diff --git a/files/procesar_registro.php b/files/procesar_registro.php deleted file mode 100644 index ab957c7..0000000 --- a/files/procesar_registro.php +++ /dev/null @@ -1,107 +0,0 @@ -prepare("SELECT ID_CLIENTE FROM Clientes WHERE EMAIL_CLI = ?"); - $stmt->bindParam(1, $email, PDO::PARAM_STR); - $stmt->execute(); - - if ($stmt->rowCount() > 0) { - header('Location: registro_cliente.php?error=email_exists'); - exit(); - } - - // Verificar si ya existe un cliente con ese nombre - $stmt = $pdo_conexion->prepare("SELECT ID_CLIENTE FROM Clientes WHERE NOMBRE_CLI = ?"); - $stmt->bindParam(1, $nombre, PDO::PARAM_STR); - $stmt->execute(); - - if ($stmt->rowCount() > 0) { - header('Location: registro_cliente.php?error=name_exists'); - exit(); - } - - // Generar salt aleatorio - $salt = bin2hex(random_bytes(16)); - - // Hashear la contraseña con salt - $password_hash = hash('sha256', $password . $salt); - - // Insertar el nuevo cliente - $stmt = $pdo_conexion->prepare(" - INSERT INTO Clientes (NOMBRE_CLI, EMAIL_CLI, TELEFONO_CLI, CONTRASEÑA_CLI, SALT_CLI, ACTIVO_CLI) - VALUES (?, ?, ?, ?, ?, 1) - "); - - $stmt->bindParam(1, $nombre, PDO::PARAM_STR); - $stmt->bindParam(2, $email, PDO::PARAM_STR); - $stmt->bindParam(3, $telefono, PDO::PARAM_STR); - $stmt->bindParam(4, $password_hash, PDO::PARAM_STR); - $stmt->bindParam(5, $salt, PDO::PARAM_STR); - - if ($stmt->execute()) { - // Registro exitoso - $nuevo_id = $conexion->lastInsertId(); - - // Log del registro exitoso - error_log("Nuevo cliente registrado - ID: $nuevo_id, Nombre: $nombre, Email: $email, IP: " . $_SERVER['REMOTE_ADDR']); - - // Redirigir al login con mensaje de éxito - header('Location: login.php?success=registered'); - exit(); - } else { - // Error en la inserción - error_log("Error al registrar cliente"); - header('Location: registro_cliente.php?error=database_error'); - exit(); - } - - } catch (Exception $e) { - // Error general - error_log("Error en registro de cliente: " . $e->getMessage()); - header('Location: registro_cliente.php?error=database_error'); - exit(); - } -} else { - // Acceso directo no permitido - header('Location: registro_cliente.php'); - exit(); -} -?> diff --git a/files/productostabla.php b/files/productostabla.php deleted file mode 100644 index c9df091..0000000 --- a/files/productostabla.php +++ /dev/null @@ -1,1504 +0,0 @@ -❌ Error de conexión a la base de datos'); -} - -// Consultar todos los productos para mostrarlos en la tabla -$consulta = "SELECT - ID_PRODUCTO, - NOMBRE_PRODUCTO, - PRECIO_PRODUCTO, - PRODUCTO_STOCK_MIN, - TIPO_PRODUCTO_MARCA, - FECHA_VENCIMIENTO_PRODUCTO, - COALESCE(ACTIVO, 1) as ACTIVO - FROM Productos - ORDER BY ID_PRODUCTO DESC"; - -$resultado = $conexion->query($consulta); - -if (!$resultado) { - die('
❌ Error en la consulta: ' . $conexion->error . '
'); -} -?> - - - - - - - - Gestión de Productos - Panadería - - - -
-
- - arrow_back - Regresar - -

Gestión de Productos

-
- - ✅ Producto agregado exitosamente
'; - } - } - - if (isset($_GET['error'])) { - $error = $_GET['error']; - $mensaje_error = ''; - switch ($error) { - case 'datos_incompletos': - $mensaje_error = 'Por favor complete todos los campos obligatorios.'; - break; - case 'error_bd': - $mensaje_error = 'Error en la base de datos. Intente nuevamente.'; - break; - default: - $mensaje_error = 'Error desconocido.'; - } - echo '
❌ ' . $mensaje_error . '
'; - } - ?> - -
-

Añadir Nuevo Producto

- -
- -
-
-

Inventario Actual

-
- - search - - -
-
- -
- - - - - - - - - - - - - - - num_rows > 0): ?> - fetch_assoc()): ?> - - - - - - - - - - - - - - - - - -
IDNombrePrecioStockMarca/TipoFecha VencimientoEstadoAcciones
-
- - $ - - - - -
-
-
- - - - - - -
-
- - - check_circle - Activo - - - - cancel - Inactivo - - - - - - -
- No hay productos registrados en el inventario. -
-
-
- - - - - - - - - - - - - diff --git a/files/prueba_modales.php b/files/prueba_modales.php deleted file mode 100644 index 126403e..0000000 --- a/files/prueba_modales.php +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - 🧪 Prueba de Modales - Sistema de Panadería - - - - - -
-

Prueba de Funcionalidades AJAX

- -
-

Prueba de Empleados

- - - -
-
- -
-

Prueba de Clientes

- - - -
-
- -
-

Prueba de Agregar Empleado

-
-
-
- - -
-
- - -
-
- - -
- -
-
-
-
- - -
- - - - - diff --git a/files/prueba_sistema_completo.php b/files/prueba_sistema_completo.php deleted file mode 100644 index e69de29..0000000 diff --git a/files/registro_cliente.php b/files/registro_cliente.php deleted file mode 100644 index 77047c8..0000000 --- a/files/registro_cliente.php +++ /dev/null @@ -1,304 +0,0 @@ - 100) { - $errores[] = "El nombre no puede tener más de 100 caracteres."; - } - - if (empty($email)) { - $errores[] = "El email es obligatorio."; - } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - $errores[] = "El formato del email no es válido."; - } elseif (strlen($email) > 150) { - $errores[] = "El email no puede tener más de 150 caracteres."; - } - - if (!empty($telefono)) { - // El teléfono es opcional, pero si se proporciona debe ser válido - if (!preg_match('/^[0-9+\-\s\(\)]{7,20}$/', $telefono)) { - $errores[] = "El formato del teléfono no es válido."; - } - } - - if (empty($password)) { - $errores[] = "La contraseña es obligatoria."; - } elseif (strlen($password) < 6) { - $errores[] = "La contraseña debe tener al menos 6 caracteres."; - } elseif (strlen($password) > 255) { - $errores[] = "La contraseña no puede tener más de 255 caracteres."; - } - - if ($password !== $confirm_password) { - $errores[] = "Las contraseñas no coinciden."; - } - - // Si no hay errores de validación, verificar si ya existe el email o nombre - if (empty($errores)) { - try { - // Verificar si ya existe un cliente con ese email - $stmt = $pdo_conexion->prepare("SELECT ID_CLIENTE FROM Clientes WHERE EMAIL_CLI = ?"); - $stmt->execute([$email]); - - if ($stmt->rowCount() > 0) { - $errores[] = "Ya existe un cliente registrado con ese email."; - } - - // Verificar si ya existe un cliente con ese nombre - $stmt = $pdo_conexion->prepare("SELECT ID_CLIENTE FROM Clientes WHERE NOMBRE_CLI = ?"); - $stmt->execute([$nombre]); - - if ($stmt->rowCount() > 0) { - $errores[] = "Ya existe un cliente registrado con ese nombre."; - } - - } catch (PDOException $e) { - $errores[] = "Error al verificar los datos: " . $e->getMessage(); - } - } - - // Si no hay errores, proceder con el registro - if (empty($errores)) { - try { - // Generar salt aleatorio - $salt = bin2hex(random_bytes(16)); - - // Hashear la contraseña con salt - $password_hash = hash('sha256', $password . $salt); - - // Insertar el nuevo cliente - $stmt = $pdo_conexion->prepare(" - INSERT INTO Clientes (NOMBRE_CLI, EMAIL_CLI, TELEFONO_CLI, CONTRASEÑA_CLI, SALT_CLI, ACTIVO_CLI) - VALUES (?, ?, ?, ?, ?, 1) - "); - - $resultado = $stmt->execute([ - $nombre, - $email, - $telefono, - $password_hash, - $salt - ]); - - if ($resultado) { - $cliente_id = $pdo_conexion->lastInsertId(); - $registro_exitoso = true; - - // Mostrar aviso emergente antes de redirigir - echo ""; - } else { - $errores[] = "Error al registrar el cliente."; - } - - } catch (PDOException $e) { - $errores[] = "Error en la base de datos: " . $e->getMessage(); - } - } -} -?> - - - - - - - - - Registro de Cliente - Panadería - - -
- -
-
- Logo Panadería -
-

Registro Cliente

-
- -
- -
- Por favor corrige los siguientes errores: -
    - -
  • - -
-
- - -
-
- - -
- -
- - -
- -
- - -
- -
- - - Mínimo 6 caracteres -
- -
- - -
- - -
- - -
-
- - - - - - - diff --git a/files/session_check.php b/files/session_check.php deleted file mode 100644 index a35ef43..0000000 --- a/files/session_check.php +++ /dev/null @@ -1,23 +0,0 @@ - session_id(), - 'session_status' => session_status(), - 'session_data' => $_SESSION, - 'cookies' => $_COOKIE, - 'is_empleado' => ( - isset($_SESSION['usuario_logueado']) && - $_SESSION['usuario_logueado'] === true && - isset($_SESSION['usuario_tipo']) && - $_SESSION['usuario_tipo'] === 'empleado' - ), - 'auth_check' => [ - 'usuario_logueado_set' => isset($_SESSION['usuario_logueado']), - 'usuario_logueado_value' => $_SESSION['usuario_logueado'] ?? 'not_set', - 'usuario_tipo_set' => isset($_SESSION['usuario_tipo']), - 'usuario_tipo_value' => $_SESSION['usuario_tipo'] ?? 'not_set' - ] -]); -?> diff --git a/files/session_debug.php b/files/session_debug.php deleted file mode 100644 index da0f109..0000000 --- a/files/session_debug.php +++ /dev/null @@ -1,46 +0,0 @@ -Información de la Sesión"; -echo "

Session ID: " . session_id() . "

"; -echo "

Session Status: " . session_status() . "

"; - -echo "

Variables de Sesión:

"; -echo "
";
-print_r($_SESSION);
-echo "
"; - -echo "

Cookies:

"; -echo "
";
-print_r($_COOKIE);
-echo "
"; - -echo "

Información del Servidor:

"; -echo "

PHP Version: " . PHP_VERSION . "

"; -echo "

Server IP: " . $_SERVER['SERVER_ADDR'] . "

"; -echo "

Client IP: " . $_SERVER['REMOTE_ADDR'] . "

"; -echo "

User Agent: " . $_SERVER['HTTP_USER_AGENT'] . "

"; - -echo "

Validación de Empleado:

"; -$is_empleado = isset($_SESSION['usuario_tipo']) && $_SESSION['usuario_tipo'] === 'empleado'; -echo "

¿Es empleado?: " . ($is_empleado ? "SÍ" : "NO") . "

"; - -if (isset($_SESSION['usuario_tipo'])) { - echo "

Tipo actual: " . $_SESSION['usuario_tipo'] . "

"; -} else { - echo "

Tipo actual: NO DEFINIDO

"; -} - -// Verificar si hay conflicto de sesiones -if (isset($_SESSION['usuario_logueado'])) { - echo "

Usuario logueado: " . ($_SESSION['usuario_logueado'] ? "SÍ" : "NO") . "

"; -} else { - echo "

Usuario logueado: NO DEFINIDO

"; -} - -echo "

Enlaces de Prueba:

"; -echo "Dashboard Empleado
"; -echo "Login
"; -echo "Logout
"; -?> diff --git a/files/setup_logs.php b/files/setup_logs.php deleted file mode 100644 index fbcdf7e..0000000 --- a/files/setup_logs.php +++ /dev/null @@ -1,87 +0,0 @@ -query("SHOW TABLES LIKE 'productos_logs'"); - - if ($check_table->num_rows == 0) { - echo "Tabla productos_logs no encontrada. Creando...
"; - - // Crear tabla de logs - $sql_tabla = " - CREATE TABLE productos_logs ( - id INT PRIMARY KEY AUTO_INCREMENT, - producto_id INT NOT NULL, - tipo_cambio ENUM('precio', 'stock', 'activacion', 'desactivacion') NOT NULL, - valor_anterior VARCHAR(50), - valor_nuevo VARCHAR(50), - usuario_id INT, - usuario_tipo ENUM('admin', 'empleado') DEFAULT 'admin', - fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - ip_usuario VARCHAR(45), - FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE - )"; - - if ($conexion->query($sql_tabla)) { - echo "✅ Tabla productos_logs creada exitosamente
"; - } else { - echo "❌ Error al crear tabla productos_logs: " . $conexion->error . "
"; - } - - // Crear índices - $indices = [ - "CREATE INDEX idx_producto_logs_fecha ON productos_logs(fecha_cambio)", - "CREATE INDEX idx_producto_logs_producto ON productos_logs(producto_id)", - "CREATE INDEX idx_producto_logs_tipo ON productos_logs(tipo_cambio)" - ]; - - foreach ($indices as $indice) { - if ($conexion->query($indice)) { - echo "✅ Índice creado exitosamente
"; - } else { - echo "❌ Error al crear índice: " . $conexion->error . "
"; - } - } - - } else { - echo "✅ Tabla productos_logs ya existe
"; - } - - // Verificar si el trigger existe - $check_trigger = $conexion->query("SHOW TRIGGERS LIKE 'actualizar_fecha_producto'"); - - if ($check_trigger->num_rows == 0) { - echo "Trigger actualizar_fecha_producto no encontrado. Creando...
"; - - $sql_trigger = " - CREATE TRIGGER actualizar_fecha_producto - BEFORE UPDATE ON Productos - FOR EACH ROW - BEGIN - SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP; - END"; - - if ($conexion->query($sql_trigger)) { - echo "✅ Trigger actualizar_fecha_producto creado exitosamente
"; - } else { - echo "❌ Error al crear trigger: " . $conexion->error . "
"; - } - } else { - echo "✅ Trigger actualizar_fecha_producto ya existe
"; - } - - echo "
Configuración completada!
"; - echo "Ir a Gestión de Productos"; - -} catch (Exception $e) { - echo "❌ Error: " . $e->getMessage(); -} - -$conexion->close(); -?> diff --git a/files/sse_menu_updates.php b/files/sse_menu_updates.php deleted file mode 100644 index 1ef1bf6..0000000 --- a/files/sse_menu_updates.php +++ /dev/null @@ -1,183 +0,0 @@ - ? - "; - - $stmt = $conexion->prepare($query); - $stmt->bind_param("d", $last_check); - $stmt->execute(); - $result = $stmt->get_result()->fetch_assoc(); - - return $result; -} - -/** - * Función para obtener detalles de productos modificados - */ -function obtenerProductosModificados($conexion, $last_check, $limit = 10) { - $query = " - SELECT - p.ID_PRODUCTO, - p.NOMBRE_PRODUCTO, - p.PRECIO_PRODUCTO, - p.PRODUCTO_STOCK_MIN, - p.ACTIVO, - c.NOMBRE_CATEGORIA_PRODUCTO as categoria, - UNIX_TIMESTAMP(p.FECHA_ULTIMA_MODIFICACION) as timestamp_modificacion - FROM Productos p - LEFT JOIN Categoria_Productos c ON p.ID_CATEGORIA_PRODUCTO = c.ID_CATEGORIA_PRODUCTO - WHERE UNIX_TIMESTAMP(p.FECHA_ULTIMA_MODIFICACION) > ? - ORDER BY p.FECHA_ULTIMA_MODIFICACION DESC - LIMIT ? - "; - - $stmt = $conexion->prepare($query); - $stmt->bind_param("di", $last_check, $limit); - $stmt->execute(); - return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); -} - -/** - * Función para verificar cambios en logs recientes - */ -function verificarLogsRecientes($conexion, $last_check) { - $query = " - SELECT - pl.*, - p.NOMBRE_PRODUCTO - FROM productos_logs pl - JOIN Productos p ON pl.producto_id = p.ID_PRODUCTO - WHERE UNIX_TIMESTAMP(pl.fecha_cambio) > ? - AND p.ACTIVO = 1 - ORDER BY pl.fecha_cambio DESC - LIMIT 20 - "; - - $stmt = $conexion->prepare($query); - $stmt->bind_param("d", $last_check); - $stmt->execute(); - return $stmt->get_result()->fetch_all(MYSQLI_ASSOC); -} - -try { - // Enviar evento inicial de conexión - sendSSEEvent('connected', [ - 'message' => 'Conectado al sistema de actualizaciones', - 'timestamp' => time() - ]); - - $iteration = 0; - $max_iterations = 300; // 5 minutos con intervalos de 1 segundo - - while ($iteration < $max_iterations) { - // Verificar cambios en productos - $cambios = verificarCambiosProductos($conexion, $last_check); - - if ($cambios['total_cambios'] > 0) { - // Hay cambios, obtener detalles - $productos_modificados = obtenerProductosModificados($conexion, $last_check); - $logs_recientes = verificarLogsRecientes($conexion, $last_check); - - // Enviar evento de actualización del menú - sendSSEEvent('menu_update', [ - 'type' => 'productos_actualizados', - 'total_cambios' => $cambios['total_cambios'], - 'ultimo_cambio' => $cambios['ultimo_cambio'], - 'productos' => $productos_modificados, - 'logs' => $logs_recientes, - 'timestamp' => time() - ]); - - // Actualizar last_check al timestamp más reciente - $last_check = $cambios['ultimo_cambio']; - } - - // Verificar si la conexión sigue activa - if (connection_aborted()) { - break; - } - - // Enviar heartbeat cada 30 segundos - if ($iteration % 30 == 0 && $iteration > 0) { - sendSSEEvent('heartbeat', [ - 'timestamp' => time(), - 'iteration' => $iteration - ]); - } - - // Esperar 1 segundo antes de la siguiente verificación - sleep(1); - $iteration++; - } - - // Enviar evento de desconexión - sendSSEEvent('disconnected', [ - 'message' => 'Sesión SSE finalizada', - 'timestamp' => time() - ]); - -} catch (Exception $e) { - // Enviar evento de error - sendSSEEvent('error', [ - 'message' => 'Error en el servidor: ' . $e->getMessage(), - 'timestamp' => time() - ]); -} - -// Cerrar la conexión -if (isset($conexion)) { - $conexion->close(); -} -?> diff --git a/files/styleadmindst.css b/files/styleadmindst.css deleted file mode 100644 index 13819a4..0000000 --- a/files/styleadmindst.css +++ /dev/null @@ -1,675 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Exo+2:wght@300;400;500;600;700&display=swap'); - -:root { - --primary-color: #8C5A37; - --primary-hover: #6E462A; - --text-dark: #3D2C21; - --text-light: #6B5B51; - --border-color: #D3C5BC; - --container-bg: rgba(255, 255, 255, 0.75); - --sidebar-width: 320px; - --header-height: 120px; - --white: #ffffff; - --light-gray: #f8f9fa; - --success-green: #4CAF50; - --info-blue: #2196F3; - --warning-orange: #FF9800; - --danger-red: #F44336; - --crema: #f5f5dc; -} - - - -body { - font-family: 'Exo 2', sans-serif; - background: linear-gradient(135deg, #4e3f30 0%, #63554b 100%); - color: var(--text-dark); - overflow-x: hidden; - min-height: 100vh; - margin: 0; -} - -/* Sidebar */ -.sidebar { - position: fixed; - top: 0; - left: 0; - width: var(--sidebar-width); - height: 100vh; - background: rgba(255, 255, 255, 0.85); - color: var(--text-dark); - z-index: 1000; - box-shadow: 4px 0 25px rgba(0, 0, 0, 0.15); - border-right: 1px solid rgba(255, 255, 255, 0.4); - display: flex; - flex-direction: column; -} -.sidebar-header { - padding: 25px; - border-bottom: 1px solid rgba(140, 90, 55, 0.3); - background: rgba(140, 90, 55, 0.9); -} - -.logo-container { - display: flex; - align-items: center; - gap: 20px; - justify-content: flex-start; -} - -.logo-container h4 { - margin: 0; - font-size: 1.4rem; -} - -.logo-img { - width: 60px; - height: 60px; - border-radius: 50%; - object-fit: cover; - border: 3px solid var(--white); - transition: all 0.3s ease; - cursor: pointer; -} - -.logo-img:hover { - transform: scale(1.05); - border-color: rgba(255, 255, 255, 0.8); - box-shadow: 0 0 15px rgba(255, 255, 255, 0.3); -} - -.logo-text { - font-family: 'Playfair Display', serif; - font-size: 1.4rem; - font-weight: 700; - color: var(--white); -} - -.sidebar-nav { - padding: 25px 0; - flex: 1; - overflow-y: auto; -} - -.sidebar-nav .nav { - padding-left: 0; - margin-bottom: 0; - list-style: none; -} - -.sidebar-nav .nav-item { - margin-bottom: 8px; -} - -.sidebar-nav .nav-link { - display: flex; - align-items: center; - gap: 18px; - padding: 18px 25px; - color: var(--text-dark); - text-decoration: none; - transition: all 0.3s ease; - border-left: 4px solid transparent; - border-radius: 0 12px 12px 0; - margin: 0 15px 0 0; - font-size: 1rem; -} - -.sidebar-nav .nav-link:hover { - background: rgba(140, 90, 55, 0.1); - color: var(--primary-color); - border-left-color: var(--primary-color); - transform: translateX(8px); -} - -.sidebar-nav .nav-link.active { - background: rgba(140, 90, 55, 0.2); - color: var(--primary-color); - border-left-color: var(--primary-color); - font-weight: 600; -} - -.sidebar-nav .nav-link i { - width: 24px; - text-align: center; - font-size: 1.2rem; -} - -/* Footer del Sidebar */ -.sidebar-footer { - padding: 25px; - border-top: 1px solid rgba(140, 90, 55, 0.3); - background: rgba(140, 90, 55, 0.9); -} - -.user-info { - display: flex; - align-items: center; - gap: 18px; - margin-bottom: 18px; - padding: 15px; - background: rgba(255, 255, 255, 0.1); - border-radius: 12px; - border: 1px solid rgba(255, 255, 255, 0.2); -} - -.user-avatar i { - font-size: 2.2rem; - color: var(--white); -} - -.user-details { - display: flex; - flex-direction: column; -} - -.user-name { - font-weight: 600; - color: var(--white); - font-size: 1.1rem; -} - -.user-role { - font-size: 0.9rem; - color: rgba(255, 255, 255, 0.8); -} - -.logout-btn { - display: flex; - align-items: center; - gap: 12px; - padding: 12px 15px; - color: var(--white); - text-decoration: none; - background: var(--danger-red); - border-radius: 10px; - transition: all 0.3s ease; - font-weight: 600; - font-size: 1rem; - font-family: 'Exo 2', sans-serif; -} - -.logout-btn:hover { - background: #d32f2f; - color: var(--white); - transform: translateY(-2px); - box-shadow: 0 5px 15px rgba(244, 67, 54, 0.3); -} - -/* Contenido principal */ -.main-content { - margin-left: var(--sidebar-width); - min-height: 100vh; -} - -/* Header Superior */ -.top-header { - font-family: "IBM Plex Sans", sans-serif; - background: rgba(140, 90, 55, 0.15); - border: 1px solid rgba(216, 188, 168, 0.2); - padding: 0 40px; - height: var(--header-height); - display: flex; - align-items: center; - justify-content: space-between; - box-shadow: 0 8px 32px rgba(140, 90, 55, 0.25); - position: relative; - overflow: hidden; -} - -.top-header::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: linear-gradient(135deg, rgba(140, 90, 55, 0.1) 0%, rgba(140, 90, 55, 0.05) 100%); - pointer-events: none; -} - -.bienvenida-admin { - font-family: "IBM Plex Sans", sans-serif; - color: var(--crema); - font-size: 1.1rem; - font-weight: 500; - position: relative; - z-index: 1; - text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); -} - -.page-title { - font-family: 'Playfair Display', serif; - font-size: 1.8rem; - font-weight: 700; - color: var(--crema); - margin: 0; - text-align: center; - flex: 1; - position: relative; - z-index: 1; - text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); -} - -/* Dashboard */ -.dashboard-content { - padding: 30px; -} - -/* Stats Container */ -.stats-container { - margin-bottom: 40px; -} - -.stats-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 20px; - max-width: 1200px; - margin: 0 auto; -} - -.stat-card { - background: rgba(255, 255, 255, 0.85); - padding: 25px; - border-radius: 15px; - text-align: center; - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); - border: 1px solid rgba(255, 255, 255, 0.4); - transition: all 0.3s ease; - border-top: 4px solid var(--primary-color); -} - -.stat-card:hover { - transform: translateY(-5px); - box-shadow: 0 15px 40px rgba(0, 0, 0, 0.2); -} - -/* Colores específicos para cada tarjeta */ -.stat-card.stat-primary { - border-top-color: var(--primary-color); -} - -.stat-card.stat-primary .stat-icon { - background: linear-gradient(135deg, var(--primary-color) 0%, rgba(140, 90, 55, 0.9) 100%); - color: var(--white); -} - -.stat-card.stat-success { - border-top-color: var(--success-green); -} - -.stat-card.stat-success .stat-icon { - background: linear-gradient(135deg, var(--success-green) 0%, rgba(76, 175, 80, 0.9) 100%); - color: var(--white); -} - -.stat-card.stat-info { - border-top-color: var(--info-blue); -} - -.stat-card.stat-info .stat-icon { - background: linear-gradient(135deg, var(--info-blue) 0%, rgba(33, 150, 243, 0.9) 100%); - color: var(--white); -} - -.stat-card.stat-warning { - border-top-color: var(--warning-orange); -} - -.stat-card.stat-warning .stat-icon { - background: linear-gradient(135deg, var(--warning-orange) 0%, rgba(255, 152, 0, 0.9) 100%); - color: var(--white); -} - -.stat-card.stat-danger { - border-top-color: var(--danger-red); -} - -.stat-card.stat-danger .stat-icon { - background: linear-gradient(135deg, var(--danger-red) 0%, rgba(244, 67, 54, 0.9) 100%); - color: var(--white); -} - -.stat-icon { - width: 60px; - height: 60px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - margin: 0 auto 15px; - font-size: 1.5rem; - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); -} - -.stat-number { - font-size: 2.5rem; - font-weight: 700; - color: var(--text-dark); - margin-bottom: 10px; -} - -.stat-label { - color: var(--text-light); - font-weight: 600; - font-size: 0.95rem; -} - -/* Actions Container */ -.actions-container { - max-width: 1200px; - margin: 0 auto; -} - -.actions-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); - gap: 30px; -} - -.action-card { - background: rgba(255, 255, 255, 0.85); - border-radius: 15px; - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); - border: 1px solid rgba(255, 255, 255, 0.4); - transition: all 0.3s ease; - overflow: hidden; -} - -.action-card:hover { - transform: translateY(-3px); - box-shadow: 0 15px 40px rgba(0, 0, 0, 0.2); -} - -.action-card .card-header { - background: linear-gradient(135deg, var(--primary-color) 0%, rgba(140, 90, 55, 0.9) 100%); - color: var(--white); - padding: 20px; - border-bottom: none; -} - -.action-card .card-header h3 { - font-family: 'Playfair Display', serif; - margin: 0; - font-size: 1.2rem; - font-weight: 700; - color: var(--white); -} - -.action-card .card-body { - padding: 25px; - background: transparent; - display: flex; - flex-direction: column; - gap: 12px; -} - -/* Botones de Acción - Estilo Transparente */ -.action-btn { - display: inline-flex; - align-items: center; - justify-content: center; - padding: 12px 20px; - border-radius: 10px; - text-decoration: none; - font-weight: 600; - transition: all 0.3s ease; - border: 2px solid rgba(140, 90, 55, 0.6); - background: rgba(140, 90, 55, 0.1); - color: var(--text-dark); - font-family: 'Exo 2', sans-serif; - font-size: 0.9rem; - text-align: center; -} - -.action-btn:hover { - background: rgba(140, 90, 55, 0.2); - border-color: var(--primary-color); - color: var(--text-dark); - transform: translateY(-2px); - box-shadow: 0 8px 20px rgba(140, 90, 55, 0.3); -} - -.action-btn i { - margin-right: 8px; -} - -/* ===== ESTILOS PARA GESTIÓN DE INGREDIENTES ===== */ - -/* Estilos para elementos editables */ -.stock-editable, .precio-editable { - cursor: pointer; - padding: 2px 6px; - border-radius: 4px; - transition: all 0.3s ease; - display: inline-block; - min-width: 60px; -} - -.stock-editable:hover, .precio-editable:hover { - background-color: rgba(0, 123, 255, 0.1); - border: 1px dashed #007bff; -} - -/* Badges para estado de stock */ -.badge-stock-alto { - background-color: var(--success-green) !important; - color: white; -} - -.badge-stock-medio { - background-color: var(--warning-orange) !important; - color: white; -} - -.badge-stock-bajo { - background-color: var(--danger-red) !important; - color: white; -} - -/* Estilos para botones de acción en tabla */ -.btn-group .btn { - margin: 0 1px; -} - -.btn-sm i { - font-size: 0.8rem; -} - -/* Modal de ingredientes específico */ -#ingredientesModal .modal-xl { - max-width: 95%; -} - -#ingredientesModal .table-responsive { - max-height: 500px; - overflow-y: auto; -} - -/* Estadísticas de ingredientes */ -.ingredientes-stats { - background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)); - color: white; - border-radius: 10px; - padding: 15px; - margin-bottom: 20px; -} - -.ingredientes-stats .stat-item { - text-align: center; - padding: 10px; -} - -.ingredientes-stats .stat-number { - font-size: 2rem; - font-weight: bold; - display: block; -} - -.ingredientes-stats .stat-label { - font-size: 0.9rem; - opacity: 0.9; -} - -/* Form de agregar ingrediente */ -#formAgregarIngrediente .form-label { - font-weight: 500; - color: var(--text-dark); -} - -#formAgregarIngrediente .form-control, -#formAgregarIngrediente .form-select { - border-radius: 8px; - border: 2px solid var(--border-color); - transition: all 0.3s ease; -} - -#formAgregarIngrediente .form-control:focus, -#formAgregarIngrediente .form-select:focus { - border-color: var(--primary-color); - box-shadow: 0 0 0 0.2rem rgba(140, 90, 55, 0.25); -} - -/* Alertas personalizadas para ingredientes */ -.alert-ingrediente { - border-radius: 10px; - border: none; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); -} - -.alert-ingrediente.alert-success { - background: linear-gradient(135deg, #d4edda, #c3e6cb); - color: #155724; -} - -.alert-ingrediente.alert-warning { - background: linear-gradient(135deg, #fff3cd, #ffeaa7); - color: #856404; -} - -.alert-ingrediente.alert-danger { - background: linear-gradient(135deg, #f8d7da, #f5c6cb); - color: #721c24; -} - -/* Spinner personalizado para carga de ingredientes */ -.ingredientes-loader { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - padding: 3rem; -} - -.ingredientes-loader .spinner-border { - width: 3rem; - height: 3rem; - border-width: 0.3rem; - color: var(--primary-color); -} - -/* Tabla de ingredientes */ -#ingredientesTableBody tr:hover { - background-color: rgba(140, 90, 55, 0.05); - transition: all 0.3s ease; -} - -/* Botones de exportar */ -.btn-export { - background: linear-gradient(135deg, var(--success-green), #45a049); - border: none; - color: white; - transition: all 0.3s ease; -} - -.btn-export:hover { - background: linear-gradient(135deg, #45a049, #3d8b40); - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3); -} - -/* Responsive para tablets */ -@media (max-width: 768px) { - #ingredientesModal .modal-xl { - max-width: 98%; - margin: 10px; - } - - .ingredientes-stats { - text-align: center; - } - - .ingredientes-stats .stat-number { - font-size: 1.5rem; - } - - .btn-group { - flex-direction: column; - align-items: stretch; - } - - .btn-group .btn { - margin: 1px 0; - border-radius: 4px !important; - } -} - -/* Animaciones para elementos de ingredientes */ -@keyframes fadeInIngrediente { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.ingrediente-row { - animation: fadeInIngrediente 0.5s ease-out; -} - -/* Tooltips personalizados */ -.tooltip-ingrediente { - position: relative; - cursor: help; -} - -.tooltip-ingrediente::after { - content: attr(data-tooltip); - position: absolute; - bottom: 125%; - left: 50%; - transform: translateX(-50%); - background-color: rgba(0, 0, 0, 0.8); - color: white; - padding: 5px 10px; - border-radius: 4px; - font-size: 0.8rem; - white-space: nowrap; - opacity: 0; - visibility: hidden; - transition: all 0.3s ease; - z-index: 1000; -} - -.tooltip-ingrediente:hover::after { - opacity: 1; - visibility: visible; -} - -/* Estilos para campos requeridos */ -.form-label .text-danger { - font-weight: bold; -} - -.form-control:invalid { - border-color: var(--danger-red); -} - -.form-control:invalid:focus { - border-color: var(--danger-red); - box-shadow: 0 0 0 0.2rem rgba(244, 67, 54, 0.25); -} \ No newline at end of file diff --git a/files/styleclienteds.css b/files/styleclienteds.css deleted file mode 100644 index 90c52c6..0000000 --- a/files/styleclienteds.css +++ /dev/null @@ -1,695 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Inter:wght@300;400;500;600;700&display=swap'); -@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&display=swap'); - -:root { - --primary-color: #8C5A37; - --primary-hover: #6E442A; - --secondary-color: #B8733A; - --accent-color: #A0522D; - --text-dark: #2C1810; - --text-light: #5D4037; - --text-muted: #8D6E63; - --bg-cream: #FFF8E1; - --bg-vanilla: #F5F5DC; - --bg-light: #FEFEF8; - --white: #FFFFFF; - --border-color: #E8D5B7; - --shadow: rgba(60, 64, 67, 0.15); - --success: #4CAF50; - --warning: #FF9800; - --danger: #F44336; - --info: #2196F3; - --sidebar-width: 240px; -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - background: linear-gradient(135deg, var(--bg-cream) 0%, var(--bg-vanilla) 100%); - color: var(--text-dark); - line-height: 1.6; - min-height: 100vh; -} - -/* === SIDEBAR === */ -.sidebar { - position: fixed; - top: 0; - left: 0; - width: var(--sidebar-width); - height: 100vh; - background: var(--white); - border-right: 1px solid var(--border-color); - box-shadow: 0 2px 10px var(--shadow); - z-index: 1000; - overflow-y: auto; -} - -.sidebar-content { - padding: 0; - height: 100%; - display: flex; - flex-direction: column; -} - -.sidebar-brand { - padding: 20px; - text-align: center; - background: var(--bg-light); -} - -.sidebar-logo { - width: 50px; - height: 50px; - border-radius: 50%; - object-fit: cover; - margin-bottom: 10px; - border: 2px solid var(--primary-color); -} - -.sidebar-brand h5 { - font-family: 'Playfair Display', serif; - font-weight: 700; - color: var(--primary-color); - margin: 0; - font-size: 1.1rem; -} - -.sidebar-divider { - height: 1px; - background: var(--border-color); - margin: 15px 0; -} - -.nav-link { - color: var(--text-light) !important; - font-weight: 500; - padding: 12px 20px; - border-radius: 0; - display: flex; - align-items: center; - gap: 10px; - font-size: 0.9rem; - border: none; - background: none; -} - -.nav-link:hover { - background: var(--bg-vanilla); - color: var(--primary-color) !important; -} - -.nav-link.active { - background: var(--primary-color); - color: var(--white) !important; -} - -.nav-link i { - width: 18px; - text-align: center; - font-size: 1.1rem; -} - -.sidebar-user { - margin-top: auto; - padding: 20px; - border-top: 1px solid var(--border-color); - background: var(--bg-light); -} - -.user-info { - color: var(--text-light); - font-weight: 500; - margin-bottom: 10px; - display: flex; - align-items: center; - gap: 8px; - font-size: 0.9rem; -} - -.user-info i { - font-size: 1.2rem; - color: var(--primary-color); -} - -.logout-btn { - background: var(--danger); - color: var(--white) !important; - text-decoration: none; - padding: 8px 16px; - border-radius: 6px; - font-weight: 500; - border: none; - cursor: pointer; - display: flex; - align-items: center; - gap: 8px; - font-size: 0.9rem; - width: 100%; - justify-content: center; -} - -.logout-btn:hover { - background: #d32f2f; - color: var(--white) !important; - text-decoration: none; -} - -/* === BOTÓN EXPLORAR === */ -.btn-explore { - background: #c05610; - color: var(--white) !important; - text-decoration: none; - padding: 12px 20px; - border-radius: 8px; - font-weight: 600; - border: none; - cursor: pointer; - display: flex; - align-items: center; - gap: 10px; - font-size: 0.9rem; - justify-content: center; - transition: all 0.3s ease; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.726); -} - -.btn-explore:hover { - background-image: url(../files/img/iconoboton1.jpg); - background-position: center center; - background-repeat: no-repeat; - background-size: cover; - color: var(--white) !important; - text-decoration: none; - transform: translateY(-2px); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); -} - -.btn-explore i { - font-size: 1.1rem; -} - -/* === MAIN CONTENT === */ -.main-content { - margin-left: var(--sidebar-width); - padding: 30px; - min-height: 100vh; - padding-bottom: 200px; -} - -.section-content { - max-width: 1200px; - margin: 0 auto; -} - -.section-content h3 { - font-family: 'Playfair Display', serif; - font-size: 1.8rem; - font-weight: 700; - color: var(--primary-color); - margin-bottom: 30px; - text-align: center; -} - -/* === WELCOME SECTION === */ -.welcome-section { - text-align: center; - margin-bottom: 40px; - background: var(--white); - padding: 30px; - border-radius: 12px; - box-shadow: 0 2px 10px var(--shadow); - border: 1px solid var(--border-color); -} - -.welcome-section h2 { - font-family: 'Playfair Display', serif; - font-size: 1.8rem; - font-weight: 700; - color: var(--primary-color); - margin-bottom: 10px; -} - -.welcome-section p { - font-size: 1rem; - color: var(--text-muted); - margin: 0; -} - -/* === STATS GRID === */ -.stats-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); - gap: 20px; - margin-bottom: 40px; -} - -.stat-card { - background: var(--white); - padding: 25px; - border-radius: 12px; - border: 1px solid var(--border-color); - box-shadow: 0 2px 8px var(--shadow); - display: flex; - align-items: center; - gap: 15px; -} - -.card-icon { - width: 50px; - height: 50px; - background: var(--primary-color); - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; -} - -.card-icon i { - font-size: 1.5rem; - color: var(--white); -} - -.card-content { - flex: 1; -} - -.stat-number { - font-size: 2rem; - font-weight: 700; - color: var(--primary-color); - margin-bottom: 5px; - line-height: 1; -} - -.stat-label { - color: var(--text-muted); - font-weight: 500; - font-size: 0.9rem; -} - -/* === ORDERS SECTION === */ -.orders-section { - background: var(--white); - border-radius: 12px; - border: 1px solid var(--border-color); - box-shadow: 0 2px 8px var(--shadow); - margin-bottom: 40px; -} - -.section-header { - padding: 20px; - border-bottom: 1px solid var(--border-color); - background: var(--bg-light); - border-radius: 12px 12px 0 0; -} - -.section-header h4 { - font-family: 'Playfair Display', serif; - font-size: 1.3rem; - font-weight: 700; - color: var(--primary-color); - margin: 0; - display: flex; - align-items: center; - gap: 10px; -} - -.orders-list { - padding: 20px; -} - -.order-item { - display: flex; - justify-content: space-between; - align-items: center; - padding: 15px; - border: 1px solid var(--border-color); - border-radius: 8px; - margin-bottom: 15px; - background: var(--bg-light); -} - -.order-item:last-child { - margin-bottom: 0; -} - -.order-info h6 { - font-weight: 600; - color: var(--primary-color); - margin-bottom: 8px; -} - -.order-info p { - color: var(--text-muted); - font-size: 0.9rem; -} - -.order-status { - padding: 6px 12px; - border-radius: 20px; - font-weight: 500; - font-size: 0.8rem; - text-align: center; - min-width: 100px; -} - -.status-pendiente { - background: #FFF3E0; - color: var(--warning); - border: 1px solid #FFE0B2; -} - -.status-enproceso { - background: #E3F2FD; - color: var(--info); - border: 1px solid #BBDEFB; -} - -.status-listo { - background: #E8F5E8; - color: var(--success); - border: 1px solid #C8E6C9; -} - -.status-entregado { - background: #F3E5F5; - color: #9C27B0; - border: 1px solid #E1BEE7; -} - -.status-cancelado { - background: #FFEBEE; - color: var(--danger); - border: 1px solid #FFCDD2; -} - -/* === ACTION CARDS === */ -.action-cards { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); - gap: 30px; - margin-bottom: 40px; -} - -.action-card { - background: var(--white); - border-radius: 12px; - border: 1px solid var(--border-color); - box-shadow: 0 2px 8px var(--shadow); - overflow: hidden; -} - -.action-card .card-header { - background: var(--primary-color); - color: var(--white); - padding: 20px; - display: flex; - align-items: center; - gap: 10px; -} - -.action-card .card-header i { - font-size: 1.3rem; -} - -.action-card .card-header h5 { - font-family: 'Playfair Display', serif; - font-weight: 700; - margin: 0; - font-size: 1.2rem; -} - -.action-card .card-body { - padding: 20px; -} - -.action-btn { - display: block; - padding: 12px 20px; - border: none; - background: var(--bg-light); - color: var(--text-dark); - text-decoration: none; - font-weight: 500; - border-bottom: 1px solid var(--border-color); - font-family: 'Inter', sans-serif; - display: flex; - align-items: center; - gap: 10px; - font-size: 0.9rem; -} - -.action-btn:hover { - background: var(--bg-vanilla); - color: var(--primary-color); - text-decoration: none; -} - -.action-btn:last-child { - border-bottom: none; -} - -.special-btn { - background: var(--success) !important; - color: var(--white) !important; - font-weight: 600; -} - -.special-btn:hover { - background: #45a049 !important; - color: var(--white) !important; -} - -/* === FOOTER === */ -.footer { - position: fixed; - bottom: 0; - left: var(--sidebar-width); - right: 0; - background: var(--white); - border-top: 1px solid var(--border-color); - box-shadow: 0 -2px 10px var(--shadow); - z-index: 500; - padding: 20px 0; -} - -.footer-content { - text-align: center; - max-width: 1200px; - margin: 0 auto; - padding: 0 30px; -} - -.footer-content h5 { - font-family: "IBM Plex Sans", sans-serif; - font-optical-sizing: auto; - font-weight: 600; - color: linear-gradient(rgba(255, 0, 0, 0.767),rgba(219, 147, 11, 0.918)); - margin-bottom: 15px; - font-size: 2rem; - display: flex; - align-items: center; - justify-content: center; - gap: 8px; -} - -.product-slider { - overflow: hidden; - position: relative; -} - -.slider-container { - display: flex; - gap: 15px; - animation: slide 20s infinite linear; -} - -.product-slide { - flex: 0 0 auto; - width: 150px; -} - -.product-card { - background: var(--bg-light); - border: 1px solid var(--border-color); - border-radius: 8px; - padding: 15px; - text-align: center; -} - -.product-icon { - width: 40px; - height: 40px; - background: var(--primary-color); - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - margin: 0 auto 10px; -} - -.product-icon i { - font-size: 1.2rem; - color: var(--white); -} - -.product-card h6 { - font-weight: 600; - color: var(--primary-color); - margin-bottom: 5px; - font-size: 0.9rem; -} - -.product-card .price { - font-weight: 700; - color: var(--accent-color); - margin-bottom: 5px; -} - -.product-card small { - color: var(--text-muted); - font-size: 0.8rem; -} - -@keyframes slide { - 0% { - transform: translateX(0); - } - 100% { - transform: translateX(-100%); - } -} - -/* === MOBILE STYLES === */ -@media (max-width: 768px) { - .sidebar { - transform: translateX(-100%); - transition: transform 0.3s ease; - width: 280px; - } - - .sidebar.show { - transform: translateX(0); - } - - .main-content { - margin-left: 0; - padding: 20px; - padding-bottom: 200px; - } - - .footer { - left: 0; - } - - #sidebarToggle { - background: var(--primary-color); - border: none; - color: var(--white); - font-weight: 500; - } - - .stats-grid { - grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); - gap: 15px; - } - - .stat-card { - padding: 20px; - flex-direction: column; - text-align: center; - gap: 10px; - } - - .stat-number { - font-size: 1.8rem; - } - - .welcome-section { - padding: 20px; - } - - .welcome-section h2 { - font-size: 1.5rem; - } - - .order-item { - flex-direction: column; - gap: 10px; - text-align: center; - } - - .order-status { - min-width: auto; - } - - .action-cards { - grid-template-columns: 1fr; - } - - .slider-container { - gap: 10px; - } - - .product-slide { - width: 120px; - } - - .product-card { - padding: 10px; - } - - .btn-explore { - padding: 10px 16px; - font-size: 0.85rem; - } -} - -@media (max-width: 576px) { - .stats-grid { - grid-template-columns: 1fr; - } - - .welcome-section { - padding: 15px; - } - - .welcome-section h2 { - font-size: 1.3rem; - } - - .section-content h3 { - font-size: 1.5rem; - } - - .main-content { - padding: 15px; - padding-bottom: 200px; - } - - .footer-content { - padding: 0 15px; - } - - .product-slide { - width: 100px; - } -} - -/* === BOTÓN CAMBIAR CONTRASEÑA (Café-Crema) === */ -.change-pass-btn { - background: var(--primary-color); - color: var(--bg-cream) !important; - text-decoration: none; -} -.change-pass-btn:hover { - background: var(--primary-hover); - color: var(--bg-cream) !important; -} \ No newline at end of file diff --git a/files/stylehomepage.css b/files/stylehomepage.css deleted file mode 100644 index 8c83444..0000000 --- a/files/stylehomepage.css +++ /dev/null @@ -1,1869 +0,0 @@ -:root { - --color-crema: #f5f5dc; - --color-marron: #8b4513; - --color-gris-oscuro: #2c3e50; - --color-cafe-claro: #d2b48c; - --color-cafe-con-leche: #ddbea9; - --color-blanco-calido: #fffef7; - --color-dorado: #ffd700; - --color-overlay: rgba(139, 69, 19, 0.8); -} - -/* Clases de colores de fondo */ -.bg-crema { background-color: var(--color-crema) !important; } -.bg-blanco-cálido { background-color:#b08d75 !important; } - -/* Clases de colores de texto */ -.text-marron { color: var(--color-marron) !important; } -.text-gris-oscuro { color: var(--color-gris-oscuro) !important; } -.text-cafe-claro { color: var(--color-cafe-claro) !important; } -.text-cafe-con-leche { color: var(--color-cafe-con-leche) !important; } -.text-crema { color: var(--color-crema) !important; } - -/* Clases de borde */ -.border-marron { border-color: var(--color-marron) !important; } - -/* Estilos generales */ -body { - font-family: 'Quicksand', sans-serif; - background-color: #bb9467 !important; - line-height: 1.6; - overflow-x: hidden; -} - -/* Navbar personalizada */ -.navbar { - transition: all 0.3s ease; - backdrop-filter: blur(10px); - position: relative; - z-index: 9999 !important; -} - -.navbar.scrolled { - background-color: rgba(245, 245, 220, 0.95) !important; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); -} - -/* Header con prioridad máxima */ -header { - position: relative; - z-index: 9999 !important; -} - -.logo { - transition: transform 0.3s ease; -} - -.logo:hover { - transform: scale(1.05); -} - -/* Botón personalizado */ -.btn-primary { - background: linear-gradient(135deg, var(--color-marron), #a0522d); - border: none; - border-radius: 25px; - padding: 8px 20px; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3); -} - -.btn-primary:hover { - background: linear-gradient(135deg, #a0522d, var(--color-marron)); - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4); -} - -.btn-rounded { - border-radius: 25px; -} - -/* Carrusel de borde a borde */ -.carousel-fullwidth { - width: 100vw; - position: relative; - left: 50%; - right: 50%; - margin-left: -50vw; - margin-right: -50vw; - overflow: hidden; - z-index: 1 !important; -} - -.carousel { - z-index: 1 !important; -} - -.carousel-inner { - z-index: 1 !important; -} - -.carousel-item { - z-index: 1 !important; -} - -.carousel-fixed-img { - height: 350px; - object-fit: cover; - object-position: center; - width: 100%; - image-rendering: -webkit-optimize-contrast; - image-rendering: crisp-edges; - transition: none !important; - filter: contrast(1.05) brightness(1.02); - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - transform: none !important; -} - -.carousel-item { - position: relative; - overflow: hidden; - transition: transform 0.8s ease-in-out; -} - -/* Suavizar la transición del carrusel */ -.carousel-inner { - overflow: hidden; -} - -.carousel-item.active, -.carousel-item-next, -.carousel-item-prev { - display: block; -} - -.carousel-link { - display: block; - position: relative; - text-decoration: none; - color: inherit; - overflow: hidden; -} - -.carousel-link::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: linear-gradient(45deg, transparent, rgba(139, 69, 19, 0.1)); - opacity: 0; - transition: opacity 0.3s ease; - z-index: 1; -} - -.carousel-link:hover::before { - opacity: 1; -} - -.carousel-link:hover .carousel-fixed-img { - transform: scale(1.02); -} - -.carousel-caption { - background: rgba(0, 0, 0, 0.7); - border-radius: 8px; - padding: 12px 20px; - backdrop-filter: blur(8px); - bottom: 20px; - left: 20px; - right: 20px; - margin: 0 auto; - max-width: 400px; -} - -.carousel-caption h5 { - margin-bottom: 5px; - font-size: 1.25rem; - text-shadow: 1px 1px 2px rgba(0,0,0,0.5); -} - -.carousel-caption p { - margin-bottom: 0; - font-size: 0.9rem; - text-shadow: 1px 1px 2px rgba(0,0,0,0.5); -} - -.carousel-control-prev, -.carousel-control-next { - width: 50px; - height: 50px; - top: 50%; - transform: translateY(-50%); - background: rgba(139, 69, 19, 0.8); - border-radius: 50%; - transition: all 0.3s ease; -} - -.carousel-control-prev { - left: 15px; -} - -.carousel-control-next { - right: 15px; -} - -.carousel-control-prev:hover, -.carousel-control-next:hover { - background: rgba(139, 69, 19, 0.9); - transform: translateY(-50%) scale(1.1); -} - -/* Cards con slide overlay */ -.card { - border: none; - transition: all 0.3s ease; - position: relative; - overflow: hidden; - cursor: pointer; -} - -.card::before { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 100%; - height: 100%; - background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent); - transition: left 0.6s ease; - z-index: 2; -} - -.card:hover::before { - left: 100%; -} - -.card:hover { - transform: translateY(-10px); - box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2); -} - -.card-img-custom { - height: 250px; - object-fit: cover; - object-position: center; - transition: transform 0.3s ease; -} - -.card:hover .card-img-custom { - transform: scale(1.05); -} - -/* Overlay de información en cards */ -.card-overlay { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: var(--color-overlay); - color: white; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - opacity: 0; - transition: opacity 0.3s ease; - z-index: 3; -} - -.card:hover .card-overlay { - opacity: 1; -} - -.card-overlay h5 { - margin-bottom: 10px; - font-weight: bold; -} - -.card-overlay p { - text-align: center; - padding: 0 20px; -} - -/* Estilos para las tarjetas de productos */ -.card-hover { - transition: all 0.3s ease; - border-radius: 15px !important; - overflow: hidden; -} - -.card-hover:hover { - transform: translateY(-10px); - box-shadow: 0 20px 40px rgba(0,0,0,0.1) !important; -} - -.product-image { - height: 250px; - object-fit: cover; - transition: transform 0.3s ease; -} - -.card-hover:hover .product-image { - transform: scale(1.05); -} - -.card-img-container { - overflow: hidden; - border-radius: 15px 15px 0 0; -} - -.btn-pedir { - background: linear-gradient(135deg, var(--color-marron), var(--color-cafe-claro)); - border: none; - padding: 12px 20px; - border-radius: 25px; - font-weight: 600; - transition: all 0.3s ease; - position: relative; - overflow: hidden; -} - -.btn-pedir:hover { - transform: translateY(-2px); - box-shadow: 0 8px 25px rgba(139, 69, 19, 0.3); -} - -.btn-pedir::before { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 100%; - height: 100%; - background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); - transition: left 0.5s; -} - -.btn-pedir:hover::before { - left: 100%; -} - -/* Animaciones */ -.fade-in { - opacity: 0; - transform: translateY(30px); - transition: all 0.8s ease; -} - -.fade-in.animate-in { - opacity: 1; - transform: translateY(0); -} - -.card { - opacity: 0; - transform: translateY(50px); - transition: all 0.6s ease; -} - -.card.animate-in { - opacity: 1; - transform: translateY(0); -} - -/* Hero section específica para menu */ -.hero-section { - background: linear-gradient(135deg, var(--color-crema), var(--color-blanco-calido)); - margin-top: 76px; - padding: 80px 0; - position: relative; - overflow: hidden; -} - -.hero-section::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: url('data:image/svg+xml,') repeat; - background-size: 50px 50px; -} - -.hero-section .container { - position: relative; - z-index: 1; -} - -/* Estilos para la página del menú */ -.hero-section { - background: linear-gradient(135deg, var(--color-crema), var(--color-blanco-calido)); - padding: 5rem 0 3rem; - margin-top: 0; -} - -.hero-section h1 { - color: var(--color-marron); - font-weight: 700; - font-size: 3rem; - margin-bottom: 1.5rem; -} - -.hero-section .lead { - color: var(--color-gris-oscuro); - font-size: 1.2rem; - font-weight: 500; -} - -.fade-in { - opacity: 0; - animation: fadeInUp 0.8s ease forwards; -} - -@keyframes fadeInUp { - to { - opacity: 1; - transform: translateY(0); - } - from { - opacity: 0; - transform: translateY(20px); - } -} - -.product-image { - height: 250px; - object-fit: cover; - border-radius: 12px 12px 0 0; - transition: transform 0.3s ease; -} - -.card-hover { - transition: all 0.3s ease; - border: none; - border-radius: 12px; - overflow: hidden; -} - -.card-hover:hover { - transform: translateY(-10px); - box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); -} - -.card-hover:hover .product-image { - transform: scale(1.05); -} - -.card-img-container { - overflow: hidden; - border-radius: 12px 12px 0 0; -} - -.product-info { - border-top: 1px solid var(--color-cafe-claro); - padding-top: 1rem; -} - -.badge { - font-size: 0.8rem; - padding: 0.5rem 0.75rem; - border-radius: 20px; -} - -.btn-pedir { - background: linear-gradient(135deg, #a0522d, var(--color-marron)); - border: none; - color: white; - padding: 0.75rem 1.5rem; - font-weight: 600; - transition: all 0.3s ease; - border-radius: 25px; -} - -.btn-pedir:hover { - background: linear-gradient(135deg, var(--color-marron), #a0522d); - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4); - color: white; -} - -.animate-in { - animation: slideInUp 0.6s ease forwards; -} - -@keyframes slideInUp { - from { - opacity: 0; - transform: translateY(30px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.text-dorado { - color: var(--color-dorado) !important; -} - -.bg-marron { - background-color: var(--color-marron) !important; -} - -.bg-gris-oscuro { - background-color: var(--color-gris-oscuro) !important; -} - -/* Estilos responsive */ -@media (max-width: 768px) { - .hero-section { - padding: 60px 0; - } - - .display-4 { - font-size: 2.5rem; - } - - .product-image { - height: 200px; - } - - .card-hover:hover { - transform: none; - } -} - -@media (max-width: 576px) { - .carousel-fixed-img { - height: 200px; - } - - .card-img-custom { - height: 180px; - } - - .carousel-caption { - padding: 8px 15px; - bottom: 10px; - left: 10px; - right: 10px; - max-width: 300px; - } - - .carousel-caption h5 { - font-size: 1rem; - } - - .carousel-caption p { - font-size: 0.8rem; - } -} - -/* Badges de estado */ -.badge { - font-size: 0.75rem; - padding: 0.5em 0.75em; - border-radius: 20px; -} - -/* Efectos de loading */ -.loading { - opacity: 0.6; - pointer-events: none; -} - -/* Estilos para el precio */ -.product-info .h5 { - font-size: 1.5rem; - font-weight: 700; - text-shadow: 1px 1px 2px rgba(0,0,0,0.1); -} - -/* Efectos de hover para navegación */ -.nav-link { - position: relative; - transition: color 0.3s ease; -} - -.nav-link::after { - content: ''; - position: absolute; - bottom: -5px; - left: 0; - width: 0; - height: 2px; - background: var(--color-marron); - transition: width 0.3s ease; -} - -.nav-link:hover::after { - width: 100%; -} - -/* Asegurar alineación correcta del navbar */ -.navbar-nav { - align-items: center; -} - -.navbar-nav .nav-item { - display: flex; - align-items: center; -} - -.navbar-nav .nav-link { - display: flex; - align-items: center; - padding: 0.5rem 1rem; -} - -/* Estilos específicos para el enlace Acceder */ -.nav-item a[href="login.php"] { - background: linear-gradient(135deg, var(--color-marron), #a0522d); - color: white !important; - border-radius: 25px; - padding: 8px 20px !important; - text-decoration: none; - font-weight: 600; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3); - margin-left: 8px; -} - -.nav-item a[href="login.php"]:hover { - background: linear-gradient(135deg, #a0522d, var(--color-marron)); - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4); - color: white !important; -} - -/* Efectos de scroll suave */ -html { - scroll-behavior: smooth; -} - -/* Sombras personalizadas */ -.shadow-sm { - box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important; -} - -.shadow { - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important; -} - -/* === DROPDOWN DEL USUARIO === */ -.dropdown-toggle { - border: none !important; - background: none !important; - color: var(--color-marron) !important; - font-weight: 600; - display: flex; - gap: 8px; - padding: 8px 12px; - border-radius: 8px; - transition: all 0.3s ease; -} - -.dropdown-toggle:hover { - background: rgba(139, 69, 19, 0.1) !important; - color: var(--color-marron) !important; -} - -.dropdown-toggle:focus { - box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2); -} - -.dropdown-toggle::after { - margin-left: 8px; - color: var(--color-marron); -} - -.dropdown-menu { - border: 1px solid var(--color-cafe-claro); - border-radius: 12px; - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); - padding: 0.75rem 0; - min-width: 200px; - margin-top: 0.5rem; - background: var(--color-crema); - z-index: 10001 !important; - position: absolute !important; -} - -.dropdown-item { - color: var(--color-gris-oscuro); - padding: 0.5rem 1.5rem !important; - font-weight: 600 !important; - display: flex; - align-items: center; - gap: 10px; - transition: all 0.3s ease; - border-radius: 8px !important; - margin: 0.2rem 0.5rem !important; -} - -.dropdown-item:hover { - background: var(--color-cafe-con-leche) !important; - color: var(--color-marron) !important; - transform: translateX(5px); -} - -.dropdown-item:focus { - background: var(--color-cafe-con-leche) !important; - color: var(--color-marron) !important; -} - -.dropdown-divider { - margin: 0.5rem 0; - border-color: var(--color-cafe-claro); -} - -/* Asegurar que main no interfiera */ -main { - position: relative; - z-index: 1; -} - -/* === NAVBAR Y DROPDOWN - VERSIÓN SIMPLIFICADA === */ -/* Navbar con z-index correcto */ -.navbar { - position: sticky !important; - top: 0; - z-index: 1050 !important; -} - -header { - position: sticky !important; - top: 0; - z-index: 1050 !important; -} - -/* Carrusel con z-index menor */ -.carousel-fullwidth, -.carousel, -.carousel-inner, -.carousel-item { - z-index: 1 !important; -} - -/* Dropdown con z-index Bootstrap estándar */ -.dropdown-menu { - z-index: 1051 !important; -} - -/* Responsive */ -@media (max-width: 768px) { - .carousel-fixed-img { - height: 250px; - } - - .card-img-custom { - height: 200px; - } - - .carousel-control-prev, - .carousel-control-next { - width: 40px; - height: 40px; - } - - h2::after { - width: 60px; - } - - h2::after { - width: 60px; - } - - /* Dropdown responsivo */ - .dropdown-toggle { - font-size: 0.9rem; - padding: 6px 10px; - } - - .dropdown-menu { - min-width: 180px; - font-size: 0.9rem; - } - - .dropdown-item { - padding: 8px 12px; - } -} - -@media (max-width: 576px) { - .carousel-fixed-img { - height: 200px; - } - - .card-img-custom { - height: 180px; - } - - .carousel-caption { - padding: 8px 15px; - bottom: 10px; - left: 10px; - right: 10px; - max-width: 300px; - } - - .carousel-caption h5 { - font-size: 1rem; - } - - .carousel-caption p { - font-size: 0.8rem; - } -} - -/* Badges de estado */ -.badge { - font-size: 0.75rem; - padding: 0.5em 0.75em; - border-radius: 20px; -} - -/* Efectos de loading */ -.loading { - opacity: 0.6; - pointer-events: none; -} - -/* Estilos para el precio */ -.product-info .h5 { - font-size: 1.5rem; - font-weight: 700; - text-shadow: 1px 1px 2px rgba(0,0,0,0.1); -} - -/* Efectos de hover para navegación */ -.nav-link { - position: relative; - transition: color 0.3s ease; -} - -.nav-link::after { - content: ''; - position: absolute; - bottom: -5px; - left: 0; - width: 0; - height: 2px; - background: var(--color-marron); - transition: width 0.3s ease; -} - -.nav-link:hover::after { - width: 100%; -} - -/* Asegurar alineación correcta del navbar */ -.navbar-nav { - align-items: center; -} - -.navbar-nav .nav-item { - display: flex; - align-items: center; -} - -.navbar-nav .nav-link { - display: flex; - align-items: center; - padding: 0.5rem 1rem; -} - -/* Estilos específicos para el enlace Acceder */ -.nav-item a[href="login.php"] { - background: linear-gradient(135deg, var(--color-marron), #a0522d); - color: white !important; - border-radius: 25px; - padding: 8px 20px !important; - text-decoration: none; - font-weight: 600; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3); - margin-left: 8px; -} - -.nav-item a[href="login.php"]:hover { - background: linear-gradient(135deg, #a0522d, var(--color-marron)); - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4); - color: white !important; -} - -/* Efectos de scroll suave */ -html { - scroll-behavior: smooth; -} - -/* Sombras personalizadas */ -.shadow-sm { - box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important; -} - -.shadow { - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important; -} - -/* === DROPDOWN DEL USUARIO === */ -.dropdown-toggle { - border: none !important; - background: none !important; - color: var(--color-marron) !important; - font-weight: 600; - display: flex; - gap: 8px; - padding: 8px 12px; - border-radius: 8px; - transition: all 0.3s ease; -} - -.dropdown-toggle:hover { - background: rgba(139, 69, 19, 0.1) !important; - color: var(--color-marron) !important; -} - -.dropdown-toggle:focus { - box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2); -} - -.dropdown-toggle::after { - margin-left: 8px; - color: var(--color-marron); -} - -.dropdown-menu { - border: 1px solid var(--color-cafe-claro); - border-radius: 12px; - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); - padding: 0.75rem 0; - min-width: 200px; - margin-top: 0.5rem; - background: var(--color-crema); - z-index: 10001 !important; - position: absolute !important; -} - -.dropdown-item { - color: var(--color-gris-oscuro); - padding: 0.5rem 1.5rem !important; - font-weight: 600 !important; - display: flex; - align-items: center; - gap: 10px; - transition: all 0.3s ease; - border-radius: 8px !important; - margin: 0.2rem 0.5rem !important; -} - -.dropdown-item:hover { - background: var(--color-cafe-con-leche) !important; - color: var(--color-marron) !important; - transform: translateX(5px); -} - -.dropdown-item:focus { - background: var(--color-cafe-con-leche) !important; - color: var(--color-marron) !important; -} - -.dropdown-divider { - margin: 0.5rem 0; - border-color: var(--color-cafe-claro); -} - -/* Asegurar que main no interfiera */ -main { - position: relative; - z-index: 1; -} - -/* === NAVBAR Y DROPDOWN - VERSIÓN SIMPLIFICADA === */ -/* Navbar con z-index correcto */ -.navbar { - position: sticky !important; - top: 0; - z-index: 1050 !important; -} - -header { - position: sticky !important; - top: 0; - z-index: 1050 !important; -} - -/* Carrusel con z-index menor */ -.carousel-fullwidth, -.carousel, -.carousel-inner, -.carousel-item { - z-index: 1 !important; -} - -/* Dropdown con z-index Bootstrap estándar */ -.dropdown-menu { - z-index: 1051 !important; -} - -/* Responsive */ -@media (max-width: 768px) { - .carousel-fixed-img { - height: 250px; - } - - .card-img-custom { - height: 200px; - } - - .carousel-control-prev, - .carousel-control-next { - width: 40px; - height: 40px; - } - - h2::after { - width: 60px; - } - - h2::after { - width: 60px; - } - - /* Dropdown responsivo */ - .dropdown-toggle { - font-size: 0.9rem; - padding: 6px 10px; - } - - .dropdown-menu { - min-width: 180px; - font-size: 0.9rem; - } - - .dropdown-item { - padding: 8px 12px; - } -} - -@media (max-width: 576px) { - .carousel-fixed-img { - height: 200px; - } - - .card-img-custom { - height: 180px; - } - - .carousel-caption { - padding: 8px 15px; - bottom: 10px; - left: 10px; - right: 10px; - max-width: 300px; - } - - .carousel-caption h5 { - font-size: 1rem; - } - - .carousel-caption p { - font-size: 0.8rem; - } -} - -/* Badges de estado */ -.badge { - font-size: 0.75rem; - padding: 0.5em 0.75em; - border-radius: 20px; -} - -/* Efectos de loading */ -.loading { - opacity: 0.6; - pointer-events: none; -} - -/* Estilos para el precio */ -.product-info .h5 { - font-size: 1.5rem; - font-weight: 700; - text-shadow: 1px 1px 2px rgba(0,0,0,0.1); -} - -/* Efectos de hover para navegación */ -.nav-link { - position: relative; - transition: color 0.3s ease; -} - -.nav-link::after { - content: ''; - position: absolute; - bottom: -5px; - left: 0; - width: 0; - height: 2px; - background: var(--color-marron); - transition: width 0.3s ease; -} - -.nav-link:hover::after { - width: 100%; -} - -/* Asegurar alineación correcta del navbar */ -.navbar-nav { - align-items: center; -} - -.navbar-nav .nav-item { - display: flex; - align-items: center; -} - -.navbar-nav .nav-link { - display: flex; - align-items: center; - padding: 0.5rem 1rem; -} - -/* Estilos específicos para el enlace Acceder */ -.nav-item a[href="login.php"] { - background: linear-gradient(135deg, var(--color-marron), #a0522d); - color: white !important; - border-radius: 25px; - padding: 8px 20px !important; - text-decoration: none; - font-weight: 600; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3); - margin-left: 8px; -} - -.nav-item a[href="login.php"]:hover { - background: linear-gradient(135deg, #a0522d, var(--color-marron)); - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4); - color: white !important; -} - -/* Efectos de scroll suave */ -html { - scroll-behavior: smooth; -} - -/* Sombras personalizadas */ -.shadow-sm { - box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important; -} - -.shadow { - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important; -} - -/* === DROPDOWN DEL USUARIO === */ -.dropdown-toggle { - border: none !important; - background: none !important; - color: var(--color-marron) !important; - font-weight: 600; - display: flex; - gap: 8px; - padding: 8px 12px; - border-radius: 8px; - transition: all 0.3s ease; -} - -.dropdown-toggle:hover { - background: rgba(139, 69, 19, 0.1) !important; - color: var(--color-marron) !important; -} - -.dropdown-toggle:focus { - box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2); -} - -.dropdown-toggle::after { - margin-left: 8px; - color: var(--color-marron); -} - -.dropdown-menu { - border: 1px solid var(--color-cafe-claro); - border-radius: 12px; - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); - padding: 0.75rem 0; - min-width: 200px; - margin-top: 0.5rem; - background: var(--color-crema); - z-index: 10001 !important; - position: absolute !important; -} - -.dropdown-item { - color: var(--color-gris-oscuro); - padding: 0.5rem 1.5rem !important; - font-weight: 600 !important; - display: flex; - align-items: center; - gap: 10px; - transition: all 0.3s ease; - border-radius: 8px !important; - margin: 0.2rem 0.5rem !important; -} - -.dropdown-item:hover { - background: var(--color-cafe-con-leche) !important; - color: var(--color-marron) !important; - transform: translateX(5px); -} - -.dropdown-item:focus { - background: var(--color-cafe-con-leche) !important; - color: var(--color-marron) !important; -} - -.dropdown-divider { - margin: 0.5rem 0; - border-color: var(--color-cafe-claro); -} - -/* Asegurar que main no interfiera */ -main { - position: relative; - z-index: 1; -} - -/* === NAVBAR Y DROPDOWN - VERSIÓN SIMPLIFICADA === */ -/* Navbar con z-index correcto */ -.navbar { - position: sticky !important; - top: 0; - z-index: 1050 !important; -} - -header { - position: sticky !important; - top: 0; - z-index: 1050 !important; -} - -/* Carrusel con z-index menor */ -.carousel-fullwidth, -.carousel, -.carousel-inner, -.carousel-item { - z-index: 1 !important; -} - -/* Dropdown con z-index Bootstrap estándar */ -.dropdown-menu { - z-index: 1051 !important; -} - -/* Responsive */ -@media (max-width: 768px) { - .carousel-fixed-img { - height: 250px; - } - - .card-img-custom { - height: 200px; - } - - .carousel-control-prev, - .carousel-control-next { - width: 40px; - height: 40px; - } - - h2::after { - width: 60px; - } - - h2::after { - width: 60px; - } - - /* Dropdown responsivo */ - .dropdown-toggle { - font-size: 0.9rem; - padding: 6px 10px; - } - - .dropdown-menu { - min-width: 180px; - font-size: 0.9rem; - } - - .dropdown-item { - padding: 8px 12px; - } -} - -@media (max-width: 576px) { - .carousel-fixed-img { - height: 200px; - } - - .card-img-custom { - height: 180px; - } - - .carousel-caption { - padding: 8px 15px; - bottom: 10px; - left: 10px; - right: 10px; - max-width: 300px; - } - - .carousel-caption h5 { - font-size: 1rem; - } - - .carousel-caption p { - font-size: 0.8rem; - } -} - -/* Badges de estado */ -.badge { - font-size: 0.75rem; - padding: 0.5em 0.75em; - border-radius: 20px; -} - -/* Efectos de loading */ -.loading { - opacity: 0.6; - pointer-events: none; -} - -/* Estilos para el precio */ -.product-info .h5 { - font-size: 1.5rem; - font-weight: 700; - text-shadow: 1px 1px 2px rgba(0,0,0,0.1); -} - -/* Efectos de hover para navegación */ -.nav-link { - position: relative; - transition: color 0.3s ease; -} - -.nav-link::after { - content: ''; - position: absolute; - bottom: -5px; - left: 0; - width: 0; - height: 2px; - background: var(--color-marron); - transition: width 0.3s ease; -} - -.nav-link:hover::after { - width: 100%; -} - -/* Asegurar alineación correcta del navbar */ -.navbar-nav { - align-items: center; -} - -.navbar-nav .nav-item { - display: flex; - align-items: center; -} - -.navbar-nav .nav-link { - display: flex; - align-items: center; - padding: 0.5rem 1rem; -} - -/* Estilos específicos para el enlace Acceder */ -.nav-item a[href="login.php"] { - background: linear-gradient(135deg, var(--color-marron), #a0522d); - color: white !important; - border-radius: 25px; - padding: 8px 20px !important; - text-decoration: none; - font-weight: 600; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3); - margin-left: 8px; -} - -.nav-item a[href="login.php"]:hover { - background: linear-gradient(135deg, #a0522d, var(--color-marron)); - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4); - color: white !important; -} - -/* Efectos de scroll suave */ -html { - scroll-behavior: smooth; -} - -/* Sombras personalizadas */ -.shadow-sm { - box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important; -} - -.shadow { - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important; -} - -/* === DROPDOWN DEL USUARIO === */ -.dropdown-toggle { - border: none !important; - background: none !important; - color: var(--color-marron) !important; - font-weight: 600; - display: flex; - gap: 8px; - padding: 8px 12px; - border-radius: 8px; - transition: all 0.3s ease; -} - -.dropdown-toggle:hover { - background: rgba(139, 69, 19, 0.1) !important; - color: var(--color-marron) !important; -} - -.dropdown-toggle:focus { - box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2); -} - -.dropdown-toggle::after { - margin-left: 8px; - color: var(--color-marron); -} - -.dropdown-menu { - border: 1px solid var(--color-cafe-claro); - border-radius: 12px; - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); - padding: 0.75rem 0; - min-width: 200px; - margin-top: 0.5rem; - background: var(--color-crema); - z-index: 10001 !important; - position: absolute !important; -} - -.dropdown-item { - color: var(--color-gris-oscuro); - padding: 0.5rem 1.5rem !important; - font-weight: 600 !important; - display: flex; - align-items: center; - gap: 10px; - transition: all 0.3s ease; - border-radius: 8px !important; - margin: 0.2rem 0.5rem !important; -} - -.dropdown-item:hover { - background: var(--color-cafe-con-leche) !important; - color: var(--color-marron) !important; - transform: translateX(5px); -} - -.dropdown-item:focus { - background: var(--color-cafe-con-leche) !important; - color: var(--color-marron) !important; -} - -.dropdown-divider { - margin: 0.5rem 0; - border-color: var(--color-cafe-claro); -} - -/* Asegurar que main no interfiera */ -main { - position: relative; - z-index: 1; -} - -/* === NAVBAR Y DROPDOWN - VERSIÓN SIMPLIFICADA === */ -/* Navbar con z-index correcto */ -.navbar { - position: sticky !important; - top: 0; - z-index: 1050 !important; -} - -header { - position: sticky !important; - top: 0; - z-index: 1050 !important; -} - -/* Carrusel con z-index menor */ -.carousel-fullwidth, -.carousel, -.carousel-inner, -.carousel-item { - z-index: 1 !important; -} - -/* Dropdown con z-index Bootstrap estándar */ -.dropdown-menu { - z-index: 1051 !important; -} - -/* Responsive */ -@media (max-width: 768px) { - .carousel-fixed-img { - height: 250px; - } - - .card-img-custom { - height: 200px; - } - - .carousel-control-prev, - .carousel-control-next { - width: 40px; - height: 40px; - } - - h2::after { - width: 60px; - } - - h2::after { - width: 60px; - } - - /* Dropdown responsivo */ - .dropdown-toggle { - font-size: 0.9rem; - padding: 6px 10px; - } - - .dropdown-menu { - min-width: 180px; - font-size: 0.9rem; - } - - .dropdown-item { - padding: 8px 12px; - } -} - -@media (max-width: 576px) { - .carousel-fixed-img { - height: 200px; - } - - .card-img-custom { - height: 180px; - } - - .carousel-caption { - padding: 8px 15px; - bottom: 10px; - left: 10px; - right: 10px; - max-width: 300px; - } - - .carousel-caption h5 { - font-size: 1rem; - } - - .carousel-caption p { - font-size: 0.8rem; - } -} - -/* Badges de estado */ -.badge { - font-size: 0.75rem; - padding: 0.5em 0.75em; - border-radius: 20px; -} - -/* Efectos de loading */ -.loading { - opacity: 0.6; - pointer-events: none; -} - -/* Estilos para el precio */ -.product-info .h5 { - font-size: 1.5rem; - font-weight: 700; - text-shadow: 1px 1px 2px rgba(0,0,0,0.1); -} - -/* Efectos de hover para navegación */ -.nav-link { - position: relative; - transition: color 0.3s ease; -} - -.nav-link::after { - content: ''; - position: absolute; - bottom: -5px; - left: 0; - width: 0; - height: 2px; - background: var(--color-marron); - transition: width 0.3s ease; -} - -.nav-link:hover::after { - width: 100%; -} - -/* Asegurar alineación correcta del navbar */ -.navbar-nav { - align-items: center; -} - -.navbar-nav .nav-item { - display: flex; - align-items: center; -} - -.navbar-nav .nav-link { - display: flex; - align-items: center; - padding: 0.5rem 1rem; -} - -/* Estilos específicos para el enlace Acceder */ -.nav-item a[href="login.php"] { - background: linear-gradient(135deg, var(--color-marron), #a0522d); - color: white !important; - border-radius: 25px; - padding: 8px 20px !important; - text-decoration: none; - font-weight: 600; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3); - margin-left: 8px; -} - -.nav-item a[href="login.php"]:hover { - background: linear-gradient(135deg, #a0522d, var(--color-marron)); - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4); - color: white !important; -} - -/* Efectos de scroll suave */ -html { - scroll-behavior: smooth; -} - -/* Sombras personalizadas */ -.shadow-sm { - box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important; -} - -.shadow { - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important; -} - -/* === DROPDOWN DEL USUARIO === */ -.dropdown-toggle { - border: none !important; - background: none !important; - color: var(--color-marron) !important; - font-weight: 600; - display: flex; - gap: 8px; - padding: 8px 12px; - border-radius: 8px; - transition: all 0.3s ease; -} - -.dropdown-toggle:hover { - background: rgba(139, 69, 19, 0.1) !important; - color: var(--color-marron) !important; -} - -.dropdown-toggle:focus { - box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2); -} - -.dropdown-toggle::after { - margin-left: 8px; - color: var(--color-marron); -} - -.dropdown-menu { - border: 1px solid var(--color-cafe-claro); - border-radius: 12px; - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); - padding: 0.75rem 0; - min-width: 200px; - margin-top: 0.5rem; - background: var(--color-crema); - z-index: 10001 !important; - position: absolute !important; -} - -.dropdown-item { - color: var(--color-gris-oscuro); - padding: 0.5rem 1.5rem !important; - font-weight: 600 !important; - display: flex; - align-items: center; - gap: 10px; - transition: all 0.3s ease; - border-radius: 8px !important; - margin: 0.2rem 0.5rem !important; -} - -.dropdown-item:hover { - background: var(--color-cafe-con-leche) !important; - color: var(--color-marron) !important; - transform: translateX(5px); -} - -.dropdown-item:focus { - background: var(--color-cafe-con-leche) !important; - color: var(--color-marron) !important; -} - -.dropdown-divider { - margin: 0.5rem 0; - border-color: var(--color-cafe-claro); -} - -/* Asegurar que main no interfiera */ -main { - position: relative; - z-index: 1; -} - -/* === NAVBAR Y DROPDOWN - VERSIÓN SIMPLIFICADA === */ -/* Navbar con z-index correcto */ -.navbar { - position: sticky !important; - top: 0; - z-index: 1050 !important; -} - -header { - position: sticky !important; - top: 0; - z-index: 1050 !important; -} - -/* Carrusel con z-index menor */ -.carousel-fullwidth, -.carousel, -.carousel-inner, -.carousel-item { - z-index: 1 !important; -} - -/* Dropdown con z-index Bootstrap estándar */ -.dropdown-menu { - z-index: 1051 !important; -} - -/* Responsive */ -@media (max-width: 768px) { - .carousel-fixed-img { - height: 250px; - } - - .card-img-custom { - height: 200px; - } - - .carousel-control-prev, - .carousel-control-next { - width: 40px; - height: 40px; - } - - h2::after { - width: 60px; - } - - h2::after { - width: 60px; - } - - /* Dropdown responsivo */ - .dropdown-toggle { - font-size: 0.9rem; - padding: 6px 10px; - } - - .dropdown-menu { - min-width: 180px; - font-size: 0.9rem; - } - - .dropdown-item { - padding: 8px 12px; - } -} - -@media (max-width: 576px) { - .carousel-fixed-img { - height: 200px; - } - - .card-img-custom { - height: 180px; - } - - .carousel-caption { - padding: 8px 15px; - bottom: 10px; - left: 10px; - right: 10px; - max-width: 300px; - } - - .carousel-caption h5 { - font-size: 1rem; - } - - .carousel-caption p { - font-size: 0.8rem; - } -} - -/* Stock agotado */ -.out-of-stock { - opacity: 0.6; -} - -.out-of-stock::before { - content: 'Agotado'; - position: absolute; - top: 10px; - left: 10px; - background: #dc3545; - color: white; - padding: 4px 8px; - border-radius: 10px; - font-size: 0.7rem; - font-weight: 600; - z-index: 3; -} - -.out-of-stock .btn-pedir { - background: #6c757d !important; - cursor: not-allowed !important; -} - -/* Animaciones para botones */ -.btn-pedir.processing { - animation: pulseButton 1s infinite; -} \ No newline at end of file diff --git a/files/stylemenu.css b/files/stylemenu.css deleted file mode 100644 index 02da0b9..0000000 --- a/files/stylemenu.css +++ /dev/null @@ -1,19 +0,0 @@ - -.product-card-item { - display: block; /* Asegura que la tarjeta sea visible por defecto */ -} -.product-card-item.hidden { - display: none; /* Oculta la tarjeta */ -} -.btn-agregar-pedido { - background-color: #E2725B; /* Tono terracota */ - color: white; - border: none; - transition: background-color 0.3s, transform 0.2s; - font-weight: bold; -} -.btn-agregar-pedido:hover { - background-color: #C66049; /* Tono terracota más oscuro */ - color: white; - transform: translateY(-2px); -} diff --git a/files/stylempleado.css b/files/stylempleado.css deleted file mode 100644 index e69de29..0000000 diff --git a/files/styleproductostabla.css b/files/styleproductostabla.css deleted file mode 100644 index 520e9aa..0000000 --- a/files/styleproductostabla.css +++ /dev/null @@ -1,842 +0,0 @@ -/* Estilos para la gestión de productos - Panadería */ -@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Exo+2:wght@300;400;500;600;700&display=swap'); - -/* Variables CSS */ -:root { - --primary-color: #8C5A37; - --primary-hover: #6E462A; - --text-dark: #3D2C21; - --text-light: #6B5B51; - --border-color: #D3C5BC; - --container-bg: rgba(255, 255, 255, 0.75); - --white: #ffffff; - --light-gray: #f8f9fa; - --medium-gray: #e9ecef; - --success-color: #4CAF50; - --info-color: #2196F3; - --warning-color: #FF9800; - --danger-color: #F44336; - --crema: #f5f5dc; - --shadow: 0 2px 10px rgba(0, 0, 0, 0.1); - --border-radius: 10px; - --transition: all 0.3s ease; -} - -/* Reset y estilos base */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: 'Exo 2', sans-serif; - background: linear-gradient(135deg, #4e3f30 0%, #63554b 100%); - color: var(--text-dark); - line-height: 1.6; - min-height: 100vh; -} - -/* Contenedor principal */ -.container { - max-width: 1200px; - margin: 0 auto; - padding: 20px; -} - -/* Header section */ -.header-section { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 30px; - background: var(--container-bg); - padding: 20px; - border-radius: var(--border-radius); - box-shadow: var(--shadow); - border: 1px solid var(--border-color); -} - -.header-section h1 { - color: var(--primary-color); - font-family: 'Playfair Display', serif; - font-size: 2.5rem; - font-weight: 700; - margin: 0; - text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); -} - -.btn-regresar { - display: flex; - align-items: center; - gap: 8px; - padding: 12px 20px; - background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%); - color: var(--white); - text-decoration: none; - border-radius: 25px; - font-weight: 600; - transition: var(--transition); - box-shadow: var(--shadow); - border: 1px solid var(--border-color); -} - -.btn-regresar:hover { - transform: translateY(-2px); - box-shadow: 0 4px 20px rgba(140, 90, 55, 0.3); - color: var(--white); -} - -/* Mensajes de éxito y error */ -.mensaje-exito, .mensaje-error { - padding: 15px 20px; - margin: 20px 0; - border-radius: var(--border-radius); - font-weight: 600; - text-align: center; - animation: slideIn 0.3s ease-out; -} - -.mensaje-exito { - background: linear-gradient(135deg, rgba(76, 175, 80, 0.1) 0%, rgba(76, 175, 80, 0.05) 100%); - color: var(--success-color); - border: 1px solid rgba(76, 175, 80, 0.3); -} - -.mensaje-error { - background: linear-gradient(135deg, rgba(244, 67, 54, 0.1) 0%, rgba(244, 67, 54, 0.05) 100%); - color: var(--danger-color); - border: 1px solid rgba(244, 67, 54, 0.3); -} - -/* Formulario container */ -.formulario-container { - background: var(--container-bg); - padding: 30px; - border-radius: var(--border-radius); - box-shadow: var(--shadow); - margin-bottom: 30px; - text-align: center; - border: 1px solid var(--border-color); -} - -.formulario-container h2 { - color: var(--primary-color); - font-family: 'Playfair Display', serif; - margin-bottom: 20px; - font-size: 1.8rem; - font-weight: 700; -} - -.btn-modal-trigger { - display: inline-flex; - align-items: center; - gap: 10px; - padding: 15px 30px; - background: linear-gradient(135deg, var(--success-color) 0%, rgba(76, 175, 80, 0.9) 100%); - color: var(--white); - border: none; - border-radius: 25px; - font-size: 1.1rem; - font-weight: 600; - cursor: pointer; - transition: var(--transition); - box-shadow: var(--shadow); -} - -.btn-modal-trigger:hover { - transform: translateY(-2px); - box-shadow: 0 4px 20px rgba(76, 175, 80, 0.3); -} - -/* Tabla section */ -.tabla-section { - background: var(--container-bg); - border-radius: var(--border-radius); - box-shadow: var(--shadow); - overflow: hidden; - border: 1px solid var(--border-color); -} - -.tabla-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 25px 30px; - background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%); - color: var(--white); -} - -.tabla-header h2 { - margin: 0; - font-size: 1.8rem; - font-family: 'Playfair Display', serif; - font-weight: 700; -} - -.filtro-busqueda { - display: flex; - align-items: center; - gap: 10px; - background: rgba(255, 255, 255, 0.1); - padding: 10px 15px; - border-radius: 20px; - backdrop-filter: blur(10px); -} - -.filtro-busqueda input { - background: transparent; - border: none; - color: var(--white); - font-size: 1rem; - outline: none; - width: 250px; -} - -.filtro-busqueda input::placeholder { - color: rgba(255, 255, 255, 0.7); -} - -.filtro-busqueda .material-symbols-outlined { - color: rgba(255, 255, 255, 0.8); -} - -/* Tabla contenedor */ -.tabla-contenedor { - overflow-x: auto; - max-height: 600px; -} - -/* Estilos de tabla */ -#tabla-productos { - width: 100%; - border-collapse: collapse; - font-size: 0.95rem; -} - -#tabla-productos thead { - background: linear-gradient(135deg, var(--text-dark) 0%, var(--text-light) 100%); - color: var(--white); - position: sticky; - top: 0; - z-index: 10; -} - -#tabla-productos th { - padding: 15px 12px; - text-align: left; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; - border-bottom: 2px solid var(--medium-gray); -} - -#tabla-productos tbody tr { - transition: var(--transition); - border-bottom: 1px solid var(--medium-gray); -} - -#tabla-productos tbody tr:hover { - background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); - transform: scale(1.01); -} - -#tabla-productos tbody tr:nth-child(even) { - background: #f8f9fa; -} - -#tabla-productos tbody tr:nth-child(even):hover { - background: linear-gradient(135deg, #e9ecef 0%, #dee2e6 100%); -} - -#tabla-productos td { - padding: 12px; - vertical-align: middle; - border-bottom: 1px solid #dee2e6; -} - -/* Precio destacado */ -.precio { - font-weight: 700; - color: var(--success-color); - font-size: 1.1rem; -} - -/* Estados */ -.estado-activo, .estado-inactivo { - display: inline-flex; - align-items: center; - gap: 5px; - padding: 5px 12px; - border-radius: 15px; - font-size: 0.85rem; - font-weight: 600; -} - -.estado-activo { - background: linear-gradient(135deg, rgba(76, 175, 80, 0.1) 0%, rgba(76, 175, 80, 0.05) 100%); - color: var(--success-color); - border: 1px solid rgba(76, 175, 80, 0.3); -} - -.estado-inactivo { - background: linear-gradient(135deg, rgba(244, 67, 54, 0.1) 0%, rgba(244, 67, 54, 0.05) 100%); - color: var(--danger-color); - border: 1px solid rgba(244, 67, 54, 0.3); -} - -/* Acciones */ -.acciones { - display: flex; - gap: 8px; - justify-content: center; -} - -.btn-action { - display: inline-flex; - align-items: center; - justify-content: center; - width: 40px; - height: 40px; - border: none; - border-radius: 50%; - cursor: pointer; - transition: var(--transition); - font-size: 1.2rem; -} - -.btn-toggle { - background: linear-gradient(135deg, var(--warning-color) 0%, rgba(255, 152, 0, 0.9) 100%); - color: var(--white); -} - -.btn-toggle:hover { - transform: scale(1.1); - box-shadow: 0 2px 10px rgba(255, 152, 0, 0.4); -} - -.btn-gestionar { - background: linear-gradient(135deg, var(--info-color) 0%, rgba(33, 150, 243, 0.9) 100%); - color: var(--white); -} - -.btn-gestionar:hover { - transform: scale(1.1); - box-shadow: 0 2px 10px rgba(33, 150, 243, 0.4); -} - -.btn-eliminar { - background: linear-gradient(135deg, var(--danger-color) 0%, rgba(244, 67, 54, 0.9) 100%); - color: var(--white); -} - -.btn-eliminar:hover { - transform: scale(1.1); - box-shadow: 0 2px 10px rgba(244, 67, 54, 0.4); -} - -/* Estilos de modal */ -.modal { - display: none; - position: fixed; - z-index: 1000; - left: 0; - top: 0; - width: 100%; - height: 100%; - background: rgba(0, 0, 0, 0.5); - backdrop-filter: blur(5px); - animation: fadeIn 0.3s ease-out; -} - -.modal-content { - background: var(--white); - margin: 5% auto; - padding: 0; - border-radius: var(--border-radius); - max-width: 600px; - width: 90%; - max-height: 80vh; - overflow-y: auto; - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); - animation: slideInModal 0.3s ease-out; -} - -.modal-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 20px 30px; - background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%); - color: var(--white); - border-radius: var(--border-radius) var(--border-radius) 0 0; -} - -.modal-header h2 { - margin: 0; - font-size: 1.5rem; - font-family: 'Playfair Display', serif; - font-weight: 700; -} - -.modal-close { - background: none; - border: none; - color: var(--white); - font-size: 2rem; - cursor: pointer; - padding: 0; - width: 30px; - height: 30px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 50%; - transition: var(--transition); -} - -.modal-close:hover { - background: rgba(255, 255, 255, 0.2); -} - -.modal-body { - padding: 30px; -} - -/* Formulario styles */ -.form-row { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 20px; - margin-bottom: 20px; -} - -.form-group { - display: flex; - flex-direction: column; -} - -.form-group label { - margin-bottom: 8px; - font-weight: 600; - color: var(--text-dark); -} - -.form-group input { - padding: 12px 15px; - border: 2px solid var(--border-color); - border-radius: var(--border-radius); - font-size: 1rem; - transition: var(--transition); - background: var(--white); -} - -.form-group input:focus { - outline: none; - border-color: var(--primary-color); - box-shadow: 0 0 0 3px rgba(140, 90, 55, 0.1); -} - -/* Modal actions */ -.modal-actions { - display: flex; - justify-content: center; - gap: 15px; - margin-top: 30px; - padding-top: 20px; - border-top: 1px solid var(--medium-gray); -} - -.modal-btn { - display: inline-flex; - align-items: center; - gap: 8px; - padding: 12px 25px; - border: none; - border-radius: 25px; - font-weight: 600; - cursor: pointer; - transition: var(--transition); - text-decoration: none; - font-size: 1rem; - font-family: 'Exo 2', sans-serif; -} - -.modal-btn.primary { - background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%); - color: var(--white); -} - -.modal-btn.primary:hover { - transform: translateY(-2px); - box-shadow: 0 4px 20px rgba(140, 90, 55, 0.3); -} - -.modal-btn.secondary { - background: linear-gradient(135deg, var(--text-light) 0%, var(--text-dark) 100%); - color: var(--white); -} - -.modal-btn.secondary:hover { - transform: translateY(-2px); - box-shadow: 0 4px 20px rgba(107, 91, 81, 0.3); -} - -.modal-btn.success { - background: linear-gradient(135deg, var(--success-color) 0%, rgba(76, 175, 80, 0.9) 100%); - color: var(--white); -} - -.modal-btn.success:hover { - transform: translateY(-2px); - box-shadow: 0 4px 20px rgba(76, 175, 80, 0.3); -} - -.modal-btn.danger { - background: linear-gradient(135deg, var(--danger-color) 0%, rgba(244, 67, 54, 0.9) 100%); - color: var(--white); -} - -.modal-btn.danger:hover { - transform: translateY(-2px); - box-shadow: 0 4px 20px rgba(244, 67, 54, 0.3); -} - -/* Modal icon */ -.modal-icon { - text-align: center; - margin-bottom: 20px; - font-size: 4rem; -} - -.modal-icon.success { - color: var(--success-color); -} - -.modal-icon.error { - color: var(--danger-color); -} - -.modal-icon.warning { - color: var(--warning-color); -} - -/* Modal message */ -.modal-message { - text-align: center; - margin-bottom: 20px; - font-size: 1.1rem; - line-height: 1.6; -} - -/* Countdown info */ -.countdown-info { - text-align: center; - margin-top: 15px; - font-size: 0.9rem; - color: var(--text-light); - opacity: 0.7; -} - -/* Status badges */ -.status-badge { - display: inline-flex; - align-items: center; - gap: 5px; - padding: 6px 12px; - border-radius: 15px; - font-size: 0.85rem; - font-weight: 600; -} - -.status-activo { - background: linear-gradient(135deg, rgba(76, 175, 80, 0.1) 0%, rgba(76, 175, 80, 0.05) 100%); - color: var(--success-color); - border: 1px solid rgba(76, 175, 80, 0.3); -} - -.status-inactivo { - background: linear-gradient(135deg, rgba(244, 67, 54, 0.1) 0%, rgba(244, 67, 54, 0.05) 100%); - color: var(--danger-color); - border: 1px solid rgba(244, 67, 54, 0.3); -} - -/* No resultados */ -.no-resultados { - text-align: center; - font-style: italic; - color: var(--text-light); - opacity: 0.7; - padding: 40px !important; -} - -/* Animaciones */ -@keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@keyframes slideIn { - from { - transform: translateY(-20px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -@keyframes slideInModal { - from { - transform: translateY(-50px); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -/* =============================================== - ESTILOS PARA EDICIÓN INLINE EN TABLA - =============================================== */ - -/* Contenedor de celda editable */ -.editable-cell { - display: flex; - align-items: center; - gap: 8px; - padding: 4px; - min-height: 40px; - position: relative; -} - -/* Display de valor */ -.editable-cell .value-display { - font-weight: 600; - padding: 6px 8px; - border-radius: 4px; - transition: all 0.3s ease; - cursor: default; -} - -/* Input de edición */ -.editable-cell .value-input { - padding: 6px 8px; - border: 2px solid var(--primary-color); - border-radius: 4px; - font-size: 14px; - font-weight: 600; - width: 100px; - background: white; - color: var(--text-dark); - transition: all 0.3s ease; -} - -.editable-cell .value-input:focus { - outline: none; - border-color: var(--info-color); - box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1); - transform: scale(1.02); -} - -/* Botón de editar */ -.editable-cell .btn-edit { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - color: white; - border: none; - padding: 6px 8px; - border-radius: 15px; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - font-size: 0.8em; - transition: all 0.3s ease; - opacity: 0.7; - min-width: 32px; - height: 32px; -} - -.editable-cell:hover .btn-edit { - opacity: 1; - transform: scale(1.1); - box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3); -} - -.editable-cell .btn-edit .material-symbols-outlined { - font-size: 16px; -} - -/* Controles de edición */ -.editable-cell .edit-controls { - display: flex; - gap: 4px; - align-items: center; -} - -.editable-cell .btn-save, -.editable-cell .btn-cancel { - border: none; - padding: 4px 6px; - border-radius: 12px; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - font-size: 0.7em; - transition: all 0.3s ease; - min-width: 28px; - height: 28px; -} - -.editable-cell .btn-save { - background: linear-gradient(135deg, #28a745 0%, #20c997 100%); - color: white; -} - -.editable-cell .btn-save:hover { - transform: scale(1.1); - box-shadow: 0 2px 8px rgba(40, 167, 69, 0.3); -} - -.editable-cell .btn-cancel { - background: linear-gradient(135deg, #dc3545 0%, #e74c3c 100%); - color: white; -} - -.editable-cell .btn-cancel:hover { - transform: scale(1.1); - box-shadow: 0 2px 8px rgba(220, 53, 69, 0.3); -} - -.editable-cell .btn-save .material-symbols-outlined, -.editable-cell .btn-cancel .material-symbols-outlined { - font-size: 14px; -} - -/* Estilos específicos para precio */ -.precio .editable-cell { - justify-content: flex-start; -} - -.precio .value-display { - color: #28a745; - font-size: 1.1em; - background: rgba(40, 167, 69, 0.1); - border: 1px solid rgba(40, 167, 69, 0.2); -} - -/* Estilos específicos para stock */ -.stock .editable-cell { - justify-content: flex-start; -} - -.stock .value-display { - color: #17a2b8; - font-size: 1.1em; - background: rgba(23, 162, 184, 0.1); - border: 1px solid rgba(23, 162, 184, 0.2); -} - -/* Efecto de carga */ -.editable-cell .loading { - display: flex; - align-items: center; - gap: 8px; - color: #007bff; - font-weight: 600; - padding: 6px 12px; - background: rgba(0, 123, 255, 0.1); - border-radius: 4px; - border: 1px solid rgba(0, 123, 255, 0.2); -} - -.editable-cell .loading .material-symbols-outlined { - animation: spin 1s linear infinite; -} - -@keyframes spin { - from { transform: rotate(0deg); } - to { transform: rotate(360deg); } -} - -/* Efecto de éxito */ -.editable-cell .success-highlight { - background: rgba(40, 167, 69, 0.2) !important; - color: #155724 !important; - border: 1px solid rgba(40, 167, 69, 0.4) !important; - animation: successPulse 2s ease-in-out; -} - -@keyframes successPulse { - 0% { transform: scale(1); } - 50% { transform: scale(1.05); } - 100% { transform: scale(1); } -} - -/* Responsive para dispositivos móviles */ -@media (max-width: 768px) { - .editable-cell { - flex-direction: column; - align-items: flex-start; - gap: 4px; - min-height: auto; - } - - .editable-cell .value-input { - width: 80px; - font-size: 12px; - } - - .editable-cell .btn-edit, - .editable-cell .btn-save, - .editable-cell .btn-cancel { - min-width: 24px; - height: 24px; - padding: 2px 4px; - } - - .editable-cell .btn-edit .material-symbols-outlined, - .editable-cell .btn-save .material-symbols-outlined, - .editable-cell .btn-cancel .material-symbols-outlined { - font-size: 12px; - } -} - -/* Tooltip para botones */ -.editable-cell [title] { - position: relative; -} - -.editable-cell [title]:hover::after { - content: attr(title); - position: absolute; - bottom: 100%; - left: 50%; - transform: translateX(-50%); - background: rgba(0, 0, 0, 0.8); - color: white; - padding: 4px 8px; - border-radius: 4px; - font-size: 12px; - white-space: nowrap; - z-index: 1000; - margin-bottom: 4px; -} - -.editable-cell [title]:hover::before { - content: ''; - position: absolute; - bottom: 100%; - left: 50%; - transform: translateX(-50%); - border: 4px solid transparent; - border-top-color: rgba(0, 0, 0, 0.8); - z-index: 1000; -} diff --git a/files/styleregister.css b/files/styleregister.css deleted file mode 100644 index 36eb72d..0000000 --- a/files/styleregister.css +++ /dev/null @@ -1,382 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Lato:wght@400;700&family=Dancing+Script:wght@700&display=swap'); - -:root { - --primary-color: #8C5A37; /* Un marrón terracota, sofisticado y cálido */ - --primary-hover: #6E462A; /* Una versión más oscura para el hover */ - --text-dark: #3D2C21; /* Un marrón muy oscuro para texto principal */ - --text-light: #6B5B51; /* Un marrón más claro para texto secundario */ - --border-color: #D3C5BC; /* Un color suave para los bordes */ - --container-bg: rgba(255, 255, 255, 0.75); /* Fondo blanco semitransparente */ -} - -body { - background-image: url(../files/img/pan-rtzqhi1ok4k1bxlo.jpg); - background-repeat: no-repeat; - background-size: cover; - height: 100vh; - margin: 0; - display: flex; - justify-content: center; - align-items: center; - font-family: 'Lato', sans-serif; -} - -.registro-container { - background: var(--container-bg); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - padding: 40px; - border-radius: 15px; - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); - border: 1px solid rgba(255, 255, 255, 0.4); - width: 90%; - max-width: 900px; - display: flex; - align-items: flex-start; - gap: 40px; - text-align: left; -} - -.registro-left { - flex: 1; - padding-right: 30px; - border-right: 3px solid #8C5A37; - min-height: 400px; - display: flex; - flex-direction: column; - justify-content: center; -} - -.registro-right { - flex: 1.5; - padding-left: 30px; -} - -.logo-registro { - margin-bottom: 20px; - text-align: center; -} - -.logo-img-registro { - margin-top: 100px !important; - width: 200px; - height: 200px; - object-fit: cover; - border-radius: 50%; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); - transition: all 0.3s ease; - cursor: pointer; - border: 3px solid var(--primary-color); -} - -.logo-img-registro:hover { - transform: scale(1.05); - box-shadow: 0 8px 25px rgba(140, 90, 55, 0.4); -} - -.titulo-registro { - font-family: 'Exo 2'; - color: var(--primary-color); - font-size: 4rem; - font-weight: 700; - text-align: center; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); -} - -.form-group-registro { - margin-bottom: 20px; - text-align: left; -} - -.label-registro { - display: block; - margin-bottom: 8px; - color: var(--text-light); - font-weight: bold; -} - -.input-registro { - width: 100%; - padding: 12px; - border: 2px solid var(--border-color); - background-color: rgba(255, 255, 255, 0.5); - border-radius: 8px; - font-size: 16px; - color: var(--text-dark); - transition: all 0.3s ease; - box-sizing: border-box; -} - -.input-registro:focus { - outline: none; - border-color: var(--primary-color); - box-shadow: 0 0 10px rgba(140, 90, 55, 0.2); -} - -.btn-registro { - width: 100%; - padding: 12px; - background-color: var(--primary-color); - color: white; - border: none; - border-radius: 8px; - font-size: 16px; - font-weight: bold; - cursor: pointer; - transition: all 0.2s ease; -} - -.btn-registro:hover { - background-color: var(--primary-hover); - transform: translateY(-3px); - box-shadow: 0 6px 20px rgba(140, 90, 55, 0.3); -} - -.btn-registro:active { - transform: translateY(0); - box-shadow: 0 3px 10px rgba(140, 90, 55, 0.3); -} - -.footer-links-registro { - margin-top: 20px; - padding-top: 20px; - border-top: 1px solid var(--border-color); -} - -.footer-links-registro a { - color: var(--primary-color); - text-decoration: none; - font-size: 14px; - font-weight: bold; -} - -.footer-links-registro a:hover { - text-decoration: underline; - color: var(--text-dark); -} - -.success-message-registro { - background-color: #d4edda; - border: 1px solid #c3e6cb; - color: #155724; - padding: 12px; - border-radius: 8px; - margin-bottom: 20px; - font-family: 'Lato', sans-serif; - font-size: 14px; - text-align: center; -} - -.error-message-registro { - background-color: #f8d7da; - border: 1px solid #f5c6cb; - color: #721c24; - padding: 12px; - border-radius: 8px; - margin-bottom: 20px; - font-size: 14px; - display: none; -} - -.error-message-registro ul { - list-style-type: none; - padding: 0; -} - -.error-message-registro li { - margin: 5px 0; - padding-left: 15px; - position: relative; -} - -.error-message-registro li:before { - content: "•"; - color: #721c24; - font-weight: bold; - position: absolute; - left: 0; -} - -.user-type-info-registro { - background-color: rgba(140, 90, 55, 0.1); - border-left: 4px solid var(--primary-color); - padding: 15px; - margin-bottom: 20px; - border-radius: 8px; - text-align: left; -} - -.user-type-info-registro h4 { - color: var(--primary-color); - margin-bottom: 10px; - font-size: 16px; - font-weight: bold; -} - -.user-type-info-registro p { - color: var(--text-light); - font-size: 14px; - margin: 5px 0; - line-height: 1.4; -} - -.loading-registro { - text-align: center; - padding: 20px 0; - display: none; -} - -.loading-registro p { - margin-top: 10px; - color: var(--text-light); - font-size: 14px; -} - -.loading-spinner-registro { - border: 3px solid rgba(140, 90, 55, 0.2); - border-top-color: var(--primary-color); - border-radius: 50%; - width: 30px; - height: 30px; - animation: spin-registro 1s linear infinite; - margin: 0 auto; -} - -/* Modal de registro exitoso */ -.modal-overlay { - position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.6); - display: flex; - justify-content: center; - align-items: center; - z-index: 1000; - backdrop-filter: blur(5px); -} - -.modal-content { - background: var(--container-bg); - backdrop-filter: blur(15px); - -webkit-backdrop-filter: blur(15px); - border-radius: 20px; - padding: 40px; - box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2); - border: 1px solid rgba(255, 255, 255, 0.4); - text-align: center; - max-width: 400px; - width: 90%; - animation: modalAppear 0.3s ease-out; -} - -.modal-header { - margin-bottom: 25px; -} - -.check-icon { - margin-bottom: 20px; - animation: bounceIn 0.6s ease-out; -} - -.modal-header h2 { - font-family: 'Dancing Script', cursive; - color: var(--primary-color); - font-size: 2.2rem; - margin: 0; - font-weight: 700; -} - -.modal-body { - margin-bottom: 30px; -} - -.modal-body p { - color: var(--text-dark); - font-size: 16px; - margin: 10px 0; - line-height: 1.5; -} - -.btn-modal { - background-color: var(--primary-color); - color: white; - border: none; - padding: 12px 30px; - border-radius: 8px; - font-size: 16px; - font-weight: bold; - cursor: pointer; - transition: all 0.3s ease; -} - -.btn-modal:hover { - background-color: var(--primary-hover); - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(140, 90, 55, 0.3); -} - -@keyframes modalAppear { - from { - opacity: 0; - transform: scale(0.8) translateY(-20px); - } - to { - opacity: 1; - transform: scale(1) translateY(0); - } -} - -@keyframes bounceIn { - 0% { - transform: scale(0); - } - 50% { - transform: scale(1.2); - } - 100% { - transform: scale(1); - } -} - -@media (max-width: 768px) { - .registro-container { - flex-direction: column; - padding: 30px 20px; - margin: 20px; - max-width: 90%; - gap: 20px; - } - - .registro-left { - border-right: none; - border-bottom: 3px solid #8C5A37; - padding-right: 0; - padding-bottom: 20px; - min-height: auto; - } - - .registro-right { - padding-left: 0; - padding-top: 20px; - } - - .titulo-registro { - font-size: 2rem; - } - - .logo-img-registro { - margin-top: 50px !important; - width: 100px; - height: 100px; - } - - .form-group-registro { - margin-bottom: 18px; - } - - .user-type-info-registro { - padding: 12px; - } -} \ No newline at end of file diff --git a/files/styles-index.css b/files/styles-index.css deleted file mode 100644 index 4708d3a..0000000 --- a/files/styles-index.css +++ /dev/null @@ -1,367 +0,0 @@ -/* Variables de colores personalizadas */ -:root { - --color-crema: #f5f5dc; - --color-marron: #8b4513; - --color-gris-oscuro: #2c3e50; - --color-cafe-claro: #d2b48c; - --color-cafe-con-leche: #ddbea9; - --color-blanco-calido: #fffef7; - --color-dorado: #ffd700; - --color-overlay: rgba(139, 69, 19, 0.8); -} - -/* Clases de colores de fondo */ -.bg-crema { background-color: var(--color-crema) !important; } -.bg-blanco-calido { background-color: var(--color-blanco-calido) !important; } - -/* Clases de colores de texto */ -.text-marron { color: var(--color-marron) !important; } -.text-gris-oscuro { color: var(--color-gris-oscuro) !important; } -.text-cafe-claro { color: var(--color-cafe-claro) !important; } -.text-cafe-con-leche { color: var(--color-cafe-con-leche) !important; } -.text-crema { color: var(--color-crema) !important; } - -/* Clases de borde */ -.border-marron { border-color: var(--color-marron) !important; } - -/* Estilos generales */ -body { - font-family: 'Quicksand', sans-serif; - line-height: 1.6; - overflow-x: hidden; -} - -/* Navbar personalizada */ -.navbar { - transition: all 0.3s ease; - backdrop-filter: blur(10px); -} - -.logo { - transition: transform 0.3s ease; -} - -.logo:hover { - transform: scale(1.05); -} - -/* Botón personalizado */ -.btn-primary { - background: linear-gradient(135deg, var(--color-marron), #a0522d); - border: none; - border-radius: 25px; - padding: 8px 20px; - transition: all 0.3s ease; - box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3); -} - -.btn-primary:hover { - background: linear-gradient(135deg, #a0522d, var(--color-marron)); - transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4); -} - -.btn-rounded { - border-radius: 25px; -} - -/* Carrusel de borde a borde */ -.carousel-fullwidth { - width: 100vw; - position: relative; - left: 50%; - right: 50%; - margin-left: -50vw; - margin-right: -50vw; -} - -.carousel-fixed-img { - height: 450px; - object-fit: cover; - object-position: center; - width: 100%; -} - -.carousel-item { - position: relative; - overflow: hidden; -} - -.carousel-link { - display: block; - position: relative; - text-decoration: none; - color: inherit; -} - -.carousel-link::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: linear-gradient(45deg, transparent, rgba(139, 69, 19, 0.1)); - opacity: 0; - transition: opacity 0.3s ease; - z-index: 1; -} - -.carousel-link:hover::before { - opacity: 1; -} - -.carousel-caption { - background: rgba(0, 0, 0, 0.6); - border-radius: 10px; - padding: 15px; - backdrop-filter: blur(10px); - bottom: 20px; -} - -.carousel-control-prev, -.carousel-control-next { - width: 50px; - height: 50px; - top: 50%; - transform: translateY(-50%); - background: rgba(139, 69, 19, 0.8); - border-radius: 50%; - transition: all 0.3s ease; -} - -.carousel-control-prev { - left: 15px; -} - -.carousel-control-next { - right: 15px; -} - -.carousel-control-prev:hover, -.carousel-control-next:hover { - background: rgba(139, 69, 19, 0.9); - transform: translateY(-50%) scale(1.1); -} - -/* Cards optimizadas */ -.card { - border: none; - transition: all 0.3s ease; - position: relative; - overflow: hidden; - cursor: pointer; - background: white; -} - -.card::before { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 100%; - height: 100%; - background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent); - transition: left 0.6s ease; - z-index: 2; -} - -.card:hover::before { - left: 100%; -} - -.card:hover { - transform: translateY(-10px); - box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2); -} - -.card-img-custom { - height: 250px; - object-fit: cover; - object-position: center; - transition: transform 0.3s ease; -} - -.card:hover .card-img-custom { - transform: scale(1.05); -} - -/* Overlay de información en cards */ -.card-overlay { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: var(--color-overlay); - color: white; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - opacity: 0; - transition: opacity 0.3s ease; - z-index: 3; - padding: 20px; - text-align: center; -} - -.card:hover .card-overlay { - opacity: 1; -} - -.card-overlay h5 { - margin-bottom: 15px; - font-weight: bold; - font-size: 1.4rem; -} - -.card-overlay p { - font-size: 0.95rem; - line-height: 1.4; -} - -/* Títulos con efecto */ -h2 { - position: relative; -} - -h2::after { - content: ''; - position: absolute; - bottom: -10px; - left: 50%; - transform: translateX(-50%); - width: 80px; - height: 3px; - background: linear-gradient(90deg, var(--color-marron), var(--color-dorado)); - border-radius: 2px; -} - -/* Navegación mejorada */ -.nav-link { - position: relative; - transition: color 0.3s ease; -} - -.nav-link::after { - content: ''; - position: absolute; - bottom: -5px; - left: 0; - width: 0; - height: 2px; - background: var(--color-marron); - transition: width 0.3s ease; -} - -.nav-link:hover::after { - width: 100%; -} - -/* Footer mejorado */ -footer { - background: linear-gradient(135deg, #2c3e50, #34495e) !important; - position: relative; - overflow: hidden; -} - -footer::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: url('data:image/svg+xml,'); - background-size: 50px 50px; - animation: float 20s infinite linear; -} - -/* Iconos sociales */ -.social-icon-hover { - transition: all 0.3s ease; - display: inline-block; -} - -.social-icon-hover:hover { - color: var(--color-dorado) !important; - transform: translateY(-3px); -} - -/* Sombras optimizadas */ -.shadow-sm { - box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important; -} - -.shadow { - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important; -} - -/* Animaciones */ -@keyframes float { - 0% { transform: translateY(0px); } - 100% { transform: translateY(-100px); } -} - -/* Clases de delay optimizadas */ -.animate__delay-1s { animation-delay: 0.2s; } -.animate__delay-2s { animation-delay: 0.4s; } -.animate__delay-3s { animation-delay: 0.6s; } -.animate__delay-4s { animation-delay: 0.8s; } -.animate__delay-5s { animation-delay: 1s; } - -/* Responsive optimizado */ -@media (max-width: 768px) { - .carousel-fixed-img { - height: 300px; - } - - .card-img-custom { - height: 200px; - } - - h2::after { - width: 60px; - } - - .carousel-control-prev, - .carousel-control-next { - width: 40px; - height: 40px; - } - - .carousel-caption { - padding: 10px; - bottom: 10px; - } - - .carousel-caption h5 { - font-size: 1rem; - margin-bottom: 5px; - } -} - -@media (max-width: 576px) { - .carousel-small-img { - height: 200px; - } - - .card-img-custom { - height: 180px; - } - - .carousel-control-prev, - .carousel-control-next { - width: 35px; - height: 35px; - } - - .carousel-control-prev { - left: 10px; - } - - .carousel-control-next { - right: 10px; - } -} diff --git a/files/styleslogin.css b/files/styleslogin.css deleted file mode 100644 index c58c60a..0000000 --- a/files/styleslogin.css +++ /dev/null @@ -1,218 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Lato:wght@400;700&display=swap'); -:root { - --primary-color: #8C5A37; /* Un marrón terracota, sofisticado y cálido */ - --primary-hover: #6E462A; /* Una versión más oscura para el hover */ - --text-dark: #3D2C21; /* Un marrón muy oscuro para texto principal */ - --text-light: #6B5B51; /* Un marrón más claro para texto secundario */ - --border-color: #D3C5BC; /* Un color suave para los bordes */ - --container-bg: rgba(255, 255, 255, 0.75); /* Fondo blanco semitransparente */ -} - -body { - background-image: url(../files/img/pan-rtzqhi1ok4k1bxlo.jpg); - background-repeat: no-repeat; - background-size: cover; - height: 100vh; - margin: 0; - display: flex; - justify-content: center; - align-items: center; - font-family: 'Lato', sans-serif; -} -.logo-img { - width: 80px; - height: 80px; - border-radius: 50%; - box-shadow: 0 8px 25px rgba(140, 90, 55, 0.4); - object-fit: cover; - border: 3px solid var(--primary-color); - animation: bounce 2s infinite; - transition: all 0.3s ease; -} - -.logo-img:hover { - transform: scale(1.05); - box-shadow: 0 12px 35px rgba(140, 90, 55, 0.5); -} - -.login-container { - background: var(--container-bg); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - padding: 40px; - border-radius: 50px; - box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); - border: 1px solid rgba(255, 255, 255, 0.4); - width: 100%; - max-width: 400px; - text-align: center; -} -.logo { - font-size: 48px; - margin-bottom: 10px; - color: var(--primary-color); -} - -/* Contenedor específico para el logo con imagen */ -.logo.animated-logo { - display: flex; - justify-content: center; - align-items: center; - margin: 0 auto 20px auto; - animation: bounce 2s infinite; - padding: 10px; - background: rgba(255, 255, 255, 0.2); - border-radius: 40%; - backdrop-filter: blur(5px); - width: 120px; - height: 120px; - box-shadow: 0 10px 30px rgba(140, 90, 55, 0.3); - font-size: initial; -} - -.logo.animated-logo img { - border: 3px solid var(--primary-color); - box-shadow: 0 4px 15px rgba(140, 90, 55, 0.3); - border-radius: 50%; -} - -h1 { - font-family: 'Playfair Display', serif; - color: var(--text-dark); - margin-bottom: 30px; - font-size: 28px; -} - -.form-group { - margin-bottom: 20px; - text-align: left; -} - -label { - display: block; - margin-bottom: 8px; - color: var(--text-light); - font-weight: bold; -} - -input[type="text"], input[type="password"], input[type="email"], select { - width: 100%; - padding: 12px; - border: 2px solid var(--border-color); - background-color: rgba(255, 255, 255, 0.5); - border-radius: 8px; - font-size: 16px; - color: var(--text-dark); - transition: all 0.3s ease; - box-sizing: border-box; -} - -input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus, select:focus { - outline: none; - border-color: var(--primary-color); - box-shadow: 0 0 10px rgba(140, 90, 55, 0.2); -} - -.btn { - width: 100%; - padding: 12px; - background-color: var(--primary-color); - color: white; - border: none; - border-radius: 8px; - font-size: 16px; - font-weight: bold; - cursor: pointer; - transition: all 0.2s ease; -} - -.btn:hover { - background-color: var(--primary-hover); - transform: translateY(-3px); - box-shadow: 0 6px 20px rgba(140, 90, 55, 0.3); -} - -.btn:active { - transform: translateY(0); - box-shadow: 0 3px 10px rgba(140, 90, 55, 0.3); -} - -.footer-links { - margin-top: 20px; - padding-top: 20px; - border-top: 1px solid var(--border-color); -} - -/* Estilo para enlace de registro - más notorio */ -.signup-link { - text-align: left; - margin-top: 25px; - padding: 15px 20px; - background: rgba(140, 90, 55, 0.2) !important; - border-radius: 10px; - border-left: 4px solid var(--primary-color); - backdrop-filter: blur(5px); - box-shadow: 0 4px 15px rgba(140, 90, 55, 0.15); - transition: all 0.3s ease; -} - -.signup-link:hover { - background: rgba(140, 90, 55, 0.3) !important; - transform: translateX(5px); - box-shadow: 0 6px 20px rgba(140, 90, 55, 0.2); -} - -.signup-link a { - color: var(--primary-color) !important; - font-size: 15px; - font-weight: bold; - text-decoration: none; - display: block; -} - -.signup-link a:hover { - text-decoration: underline; - color: var(--text-dark); -} - -.footer-links a { - color: var(--primary-color); - text-decoration: none; - font-size: 14px; - font-weight: bold; -} - -.footer-links a:hover { - text-decoration: underline; - color: var(--text-dark); -} - -.loading-spinner { - border: 3px solid rgba(140, 90, 55, 0.2); - border-top-color: var(--primary-color); - border-radius: 50%; - width: 30px; - height: 30px; - animation: spin 1s linear infinite; - margin: 0 auto; -} - -@keyframes spin { - 0% { transform: rotate(0deg); } - 100% { transform: rotate(360deg); } -} - -@keyframes bounce { -0%, 100% { - transform: translateY(0); -} - 50% { - transform: translateY(-10px); - } -} -.success-message{ - font-family: 'Exo 2', sans-serif; - color: var(--text-dark); - margin-bottom: 30px; - font-size: 16px; -} \ No newline at end of file diff --git a/files/test_database.php b/files/test_database.php deleted file mode 100644 index d0832fb..0000000 --- a/files/test_database.php +++ /dev/null @@ -1,84 +0,0 @@ -query("SHOW TABLES LIKE 'Pedidos'"); - $tests['pedidos_table_exists'] = $result && $result->num_rows > 0; - - // Test 2: Check if Estado_Pedidos table exists - $result = $conexion->query("SHOW TABLES LIKE 'Estado_Pedidos'"); - $tests['estado_pedidos_table_exists'] = $result && $result->num_rows > 0; - - // Test 3: Check if Productos table exists - $result = $conexion->query("SHOW TABLES LIKE 'Productos'"); - $tests['productos_table_exists'] = $result && $result->num_rows > 0; - - // Test 4: Check if Usuario table exists - $result = $conexion->query("SHOW TABLES LIKE 'Usuario'"); - $tests['usuario_table_exists'] = $result && $result->num_rows > 0; - - // Test 5: Check Pedidos structure - if ($tests['pedidos_table_exists']) { - $result = $conexion->query("DESCRIBE Pedidos"); - $pedidos_columns = []; - while ($row = $result->fetch_assoc()) { - $pedidos_columns[] = $row['Field']; - } - $tests['pedidos_columns'] = $pedidos_columns; - } - - // Test 6: Check Productos structure - if ($tests['productos_table_exists']) { - $result = $conexion->query("DESCRIBE Productos"); - $productos_columns = []; - while ($row = $result->fetch_assoc()) { - $productos_columns[] = $row['Field']; - } - $tests['productos_columns'] = $productos_columns; - } - - // Test 7: Count records - if ($tests['pedidos_table_exists']) { - $result = $conexion->query("SELECT COUNT(*) as count FROM Pedidos"); - $row = $result->fetch_assoc(); - $tests['pedidos_count'] = $row['count']; - } - - if ($tests['productos_table_exists']) { - $result = $conexion->query("SELECT COUNT(*) as count FROM Productos"); - $row = $result->fetch_assoc(); - $tests['productos_count'] = $row['count']; - } - - echo json_encode([ - 'success' => true, - 'tests' => $tests, - 'session_info' => [ - 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'not_set', - 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'not_set', - 'usuario_id' => $_SESSION['usuario_id'] ?? 'not_set' - ] - ]); - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'error' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine() - ]); -} -?> diff --git a/files/test_detalle_pedido.php b/files/test_detalle_pedido.php deleted file mode 100644 index 96a299f..0000000 --- a/files/test_detalle_pedido.php +++ /dev/null @@ -1,112 +0,0 @@ -Test Detalle de Pedido"; - -try { - // Verificar conexión - if (!$conexion) { - throw new Exception("No se pudo conectar a la base de datos"); - } - - echo "

✅ Conexión a BD exitosa

"; - - // Verificar estructura de tablas - echo "

📋 Estructura de tablas:

"; - - // Verificar tabla Detalle_Pedidos - $result = $conexion->query("DESCRIBE Detalle_Pedidos"); - if ($result) { - echo "Tabla Detalle_Pedidos:
"; - while ($row = $result->fetch_assoc()) { - echo "- {$row['Field']} ({$row['Type']})
"; - } - } - - echo "
"; - - // Verificar tabla Productos - $result = $conexion->query("DESCRIBE Productos"); - if ($result) { - echo "Tabla Productos:
"; - while ($row = $result->fetch_assoc()) { - echo "- {$row['Field']} ({$row['Type']})
"; - } - } - - echo "
"; - - // Buscar un pedido existente - $pedidos = $conexion->query("SELECT ID_PEDIDO FROM Pedidos LIMIT 5"); - if ($pedidos && $pedidos->num_rows > 0) { - echo "

🔍 Pedidos disponibles:

"; - while ($pedido = $pedidos->fetch_assoc()) { - echo "- Pedido ID: {$pedido['ID_PEDIDO']}
"; - } - - // Tomar el primer pedido para test - $pedidos->data_seek(0); - $primer_pedido = $pedidos->fetch_assoc(); - $test_pedido_id = $primer_pedido['ID_PEDIDO']; - - echo "

🧪 Probando detalle del pedido #{$test_pedido_id}:

"; - - // Simular la llamada AJAX - $_POST['pedido_id'] = $test_pedido_id; - $input_data = json_encode(['pedido_id' => $test_pedido_id]); - - // Incluir el archivo AJAX directamente - ob_start(); - - // Simulamos la entrada JSON - file_put_contents('php://temp', $input_data); - - // Llamamos al endpoint - include 'obtener_detalle_pedido_ajax.php'; - - $output = ob_get_clean(); - - echo "Respuesta del endpoint:
"; - echo "
" . htmlspecialchars($output) . "
"; - - // Intentar parsear como JSON - $data = json_decode($output, true); - if ($data) { - echo "Datos parseados:
"; - echo "- Success: " . ($data['success'] ? 'true' : 'false') . "
"; - if ($data['success']) { - echo "- Pedido ID: " . $data['pedido']['id'] . "
"; - echo "- Cliente: " . $data['pedido']['cliente'] . "
"; - echo "- Total: $" . number_format($data['pedido']['total']) . "
"; - echo "- Productos: " . count($data['productos']) . "
"; - - if (!empty($data['productos'])) { - echo "
Productos del pedido:
"; - foreach ($data['productos'] as $producto) { - echo " - {$producto['nombre']} (Cantidad: {$producto['cantidad']}, Precio: $" . number_format($producto['precio_unitario']) . ")
"; - } - } - } else { - echo "- Error: " . ($data['mensaje'] ?? 'No especificado') . "
"; - } - } - - } else { - echo "

❌ No se encontraron pedidos en la base de datos

"; - } - -} catch (Exception $e) { - echo "

❌ Error: " . htmlspecialchars($e->getMessage()) . "

"; -} - -echo "

"; -echo "← Volver al Dashboard"; -?> diff --git a/files/test_detalle_pedido_correccion.php b/files/test_detalle_pedido_correccion.php deleted file mode 100644 index cdcffe8..0000000 --- a/files/test_detalle_pedido_correccion.php +++ /dev/null @@ -1,134 +0,0 @@ -🔧 Test de Corrección - Detalle de Pedidos"; -echo "

Verificando que las consultas funcionen correctamente después de las correcciones.

"; - -try { - // Verificar la estructura de la tabla Detalle_Pedidos - echo "

📋 Estructura de Detalle_Pedidos:

"; - $result = $conexion->query("SHOW COLUMNS FROM Detalle_Pedidos"); - if ($result) { - echo "
    "; - while ($row = $result->fetch_assoc()) { - echo "
  • {$row['Field']} - {$row['Type']}
  • "; - } - echo "
"; - } - - // Probar la consulta corregida para el dashboard de empleado - echo "

🔍 Test Query Dashboard Empleado (AJAX):

"; - $pedido_id = 1; // Usar el primer pedido como prueba - - // Verificar si la columna DESCRIPCION_PRODUCTO existe - $check_descripcion = $conexion->query("SHOW COLUMNS FROM Productos LIKE 'DESCRIPCION_PRODUCTO'"); - $has_descripcion = $check_descripcion && $check_descripcion->num_rows > 0; - - $descripcion_field = $has_descripcion ? - "COALESCE(prod.DESCRIPCION_PRODUCTO, prod.TIPO_PRODUCTO_MARCA, '') as producto_descripcion" : - "COALESCE(prod.TIPO_PRODUCTO_MARCA, '') as producto_descripcion"; - - $stmt = $conexion->prepare(" - SELECT - dp.ID_DETALLE, - dp.CANTIDAD_PRODUCTO, - dp.PRECIO_UNITARIO, - dp.SUBTOTAL, - COALESCE(prod.NOMBRE_PRODUCTO, 'Producto eliminado') as producto_nombre, - $descripcion_field, - COALESCE(cat.NOMBRE_CATEGORIAPRODUCTO, 'Sin categoría') as categoria_nombre, - prod.ID_PRODUCTO as producto_id - FROM Detalle_Pedidos dp - LEFT JOIN Productos prod ON dp.ID_PRODUCTO = prod.ID_PRODUCTO - LEFT JOIN Categoria_Productos cat ON prod.ID_CATEGORIA_PRODUCTO = cat.ID_CATEGORIA_PRODUCTO - WHERE dp.ID_PEDIDO = ? - ORDER BY dp.ID_DETALLE - "); - - if ($stmt) { - $stmt->bind_param("i", $pedido_id); - $stmt->execute(); - $result = $stmt->get_result(); - - echo "

✅ Query ejecutada exitosamente para pedido #$pedido_id

"; - echo ""; - echo ""; - - while ($row = $result->fetch_assoc()) { - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - } - echo "
ID_DETALLEPRODUCTO_IDNOMBRECANTIDADPRECIOSUBTOTAL
{$row['ID_DETALLE']}#{$row['producto_id']}{$row['producto_nombre']}{$row['CANTIDAD_PRODUCTO']}\${$row['PRECIO_UNITARIO']}\${$row['SUBTOTAL']}
"; - } else { - echo "

❌ Error preparando query: " . $conexion->error . "

"; - } - - // Probar la consulta corregida para el dashboard de admin - echo "

🔍 Test Query Dashboard Admin:

"; - $query_detalles = "SELECT dp.*, pr.ID_PRODUCTO as producto_id, pr.NOMBRE_PRODUCTO as producto_nombre, - COALESCE(pr.DESCRIPCION_PRODUCTO, pr.TIPO_PRODUCTO_MARCA, '') as producto_descripcion, - cp.NOMBRE_CATEGORIAPRODUCTO as categoria_nombre - FROM Detalle_Pedidos dp - JOIN Productos pr ON dp.ID_PRODUCTO = pr.ID_PRODUCTO - LEFT JOIN Categoria_Productos cp ON pr.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO - WHERE dp.ID_PEDIDO = ? - ORDER BY dp.ID_DETALLE"; - - $stmt_admin = $conexion->prepare($query_detalles); - if ($stmt_admin) { - $stmt_admin->bind_param("i", $pedido_id); - $stmt_admin->execute(); - $result_admin = $stmt_admin->get_result(); - - echo "

✅ Query de admin ejecutada exitosamente para pedido #$pedido_id

"; - echo ""; - echo ""; - - while ($row = $result_admin->fetch_assoc()) { - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - echo ""; - } - echo "
ID_DETALLEPRODUCTO_IDNOMBREDESCRIPCIÓNCATEGORÍACANTIDAD
{$row['ID_DETALLE']}#{$row['producto_id']}{$row['producto_nombre']}" . substr($row['producto_descripcion'], 0, 50) . "...{$row['categoria_nombre']}{$row['CANTIDAD_PRODUCTO']}
"; - } else { - echo "

❌ Error preparando query de admin: " . $conexion->error . "

"; - } - - echo "

🎯 Resumen de Correcciones:

"; - echo "
    "; - echo "
  • ✅ Corregido error 'dp.ID_DETALLE_PEDIDO' → 'dp.ID_DETALLE'
  • "; - echo "
  • ✅ Agregada columna de ID de producto en ambos dashboards
  • "; - echo "
  • ✅ Eliminada columna de imagen en dashboard admin
  • "; - echo "
  • ✅ Agregado soporte para descripción de productos
  • "; - echo "
  • ✅ Agregada columna de categoría
  • "; - echo "
  • ✅ Estructura consistente entre empleado y admin
  • "; - echo "
"; - -} catch (Exception $e) { - echo "

❌ Error en el test: " . $e->getMessage() . "

"; -} -?> - - diff --git a/files/test_endpoints.php b/files/test_endpoints.php deleted file mode 100644 index c5af2b3..0000000 --- a/files/test_endpoints.php +++ /dev/null @@ -1,69 +0,0 @@ -Prueba de Endpoints de Ingredientes\n"; -echo "

1. Prueba de Categorías de Ingredientes:

\n"; - -// Probar endpoint de categorías -$url_categorias = 'http://localhost/proyectopanaderia/files/obtener_categorias_ingredientes_ajax.php'; -$context = stream_context_create([ - 'http' => [ - 'method' => 'GET', - 'header' => [ - 'Content-Type: application/json', - 'X-Requested-With: XMLHttpRequest', - 'Cookie: ' . session_name() . '=' . session_id() - ] - ] -]); - -$response_categorias = file_get_contents($url_categorias, false, $context); -echo "
" . htmlspecialchars($response_categorias) . "
\n"; - -echo "

2. Prueba de Proveedores:

\n"; - -// Probar endpoint de proveedores -$url_proveedores = 'http://localhost/proyectopanaderia/files/obtener_proveedores_ajax.php'; -$response_proveedores = file_get_contents($url_proveedores, false, $context); -echo "
" . htmlspecialchars($response_proveedores) . "
\n"; - -// Verificar datos en base de datos directamente -echo "

3. Verificación directa en Base de Datos:

\n"; - -require_once 'conexion.php'; - -echo "

Categorías en BD:

\n"; -$consulta_cat = "SELECT * FROM Categoria_Ingredientes ORDER BY NOMBRE_CATEGORIA_INGREDIENTE"; -$resultado_cat = $conexion->query($consulta_cat); -if ($resultado_cat) { - echo "
    \n"; - while ($fila = $resultado_cat->fetch_assoc()) { - echo "
  • ID: {$fila['ID_CATEGORIA']} - {$fila['NOMBRE_CATEGORIA_INGREDIENTE']}
  • \n"; - } - echo "
\n"; -} else { - echo "Error: " . $conexion->error . "\n"; -} - -echo "

Proveedores en BD:

\n"; -$consulta_prov = "SELECT * FROM Proveedores ORDER BY NOMBRE_PROV"; -$resultado_prov = $conexion->query($consulta_prov); -if ($resultado_prov) { - echo "
    \n"; - while ($fila = $resultado_prov->fetch_assoc()) { - $activo = $fila['ACTIVO_PROV'] ? 'Activo' : 'Inactivo'; - echo "
  • ID: {$fila['ID_PROVEEDOR']} - {$fila['NOMBRE_PROV']} ({$activo})
  • \n"; - } - echo "
\n"; -} else { - echo "Error: " . $conexion->error . "\n"; -} - -$conexion->close(); -?> diff --git a/files/test_ingredientes_funcionalidad.php b/files/test_ingredientes_funcionalidad.php deleted file mode 100644 index e69de29..0000000 diff --git a/files/test_pedidos_simple.php b/files/test_pedidos_simple.php deleted file mode 100644 index dccc60b..0000000 --- a/files/test_pedidos_simple.php +++ /dev/null @@ -1,63 +0,0 @@ -query($query); - - if ($result) { - $count = $result->fetch_assoc()['count']; - - // Get a few sample records - $sample_query = " - SELECT - ID_PEDIDO as id, - FECHA_INGRESO as fecha_ingreso, - FECHA_ENTREGA as fecha_entrega, - TOTAL_PRODUCTO as total, - ID_ESTADO_PEDIDO as estado - FROM Pedidos - ORDER BY ID_PEDIDO DESC - LIMIT 5 - "; - - $sample_result = $conexion->query($sample_query); - $samples = []; - - if ($sample_result) { - while ($row = $sample_result->fetch_assoc()) { - $samples[] = [ - 'id' => (int)$row['id'], - 'cliente' => 'Cliente Test', - 'empleado' => 'Empleado Test', - 'fecha_ingreso' => $row['fecha_ingreso'], - 'fecha_entrega' => $row['fecha_entrega'], - 'total' => (float)$row['total'], - 'estado' => (int)$row['estado'], - 'estado_nombre' => 'Estado ' . $row['estado'] - ]; - } - } - - echo json_encode([ - 'success' => true, - 'total_pedidos' => $count, - 'pedidos' => $samples, - 'total' => count($samples) - ]); - } else { - throw new Exception("Error en consulta: " . $conexion->error); - } - -} catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage() - ]); -} -?> diff --git a/files/toggle_estado_cliente.php b/files/toggle_estado_cliente.php deleted file mode 100644 index 554c83d..0000000 --- a/files/toggle_estado_cliente.php +++ /dev/null @@ -1,119 +0,0 @@ - false, 'mensaje' => 'Acceso no autorizado']); - exit(); -} - -// Headers de respuesta JSON -header('Content-Type: application/json'); - -// Verificar método POST -if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']); - exit(); -} - -try { - // Conexión PDO - $dsn = "mysql:host=localhost;dbname=proyectopanaderia;charset=utf8"; - $username = "root"; - $password = ""; - - $pdo_conexion = new PDO($dsn, $username, $password); - $pdo_conexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - // Obtener datos JSON del cuerpo de la petición - $raw_input = file_get_contents('php://input'); - error_log("Raw input recibido para cliente: " . $raw_input); - - $input = json_decode($raw_input, true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new Exception('Error al decodificar JSON: ' . json_last_error_msg()); - } - - if (!$input) { - throw new Exception('Datos JSON inválidos o vacíos'); - } - - // Debug: Log de los datos recibidos - error_log("Datos decodificados para cliente: " . print_r($input, true)); - - // Validar que se recibieron los campos necesarios - if (!isset($input['id'])) { - throw new Exception('Campo "id" faltante en los datos JSON'); - } - - if (!isset($input['estado'])) { - throw new Exception('Campo "estado" faltante en los datos JSON'); - } - - // Convertir y validar los datos - $cliente_id = filter_var($input['id'], FILTER_VALIDATE_INT); - $nuevo_estado = filter_var($input['estado'], FILTER_VALIDATE_INT); - - // Validaciones estrictas - if ($cliente_id === false || $cliente_id <= 0) { - throw new Exception('ID de cliente inválido: ' . json_encode($input['id'])); - } - - if ($nuevo_estado === false || !in_array($nuevo_estado, [0, 1], true)) { - throw new Exception('Estado inválido: ' . json_encode($input['estado'])); - } - - error_log("Validaciones pasadas para cliente - ID: $cliente_id, Estado: $nuevo_estado"); - - // Verificar que el cliente existe - $consulta_verificar = "SELECT ID_CLIENTE, NOMBRE_CLI, ACTIVO_CLI FROM Clientes WHERE ID_CLIENTE = :cliente_id"; - $stmt_verificar = $pdo_conexion->prepare($consulta_verificar); - $stmt_verificar->bindParam(':cliente_id', $cliente_id, PDO::PARAM_INT); - $stmt_verificar->execute(); - - $cliente = $stmt_verificar->fetch(PDO::FETCH_ASSOC); - - if (!$cliente) { - throw new Exception("Cliente con ID $cliente_id no encontrado en la base de datos"); - } - - error_log("Cliente encontrado: " . print_r($cliente, true)); - - // Actualizar el estado del cliente - $consulta_actualizar = "UPDATE Clientes SET ACTIVO_CLI = :nuevo_estado WHERE ID_CLIENTE = :cliente_id"; - $stmt_actualizar = $pdo_conexion->prepare($consulta_actualizar); - $stmt_actualizar->bindParam(':nuevo_estado', $nuevo_estado, PDO::PARAM_INT); - $stmt_actualizar->bindParam(':cliente_id', $cliente_id, PDO::PARAM_INT); - - $update_result = $stmt_actualizar->execute(); - $affected_rows = $stmt_actualizar->rowCount(); - - error_log("Resultado de la actualización de cliente - Éxito: " . ($update_result ? 'Sí' : 'No') . ", Filas afectadas: $affected_rows"); - - if ($update_result && $affected_rows > 0) { - $estado_texto = $nuevo_estado ? 'activo' : 'inactivo'; - $accion_texto = $nuevo_estado ? 'activado' : 'desactivado'; - - echo json_encode([ - 'success' => true, - 'mensaje' => "Cliente {$accion_texto} exitosamente", - 'cliente' => [ - 'id' => $cliente_id, - 'nombre' => $cliente['NOMBRE_CLI'], - 'estado' => $nuevo_estado, - 'estado_texto' => $estado_texto - ] - ]); - } else { - throw new Exception('Error al actualizar el estado del cliente. Filas afectadas: ' . $affected_rows); - } - -} catch (Exception $e) { - error_log("Error en toggle_estado_cliente.php: " . $e->getMessage()); - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage() - ]); -} -?> diff --git a/files/toggle_estado_empleado.php b/files/toggle_estado_empleado.php deleted file mode 100644 index 707c12e..0000000 --- a/files/toggle_estado_empleado.php +++ /dev/null @@ -1,119 +0,0 @@ - false, 'mensaje' => 'Acceso no autorizado']); - exit(); -} - -// Headers de respuesta JSON -header('Content-Type: application/json'); - -// Verificar método POST -if ($_SERVER['REQUEST_METHOD'] !== 'POST') { - echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']); - exit(); -} - -try { - // Conexión PDO - $dsn = "mysql:host=localhost;dbname=proyectopanaderia;charset=utf8"; - $username = "root"; - $password = ""; - - $pdo_conexion = new PDO($dsn, $username, $password); - $pdo_conexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - // Obtener datos JSON del cuerpo de la petición - $raw_input = file_get_contents('php://input'); - error_log("Raw input recibido: " . $raw_input); - - $input = json_decode($raw_input, true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new Exception('Error al decodificar JSON: ' . json_last_error_msg()); - } - - if (!$input) { - throw new Exception('Datos JSON inválidos o vacíos'); - } - - // Debug: Log de los datos recibidos - error_log("Datos decodificados: " . print_r($input, true)); - - // Validar que se recibieron los campos necesarios - if (!isset($input['id'])) { - throw new Exception('Campo "id" faltante en los datos JSON'); - } - - if (!isset($input['estado'])) { - throw new Exception('Campo "estado" faltante en los datos JSON'); - } - - // Convertir y validar los datos - $empleado_id = filter_var($input['id'], FILTER_VALIDATE_INT); - $nuevo_estado = filter_var($input['estado'], FILTER_VALIDATE_INT); - - // Validaciones estrictas - if ($empleado_id === false || $empleado_id <= 0) { - throw new Exception('ID de empleado inválido: ' . json_encode($input['id'])); - } - - if ($nuevo_estado === false || !in_array($nuevo_estado, [0, 1], true)) { - throw new Exception('Estado inválido: ' . json_encode($input['estado'])); - } - - error_log("Validaciones pasadas - ID: $empleado_id, Estado: $nuevo_estado"); - - // Verificar que el empleado existe - $consulta_verificar = "SELECT ID_EMPLEADO, NOMBRE_EMPLEADO, ACTIVO_EMPLEADO FROM Empleados WHERE ID_EMPLEADO = :empleado_id"; - $stmt_verificar = $pdo_conexion->prepare($consulta_verificar); - $stmt_verificar->bindParam(':empleado_id', $empleado_id, PDO::PARAM_INT); - $stmt_verificar->execute(); - - $empleado = $stmt_verificar->fetch(PDO::FETCH_ASSOC); - - if (!$empleado) { - throw new Exception("Empleado con ID $empleado_id no encontrado en la base de datos"); - } - - error_log("Empleado encontrado: " . print_r($empleado, true)); - - // Actualizar el estado del empleado - $consulta_actualizar = "UPDATE Empleados SET ACTIVO_EMPLEADO = :nuevo_estado WHERE ID_EMPLEADO = :empleado_id"; - $stmt_actualizar = $pdo_conexion->prepare($consulta_actualizar); - $stmt_actualizar->bindParam(':nuevo_estado', $nuevo_estado, PDO::PARAM_INT); - $stmt_actualizar->bindParam(':empleado_id', $empleado_id, PDO::PARAM_INT); - - $update_result = $stmt_actualizar->execute(); - $affected_rows = $stmt_actualizar->rowCount(); - - error_log("Resultado de la actualización - Éxito: " . ($update_result ? 'Sí' : 'No') . ", Filas afectadas: $affected_rows"); - - if ($update_result && $affected_rows > 0) { - $estado_texto = $nuevo_estado ? 'activo' : 'inactivo'; - $accion_texto = $nuevo_estado ? 'activado' : 'desactivado'; - - echo json_encode([ - 'success' => true, - 'mensaje' => "Empleado {$accion_texto} exitosamente", - 'empleado' => [ - 'id' => $empleado_id, - 'nombre' => $empleado['NOMBRE_EMPLEADO'], - 'estado' => $nuevo_estado, - 'estado_texto' => $estado_texto - ] - ]); - } else { - throw new Exception('Error al actualizar el estado del empleado. Filas afectadas: ' . $affected_rows); - } - -} catch (Exception $e) { - error_log("Error en toggle_estado_empleado.php: " . $e->getMessage()); - echo json_encode([ - 'success' => false, - 'mensaje' => $e->getMessage() - ]); -} -?> diff --git a/files/toggle_producto.php b/files/toggle_producto.php deleted file mode 100644 index dc40146..0000000 --- a/files/toggle_producto.php +++ /dev/null @@ -1,267 +0,0 @@ -prepare($consulta_producto); - $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT); - $stmt_producto->execute(); - $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC); - - if ($producto) { - $nombre_producto = $producto['NOMBRE_PRODUCTO']; - - // Actualizar el estado del producto - $consulta_update = "UPDATE Productos SET ACTIVO = :nuevo_estado WHERE ID_PRODUCTO = :id"; - $stmt_update = $pdo_conexion->prepare($consulta_update); - $stmt_update->bindParam(':nuevo_estado', $nuevo_estado, PDO::PARAM_INT); - $stmt_update->bindParam(':id', $id_producto, PDO::PARAM_INT); - - if ($stmt_update->execute()) { - $mensaje = "El producto '{$nombre_producto}' ha sido {$accion_texto} exitosamente."; - $tipo_mensaje = "success"; - } else { - $mensaje = "Error: No se pudo cambiar el estado del producto."; - $tipo_mensaje = "error"; - } - } else { - $mensaje = "Error: El producto no existe."; - $tipo_mensaje = "error"; - } - - } catch (PDOException $e) { - $mensaje = "Error en la base de datos: " . $e->getMessage(); - $tipo_mensaje = "error"; - } -} else { - $mensaje = "Error: Parámetros no válidos."; - $tipo_mensaje = "error"; -} -?> - - - - - - - Cambiar Estado - Panadería - - - -
- -
-

Estado Cambiado

- -
-

Error al Cambiar Estado

- - -
- -
- - -
-

Información del Cambio:

-

Producto:

-

Nuevo Estado: - - ✓ Activo - - ✗ Inactivo - -

-

Fecha del Cambio:

-
- -
-

💡 Información Importante:

-
    - -
  • El producto está ahora INACTIVO y no aparecerá en búsquedas normales
  • -
  • Los pedidos existentes que contienen este producto NO se ven afectados
  • -
  • Puedes reactivarlo en cualquier momento
  • - -
  • El producto está ahora ACTIVO y disponible para nuevos pedidos
  • -
  • Aparecerá en todas las búsquedas y listados normales
  • -
  • Los clientes pueden volver a pedirlo
  • - -
-
- - -
- -
- -
- ⏱️ Por favor, lee toda la información mostrada arriba antes de continuar. - El botón se activará en 5 segundos. -
-
- - - - diff --git a/files/toggle_producto_ajax.php b/files/toggle_producto_ajax.php deleted file mode 100644 index 72179c1..0000000 --- a/files/toggle_producto_ajax.php +++ /dev/null @@ -1,70 +0,0 @@ - false, - 'mensaje' => 'Método no permitido. Use POST.' - ]); - exit(); -} - -// Verificar si se recibió el ID del producto y el estado actual -if (isset($_POST['id']) && !empty($_POST['id']) && isset($_POST['estado'])) { - $id_producto = $_POST['id']; - $estado_actual = $_POST['estado']; - - // Determinar el nuevo estado (invertir el actual) - $nuevo_estado = ($estado_actual == 1) ? 0 : 1; - $accion_texto = ($nuevo_estado == 1) ? "activado" : "desactivado"; - - try { - // Obtener información del producto antes del cambio - $consulta_producto = "SELECT NOMBRE_PRODUCTO, ACTIVO FROM Productos WHERE ID_PRODUCTO = ?"; - $stmt_producto = $conexion->prepare($consulta_producto); - $stmt_producto->bind_param("i", $id_producto); - $stmt_producto->execute(); - $resultado = $stmt_producto->get_result(); - $producto = $resultado->fetch_assoc(); - - if ($producto) { - $nombre_producto = $producto['NOMBRE_PRODUCTO']; - - // Actualizar el estado del producto - $consulta_update = "UPDATE Productos SET ACTIVO = ? WHERE ID_PRODUCTO = ?"; - $stmt_update = $conexion->prepare($consulta_update); - $stmt_update->bind_param("ii", $nuevo_estado, $id_producto); - - if ($stmt_update->execute()) { - echo json_encode([ - 'success' => true, - 'mensaje' => "El producto '{$nombre_producto}' ha sido {$accion_texto} exitosamente." - ]); - } else { - echo json_encode([ - 'success' => false, - 'mensaje' => "Error: No se pudo cambiar el estado del producto." - ]); - } - } else { - echo json_encode([ - 'success' => false, - 'mensaje' => "Error: El producto no existe." - ]); - } - - } catch (Exception $e) { - echo json_encode([ - 'success' => false, - 'mensaje' => "Error en la base de datos: " . $e->getMessage() - ]); - } -} else { - echo json_encode([ - 'success' => false, - 'mensaje' => "Error: Parámetros no válidos." - ]); -} -?> diff --git a/files/update_productos_table.sql b/files/update_productos_table.sql deleted file mode 100644 index e69de29..0000000 diff --git a/files/verificacion_sistema_precios.php b/files/verificacion_sistema_precios.php deleted file mode 100644 index e69de29..0000000 diff --git a/files/verificar_actualizacion.php b/files/verificar_actualizacion.php deleted file mode 100644 index 1592697..0000000 --- a/files/verificar_actualizacion.php +++ /dev/null @@ -1,157 +0,0 @@ -🔧 Verificador y Actualizador de Base de Datos - Panadería"; -echo "
"; - -try { - echo "

📋 Verificando estado actual de la base de datos...

"; - - // 1. Verificar si la tabla productos_logs existe - echo "

1. Verificando tabla productos_logs: "; - $check_table = $conexion->query("SHOW TABLES LIKE 'productos_logs'"); - - if ($check_table->num_rows == 0) { - echo "❌ No existe

"; - - echo "

🔨 Creando tabla productos_logs...

"; - $sql_tabla = " - CREATE TABLE productos_logs ( - id INT PRIMARY KEY AUTO_INCREMENT, - producto_id INT NOT NULL, - tipo_cambio ENUM('precio', 'stock', 'activacion', 'desactivacion') NOT NULL, - valor_anterior VARCHAR(50), - valor_nuevo VARCHAR(50), - usuario_id INT, - usuario_tipo ENUM('admin', 'empleado') DEFAULT 'admin', - fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - ip_usuario VARCHAR(45), - INDEX idx_producto_logs_fecha (fecha_cambio), - INDEX idx_producto_logs_producto (producto_id), - INDEX idx_producto_logs_tipo (tipo_cambio), - CONSTRAINT FK_PRODUCTO_LOG - FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE - )"; - - if ($conexion->query($sql_tabla)) { - echo "

✅ Tabla productos_logs creada exitosamente

"; - } else { - echo "

❌ Error al crear tabla: " . $conexion->error . "

"; - } - } else { - echo "✅ Existe

"; - } - - // 2. Verificar tipo de dato de PRECIO_PRODUCTO - echo "

2. Verificando tipo de dato PRECIO_PRODUCTO: "; - $check_column = $conexion->query("SELECT DATA_TYPE, COLUMN_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'ProyectoPanaderia' AND TABLE_NAME = 'Productos' AND COLUMN_NAME = 'PRECIO_PRODUCTO'"); - - if ($check_column && $row = $check_column->fetch_assoc()) { - if (strpos($row['DATA_TYPE'], 'decimal') !== false) { - echo "✅ DECIMAL(10,2)

"; - } else { - echo "⚠️ " . $row['COLUMN_TYPE'] . " (necesita actualización)

"; - - echo "

🔨 Actualizando tipo de dato a DECIMAL(10,2)...

"; - if ($conexion->query("ALTER TABLE Productos MODIFY COLUMN PRECIO_PRODUCTO DECIMAL(10,2) NOT NULL")) { - echo "

✅ Tipo de dato actualizado exitosamente

"; - } else { - echo "

❌ Error al actualizar: " . $conexion->error . "

"; - } - } - } else { - echo "❌ No se pudo verificar

"; - } - - // 3. Verificar trigger - echo "

3. Verificando trigger tr_actualizar_fecha_producto: "; - $check_trigger = $conexion->query("SELECT TRIGGER_NAME FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'ProyectoPanaderia' AND TRIGGER_NAME = 'tr_actualizar_fecha_producto'"); - - if ($check_trigger->num_rows == 0) { - echo "❌ No existe

"; - - echo "

🔨 Creando trigger...

"; - $sql_trigger = " - CREATE TRIGGER tr_actualizar_fecha_producto - BEFORE UPDATE ON Productos - FOR EACH ROW - BEGIN - SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP; - END"; - - if ($conexion->query($sql_trigger)) { - echo "

✅ Trigger creado exitosamente

"; - } else { - echo "

❌ Error al crear trigger: " . $conexion->error . "

"; - } - } else { - echo "✅ Existe

"; - } - - // 4. Verificar índices de productos_logs - if ($check_table->num_rows > 0) { - echo "

4. Verificando índices de productos_logs:

"; - $indices = $conexion->query("SHOW INDEX FROM productos_logs"); - $indices_encontrados = []; - - while ($indice = $indices->fetch_assoc()) { - $indices_encontrados[] = $indice['Key_name']; - } - - $indices_requeridos = ['PRIMARY', 'idx_producto_logs_fecha', 'idx_producto_logs_producto', 'idx_producto_logs_tipo', 'FK_PRODUCTO_LOG']; - - foreach ($indices_requeridos as $req) { - if (in_array($req, $indices_encontrados)) { - echo "

✅ Índice $req: Existe

"; - } else { - echo "

⚠️ Índice $req: No encontrado

"; - } - } - } - - // 5. Estadísticas generales - echo "

📊 Estadísticas actuales:

"; - - $productos_count = $conexion->query("SELECT COUNT(*) as total FROM Productos")->fetch_assoc()['total']; - echo "

📦 Total de productos: $productos_count

"; - - if ($check_table->num_rows > 0) { - $logs_count = $conexion->query("SELECT COUNT(*) as total FROM productos_logs")->fetch_assoc()['total']; - echo "

📝 Total de logs: $logs_count

"; - - if ($logs_count > 0) { - $ultimo_cambio = $conexion->query("SELECT MAX(fecha_cambio) as ultimo FROM productos_logs")->fetch_assoc()['ultimo']; - echo "

🕒 Último cambio: $ultimo_cambio

"; - } - } - - echo "

✅ Verificación completada

"; - echo "

Estado del sistema: LISTO PARA USAR

"; - - echo "
"; - echo "

🚀 Próximos pasos:

"; - echo "
    "; - echo "
  1. La funcionalidad de edición inline ya está disponible en productostabla.php
  2. "; - echo "
  3. Los cambios se registrarán automáticamente en la tabla productos_logs
  4. "; - echo "
  5. El sistema SSE funcionará con las actualizaciones en tiempo real
  6. "; - echo "
"; - echo "
"; - -} catch (Exception $e) { - echo "

❌ Error: " . $e->getMessage() . "

"; -} - -echo "
"; -echo "📋 Ir a Productos"; -echo "🏠 Dashboard Admin"; -echo "
"; - -echo "
"; - -$conexion->close(); -?> diff --git a/php-api/api-client.php b/php-api/api-client.php new file mode 100644 index 0000000..4122f48 --- /dev/null +++ b/php-api/api-client.php @@ -0,0 +1,77 @@ + $usuario) { + echo "Cliente " . ($recorrido + 1) . ":\n"; + foreach ($usuario as $atributo => $valor) { + echo " $atributo $valor\n"; + } + echo "------------------------\n"; + } + echo "====================================================\n"; + echo "Total de clientes: " . count($usuarios_clientes) . "\n"; + echo "====================================================\n"; + } else if ($opcion == 2) { + echo "Vista de clientes omitida.\n"; + } + +} else if ($decision == 2) { + echo "Bienvenido Empleado $nombre_user\n"; + echo "¿Desea ver todos los datos de los administradores?\n"; + echo "1. Sí\n"; + echo "2. No\n"; + $opcion = readline(); + + if ($opcion == 1) { + foreach ($usuarios_admins as $recorrido => $admin) { + echo "Administrador " . ($recorrido + 1) . ":\n"; + echo " Nombre: " . ($admin['Nombre:'] ?? 'No disponible') . "\n"; + echo " Telefono: " . ($admin['Telefono:'] ?? 'No disponible') . "\n"; + echo "------------------------\n"; + } + echo "====================================================\n"; + echo "Total de administradores: " . count($usuarios_admins) . "\n"; + echo "====================================================\n"; + } else if ($opcion == 2) { + echo "Saliendo del sistema....\n"; + } + +} else if ($decision == 3) { + echo "Cerrando programa...\n"; + exit; +} else { + echo "Opción inválida.\n"; +} +?> diff --git a/php_api_user/actualizarEmpleado.php b/php_api_user/actualizarEmpleado.php new file mode 100644 index 0000000..5497e64 --- /dev/null +++ b/php_api_user/actualizarEmpleado.php @@ -0,0 +1,109 @@ + endopointActualizacion::empleado($id), + default => throw new InvalidArgumentException("Tipo desconocido: $tipo"), + }; + } + + public function actualizarEmpleado(string $tipo): array { + echo "\n==============================\n"; + echo "=== ACTUALIZAR EMPLEADO ===\n"; + echo "==============================\n"; + + echo "Ingrese el ID del empleado a actualizar: "; + $id_empleado = (int)readline(); + + $url = $this->getActualizacionEndpoint($tipo, $id_empleado); + + echo "\nEmpleado/a a actualizar es: $id_empleado\n"; + echo "\n¿Qué desea actualizar?\n"; + echo "1. Nombre\n"; + echo "2. Email\n"; + echo "4. Contraseña\n"; + echo "5. Todos los campos\n"; + echo "Seleccione una opción (1-5): "; + + $opcion = readline(); + $datos_nuevos = array(); + + switch ($opcion) { + case '1': + $nombre = readline("Ingrese el nuevo nombre: "); + $datos_nuevos["nombre"] = $nombre; + break; + + case '2': + $email = readline("Ingrese el nuevo email: "); + $datos_nuevos["email"] = $email; + break; + + case '3': + $contrasena = readline("Ingrese la nueva contraseña: "); + $datos_nuevos["contrasena"] = $contrasena; + break; + + case '4': + $nombre = readline("Ingrese el nombre: "); + $email = readline("Ingrese el email: "); + $telefono = readline("Ingrese el teléfono: "); + $contrasena = readline("Ingrese la contraseña: "); + + $datos_nuevos = array( + "nombre" => $nombre, + "email" => $email, + "contrasena" => $contrasena + ); + break; + default: + throw new InvalidArgumentException("Opción inválida seleccionada"); + } + + $data_json = json_encode($datos_nuevos); + + $proceso = curl_init($url); + curl_setopt($proceso, CURLOPT_CUSTOMREQUEST, "PATCH"); + curl_setopt($proceso, CURLOPT_POSTFIELDS, $data_json); + curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true); + curl_setopt($proceso, CURLOPT_HTTPHEADER, array( + "Content-Type: application/json", + "Content-Length: " . strlen($data_json) + )); + + $response = curl_exec($proceso); + $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE); + curl_close($proceso); + + return [ + 'http_code' => $http_code, + 'data' => json_decode($response, true) + ]; + } + + public function mostrarActualizacion(string $tipo): void { + echo "\n=== ACTUALIZACIÓN DE EMPLEADO ===\n"; + + $resultado = $this->actualizarEmpleado($tipo); + + echo "\n HTTP Code: " . $resultado['http_code'] . "\n"; + + if ($resultado['http_code'] == 200){ + echo "Empleado actualizado exitosamente.\n"; + } else { + echo "Error al actualizar el empleado.\n"; + } + + if ($resultado['data'] !== null && !empty($resultado['data'])) { + echo "Respuesta del servidor:\n"; + echo json_encode($resultado['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"; + } + echo "\n"; + } +} + +$actualizacion = new actualizarEmpleado(); +$actualizacion->mostrarActualizacion('empleado'); +?> diff --git a/php_api_user/config.php b/php_api_user/config.php new file mode 100644 index 0000000..a551f0e --- /dev/null +++ b/php_api_user/config.php @@ -0,0 +1,47 @@ + diff --git a/php_api_user/detalleClientes.php b/php_api_user/detalleClientes.php new file mode 100644 index 0000000..ce82fcc --- /dev/null +++ b/php_api_user/detalleClientes.php @@ -0,0 +1,47 @@ + endpointDetalles::API_DETALLE_CLIENTE, + default => throw new InvalidArgumentException("Tipo desconocido: $tipo"), + }; + } + + public function obtenerDatos(string $tipo): array { + $url = $this->getDetalleEndpoint($tipo); + + $proceso = curl_init(); + curl_setopt($proceso, CURLOPT_URL, $url); + curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true); + curl_setopt($proceso, CURLOPT_TIMEOUT, 30); + curl_setopt($proceso, CURLOPT_HTTPHEADER, [ + 'Accept: application/json', + 'Content-Type: application/json' + ]); + + $response = curl_exec($proceso); + $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE); + curl_close($proceso); + + $dato = json_decode($response, true); + + return ['http_code' => $http_code,'data' => $dato]; + } + public function mostrarDatos(string $tipo): void { + echo "\n=== DATOS DE CLIENTES ===\n"; + echo "Endpoint: " . $this->getDetalleEndpoint($tipo) . "\n"; + + $resultado = $this->obtenerDatos($tipo); + + echo "HTTP Code: " . $resultado['http_code'] . "\n"; + echo "Datos obtenidos:\n"; + echo json_encode($resultado['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"; + echo "\n"; + echo "El conteo total de clientes es: " . count($resultado['data']) . "\n"; + } +} +$detalles = new DetallesUsusarios(); +$detalles->mostrarDatos('cliente'); +?> \ No newline at end of file diff --git a/php_api_user/detalleEmpleados.php b/php_api_user/detalleEmpleados.php new file mode 100644 index 0000000..6a06dde --- /dev/null +++ b/php_api_user/detalleEmpleados.php @@ -0,0 +1,46 @@ + endpointDetalles::API_DETALLE_EMPLEADO, + default => throw new InvalidArgumentException("Tipo desconocido: $tipo"), + }; + } + public function obtenerDatos(string $tipo): array { + $url = $this->getDetalleEndpoint($tipo); + + $proceso = curl_init(); + curl_setopt($proceso, CURLOPT_URL, $url); + curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true); + curl_setopt($proceso, CURLOPT_TIMEOUT, 30); + curl_setopt($proceso, CURLOPT_HTTPHEADER, [ + 'Accept: application/json', + 'Content-Type: application/json' + ]); + + $response = curl_exec($proceso); + $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE); + curl_close($proceso); + + $dato = json_decode($response, true); + + return ['http_code' => $http_code,'data' => $dato]; + } + public function mostrarDatos(string $tipo): void { + echo "\n=== DATOS DE EMPLEADOS ===\n"; + echo "Endpoint: " . $this->getDetalleEndpoint($tipo) . "\n"; + + $resultado = $this->obtenerDatos($tipo); + + echo "HTTP Code: " . $resultado['http_code'] . "\n"; + echo "Datos obtenidos:\n"; + echo json_encode($resultado['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"; + echo "\n"; + echo "El conteo total de empleados es: " . count($resultado['data']) . "\n"; + } +} +$detalles = new DetallesEmpleados(); +$detalles->mostrarDatos('empleados'); +?> \ No newline at end of file diff --git a/php_api_user/registroClientes.php b/php_api_user/registroClientes.php new file mode 100644 index 0000000..456f6e6 --- /dev/null +++ b/php_api_user/registroClientes.php @@ -0,0 +1,74 @@ + endpointCreacion::API_CREAR_CLIENTE, + default => throw new InvalidArgumentException("Tipo desconocido: $tipo"), + }; + } + + public function crearCliente(string $tipo): array { + $url = $this->getCreacionEndpoint($tipo); + + echo "\n==============================\n"; + echo "=== REGISTRO DE CLIENTES ===\n"; + echo "==============================\n"; + + $nombre = readline("Ingrese el nombre: "); + $telefono = readline("Ingrese el telefono: "); + $correo = readline("Ingrese el correo: "); + $contrasena = readline("Ingrese la contraseña: "); + + $datos_nuevos = array( + "nombre" => $nombre, + "email" => $correo, + "telefono" => $telefono, + "contrasena" => $contrasena + ); + + $data_json = json_encode($datos_nuevos); + + $proceso = curl_init($url); + curl_setopt($proceso, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($proceso, CURLOPT_POSTFIELDS, $data_json); + curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true); + curl_setopt($proceso, CURLOPT_HTTPHEADER, array( + "Content-Type: application/json", + "Content-Length: " . strlen($data_json) + )); + + $response = curl_exec($proceso); + $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE); + curl_close($proceso); + + return [ + 'http_code' => $http_code, + 'data' => json_decode($response, true) + ]; + } + + public function mostrarRegistro(string $tipo): void { + echo "\n=== REGISTRO DE NUEVO CLIENTE ===\n"; + echo "Endpoint: " . $this->getCreacionEndpoint($tipo) . "\n"; + + $resultado = $this->crearCliente($tipo); + + echo "HTTP Code: " . $resultado['http_code'] . "\n"; + if ($resultado['http_code'] == 200){ + echo "Cliente registrado exitosamente.\n"; + } else { + echo "Error al registrar el cliente.\n"; + } + if ($resultado['data'] !== null && !empty($resultado['data'])) { + echo "Respuesta del servidor:\n"; + echo json_encode($resultado['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"; + } + echo "\n"; + } +} + +$registro = new RegistroClientes(); +$registro->mostrarRegistro('cliente'); +?> \ No newline at end of file diff --git a/php_api_user/registroEmpleados.php b/php_api_user/registroEmpleados.php new file mode 100644 index 0000000..73d0fe3 --- /dev/null +++ b/php_api_user/registroEmpleados.php @@ -0,0 +1,75 @@ + endpointCreacion::API_CREAR_EMPLEADO, + default => throw new InvalidArgumentException("Tipo desconocido: $tipo"), + }; + } + + public function crearEmpleado(string $tipo): array { + $url = $this->getCreacionEndpoint($tipo); + + echo "\n==============================\n"; + echo "=== REGISTRO DE EMPLEADOS ===\n"; + echo "==============================\n"; + + $nombre = readline("Ingrese el nombre: "); + $telefono = readline("Ingrese el telefono: "); + $correo = readline("Ingrese el correo: "); + $contrasena = readline("Ingrese la contraseña: "); + + $datos_nuevos = array( + "nombre" => $nombre, + "email" => $correo, + "telefono" => $telefono, + "contrasena" => $contrasena + ); + + $data_json = json_encode($datos_nuevos); + + $proceso = curl_init($url); + curl_setopt($proceso, CURLOPT_CUSTOMREQUEST, "POST"); + curl_setopt($proceso, CURLOPT_POSTFIELDS, $data_json); + curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true); + curl_setopt($proceso, CURLOPT_HTTPHEADER, array( + "Content-Type: application/json", + "Content-Length: " . strlen($data_json) + )); + + $response = curl_exec($proceso); + $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE); + curl_close($proceso); + + return [ + 'http_code' => $http_code, + 'data' => json_decode($response, true) + ]; + } + + public function mostrarRegistro(string $tipo): void { + echo "\n=== REGISTRO DE NUEVO EMPLEADO ===\n"; + echo "Endpoint: " . $this->getCreacionEndpoint($tipo) . "\n"; + + $resultado = $this->crearEmpleado($tipo); + + echo "HTTP Code: " . $resultado['http_code'] . "\n"; + + if ($resultado['http_code'] == 200){ + echo "Empleado registrado exitosamente.\n"; + } else { + echo "Error al registrar el Empleado.\n"; + } + if ($resultado['data'] !== null && !empty($resultado['data'])) { + echo "Respuesta del servidor:\n"; + echo json_encode($resultado['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"; + } + echo "\n"; + } +} + +$registro = new RegistroEmpleados(); +$registro->mostrarRegistro('cliente'); +?> \ No newline at end of file diff --git a/target/classes/com/example/Proyecto/Controllers/ConexionController.class b/target/classes/com/example/Proyecto/Controllers/ConexionController.class deleted file mode 100644 index c9c646f..0000000 Binary files a/target/classes/com/example/Proyecto/Controllers/ConexionController.class and /dev/null differ diff --git a/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService$1.class b/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService$1.class deleted file mode 100644 index 812d5b5..0000000 Binary files a/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService$1.class and /dev/null differ diff --git a/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService.class b/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService.class deleted file mode 100644 index fdeaa36..0000000 Binary files a/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService.class and /dev/null differ diff --git a/target/classes/com/example/Proyecto/Services/Administrador/PojoAdmin.class b/target/classes/com/example/Proyecto/Services/Administrador/PojoAdmin.class deleted file mode 100644 index 855d7ff..0000000 Binary files a/target/classes/com/example/Proyecto/Services/Administrador/PojoAdmin.class and /dev/null differ diff --git a/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService$1.class b/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService$1.class deleted file mode 100644 index 5e9b77f..0000000 Binary files a/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService$1.class and /dev/null differ diff --git a/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService.class b/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService.class deleted file mode 100644 index 64684dc..0000000 Binary files a/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService.class and /dev/null differ diff --git a/target/classes/com/example/Proyecto/Services/Clientes/PojoCliente.class b/target/classes/com/example/Proyecto/Services/Clientes/PojoCliente.class deleted file mode 100644 index 6e8f743..0000000 Binary files a/target/classes/com/example/Proyecto/Services/Clientes/PojoCliente.class and /dev/null differ diff --git a/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService$1.class b/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService$1.class deleted file mode 100644 index e9027b8..0000000 Binary files a/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService$1.class and /dev/null differ diff --git a/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.class b/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.class deleted file mode 100644 index 1f5d092..0000000 Binary files a/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.class and /dev/null differ diff --git a/target/classes/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.class b/target/classes/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.class deleted file mode 100644 index 9409bee..0000000 Binary files a/target/classes/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.class and /dev/null differ diff --git a/target/classes/com/example/Proyecto/Services/Empleados/PojoEmpleado.class b/target/classes/com/example/Proyecto/Services/Empleados/PojoEmpleado.class deleted file mode 100644 index 5cd4549..0000000 Binary files a/target/classes/com/example/Proyecto/Services/Empleados/PojoEmpleado.class and /dev/null differ