<?php

namespace Core\Librerias;

use App\Controladores\TarifasControlador;
use App\Modelos\AlmacenUbicacion;
use App\Modelos\CarritoVentasModel;
use App\Modelos\MovimientoModel;
use App\Modelos\ProductoUbicacion;
use App\Modelos\Proveedor;
use Core\Helpers\Moneda;
use Core\Helpers\Notifica;

final class CarritoComprasEditar
{
    private $carrito = [];
    private $array_errors = [];
    private $divisa_master;
    private $carritoModel;

    public function __construct()
    {
        $this->carritoModel = new CarritoVentasModel();
        $this->divisa_master = Moneda::Predeterminada();
    }

    public function obtenerDivisaFacturar(): array
    {
        return $this->carritoModel->obtenerDivisaFacturar();
    }

    public function obtenerDivisasParaFacturar(): array
    {
        $data_divisa = $this->carritoModel->obtenerDivisaEmpleado($_SESSION['user_data']['emp_id']);

        if ($data_divisa) {
            $divisas = $data_divisa;
        } else {
            $divisas = $this->carritoModel->obtenerDivisas();
        }

        return $divisas;
    }

    public function obtenerAlmacen(int $id_almacen)
    {
        return $this->carritoModel->obtenerAlmacen($id_almacen);
    }

    public function chuequearStock(int $id_producto, int $id_almacen)
    {
        return $this->carritoModel->chuequearStock($id_producto, $id_almacen);
    }

    public function obtenerProducto(int $id_producto)
    {
        return $this->carritoModel->obtenerProducto($id_producto);
    }

    public function obtenerDivisa(int $id_divisa)
    {
        return $this->carritoModel->obtenerDivisa($id_divisa);
    }

    public function obtenerSerie(int $id_serie)
    {
        return $this->carritoModel->obtenerSerie($id_serie);
    }

    public function obtenerCliente(int $id_cliente)
    {
        return $this->carritoModel->obtenerCliente($id_cliente);
    }

    public function obtenerEmpleados()
    {
        return $this->carritoModel->obtenerEmpleados();
    }

    public function obtenerEmpleado(int $id_empleado)
    {
        return $this->carritoModel->obtenerEmpleado($id_empleado);
    }

    public function obtenerDatosEmpresa()
    {
        return $this->carritoModel->obtenerDatosEmpresa();
    }

    public function obternerTiposDeDocumentos()
    {
        return $this->carritoModel->obternerTiposDeDocumentos();
    }

    public function obtenerImpuestos()
    {
        return $this->carritoModel->obtenerImpuestos();
    }

    public function obtenerPaises()
    {
        return $this->carritoModel->obtenerPaises();
    }

    public function obtenerAlmacenesEmpleado()
    {
        return $this->carritoModel->obtenerAlmacenesEmpleado();
    }

    public function obtenerSeriesEmpleado()
    {
        return $this->carritoModel->obtenerSeriesEmpleado();
    }

    public function chuequearCorrelativo(int $id_serie, int $id_documento)
    {
        return $this->carritoModel->chuequearCorrelativo($id_serie, $id_documento);
    }

    public function actualizarCorrelativo(int $id_serie, int $id_documento, int $correlativo)
    {
        return $this->carritoModel->actualizarCorrelativo($id_serie, $id_documento, $correlativo);
    }

    public function obtenerFactura(string $tabla_db, string $_nombre_carrito_, int $id_factura)
    {
        $this->carrito  = null;
        $array_abonos   = [];
        //$list_creditos  = [];
        $_SESSION["$_nombre_carrito_$id_factura"] = [];

        if ($tabla_db == 'app_compras') {
            $factura        = $this->carritoModel->obtenerFacCompra($id_factura);
            $articulos      = $this->carritoModel->obtenerFacArticulosCompra($id_factura);
            $abonos         = $this->carritoModel->abonosFacCompra($id_factura);
            $total_pagos    = $this->carritoModel->totalPagos($id_factura, 8,2);
            //$creditos       = $this->carritoModel->obtenerCreditos($id_factura, 2);
            $total_pagos    = $total_pagos['total'] ? $total_pagos['total'] : 0.00;
        } else if ($tabla_db == 'app_compras_notas') {
            $factura        = $this->carritoModel->obtenerNeCompra($id_factura);
            $articulos      = $this->carritoModel->obtenerNeArticulosCompra($id_factura);
            $abonos         = $this->carritoModel->abonosNeCompra($id_factura);
            $total_pagos    = $this->carritoModel->totalPagos($id_factura, 9,2);
            //$creditos       = $this->carritoModel->obtenerCreditos($id_factura, 1);
            $total_pagos    = $total_pagos['total'] ? $total_pagos['total'] : 0.00;
        }else if ($tabla_db == 'app_cmppedidos') {
            $factura        = $this->carritoModel->obtenerPeCompra($id_factura);
            $articulos      = $this->carritoModel->obtenerPeArticulosCompra($id_factura);
            $abonos         = [];
            $creditos       = [];
            $total_pagos    = 0.00;
        }

        /*
        $documento_credito = $this->carritoModel->obtenerDocumento(7);

        if (is_countable($creditos) && count($creditos)) {
            foreach ($creditos as $row) {
                $list_creditos[] = [
                    'id' => $row['cre_id'],
                    'fecha' => date('d-m-Y h:i A', strtotime($row['cre_fecha'])),
                    'estatus' => $row['cre_estatus'] ? true : false,
                    'correlativo' => $documento_credito['doc_prefijo'] . '' . $row['cre_correlativo'],
                    'monto' => Moneda::moneda($row['cre_monto'], $this->divisa_master['locale'], $this->divisa_master['symbol']),
                    'observaciones' => $row['cre_descripcion'] . ' ' . $row['cre_observacion']
                ];
            }
        }*/

        $divisa = $this->carritoModel->obtenerDivisa($factura['id_divisa']);

        if (is_countable($articulos) && count($articulos)) {
            foreach ($articulos as $row) {
                $articulo = [
                    'id'            => $row['id_producto'],
                    'codigo'        => $row['codigo'],
                    'nombre'        => $row['nombre'],
                    'costo'         => $row['precio'],
                    'id_iva'        => $row['id_iva'],
                    'iva'           => $row['iva'],
                    'iva_total'     => $row['iva_total'],
                    'descuento'     => $row['descuento'],
                    'cantidad'      => $row['cantidad'],
                    'neto'          => $row['neto'],
                    'total'         => $row['total'],
                    'id_almacen'    => $row['alm_id']
                ];
                $articulo['unique'] = md5($articulo['id']);
                $_SESSION["$_nombre_carrito_$id_factura"][$articulo['unique']] = $articulo;
            }
        }

        $this->carrito_c = $_SESSION["$_nombre_carrito_$id_factura"];

        $_SESSION["$_nombre_carrito_$id_factura"]['divisa'] = $factura['id_divisa'];
        $_SESSION["$_nombre_carrito_$id_factura"]['id_almacen'] = $factura['id_almacen'];

        $div_format = Moneda::obtenerDivisa($_SESSION["$_nombre_carrito_$id_factura"]['divisa']);

        if ($this->carrito_c !== []) {
            foreach ($this->carrito_c as $row) {
                $this->carrito_c[$row['unique']]['costo'] = number_format($row['costo'], $div_format['precision'], $div_format['decimal'], $div_format['thousands']);
                $this->carrito_c[$row['unique']]['iva'] = number_format($row['iva'], $div_format['precision'], $div_format['decimal'], $div_format['thousands']);
                $this->carrito_c[$row['unique']]['iva_total'] = number_format($row['iva_total'], $div_format['precision'], $div_format['decimal'], $div_format['thousands']);
                $this->carrito_c[$row['unique']]['neto'] = number_format($row['neto'], $div_format['precision'], $div_format['decimal'], $div_format['thousands']);
                $this->carrito_c[$row['unique']]['total'] = number_format($row['total'], $div_format['precision'], $div_format['decimal'], $div_format['thousands']);
            }
        }

        if (is_countable($abonos) && count($abonos)) {

            foreach ($abonos as $row) {

                if (is_null($row['fab_divisa'])) {
                    $divisa_mov = $this->divisa_master;
                } else {
                    $divisa_mov = Moneda::obtenerDivisa($row['fab_divisa']);
                }

                if (is_null($row['fab_divid_conversion'])) {
                    $divisa_conv_mov = $this->divisa_master;
                } else {
                    $divisa_conv_mov = Moneda::obtenerDivisa($row['fab_divid_conversion']);
                }

                if (is_null($row['fab_factor'])) {
                    $row['fab_factor'] = 1;
                }

                $array_abonos[] = [
                    'fab_id'            => $row['fab_id'],
                    'fab_fecha'         => $row['fecha'],
                    'bc_alias'          => $row['bc_alias'],
                    'bc_tipo'           => $row['bc_tipo'],
                    'fab_retiro'        => $row['fab_retiro'],
                    'credito'           => $row['fab_credito'],
                    'mp_nombre'         => $row['mp_nombre'],
                    'referencia'        => $row['fab_descripcion'],
                    'fab_monto'         => Moneda::moneda($row['fab_monto'], $divisa_mov['locale'], $divisa_mov['symbol']),
                    'fab_factor'        => ($row['fab_factor'] < 1) ? $row['fab_factor'] : Moneda::decimal($row['fab_factor'], $div_format['locale']),
                    'fab_conversion'    => Moneda::moneda($row['fab_conversion'], $div_format['locale'], $div_format['symbol'])
                ];
            }
        }

        $data = [
            //'creditos'              => $list_creditos,
            'divisa'                => $div_format,
            'id_divisa'             => $factura['id_divisa'],
            'factura'               => $factura,
            'observaciones'         => $factura['observaciones'] ?? '',
            'articulos_cantidad'    => $factura['art_total'],
            'subtotal'              => round($factura['subtotal'], 2),
            'descuento'             => round($factura['descuento'], 2),
            'neto'                  => round($factura['neto'], 2),
            'iva'                   => round($factura['iva'], 2),
            'total'                 => round($factura['total'], 2),
            'total_pagado'          => round($total_pagos, 2),
            'restante'              => round($factura['total'] +  $total_pagos, 2),
            'data_carrito'          => $this->carrito_c,
            'abonos'                => $array_abonos,
            'factor'                => 1,
            'div_nombre'            => $divisa['div_nombre'],
            'div_locale'            => $divisa['div_locale'],
            'div_simbolo'           => $divisa['div_simbolo'],
            'div_decimal'           => $divisa['div_decimal'],
        ];

        $_SESSION["$_nombre_carrito_$id_factura"]['divisa']             = $factura['id_divisa'];
        $_SESSION["$_nombre_carrito_$id_factura"]['subtotal']           = $factura['subtotal'];
        $_SESSION["$_nombre_carrito_$id_factura"]['descuento']          = $factura['descuento'];
        $_SESSION["$_nombre_carrito_$id_factura"]['neto']               = $factura['neto'];
        $_SESSION["$_nombre_carrito_$id_factura"]['iva']                = $factura['iva'];
        $_SESSION["$_nombre_carrito_$id_factura"]['total']              = $factura['total'];
        $_SESSION["$_nombre_carrito_$id_factura"]['articulos_cantidad'] = $factura['art_total'];

        return $data;
    }

