541 lines
19 KiB
PHP
541 lines
19 KiB
PHP
<?php
|
|
|
|
// Validacion de token
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
|
if (!isset($_POST['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) { // Recorre todos los caracteres (siempre) y retorna true or false
|
|
$_SESSION['flash_error'] = 'Acción inválida.';
|
|
header('Location: index.php?opt=inicio_operador');
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Requiere el modelo de producto
|
|
|
|
require_once __DIR__ . '/../models/productoModel.php';
|
|
$productomodel = new productoModel;
|
|
|
|
// Validar sesón
|
|
|
|
if (!isset($_SESSION['user'])) {
|
|
header("Location: index.php?opt=login_operador");
|
|
exit;
|
|
}
|
|
|
|
$opt = $_GET['opt'] ?? null;
|
|
|
|
// Manejo de opciones $opt
|
|
|
|
switch($opt) {
|
|
|
|
// LISTAR PRODUCTOS
|
|
|
|
case 'productos':
|
|
|
|
// Utilizamos el modelo para obtener la lista completa de productos
|
|
|
|
$productos = $productomodel->listarProductos();
|
|
|
|
// Saneamiento de datos para enviar a la view
|
|
|
|
foreach ($productos as $i => $p) {
|
|
|
|
if (($p['precio'] === null) || ($p['precio'] == 0)) {
|
|
$productos[$i]['precio'] = '-';
|
|
} else {
|
|
$productos[$i]['precio'] = '$ ' . number_format($p['precio'], 2, '.', ',');
|
|
}
|
|
|
|
if ($p['stock'] === null || $p['stock'] === 0) {
|
|
$productos[$i]['stock'] = '-';
|
|
}
|
|
|
|
$productos[$i]['descuento_total'] = number_format($p['descuento_total'], 2, '.', '') . ' %';
|
|
}
|
|
|
|
ob_start();
|
|
require __DIR__ . '/../views/productos/listaProductosView.php';
|
|
return ob_get_clean();
|
|
|
|
// LISTAR PRODUCTOS INACTIVOS
|
|
|
|
case 'productos_inactivos':
|
|
|
|
// Utilizamos el modelo para obtener la lista completa de productos
|
|
|
|
$productos = $productomodel->listarProductosInactivos();
|
|
|
|
ob_start();
|
|
require __DIR__ . '/../views/productos/listaProductosInactivosView.php';
|
|
return ob_get_clean();
|
|
|
|
// CREAR PRODUCTO
|
|
|
|
case 'crear_producto':
|
|
|
|
// Mostramos la vista con los datos correspondientes
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
|
$categorias = $productomodel->listarCategorias();
|
|
$tipos = $productomodel->listarTipos();
|
|
|
|
ob_start();
|
|
require __DIR__ . '/../views/productos/crearProductoView.php';
|
|
return ob_get_clean();
|
|
}
|
|
|
|
// En caso de modificación de datos
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
|
$marca = trim($_POST['marca'] ?? '');
|
|
$modelo = trim($_POST['modelo'] ?? '');
|
|
$id_categoria = trim($_POST['categoria'] ?? '');
|
|
$id_tipo = trim($_POST['tipo'] ?? '');
|
|
|
|
// Normalización de datos
|
|
|
|
$descuentoRaw = trim($_POST['descuento'] ?? '');
|
|
$descuento = $descuentoRaw === '' ? null : $descuentoRaw;
|
|
|
|
$errores = [];
|
|
|
|
// Validaciones
|
|
|
|
if ($marca === '') {
|
|
$errores[] = "La marca no puede estar vacía.";
|
|
} else if (!preg_match("/^[A-Za-zÁÉÍÓÚÑáéíóúñ0-9]+(?: [A-Za-zÁÉÍÓÚÑáéíóúñ0-9]+)*$/", $marca)) {
|
|
$errores[] = "La marca solo puede contener letras, números y espacios.";
|
|
} else if (strlen($marca) < 2) {
|
|
$errores[] = "La marca debe tener al menos 2 caracteres.";
|
|
} else if (strlen($marca) > 50) {
|
|
$errores[] = "La marca no puede superar los 50 caracteres.";
|
|
}
|
|
|
|
if ($modelo === '') {
|
|
$errores[] = "El modelo no puede estar vacío.";
|
|
} else if (!preg_match("/^[A-Za-zÁÉÍÓÚÑáéíóúñ0-9.\-]+(?: [A-Za-zÁÉÍÓÚÑáéíóúñ0-9.\-]+)*$/", $modelo)) {
|
|
$errores[] = "El modelo solo puede contener letras, números, espacios, guiones y puntos";
|
|
} else if (strlen($modelo) < 2) {
|
|
$errores[] = "El modelo debe tener al menos 2 caracteres.";
|
|
} else if (strlen($modelo) > 50) {
|
|
$errores[] = "El modelo no puede superar los 50 caracteres.";
|
|
}
|
|
|
|
if ($descuento !== null) {
|
|
|
|
if (!preg_match("/^\d{1,3}(\.\d{1,2})?$/", $descuento)) {
|
|
$errores[] = "El descuento debe ser un número válido con hasta 2 decimales.";
|
|
} else if ((float)$descuento <= 0 || (float)$descuento > 100) {
|
|
$errores[] = "El descuento debe estar entre 0 a 100.";
|
|
}
|
|
}
|
|
|
|
if ($id_categoria === '') {
|
|
$errores[] = "Debe seleccionar una categoría.";
|
|
} else if (!filter_var($id_categoria, FILTER_VALIDATE_INT) || $id_categoria <= 0) {
|
|
$errores[] = "La categoría seleccionada no es válida.";
|
|
} else if (!$productomodel->existeCategoria($id_categoria)) {
|
|
$errores[] = "La categoría ingresada no existe.";
|
|
}
|
|
|
|
if ($id_tipo === '') {
|
|
$errores[] = "Debe seleccionar un tipo.";
|
|
} else if (!filter_var($id_tipo, FILTER_VALIDATE_INT) || $id_tipo <= 0) {
|
|
$errores[] = "El tipo seleccionado no es válido.";
|
|
} else if (!$productomodel->existeTipo($id_tipo)) {
|
|
$errores[] = "El tipo ingresado no existe.";
|
|
}
|
|
|
|
if (($id_tipo === 2) && ($descuento !== null)) {
|
|
$errores[] = "No se permite descuento si el tipo de producto es Servicio.";
|
|
}
|
|
|
|
if (!empty($errores)) {
|
|
$_SESSION['flash_error'] = implode('<br>', $errores);
|
|
header("Location: index.php?opt=crear_producto");
|
|
exit;
|
|
}
|
|
|
|
// Utilizamos el método del modelo para crear el producto
|
|
|
|
if ($productomodel->crearProducto([
|
|
'marca' => $marca,
|
|
'modelo' => $modelo,
|
|
'precio' => null,
|
|
'stock' => null,
|
|
'descuento' => $descuento !== null ? (float)$descuento : null,
|
|
'id_categoria' => $id_categoria,
|
|
'id_tipo' => $id_tipo
|
|
])) {
|
|
$_SESSION['flash_success'] = "Producto creado correctamente.";
|
|
} else {
|
|
$_SESSION['flash_error'] = "No se pudo crear el producto.";
|
|
}
|
|
|
|
header("Location: index.php?opt=productos");
|
|
exit;
|
|
}
|
|
|
|
// EDITAR PRODUCTO
|
|
|
|
case 'editar_producto':
|
|
|
|
$idEditar = (int) ($_GET['id'] ?? 0);
|
|
|
|
if ($idEditar <= 0) {
|
|
header("Location: index.php?opt=productos");
|
|
exit;
|
|
}
|
|
|
|
// Busco el producto en la base de datos mediante el modelo
|
|
|
|
$producto = $productomodel->obtenerPorId($idEditar);
|
|
|
|
if (!$producto) {
|
|
$_SESSION['flash_error'] = "No se encontró el producto.";
|
|
header("Location: index.php?opt=productos");
|
|
exit;
|
|
};
|
|
|
|
// (Para indicar que aún no existen pedidos que incluyan dicho producto (no existe ID de pedido))
|
|
|
|
if ($producto['id_pedido'] === null) {
|
|
$producto['id_pedido'] = 'Aún no existe pedido que incluya este producto';
|
|
}
|
|
|
|
// Si el descuento es null lo seteamos en 0
|
|
|
|
if ($producto['descuento'] === null) {
|
|
$producto['descuento'] = 0;
|
|
}
|
|
|
|
// Mostrar datos de producto
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
|
$categorias = $productomodel->listarCategorias();
|
|
$tipos = $productomodel->listarTipos();
|
|
|
|
ob_start();
|
|
require __DIR__ . '/../views/productos/editarProductoView.php';
|
|
return ob_get_clean();
|
|
}
|
|
|
|
// Caso en donde se modifican los datos
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
|
// Normalización de datos
|
|
|
|
$descuentoRaw = trim($_POST['descuento'] ?? '');
|
|
$descuento = $descuentoRaw === '' ? null : $descuentoRaw;
|
|
|
|
$errores = [];
|
|
|
|
// Validaciones
|
|
|
|
if ($descuento !== null) {
|
|
|
|
if (!preg_match("/^\d{1,3}(\.\d{1,2})?$/", $descuento)) {
|
|
$errores[] = "El descuento debe ser un número válido con hasta 2 decimales.";
|
|
} else if ((float)$descuento < 0 || (float)$descuento > 100) {
|
|
$errores[] = "El descuento debe estar entre 0 a 100.";
|
|
}
|
|
}
|
|
|
|
if (!empty($errores)) {
|
|
$_SESSION['flash_error'] = implode('<br>', $errores);
|
|
header("Location: index.php?opt=editar_producto&id=" . $idEditar);
|
|
exit;
|
|
}
|
|
|
|
// Recalculoamos precio (en caso de que se modifique descuento)
|
|
|
|
require_once __DIR__ . '/../models/pedidoModel.php';
|
|
$pedidomodel = new pedidoModel();
|
|
|
|
$costoUnitario = $pedidomodel->obtenerCosto($_GET['id']);
|
|
$categoria = $productomodel->obtenerPorIdCategoria($producto['id_categoria']);
|
|
|
|
// Antes de guardar los datos verificamos que la suma del descuento no sea mayor a 100
|
|
|
|
if (($categoria['porcentaje_ganancia'] + $descuento) > 100) {
|
|
$_SESSION['flash_error'] = "La suma entre el descuento ingresado y el descuento de la categoria supera el 100%. Verifique.";
|
|
header("Location:index.php?opt=editar_producto&id=$idEditar");
|
|
exit;
|
|
}
|
|
|
|
// Creamos el array con los datos correspondientes
|
|
|
|
$guardarData = [
|
|
'precio' => $costoUnitario !== null ? (100 + $categoria['porcentaje_ganancia']) * $costoUnitario / 100 : null,
|
|
'descuento' => $descuento !== null ? (float) $descuento : null,
|
|
'id_categoria' => $producto['id_categoria']
|
|
];
|
|
|
|
// Utilizamos la función del modelo para actualizar el producto
|
|
|
|
if ($productomodel->actualizarProducto($_GET['id'], $guardarData)) {
|
|
$_SESSION['flash_success'] = "Datos actualizados correctamente.";
|
|
} else {
|
|
$_SESSION['flash_error'] = "No se pudo actualizar los datos.";
|
|
}
|
|
|
|
header("Location: index.php?opt=productos");
|
|
exit;
|
|
}
|
|
|
|
// CAMBIAR ESTADO DEL PRODUCTO (ACTIVO / INACTIVO)
|
|
|
|
case 'cambiar_estado':
|
|
|
|
$idProducto = (int) ($_POST['id'] ?? 0);
|
|
$nuevoEstado = isset($_POST['estado']) ? (bool) $_POST['estado'] : null;
|
|
|
|
if ($idProducto <= 0 || !is_bool($nuevoEstado)) {
|
|
header("Location: index.php?opt=productos");
|
|
exit;
|
|
};
|
|
|
|
$productomodel->actualizarEstado($idProducto, $nuevoEstado);
|
|
|
|
$_SESSION['flash_success'] = "Estado actualizado correctamente.";
|
|
header("Location: index.php?opt=productos");
|
|
exit;
|
|
|
|
// LISTAR LAS CATEGORIAS DE PRODUCTOS
|
|
|
|
case 'categorias':
|
|
|
|
$categorias = $productomodel->listarCategorias();
|
|
|
|
foreach ($categorias as $i => $c) {
|
|
|
|
if (($categorias)[$i]['porcentaje_ganancia'] === null) {
|
|
$c['porcentaje_ganancia'] = 0;
|
|
}
|
|
|
|
if (($categorias)[$i]['descuento'] === null) {
|
|
$c['descuento'] = 0;
|
|
}
|
|
|
|
$categorias[$i]['porcentaje_ganancia'] = number_format($c['porcentaje_ganancia'], 2, '.', '') . ' %';
|
|
$categorias[$i]['descuento'] = number_format($c['descuento'], 2, '.', '') . ' %';
|
|
}
|
|
|
|
ob_start();
|
|
require __DIR__ . '/../views/productos/listaCategoriasView.php';
|
|
return ob_get_clean();
|
|
|
|
// CREAR NUEVA CATEGORIA DE PRODUCTOS
|
|
|
|
case 'crear_categoria':
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
|
ob_start();
|
|
require __DIR__ . '/../views/productos/crearCategoriaView.php';
|
|
return ob_get_clean();
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
|
$nombre = trim($_POST['nombre'] ?? '');
|
|
|
|
// Normalización
|
|
|
|
$porcentaje_gananciaRaw = trim($_POST['porcentaje_ganancia'] ?? '');
|
|
$porcentaje_ganancia = $porcentaje_gananciaRaw === '' ? null : $porcentaje_gananciaRaw;
|
|
|
|
$descuentoRaw = trim($_POST['descuento'] ?? '');
|
|
$descuento = $descuentoRaw === '' ? null : $descuentoRaw;
|
|
|
|
$errores = [];
|
|
|
|
// Validaciones
|
|
|
|
if ($nombre === '') {
|
|
$errores[] = "El nombre no puede estar vacío.";
|
|
} else if (!preg_match("/^[A-Za-zÁÉÍÓÚÑáéíóúñ0-9]+(?: [A-Za-zÁÉÍÓÚÑáéíóúñ0-9]+)*$/", $nombre)) {
|
|
$errores[] = "El nombre solo puede contener letras, números y espacios.";
|
|
} else if (strlen($nombre) < 2) {
|
|
$errores[] = "El nombre debe tener al menos 2 caracteres.";
|
|
} else if (strlen($nombre) > 50) {
|
|
$errores[] = "El nombre no puede superar los 50 caracteres.";
|
|
}
|
|
|
|
if ($porcentaje_ganancia !== null) {
|
|
|
|
if (!preg_match("/^\d{1,3}(\.\d{1,2})?$/", $porcentaje_ganancia)) {
|
|
$errores[] = "La ganancia debe ser un número válido con hasta 2 decimales.";
|
|
} else if ((float)$porcentaje_ganancia <= 0 || (float)$porcentaje_ganancia > 100) {
|
|
$errores[] = "La ganancia debe estar entre 0 a 100.";
|
|
}
|
|
}
|
|
|
|
if ($descuento !== null) {
|
|
|
|
if (!preg_match("/^\d{1,3}(\.\d{1,2})?$/", $descuento)) {
|
|
$errores[] = "El descuento debe ser un número válido con hasta 2 decimales.";
|
|
} else if ((float)$descuento < 0 || (float)$descuento > 100) {
|
|
$errores[] = "El descuento debe estar entre 0 a 100.";
|
|
}
|
|
}
|
|
|
|
if (!empty($errores)) {
|
|
$_SESSION['flash_error'] = implode('<br>', $errores);
|
|
header("Location: index.php?opt=crear_categoria");
|
|
exit;
|
|
}
|
|
|
|
if ($productomodel->crearCategoria([
|
|
'nombre' => $nombre,
|
|
'porcentaje_ganancia' => $porcentaje_ganancia !== null ? (float) $porcentaje_ganancia : null,
|
|
'descuento' => $descuento !== null ? (float) $descuento : null
|
|
])) {
|
|
$_SESSION['flash_success'] = "Categoría creada correctamente.";
|
|
} else {
|
|
$_SESSION['flash_error'] = "No se pudo crear la categoría.";
|
|
}
|
|
|
|
header("Location: index.php?opt=categorias");
|
|
exit;
|
|
}
|
|
|
|
// EDITAR CATEGORIA
|
|
|
|
case 'editar_categoria':
|
|
|
|
$idEditar = (int) ($_GET['id'] ?? 0);
|
|
|
|
if ($idEditar <= 0) {
|
|
header("Location: index.php?opt=categorias");
|
|
exit;
|
|
}
|
|
|
|
// Busco la categoría en la base de datos mediante el modelo
|
|
|
|
$categorias = $productomodel->obtenerPorIdCategoria($idEditar);
|
|
|
|
if (!$categorias) {
|
|
header("Location: index.php?opt=categorias");
|
|
exit;
|
|
};
|
|
|
|
// Si el descuento o el porcentaje_ganancia es null lo seteamos en 0
|
|
|
|
if ($categorias['porcentaje_ganancia'] === null) {
|
|
$categorias['porcentaje_ganancia'] = 0;
|
|
}
|
|
|
|
if ($categorias['descuento'] === null) {
|
|
$categorias['descuento'] = 0;
|
|
}
|
|
|
|
// Mostrar datos de producto
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
|
ob_start();
|
|
require __DIR__ . '/../views/productos/editarCategoriaView.php';
|
|
return ob_get_clean();
|
|
}
|
|
|
|
// Caso en donde se modifican los datos
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
|
|
$nombre = trim($_POST['nombre'] ?? '');
|
|
|
|
// Normalización
|
|
|
|
$porcentaje_gananciaRaw = trim($_POST['porcentaje_ganancia'] ?? '');
|
|
$porcentaje_ganancia = $porcentaje_gananciaRaw === '' ? null : $porcentaje_gananciaRaw;
|
|
|
|
$descuentoRaw = trim($_POST['descuento'] ?? '');
|
|
$descuento = $descuentoRaw === '' ? null : $descuentoRaw;
|
|
|
|
$errores = [];
|
|
|
|
// Validaciones
|
|
|
|
if ($nombre === '') {
|
|
$errores[] = "El nombre no puede estar vacío.";
|
|
} else if (!preg_match("/^[A-Za-zÁÉÍÓÚÑáéíóúñ0-9]+(?: [A-Za-zÁÉÍÓÚÑáéíóúñ0-9]+)*$/", $nombre)) {
|
|
$errores[] = "El nombre solo puede contener letras, números y espacios.";
|
|
} else if (strlen($nombre) < 2) {
|
|
$errores[] = "El nombre debe tener al menos 2 caracteres.";
|
|
} else if (strlen($nombre) > 50) {
|
|
$errores[] = "El nombre no puede superar los 50 caracteres.";
|
|
}
|
|
|
|
if ($porcentaje_ganancia !== null) {
|
|
|
|
if (!preg_match("/^\d{1,3}(\.\d{1,2})?$/", $porcentaje_ganancia)) {
|
|
$errores[] = "La ganancia debe ser un número válido con hasta 2 decimales.";
|
|
} else if ((float)$porcentaje_ganancia <= 0 || (float)$porcentaje_ganancia > 100) {
|
|
$errores[] = "La ganancia debe estar entre 0 a 100.";
|
|
}
|
|
}
|
|
|
|
if ($descuento !== null) {
|
|
|
|
if (!preg_match("/^\d{1,3}(\.\d{1,2})?$/", $descuento)) {
|
|
$errores[] = "El descuento debe ser un número válido con hasta 2 decimales.";
|
|
} else if ((float)$descuento < 0 || (float)$descuento > 100) {
|
|
$errores[] = "El descuento debe estar entre 0 a 100.";
|
|
}
|
|
}
|
|
|
|
if (!empty($errores)) {
|
|
$_SESSION['flash_error'] = implode('<br>', $errores);
|
|
header("Location: index.php?opt=editar_categoria&id=" . $idEditar);
|
|
exit;
|
|
}
|
|
|
|
// Verificamos que la suma entre los descuentos no supere el 100%
|
|
|
|
require_once __DIR__ . '/../models/productoModel.php';
|
|
$productomodel = new productoModel();
|
|
|
|
$productosDescuentos = $productomodel->obtenerDescuento($idEditar);
|
|
|
|
foreach ($productosDescuentos as $i => $p) {
|
|
|
|
if (($productosDescuentos[$i]['descuento'] + $descuento) > 100) {
|
|
$_SESSION['flash_error'] = "Existe al menos un producto que supera el 100% de sumatoria en el descuento. Verifique.";
|
|
header("Location:index.php?opt=editar_categoria&id=$idEditar");
|
|
exit;
|
|
}
|
|
}
|
|
|
|
$guardarData = [
|
|
'nombre' => $nombre,
|
|
'porcentaje_ganancia' => $porcentaje_ganancia !== null ? (float) $porcentaje_ganancia : null,
|
|
'descuento' => $descuento !== null ? (float) $descuento : null
|
|
];
|
|
|
|
// Obtenemos productos con sus respectivos costos para recalcular el precio de venta
|
|
|
|
require_once __DIR__ . '/../models/pedidoModel.php';
|
|
$pedidomodel = new pedidoModel();
|
|
|
|
$costosProductos = $pedidomodel->obtenerCostosPorCategoria($idEditar);
|
|
|
|
if ($productomodel->actualizarPreciosPorCategoria($idEditar, $guardarData, $costosProductos)) {
|
|
$_SESSION['flash_success'] = "Datos actualizados correctamente.";
|
|
} else {
|
|
$_SESSION['flash_error'] = "No se pudo actualizar la categoría.";
|
|
}
|
|
|
|
header("Location: index.php?opt=categorias");
|
|
exit;
|
|
}
|
|
|
|
// DEFAULT (404)
|
|
|
|
default:
|
|
|
|
ob_start();
|
|
require __DIR__ . '/../views/404View.php';
|
|
return ob_get_clean();
|
|
} |