<?php class InventarioModel { private $conexion; public function __construct() { $database = new Database(); $this->conexion = $database->connect(); } // ───────────────────────────────────────────────────────────── // EPP (catálogo compartido por ambos inventarios) // ───────────────────────────────────────────────────────────── public function getEPPs() { $result = $this->conexion->query("SELECT CODIGO, NOMBRE FROM eppsst ORDER BY NOMBRE"); $rows = []; while ($row = $result->fetch_assoc()) $rows[] = $row; return $rows; } public function agregarEPP($codigo, $nombre) { $codigo = $this->conexion->real_escape_string(trim($codigo)); $nombre = $this->conexion->real_escape_string(strtoupper(trim($nombre))); $sql = "INSERT INTO eppsst (codigo, NOMBRE) VALUES ('$codigo', '$nombre')"; return $this->conexion->query($sql); } // ───────────────────────────────────────────────────────────── // INVENTARIO PRINCIPAL (tabla: inventario) // ───────────────────────────────────────────────────────────── public function getInventarioPrincipal() { $result = $this->conexion->query( "SELECT i.CODIGO, i.DESCRIPCION, i.CANTIDAD, i.ESTADO, e.NOMBRE as nombre_epp FROM inventario i LEFT JOIN eppsst e ON i.CODIGO = e.CODIGO WHERE i.estado = 0 ORDER BY i.CODIGO" ); $rows = []; while ($row = $result->fetch_assoc()) $rows[] = $row; return $rows; } public function getCantidadActualPrincipal($codigo) { $codigo = $this->conexion->real_escape_string($codigo); $result = $this->conexion->query( "SELECT CANTIDAD FROM inventario WHERE CODIGO = '$codigo' AND estado = 0 LIMIT 1" ); if ($result && $result->num_rows > 0) { return (int)$result->fetch_assoc()['CANTIDAD']; } return 0; } /** * Confirmar ingreso de EPPs al inventario principal * Con factura, proveedor y precio por cada elemento */ public function confirmarIngresoPrincipal(array $elementos, array $info_elementos, string $userEntrega): array { $this->conexion->begin_transaction(); $resumen = []; try { foreach ($elementos as $elemento) { $codigo = $this->conexion->real_escape_string($elemento['codigo']); $descripcion = $this->conexion->real_escape_string($elemento['descripcion']); $cantidad = intval($elemento['cantidad']); $info = $info_elementos[$elemento['codigo']]; $nfactura = $this->conexion->real_escape_string($info['nfactura']); $provedor = $this->conexion->real_escape_string($info['provedor']); $precio = floatval($info['precio']); // Actualizar o insertar en inventario $consulta = "SELECT CANTIDAD FROM inventario WHERE CODIGO = '$codigo' AND estado = 0 LIMIT 1"; $resultado = $this->conexion->query($consulta); if ($resultado && $resultado->num_rows > 0) { $nueva = (int)$resultado->fetch_assoc()['CANTIDAD'] + $cantidad; $sql = "UPDATE inventario SET CANTIDAD = $nueva WHERE CODIGO = '$codigo' AND estado = 0"; if (!$this->conexion->query($sql)) { throw new Exception("Error actualizando $codigo: " . $this->conexion->error); } } else { $sql = "INSERT INTO inventario (CODIGO, DESCRIPCION, CANTIDAD, ESTADO) VALUES ('$codigo', '$descripcion', $cantidad, 0)"; if (!$this->conexion->query($sql)) { throw new Exception("Error insertando $codigo: " . $this->conexion->error); } } // Registro histórico con factura/proveedor/precio $user = $this->conexion->real_escape_string($userEntrega); $sql_reg = "INSERT INTO regInventario (CODIGO, DESCRIPCION, CANTIDAD, MOVIMIENTO, userEntrega, fechaIngreso, nfactura, provedor, precio) VALUES ('$codigo', '$descripcion', $cantidad, 'Entrada', '$user', NOW(), '$nfactura', '$provedor', $precio)"; if (!$this->conexion->query($sql_reg)) { throw new Exception("Error en regInventario $codigo: " . $this->conexion->error); } $resumen[] = compact('codigo', 'descripcion', 'cantidad', 'nfactura', 'provedor', 'precio'); } $this->conexion->commit(); return ['ok' => true, 'resumen' => $resumen]; } catch (Exception $e) { $this->conexion->rollback(); return ['ok' => false, 'error' => $e->getMessage()]; } } public function eliminarItemPrincipal($codigo) { $codigo = $this->conexion->real_escape_string($codigo); return $this->conexion->query("DELETE FROM inventario WHERE CODIGO = '$codigo'"); } // ───────────────────────────────────────────────────────────── // INVENTARIO USADO (tabla: inventarioUsado) // ───────────────────────────────────────────────────────────── public function getInventarioUsado() { $result = $this->conexion->query( "SELECT i.CODIGO, i.DESCRIPCION, i.CANTIDAD, e.NOMBRE as nombre_epp FROM inventarioUsado i LEFT JOIN eppsst e ON i.CODIGO = e.CODIGO ORDER BY i.CODIGO" ); $rows = []; while ($row = $result->fetch_assoc()) $rows[] = $row; return $rows; } public function getCantidadActualUsado($codigo) { $codigo = $this->conexion->real_escape_string($codigo); $result = $this->conexion->query( "SELECT CANTIDAD FROM inventarioUsado WHERE CODIGO = '$codigo' LIMIT 1" ); if ($result && $result->num_rows > 0) { return (int)$result->fetch_assoc()['CANTIDAD']; } return 0; } /** * Confirmar ingreso de EPPs al inventario de usados */ public function confirmarIngresoUsado(array $elementos, string $userEntrega): array { $this->conexion->begin_transaction(); try { foreach ($elementos as $elemento) { $codigo = $this->conexion->real_escape_string($elemento['codigo']); $descripcion = $this->conexion->real_escape_string($elemento['descripcion']); $cantidad = intval($elemento['cantidad']); // Verificar existencia en inventarioUsado $consulta = "SELECT CANTIDAD FROM inventarioUsado WHERE CODIGO = '$codigo' LIMIT 1"; $resultado = $this->conexion->query($consulta); if ($resultado && $resultado->num_rows > 0) { $nueva = (int)$resultado->fetch_assoc()['CANTIDAD'] + $cantidad; $sql = "UPDATE inventarioUsado SET CANTIDAD = $nueva WHERE CODIGO = '$codigo'"; if (!$this->conexion->query($sql)) { throw new Exception("Error actualizando $codigo: " . $this->conexion->error); } } else { $sql = "INSERT INTO inventarioUsado (CODIGO, DESCRIPCION, CANTIDAD) VALUES ('$codigo', '$descripcion', $cantidad)"; if (!$this->conexion->query($sql)) { throw new Exception("Error insertando $codigo: " . $this->conexion->error); } } // Registro histórico en regUsado $user = $this->conexion->real_escape_string($userEntrega); $sql_reg = "INSERT INTO regUsado (CODIGO, DESCRIPCION, CANTIDAD, MOVIMIENTO, userEntrega, fechaIngreso) VALUES ('$codigo', '$descripcion', $cantidad, 'Entrada', '$user', NOW())"; if (!$this->conexion->query($sql_reg)) { throw new Exception("Error en regUsado $codigo: " . $this->conexion->error); } } $this->conexion->commit(); return ['ok' => true]; } catch (Exception $e) { $this->conexion->rollback(); return ['ok' => false, 'error' => $e->getMessage()]; } } public function eliminarItemUsado($codigo) { $codigo = $this->conexion->real_escape_string($codigo); return $this->conexion->query("DELETE FROM inventarioUsado WHERE CODIGO = '$codigo'"); } // AJAX — actualizar cantidad inventario principal public function actualizarCantidadPrincipal($codigo, $cantidad) { $codigo = $this->conexion->real_escape_string($codigo); $cantidad = intval($cantidad); $result = $this->conexion->query( "SELECT CANTIDAD FROM inventario WHERE CODIGO = '$codigo' LIMIT 1" ); if ($result && $result->num_rows > 0) { $nueva = (int)$result->fetch_assoc()['CANTIDAD'] + $cantidad; return $this->conexion->query("UPDATE inventario SET CANTIDAD = $nueva WHERE CODIGO = '$codigo'"); } else { $desc = $this->getDescripcionEPP($codigo); return $this->conexion->query( "INSERT INTO inventario (CODIGO, DESCRIPCION, CANTIDAD) VALUES ('$codigo', '$desc', $cantidad)" ); } } // AJAX — actualizar cantidad inventario usado public function actualizarCantidadUsado($codigo, $cantidad) { $codigo = $this->conexion->real_escape_string($codigo); $cantidad = intval($cantidad); $result = $this->conexion->query( "SELECT CANTIDAD FROM inventarioUsado WHERE CODIGO = '$codigo' LIMIT 1" ); if ($result && $result->num_rows > 0) { $nueva = (int)$result->fetch_assoc()['CANTIDAD'] + $cantidad; return $this->conexion->query("UPDATE inventarioUsado SET CANTIDAD = $nueva WHERE CODIGO = '$codigo'"); } else { $desc = $this->getDescripcionEPP($codigo); return $this->conexion->query( "INSERT INTO inventarioUsado (CODIGO, DESCRIPCION, CANTIDAD) VALUES ('$codigo', '$desc', $cantidad)" ); } } private function getDescripcionEPP($codigo) { $codigo = $this->conexion->real_escape_string($codigo); $result = $this->conexion->query("SELECT NOMBRE FROM eppsst WHERE CODIGO = '$codigo' LIMIT 1"); if ($result && $result->num_rows > 0) return $result->fetch_assoc()['NOMBRE']; return ''; } // ═══════════════════════════════════════════════════════════════ // CONSULTAS DE EXISTENCIAS (invenconsul) // Agregado para ExistenciasController // ═══════════════════════════════════════════════════════════════ public function getExistenciasNuevo() { $result = $this->conexion->query( "SELECT ID, CODIGO, DESCRIPCION, CANTIDAD FROM inventario ORDER BY CODIGO" ); $rows = []; while ($row = $result->fetch_assoc()) $rows[] = $row; return $rows; } public function getExcelNuevo() { // ✅ JOIN con regInventario para traer el precio más reciente // Como regInventario puede tener múltiples entradas por código, // usamos una subconsulta para traer solo el precio más reciente $result = $this->conexion->query( "SELECT i.CODIGO, i.DESCRIPCION, i.CANTIDAD, (SELECT r.precio FROM regInventario r WHERE r.CODIGO = i.CODIGO AND r.precio IS NOT NULL AND r.precio > 0 ORDER BY r.fechaIngreso DESC LIMIT 1) AS precio FROM inventario i ORDER BY i.CODIGO" ); $rows = []; while ($row = $result->fetch_assoc()) $rows[] = $row; return $rows; } public function getExcelUsado() { return $this->getExistenciasUsado(); } public function getFiltrosMovimientos() { $areas = []; $usuarios = []; $result = $this->conexion->query( "(SELECT AREA, userEntrega FROM regInventario WHERE AREA IS NOT NULL) UNION (SELECT AREA, userEntrega FROM regUsado WHERE AREA IS NOT NULL)" ); if ($result) { while ($row = $result->fetch_assoc()) { if (!empty($row['AREA']) && !in_array($row['AREA'], $areas)) $areas[] = $row['AREA']; if (!empty($row['userEntrega']) && !in_array($row['userEntrega'], $usuarios)) $usuarios[] = $row['userEntrega']; } } sort($areas); sort($usuarios); return compact('areas', 'usuarios'); } public function getMovimientos(string $tabla, array $filtros, int $limit = 500): array { $tabla = in_array($tabla, ['regInventario', 'regUsado']) ? $tabla : 'regInventario'; $where = $this->buildWhereMovimientos($filtros); $result = $this->conexion->query( "SELECT * FROM $tabla $where ORDER BY fechaIngreso DESC LIMIT $limit" ); $rows = []; if ($result) while ($row = $result->fetch_assoc()) $rows[] = $row; return $rows; } public function getMovimientosExcel(string $tabla, array $filtros): array { return $this->getMovimientos($tabla, $filtros, 99999); } public function getFiltrosFacturas() { $provedores = []; $usuarios = []; $result = $this->conexion->query( "SELECT DISTINCT provedor, userEntrega FROM regInventario WHERE provedor IS NOT NULL AND userEntrega IS NOT NULL AND MOVIMIENTO = 'Entrada'" ); if ($result) { while ($row = $result->fetch_assoc()) { if (!empty($row['provedor']) && !in_array($row['provedor'], $provedores)) $provedores[] = $row['provedor']; if (!empty($row['userEntrega']) && !in_array($row['userEntrega'], $usuarios)) $usuarios[] = $row['userEntrega']; } } sort($provedores); sort($usuarios); return compact('provedores', 'usuarios'); } public function getFacturas(array $filtros, int $limit = 500): array { $where = ["MOVIMIENTO = 'Entrada'"]; $campos = ['CODIGO' => 'CODIGO', 'nfactura' => 'nfactura', 'provedor' => 'provedor', 'userEntrega' => 'userEntrega']; foreach ($campos as $key => $col) { if (!empty($filtros[$key])) { $v = $this->conexion->real_escape_string($filtros[$key]); $where[] = "$col = '$v'"; } } if (!empty($filtros['fecha_inicio'])) { $v = $this->conexion->real_escape_string($filtros['fecha_inicio']); $where[] = "fechaIngreso >= '$v'"; } if (!empty($filtros['fecha_fin'])) { $v = $this->conexion->real_escape_string($filtros['fecha_fin']); $where[] = "fechaIngreso <= '$v 23:59:59'"; } $wc = 'WHERE ' . implode(' AND ', $where); $result = $this->conexion->query( "SELECT * FROM regInventario $wc ORDER BY fechaIngreso DESC LIMIT $limit" ); $rows = []; if ($result) while ($row = $result->fetch_assoc()) $rows[] = $row; return $rows; } private function buildWhereMovimientos(array $filtros): string { $where = []; $map = ['CODIGO' => 'CODIGO', 'MOVIMIENTO' => 'MOVIMIENTO', 'AREA' => 'AREA', 'userEntrega' => 'userEntrega']; foreach ($map as $key => $col) { if (!empty($filtros[$key])) { $v = $this->conexion->real_escape_string($filtros[$key]); $where[] = "$col = '$v'"; } } if (!empty($filtros['fecha_inicio'])) { $v = $this->conexion->real_escape_string($filtros['fecha_inicio']); $where[] = "fechaIngreso >= '$v'"; } if (!empty($filtros['fecha_fin'])) { $v = $this->conexion->real_escape_string($filtros['fecha_fin']); $where[] = "fechaIngreso <= '$v 23:59:59'"; } return !empty($where) ? 'WHERE ' . implode(' AND ', $where) : ''; } } ?>