    public function contenidoCarrito(string $_nombre_carrito_, int $id_factura)
    {
        $this->carrito = [];
        $this->carrito = $_SESSION["$_nombre_carrito_$id_factura"];
        unset($this->carrito['articulos_cantidad']);
        unset($this->carrito['subtotal']);
        unset($this->carrito['descuento']);
        unset($this->carrito['neto']);
        unset($this->carrito['iva']);
        unset($this->carrito['total']);
        unset($this->carrito['divisa']);
        unset($this->carrito['id_almacen']);
        return $this->carrito;
    }

    public function predeterminarDivisa(string $_nombre_carrito_, int $id_factura, $id_cliente, int $id_divisa, string $descuento_global)
    {
        $divisa = Moneda::obtenerDivisa($id_divisa);

        if ($divisa) {
            if ($divisa['id'] !== $this->divisa_master['id']) {
                $div_master = $_SESSION["$_nombre_carrito_$id_factura"]['divisa'] ?? $this->divisa_master['id'];
                if (!$this->carritoModel->obtenerDivisaAlCambio($div_master, $divisa['id'])) {
                    $this->array_errors[] = 'Lo siento no se encuentra algun valor establecido para la conversión con la moneda predetermminada';
                }
            }
        } else {
            $this->array_errors[] = 'Divisa predeterminada no establecisa o divisa no enontrada';
        }

        if (empty($this->array_errors)) {

            if (!is_null($_SESSION["$_nombre_carrito_$id_factura"])) {

                $descuento_global = convertir_a_float($descuento_global);
                $contenido_carrito = $this->contenidoCarrito($_nombre_carrito_, $id_factura);

                foreach ($contenido_carrito as $row) {
                    $precio = $this->obtenerPrecioSegunDivisa($_SESSION["$_nombre_carrito_$id_factura"][$row['unique']]['costo'], $_SESSION["$_nombre_carrito_$id_factura"]['divisa'], $id_divisa);
                    $_SESSION["$_nombre_carrito_$id_factura"][$row['unique']]['costo'] = $precio['precio'];
                    $pc = $_SESSION["$_nombre_carrito_$id_factura"][$row['unique']]['cantidad'] * $_SESSION["$_nombre_carrito_$id_factura"][$row['unique']]['costo'];
                    $precio = $this->obtenerDescuentoMasIvaProducto($pc, $row['iva'], 'pvp', $_SESSION["$_nombre_carrito_$id_factura"][$row['unique']]['descuento']);
                    $_SESSION["$_nombre_carrito_$id_factura"][$row['unique']]['iva_total']      = $precio['iva'];
                    $_SESSION["$_nombre_carrito_$id_factura"][$row['unique']]['neto']           = $precio['neto'];
                    $_SESSION["$_nombre_carrito_$id_factura"][$row['unique']]['total']          = $precio['total'];
                }

                $_SESSION["$_nombre_carrito_$id_factura"]['divisa'] = $id_divisa;

                return [
                    'divisa' => $divisa,
                    'data_carrito' => $this->obtenerCarritoCliente($_nombre_carrito_, $id_factura, $id_cliente, $descuento_global)
                ];
            } else {
                return true;
            }
        }

        return ['errors' => $this->array_errors];
    }

