El kardex de inventario es un documento o sistema de registro que permite llevar un control de las entradas y salidas de mercancías o productos en un almacén. En él se registran los datos básicos de cada producto, como el código, la descripción, la unidad de medida, el precio unitario y el stock.

El kardex de inventario es una herramienta fundamental para la gestión del inventario. Permite conocer la cantidad de cada producto en existencia, así como su valor total. También ayuda a identificar las tendencias de consumo y a detectar posibles problemas de desabastecimiento.

El kardex de inventario se puede llevar de forma manual o automatizada. En el caso de la gestión manual, el registro se realiza en una hoja de cálculo o en un libro. En el caso de la gestión automatizada, el registro se realiza en un sistema informático.

Los datos que se registran en el kardex de inventario son los siguientes:

  • Código: Identificador único del producto.
  • Descripción: Nombre o descripción del producto.
  • Unidad de medida: Unidad en la que se mide el producto (unidades, kilos, metros, etc.).
  • Precio unitario: Precio de venta o de compra del producto.
  • Stock inicial: Cantidad de producto en existencia al inicio del periodo.
  • Entradas: Cantidad de producto que ha entrado en el almacén durante el periodo.
  • Salidas: Cantidad de producto que ha salido del almacén durante el periodo.
  • Stock final: Cantidad de producto en existencia al final del periodo.

El kardex de inventario se actualiza con cada movimiento de inventario. Cuando se recibe un producto, se registra la entrada con la cantidad recibida y el precio unitario. Cuando se vende un producto, se registra la salida con la cantidad vendida y el precio unitario.

El kardex de inventario es una herramienta esencial para la gestión del inventario. Permite conocer la cantidad de cada producto en existencia, así como su valor total. También ayuda a identificar las tendencias de consumo y a detectar posibles problemas de desabastecimiento.

Primero creamos el archivo de migración para la tabla principal App/Database/Migrations/2023-05-12-021155_Inventory.php

<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class Inventory extends Migration {

    public function up() {
        // Quotes  
        $this->forge->addField([
            'id' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true],
            'idEmpresa' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'null' => true],
            'idTipoInventario' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'null' => true],
            'idStorage' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'null' => true],
            'tipoES' => ['type' => 'varchar', 'constraint' => 3, 'null' => true],
            'idProveedor' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'null' => true],
            'folio' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'null' => true],
            'idUser' => ['type' => 'bigint', 'constraint' => 11, 'null' => true],
            'listProducts' => ['type' => 'text', 'null' => true],
            'taxes' => ['type' => 'decimal', 'constraint' => '18,2', 'null' => true],
            'IVARetenido' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'ISRRetenido' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'subTotal' => ['type' => 'decimal', 'constraint' => '18,2', 'null' => true],
            'total' => ['type' => 'decimal', 'constraint' => '18,2', 'null' => true],
            'balance' => ['type' => 'decimal', 'constraint' => '18,2', 'null' => true],
            'date' => ['type' => 'date', 'null' => true],
            'dateVen' => ['type' => 'date', 'null' => true],
            'quoteTo' => ['type' => 'varchar', 'constraint' => 512, 'null' => true],
            'delivaryTime' => ['type' => 'varchar', 'constraint' => 512, 'null' => true],
            'generalObservations' => ['type' => 'varchar', 'constraint' => 512, 'null' => true],
            'UUID' => ['type' => 'varchar', 'constraint' => 36, 'null' => true],
            'idOrdenCompra' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'null' => true],
            'created_at' => ['type' => 'datetime', 'null' => true],
            'updated_at' => ['type' => 'datetime', 'null' => true],
            'deleted_at' => ['type' => 'datetime', 'null' => true],
        ]);

        $this->forge->addKey('id', true);
        $this->forge->addUniqueKey('UUID', 'UQ_UUID');
        $this->forge->createTable('inventory', true);
    }

    public function down() {
        $this->forge->dropTable('inventory', true);
    }

}

Creamos el archivo de migración para el detalle del kardex de inventario App/Database/Migrations/2023-06-01052347_InventoryDetails.php con el siguiente codigo

