490 lines
14 KiB
PHP
490 lines
14 KiB
PHP
<?php
|
|
|
|
require_once __DIR__ . '/../database/database.php';
|
|
|
|
class productoModel {
|
|
|
|
private PDO $db;
|
|
|
|
public function __construct() {
|
|
$this->db = Database::getConnection();
|
|
}
|
|
|
|
// LISTAR PRODUCTOS
|
|
|
|
public function listarProductos(): array {
|
|
|
|
$sql = "SELECT p.id, p.marca, p.modelo, p.precio, p.stock, (COALESCE(p.descuento, 0) + COALESCE(c.descuento, 0)) AS descuento_total, c.nombre AS categoria, t.nombre AS tipo
|
|
FROM productos AS p
|
|
INNER JOIN categorias AS c ON (p.id_categoria = c.id)
|
|
INNER JOIN tipos AS t ON (p.id_tipo = t.id)
|
|
WHERE (p.estado IS TRUE)
|
|
ORDER BY p.id ASC";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute();
|
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
// LISTAR PRODUCTOS INACTIVOS
|
|
|
|
public function listarProductosInactivos(): array {
|
|
|
|
$sql = "SELECT p.id, p.marca, p.modelo, p.precio, c.nombre AS categoria, t.nombre AS tipo
|
|
FROM productos AS p
|
|
INNER JOIN categorias AS c ON (p.id_categoria = c.id)
|
|
INNER JOIN tipos AS t ON (p.id_tipo = t.id)
|
|
WHERE (p.estado IS FALSE)
|
|
ORDER BY p.id ASC";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute();
|
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
// LISTAR PRODUCTOS PARA VENTA
|
|
|
|
public function listarProductosVenta(): array {
|
|
|
|
$sql = "SELECT p.id, p.marca, p.modelo, p.precio, CAST(p.precio - ((COALESCE(p.descuento, 0) + COALESCE(c.descuento, 0)) * p.precio / 100) AS DECIMAL(10,2)) AS precio_final, p.stock,
|
|
(COALESCE(p.descuento, 0) + COALESCE(c.descuento, 0)) AS descuento_total
|
|
FROM productos AS p
|
|
INNER JOIN categorias AS c ON (p.id_categoria = c.id)
|
|
INNER JOIN tipos AS t ON (p.id_tipo = t.id)
|
|
WHERE (p.estado IS TRUE) AND (p.id_tipo = 1) AND (p.precio IS NOT NULL) AND (p.stock <> 0)
|
|
ORDER BY p.id ASC";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute();
|
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
// LISTAR PORDUCTOS PARA PEDIDO
|
|
|
|
public function listarProductosPedido(): array {
|
|
|
|
$sql = "SELECT p.id, p.marca, p.modelo, p.stock FROM productos AS p
|
|
INNER JOIN tipos AS t ON (p.id_tipo = t.id)
|
|
WHERE (p.estado IS TRUE)
|
|
ORDER BY p.id ASC";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute();
|
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
// LISTAR INSUMOS PARA SERVICIO
|
|
|
|
public function listarInsumosServicio(): array {
|
|
|
|
$sql = "SELECT p.id, p.marca, p.modelo, p.precio, p.stock
|
|
FROM productos AS p
|
|
INNER JOIN categorias AS c ON (p.id_categoria = c.id)
|
|
INNER JOIN tipos AS t ON (p.id_tipo = t.id)
|
|
WHERE (p.estado IS TRUE) AND (p.id_tipo = 2) AND (p.precio IS NOT NULL) AND (p.stock <> 0)
|
|
ORDER BY p.id ASC";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute();
|
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
// CREAR PRODUCTO
|
|
|
|
public function crearProducto(array $data): bool {
|
|
|
|
$sql = "INSERT INTO productos (marca, modelo, precio, stock, descuento, estado, id_categoria, id_tipo)
|
|
VALUES (:marca, :modelo, :precio, :stock, :descuento, :estado, :id_categoria, :id_tipo)";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
return $stmt->execute([
|
|
':marca' => $data['marca'],
|
|
':modelo' => $data['modelo'],
|
|
':precio' => $data['precio'],
|
|
':stock' => $data['stock'],
|
|
':descuento' => $data['descuento'],
|
|
':estado' => 1, // Cuando un producto se crea, automáticamente se setea el estado en true, es decir está activo
|
|
':id_categoria' => $data['id_categoria'],
|
|
':id_tipo' => $data['id_tipo']
|
|
]);
|
|
}
|
|
|
|
// OBTENER PRODUCTO MEDIANTE ID
|
|
|
|
public function obtenerPorId(int $id): ?array {
|
|
|
|
$sql = "SELECT p.id, p.marca, p.modelo, p.precio, p.stock, p.descuento, p.id_categoria, p.id_tipo, pd.id_pedido AS id_pedido FROM productos AS p
|
|
LEFT JOIN pedido_detalle AS pd ON (p.id = pd.id_producto)
|
|
WHERE p.id = :id
|
|
ORDER BY pd.id_pedido DESC LIMIT 1";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute([':id' => $id]);
|
|
|
|
$producto = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
return $producto ?: null;
|
|
}
|
|
|
|
// OBTENER PRODUCTO POR ID PARA CAJA
|
|
|
|
public function obtenerPorIdParaCaja(int $id): ?array {
|
|
|
|
$sql = "SELECT p.id, p.marca, p.modelo, p.precio, COALESCE(p.descuento, 0) AS descuento_producto, COALESCE(c.descuento, 0) AS descuento_categoria, p.stock
|
|
FROM productos AS p
|
|
LEFT JOIN categorias AS c ON (c.id = p.id_categoria)
|
|
WHERE (p.id = :id) AND (p.estado IS TRUE) AND (p.id_tipo = 1) LIMIT 1";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute([':id' => $id]);
|
|
|
|
return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
|
|
}
|
|
|
|
// OBTENER PRODUCTOS DE PEDIDO POR ID PARA CAJA
|
|
|
|
public function obtenerPorIdParaCajaPedido(int $id): ?array {
|
|
|
|
$sql = "SELECT p.id, p.marca, p.modelo, p.stock, COALESCE(c.porcentaje_ganancia, 0) AS porcentaje_ganancia
|
|
FROM productos AS p
|
|
LEFT JOIN categorias AS c ON (c.id = p.id_categoria)
|
|
WHERE (p.id = :id) AND (p.estado IS TRUE) LIMIT 1";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute([':id' => $id]);
|
|
|
|
return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
|
|
}
|
|
|
|
// OBTENER INSUMO DE SERVICIO POR ID PARA CAJA
|
|
|
|
public function obtenerPorIdParaCajaServicio(int $id): ?array {
|
|
|
|
$sql = "SELECT p.id, p.marca, p.modelo, p.precio, p.stock
|
|
FROM productos AS p
|
|
LEFT JOIN categorias AS c ON (c.id = p.id_categoria)
|
|
WHERE (p.id = :id) AND (p.estado IS TRUE) AND (p.id_tipo = 2) LIMIT 1";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute([':id' => $id]);
|
|
|
|
return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
|
|
}
|
|
|
|
// EDITAR PRODUCTO
|
|
|
|
public function actualizarProducto(int $id, array $data): bool {
|
|
|
|
if (empty($data)) {
|
|
return false;
|
|
}
|
|
|
|
$campos = [];
|
|
$params = [];
|
|
|
|
foreach ($data as $campo => $valor) {
|
|
$campos[] = "$campo = :$campo";
|
|
$params[":$campo"] = $valor;
|
|
}
|
|
|
|
$params[':id'] = $id;
|
|
|
|
$sql = "UPDATE productos SET " . implode(', ', $campos) . " WHERE id = :id";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
return $stmt->execute($params);
|
|
}
|
|
|
|
// ACTUALIZAR ESTADO (ACTIVO / INACTIVO)
|
|
|
|
public function actualizarEstado(int $idProducto, bool $nuevoEstado): bool {
|
|
|
|
try {
|
|
$this->db->beginTransaction();
|
|
|
|
// Actualizamaos datos del producto
|
|
|
|
$sql1 = "UPDATE productos
|
|
SET estado = :estado,
|
|
precio = NULL,
|
|
stock = NULL,
|
|
descuento = NULL
|
|
WHERE id = :id";
|
|
|
|
$stmt1 = $this->db->prepare($sql1);
|
|
|
|
$stmt1->bindValue(':estado', $nuevoEstado, PDO::PARAM_BOOL);
|
|
|
|
$stmt1->bindValue(':id', $idProducto, PDO::PARAM_INT);
|
|
|
|
$stmt1->execute();
|
|
|
|
// Actualizamos los stock y cantidades de pedido_detalle
|
|
|
|
$sql2 = "UPDATE pedido_detalle
|
|
SET cantidad_vendida = cantidad
|
|
WHERE id_producto = :id";
|
|
|
|
$stmt2 = $this->db->prepare($sql2);
|
|
|
|
$stmt2->bindValue(':id', $idProducto, PDO::PARAM_INT);
|
|
|
|
$stmt2->execute();
|
|
|
|
$this->db->commit();
|
|
return true;
|
|
|
|
} catch (Exception $e) {
|
|
$this->db->rollBack();
|
|
|
|
// Log interno
|
|
|
|
error_log($e->getMessage());
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// LISTAR CATEGORIAS
|
|
|
|
public function listarCategorias(): array {
|
|
|
|
$sql = "SELECT id, nombre, porcentaje_ganancia, descuento FROM categorias ORDER BY nombre ASC";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute();
|
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
// VERIFICAR SI EXISTE UNA CATEGORIA
|
|
|
|
public function existeCategoria(int $id): bool {
|
|
|
|
$sql = "SELECT 1 FROM categorias WHERE id = :id LIMIT 1";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute([':id' => $id]);
|
|
|
|
return (bool) $stmt->fetchColumn();
|
|
}
|
|
|
|
// OBTENER CATEGORIA POR ID
|
|
|
|
public function obtenerPorIdCategoria(int $id): ?array {
|
|
|
|
$sql = "SELECT id, nombre, porcentaje_ganancia, descuento FROM categorias WHERE id = :id";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute([':id' => $id]);
|
|
|
|
$categoria = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
return $categoria ?: null;
|
|
}
|
|
|
|
// CREAR CATEGORIA
|
|
|
|
public function crearCategoria(array $data): bool {
|
|
|
|
$sql = "INSERT INTO categorias (nombre, porcentaje_ganancia, descuento) VALUES (:nombre, :porcentaje_ganancia, :descuento)";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
return $stmt->execute([
|
|
':nombre' => $data['nombre'],
|
|
':porcentaje_ganancia' => $data['porcentaje_ganancia'],
|
|
':descuento' => $data['descuento']
|
|
]);
|
|
}
|
|
|
|
// EDITAR CATEGORIA
|
|
|
|
public function actualizarCategoria(int $id, array $data): bool {
|
|
|
|
if (empty($data)) {
|
|
return false;
|
|
}
|
|
|
|
$campos = [];
|
|
$params = [];
|
|
|
|
foreach ($data as $campo => $valor) {
|
|
$campos[] = "$campo = :$campo";
|
|
$params[":$campo"] = $valor;
|
|
}
|
|
|
|
$params[':id'] = $id;
|
|
|
|
$sql = "UPDATE categorias SET " . implode(', ', $campos) . " WHERE id = :id";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
return $stmt->execute($params);
|
|
}
|
|
|
|
// ACTUALIZAR PRECIOS DE PRODUCTOS AL EDITAR LA CATEGORIA
|
|
|
|
public function actualizarPreciosPorCategoria(int $idCategoria, array $data, array $costosProductos): bool {
|
|
|
|
try {
|
|
|
|
$this->db->beginTransaction();
|
|
|
|
// Actualizamos la categoría
|
|
|
|
$ok = $this->actualizarCategoria($idCategoria, $data);
|
|
|
|
if (!$ok) {
|
|
$this->db->rollBack();
|
|
return false;
|
|
}
|
|
|
|
// Obtenemos el nuevo porcentaje de ganancia
|
|
|
|
$stmt = $this->db->prepare("
|
|
SELECT porcentaje_ganancia
|
|
FROM categorias
|
|
WHERE id = :id
|
|
");
|
|
|
|
$stmt->execute([':id' => $idCategoria]);
|
|
|
|
$categoria = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if (!$categoria) {
|
|
$this->db->rollBack();
|
|
return false;
|
|
}
|
|
|
|
$porcentaje_ganancia = (float) $categoria['porcentaje_ganancia'];
|
|
|
|
$stmt = $this->db->prepare("
|
|
UPDATE productos
|
|
SET precio = :precio
|
|
WHERE (id = :id) AND (id_categoria = :idCategoria)
|
|
");
|
|
|
|
foreach ($costosProductos as $c) {
|
|
|
|
// Validaciones defensivas
|
|
|
|
if (empty($c['id_producto']) || $c['costo'] === null) {
|
|
continue;
|
|
}
|
|
|
|
$costo = (float) $c['costo'];
|
|
|
|
// Fórmula correcta
|
|
|
|
$nuevoPrecio = (100 + $porcentaje_ganancia) * $costo / 100;
|
|
|
|
$stmt->execute([
|
|
':precio' => $nuevoPrecio,
|
|
':id' => $c['id_producto'],
|
|
':idCategoria' => $idCategoria
|
|
]);
|
|
}
|
|
|
|
$this->db->commit();
|
|
return true;
|
|
|
|
} catch (Exception $e) {
|
|
$this->db->rollBack();
|
|
|
|
// Log interno
|
|
|
|
error_log($e->getMessage());
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// LISTAR TIPOS DE PRODUCTOS
|
|
|
|
public function listarTipos(): array {
|
|
|
|
$sql = "SELECT id, nombre FROM tipos ORDER BY id ASC";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute();
|
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
// VERIFICAR SI EXISTE EL TIPO DE PRODUCTO
|
|
|
|
public function existeTipo(int $id): bool {
|
|
|
|
$sql = "SELECT 1 FROM tipos WHERE id = :id LIMIT 1";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute([':id' => $id]);
|
|
|
|
return (bool) $stmt->fetchColumn();
|
|
}
|
|
|
|
// OBTENER TIPO POR ID
|
|
|
|
public function obtenerPorIdTipo(int $tipo): ?array {
|
|
|
|
$sql = "SELECT id, nombre FROM tipos WHERE id = :id";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$tipo = $stmt->execute();
|
|
|
|
return $tipo ?: null;
|
|
}
|
|
|
|
// OBTENER DESCUENTOS DE PRODUCTOS EN BASE A UNA CATEGORIA
|
|
|
|
public function obtenerDescuento(int $idCategoria): ?array {
|
|
|
|
$sql = "SELECT productos.id, productos.descuento FROM productos
|
|
INNER JOIN categorias ON (categorias.id = productos.id_categoria)
|
|
WHERE (categorias.id = :idCategoria)";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute([':idCategoria' => $idCategoria]);
|
|
|
|
$resultado = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
return !empty($resultado) ? $resultado : null;
|
|
}
|
|
|
|
// BÚSQUEDA EN INPUT DE DESCRIPCIÓN DEL EQUIPO (MÓDULO SERVICIOS)
|
|
|
|
public function busquedaParaServicio(): array {
|
|
|
|
$sql = "SELECT marca, modelo FROM productos WHERE (id_tipo = 1)";
|
|
|
|
$stmt = $this->db->prepare($sql);
|
|
|
|
$stmt->execute();
|
|
|
|
return $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
} |