    public function buscarProducto(string $producto, int $id_divisa, int $id_almacen)
    {
        $divisa = Moneda::obtenerDivisa($id_divisa);

        if ($divisa) {
            if ($divisa['id'] !== $this->divisa_master['id']) {
                $divisa_factor = $this->carritoModel->obtenerDivisaAlCambio($this->divisa_master['id'], $divisa['id']);
                if (!$divisa_factor) {
                    $this->array_errors[] = 'Lo siento no se encuentra algun valor establecido para la conversión con la moneda predetermminada.';
                } else {
                    $factor = $divisa_factor['df_factor'];
                }
            } else {
                $factor = 1;
            }
        } else {
            $this->array_errors[] = 'Divisa predeterminada no establecisa o divisa no encontrada';
        }

        if (empty($this->array_errors)) {

            $array_productos = [];

            if (strlen($producto) > 0) {

                $productos = $this->carritoModel->buscarProductosCompras($producto);

                if (is_countable($productos) && count($productos)) {
                    foreach ($productos as $row) {
                        $imagen = null;
                        if (($row['pi_imagen'] != null || $row['pi_imagen'] != '') && file_exists(constant('UPLOADS_URI') . 'productos/' . $row['pi_imagen'])) {
                            $imagen = constant('IMG_URI') . 'productos/' . $row['pi_imagen'];
                        }
                        $array_productos[] = [
                            'pro_id'            => $row['pro_id'],
                            'pro_descripcion'   => "({$row['pro_codigo']}) {$row['pro_descripcion']}",
                            'pro_costo'         => Moneda::moneda(($row['pro_costo'] * $factor), $divisa['locale'], $divisa['symbol']),
                            'ps_cantidad'       => $row['ps_cantidad'] ?? 0,
                            'id_almacen'        => $id_almacen,
                            'fabricante'        => $row['fa_nombre'],
                            'imagen'            => $imagen
                        ];
                    }
                }
            }

            return $array_productos;
        }

        return ['errors' => $this->array_errors];
    }

    public function actualizarPrecioTotalYCantidad(string $_nombre_carrito_, int $id_factura, int $id_cliente, $descuento = null)
    {
        $this->carrito = $_SESSION["$_nombre_carrito_$id_factura"];
        unset($this->carrito['articulos_cantidad']);
        unset($this->carrito['subtotal']);
        unset($this->carrito['descuento']);
        unset($this->carrito['neto']);
        unset($this->carrito['iva']);
        unset($this->carrito['total']);
        unset($this->carrito['divisa']);
        unset($this->carrito['id_almacen']);

        $subtotal = $total_iva = $neto = $total = $articulos_cantidad = 0;

        if ($descuento > 0) {
            foreach ($this->carrito as $row) {
                $articulos_cantidad += 1;
                $subtotal += $row['neto'];
                $precio = $this->obtenerDescuentoMasIvaProducto($row['neto'], $row['iva'], 'pvp', $descuento, 0);
                $neto += $precio['neto'];
                $total_iva += $precio['iva'];
                $total += $precio['total'];
            }
        } else {
            foreach ($this->carrito as $row) {
                $articulos_cantidad += 1;
                $neto += $row['neto'];
                $total_iva += $row['iva_total'];
                $total += $row['total'];
            }
            $subtotal = $neto;
        }

        $_SESSION["$_nombre_carrito_$id_factura"]['articulos_cantidad']   = $articulos_cantidad;
        $_SESSION["$_nombre_carrito_$id_factura"]['subtotal']             = $subtotal;
        $_SESSION["$_nombre_carrito_$id_factura"]['descuento']            = $descuento;
        $_SESSION["$_nombre_carrito_$id_factura"]['neto']                 = $neto;
        $_SESSION["$_nombre_carrito_$id_factura"]['iva']                  = $total_iva;
        $_SESSION["$_nombre_carrito_$id_factura"]['total']                = $neto + $total_iva;
    }

    public function obtenerCarritoCliente(string $_nombre_carrito_, int $id_factura, int $id_cliente, $descuento = null)
    {
        $this->actualizarPrecioTotalYCantidad($_nombre_carrito_, $id_factura, $id_cliente, $descuento);

        $div_format = Moneda::obtenerDivisa($_SESSION["$_nombre_carrito_$id_factura"]['divisa']);

        $carrito_c = [];
        $carrito_c = $_SESSION["$_nombre_carrito_$id_factura"];
        unset($carrito_c['articulos_cantidad']);
        unset($carrito_c['subtotal']);
        unset($carrito_c['descuento']);
        unset($carrito_c['neto']);
        unset($carrito_c['iva']);
        unset($carrito_c['total']);
        unset($carrito_c['divisa']);
        unset($carrito_c['id_almacen']);

        foreach ($carrito_c as $row) {
            $carrito_c[$row['unique']]['costo'] = number_format($row['costo'], $div_format['precision'], $div_format['decimal'], $div_format['thousands']);
            $carrito_c[$row['unique']]['iva'] = number_format($row['iva'], $div_format['precision'], $div_format['decimal'], $div_format['thousands']);
            $carrito_c[$row['unique']]['iva_total'] = number_format($row['iva_total'], $div_format['precision'], $div_format['decimal'], $div_format['thousands']);
            $carrito_c[$row['unique']]['neto'] = number_format($row['neto'], $div_format['precision'], $div_format['decimal'], $div_format['thousands']);
            $carrito_c[$row['unique']]['total'] = number_format($row['total'], $div_format['precision'], $div_format['decimal'], $div_format['thousands']);
        }

        return [
            'articulos_cantidad'    => round($_SESSION["$_nombre_carrito_$id_factura"]['articulos_cantidad'] ?? 0, 2),
            'subtotal'              => number_format($_SESSION["$_nombre_carrito_$id_factura"]['subtotal'] ?? 0, $div_format['precision'], $div_format['decimal'], $div_format['thousands']),
            'descuento'             => round($_SESSION["$_nombre_carrito_$id_factura"]['descuento'] ?? 0, 2),
            'neto'                  => number_format($_SESSION["$_nombre_carrito_$id_factura"]['neto'] ?? 0, $div_format['precision'], $div_format['decimal'], $div_format['thousands']),
            'iva'                   => number_format($_SESSION["$_nombre_carrito_$id_factura"]['iva'] ?? 0, $div_format['precision'], $div_format['decimal'], $div_format['thousands']),
            'total'                 => number_format($_SESSION["$_nombre_carrito_$id_factura"]['total'] ?? 0, $div_format['precision'], $div_format['decimal'], $div_format['thousands']),
            'carrito'               => $carrito_c
        ];
    }

    private function obtenerDescuentoMasIvaProducto(float $precio, float $iva, string $tipo_tarifa, float $tarifa)
    {
        $ivam = $precio * ($iva / 100);
        
        if ($tarifa > 0) {
            $precio = TarifasControlador::aplicar(null, $precio, $tipo_tarifa, $tarifa, 0,$ivam); //DESCUENTO PRODUCTO
        }

        $ivam = $precio * ($iva / 100);

        return [
            'iva' => $ivam,
            'neto' => $precio,
            'total' => $precio + $ivam,
        ];
    }

    public function obtenerPrecioSegunDivisa(float $precio, int $id_divisa_master, int $id_divisa_buscada)
    {
        $divisa_factor = $this->carritoModel->obtenerDivisaAlCambio($id_divisa_master, $id_divisa_buscada);

        if ($divisa_factor) {
            $precio *= $divisa_factor['df_factor'];
            $factor = $divisa_factor['df_factor'];
        } else {
            $precio = $precio;
            $factor = 1;
        }

        return [
            'precio' => $precio,
            'factor' => $factor
        ];
    }

