<?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) : '';
}
}
?>