File "InventarioModel.php"

Full Path: C:/wamp64/www/AVIDOTAPP/models/InventarioModel.php
File size: 17.12 KB
MIME-type: text/x-php
Charset: utf-8

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