    public function agregarProductoBarcode(string $_nombre_carrito_, int $id_cliente, string $producto, int $id_almacen, int $id_divisa, string $descuento_global, bool $chequear_stock = true)
    {
        $producto = $this->carritoModel->buscarProductoBarcode($id_almacen, $producto);
        $divisa   = Moneda::obtenerDivisa($id_divisa);

        $imp_data = $this->carritoModel->obtenerImpuesto(2);

        if (!$producto || !$divisa)
            $this->array_errors[] = 'Producto o Divisa no disponibles';

        if ($_SESSION["$_nombre_carrito_$id_cliente"] != null) {
            if ($_SESSION["$_nombre_carrito_$id_cliente"]['id_almacen'] != $id_almacen)
                $this->array_errors[] = 'No puede seleccionar otro almacén diferente';
            if ($_SESSION["$_nombre_carrito_$id_cliente"]['divisa'] != $id_divisa)
                $this->array_errors[] = 'No puede seleccionar otra divisa diferente';
        }

        if ($divisa['id'] !== $this->divisa_master['id']) {
            $divisa_factor = $this->carritoModel->obtenerDivisaAlCambio($this->divisa_master['id'], $divisa['id']);
            if (!$divisa_factor)
                $this->array_errors[] = 'Lo siento no se encuentra el valor establecido para la conversión con la moneda predeterminada.';
        }

        if (empty($this->array_errors)) {

            $descuento_global = convertir_a_float($descuento_global);
            $unique = md5($producto['pro_id']);

            if (isset($_SESSION["$_nombre_carrito_$id_cliente"][$unique])) {
                $id_divisa_master   = $_SESSION["$_nombre_carrito_$id_cliente"]['divisa'];
                $costo              = $_SESSION["$_nombre_carrito_$id_cliente"][$unique]['costo'];
                $id_iva             = $_SESSION["$_nombre_carrito_$id_cliente"][$unique]['id_iva'];
                $iva                = $_SESSION["$_nombre_carrito_$id_cliente"][$unique]['iva'];
                $nombre             = $_SESSION["$_nombre_carrito_$id_cliente"][$unique]['nombre'];
            } else {
                $id_divisa_master   = $this->divisa_master['id'];
                $costo             = $producto['pro_costo'];
                $id_iva             = $imp_data['imp_id'];
                $iva                = $imp_data['imp_valor'];
                $nombre             = $producto['pro_descripcion'];
            }

            $costo = $this->obtenerPrecioSegunDivisa($costo, $id_divisa_master, $divisa['id']);

            $articulo = [
                'id'                => $producto['pro_id'],
                'codigo'            => $producto['pro_codigo'],
                'nombre'            => $nombre,
                'costo'             => $costo['precio'],
                'id_iva'            => $id_iva,
                'iva'               => $iva,
                'id_almacen'        => $id_almacen,
                'descuento'         => 0.00,
                'cantidad'          => 1.00,
            ];

            $articulo['unique'] = $unique;

            $contenido_carrito = $this->contenidoCarrito($_nombre_carrito_, $id_cliente);

            if (!empty($contenido_carrito)) {
                foreach ($contenido_carrito as $row) {
                    if ($row['id'] === $articulo['id']) {
                        $articulo['cantidad'] += $row['cantidad'];
                    }
                }
            }

            $precio = $this->obtenerDescuentoMasIvaProducto(($articulo['cantidad'] * $articulo['costo']), $articulo['iva'], 'pvp', 0);

            $articulo['iva_total']  = $precio['iva'];
            $articulo['neto']       = $precio['neto'];
            $articulo['total']      = $precio['total'];

            $_SESSION["$_nombre_carrito_$id_cliente"][$unique] = $articulo;
            $_SESSION["$_nombre_carrito_$id_cliente"]['divisa'] = $id_divisa;
            $_SESSION["$_nombre_carrito_$id_cliente"]['id_almacen'] = $id_almacen;

            return $this->obtenerCarritoCliente($_nombre_carrito_, $id_cliente, $descuento_global);
        }

        return ['errors' => $this->array_errors];
    }

    public function agregarProducto(string $_nombre_carrito_, int $id_factura, int $id_cliente, int $id_producto, int $id_almacen, int $id_divisa, string $descuento_global)
    {
        $producto = $this->carritoModel->obtenerProducto($id_producto);
        $divisa   = Moneda::obtenerDivisa($id_divisa);

        if (!$producto || !$divisa)
            $this->array_errors[] = 'Producto o Divisa no disponibles';

        if ($_SESSION["$_nombre_carrito_$id_factura"] != null) {
            if ($_SESSION["$_nombre_carrito_$id_factura"]['id_almacen'] != $id_almacen)
                $this->array_errors[] = 'No puede seleccionar otro almacen diferente';
            if ($_SESSION["$_nombre_carrito_$id_factura"]['divisa'] != $id_divisa)
                $this->array_errors[] = 'No puede seleccionar otra divisa diferente';
        }

        if ($divisa['id'] !== $this->divisa_master['id']) {
            $divisa_factor = $this->carritoModel->obtenerDivisaAlCambio($this->divisa_master['id'], $divisa['id']);
            if (!$divisa_factor)
                $this->array_errors[] = 'Lo siento no se encuentra el valor establecido para la conversión con la moneda predeterminada.';
        }

        if (empty($this->array_errors)) {

            $imp_data = $this->carritoModel->obtenerImpuesto(2);
            $descuento_global = convertir_a_float($descuento_global);
            $unique = md5($producto['pro_id']);

            if (isset($_SESSION["$_nombre_carrito_$id_factura"][$unique])) {
                $id_divisa_master   = $_SESSION["$_nombre_carrito_$id_factura"]['divisa'];
                $costo              = $_SESSION["$_nombre_carrito_$id_factura"][$unique]['costo'];
                $id_iva             = $_SESSION["$_nombre_carrito_$id_factura"][$unique]['id_iva'];
                $iva                = $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva'];
                $nombre             = $_SESSION["$_nombre_carrito_$id_factura"][$unique]['nombre'];
            } else {
                $id_divisa_master   = $this->divisa_master['id'];
                $costo              = $producto['pro_costo'];
                $id_iva             = $imp_data['imp_id'];
                $iva                = $imp_data['imp_valor'];
                $nombre             = $producto['pro_descripcion'];
            }

            $costo = $this->obtenerPrecioSegunDivisa($costo, $id_divisa_master, $divisa['id']);

            $articulo = [
                'id'            => $producto['pro_id'],
                'codigo'        => $producto['pro_codigo'],
                'nombre'        => $nombre,
                'costo'         => $costo['precio'],
                'id_iva'        => $id_iva,
                'iva'           => $iva,
                'id_almacen'    => $id_almacen,
                'descuento'     => 0.00,
                'cantidad'      => 1.00,
            ];

            $articulo['unique'] = $unique;

            $contenido_carrito = $this->contenidoCarrito($_nombre_carrito_, $id_factura);

            if (!empty($contenido_carrito)) {
                foreach ($contenido_carrito as $row) {
                    if ($row['id'] === $articulo['id']) {
                        $articulo['cantidad'] += $row['cantidad'];
                    }
                }
            }

            $precio = $this->obtenerDescuentoMasIvaProducto(($articulo['cantidad'] * $articulo['costo']), $articulo['iva'], 'pvp', 0);

            $articulo['iva_total']  = $precio['iva'];
            $articulo['neto']       = $precio['neto'];
            $articulo['total']      = $precio['total'];

            $_SESSION["$_nombre_carrito_$id_factura"][$unique] = $articulo;
            $_SESSION["$_nombre_carrito_$id_factura"]['divisa'] = $id_divisa;
            $_SESSION["$_nombre_carrito_$id_factura"]['id_almacen'] = $id_almacen;

            return $this->obtenerCarritoCliente($_nombre_carrito_, $id_factura, $id_cliente, $descuento_global);
        }

        return ['errors' => $this->array_errors];
    }

