Para corregir solo hay que instalar pavucontrol
sudo apt-get install pavucontrol
Abren pavucontrol y seleccionan headphones

Y listo problema solucionado
Para corregir solo hay que instalar pavucontrol
sudo apt-get install pavucontrol
Abren pavucontrol y seleccionan headphones
Y listo problema solucionado
Open Source Point of Sale es un sistema de punto de venta basado en la web. La aplicación está escrita en PHP, utiliza MySQL (o MariaDB) como back-end de almacenamiento de datos y tiene una interfaz de usuario simple pero intuitiva.
La última versión 3.x es una revisión completa del software original. Utiliza CodeIgniter 3 como marco y se basa en Bootstrap 3 usando temas de Bootswatch. Junto con funcionalidad y seguridad mejoradas.
Es este caso hicimos una versión desktop para hacer una instalación mas fácil y cómoda en el caso de usar Windows 10
Programa ideal para papelerías, tiendas pequeñas, expendios del pacifico o tecate ETC
Las características incluyen:
El proceso de instalación se divide en dos partes, la instalación de la base de datos y la instalación del sistema en general
Instalando la base de datos
Para instalar la base de datos ocuparemos el instalador de MariaDB 11 y el archivo de base de datos OSPOS.SQL les dejo los enlaces de descarga desde Mega.nz
Instalación de OSPOS Desktop
Descargamos el instalador donde viene el programa
No se olviden de programar los respaldos automáticos pueden ver como generarles aquí GENERAR RESPALDOS AUTOMATICOS MARIADB
Dentro del software libre tenemos muchas herramientas que nos permiten realizar nuestro trabajo y en este caso que es la edición de video hay una herramienta hecha en Python que nos permite quitar los silencios en un video, es decir, quitar esas regiones del video en las que no hablamos.
Bien para ello necesitaremos descargar el software jumpcutter que la pueden descargar desde Github, para descargarlo usan el siguiente comando
git clone https://github.com/carykh/jumpcutter
Para usarlo necesitamos la dependencia de Python python3-pip, podemos instalarla con el siguiente comando
sudo apt install python3-pip
entramos al directorio de jumpcutter que descargamos
cd jumpcutter/
Ahora instalamos las dependencias de jumpcutter
pip install --user -r requirements.txt
Ahora si podemos usar la utilitaria para quitarle los silencios a nuestros videos, colocamos el video con nombre 1.mkv, si nuestro video es de 30 fotogramas por segundo le ponemos en el –frame_rate 30, se es de 24 le ponemos –frame_rate 24
python3 jumpcutter.py --input_file 1.mkv --sounded_speed 1 --silent_speed 999999 --frame_margin 2 --frame_rate 30
Y listo esto nos generara un archivo 1_altered.mkv
Ya hemos vuelvo después de varios años instalamos Linux Mint 21 dejando atrás a Zorin Linux
Vamos a dejar la maquina lista para la edición de videos, programación y edición de música para ello le instalaremos el siguiente software
Primero hacemos el clásico update y upgrade
sudo apt update
sudo apt upgrade
Instalamos RustDesk que es un software de escritorio remoto similar al AnyDesk
wget https://github.com/rustdesk/rustdesk/releases/download/1.2.0/rustdesk-1.2.0-x86_64.deb
Le asignamos el bit de ejecutable
sudo chmod +x rustdesk-1.2.0-x86_64.deb
Y lo instalamos con este comando
sudo dpkg -i rustdesk-1.2.0-x86_64.deb
Ahora vamos a instalar Java y el IDE Netbeans
Instalamos Java
sudo apt install default-jdk
Borramos las preferencias del Snap
sudo rm /etc/apt/preferences.d/nosnap.pref
Instalamos snapd
sudo apt install snapd
Instalamos Netbeans
sudo snap install netbeans --classic
Ahora instalaremos PHP
Agregamos el repositorio
sudo add-apt-repository ppa:ondrej/php
Actualizamos
sudo apt update
Después instalamos los siguientes comandos uno por uno
sudo apt install php8.1
sudo apt install php8.1-mysql
sudo apt install php8.1-xdebug
sudo apt install php8.1-mbstring
sudo apt-get install php-intl
sudo apt install php
sudo apt install php8.2-pdo-mysql
Ahora para instalar composer solo ejecutamos el siguiente instrucción
sudo apt install composer
Ahora instalamos la pila XAMPP que contiene PHP8.2 MySQL y Apache
Primero descargamos el archivo .run con el siguiente comando
wget https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/8.2.4/xampp-linux-x64-8.2.4-0-installer.run
Le asignamos el bit de ejecutable
sudo chmod +x xampp-linux-x64-8.2.4-0-installer.run
Y por ultimo ejecutamos el archivo
sudo ./xampp-linux-x64-8.2.4-0-installer.run
Instalamos Telegram que es como un WhatsApp pero mucho mejor
sudo apt install telegram-desktop -y
Instalamos OBS Studio para nuestras transmisiones en vivo y grabaciones de nuevo escritorio, aunque realmente para grabar prefiero el simplescreenrecorder
sudo apt install obs-studio
Instalamos Simple Screen Recorder para grabar nuestro escritorio para los videos tutoriales
sudo apt install simplescreenrecorder
Instalamos Kdenlive para editar videos de gran calidad
sudo apt install obs-studio
Instalamos audacity para edición, corrección y mejoramiento de pistas de audio
sudo apt install audacity
Instalamos Ardour un DAW muy profesional similar a Pro Tools para crear música y podcast
sudo apt install ardour
Instalamos guitarix para efectos de guitarra eléctrica
sudo apt install guitarix
Instalamos Remmina, es el equivalente a Escritorio Remoto de Windows pero mejor
sudo apt install remmina
Instalamos Filezilla un programa para subir archivos a nuestros hosting compartido o VPS
sudo apt install filezilla
Instalamos Gambas3 Un lenguaje de programación RAD similar a Visual Basic, nos servira para crear programas rapidamente tanto de escritorio como Web
sudo apt install gambas3
instalamos Visual Studio Code, anteriormente usábamos Atom, podremos programar en PHP y subir facilmente el fuente en GitHub
Instalamos los certificados
sudo apt install dirmngr ca-certificates software-properties-common apt-transport-https -y
Agregamos el repositorio
curl -fSsL https://packages.microsoft.com/keys/microsoft.asc | sudo gpg --dearmor | sudo tee /usr/share/keyrings/vscode.gpg > /dev/null
echo deb [arch=amd64 signed-by=/usr/share/keyrings/vscode.gpg] https://packages.microsoft.com/repos/vscode stable main | sudo tee /etc/apt/sources.list.d/vscode.list
Actualizamos e instalamos
sudo apt update
sudo apt install code -y
Instalamos quemador de discos brasero, si aun puede usarse
sudo apt install brasero
Instalamos programa para crear mapas conceptuales
sudo apt install minder
Instalamos administrador de fotos, el mejor que he visto libre, identifica rostros ademas ubica en el globo en que lugar se tomo la fotografía
Para instalarlo corremos el siguiente comando
sudo apt install digikam
Ahora nos toca instalar pomodoro una útil herramienta la cual nos permitirá cronometrar nuestras actividades, dar minutos de descanso y anotar cuanto tiempo nos llevo una actividad, muy útil para los programadores
sudo apt install gnomo-shell-pomodoro
Ahora procederemos instalar DBeaver un cliente muy potente para diferentes motores de base de datos
Primero descargamos el archivo .deb
wget https://dbeaver.io/files/dbeaver-ce_latest_amd64.deb
Asignamos el bit de ejecutable
sudo chmod +x dbeaver-ce_latest_amd64.deb
Instalamos dbeaver con el siguiente comando
sudo dpkg -i dbeaver-ce_latest_amd64.deb
Para instalar GIMP un potente editor de fotografía corremos el siguiente comando
sudo apt install gimp
La DIOT es la declaración informativa de operaciones con Terceros, la cual es una obligación fiscal prevista más del IVA donde se da a conocer el estado de las operaciones para con terceros (como su nombre lo dice) o lo que es lo mismo con los proveedores.
Leer Mas: Generador DIOT para Windows 10Si eres persona física o moral que tributa en el Régimen Simplificado de Confianza; o persona física con ingresos por actividades empresariales, profesionales y/o arrendamiento, cuyos ingresos totales del ejercicio inmediato anterior no excedieron de 4 millones de pesos o iniciaste actividades en el ejercicio y estimas que tus ingresos no excederán de la cantidad señalada, quedarás relevado de cumplir con la presentación de la Información de Operaciones con Terceros (DIOT) a que se refiere el artículo 32, fracción VIII de la Ley del IVA.
Hemos desarrollado un programa para generar la DIOT en base a un layout
Incluimos un layout de ejemplo en cual pueden obtener desde la aplicación
Se puede cambiar la configuración por RFC
Ya vimos como usar AutoCrud para crear los catálogos, en esta ocasión tambien usamos autocrud, aun así dejaremos el código fuente completo de este modulo
Creamos el archivo modelo al app/models/CustumersModel.php con el siguiente contenido
Leer Mas: Creando CRUD de clientes #06<?php
namespace App\Models;
use CodeIgniter\Model;
class CustumersModel extends Model{
protected $table = 'custumers';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'array';
protected $useSoftDeletes = true;
protected $allowedFields = ['id','firstname','lastname','taxID','email','direction','birthdate','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 nuestro archivo controlador app/controllers/CustumersControllers.php
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
use \App\Models\{CustumersModel};
use App\Models\LogModel;
use CodeIgniter\API\ResponseTrait;
class CustumersController extends BaseController {
use ResponseTrait;
protected $log;
protected $custumers;
public function __construct() {
$this->custumers = new CustumersModel();
$this->log = new LogModel();
helper('menu');
helper('utilerias');
}
public function index() {
if ($this->request->isAJAX()) {
$datos = $this->custumers->select('id,firstname,lastname,taxID,email,direction,birthdate,created_at,updated_at,deleted_at')->where('deleted_at', null);
return \Hermawan\DataTables\DataTable::of($datos)->toJson(true);
}
$fechaActual = fechaMySQLADateTimeHTML5(fechaHoraActual());
$titulos["title"] = lang('custumers.title');
$titulos["subtitle"] = lang('custumers.subtitle');
$titulos["fecha"] = $fechaActual;
return view('custumers', $titulos);
}
/**
* Read Custumers
*/
public function getCustumers() {
$idCustumers = $this->request->getPost("idCustumers");
$datosCustumers = $this->custumers->find($idCustumers);
echo json_encode($datosCustumers);
}
/**
* Save or update Custumers
*/
public function save() {
helper('auth');
$userName = user()->username;
$idUser = user()->id;
$datos = $this->request->getPost();
if ($datos["idCustumers"] == 0) {
try {
if ($this->custumers->save($datos) === false) {
$errores = $this->custumers->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->custumers->update($datos["idCustumers"], $datos) == false) {
$errores = $this->custumers->errors();
foreach ($errores as $field => $error) {
echo $error . " ";
}
return;
} else {
$dateLog["description"] = lang("custumers.logUpdated") . json_encode($datos);
$dateLog["user"] = $userName;
$this->log->save($dateLog);
echo "Actualizado Correctamente";
return;
}
}
return;
}
/**
* Delete Custumers
* @param type $id
* @return type
*/
public function delete($id) {
$infoCustumers = $this->custumers->find($id);
helper('auth');
$userName = user()->username;
if (!$found = $this->custumers->delete($id)) {
return $this->failNotFound(lang('custumers.msg.msg_get_fail'));
}
$this->custumers->purgeDeleted();
$logData["description"] = lang("custumers.logDeleted") . json_encode($infoCustumers);
$logData["user"] = $userName;
$this->log->save($logData);
return $this->respondDeleted($found, lang('custumers.msg_delete'));
}
}
Creamos nuestro archivo de la visa en app/views/custumers.php con el siguiente contenido
<?= $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('modulesCustumers/modalCaptureCustumers') ?>
<!-- SELECT2 EXAMPLE -->
<div class="card card-default">
<div class="card-header">
<div class="float-right">
<div class="btn-group">
<button class="btn btn-primary btnAddCustumers" data-toggle="modal" data-target="#modalAddCustumers"><i class="fa fa-plus"></i>
<?= lang('custumers.add') ?>
</button>
</div>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
<div class="table-responsive">
<table id="tableCustumers" class="table table-striped table-hover va-middle tableCustumers">
<thead>
<tr>
<th>#</th>
<th><?= lang('custumers.fields.firstname') ?></th>
<th><?= lang('custumers.fields.lastname') ?></th>
<th><?= lang('custumers.fields.taxID') ?></th>
<th><?= lang('custumers.fields.email') ?></th>
<th><?= lang('custumers.fields.direction') ?></th>
<th><?= lang('custumers.fields.birthdate') ?></th>
<th><?= lang('custumers.fields.created_at') ?></th>
<th><?= lang('custumers.fields.updated_at') ?></th>
<th><?= lang('custumers.fields.deleted_at') ?></th>
<th><?= lang('custumers.fields.actions') ?> </th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- /.card -->
<?= $this->endSection() ?>
<?= $this->section('js') ?>
<script>
/**
* Cargamos la tabla
*/
var tableCustumers = $('#tableCustumers').DataTable({
processing: true,
serverSide: true,
responsive: true,
autoWidth: false,
order: [[1, 'asc']],
ajax: {
url: '<?= base_url(route_to('admin/custumers')) ?>',
method: 'GET',
dataType: "json"
},
columnDefs: [{
orderable: false,
targets: [10],
searchable: false,
targets: [10]
}],
columns: [{
'data': 'id'
},
{
'data': 'firstname'
},
{
'data': 'lastname'
},
{
'data': 'taxID'
},
{
'data': 'email'
},
{
'data': 'direction'
},
{
'data': 'birthdate'
},
{
'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 btnEditCustumers" data-toggle="modal" idCustumers="${data.id}" data-target="#modalAddCustumers"> <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', '#btnSaveCustumers', function (e) {
var idCustumers = $("#idCustumers").val();
var firstname = $("#firstname").val();
var lastname = $("#lastname").val();
var taxID = $("#taxID").val();
var email = $("#email").val();
var direction = $("#direction").val();
var birthdate = $("#birthdate").val();
$("#btnSaveCustumers").attr("disabled", true);
var datos = new FormData();
datos.append("idCustumers", idCustumers);
datos.append("firstname", firstname);
datos.append("lastname", lastname);
datos.append("taxID", taxID);
datos.append("email", email);
datos.append("direction", direction);
datos.append("birthdate", birthdate);
$.ajax({
url: "<?= route_to('admin/custumers/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"
});
tableCustumers.ajax.reload();
$("#btnSaveCustumers").removeAttr("disabled");
$('#modalAddCustumers').modal('hide');
} else {
Toast.fire({
icon: 'error',
title: respuesta
});
$("#btnSaveCustumers").removeAttr("disabled");
}
}
}
)
});
/**
* Carga datos actualizar
*/
/*=============================================
EDITAR Custumers
=============================================*/
$(".tableCustumers").on("click", ".btnEditCustumers", function () {
var idCustumers = $(this).attr("idCustumers");
var datos = new FormData();
datos.append("idCustumers", idCustumers);
$.ajax({
url: "<?= base_url(route_to('admin/custumers/getCustumers')) ?>",
method: "POST",
data: datos,
cache: false,
contentType: false,
processData: false,
dataType: "json",
success: function (respuesta) {
$("#idCustumers").val(respuesta["id"]);
$("#firstname").val(respuesta["firstname"]);
$("#lastname").val(respuesta["lastname"]);
$("#taxID").val(respuesta["taxID"]);
$("#email").val(respuesta["email"]);
$("#direction").val(respuesta["direction"]);
$("#birthdate").val(respuesta["birthdate"]);
}
})
})
/*=============================================
ELIMINAR custumers
=============================================*/
$(".tableCustumers").on("click", ".btn-delete", function () {
var idCustumers = $(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(route_to('admin/custumers')) ?>/` + idCustumers,
method: 'DELETE',
}).done((data, textStatus, jqXHR) => {
Toast.fire({
icon: 'success',
title: jqXHR.statusText,
});
tableCustumers.ajax.reload();
}).fail((error) => {
Toast.fire({
icon: 'error',
title: error.responseJSON.messages.error,
});
})
}
})
})
$(function () {
$("#modalAddCustumers").draggable();
});
</script>
<?= $this->endSection() ?>
Para el modal creamos el siguiente archivo app/views/modulesCustumers/modalCaptureCustumers.php con el siguiente contenido
<!-- Modal Custumers -->
<div class="modal fade" id="modalAddCustumers" tabindex="-1" role="dialog" aria-labelledby="modalAddCustumers" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><?= lang('custumers.createEdit') ?></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form id="form-custumers" class="form-horizontal">
<input type="hidden" id="idCustumers" name="idCustumers" value="0">
<div class="form-group row">
<label for="firstname" class="col-sm-2 col-form-label"><?= lang('custumers.fields.firstname') ?></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="firstname" id="firstname" class="form-control <?= session('error.firstname') ? 'is-invalid' : '' ?>" value="<?= old('firstname') ?>" placeholder="<?= lang('custumers.fields.firstname') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="lastname" class="col-sm-2 col-form-label"><?= lang('custumers.fields.lastname') ?></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="lastname" id="lastname" class="form-control <?= session('error.lastname') ? 'is-invalid' : '' ?>" value="<?= old('lastname') ?>" placeholder="<?= lang('custumers.fields.lastname') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="taxID" class="col-sm-2 col-form-label"><?= lang('custumers.fields.taxID') ?></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="taxID" id="taxID" class="form-control <?= session('error.taxID') ? 'is-invalid' : '' ?>" value="<?= old('taxID') ?>" placeholder="<?= lang('custumers.fields.taxID') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-2 col-form-label"><?= lang('custumers.fields.email') ?></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="email" id="email" class="form-control <?= session('error.email') ? 'is-invalid' : '' ?>" value="<?= old('email') ?>" placeholder="<?= lang('custumers.fields.email') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="direction" class="col-sm-2 col-form-label"><?= lang('custumers.fields.direction') ?></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="direction" id="direction" class="form-control <?= session('error.direction') ? 'is-invalid' : '' ?>" value="<?= old('direction') ?>" placeholder="<?= lang('custumers.fields.direction') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="birthdate" class="col-sm-2 col-form-label"><?= lang('custumers.fields.birthdate') ?></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="datetime-local" name="birthdate" id="birthdate" class="form-control <?= session('error.birthdate') ? 'is-invalid' : '' ?>" value="<?= $fecha ?>" placeholder="<?= lang('custumers.fields.birthdate') ?>" 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="btnSaveCustumers"><?= lang('boilerplate.global.save') ?></button>
</div>
</div>
</div>
</div>
<?= $this->section('js') ?>
<script>
$(document).on('click', '.btnAddCustumers', function (e) {
$(".form-control").val("");
$("#idCustumers").val("0");
$("#birthdate").val("<?= $fecha ?>");
$("#btnSaveCustumers").removeAttr("disabled");
});
/*
* AL hacer click al editar
*/
$(document).on('click', '.btnEditCustumers', function (e) {
var idCustumers = $(this).attr("idCustumers");
//LIMPIAMOS CONTROLES
$(".form-control").val("");
$("#idCustumers").val(idCustumers);
$("#btnGuardarCustumers").removeAttr("disabled");
});
</script>
<?= $this->endSection() ?>
Para la traducción en ingles creamos el archivo app/languaje/es/custumers.php con el siguiente contenido
<?php
$custumers["logDescription"] = "The custumers was saved with the following data:";
$custumers["logUpdate"] = "The custumers was updated with the following data:";
$custumers["logDeleted"] = "The custumers was deleted with the following data:";
$custumers["msg_delete"] = "The custumers was deleted correctly:";
$custumers["add"] = "Add Custumers";
$custumers["edit"] = "Edit custumers";
$custumers["createEdit"] = "Create / Edit";
$custumers["title"] = "custumers management";
$custumers["subtitle"] = "custumers list";
$custumers["fields"]["firstname"] = "Firstname";
$custumers["fields"]["lastname"] = "Lastname";
$custumers["fields"]["taxID"] = "TaxID";
$custumers["fields"]["email"] = "Email";
$custumers["fields"]["direction"] = "Direction";
$custumers["fields"]["birthdate"] = "Birthdate";
$custumers["fields"]["created_at"] = "Created_at";
$custumers["fields"]["updated_at"] = "Updated_at";
$custumers["fields"]["deleted_at"] = "Deleted_at";
$custumers["fields"]["actions"] = "Actions";
$custumers["msg"]["msg_insert"] = "The custumers has been correctly added.";
$custumers["msg"]["msg_update"] = "The custumers has been correctly modified.";
$custumers["msg"]["msg_delete"] = "The custumers has been correctly deleted.";
$custumers["msg"]["msg_get"] = "The Custumers has been successfully get.";
$custumers["msg"]["msg_get_fail"] = "The custumers not found or already deleted.";
return $custumers;
Para nuestra traduccion en español creamos el archivo app/languaje/es/custumers.php
<?php
$custumers["logDescription"] = "El registro en clientes fue guardado con los siguientes datos:";
$custumers["logUpdate"] = "El registro en clientes fue actualizado con los siguientes datos:";
$custumers["logDeleted"] = "El registro en clientes fue eliminado con los siguientes datos:";
$custumers["msg_delete"] = "El Registro en clientes fue eliminado correctamente:";
$custumers["add"] = "Agregar Cliente";
$custumers["edit"] = "Editar Cliente";
$custumers["createEdit"] = "Crear / Editar";
$custumers["title"] = "Admon. Clientes";
$custumers["subtitle"] = "Lista de Clientes";
$custumers["fields"]["firstname"] = "Nombre";
$custumers["fields"]["lastname"] = "Apellido";
$custumers["fields"]["taxID"] = "RFC";
$custumers["fields"]["email"] = "Correo Electronico";
$custumers["fields"]["direction"] = "Direccion";
$custumers["fields"]["birthdate"] = "Fecha de nacimiento";
$custumers["fields"]["created_at"] = "Fecha de creacion";
$custumers["fields"]["updated_at"] = "Ultima modificacion";
$custumers["fields"]["deleted_at"] = "Fecha de eliminacion";
$custumers["fields"]["actions"] = "Acciones";
$custumers["msg"]["msg_insert"] = "Registro agregado correctamente.";
$custumers["msg"]["msg_update"] = "Registro modificado correctamente.";
$custumers["msg"]["msg_delete"] = "Registro eliminado correctamente.";
$custumers["msg"]["msg_get"] = "Registro obtenido correctamente.";
$custumers["msg"]["msg_get_fail"] = "Registro no encontrado o eliminado.";
return $custumers;
Creamos nuestro archivo de migración en app/databases/migrations/2023-04-21063335_Custumers.php con el siguiente contenido
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class Custumers extends Migration
{
public function up()
{
// Custumers
$this->forge->addField([
'id' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true],
'firstname' => ['type' => 'varchar', 'constraint' => 128, 'null' => true],
'lastname' => ['type' => 'varchar', 'constraint' => 128, 'null' => true],
'taxID' => ['type' => 'varchar', 'constraint' => 64, 'null' => true],
'email' => ['type' => 'varchar', 'constraint' => 128, 'null' => true],
'direction' => ['type' => 'varchar', 'constraint' => 1024, 'null' => true],
'birthdate' => ['type' => 'datetime' , '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('custumers', true);
}
public function down(){
$this->forge->dropTable('custumers', true);
}
}
Corremos el comando php serve migrate para levantar la tabla custumers
Listo ya solo queda configurar los permisos y menú
Ya vimos como crear módulos y catalogo ahora mostraremos como automatizar esa parte del proceso de desarrollo para ser un poco mas eficientes para ello escribimos un código que escribe el código repetitivo
Creamos el archivo app/controller/AutoCrudController.php con el siguiente código
Leer Mas: Creando CRUD de categorías usando AutoCrud #05<?php
namespace App\Controllers;
use App\Controllers\BaseController;
use App\Controllers\Time;
use CodeIgniter\API\ResponseTrait;
use Faker\Provider\zh_CN\DateTime;
class AutoCrudController extends BaseController {
use ResponseTrait;
protected $db;
public function __construct() {
$this->db = \Config\Database::connect();
helper('utilerias');
}
public function index($table) {
/*
$this->generateModel($table);
$this->generateController($table);
$this->generateView($table);
$this->generateViewModal($table);
$this->generateLanguage($table);
*/
$this->generateMigration($table);
//$this->generateLanguageES($table);
$tableUpCase = ucfirst($table);
$route = <<<EOF
\$routes->resource('$table', [
'filter' => 'permission:$table-permission',
'controller' => '{$table}Controller',
'except' => 'show'
]);
\$routes->post('$table/save', '{$tableUpCase}Controller::save');
\$routes->post('{$table}/get{$tableUpCase}', '{$tableUpCase}Controller::get$tableUpCase');
EOF;
echo $route;
}
/**
* Generate Model
*/
public function generateModel($table) {
$tableUpCase = ucfirst($table);
$query = $this->db->getFieldNames($table);
$fields = "";
foreach ($query as $field) {
$fields .= "'" . $field . "'" . ",";
}
$fields = substr($fields, 0, strlen($fields) - 1);
$nombreClase = ucfirst($table) . "Model";
$model = <<<EOF
<?php
namespace App\Models;
use CodeIgniter\Model;
class $nombreClase extends Model{
protected \$table = '$table';
protected \$primaryKey = 'id';
protected \$useAutoIncrement = true;
protected \$returnType = 'array';
protected \$useSoftDeletes = true;
protected \$allowedFields = [$fields];
protected \$useTimestamps = true;
protected \$createdField = 'created_at';
protected \$deletedField = 'deleted_at';
protected \$validationRules = [
];
protected \$validationMessages = [];
protected \$skipValidation = false;
}
EOF;
file_put_contents(ROOTPATH . "app/Models/$nombreClase.php", $model);
}
/**
* Generate Controller
*
*/
/**
* Generate Controller
*/
public function generateController($table) {
$query = $this->db->getFieldNames($table);
$fields = "";
foreach ($query as $field) {
$fields .= $field . ",";
}
$fields = substr($fields, 0, strlen($fields) - 1);
$nameClassModel = ucfirst($table) . "Model";
$tableUpCase = ucfirst($table);
$controller = <<<EOF
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
use \App\Models\{$nameClassModel};
use App\Models\LogModel;
use CodeIgniter\API\ResponseTrait;
class {$tableUpCase}Controller extends BaseController {
use ResponseTrait;
protected \$log;
protected $$table;
public function __construct() {
\$this->$table = new $nameClassModel();
\$this->log = new LogModel();
helper('menu');
}
public function index() {
if (\$this->request->isAJAX()) {
\$datos = \$this->{$table}->select('$fields')->where('deleted_at', null);
return \Hermawan\DataTables\DataTable::of(\$datos)->toJson(true);
}
\$titulos["title"] = lang('$table.title');
\$titulos["subtitle"] = lang('$table.subtitle');
return view('$table', \$titulos);
}
/**
* Read $tableUpCase
*/
public function get$tableUpCase() {
\$id$tableUpCase = \$this->request->getPost("id$tableUpCase");
\$datos$tableUpCase = \$this->{$table}->find(\$id$tableUpCase);
echo json_encode(\$datos$tableUpCase);
}
/**
* Save or update $tableUpCase
*/
public function save() {
helper('auth');
\$userName = user()->username;
\$idUser = user()->id;
\$datos = \$this->request->getPost();
if (\$datos["id$tableUpCase"] == 0) {
try {
if (\$this->{$table}->save(\$datos) === false) {
\$errores = \$this->{$table}->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->{$table}->update(\$datos["id$tableUpCase"], \$datos) == false) {
\$errores = \$this->{$table}->errors();
foreach (\$errores as \$field => \$error) {
echo \$error . " ";
}
return;
} else {
\$dateLog["description"] = lang("$table.logUpdated") . json_encode(\$datos);
\$dateLog["user"] = \$userName;
\$this->log->save(\$dateLog);
echo "Actualizado Correctamente";
return;
}
}
return;
}
/**
* Delete $tableUpCase
* @param type \$id
* @return type
*/
public function delete(\$id) {
\$info$tableUpCase = \$this->{$table}->find(\$id);
helper('auth');
\$userName = user()->username;
if (!\$found = \$this->{$table}->delete(\$id)) {
return \$this->failNotFound(lang('$table.msg.msg_get_fail'));
}
\$this->{$table}->purgeDeleted();
\$logData["description"] = lang("{$table}.logDeleted") . json_encode(\$info$tableUpCase);
\$logData["user"] = \$userName;
\$this->log->save(\$logData);
return \$this->respondDeleted(\$found, lang('$table.msg_delete'));
}
}
EOF;
file_put_contents(ROOTPATH . "app/Controllers/{$tableUpCase}Controller.php", $controller);
}
/**
* Generate View
*/
public function generateView($table) {
$tableUpCase = ucfirst($table);
$query = $this->db->getFieldNames($table);
$fields = "";
$columnaDatatable = "";
$datosDatatable = "";
$variablesGuardar1 = "";
$variablesFormData = "";
$inputsEdit = "";
$contador = 0;
foreach ($query as $field) {
$fields .= $field . ",";
if ($contador > 0) {
$columnaDatatable .= "<th><?= lang('$table.fields.$field') ?></th>" . PHP_EOL;
$datosDatatable .= <<<EOF
{
'data': '$field'
},
EOF . PHP_EOL;
if ($field <> "created_at" && $field <> "updated_at" && $field <> "deleted_at") {
$variablesGuardar1 .= "var $field = $(\"#$field\").val();" . PHP_EOL;
$variablesFormData .= "datos.append(\"$field\", $field);" . PHP_EOL;
$inputsEdit .= "$(\"#$field\").val(respuesta[\"$field\"]);" . PHP_EOL;
;
}
} else {
$variablesGuardar1 .= <<<EOF
var id$tableUpCase = $("#id$tableUpCase").val();
EOF . PHP_EOL;
$variablesFormData .= <<<EOF
var datos = new FormData();
datos.append("id$tableUpCase", id$tableUpCase);
EOF . PHP_EOL;
}
$contador++;
}
$fields = substr($fields, 0, strlen($fields) - 1);
$nameClassModel = ucfirst($table) . "Model";
$view = <<<EOF
<?= \$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('modules$tableUpCase/modalCapture$tableUpCase') ?>
<!-- SELECT2 EXAMPLE -->
<div class="card card-default">
<div class="card-header">
<div class="float-right">
<div class="btn-group">
<button class="btn btn-primary btnAdd$tableUpCase" data-toggle="modal" data-target="#modalAdd$tableUpCase"><i class="fa fa-plus"></i>
<?= lang('$table.add') ?>
</button>
</div>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
<div class="table-responsive">
<table id="table$tableUpCase" class="table table-striped table-hover va-middle table$tableUpCase">
<thead>
<tr>
<th>#</th>
$columnaDatatable
<th><?= lang('$table.fields.actions') ?> </th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- /.card -->
<?= \$this->endSection() ?>
<?= \$this->section('js') ?>
<script>
/**
* Cargamos la tabla
*/
var table{$tableUpCase} = $('#table{$tableUpCase}').DataTable({
processing: true,
serverSide: true,
responsive: true,
autoWidth: false,
order: [[1, 'asc']],
ajax: {
url: '<?= base_url(route_to('admin/$table')) ?>',
method: 'GET',
dataType: "json"
},
columnDefs: [{
orderable: false,
targets: [$contador],
searchable: false,
targets: [$contador]
}],
columns: [{
'data': 'id'
},
$datosDatatable
{
"data": function (data) {
return `<td class="text-right py-0 align-middle">
<div class="btn-group btn-group-sm">
<button class="btn btn-warning btnEdit$tableUpCase" data-toggle="modal" id$tableUpCase="\${data.id}" data-target="#modalAdd$tableUpCase"> <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', '#btnSave$tableUpCase', function (e) {
$variablesGuardar1
$("#btnSave$tableUpCase").attr("disabled", true);
$variablesFormData
$.ajax({
url: "<?= route_to('admin/$table/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"
});
table$tableUpCase.ajax.reload();
$("#btnSave$tableUpCase").removeAttr("disabled");
$('#modalAdd$tableUpCase').modal('hide');
} else {
Toast.fire({
icon: 'error',
title: respuesta
});
$("#btnSave$tableUpCase").removeAttr("disabled");
}
}
}
)
});
/**
* Carga datos actualizar
*/
/*=============================================
EDITAR $tableUpCase
=============================================*/
$(".table$tableUpCase").on("click", ".btnEdit$tableUpCase", function () {
var id$tableUpCase = $(this).attr("id$tableUpCase");
var datos = new FormData();
datos.append("id$tableUpCase", id$tableUpCase);
$.ajax({
url: "<?= base_url(route_to('admin/$table/get$tableUpCase')) ?>",
method: "POST",
data: datos,
cache: false,
contentType: false,
processData: false,
dataType: "json",
success: function (respuesta) {
$("#id$tableUpCase").val(respuesta["id"]);
$inputsEdit
}
})
})
/*=============================================
ELIMINAR $table
=============================================*/
$(".table$tableUpCase").on("click", ".btn-delete", function () {
var id$tableUpCase = $(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(route_to('admin/$table')) ?>/` + id$tableUpCase,
method: 'DELETE',
}).done((data, textStatus, jqXHR) => {
Toast.fire({
icon: 'success',
title: jqXHR.statusText,
});
table$tableUpCase.ajax.reload();
}).fail((error) => {
Toast.fire({
icon: 'error',
title: error.responseJSON.messages.error,
});
})
}
})
})
$(function () {
$("#modalAdd$tableUpCase").draggable();
});
</script>
<?= \$this->endSection() ?>
EOF;
file_put_contents(ROOTPATH . "app/Views/{$table}.php", $view);
}
/**
* Generate ViewModal
*/
public function generateViewModal($table) {
$tableUpCase = ucfirst($table);
$query = $this->db->getFieldNames($table);
$fields = "";
$campos = "";
$contador = 0;
foreach ($query as $field) {
$fields .= $field . ",";
if ($contador > 0) {
if ($field <> "created_at" && $field <> "updated_at" && $field <> "deleted_at") {
$campos .= <<<EOF
<div class="form-group row">
<label for="$field" class="col-sm-2 col-form-label"><?= lang('$table.fields.$field') ?></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="$field" id="$field" class="form-control <?= session('error.$field') ? 'is-invalid' : '' ?>" value="<?= old('$field') ?>" placeholder="<?= lang('$table.fields.$field') ?>" autocomplete="off">
</div>
</div>
</div>
EOF . PHP_EOL;
}
}
$contador++;
}
$fields = substr($fields, 0, strlen($fields) - 1);
$nameClassModel = ucfirst($table) . "Model";
$viewModal = <<<EOF
<!-- Modal $tableUpCase -->
<div class="modal fade" id="modalAdd$tableUpCase" tabindex="-1" role="dialog" aria-labelledby="modalAdd$tableUpCase" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><?= lang('$table.createEdit') ?></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form id="form-$table" class="form-horizontal">
<input type="hidden" id="id$tableUpCase" name="id$tableUpCase" value="0">
$campos
</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="btnSave$tableUpCase"><?= lang('boilerplate.global.save') ?></button>
</div>
</div>
</div>
</div>
<?= \$this->section('js') ?>
<script>
$(document).on('click', '.btnAdd$tableUpCase', function (e) {
$(".form-control").val("");
$("#id$tableUpCase").val("0");
$("#btnSave$tableUpCase").removeAttr("disabled");
});
/*
* AL hacer click al editar
*/
$(document).on('click', '.btnEdit$tableUpCase', function (e) {
var id$tableUpCase = $(this).attr("id$tableUpCase");
//LIMPIAMOS CONTROLES
$(".form-control").val("");
$("#id$tableUpCase").val(id$tableUpCase);
$("#btnGuardar$tableUpCase").removeAttr("disabled");
});
</script>
<?= \$this->endSection() ?>
EOF;
$path = ROOTPATH . "app/Views/modules$tableUpCase/";
if (!is_dir($path))
mkdir($path, 0777, TRUE);
file_put_contents($path . "modalCapture{$tableUpCase}.php", $viewModal);
}
/**
* Generate Languaje EN
*/
public function generateLanguage($table) {
$tableUpCase = ucfirst($table);
$query = $this->db->getFieldNames($table);
$fields = "";
$campos = "";
$contador = 0;
foreach ($query as $field) {
$fields .= $field . ",";
if ($contador > 0) {
$campos .= "\${$table}[\"fields\"][\"$field\"] = \"" . ucfirst($field) . "\";" . PHP_EOL;
}
$contador++;
}
$fields = substr($fields, 0, strlen($fields) - 1);
$nameClassModel = ucfirst($table) . "Model";
$languaje = <<<EOF
<?php
\${$table}["logDescription"] = "The $table was saved with the following data:";
\${$table}["logUpdate"] = "The $table was updated with the following data:";
\${$table}["logDeleted"] = "The $table was deleted with the following data:";
\${$table}["msg_delete"] = "The $table was deleted correctly:";
\${$table}["add"] = "Add $tableUpCase";
\${$table}["edit"] = "Edit $table";
\${$table}["createEdit"] = "Create / Edit";
\${$table}["title"] = "$table management";
\${$table}["subtitle"] = "$table list";
$campos
\${$table}["fields"]["actions"] = "Actions";
\${$table}["msg"]["msg_insert"] = "The $table has been correctly added.";
\${$table}["msg"]["msg_update"] = "The $table has been correctly modified.";
\${$table}["msg"]["msg_delete"] = "The $table has been correctly deleted.";
\${$table}["msg"]["msg_get"] = "The $tableUpCase has been successfully get.";
\${$table}["msg"]["msg_get_fail"] = "The $table not found or already deleted.";
return $$table;
EOF;
$path = ROOTPATH . "app/Language/en/";
if (!is_dir($path))
mkdir($path, 0777, TRUE);
file_put_contents($path . "$table.php", $languaje);
}
/**
* Lenguaje ES
* @param type $table
*/
public function generateLanguageES($table) {
$tableUpCase = ucfirst($table);
$query = $this->db->getFieldNames($table);
$fields = "";
$campos = "";
$contador = 0;
foreach ($query as $field) {
$fields .= $field . ",";
if ($contador > 0) {
$campos .= "\${$table}[\"fields\"][\"$field\"] = \"" . ucfirst($field) . "\";" . PHP_EOL;
}
$contador++;
}
$fields = substr($fields, 0, strlen($fields) - 1);
$nameClassModel = ucfirst($table) . "Model";
$languaje = <<<EOF
<?php
\${$table}["logDescription"] = "El registro en $table fue guardado con los siguientes datos:";
\${$table}["logUpdate"] = "El registro en $table fue actualizado con los siguientes datos:";
\${$table}["logDeleted"] = "El registro en $table fue eliminado con los siguientes datos:";
\${$table}["msg_delete"] = "El Registro en $table fue eliminado correctamente:";
\${$table}["add"] = "Agregar $tableUpCase";
\${$table}["edit"] = "Editar $table";
\${$table}["createEdit"] = "Crear / Editar";
\${$table}["title"] = "Admon. $table";
\${$table}["subtitle"] = "Lista $table";
$campos
\${$table}["fields"]["actions"] = "Acciones";
\${$table}["msg"]["msg_insert"] = "Registro agregado correctamente.";
\${$table}["msg"]["msg_update"] = "Registro modificado correctamente.";
\${$table}["msg"]["msg_delete"] = "Registro eliminado correctamente.";
\${$table}["msg"]["msg_get"] = "Registro obtenido correctamente.";
\${$table}["msg"]["msg_get_fail"] = "Registro no encontrado o eliminado.";
return $$table;
EOF;
$path = ROOTPATH . "app/Language/es/";
if (!is_dir($path))
mkdir($path, 0777, TRUE);
file_put_contents($path . "$table.php", $languaje);
}
/**
* Generate Migration
* @param type $table
*/
public function generateMigration($table) {
$tableUpCase = ucfirst($table);
$query = $this->db->getFieldData($table);
$campos = "";
$contador = 0;
foreach ($query as $field) {
if ($contador > 0) {
if($field->nullable==1){
$nullable="true";
} else{
$nullable="false";
}
if ($field->name <> "created_at" && $field->name <> "updated_at" && $field->name <> "deleted_at") {
$campos .= "'{$field->name}' => ['type' => '{$field->type}', 'constraint' => {$field->max_length}, 'null' => $nullable]," . PHP_EOL;
}
} else {
$campos .= "'id' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true]," . PHP_EOL;
}
$contador++;
}
$nameClassModel = ucfirst($table) . "Model";
$migration = <<<EOF
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class $tableUpCase extends Migration
{
public function up()
{
// $tableUpCase
\$this->forge->addField([
$campos
'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('$table', true);
}
public function down(){
\$this->forge->dropTable('$table', true);
}
}
EOF;
$path = ROOTPATH . "app/Database/Migrations/";
if (!is_dir($path))
mkdir($path, 0777, TRUE);
$fechaActual = fechaParaMigraciones(fechaHoraActual());
file_put_contents($path . "{$fechaActual}_{$tableUpCase}.php", $migration);
//file_put_contents($path . "2023-02-07-165411_$tableUpCase.php", $viewModal);
}
}
Creamos el archivo app/helpers/utilerias_helper.php con el siguiente codigo
<?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;
}
}
//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";
*
*/
}
//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));
}
//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));
}
En rutas ponemos el siguiente codigo
$routes->get('generateCRUD/(:any)', 'AutoCrudController::index/$1');
Creamos la tabla de categorías
-- phpMyAdmin SQL Dump
-- version 5.0.4
-- https://www.phpmyadmin.net/
--
-- Servidor: 127.0.0.1
-- Tiempo de generación: 21-04-2023 a las 20:19:25
-- Versión del servidor: 10.4.17-MariaDB
-- Versión de PHP: 7.4.15
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Base de datos: `ci4jcpos`
--
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `categorias`
--
CREATE TABLE `categorias` (
`id` int(11) NOT NULL,
`descripcion` varchar(128) COLLATE utf8mb4_spanish2_ci DEFAULT NULL,
`deleted_at` datetime DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish2_ci;
--
-- Índices para tablas volcadas
--
--
-- Indices de la tabla `categorias`
--
ALTER TABLE `categorias`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT de las tablas volcadas
--
--
-- AUTO_INCREMENT de la tabla `categorias`
--
ALTER TABLE `categorias`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
Corremos la siguiente URL en el navegador para crear todo el catalogo
http://localhost:8080/admin/generateCRUD/categorias
Esto nos generara los archivos necesarios y ademas la ruta para agregarlo en routes.php
$routes->resource('categorias', [
'filter' => 'permission:categorias-permission',
'controller' => 'categoriasController',
'except' => 'show'
]);
$routes->post('categorias/save', 'CategoriasController::save');
$routes->post('categorias/getCategorias', 'CategoriasController::getCategorias');
Ya creamos el catalogo de empresas, ahora vamos a ir creando un modulo de configuración de correo electrónico
Primero creamos el archivo del modelo en app/Models/SettingsMailModel.php con el siguiente contenido
<?php
namespace App\Models;
use CodeIgniter\Model;
class SettingsMailModel extends Model
{
protected $table = 'mailsettings';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'array';
protected $useSoftDeletes = true;
protected $allowedFields = ['id', 'email', 'host', 'smtpDebug', 'SMTPAuth', 'port', 'created_at', 'deleted_at', 'updated_at', 'smptSecurity', 'pass'];
}
Para la tabla donde se guardara la información corremos el siguiente código SQL en PHPMYADMIN en nuestra base de datos, en publicaciones posteriores les dejare los archivos de migración para que no tengan la necesidad de correr archivos SQL y sirva para diferentes motores de base de datos
-- phpMyAdmin SQL Dump
-- version 5.0.4
-- https://www.phpmyadmin.net/
--
-- Servidor: 127.0.0.1
-- Tiempo de generación: 18-04-2023 a las 00:56:17
-- Versión del servidor: 10.4.17-MariaDB
-- Versión de PHP: 7.4.15
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Base de datos: `wheelsoft`
--
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `mailsettings`
--
CREATE TABLE `mailsettings` (
`id` int(11) NOT NULL,
`email` varchar(512) DEFAULT NULL,
`host` varchar(128) DEFAULT NULL,
`smtpDebug` varchar(16) DEFAULT NULL,
`SMTPAuth` varchar(16) DEFAULT NULL,
`port` varchar(16) DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`deleted_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`smptSecurity` varchar(64) DEFAULT NULL,
`pass` varchar(128) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Volcado de datos para la tabla `mailsettings`
--
INSERT INTO `mailsettings` (`id`, `email`, `host`, `smtpDebug`, `SMTPAuth`, `port`, `created_at`, `deleted_at`, `updated_at`, `smptSecurity`, `pass`) VALUES
(1, 'mail@domain.com', 'mail.host5.com', '1', '1', '587', NULL, NULL, NULL, 'tls', 'password');
--
-- Índices para tablas volcadas
--
--
-- Indices de la tabla `mailsettings`
--
ALTER TABLE `mailsettings`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT de las tablas volcadas
--
--
-- AUTO_INCREMENT de la tabla `mailsettings`
--
ALTER TABLE `mailsettings`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
Creamos el archivo app/controllers/SettingsMailController.php con el siguiente contenido
<?php
namespace julio101290\boilerplate\Controllers\Users;
namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Controller;
use App\Models\SettingsMailModel;
use App\Models\LogModel;
use julio101290\boilerplate\Controllers\BaseController;
use julio101290\boilerplate\Entities\Collection;
use julio101290\boilerplate\Models\GroupModel;
use CodeIgniter\Config\Services;
use App\Models\RegisterModel;
use App\Controllers\RegisterController;
use PHPMailer\PHPMailer;
/**
* Class UserController.
*/
class SettingsMailController extends BaseController
{
use ResponseTrait;
/** @var \agungsugiarto\boilerplate\Models\GroupModel */
protected $group;
protected $settingsMail;
protected $log;
protected $register;
protected $registerController;
protected $custumer;
/** @var \agungsugiarto\boilerplate\Models\UserModel */
protected $users;
public function __construct()
{
$this->group = new GroupModel();
$this->log = new LogModel();
$this->settingsMail = new SettingsMailModel();
$autorize = $this->authorize = Services::authorization();
helper('menu');
}
public function index()
{
$datos = $this->settingsMail->where("id", 1)->first();
$data["title"] = "Correo Electronicos";
$data["subtitle"] = "Configuraciones de Correo Electronico";
$data["data"] = $datos;
return view('mailSettings', $data);
}
/**
public function sendMailPDF($uuid)
{
//DATOS CORREO
$datos = $this->settingsMail->where("id", 1)->first();
//DATOS REGISTRO
$register = $this->register->select("*")->where("uuid", $uuid)->first();
$custumer = $this->custumer->select("*")->where("id", $register["custumer"])->first();
$mailsTarjets = "";
$correo = $datos["email"];
$SMTPDebug = $datos["smtpDebug"];
$host = $datos["host"];
if ($datos["SMTPAuth"] == 1) {
$SMTPAuth = true;
} else {
$SMTPAuth = false;
}
$puerto = $datos["port"];
$clave = $datos["pass"];
$SMTPSeguridad = $datos["smptSecurity"];
// Load Composer's autoloader
// Instantiation and passing `true` enables exceptions
$mail = new PHPMailer\PHPMailer();
try {
//Server settings
$mail->SMTPDebug = $SMTPDebug; // Enable verbose debug output
$mail->isSMTP(); // Send using SMTP
$mail->Host = $host; // Set the SMTP server to send through
$mail->SMTPAuth = $SMTPAuth; // Enable SMTP authentication
$mail->Username = $correo; // SMTP username
$mail->Password = $clave; // SMTP password
$mail->SMTPSecure = $SMTPSeguridad; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
$mail->Port = $puerto;
$nombreEmpresa = "";
// TCP port to connect to
//Recipients
$mail->setFrom($correo, $nombreEmpresa);
if ($custumer["email1"] != "") {
try {
$mailAddress = $mail->addAddress($custumer["email1"], '');
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
if ($custumer["email2"] != "") {
try {
$mailAddress = $mail->addAddress($custumer["email2"], '');
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
if ($custumer["email3"] != "") {
try {
$mailAddress = $mail->addAddress($custumer["email3"], '');
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
if ($custumer["email4"] != "") {
try {
$mailAddress = $mail->addAddress($custumer["email4"], '');
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
if ($custumer["email5"] != "") {
try {
$mailAddress = $mail->addAddress($custumer["email5"], '');
if (!$mailAddress) {
echo "Error con el correo Electronico";
return;
}
} catch (Exception $ex) {
echo $ex->getMessage();
}
}
// Add a recipient
//$mail->addReplyTo('info@example.com', 'Information');
//mail->addCC('cc@example.com');
//$mail->addBCC('bcc@example.com');
// Attachments
$attachment = $this->registerController->report($uuid, 1);
$mail->AddStringAttachment($attachment, 'registro' . $register["codeCustumer"] . '.pdf', 'base64', 'application/pdf');
// Add attachments
//$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
// Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = "Envio de Registro";
$mail->Body = "Adjuntamos el registro de verificación de neumaticos";
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
try {
$send = $mail->send();
} catch (Exception $ex) {
echo $ex->getMessage();
return;
}
if ($send) {
echo 'Correo Enviado Correctamente';
} else {
echo 'Error al enviar el correo';
}
} catch (Exception $e) {
echo "Error al enviar el correo: {$e->ErrorInfo}";
}
}
*/
public function guardar()
{
helper('auth');
$userName = user()->username;
$idUser = user()->id;
//GUARDA CONFIGURACIONES
$this->settingsMail->update(1, $_POST);
// return redirect()->to("/admin/hospital");
return redirect()->back()->with('sweet-success', 'Actualizado Correctamente');
// return redirect()->back()->with('sweet-success','Guardado Correctamente');
}
}
Creamos el archivo app/views/mailSettings.php con el siguiente contenido
<?= $this->extend('julio101290\boilerplate\Views\layout\index') ?>
<!-- Section content -->
<?= $this->section('content') ?>
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<div class="card card-primary">
<div class="card-header">
<h3 class="card-title">Configuración Correo Electrónico</h3>
</div>
<form action="<?= base_url('admin/mailSettings') ?>/save" method="post">
<?= csrf_field() ?>
<div class="card-body">
<div class="form-group">
<label for="nombreEmpresa">E-Mail</label>
<input type="text" class="form-control" id="email" value="<?= $data["email"] ?>" name="email" placeholder="Inserte el Email">
</div>
<div class="form-group">
<label for="correoElectronico">Host</label>
<input type="text" class="form-control" value="<?= $data["host"] ?>" id="host" name="host" placeholder="Host">
</div>
<div class="form-group">
<label for="smtpDebug">Debug Client</label>
<select id="smtpDebug" name="smtpDebug">
<option value="0">DEBUG_OFF</option>
<option value="1">DEBUG_CLIENT</option>
<option value="2">DEBUG_SERVER</option>
</select>
</div>
<div class="form-group">
<label for="SMTPAuth">SMTP Auth</label>
<select id="SMTPAuth" name="SMTPAuth">
<option value=""></option>
<option value="0">Sin autentificación</option>
<option value="1">Con autentificación</option>
</select>
</div>
<div class="form-group">
<label for="smptSecurity">Seguridad</label>
<select id="smptSecurity" name="smptSecurity">
<option value="">Sin Seguridad</option>
<option value="ssl">Seguridad SSL</option>
<option value="tls">Seguridad TLS</option>
</select>
</div>
<div class="form-group">
<label for="port">Puerto</label>
<input type="number" class="form-control" value="<?= $data["port"] ?>" id="port" name="port" placeholder="Puerto">
</div>
<div class="form-group">
<label for="port">Contraseña</label>
<input type="password" class="form-control" value="<?= $data["pass"] ?>" id="pass" name="pass" placeholder="Contraseña">
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary btnGuardar">Guardar</button>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
<?= $this->endSection() ?>
<?= $this->section('js') ?>
<script>
$("#smptSecurity").val("<?= $data["smptSecurity"] ?>");
$("#SMTPAuth").val("<?= $data["SMTPAuth"] ?>");
$("#smtpDebug").val("<?= $data["smtpDebug"] ?>");
</script>
<?= $this->endSection() ?>
en app/config/routes.php agregamos el siguiente codigo
$routes->resource('emailSettings', [
'filter' => 'permission:email-permiso',
'controller' => 'SettingsMailController',
]);
$routes->post('mailSettings/save', 'SettingsMailController::guardar');
//Para futuros envios
//$routes->get('mailSettings/sendMail/(:any)', 'SettingsMailController::sendMailPDF/$1');
Ya tenemos nuestros menús creados ahora sigue meter los catálogos de configuración, el primero seria el catalogo de empresas en el cual se van a capturar los datos de la empresa como nombre, razón social, domicilio logo y datos de facturación del SAT, estos datos saldrán en las impresiones de cotizaciones, ventas y reportes.
Primero para hacer los datatables mas fácil instalamos el paquete de hermawan/codeigniter4-datatables esto solo lo haremos una vez y nos servira para los demás catálogos para instalarlo corremos el siguiente código en nuestro proyecto
composer require hermawan/codeigniter4-datatables
Luego en app/config/autoload.php en la variable $psr4 agregamos el namespace
public $psr4 = [
APP_NAMESPACE => APPPATH, // For custom app namespace
'Config' => APPPATH . 'Config',
'Hermawan\DataTables' => APPPATH .'ThirdParty/codeigniter4-datatables/src', // <-- namespace for this library
];
Ahora para obtener todos los catálogos del SAT instalamos el paquete de phpcfdi/sat-catalogos
composer require phpcfdi/sat-catalogos
El archivo de app/controller/BaseController.php quedaria de la siguiente forma para poder utilizar los catalogos del SAT en todo momento.
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
use PhpCfdi\SatCatalogos\Factory;
/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*/
abstract class BaseController extends Controller
{
/**
* Instance of the main Request object.
*
* @var CLIRequest|IncomingRequest
*/
protected $request;
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* @var array
*/
protected $helpers = [];
public $catalogosSAT;
/**
* Constructor.
*/
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
// Preload any models, libraries, etc, here.
// E.g.: $this->session = \Config\Services::session();
$dsn = "sqlite:".ROOTPATH."writable\database\catalogossat.db";
$factory = new Factory();
$satCatalogos = $factory->catalogosFromDsn($dsn);
$this->catalogosSAT = $satCatalogos;
}
}
Si se dan cuenta nosotros tenemos un archivo en writable/database/catalogossat.db para generar el archivo de base de datos SQLITE con los datos que proporciona el SAT tenemos el siguiente script en PHP, cortesía de nuestro amigo Rene
<?php
if(file_exists ( 'sat.db' )){
unlink('sat.db' );
}
$sat = new SQLite3('sat.db');
$list = "https://raw.githubusercontent.com/phpcfdi/resources-sat-catalogs/master/database/tables.list";
$schema = "https://raw.githubusercontent.com/phpcfdi/resources-sat-catalogs/master/database/schemas/";
$data = "https://raw.githubusercontent.com/phpcfdi/resources-sat-catalogs/master/database/data/";
$listaText = file_get_contents($list);
$lines = array_filter(array_map('trim',explode("\n", $listaText)));
foreach ($lines as $line) {
echo "\x1b[33m" . $line . "\x1b[0m \n";
$schemaText = file_get_contents($schema . $line . ".sql");
echo $schemaText . "\n";
$sat->exec($schemaText);
$dataText = file_get_contents($data . $line . ".sql");
$dataLines = array_filter(array_map('trim',explode("\n", $dataText)));
foreach ($dataLines as $dataLine) {
echo "\x1b[2m" . $dataLine . "\x1b[0m \n";
$sat->exec($dataLine);
}
echo "\x1b[32m data done\n \x1b[0m \n";
}
Ahora si los archivos del catalogo, creamos el archivo app/controller/EmpresasController.php con el siguiente contenido
<?php
namespace App\Controllers;
use App\Controllers\BaseController;
use \App\Models\EmpresasModel;
use App\Models\LogModel;
use CodeIgniter\API\ResponseTrait;
class EmpresasController extends BaseController {
use ResponseTrait;
protected $log;
protected $empresas;
public function __construct() {
$this->empresas = new EmpresasModel();
$this->log = new LogModel();
helper('menu', 'filesystem');
}
public function index() {
if ($this->request->isAJAX()) {
$datos = $this->empresas->select('id,nombre,direccion,rfc,telefono,correoElectronico,'
. 'diasEntrega,caja,logo,certificado,archivoKey,contraCertificado,regimenFiscal,razonSocial,codigoPostal,'
. 'CURP,created_at,updated_at')->where('deleted_at', null);
return \Hermawan\DataTables\DataTable::of($datos)->toJson(true);
}
$regimenesFiscales = $this->catalogosSAT->regimenesFiscales40()->searchByField("texto", "%%", 1000);
$titulos["title"] = lang('empresas.title');
$titulos["subtitle"] = lang('empresas.subtitle');
$titulos["regimenesFiscales"] = $regimenesFiscales;
//$data["data"] = $datos;
return view('empresas', $titulos);
}
/**
* Read Vehicle
*/
public function obtenerEmpresa() {
$idEmpresa = $this->request->getPost("idEmpresa");
$datosEmpresa = $this->empresas->find($idEmpresa);
echo json_encode($datosEmpresa);
}
/**
* Save or update Vehicle
*/
public function save() {
helper('auth');
$userName = user()->username;
$idUser = user()->id;
$datos = $this->request->getPost();
unset($datos["certificado"]);
unset($datos["archivoKey"]);
unset($datos["logo"]);
$certificado = $this->request->getFile('certificado');
$archivoKey = $this->request->getFile('archivoKey');
$logo = $this->request->getFile('logo');
if ($certificado <> null) {
if ($certificado->getClientExtension() <> "cer") {
return lang("empresas.certExtensionIncorrect");
}
$datos["certificado"] = $datos["rfc"] . "_certificado.cer";
}
if ($archivoKey <> null) {
if ($archivoKey->getClientExtension() <> "key") {
return lang("empresas.keyFileExtensionIncorrect");
}
$datos["archivoKey"] = $datos["rfc"] . "_certificado.key";
}
if ($logo) {
if ($logo->getClientExtension() <> "png") {
return lang("empresas.pngFileExtensionIncorrect");
}
$datos["logo"] = $datos["rfc"] . "_logo.png";
}
if ($datos["idEmpresa"] == 0) {
try {
if ($this->empresas->save($datos) === false) {
$errores = $this->empresas->errors();
foreach ($errores as $field => $error) {
echo $error . " ";
}
return;
}
$dateLog["description"] = lang("empresas.logDescription") . json_encode($datos);
$dateLog["user"] = $userName;
$this->log->save($dateLog);
if ($certificado <> null) {
$certificado->move(WRITEPATH . "uploads\certificates", $datos["rfc"] . "_certificado.cer");
}
if ($archivoKey <> null) {
$archivoKey->move(WRITEPATH . "uploads\certificates", $datos["rfc"] . "_certificado.key");
}
if ($logo <> null) {
$logo->move("images\logo", $datos["rfc"] . "_logo.png");
}
echo "Guardado Correctamente";
} catch (\PHPUnit\Framework\Exception $ex) {
echo "Error al guardar " . $ex->getMessage();
}
} else {
$datosAnteriores = $this->empresas->find($datos["idEmpresa"]);
if ($this->empresas->update($datos["idEmpresa"], $datos) == false) {
$errores = $this->empresas->errors();
foreach ($errores as $field => $error) {
echo $error . " ";
}
return;
} else {
if ($certificado <> null) {
unlink(WRITEPATH . "uploads\certificates\\" . $datosAnteriores["rfc"] . "_certificado.cer");
$certificado->move(WRITEPATH . "uploads\certificates", $datos["rfc"] . "_certificado.cer");
}
if ($archivoKey <> null) {
unlink(WRITEPATH . "uploads\certificates\\" . $datosAnteriores["rfc"] . "_certificado.key");
$archivoKey->move(WRITEPATH . "uploads\certificates", $datos["rfc"] . "_certificado.key");
}
if ($logo <> null) {
unlink("images\logo\\" . $datosAnteriores["rfc"] . "_logo.png");
$logo->move("images\logo", $datos["rfc"] . "_logo.png");
}
$dateLog["description"] = lang("empresas.logUpdated") . json_encode($datosAnteriores);
$dateLog["user"] = $userName;
$this->log->save($dateLog);
echo "Actualizado Correctamente";
return;
}
}
return;
}
/**
* Delete Empresas
* @param type $id
* @return type
*/
public function delete($id) {
$infoEmpresa = $this->empresas->find($id);
helper('auth');
$userName = user()->username;
if (!$found = $this->empresas->delete($id)) {
return $this->failNotFound(lang('empresas.msg.msg_get_fail'));
}
$logData["description"] = lang("empresas.logDeleted") . json_encode($infoEmpresa);
$logData["user"] = $userName;
if(file_exists(WRITEPATH . "uploads\certificates\\" . $infoEmpresa["rfc"] . "_certificado.cer")){
unlink(WRITEPATH . "uploads\certificates\\" . $infoEmpresa["rfc"] . "_certificado.cer");
}
if(file_exists(WRITEPATH . "uploads\certificates\\" . $infoEmpresa["rfc"] . "_certificado.key")){
unlink(WRITEPATH . "uploads\certificates\\" . $infoEmpresa["rfc"] . "_certificado.key");
}
if(file_exists("images\logo\\" . $infoEmpresa["rfc"] . "_logo.png")){
unlink("images\logo\\" . $infoEmpresa["rfc"] . "_logo.png");
}
$this->empresas->purgeDeleted();
$this->log->save($logData);
return $this->respondDeleted($found, lang('empresas.msg_delete'));
}
}
Para crear el modelo creamos el archivo app/models/EmpresasModel.php con el siguiente contenido
<?php
namespace App\Models;
use CodeIgniter\Model;
/**
* @method User|null first()
*/
class EmpresasModel extends Model {
protected $table = 'empresas';
protected $primaryKey = 'id';
protected $useSoftDeletes = true;
protected $allowedFields = [
'id', 'nombre', 'direccion', 'rfc', 'telefono', 'correoElectronico', 'diasEntrega',
'caja', 'logo', 'certificado', 'archivoKey', 'contraCertificado', 'regimenFiscal', 'razonSocial', 'CURP',
'codigoPostal', 'created_at ', 'updated_at ', 'deleted_at'
];
protected $useTimestamps = true;
protected $validationRules = [
'correoElectronico' => 'required|valid_email',
'razonSocial ' => 'required|alpha_numeric_punct|min_length[3]|is_unique[empresas.razonSocial]',
'rfc ' => 'is_unique[empresas.rfc]',
];
protected $validationMessages = [];
protected $skipValidation = false;
}
Ahora los archivos de la vista, creamos el archivo principal de la vista en app/views/empresas.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('modulosEmpresas/modalCapturaEmpresas') ?>
<!-- SELECT2 EXAMPLE -->
<div class="card card-default">
<div class="card-header">
<div class="float-right">
<div class="btn-group">
<button class="btn btn-primary btnAddEmpresa" data-toggle="modal" data-target="#modalAddEmpresa"><i class="fa fa-plus"></i>
<?= lang('empresas.add') ?>
</button>
</div>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
<div class="table-responsive">
<table id="tableEmpresas" class="table table-striped table-hover va-middle tableEmpresas">
<thead>
<tr>
<th>#</th>
<th><?= lang('empresas.fields.nombre') ?></th>
<th><?= lang('empresas.fields.direccion') ?></th>
<th><?= lang('empresas.fields.rfc') ?></th>
<th><?= lang('empresas.fields.logo') ?></th>
<th><?= lang('empresas.fields.regimenFiscal') ?></th>
<th><?= lang('empresas.fields.razonSocial') ?></th>
<th><?= lang('empresas.fields.codigoPostal') ?></th>
<th><?= lang('empresas.fields.CURP') ?></th>
<th><?= lang('empresas.fields.Created_at') ?></th>
<th><?= lang('empresas.fields.Update_At') ?></th>
<th><?= lang('empresas.fields.acciones') ?> </th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- /.card -->
<?= $this->endSection() ?>
<?= $this->section('js') ?>
<script>
/**
* Cargamos la tabla
*/
var tableEmpresas = $('#tableEmpresas').DataTable({
processing: true,
serverSide: true,
responsive: true,
autoWidth: false,
order: [[1, 'asc']],
ajax: {
url: '<?= base_url(route_to('admin/empresas')) ?>',
method: 'GET',
dataType: "json"
},
columnDefs: [{
orderable: false,
targets: [12],
searchable: false,
targets: [12]
}],
columns: [{
'data': 'id'
},
{
'data': 'nombre'
},
{
'data': 'direccion'
},
{
'data': 'rfc'
},
{
'data': 'logo'
},
{
'data': 'regimenFiscal'
},
{
'data': 'razonSocial'
},
{
'data': 'codigoPostal'
},
{
'data': 'CURP'
},
{
'data': 'created_at'
},
{
'data': 'updated_at'
},
{
'data': 'CURP'
},
{
"data": function (data) {
return `<td class="text-right py-0 align-middle">
<div class="btn-group btn-group-sm">
<button class="btn btn-warning btnEditEmpresa" data-toggle="modal" idEmpresa="${data.id}" data-target="#modalAddEmpresa"> <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', '#btnSaveEmpresa', function (e) {
var idEmpresa = $("#idEmpresa").val();
var nombre = $("#nombre").val();
var direccion = $("#direccion").val();
var telefono = $("#telefono").val();
var correoElectronico = $("#correoElectronico").val();
var razonSocial = $("#razonSocial").val();
var rfc = $("#rfc").val();
var CURP = $("#CURP").val();
var regimenFiscal = $("#regimenFiscal").val();
var codigoPostal = $("#codigoPostal").val();
var certificado = $("#certificado").prop("files")[0];
var archivoKey = $("#archivoKey").prop("files")[0];
var contraCertificado = $("#contraCertificado").val();
var logo = $("#logo").prop("files")[0];
$("#btnSaveEmpresa").attr("disabled", true);
var datos = new FormData();
datos.append("idEmpresa", idEmpresa);
datos.append("nombre", nombre);
datos.append("direccion", direccion);
datos.append("telefono", telefono);
datos.append("correoElectronico", correoElectronico);
datos.append("razonSocial", razonSocial);
datos.append("codigoPostal", codigoPostal);
datos.append("rfc", rfc);
datos.append("CURP", CURP);
datos.append("regimenFiscal", regimenFiscal);
datos.append("certificado", certificado);
datos.append("archivoKey", archivoKey);
datos.append("contraCertificado", contraCertificado);
datos.append("logo", logo);
$.ajax({
url: "<?= route_to('admin/empresas/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: "<?= lang('empresas..msg.msg_save') ?>"
});
tableEmpresas.ajax.reload();
$("#btnSaveEmpresa").removeAttr("disabled");
$('#modalAddEmpresa').modal('hide');
} else {
Toast.fire({
icon: 'error',
title: respuesta
});
$("#btnSaveEmpresa").removeAttr("disabled");
// $('#modalAgregarPaciente').modal('hide');
}
}
}
)
});
/**
* Carga datos actualizar
*/
/*=============================================
EDITAR PACIENTE
=============================================*/
$(".tableEmpresas").on("click", ".btnEditEmpresa", function () {
var idEmpresa = $(this).attr("idEmpresa");
var datos = new FormData();
datos.append("idEmpresa", idEmpresa);
$.ajax({
url: "<?= base_url('admin/empresas/obtenerEmpresa') ?>",
method: "POST",
data: datos,
cache: false,
contentType: false,
processData: false,
dataType: "json",
success: function (respuesta) {
console.log(respuesta);
$("#idEmpresa").val(respuesta["id"]);
$("#nombre").val(respuesta["nombre"]);
$("#direccion").val(respuesta["direccion"]);
$("#rfc").val(respuesta["rfc"]);
$("#telefono").val(respuesta["telefono"]);
$("#diasEntrega").val(respuesta["diasEntrega"]);
$("#caja").val(respuesta["caja"]);
$("#contraCertificado").val(respuesta["contraCertificado"]);
$("#regimenFiscal").val(respuesta["regimenFiscal"]);
$("#regimenFiscal").trigger("change");
$("#razonSocial ").val(respuesta["razonSocial"]);
$("#codigoPostal").val(respuesta["codigoPostal"]);
$("#CURP").val(respuesta["CURP"]);
$("#correoElectronico").val(respuesta["correoElectronico"]);
if (respuesta["logo"] != "") {
$(".previsualizarLogo").attr('src', '<?= base_URL("images/logo") ?>' + '/' + respuesta["logo"]);
}
}
})
})
/*=============================================
ELIMINAR PACIENTE
=============================================*/
$(".tableEmpresas").on("click", ".btn-delete", function () {
var idEmpresa = $(this).attr("data-id");
console.log("eliminar");
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/empresas') ?>/` + idEmpresa,
method: 'DELETE',
}).done((data, textStatus, jqXHR) => {
Toast.fire({
icon: 'success',
title: jqXHR.statusText,
});
tableEmpresas.ajax.reload();
}).fail((error) => {
Toast.fire({
icon: 'error',
title: error.responseJSON.messages.error,
});
})
}
})
});
$('#regimenFiscal').select2();
/*=============================================
SUBIENDO LA FOTO DEL USUARIO
=============================================*/
$(".logo").change(function () {
var imagen = this.files[0];
/*=============================================
VALIDAMOS EL FORMATO DE LA IMAGEN SEA JPG O PNG
=============================================*/
if (imagen["type"] != "image/png") {
$(".logo").val("");
Toast.fire({
icon: 'error',
title: "<?= lang('empresas.imagenesFormato') ?>",
});
} else if (imagen["size"] > 2000000) {
$(".logo").val("");
Toast.fire({
icon: 'error',
title: "<?= lang('empresas.imagenesPeso') ?>",
});
} else {
var datosImagen = new FileReader;
datosImagen.readAsDataURL(imagen);
$(datosImagen).on("load", function (event) {
var rutaImagen = event.target.result;
$(".previsualizarLogo").attr("src", rutaImagen);
})
}
})
</script>
<?= $this->endSection() ?>
Ahora los archivos de la vista creamos el archivo app/views/modulosEmpresas/facturacionEmpresa.php y dentro de el metemos el siguiente código
<p>
<h3>Datos Facturación</h3>
<div class="form-group row">
<label for="inputName" class="col-sm-2 col-form-label"><?= lang('empresas.fields.razonSocial') ?></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="razonSocial" id="razonSocial" class="form-control <?= session('error.razonSocial') ? 'is-invalid' : '' ?>" value="<?= old('razonSocial') ?>" placeholder="<?= lang('empresas.fields.razonSocial') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="codigoPostal" class="col-sm-2 col-form-label"><?= lang('empresas.fields.codigoPostal') ?></label>
<div class="col-sm-10">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-location-arrow"></i></span>
</div>
<input type="text" name="codigoPostal" id="codigoPostal"class="form-control <?= session('error.codigoPostal') ? 'is-invalid' : '' ?>" value="<?= old('codigoPostal') ?>" placeholder="<?= lang('empresas.fields.codigoPostal') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="rfc" class="col-sm-2 col-form-label"><?= lang('empresas.fields.rfc') ?></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>
<input type="text" name="rfc" id="rfc" class="form-control <?= session('error.rfc') ? 'is-invalid' : '' ?>" value="<?= old('rfc') ?>" placeholder="<?= lang('empresas.fields.rfc') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="CURP" class="col-sm-2 col-form-label"><?= lang('empresas.fields.CURP') ?></label>
<div class="col-sm-10">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="far fa-id-card"></i></span>
</div>
<input type="text" name="CURP" id="CURP" class="form-control <?= session('error.CURP') ? 'is-invalid' : '' ?>" value="<?= old('CURP') ?>" placeholder="<?= lang('empresas.fields.CURP') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="inputSkills" class="col-sm-2 col-form-label"><?= lang('empresas.fields.regimenFiscal') ?></label>
<div class="col-sm-8">
<select class="form-control select" name="regimenFiscal" id="regimenFiscal" style="width: 100%;">
<option value="0"><?= lang('empresas.fields.regimenFiscalOpcion') ?></option>
<?php
foreach ($regimenesFiscales as $key => $value) {
echo '<option value="' . $value->id() . '">' . $value->id() . ' - ' . $value->texto() . '</option>';
}
?>
</select>
</div>
</div>
<div class="form-group row">
<label for="certificado" class="col-sm-2 col-form-label"><?= lang('empresas.fields.certificado') ?></label>
<div class="col-sm-10">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-award"></i></span>
</div>
<input type="file" name="certificado" id="certificado" class="form-control <?= session('error.certificado') ? 'is-invalid' : '' ?>" value="<?= old('certificado') ?>" placeholder="<?= lang('empresas.fields.correoElectronico') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="archivoKey" class="col-sm-2 col-form-label"><?= lang('empresas.fields.archivoKey') ?></label>
<div class="col-sm-10">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-key"></i></span>
</div>
<input type="file" name="archivoKey" id="archivoKey" class="form-control <?= session('error.certificado') ? 'is-invalid' : '' ?>" value="<?= old('archivoKey') ?>" placeholder="<?= lang('empresas.fields.archivoKey') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="contraCertificado" class="col-sm-2 col-form-label"><?= lang('empresas.fields.contraCertificado') ?></label>
<div class="col-sm-10">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-unlock"></i></span>
</div>
<input type="text" name="contraCertificado" id="contraCertificado" class="form-control <?= session('error.contraCertificado') ? 'is-invalid' : '' ?>" value="<?= old('contraCertificado') ?>" placeholder="<?= lang('empresas.fields.contraCertificado') ?>" autocomplete="off">
</div>
</div>
</div>
</p>
Ahora los archivos de la vista creamos el archivo app/views/modulosEmpresas/generalesEmpresa.php y dentro de el metemos el siguiente código
<p>
<h3>Datos Generales</h3>
<div class="form-group row">
<label for="inputName" class="col-sm-2 col-form-label"><?= lang('empresas.fields.nombre') ?></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="hidden" name="idEmpresa" id="idEmpresa" value="0">
<input type="text" name="nombre" id="nombre" class="form-control <?= session('error.nombre') ? 'is-invalid' : '' ?>" value="<?= old('nombre') ?>" placeholder="<?= lang('empresas.fields.nombre') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="inputName" class="col-sm-2 col-form-label"><?= lang('empresas.fields.direccion') ?></label>
<div class="col-sm-10">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fas fa-location-arrow"></i></span>
</div>
<input type="text" name="direccion" id="direccion"class="form-control <?= session('error.direccion') ? 'is-invalid' : '' ?>" value="<?= old('direccion') ?>" placeholder="<?= lang('empresas.fields.direccion') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="telefono" class="col-sm-2 col-form-label"><?= lang('empresas.fields.telefono') ?></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" name="telefono" id="telefono" class="form-control <?= session('error.telefono') ? 'is-invalid' : '' ?>" value="<?= old('telefono') ?>" placeholder="<?= lang('empresas.fields.telefono') ?>" autocomplete="off">
</div>
</div>
</div>
<div class="form-group row">
<label for="correoElectronico" class="col-sm-2 col-form-label"><?= lang('empresas.fields.correoElectronico') ?></label>
<div class="col-sm-10">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="far fa-envelope"></i></span>
</div>
<input type="text" name="correoElectronico" id="correoElectronico" class="form-control <?= session('error.correoElectronico') ? 'is-invalid' : '' ?>" value="<?= old('correoElectronico') ?>" placeholder="<?= lang('empresas.fields.correoElectronico') ?>" autocomplete="off">
</div>
</div>
</div>
</p>
Ahora los archivos de la vista creamos el archivo app/views/modulosEmpresas/logosEmpresa.php y dentro de el metemos el siguiente código
<p>
<h3>Imagenes</h3>
<div class="form-group">
<div class="panel"><?= lang("empresas.fields.logo") ?></div>
<input type="file" class="logo" name="logo" id="logo">
<p class="help-block"><?= lang("empresas.imagenesPesoMaximo") ?></p>
<img src="<?= base_url("images/logo/anonymous.png") ?>" class="img-thumbnail previsualizarLogo" width="100px">
<input type="hidden" name="logoActual" id="logoActual">
</div>
</p>
Ahora los archivos de la vista creamos el archivo app/views/modulosEmpresas/modalCapturaEmpresas.php y dentro de el metemos el siguiente código
<!-- Modal Empresas -->
<div class="modal fade" id="modalAddEmpresa" tabindex="-1" role="dialog" aria-labelledby="modalAddEmpresa" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><?= lang('empresas.createEdit') ?></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="home-tab" data-toggle="tab" data-target="#generales" type="button" role="tab" aria-controls="home" aria-selected="true">Generales</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="profile-tab" data-toggle="tab" data-target="#datosFacturacion" type="button" role="tab" aria-controls="profile" aria-selected="false">Facturacion</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="contact-tab" data-toggle="tab" data-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="false">Logos / Imagenes</button>
</li>
</ul>
<form id="form-empresa" class="form-horizontal">
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="generales" role="tabpanel" aria-labelledby="generales">
<?= $this->include('modulosEmpresas/generalesEmpresa') ?>
</div>
<div class="tab-pane fade" id="datosFacturacion" role="tabpanel" aria-labelledby="datosFacturacion">
<?= $this->include('modulosEmpresas/facturacionEmpresa') ?>
</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">
<?= $this->include('modulosEmpresas/logosEmpresa') ?>
</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="btnSaveEmpresa"><?= lang('boilerplate.global.save') ?></button>
</div>
</div>
</div>
</div>
<?= $this->section('js') ?>
<script>
$(document).on('click', '.btnAddEmpresa', function (e) {
console.log("asd");
$(".form-control").val("");
$("#idEmpresa").val("0");
$(".previsualizarLogo").attr('src','<?= base_URL("images/logo") ?>/anonymous.png' );
$("#btnSaveEmpresa").removeAttr("disabled");
});
/*
* AL hacer click al editar
*/
$(document).on('click', '.btnEditarEmpresa', function (e) {
var idEmpresa = $(this).attr("idEmpresa");
//LIMPIAMOS CONTROLES
$(".form-control").val("");
$("#idEmpresa").val(idEmpresa);
$("#btnGuardarEmpresa").removeAttr("disabled");
});
</script>
<?= $this->endSection() ?>
En el archivo app/config/routes.php quedaria de la siguiente forma
$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');
});
En los archivos de lenguaje para ingles creamos el archivo app/Language/en/empresas.php con el siguiente contenido
<?php
$empresas["logDescription"] = "The companie was saved with the following data:";
$empresas["logUpdate"] = "The companie was updated with the following data:";
$empresas["logDeleted"] = "The companie was deleted with the following data:";
$empresas["msg_delete"] = "The companie was deleted correctly:";
$empresas["add"] = "Add companie";
$empresas["edit"] = "Edit companie";
$empresas["createEdit"] = "Create / Edith";
$empresas["title"] = "companie management";
$empresas["subtitle"] = "companie list";
$empresas["fields"]["nombre"] = "Name";
$empresas["fields"]["direccion"] = "direction";
$empresas["fields"]["rfc"] = "RFC";
$empresas["fields"]["logo"] = "logo";
$empresas["fields"]["certificado"] = "certificate";
$empresas["fields"]["archivoKey"] = "KeyFile";
$empresas["fields"]["contraCertificado"] = "Password Certificate";
$empresas["fields"]["regimenFiscal"] = "Tax Regime";
$empresas["fields"]["regimenFiscalOpcion"] = "Select tax regime";
$empresas["fields"]["razonSocial "] = "Business name";
$empresas["fields"]["codigoPostal "] = "Postal Code ";
$empresas["fields"]["CURP"] = "CURP";
$empresas["fields"]["Created_at"] = "Created At";
$empresas["fields"]["Update_At"] = "Update At";
$empresas["msg"]["msg_save"] = "The companie has been correctly saved.";
$empresas["msg"]["msg_insert"] = "The companie has been correctly added.";
$empresas["msg"]["msg_update"] = "The companie has been correctly modified.";
$empresas["msg"]["msg_delete"] = "The companie has been correctly deleted.";
$empresas["msg"]["msg_get"] = "The companie has been successfully get.";
$empresas["msg"]["msg_get_fail"] = "The vehicle not found or already deleted.";
$empresas["imagenesFormato"] = "The image must be in PNG format!";
$empresas["imagenesPeso"] = "The image must not be larger than 2MB!";
$empresas["imagenesPesoMaximo"] = "Maximum weight of the photo 1MB";
$empresas["certExtensionIncorrect"] = "Extensión certificate incorrect";
$empresas["keyFileExtensionIncorrect"] = "Extensión key file incorrect";
$empresas["pngFileExtensionIncorrect"] = "This image not is PNG";
return $empresas;
En los archivos de lenguaje para ingles creamos el archivo app/Language/es/empresas.php con el siguiente contenido
<?php
$empresas["logDescription"] = "El Empresa ha sido guardado con los siguientes datos:";
$empresas["logUpdate"] = "EL Empresa ha sido actualizado con los siguientes datos";
$empresas["logDeleted"] = "El Empresa ha sido eliminado con los siguientes datos:";
$empresas["add"] = "Agregar Empresa";
$empresas["edit"] = "Editar Empresa";
$empresas["createEdit"] = "Crear / Editar";
$empresas["title"] = "Administración de Empresas";
$empresas["subtitle"] = "Lista de Empresas";
$empresas["fields"]["nombre"] = "Nombre";
$empresas["fields"]["direccion"] = "Direccion";
$empresas["fields"]["rfc"] = "RFC";
$empresas["fields"]["logo"] = "Logo";
$empresas["fields"]["certificado"] = "Certificado";
$empresas["fields"]["archivoKey"] = "Archivo Key";
$empresas["fields"]["telefono"] = "Telefono";
$empresas["fields"]["contraCertificado"] = "Contra Certificado";
$empresas["fields"]["regimenFiscal"] = "Regimen Fiscal";
$empresas["fields"]["regimenFiscalOpcion"] = "Seleccionar regimen fiscal";
$empresas["fields"]["razonSocial"] = "Razon Social";
$empresas["fields"]["codigoPostal"] = "Código Postal";
$empresas["fields"]["CURP"] = "CURP";
$empresas["fields"]["correoElectronico"] = "Correo Electronico";
$empresas["fields"]["acciones"] = "Acciones";
$empresas["msg"]["msg_save"] = "La Empresa ha sido correctamente guardada.";
$empresas["msg"]["msg_insert"] = "La Empresa ha sido correctamente agregado.";
$empresas["msg"]["msg_update"] = "La Empresa ha sido correctamente actualizado.";
$empresas["msg"]["msg_delete"] = "La Empresa ha sido correctamente eliminado.";
$empresas["msg"]["msg_get"] = "La Empresa ha sido correctamente obtenido.";
$empresas["msg"]["msg_get_fail"] = "No se encontro Empresa o fue eliminado.";
// Validations
$empresas["imagenesFormato"] = "¡La imagen debe estar en formato PNG!";
$empresas["imagenesPeso"] = "¡La imagen no debe pesar más de 2MB!";
$empresas["imagenesPesoMaximo"] = "Peso máximo de la foto 1MB";
$empresas["certExtensionIncorrect"] = "Extensión del certificado incorrecto";
$empresas["keyFileExtensionIncorrect"] = "Extensión del archivo key incorrecto";
$empresas["pngFileExtensionIncorrect"] = "Solo se permiten imagenes con formato png";
return $empresas;
Creamos el siguiente directorio para las imagenes, public/images/logo
Creamos el archivo app/databe/migrations/2023-02-14001801_Empresas.php con el siguiente contenido, este nos servirá para crear la tabla
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class Empresas extends Migration {
public function up() {
// Empresas
$this->forge->addField([
'id' => ['type' => 'int', 'constraint' => 11, 'unsigned' => true, 'auto_increment' => true],
'nombre' => ['type' => 'varchar', 'constraint' => 500, 'null' => false],
'direccion' => ['type' => 'varchar', 'constraint' => 30, 'null' => true],
'rfc' => ['type' => 'varchar', 'constraint' => 14, 'null' => false],
'telefono' => ['type' => 'varchar', 'constraint' => 255, 'null' => true],
'correoElectronico' => ['type' => 'varchar', 'constraint' => 256, 'null' => true],
'diasEntrega' => ['type' => 'varchar', 'constraint' => 8, 'null' => true],
'caja' => ['type' => 'varchar', 'constraint' => 255, 'null' => true],
'logo' => ['type' => 'varchar', 'constraint' => 1024, 'null' => true],
'certificado' => ['type' => 'varchar', 'constraint' => 1024, 'null' => true],
'archivoKey' => ['type' => 'varchar', 'constraint' => 68, 'null' => true],
'contraCertificado' => ['type' => 'varchar', 'constraint' => 68, 'null' => true],
'regimenFiscal' => ['type' => 'varchar', 'constraint' => 68, 'null' => true],
'razonSocial' => ['type' => 'varchar', 'constraint' => 68, 'null' => true],
'codigoPostal' => ['type' => 'varchar', 'constraint' => 68, 'null' => true],
'CURP' => ['type' => 'varchar', 'constraint' => 68, '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('empresas', true);
}
public function down() {
$this->forge->dropTable('empresas', true);
}
}
Creamos el modelo para la bitacora app/models/LogModel.php con el siguiente contenido
<?php
namespace App\Models;
use CodeIgniter\Model;
class LogModel extends Model
{
protected $table = 'log';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'array';
protected $useSoftDeletes = true;
protected $allowedFields = ['id','description', 'user',"created_at","updated_at"];
protected $useTimestamps = true;
protected $createdField = 'created_at';
protected $deletedField = 'deleted_at';
protected $validationRules = [];
protected $validationMessages = [];
protected $skipValidation = false;
}
Creamos el archivo de migración para LogModel en app/database/migration/2023-02-07-165412_Log.php con el siguiente contenido
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class Log extends Migration
{
public function up()
{
$this->forge->addField([
'id' => [
'type' => 'INT',
'constraint' => 5,
'unsigned' => true,
'auto_increment' => true,
],
'description' => [
'type' => 'VARCHAR',
'constraint' => '256',
],
'user' => [
'type' => 'TEXT',
'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('log', true);
}
public function down()
{
$this->forge->dropTable('log');
}
}
Por ultimo corremos el siguiente código en la terminal para correr la migración y así nos genere la tabla empresas y bitacora en la base de datos
php spark migrate
Ya tenemos la base del proyecto, ahora lo que sigue es darle forma creando los menús
Creado con WordPress & Tema de Anders Norén