diff --git a/agregar_producto.php b/agregar_producto.php new file mode 100644 index 0000000..dd58d95 --- /dev/null +++ b/agregar_producto.php @@ -0,0 +1,65 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // Insertar el nuevo producto + $stmt = $pdo->prepare("INSERT INTO products (nombre) VALUES (:nombre)"); + $stmt->execute(['nombre' => $nombre_producto]); + + $message = "¡Producto '" . htmlspecialchars($nombre_producto) . "' agregado correctamente!"; + + } catch (PDOException $e) { + $error = "Error al agregar el producto: " . $e->getMessage(); + } + } else { + $error = "Por favor, ingrese el nombre del producto."; + } +} +?> + +
+
+
+ + + + + + + + +
+
+ Agregar Nuevo Producto al Catálogo +
+
+
+
+ + +
+ +
+
+
+
+
+
+ + \ No newline at end of file diff --git a/cobertura.php b/cobertura.php index 877881e..ba2623b 100644 --- a/cobertura.php +++ b/cobertura.php @@ -1,212 +1,98 @@ query("SELECT id, titulo, texto FROM cobertura ORDER BY id ASC"); -$coberturas = $stmt->fetchAll(PDO::FETCH_ASSOC); +try { + $pdo = db(); + $stmt = $pdo->query("SELECT * FROM cobertura ORDER BY id DESC"); + $coberturas = $stmt->fetchAll(PDO::FETCH_ASSOC); +} catch (PDOException $e) { + echo "
Error al conectar con la base de datos: " . $e->getMessage() . "
"; + die(); +} + +$cobertura_banner = 'assets/uploads/cobertura_banner.jpg'; ?> - +
+

Gestión de Cobertura

-
-

Textos de Cobertura

- - -
- +
+
+ Banner de la Página de Cobertura
- - -
- -
- - - - - - -
- '; - } else { - echo '

No hay imagen de cabecera todavía.

'; - } - ?> + +

Banner Actual:

+ Banner Cobertura + +

No hay un banner de cobertura actualmente.

+ + +
+
+ + +
+ +
-
- Coberturas Guardadas +
+ Zonas de Cobertura + Agregar Nueva Zona
- - +
+ - - - + + + + - - - - - + + + - + + + + + + + + + +
ProductosCoberturaImagenTítuloDescripciónAcciones
No hay zonas de cobertura definidas.
+ + Imagen de cobertura + + Sin imagen + + + + Eliminar + +
- - -
- - - \ No newline at end of file + diff --git a/cobertura_xpress.php b/cobertura_xpress.php index a6e5ff3..fee3c72 100644 --- a/cobertura_xpress.php +++ b/cobertura_xpress.php @@ -1,208 +1,52 @@ query("SELECT id, titulo, texto FROM cobertura_xpress ORDER BY id ASC"); -$coberturas = $stmt->fetchAll(PDO::FETCH_ASSOC); ?> - +
+

Gestión de Cobertura Xpress

-
-

Textos de Cobertura Xpress

- - -
- +
+
+ Banner de la Página de Cobertura Xpress
- - -
- -
- - -
- '; - } else { - echo '

No hay imagen de cabecera todavía.

'; - } - ?> + +

Banner Actual:

+ Banner Cobertura Xpress + +

No hay un banner de Cobertura Xpress actualmente.

+ + +
+
+ + +
+ +
-
- Coberturas Xpress Guardadas +
+ Zonas de Cobertura Xpress + Agregar Nueva Zona Xpress
-
- - - - - - - - - - - - - - - - - -
CiudadCobertura
-
+

La configuración para las zonas de cobertura Xpress estará disponible aquí.

+
- - -
- - - + \ No newline at end of file diff --git a/db/migrations/050_create_stock_sedes_table.sql b/db/migrations/050_create_stock_sedes_table.sql new file mode 100644 index 0000000..2bc3bae --- /dev/null +++ b/db/migrations/050_create_stock_sedes_table.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS stock_sedes ( + id INT AUTO_INCREMENT PRIMARY KEY, + product_id INT NOT NULL, + sede_id INT NOT NULL, + quantity INT NOT NULL DEFAULT 0, + last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE, + FOREIGN KEY (sede_id) REFERENCES sedes(id) ON DELETE CASCADE, + UNIQUE KEY `product_sede` (`product_id`, `sede_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/layout_header.php b/layout_header.php index 15c7f72..aa3e9f5 100644 --- a/layout_header.php +++ b/layout_header.php @@ -74,43 +74,49 @@ $navItems = [ 'text' => 'Agregar Pedido', 'roles' => ['Administrador', 'admin', 'Asesor', 'Control Logistico'] ], - 'productos' => [ - 'url' => 'productos.php', - 'icon' => 'fa-box', - 'text' => 'Gestionar Productos', - 'roles' => ['Administrador', 'admin'] - ], - 'panel_inventario' => [ - 'icon' => 'fa-warehouse', - 'text' => 'Panel de Inventario', - 'roles' => ['Administrador', 'admin', 'Control Logistico'], - 'submenu' => [ - 'dashboard' => [ - 'url' => 'panel_inventario.php?seccion=dashboard', - 'icon' => 'fa-tachometer-alt', - 'text' => 'Dashboard', - 'roles' => ['Administrador', 'admin', 'Control Logistico'] - ], - 'entrada' => [ - 'url' => 'panel_inventario.php?seccion=entrada', - 'icon' => 'fa-arrow-circle-down', - 'text' => 'Registro de Entrada', - 'roles' => ['Administrador', 'admin', 'Control Logistico'] - ], - 'salida' => [ - 'url' => 'panel_inventario.php?seccion=salida', - 'icon' => 'fa-arrow-circle-up', - 'text' => 'Registro de Salida', - 'roles' => ['Administrador', 'admin', 'Control Logistico'] - ], - 'registro_producto' => [ - 'url' => 'panel_inventario.php?seccion=registro_producto', - 'icon' => 'fa-plus-circle', - 'text' => 'Registro de Producto', - 'roles' => ['Administrador', 'admin', 'Control Logistico'] + 'inventario_group' => [ + 'icon' => 'fa-warehouse', + 'text' => 'Inventario', + 'roles' => ['Administrador', 'admin', 'Control Logistico'], + 'submenu' => [ + 'panel_inventario' => [ + 'url' => 'panel_inventario.php', + 'icon' => 'fa-warehouse', + 'text' => 'Inventario General', + 'roles' => ['Administrador', 'admin', 'Control Logistico'] + ], + 'registro_entrada' => [ + 'url' => 'registro_entrada.php', + 'icon' => 'fa-arrow-circle-down', + 'text' => 'Registro de Entrada', + 'roles' => ['Administrador', 'admin', 'Control Logistico'] + ], + 'registro_salida' => [ + 'url' => 'registro_salida.php', + 'icon' => 'fa-arrow-circle-up', + 'text' => 'Registro de Salida', + 'roles' => ['Administrador', 'admin', 'Control Logistico'] + ], + 'sede' => [ + 'url' => 'sedes.php', + 'icon' => 'fa-building', + 'text' => 'Sede', + 'roles' => ['Administrador', 'admin', 'Control Logistico'] + ], + 'resumen_stock' => [ + 'url' => '#', + 'icon' => 'fa-chart-bar', + 'text' => 'Resumen de stock', + 'roles' => ['Administrador', 'admin', 'Control Logistico'] + ], + 'agregar_producto' => [ + 'url' => 'agregar_producto.php', + 'icon' => 'fa-plus', + 'text' => 'Agregar Producto', + 'roles' => ['Administrador', 'admin', 'Control Logistico'] + ] ] - ] - ], + ], 'finanzas_group' => [ 'icon' => 'fa-dollar-sign', 'text' => 'Finanzas', @@ -142,12 +148,6 @@ $navItems = [ ], ] ], - 'info_producto' => [ - 'url' => 'info_producto.php', - 'icon' => 'fa-info-circle', - 'text' => 'Info Producto', - 'roles' => ['Administrador', 'admin', 'Control Logistico'] - ], 'pedidos_duplicados' => [ 'url' => 'pedidos_duplicados.php', 'icon' => 'fa-copy', @@ -165,12 +165,6 @@ $navItems = [ 'icon' => 'fa-users', 'text' => 'Gestionar Usuarios', 'roles' => ['Administrador', 'admin'] - ], - 'configuracion' => [ - 'url' => 'configuracion.php', - 'icon' => 'fa-cog', - 'text' => 'Configuración', - 'roles' => ['Administrador', 'admin'] ] ]; diff --git a/panel_inventario.php b/panel_inventario.php index 866234b..81c500a 100644 --- a/panel_inventario.php +++ b/panel_inventario.php @@ -6,116 +6,62 @@ if (!isset($_SESSION['user_id'])) { } require_once 'layout_header.php'; require_once 'db/config.php'; -$pdo = db(); + +try { + $pdo = db(); + $stmt = $pdo->query("SELECT * FROM products ORDER BY order_position ASC"); + $products = $stmt->fetchAll(PDO::FETCH_ASSOC); +} catch (PDOException $e) { + echo "
Error al conectar con la base de datos: " . $e->getMessage() . "
"; + // Consider logging the error and showing a more user-friendly message + // For now, we stop execution if the database connection fails. + die(); +} ?>
-

Panel de Inventario

+
+

Inventario General

+ Añadir Producto +
- - -
-
- query("SELECT * FROM products ORDER BY order_position ASC"); - $products = $stmt->fetchAll(PDO::FETCH_ASSOC); - ?> -
-

Inventario General

- Añadir Producto -
- - - - - - - - - - - - +
+
+
+
IDNombreSKUPrecioAcciones
+ - - - - - - - - -
S/ - Editar - Eliminar -
-
-
- "; - } - ?> -
-
- - -
- -
- - Agregar Nueva Cobertura - - - - - - - - + + + + + - query("SELECT * FROM cobertura ORDER BY id DESC"); - while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { - echo ""; - $image_path = 'assets/uploads/cobertura_images/' . $row['imagen']; - if (file_exists($image_path)) { - echo ""; - } else { - echo ""; - } - echo ""; - echo ""; - echo ""; - echo ""; - } - ?> + + + + + + + + + + + + + + +
ImagenTítuloDescripciónAccionesIDNombreSKUPrecioAcciones
Imagen de coberturaImagen no encontrada" . htmlspecialchars($row['titulo']) . "" . htmlspecialchars($row['descripcion']) . ""; - echo "Eliminar"; - echo "
No hay productos en el inventario. Agrega el primero.
S/ + Editar + Eliminar +
-
-

Aquí irá la configuración de cobertura xpress.

- + \ No newline at end of file diff --git a/registro_entrada.php b/registro_entrada.php new file mode 100644 index 0000000..767eb0e --- /dev/null +++ b/registro_entrada.php @@ -0,0 +1,121 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // Verificar si ya existe un registro para este producto en esta sede + $stmt = $pdo->prepare("SELECT * FROM stock_sedes WHERE product_id = :product_id AND sede_id = :sede_id"); + $stmt->execute(['product_id' => $product_id, 'sede_id' => $sede_id]); + $existing_stock = $stmt->fetch(); + + if ($existing_stock) { + // Si existe, actualizar la cantidad + $new_quantity = $existing_stock['quantity'] + $quantity; + $update_stmt = $pdo->prepare("UPDATE stock_sedes SET quantity = :quantity WHERE id = :id"); + $update_stmt->execute(['quantity' => $new_quantity, 'id' => $existing_stock['id']]); + } else { + // Si no existe, insertar un nuevo registro + $insert_stmt = $pdo->prepare("INSERT INTO stock_sedes (product_id, sede_id, quantity) VALUES (:product_id, :sede_id, :quantity)"); + $insert_stmt->execute(['product_id' => $product_id, 'sede_id' => $sede_id, 'quantity' => $quantity]); + } + + $message = "¡Inventario actualizado correctamente!"; + + } catch (PDOException $e) { + $error = "Error al actualizar el inventario: " . $e->getMessage(); + } + } else { + $error = "Por favor, complete todos los campos del formulario."; + } +} + +// Obtener productos y sedes de la base de datos para los dropdowns +$products = []; +$sedes = []; + +try { + $pdo = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8", DB_USER, DB_PASS); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + $products_stmt = $pdo->query("SELECT id, nombre FROM products ORDER BY nombre ASC"); + $products = $products_stmt->fetchAll(PDO::FETCH_ASSOC); + + $sedes_stmt = $pdo->query("SELECT id, nombre FROM sedes ORDER BY nombre ASC"); + $sedes = $sedes_stmt->fetchAll(PDO::FETCH_ASSOC); + +} catch (PDOException $e) { + $error = "Error al cargar datos: " . $e->getMessage(); +} + +?> + +
+
+
+ + + + + + + + +
+
+ Registro de Entrada de Producto +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+
+
+ + \ No newline at end of file diff --git a/registro_salida.php b/registro_salida.php new file mode 100644 index 0000000..9c99abd --- /dev/null +++ b/registro_salida.php @@ -0,0 +1,123 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // Verificar si ya existe un registro para este producto en esta sede + $stmt = $pdo->prepare("SELECT * FROM stock_sedes WHERE product_id = :product_id AND sede_id = :sede_id"); + $stmt->execute(['product_id' => $product_id, 'sede_id' => $sede_id]); + $existing_stock = $stmt->fetch(); + + if ($existing_stock) { + // Si existe, actualizar la cantidad + $new_quantity = $existing_stock['quantity'] - $quantity; + if ($new_quantity < 0) { + $error = "No hay suficiente stock para registrar la salida."; + } else { + $update_stmt = $pdo->prepare("UPDATE stock_sedes SET quantity = :quantity WHERE id = :id"); + $update_stmt->execute(['quantity' => $new_quantity, 'id' => $existing_stock['id']]); + $message = "¡Inventario actualizado correctamente!"; + } + } else { + // Si no existe, no se puede dar salida + $error = "No hay stock registrado para este producto en la sede seleccionada."; + } + + } catch (PDOException $e) { + $error = "Error al actualizar el inventario: " . $e->getMessage(); + } + } else { + $error = "Por favor, complete todos los campos del formulario."; + } +} + +// Obtener productos y sedes de la base de datos para los dropdowns +$products = []; +$sedes = []; + +try { + $pdo = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8", DB_USER, DB_PASS); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + $products_stmt = $pdo->query("SELECT id, nombre FROM products ORDER BY nombre ASC"); + $products = $products_stmt->fetchAll(PDO::FETCH_ASSOC); + + $sedes_stmt = $pdo->query("SELECT id, nombre FROM sedes ORDER BY nombre ASC"); + $sedes = $sedes_stmt->fetchAll(PDO::FETCH_ASSOC); + +} catch (PDOException $e) { + $error = "Error al cargar datos: " . $e->getMessage(); +} + +?> + +
+
+
+ + + + + + + + +
+
+ Registro de Salida de Producto +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+
+
+ + \ No newline at end of file diff --git a/sedes.php b/sedes.php new file mode 100644 index 0000000..25f7775 --- /dev/null +++ b/sedes.php @@ -0,0 +1,111 @@ +prepare("SELECT COUNT(*) FROM sedes WHERE nombre = ?"); + $stmt->execute([$nombre_sede]); + if ($stmt->fetchColumn() > 0) { + $error = "La sede '" . htmlspecialchars($nombre_sede) . "' ya existe."; + } else { + // Insert new sede + $stmt = $pdo->prepare("INSERT INTO sedes (nombre) VALUES (?)"); + if ($stmt->execute([$nombre_sede])) { + $message = "Sede '" . htmlspecialchars($nombre_sede) . "' agregada correctamente."; + } else { + $error = "Error al agregar la sede."; + } + } + } catch (PDOException $e) { + // Do not show detailed SQL errors to the user + error_log("Database Error: " . $e->getMessage()); + $error = "Error de base de datos al intentar agregar la sede."; + } + } else { + $error = "El nombre de la sede no puede estar vacío."; + } +} + +// Fetch all existing sedes +$sedes = []; +try { + $pdo = db(); + $stmt = $pdo->query("SELECT id, nombre FROM sedes ORDER BY nombre ASC"); + $sedes = $stmt->fetchAll(PDO::FETCH_ASSOC); +} catch (PDOException $e) { + error_log("Database Error: " . $e->getMessage()); + $error .= " Error al cargar la lista de sedes."; +} + +?> + +
+
+
+ +

Gestionar Sedes

+

Aquí puedes agregar nuevas sedes para la gestión de inventario.

+ + +
+ + +
+ + + +
+
+
Agregar Nueva Sede
+
+
+
+
+ + +
+ +
+
+
+ + +
+
+
Sedes Existentes
+
+
+ 0): ?> +
    + +
  • + + +
  • + +
+ +

No hay sedes registradas. ¡Agrega la primera!

+ +
+
+ +
+
+
+ +