    public function actualizarPrecio(string $_nombre_carrito_, int $id_factura, int $id_cliente, string $unique, string $precio, string $descuento_global)
    {
        if (!isset($_SESSION["$_nombre_carrito_$id_factura"][$unique])) {
            $this->array_errors[] = 'Acción prohibida';
        } else {
            $precio = convertir_a_float($precio);
            $descuento_global = convertir_a_float($descuento_global);
            $_SESSION["$_nombre_carrito_$id_factura"][$unique]['costo'] = $precio;
            $pc = $_SESSION["$_nombre_carrito_$id_factura"][$unique]['cantidad'] * $precio;
            $precio = $this->obtenerDescuentoMasIvaProducto($pc, $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva'], 'pvp', $_SESSION["$_nombre_carrito_$id_factura"][$unique]['descuento']);
            $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva_total']   = $precio['iva'];
            $_SESSION["$_nombre_carrito_$id_factura"][$unique]['neto']        = $precio['neto'];
            $_SESSION["$_nombre_carrito_$id_factura"][$unique]['total']       = $precio['total'];
            return $this->obtenerCarritoCliente($_nombre_carrito_, $id_factura, $id_cliente, $descuento_global);
        }
    }

    public function actualizarCantidad(string $_nombre_carrito_, string $tabla_db = '', int $id_factura, int $id_cliente, int $id_producto, float $cantidad, string $descuento_global, bool $chequear_stock = true)
    {
        $producto = $this->carritoModel->obtenerProducto($id_producto);

        if (!$producto)
            $this->array_errors[] = 'Producto no disponible';

        if (empty($this->array_errors)) {

            $unique = md5($id_producto);
            $cantidad = round($cantidad, constant('EMP_CANTIDAD'));

            if (!isset($_SESSION["$_nombre_carrito_$id_factura"][$unique])) {
                $this->array_errors[] = 'Producto no disponible';
            } else {
                $descuento_global = convertir_a_float($descuento_global);
                $pc = $cantidad * $_SESSION["$_nombre_carrito_$id_factura"][$unique]['costo'];
                $precio = $this->obtenerDescuentoMasIvaProducto($pc, $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva'], 'pvp', $_SESSION["$_nombre_carrito_$id_factura"][$unique]['descuento']);
                $_SESSION["$_nombre_carrito_$id_factura"][$unique]['cantidad']    = $cantidad;
                $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva_total']   = $precio['iva'];
                $_SESSION["$_nombre_carrito_$id_factura"][$unique]['neto']        = $precio['neto'];
                $_SESSION["$_nombre_carrito_$id_factura"][$unique]['total']       = $precio['total'];
                return $this->obtenerCarritoCliente($_nombre_carrito_, $id_factura, $id_cliente, $descuento_global);
            }
        }

        return ['errors' => $this->array_errors];
    }

    public function actualizarDescripcion(string $_nombre_carrito_, int $id_factura, string $unique, string $descripcion)
    {
        if (!isset($_SESSION["$_nombre_carrito_$id_factura"][$unique])) {
            $this->array_errors[] = 'Producto no disponible';
        } else {
            $_SESSION["$_nombre_carrito_$id_factura"][$unique]['nombre'] = $descripcion;
            return true;
        }

        return ['errors' => $this->array_errors];
    }

    public function aplicarNuevoIva(string $_nombre_carrito_, int $id_factura, $id_cliente, string $unique, int $id_iva, string $descuento_global)
    {
        $iva = $this->carritoModel->obtenerImpuesto($id_iva);

        if (!$iva) {
            $this->array_errors[] = 'IVA no disponible';
        } else {
            if (!isset($_SESSION["$_nombre_carrito_$id_factura"][$unique])) {
                $this->array_errors[] = 'Producto no disponible';
            } else {

                $descuento_global = convertir_a_float($descuento_global);

                $_SESSION["$_nombre_carrito_$id_factura"][$unique]['id_iva'] = $iva['imp_id'];
                $iva_total = $_SESSION["$_nombre_carrito_$id_factura"][$unique]['neto'] * ($iva['imp_valor'] / 100);

                if ($iva['imp_valor'] > 0) {
                    $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva']         = $iva['imp_valor'];
                    $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva_total']   = $iva_total;
                    $_SESSION["$_nombre_carrito_$id_factura"][$unique]['total']       = $_SESSION["$_nombre_carrito_$id_factura"][$unique]['neto'] + $iva_total;
                } else {
                    $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva']         = 0.00;
                    $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva_total']   = 0.00;
                    $_SESSION["$_nombre_carrito_$id_factura"][$unique]['total']       = $_SESSION["$_nombre_carrito_$id_factura"][$unique]['neto'];
                }

                return $this->obtenerCarritoCliente($_nombre_carrito_, $id_factura, $id_cliente, $descuento_global);
            }
        }

        return ['errors' => $this->array_errors];
    }

    public function aplicarDescuentoProducto(string $_nombre_carrito_, int $id_factura, int $id_cliente, string $unique, string $descuento, string $descuento_global)
    {
        if (!isset($_SESSION["$_nombre_carrito_$id_factura"][$unique])) {
            $this->array_errors[] = 'Producto no disponible';
        } else {
            $descuento = convertir_a_float($descuento);
            $descuento_global = convertir_a_float($descuento_global);
            $_SESSION["$_nombre_carrito_$id_factura"][$unique]['descuento'] = $descuento;
            $precio_total = $_SESSION["$_nombre_carrito_$id_factura"][$unique]['cantidad'] * $_SESSION["$_nombre_carrito_$id_factura"][$unique]['costo'];
            $precio = $this->obtenerDescuentoMasIvaProducto($precio_total, $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva'], 'pvp', $descuento);
            $_SESSION["$_nombre_carrito_$id_factura"][$unique]['iva_total']   = $precio['iva'];
            $_SESSION["$_nombre_carrito_$id_factura"][$unique]['neto']        = $precio['neto'];
            $_SESSION["$_nombre_carrito_$id_factura"][$unique]['total']       = $precio['total'];
            return $this->obtenerCarritoCliente($_nombre_carrito_, $id_factura, $id_cliente, $descuento_global);
        }

        return ['errors' => $this->array_errors];
    }

    public function aplicarDescuentoAdicional(string $_nombre_carrito_, int $id_factura, int $id_cliente, string $descuento_global)
    {
        $descuento = convertir_a_float($descuento_global);
        return $this->obtenerCarritoCliente($_nombre_carrito_, $id_factura, $id_cliente, $descuento);
    }

    public function eliminarProducto(string $_nombre_carrito_, string $tabla_db, int $id_factura, int $id_cliente, string $unique, string $descuento_global)
    {
        if (!isset($_SESSION["$_nombre_carrito_$id_factura"][$unique])) {
            $this->array_errors[] = 'Producto no disponible';
        } else {

            $descuento_global = convertir_a_float($descuento_global);
            $almacen = $this->carritoModel->obtenerAlmacen($_SESSION["$_nombre_carrito_$id_factura"][$unique]['id_almacen']);
            $cantidad_en_stock = $this->carritoModel->verificarProductoEnStock($_SESSION["$_nombre_carrito_$id_factura"][$unique]['id'], $almacen['alm_id']);
            $habia = $cantidad_en_stock['ps_cantidad'] ?? 0;

            if ($tabla_db == 'app_compras_notas') {
                $det_prod = $this->carritoModel->obtenerProductoNeCompra($id_factura, $_SESSION["$_nombre_carrito_$id_factura"][$unique]['id']);
                if ($det_prod) {
                    if ($det_prod['agregado'] > 0) {
                        try {
                            $this->carritoModel->transactionBegin();
                            $this->carritoModel->descontardeStock($det_prod['pro_id'], $almacen['alm_id'], $det_prod['agregado']);
                            $this->carritoModel->eliminarProductoNeCompra($id_factura, $det_prod['pro_id'], $det_prod['agregado']);
                            $this->carritoModel->transactionCommit();
                        } catch (\Throwable $th) {
                            $this->carritoModel->transactionRollBack();
                            $this->array_errors[] = $th;
                        }
                        if (empty($this->array_errors)) {
                            Notifica::stock($det_prod['pro_id'], $almacen['alm_nombre'], 'compras', $habia, 0, $det_prod['agregado'], $habia - $det_prod['agregado'], $id_factura, 9);
                        }
                    } else {
                        try {
                            $this->carritoModel->transactionBegin();
                            $this->carritoModel->eliminarProductoNe($id_factura, $det_prod['pro_id'], $_SESSION["$_nombre_carrito_$id_factura"][$unique]['cantidad']);
                            $this->carritoModel->transactionCommit();
                        } catch (\Throwable $th) {
                            $this->carritoModel->transactionRollBack();
                            $this->array_errors[] = $th;
                        }
                    }
                }
            }
            if ($tabla_db == 'app_cmppedidos') {
                $det_prod = $this->carritoModel->obtenerProductoPeCompra($id_factura, $_SESSION["$_nombre_carrito_$id_factura"][$unique]['id']);
                if ($det_prod) {
                    try {
                        $this->carritoModel->transactionBegin();
                        $this->carritoModel->eliminarProductoPeCompra($id_factura, $det_prod['pro_id'], $_SESSION["$_nombre_carrito_$id_factura"][$unique]['cantidad']);
                        $this->carritoModel->transactionCommit();
                    } catch (\Throwable $th) {
                        $this->carritoModel->transactionRollBack();
                        $this->array_errors[] = 'Error al eliminar el producto'.$th;
                    }
                }
            } 
            if ($tabla_db == 'app_compras') {
                $det_prod = $this->carritoModel->obtenerProductoFacCompra($id_factura, $_SESSION["$_nombre_carrito_$id_factura"][$unique]['id']);
                if ($det_prod) {
                    if ($det_prod['agregado'] > 0) {
                        try {
                            $this->carritoModel->transactionBegin();
                            $this->carritoModel->descontardeStock($det_prod['pro_id'], $almacen['alm_id'], $det_prod['agregado']);
                            $this->carritoModel->eliminarProductoFacCompra($id_factura, $det_prod['pro_id'], $det_prod['agregado']);
                            $this->carritoModel->transactionCommit();
                        } catch (\Throwable $th) {
                            $this->carritoModel->transactionRollBack();
                            $this->array_errors[] = $th;
                        }
                        if (empty($this->array_errors)) {
                            Notifica::stock($det_prod['pro_id'], $almacen['alm_nombre'], 'compras', $habia, 0, $det_prod['agregado'], $habia - $det_prod['agregado'], $id_factura, 8);
                        }
                    } else {
                        try {
                            $this->carritoModel->transactionBegin();
                            $this->carritoModel->eliminarProductoFac($id_factura, $det_prod['pro_id'], $_SESSION["$_nombre_carrito_$id_factura"][$unique]['cantidad']);
                            $this->carritoModel->transactionCommit();
                        } catch (\Throwable $th) {
                            $this->carritoModel->transactionRollBack();
                            $this->array_errors[] = $th;
                        }
                    }
                }
            }

            if (empty($this->array_errors)) {
                unset($_SESSION["$_nombre_carrito_$id_factura"][$unique]);
                return $this->obtenerCarritoCliente($_nombre_carrito_, $id_factura, $id_cliente, $descuento_global);
            }
        }

        return ['errors' => $this->array_errors];
    }

    public function pagar(string $tabla_db, string $monto, int $id_divisa, int $id_factura, bool $generar_credito, int $id_cuenta_metodo, int $id_metodo_divisa,string $referencia = '',string $fact = '')
    {
        if ($tabla_db == 'app_compras_notas') {
            $tipo_doc = 9;
            $tipo_doc_a = 'NEC';
            $tipo_doc_descripcion = 'Notas de Entrega Compras';
            $status = ['cmpn_estatus' => 1];
            $id_tabla = 'cmpn_id';
            $factura = $this->carritoModel->obtenerNeCompra($id_factura);
        } else if ($tabla_db == 'app_compras') {
            $tipo_doc = 8;
            $tipo_doc_a = 'FACC';
            $tipo_doc_descripcion = 'Factura Compras';
            $status = ['cmp_estatus' => 1];
            $id_tabla = 'cmp_id';
            $factura = $this->carritoModel->obtenerFacCompra($id_factura);
        }

        $modulo = new Module();

        $permiso_factor = $modulo->has_module_action_permission('facturacion', 'cambiar_factor', $_SESSION['user_data']['emp_id']);
        $total_pagos = $this->carritoModel->totalPagos($id_factura, $tipo_doc,2);

        if ((round($total_pagos['total'] ?? 0, 2) >= round($factura['total'], 2))) {
            $this->array_errors[] = 'EL documento ha sido pagado en su totalidad';
        } else {

            $pagado = false;
            $factor_factura = 1;
            $factor_master  = 1;
            $monto  = convertir_a_float($monto);
            $divisa = $this->carritoModel->obtenerDivisa($id_divisa);

            if ($monto <= 0) {
                $this->array_errors[] = 'El monto no puede quedar en 0';
            }

            if ($this->divisa_master['id'] != $divisa['div_id']) {
                $data_factor = $this->carritoModel->obtenerDivisaAlCambio($this->divisa_master['id'], $id_divisa);
                if (!$data_factor) {
                    $this->array_errors[] = 'No se encuentra el factor de conversion entre la divisa' . $divisa['div_nombre'] . ' y la divisa predeterminada ' . $this->div_master['divisa'];
                } else {
                    $factor_master = $data_factor['df_factor'];
                    if ($id_divisa == 1) {
                        $factor_master = ($permiso_factor) ? $fact : $data_factor['df_factor'];
                    }
                }
            }

            if ($factura['id_divisa'] != $divisa['div_id']) {
                $data_factor_factura = $this->carritoModel->obtenerDivisaAlCambio($factura['id_divisa'], $id_divisa);
                if (!$data_factor_factura) {
                    $this->array_errors[] = 'No se encuentra el factor de conversion entre la divisa' . $divisa['div_nombre'] . ' y la divisa en que se registró la factura.';
                } else {
                    $factor_factura = $data_factor_factura['df_factor'];
                    if ($id_divisa == 1) {
                        $factor_factura = ($permiso_factor) ? $fact : $data_factor_factura['df_factor'];
                    }
                }
            }

            if (empty($this->array_errors)) {

                $proveedor = $this->carritoModel->obtenerProveedor($factura['id_cliente']);
                $total_pagos = $this->carritoModel->totalPagos($id_factura, 8,2);

                $conversion = $monto / $factor_factura;
                $restante = $factura['total'] - $total_pagos['total'];

                if (round($conversion, 2) > round($restante, 2)) {
                    $this->array_errors[] = 'El monto supera la cantidad restante por pagar';
                }

                $cuenta = $this->carritoModel->consultar("SELECT cmp_saldo, cmp_cueid FROM app_cuentas_metodopago WHERE cmp_id = $id_cuenta_metodo")->row();
                $saldo = $this->carritoModel->consultar("SELECT bc_saldo FROM app_bancos_cuentas WHERE bc_id = {$cuenta['cmp_cueid']}")->row();

                if ($monto > round($saldo['bc_saldo'], 2)) {
                    $this->array_errors[] = 'Saldo insuficiente.';
                }

                if (empty($this->array_errors)) {

                    try {

                        $this->carritoModel->transactionBegin();

                        $this->carritoModel->guardar([
                            'fab_idgenerico'        => $factura['id'],
                            'fab_doc'               => $tipo_doc,
                            'fab_divisa'            => $divisa['div_id'],
                            'fab_metodo'            => $id_metodo_divisa,
                            'fab_cmpid'             => $id_cuenta_metodo,
                            'fab_monto'             => $monto * -1,
                            'fab_factor'            => $factor_factura,
                            'fab_conversion'        => $conversion * -1,
                            'fab_divid_conversion'  => $factura['id_divisa'],
                            'fab_factor_master'     => $factor_master,
                            'fab_retiro'            => 1,
                            'fab_empid'             => $_SESSION['user_data']['emp_id'],
                            'fab_modulo'            => $tipo_doc_descripcion,
                            'fab_descripcion'       => ($referencia != '') ? 'Referencia: ' . $referencia : '',
                            'fab_observacion'       => "Egreso $tipo_doc_a #  {$factura['correlativo']} {$proveedor['prov_razonsocial']}  Monto: " . Moneda::moneda($monto, $divisa['div_locale'], $divisa['div_simbolo']),
                            'fab_categoria'         => 2,
                            'fab_saldo_anterior'    => $saldo['bc_saldo']
                        ], true, 'app_movimientos');

                        $this->carritoModel->consultar("UPDATE app_bancos_cuentas SET bc_saldo =  bc_saldo - $monto WHERE bc_id={$cuenta['cmp_cueid']}")->run();
                        $this->carritoModel->consultar("UPDATE app_cuentas_metodopago SET cmp_saldo = cmp_saldo - $monto WHERE cmp_id = $id_cuenta_metodo")->run();

                        $total_pagos = $this->carritoModel->totalPagos($id_factura, $tipo_doc,2);

                        if ((round($total_pagos['total'], 2) * -1) >= round($factura['total'], 2)) {
                            $this->carritoModel->editar($id_factura, $status, $tabla_db, $id_tabla);
                            $pagado = true;
                        }

                        $this->carritoModel->transactionCommit();
                    } catch (\Throwable $th) {
                        $this->carritoModel->transactionRollBack();
                        $this->array_errors[] = 'Error en transacción';
                    }

                    if (empty($this->array_errors)) {

                        $array_abonos = [];
                        $total_pagos = $this->carritoModel->totalPagos($factura['id'], $tipo_doc,2);

                        if ($tabla_db == 'app_compras') {
                            $abonos = $this->carritoModel->abonosFacCompra($factura['id']);
                        } else if ($tabla_db == 'app_compras_notas') {
                            $abonos = $this->carritoModel->abonosNeCompra($factura['id']);
                        }

                        if (is_countable($abonos) && count($abonos)) {

                            foreach ($abonos as $row) {

                                if (is_null($row['fab_divisa'])) {
                                    $divisa_mov = $this->divisa_master;
                                } else {
                                    $divisa_mov = Moneda::obtenerDivisa($row['fab_divisa']);
                                }

                                if (is_null($row['fab_divid_conversion'])) {
                                    $divisa_conv_mov = $this->divisa_master;
                                } else {
                                    $divisa_conv_mov = Moneda::obtenerDivisa($row['fab_divid_conversion']);
                                }

                                if (is_null($row['fab_factor'])) {
                                    $row['fab_factor'] = 1;
                                }

                                $array_abonos[] = [
                                    'fab_id'            => $row['fab_id'],
                                    'fab_fecha'         => $row['fecha'],
                                    'bc_alias'          => $row['bc_alias'],
                                    'bc_tipo'           => $row['bc_tipo'],
                                    'fab_retiro'        => $row['fab_retiro'],
                                    'mp_nombre'         => $row['mp_nombre'],
                                    'referencia'        => $row['fab_descripcion'],
                                    'fab_monto'         => Moneda::moneda($row['fab_monto'], $divisa_mov['locale'], $divisa_mov['symbol']),
                                    'fab_factor'        => ($row['fab_factor'] < 1) ? $row['fab_factor'] : Moneda::decimal($row['fab_factor'], $this->divisa_master['locale']),
                                    'fab_conversion'    => Moneda::moneda($row['fab_conversion'], $divisa_conv_mov['locale'], $divisa_conv_mov['symbol']),
                                ];
                            }
                        }

                        Http::json_response([
                            'abonos'        => $array_abonos,
                            'total_factura' => round($factura['total'], 2),
                            'pagado'        => $pagado,
                            'restante'      => round(($factura['total'] + $total_pagos['total']), 2),
                            'total_pagado'  => round($total_pagos['total'], 2)
                        ]);
                    }
                }
            }
        }

        return ['errors' => $this->array_errors];
    }

    public function eliminarPago(string $tabla_db, int $id_factura, int $id_movimiento)
    {
        if ($tabla_db == 'app_compras_notas') {
            $tipo_doc = 9;
            $tipo_doc_a = 'NEC';
            $tipo_doc_descripcion = 'Notas de Entrega Compras';
            $status = ['cmpn_estatus' => 1];
            $id_tabla = 'cmpn_id';
            $factura = $this->carritoModel->obtenerNeCompra($id_factura);
        } else if ($tabla_db == 'app_compras') {
            $tipo_doc = 8;
            $tipo_doc_a = 'FACC';
            $tipo_doc_descripcion = 'Factura Compras';
            $status = ['cmp_estatus' => 1];
            $id_tabla = 'cmp_id';
            $factura = $this->carritoModel->obtenerFacCompra($id_factura);
        }

        $movimiento_model = new MovimientoModel();
        $movimiento = $movimiento_model->abtenerMovimiento($id_movimiento);

        if ($factura['estatus'] == 1) {
            $this->array_errors[] = 'Lo siento no se puede eliminar el pago ya que la factura a sido cancelada en su totalidad';
        } else {
            if (!$movimiento && $factura['id'] != $movimiento['fab_idgenerico']) {
                $this->array_errors[] = 'Acción prohibida';
            } else {
                if ($movimiento_model->abtenerMovimientoNegativo($id_movimiento)) {
                    $this->array_errors[] = 'EL pago no se puede eliminar ya que se encuentra en reverso';
                }
            }
        }

        if (empty($this->array_errors)) {

            $proveedor = $this->carritoModel->obtenerProveedor($factura['id_cliente']);
            $divisa_fac_mov = $this->carritoModel->obtenerDivisa($movimiento['fab_divisa']);
            $cuenta = $this->carritoModel->consultar("SELECT cmp_cueid, cmp_saldo FROM app_cuentas_metodopago WHERE cmp_id = {$movimiento['fab_cmpid']}")->row();
            $total_saldo_cuenta = $this->carritoModel->consultar("SELECT bc_saldo FROM app_bancos_cuentas WHERE bc_id = {$cuenta['cmp_cueid']}")->row();

            try {

                $this->carritoModel->transactionBegin();

                $this->carritoModel->guardar([
                    'fab_idgenerico'        => $movimiento['fab_idgenerico'],
                    'fab_doc'               => $tipo_doc,
                    'fab_divisa'            => $movimiento['fab_divisa'],
                    'fab_metodo'            => $movimiento['fab_metodo'],
                    'fab_cmpid'             => $movimiento['fab_cmpid'],
                    'fab_monto'             => $movimiento['fab_monto'] * -1,
                    'fab_factor'            => $movimiento['fab_factor'],
                    'fab_conversion'        => $movimiento['fab_conversion'] * -1,
                    'fab_divid_conversion'  => $movimiento['fab_divid_conversion'],
                    'fab_factor_master'     => $movimiento['fab_factor_master'],
                    'fab_idretiro'          => $movimiento['fab_id'],
                    'fab_empid'             => $movimiento['fab_empid'],
                    'fab_modulo'            => $movimiento['fab_modulo'],
                    'fab_descripcion'       => '',
                    'fab_observacion'       => "Devolución $tipo_doc_a #  {$factura['correlativo']} {$proveedor['prov_razonsocial']} Monto: " . Moneda::moneda($movimiento['fab_monto'], $divisa_fac_mov['div_locale'], $divisa_fac_mov['div_simbolo']),
                    'fab_categoria'         => 2,
                    'fab_saldo_anterior'    => $total_saldo_cuenta['bc_saldo']
                ], true, 'app_movimientos');

                $this->carritoModel->consultar("UPDATE app_bancos_cuentas SET bc_saldo =  bc_saldo - {$movimiento['fab_monto']} WHERE bc_id={$cuenta['cmp_cueid']}")->run();
                $this->carritoModel->consultar("UPDATE app_cuentas_metodopago SET cmp_saldo = cmp_saldo - {$movimiento['fab_monto']}  WHERE cmp_id={$movimiento['fab_cmpid']}")->run();

                $this->carritoModel->transactionCommit();
            } catch (\Throwable $th) {
                $this->carritoModel->transactionRollBack();
                $this->array_errors[] = 'Error en transacción';
            }

            if (empty($this->array_errors)) {

                $array_abonos = [];
                $total_pagos = $this->carritoModel->totalPagos($factura['id'], $tipo_doc,2);

                if ($tabla_db == 'app_compras') {
                    $abonos = $this->carritoModel->abonosFacCompra($factura['id']);
                } else if ($tabla_db == 'app_compras_notas') {
                    $abonos = $this->carritoModel->abonosNeCompra($factura['id']);
                }

                if (is_countable($abonos) && count($abonos)) {

                    foreach ($abonos as $row) {

                        if (is_null($row['fab_divisa'])) {
                            $divisa_mov = $this->divisa_master;
                        } else {
                            $divisa_mov = Moneda::obtenerDivisa($row['fab_divisa']);
                        }

                        if (is_null($row['fab_divid_conversion'])) {
                            $divisa_conv_mov = $this->divisa_master;
                        } else {
                            $divisa_conv_mov = Moneda::obtenerDivisa($row['fab_divid_conversion']);
                        }

                        if (is_null($row['fab_factor'])) {
                            $row['fab_factor'] = 1;
                        }

                        $array_abonos[] = [
                            'fab_id'            => $row['fab_id'],
                            'fab_fecha'         => $row['fecha'],
                            'bc_alias'          => $row['bc_alias'],
                            'bc_tipo'           => $row['bc_tipo'],
                            'fab_retiro'        => $row['fab_retiro'],
                            'mp_nombre'         => $row['mp_nombre'],
                            'fab_monto'         => Moneda::moneda($row['fab_monto'], $divisa_mov['locale'], $divisa_mov['symbol']),
                            'fab_factor'        => ($row['fab_factor'] < 1) ? $row['fab_factor'] : Moneda::decimal($row['fab_factor'], $this->divisa_master['locale']),
                            'fab_conversion'    => Moneda::moneda($row['fab_conversion'], $divisa_conv_mov['locale'], $divisa_conv_mov['symbol']),
                        ];
                    }
                }

                Http::json_response([
                    'abonos'        => $array_abonos,
                    'total_factura' => round($factura['total'], 2),
                    'pagado'        => false,
                    'restante'      => round(($factura['total'] + $total_pagos['total']), 2),
                    'total_pagado'  => round($total_pagos['total'], 2)
                ]);
            }
        }

        return ['errors' => $this->array_errors];
    }

    public function editarDetallesCliente(int $prov_id, array $data)
    {
        $new_proveedor = new Proveedor();

        if ($new_proveedor->where(['prov_id!=' => $prov_id, 'prov_cifnif' => $data['prov_cifnif']], true))
            $this->array_errors[] = 'El DNI ya se encuentra en uso';

        if (empty($this->array_errors)) {
            return $new_proveedor->editar($prov_id, [
                'prov_tipoidfiscal'     => $data['prov_tipoidfiscal'],
                'prov_cifnif'           => $data['prov_cifnif'],
                'prov_razonsocial'      => $data['prov_razonsocial'],
                'prov_direccion'        => $data['prov_direccion'],
                'prov_paisid'           => $data['prov_paisid'],
                'prov_estado'           => $data['prov_estado'],
                'prov_ciudad'           => $data['prov_ciudad'],
                'prov_codigo_postal'    => $data['prov_codigo_postal']
            ]);
        }

        return ['errors' => $this->array_errors];
    }

    public function obtenerUbicacionesProducto(string $_nombre_carrito_, int $id_cliente)
    {
        $newProUbi = new ProductoUbicacion();
        $newAU = new AlmacenUbicacion();
        $tipo_de_escalon = [];
        $lista = [];
        $array_tipo = [
            'Zonas' => 'Zona',
            'Pasillos' => 'Pasillo',
            'Armarios' => 'Armario',
            'Secciones' => 'Sección',
            'Cajones' => 'Cajón'
        ];

        $contenido_carrito = $this->contenidoCarrito($_nombre_carrito_, $id_cliente);

        if (!empty($contenido_carrito)) {

            foreach ($contenido_carrito as $car) {

                $ubicacion = $newProUbi->obtenerubicacionProductoAlmacen($car['id'], $car['id_almacen']);

                if (is_countable($ubicacion) && count($ubicacion)) {

                    foreach ($ubicacion as $row) {

                        $tipo_de_escalon = [];
                        $padre = $row['au_padre'];

                        $tipo_de_escalon[] = [
                            'id' => $row['au_id'],
                            'tipo' => $array_tipo[$row['au_tipo']],
                            'descripcion' => $row['au_descripcion']
                        ];

                        while ($padre != 0) {
                            $escalon = $newAU->obtenerUbicacion($padre);
                            if ($escalon) {
                                $tipo_de_escalon[] = [
                                    'id' => $escalon['au_id'],
                                    'tipo' => $array_tipo[$escalon['au_tipo']],
                                    'descripcion' => $escalon['au_descripcion']
                                ];
                                $padre = $escalon['au_padre'];
                            } else {
                                $padre = 0;
                            }
                        }

                        $lista[] = [
                            'almacen' => [
                                'id' => $row['alm_id'],
                                'descripcion' => $row['alm_nombre']
                            ],
                            'producto' => [
                                'id' => $row['pro_id'],
                                'codigo' => $row['pro_codigo'],
                                'descripcion' => $row['pro_descripcion']
                            ],
                            'ubicacion' => $tipo_de_escalon
                        ];
                    }
                }
            }
        }

        return $lista;
    }
}
