Ya esta creado el catalogo de tipos de vehículos ahora crearemos el catalogo de vehículos que va a tener los siguientes datos

  • Empresa
  • Tipo Vehiculo
  • Descripción
  • Placas

Creamos el archivo de migración en App/Database/Migrations/2023-09-02171027_Vehiculos.php con el siguiente codigo

<?php

namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class Vehiculos extends Migration {

    public function up() {
        // Vehiculos
        $this->forge->addField([
            'id' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true],
            'idEmpresa' => ['type' => 'bigint', 'constraint' => 20, 'null' => true],
            'idTipoVehiculo' => ['type' => 'bigint', 'constraint' => 20, 'null' => true],
            'descripcion' => ['type' => 'varchar', 'constraint' => 512, 'null' => true],
            'placas' => ['type' => 'varchar', 'constraint' => 16, '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('vehiculos', true);
    }

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

}

Creamos el archivo de modelo en App/Models/VehiculosModel.php con el siguiente código

<?php

namespace App\Models;

use CodeIgniter\Model;

class VehiculosModel extends Model {

    protected $table = 'vehiculos';
    protected $primaryKey = 'id';
    protected $useAutoIncrement = true;
    protected $returnType = 'array';
    protected $useSoftDeletes = true;
    protected $allowedFields = ['id', 'idEmpresa', 'idTipoVehiculo', 'descripcion', 'placas', 'created_at', 'updated_at', 'deleted_at'];
    protected $useTimestamps = true;
    protected $createdField = 'created_at';
    protected $deletedField = 'deleted_at';
    protected $validationRules = [
    ];
    protected $validationMessages = [];
    protected $skipValidation = false;

    public function mdlGetVehiculos($idEmpresas) {

        $result = $this->db->table('vehiculos a, empresas b, tipovehiculo c')
                ->select('a.id
                         ,b.nombre as nombreEmpresa
                         ,a.idEmpresa
                         ,a.idTipoVehiculo
                         ,c.codigo as codigoTipo
                         ,c.descripcion as descripcionTipo
                         ,a.descripcion
                         ,a.placas
                         ,a.created_at
                         ,a.updated_at
                         ,a.deleted_at 
                         ,b.nombre as nombreEmpresa')
                ->where('a.idEmpresa', 'b.id', FALSE)
                ->where('a.idTipoVehiculo', 'c.id', FALSE)
                ->whereIn('a.idEmpresa', $idEmpresas);

        return $result;
    }

}

Agregamos el archivo controlador en App/Controllers/VehiculosController.php con el siguiente código

<?php

namespace App\Controllers;

use App\Controllers\BaseController;
use \App\Models\{
    VehiculosModel
};
use App\Models\LogModel;
use CodeIgniter\API\ResponseTrait;
use App\Models\EmpresasModel;
use App\Models\TipovehiculoModel;

class VehiculosController extends BaseController {

    use ResponseTrait;

    protected $log;
    protected $vehiculos;
    protected $tiposVehiculo;

    public function __construct() {
        $this->vehiculos = new VehiculosModel();
        $this->log = new LogModel();
        $this->empresa = new EmpresasModel();
        $this->tiposVehiculo = new TipovehiculoModel();
        helper('menu');
        helper('utilerias');
    }

    public function index() {



        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");
        }


        $tiposVehiculo = $this->tiposVehiculo->mdlGetTipovehiculoArray($empresasID);

        if ($this->request->isAJAX()) {
            $datos = $this->vehiculos->mdlGetVehiculos($empresasID);

            return \Hermawan\DataTables\DataTable::of($datos)->toJson(true);
        }
        $titulos["title"] = lang('vehiculos.title');
        $titulos["subtitle"] = lang('vehiculos.subtitle');
        $titulos["tiposVehiculo"] = $tiposVehiculo;

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

    /**
     * Read Vehiculos
     */
    public function getVehiculos() {

        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");
        }


        $idVehiculos = $this->request->getPost("idVehiculos");

        $datosVehiculos = $this->vehiculos->whereIn('idEmpresa', $empresasID)
                        ->where("id", $idVehiculos)->first();

        $tipoVehiculo = $this->tiposVehiculo->select("*")
                        ->where("id", $datosVehiculos["idTipoVehiculo"])
                        ->whereIn("idEmpresa", $empresasID)->first();

        $datosVehiculos["descripcionTipo"] = $tipoVehiculo["descripcion"];
        echo json_encode($datosVehiculos);
    }

    /**
     * Save or update Vehiculos
     */
    public function save() {
        helper('auth');
        $userName = user()->username;
        $idUser = user()->id;
        $datos = $this->request->getPost();
        if ($datos["idVehiculos"] == 0) {
            try {
                if ($this->vehiculos->save($datos) === false) {
                    $errores = $this->vehiculos->errors();
                    foreach ($errores as $field => $error) {
                        echo $error . " ";
                    }
                    return;
                }
                $dateLog["description"] = lang("vehicles.logDescription") . json_encode($datos);
                $dateLog["user"] = $userName;
                $this->log->save($dateLog);
                echo "Guardado Correctamente";
            } catch (\PHPUnit\Framework\Exception $ex) {
                echo "Error al guardar " . $ex->getMessage();
            }
        } else {
            if ($this->vehiculos->update($datos["idVehiculos"], $datos) == false) {
                $errores = $this->vehiculos->errors();
                foreach ($errores as $field => $error) {
                    echo $error . " ";
                }
                return;
            } else {
                $dateLog["description"] = lang("vehiculos.logUpdated") . json_encode($datos);
                $dateLog["user"] = $userName;
                $this->log->save($dateLog);
                echo "Actualizado Correctamente";
                return;
            }
        }
        return;
    }

    /**
     * Get Vehiculos via AJax
     */
    public function getVehiculosAjax() {

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

        $response = array();

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

        if (!isset($postData['searchTerm'])) {
            // Fetch record

            $listCustumers = $custumers->select('id,descripcion,placas')->where("deleted_at", null)
                    ->where('idEmpresa', $idEmpresa)
                    ->orderBy('id')
                    ->orderBy('descripcion')
                    ->orderBy('placas')
                    ->findAll(1000);
        } else {
            $searchTerm = $postData['searchTerm'];

            // Fetch record

            $listCustumers = $custumers->select('id,descripcion,placas')->where("deleted_at", null)
                    ->where('idEmpresa', $idEmpresa)
                    ->groupStart()
                    ->like('descripcion', $searchTerm)
                    ->orLike('id', $searchTerm)
                    ->orLike('placas', $searchTerm)
                    ->groupEnd()
                    ->findAll(1000);
        }

        $data = array();
        foreach ($listCustumers as $custumers) {
            $data[] = array(
                "id" => $custumers['id'],
                "text" => $custumers['id'] . ' ' . $custumers['placas'] . ' ' . $custumers['descripcion'],
            );
        }

        $response['data'] = $data;

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

    /**
     * Delete Vehiculos
     * @param type $id
     * @return type
     */
    public function delete($id) {
        $infoVehiculos = $this->vehiculos->find($id);
        helper('auth');
        $userName = user()->username;
        if (!$found = $this->vehiculos->delete($id)) {
            return $this->failNotFound(lang('vehiculos.msg.msg_get_fail'));
        }
        $this->vehiculos->purgeDeleted();
        $logData["description"] = lang("vehiculos.logDeleted") . json_encode($infoVehiculos);
        $logData["user"] = $userName;
        $this->log->save($logData);
        return $this->respondDeleted($found, lang('vehiculos.msg_delete'));
    }

}

Metemos el archivo de la vista en App/Views/vehiculos.php con el siguiente código

<?= $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('modulesVehiculos/modalCaptureVehiculos') ?>

<!-- SELECT2 EXAMPLE -->
<div class="card card-default">
    <div class="card-header">
        <div class="float-right">
            <div class="btn-group">

                <button class="btn btn-primary btnAddVehiculos" data-toggle="modal" data-target="#modalAddVehiculos"><i class="fa fa-plus"></i>

                    <?= lang('vehiculos.add') ?>

                </button>

            </div>
        </div>
    </div>
    <div class="card-body">
        <div class="row">
            <div class="col-md-12">
                <div class="table-responsive">
                    <table id="tableVehiculos" class="table table-striped table-hover va-middle tableVehiculos">
                        <thead>
                            <tr>

                                <th>#</th>
                                <th><?= lang('vehiculos.fields.idEmpresa') ?></th>
                                <th><?= lang('vehiculos.fields.idTipoVehiculo') ?></th>
                                <th><?= lang('vehiculos.fields.descripcion') ?></th>
                                <th><?= lang('vehiculos.fields.placas') ?></th>
                                <th><?= lang('vehiculos.fields.created_at') ?></th>
                                <th><?= lang('vehiculos.fields.updated_at') ?></th>
                                <th><?= lang('vehiculos.fields.deleted_at') ?></th>

                                <th><?= lang('vehiculos.fields.actions') ?> </th>

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

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


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

    /**
     * Cargamos la tabla
     */

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

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

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

            {
                'data': 'nombreEmpresa'
            },

            {
                'data': 'descripcionTipo'
            },

            {
                'data': 'descripcion'
            },

            {
                'data': 'placas'
            },

            {
                'data': 'created_at'
            },

            {
                'data': 'updated_at'
            },

            {
                'data': 'deleted_at'
            },

            {
                "data": function (data) {
                    return `<td class="text-right py-0 align-middle">
                         <div class="btn-group btn-group-sm">
                             <button class="btn btn-warning btnEditVehiculos" data-toggle="modal" idVehiculos="${data.id}" data-target="#modalAddVehiculos">  <i class=" fa fa-edit"></i></button>
                             <button class="btn btn-danger btn-delete" data-id="${data.id}"><i class="fas fa-trash"></i></button>
                         </div>
                         </td>`
                }
            }
        ]
    });



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


        var idVehiculos = $("#idVehiculos").val();
        var idEmpresa = $("#idEmpresaVehiculos").val();
        var idTipoVehiculo = $("#idTipoVehiculo").val();
        var descripcion = $("#descripcion").val();
        var placas = $("#placas").val();



        if (idEmpresa == 0 || idEmpresa == null) {

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

        if (idTipoVehiculo == 0 || idTipoVehiculo == null) {

            Toast.fire({
                icon: 'error',
                title: "Tiene que seleccionar el tipo de vehiculo"
            });
            return;
        }



        $("#btnSaveVehiculos").attr("disabled", true);

        var datos = new FormData();
        datos.append("idVehiculos", idVehiculos);
        datos.append("idEmpresa", idEmpresa);
        datos.append("idTipoVehiculo", idTipoVehiculo);
        datos.append("descripcion", descripcion);
        datos.append("placas", placas);


        $.ajax({

            url: "<?= base_url('admin/vehiculos/save') ?>",
            method: "POST",
            data: datos,
            cache: false,
            contentType: false,
            processData: false,
            success: function (respuesta) {
                if (respuesta.match(/Correctamente.*/)) {

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

                    tableVehiculos.ajax.reload();
                    $("#btnSaveVehiculos").removeAttr("disabled");


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

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

                    $("#btnSaveVehiculos").removeAttr("disabled");


                }

            }

        }

        )

    });



    /**
     * Carga datos actualizar
     */


    /*=============================================
     EDITAR Vehiculos
     =============================================*/
    $(".tableVehiculos").on("click", ".btnEditVehiculos", function () {

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

        var datos = new FormData();
        datos.append("idVehiculos", idVehiculos);

        $.ajax({

            url: "<?= base_url('admin/vehiculos/getVehiculos') ?>",
            method: "POST",
            data: datos,
            cache: false,
            contentType: false,
            processData: false,
            dataType: "json",
            success: function (respuesta) {
                $("#idVehiculos").val(respuesta["id"]);

                $("#idEmpresaVehiculos").val(respuesta["idEmpresa"]);
                $("#idEmpresaVehiculos").trigger("change");
                $("#idTipoVehiculo").val(respuesta["idTipoVehiculo"]);
                $("#idTipoVehiculo").trigger("change");
                $("#descripcion").val(respuesta["descripcion"]);
                $("#placas").val(respuesta["placas"]);


            }

        })

    })


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

        var idVehiculos = $(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/vehiculos') ?>/` + idVehiculos,
                            method: 'DELETE',
                        }).done((data, textStatus, jqXHR) => {
                            Toast.fire({
                                icon: 'success',
                                title: jqXHR.statusText,
                            });


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

    $(function () {
        $("#modalAddVehiculos").draggable();

    });



    $("#idTipoVehiculo").select2({
        ajax: {
            url: "<?= site_url('admin/vehiculos/getTipoVehiculoAjax') ?>",
            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 = $('.idEmpresaVehiculos').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() ?>
        

Metemos el archivo que contiene el modal en App/Views/modulesVehiculos/modalCaptureVehiculos.php con el siguiente código

<!-- Modal Vehiculos -->
<div class="modal fade" id="modalAddVehiculos" tabindex="-1" role="dialog" aria-labelledby="modalAddVehiculos" aria-hidden="true">
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title"><?= lang('vehiculos.createEdit') ?></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-vehiculos" class="form-horizontal">
                    <input type="hidden" id="idVehiculos" name="idVehiculos" value="0">

                    <div class="form-group row">
                        <label for="idEmpresa" class="col-sm-2 col-form-label">Empresa</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 class="form-control idEmpresaVehiculos form-controlVehiculos" name="idEmpresaVehiculos" id="idEmpresaVehiculos" style="width:80%;">
                                    <option value="0">Seleccione empresa</option>
                                    <?php
                                    foreach ($empresas as $key => $value) {

                                        echo "<option value='$value[id]'>$value[id] - $value[nombre] </option>  ";
                                    }
                                    ?>

                                </select>

                            </div>
                        </div>
                    </div>
                    <div class="form-group row">
                        <label for="idEmpresa" class="col-sm-2 col-form-label">Tipo Vehiculo</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 class="form-control idTipoVehiculo form-controlVehiculos " name="idTipoVehiculo" id="idTipoVehiculo" style="width:80%;">
                                    <option value="0">Seleccione tipo Vehiculo</option>
              

                                </select>

                            </div>
                        </div>
                    </div>
                    <div class="form-group row">
                        <label for="descripcion" class="col-sm-2 col-form-label"><?= lang('vehiculos.fields.descripcion') ?></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="descripcion" id="descripcion" class="form-control datosVehiculos <?= session('error.descripcion') ? 'is-invalid' : '' ?>" value="<?= old('descripcion') ?>" placeholder="<?= lang('vehiculos.fields.descripcion') ?>" autocomplete="off">
                            </div>
                        </div>
                    </div>
                    <div class="form-group row">
                        <label for="placas" class="col-sm-2 col-form-label"><?= lang('vehiculos.fields.placas') ?></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="placas" id="placas" class="form-control datosVehiculos <?= session('error.placas') ? 'is-invalid' : '' ?>" value="<?= old('placas') ?>" placeholder="<?= lang('vehiculos.fields.placas') ?>" 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" id="btnSaveVehiculos"><?= lang('boilerplate.global.save') ?></button>
            </div>
        </div>
    </div>
</div>

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


<script>

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


       

        $("#idVehiculos").val("0");
        
        $("#idEmpresaVehiculos").val("0");
        
        $(".datosVehiculos").val("");
        
        $("#idEmpresaVehiculos").trigger("change");
        
        
        $("#idTipoVehiculo").val("0");
        
        $("#idTipoVehiculo").trigger("change");
         

        $("#btnSaveVehiculos").removeAttr("disabled");

    });

    /* 
     * AL hacer click al editar
     */



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


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

        //LIMPIAMOS CONTROLES
        $(".form-control").val("");

        $("#idVehiculos").val(idVehiculos);
        $("#btnGuardarVehiculos").removeAttr("disabled");

    });



    $("#idEmpresa").select2();
    
</script>


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

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

<?php

namespace Config;

// Create a new instance of our RouteCollection class.
$routes = Services::routes();

/*
 * --------------------------------------------------------------------
 * Router Setup
 * --------------------------------------------------------------------
 */
$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
// The Auto Routing (Legacy) is very dangerous. It is easy to create vulnerable apps
// where controller filters or CSRF protection are bypassed.
// If you don't want to define all routes, please use the Auto Routing (Improved).
// Set `$autoRoutesImproved` to true in `app/Config/Feature.php` and set the following to true.
// $routes->setAutoRoute(false);

/*
 * --------------------------------------------------------------------
 * Route Definitions
 * --------------------------------------------------------------------
 */

// We get a performance increase by specifying the default
// route since we don't have to scan directories.
$routes->get('/', 'Home::index');

$routes->group('admin', function ($routes) {

    $routes->resource('empresas', [
        'filter' => 'permission:empresas-permisos',
        'controller' => 'EmpresasController',
        'except' => 'show'
    ]);

    $routes->post('empresas/save', 'EmpresasController::save');
    $routes->post('empresas/obtenerEmpresa', 'EmpresasController::obtenerEmpresa');

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

    $routes->post('branchoffices/save', 'BranchofficesController::save');
    $routes->post('branchoffices/getBranchoffices', 'BranchofficesController::getBranchoffices');

    /** Rutas para el correo electronico */
    $routes->resource('emailSettings', [
        'filter' => 'permission:email-permiso',
        'controller' => 'SettingsMailController',
    ]);

    $routes->post('mailSettings/save', 'SettingsMailController::guardar');

    $routes->resource('categorias', [
        'filter' => 'permission:categorias-permission',
        'controller' => 'categoriasController',
        'except' => 'show'
    ]);
    $routes->post('categorias/save', 'CategoriasController::save');
    $routes->post('categorias/getCategorias', 'CategoriasController::getCategorias');
    $routes->post('categorias/buscarFolio', 'CategoriasController::getFolio');
    $routes->post('categorias/getCategoriasAjax', 'CategoriasController::getCategoriasAjax');

    $routes->get('generateCRUD/(:any)', 'AutoCrudController::index/$1');

    //Para futuros envios
    $routes->get('mailSettings/sendMailCotizacion/(:any)/(:any)', 'SettingsMailController::sendMailCotizacionesPDF/$1/$2');

    $routes->resource('custumers', [
        'filter' => 'permission:custumers-permission',
        'controller' => 'custumersController',
        'except' => 'show'
    ]);
    $routes->post('custumers/save', 'CustumersController::save');
    $routes->post('custumers/getCustumers', 'CustumersController::getCustumers');
    $routes->post('custumers/getCustumersAjax', 'CustumersController::getCustumersAjax');
    $routes->post('custumers/getCustumersTodosAjax', 'CustumersController::getCustumersTodosAjax');

    $routes->resource('proveedores', [
        'filter' => 'permission:proveedores-permission',
        'controller' => 'ProveedoresController',
        'except' => 'show'
    ]);
    $routes->post('proveedores/save', 'ProveedoresController::save');
    $routes->post('proveedores/getProveedores', 'ProveedoresController::getProveedores');
    $routes->post('proveedores/getProveedoresAjax', 'ProveedoresController::getProveedoresAjax');

    $routes->resource('products', [
        'filter' => 'permission:products-permission',
        'controller' => 'productsController',
        'except' => 'show'
    ]);
    $routes->post('products/save', 'ProductsController::save');
    $routes->post('products/getProducts', 'ProductsController::getProducts');
    $routes->get('products/getAllProducts/(:any)', 'ProductsController::getAllProducts/$1');

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

    $routes->post('products/getUnidadSATAjax', 'ProductsController::getUnidadSATAjax');
    $routes->post('products/getProductosSATAjax', 'ProductsController::getProductosSATAjax');

    $routes->post('products/getProductsAjax', 'ProductsController::getProductsAjaxSelect2');

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

    $routes->post('costcenter/save', 'CostcenterController::save');
    $routes->post('costcenter/getCostcenter', 'CostcenterController::getCostcenter');
    $routes->post('costCenter/getCostCenterAjax', 'CostcenterController::getCostCenterAjax');

    $routes->resource('storages', [
        'filter' => 'permission:storages-permission',
        'controller' => 'storagesController',
        'except' => 'show'
    ]);
    $routes->post('storages/save', 'StoragesController::save');
    $routes->post('storages/getStorages', 'StoragesController::getStorages');
    $routes->post('storages/getStoragesAjax', 'StoragesController::getStoragesAjax');

    $routes->get('newRequisition', 'RequisitionController::newRequisition');
    $routes->post('requisitions/getLastCode', 'RequisitionController::getLastCode');

    $routes->post('tiposMovimientoInventario/getTiposMovimientoInventarioAjax', 'Tipos_movimientos_inventarioController::getTiposMovimientoAjax');

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

    $routes->get('newQuotes', 'QuotesController::newQuote');

    $routes->get('editQuote/(:any)', 'QuotesController::editQuote/$1');
    $routes->get('convertQuote/(:any)', 'QuotesController::convertQuote/$1');

    $routes->post('quotes/save', 'QuotesController::save');
    $routes->post('quotes/getLastCode', 'QuotesController::getLastCode');
    $routes->get('quotes/report/(:any)', 'QuotesController::report/$1');
    $routes->get('quotes/(:any)/(:any)', 'QuotesController::quotesFilters/$1/$2');

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

    $routes->get('newSells', 'SellsController::newSell');

    $routes->get('editSell/(:any)', 'SellsController::editSell/$1');

    $routes->post('sells/save', 'SellsController::save');
    $routes->post('sells/getLastCode', 'SellsController::getLastCode');
    $routes->get('sells/report/(:any)', 'SellsController::report/$1');
    $routes->get('sells/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)', 'SellsController::sellsFilters/$1/$2/$3/$4/$5/$6');

    $routes->get('reporteVentas', 'SellsController::reportSellsProducts');

    $routes->get('sellsReport/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)', 'SellsController::sellsReport/$1/$2/$3/$4/$5/$6');

    $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');

    $routes->post('payments/save', 'PaymentsController::save');

    $routes->get('payments/getPayments/(:any)', 'PaymentsController::ctrGetPayments/$1');
    $routes->get('payments/delete/(:any)', 'PaymentsController::delete/$1');

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

    $routes->post('peticionesdescargamasiva/save', 'PeticionesdescargamasivaController::save');
    $routes->post('peticionesdescargamasiva/getPeticionesdescargamasiva', 'PeticionesdescargamasivaController::getPeticionesdescargamasiva');

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

    $routes->post('xml/save', 'XmlController::save');
    $routes->post('xml/getXml', 'XmlController::getXml');

    $routes->get('xml/generarPDF/(:any)', 'XmlController::generarPDF/$1');
    $routes->get('xml/descargaXML/(:any)', 'XmlController::descargaXML/$1');

    $routes->get('xml/generarPDFDesdeVenta/(:any)', 'XmlController::generaPDFDesdeVenta/$1');

    $routes->get('xmlFilters/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)', 'XmlController::xmlFilters/$1/$2/$3/$4/$5/$6/$7/$8/$9/$10/$11');

    $routes->get('xml/descargarXMLS/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)', 'XmlController::descargarXMLS/$1/$2/$3/$4/$5/$6/$7/$8/$9/$10/$11');

    $routes->post('xml/cancelaCFDI', 'XmlController::cancelaCFDI');

    $routes->resource('usuariosempresa', [
        'filter' => 'permission:usuariosempresa-permission',
        'controller' => 'usuariosempresaController',
        'except' => 'show'
    ]);
    $routes->post('usuariosempresa/save', 'UsuariosempresaController::save');
    $routes->post('usuariosempresa/getUsuariosempresa', 'UsuariosempresaController::getUsuariosempresa');

    $routes->get('empresa/usuariosPorEmpresa/(:any)', 'EmpresasController::usuariosPorEmpresa/$1');
    $routes->post('empresa/activarDesactivar', 'EmpresasController::activarDesactivar');

    $routes->resource('comprobantes_rd', [
        'filter' => 'permission:comprobantes_rd-permission',
        'controller' => 'comprobantes_rdController',
        'except' => 'show'
    ]);
    $routes->post('comprobantes_rd/save', 'Comprobantes_rdController::save');
    $routes->post('comprobantes_rd/getComprobantes_rd', 'Comprobantes_rdController::getComprobantes_rd');

    $routes->post('comprobantes_rd/getTiposComprobanteAjax', 'Comprobantes_rdController::getComprobantes_rdAjax');

    $routes->get('facturar/(:any)', 'FacturaElectronicaController::timbrar/$1');
    $routes->get('graficas/(:any)/(:any)', 'DashboardController::traerInfo/$1/$2');

    $routes->resource('tipos_movimientos_inventario', [
        'filter' => 'permission:tipos_movimientos_inventario-permission',
        'controller' => 'tipos_movimientos_inventarioController',
        'except' => 'show'
    ]);
    $routes->post('tipos_movimientos_inventario/save', 'Tipos_movimientos_inventarioController::save');
    $routes->post('tipos_movimientos_inventario/getTipos_movimientos_inventario', 'Tipos_movimientos_inventarioController::getTipos_movimientos_inventario');

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

    $routes->post('usuariosAlmacen/getUsuariosAlmacen', 'UsuariosAlmacenController::getUsuariosAlmacen');

    $routes->get('almacen/usuariosPorAlmacen/(:any)', 'StoragesController::usuariosPorAlmacen/$1');
    $routes->post('almacen/activarDesactivar', 'StoragesController::activarDesactivar');

    $routes->resource('tipovehiculo', [
        'filter' => 'permission:tipovehiculo-permission',
        'controller' => 'tipovehiculoController',
        'except' => 'show'
    ]);
    $routes->post('tipovehiculo/save', 'TipovehiculoController::save');
    $routes->post('tipovehiculo/getTipovehiculo', 'TipovehiculoController::getTipovehiculo');
    $routes->post('vehiculos/getTipoVehiculoAjax', 'TipovehiculoController::getTipoVehiculosAjax');

    $routes->resource('vehiculos', [
        'filter' => 'permission:vehiculos-permission',
        'controller' => 'vehiculosController',
        'except' => 'show'
    ]);
    $routes->post('vehiculos/save', 'VehiculosController::save');
    $routes->post('vehiculos/getVehiculos', 'VehiculosController::getVehiculos');
    $routes->post('vehiculos/getVehiculossAjax', 'VehiculosController::getVehiculosAjax');

    $routes->resource('choferes', [
        'filter' => 'permission:choferes-permission',
        'controller' => 'choferesController',
        'except' => 'show'
    ]);
    $routes->post('choferes/save', 'ChoferesController::save');
    $routes->post('choferes/getChoferes', 'ChoferesController::getChoferes');
    $routes->post('choferes/getChoferesAjax', 'ChoferesController::getChoferesAjax');

    $routes->post('usuariosSucursal/getUsuariosSucursal', 'UsuariosSucursalController::getUsuariosSucursal');

    $routes->get('sucursales/usuariosPorSucursal/(:any)', 'BranchofficesController::usuariosPorSucursal/$1');
    $routes->post('sucursales/activarDesactivar', 'BranchofficesController::activarDesactivar');
    $routes->post('sucursales/getSucursalesAjax', 'BranchofficesController::getSucursalesAjax');

    $routes->resource('arqueoCaja', [
        'filter' => 'permission:arqueoCaja-permission',
        'controller' => 'arqueoCajaController',
        'except' => 'show'
    ]);
    $routes->post('arqueoCaja/save', 'ArqueoCajaController::save');
    $routes->post('arqueoCaja/getArqueoCaja', 'ArqueoCajaController::getArqueoCaja');

    $routes->get('ArqueoCaja/report/(:num)', 'ArqueoCajaController::report/$1');

    $routes->post('usuarios/getUsuariosEmpresaAjaxSelect2', 'UsuariosempresaController::getUsuariosEmpresaAjax');

    $routes->post('xml/getRFCEmisorAjax', 'XmlController::getRFCEmisorAjax');
    $routes->post('xml/getRFCReceptorAjax', 'XmlController::getRFCReceptorAjax');

    $routes->resource('seriesfacturaelectronica', [
        'filter' => 'permission:seriesfacturaelectronica-permission',
        'controller' => 'seriesfacturaelectronicaController',
        'except' => 'show'
    ]);
    $routes->post('seriesfacturaelectronica/save', 'SeriesfacturaelectronicaController::save');
    $routes->post('seriesfacturaelectronica/getSeriesfacturaelectronica', 'SeriesfacturaelectronicaController::getSeriesfacturaelectronica');

    $routes->get('xmlenlace/getXMLEnlazados/(:any)', 'XmlController::getXMLEnlazados/$1');
    $routes->get('xml/xmlSinAsignar/(:any)', 'XmlController::xmlSinAsignar/$1');

    $routes->get('enlacexml/delete/(:num)', 'EnlacexmlController::delete/$1');
    $routes->post('xmlenlace/enlazaVenta', 'XmlController::enlazaVenta');

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

    $routes->get('newPago', 'PagosController::newPago');

    $routes->post('sells/obtenerVentasPendientes', 'PagosController::obtenerFacturasPendientes');

    $routes->post('pagos/getLastCode', 'PagosController::getLastCode');

    $routes->post('complementoPago/save', 'PagosController::save');

    $routes->resource('listCompPag', [
        'filter' => 'permission:listaPagos-permission',
        'controller' => 'PagosController',
        'except' => 'show'
    ]);

    $routes->get('pagos/(:any)/(:any)/(:any)/(:any)/(:any)/(:any)', 'PagosController::PagosFilters/$1/$2/$3/$4/$5/$6');
    $routes->get('editPago/(:any)', 'PagosController::editPago/$1');
    $routes->get('pagos/delete/(:any)', 'PagosController::delete/$1');
    $routes->get('timbrarComplemento/(:any)', 'FacturaElectronicaController::timbrarPago/$1');

    $routes->get('xml/generarPDFDesdePago/(:any)', 'XmlController::generaPDFDesdePago/$1');

    /**
     * Rutas para carta porte
     * 
     */
    $routes->get('nuevaCartaPorte', 'CartaPorteController::newCartaPorte');
    $routes->post('cartaPorte/save', 'CartaPorteController::save');
    $routes->post('cartaPorte/getLastCode', 'CartaPorteController::getLastCode');
    $routes->resource('listCompPag', [
        'filter' => 'permission:listaPagos-permission',
        'controller' => 'PagosController',
        'except' => 'show'
    ]);

    /**
     * Ruta para las ubicaciones
     */
    $routes->resource('ubicaciones', [
        'filter' => 'permission:ubicaciones-permission',
        'controller' => 'ubicacionesController',
        'except' => 'show'
    ]);
    
    $routes->post('ubicaciones/save', 'UbicacionesController::save');
    $routes->post('ubicaciones/getUbicaciones', 'UbicacionesController::getUbicaciones');
    $routes->post('ubicaciones/getColoniaSATAjax', 'UbicacionesController::getColoniasSAT');
    $routes->post('ubicaciones/getLocalidadSATAjax', 'UbicacionesController::getLocalidadSAT');
    $routes->post('ubicaciones/getPaisesSATAjax', 'UbicacionesController::getPaisesSAT');
    $routes->post('ubicaciones/getEstadosSATAjax', 'UbicacionesController::getEstadosSAT');
    $routes->post('ubicaciones/getMunicipiosSATAjax', 'UbicacionesController::getMunicipiosSAT');
    
});

/*
 * --------------------------------------------------------------------
 * Additional Routing
 * --------------------------------------------------------------------
 *
 * There will often be times that you need additional routing and you
 * need it to be able to override any defaults in this file. Environment
 * based routes is one such time. require() additional route files here
 * to make that happen.
 *
 * You will have access to the $routes object within that file without
 * needing to reload it.
 */
if (is_file(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
    require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}

Agregamos el menú con los siguientes datos

Agregamos los permisos

Y listo ya tenemos nuestro catalogo hecho

Video Demostrativo