<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class InventoryDetails extends MigrationCarta {

    public function up() {
        // QuotesDetails
        $this->forge->addField([
            'id' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true],
            'idInventory' => ['type' => 'int', 'constraint' => 11, 'null' => true],
            'idProduct' => ['type' => 'int', 'constraint' => 11, 'null' => true],
            'lote' => ['type' => 'varchar', 'constraint' => 512, 'null' => true],
            'description' => ['type' => 'varchar', 'constraint' => 512, 'null' => true],
            'unidad' => ['type' => 'varchar', 'constraint' => 64, 'null' => true],
            'claveProductoSAT' => ['type' => 'varchar', 'constraint' => 64, 'null' => true],
            'claveUnidadSAT' => ['type' => 'varchar', 'constraint' => 64, 'null' => true],
            'codeProduct' => ['type' => 'varchar', 'constraint' => 32, 'null' => true],
            'cant' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'price' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'porcentTax' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'porcentIVARetenido' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'IVARetenido' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'porcentISRRetenido' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'ISRRetenido' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'tax' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'neto' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'total' => ['type' => 'decimal', 'constraint' => '18,4', 'null' => true],
            'created_at' => ['type' => 'datetime', 'null' => true],
            'updated_at' => ['type' => 'datetime', 'null' => true],
            'deleted_at' => ['type' => 'datetime', 'null' => true],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->createTable('inventorydetails', true);
    }

    public function down() {
        $this->forge->dropTable('inventorydetails', true);
    }

}

Creamos el archivo de migración para llevar el control de los saldos en App/Database/Migrations/2023-08-31154316_Saldos.php con el siguiente código

<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class Saldos extends Migration {

    public function up() {
        // Saldos
        $this->forge->addField([
            'id' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true],
            'idEmpresa' => ['type' => 'bigint', 'constraint' => 20, 'null' => false],
            'idAlmacen' => ['type' => 'bigint', 'constraint' => 20, 'null' => false],
            'lote' => ['type' => 'varchar', 'constraint' => 128, 'null' => false],
            'idProducto' => ['type' => 'bigint', 'constraint' => 20, 'null' => false],
            'codigoProducto' => ['type' => 'varchar', 'constraint' => 64, 'null' => false],
            'descripcion' => ['type' => 'varchar', 'constraint' => 1024, 'null' => false],
            'cantidad' => ['type' => 'decimal', 'constraint' => 18, 'null' => false],
            'created_at' => ['type' => 'datetime', 'null' => true],
            'updated_at' => ['type' => 'datetime', 'null' => true],
            'deleted_at' => ['type' => 'datetime', 'null' => true],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->createTable('saldos', true);
    }

    public function down() {
        $this->forge->dropTable('saldos', true);
    }

}

Ahora creamos el archivo modelo para el encabezado del Kardex App/Models/InventoryModel.php con el siguiente código

<?php

namespace App\Models;

use CodeIgniter\Model;

class InventoryModel extends Model
{

    protected $table = 'inventory';
    protected $primaryKey = 'id';
    protected $useAutoIncrement = true;
    protected $returnType = 'array';
    protected $useSoftDeletes = true;
    protected $allowedFields = [
        'id',
        'idEmpresa',
        'idStorage',
        'idTipoInventario',
        'tipoES',
        'folio',
        'idUser',
        'idProveedor',
        'listProducts',
        'taxes',
        'IVARetenido',
        'ISRRetenido',
        'subTotal',
        'total',
        'balance',
        'date',
        'dateVen',
        'generalObservations',
        'delivaryTime',
        'created_at',
        'updated_at',

        'RFCReceptor',
        'usoCFDI',
        'metodoPago',
        'formaPago',
        'razonSocialReceptor',
        'codigoPostalReceptor',
        'regimenFiscalReceptor',

        'UUID'
    ];
    protected $useTimestamps = true;
    protected $createdField = 'created_at';
    protected $deletedField = 'deleted_at';
    protected $validationRules = [
        'idProveedor' => 'required|',
    ];
    protected $validationMessages = [];
    protected $skipValidation = false;

    public function mdlGetInventory($empresas)
    {

        $result = $this->db->table('inventory a, proveedores b, empresas c')
            ->select('a.UUID,a.id,concat(b.firstname,\' \',b.lastname) as nameProveedor
                    ,a.idStorage
                    ,a.idTipoInventario
                    ,a.tipoES
                    ,a.idProveedor
                    ,a.folio
                    ,a.date
                    ,b.email as correoCliente
                    ,a.dateVen
                    ,a.total
                    ,a.taxes
                    ,a.subTotal
                    ,a.balance
                    ,a.delivaryTime
                    ,a.generalObservations
                    ,a.IVARetenido
                    ,a.ISRRetenido
                  


                    ,a.RFCReceptor
                    ,a.usoCFDI
                    ,a.metodoPago
                    ,a.formaPago
                    ,a.razonSocialReceptor
                    ,a.codigoPostalReceptor
                    ,a.regimenFiscalReceptor

                    ,a.created_at
                    ,a.updated_at
                    ,a.deleted_at')
            ->where('a.idProveedor', 'b.id', FALSE)
            ->where('a.idEmpresa', 'c.id', FALSE)
            ->whereIn('a.idEmpresa', $empresas);

        return $result;
    }


    /**
     * Search by filters
     */
    public function mdlGetInventoryFilters($empresas, $from, $to)
    {

        $result = $this->db->table('inventory a, proveedores b, empresas c')
            ->select('a.UUID,a.id,concat(b.firstname,\' \',b.lastname) as nameProveedor
                    ,a.idStorage
                    ,a.idTipoInventario
                    ,a.tipoES
                    ,a.idProveedor
                    ,a.folio
                    ,a.date
                    ,b.email as correoCliente
                    ,a.dateVen
                    ,a.total
                    ,a.taxes
                    ,a.subTotal
                    ,a.balance
                    ,a.delivaryTime
                    ,a.generalObservations
                    ,a.IVARetenido
                    ,a.ISRRetenido


                    ,a.RFCReceptor
                    ,a.usoCFDI
                    ,a.metodoPago
                    ,a.formaPago
                    ,a.razonSocialReceptor
                    ,a.codigoPostalReceptor
                    ,a.regimenFiscalReceptor

                    ,a.created_at
                    ,a.updated_at
                    ,a.deleted_at')
            ->where('a.idProveedor', 'b.id', FALSE)
            ->where('a.idEmpresa', 'c.id', FALSE)
            ->where('a.date >=', $from . ' 00:00:00')
            ->where('a.date <=', $to . ' 23:59:59')
            ->whereIn('a.idEmpresa', $empresas);

        return $result;
    }
    
    
    public function lastCode($idStorage,$idTipoMovimiento){
        
        $result = $this->db->table('inventory')
        ->selectMax('folio as lastFolio')
        ->where(array('idStorage' => $idStorage,'idTipoInventario' => $idTipoMovimiento));

    }



    /**
     * Obtener Cotización por UUID
     */

    public function mdlGetInventoryUUID($uuid, $empresas)
    {

        $result = $this->db->table('inventory a, proveedores b, empresas c')
            ->select('a.idProveedor
            ,a.idStorage
            ,a.idTipoInventario
            ,a.tipoES
            ,a.folio
            ,a.quoteTo
            ,a.UUID
            ,a.idUser
            ,a.id
            ,concat(b.firstname,\' \',b.lastname) as nameProveedor
            ,a.idEmpresa
            ,c.nombre as nombreEmpresa
            ,a.listProducts
            ,a.date
            ,a.dateVen
            ,a.total
            ,a.taxes
            ,a.IVARetenido
            ,a.ISRRetenido
            ,a.subTotal
            ,a.delivaryTime
            ,a.generalObservations

            ,a.RFCReceptor
            ,a.usoCFDI
            ,a.metodoPago
            ,a.formaPago
            ,a.razonSocialReceptor
            ,a.codigoPostalReceptor
            ,a.regimenFiscalReceptor

            ,a.created_at
            ,a.updated_at,
            a.deleted_at')
            ->where('a.idProveedor', 'b.id', FALSE)
            ->where('a.idEmpresa', 'c.id', FALSE)
            ->where('UUID', $uuid)
            ->whereIn('a.idEmpresa', $empresas)
            ->get()->getRowArray();

        return $result;
    }
}

Creamos el archivo de modelo del detalle del kardex App/Models/InventoryDetailsModel.php con el siguiente código

<?php

namespace App\Models;

use CodeIgniter\Model;

class InventoryDetailsModel extends Model {

    protected $table = 'inventorydetails';
    protected $primaryKey = 'id';
    protected $useAutoIncrement = true;
    protected $returnType = 'array';
    protected $useSoftDeletes = true;
    protected $allowedFields = ['id'
        , 'idInventory'
        , 'idProduct'
        , 'lote'
        , 'description'
        , 'claveProductoSAT'
        , 'claveUnidadSAT'
        , 'unidad'
        , 'codeProduct'
        , 'cant'
        , 'price'
        , 'porcentTax'
        , 'tax'
        , 'porcentIVARetenido'
        , 'IVARetenido'
        , 'porcentISRRetenido'
        , 'ISRRetenido'
        , 'neto'
        , 'total'
        , 'created_at'
        , 'updated_at'
        , 'deleted_at'];
    protected $useTimestamps = true;
    protected $createdField = 'created_at';
    protected $deletedField = 'deleted_at';
    protected $validationRules = [
    ];
    protected $validationMessages = [];
    protected $skipValidation = false;

}

Creamos el archivo modelo para los saldos en App/Models/SaldosModel.php con el siguiente código

<?php

namespace App\Models;

use CodeIgniter\Model;

class SaldosModel extends Model {

    protected $table = 'saldos';
    protected $primaryKey = 'id';
    protected $useAutoIncrement = true;
    protected $returnType = 'array';
    protected $useSoftDeletes = true;
    protected $allowedFields = ['id'
        , 'idEmpresa'
        , 'idAlmacen'
        , 'idProducto'
        , 'codigoProducto'
        , 'descripcion'
        , 'cantidad'
        , 'lote'
        , 'created_at'
        , 'deleted_at'
        , 'updated_at'];
    protected $useTimestamps = true;
    protected $createdField = 'created_at';
    protected $deletedField = 'deleted_at';
    protected $validationRules = [
    ];
    protected $validationMessages = [];
    protected $skipValidation = false;

    public function mdlGetSaldos($idEmpresas) {

        $result = $this->db->table('saldos a, empresas b')
                ->select('a.id
                         ,a.idEmpresa
                         ,a.idAlmacen
                         ,a.idProducto
                         ,a.codigoProducto
                         ,a.descripcion
                         ,a.cantidad
                         ,a.created_at
                         ,a.deleted_at
                         ,a.updated_at 
                         ,b.nombre as nombreEmpresa')
                ->where('a.idEmpresa', 'b.id', FALSE)
                ->whereIn('a.idEmpresa', $idEmpresas);

        return $result;
    }

}

Ahora creamos el archivo controlador en App/Controllers/InventoryController.php con el siguiente codigo

<?php

namespace App\Controllers;

use App\Controllers\BaseController;
use App\Database\Migrations\Storages;
use App\Models\ProductsModel;
use \App\Models\UserModel;
use App\Models\LogModel;
use App\Models\QuotesModel;
use App\Models\InventoryModel;
use App\Models\CompaniesModel;
use App\Models\StoragesModel;
use App\Models\InventoryDetailsModel;
use CodeIgniter\API\ResponseTrait;
use App\Models\EmpresasModel;
use App\Models\CustumersModel;
use App\Models\PaymentsModel;
use App\Models\Comprobantes_rdModel;
use App\Models\Tipos_movimientos_inventarioModel;
use App\Models\SaldosModel;

class InventoryController extends BaseController {

    use ResponseTrait;

    protected $log;
    protected $inventory;
    protected $storages;
    protected $inventoryDetail;
    protected $empresa;
    protected $user;
    protected $custumer;
    protected $payments;
    protected $products;
    protected $quotes;
    protected $comprobantesRD;
    protected $tiposMovimiento;
    protected $saldos;

    public function __construct() {
        $this->log = new LogModel();

        $this->inventory = new InventoryModel();
        $this->inventoryDetail = new InventoryDetailsModel();
        $this->empresa = new EmpresasModel();
        $this->user = new UserModel();
        $this->custumer = new CustumersModel();
        $this->payments = new PaymentsModel();
        $this->products = new ProductsModel();
        $this->quotes = new QuotesModel();
        $this->comprobantesRD = new Comprobantes_rdModel();
        $this->tiposMovimiento = new Tipos_movimientos_inventarioModel();
        $this->saldos = new SaldosModel();
        $this->storages = new StoragesModel();

        helper('menu');
        helper('utilerias');
    }

    public function index() {

        $auth = service('authentication');
        if (!$auth->check()) {

            return redirect()->route('admin');
        }


        helper('auth');

        $idUser = user()->id;
        $titulos["empresas"] = $this->empresa->mdlEmpresasPorUsuario($idUser);

        if (count($titulos["empresas"]) == "0") {

            $empresasID[0] = "0";
        } else {

            $empresasID = array_column($titulos["empresas"], "id");
        }


        if ($this->request->isAJAX()) {


            $datos = $this->inventory->mdlGetInventory($empresasID);

            return \Hermawan\DataTables\DataTable::of($datos)->toJson(true);
        }


        $titulos["listaTitle"] = "Administracion de ventas";
        $titulos["listaSubtitle"] = "Muestra la lista de ventas";

        //$data["data"] = $datos;
        return view('inventory', $titulos);
    }

    public function inventoryFilters($desdeFecha, $hastaFecha, $todas) {


        $auth = service('authentication');
        if (!$auth->check()) {

            return redirect()->route('admin');
        }


        helper('auth');

        $idUser = user()->id;
        $titulos["empresas"] = $this->empresa->mdlEmpresasPorUsuario($idUser);

        if (count($titulos["empresas"]) == "0") {

            $empresasID[0] = "0";
        } else {

            $empresasID = array_column($titulos["empresas"], "id");
        }


        if ($this->request->isAJAX()) {


            $datos = $this->inventory->mdlGetInventoryFilters($empresasID, $desdeFecha, $hastaFecha, $todas);

            return \Hermawan\DataTables\DataTable::of($datos)->toJson(true);
        }
    }

    public function newinventory() {
        $auth = service('authentication');
        if (!$auth->check()) {

            return redirect()->route('admin');
        }



        helper('auth');
        $userName = user()->username;
        $idUser = user()->id;

        $titulos["empresas"] = $this->empresa->mdlEmpresasPorUsuario($idUser);

        if (count($titulos["empresas"]) == "0") {

            $empresasID[0] = "0";
        } else {

            $empresasID = array_column($titulos["empresas"], "id");
        }


        $fechaActual = fechaMySQLADateHTML5(fechaHoraActual());

        $idMax = "0";

        $titulos["idMax"] = $idMax;
        $titulos["idInventory"] = $idMax;
        $titulos["tipoES"] = "ENT";

        $titulos["folio"] = "0";
        $titulos["fecha"] = $fechaActual;
        $titulos["userName"] = $userName;
        $titulos["idUser"] = $idUser;
        $titulos["contact"] = "";
        $titulos["idQuote"] = "0";
        $titulos["codeCustumer"] = "";
        $titulos["observations"] = "";
        $titulos["taxes"] = "0.00";
        $titulos["IVARetenido"] = "0.00";
        $titulos["ISRRetenido"] = "0.00";
        $titulos["subTotal"] = "0.00";
        $titulos["total"] = "0.00";
        $titulos["formaPago"] = $this->catalogosSAT->formasDePago40()->searchByField("texto", "%%", 99999);
        $titulos["usoCFDI"] = $this->catalogosSAT->usosCfdi40()->searchByField("texto", "%%", 99999);
        $titulos["metodoPago"] = $this->catalogosSAT->metodosDePago40()->searchByField("texto", "%%", 99999);
        $titulos["regimenFiscal"] = $this->catalogosSAT->regimenesFiscales40()->searchByField("texto", "%%", 99999);

        $titulos["RFCReceptor"] = "";
        $titulos["regimenFiscalReceptor"] = "";
        $titulos["usoCFDIReceptor"] = "";
        $titulos["metodoPagoReceptor"] = "";
        $titulos["formaPagoReceptor"] = "";
        $titulos["razonSocialReceptor"] = "";
        $titulos["codigoPostalReceptor"] = "";

        $titulos["folioComprobanteRD"] = "0";

        $titulos["uuid"] = generaUUID();

        $titulos["title"] = "Nuevo Inventario"; //lang('registerNew.title');
        $titulos["subtitle"] = "Captura de Inventario"; // lang('registerNew.subtitle');

        return view('newInventory', $titulos);
    }

    /**
     * Get Last Code
     */
    public function getLastCode() {

        $idEmpresa = $this->request->getPost("idEmpresa");
        $idStorage = $this->request->getPost("idStorage");
        $idTipoMovimiento = $this->request->getPost("idTipoMovimiento");

        $result = $this->inventory->selectMax("folio")
                ->where("idEmpresa", $idEmpresa)
                ->where("idStorage", $idStorage)
                ->where("idTipoInventario", $idTipoMovimiento)
                ->first();

        if ($result["folio"] == null) {

            $result["folio"] = 1;
        } else {

            $result["folio"] = $result["folio"] + 1;
        }

        echo json_encode($result);
    }

    /**
     * Get Last Code
     */
    public function getLastCodeInterno($idEmpresa) {


        $result = $this->inventory->selectMax("folio")
                ->where("idEmpresa", $idEmpresa)
                ->first();

        if ($result["folio"] == null) {

            $result["folio"] = 1;
        } else {

            $result["folio"] = $result["folio"] + 1;
        }

        return $result["folio"];
    }

    /*
     * Editar Cotizacion
     */

    public function editInventory($uuid) {

        helper('auth');
        $userName = user()->username;
        $idUser = user()->id;

        $auth = service('authentication');
        if (!$auth->check()) {

            return redirect()->route('admin');
        }


        $auth = service('authentication');
        if (!$auth->check()) {

            return redirect()->route('admin');
        }

        helper('auth');
        $userName = user()->username;
        $idUser = user()->id;

        $titulos["empresas"] = $this->empresa->mdlEmpresasPorUsuario($idUser);

        if (count($titulos["empresas"]) == "0") {

            $empresasID[0] = "0";
        } else {

            $empresasID = array_column($titulos["empresas"], "id");
        }


        $inventory = $this->inventory->mdlGetInventoryUUID($uuid, $empresasID);

        $listProducts = json_decode($inventory["listProducts"], true);

        $titulos["idInventory"] = $inventory["id"];
        $titulos["folio"] = $inventory["folio"];

        $titulos["idStorage"] = $inventory["idStorage"];

        $datosAlmacen = $this->storages->select("*")->where("id", $inventory["idStorage"])->first();

        $titulos["nombreAlmacen"] = $datosAlmacen["name"];
        $titulos["tipoES"] = $inventory["tipoES"];

        $titulos["idTipoInventario"] = $inventory["idTipoInventario"];

        $tiposInventario = $this->tiposMovimiento->select("*")->where("id", $inventory["idTipoInventario"])->first();
        $titulos["idTipoInventario"] = $inventory["idTipoInventario"];
        $titulos["nombreTipoInventario"] = $tiposInventario["descripcion"];

        $titulos["idProveedor"] = $inventory["idProveedor"];
        $titulos["nameProveedor"] = $inventory["nameProveedor"];
        $titulos["idEmpresa"] = $inventory["idEmpresa"];
        $titulos["nombreEmpresa"] = $inventory["nombreEmpresa"];

        $titulos["idUser"] = $idUser;
        $titulos["userName"] = $userName;
        $titulos["listProducts"] = $listProducts;
        $titulos["taxes"] = number_format($inventory["taxes"], 2, ".");
        $titulos["IVARetenido"] = number_format($inventory["IVARetenido"], 2, ".");
        $titulos["ISRRetenido"] = number_format($inventory["ISRRetenido"], 2, ".");
        $titulos["subTotal"] = number_format($inventory["subTotal"], 2, ".");
        $titulos["total"] = number_format($inventory["total"], 2, ".");
        $titulos["fecha"] = $inventory["date"];
        $titulos["dateVen"] = $inventory["dateVen"];
        $titulos["quoteTo"] = $inventory["quoteTo"];
        $titulos["observations"] = $inventory["generalObservations"];
        $titulos["uuid"] = $inventory["UUID"];
        $titulos["idQuote"] = "0";
        $titulos["formaPago"] = $this->catalogosSAT->formasDePago40()->searchByField("texto", "%%", 99999);
        $titulos["usoCFDI"] = $this->catalogosSAT->usosCfdi40()->searchByField("texto", "%%", 99999);
        $titulos["metodoPago"] = $this->catalogosSAT->metodosDePago40()->searchByField("texto", "%%", 99999);
        $titulos["regimenFiscal"] = $this->catalogosSAT->regimenesFiscales40()->searchByField("texto", "%%", 99999);

        $titulos["RFCReceptor"] = $inventory["RFCReceptor"];
        $titulos["regimenFiscalReceptor"] = $inventory["regimenFiscalReceptor"];
        $titulos["usoCFDIReceptor"] = $inventory["usoCFDI"];
        $titulos["metodoPagoReceptor"] = $inventory["metodoPago"];
        $titulos["formaPagoReceptor"] = $inventory["formaPago"];
        $titulos["razonSocialReceptor"] = $inventory["razonSocialReceptor"];
        $titulos["codigoPostalReceptor"] = $inventory["codigoPostalReceptor"];

        $titulos["folioComprobanteRD"] = "0";
        $titulos["tipoComprobanteRDID"] = "0";
        $titulos["tipoComprobanteRDNombre"] = "0";
        $titulos["tipoComprobanteRDPrefijo"] = "0";

        $titulos["title"] = "Editar Inventario";
        $titulos["subtitle"] = "Edición de Inventario";

        return view('newInventory', $titulos);
    }

    /*
     * Save or Update
     */

    public function save() {

        $auth = service('authentication');

        if (!$auth->check()) {
            $this->session->set('redirect_url', current_url());
            return redirect()->route('admin');
        }

        helper('auth');
        $userName = user()->username;
        $idUser = user()->id;

        $datos = $this->request->getPost();

        $tiposMovimiento = $this->tiposMovimiento->select("*")->where("id", $datos["idTipoInventario"])->first();

        $datos["tipoES"] = $tiposMovimiento["tipo"];

        $this->inventory->db->transBegin();

        $existsInventory = $this->inventory->where("UUID", $datos["UUID"])->countAllResults();

        $listProducts = json_decode($datos["listProducts"], true);

        /**
         * if is new inventory
         */
        if ($existsInventory == 0) {


            $ultimoFolio = $this->getLastCodeInterno($datos["idEmpresa"]);

            $empresa = $this->empresa->find($datos["idEmpresa"]);

            $datos["folio"] = $ultimoFolio;

            $datos["balance"] = $datos["total"] - ($datos["importPayment"] - $datos["importBack"]);

            try {


                if ($this->inventory->save($datos) === false) {

                    $errores = $this->inventory->errors();

                    $listErrors = "";

                    foreach ($errores as $field => $error) {

                        $listErrors .= $error . " ";
                    }

                    echo $listErrors;

                    return;
                }

                $idInventoryInserted = $this->inventory->getInsertID();

                // save datail

                foreach ($listProducts as $key => $value) {

                    $datosDetalle["idInventory"] = $idInventoryInserted;
                    $datosDetalle["idProduct"] = $value["idProduct"];
                    $datosDetalle["lote"] = $value["lote"];
                    $datosDetalle["description"] = $value["description"];
                    $datosDetalle["unidad"] = $value["unidad"];
                    $datosDetalle["codeProduct"] = $value["codeProduct"];
                    $datosDetalle["cant"] = $value["cant"];
                    $datosDetalle["price"] = $value["price"];
                    $datosDetalle["porcentTax"] = $value["porcentTax"];

                    $datosDetalle["porcentIVARetenido"] = $value["porcentIVARetenido"];
                    $datosDetalle["porcentISRRetenido"] = $value["porcentISRRetenido"];
                    $datosDetalle["IVARetenido"] = $value["IVARetenido"];
                    $datosDetalle["ISRRetenido"] = $value["ISRRetenido"];

                    $datosDetalle["claveProductoSAT"] = $value["claveProductoSAT"];
                    $datosDetalle["claveUnidadSAT"] = $value["claveUnidadSAT"];

                    $datosDetalle["tax"] = $value["tax"];
                    $datosDetalle["total"] = $value["total"];
                    $datosDetalle["neto"] = $value["neto"];

                    //Valida Stock
                    $products = $this->products->find($datosDetalle["idProduct"]);

                    if ($products["validateStock"] == "on") {

                        $datosSaldo["idEmpresa"] = $datos["idEmpresa"];
                        $datosSaldo["idAlmacen"] = $datos["idStorage"];
                        $datosSaldo["idProducto"] = $datosDetalle["idProduct"];
                        $datosSaldo["lote"] = $datosDetalle["lote"];

                        if ($tiposMovimiento["tipo"] == "ENT") {

                            //VERIFICAMOS STOCK ACTUAL

                            $existeSaldo = $this->saldos->where($datosSaldo)->countAllResults();

                            if ($existeSaldo == 0) {

                                $datosSaldo["cantidad"] = $datosDetalle["cant"];

                                $products["stock"] = $products["stock"] + $datosDetalle["cant"];

                                $stockNuevoProducto["stock"] = $products["stock"];

                                if ($this->products->update($products["id"], $stockNuevoProducto) === false) {

                                    echo "error al actualizar el stock en el producto $datosDetalle[idProduct]";

                                    $this->inventory->db->transRollback();
                                    return;
                                }

                                if ($this->saldos->save($datosSaldo) === false) {


                                    $errores = $this->saldos->errors();

                                    $listErrors = "";

                                    foreach ($errores as $field => $error) {

                                        $listErrors .= $error . " ";
                                    }

                                    echo $listErrors . " error al insertar el saldo $datosDetalle[idProduct]";

                                    $this->inventory->db->transRollback();
                                    return;
                                }
                            } else {


                                $datosNuevosSaldo = $this->saldos->select("*")->where($datosSaldo)->first();

                                $datosNuevosSaldo["cantidad"] = $datosNuevosSaldo["cantidad"] + $datosDetalle["cant"];

                                $products["stock"] = $products["stock"] + $datosDetalle["cant"];

                                $stockNuevoProducto["stock"] = $products["stock"];

                                if ($this->products->update($products["id"], $stockNuevoProducto) === false) {

                                    echo "error al actualizar el stock en el producto $datosDetalle[idProduct]";

                                    $this->inventory->db->transRollback();
                                    return;
                                }


                                if ($this->saldos->update($datosNuevosSaldo["id"], $datosNuevosSaldo) === false) {

                                    echo "error al actualizar el saldo $datosDetalle[idProduct]";

                                    $this->inventory->db->transRollback();
                                    return;
                                }
                            }
                        }

                        /**
                         * Si es salida
                         */
                        if ($tiposMovimiento["tipo"] == "SAL") {


                            /**
                             * Verificamos saldo
                             */
                            $datosNuevosSaldo = $this->saldos->select("*")->where($datosSaldo)->first();

                            if ($datosNuevosSaldo["cantidad"] < $datosDetalle["cant"]) {

                                echo "Stock agotado en el producto " . $datosDetalle["description"];
                                $this->inventory->db->transRollback();
                                return;
                            }

                            $datosNuevosSaldo["cantidad"] = $datosNuevosSaldo["cantidad"] - $datosDetalle["cant"];

                            $existenciaProducto["stock"] = $products["stock"] - $datosDetalle["cant"];

                            if ($this->products->update($products["id"], $existenciaProducto) === false) {

                                echo "error al actualizar el saldo $datosDetalle[idProduct]";

                                $this->inventory->db->transRollback();
                                return;
                            }


                            if ($this->saldos->update($datosNuevosSaldo["id"], $datosNuevosSaldo) === false) {



                                $errores = $this->inventory->errors();

                                $listErrors = "";

                                foreach ($errores as $field => $error) {

                                    $listErrors .= $error . " ";
                                }

                                echo $listErrors . " error al actualizar el saldo $datosDetalle[idProduct]";
                                ;

                                $this->inventory->db->transRollback();
                                return;
                            }
                        }
                    }


                    if ($this->inventoryDetail->save($datosDetalle) === false) {

                        $errores = $this->inventory->errors();

                        $listErrors = "";

                        foreach ($errores as $field => $error) {

                            $listErrors .= $error . " ";
                        }

                        echo $listErrors . " error al actualizar el saldo $datosDetalle[idProduct]";
                        ;

                        $this->inventory->db->transRollback();
                        return;

                        $this->inventoryDetail->db->transRollback();
                        return;
                    } else {
                        
                    }
                }





                /**
                 * if Payments i mayor to cero
                 */
                /*
                  if ($datos["importPayment"] > 0) {

                  $dataPayment["idSell"] = $idSellInserted;
                  $dataPayment["importPayment"] = $datos["importPayment"];
                  $dataPayment["importBack"] = $datos["importBack"];
                  $dataPayment["datePayment"] = $datos["datePayment"];
                  $dataPayment["metodPayment"] = $datos["metodoPago"];

                  try {


                  if ($this->payments->save($dataPayment) === false) {

                  echo "error al insertar el pago ";

                  $this->sellsDetail->db->transRollback();
                  return;
                  }
                  } catch (\Exception $e) {


                  $this->sellsDetail->db->transRollback();
                  echo $e->getMessage();
                  return;
                  }
                  }
                 * 
                 */

                //ACTUALIZAMOS FOLIO ACTUAL COMPROBANTE



                $datosBitacora["description"] = "Se guardo la cotizacion con los siguientes datos" . json_encode($datos);
                $datosBitacora["user"] = $userName;

                $this->log->save($datosBitacora);

                $this->inventory->db->transCommit();
                echo "Guardado Correctamente";
            } catch (\PHPUnit\Framework\Exception $ex) {


                echo "Error al guardar " . $ex->getMessage();
            }
        } else {




            $backInventory = $this->inventory->where("UUID", $datos["UUID"])->first();
            $listProductsBack = json_decode($backInventory["listProducts"], true);

            $datos["folio"] = $backInventory["folio"];

            if ($this->inventory->update($backInventory["id"], $datos) == false) {

                $errores = $this->inventory->errors();
                $listError = "";
                foreach ($errores as $field => $error) {

                    $listError .= $error . " ";
                }

                echo $listError;

                return;
            } else {



                //DEJAMOS EL STOCK COMO ESTABA ANTES

                foreach ($listProductsBack as $key => $value) {


                    if ($tiposMovimiento["tipo"] == "ENT") {
                        //BUSCAMOS STOCK DEL PRODUCTO
                        $products = $this->products->find($value["idProduct"]);

                        $productsBackStock["stock"] = $products["stock"] - $value["cant"];

                        // ACTUALIZA STOCK
                        $newStock["stock"] = $products["stock"] - $value["cant"];

                        if ($this->products->update($value["idProduct"], $newStock) === false) {

                            echo "error al actualizar el stock del producto $value[idProducto]";

                            $this->inventory->db->transRollback();
                            return;
                        }


                        $datosSaldo["idEmpresa"] = $datos["idEmpresa"];
                        $datosSaldo["idAlmacen"] = $datos["idStorage"];
                        $datosSaldo["idProducto"] = $value["idProduct"];
                        $datosSaldo["lote"] = $value["lote"];

                        $datosNuevosSaldo = $this->saldos->select("*")->where($datosSaldo)->first();

                        $datosNuevosSaldo["cantidad"] = $datosNuevosSaldo["cantidad"] - $value["cant"];

                        if ($datosNuevosSaldo["cantidad"] > 0) {
                            if ($this->saldos->update($datosNuevosSaldo["id"], $datosNuevosSaldo) === false) {

                                echo "error al actualizar el saldo $datosDetalle[idProducto]";

                                $this->inventory->db->transRollback();
                                return;
                            }
                        } else {


                            if ($this->saldos->select("*")->where("id", $datosNuevosSaldo["id"])->delete() === false) {

                                echo "error al actualizar el saldo $datosDetalle[idProducto]";

                                $this->inventory->db->transRollback();
                                return;
                            }

                            $this->saldos->purgeDeleted();
                        }
                    }


                    if ($tiposMovimiento["tipo"] == "SAL") {
                        //BUSCAMOS STOCK DEL PRODUCTO
                        $products = $this->products->find($value["idProduct"]);

                        // ACTUALIZA STOCK
                        $newStock = $products["stock"] + $value["cant"];

                        $updateDataStock["stock"] = $newStock;
                        if ($this->products->update($value["idProduct"], $updateDataStock) === false) {

                            echo "error al actualizar el stock del producto $value[idProducto]";

                            $this->inventory->db->transRollback();
                            return;
                        }


                        $datosSaldo["idEmpresa"] = $datos["idEmpresa"];
                        $datosSaldo["idAlmacen"] = $datos["idAlmacen"];
                        $datosSaldo["idProducto"] = $value["idProduct"];
                        $datosSaldo["lote"] = $value["lote"];

                        $datosNuevosSaldo = $this->saldos->select("*")->where($datosSaldo)->first();

                        $datosNuevosSaldo["cantidad"] = $datosNuevosSaldo["cantidad"] + $value["cant"];

                        if ($this->saldos->update($datosNuevosSaldo["id"], $datosNuevosSaldo) === false) {

                            echo "error al actualizar el saldo $datosDetalle[idProducto]";

                            $this->inventory->db->transRollback();
                            return;
                        }
                    }


                    //REGRESAMOS EL SALDO A COMO ESTABA ANTES
                }

                $this->inventoryDetail->select("*")->where("idInventory", $backInventory["id"])->delete();
                $this->inventoryDetail->purgeDeleted();
                foreach ($listProducts as $key => $value) {

                    $datosDetalle["idInventory"] = $backInventory["id"];
                    $datosDetalle["idProduct"] = $value["idProduct"];
                    $datosDetalle["lote"] = $value["lote"];
                    $datosDetalle["description"] = $value["description"];
                    $datosDetalle["unidad"] = $value["unidad"];
                    $datosDetalle["codeProduct"] = $value["codeProduct"];
                    $datosDetalle["cant"] = $value["cant"];
                    $datosDetalle["price"] = $value["price"];
                    $datosDetalle["porcentTax"] = $value["porcentTax"];

                    $datosDetalle["porcentIVARetenido"] = $value["porcentIVARetenido"];
                    $datosDetalle["porcentISRRetenido"] = $value["porcentISRRetenido"];
                    $datosDetalle["IVARetenido"] = $value["IVARetenido"];
                    $datosDetalle["ISRRetenido"] = $value["ISRRetenido"];

                    $datosDetalle["claveProductoSAT"] = $value["claveProductoSAT"];
                    $datosDetalle["claveUnidadSAT"] = $value["claveUnidadSAT"];

                    $datosDetalle["tax"] = $value["tax"];
                    $datosDetalle["total"] = $value["total"];
                    $datosDetalle["neto"] = $value["neto"];

                    if ($this->inventoryDetail->save($datosDetalle) === false) {

                        echo "error al insertar el producto $datosDetalle[idProducto]";

                        $this->inventory->db->transRollback();
                        return;
                    } else {

                        //SI ES ENTRADA CAMBIAMOS EL SALDO
                        if ($datos["tipoES"] == "ENT") {

                            $datosSaldo["idEmpresa"] = $datos["idEmpresa"];

                            $datosSaldo["idAlmacen"] = $datos["idStorage"];
                            $datosSaldo["idProducto"] = $datosDetalle["idProduct"];
                            $datosSaldo["lote"] = $datosDetalle["lote"];

                            if ($this->saldos->select("*")->where($datosSaldo)->countAllResults() > 0) {
                                $saldoLote = $this->saldos->select("*")->where($datosSaldo)->first();
                            }
                            $products = $this->products->select("*")->where("id", $datosSaldo["idProducto"])->first();

                            $stockNuevoProducto["stock"] = $products["stock"] + $datosDetalle["cant"];

                            if (isset($saldoLote)) {

                                $datosNuevosSaldo["cantidad"] = $saldoLote["cantidad"] + $datosDetalle["cant"];
                            } else {

                                $datosNuevosSaldo["cantidad"] = $datosDetalle["cant"];
                            }

                            if ($this->products->update($products["id"], $stockNuevoProducto) === false) {

                                echo "error al actualizar el saldo en el producto $datosDetalle[idProducto]";

                                $this->inventory->db->transRollback();
                                return;
                            }


                            if (isset($saldoLote)) {
                                if ($this->saldos->update($saldoLote["id"], $datosNuevosSaldo) === false) {

                                    echo "error al actualizar el saldo $datosDetalle[idProducto]";

                                    $this->inventory->db->transRollback();
                                    return;
                                }
                            } else {

                                $datosSaldo["cantidad"] = $datosNuevosSaldo["cantidad"];
                                if ($this->saldos->save($datosSaldo) === false) {

                                    echo "error al actualizar el saldo $datosDetalle[idProducto]";

                                    $this->inventory->db->transRollback();
                                    return;
                                }
                            }
                        }


                        if ($products["validateStock"] == "on" && $datos["tipoES"] == "SAL") {
                            if ($products["stock"] < $datosDetalle["cant"]) {

                                echo "Stock agotado en el producto " . $datosDetalle["description"];
                                $this->inventoryDetail->db->transRollback();
                                return;
                            }
                            //BUSCAMOS STOCK DEL PRODUCTO
                            $products = $this->products->find($value["idProduct"]);
                            // ACTUALIZA STOCK
                            $newStock = $products["stock"] - $datosDetalle["cant"];

                            $updateDataStock["stock"] = $newStock;

                            $datosSaldo["idEmpresa"] = $datos["idEmpresa"];

                            $datosSaldo["idAlmacen"] = $datos["idStorage"];
                            $datosSaldo["idProducto"] = $datosDetalle["idProduct"];
                            $datosSaldo["lote"] = $datosDetalle["lote"];

                            $datosNuevosSaldo = $this->saldos->select("*")->where($datosSaldo)->first();

                            $datosNuevosSaldo["cantidad"] = $datosNuevosSaldo["cantidad"] - $datosDetalle["cant"];

                            if ($this->products->update($datosDetalle["idProduct"], $updateDataStock) === false) {

                                echo "error al actualizar el stock del producto $datosDetalle[idProducto]";

                                $this->inventory->db->transRollback();
                                return;
                            }


                            if ($this->saldos->update($datosNuevosSaldo["id"], $datosNuevosSaldo) === false) {

                                echo "error al actualizar el saldo $datosDetalle[idProducto]";

                                $this->inventory->db->transRollback();
                                return;
                            }
                        }
                    }
                }


                $datosBitacora["description"] = "Se actualizo" . json_encode($datos) .
                        " Los datos anteriores son" . json_encode($backInventory);
                $datosBitacora["user"] = $userName;
                $this->log->save($datosBitacora);

                echo "Actualizado Correctamente";
                $this->inventory->db->transCommit();
                return;
            }
        }

        return;
    }

    public function delete($id) {
        helper('auth');
        $userName = user()->username;
        $idUser = user()->id;

        $auth = service('authentication');
        if (!$auth->check()) {

            return redirect()->route('admin');
        }


        $auth = service('authentication');
        if (!$auth->check()) {

            return redirect()->route('admin');
        }

        helper('auth');
        $userName = user()->username;
        $idUser = user()->id;

        $titulos["empresas"] = $this->empresa->mdlEmpresasPorUsuario($idUser);

        if (count($titulos["empresas"]) == "0") {

            $empresasID[0] = "0";
        } else {

            $empresasID = array_column($titulos["empresas"], "id");
        }


        if ($this->inventory->select("*")->whereIn("idEmpresa", $empresasID)->where("id", $id)->countAllResults() == 0) {

            return $this->failNotFound('Acceso Prohibido');
        }

        $this->inventory->db->transBegin();

        $infoInventory = $this->inventory->find($id);

        if (!$found = $this->inventory->delete($id)) {
            $this->inventory->db->transRollback();
            return $this->failNotFound('Error al eliminar');
        }

        //Borramos quotesdetails

        if ($this->inventoryDetail->select("*")->where("idInventory", $id)->delete() === false) {

            $this->inventoryDetail->db->transRollback();
            return $this->failNotFound('Error al eliminar el detalle');
        }

        $this->inventoryDetail->purgeDeleted();

        $listProducts = json_decode($infoInventory["listProducts"], true);
        $this->inventory->purgeDeleted();

        //Devolvemos el Stock

        foreach ($listProducts as $key => $value) {


            if ($infoInventory["tipoES"] == "ENT") {


                $product = $this->products->find($value["idProduct"]);

                $stock = $product["stock"] - $value["cant"];

                $newStock["stock"] = $stock;

                if ($this->products->update($value["idProduct"], $newStock) === false) {

                    $this->inventory->db->transRollback();
                    return $this->failNotFound('Error al actualizar el Stock');
                }


                $datosSaldo["idEmpresa"] = $infoInventory["idEmpresa"];

                $datosSaldo["idAlmacen"] = $infoInventory["idStorage"];
                $datosSaldo["idProducto"] = $value["idProduct"];
                $datosSaldo["lote"] = $value["lote"];

                $datosNuevosSaldo = $this->saldos->select("*")->where($datosSaldo)->first();

                $nuevoSaldo["cantidad"] = $datosNuevosSaldo["cantidad"] - $value["cant"];

                if ($nuevoSaldo["cantidad"] > 0) {
                    if ($this->saldos->update($datosNuevosSaldo["id"], $nuevoSaldo) === false) {

                        echo "error al actualizar el saldo del producto $datosDetalle[idProducto]";

                        $this->inventory->db->transRollback();
                        return;
                    }
                } else {

                    if ($this->saldos->select("*")->where("id", $datosNuevosSaldo["id"])->delete() === false) {

                        echo "error al actualizar el saldo del producto $datosDetalle[idProducto]";

                        $this->inventory->db->transRollback();
                        return;
                    }

                    $this->saldos->purgeDeleted();
                }
            }



            if ($infoInventory["tipoES"] == "SAL") {


                $product = $this->products->find($value["idProduct"]);

                $stock = $product["stock"] + $value["cant"];

                $newStock["stock"] = $stock;

                if ($this->products->update($datosNuevosSaldo["id"], $newStock) === false) {

                    $this->inventory->db->transRollback();
                    return $this->failNotFound('Error al actualizar el Stock');
                }


                $datosSaldo["idEmpresa"] = $infoInventory["idEmpresa"];

                $datosSaldo["idAlmacen"] = $infoInventory["idStorage"];
                $datosSaldo["idProducto"] = $value["idProduct"];
                $datosSaldo["lote"] = $value["lote"];

                $datosNuevosSaldo = $this->saldos->select("*")->where($datosSaldo)->first();

                $nuevoSaldo["cantidad"] = $datosNuevosSaldo["cantidad"] + $value["cant"];

                if ($this->saldos->update($datosNuevosSaldo["id"], $nuevoSaldo) === false) {

                    echo "error al actualizar el saldo del producto $datosDetalle[idProducto]";

                    $this->inventory->db->transRollback();
                    return;
                }
            }
        }


        $datosBitacora["description"] = 'Se elimino el Registro' . json_encode($infoInventory);

        $this->log->save($datosBitacora);

        $this->inventory->db->transCommit();
        return $this->respondDeleted($found, 'Eliminado Correctamente');
    }

    /*

      public function delete($id) {

      if (!$found = $this->register->delete($id)) {
      return $this->failNotFound('Error al eliminar');
      }

      $infoConsukta = $this->register->find($id);

      $this->register->purgeDeleted();

      $datosBitacora["description"] = 'Se elimino el Registro' . json_encode($infoConsukta);

      $this->log->save($datosBitacora);
      return $this->respondDeleted($found, 'Eliminado Correctamente');
      }

      /**
     * Trae en formato JSON los pacientes para el select2
     * @return type
     */

    /*
      public function traerPacientesAjax() {

      $request = service('request');
      $postData = $request->getPost();

      $response = array();

      // Read new token and assign in $response['token']
      $response['token'] = csrf_hash();

      if (!isset($postData['searchTerm'])) {
      // Fetch record
      $pacientes = new PacientesModel();
      $listaPacientes = $pacientes->select('id,nombres,apellidos')
      ->orderBy('nombres')
      ->findAll(10);
      } else {
      $searchTerm = $postData['searchTerm'];

      // Fetch record
      $pacientes = new PacientesModel();
      $listaPacientes = $pacientes->select('id,nombres,apellidos')
      ->where("deleted_at", null)
      ->like('nombres', $searchTerm)
      ->orLike('apellidos', $searchTerm)
      ->orderBy('nombres')
      ->findAll(10);
      }

      $data = array();
      foreach ($listaPacientes as $paciente) {
      $data[] = array(
      "id" => $paciente['id'],
      "text" => $paciente['nombres'] . ' ' . $paciente['apellidos'],
      );
      }

      $response['data'] = $data;

      return $this->response->setJSON($response);
      } */

    /**
     * Reporte Consulta
     */
    public function report($uuid, $isMail = 0) {

        $pdf = new PDFLayout(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);

        $dataSells = $this->sells->where("uuid", $uuid)->first();

        $listProducts = json_decode($dataSells["listProducts"], true);

        $user = $this->user->where("id", $dataSells["idUser"])->first()->toArray();

        $custumer = $this->custumer->where("id", $dataSells["idCustumer"])->where("deleted_at", null)->first();

        $datosEmpresa = $this->empresa->select("*")->where("id", $dataSells["idEmpresa"])->first();
        $datosEmpresaObj = $this->empresa->select("*")->where("id", $dataSells["idEmpresa"])->asObject()->first();

        $pdf->nombreDocumento = "Nota De Venta";
        $pdf->direccion = $datosEmpresaObj->direccion;

        if ($datosEmpresaObj->logo == NULL || $datosEmpresaObj->logo == "") {

            $pdf->logo = ROOTPATH . "public/images/logo/default.png";
        } else {

            $pdf->logo = ROOTPATH . "public/images/logo/" . $datosEmpresaObj->logo;
        }
        $pdf->folio = str_pad($dataSells["folio"], 5, "0", STR_PAD_LEFT);

        $folioConsulta = "Folio Consulta";
        $fecha = " Fecha: ";

        // set document information
        $pdf->nombreEmpresa = $datosEmpresa["nombre"];
        $pdf->direccion = $datosEmpresa["direccion"];
        $pdf->usuario = $user["firstname"] . " " . $user["lastname"];
        $pdf->SetCreator(PDF_CREATOR);
        $pdf->SetAuthor($user["username"]);
        $pdf->SetTitle('CI4JCPOS');
        $pdf->SetSubject('CI4JCPOS');
        $pdf->SetKeywords('CI4JCPOS, PDF, PHP, CodeIgniter, CESARSYSTEMS.COM.MX');

        // set default header data
        $pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, PDF_HEADER_TITLE, PDF_HEADER_STRING);

        // set header and footer fonts
        $pdf->setHeaderFont(array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
        $pdf->setFooterFont(array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));

        // set default monospaced font
        $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);

        // set margins
        $pdf->SetMargins(PDF_MARGIN_LEFT, 35, PDF_MARGIN_RIGHT);
        $pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
        $pdf->SetFooterMargin(PDF_MARGIN_FOOTER);

        // set auto page breaks
        $pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);

        // set image scale factor
        $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);

        // ---------------------------------------------------------
        // add a page
        $pdf->AddPage();

        $pdf->SetY(45);
        //ETIQUETAS
        $cliente = "Cliente: ";
        $folioRegistro = " Folio: ";
        $fecha = " Fecha:";

        $pdf->SetY(45);
        //ETIQUETAS
        $cliente = "Cliente: ";
        $folioRegistro = " Folio: ";
        $fecha = " Fecha:";

        // set font
        //$pdf->SetFont('times', '', 12);

        if ($datosEmpresa["facturacionRD"] == "on" && $dataSells["folioComprobanteRD"] > 0) {


            $comprobante = $this->comprobantesRD->find($dataSells["tipoComprobanteRD"]);
            if ($comprobante["tipoDocumento"] == "COF") {
                $tipoDocumento = "FACTURA PARA CONSUMIDOR FINAL";
            }

            if ($comprobante["tipoDocumento"] == "CF") {
                $tipoDocumento = "FACTURA PARA CREDITO FISCAL";
            }

            $comprobanteFactura = $comprobante["prefijo"] . str_pad($dataSells["folioComprobanteRD"], 10, "0", STR_PAD_LEFT);
            $fechaVencimiento = "AUTORIZADO POR DGII :" . $comprobante["hastaFecha"];
        } else {

            $tipoDocumento = "";
            $comprobanteFactura = "";
            $fechaVencimiento = "";
        }

        $bloque2 = <<<EOF

    
        <table style="font-size:10px; padding:0px 10px;">
    
             <tr>
               <td style="width: 50%; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white;">ATENCION A
               </td>
               <td style="width: 50%; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white;">OBSERVACIONES
               </td>
            </tr>
            <tr>
    
                <td >
    
    
                Cliente: $custumer[firstname] $custumer[lastname] 
    
                    <br>
                    Telefono: 000
                    <br>
                    E-Mail: $custumer[email]
                    <br>
                </td>
                <td >
                    $dataSells[generalObservations]
                    $tipoDocumento  <br>
                    $comprobanteFactura  <br>
                    $fechaVencimiento <br>
                </td>
    
    
            </tr>
    
            <tr>
    
                <td style="width: 25%; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white;">VENDEDOR
                </td>
    
                <td style="width: 24%; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white;">FECHA
                </td>
                <td style="width: 30%; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white;">FECHA DE VENCIMIENTO
                </td>
    
    
                <td style="width: 21%; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white;">VIGENCIA
                </td>
    
            </tr>
            <tr>
                    <td>
                        $user[firstname] $user[lastname]
                    </td>
                    <td>
                    $dataSells[date]
                    </td>
                    <td>
                    $dataSells[dateVen]
                    </td>
                    <td>
                    $dataSells[delivaryTime]
                    </td>
            </tr>
            <tr>
                <td style="border-bottom: 1px solid #666; background-color:white; width:640px"></td>
            </tr>
        </table>
    EOF;

        $pdf->writeHTML($bloque2, false, false, false, false, '');

        $bloque3 = <<<EOF

        <table style="font-size:10px; padding:5px 10px;">
    
            <tr>
    
            <td style="width: 100px; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white; text-align:center">Código</td>
            <td style="width: 200px; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white; text-align:center">Descripción</td>
                     <td style="width: 60px; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white; text-align:center">Cant</td>
    
            <td style="width: 80px; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white; text-align:center">Precio</td>
            <td style="width: 100px; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white; text-align:center">SubTotal</td>
            <td style="width: 100px; background-color:#2c3e50; padding: 4px 4px 4px; font-weight:bold;  color:white; text-align:center">Total</td>
    
            </tr>
    
        </table>
    
    EOF;

        $pdf->writeHTML($bloque3, false, false, false, false, '');

        $contador = 0;
        foreach ($listProducts as $key => $value) {



            if ($contador % 2 == 0) {
                $clase = 'style=" background-color:#ecf0f1; padding: 3px 4px 3px; ';
            } else {
                $clase = 'style="background-color:white; padding: 3px 4px 3px; ';
            }

            $precio = number_format($value["price"], 2, ".");
            $subTotal = number_format($value["total"], 2, ".");
            $total = number_format($value["neto"], 2, ".");
            $bloque4 = <<<EOF
    
        <table style="font-size:10px; padding:5px 10px;">
    
            <tr>
    
                <td  $clase width:100px; text-align:center">
                    $value[codeProduct]
                </td>
    
    
                <td  $clase width:200px; text-align:center">
                    $value[description]
                </td>
    
                <td $clase width:60px; text-align:center">
                    $value[cant]
                </td>
    
                <td $clase width:80px; text-align:right">
                    $precio
                </td>
    
                <td $clase width:100px; text-align:center">
                $subTotal
            </td>
    
                <td $clase width:100px; text-align:right">
                $total
                </td>
    
               
    
    
            </tr>
    
        </table>
    
    
    EOF;
            $contador++;
            $pdf->writeHTML($bloque4, false, false, false, false, '');
        }




        /**
         * TOTALES
         */
        $pdf->Setx(43);
        $subTotal = number_format($dataSells["subTotal"], 2, ".");
        $impuestos = number_format($dataSells["taxes"], 2, ".");
        $total = number_format($dataSells["total"], 2, ".");
        $IVARetenido = number_format($dataSells["IVARetenido"], 2, ".");
        $ISRRetenido = number_format($dataSells["ISRRetenido"], 2, ".");

        if ($IVARetenido > 0) {

            $bloqueIVARetenido = <<<EOF
                    <tr>
            
                    <td style="border-right: 0px solid #666; color:#333; background-color:white; width:340px; text-align:right"></td>
    
                    <td style="border: 0px solid #666; background-color:white; width:100px; text-align:right">
                    IVA Retenido:
                    </td>
    
                    <td style="border: 0px solid #666; color:#333; background-color:white; width:100px; text-align:right">
                        $IVARetenido
                    </td>
    
                </tr>
    
            EOF;
        } else {

            $bloqueIVARetenido = "";
        }


        if ($ISRRetenido > 0) {

            $bloqueISRRetenido = <<<EOF
                    <tr>
            
                    <td style="border-right: 0px solid #666; color:#333; background-color:white; width:340px; text-align:right"></td>
    
                    <td style="border: 0px solid #666; background-color:white; width:100px; text-align:right">
                    ISR Retenido:
                    </td>
    
                    <td style="border: 0px solid #666; color:#333; background-color:white; width:100px; text-align:right">
                        $ISRRetenido
                    </td>
    
                </tr>
    
            EOF;
        } else {

            $bloqueISRRetenido = "";
        }





        $bloque5 = <<<EOF

      <table style="font-size:10px; padding:5px 10px;">
  
          <tr>
  
              <td style="color:#333; background-color:white; width:340px; text-align:right"></td>
  
              <td style="border-bottom: 0px solid #666; background-color:white; width:100px; text-align:right"></td>
  
              <td style="border-bottom: 0px solid #666; color:#333; background-color:white; width:100px; text-align:right"></td>
  
          </tr>
  
          <tr>
  
              <td style="border-right: 0px solid #666; color:#333; background-color:white; width:340px; text-align:right"></td>
  
              <td style="border: 0px solid #666;  background-color:white; width:100px; text-align:right">
              Subtotal:
              </td>
  
              <td style="border: 0px solid #666; color:#333; background-color:white; width:100px; text-align:right">
                   $subTotal
              </td>
  
          </tr>
  
          <tr>
  
              <td style="border-right: 0px solid #666; color:#333; background-color:white; width:340px; text-align:right"></td>
  
              <td style="border: 0px solid #666; background-color:white; width:100px; text-align:right">
               IVA:
              </td>
  
              <td style="border: 0px solid #666; color:#333; background-color:white; width:100px; text-align:right">
                   $impuestos
              </td>
  
          </tr>
  
  
          $bloqueIVARetenido
          $bloqueISRRetenido
  
  
          <tr>
  
              <td style="border-right: 0px solid #666; color:#333; background-color:white; width:340px; text-align:right"></td>
  
              <td style="border: 0px solid #666; background-color:white; width:100px; text-align:right">
                  Total:
              </td>
  
              <td style="border: 0px solid #666; color:#333; background-color:white; width:100px; text-align:right">
                  $ $total
              </td>
  
          </tr>
  
  
      </table>
      <br>
      <div style="font-size:11pt;text-align:center;font-weight:bold">Gracias por su compra!</div>
  <br><br>
                  
          <div style="font-size:8.5pt;text-align:left;font-weight:ligth">UUID DOCUMENTO: $dataSells[UUID]</div>
          
     
      <div style="font-size:8.5pt;text-align:left;font-weight:ligth">ES RESPONSABILIDAD DEL CLIENTE REVISAR A DETALLE ESTA COTIZACION PARA SU POSTERIOR SURTIDO, UNA VEZ CONFIRMADA, NO HAY CAMBIOS NI DEVOLUCIONES.</div>
  
      
  
  
  EOF;

        $pdf->writeHTML($bloque5, false, false, false, false, 'R');

        if ($isMail == 0) {
            $this->response->setHeader("Content-Type", "application/pdf");
            $pdf->Output('notaVenta.pdf', 'I');
        } else {

            $attachment = $pdf->Output('notaVenta.pdf', 'S');

            return $attachment;
        }


        //============================================================+
        // END OF FILE
        //============================================================+
    }

}

Creamos el archivo para crear el nuevo kardex de inventario en App/Views/newInventory.php con el siguiente código

<?= $this->include('load/toggle') ?>
<?= $this->include('julio101290\boilerplate\Views\load\select2') ?>
<?= $this->include('julio101290\boilerplate\Views\load\datatables') ?>
<?= $this->include('julio101290\boilerplate\Views\load\nestable') ?>
<!-- Extend from layout index -->
<?= $this->extend('julio101290\boilerplate\Views\layout\index') ?>

<!-- Section content -->
<?= $this->section('content') ?>

<?= $this->include('modulesInventory/dataHeadInventory') ?>
<?= $this->include('modulesInventory/productosModalInventory') ?>
<?= $this->include('modulesInventory/modalPayment') ?>
<?= $this->include('modulesInventory/moreInfoRow') ?>
<?= $this->include('modulesProducts/modalCaptureProducts') ?>
<?= $this->include('modulesCustumers/modalCaptureCustumers') ?>

<?= $this->endSection() ?>

Creamos el archivo de encabezado principal en App/Views/modulesInventory/dataHeadInventory.php con el siguiente código

<div class="row">

    <div class="col-12">

        <div class="card card-primary">
            <div class="card-header">
                <h3 class="card-title">Encabezado</h3>

                <div class="card-tools">
                    <button type="button" class="btn btn-tool" data-card-widget="collapse">
                        <i class="fas fa-minus"></i>
                    </button>

                </div>
            </div>



            <div class="card-body">


                <ul class="nav nav-tabs" id="myTab" role="tablist">
                    <li class="nav-item" role="presentation">
                        <button class="nav-link active" id="generales-tab" data-toggle="tab" data-target="#generales" type="button" role="tab" aria-controls="generales" aria-selected="true">Generales</button>
                    </li>
                    <li class="nav-item" role="presentation">
                        <button class="nav-link" id="profile-tab" data-toggle="tab" data-target="#otrosDatos" type="button" role="tab" aria-controls="otrosDatos" aria-selected="false">Otros
                            Datos</button>
                    </li>

                    <li class="nav-item" role="presentation">
                        <button class="nav-link" id="profile-tab" data-toggle="tab" data-target="#facturacionMX" type="button" role="tab" aria-controls="facturacionMX" aria-selected="false">
                            Facturación MX
                        </button>
                    </li>

                </ul>

                <div class="tab-content" id="myTabContent">
                    <div class="tab-pane fade show active" id="generales" role="tabpanel" aria-labelledby="generales">

                        <?= $this->include('modulesInventory/generalInventory') ?>

                    </div>

                    <div class="tab-pane fade" id="otrosDatos" role="tabpanel" aria-labelledby="otrosDatos">

                        <?= $this->include('modulesSells/otrosDatos') ?>

                    </div>


                    <div class="tab-pane fade" id="facturacionMX" role="tabpanel" aria-labelledby="otrosDatos">

                        <?= $this->include('modulesSells/facturacionMX') ?>

                    </div>




                </div>


            </div>

        </div>

    </div>

    <div class="row">
        <div class="col-12">
            <div class="card card-default">
                <div class="card-header">
                    <h3 class="card-title">Detalle del Inventario</h3>
                    <div class="card-tools">
                        <button type="button" class="btn btn-tool" data-card-widget="collapse">
                            <i class="fas fa-minus"></i>
                        </button>

                    </div>
                </div>

                <div class="card-body">
                    <div class="row">


                        <div class="col-md-12">

                            <div class="box-body">

                                <div class="box" style="overflow-y: scroll; height:250px;">




                                    <div class="row">

                                        <!--=====================================
                                    ENCABEZADO
                                    ======================================-->
                                        <div class="col-1"> # </div>
                                        <div class="col-1"> Codigo </div>
                                        <div class="col-1"> Lote </div>
                                        <div class="col-6"> Descripción </div>
                                        <div class="col-1">Cantidad </div>
                                        <div class="col-1">Precio </div>
                                        <div class="col-1">Total </div>


                                    </div>
                                    <hr class="hr" />
                                    <!--=====================================
                                ENTRADA PARA AGREGAR PRODUCTO
                                ======================================-->
                                    <div class="rowProducts">

                                        <?php
                                        if (isset($listProducts)) {

                                            $list = "";
                                            foreach ($listProducts as $key => $value) {


                                                if (!isset($value["porcentIVARetenido"])) {

                                                    $value["porcentIVARetenido"] = "0.00";
                                                }


                                                if (!isset($value["IVARetenido"])) {

                                                    $value["IVARetenido"] = "0.00";
                                                }

                                                if (!isset($value["porcentISRRetenido"])) {

                                                    $value["porcentISRRetenido"] = "0.00";
                                                }

                                                if (!isset($value["ISRRetenido"])) {

                                                    $value["ISRRetenido"] = "0.00";
                                                }

                                                if (!isset($value["claveProductoSAT"])) {

                                                    $value["claveProductoSAT"] = "";
                                                }

                                                if (!isset($value["claveUnidadSAT"])) {

                                                    $value["claveUnidadSAT"] = "";
                                                }


                                                if (!isset($value["unidad"])) {

                                                    $value["unidad"] = "";
                                                }

                                                $list .= <<<EOF
                                                    
                                                <div class="form-group row nuevoProduct"><div class="col-1"> <button type="button" class="btn btn-danger quitProduct"><span class="far fa-trash-alt"></button>
                                                <button type="button"  data-toggle="modal" data-target="#modelMoreInfoRow" class="btn btn-primary  btnInfo" ><span class="fa fa-fw fa-pencil-alt"></span></button>
                                                </div>
                                                <div class="col-1"> <input type="text" id="codeProduct" class="form-control codeProduct" name="codeProduct" value="$value[codeProduct]" required=""> 
                                                <input type="hidden" id="claveProductoSATR" class="form-control claveProductoSATR"  name="claveProductoSATR" value="$value[claveProductoSAT]" required="">
                                                <input type="hidden" id="claveUnidadSatR" class="form-control claveUnidadSatR"  name="claveUnidadSatR" value="$value[claveUnidadSAT]" required="">
                                                <input type="hidden" id="unidad" class="form-control unidad"  name="unidad" value="$value[unidad]" required="">
                                                </div>
                                                
                                                <div class="col-1"> <input type="text" id="lote" class="form-control lote" idproducto="$value[idProduct]" name="lote" value="$value[lote]" required=""> </div>
                                                <div class="col-6"> <input type="text" id="description" class="form-control description" idproducto="$value[idProduct]" name="description" value="$value[description]" required=""> </div>
                                                <div class="col-1"> <input type="number" id="cant" class="form-control cant" name="cant" value="$value[cant]" required=""> 
                                                
                                                <input type="hidden" id="porcentIVARetenido" class="form-control porcentIVARetenido" name="porcentIVARetenido" value="$value[porcentIVARetenido]" required="">
                                                <input type="hidden" id="porcentISRRetenido" class="form-control porcentISRRetenido" name="porcentISRRetenido" value="$value[porcentISRRetenido]" required="">
                                                <input type="hidden" id="porcentTax" class="form-control porcentTax" name="porcentTax" value="$value[porcentTax]" required=""></div>
                                                <div class="col-1"> <input type="number" id="price" class="form-control price" name="price" value="$value[price]" required="">
                                                
                                                <input type="hidden" id="IVARetenido" class="form-control IVARetenido" name="IVARetenido" value="$value[IVARetenido]" required="">
                                                <input type="hidden" id="ISRRetenido" class="form-control ISRRetenido" name="ISRRetenido" value="$value[ISRRetenido]" required="">
                                                
                                                <input type="hidden" id="tax" class="form-control tax" name="tax" value="$value[tax]" required=""> </div>
                                                <div class="col-1"> <input readonly="" type="number" id="total" class="form-control total" name="total" value="$value[total]" required="">
                                                <input type="hidden" id="neto" class="form-control neto" name="neto" value="$value[neto]" required="">
                                                </div></div>
                                                    
                                                    
                                            EOF;
                                            }

                                            echo $list;
                                        }
                                        ?>

                                    </div>

                                    <input type="hidden" id="listProducts" name="listProducts" value="[]">
                                    <!--=====================================
                                BOTÓN PARA AGREGAR PRODUCTO
                                ======================================-->


                                    <hr>
                                </div>
                            </div>



                            <div class="box-footer" style="
                                 text-align: right;
                                 ">
                                <div class="row form-group">

                                    <div class="col-7">

                                    </div>
                                    <div class="col-3" style="
                                         vertical-align: middle;
                                         ">
                                        <label style="vertical-align: sub;margin-bottom: 0px;">Sub Total:</label>
                                    </div>

                                    <div class="col-2">
                                        <input readonly="" type="text" id="subTotal" class="form-control subTotal" name="subTotal" value="<?= $subTotal ?>" style="
                                               text-align: right;
                                               ">
                                    </div>


                                </div>


                                <div class="row form-group">

                                    <div class="col-7">

                                    </div>
                                    <div class="col-3" style="
                                         vertical-align: middle;
                                         ">
                                        <label style="
                                               vertical-align: sub;
                                               ">Impuesto:</label>
                                    </div>

                                    <div class="col-2">
                                        <input readonly="" type="text" id="totalImpuesto" class="form-control totalImpuesto" name="totalImpuesto" value="<?= $taxes ?>" style="
                                               text-align: right;
                                               ">
                                    </div>


                                </div>


                                <div class="row form-group grupoTotalRetencionIVA" hidden>

                                    <div class="col-7">

                                    </div>
                                    <div class="col-3" style="
                                         vertical-align: middle;
                                         ">
                                        <label style="
                                               vertical-align: sub;
                                               ">Retencion IVA:</label>
                                    </div>

                                    <div class="col-2">
                                        <input readonly="" type="text" id="totalRetencionIVA" class="form-control totalRetencionIVA" name="totalRetencionIVA" value="<?= $IVARetenido ?>" style="
                                               text-align: right;
                                               ">
                                    </div>


                                </div>


                                <div class="row form-group grupoTotalRetencionISR" hidden>

                                    <div class="col-7">

                                    </div>
                                    <div class="col-3" style="
                                         vertical-align: middle;
                                         ">
                                        <label style="
                                               vertical-align: sub;
                                               ">Retencion ISR:</label>
                                    </div>

                                    <div class="col-2">
                                        <input readonly="" type="text" id="totalRetencionISR" class="form-control totalRetencionISR" name="totalRetencionISR" value="<?= $ISRRetenido ?>" style="
                                               text-align: right;
                                               ">
                                    </div>


                                </div>

                                <div class="row form-group">

                                    <div class="col-7">

                                    </div>
                                    <div class="col-3" style="
                                         vertical-align: middle;
                                         ">
                                        <label style="
                                               vertical-align: sub;
                                               ">Total:</label>
                                    </div>

                                    <div class="col-2">
                                        <input readonly="" type="text" id="granTotal" class="form-control granTotal" name="granTotal" value="<?= $total ?>" style="
                                               text-align: right;
                                               ">
                                    </div>


                                </div>


                                <button type="button" class="btn btn-primary pull-right btnSaveInventory" data-toggle="modal">
                                    <i class="fa far fa-save"> </i>Guardar</button>

                                <button type="button" class="btn bg-maroon btnPrint" data-toggle="modal" required="" data-placement="top" title="Imprimir">
                                    <i class="fa fa-print"> </i> Guardar e Imprimir
                                </button>

                            </div>

                        </div>

                    </div>

                </div>

            </div>
        </div>
    </div>





    <?= $this->section('js') ?>


    <script>
        $("#metodoPagoVenta").select2();
        $("#usoCFDIVenta").select2();
        $("#formaPagoVenta").select2();
        $("#regimenFiscalReceptor").select2();
        /**
         * Obtiene el ultimo folio por almacen
         */

        $("#idEmpresaInventory").on("change", function () {


            var idEmpresa = $(this).val();
            console.log("ID EMPRESA", idEmpresa);
            var datos = new FormData();
            datos.append("idEmpresa", idEmpresa);
            // TRAE ULTIMO FOLIO
            $.ajax({

                url: "<?= base_url('admin/inventory/getLastCode') ?>",
                method: "POST",
                data: datos,
                cache: false,
                contentType: false,
                processData: false,
                dataType: "json",
                success: function (respuesta) {

                    //console.log(respuesta);

                    //$("#codeSell").val(respuesta["folio"]);


                }

            });
        });
        $("#idEmpresaInventory").select2();
        // Initialize select2 vendors
        $("#ProveedorInventory").select2({
            ajax: {
                url: "<?= site_url('admin/proveedores/getProveedoresAjax') ?>",
                type: "post",
                dataType: 'json',
                delay: 250,
                data: function (params) {
                    // CSRF Hash
                    var csrfName = $('.txt_csrfname').attr('name'); // CSRF Token name
                    var csrfHash = $('.txt_csrfname').val(); // CSRF hash
                    var idEmpresa = $('.idEmpresaInventory').val(); // CSRF hash

                    return {
                        searchTerm: params.term, // search term
                        [csrfName]: csrfHash, // CSRF Token
                        idEmpresa: idEmpresa // search term
                    };
                },
                processResults: function (response) {

                    // Update CSRF Token
                    $('.txt_csrfname').val(response.token);
                    return {
                        results: response.data
                    };
                },
                cache: true
            }
        });
        // Initialize select2 storages
        $("#idStorage").select2({
            ajax: {
                url: "<?= site_url('admin/storages/getStoragesAjax') ?>",
                type: "post",
                dataType: 'json',
                delay: 250,
                data: function (params) {
                    // CSRF Hash
                    var csrfName = $('.txt_csrfname').attr('name'); // CSRF Token name
                    var csrfHash = $('.txt_csrfname').val(); // CSRF hash
                    var idEmpresa = $('.idEmpresaInventory').val(); // CSRF hash

                    return {
                        searchTerm: params.term, // search term
                        [csrfName]: csrfHash, // CSRF Token
                        idEmpresa: idEmpresa // search term
                    };
                },
                processResults: function (response) {

                    // Update CSRF Token
                    $('.txt_csrfname').val(response.token);
                    return {
                        results: response.data
                    };
                },
                cache: true
            }
        });
        // Initialize select2 storages
        $("#idTipoMovimientoInventario").select2({
            ajax: {
                url: "<?= base_url('admin/tiposMovimientoInventario/getTiposMovimientoInventarioAjax') ?>",
                type: "post",
                dataType: 'json',
                delay: 250,
                data: function (params) {
                    // CSRF Hash
                    var csrfName = $('.txt_csrfname').attr('name'); // CSRF Token name
                    var csrfHash = $('.txt_csrfname').val(); // CSRF hash
                    var idEmpresa = $('.idEmpresaInventory').val(); // CSRF hash

                    return {
                        searchTerm: params.term, // search term
                        [csrfName]: csrfHash, // CSRF Token
                        idEmpresa: idEmpresa // search term
                    };
                },
                processResults: function (response) {

                    // Update CSRF Token
                    $('.txt_csrfname').val(response.token);
                    return {
                        results: response.data
                    };
                },
                cache: true
            }
        });


        $("#idStorage").on("change", function () {


            var idStorage = $(this).val();
            var idEmpresa = $("#idEmpresaInventory").val();
            var idTipoMovimiento = $("#idTipoMovimientoInventario").val();


            console.log("idAlmacen", idStorage);
            console.log("idEmpresa", idEmpresa);
            console.log("idTipoMovimiento", $(this).val());

            ultimoFolio(idEmpresa, idStorage, idTipoMovimiento);
            cargaProductos(idEmpresa, idStorage, idTipoMovimiento);


        });


        $("#idTipoMovimientoInventario").on("change", function () {


            var idStorage = $("#idStorage").val();
            var idEmpresa = $("#idEmpresaInventory").val();
            var idTipoMovimiento = $(this).val();


            console.log("idAlmacen", idStorage);
            console.log("idEmpresa", idEmpresa);
            console.log("idTipoMovimiento", $(this).val());

            ultimoFolio(idEmpresa, idStorage, idTipoMovimiento);
            cargaProductos(idEmpresa, idStorage, idTipoMovimiento);


        });



        function ultimoFolio(empresa, almacen, tipoMovimiento) {


            var datos = new FormData();
            datos.append("idEmpresa", empresa);
            datos.append("idStorage", almacen);
            datos.append("idTipoMovimiento", tipoMovimiento);
            // TRAE ULTIMO FOLIO
            $.ajax({

                url: "<?= base_url('admin/inventory/getLastCode') ?>",
                method: "POST",
                data: datos,
                cache: false,
                contentType: false,
                processData: false,
                dataType: "json",
                success: function (respuesta) {


                    console.log(respuesta);
                    $("#codeInventory").val(respuesta["folio"]);

                }

            });






        }





        /**
         * Get data Proveedor on change
         */

        $("#ProveedorInventory").on("change", function () {


            var idProveedor = $(this).val();
            var datos = new FormData();
            datos.append("idProveedor", idProveedor);
            // TRAE ULTIMO FOLIO
            $.ajax({

                url: "<?= base_url('admin/proveedor/getProveedors') ?>",
                method: "POST",
                data: datos,
                cache: false,
                contentType: false,
                processData: false,
                dataType: "json",
                success: function (respuesta) {


                    console.log(respuesta);
                    $("#RFCReceptor").val(respuesta["taxID"]);
                    $("#razonSocialReceptor").val(respuesta["razonSocial"]);
                    $("#codigoPostalReceptor").val(respuesta["codigoPostal"]);
                    $("#usoCFDIVenta").val(respuesta["usoCFDI"]);
                    $("#usoCFDIVenta").trigger("change");
                    $("#metodoPagoVenta").val(respuesta["metodoPago"]);
                    $("#metodoPagoVenta").trigger("change");
                    $("#formaPagoVenta").val(respuesta["formaPago"]);
                    $("#formaPagoVenta").trigger("change");
                    $("#regimenFiscalReceptor").val(respuesta["regimenFiscal"]);
                    $("#regimenFiscalReceptor").trigger("change");
                }

            });
        });
        $(".btnSavePayment").on("click", function () {

            var titulo = $("#titulo").val();
            listProducts();
            if (titulo == "Editar Cotizacion") {

                saveInventory();
            } else {


                $("#modalPayment").modal("toggle");
                saveInventory();
            }

        });
        /**
         * Save Quote
         */

        $(".btnSaveInventory").on("click", function () {

            listProducts();
            var titulo = $("#titulo").val();
            if (titulo == "Editar Cotizacion") {

                saveInventory();
            } else {

                $("#modalPayment").modal("toggle");
            }


        });
        function saveInventory() {


            var UUID = $("#uuid").val();
            var folio = $("#folio").val();
            var idQuote = $("#idQuote").val();
            var idEmpresa = $("#idEmpresaInventory").val();
            var idProveedor = $("#ProveedorInventory").val();
            var idStorage = $("#idStorage").val();
            var idTipoMovimientoInventario = $("#idTipoMovimientoInventario").val();
            var date = $("#date").val();
            var dateVen = $("#dateVen").val()
            var idUser = $("#idUser").val();
            var generalObservations = $("#obsevations").val();
            var listProducts = $("#listProducts").val();
            var quoteTo = $("#quoteTo").val();
            var delivaryTime = $("#delivaryTime").val();
            var subTotal = $("#subTotal").val();
            var taxes = $("#totalImpuesto").val();
            var IVARetenido = $("#totalRetencionIVA").val();
            var ISRRetenido = $("#totalRetencionISR").val();
            var total = $("#granTotal").val();
            var datePayment = $("#datePayment").val();
            var metodoPago = $("#metodoPago").val();
            var pago = $("#pago").val();
            var cambio = $("#cambio").val();
            var tipoComprobanteRD = $("#tipoComprobanteRD").val();
            var folioComprobanteRD = $("#folioComprobanteRD").val();
            var RFCReceptor = $("#RFCReceptor").val();
            var usoCFDIVenta = $("#usoCFDIVenta").val();
            var metodoPagoVenta = $("#metodoPagoVenta").val();
            var formaPagoVenta = $("#formaPagoVenta").val();
            var razonSocialReceptor = $("#razonSocialReceptor").val();
            var codigoPostalReceptor = $("#codigoPostalReceptor").val();
            var regimenFiscalReceptor = $("#regimenFiscalReceptor").val();
            var ajaxGuardarConsulta = "ajaxGuardarConsulta";
            /**
             * Validaciones
             * 
             */
            if (idEmpresa == 0 || idEmpresa == "") {

                Toast.fire({
                    icon: 'error',
                    title: "Tiene que seleccionar la empresa"
                });
                return false;
            }


            if (idProveedor == 0 || idProveedor == "") {

                Toast.fire({
                    icon: 'error',
                    title: "Tiene que seleccionar un proveedor"
                });
                return false;
            }

            if (idStorage == 0 || idStorage == "") {

                Toast.fire({
                    icon: 'error',
                    title: "Tiene que seleccionar un almacen"
                });
                return false;
            }

            if (idTipoMovimientoInventario == 0 || idTipoMovimientoInventario == "") {

                Toast.fire({
                    icon: 'error',
                    title: "Tiene que seleccionar un tipo movimiento"
                });
                return false;
            }


            if (listProducts == "[]") {

                Toast.fire({
                    icon: 'error',
                    title: "Tiene que agregar al menos un producto"
                });
                return false;
            }



            $(".btnSaveInventory").attr("disabled", true);
            var datos = new FormData();
            datos.append("idProveedor", idProveedor);
            datos.append("idEmpresa", idEmpresa);

            datos.append("idTipoInventario", idTipoMovimientoInventario);
            datos.append("idStorage", idStorage);
            datos.append("idQuote", idQuote);
            datos.append("folio", folio);
            datos.append("date", date);
            datos.append("idUser", idUser);
            datos.append("listProducts", listProducts);
            datos.append("generalObservations", generalObservations);
            datos.append("dateVen", dateVen);
            datos.append("quoteTo", quoteTo);
            datos.append("delivaryTime", delivaryTime);
            datos.append("subTotal", subTotal);
            datos.append("taxes", taxes);
            datos.append("IVARetenido", IVARetenido);
            datos.append("ISRRetenido", ISRRetenido);
            datos.append("total", total);
            datos.append("importPayment", pago);
            datos.append("importBack", cambio);
            datos.append("datePayment", datePayment);
            datos.append("metodoPago", metodoPago);
            datos.append("tipoComprobanteRD", tipoComprobanteRD);
            datos.append("folioComprobanteRD", folioComprobanteRD);
            datos.append("RFCReceptor", RFCReceptor);
            datos.append("usoCFDI", usoCFDIVenta);
            datos.append("metodoPago", metodoPagoVenta);
            datos.append("formaPago", formaPagoVenta);
            datos.append("razonSocialReceptor", razonSocialReceptor);
            datos.append("codigoPostalReceptor", codigoPostalReceptor);
            datos.append("regimenFiscalReceptor", regimenFiscalReceptor);
            datos.append("UUID", UUID);
            $.ajax({

                url: "<?= base_url('admin/inventory/save') ?>",
                method: "POST",
                data: datos,
                cache: false,
                contentType: false,
                processData: false,
                //dataType:"json",
                success: function (respuesta) {


                    if (respuesta.match(/Correctamente.*/)) {


                        Toast.fire({
                            icon: 'success',
                            title: "Guardado Correctamente"
                        });
                        $(".btnSaveInventory").removeAttr("disabled");
                        return true;
                    } else {

                        Toast.fire({
                            icon: 'error',
                            title: respuesta
                        });
                        $(".btnSaveInventory").removeAttr("disabled");
                        return false;
                    }

                }

            }

            )

            return true;
        }


        function listProducts() {




            var listProducts = [];
            var lote = $(".lote");
            var description = $(".description");
            var codeProduct = $(".codeProduct");
            var cant = $(".cant");
            var price = $(".price");
            var total = $(".total");
            var porcentTax = $(".porcentTax");
            var tax = $(".tax");
            var IVARetenidoRenglon = $(".IVARetenido");
            var porcentIVARetenido = $(".porcentIVARetenido");
            var porcentISRRetenido = $(".porcentISRRetenido");
            var ISRRetenidoRenglon = $(".ISRRetenido");
            var neto = $(".neto");
            var unidad = $(".unidad");
            var claveProductoSATR = $(".claveProductoSATR");
            var claveUnidadSatR = $(".claveUnidadSatR");
            var subTotal = 0;
            var impuesto = 0;
            var netoTotal = 0;
            var IVARetenido = 0;
            var ISRRetenido = 0;
            for (var i = 0; i < description.length; i++) {

                listProducts.push({
                    "idProduct": $(description[i]).attr("idProducto"),
                    "lote": $(lote[i]).val(),
                    "description": $(description[i]).val(),
                    "codeProduct": $(codeProduct[i]).val(),
                    "cant": $(cant[i]).val(),
                    "price": $(price[i]).val(),
                    "porcentTax": $(porcentTax[i]).val(),
                    "tax": $(tax[i]).val(),
                    "porcentIVARetenido": $(porcentIVARetenido[i]).val(),
                    "porcentISRRetenido": $(porcentISRRetenido[i]).val(),
                    "IVARetenido": $(IVARetenidoRenglon[i]).val(),
                    "ISRRetenido": $(ISRRetenidoRenglon[i]).val(),
                    "claveProductoSAT": $(claveProductoSATR[i]).val(),
                    "claveUnidadSAT": $(claveUnidadSatR[i]).val(),
                    "neto": $(neto[i]).val(),
                    "unidad": $(unidad[i]).val(),
                    "total": $(total[i]).val()
                });
                subTotal = Number(Number(subTotal) + Number($(total[i]).val())).toFixed(2);
                impuesto = Number(Number(impuesto) + Number($(tax[i]).val())).toFixed(2);
                IVARetenido = Number(Number(IVARetenido) + Number($(IVARetenidoRenglon[i]).val())).toFixed(2);
                ISRRetenido = Number(Number(ISRRetenido) + Number($(ISRRetenidoRenglon[i]).val())).toFixed(2);
                netoTotal = Number(Number(netoTotal) + Number($(neto[i]).val())).toFixed(2);
            }


            $("#subTotal").val(subTotal);
            $("#totalImpuesto").val(impuesto);
            $("#granTotal").val(netoTotal);
            $("#totalRetencionIVA").val(IVARetenido);
            $("#totalRetencionISR").val(ISRRetenido);
            //Asignamos el JSON en el input

            $("#listProducts").val(JSON.stringify(listProducts));
        }


        /*=============================================
         IMPRIMIR CONSULTA
         =============================================*/



        $(".btnPrint").on("click", function () {


            var saved = saveInventory();
            var uuid = $("#uuid").val();
            if (saved == true) {

                var uuid = $("#uuid").val();
                window.open("<?= base_url('admin/inventory/report') ?>" + "/" + uuid, "_blank");
            }

        })



        //CARGA CONSULTAS ANTERIORES

        $(".btnAddArticle").on("click", function () {

            var idStorage = $("#idStorage").val();
            var idEmpresa = $("#idEmpresaInventory").val();
            var idTipoMovimiento = $("#idTipoMovimientoInventario").val();

            cargaProductos(idEmpresa, idStorage, idTipoMovimiento);

        });
        document.addEventListener("keydown", function (event) {

            console.log(event.code);
            if (event.altKey && event.code === "KeyA") {

                cargaProductos();
                $("#modalAddbtnAddArticle").modal('show');
                event.preventDefault();
            }
        });
        function cargaProductos(idEmpresa = 0, idStorage = 0, idTipoMovimiento = 0) {

            console.log("empresa Carga Productos:", idEmpresa);
            if (idEmpresa == "") {

                idEmpresa = 0;
            }

            if (idTipoMovimiento == "") {

                idTipoMovimiento = 0;
            }

            if (idStorage == "") {

                idStorage = 0;
            }

            tableProducts.ajax.url(`<?= base_url('admin/products/getAllProductsInventory') ?>/` + idEmpresa + '/' + idStorage + '/' + idTipoMovimiento).load();
        }

<?php
if ($folioComprobanteRD > 0) {


    echo '$(".comprobantesRD").removeAttr("hidden")';
}

echo '$("#usoCFDIVenta").val("' . $usoCFDIReceptor . '"); ';
echo '$("#usoCFDIVenta").trigger("change"); ';
echo '$("#metodoPagoVenta").val("' . $metodoPagoReceptor . '"); ';
echo '$("#metodoPagoVenta").trigger("change"); ';
echo '$("#formaPagoVenta").val("' . $formaPagoReceptor . '"); ';
echo '$("#formaPagoVenta").trigger("change"); ';
echo '$("#regimenFiscalReceptor").val("' . $regimenFiscalReceptor . '"); ';
echo '$("#regimenFiscalReceptor").trigger("change"); ';
?>
    </script>


    <?= $this->endSection() ?>

Creamos el archivo que contiene el modal para ir agregando productos en el kardex en App/Views/modulesInventory/productosModalInventory.php con el siguiente código

<!-- Modal Pacientes -->
<div class="modal fade" id="modalAddbtnAddArticle" tabindex="-1" role="dialog" aria-labelledby="modalAddbtnAddArticle" aria-hidden="true">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Seleccione Articulo</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <div class="row">
                    <div class="col-md-12">
                        <div class="table-responsive">
                            <table id="table-products" class="table table-striped table-hover va-middle tableProducts">
                                <thead>
                                    <tr>
                                        <th>#</th>

                                        <th>Descripcion</th>
                                        <th>Almacen</th>
                                        <th>lote</th>
                                        <th>Stock</th>
                                        <th>Acciones</th>
                                    </tr>
                                </thead>
                                <tbody>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">
                    <?= lang('boilerplate.global.close') ?>
                </button>

            </div>
        </div>
    </div>
</div>



<?= $this->section('js') ?>


<script>

    var tableProducts = $('#table-products').DataTable({
        processing: true,
        serverSide: true,
        autoWidth: false,
        order: [
            [1, 'asc']
        ],

        ajax: {
            url: '<?= base_url('admin/products/getAllProductsInventory') ?>/0/0/0',
            method: 'GET',
            dataType: "json"
        },
        columnDefs: [{
                orderable: false,
                targets: [3],
                searchable: false,
                targets: [3]

            }],
        columns: [{
                'data': 'id'
            },
            {
                'data': 'description'
            },

            {
                'data': 'almacen'
            },

            {
                'data': 'lote'
            },

            {
                'data': 'stock'
            },

            {
                "data": function (data) {
                    return `<td class="text-right py-0 align-middle">
                            <div class="btn-group btn-group-sm">
                            <button class="btn bg-blue btnAddProduct" lote="${data.lote}" almacen="${data.almacen}" data-id="${data.id}" unidad="${data.unidad}" claveProductoSAT="${data.claveProductoSAT}" unidadSAT="${data.unidadSAT}" porcentIVARetenido="${data.porcentIVARetenido}" porcentISRRetenido="${data.porcentISRRetenido}" porcentTax="${data.porcentTax}" code="${data.code}" price = "${data.salePrice}" description = "${data.description}"><i class="fas fa-plus"></i></button>
                            </div>
                            </td>`
                }
            }
        ]
    });


    /**
     * Evento al hacer click al boton btnAgregarDiagnostico
     */


    $("#table-products").on("click", ".btnAddProduct", function () {



        var idProduct = $(this).attr("data-id");
        var almacen = $(this).attr("almacen");
        var lote = $(this).attr("lote");
        var description = $(this).attr("description");
        var codeProduct = $(this).attr("code");
        var salePrice = $(this).attr("price");
        var porcentTax = $(this).attr("porcentTax");
        var porcentIVARetenido = $(this).attr("porcentIVARetenido");
        var porcentISRRetenido = $(this).attr("porcentISRRetenido");
        var claveUnidadSAT = $(this).attr("unidadSAT");
        var unidad = $(this).attr("unidad");
        var claveProductoSAT = $(this).attr("claveProductoSAT");

        if (porcentTax > 0) {

            var tax = ((porcentTax * 0.01)) * salePrice;



        } else {

            var tax = 0;
        }

        if (porcentIVARetenido > 0) {

            var IVARetenido = ((porcentIVARetenido * 0.01)) * salePrice;
            $(".grupoTotalRetencionIVA").removeAttr("hidden");

        } else {

            var IVARetenido = 0;

        }

        if (porcentISRRetenido > 0) {

            var ISRRetenido = ((porcentISRRetenido * 0.01)) * salePrice;
            $(".grupoTotalRetencionISR").removeAttr("hidden");

        } else {

            var ISRRetenido = 0;

        }


        var neto = (((porcentTax * 0.01) + 1) * salePrice) - (IVARetenido + ISRRetenido);


        /**
         * Agregando registros
         */
        var renglon = "<div class=\"form-group row nuevoProduct\">";
        renglon = renglon + "<div class =\"col-1\"> <button type=\"button\" class=\"btn btn-danger quitProduct\" ><span class=\"far fa-trash-alt\"></span></button> ";
        renglon = renglon + " <button type=\"button\"  data-toggle=\"modal\" data-target=\"#modelMoreInfoRow\" class=\"btn btn-primary  btnInfo\" ><span class=\"fa fa-fw fa-pencil-alt\"></span></button> </div>";
        renglon = renglon + "<div class =\"col-1\"> <input type=\"hidden\" id=\"claveProductoSATR\" class=\"form-control claveProductoSATR\"  name=\"claveProductoSATR\" value=\"" + claveProductoSAT + "\" required=\"\">";
        renglon = renglon + "<input type=\"hidden\" id=\"claveUnidadSatR\" class=\"form-control claveUnidadSatR\"  name=\"claveUnidadSatR\" value=\"" + claveUnidadSAT + "\" required=\"\">";
        renglon = renglon + "<input type=\"hidden\" id=\"unidad\" class=\"form-control unidad\"  name=\"unidad\" value=\"" + unidad + "\" required=\"\">";
        renglon = renglon + "<input type=\"text\" id=\"codeProduct\" class=\"form-control codeProduct\"  name=\"codeProduct\" value=\"" + codeProduct + "\" required=\"\"> </div>";
        renglon = renglon + "<div class =\"col-1\"> <input type=\"text\" id=\"lote\" class=\"form-control lote\" idProducto =\"" + idProduct + "\" name=\"lote\"  value=\"" + lote + "\" required=\"\"> </div>";
        renglon = renglon + "<div class =\"col-6\"> <input type=\"text\" id=\"description\" class=\"form-control description\" idProducto =\"" + idProduct + "\" name=\"description\" value=\"" + description + "\" required=\"\"> </div>";
        renglon = renglon + "<div class =\"col-1\"> <input type=\"number\" id=\"cant\" class=\"form-control cant\"name=\"cant\" value=\"1\" required=\"\"><input type=\"hidden\" id=\"porcentIVARetenido\" class=\"form-control porcentIVARetenido\"name=\"porcentIVARetenido\" value=\"" + porcentIVARetenido + "\" required=\"\"><input type=\"hidden\" id=\"porcentISRRetenido\" class=\"form-control porcentISRRetenido\"name=\"porcentISRRetenido\" value=\"" + porcentISRRetenido + "\" required=\"\"> <input type=\"hidden\" id=\"porcentTax\" class=\"form-control porcentTax\"name=\"porcentTax\" value=\"" + porcentTax + "\" required=\"\"></div>";
        renglon = renglon + "<div class =\"col-1\"> <input type=\"number\" id=\"price\" class=\"form-control price\"name=\"price\" value=\"" + salePrice + "\" required=\"\"> <input type=\"hidden\" id=\"IVARetenido\" class=\"form-control IVARetenido\"name=\"IVARetenido\" value=\"" + IVARetenido + "\" required=\"\"><input type=\"hidden\" id=\"ISRRetenido\" class=\"form-control ISRRetenido\"name=\"ISRRetenido\" value=\"" + ISRRetenido + "\" required=\"\"> <input type=\"hidden\" id=\"tax\" class=\"form-control tax\"name=\"tax\" value=\"" + tax + "\" required=\"\"> </div>";


        renglon = renglon + "<div class =\"col-1\"> <input readonly type=\"number\" id=\"total\" class=\"form-control total\" name=\"total\" value=\"" + salePrice + "\" required=\"\"> <input type=\"hidden\" id=\"neto\" class=\"form-control neto\" name=\"neto\" value=\"" + neto + "\" required=\"\"></div></div>";

        $(".rowProducts").append(renglon);

        listProducts();

    });

    var nombreDiv = "";


    /**
     * Eliminar Renglon Diagnostico
     */

    $(".rowProducts").on("click", ".quitProduct", function () {

        $(this).parent().parent().remove();

        listProducts();

    });


    /**
     * Mas datos Producto
     */

    $(".rowProducts").on("click", ".btnInfo", function () {

        nombreDiv = $(this);

        var unidadSAT = $(this).parent().parent().find(".claveUnidadSatR").val();
        var claveProductoSAT = $(this).parent().parent().find(".claveProductoSATR").val();

        var newOption = new Option(unidadSAT, unidadSAT, true, true);
        $('#unidadSATRow').append(newOption).trigger('change');
        $("#unidadSATRow").val(unidadSAT);

        var newOptionClaveProducto = new Option(claveProductoSAT, claveProductoSAT, true, true);
        $('#claveProductoSATRow').append(newOptionClaveProducto).trigger('change');
        $("#claveProductoSATRow").val(claveProductoSAT);


    });




    /**
     * Eliminar Renglon Diagnostico
     */

    $(".rowProducts").on("click", ".quitProduct", function () {



        $(this).parent().parent().remove();

        listProducts();

    });



    /**
     * Cambia Cantidad
     */

    $(".rowProducts").on("change", ".cant", function () {


        var cant = Number($(this).val());



        precio = $(this).parent().parent().find(".price").val();

        total = Number(cant) * Number(precio);

        porcIva = Number($(this).parent().parent().find(".porcentTax").val()) * 0.01;

        porcIVARetenido = Number($(this).parent().parent().find(".porcentIVARetenido").val()) * 0.01;

        porcISRRetenido = Number($(this).parent().parent().find(".porcentISRRetenido").val()) * 0.01;

        impuesto = (porcIva) * Number(total);

        IVARetenido = (porcIVARetenido) * Number(total);

        ISRRetenido = (porcISRRetenido) * Number(total);

        neto = ((porcIva + 1) * Number(total)) - (IVARetenido + ISRRetenido);

        $(this).parent().parent().find(".total").val(total);

        $(this).parent().parent().find(".neto").val(neto);

        $(this).parent().parent().find(".tax").val(impuesto);

        $(this).parent().parent().find(".IVARetenido").val(IVARetenido);

        $(this).parent().parent().find(".ISRRetenido").val(ISRRetenido);

        listProducts();

    });


    /**
     * Cambia Cantidad
     */

    $(".rowProducts").on("change", ".price", function () {


        var precio = Number($(this).val());



        cant = $(this).parent().parent().find(".cant").val();

        total = Number(cant) * Number(precio);

        porcIva = Number($(this).parent().parent().find(".porcentTax").val()) * 0.01;

        porcIVARetenido = Number($(this).parent().parent().find(".porcentIVARetenido").val()) * 0.01;

        porcISRRetenido = Number($(this).parent().parent().find(".porcentISRRetenido").val()) * 0.01;


        IVARetenido = (porcIVARetenido) * Number(total);

        ISRRetenido = (porcISRRetenido) * Number(total);

        neto = ((porcIva + 1) * Number(total)) - (IVARetenido + ISRRetenido);

        impuesto = (porcIva) * Number(total);

        $(this).parent().parent().find(".total").val(total);

        $(this).parent().parent().find(".neto").val(neto);

        $(this).parent().parent().find(".tax").val(impuesto);

        $(this).parent().parent().find(".IVARetenido").val(IVARetenido);

        $(this).parent().parent().find(".ISRRetenido").val(ISRRetenido);

        listProducts();

    });
</script>


<?= $this->endSection() ?>

Agregamos el archivo que contiene al modal para el pago a proveedores que se agregara en un futuro en App/Views/modulesInventory/modalPayment.php con el siguiente código.

<!-- Modal Vehicles -->
<div class="modal fade" id="modalPayment" tabindex="-1" role="dialog" aria-labelledby="modalPayment" aria-hidden="true">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Total a Pagar</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <form id="form-paciente" class="form-horizontal">

                    <div class="form-group row">
                        <label for="inputName" class="col-sm-2 col-form-label">Fecha Pago</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="far fa-calendar-alt"></i></span>
                                </div>
                                <input type="date"  name="datePayment" id="datePayment" class="form-control <?= session('error.datePayment') ? 'is-invalid' : '' ?>" value="<?php echo date('Y-m-d'); ?>" placeholder="datePayment" autocomplete="off">
                            </div>
                        </div>
                    </div>

                    <div class="form-group row">
                        <label for="inputName" class="col-sm-2 col-form-label">Método de Pago</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-credit-card"></i></span>
                                </div>
                                <select  name="metodoPago" id="metodoPago" class="form-control <?= session('error.uuidMail') ? 'is-invalid' : '' ?>" value="" placeholder="UUID Registro" autocomplete="off">
                                    <option value="1"> Efectivo</option>
                                    <option value="1"> Tarjeta</option>

                                    <select>

                                        </div>
                                        </div>
                                        </div>


                                        <div class="form-group row">
                                            <label for="inputName" class="col-sm-2 col-form-label">Pago</label>
                                            <div class="col-sm-10">
                                                <div class="input-group">
                                                    <div class="input-group-prepend">
                                                        <span class="input-group-text"><i class="fas fa-dollar-sign"></i></span>
                                                    </div>
                                                    <input type="number"  name="pago" id="pago" class="form-control <?= session('error.datePayment') ? 'is-invalid' : '' ?>" value="0.00" placeholder="datePayment" autocomplete="off">
                                                </div>
                                            </div>
                                        </div>

                                        <div class="form-group row">
                                            <label for="tireType" class="col-sm-2 col-form-label">Cambio</label>
                                            <div class="col-sm-10">
                                                <div class="input-group">
                                                    <div class="input-group-prepend">
                                                        <span class="input-group-text"><i class="fas fa-hand-holding"></i></span>
                                                    </div>
                                                    <input type="number" readonly="" name="cambio" id="cambio" class="form-control <?= session('error.folioVentaMail') ? 'is-invalid' : '' ?>" value="0.00" placeholder="" autocomplete="off">

                                                </div>
                                            </div>
                                        </div>




                                        </form>
                                        </div>
                                        <div class="modal-footer">
                                            <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal"><?= lang('boilerplate.global.close') ?></button>
                                            <button type="button" class="btn btn-primary btn-sm btnSavePayment" id="btnSavePayment">Guardar</button>
                                        </div>
                                        </div>
                                        </div>
                                        </div>

                                        <?= $this->section('js') ?>


                                        <script>




                                            /*=============================================
                                             CAMBIO EN EFECTIVO
                                             =============================================*/
                                            $("#pago").on("keyup", function () {

                                                console.log("asdasd");


                                                var efectivo = $(this).val();
                                                var total = $("#granTotal").val();


                                                var cambio = Number(efectivo) - Number(total);

                                                if (Number(efectivo) < Number(total)) {
                                                    cambio = 0;
                                                }


                                                $("#cambio").val(cambio);



                                            })

                                        </script>


                                        <?= $this->endSection() ?>

Agregamos el modal para ver mas datos del renglón agregado en App/Views/modulesInventory/moreInfoRow con el siguiente código

<!-- Modal More Info -->
<div class="modal fade" id="modelMoreInfoRow" tabindex="-1" role="dialog" aria-labelledby="modelMoreInfoRow" aria-hidden="true">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Información del Renglon</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <form id="form-otrosDatosRenglon" class="form-horizontal">




                    <div class="form-group row">
                        <label for="unidadSATRow" class="col-sm-2 col-form-label">
                            Clave Unidad SAT
                        </label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-pencil-alt"></i></span>
                                </div>
                                <select name="unidadSATRow" id="unidadSATRow" style="width: 90%;" class="form-control unidadSAT form-controlProducts">
                                    <option value="0" selected>
                                        Seleccione Clave De Unidad SAT
                                    </option>
                                </select>


                            </div>
                        </div>

                    </div>

                    <div class="form-group row">
                        <label for="claveProductoSATRow" class="col-sm-2 col-form-label">
                            Clave Producto SAT
                        </label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-pencil-alt"></i></span>
                                </div>
                                <select name="claveProductoSATRow" id="claveProductoSATRow" style="width: 90%;" class="form-control claveProductoSAT form-controlProducts">
                                    <option value="0" selected>
                                        Seleccione Clave de Producto SAT
                                    </option>

                                </select>


                            </div>
                        </div>

                    </div>



                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal"><?= lang('boilerplate.global.close') ?></button>
                <button type="button" class="btn btn-primary btn-sm btnGuardarRenglon" id="btnGuardarRenglon"  data-dismiss="modal">Guardar</button>
            </div>
        </div>
    </div>
</div>

<?= $this->section('js') ?>


<script>
    /* 
     * AL hacer click al editar
     */



    $(document).on('click', '.btnGuardarRenglon', function (e) {


        nombreDiv.parent().parent().find(".claveUnidadSatR").val($("#unidadSATRow").val());
        nombreDiv.parent().parent().find(".claveProductoSATR").val($("#claveProductoSATRow").val());

        listProducts();
    });



    /**
     * Categorias por empresa
     */

    $(".unidadSATRow").select2({
        ajax: {
            url: "<?= base_url('admin/products/getUnidadSATAjax') ?>",
            type: "post",
            dataType: 'json',
            delay: 250,

            data: function (params) {
                // CSRF Hash
                var csrfName = $('.txt_csrfname').attr('name'); // CSRF Token name
                var csrfHash = $('.txt_csrfname').val(); // CSRF hash
                var idEmpresa = $('.idEmpresa').val(); // CSRF hash

                return {
                    searchTerm: params.term, // search term
                    [csrfName]: csrfHash, // CSRF Token
                    idEmpresa: idEmpresa // search term
                };
            },
            processResults: function (response) {

                // Update CSRF Token
                $('.txt_csrfname').val(response.token);

                return {
                    results: response.data
                };
            },

            cache: true
        }
    });


    /**
     * Categorias por empresa
     */

    $(".claveProductoSATRow").select2({
        ajax: {
            url: "<?= base_url('admin/products/getProductosSATAjax') ?>",
            type: "post",
            dataType: 'json',
            delay: 250,
            data: function (params) {
                // CSRF Hash
                var csrfName = $('.txt_csrfname').attr('name'); // CSRF Token name
                var csrfHash = $('.txt_csrfname').val(); // CSRF hash
                var idEmpresa = $('.idEmpresa').val(); // CSRF hash

                return {
                    searchTerm: params.term, // search term
                    [csrfName]: csrfHash, // CSRF Token
                    idEmpresa: idEmpresa // search term
                };
            },
            processResults: function (response) {

                // Update CSRF Token
                $('.txt_csrfname').val(response.token);

                return {
                    results: response.data
                };
            },
            cache: true
        }
    });
</script>


<?= $this->endSection() ?>

Los otros sub archivos como capturar productos y clientes ya están hechos

Creamos el archivo para ver la lista de kardex registrados en App/Views/inventory.php con el siguiente código

<?= $this->include('load/daterangapicker') ?>
<?= $this->include('load/toggle') ?>
<?= $this->include('julio101290\boilerplate\Views\load\datatables') ?>


<!-- Extend from layout index -->
<?= $this->extend('julio101290\boilerplate\Views\layout\index') ?>


<!-- Section content -->
<?= $this->section('content') ?>

<?= $this->include('modulesInventory/modaSendMail') ?>
<?= $this->include('modulesInventory/modalPaymentList') ?>
<?= $this->include('modulesInventory/paymentsList') ?>



<!-- SELECT2 EXAMPLE -->
<div class="card card-default">
    <div class="card-header">

        <div class="float-left">
            <div class="btn-group">

                <div id="reportrange" style="background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc; width: 100%">
                    <i class="fa fa-calendar"></i>&nbsp;
                    <span></span> <i class="fa fa-caret-down"></i>
                </div>


            </div>
            <div class="btn-group">



                <input type="checkbox" id="chkTodasLasVentas" name="chkTodasLasVentas" class="chkTodasLasVentas" data-width="250" data-height="40" checked data-toggle="toggle" data-on="Todas las ventas" data-off="Pendientes de Pago" data-onstyle="success" data-offstyle="danger">

            </div>


        </div>

        <div class="float-right">
            <div class="btn-group">

                <a href="<?= base_url("admin/newInventory") ?>" class="btn btn-primary btnAddCustumers" data-target="#modalAddCustumers"><i class="fa fa-plus"></i>

                    Nueva Entrada/Salida

                </a>

            </div>
        </div>
    </div>
    <div class="card-body">
        <div class="row">

            <div class="col-md-12">

                <div class="table-responsive">

                    <table id="tableInventory" class="table table-striped table-hover va-middle tableInventory">

                        <thead>

                            <tr>

                                <th>#</th>
                                <th>
                                    Proveedor
                                </th>
                                <th>
                                    Fecha
                                </th>

                                <th>
                                    Fecha Vencimiento
                                </th>
                                <th>
                                    SubTotal
                                </th>
                                <th>
                                    Impuesto
                                </th>
                                <th>
                                    Total
                                </th>

                                <th>
                                    Pendiente
                                </th>
                                <th>
                                    Tiempo Entrega
                                </th>
                                <th>
                                    Creado
                                </th>
                                <th>
                                    Modificado
                                </th>
                                <th>
                                    Eliminado
                                </th>

                                <th>
                                    Acciones
                                </th>

                            </tr>
                        </thead>
                        <tbody>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- /.card -->

<?= $this->endSection() ?>


<?= $this->section('js') ?>
<script>
    /**
     * Cargamos la tabla
     */

    var tableInventory = $('#tableInventory').DataTable({
        processing: true,
        serverSide: true,
        responsive: true,
        autoWidth: false,
        order: [
            [1, 'desc']
        ],

        ajax: {
            url: '<?= base_url('admin/inventory') ?>',
            method: 'GET',
            dataType: "json"
        },
        columnDefs: [{
                orderable: false,
                targets: [12],
                searchable: false,
                targets: [12]

            }],
        columns: [{
                'data': 'id'
            },

            {
                'data': 'nameProveedor'
            },

            {
                'data': 'date'
            },

            {
                'data': 'dateVen'
            },

            {
                'data': 'subTotal'
            },

            {
                'data': 'taxes'
            },

            {
                'data': 'total'
            },

            {
                'data': 'balance'
            },

            {
                'data': 'delivaryTime'
            },

            {
                'data': 'created_at'
            },

            {
                'data': 'updated_at'
            },

            {
                'data': 'deleted_at'
            },

            {
                "data": function (data) {

                    var buttonPayment = "";

                    if (data.balance > 0) {

                        buttonPayment = `<button class="btn btn-success btnSetPayment" data-toggle="modal" balance ="${data.balance}" uuid="${data.UUID}" folio="${data.folio}" data-toggle="modal" data-target="#modalPayment"  >  <i class="fab fa-cc-visa"></i></button> `;

                    } else {

                        buttonPayment = `<button class="btn btn-success "   uuid="${data.UUID}" folio="${data.folio}">  <i class="far fa-check-square"></i></button> `;

                    }

                    return `<td class="text-right py-0 align-middle">
                         <div class="btn-group btn-group-sm">
                             <a href="<?= base_url('admin/editInventory') ?>/${data.UUID}" class="btn btn-primary btn-edit"><i class="fas fa-pencil-alt"></i></a>
                             <button class="btn btn-success btnSendMail" data-toggle="modal" correoCliente ="${data.correoCliente}" uuid="${data.UUID}" folio="${data.folio}" data-toggle="modal" data-target="#modalSendMail"  >  <i class=" fas fa-envelope"></i></button>
                             <button class="btn bg-warning btnImprimirVenta" uuid="${data.UUID}" ><i class="far fa-file-pdf"></i></button>
                             <button class="btn btn-danger btn-delete" data-id="${data.id}"><i class="fas fa-trash"></i></button>
                             ${buttonPayment}
                             <button class="btn bg-maroon btnPaymentsList" data-toggle="modal"  uuid="${data.UUID}" data-toggle="modal" data-target="#modalPaymentsList"  >  <i class="fas fa-search"></i></button>
                         </div>
                         </td>`
                }
            }
        ]
    });




    /**@abstract
     * 
     * Al cambiar la el rango de fecha
     */

    $("#chkTodasLasVentas").on("change", function () {

        var datePicker = $('#reportrange').data('daterangepicker');
        var desdeFecha = datePicker.startDate.format('YYYY-MM-DD');
        var hastaFecha = datePicker.endDate.format('YYYY-MM-DD');


        if ($(this).is(':checked')) {

            todas = true;

        } else {

            todas = false;

        }

        tableInventory.ajax.url(`<?= base_url('admin/inventory') ?>/` + desdeFecha + '/' + hastaFecha + '/' + todas).load();

    });

    /*=============================================
     Load Payment List 
     =============================================*/

    $(".tableSells").on("click", '.btnPaymentsList', function () {


        var uuid = $(this).attr("uuid");

        console.log(uuid);

        tableProducts.ajax.url(`<?= base_url('admin/payments/getPayments') ?>/` + uuid).load();

    });


    /*=============================================
     ENVIAR CORREO  
     =============================================*/

    $(".tableInventory").on("click", '.btnSendMail', function () {

        var uuid = $(this).attr("uuid");
        var folio = $(this).attr("folio");
        var correo = $(this).attr("correocliente");


        var newOption = new Option(correo, correo);
        $('#correos').append(newOption).trigger('change');

        $("#uuidMail").val(uuid);
        $("#folioVentanMail").val(folio);


    });


    /*=============================================
     ENVIAR CORREO  
     =============================================*/

    $(".tableInventory").on("click", '.btnSetPayment', function () {

        var uuid = $(this).attr("uuid");
        var balance = $(this).attr("balance");

        $("#uuidSellPayment").val(uuid);
        $("#granTotal").val(balance);


    });




    /*=============================================
     IMPRIMIR VEnta
     =============================================*/

    $(".tableInventory").on("click", '.btnImprimirVenta', function () {

        var uuid = $(this).attr("uuid");


        window.open("<?= base_url('admin/inventory/report') ?>" + "/" + uuid, "_blank");

    });


    /*=============================================
     ELIMINAR custumers
     =============================================*/
    $(".tableInventory").on("click", ".btn-delete", function () {

        var idInventory = $(this).attr("data-id");

        Swal.fire({
            title: '<?= lang('boilerplate.global.sweet.title') ?>',
            text: "<?= lang('boilerplate.global.sweet.text') ?>",
            icon: 'warning',
            showCancelButton: true,
            confirmButtonColor: '#3085d6',
            cancelButtonColor: '#d33',
            confirmButtonText: '<?= lang('boilerplate.global.sweet.confirm_delete') ?>'
        })
                .then((result) => {
                    if (result.value) {
                        $.ajax({
                            url: `<?= base_url('admin/inventory') ?>/` + idInventory,
                            method: 'DELETE',
                        }).done((data, textStatus, jqXHR) => {
                            Toast.fire({
                                icon: 'success',
                                title: jqXHR.statusText,
                            });


                            tableInventory.ajax.reload();
                        }).fail((error) => {
                            Toast.fire({
                                icon: 'error',
                                title: error.responseJSON.messages.error,
                            });
                        })
                    }
                })
    })





    $(function () {

        var start = moment().subtract(29, 'days');
        var end = moment();
        var todas = true;

        function cb(start, end) {
            $('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));

            if ($('#chkTodasLasVentas').is(':checked')) {

                todas = true;

            } else {

                todas = false;

            }



            var desdeFecha = start.format('YYYY-MM-DD');
            var hastaFecha = end.format('YYYY-MM-DD');

            tableInventory.ajax.url(`<?= base_url('admin/inventory') ?>/` + desdeFecha + '/' + hastaFecha + '/' + todas).load();


        }

        $('#reportrange').daterangepicker({
            startDate: start,
            endDate: end,
            ranges: {
                'Hoy': [moment(), moment()],
                'Ayer': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
                'Ultimos 7 Dias': [moment().subtract(6, 'days'), moment()],
                'Ultimos 30 Dias': [moment().subtract(29, 'days'), moment()],
                'Este Mes': [moment().startOf('month'), moment().endOf('month')],
                'Último Mes': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')],
                'Todo': [moment().subtract(100, 'year').startOf('month'), moment().add(100, 'year').endOf('year')]
            }
        }, cb);

        cb(start, end);



    });
</script>
<?= $this->endSection() ?>

Agregamos el modal para el envió de correo en App/Views/modulesInventory/modaSendMail.php con el siguiente código

<!-- Modal Vehicles -->
<div class="modal fade" id="modalSendMail" tabindex="-1" role="dialog" aria-labelledby="modalSendMail" aria-hidden="true">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Envio Correo</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <form id="form-paciente" class="form-horizontal">

                    <div class="form-group row">
                        <label for="inputName" class="col-sm-2 col-form-label">Correos</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-pencil-alt"></i></span>
                                </div>
                                <input type="text"  name="correos" id="correos" class="form-control <?= session('error.correos') ? 'is-invalid' : '' ?>" value="" placeholder="correos" autocomplete="off">
                            </div>
                        </div>
                    </div>

                    <div class="form-group row">
                        <label for="inputName" class="col-sm-2 col-form-label">UUID</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-pencil-alt"></i></span>
                                </div>
                                <input type="text" readonly="" name="uuidMail" id="uuidMail" class="form-control <?= session('error.uuidMail') ? 'is-invalid' : '' ?>" value="" placeholder="UUID Registro" autocomplete="off">
                            </div>
                        </div>
                    </div>




                    <div class="form-group row">
                        <label for="tireType" class="col-sm-2 col-form-label">Folio Venta</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-mobile"></i></span>
                                </div>
                                <input type="text" readonly="" name="folioVentaMail" id="folioVentaMail" class="form-control <?= session('error.folioVentaMail') ? 'is-invalid' : '' ?>" value="" placeholder="" autocomplete="off">

                            </div>
                        </div>
                    </div>




                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal"><?= lang('boilerplate.global.close') ?></button>
                <button type="button" class="btn btn-primary btn-sm btnSendMailConfirm" id="btnSendMailConfirm">Enviar</button>
            </div>
        </div>
    </div>
</div>

<?= $this->section('js') ?>


<script>


    /* 
     * AL hacer click al editar
     */



    $(document).on('click', '.btnSendMailConfirm', function (e) {

        console.log("Enviar correo");

        $(".btnSendMailConfirm").attr("disabled", true);

        var uuid = $("#uuidMail").val();

        var correos = $("#correos").val();

        $.ajax({

            url: "<?= base_url('admin/mailSettings/sendMailVenta/') ?>" + uuid + '/' + correos,
            method: "GET",

            cache: false,
            contentType: false,
            processData: false,
            //dataType:"json",
            success: function (respuesta) {


                if (respuesta.match(/Correctamente.*/)) {


                    Toast.fire({
                        icon: 'success',
                        title: "Enviado Correctamente"
                    });



                    $(".btnSendMailConfirm").removeAttr("disabled");


                    $('#modalSendMail').modal('hide');
                } else {

                    Toast.fire({
                        icon: 'error',
                        title: respuesta
                    });

                    $(".btnSendMailConfirm").removeAttr("disabled");

                }

            }

        }

        )


    });
</script>


<?= $this->endSection() ?>

Creamos el pago para generarle pagos a los proveedores en App/Views/modulesInventory/modalPaymentList.php

<!-- Modal Vehicles -->
<div class="modal fade" id="modalPayment" tabindex="-1" role="dialog" aria-labelledby="modalPayment" aria-hidden="true">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Total a Pagar</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <form id="form-paciente" class="form-horizontal">

                    <div class="form-group row">
                        <label for="inputName" class="col-sm-2 col-form-label">Fecha Pago</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="far fa-calendar-alt"></i></span>
                                </div>
                                <input type="date" name="datePayment" id="datePayment" class="form-control <?= session('error.datePayment') ? 'is-invalid' : '' ?>" value="<?php echo date('Y-m-d'); ?>" placeholder="datePayment" autocomplete="off">
                            </div>
                        </div>
                    </div>

                    <div class="form-group row">
                        <label for="inputName" class="col-sm-2 col-form-label">Método de Pago</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-credit-card"></i></span>
                                </div>
                                <select name="metodoPago" id="metodoPago" class="form-control <?= session('error.uuidMail') ? 'is-invalid' : '' ?>" value="" placeholder="UUID Registro" autocomplete="off">
                                    <option value="1"> Efectivo</option>
                                    <option value="2"> Tarjeta</option>

                                    <select>

                            </div>
                        </div>
                    </div>


                    <div class="form-group row">
                        <label for="inputName" class="col-sm-2 col-form-label">Pago</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-dollar-sign"></i></span>
                                </div>
                                <input type="hidden" name="uuidSellPayment" id="uuidSellPayment" class="form-control <?= session('error.uuidSellPayment') ? 'is-invalid' : '' ?>" value="0.00" placeholder="uuidSellPayment" autocomplete="off">
                                <input type="hidden" name="granTotal" id="granTotal" class="form-control " value="0.00" autocomplete="off">
                                <input type="number" name="pago" id="pago" class="form-control <?= session('error.datePayment') ? 'is-invalid' : '' ?>" value="0.00" placeholder="datePayment" autocomplete="off">
                            </div>
                        </div>
                    </div>

                    <div class="form-group row">
                        <label for="tireType" class="col-sm-2 col-form-label">Cambio</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-hand-holding"></i></span>
                                </div>
                                <input type="number" readonly="" name="cambio" id="cambio" class="form-control <?= session('error.folioVentaMail') ? 'is-invalid' : '' ?>" value="0.00" placeholder="" autocomplete="off">

                            </div>
                        </div>
                    </div>




                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal"><?= lang('boilerplate.global.close') ?></button>
                <button type="button" class="btn btn-primary btn-sm btnSavePayment" id="btnSavePayment">Guardar</button>
            </div>
        </div>
    </div>
</div>

<?= $this->section('js') ?>


<script>
    /**
     * Save Payment
     */

    $(".btnSavePayment").on("click", function() {


        savePayment();


    });




    function savePayment() {


        var UUID = $("#uuidSellPayment").val();
        var pago = $("#pago").val();
        var cambio = $("#cambio").val();
        var datePayment = $("#datePayment").val();
        var metodoPago = $("#metodoPago").val();


      



        $(".btnSavePayment").attr("disabled", true);


        var datos = new FormData();
        datos.append("UUID", UUID);
        datos.append("importPayment", pago);
        datos.append("importBack", cambio);
        datos.append("datePayment", datePayment);
        datos.append("metodoPago", metodoPago);
      

        $.ajax({

                url: "<?= base_url('admin/payments/save') ?>",
                method: "POST",
                data: datos,
                cache: false,
                contentType: false,
                processData: false,
                //dataType:"json",
                success: function(respuesta) {


                    if (respuesta.match(/Correctamente.*/)) {


                        Toast.fire({
                            icon: 'success',
                            title: "Guardado Correctamente"
                        });

                        $(".btnSavePayment").removeAttr("disabled");

                        $("#modalPayment").modal("toggle");
                        tableQuotes.ajax.reload();

                    } else {

                        Toast.fire({
                            icon: 'error',
                            title: respuesta
                        });

                        $(".btnSavePayment").removeAttr("disabled");


                    }

                }

            }

        )
    }
    /*=============================================
 CAMBIO EN EFECTIVO
 =============================================*/
    $("#pago").on("keyup", function() {

        console.log("asdasd");


        var efectivo = $(this).val();
        var total = $("#granTotal").val();


        var cambio = Number(efectivo) - Number(total);

        if (Number(efectivo) < Number(total)) {
            cambio = 0;
        }


        $("#cambio").val(cambio);



    })
</script>


<?= $this->endSection() ?>

Ahora creamos el modal para poder observar la lista de pagos en App/Views/modulesInventory/paymentsList.php con el siguiente código

<!-- Modal Vehicles -->
<div class="modal fade" id="modalPayment" tabindex="-1" role="dialog" aria-labelledby="modalPayment" aria-hidden="true">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">Total a Pagar</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <form id="form-paciente" class="form-horizontal">

                    <div class="form-group row">
                        <label for="inputName" class="col-sm-2 col-form-label">Fecha Pago</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="far fa-calendar-alt"></i></span>
                                </div>
                                <input type="date" name="datePayment" id="datePayment" class="form-control <?= session('error.datePayment') ? 'is-invalid' : '' ?>" value="<?php echo date('Y-m-d'); ?>" placeholder="datePayment" autocomplete="off">
                            </div>
                        </div>
                    </div>

                    <div class="form-group row">
                        <label for="inputName" class="col-sm-2 col-form-label">Método de Pago</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-credit-card"></i></span>
                                </div>
                                <select name="metodoPago" id="metodoPago" class="form-control <?= session('error.uuidMail') ? 'is-invalid' : '' ?>" value="" placeholder="UUID Registro" autocomplete="off">
                                    <option value="1"> Efectivo</option>
                                    <option value="2"> Tarjeta</option>

                                    <select>

                            </div>
                        </div>
                    </div>


                    <div class="form-group row">
                        <label for="inputName" class="col-sm-2 col-form-label">Pago</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-dollar-sign"></i></span>
                                </div>
                                <input type="hidden" name="uuidSellPayment" id="uuidSellPayment" class="form-control <?= session('error.uuidSellPayment') ? 'is-invalid' : '' ?>" value="0.00" placeholder="uuidSellPayment" autocomplete="off">
                                <input type="hidden" name="granTotal" id="granTotal" class="form-control " value="0.00" autocomplete="off">
                                <input type="number" name="pago" id="pago" class="form-control <?= session('error.datePayment') ? 'is-invalid' : '' ?>" value="0.00" placeholder="datePayment" autocomplete="off">
                            </div>
                        </div>
                    </div>

                    <div class="form-group row">
                        <label for="tireType" class="col-sm-2 col-form-label">Cambio</label>
                        <div class="col-sm-10">
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fas fa-hand-holding"></i></span>
                                </div>
                                <input type="number" readonly="" name="cambio" id="cambio" class="form-control <?= session('error.folioVentaMail') ? 'is-invalid' : '' ?>" value="0.00" placeholder="" autocomplete="off">

                            </div>
                        </div>
                    </div>




                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal"><?= lang('boilerplate.global.close') ?></button>
                <button type="button" class="btn btn-primary btn-sm btnSavePayment" id="btnSavePayment">Guardar</button>
            </div>
        </div>
    </div>
</div>

<?= $this->section('js') ?>


<script>
    /**
     * Save Payment
     */

    $(".btnSavePayment").on("click", function() {


        savePayment();


    });




    function savePayment() {


        var UUID = $("#uuidSellPayment").val();
        var pago = $("#pago").val();
        var cambio = $("#cambio").val();
        var datePayment = $("#datePayment").val();
        var metodoPago = $("#metodoPago").val();


      



        $(".btnSavePayment").attr("disabled", true);


        var datos = new FormData();
        datos.append("UUID", UUID);
        datos.append("importPayment", pago);
        datos.append("importBack", cambio);
        datos.append("datePayment", datePayment);
        datos.append("metodoPago", metodoPago);
      

        $.ajax({

                url: "<?= base_url('admin/payments/save') ?>",
                method: "POST",
                data: datos,
                cache: false,
                contentType: false,
                processData: false,
                //dataType:"json",
                success: function(respuesta) {


                    if (respuesta.match(/Correctamente.*/)) {


                        Toast.fire({
                            icon: 'success',
                            title: "Guardado Correctamente"
                        });

                        $(".btnSavePayment").removeAttr("disabled");

                        $("#modalPayment").modal("toggle");
                        tableQuotes.ajax.reload();

                    } else {

                        Toast.fire({
                            icon: 'error',
                            title: respuesta
                        });

                        $(".btnSavePayment").removeAttr("disabled");


                    }

                }

            }

        )
    }
    /*=============================================
 CAMBIO EN EFECTIVO
 =============================================*/
    $("#pago").on("keyup", function() {

        console.log("asdasd");


        var efectivo = $(this).val();
        var total = $("#granTotal").val();


        var cambio = Number(efectivo) - Number(total);

        if (Number(efectivo) < Number(total)) {
            cambio = 0;
        }


        $("#cambio").val(cambio);



    })
</script>


<?= $this->endSection() ?>

Por si no lo puse antes hicimos unas funciones, estas las vamos agregar en App/Helpers/utilerias_helper.php

<?php

function strMenuActivo($strMenu1, $strMenu2) {
    if ($strMenu1 == $strMenu2) {
        $respuesta = 'class="active"';
    } else {
        $respuesta = "";
    }
    return $respuesta;
}

//SI LA VARIABLE ESTA VACIA O NO SETA DECLARADA MANDARA CERO SIEMPRE, ES COMO EL VAL DE VISUAL BASIC 6.0

function esCero($value) {

    if (empty($value)) {
        return "0";
    } else {
        return $value;
    }
}


// CONVIERTE FECHA MYSQLDATETIME A HTML5
function fechaMySQLADateHTML5($fecha) {

    return date("Y-m-d", strtotime($fecha));
}

//FECHA SQL PARA GUARDAR EN BASE DE DATOS

function fechaSQL($fecha) {

    return date("Ymd", strtotime($fecha));
}

// CONVIERTE FECHA MYSQLDATETIME A HTML5
function fechaMySQLADateTimeHTML5($fecha) {

    return date("Y-m-d", strtotime($fecha)) . "T" . date("H:i:s", strtotime($fecha));
}

function agregarMinutos($fecha, $minutos) {


    return date("Y/m/d h:i:s", strtotime($fecha . "+ $minutos minutes"));

    /*
      $fecha1= new DateTime($fecha);
      $fecha1->add(new DateInterval('PT10H30S'));
      return $date->format('Y-m-d H:i:s') . "\n";
     * 
     */
}

function fechaHoraActualSQL($fecha) {

    return date("Y-m-d h:i:s ", strtotime($fecha));
}


function fechaHoraActualSQLFinal($fecha) {

    return date("Y-m-d  ", strtotime($fecha))."23:59:59";
}


//CONVIERTE LA FECHA EN PERIODO
function fechaPeriodo($fecha) {

    return date("Ym", strtotime($fecha));
}

//OBTIENE FECHA ACTUAL
function fechaActual() {

    return date("Y/m/d");
}

//OBTIENE FECHA HORA ACTUAL

function fechaHoraActual() {

    return date("Y-m-d H:i:s ", time());
}

//DIFERENCIA ENTRE MINUTOS
function diferenciaMinutos($fecha_i, $fecha_f) {
    $minutos = (strtotime($fecha_i) - strtotime($fecha_f)) / 60;

    $minutos = abs($minutos);
    $minutos = floor($minutos);

    return $minutos;
}

function strSellar($llave, $password, $cadenaOriginal) {


    $archivoPem = "/tmp/llave.key.pem";
    $comando = "openssl pkcs8 -inform DER -in $llave -passin pass:$password -out $archivoPem";

    exec($comando);
    $sello = "ok";

    //Sellar
    $archivo = openssl_pkey_get_private(file_get_contents($archivoPem));
    $sig = "";
    openssl_sign($cadenaOriginal, $sig, $archivo, OPENSSL_ALGO_SHA256);

    $sello = base64_encode($sig);

    return $sello;
}

//SOLO DIA
function dia($fecha) {

    return date("d", strtotime($fecha));
}

//SOLO MES
function mes($fecha) {

    return date("m", strtotime($fecha));
}

//SOLO AÑO
function año($fecha) {

    return date("Y", strtotime($fecha));
}

/**
 * Fecha Humanizada
 * @param type $fecha
 * @return type
 */
function fechaHumanizada($fecha) {
    
    $dias["Monday"] = "Lunes";
    $dias["Tuesday"] = "Martes";
    $dias["Wednesday"] = "Miercoles";
    $dias["Thursday"] = "Jueves";
    $dias["Friday"] = "Viernes";
    $dias["Saturday"] = "Sabado";
    $dias["Sunday"] = "Domingo";
    
    $meses["January"] = "Enero";
    $meses["February"] = "Febrero ";
    $meses["March"] = "Marzo";
    $meses["April"] = "Abril";
    $meses["May"] = "Mayo";
    $meses["June"] = "Junio";
    $meses["July"] = "Julio";
    $meses["August"] = "Agosto";
    $meses["September"] = "Septiembre";
    $meses["October"] = "Octubre";
    $meses["November"] = "Noviembre";
    $meses["December"] = "Diciembre";
    
    $fechaHumanizada = $dias[date("l", strtotime($fecha))] 
                        .", "
                        .date("d", strtotime($fecha))." de "
                        . $meses[date("F", strtotime($fecha))] . " de "
                        .date("Y", strtotime($fecha));
                            
    return  $fechaHumanizada;
}

//GENERA UUID
function generaUUID() {


    $uuid = service('uuid');
    $uuid4 = $uuid->uuid4();
    $string = $uuid4->toString();

    return $string;
}

function satinizar($var, $type) {
    switch ($type) {
        case 'html':
            $safe = htmlspecialchars($var);
            break;
        case 'sql':
            $safe = mysql_real_escape_string($var);
            break;
        case 'file':
            $safe = preg_replace('/(\/|-|_)/', '', $var);
            break;
        case 'shell':
            $safe = escapeshellcmd($var);
            break;
        default:
            $safe = htmlspecialchars($var);
    }
    return $safe;
}

function limpiaCadena($cadena) {

    $cadena = str_replace('"', "", $cadena);
    $cadena = str_replace('\n', "", $cadena);
    $cadena = str_replace('\t', "", $cadena);
    $cadena = trim($cadena);

    $cadena = preg_replace("[\n|\r|\n\r]", "", $cadena);

    $descripcion = preg_replace("[\n|\r|\n\r]", "", $descripcion);

    return $cadena;
}


// CONVIERTE FECHA MYSQLDATETIME A HTML5
function fechaParaMigraciones($fecha) {

    return date("Y-m-d", strtotime($fecha)) . date("His", strtotime($fecha));
    
}

Creamos las rutas necesarias en App/Config/Routes.php en el grupo de admin

$routes->get('products/getAllProductsInventory/(:any)/(:any)/(:any)', 'ProductsController::getAllProductsInventory/$1/$2/$3');

  $routes->resource('inventory', [
        'filter' => 'permission:inventory-permission',
        'controller' => 'InventoryController',
        'except' => 'show'
    ]);

    $routes->get('nuevoMovimientoInventario', 'InventoryController::newInventory');

    $routes->get('editInventory/(:any)', 'InventoryController::editInventory/$1');

    $routes->post('inventory/save', 'InventoryController::save');
    $routes->post('inventory/getLastCode', 'InventoryController::getLastCode');
    $routes->get('inventory/report/(:any)', 'InventoryController::report/$1');
    $routes->get('inventory/(:any)/(:any)/(:any)', 'InventoryController::inventoryFilters/$1/$2/$3');

Creamos el menú para nuevo movimiento de kardex con los siguientes datos

Creamos el menú para ver la lista de kardex con los siguientes datos

Creamos los permisos para la visualización de movimientos de inventario

Y listo ya tenemos nuestra captura de kardex

Video Demostrativo